summaryrefslogtreecommitdiffstats
path: root/src/gui/text
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-02-10 21:10:21 +0100
committerLiang Qi <liang.qi@qt.io>2017-02-10 22:35:04 +0100
commit364b161122b567e3a6f7343d438fb540b9fb7e5c (patch)
tree3d49953be9a58295a8c956cf5fdb00f581020605 /src/gui/text
parente58401a75b29beb38d37a40072106d5ef7cb0336 (diff)
parent8a410f60ae39b06555d807581caf7cb8bfab4fac (diff)
Merge remote-tracking branch 'origin/5.9' into dev
Conflicts: src/widgets/widgets/qmainwindowlayout_p.h Change-Id: Id406a67606b885052ed405b0fbc8eea7d9d03224
Diffstat (limited to 'src/gui/text')
-rw-r--r--src/gui/text/qfontmetrics.cpp6
-rw-r--r--src/gui/text/qharfbuzzng.cpp117
-rw-r--r--src/gui/text/qtextengine.cpp28
3 files changed, 83 insertions, 68 deletions
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index aca59d0288..8067969f56 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -556,7 +556,6 @@ int QFontMetrics::width(const QString &text, int len, int flags) const
}
QStackTextEngine layout(text, QFont(d.data()));
- layout.ignoreBidi = true;
return qRound(layout.width(0, len));
}
@@ -692,7 +691,6 @@ QRect QFontMetrics::boundingRect(const QString &text) const
return QRect();
QStackTextEngine layout(text, QFont(d.data()));
- layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, text.length());
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
@@ -861,7 +859,6 @@ QRect QFontMetrics::tightBoundingRect(const QString &text) const
return QRect();
QStackTextEngine layout(text, QFont(d.data()));
- layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
@@ -1413,7 +1410,6 @@ qreal QFontMetricsF::width(const QString &text) const
int len = (pos != -1) ? pos : text.length();
QStackTextEngine layout(text, QFont(d.data()));
- layout.ignoreBidi = true;
layout.itemize();
return layout.width(0, len).toReal();
}
@@ -1496,7 +1492,6 @@ QRectF QFontMetricsF::boundingRect(const QString &text) const
return QRectF();
QStackTextEngine layout(text, QFont(d.data()));
- layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, len);
return QRectF(gm.x.toReal(), gm.y.toReal(),
@@ -1668,7 +1663,6 @@ QRectF QFontMetricsF::tightBoundingRect(const QString &text) const
return QRect();
QStackTextEngine layout(text, QFont(d.data()));
- layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp
index 55ef9f0d15..6aca660205 100644
--- a/src/gui/text/qharfbuzzng.cpp
+++ b/src/gui/text/qharfbuzzng.cpp
@@ -422,19 +422,53 @@ hb_unicode_funcs_t *hb_qt_get_unicode_funcs()
// Font routines
+#if HB_VERSION_ATLEAST(1, 1, 3)
static hb_bool_t
-_hb_qt_font_get_glyph(hb_font_t * /*font*/, void *font_data,
- hb_codepoint_t unicode, hb_codepoint_t /*variation_selector*/,
- hb_codepoint_t *glyph,
- void * /*user_data*/)
+_hb_qt_get_font_h_extents(hb_font_t * /*font*/, void *font_data,
+ hb_font_extents_t *metrics,
+ void * /*user_data*/)
{
QFontEngine *fe = static_cast<QFontEngine *>(font_data);
Q_ASSERT(fe);
- *glyph = fe->glyphIndex(unicode);
+ metrics->ascender = fe->ascent().value();
+ metrics->descender = fe->descent().value();
+ metrics->line_gap = fe->leading().value();
return true;
}
+#endif
+
+#if HB_VERSION_ATLEAST(1, 2, 3)
+static hb_bool_t
+_hb_qt_font_get_nominal_glyph(hb_font_t * /*font*/, void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ void * /*user_data*/)
+{
+ QFontEngine *fe = static_cast<QFontEngine *>(font_data);
+ Q_ASSERT(fe);
+
+ *glyph = fe->glyphIndex(unicode);
+
+ return *glyph != 0;
+}
+#endif
+
+static hb_bool_t
+_hb_qt_font_get_variation_glyph(hb_font_t * /*font*/, void *font_data,
+ hb_codepoint_t unicode, hb_codepoint_t /*variation_selector*/,
+ hb_codepoint_t *glyph,
+ void * /*user_data*/)
+{
+ QFontEngine *fe = static_cast<QFontEngine *>(font_data);
+ Q_ASSERT(fe);
+
+ // ### TODO add support for variation selectors
+ *glyph = fe->glyphIndex(unicode);
+
+ return *glyph != 0;
+}
static hb_position_t
_hb_qt_font_get_glyph_h_advance(hb_font_t *font, void *font_data,
@@ -456,15 +490,7 @@ _hb_qt_font_get_glyph_h_advance(hb_font_t *font, void *font_data,
return advance.value();
}
-static hb_position_t
-_hb_qt_font_get_glyph_v_advance(hb_font_t * /*font*/, void * /*font_data*/,
- hb_codepoint_t /*glyph*/,
- void * /*user_data*/)
-{
- qCritical("hb_qt_font_get_glyph_v_advance: vertical writing isn't supported!");
- return 0;
-}
-
+#if !HB_VERSION_ATLEAST(1, 1, 2)
static hb_bool_t
_hb_qt_font_get_glyph_h_origin(hb_font_t * /*font*/, void * /*font_data*/,
hb_codepoint_t /*glyph*/,
@@ -473,16 +499,7 @@ _hb_qt_font_get_glyph_h_origin(hb_font_t * /*font*/, void * /*font_data*/,
{
return true; // we always work in the horizontal coordinates
}
-
-static hb_bool_t
-_hb_qt_font_get_glyph_v_origin(hb_font_t * /*font*/, void * /*font_data*/,
- hb_codepoint_t /*glyph*/,
- hb_position_t * /*x*/, hb_position_t * /*y*/,
- void * /*user_data*/)
-{
- qCritical("hb_qt_get_glyph_v_origin: vertical writing isn't supported!");
- return false;
-}
+#endif
static hb_position_t
_hb_qt_font_get_glyph_h_kerning(hb_font_t *font, void *font_data,
@@ -505,15 +522,6 @@ _hb_qt_font_get_glyph_h_kerning(hb_font_t *font, void *font_data,
return advance.value();
}
-static hb_position_t
-_hb_qt_font_get_glyph_v_kerning(hb_font_t * /*font*/, void * /*font_data*/,
- hb_codepoint_t /*first_glyph*/, hb_codepoint_t /*second_glyph*/,
- void * /*user_data*/)
-{
- qCritical("hb_qt_get_glyph_v_kerning: vertical writing isn't supported!");
- return 0;
-}
-
static hb_bool_t
_hb_qt_font_get_glyph_extents(hb_font_t * /*font*/, void *font_data,
hb_codepoint_t glyph,
@@ -554,29 +562,6 @@ _hb_qt_font_get_glyph_contour_point(hb_font_t * /*font*/, void *font_data,
return false;
}
-static hb_bool_t
-_hb_qt_font_get_glyph_name(hb_font_t * /*font*/, void * /*font_data*/,
- hb_codepoint_t /*glyph*/,
- char *name, unsigned int size,
- void * /*user_data*/)
-{
- qCritical("hb_qt_font_get_glyph_name: not implemented!");
- if (size)
- *name = '\0';
- return false;
-}
-
-static hb_bool_t
-_hb_qt_font_get_glyph_from_name(hb_font_t * /*font*/, void * /*font_data*/,
- const char * /*name*/, int /*len*/,
- hb_codepoint_t *glyph,
- void * /*user_data*/)
-{
- qCritical("hb_qt_font_get_glyph_from_name: not implemented!");
- *glyph = 0;
- return false;
-}
-
static hb_user_data_key_t _useDesignMetricsKey;
@@ -595,17 +580,25 @@ struct _hb_qt_font_funcs_t {
_hb_qt_font_funcs_t()
{
funcs = hb_font_funcs_create();
- hb_font_funcs_set_glyph_func(funcs, _hb_qt_font_get_glyph, NULL, NULL);
+
+#if HB_VERSION_ATLEAST(1, 1, 3)
+ hb_font_funcs_set_font_h_extents_func(funcs, _hb_qt_get_font_h_extents, NULL, NULL);
+#endif
+#if HB_VERSION_ATLEAST(1, 2, 3)
+ hb_font_funcs_set_nominal_glyph_func(funcs, _hb_qt_font_get_nominal_glyph, NULL, NULL);
+ hb_font_funcs_set_variation_glyph_func(funcs, _hb_qt_font_get_variation_glyph, NULL, NULL);
+#else
+ hb_font_funcs_set_glyph_func(funcs, _hb_qt_font_get_variation_glyph, NULL, NULL);
+#endif
hb_font_funcs_set_glyph_h_advance_func(funcs, _hb_qt_font_get_glyph_h_advance, NULL, NULL);
- hb_font_funcs_set_glyph_v_advance_func(funcs, _hb_qt_font_get_glyph_v_advance, NULL, NULL);
+#if !HB_VERSION_ATLEAST(1, 1, 2)
hb_font_funcs_set_glyph_h_origin_func(funcs, _hb_qt_font_get_glyph_h_origin, NULL, NULL);
- hb_font_funcs_set_glyph_v_origin_func(funcs, _hb_qt_font_get_glyph_v_origin, NULL, NULL);
+#endif
hb_font_funcs_set_glyph_h_kerning_func(funcs, _hb_qt_font_get_glyph_h_kerning, NULL, NULL);
- hb_font_funcs_set_glyph_v_kerning_func(funcs, _hb_qt_font_get_glyph_v_kerning, NULL, NULL);
hb_font_funcs_set_glyph_extents_func(funcs, _hb_qt_font_get_glyph_extents, NULL, NULL);
hb_font_funcs_set_glyph_contour_point_func(funcs, _hb_qt_font_get_glyph_contour_point, NULL, NULL);
- hb_font_funcs_set_glyph_name_func(funcs, _hb_qt_font_get_glyph_name, NULL, NULL);
- hb_font_funcs_set_glyph_from_name_func(funcs, _hb_qt_font_get_glyph_from_name, NULL, NULL);
+
+ hb_font_funcs_make_immutable(funcs);
}
~_hb_qt_font_funcs_t()
{
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 67cafa53fe..f3ed8ef63a 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1165,6 +1165,20 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
hb_buffer_clear_contents(buffer);
hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16_t *>(string) + item_pos, item_length, 0, item_length);
+#if defined(Q_OS_DARWIN)
+ // ### temporary workaround for QTBUG-38113
+ // CoreText throws away the PDF token, while the OpenType backend will replace it with
+ // a zero-advance glyph. This becomes a real issue when PDF is the last character,
+ // since it gets treated like if it were a grapheme extender, so we
+ // temporarily replace it with some visible grapheme starter.
+ bool endsWithPDF = actualFontEngine->type() == QFontEngine::Mac && string[item_pos + item_length - 1] == 0x202c;
+ if (Q_UNLIKELY(endsWithPDF)) {
+ uint num_glyphs;
+ hb_glyph_info_t *infos = hb_buffer_get_glyph_infos(buffer, &num_glyphs);
+ infos[num_glyphs - 1].codepoint = '.';
+ }
+#endif
+
hb_buffer_set_segment_properties(buffer, &props);
hb_buffer_guess_segment_properties(buffer);
@@ -1286,6 +1300,20 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
while (str_pos < item_length)
log_clusters[str_pos++] = last_glyph_pos;
+#if defined(Q_OS_DARWIN)
+ if (Q_UNLIKELY(endsWithPDF)) {
+ int last_glyph_idx = num_glyphs - 1;
+ g.glyphs[last_glyph_idx] = 0xffff;
+ g.advances[last_glyph_idx] = QFixed();
+ g.offsets[last_glyph_idx].x = QFixed();
+ g.offsets[last_glyph_idx].y = QFixed();
+ g.attributes[last_glyph_idx].clusterStart = true;
+ g.attributes[last_glyph_idx].dontPrint = true;
+
+ log_clusters[item_length - 1] = glyphs_shaped + last_glyph_idx;
+ }
+#endif
+
if (Q_UNLIKELY(engineIdx != 0)) {
for (quint32 i = 0; i < num_glyphs; ++i)
g.glyphs[i] |= (engineIdx << 24);