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 <lars.knoll@theqtcompany.com> Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>bb10
parent
67ced1d9c4
commit
fef629cd91
|
|
@ -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<QFontEngine::FaceData *>(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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<uint> &itemBoundaries, bool kerningEnabled) const
|
||||
int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
|
||||
const ushort *string,
|
||||
int itemLength,
|
||||
QFontEngine *fontEngine,
|
||||
const QVector<uint> &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) }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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<uint> &itemBoundaries, bool kerningEnabled) const;
|
||||
int shapeTextWithHarfbuzzNG(const QScriptItem &si,
|
||||
const ushort *string,
|
||||
int itemLength,
|
||||
QFontEngine *fontEngine,
|
||||
const QVector<uint> &itemBoundaries,
|
||||
bool kerningEnabled,
|
||||
bool hasLetterSpacing) const;
|
||||
#endif
|
||||
int shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue