From 1fda23c0c63e0b445e303c1fd64ecb9d925b6976 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Thu, 9 Jun 2011 15:58:09 +0200 Subject: Store styleName in font database So that queries like QFontDatabase::styles() can return exactly the same styles as the system does. Then application can use QFont::setStyleName() to select those styles later. With a lot of fonts not providing correct numeric weight/width values and even if they did, values are usually not directly mapped to QFont enums, styleName is probably the only reliable way to select any possible font in the system. Reviewed-by: QTBUG-13518 Change-Id: Id8a9469b804f1b5bb81d8c7378e7e8778f9a4fff Reviewed-on: http://codereview.qt.nokia.com/739 Reviewed-by: Qt Sanity Bot Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontdatabase.cpp | 42 ++++++++++++++++++++++++++++---------- src/gui/text/qfontdatabase_mac.cpp | 2 ++ src/gui/text/qfontdatabase_x11.cpp | 6 +++++- 3 files changed, 38 insertions(+), 12 deletions(-) (limited to 'src/gui/text') diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 1d07b567f8..2a73223da1 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -218,16 +218,17 @@ struct QtFontStyle Key(const QString &styleString); Key() : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0) { } - Key(const Key &o) : style(o.style), + Key(const Key &o) : styleName(o.styleName), style(o.style), weight(o.weight), stretch(o.stretch) { } + QString styleName; uint style : 2; signed int weight : 8; signed int stretch : 12; bool operator==(const Key & other) { - return (style == other.style && + return styleName == other.styleName && style == other.style && weight == other.weight && - (stretch == 0 || other.stretch == 0 || stretch == other.stretch)); + (stretch == 0 || other.stretch == 0 || stretch == other.stretch); } bool operator!=(const Key &other) { return !operator==(other); @@ -292,7 +293,7 @@ struct QtFontStyle }; QtFontStyle::Key::Key(const QString &styleString) - : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0) + : styleName(styleString), style(QFont::StyleNormal), weight(QFont::Normal), stretch(0) { weight = getFontWeight(styleString); @@ -1139,6 +1140,12 @@ static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &st for ( int i = 0; i < foundry->count; i++ ) { QtFontStyle *style = foundry->styles[i]; + if (!styleKey.styleName.isEmpty() && styleKey.styleName == style->key.styleName) { + dist = 0; + best = i; + break; + } + int d = qAbs( styleKey.weight - style->key.weight ); if ( styleKey.stretch != 0 && style->key.stretch != 0 ) { @@ -1532,7 +1539,8 @@ static QString styleStringHelper(int weight, QFont::Style style) */ QString QFontDatabase::styleString(const QFont &font) { - return styleStringHelper(font.weight(), font.style()); + return font.styleName().isEmpty() ? styleStringHelper(font.weight(), font.style()) + : font.styleName(); } /*! @@ -1542,7 +1550,8 @@ QString QFontDatabase::styleString(const QFont &font) */ QString QFontDatabase::styleString(const QFontInfo &fontInfo) { - return styleStringHelper(fontInfo.weight(), fontInfo.style()); + return fontInfo.styleName().isEmpty() ? styleStringHelper(fontInfo.weight(), fontInfo.style()) + : fontInfo.styleName(); } @@ -1793,8 +1802,12 @@ QStringList QFontDatabase::styles(const QString &family) const } } - for (int i = 0; i < allStyles.count; i++) - l.append(styleStringHelper(allStyles.styles[i]->key.weight, (QFont::Style)allStyles.styles[i]->key.style)); + for (int i = 0; i < allStyles.count; i++) { + l.append(allStyles.styles[i]->key.styleName.isEmpty() ? + styleStringHelper(allStyles.styles[i]->key.weight, + (QFont::Style)allStyles.styles[i]->key.style) : + allStyles.styles[i]->key.styleName); + } return l; } @@ -2017,9 +2030,16 @@ QFont QFontDatabase::font(const QString &family, const QString &style, if (!s) // no styles found? return QApplication::font(); - QFont fnt(family, pointSize, s->key.weight); - fnt.setStyle((QFont::Style)s->key.style); - return fnt; + if (s->key.styleName.isEmpty()) { + QFont fnt(family, pointSize, s->key.weight); + fnt.setStyle((QFont::Style)s->key.style); + return fnt; + } else { + // found a perfect match + QFont fnt(family, pointSize); + fnt.setStyleName(s->key.styleName); + return fnt; + } } diff --git a/src/gui/text/qfontdatabase_mac.cpp b/src/gui/text/qfontdatabase_mac.cpp index 724dbf6c4a..b7335d684e 100644 --- a/src/gui/text/qfontdatabase_mac.cpp +++ b/src/gui/text/qfontdatabase_mac.cpp @@ -106,12 +106,14 @@ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i); QCFString family_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute); + QCFString style_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontStyleNameAttribute); QtFontFamily *family = db->family(family_name, true); for(int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) family->writingSystems[ws] = QtFontFamily::Supported; QtFontFoundry *foundry = family->foundry(foundry_name, true); QtFontStyle::Key styleKey; + styleKey.styleName = style_name; if(QCFType styles = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)) { if(CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontWeightTrait)) { Q_ASSERT(CFNumberIsFloatType(weight)); diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp index 958daa2506..ed94fa6be1 100644 --- a/src/gui/text/qfontdatabase_x11.cpp +++ b/src/gui/text/qfontdatabase_x11.cpp @@ -1034,13 +1034,14 @@ static void loadFontConfig() FcChar8 *file_value; int index_value; FcChar8 *foundry_value; + FcChar8 *style_value; FcBool scalable; { FcObjectSet *os = FcObjectSetCreate(); FcPattern *pattern = FcPatternCreate(); const char *properties [] = { - FC_FAMILY, FC_WEIGHT, FC_SLANT, + FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT, FC_SPACING, FC_FILE, FC_INDEX, FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WEIGHT, FC_WIDTH, @@ -1085,6 +1086,8 @@ static void loadFontConfig() scalable = FcTrue; if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) foundry_value = 0; + if (FcPatternGetString(fonts->fonts[i], FC_STYLE, 0, &style_value) != FcResultMatch) + style_value = 0; QtFontFamily *family = db->family(familyName, true); FcLangSet *langset = 0; @@ -1142,6 +1145,7 @@ static void loadFontConfig() family->fontFileIndex = index_value; QtFontStyle::Key styleKey; + styleKey.styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); styleKey.style = (slant_value == FC_SLANT_ITALIC) ? QFont::StyleItalic : ((slant_value == FC_SLANT_OBLIQUE) -- cgit v1.2.3 From bb6be57b38808273b3d302a782d68f31b3076894 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Mon, 27 Jun 2011 10:15:39 +0200 Subject: Only compare styleNames if they are not empty Task-number: QTBUG-19366 (cherry picked from commit 15e6ac8f4d9e7a419cd0c10405954bde78559fac) Change-Id: I5f06bb5133f23dbc8ad6d745d44ca0a85ef49686 Reviewed-on: http://codereview.qt.nokia.com/760 Reviewed-by: Qt Sanity Bot Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfont.cpp | 2 +- src/gui/text/qfont_p.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/gui/text') diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index e771b070ed..2d6af3b662 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -147,7 +147,7 @@ bool QFontDef::exactMatch(const QFontDef &other) const && weight == other.weight && style == other.style && this_family == other_family - && styleName == other.styleName + && (styleName.isEmpty() || other.styleName.isEmpty() || styleName == other.styleName) && (this_foundry.isEmpty() || other_foundry.isEmpty() || this_foundry == other_foundry) diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h index 4ae31c38d6..ebc842c794 100644 --- a/src/gui/text/qfont_p.h +++ b/src/gui/text/qfont_p.h @@ -113,7 +113,7 @@ struct QFontDef && styleStrategy == other.styleStrategy && ignorePitch == other.ignorePitch && fixedPitch == other.fixedPitch && family == other.family - && styleName == other.styleName + && (styleName.isEmpty() || other.styleName.isEmpty() || styleName == other.styleName) && hintingPreference == other.hintingPreference #ifdef Q_WS_X11 && addStyle == other.addStyle -- cgit v1.2.3 From 06c20891c12fd1089f7c41138fd50c6b26fdda69 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Mon, 27 Jun 2011 15:23:03 +0200 Subject: Add missing APIs to QRawFont and some additional notes to fromFont Change-Id: I8487a2e32f5b71a1eb51dcb8540cb5de2def09f6 Reviewed-on: http://codereview.qt.nokia.com/769 Reviewed-by: Qt Sanity Bot Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qrawfont.cpp | 27 +++++++++++++++++++++++++++ src/gui/text/qrawfont.h | 2 ++ 2 files changed, 29 insertions(+) (limited to 'src/gui/text') diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp index 71762df09f..4c65ad5de0 100644 --- a/src/gui/text/qrawfont.cpp +++ b/src/gui/text/qrawfont.cpp @@ -392,6 +392,30 @@ qreal QRawFont::unitsPerEm() const return d->fontEngine->emSquareSize().toReal(); } +/*! + Returns the thickness for drawing lines (underline, overline, etc.) + along with text drawn in this font. + */ +qreal QRawFont::lineThickness() const +{ + if (!isValid()) + return 0.0; + + return d->fontEngine->lineThickness().toReal(); +} + +/*! + Returns the position from baseline for drawing underlines below the text + rendered with this font. + */ +qreal QRawFont::underlinePosition() const +{ + if (!isValid()) + return 0.0; + + return d->fontEngine->underlinePosition().toReal(); +} + /*! Returns the family name of this QRawFont. */ @@ -652,6 +676,9 @@ extern int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSyst /*! Fetches the physical representation based on a \a font query. The physical font returned is the font that will be preferred by Qt in order to display text in the selected \a writingSystem. + + \warning This function is potentially expensive and should not be called in performance + sensitive code. */ QRawFont QRawFont::fromFont(const QFont &font, QFontDatabase::WritingSystem writingSystem) { diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h index aca33af127..d517c9ad7a 100644 --- a/src/gui/text/qrawfont.h +++ b/src/gui/text/qrawfont.h @@ -111,6 +111,8 @@ public: qreal xHeight() const; qreal averageCharWidth() const; qreal maxCharWidth() const; + qreal lineThickness() const; + qreal underlinePosition() const; qreal unitsPerEm() const; -- cgit v1.2.3 From a40d74e5547b3a27492d4ebc650dc6b69ab94728 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 28 Jun 2011 14:19:51 +0200 Subject: compile on Mac OS X Change-Id: Ibe74e51aab6e6b8d7a0e71cd88dcc97f72fcd1f9 Reviewed-on: http://codereview.qt.nokia.com/833 Reviewed-by: Qt Sanity Bot Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfont.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/gui/text') diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 2d6af3b662..cf97310ea3 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -80,7 +80,8 @@ #include #endif -#include +#include +#include // #define QFONTCACHE_DEBUG #ifdef QFONTCACHE_DEBUG -- cgit v1.2.3 From 399208c54b18bf7dd671439107fbb9910218a51c Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Thu, 30 Jun 2011 12:45:44 +0200 Subject: Move glyph run merging logic to QTextLayout level So that we can merge glyph runs from different QTextLines. Change-Id: Id8e0cc1aa21a482a995773fd55599c0011245e82 Reviewed-on: http://codereview.qt.nokia.com/950 Reviewed-by: Qt Sanity Bot Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qrawfont.h | 1 + src/gui/text/qtextlayout.cpp | 210 +++++++++++++++++++++---------------------- 2 files changed, 101 insertions(+), 110 deletions(-) (limited to 'src/gui/text') diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h index d517c9ad7a..e94bd99b8c 100644 --- a/src/gui/text/qrawfont.h +++ b/src/gui/text/qrawfont.h @@ -135,6 +135,7 @@ public: private: friend class QRawFontPrivate; + friend class QTextLayout; void detach(); diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index f9bfcbfce7..ae978b019a 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1004,15 +1004,46 @@ QList QTextLayout::glyphRuns(int from, int length) const if (length < 0) length = text().length(); - QList glyphs; + QHash, QGlyphRun> glyphRunHash; for (int i=0; ilines.size(); ++i) { if (d->lines[i].from > from + length) break; - else if (d->lines[i].from + d->lines[i].length >= from) - glyphs += QTextLine(i, d).glyphRuns(from, length); + else if (d->lines[i].from + d->lines[i].length >= from) { + QList glyphRuns = QTextLine(i, d).glyphRuns(from, length); + + for (int j = 0; j < glyphRuns.size(); j++) { + const QGlyphRun &glyphRun = glyphRuns.at(j); + QRawFont rawFont = glyphRun.rawFont(); + + QFontEngine *fontEngine = rawFont.d->fontEngine; + QTextItem::RenderFlags flags; + if (glyphRun.underline()) + flags |= QTextItem::Underline; + if (glyphRun.overline()) + flags |= QTextItem::Overline; + if (glyphRun.strikeOut()) + flags |= QTextItem::StrikeOut; + QPair key(fontEngine, int(flags)); + // merge the glyph runs using the same font + if (glyphRunHash.contains(key)) { + QGlyphRun &oldGlyphRun = glyphRunHash[key]; + + QVector indexes = oldGlyphRun.glyphIndexes(); + QVector positions = oldGlyphRun.positions(); + + indexes += glyphRun.glyphIndexes(); + positions += glyphRun.positions(); + + oldGlyphRun.setGlyphIndexes(indexes); + oldGlyphRun.setPositions(positions); + } else { + glyphRunHash[key] = glyphRun; + } + } + } } - return glyphs; + return glyphRunHash.values(); } #endif // QT_NO_RAWFONT @@ -2077,19 +2108,65 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q } -namespace { - struct GlyphInfo - { - GlyphInfo(const QGlyphLayout &layout, const QPointF &position, - const QTextItemInt::RenderFlags &renderFlags) - : glyphLayout(layout), itemPosition(position), flags(renderFlags) - { - } +static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &glyphLayout, + const QPointF &pos, const QTextItem::RenderFlags &flags) +{ + QGlyphRun glyphRun; - QGlyphLayout glyphLayout; - QPointF itemPosition; - QTextItem::RenderFlags flags; - }; + // Make a font for this particular engine + QRawFont font; + QRawFontPrivate *fontD = QRawFontPrivate::get(font); + fontD->fontEngine = fontEngine; + fontD->fontEngine->ref.ref(); + +#if defined(Q_WS_WIN) + if (fontEngine->supportsSubPixelPositions()) + fontD->hintingPreference = QFont::PreferVerticalHinting; + else + fontD->hintingPreference = QFont::PreferFullHinting; +#elif defined(Q_WS_MAC) + fontD->hintingPreference = QFont::PreferNoHinting; +#elif !defined(QT_NO_FREETYPE) + if (fontEngine->type() == QFontEngine::Freetype) { + QFontEngineFT *freeTypeEngine = static_cast(fontEngine); + switch (freeTypeEngine->defaultHintStyle()) { + case QFontEngineFT::HintNone: + fontD->hintingPreference = QFont::PreferNoHinting; + break; + case QFontEngineFT::HintLight: + fontD->hintingPreference = QFont::PreferVerticalHinting; + break; + case QFontEngineFT::HintMedium: + case QFontEngineFT::HintFull: + fontD->hintingPreference = QFont::PreferFullHinting; + break; + }; + } +#endif + + QVarLengthArray glyphsArray; + QVarLengthArray positionsArray; + + fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray, + positionsArray); + Q_ASSERT(glyphsArray.size() == positionsArray.size()); + + QVector glyphs; + QVector positions; + for (int i=0; i QTextLine::glyphRuns(int from, int length) const if (length < 0) length = textLength(); - QHash glyphLayoutHash; - QTextLineItemIterator iterator(eng, i); qreal y = line.y.toReal() + line.base().toReal(); + QList glyphRuns; while (!iterator.atEnd()) { QScriptItem &si = iterator.next(); if (si.analysis.flags >= QScriptAnalysis::TabOrObject) @@ -2193,8 +2269,8 @@ QList QTextLine::glyphRuns(int from, int length) const continue; QGlyphLayout subLayout = glyphLayout.mid(start, end - start); - glyphLayoutHash.insertMulti(multiFontEngine->engine(which), - GlyphInfo(subLayout, pos, flags)); + glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which), + subLayout, pos, flags)); for (int i = 0; i < subLayout.numGlyphs; i++) { pos += QPointF(subLayout.advances_x[i].toReal(), subLayout.advances_y[i].toReal()); @@ -2205,101 +2281,15 @@ QList QTextLine::glyphRuns(int from, int length) const } QGlyphLayout subLayout = glyphLayout.mid(start, end - start); - glyphLayoutHash.insertMulti(multiFontEngine->engine(which), - GlyphInfo(subLayout, pos, flags)); - + glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which), + subLayout, pos, flags)); } else { - glyphLayoutHash.insertMulti(mainFontEngine, - GlyphInfo(glyphLayout, pos, flags)); - } - } - } - - QHash, QGlyphRun> glyphsHash; - - QList keys = glyphLayoutHash.uniqueKeys(); - for (int i=0; ifontEngine = fontEngine; - fontD->fontEngine->ref.ref(); - -#if defined(Q_WS_WIN) - if (fontEngine->supportsSubPixelPositions()) - fontD->hintingPreference = QFont::PreferVerticalHinting; - else - fontD->hintingPreference = QFont::PreferFullHinting; -#elif defined(Q_WS_MAC) - fontD->hintingPreference = QFont::PreferNoHinting; -#elif !defined(QT_NO_FREETYPE) - if (fontEngine->type() == QFontEngine::Freetype) { - QFontEngineFT *freeTypeEngine = static_cast(fontEngine); - switch (freeTypeEngine->defaultHintStyle()) { - case QFontEngineFT::HintNone: - fontD->hintingPreference = QFont::PreferNoHinting; - break; - case QFontEngineFT::HintLight: - fontD->hintingPreference = QFont::PreferVerticalHinting; - break; - case QFontEngineFT::HintMedium: - case QFontEngineFT::HintFull: - fontD->hintingPreference = QFont::PreferFullHinting; - break; - }; - } -#endif - - QList glyphLayouts = glyphLayoutHash.values(fontEngine); - for (int j=0; j glyphsArray; - QVarLengthArray positionsArray; - - fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray, - positionsArray); - Q_ASSERT(glyphsArray.size() == positionsArray.size()); - - QVector glyphs; - QVector positions; - for (int i=0; i key(fontEngine, int(flags)); - if (!glyphsHash.contains(key)) { - glyphsHash.insert(key, glyphIndexes); - } else { - QGlyphRun &glyphRun = glyphsHash[key]; - - QVector indexes = glyphRun.glyphIndexes(); - QVector positions = glyphRun.positions(); - - indexes += glyphIndexes.glyphIndexes(); - positions += glyphIndexes.positions(); - - glyphRun.setGlyphIndexes(indexes); - glyphRun.setPositions(positions); + glyphRuns.append(glyphRunWithInfo(mainFontEngine, glyphLayout, pos, flags)); } } } - return glyphsHash.values(); + return glyphRuns; } #endif // QT_NO_RAWFONT -- cgit v1.2.3 From 3debd70c08da8bf974c8d226427a76aba51b754a Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 21 Jun 2011 11:24:35 +0200 Subject: Add HB_LineBreakType to qharfbuzz_copy_p.h. The QTextLayout relies on this enum to be defined. Change-Id: Ibcc8a0073bd56e29431c52c4ea54a909ff42f07b Reviewed-on: http://codereview.qt.nokia.com/537 Reviewed-by: Qt Sanity Bot Reviewed-by: Simon Hausmann --- src/gui/text/qharfbuzz_copy_p.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/gui/text') diff --git a/src/gui/text/qharfbuzz_copy_p.h b/src/gui/text/qharfbuzz_copy_p.h index 835d8fb1a6..10356e4aea 100644 --- a/src/gui/text/qharfbuzz_copy_p.h +++ b/src/gui/text/qharfbuzz_copy_p.h @@ -66,6 +66,13 @@ typedef enum { HB_Err_Out_Of_Memory = 0xDEAD } HB_Error; +typedef enum { + HB_NoBreak, + HB_SoftHyphen, + HB_Break, + HB_ForcedBreak +} HB_LineBreakType; + typedef QT_PREPEND_NAMESPACE(quint32) HB_Glyph; typedef void * HB_Font; typedef void * HB_Face; -- cgit v1.2.3 From 46c128bbf5561562458f6f7057e74eabacebe0ec Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 28 Jun 2011 17:07:13 +0200 Subject: Fix text color in some cases of QML and QStaticText This reverts 518c2a58ed6fdfd7449cb4476aa8ea0d32ad16e3 which caused a regression. When writing systems are mixed and an underline is set on the font, QPainter will set a pen with the current color and a new width on itself before drawing the decoration. This would cause the recorder in QStaticText to mark the pen as dirty, saving the current pen color in all subsequent text items. The effect was e.g. that in QML the cached color would override the current one, making it impossible to change the color on the text without forcing a relayout somehow. The right fix is to only mark the pen as dirty when its color actually changes. Task-number: QTBUG-20159 Change-Id: Ia819b67cccc9eaedd23fde655eab58cd892646f8 Reviewed-by: Jiang Jiang Reviewed-on: http://codereview.qt.nokia.com/870 Reviewed-by: Qt Sanity Bot Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qstatictext.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/gui/text') diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index fd17c4b214..388be3999c 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -427,14 +427,17 @@ namespace { public: DrawTextItemRecorder(bool untransformedCoordinates, bool useBackendOptimizations) : m_dirtyPen(false), m_useBackendOptimizations(useBackendOptimizations), - m_untransformedCoordinates(untransformedCoordinates) + m_untransformedCoordinates(untransformedCoordinates), m_currentColor(Qt::black) { } virtual void updateState(const QPaintEngineState &newState) { - if (newState.state() & QPaintEngine::DirtyPen) + if (newState.state() & QPaintEngine::DirtyPen + && newState.pen().color() != m_currentColor) { m_dirtyPen = true; + m_currentColor = newState.pen().color(); + } } virtual void drawTextItem(const QPointF &position, const QTextItem &textItem) @@ -450,7 +453,7 @@ namespace { currentItem.positionOffset = m_glyphs.size(); // Offset into position pool currentItem.useBackendOptimizations = m_useBackendOptimizations; if (m_dirtyPen) - currentItem.color = state->pen().color(); + currentItem.color = m_currentColor; QTransform matrix = m_untransformedCoordinates ? QTransform() : state->transform(); matrix.translate(position.x(), position.y()); @@ -521,6 +524,7 @@ namespace { bool m_dirtyPen; bool m_useBackendOptimizations; bool m_untransformedCoordinates; + QColor m_currentColor; }; class DrawTextItemDevice: public QPaintDevice -- cgit v1.2.3 From 0fc1e852aef7d97f41d32fd575d7ee3b94c11f80 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 30 Jun 2011 11:57:09 +0200 Subject: Fix transformations on DirectWrite rasterized text There were a few bugs in the DirectWrite font engine that caused transformed text to break. First of all, alphaMapForGlyph() ignored the transform, so no gray antialiased text would be transformed. Second of all, the imageForGlyph() function would use the wrong bounding box for the rasterized glyph, causing its positioning to become a little bit off when rotating. The fix is to get the bounding box from the system and add a margin to this instead of trying to predict how it will appear after the vertical hinting etc. has been applied. So that the positioning metrics are in sync with the actual metrics used by the alphaMap* functions, we also need to implement the alphaMapBoundingBox() function. Task-number: QTBUG-19829 Reviewed-by: Jiang Jiang (cherry picked from commit f54c5d9133d7aa7636988db36fa6cc51d26434b6) Change-Id: I3c3840b41e19fcacf926dbf454bdc2cba4bd5a99 Reviewed-on: http://codereview.qt.nokia.com/948 Reviewed-by: Qt Sanity Bot Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontenginedirectwrite.cpp | 145 ++++++++++++++++++++++---------- src/gui/text/qfontenginedirectwrite_p.h | 6 +- 2 files changed, 104 insertions(+), 47 deletions(-) (limited to 'src/gui/text') diff --git a/src/gui/text/qfontenginedirectwrite.cpp b/src/gui/text/qfontenginedirectwrite.cpp index 890cad9824..b6a172e03e 100644 --- a/src/gui/text/qfontenginedirectwrite.cpp +++ b/src/gui/text/qfontenginedirectwrite.cpp @@ -390,6 +390,60 @@ glyph_metrics_t QFontEngineDirectWrite::boundingBox(const QGlyphLayout &glyphs) return glyph_metrics_t(0, -m_ascent, w - lastRightBearing(glyphs), m_ascent + m_descent, w, 0); } +glyph_metrics_t QFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, + const QTransform &matrix, + GlyphFormat /*format*/) +{ + glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance + + UINT16 glyphIndex = glyph; + FLOAT glyphAdvance = 0; + + DWRITE_GLYPH_OFFSET glyphOffset; + glyphOffset.advanceOffset = 0; + glyphOffset.ascenderOffset = 0; + + DWRITE_GLYPH_RUN glyphRun; + glyphRun.fontFace = m_directWriteFontFace; + glyphRun.fontEmSize = fontDef.pixelSize; + glyphRun.glyphCount = 1; + glyphRun.glyphIndices = &glyphIndex; + glyphRun.glyphAdvances = &glyphAdvance; + glyphRun.isSideways = false; + glyphRun.bidiLevel = 0; + glyphRun.glyphOffsets = &glyphOffset; + + DWRITE_MATRIX transform; + transform.dx = subPixelPosition.toReal(); + transform.dy = 0; + transform.m11 = matrix.m11(); + transform.m12 = matrix.m12(); + transform.m21 = matrix.m21(); + transform.m22 = matrix.m22(); + + IDWriteGlyphRunAnalysis *glyphAnalysis = NULL; + HRESULT hr = m_directWriteFactory->CreateGlyphRunAnalysis( + &glyphRun, + 1.0f, + &transform, + DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, + DWRITE_MEASURING_MODE_NATURAL, + 0.0, 0.0, + &glyphAnalysis + ); + + if (SUCCEEDED(hr)) { + RECT rect; + glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect); + glyphAnalysis->Release(); + + return glyph_metrics_t(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, + bbox.xoff, bbox.yoff); + } else { + return glyph_metrics_t(); + } +} + glyph_metrics_t QFontEngineDirectWrite::boundingBox(glyph_t g) { if (m_directWriteFontFace == 0) @@ -459,9 +513,10 @@ qreal QFontEngineDirectWrite::maxCharWidth() const extern uint qt_pow_gamma[256]; -QImage QFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) +QImage QFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, + const QTransform &xform) { - QImage im = imageForGlyph(glyph, subPixelPosition, 0, QTransform()); + QImage im = imageForGlyph(glyph, subPixelPosition, 0, xform); QImage indexed(im.width(), im.height(), QImage::Format_Indexed8); QVector colors(256); @@ -492,12 +547,8 @@ QImage QFontEngineDirectWrite::imageForGlyph(glyph_t t, int margin, const QTransform &xform) { - glyph_metrics_t metrics = QFontEngine::boundingBox(t, xform); - int width = (metrics.width + margin * 2 + 4).ceil().toInt() ; - int height = (metrics.height + margin * 2 + 4).ceil().toInt(); - UINT16 glyphIndex = t; - FLOAT glyphAdvance = metrics.xoff.toReal(); + FLOAT glyphAdvance = 0; DWRITE_GLYPH_OFFSET glyphOffset; glyphOffset.advanceOffset = 0; @@ -513,12 +564,9 @@ QImage QFontEngineDirectWrite::imageForGlyph(glyph_t t, glyphRun.bidiLevel = 0; glyphRun.glyphOffsets = &glyphOffset; - QFixed x = margin - metrics.x.round() + subPixelPosition; - QFixed y = margin - metrics.y.floor(); - DWRITE_MATRIX transform; - transform.dx = x.toReal(); - transform.dy = y.toReal(); + transform.dx = subPixelPosition.toReal(); + transform.dy = 0; transform.m11 = xform.m11(); transform.m12 = xform.m12(); transform.m21 = xform.m21(); @@ -537,48 +585,53 @@ QImage QFontEngineDirectWrite::imageForGlyph(glyph_t t, if (SUCCEEDED(hr)) { RECT rect; - rect.left = 0; - rect.top = 0; - rect.right = width; - rect.bottom = height; - - int size = width * height * 3; - BYTE *alphaValues = new BYTE[size]; - qMemSet(alphaValues, size, 0); - - hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, - &rect, - alphaValues, - size); - - if (SUCCEEDED(hr)) { - QImage img(width, height, QImage::Format_RGB32); - img.fill(0xffffffff); + glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect); - for (int y=0; y(img.scanLine(y)); - BYTE *src = alphaValues + width * 3 * y; + rect.left -= margin; + rect.top -= margin; + rect.right += margin; + rect.bottom += margin; - for (int x=0; x 0) { + BYTE *alphaValues = new BYTE[size]; + qMemSet(alphaValues, size, 0); + + hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, + &rect, + alphaValues, + size); + + if (SUCCEEDED(hr)) { + QImage img(width, height, QImage::Format_RGB32); + img.fill(0xffffffff); + + for (int y=0; y(img.scanLine(y)); + BYTE *src = alphaValues + width * 3 * y; + + for (int x=0; xRelease(); + delete[] alphaValues; + return img; + } else { + delete[] alphaValues; - return img; - } else { - delete[] alphaValues; - glyphAnalysis->Release(); - - qErrnoWarning("QFontEngineDirectWrite::imageForGlyph: CreateAlphaTexture failed"); + qErrnoWarning("QFontEngineDirectWrite::imageForGlyph: CreateAlphaTexture failed"); + } } + glyphAnalysis->Release(); } else { qErrnoWarning("QFontEngineDirectWrite::imageForGlyph: CreateGlyphRunAnalysis failed"); } diff --git a/src/gui/text/qfontenginedirectwrite_p.h b/src/gui/text/qfontenginedirectwrite_p.h index d0086fc49b..edf1e6a182 100644 --- a/src/gui/text/qfontenginedirectwrite_p.h +++ b/src/gui/text/qfontenginedirectwrite_p.h @@ -86,6 +86,10 @@ public: glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); glyph_metrics_t boundingBox(glyph_t g); + glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, + QFixed subPixelPosition, + const QTransform &matrix, + GlyphFormat format); QFixed ascent() const; QFixed descent() const; @@ -97,7 +101,7 @@ public: bool supportsSubPixelPositions() const; - QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition); + QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t); QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform); -- cgit v1.2.3 From 25beb403ff2f419bfbd4c44220916486e58f4ed0 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 30 Jun 2011 12:54:46 +0200 Subject: Fix resource leak in QFontEngineDirectWrite Bug introduced by f54c5d9133d7aa7636988db36fa6cc51d26434b6. The release statement has to come before the return statement :) Reviewed-by: Jiang Jiang (cherry picked from commit d58eec3c932d1cdbcf3b42534e8fe870ec109487) Change-Id: Ib0b550ead3f971736142d88f4ca19bb8edc1b654 Reviewed-on: http://codereview.qt.nokia.com/949 Reviewed-by: Qt Sanity Bot Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontenginedirectwrite.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/gui/text') diff --git a/src/gui/text/qfontenginedirectwrite.cpp b/src/gui/text/qfontenginedirectwrite.cpp index b6a172e03e..d6932738f5 100644 --- a/src/gui/text/qfontenginedirectwrite.cpp +++ b/src/gui/text/qfontenginedirectwrite.cpp @@ -623,15 +623,16 @@ QImage QFontEngineDirectWrite::imageForGlyph(glyph_t t, } delete[] alphaValues; + glyphAnalysis->Release(); + return img; } else { delete[] alphaValues; + glyphAnalysis->Release(); qErrnoWarning("QFontEngineDirectWrite::imageForGlyph: CreateAlphaTexture failed"); } } - - glyphAnalysis->Release(); } else { qErrnoWarning("QFontEngineDirectWrite::imageForGlyph: CreateGlyphRunAnalysis failed"); } -- cgit v1.2.3 From df515ded6096a3c24df7bc9307a12790a6f474e1 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Fri, 3 Jun 2011 15:38:44 +0200 Subject: Doc: Fixed qdoc warnings. Change-Id: I7b4e9ef513b82a82d2365c9256d09520a44ad10d Reviewed-on: http://codereview.qt.nokia.com/324 Reviewed-by: Qt Sanity Bot Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qglyphrun.cpp | 3 ++- src/gui/text/qplatformfontdatabase_qpa.cpp | 37 +++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 7 deletions(-) (limited to 'src/gui/text') diff --git a/src/gui/text/qglyphrun.cpp b/src/gui/text/qglyphrun.cpp index 18b6357863..cc825525c4 100644 --- a/src/gui/text/qglyphrun.cpp +++ b/src/gui/text/qglyphrun.cpp @@ -175,7 +175,8 @@ QRawFont QGlyphRun::rawFont() const } /*! - Sets the font in which to look up the glyph indexes to \a font. + Sets the font in which to look up the glyph indexes to the \a rawFont + specified. \sa rawFont(), setGlyphIndexes() */ diff --git a/src/gui/text/qplatformfontdatabase_qpa.cpp b/src/gui/text/qplatformfontdatabase_qpa.cpp index 7e829dbd3f..059dc3e188 100644 --- a/src/gui/text/qplatformfontdatabase_qpa.cpp +++ b/src/gui/text/qplatformfontdatabase_qpa.cpp @@ -52,7 +52,7 @@ extern void qt_registerFont(const QString &familyname, const QString &foundrynam const QSupportedWritingSystems &writingSystems, void *hanlde); /*! - \fn void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *) + \fn void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *handle) Registers the pre-rendered QPF2 font contained in the given \a dataArray. @@ -149,17 +149,26 @@ public: QVector vector; }; +/*! + Constructs a new object to handle supported writing systems. +*/ QSupportedWritingSystems::QSupportedWritingSystems() { d = new QWritingSystemsPrivate; } +/*! + Constructs a copy of the \a other writing systems object. +*/ QSupportedWritingSystems::QSupportedWritingSystems(const QSupportedWritingSystems &other) { d = other.d; d->ref.ref(); } +/*! + Constructs a copy of the \a other writing systems object. +*/ QSupportedWritingSystems &QSupportedWritingSystems::operator=(const QSupportedWritingSystems &other) { if (d != other.d) { @@ -171,12 +180,18 @@ QSupportedWritingSystems &QSupportedWritingSystems::operator=(const QSupportedWr return *this; } +/*! + Destroys the supported writing systems object. +*/ QSupportedWritingSystems::~QSupportedWritingSystems() { if (!d->ref.deref()) delete d; } +/*! + \internal +*/ void QSupportedWritingSystems::detach() { if (d->ref != 1) { @@ -187,12 +202,20 @@ void QSupportedWritingSystems::detach() } } +/*! + Sets or clears support for the specified \a writingSystem based on the + value given by \a support. +*/ void QSupportedWritingSystems::setSupported(QFontDatabase::WritingSystem writingSystem, bool support) { detach(); d->vector[writingSystem] = support; } +/*! + Returns true if the writing system specified by \a writingSystem is + supported; otherwise returns false. +*/ bool QSupportedWritingSystems::supported(QFontDatabase::WritingSystem writingSystem) const { return d->vector.at(writingSystem); @@ -210,10 +233,12 @@ bool QSupportedWritingSystems::supported(QFontDatabase::WritingSystem writingSys */ /*! - This function is called once at startup by Qts internal fontdatabase. Reimplement this function - in a subclass for a convenient place to initialise the internal fontdatabase. + This function is called once at startup by Qt's internal font database. + Reimplement this function in a subclass for a convenient place to initialize + the internal font database. - The default implementation looks in the fontDir() location and registers all qpf2 fonts. + The default implementation looks in the fontDir() location and registers all + QPF2 fonts. */ void QPlatformFontDatabase::populateFontDatabase() { @@ -294,7 +319,7 @@ QStringList QPlatformFontDatabase::addApplicationFont(const QByteArray &fontData } /*! - + Releases the specified font \a handle. */ void QPlatformFontDatabase::releaseHandle(void *handle) { @@ -303,7 +328,7 @@ void QPlatformFontDatabase::releaseHandle(void *handle) } /*! - + Returns the directory containing the fonts used by the database. */ QString QPlatformFontDatabase::fontDir() const { -- cgit v1.2.3