diff options
Diffstat (limited to 'src/gui/text/qtextengine.cpp')
-rw-r--r-- | src/gui/text/qtextengine.cpp | 200 |
1 files changed, 31 insertions, 169 deletions
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 26e8141184..ce14793858 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1510,7 +1510,12 @@ void QTextEngine::shapeText(int item) const itemBoundaries.append(0); } - if (Q_UNLIKELY(!shapingEnabled)) { +#if QT_CONFIG(harfbuzz) + if (Q_LIKELY(shapingEnabled && qt_useHarfbuzzNG())) { + si.num_glyphs = shapeTextWithHarfbuzzNG(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled, letterSpacing != 0); + } else +#endif + { ushort *log_clusters = logClusters(&si); int glyph_pos = 0; @@ -1540,12 +1545,6 @@ void QTextEngine::shapeText(int item) const } si.num_glyphs = glyph_pos; -#if QT_CONFIG(harfbuzz) - } else if (Q_LIKELY(qt_useHarfbuzzNG())) { - si.num_glyphs = shapeTextWithHarfbuzzNG(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled, letterSpacing != 0); -#endif - } else { - si.num_glyphs = shapeTextWithHarfbuzz(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled); } if (Q_UNLIKELY(si.num_glyphs == 0)) { Q_UNREACHABLE(); // ### report shaping errors somehow @@ -1800,138 +1799,6 @@ QT_WARNING_POP #endif // harfbuzz - -QT_BEGIN_INCLUDE_NAMESPACE - -#include <private/qharfbuzz_p.h> - -QT_END_INCLUDE_NAMESPACE - -Q_STATIC_ASSERT(sizeof(HB_Glyph) == sizeof(glyph_t)); -Q_STATIC_ASSERT(sizeof(HB_Fixed) == sizeof(QFixed)); -Q_STATIC_ASSERT(sizeof(HB_FixedPoint) == sizeof(QFixedPoint)); - -static inline void moveGlyphData(const QGlyphLayout &destination, const QGlyphLayout &source, int num) -{ - if (num > 0 && destination.glyphs != source.glyphs) - memmove(destination.glyphs, source.glyphs, num * sizeof(glyph_t)); -} - -int QTextEngine::shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const -{ - HB_ShaperItem entire_shaper_item; - memset(&entire_shaper_item, 0, sizeof(entire_shaper_item)); - entire_shaper_item.string = reinterpret_cast<const HB_UChar16 *>(string); - entire_shaper_item.stringLength = itemLength; - entire_shaper_item.item.script = script_to_hbscript(si.analysis.script); - entire_shaper_item.item.pos = 0; - entire_shaper_item.item.length = itemLength; - entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel; - - entire_shaper_item.shaperFlags = 0; - if (!kerningEnabled) - entire_shaper_item.shaperFlags |= HB_ShaperFlag_NoKerning; - if (option.useDesignMetrics()) - entire_shaper_item.shaperFlags |= HB_ShaperFlag_UseDesignMetrics; - - // ensure we are not asserting in HB_HeuristicSetGlyphAttributes() - entire_shaper_item.num_glyphs = 0; - for (int i = 0; i < itemLength; ++i, ++entire_shaper_item.num_glyphs) { - if (QChar::isHighSurrogate(string[i]) && i + 1 < itemLength && QChar::isLowSurrogate(string[i + 1])) - ++i; - } - - - int remaining_glyphs = entire_shaper_item.num_glyphs; - int glyph_pos = 0; - // for each item shape using harfbuzz and store the results in our layoutData's glyphs array. - for (int k = 0; k < itemBoundaries.size(); k += 3) { - HB_ShaperItem shaper_item = entire_shaper_item; - shaper_item.item.pos = itemBoundaries[k]; - if (k + 4 < itemBoundaries.size()) { - shaper_item.item.length = itemBoundaries[k + 3] - shaper_item.item.pos; - shaper_item.num_glyphs = itemBoundaries[k + 4] - itemBoundaries[k + 1]; - } else { // last combo in the list, avoid out of bounds access. - shaper_item.item.length -= shaper_item.item.pos - entire_shaper_item.item.pos; - shaper_item.num_glyphs -= itemBoundaries[k + 1]; - } - shaper_item.initialGlyphCount = shaper_item.num_glyphs; - if (shaper_item.num_glyphs < shaper_item.item.length) - shaper_item.num_glyphs = shaper_item.item.length; - - uint engineIdx = itemBoundaries[k + 2]; - QFontEngine *actualFontEngine = fontEngine; - if (fontEngine->type() == QFontEngine::Multi) { - actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx); - - if ((si.analysis.bidiLevel % 2) == 0) - shaper_item.glyphIndicesPresent = true; - } - - shaper_item.font = (HB_Font)actualFontEngine->harfbuzzFont(); - shaper_item.face = (HB_Face)actualFontEngine->harfbuzzFace(); - - remaining_glyphs -= shaper_item.initialGlyphCount; - - QVarLengthArray<HB_GlyphAttributes, 128> hbGlyphAttributes; - do { - if (!ensureSpace(glyph_pos + shaper_item.num_glyphs + remaining_glyphs)) - return 0; - if (hbGlyphAttributes.size() < int(shaper_item.num_glyphs)) { - hbGlyphAttributes.resize(shaper_item.num_glyphs); - memset(hbGlyphAttributes.data(), 0, hbGlyphAttributes.size() * sizeof(HB_GlyphAttributes)); - } - - const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos); - if (fontEngine->type() == QFontEngine::Multi && shaper_item.num_glyphs > shaper_item.item.length) - moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs); - - shaper_item.glyphs = reinterpret_cast<HB_Glyph *>(g.glyphs); - shaper_item.advances = reinterpret_cast<HB_Fixed *>(g.advances); - shaper_item.offsets = reinterpret_cast<HB_FixedPoint *>(g.offsets); - shaper_item.attributes = hbGlyphAttributes.data(); - - if (engineIdx != 0 && shaper_item.glyphIndicesPresent) { - for (quint32 i = 0; i < shaper_item.initialGlyphCount; ++i) - shaper_item.glyphs[i] &= 0x00ffffff; - } - - shaper_item.log_clusters = logClusters(&si) + shaper_item.item.pos - entire_shaper_item.item.pos; - } while (!qShapeItem(&shaper_item)); // this does the actual shaping via harfbuzz. - - QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos, shaper_item.num_glyphs); - if (fontEngine->type() == QFontEngine::Multi) - moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs); - - for (quint32 i = 0; i < shaper_item.num_glyphs; ++i) { - HB_GlyphAttributes hbAttrs = hbGlyphAttributes.at(i); - QGlyphAttributes &attrs = g.attributes[i]; - attrs.clusterStart = hbAttrs.clusterStart; - attrs.dontPrint = hbAttrs.dontPrint; - attrs.justification = hbAttrs.justification; - } - - for (quint32 i = 0; i < shaper_item.item.length; ++i) { - // Workaround wrong log_clusters for surrogates (i.e. QTBUG-39875) - if (shaper_item.log_clusters[i] >= shaper_item.num_glyphs) - shaper_item.log_clusters[i] = shaper_item.num_glyphs - 1; - shaper_item.log_clusters[i] += glyph_pos; - } - - if (kerningEnabled && !shaper_item.kerning_applied) - actualFontEngine->doKerning(&g, option.useDesignMetrics() ? QFontEngine::DesignMetrics : QFontEngine::ShaperFlags{}); - - if (engineIdx != 0) { - for (quint32 i = 0; i < shaper_item.num_glyphs; ++i) - g.glyphs[i] |= (engineIdx << 24); - } - - glyph_pos += shaper_item.num_glyphs; - } - - return glyph_pos; -} - void QTextEngine::init(QTextEngine *e) { e->ignoreBidi = false; @@ -1985,7 +1852,7 @@ const QCharAttributes *QTextEngine::attributes() const for (int i = 0; i < layoutData->items.size(); ++i) { const QScriptItem &si = layoutData->items.at(i); scriptItems[i].position = si.position; - scriptItems[i].script = si.analysis.script; + scriptItems[i].script = QChar::Script(si.analysis.script); } QUnicodeTools::initCharAttributes(reinterpret_cast<const ushort *>(layoutData->string.constData()), @@ -2005,7 +1872,7 @@ void QTextEngine::shape(int item) const auto &li = layoutData->items[item]; if (li.analysis.flags == QScriptAnalysis::Object) { ensureSpace(1); - if (block.docHandle()) { + if (QTextDocumentPrivate::get(block) != nullptr) { docLayout()->resizeInlineObject(QTextInlineObject(item, const_cast<QTextEngine *>(this)), li.position + block.position(), format(&li)); @@ -2061,7 +1928,7 @@ void QTextEngine::validate() const if (layoutData) return; layoutData = new LayoutData(); - if (block.docHandle()) { + if (QTextDocumentPrivate::get(block) != nullptr) { layoutData->string = block.text(); const bool nextBlockValid = block.next().isValid(); if (!nextBlockValid && option.flags() & QTextOption::ShowDocumentTerminator) { @@ -2098,10 +1965,14 @@ void QTextEngine::itemize() const layoutData->hasBidi = bidi.process(); { - QVarLengthArray<uchar> scripts(length); - QUnicodeTools::initScripts(string, length, scripts.data()); - for (int i = 0; i < length; ++i) - analysis[i].script = scripts.at(i); + QUnicodeTools::ScriptItemArray scriptItems; + QUnicodeTools::initScripts(string, length, &scriptItems); + for (int i = 0; i < scriptItems.length(); ++i) { + const auto &item = scriptItems.at(i); + int end = i < scriptItems.length() - 1 ? scriptItems.at(i + 1).position : length; + for (int j = item.position; j < end; ++j) + analysis[j].script = item.script; + } } const ushort *uc = string; @@ -2137,26 +2008,16 @@ void QTextEngine::itemize() const analysis->flags = QScriptAnalysis::None; break; } -#if !QT_CONFIG(harfbuzz) - analysis->script = hbscript_to_script(script_to_hbscript(analysis->script)); -#endif ++uc; ++analysis; } if (option.flags() & QTextOption::ShowLineAndParagraphSeparators) { (analysis-1)->flags = QScriptAnalysis::LineOrParagraphSeparator; // to exclude it from width } -#if QT_CONFIG(harfbuzz) - analysis = scriptAnalysis.data(); - if (!qt_useHarfbuzzNG()) { - for (int i = 0; i < length; ++i) - analysis[i].script = hbscript_to_script(script_to_hbscript(analysis[i].script)); - } -#endif Itemizer itemizer(layoutData->string, scriptAnalysis.data(), layoutData->items); - const QTextDocumentPrivate *p = block.docHandle(); + const QTextDocumentPrivate *p = QTextDocumentPrivate::get(block); if (p) { SpecialData *s = specialData; @@ -2434,9 +2295,10 @@ QFont QTextEngine::font(const QScriptItem &si) const QTextCharFormat f = format(&si); font = f.font(); - if (block.docHandle() && block.docHandle()->layout()) { + const QTextDocumentPrivate *document_d = QTextDocumentPrivate::get(block); + if (document_d != nullptr && document_d->layout() != nullptr) { // Make sure we get the right dpi on printers - QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); + QPaintDevice *pdev = document_d->layout()->paintDevice(); if (pdev) font = QFont(font, pdev); } else { @@ -2511,9 +2373,9 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix QTextCharFormat f = format(&si); font = f.font(); - if (block.docHandle() && block.docHandle()->layout()) { + if (QTextDocumentPrivate::get(block) != nullptr && QTextDocumentPrivate::get(block)->layout() != nullptr) { // Make sure we get the right dpi on printers - QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); + QPaintDevice *pdev = QTextDocumentPrivate::get(block)->layout()->paintDevice(); if (pdev) font = QFont(font, pdev); } else { @@ -2810,10 +2672,10 @@ void QScriptLine::setDefaultHeight(QTextEngine *eng) QFont f; QFontEngine *e; - if (eng->block.docHandle() && eng->block.docHandle()->layout()) { + if (QTextDocumentPrivate::get(eng->block) != nullptr && QTextDocumentPrivate::get(eng->block)->layout() != nullptr) { f = eng->block.charFormat().font(); // Make sure we get the right dpi on printers - QPaintDevice *pdev = eng->block.docHandle()->layout()->paintDevice(); + QPaintDevice *pdev = QTextDocumentPrivate::get(eng->block)->layout()->paintDevice(); if (pdev) f = QFont(f, pdev); e = f.d->engineForScript(QChar::Script_Common); @@ -2975,7 +2837,7 @@ int QTextEngine::formatIndex(const QScriptItem *si) const return collection->indexForFormat(specialData->resolvedFormats.at(si - &layoutData->items.at(0))); } - QTextDocumentPrivate *p = block.docHandle(); + const QTextDocumentPrivate *p = QTextDocumentPrivate::get(block); if (!p) return -1; int pos = si->position; @@ -3100,7 +2962,7 @@ void QTextEngine::indexFormats() { QTextFormatCollection *collection = formatCollection(); if (!collection) { - Q_ASSERT(!block.docHandle()); + Q_ASSERT(QTextDocumentPrivate::get(block) == nullptr); specialData->formatCollection.reset(new QTextFormatCollection); collection = specialData->formatCollection.data(); } @@ -3362,8 +3224,8 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const const QScriptItem &si = layoutData->items[item]; QFixed dpiScale = 1; - if (block.docHandle() && block.docHandle()->layout()) { - QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); + if (QTextDocumentPrivate::get(block) != nullptr && QTextDocumentPrivate::get(block)->layout() != nullptr) { + QPaintDevice *pdev = QTextDocumentPrivate::get(block)->layout()->paintDevice(); if (pdev) dpiScale = QFixed::fromReal(pdev->logicalDpiY() / qreal(qt_defaultDpiY())); } else { @@ -3525,8 +3387,8 @@ void QTextEngine::resolveFormats() const } QTextCharFormat &format = resolvedFormats[i]; - if (block.docHandle()) { - // when we have a docHandle, formatIndex might still return a valid index based + if (QTextDocumentPrivate::get(block) != nullptr) { + // when we have a QTextDocumentPrivate, formatIndex might still return a valid index based // on the preeditPosition. for all other cases, we cleared the resolved format indices format = collection->charFormat(formatIndex(si)); } |