diff options
Diffstat (limited to 'src/gui/text')
-rw-r--r-- | src/gui/text/qfontengine.cpp | 7 | ||||
-rw-r--r-- | src/gui/text/qfontengine_p.h | 1 | ||||
-rw-r--r-- | src/gui/text/qharfbuzzng.cpp | 117 | ||||
-rw-r--r-- | src/gui/text/qplatformfontdatabase.cpp | 11 | ||||
-rw-r--r-- | src/gui/text/qtextdocument.cpp | 19 | ||||
-rw-r--r-- | src/gui/text/qtextdocument.h | 1 | ||||
-rw-r--r-- | src/gui/text/qtextengine.cpp | 28 | ||||
-rw-r--r-- | src/gui/text/qtexthtmlparser.cpp | 57 | ||||
-rw-r--r-- | src/gui/text/qtextlayout.cpp | 10 |
9 files changed, 151 insertions, 100 deletions
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 0b2972f189..596c79fd05 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -445,6 +445,11 @@ bool QFontEngine::supportsTransformation(const QTransform &transform) const return transform.type() < QTransform::TxProject; } +bool QFontEngine::expectsGammaCorrectedBlending() const +{ + return true; +} + void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions) { @@ -1268,7 +1273,7 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy if (!qSafeFromBigEndian(maps + 8 * n, endPtr, &platformId)) return 0; - quint16 platformSpecificId; + quint16 platformSpecificId = 0; if (!qSafeFromBigEndian(maps + 8 * n + 2, endPtr, &platformSpecificId)) return 0; diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index c0e350f755..514e9424b2 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -254,6 +254,7 @@ public: static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily); virtual bool hasUnreliableGlyphOutline() const; + virtual bool expectsGammaCorrectedBlending() const; enum HintStyle { HintNone, 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/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp index b83affecdc..ac3d274b36 100644 --- a/src/gui/text/qplatformfontdatabase.cpp +++ b/src/gui/text/qplatformfontdatabase.cpp @@ -423,14 +423,14 @@ QFont QPlatformFontDatabase::defaultFont() const return QFont(QLatin1String("Helvetica")); } + +QString qt_resolveFontFamilyAlias(const QString &alias); + /*! Resolve alias to actual font family names. \since 5.0 */ - -QString qt_resolveFontFamilyAlias(const QString &alias); - QString QPlatformFontDatabase::resolveFontFamilyAlias(const QString &family) const { return qt_resolveFontFamilyAlias(family); @@ -628,12 +628,13 @@ QSupportedWritingSystems QPlatformFontDatabase::writingSystemsFromTrueTypeBits(q } /*! - Helper function that returns the Qt font weight matching a given opentype integer value. + Helper function that returns the Qt font weight matching + a given opentype integer value. Converts the integer + \a weight (0 ~ 1000) to QFont::Weight and returns it. \since 5.5 */ -// convert 0 ~ 1000 integer to QFont::Weight QFont::Weight QPlatformFontDatabase::weightFromInteger(int weight) { if (weight < 150) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index c006e7f427..6074917087 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -1145,13 +1145,30 @@ void QTextDocument::setMetaInformation(MetaInformation info, const QString &stri } /*! + Returns the raw text contained in the document without any + formatting information. If you want formatting information + use a QTextCursor instead. + + \since 5.9 + \sa toPlainText() +*/ +QString QTextDocument::toRawText() const +{ + Q_D(const QTextDocument); + return d->plainText(); +} + +/*! Returns the plain text contained in the document. If you want formatting information use a QTextCursor instead. - Some formatting characters are replaced by ASCII equivalents. + This function returns the same as toRawText(), but will replace + some unicode characters with ASCII alternatives. In particular, no-break space (U+00A0) is replaced by a regular space (U+0020), and both paragraph (U+2029) and line (U+2028) separators are replaced by line feed (U+000A). + If you need the precise contents of the document, use toRawText() + instead. \note Embedded objects, such as images, are represented by a Unicode value U+FFFC (OBJECT REPLACEMENT CHARACTER). diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index 1888088f0d..c2761a39b9 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -151,6 +151,7 @@ public: void setHtml(const QString &html); #endif + QString toRawText() const; QString toPlainText() const; void setPlainText(const QString &text); 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); diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp index d4c43b3069..269e505a56 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -329,17 +329,17 @@ bool operator<(const QTextHtmlEntity &entity1, const QTextHtmlEntity &entity2) } #endif -static bool operator<(const QString &entityStr, const QTextHtmlEntity &entity) +static bool operator<(const QStringRef &entityStr, const QTextHtmlEntity &entity) { return entityStr < QLatin1String(entity.name); } -static bool operator<(const QTextHtmlEntity &entity, const QString &entityStr) +static bool operator<(const QTextHtmlEntity &entity, const QStringRef &entityStr) { return QLatin1String(entity.name) < entityStr; } -static QChar resolveEntity(const QString &entity) +static QChar resolveEntity(const QStringRef &entity) { const QTextHtmlEntity *start = &entities[0]; const QTextHtmlEntity *end = &entities[MAX_ENTITY]; @@ -801,8 +801,9 @@ void QTextHtmlParser::parseExclamationTag() // parses an entity after "&", and returns it QString QTextHtmlParser::parseEntity() { - int recover = pos; - QString entity; + const int recover = pos; + int entityLen = 0; + QStringRef entity; while (pos < len) { QChar c = txt.at(pos++); if (c.isSpace() || pos - recover > 9) { @@ -810,36 +811,38 @@ QString QTextHtmlParser::parseEntity() } if (c == QLatin1Char(';')) break; - entity += c; + ++entityLen; } - { + if (entityLen) { + entity = QStringRef(&txt, recover, entityLen); QChar resolved = resolveEntity(entity); if (!resolved.isNull()) return QString(resolved); - } - if (entity.length() > 1 && entity.at(0) == QLatin1Char('#')) { - entity.remove(0, 1); // removing leading # - int base = 10; - bool ok = false; + if (entityLen > 1 && entity.at(0) == QLatin1Char('#')) { + entity = entity.mid(1); // removing leading # - if (entity.at(0).toLower() == QLatin1Char('x')) { // hex entity? - entity.remove(0, 1); - base = 16; - } + int base = 10; + bool ok = false; - uint uc = entity.toUInt(&ok, base); - if (ok) { - if (uc >= 0x80 && uc < 0x80 + (sizeof(windowsLatin1ExtendedCharacters)/sizeof(windowsLatin1ExtendedCharacters[0]))) - uc = windowsLatin1ExtendedCharacters[uc - 0x80]; - QString str; - if (QChar::requiresSurrogates(uc)) { - str += QChar(QChar::highSurrogate(uc)); - str += QChar(QChar::lowSurrogate(uc)); - } else { - str = QChar(uc); + if (entity.at(0).toLower() == QLatin1Char('x')) { // hex entity? + entity = entity.mid(1); + base = 16; + } + + uint uc = entity.toUInt(&ok, base); + if (ok) { + if (uc >= 0x80 && uc < 0x80 + (sizeof(windowsLatin1ExtendedCharacters)/sizeof(windowsLatin1ExtendedCharacters[0]))) + uc = windowsLatin1ExtendedCharacters[uc - 0x80]; + QString str; + if (QChar::requiresSurrogates(uc)) { + str += QChar(QChar::highSurrogate(uc)); + str += QChar(QChar::lowSurrogate(uc)); + } else { + str = QChar(uc); + } + return str; } - return str; } } error: diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 540bbf5d54..023a1b7f52 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1653,6 +1653,7 @@ namespace { int maxGlyphs; int currentPosition; glyph_t previousGlyph; + QFontEngine *previousGlyphFontEngine; QFixed minw; QFixed softHyphenWidth; @@ -1686,13 +1687,14 @@ namespace { if (currentPosition > 0 && logClusters[currentPosition - 1] < glyphs.numGlyphs) { previousGlyph = currentGlyph(); // needed to calculate right bearing later + previousGlyphFontEngine = fontEngine; } } - inline void calculateRightBearing(glyph_t glyph) + inline void calculateRightBearing(QFontEngine *engine, glyph_t glyph) { qreal rb; - fontEngine->getGlyphBearings(glyph, 0, &rb); + engine->getGlyphBearings(glyph, 0, &rb); // We only care about negative right bearings, so we limit the range // of the bearing here so that we can assume it's negative in the rest @@ -1705,13 +1707,13 @@ namespace { { if (currentPosition <= 0) return; - calculateRightBearing(currentGlyph()); + calculateRightBearing(fontEngine, currentGlyph()); } inline void calculateRightBearingForPreviousGlyph() { if (previousGlyph > 0) - calculateRightBearing(previousGlyph); + calculateRightBearing(previousGlyphFontEngine, previousGlyph); } static const QFixed RightBearingNotCalculated; |