diff options
Diffstat (limited to 'src/gui/text/qfontengine.cpp')
-rw-r--r-- | src/gui/text/qfontengine.cpp | 97 |
1 files changed, 51 insertions, 46 deletions
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 1ce70c6d83..9e6b8d6ffd 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -50,6 +50,8 @@ #include <qendian.h> #include <private/qharfbuzz_p.h> +#include <algorithm> + QT_BEGIN_NAMESPACE static inline bool qtransform_equals_no_translate(const QTransform &a, const QTransform &b) @@ -71,11 +73,16 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr // Harfbuzz helper functions +Q_STATIC_ASSERT(sizeof(HB_Glyph) == sizeof(glyph_t)); +Q_STATIC_ASSERT(sizeof(HB_Fixed) == sizeof(QFixed)); + static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft) { QFontEngine *fe = (QFontEngine *)font->userData; - QVarLengthGlyphLayoutArray qglyphs(*numGlyphs); + QGlyphLayout qglyphs; + qglyphs.numGlyphs = *numGlyphs; + qglyphs.glyphs = glyphs; QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly); if (rightToLeft) @@ -84,28 +91,23 @@ static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint int nGlyphs = *numGlyphs; bool result = fe->stringToCMap(reinterpret_cast<const QChar *>(string), length, &qglyphs, &nGlyphs, shaperFlags); *numGlyphs = nGlyphs; - if (!result) - return false; - - for (hb_uint32 i = 0; i < *numGlyphs; ++i) - glyphs[i] = qglyphs.glyphs[i]; - return true; + return result; } static void hb_getAdvances(HB_Font font, const HB_Glyph *glyphs, hb_uint32 numGlyphs, HB_Fixed *advances, int flags) { QFontEngine *fe = (QFontEngine *)font->userData; - QVarLengthGlyphLayoutArray qglyphs(numGlyphs); + QVarLengthArray<QFixed> advances_y(numGlyphs); - for (hb_uint32 i = 0; i < numGlyphs; ++i) - qglyphs.glyphs[i] = glyphs[i]; + QGlyphLayout qglyphs; + qglyphs.numGlyphs = numGlyphs; + qglyphs.glyphs = const_cast<glyph_t *>(glyphs); + qglyphs.advances_x = reinterpret_cast<QFixed *>(advances); + qglyphs.advances_y = advances_y.data(); // not used fe->recalcAdvances(&qglyphs, (flags & HB_ShaperFlag_UseDesignMetrics) ? QFontEngine::DesignMetrics : QFontEngine::ShaperFlags(0)); - - for (hb_uint32 i = 0; i < numGlyphs; ++i) - advances[i] = qglyphs.advances_x[i].value(); } static HB_Bool hb_canRender(HB_Font font, const HB_UChar16 *string, hb_uint32 length) @@ -143,7 +145,7 @@ int QFontEngine::getPointInOutline(glyph_t glyph, int flags, quint32 point, QFix Q_UNUSED(xpos) Q_UNUSED(ypos) Q_UNUSED(nPoints) - return HB_Err_Not_Covered; + return Err_Not_Covered; } static HB_Error hb_getPointInOutline(HB_Font font, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints) @@ -203,17 +205,6 @@ QFontEngine::QFontEngine() fsType = 0; symbol = false; - { - HB_FontRec *hbFont = (HB_FontRec *) malloc(sizeof(HB_FontRec)); - Q_CHECK_PTR(hbFont); - memset(hbFont, 0, sizeof(HB_FontRec)); - hbFont->klass = &hb_fontClass; - hbFont->userData = this; - - font_ = (void *)hbFont; - font_destroy_func = free; - } - glyphFormat = -1; m_subPixelPositionCount = 0; @@ -262,8 +253,12 @@ QFixed QFontEngine::underlinePosition() const void *QFontEngine::harfbuzzFont() const { - HB_FontRec *hbFont = (HB_FontRec *)font_; - if (!hbFont->x_ppem) { + if (!font_) { + HB_FontRec *hbFont = (HB_FontRec *) malloc(sizeof(HB_FontRec)); + Q_CHECK_PTR(hbFont); + hbFont->klass = &hb_fontClass; + hbFont->userData = const_cast<QFontEngine *>(this); + qint64 emSquare = emSquareSize().truncate(); Q_ASSERT(emSquare == emSquareSize().toInt()); // ensure no truncation if (emSquare == 0) @@ -273,6 +268,9 @@ void *QFontEngine::harfbuzzFont() const // same as QFixed(x)/QFixed(emSquare) but without int32 overflow for x hbFont->x_scale = (((qint64)hbFont->x_ppem << 6) * 0x10000L + (emSquare >> 1)) / emSquare; hbFont->y_scale = (((qint64)hbFont->y_ppem << 6) * 0x10000L + (emSquare >> 1)) / emSquare; + + font_ = (void *)hbFont; + font_destroy_func = free; } return font_; } @@ -973,7 +971,7 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor) } } end: - qSort(kerning_pairs); + std::sort(kerning_pairs.begin(), kerning_pairs.end()); // for (int i = 0; i < kerning_pairs.count(); ++i) // qDebug() << 'i' << i << "left_right" << hex << kerning_pairs.at(i).left_right; } @@ -1439,10 +1437,12 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, bool surrogate = (str[i].isHighSurrogate() && i < len-1 && str[i+1].isLowSurrogate()); uint ucs4 = surrogate ? QChar::surrogateToUcs4(str[i], str[i+1]) : str[i].unicode(); if (glyphs->glyphs[glyph_pos] == 0 && str[i].category() != QChar::Separator_Line) { - QGlyphLayoutInstance tmp; - if (!(flags & GlyphIndicesOnly)) - tmp = glyphs->instance(glyph_pos); - for (int x=1; x < engines.size(); ++x) { + QFixedPoint tmpAdvance; + if (!(flags & GlyphIndicesOnly)) { + tmpAdvance.x = glyphs->advances_x[glyph_pos]; + tmpAdvance.y = glyphs->advances_y[glyph_pos]; + } + for (int x = 1, n = qMin(engines.size(), 256); x < n; ++x) { if (engines.at(x) == 0 && !shouldLoadFontEngineForCharacter(x, ucs4)) continue; @@ -1455,10 +1455,8 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, if (engine->type() == Box) continue; - if (!(flags & GlyphIndicesOnly)) { + if (!(flags & GlyphIndicesOnly)) glyphs->advances_x[glyph_pos] = glyphs->advances_y[glyph_pos] = 0; - glyphs->offsets[glyph_pos] = QFixedPoint(); - } int num = 2; QGlyphLayout offs = glyphs->mid(glyph_pos, num); engine->stringToCMap(str + i, surrogate ? 2 : 1, &offs, &num, flags); @@ -1471,8 +1469,10 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, } // ensure we use metrics from the 1st font when we use the fallback image. - if (!(flags & GlyphIndicesOnly) && !glyphs->glyphs[glyph_pos]) - glyphs->setInstance(glyph_pos, tmp); + if (!(flags & GlyphIndicesOnly) && glyphs->glyphs[glyph_pos] == 0) { + glyphs->advances_x[glyph_pos] = tmpAdvance.x; + glyphs->advances_y[glyph_pos] = tmpAdvance.y; + } } if (surrogate) @@ -1774,22 +1774,27 @@ bool QFontEngineMulti::canRender(const QChar *string, int len) if (engine(0)->canRender(string, len)) return true; - QVarLengthGlyphLayoutArray glyphs(len); int nglyphs = len; - if (!stringToCMap(string, len, &glyphs, &nglyphs, GlyphIndicesOnly)) { + + QVarLengthArray<glyph_t> glyphs(nglyphs); + + QGlyphLayout g; + g.numGlyphs = nglyphs; + g.glyphs = glyphs.data(); + if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly)) { glyphs.resize(nglyphs); - stringToCMap(string, len, &glyphs, &nglyphs, GlyphIndicesOnly); + g.numGlyphs = nglyphs; + g.glyphs = glyphs.data(); + if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly)) + Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice"); } - bool allExist = true; for (int i = 0; i < nglyphs; i++) { - if (!glyphs.glyphs[i]) { - allExist = false; - break; - } + if (g.glyphs[i] == 0) + return false; } - return allExist; + return true; } /* Implement alphaMapForGlyph() which is called by Lighthouse/Windows code. |