diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 78284d1c7..24abf5b29 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -4789,17 +4789,11 @@ void QPainter::drawText(const QPointF &p, const QString &str) engine.shapeLine(line); int nItems = engine.layoutData->items.size(); - QVarLengthArray visualOrder(nItems); - QVarLengthArray 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; jleadingSpaceWidth(eng->lines[line.lineNumber()]).toReal(); + xoff = r.width() - advance; } else if (tf & Qt::AlignHCenter) xoff = (r.width() - advance) / 2; diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 9d173a599..9b0a8b41f 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -1104,24 +1104,14 @@ void QPainterPath::addText(const QPointF &point, const QFont &f, const QString & qreal x(point.x()); qreal y(point.y()); - QVarLengthArray visualOrder(nItems); - QVarLengthArray 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) { diff --git a/src/gui/text/qharfbuzz.cpp b/src/gui/text/qharfbuzz.cpp index 6caf0cbec..a7471b119 100644 --- a/src/gui/text/qharfbuzz.cpp +++ b/src/gui/text/qharfbuzz.cpp @@ -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(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(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; } } diff --git a/src/gui/text/qharfbuzz_p.h b/src/gui/text/qharfbuzz_p.h index 5a4b45107..bd86f92de 100644 --- a/src/gui/text/qharfbuzz_p.h +++ b/src/gui/text/qharfbuzz_p.h @@ -400,7 +400,6 @@ typedef struct { uint32_t pos; uint32_t length; HB_Script script; - uint8_t bidiLevel; } HB_ScriptItem; typedef struct { diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 1e4e395ee..43dbe3b20 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -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(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(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(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 tabArray = option.tabs(); if (!tabArray.isEmpty()) { - if (isRightToLeft()) { // rebase the tabArray positions. - QList newTabs; - QList::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 &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 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 diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 143a9b686..66671a504 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -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 visualOrder; - QVarLengthArray levels; - const QTextLayout::FormatRange *selection; }; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 11586299b..10bb72621 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -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 QVectorleadingSpaceWidth(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 visualOrder(nItems); - QVarLengthArray 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 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;