summaryrefslogtreecommitdiffstats
path: root/src/gui/text
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/text')
-rw-r--r--src/gui/text/qfontengine.cpp7
-rw-r--r--src/gui/text/qfontengine_p.h1
-rw-r--r--src/gui/text/qharfbuzzng.cpp117
-rw-r--r--src/gui/text/qplatformfontdatabase.cpp11
-rw-r--r--src/gui/text/qtextdocument.cpp19
-rw-r--r--src/gui/text/qtextdocument.h1
-rw-r--r--src/gui/text/qtextengine.cpp28
-rw-r--r--src/gui/text/qtexthtmlparser.cpp57
-rw-r--r--src/gui/text/qtextlayout.cpp10
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;