summaryrefslogtreecommitdiffstats
path: root/src/gui/text/qtextengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/text/qtextengine.cpp')
-rw-r--r--src/gui/text/qtextengine.cpp200
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));
}