diff options
Diffstat (limited to 'src/gui/text/qtextengine.cpp')
-rw-r--r-- | src/gui/text/qtextengine.cpp | 140 |
1 files changed, 77 insertions, 63 deletions
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index c6da4b8f4a..ec528760e3 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -101,7 +101,7 @@ private: if (!m_splitter) m_splitter = new QTextBoundaryFinder(QTextBoundaryFinder::Word, - m_string.constData(), m_string.length(), + m_string.constData(), m_string.size(), /*buffer*/nullptr, /*buffer size*/0); m_splitter->setPosition(start); @@ -1675,9 +1675,14 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, hb_buffer_reverse(buffer); } - const uint num_glyphs = hb_buffer_get_length(buffer); + uint num_glyphs = hb_buffer_get_length(buffer); + const bool has_glyphs = num_glyphs > 0; + // If Harfbuzz returns zero glyphs, we have to manually add a missing glyph + if (Q_UNLIKELY(!has_glyphs)) + num_glyphs = 1; + // ensure we have enough space for shaped glyphs and metrics - if (Q_UNLIKELY(num_glyphs == 0 || !ensureSpace(glyphs_shaped + num_glyphs))) { + if (Q_UNLIKELY(!ensureSpace(glyphs_shaped + num_glyphs))) { hb_buffer_destroy(buffer); return 0; } @@ -1685,35 +1690,44 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, // fetch the shaped glyphs and metrics QGlyphLayout g = availableGlyphs(&si).mid(glyphs_shaped, num_glyphs); ushort *log_clusters = logClusters(&si) + item_pos; - - hb_glyph_info_t *infos = hb_buffer_get_glyph_infos(buffer, nullptr); - hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer, nullptr); - uint str_pos = 0; - uint last_cluster = ~0u; - uint last_glyph_pos = glyphs_shaped; - for (uint i = 0; i < num_glyphs; ++i, ++infos, ++positions) { - g.glyphs[i] = infos->codepoint; - - g.advances[i] = QFixed::fromFixed(positions->x_advance); - g.offsets[i].x = QFixed::fromFixed(positions->x_offset); - g.offsets[i].y = QFixed::fromFixed(positions->y_offset); - - uint cluster = infos->cluster; - if (Q_LIKELY(last_cluster != cluster)) { - g.attributes[i].clusterStart = true; - - // fix up clusters so that the cluster indices will be monotonic - // and thus we never return out-of-order indices - while (last_cluster++ < cluster && str_pos < item_length) - log_clusters[str_pos++] = last_glyph_pos; - last_glyph_pos = i + glyphs_shaped; - last_cluster = cluster; - - applyVisibilityRules(string[item_pos + str_pos], &g, i, actualFontEngine); + if (Q_LIKELY(has_glyphs)) { + hb_glyph_info_t *infos = hb_buffer_get_glyph_infos(buffer, nullptr); + hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer, nullptr); + uint str_pos = 0; + uint last_cluster = ~0u; + uint last_glyph_pos = glyphs_shaped; + for (uint i = 0; i < num_glyphs; ++i, ++infos, ++positions) { + g.glyphs[i] = infos->codepoint; + + g.advances[i] = QFixed::fromFixed(positions->x_advance); + g.offsets[i].x = QFixed::fromFixed(positions->x_offset); + g.offsets[i].y = QFixed::fromFixed(positions->y_offset); + + uint cluster = infos->cluster; + if (Q_LIKELY(last_cluster != cluster)) { + g.attributes[i].clusterStart = true; + + // fix up clusters so that the cluster indices will be monotonic + // and thus we never return out-of-order indices + while (last_cluster++ < cluster && str_pos < item_length) + log_clusters[str_pos++] = last_glyph_pos; + last_glyph_pos = i + glyphs_shaped; + last_cluster = cluster; + + applyVisibilityRules(string[item_pos + str_pos], &g, i, actualFontEngine); + } } + while (str_pos < item_length) + log_clusters[str_pos++] = last_glyph_pos; + } else { // Harfbuzz did not return a glyph for the character, so we add a placeholder + g.glyphs[0] = 0; + g.advances[0] = QFixed{}; + g.offsets[0].x = QFixed{}; + g.offsets[0].y = QFixed{}; + g.attributes[0].clusterStart = true; + g.attributes[0].dontPrint = true; + log_clusters[0] = glyphs_shaped; } - while (str_pos < item_length) - log_clusters[str_pos++] = last_glyph_pos; if (Q_UNLIKELY(engineIdx != 0)) { for (quint32 i = 0; i < num_glyphs; ++i) @@ -1781,7 +1795,7 @@ const QCharAttributes *QTextEngine::attributes() const return (QCharAttributes *) layoutData->memory; itemize(); - if (! ensureSpace(layoutData->string.length())) + if (! ensureSpace(layoutData->string.size())) return nullptr; QVarLengthArray<QUnicodeTools::ScriptItem> scriptItems(layoutData->items.size()); @@ -1888,7 +1902,7 @@ void QTextEngine::itemize() const if (layoutData->items.size()) return; - int length = layoutData->string.length(); + int length = layoutData->string.size(); if (!length) return; @@ -1905,9 +1919,9 @@ void QTextEngine::itemize() const { QUnicodeTools::ScriptItemArray scriptItems; QUnicodeTools::initScripts(layoutData->string, &scriptItems); - for (int i = 0; i < scriptItems.length(); ++i) { + for (int i = 0; i < scriptItems.size(); ++i) { const auto &item = scriptItems.at(i); - int end = i < scriptItems.length() - 1 ? scriptItems.at(i + 1).position : length; + int end = i < scriptItems.size() - 1 ? scriptItems.at(i + 1).position : length; for (int j = item.position; j < end; ++j) analysis[j].script = item.script; } @@ -1970,7 +1984,7 @@ void QTextEngine::itemize() const const QTextFragmentData * const frag = it.value(); if (it == end || format != frag->format) { if (s && position >= preeditPosition) { - position += s->preeditText.length(); + position += s->preeditText.size(); preeditPosition = INT_MAX; } Q_ASSERT(position <= length); @@ -1979,7 +1993,7 @@ void QTextEngine::itemize() const ? formatCollection()->charFormat(format).fontCapitalization() : formatCollection()->defaultFont().capitalization(); if (s) { - for (const auto &range : qAsConst(s->formats)) { + for (const auto &range : std::as_const(s->formats)) { if (range.start + range.length <= prevPosition || range.start >= position) continue; if (range.format.hasProperty(QTextFormat::FontCapitalization)) { @@ -2399,7 +2413,7 @@ void QTextEngine::justify(const QScriptLine &line) if (!forceJustification) { int end = line.from + (int)line.length + line.trailingSpaces; - if (end == layoutData->string.length()) + if (end == layoutData->string.size()) return; // no justification at end of paragraph if (end && layoutData->items.at(findItem(end - 1)).analysis.flags == QScriptAnalysis::LineOrParagraphSeparator) return; // no justification at the end of an explicitly separated line @@ -2612,11 +2626,11 @@ QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, int { allocated = _allocated; - int space_charAttributes = int(sizeof(QCharAttributes) * string.length() / sizeof(void*) + 1); - int space_logClusters = int(sizeof(unsigned short) * string.length() / sizeof(void*) + 1); + int space_charAttributes = int(sizeof(QCharAttributes) * string.size() / sizeof(void*) + 1); + int space_logClusters = int(sizeof(unsigned short) * string.size() / sizeof(void*) + 1); available_glyphs = ((int)allocated - space_charAttributes - space_logClusters)*(int)sizeof(void*)/(int)QGlyphLayout::SpaceNeeded; - if (available_glyphs < str.length()) { + if (available_glyphs < str.size()) { // need to allocate on the heap allocated = 0; @@ -2629,7 +2643,7 @@ QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, int logClustersPtr = (unsigned short *)(memory + space_charAttributes); void *m = memory + space_charAttributes + space_logClusters; - glyphLayout = QGlyphLayout(reinterpret_cast<char *>(m), str.length()); + glyphLayout = QGlyphLayout(reinterpret_cast<char *>(m), str.size()); glyphLayout.clear(); memset(memory, 0, space_charAttributes*sizeof(void *)); } @@ -2654,8 +2668,8 @@ bool QTextEngine::LayoutData::reallocate(int totalGlyphs) return true; } - int space_charAttributes = int(sizeof(QCharAttributes) * string.length() / sizeof(void*) + 1); - int space_logClusters = int(sizeof(unsigned short) * string.length() / sizeof(void*) + 1); + int space_charAttributes = int(sizeof(QCharAttributes) * string.size() / sizeof(void*) + 1); + int space_logClusters = int(sizeof(unsigned short) * string.size() / sizeof(void*) + 1); int space_glyphs = (totalGlyphs * QGlyphLayout::SpaceNeeded) / sizeof(void *) + 2; int newAllocated = space_charAttributes + space_glyphs + space_logClusters; @@ -2745,10 +2759,10 @@ int QTextEngine::formatIndex(const QScriptItem *si) const return -1; int pos = si->position; if (specialData && si->position >= specialData->preeditPosition) { - if (si->position < specialData->preeditPosition + specialData->preeditText.length()) + if (si->position < specialData->preeditPosition + specialData->preeditText.size()) pos = qMax(qMin(block.length(), specialData->preeditPosition) - 1, 0); else - pos -= specialData->preeditText.length(); + pos -= specialData->preeditText.size(); } QTextDocumentPrivate::FragmentIterator it = p->find(block.position() + pos); return it.value()->format; @@ -2883,9 +2897,9 @@ void QTextEngine::indexFormats() */ static inline bool nextCharJoins(const QString &string, int pos) { - while (pos < string.length() && string.at(pos).category() == QChar::Mark_NonSpacing) + while (pos < string.size() && string.at(pos).category() == QChar::Mark_NonSpacing) ++pos; - if (pos == string.length()) + if (pos == string.size()) return false; QChar::JoiningType joining = string.at(pos).joiningType(); return joining != QChar::Joining_None && joining != QChar::Joining_Transparent; @@ -2968,12 +2982,12 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, QFixed width, int flags, validate(); - const int to = count >= 0 && count <= layoutData->string.length() - from + const int to = count >= 0 && count <= layoutData->string.size() - from ? from + count - : layoutData->string.length(); + : layoutData->string.size(); if (mode == Qt::ElideNone - || this->width(from, layoutData->string.length()) <= width + || this->width(from, layoutData->string.size()) <= width || to - from <= 1) return layoutData->string.mid(from, from - to); @@ -3040,7 +3054,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, QFixed width, int flags, pos = nextBreak; ++nextBreak; - while (nextBreak < layoutData->string.length() && !attributes[nextBreak].graphemeBoundary) + while (nextBreak < layoutData->string.size() && !attributes[nextBreak].graphemeBoundary) ++nextBreak; currentWidth += this->width(pos, nextBreak - pos); @@ -3092,7 +3106,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, QFixed width, int flags, rightPos = nextRightBreak; ++nextLeftBreak; - while (nextLeftBreak < layoutData->string.length() && !attributes[nextLeftBreak].graphemeBoundary) + while (nextLeftBreak < layoutData->string.size() && !attributes[nextLeftBreak].graphemeBoundary) ++nextLeftBreak; --nextRightBreak; @@ -3165,14 +3179,14 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const } } } - for (const QTextOption::Tab &tabSpec : qAsConst(tabArray)) { + for (const QTextOption::Tab &tabSpec : std::as_const(tabArray)) { QFixed tab = QFixed::fromReal(tabSpec.position) * dpiScale; if (tab > x) { // this is the tab we need. - int tabSectionEnd = layoutData->string.length(); + int tabSectionEnd = layoutData->string.size(); if (tabSpec.type == QTextOption::RightTab || tabSpec.type == QTextOption::CenterTab) { // find next tab to calculate the width required. tab = QFixed::fromReal(tabSpec.position); - for (int i=item + 1; i < layoutData->items.count(); i++) { + for (int i=item + 1; i < layoutData->items.size(); i++) { const QScriptItem &item = layoutData->items[i]; if (item.analysis.flags == QScriptAnalysis::TabOrObject) { // found it. tabSectionEnd = item.position; @@ -3187,7 +3201,7 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const if (tabSectionEnd > si.position) { QFixed length; // Calculate the length of text between this tab and the tabSectionEnd - for (int i=item; i < layoutData->items.count(); i++) { + for (int i=item; i < layoutData->items.size(); i++) { const QScriptItem &item = layoutData->items.at(i); if (item.position > tabSectionEnd || item.position <= si.position) continue; @@ -3259,7 +3273,7 @@ void QTextEngine::resolveFormats() const QTextFormatCollection *collection = formatCollection(); - QList<QTextCharFormat> resolvedFormats(layoutData->items.count()); + QList<QTextCharFormat> resolvedFormats(layoutData->items.size()); QVarLengthArray<int, 64> formatsSortedByStart; formatsSortedByStart.reserve(specialData->formats.size()); @@ -3277,7 +3291,7 @@ void QTextEngine::resolveFormats() const const int *startIt = formatsSortedByStart.constBegin(); const int *endIt = formatsSortedByEnd.constBegin(); - for (int i = 0; i < layoutData->items.count(); ++i) { + for (int i = 0; i < layoutData->items.size(); ++i) { const QScriptItem *si = &layoutData->items.at(i); int end = si->position + length(si); @@ -3453,8 +3467,8 @@ int QTextEngine::previousLogicalPosition(int oldPos) const { const QCharAttributes *attrs = attributes(); int len = block.isValid() ? block.length() - 1 - : layoutData->string.length(); - Q_ASSERT(len <= layoutData->string.length()); + : layoutData->string.size(); + Q_ASSERT(len <= layoutData->string.size()); if (!attrs || oldPos <= 0 || oldPos > len) return oldPos; @@ -3468,8 +3482,8 @@ int QTextEngine::nextLogicalPosition(int oldPos) const { const QCharAttributes *attrs = attributes(); int len = block.isValid() ? block.length() - 1 - : layoutData->string.length(); - Q_ASSERT(len <= layoutData->string.length()); + : layoutData->string.size(); + Q_ASSERT(len <= layoutData->string.size()); if (!attrs || oldPos < 0 || oldPos >= len) return oldPos; @@ -3483,7 +3497,7 @@ int QTextEngine::lineNumberForTextPosition(int pos) { if (!layoutData) itemize(); - if (pos == layoutData->string.length() && lines.size()) + if (pos == layoutData->string.size() && lines.size()) return lines.size() - 1; for (int i = 0; i < lines.size(); ++i) { const QScriptLine& line = lines[i]; |