summaryrefslogtreecommitdiffstats
path: root/src/gui/text
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/text')
-rw-r--r--src/gui/text/qfont.cpp5
-rw-r--r--src/gui/text/qfont_p.h2
-rw-r--r--src/gui/text/qfontdatabase.cpp42
-rw-r--r--src/gui/text/qfontenginedirectwrite.cpp146
-rw-r--r--src/gui/text/qfontenginedirectwrite_p.h6
-rw-r--r--src/gui/text/qglyphrun.cpp3
-rw-r--r--src/gui/text/qharfbuzz_copy_p.h7
-rw-r--r--src/gui/text/qplatformfontdatabase_qpa.cpp37
-rw-r--r--src/gui/text/qrawfont.cpp27
-rw-r--r--src/gui/text/qrawfont.h3
-rw-r--r--src/gui/text/qstatictext.cpp10
-rw-r--r--src/gui/text/qtextlayout.cpp210
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