mirror of
https://bitbucket.org/smil3y/katie.git
synced 2025-02-24 19:02:59 +00:00
drop BiDi support
still wonky on selection: https://ibb.co/D4bWVqX Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
57dbb8d1cd
commit
a699a16de9
7 changed files with 54 additions and 389 deletions
|
@ -4789,17 +4789,11 @@ void QPainter::drawText(const QPointF &p, const QString &str)
|
|||
engine.shapeLine(line);
|
||||
|
||||
int nItems = engine.layoutData->items.size();
|
||||
QVarLengthArray<int> visualOrder(nItems);
|
||||
QVarLengthArray<uchar> levels(nItems);
|
||||
for (int i = 0; i < nItems; ++i)
|
||||
levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
|
||||
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
|
||||
|
||||
QFixed x = QFixed::fromReal(p.x());
|
||||
|
||||
for (int i = 0; i < nItems; ++i) {
|
||||
int item = visualOrder[i];
|
||||
const QScriptItem &si = engine.layoutData->items.at(item);
|
||||
const QScriptItem &si = engine.layoutData->items.at(i);
|
||||
if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
|
||||
x += si.width;
|
||||
continue;
|
||||
|
@ -4808,7 +4802,7 @@ void QPainter::drawText(const QPointF &p, const QString &str)
|
|||
QTextItemInt gf(si, &f);
|
||||
gf.glyphs = engine.shapedGlyphs(&si);
|
||||
gf.chars = engine.layoutData->string.unicode() + si.position;
|
||||
gf.num_chars = engine.length(item);
|
||||
gf.num_chars = engine.length(i);
|
||||
if (engine.forceJustification) {
|
||||
for (int j=0; j<gf.glyphs.numGlyphs; ++j)
|
||||
gf.width += gf.glyphs.effectiveAdvance(j);
|
||||
|
@ -6379,9 +6373,7 @@ start_lengthVariant:
|
|||
qreal advance = line.horizontalAdvance();
|
||||
xoff = 0;
|
||||
if (tf & Qt::AlignRight) {
|
||||
QTextEngine *eng = textLayout.engine();
|
||||
xoff = r.width() - advance -
|
||||
eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
|
||||
xoff = r.width() - advance;
|
||||
}
|
||||
else if (tf & Qt::AlignHCenter)
|
||||
xoff = (r.width() - advance) / 2;
|
||||
|
|
|
@ -1104,24 +1104,14 @@ void QPainterPath::addText(const QPointF &point, const QFont &f, const QString &
|
|||
qreal x(point.x());
|
||||
qreal y(point.y());
|
||||
|
||||
QVarLengthArray<int> visualOrder(nItems);
|
||||
QVarLengthArray<uchar> levels(nItems);
|
||||
for (int i = 0; i < nItems; ++i)
|
||||
levels[i] = eng->layoutData->items[i].analysis.bidiLevel;
|
||||
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
|
||||
|
||||
for (int i = 0; i < nItems; ++i) {
|
||||
int item = visualOrder[i];
|
||||
QScriptItem &si = eng->layoutData->items[item];
|
||||
QScriptItem &si = eng->layoutData->items[i];
|
||||
|
||||
if (si.analysis.flags < QScriptAnalysis::TabOrObject) {
|
||||
QGlyphLayout glyphs = eng->shapedGlyphs(&si);
|
||||
QFontEngine *fe = f.d->engineForScript(si.analysis.script);
|
||||
Q_ASSERT(fe);
|
||||
fe->addOutlineToPath(x, y, glyphs, this,
|
||||
si.analysis.bidiLevel % 2
|
||||
? QTextItem::RenderFlags(QTextItem::RightToLeft)
|
||||
: QTextItem::RenderFlags(0));
|
||||
fe->addOutlineToPath(x, y, glyphs, this, QTextItem::RenderFlags(0));
|
||||
|
||||
const qreal lw = fe->lineThickness().toReal();
|
||||
if (f.d->underline) {
|
||||
|
|
|
@ -113,8 +113,6 @@ static bool qHB_ConvertStringToGlyphIndices(HB_ShaperItem *shaper_item)
|
|||
QVarLengthGlyphLayoutArray qglyphs(shaper_item->num_glyphs);
|
||||
|
||||
QTextEngine::ShaperFlags shaperFlags(QTextEngine::GlyphIndicesOnly);
|
||||
if (shaper_item->item.bidiLevel % 2)
|
||||
shaperFlags |= QTextEngine::RightToLeft;
|
||||
|
||||
int nGlyphs = shaper_item->num_glyphs;
|
||||
bool result = fe->stringToCMap(reinterpret_cast<const QChar *>(shaper_item->string + shaper_item->item.pos),
|
||||
|
@ -270,8 +268,6 @@ static inline void positionCluster(HB_ShaperItem *item, int gfrom, int glast)
|
|||
//qreal offsetBase = (size - 4) / 4 + qMin<qreal>(size, 4) + 1;
|
||||
// qDebug("offset = %f", offsetBase);
|
||||
|
||||
bool rightToLeft = item->item.bidiLevel % 2;
|
||||
|
||||
int i;
|
||||
unsigned char lastCmb = 0;
|
||||
HB_GlyphMetrics attachmentRect;
|
||||
|
@ -365,13 +361,8 @@ static inline void positionCluster(HB_ShaperItem *item, int gfrom, int glast)
|
|||
attachmentRect = unitedAttachmentRect;
|
||||
|
||||
lastCmb = cmb;
|
||||
if (rightToLeft) {
|
||||
item->offsets[gfrom+i].x = p.x;
|
||||
item->offsets[gfrom+i].y = p.y;
|
||||
} else {
|
||||
item->offsets[gfrom+i].x = p.x - baseMetrics.xOffset;
|
||||
item->offsets[gfrom+i].y = p.y - baseMetrics.yOffset;
|
||||
}
|
||||
item->offsets[gfrom+i].x = p.x - baseMetrics.xOffset;
|
||||
item->offsets[gfrom+i].y = p.y - baseMetrics.yOffset;
|
||||
item->advances[gfrom+i] = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -400,7 +400,6 @@ typedef struct {
|
|||
uint32_t pos;
|
||||
uint32_t length;
|
||||
HB_Script script;
|
||||
uint8_t bidiLevel;
|
||||
} HB_ScriptItem;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -78,8 +78,7 @@ public:
|
|||
// the font and because Japanese and Chinese are also aliases of the script "Common",
|
||||
// doing this would break too many things. So instead we only pass the full stop
|
||||
// along, and nothing else.
|
||||
if (m_analysis[i].bidiLevel == m_analysis[start].bidiLevel
|
||||
&& m_analysis[i].flags == m_analysis[start].flags
|
||||
if (m_analysis[i].flags == m_analysis[start].flags
|
||||
&& (m_analysis[i].script == m_analysis[start].script || m_string[i] == QLatin1Char('.'))
|
||||
&& m_analysis[i].flags < QScriptAnalysis::SpaceTabOrObject
|
||||
&& i - start < MaxItemLength)
|
||||
|
@ -99,88 +98,12 @@ private:
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// The BiDi algorithm
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
#if (BIDI_DEBUG >= 1)
|
||||
static const char *directions[] = {
|
||||
"DirL", "DirR", "DirEN", "DirES", "DirET", "DirAN", "DirCS", "DirB", "DirS", "DirWS", "DirON",
|
||||
"DirLRE", "DirLRO", "DirAL", "DirRLE", "DirRLO", "DirPDF", "DirNSM", "DirBN", "DirLRI",
|
||||
"DirRLI", "DirFSI", "DirPDI"
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void QTextEngine::bidiReorder(int numItems, const quint8 *levels, int *visualOrder)
|
||||
{
|
||||
|
||||
// first find highest and lowest levels
|
||||
quint8 levelLow = 128;
|
||||
quint8 levelHigh = 0;
|
||||
int i = 0;
|
||||
while (i < numItems) {
|
||||
//printf("level = %d\n", r->level);
|
||||
if (levels[i] > levelHigh)
|
||||
levelHigh = levels[i];
|
||||
if (levels[i] < levelLow)
|
||||
levelLow = levels[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
// implements reordering of the line (L2 according to BiDi spec):
|
||||
// L2. From the highest level found in the text to the lowest odd level on each line,
|
||||
// reverse any contiguous sequence of characters that are at that level or higher.
|
||||
|
||||
// reversing is only done up to the lowest odd level
|
||||
if(!(levelLow%2)) levelLow++;
|
||||
|
||||
#if (BIDI_DEBUG >= 1)
|
||||
// qDebug() << "reorderLine: lineLow = " << (uint)levelLow << ", lineHigh = " << (uint)levelHigh;
|
||||
#endif
|
||||
|
||||
int count = numItems - 1;
|
||||
for (i = 0; i < numItems; i++)
|
||||
visualOrder[i] = i;
|
||||
|
||||
while(levelHigh >= levelLow) {
|
||||
int i = 0;
|
||||
while (i < count) {
|
||||
while(i < count && levels[i] < levelHigh) i++;
|
||||
int start = i;
|
||||
while(i <= count && levels[i] >= levelHigh) i++;
|
||||
int end = i-1;
|
||||
|
||||
if(start != end) {
|
||||
//qDebug() << "reversing from " << start << " to " << end;
|
||||
for(int j = 0; j < (end-start+1)/2; j++) {
|
||||
int tmp = visualOrder[start+j];
|
||||
visualOrder[start+j] = visualOrder[end-j];
|
||||
visualOrder[end-j] = tmp;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
levelHigh--;
|
||||
}
|
||||
|
||||
#if (BIDI_DEBUG >= 1)
|
||||
// qDebug() << "visual order is:";
|
||||
// for (i = 0; i < numItems; i++)
|
||||
// qDebug() << visualOrder[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
// ask the font engine to find out which glyphs (as an index in the specific font) to use for the text in one item.
|
||||
static bool stringToGlyphs(HB_ShaperItem *item, QGlyphLayout *glyphs, QFontEngine *fontEngine)
|
||||
{
|
||||
int nGlyphs = item->num_glyphs;
|
||||
|
||||
QTextEngine::ShaperFlags shaperFlags(QTextEngine::GlyphIndicesOnly);
|
||||
if (item->item.bidiLevel % 2)
|
||||
shaperFlags |= QTextEngine::RightToLeft;
|
||||
|
||||
bool result = fontEngine->stringToCMap(reinterpret_cast<const QChar *>(item->string + item->item.pos), item->item.length, glyphs, &nGlyphs, shaperFlags);
|
||||
item->num_glyphs = nGlyphs;
|
||||
|
@ -298,7 +221,6 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
|
|||
entire_shaper_item.item.script = (HB_Script)si.analysis.script;
|
||||
entire_shaper_item.item.pos = si.position;
|
||||
entire_shaper_item.item.length = length(item);
|
||||
entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel;
|
||||
|
||||
entire_shaper_item.shaperFlags = 0;
|
||||
if (!kerningEnabled)
|
||||
|
@ -487,12 +409,6 @@ void QTextEngine::itemize() const
|
|||
QSTACKARRAY(QScriptAnalysis, scriptAnalysis, length);
|
||||
QScriptAnalysis *analysis = scriptAnalysis;
|
||||
|
||||
if (option.textDirection() == Qt::RightToLeft) {
|
||||
for (int i = 0; i < length; ++i)
|
||||
analysis[i].bidiLevel = 1;
|
||||
layoutData->hasBidi = true;
|
||||
}
|
||||
|
||||
const ushort *uc = reinterpret_cast<const ushort *>(layoutData->string.unicode());
|
||||
const ushort *e = uc + length;
|
||||
QUnicodeTables::Script lastScript = QUnicodeTables::Common;
|
||||
|
@ -503,8 +419,6 @@ void QTextEngine::itemize() const
|
|||
analysis->flags = QScriptAnalysis::Object;
|
||||
break;
|
||||
case QChar::LineSeparator:
|
||||
if (analysis->bidiLevel % 2)
|
||||
--analysis->bidiLevel;
|
||||
analysis->script = QUnicodeTables::Common;
|
||||
analysis->flags = QScriptAnalysis::LineOrParagraphSeparator;
|
||||
if (option.flags() & QTextOption::ShowLineAndParagraphSeparators)
|
||||
|
@ -513,14 +427,12 @@ void QTextEngine::itemize() const
|
|||
case 9: // Tab
|
||||
analysis->script = QUnicodeTables::Common;
|
||||
analysis->flags = QScriptAnalysis::Tab;
|
||||
analysis->bidiLevel = 0;
|
||||
break;
|
||||
case 32: // Space
|
||||
case QChar::Nbsp:
|
||||
if (option.flags() & QTextOption::ShowTabsAndSpaces) {
|
||||
analysis->script = QUnicodeTables::Common;
|
||||
analysis->flags = QScriptAnalysis::Space;
|
||||
analysis->bidiLevel = 0;
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
|
@ -578,25 +490,6 @@ void QTextEngine::itemize() const
|
|||
resolveAdditionalFormats();
|
||||
}
|
||||
|
||||
bool QTextEngine::isRightToLeft() const
|
||||
{
|
||||
switch (option.textDirection()) {
|
||||
case Qt::LeftToRight:
|
||||
return false;
|
||||
case Qt::RightToLeft:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!layoutData)
|
||||
itemize();
|
||||
// this places the cursor in the right position depending on the keyboard layout
|
||||
if (layoutData->string.isEmpty())
|
||||
return QApplication::keyboardInputDirection() == Qt::RightToLeft;
|
||||
return layoutData->string.isRightToLeft();
|
||||
}
|
||||
|
||||
|
||||
int QTextEngine::findItem(int strPos) const
|
||||
{
|
||||
itemize();
|
||||
|
@ -1015,8 +908,7 @@ void QTextEngine::justify(const QScriptLine &line)
|
|||
}
|
||||
}
|
||||
|
||||
QFixed leading = leadingSpaceWidth(line);
|
||||
QFixed need = line.width - line.textWidth - leading;
|
||||
QFixed need = line.width - line.textWidth;
|
||||
if (need < 0) {
|
||||
// line overflows already!
|
||||
const_cast<QScriptLine &>(line).justified = true;
|
||||
|
@ -1105,7 +997,6 @@ QTextEngine::LayoutData::LayoutData()
|
|||
allocated = 0;
|
||||
memory_on_stack = false;
|
||||
used = 0;
|
||||
hasBidi = false;
|
||||
layoutState = LayoutEmpty;
|
||||
haveCharAttributes = false;
|
||||
logClustersPtr = 0;
|
||||
|
@ -1139,7 +1030,6 @@ QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, int
|
|||
::memset(memory, 0, space_charAttributes * QT_POINTER_SIZE);
|
||||
}
|
||||
used = 0;
|
||||
hasBidi = false;
|
||||
layoutState = LayoutEmpty;
|
||||
haveCharAttributes = false;
|
||||
}
|
||||
|
@ -1225,7 +1115,6 @@ void QTextEngine::freeMemory()
|
|||
layoutData = 0;
|
||||
} else {
|
||||
layoutData->used = 0;
|
||||
layoutData->hasBidi = false;
|
||||
layoutData->layoutState = LayoutEmpty;
|
||||
layoutData->haveCharAttributes = false;
|
||||
}
|
||||
|
@ -1566,20 +1455,6 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const
|
|||
|
||||
QList<QTextOption::Tab> tabArray = option.tabs();
|
||||
if (!tabArray.isEmpty()) {
|
||||
if (isRightToLeft()) { // rebase the tabArray positions.
|
||||
QList<QTextOption::Tab> newTabs;
|
||||
QList<QTextOption::Tab>::Iterator iter = tabArray.begin();
|
||||
while(iter != tabArray.end()) {
|
||||
QTextOption::Tab tab = *iter;
|
||||
if (tab.type == QTextOption::LeftTab)
|
||||
tab.type = QTextOption::RightTab;
|
||||
else if (tab.type == QTextOption::RightTab)
|
||||
tab.type = QTextOption::LeftTab;
|
||||
newTabs << tab;
|
||||
++iter;
|
||||
}
|
||||
tabArray = newTabs;
|
||||
}
|
||||
for (int i = 0; i < tabArray.size(); ++i) {
|
||||
QFixed tab = QFixed::fromReal(tabArray[i].position) * dpiScale;
|
||||
if (tab > x) { // this is the tab we need.
|
||||
|
@ -1663,16 +1538,6 @@ void QTextEngine::resolveAdditionalFormats() const
|
|||
specialData->resolvedFormatIndices = indices;
|
||||
}
|
||||
|
||||
QFixed QTextEngine::leadingSpaceWidth(const QScriptLine &line)
|
||||
{
|
||||
if (!line.hasTrailingSpaces
|
||||
|| (option.flags() & QTextOption::IncludeTrailingSpaces)
|
||||
|| !isRightToLeft())
|
||||
return QFixed();
|
||||
|
||||
return width(line.from + line.length, line.trailingSpaces);
|
||||
}
|
||||
|
||||
QFixed QTextEngine::alignLine(const QScriptLine &line)
|
||||
{
|
||||
QFixed x = 0;
|
||||
|
@ -1680,8 +1545,6 @@ QFixed QTextEngine::alignLine(const QScriptLine &line)
|
|||
// if width is QFIXED_MAX that means we used setNumColumns() and that implicitly makes this line left aligned.
|
||||
if (!line.justified && line.width != QFIXED_MAX) {
|
||||
int align = option.alignment();
|
||||
if (align & Qt::AlignJustify && isRightToLeft())
|
||||
align = Qt::AlignRight;
|
||||
if (align & Qt::AlignRight)
|
||||
x = line.width - (line.textAdvance);
|
||||
else if (align & Qt::AlignHCenter)
|
||||
|
@ -1838,25 +1701,16 @@ int QTextEngine::lineNumberForTextPosition(int pos)
|
|||
void QTextEngine::insertionPointsForLine(int lineNum, QVector<int> &insertionPoints)
|
||||
{
|
||||
QTextLineItemIterator iterator(this, lineNum);
|
||||
bool rtl = isRightToLeft();
|
||||
bool lastLine = lineNum >= lines.size() - 1;
|
||||
|
||||
while (!iterator.atEnd()) {
|
||||
iterator.next();
|
||||
const QScriptItem *si = &layoutData->items[iterator.item];
|
||||
if (si->analysis.bidiLevel % 2) {
|
||||
int i = iterator.itemEnd - 1, min = iterator.itemStart;
|
||||
if (lastLine && (rtl ? iterator.atBeginning() : iterator.atEnd()))
|
||||
i++;
|
||||
for (; i >= min; i--)
|
||||
insertionPoints.push_back(i);
|
||||
} else {
|
||||
int i = iterator.itemStart, max = iterator.itemEnd;
|
||||
if (lastLine && (rtl ? iterator.atBeginning() : iterator.atEnd()))
|
||||
max++;
|
||||
for (; i < max; i++)
|
||||
insertionPoints.push_back(i);
|
||||
}
|
||||
int i = iterator.itemStart, max = iterator.itemEnd;
|
||||
if (lastLine && iterator.atEnd())
|
||||
max++;
|
||||
for (; i < max; i++)
|
||||
insertionPoints.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1886,37 +1740,8 @@ int QTextEngine::positionAfterVisualMovement(int pos, QTextCursor::MoveOperation
|
|||
itemize();
|
||||
|
||||
bool moveRight = (op == QTextCursor::Right);
|
||||
bool alignRight = isRightToLeft();
|
||||
if (!layoutData->hasBidi)
|
||||
return moveRight ^ alignRight ? nextLogicalPosition(pos) : previousLogicalPosition(pos);
|
||||
|
||||
int lineNum = lineNumberForTextPosition(pos);
|
||||
Q_ASSERT(lineNum >= 0);
|
||||
|
||||
QVector<int> insertionPoints;
|
||||
insertionPointsForLine(lineNum, insertionPoints);
|
||||
int i, max = insertionPoints.size();
|
||||
for (i = 0; i < max; i++)
|
||||
if (pos == insertionPoints[i]) {
|
||||
if (moveRight) {
|
||||
if (i + 1 < max)
|
||||
return insertionPoints[i + 1];
|
||||
} else {
|
||||
if (i > 0)
|
||||
return insertionPoints[i - 1];
|
||||
}
|
||||
|
||||
if (moveRight ^ alignRight) {
|
||||
if (lineNum + 1 < lines.size())
|
||||
return alignRight ? endOfLine(lineNum + 1) : beginningOfLine(lineNum + 1);
|
||||
}
|
||||
else {
|
||||
if (lineNum > 0)
|
||||
return alignRight ? beginningOfLine(lineNum - 1) : endOfLine(lineNum - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
return (moveRight ? nextLogicalPosition(pos) : previousLogicalPosition(pos));
|
||||
}
|
||||
|
||||
QStackTextEngine::QStackTextEngine(const QString &string, const QFont &f)
|
||||
|
@ -1950,8 +1775,6 @@ void QTextItemInt::initWithScriptItem(const QScriptItem &si)
|
|||
// explicitly initialize flags so that initFontAttributes can be called
|
||||
// multiple times on the same TextItem
|
||||
flags = 0;
|
||||
if (si.analysis.bidiLevel %2)
|
||||
flags |= QTextItem::RightToLeft;
|
||||
ascent = si.ascent;
|
||||
descent = si.descent;
|
||||
|
||||
|
@ -1984,8 +1807,6 @@ QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int _lineNum, co
|
|||
nItems((firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0),
|
||||
logicalItem(-1),
|
||||
item(-1),
|
||||
visualOrder(nItems),
|
||||
levels(nItems),
|
||||
selection(_selection)
|
||||
{
|
||||
pos_x = x = QFixed::fromReal(pos.x());
|
||||
|
@ -1994,10 +1815,6 @@ QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int _lineNum, co
|
|||
|
||||
x += eng->alignLine(line);
|
||||
|
||||
for (int i = 0; i < nItems; ++i)
|
||||
levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
|
||||
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
|
||||
|
||||
eng->shapeLine(line);
|
||||
}
|
||||
|
||||
|
@ -2006,7 +1823,7 @@ QScriptItem &QTextLineItemIterator::next()
|
|||
x += itemWidth;
|
||||
|
||||
++logicalItem;
|
||||
item = visualOrder[logicalItem] + firstItem;
|
||||
item = (logicalItem + firstItem);
|
||||
itemLength = eng->length(item);
|
||||
si = &eng->layoutData->items[item];
|
||||
if (!si->num_glyphs)
|
||||
|
@ -2068,17 +1885,10 @@ bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selec
|
|||
int end_glyph = (to == eng->length(item)) ? si->num_glyphs : logClusters[to];
|
||||
QFixed soff;
|
||||
QFixed swidth;
|
||||
if (si->analysis.bidiLevel %2) {
|
||||
for (int g = glyphsEnd - 1; g >= end_glyph; --g)
|
||||
soff += glyphs.effectiveAdvance(g);
|
||||
for (int g = end_glyph - 1; g >= start_glyph; --g)
|
||||
swidth += glyphs.effectiveAdvance(g);
|
||||
} else {
|
||||
for (int g = glyphsStart; g < start_glyph; ++g)
|
||||
soff += glyphs.effectiveAdvance(g);
|
||||
for (int g = start_glyph; g < end_glyph; ++g)
|
||||
swidth += glyphs.effectiveAdvance(g);
|
||||
}
|
||||
for (int g = glyphsStart; g < start_glyph; ++g)
|
||||
soff += glyphs.effectiveAdvance(g);
|
||||
for (int g = start_glyph; g < end_glyph; ++g)
|
||||
swidth += glyphs.effectiveAdvance(g);
|
||||
|
||||
// If the starting character is in the middle of a ligature,
|
||||
// selection should only contain the right part of that ligature
|
||||
|
|
|
@ -90,10 +90,9 @@ struct Q_AUTOTEST_EXPORT QScriptAnalysis
|
|||
Object = 4
|
||||
};
|
||||
QUnicodeTables::Script script;
|
||||
unsigned short bidiLevel; // Unicode Bidi algorithm embedding level (0-61)
|
||||
Flags flags;
|
||||
inline bool operator == (const QScriptAnalysis &other) const {
|
||||
return script == other.script && bidiLevel == other.bidiLevel && flags == other.flags;
|
||||
return script == other.script && flags == other.flags;
|
||||
}
|
||||
};
|
||||
Q_DECLARE_TYPEINFO(QScriptAnalysis, Q_PRIMITIVE_TYPE);
|
||||
|
@ -356,7 +355,6 @@ public:
|
|||
unsigned short *logClustersPtr;
|
||||
QGlyphLayout glyphLayout;
|
||||
mutable int used;
|
||||
bool hasBidi;
|
||||
LayoutState layoutState;
|
||||
bool memory_on_stack;
|
||||
bool haveCharAttributes;
|
||||
|
@ -383,9 +381,6 @@ public:
|
|||
void validate() const;
|
||||
void itemize() const;
|
||||
|
||||
bool isRightToLeft() const;
|
||||
static void bidiReorder(int numRuns, const quint8 *levels, int *visualOrder);
|
||||
|
||||
const HB_CharAttributes *attributes() const;
|
||||
|
||||
void shape(int item) const;
|
||||
|
@ -509,7 +504,6 @@ public:
|
|||
QString elidedText(Qt::TextElideMode mode, const QFixed &width, int flags = 0) const;
|
||||
|
||||
void shapeLine(const QScriptLine &line);
|
||||
QFixed leadingSpaceWidth(const QScriptLine &line);
|
||||
|
||||
QFixed offsetInLigature(const QScriptItem *si, int pos, int max, int glyph_pos);
|
||||
int positionInLigature(const QScriptItem *si, int end, QFixed x, QFixed edge, int glyph_pos, bool cursorOnCharacter);
|
||||
|
@ -577,9 +571,6 @@ struct QTextLineItemIterator
|
|||
|
||||
QFixed itemWidth;
|
||||
|
||||
QVarLengthArray<int> visualOrder;
|
||||
QVarLengthArray<uchar> levels;
|
||||
|
||||
const QTextLayout::FormatRange *selection;
|
||||
};
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ QTextFormat QTextInlineObject::format() const
|
|||
*/
|
||||
Qt::LayoutDirection QTextInlineObject::textDirection() const
|
||||
{
|
||||
return (eng->layoutData->items[itm].analysis.bidiLevel % 2 ? Qt::RightToLeft : Qt::LeftToRight);
|
||||
return Qt::LeftToRight;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1027,7 +1027,6 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRang
|
|||
|
||||
QRectF lineRect(tl.naturalTextRect());
|
||||
lineRect.translate(position);
|
||||
lineRect.adjust(0, 0, d->leadingSpaceWidth(sl).toReal(), 0);
|
||||
|
||||
bool isLastLineInBlock = (line == d->lines.size()-1);
|
||||
int sl_length = sl.length + (isLastLineInBlock? 1 : 0); // the infamous newline
|
||||
|
@ -1202,14 +1201,12 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
|
|||
|
||||
QFixed base = sl.base();
|
||||
QFixed descent = sl.descent;
|
||||
bool rightToLeft = d->isRightToLeft();
|
||||
if (itm >= 0) {
|
||||
const QScriptItem &si = d->layoutData->items.at(itm);
|
||||
if (si.ascent > 0)
|
||||
base = si.ascent;
|
||||
if (si.descent > 0)
|
||||
descent = si.descent;
|
||||
rightToLeft = si.analysis.bidiLevel % 2;
|
||||
}
|
||||
qreal y = position.y() + (sl.y + sl.base() - base).toReal();
|
||||
bool toggleAntialiasing = !(p->renderHints() & QPainter::Antialiasing)
|
||||
|
@ -1219,13 +1216,6 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
|
|||
p->fillRect(QRectF(x, y, qreal(width), (base + descent + 1).toReal()), p->pen().brush());
|
||||
if (toggleAntialiasing)
|
||||
p->setRenderHint(QPainter::Antialiasing, false);
|
||||
if (d->layoutData->hasBidi) {
|
||||
const int arrow_extent = 4;
|
||||
int sign = rightToLeft ? -1 : 1;
|
||||
p->drawLine(QLineF(x, y, x + (sign * arrow_extent/2), y + arrow_extent/2));
|
||||
p->drawLine(QLineF(x, y+arrow_extent, x + (sign * arrow_extent/2), y + arrow_extent/2));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1966,9 +1956,6 @@ static void drawMenuText(QPainter *p, QFixed x, QFixed y, const QScriptItem &si,
|
|||
if (ul)
|
||||
while (*ul != -1 && *ul < start)
|
||||
++ul;
|
||||
bool rtl = si.analysis.bidiLevel % 2;
|
||||
if (rtl)
|
||||
x += si.width;
|
||||
|
||||
do {
|
||||
int gtmp = ge;
|
||||
|
@ -1988,12 +1975,9 @@ static void drawMenuText(QPainter *p, QFixed x, QFixed y, const QScriptItem &si,
|
|||
}
|
||||
start = stmp;
|
||||
gf.width = w;
|
||||
if (rtl)
|
||||
x -= w;
|
||||
if (gf.num_chars)
|
||||
p->drawTextItem(QPointF(x.toReal(), y.toReal()), gf);
|
||||
if (!rtl)
|
||||
x += w;
|
||||
x += w;
|
||||
if (ul && *ul != -1 && *ul < end) {
|
||||
// draw underline
|
||||
gtmp = (*ul == end-1) ? ge : logClusters[*ul+1-si.position];
|
||||
|
@ -2010,11 +1994,8 @@ static void drawMenuText(QPainter *p, QFixed x, QFixed y, const QScriptItem &si,
|
|||
++start;
|
||||
gf.width = w;
|
||||
gf.underlineStyle = QTextCharFormat::SingleUnderline;
|
||||
if (rtl)
|
||||
x -= w;
|
||||
p->drawTextItem(QPointF(x.toReal(), y.toReal()), gf);
|
||||
if (!rtl)
|
||||
x += w;
|
||||
x += w;
|
||||
gf.underlineStyle = QTextCharFormat::NoUnderline;
|
||||
++gf.chars;
|
||||
++ul;
|
||||
|
@ -2279,7 +2260,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
|
|||
bool lastLine = i >= eng->lines.size() - 1;
|
||||
|
||||
QFixed x = line.x;
|
||||
x += eng->alignLine(line) - eng->leadingSpaceWidth(line);
|
||||
x += eng->alignLine(line);
|
||||
|
||||
if (!i && !eng->layoutData->items.size()) {
|
||||
*cursorPos = 0;
|
||||
|
@ -2326,23 +2307,14 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
|
|||
glyph_pos++;
|
||||
}
|
||||
|
||||
bool reverse = eng->layoutData->items[itm].analysis.bidiLevel % 2;
|
||||
|
||||
|
||||
// add the items left of the cursor
|
||||
|
||||
int firstItem = eng->findItem(line.from);
|
||||
int lastItem = eng->findItem(lineEnd - 1);
|
||||
int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
|
||||
|
||||
QVarLengthArray<int> visualOrder(nItems);
|
||||
QVarLengthArray<uchar> levels(nItems);
|
||||
for (int i = 0; i < nItems; ++i)
|
||||
levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
|
||||
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
|
||||
|
||||
for (int i = 0; i < nItems; ++i) {
|
||||
int item = visualOrder[i]+firstItem;
|
||||
int item = (i + firstItem);
|
||||
if (item == itm)
|
||||
break;
|
||||
QScriptItem &si = eng->layoutData->items[item];
|
||||
|
@ -2372,27 +2344,17 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
|
|||
logClusters = eng->logClusters(si);
|
||||
glyphs = eng->shapedGlyphs(si);
|
||||
if (si->analysis.flags >= QScriptAnalysis::TabOrObject) {
|
||||
if (pos == (reverse ? 0 : l))
|
||||
if (pos == l)
|
||||
x += si->width;
|
||||
} else {
|
||||
bool rtl = eng->isRightToLeft();
|
||||
bool visual = eng->visualCursorMovement();
|
||||
int end = qMin(lineEnd, si->position + l) - si->position;
|
||||
if (reverse) {
|
||||
int glyph_end = end == l ? si->num_glyphs : logClusters[end];
|
||||
int glyph_start = glyph_pos;
|
||||
if (visual && !rtl && !(lastLine && itm == (visualOrder[nItems - 1] + firstItem)))
|
||||
glyph_start++;
|
||||
for (int i = glyph_end - 1; i >= glyph_start; i--)
|
||||
x += glyphs.effectiveAdvance(i);
|
||||
} else {
|
||||
int start = qMax(line.from - si->position, 0);
|
||||
int glyph_start = logClusters[start];
|
||||
int glyph_end = glyph_pos;
|
||||
if (!visual || !rtl || (lastLine && itm == visualOrder[0] + firstItem))
|
||||
glyph_end--;
|
||||
for (int i = glyph_start; i <= glyph_end; i++)
|
||||
x += glyphs.effectiveAdvance(i);
|
||||
int start = qMax(line.from - si->position, 0);
|
||||
int glyph_start = logClusters[start];
|
||||
int glyph_end = glyph_pos;
|
||||
glyph_end--;
|
||||
for (int i = glyph_start; i <= glyph_end; i++) {
|
||||
x += glyphs.effectiveAdvance(i);
|
||||
}
|
||||
x += eng->offsetInLigature(si, pos, end, glyph_pos);
|
||||
}
|
||||
|
@ -2441,22 +2403,14 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
|
|||
x -= eng->alignLine(line);
|
||||
// qDebug("xToCursor: x=%f, cpos=%d", x.toReal(), cpos);
|
||||
|
||||
QSTACKARRAY(int, visualOrder, nItems);
|
||||
QSTACKARRAY(unsigned char, levels, nItems);
|
||||
for (int i = 0; i < nItems; ++i)
|
||||
levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
|
||||
QTextEngine::bidiReorder(nItems, levels, visualOrder);
|
||||
|
||||
bool visual = eng->visualCursorMovement();
|
||||
if (x <= 0) {
|
||||
// left of first item
|
||||
int item = visualOrder[0]+firstItem;
|
||||
int item = firstItem;
|
||||
QScriptItem &si = eng->layoutData->items[item];
|
||||
if (!si.num_glyphs)
|
||||
eng->shape(item);
|
||||
int pos = si.position;
|
||||
if (si.analysis.bidiLevel % 2)
|
||||
pos += eng->length(item);
|
||||
pos = qMax(line.from, pos);
|
||||
pos = qMin(line.from + line_length, pos);
|
||||
return pos;
|
||||
|
@ -2464,15 +2418,11 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
|
|||
|| (line.justified && x < line.width)) {
|
||||
// has to be in one of the runs
|
||||
QFixed pos;
|
||||
bool rtl = eng->isRightToLeft();
|
||||
|
||||
eng->shapeLine(line);
|
||||
QVector<int> insertionPoints;
|
||||
if (visual && rtl)
|
||||
eng->insertionPointsForLine(lineNum, insertionPoints);
|
||||
int nchars = 0;
|
||||
for (int i = 0; i < nItems; ++i) {
|
||||
int item = visualOrder[i]+firstItem;
|
||||
int item = (i + firstItem);
|
||||
QScriptItem &si = eng->layoutData->items[item];
|
||||
int item_length = eng->length(item);
|
||||
// qDebug(" item %d, visual %d x_remain=%f", i, item, x.toReal());
|
||||
|
@ -2509,7 +2459,7 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
|
|||
return si.position;
|
||||
bool left_half = (x - pos) < item_width/2;
|
||||
|
||||
if (bool(si.analysis.bidiLevel % 2) != left_half)
|
||||
if (left_half)
|
||||
return si.position;
|
||||
return si.position + 1;
|
||||
}
|
||||
|
@ -2518,91 +2468,34 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
|
|||
QFixed edge;
|
||||
// has to be inside run
|
||||
if (cpos == QTextLine::CursorOnCharacter) {
|
||||
if (si.analysis.bidiLevel % 2) {
|
||||
pos += item_width;
|
||||
glyph_pos = gs;
|
||||
while (gs <= ge) {
|
||||
if (glyphs.attributes[gs].clusterStart) {
|
||||
if (pos < x)
|
||||
break;
|
||||
glyph_pos = gs;
|
||||
edge = pos;
|
||||
glyph_pos = gs;
|
||||
while (gs <= ge) {
|
||||
if (glyphs.attributes[gs].clusterStart) {
|
||||
if (pos > x)
|
||||
break;
|
||||
}
|
||||
pos -= glyphs.effectiveAdvance(gs);
|
||||
++gs;
|
||||
}
|
||||
} else {
|
||||
glyph_pos = gs;
|
||||
while (gs <= ge) {
|
||||
if (glyphs.attributes[gs].clusterStart) {
|
||||
if (pos > x)
|
||||
break;
|
||||
glyph_pos = gs;
|
||||
edge = pos;
|
||||
}
|
||||
pos += glyphs.effectiveAdvance(gs);
|
||||
++gs;
|
||||
glyph_pos = gs;
|
||||
edge = pos;
|
||||
}
|
||||
pos += glyphs.effectiveAdvance(gs);
|
||||
++gs;
|
||||
}
|
||||
} else {
|
||||
QFixed dist = INT_MAX/256;
|
||||
if (si.analysis.bidiLevel % 2) {
|
||||
if (!visual || rtl || (lastLine && i == nItems - 1)) {
|
||||
pos += item_width;
|
||||
while (gs <= ge) {
|
||||
if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
|
||||
glyph_pos = gs;
|
||||
edge = pos;
|
||||
dist = qAbs(x-pos);
|
||||
}
|
||||
pos -= glyphs.effectiveAdvance(gs);
|
||||
++gs;
|
||||
}
|
||||
} else {
|
||||
while (ge >= gs) {
|
||||
if (glyphs.attributes[ge].clusterStart && qAbs(x-pos) < dist) {
|
||||
glyph_pos = ge;
|
||||
edge = pos;
|
||||
dist = qAbs(x-pos);
|
||||
}
|
||||
pos += glyphs.effectiveAdvance(ge);
|
||||
--ge;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!visual || !rtl || (lastLine && i == 0)) {
|
||||
while (gs <= ge) {
|
||||
if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
|
||||
glyph_pos = gs;
|
||||
edge = pos;
|
||||
dist = qAbs(x-pos);
|
||||
}
|
||||
pos += glyphs.effectiveAdvance(gs);
|
||||
++gs;
|
||||
}
|
||||
} else {
|
||||
QFixed oldPos = pos;
|
||||
while (gs <= ge) {
|
||||
pos += glyphs.effectiveAdvance(gs);
|
||||
if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
|
||||
glyph_pos = gs;
|
||||
edge = pos;
|
||||
dist = qAbs(x-pos);
|
||||
}
|
||||
++gs;
|
||||
}
|
||||
pos = oldPos;
|
||||
while (gs <= ge) {
|
||||
if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
|
||||
glyph_pos = gs;
|
||||
edge = pos;
|
||||
dist = qAbs(x-pos);
|
||||
}
|
||||
pos += glyphs.effectiveAdvance(gs);
|
||||
++gs;
|
||||
}
|
||||
if (qAbs(x-pos) < dist) {
|
||||
if (visual) {
|
||||
if (!rtl && i < nItems - 1) {
|
||||
if (i < nItems - 1) {
|
||||
nchars += end;
|
||||
continue;
|
||||
}
|
||||
if (rtl && nchars > 0)
|
||||
return insertionPoints[lastLine ? nchars : nchars - 1];
|
||||
}
|
||||
return eng->positionInLigature(&si, end, x, pos, -1,
|
||||
cpos == QTextLine::CursorOnCharacter);
|
||||
|
@ -2615,13 +2508,12 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
|
|||
}
|
||||
// right of last item
|
||||
// qDebug() << "right of last";
|
||||
int item = visualOrder[nItems-1]+firstItem;
|
||||
int item = (nItems -1 + firstItem);
|
||||
QScriptItem &si = eng->layoutData->items[item];
|
||||
if (!si.num_glyphs)
|
||||
eng->shape(item);
|
||||
int pos = si.position;
|
||||
if (!(si.analysis.bidiLevel % 2))
|
||||
pos += eng->length(item);
|
||||
pos += eng->length(item);
|
||||
pos = qMax(line.from, pos);
|
||||
|
||||
int maxPos = line.from + line_length;
|
||||
|
|
Loading…
Add table
Reference in a new issue