diff options
Diffstat (limited to 'src/gui/text')
-rw-r--r-- | src/gui/text/qfont.cpp | 5 | ||||
-rw-r--r-- | src/gui/text/qfont_p.h | 2 | ||||
-rw-r--r-- | src/gui/text/qfontdatabase.cpp | 42 | ||||
-rw-r--r-- | src/gui/text/qfontenginedirectwrite.cpp | 146 | ||||
-rw-r--r-- | src/gui/text/qfontenginedirectwrite_p.h | 6 | ||||
-rw-r--r-- | src/gui/text/qglyphrun.cpp | 3 | ||||
-rw-r--r-- | src/gui/text/qharfbuzz_copy_p.h | 7 | ||||
-rw-r--r-- | src/gui/text/qplatformfontdatabase_qpa.cpp | 37 | ||||
-rw-r--r-- | src/gui/text/qrawfont.cpp | 27 | ||||
-rw-r--r-- | src/gui/text/qrawfont.h | 3 | ||||
-rw-r--r-- | src/gui/text/qstatictext.cpp | 10 | ||||
-rw-r--r-- | src/gui/text/qtextlayout.cpp | 210 |
12 files changed, 317 insertions, 181 deletions
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 846d5a3814..b85c045064 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -73,7 +73,8 @@ #include <QtGui/private/qguiapplication_p.h> #endif -#include <QMutexLocker> +#include <QtCore/QMutexLocker> +#include <QtCore/QMutex> // #define QFONTCACHE_DEBUG #ifdef QFONTCACHE_DEBUG @@ -140,7 +141,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 diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 5369ac52f3..98b43d5b5e 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 QGuiApplication::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/qfontenginedirectwrite.cpp b/src/gui/text/qfontenginedirectwrite.cpp index 890cad9824..d6932738f5 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<QRgb> 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,54 @@ 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<height; ++y) { - uint *dest = reinterpret_cast<uint *>(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<width; ++x) { - dest[x] = *(src) << 16 - | *(src + 1) << 8 - | *(src + 2); + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; - src += 3; + int size = width * height * 3; + if (size > 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<height; ++y) { + uint *dest = reinterpret_cast<uint *>(img.scanLine(y)); + BYTE *src = alphaValues + width * 3 * y; + + for (int x=0; x<width; ++x) { + dest[x] = *(src) << 16 + | *(src + 1) << 8 + | *(src + 2); + + src += 3; + } } - } - delete[] alphaValues; - glyphAnalysis->Release(); + delete[] alphaValues; + glyphAnalysis->Release(); - return img; - } else { - delete[] alphaValues; - glyphAnalysis->Release(); + return img; + } else { + delete[] alphaValues; + glyphAnalysis->Release(); - qErrnoWarning("QFontEngineDirectWrite::imageForGlyph: CreateAlphaTexture failed"); + qErrnoWarning("QFontEngineDirectWrite::imageForGlyph: CreateAlphaTexture failed"); + } } - } 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); 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/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; 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<bool> 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 { 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 @@ -393,6 +393,30 @@ qreal QRawFont::unitsPerEm() const } /*! + 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. */ QString QRawFont::familyName() const @@ -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..e94bd99b8c 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; @@ -133,6 +135,7 @@ public: private: friend class QRawFontPrivate; + friend class QTextLayout; void detach(); diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index baa9eebb79..10c494dec9 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -425,14 +425,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) @@ -448,7 +451,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()); @@ -519,6 +522,7 @@ namespace { bool m_dirtyPen; bool m_useBackendOptimizations; bool m_untransformedCoordinates; + QColor m_currentColor; }; class DrawTextItemDevice: public QPaintDevice diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 03e00ed0df..918ddcc280 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1002,15 +1002,46 @@ QList<QGlyphRun> QTextLayout::glyphRuns(int from, int length) const if (length < 0) length = text().length(); - QList<QGlyphRun> glyphs; + QHash<QPair<QFontEngine *, int>, QGlyphRun> glyphRunHash; for (int i=0; i<d->lines.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<QGlyphRun> 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<QFontEngine *, int> key(fontEngine, int(flags)); + // merge the glyph runs using the same font + if (glyphRunHash.contains(key)) { + QGlyphRun &oldGlyphRun = glyphRunHash[key]; + + QVector<quint32> indexes = oldGlyphRun.glyphIndexes(); + QVector<QPointF> 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 @@ -2075,19 +2106,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<QFontEngineFT *>(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<glyph_t> glyphsArray; + QVarLengthArray<QFixedPoint> positionsArray; + + fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray, + positionsArray); + Q_ASSERT(glyphsArray.size() == positionsArray.size()); + + QVector<quint32> glyphs; + QVector<QPointF> positions; + for (int i=0; i<glyphsArray.size(); ++i) { + glyphs.append(glyphsArray.at(i) & 0xffffff); + positions.append(positionsArray.at(i).toPointF() + pos); + } + + glyphRun.setGlyphIndexes(glyphs); + glyphRun.setPositions(positions); + + glyphRun.setOverline(flags.testFlag(QTextItem::Overline)); + glyphRun.setUnderline(flags.testFlag(QTextItem::Underline)); + glyphRun.setStrikeOut(flags.testFlag(QTextItem::StrikeOut)); + glyphRun.setRawFont(font); + + return glyphRun; } /*! @@ -2117,10 +2194,9 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const if (length < 0) length = textLength(); - QHash<QFontEngine *, GlyphInfo> glyphLayoutHash; - QTextLineItemIterator iterator(eng, i); qreal y = line.y.toReal() + line.base().toReal(); + QList<QGlyphRun> glyphRuns; while (!iterator.atEnd()) { QScriptItem &si = iterator.next(); if (si.analysis.flags >= QScriptAnalysis::TabOrObject) @@ -2191,8 +2267,8 @@ QList<QGlyphRun> 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()); @@ -2203,101 +2279,15 @@ QList<QGlyphRun> 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<QPair<QFontEngine *, int>, QGlyphRun> glyphsHash; - - QList<QFontEngine *> keys = glyphLayoutHash.uniqueKeys(); - for (int i=0; i<keys.size(); ++i) { - QFontEngine *fontEngine = keys.at(i); - - // 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<QFontEngineFT *>(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<GlyphInfo> glyphLayouts = glyphLayoutHash.values(fontEngine); - for (int j=0; j<glyphLayouts.size(); ++j) { - const QPointF &pos = glyphLayouts.at(j).itemPosition; - const QGlyphLayout &glyphLayout = glyphLayouts.at(j).glyphLayout; - const QTextItem::RenderFlags &flags = glyphLayouts.at(j).flags; - - QVarLengthArray<glyph_t> glyphsArray; - QVarLengthArray<QFixedPoint> positionsArray; - - fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray, - positionsArray); - Q_ASSERT(glyphsArray.size() == positionsArray.size()); - - QVector<quint32> glyphs; - QVector<QPointF> positions; - for (int i=0; i<glyphsArray.size(); ++i) { - glyphs.append(glyphsArray.at(i) & 0xffffff); - positions.append(positionsArray.at(i).toPointF() + pos); - } - - QGlyphRun glyphIndexes; - glyphIndexes.setGlyphIndexes(glyphs); - glyphIndexes.setPositions(positions); - - glyphIndexes.setOverline(flags.testFlag(QTextItem::Overline)); - glyphIndexes.setUnderline(flags.testFlag(QTextItem::Underline)); - glyphIndexes.setStrikeOut(flags.testFlag(QTextItem::StrikeOut)); - glyphIndexes.setRawFont(font); - - QPair<QFontEngine *, int> key(fontEngine, int(flags)); - if (!glyphsHash.contains(key)) { - glyphsHash.insert(key, glyphIndexes); - } else { - QGlyphRun &glyphRun = glyphsHash[key]; - - QVector<quint32> indexes = glyphRun.glyphIndexes(); - QVector<QPointF> 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 |