From fef629cd9191bb73f22c5efb6f943e6b672953c1 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 5 Feb 2016 13:25:13 +0100 Subject: Disable unneeded ligatures when letter spacing is set For writing systems where glyph substitutions are purely cosmetic, we should disable them when letter spacing is set, otherwise we get ligatures where the spacing is not applied. To avoid changing Harfbuzz-NG upstream, we detect this case when fetching the GSUB table and return an empty blob instead. Task-number: QTBUG-44393 Change-Id: Ie5f6b2d795d7fecbba0ece3941fb70ba7f04c395 Reviewed-by: Lars Knoll Reviewed-by: Simon Hausmann --- src/gui/text/qharfbuzzng.cpp | 15 ++++++++++++++- src/gui/text/qharfbuzzng_p.h | 3 +++ src/gui/text/qtextengine.cpp | 19 ++++++++++++++++--- src/gui/text/qtextengine_p.h | 8 +++++++- 4 files changed, 40 insertions(+), 5 deletions(-) (limited to 'src/gui') diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp index b2edfc00a0..6437465da8 100644 --- a/src/gui/text/qharfbuzzng.cpp +++ b/src/gui/text/qharfbuzzng.cpp @@ -573,17 +573,27 @@ _hb_qt_font_get_glyph_from_name(hb_font_t * /*font*/, void * /*font_data*/, static hb_user_data_key_t _useDesignMetricsKey; +static hb_user_data_key_t _ignoreGSUB; void hb_qt_font_set_use_design_metrics(hb_font_t *font, uint value) { hb_font_set_user_data(font, &_useDesignMetricsKey, (void *)quintptr(value), NULL, true); } +void hb_qt_face_set_ignore_gsub(hb_face_t *face, uint value) +{ + hb_face_set_user_data(face, &_ignoreGSUB, (void *)quintptr(value), NULL, true); +} + uint hb_qt_font_get_use_design_metrics(hb_font_t *font) { return quintptr(hb_font_get_user_data(font, &_useDesignMetricsKey)); } +uint hb_qt_face_get_ignore_gsub(hb_face_t *face) +{ + return quintptr(hb_face_get_user_data(face, &_ignoreGSUB)); +} struct _hb_qt_font_funcs_t { _hb_qt_font_funcs_t() @@ -618,11 +628,14 @@ hb_font_funcs_t *hb_qt_get_font_funcs() static hb_blob_t * -_hb_qt_reference_table(hb_face_t * /*face*/, hb_tag_t tag, void *user_data) +_hb_qt_reference_table(hb_face_t *face, hb_tag_t tag, void *user_data) { QFontEngine::FaceData *data = static_cast(user_data); Q_ASSERT(data); + if (hb_qt_face_get_ignore_gsub(face) && tag == HB_TAG('G','S','U','B')) + return hb_blob_get_empty(); + qt_get_font_table_func_t get_font_table = data->get_font_table; Q_ASSERT(get_font_table); diff --git a/src/gui/text/qharfbuzzng_p.h b/src/gui/text/qharfbuzzng_p.h index d5e11e6264..8beadbc72c 100644 --- a/src/gui/text/qharfbuzzng_p.h +++ b/src/gui/text/qharfbuzzng_p.h @@ -72,6 +72,9 @@ Q_GUI_EXPORT hb_font_t *hb_qt_font_get_for_engine(QFontEngine *fe); Q_GUI_EXPORT void hb_qt_font_set_use_design_metrics(hb_font_t *font, uint value); Q_GUI_EXPORT uint hb_qt_font_get_use_design_metrics(hb_font_t *font); +Q_GUI_EXPORT void hb_qt_face_set_ignore_gsub(hb_face_t *font, uint value); +Q_GUI_EXPORT uint hb_qt_face_get_ignore_gsub(hb_face_t *font); + QT_END_NAMESPACE #endif // QHARFBUZZNG_P_H diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 1c924175e2..7dc8e8fadb 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1059,7 +1059,7 @@ void QTextEngine::shapeText(int item) const #ifdef QT_ENABLE_HARFBUZZ_NG if (Q_LIKELY(qt_useHarfbuzzNG())) - si.num_glyphs = shapeTextWithHarfbuzzNG(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled); + si.num_glyphs = shapeTextWithHarfbuzzNG(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled, letterSpacing != 0); else #endif si.num_glyphs = shapeTextWithHarfbuzz(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled); @@ -1121,7 +1121,13 @@ QT_BEGIN_INCLUDE_NAMESPACE QT_END_INCLUDE_NAMESPACE -int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector &itemBoundaries, bool kerningEnabled) const +int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, + const ushort *string, + int itemLength, + QFontEngine *fontEngine, + const QVector &itemBoundaries, + bool kerningEnabled, + bool hasLetterSpacing) const { uint glyphs_shaped = 0; @@ -1135,7 +1141,8 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st hb_segment_properties_t props = HB_SEGMENT_PROPERTIES_DEFAULT; props.direction = si.analysis.bidiLevel % 2 ? HB_DIRECTION_RTL : HB_DIRECTION_LTR; - props.script = hb_qt_script_to_script(QChar::Script(si.analysis.script)); + QChar::Script script = QChar::Script(si.analysis.script); + props.script = hb_qt_script_to_script(script); // ### props.language = hb_language_get_default_for_script(props.script); for (int k = 0; k < itemBoundaries.size(); k += 3) { @@ -1168,6 +1175,12 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st Q_ASSERT(hb_font); hb_qt_font_set_use_design_metrics(hb_font, option.useDesignMetrics() ? uint(QFontEngine::DesignMetrics) : 0); // ### + bool scriptRequiresOpenType = ((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala) + || script == QChar::Script_Khmer || script == QChar::Script_Nko); + hb_face_t *hb_face = hb_font_get_face(hb_font); + Q_ASSERT(hb_face); + hb_qt_face_set_ignore_gsub(hb_face, hasLetterSpacing && !scriptRequiresOpenType); + const hb_feature_t features[1] = { { HB_TAG('k','e','r','n'), !!kerningEnabled, 0, uint(-1) } }; diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 39c228fd52..7e507bba2d 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -643,7 +643,13 @@ private: void addRequiredBoundaries() const; void shapeText(int item) const; #ifdef QT_ENABLE_HARFBUZZ_NG - int shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector &itemBoundaries, bool kerningEnabled) const; + int shapeTextWithHarfbuzzNG(const QScriptItem &si, + const ushort *string, + int itemLength, + QFontEngine *fontEngine, + const QVector &itemBoundaries, + bool kerningEnabled, + bool hasLetterSpacing) const; #endif int shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector &itemBoundaries, bool kerningEnabled) const; -- cgit v1.2.3