diff options
Diffstat (limited to 'src/gui/text')
-rw-r--r-- | src/gui/text/qfontengine.cpp | 13 | ||||
-rw-r--r-- | src/gui/text/qfontengine_ft.cpp | 94 | ||||
-rw-r--r-- | src/gui/text/qharfbuzzng.cpp | 10 | ||||
-rw-r--r-- | src/gui/text/qtextengine.cpp | 54 | ||||
-rw-r--r-- | src/gui/text/qtextimagehandler.cpp | 20 |
5 files changed, 111 insertions, 80 deletions
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index a0eedee6b9..f267b2d147 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -370,17 +370,15 @@ bool QFontEngine::supportsScript(QChar::Script script) const return true; } -#ifdef Q_OS_MAC - { +#ifdef QT_ENABLE_HARFBUZZ_NG + if (qt_useHarfbuzzNG()) { +#if defined(Q_OS_DARWIN) // in AAT fonts, 'gsub' table is effectively replaced by 'mort'/'morx' table uint len; if (getSfntTableData(MAKE_TAG('m','o','r','t'), 0, &len) || getSfntTableData(MAKE_TAG('m','o','r','x'), 0, &len)) return true; - } #endif -#ifdef QT_ENABLE_HARFBUZZ_NG - if (qt_useHarfbuzzNG()) { bool ret = false; if (hb_face_t *face = hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this))) { hb_tag_t script_tag_1, script_tag_2; @@ -1837,7 +1835,10 @@ QFontEngine *QFontEngineMulti::loadEngine(int at) request.family = fallbackFamilyAt(at - 1); if (QFontEngine *engine = QFontDatabase::findFont(request, m_script)) { - engine->fontDef = request; + if (request.weight > QFont::Normal) + engine->fontDef.weight = request.weight; + if (request.style > QFont::StyleNormal) + engine->fontDef.style = request.style; return engine; } diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 0d28785aa1..8dfabd48ad 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -534,69 +534,87 @@ QFontEngineFT::Glyph::~Glyph() delete [] data; } -static const uint subpixel_filter[3][3] = { - { 180, 60, 16 }, - { 38, 180, 38 }, - { 16, 60, 180 } +struct LcdFilterDummy +{ + static inline void filterPixel(uchar &, uchar &, uchar &) + {} }; -static inline uint filterPixel(uint red, uint green, uint blue, bool legacyFilter) +struct LcdFilterLegacy { - uint res; - if (legacyFilter) { - uint high = (red*subpixel_filter[0][0] + green*subpixel_filter[0][1] + blue*subpixel_filter[0][2]) >> 8; - uint mid = (red*subpixel_filter[1][0] + green*subpixel_filter[1][1] + blue*subpixel_filter[1][2]) >> 8; - uint low = (red*subpixel_filter[2][0] + green*subpixel_filter[2][1] + blue*subpixel_filter[2][2]) >> 8; - res = (mid << 24) + (high << 16) + (mid << 8) + low; - } else { - uint alpha = green; - res = (alpha << 24) + (red << 16) + (green << 8) + blue; + static inline void filterPixel(uchar &red, uchar &green, uchar &blue) + { + uint r = red, g = green, b = blue; + // intra-pixel filter used by the legacy filter (adopted from _ft_lcd_filter_legacy) + red = (r * uint(65538 * 9/13) + g * uint(65538 * 1/6) + b * uint(65538 * 1/13)) / 65536; + green = (r * uint(65538 * 3/13) + g * uint(65538 * 4/6) + b * uint(65538 * 3/13)) / 65536; + blue = (r * uint(65538 * 1/13) + g * uint(65538 * 1/6) + b * uint(65538 * 9/13)) / 65536; } - return res; -} +}; -static void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter) +template <typename LcdFilter> +static void convertRGBToARGB_helper(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr) { - int h = height; const int offs = bgr ? -1 : 1; const int w = width * 3; - while (h--) { + while (height--) { uint *dd = dst; for (int x = 0; x < w; x += 3) { - uint red = src[x+1-offs]; - uint green = src[x+1]; - uint blue = src[x+1+offs]; - *dd = filterPixel(red, green, blue, legacyFilter); - ++dd; + uchar red = src[x + 1 - offs]; + uchar green = src[x + 1]; + uchar blue = src[x + 1 + offs]; + LcdFilter::filterPixel(red, green, blue); + // alpha = green + *dd++ = (green << 24) | (red << 16) | (green << 8) | blue; } dst += width; src += src_pitch; } } -static void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter) +static inline void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter) +{ + if (!legacyFilter) + convertRGBToARGB_helper<LcdFilterDummy>(src, dst, width, height, src_pitch, bgr); + else + convertRGBToARGB_helper<LcdFilterLegacy>(src, dst, width, height, src_pitch, bgr); +} + +template <typename LcdFilter> +static void convertRGBToARGB_V_helper(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr) { - int h = height; const int offs = bgr ? -src_pitch : src_pitch; - while (h--) { + while (height--) { for (int x = 0; x < width; x++) { - uint red = src[x+src_pitch-offs]; - uint green = src[x+src_pitch]; - uint blue = src[x+src_pitch+offs]; - dst[x] = filterPixel(red, green, blue, legacyFilter); + uchar red = src[x + src_pitch - offs]; + uchar green = src[x + src_pitch]; + uchar blue = src[x + src_pitch + offs]; + LcdFilter::filterPixel(red, green, blue); + // alpha = green + *dst++ = (green << 24) | (red << 16) | (green << 8) | blue; } - dst += width; src += 3*src_pitch; } } -static void convertGRAYToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch) { - for (int y = 0; y < height; ++y) { - int readpos = (y * src_pitch); - int writepos = (y * width); - for (int x = 0; x < width; ++x) { - dst[writepos + x] = (0xFF << 24) + (src[readpos + x] << 16) + (src[readpos + x] << 8) + src[readpos + x]; +static inline void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter) +{ + if (!legacyFilter) + convertRGBToARGB_V_helper<LcdFilterDummy>(src, dst, width, height, src_pitch, bgr); + else + convertRGBToARGB_V_helper<LcdFilterLegacy>(src, dst, width, height, src_pitch, bgr); +} + +static inline void convertGRAYToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch) +{ + while (height--) { + const uchar *p = src; + const uchar * const e = p + width; + while (p < e) { + uchar gray = *p++; + *dst++ = (0xFF << 24) | (gray << 16) | (gray << 8) | gray; } + src += src_pitch; } } diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp index 102c62ea8a..b2edfc00a0 100644 --- a/src/gui/text/qharfbuzzng.cpp +++ b/src/gui/text/qharfbuzzng.cpp @@ -188,7 +188,15 @@ static const hb_script_t _qtscript_to_hbscript[] = { HB_SCRIPT_SIDDHAM, HB_SCRIPT_KHUDAWADI, HB_SCRIPT_TIRHUTA, - HB_SCRIPT_WARANG_CITI + HB_SCRIPT_WARANG_CITI, + + // Unicode 8.0 additions + HB_SCRIPT_AHOM, + HB_SCRIPT_ANATOLIAN_HIEROGLYPHS, + HB_SCRIPT_HATRAN, + HB_SCRIPT_MULTANI, + HB_SCRIPT_OLD_HUNGARIAN, + HB_SCRIPT_SIGNWRITING }; Q_STATIC_ASSERT(QChar::ScriptCount == sizeof(_qtscript_to_hbscript) / sizeof(_qtscript_to_hbscript[0])); diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 6b98c14205..50a242d81e 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1120,15 +1120,6 @@ QT_BEGIN_INCLUDE_NAMESPACE QT_END_INCLUDE_NAMESPACE -#if defined(Q_OS_OSX) && !defined(QT_NO_FREETYPE) -static const char *s_shapersForOsxFreeType[] = -{ - "ot", - "fallback", - Q_NULLPTR -}; -#endif - int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const { uint glyphs_shaped = 0; @@ -1182,13 +1173,21 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st const int num_features = 1; const char *const *shaper_list = Q_NULLPTR; -#if defined(Q_OS_OSX) && !defined(QT_NO_FREETYPE) - // What's behind QFontEngine::FaceData::user_data isn't compatible between CoreText and - // FreeType font engines - specifically functions in hb-coretext.cc would run into undefined - // behavior with data from the FreeType engine. The OpenType shaper works with that engine. - if (actualFontEngine->type() == QFontEngine::Freetype) - shaper_list = s_shapersForOsxFreeType; +#if defined(Q_OS_DARWIN) + // What's behind QFontEngine::FaceData::user_data isn't compatible between different font engines + // - specifically functions in hb-coretext.cc would run into undefined behavior with data + // from non-CoreText engine. The other shapers works with that engine just fine. + if (actualFontEngine->type() != QFontEngine::Mac) { + static const char *s_shaper_list_without_coretext[] = { + "graphite2", + "ot", + "fallback", + Q_NULLPTR + }; + shaper_list = s_shaper_list_without_coretext; + } #endif + bool shapedOk = hb_shape_full(hb_font, buffer, features, num_features, shaper_list); if (Q_UNLIKELY(!shapedOk)) { hb_buffer_destroy(buffer); @@ -1268,19 +1267,20 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st g.glyphs[i] |= (engineIdx << 24); } -#ifdef Q_OS_MAC - // CTRunGetPosition has a bug which applies matrix on 10.6, so we disable - // scaling the advances for this particular version - if (actualFontEngine->fontDef.stretch != 100 - && QSysInfo::MacintoshVersion != QSysInfo::MV_10_6) { - QFixed stretch = QFixed(int(actualFontEngine->fontDef.stretch)) / QFixed(100); - for (uint i = 0; i < num_glyphs; ++i) - g.advances[i] *= stretch; - } +#ifdef Q_OS_DARWIN + if (actualFontEngine->type() == QFontEngine::Mac) { + // CTRunGetPosition has a bug which applies matrix on 10.6, so we disable + // scaling the advances for this particular version + if (QSysInfo::MacintoshVersion != QSysInfo::MV_10_6 && actualFontEngine->fontDef.stretch != 100) { + QFixed stretch = QFixed(int(actualFontEngine->fontDef.stretch)) / QFixed(100); + for (uint i = 0; i < num_glyphs; ++i) + g.advances[i] *= stretch; + } - if (actualFontEngine->fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - for (uint i = 0; i < num_glyphs; ++i) - g.advances[i] = g.advances[i].round(); + if (actualFontEngine->fontDef.styleStrategy & QFont::ForceIntegerMetrics) { + for (uint i = 0; i < num_glyphs; ++i) + g.advances[i] = g.advances[i].round(); + } } #endif diff --git a/src/gui/text/qtextimagehandler.cpp b/src/gui/text/qtextimagehandler.cpp index 686a00e42a..d7a418e7c8 100644 --- a/src/gui/text/qtextimagehandler.cpp +++ b/src/gui/text/qtextimagehandler.cpp @@ -45,8 +45,10 @@ QT_BEGIN_NAMESPACE -extern QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio); -static QString resolveFileName(QString fileName, QUrl *url, qreal targetDevicePixelRatio) +extern QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio, + qreal *sourceDevicePixelRatio); +static QString resolveFileName(QString fileName, QUrl *url, qreal targetDevicePixelRatio, + qreal *sourceDevicePixelRatio) { // We might use the fileName for loading if url loading fails // try to make sure it is a valid file path. @@ -65,7 +67,7 @@ static QString resolveFileName(QString fileName, QUrl *url, qreal targetDevicePi return fileName; // try to find a Nx version - return qt_findAtNxFile(fileName, targetDevicePixelRatio); + return qt_findAtNxFile(fileName, targetDevicePixelRatio, sourceDevicePixelRatio); } @@ -77,7 +79,8 @@ static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format, con if (name.startsWith(QLatin1String(":/"))) // auto-detect resources and convert them to url name.prepend(QLatin1String("qrc")); QUrl url = QUrl(name); - name = resolveFileName(name, &url, devicePixelRatio); + qreal sourcePixelRatio = 1.0; + name = resolveFileName(name, &url, devicePixelRatio, &sourcePixelRatio); const QVariant data = doc->resource(QTextDocument::ImageResource, url); if (data.type() == QVariant::Pixmap || data.type() == QVariant::Image) { pm = qvariant_cast<QPixmap>(data); @@ -103,7 +106,7 @@ static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format, con } if (name.contains(QStringLiteral("@2x"))) - pm.setDevicePixelRatio(2.0); + pm.setDevicePixelRatio(sourcePixelRatio); return pm; } @@ -158,7 +161,8 @@ static QImage getImage(QTextDocument *doc, const QTextImageFormat &format, const if (name.startsWith(QLatin1String(":/"))) // auto-detect resources name.prepend(QLatin1String("qrc")); QUrl url = QUrl(name); - name = resolveFileName(name, &url, devicePixelRatio); + qreal sourcePixelRatio = 1.0; + name = resolveFileName(name, &url, devicePixelRatio, &sourcePixelRatio); const QVariant data = doc->resource(QTextDocument::ImageResource, url); if (data.type() == QVariant::Image) { image = qvariant_cast<QImage>(data); @@ -182,8 +186,8 @@ static QImage getImage(QTextDocument *doc, const QTextImageFormat &format, const doc->addResource(QTextDocument::ImageResource, url, image); } - if (name.contains(QStringLiteral("@2x"))) - image.setDevicePixelRatio(2.0); + if (sourcePixelRatio != 1.0) + image.setDevicePixelRatio(sourcePixelRatio); return image; } |