summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2010-05-03 09:55:44 +0200
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2010-06-04 08:59:59 +0200
commitcad70d64d0bbada72a072ac7fdf461839db9d72a (patch)
treed90c97fdc9561d6108820126e8c7e6d46683f88f /src/gui
parenta64791bdf663fb1d7595f11fbe7e44a62acd4126 (diff)
New class: QGlyphs
Introduce an API to access glyph indexes in a font directly. A bug was discovered during this work, where different hinting flags in loadGlyph() and loadGlyphMetrics() would make the metrics in the two functions different, thus causing drawCachedGlyphs() (which uses loadGlyphMetrics() indirectly) to use different metrics than the standard drawTextItem() code path (which uses loadGlyph()). The bug was visible in the tst_QGlyphs::drawExistingGlyphs() test. Reviewed-by: Simon Hausmann
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/painting/qpainter.cpp52
-rw-r--r--src/gui/painting/qpainter.h3
-rw-r--r--src/gui/painting/qpainter_p.h3
-rw-r--r--src/gui/text/qfont.h1
-rw-r--r--src/gui/text/qfontengine.cpp18
-rw-r--r--src/gui/text/qfontengine_ft.cpp9
-rw-r--r--src/gui/text/qfontengine_mac.mm27
-rw-r--r--src/gui/text/qfontengine_p.h9
-rw-r--r--src/gui/text/qglyphs.cpp199
-rw-r--r--src/gui/text/qglyphs.h96
-rw-r--r--src/gui/text/qglyphs_p.h84
-rw-r--r--src/gui/text/qtextlayout.cpp136
-rw-r--r--src/gui/text/qtextlayout.h5
-rw-r--r--src/gui/text/text.pri7
14 files changed, 633 insertions, 16 deletions
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index dd3584af3c..cb56ac8828 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -61,6 +61,8 @@
#include "qstyle.h"
#include "qthread.h"
#include "qvarlengtharray.h"
+#include "qstatictext.h"
+#include "qglyphs.h"
#include <private/qfontengine_p.h>
#include <private/qpaintengine_p.h>
@@ -70,8 +72,8 @@
#include <private/qwidget_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qmath_p.h>
-#include <qstatictext.h>
#include <private/qstatictext_p.h>
+#include <private/qglyphs_p.h>
QT_BEGIN_NAMESPACE
@@ -5704,16 +5706,47 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR
d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
}
+/*!
+ Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
+ edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
+ selected on \a glyphs and at offsets given by the positions in \a glyphs.
+
+ \since 4.8
+
+ \sa QGlyphs::setFont(), QGlyphs::setPositions(), QGlyphs::setGlyphIndexes()
+*/
+void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs)
+{
+ Q_D(QPainter);
+
+ QFont oldFont = d->state->font;
+ d->state->font = glyphs.font();
+
+ QVector<quint32> glyphIndexes = glyphs.glyphIndexes();
+ QVector<QPointF> glyphPositions = glyphs.positions();
+
+ int count = qMin(glyphIndexes.size(), glyphPositions.size());
+ QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
+ for (int i=0; i<count; ++i)
+ fixedPointPositions[i] = QFixedPoint::fromPointF(position + glyphPositions.at(i));
+
+ d->drawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count);
+
+ d->state->font = oldFont;
+}
void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray, const QPointF *positionArray,
int glyphCount)
-{
+{
+ QVarLengthArray<QFixedPoint, 128> positions(glyphCount);
+ for (int i=0; i<glyphCount; ++i)
+ positions[i] = QFixedPoint::fromPointF(positionArray[i]);
+
QPainterPrivate *painter_d = QPainterPrivate::get(painter);
- painter_d->drawGlyphs(glyphArray, positionArray, glyphCount);
+ painter_d->drawGlyphs(const_cast<quint32 *>(glyphArray), positions.data(), glyphCount);
}
-void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray,
- int glyphCount)
+void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, int glyphCount)
{
updateState(state);
@@ -5729,11 +5762,6 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit
fontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);
}
- QVarLengthArray<QFixedPoint, 128> positions;
- for (int i=0; i<glyphCount; ++i) {
- QFixedPoint fp = QFixedPoint::fromPointF(positionArray[i]);
- positions.append(fp);
- }
if (extended != 0) {
QStaticTextItem staticTextItem;
@@ -5742,7 +5770,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit
staticTextItem.fontEngine = fontEngine;
staticTextItem.numGlyphs = glyphCount;
staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
- staticTextItem.glyphPositions = positions.data();
+ staticTextItem.glyphPositions = positions;
extended->drawStaticTextItem(&staticTextItem);
} else {
@@ -5759,7 +5787,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit
textItem.glyphs.numGlyphs = glyphCount;
textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
- textItem.glyphs.offsets = positions.data();
+ textItem.glyphs.offsets = positions;
textItem.glyphs.advances_x = advances.data();
textItem.glyphs.advances_y = advances.data();
textItem.glyphs.justifications = glyphJustifications.data();
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index edfb67ecb1..85751a9f2d 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -79,6 +79,7 @@ class QTextItem;
class QMatrix;
class QTransform;
class QStaticText;
+class QGlyphs;
class QPainterPrivateDeleter;
@@ -396,6 +397,8 @@ public:
void setLayoutDirection(Qt::LayoutDirection direction);
Qt::LayoutDirection layoutDirection() const;
+ void drawGlyphs(const QPointF &position, const QGlyphs &glyphs);
+
void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText);
inline void drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText);
inline void drawStaticText(int left, int top, const QStaticText &staticText);
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index 9362dbe80c..a61f5cae58 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -70,6 +70,7 @@ QT_BEGIN_NAMESPACE
class QPaintEngine;
class QEmulationPaintEngine;
class QPaintEngineEx;
+struct QFixedPoint;
struct QTLWExtra;
@@ -228,7 +229,7 @@ public:
void draw_helper(const QPainterPath &path, DrawOperation operation = StrokeAndFillDraw);
void drawStretchedGradient(const QPainterPath &path, DrawOperation operation);
void drawOpaqueBackground(const QPainterPath &path, DrawOperation operation);
- void drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, int glyphCount);
+ void drawGlyphs(quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount);
void updateMatrix();
void updateInvMatrix();
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index 6f624246b9..b0e405edd0 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -312,6 +312,7 @@ private:
friend class QPainterReplayer;
friend class QPaintBufferEngine;
friend class QCommandLinkButtonPrivate;
+ friend class QFontEngine;
#ifndef QT_NO_DATASTREAM
friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QFont &);
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 194c5f3dd4..2d95baef1f 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -242,6 +242,24 @@ glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix
return metrics;
}
+QFont QFontEngine::createExplicitFont() const
+{
+ return createExplicitFontWithName(fontDef.family);
+}
+
+QFont QFontEngine::createExplicitFontWithName(const QString &familyName) const
+{
+ QFont font(familyName);
+ font.setStyleStrategy(QFont::NoFontMerging);
+ font.setWeight(fontDef.weight);
+ font.setItalic(fontDef.style == QFont::StyleItalic);
+ if (fontDef.pointSize < 0)
+ font.setPixelSize(fontDef.pixelSize);
+ else
+ font.setPointSizeF(fontDef.pointSize);
+ return font;
+}
+
QFixed QFontEngine::xHeight() const
{
QGlyphLayoutArray<8> glyphs;
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 9056012b6c..737689365f 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -756,9 +756,18 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph
return g;
int load_flags = FT_LOAD_DEFAULT | default_load_flags;
+ int load_target = default_hint_style == HintLight
+ ? FT_LOAD_TARGET_LIGHT
+ : FT_LOAD_TARGET_NORMAL;
+
if (set->outline_drawing)
load_flags = FT_LOAD_NO_BITMAP;
+ if (default_hint_style == HintNone)
+ load_flags |= FT_LOAD_NO_HINTING;
+ else
+ load_flags |= load_target;
+
// apply our matrix to this, but note that the metrics will not be affected by this.
FT_Face face = lockFace();
FT_Matrix matrix = this->matrix;
diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm
index 3be6d284c1..c9b5655889 100644
--- a/src/gui/text/qfontengine_mac.mm
+++ b/src/gui/text/qfontengine_mac.mm
@@ -607,6 +607,12 @@ void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *position
}
}
+QFont QCoreTextFontEngine::createExplicitFont() const
+{
+ QString familyName = QCFString::toQString(CTFontCopyFamilyName(ctfont));
+ return createExplicitFontWithName(familyName);
+}
+
QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, int margin, bool aa)
{
const glyph_metrics_t br = boundingBox(glyph);
@@ -1542,6 +1548,27 @@ static void addGlyphsToPathHelper(ATSUStyle style, glyph_t *glyphs, QFixedPoint
DisposeATSCubicClosePathUPP(closePath);
}
+QFont QFontEngineMac::createExplicitFont() const
+{
+ FMFont fmFont = FMGetFontFromATSFontRef(fontID);
+
+ FMFontFamily fmFamily;
+ FMFontStyle fmStyle;
+ QString familyName;
+ if (!FMGetFontFamilyInstanceFromFont(fmFont, &fmFamily, &fmStyle)) {
+ ATSFontFamilyRef familyRef = FMGetATSFontFamilyRefFromFontFamily(fmFamily);
+ QCFString cfFamilyName;;
+ ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &cfFamilyName);
+ familyName = cfFamilyName;
+ } else {
+ QCFString cfFontName;
+ ATSFontGetName(fontID, kATSOptionFlagsDefault, &cfFontName);
+ familyName = cfFontName;
+ }
+
+ return createExplicitFontWithName(familyName);
+}
+
void QFontEngineMac::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path,
QTextItem::RenderFlags)
{
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 922acfb34c..d29ef456ae 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -173,6 +173,10 @@ public:
#endif
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
QPainterPath *path, QTextItem::RenderFlags flags);
+
+ /* Creates a QFont object to represent this particular QFontEngine */
+ virtual QFont createExplicitFont() const;
+
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags,
QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions);
@@ -252,6 +256,7 @@ public:
int glyphFormat;
protected:
+ QFont createExplicitFontWithName(const QString &familyName) const;
static const QVector<QRgb> &grayPalette();
private:
@@ -454,7 +459,7 @@ public:
virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t);
virtual qreal minRightBearing() const;
virtual qreal minLeftBearing() const;
-
+ virtual QFont createExplicitFont() const;
private:
QImage imageForGlyph(glyph_t glyph, int margin, bool colorful);
@@ -520,6 +525,8 @@ public:
virtual qreal maxCharWidth() const;
virtual QFixed averageCharWidth() const;
+ virtual QFont createExplicitFont() const;
+
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs,
QPainterPath *path, QTextItem::RenderFlags);
diff --git a/src/gui/text/qglyphs.cpp b/src/gui/text/qglyphs.cpp
new file mode 100644
index 0000000000..847646e4ba
--- /dev/null
+++ b/src/gui/text/qglyphs.cpp
@@ -0,0 +1,199 @@
+#include "qglyphs.h"
+#include "qglyphs_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QGlyphs
+ \brief the QGlyphs class provides direct access to the internal glyphs in a font
+ \since 4.8
+
+ \ingroup text
+ \mainclass
+
+ When Qt displays a string of text encoded in Unicode, it will first convert the Unicode points
+ into a list of glyph indexes and a list of positions based on one or more fonts. The Unicode
+ representation of the text and the QFont object will in this case serve as a convenient
+ abstraction that hides the details of what actually takes place when displaying the text
+ on-screen. For instance, by the time the text actually reaches the screen, it may be represented
+ by a set of fonts in addition to the one specified by the user, e.g. in case the originally
+ selected font did not support all the writing systems contained in the text.
+
+ Under certain circumstances, it can be useful as an application developer to have more low-level
+ control over which glyphs in a specific font are drawn to the screen. This could for instance
+ be the case in applications that use an external font engine and text shaper together with Qt.
+ QGlyphs provides an interface to the raw data needed to get text on the screen. It
+ contains a list of glyph indexes, a position for each glyph and a font.
+
+ It is the user's responsibility to ensure that the selected font actually contains the
+ provided glyph indexes.
+
+ QTextLayout::glyphs() can be used to convert unicode encoded text into a list of QGlyphs
+ objects, and QPainter::drawGlyphs() can be used to draw the glyphs.
+*/
+
+
+/*!
+ Constructs an empty QGlyphs object.
+*/
+QGlyphs::QGlyphs() : d(new QGlyphsPrivate)
+{
+}
+
+/*!
+ Constructs a QGlyphs object which is a copy of \a other.
+*/
+QGlyphs::QGlyphs(const QGlyphs &other)
+{
+ d = other.d;
+}
+
+/*!
+ Destroys the QGlyphs.
+*/
+QGlyphs::~QGlyphs()
+{
+ // Required for QExplicitlySharedDataPointer
+}
+
+/*!
+ \internal
+*/
+void QGlyphs::detach()
+{
+ if (d->ref != 1)
+ d.detach();
+}
+
+/*!
+ Assigns \a other to this QGlyphs object.
+*/
+QGlyphs &QGlyphs::operator=(const QGlyphs &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Compares \a other to this QGlyphs object. Returns true if the list of glyph indexes,
+ the list of positions and the font are all equal, otherwise returns false.
+*/
+bool QGlyphs::operator==(const QGlyphs &other) const
+{
+ return ((d == other.d)
+ || (d->glyphIndexes == other.d->glyphIndexes
+ && d->glyphPositions == other.d->glyphPositions
+ && d->font == other.d->font));
+}
+
+/*!
+ Compares \a other to this QGlyphs object. Returns true if any of the list of glyph
+ indexes, the list of positions or the font are different, otherwise returns false.
+*/
+bool QGlyphs::operator!=(const QGlyphs &other) const
+{
+ return !(*this == other);
+}
+
+/*!
+ \internal
+
+ Adds together the lists of glyph indexes and positions in \a other and this QGlyphs
+ object and returns the result. The font in the returned QGlyphs will be the same as in
+ this QGlyphs object.
+*/
+QGlyphs QGlyphs::operator+(const QGlyphs &other) const
+{
+ QGlyphs ret(*this);
+ ret += other;
+ return ret;
+}
+
+/*!
+ \internal
+
+ Appends the glyph indexes and positions in \a other to this QGlyphs object and returns
+ a reference to the current object.
+*/
+QGlyphs &QGlyphs::operator+=(const QGlyphs &other)
+{
+ detach();
+
+ d->glyphIndexes += other.d->glyphIndexes;
+ d->glyphPositions += other.d->glyphPositions;
+
+ return *this;
+}
+
+/*!
+ Returns the font selected for this QGlyphs object.
+
+ \sa setFont()
+*/
+QFont QGlyphs::font() const
+{
+ return d->font;
+}
+
+/*!
+ Sets the font in which to look up the glyph indexes to \a font. This must be an explicitly
+ resolvable font which defines glyphs for the specified glyph indexes.
+
+ \sa font(), setGlyphIndexes()
+*/
+void QGlyphs::setFont(const QFont &font)
+{
+ detach();
+ d->font = font;
+}
+
+/*!
+ Returns the glyph indexes for this QGlyphs object.
+
+ \sa setGlyphIndexes(), setPositions()
+*/
+QVector<quint32> QGlyphs::glyphIndexes() const
+{
+ return d->glyphIndexes;
+}
+
+/*!
+ Set the glyph indexes for this QGlyphs object to \a glyphIndexes. The glyph indexes must
+ be valid for the selected font.
+*/
+void QGlyphs::setGlyphIndexes(const QVector<quint32> &glyphIndexes)
+{
+ detach();
+ d->glyphIndexes = glyphIndexes;
+}
+
+/*!
+ Returns the position of the edge of the baseline for each glyph in this set of glyph indexes.
+*/
+QVector<QPointF> QGlyphs::positions() const
+{
+ return d->glyphPositions;
+}
+
+/*!
+ Sets the positions of the edge of the baseline for each glyph in this set of glyph indexes to
+ \a positions.
+*/
+void QGlyphs::setPositions(const QVector<QPointF> &positions)
+{
+ detach();
+ d->glyphPositions = positions;
+}
+
+/*!
+ Clears all data in the QGlyphs object.
+*/
+void QGlyphs::clear()
+{
+ detach();
+ d->glyphPositions = QVector<QPointF>();
+ d->glyphIndexes = QVector<quint32>();
+ d->font = QFont();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qglyphs.h b/src/gui/text/qglyphs.h
new file mode 100644
index 0000000000..282ecb47c5
--- /dev/null
+++ b/src/gui/text/qglyphs.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGLYPHS_H
+#define QGLYPHS_H
+
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qpoint.h>
+#include <QtGui/qfont.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QGlyphsPrivate;
+class Q_GUI_EXPORT QGlyphs
+{
+public:
+ QGlyphs();
+ QGlyphs(const QGlyphs &other);
+ ~QGlyphs();
+
+ QFont font() const;
+ void setFont(const QFont &font);
+
+ QVector<quint32> glyphIndexes() const;
+ void setGlyphIndexes(const QVector<quint32> &glyphIndexes);
+
+ QVector<QPointF> positions() const;
+ void setPositions(const QVector<QPointF> &positions);
+
+ void clear();
+
+ QGlyphs &operator=(const QGlyphs &other);
+ bool operator==(const QGlyphs &other) const;
+ bool operator!=(const QGlyphs &other) const;
+
+private:
+ friend class QGlyphsPrivate;
+ friend class QTextLine;
+
+ QGlyphs operator+(const QGlyphs &other) const;
+ QGlyphs &operator+=(const QGlyphs &other);
+
+ void detach();
+ QExplicitlySharedDataPointer<QGlyphsPrivate> d;
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif // QGLYPHS_H
diff --git a/src/gui/text/qglyphs_p.h b/src/gui/text/qglyphs_p.h
new file mode 100644
index 0000000000..c39f5d0e56
--- /dev/null
+++ b/src/gui/text/qglyphs_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGLYPHS_P_H
+#define QGLYPHS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of internal files. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qfont.h>
+#include "qglyphs.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QGlyphsPrivate: public QSharedData
+{
+public:
+ QGlyphsPrivate()
+ {
+ }
+
+ QGlyphsPrivate(const QGlyphsPrivate &other)
+ : QSharedData(other), glyphIndexes(other.glyphIndexes), glyphPositions(other.glyphPositions), font(other.font)
+ {
+ }
+
+ QVector<quint32> glyphIndexes;
+ QVector<QPointF> glyphPositions;
+ QFont font;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGLYPHS_P_H
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 412c909639..b581969f97 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -52,6 +52,8 @@
#include "qtextformat_p.h"
#include "qstyleoption.h"
#include "qpainterpath.h"
+#include "qglyphs.h"
+#include "qglyphs_p.h"
#include <limits.h>
#include <qdebug.h>
@@ -894,6 +896,7 @@ qreal QTextLayout::maximumWidth() const
return d->maxWidth.toReal();
}
+
/*!
\internal
*/
@@ -1106,6 +1109,24 @@ static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip)
return clip.isValid() ? (rect & clip) : rect;
}
+
+/*!
+ Returns the glyph indexes and positions for all glyphs in this QTextLayout. This is an
+ expensive function, and should not be called in a time sensitive context.
+
+ \since 4.8
+
+ \sa draw(), QPainter::drawGlyphs()
+*/
+QList<QGlyphs> QTextLayout::glyphs() const
+{
+ QList<QGlyphs> glyphs;
+ for (int i=0; i<d->lines.size(); ++i)
+ glyphs += QTextLine(i, d).glyphs();
+
+ return glyphs;
+}
+
/*!
Draws the whole layout on the painter \a p at the position specified by
\a pos.
@@ -2135,6 +2156,121 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q
}
+namespace {
+ struct GlyphInfo
+ {
+ GlyphInfo(const QGlyphLayout &layout, const QPointF &position)
+ : glyphLayout(layout), itemPosition(position)
+ {
+ }
+
+ QGlyphLayout glyphLayout;
+ QPointF itemPosition;
+ };
+}
+
+/*!
+ \internal
+
+ Returns the glyph indexes and positions for all glyphs in this QTextLine.
+
+ \since 4.8
+
+ \sa QTextLayout::glyphs()
+*/
+QList<QGlyphs> QTextLine::glyphs() const
+{
+ const QScriptLine &line = eng->lines[i];
+
+ if (line.length == 0)
+ return QList<QGlyphs>();
+
+ QHash<QFontEngine *, GlyphInfo> glyphLayoutHash;
+
+ QTextLineItemIterator iterator(eng, i);
+ qreal y = line.y.toReal() + line.base().toReal();
+ while (!iterator.atEnd()) {
+ QScriptItem &si = iterator.next();
+ QPointF pos(iterator.x.toReal(), y);
+
+ QFont font = eng->font(si);
+ QGlyphLayout glyphLayout = eng->shapedGlyphs(&si).mid(iterator.glyphsStart,
+ iterator.glyphsEnd - iterator.glyphsStart);
+
+ if (glyphLayout.numGlyphs > 0) {
+ QFontEngine *mainFontEngine = font.d->engineForScript(si.analysis.script);
+ if (mainFontEngine->type() == QFontEngine::Multi) {
+ QFontEngineMulti *multiFontEngine = static_cast<QFontEngineMulti *>(mainFontEngine);
+ int start = 0;
+ int end;
+ int which = glyphLayout.glyphs[0] >> 24;
+ for (end = 0; end < glyphLayout.numGlyphs; ++end) {
+ const int e = glyphLayout.glyphs[end] >> 24;
+ if (e == which)
+ continue;
+
+ QGlyphLayout subLayout = glyphLayout.mid(start, end - start);
+ glyphLayoutHash.insertMulti(multiFontEngine->engine(which),
+ GlyphInfo(subLayout, pos));
+
+ start = end;
+ which = e;
+ }
+
+ QGlyphLayout subLayout = glyphLayout.mid(start, end - start);
+ glyphLayoutHash.insertMulti(multiFontEngine->engine(which),
+ GlyphInfo(subLayout, pos));
+
+ } else {
+ glyphLayoutHash.insertMulti(mainFontEngine,
+ GlyphInfo(glyphLayout, pos));
+ }
+ }
+ }
+
+ QHash<QFontEngine *, QGlyphs> 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
+ QFont font = fontEngine->createExplicitFont();
+
+ 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;
+
+ QVarLengthArray<glyph_t> glyphsArray;
+ QVarLengthArray<QFixedPoint> positionsArray;
+
+ fontEngine->getGlyphPositions(glyphLayout, QTransform(), 0, 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);
+ }
+
+ QGlyphs glyphIndexes;
+ glyphIndexes.setGlyphIndexes(glyphs);
+ glyphIndexes.setPositions(positions);
+
+ if (!glyphsHash.contains(fontEngine))
+ glyphsHash.insert(fontEngine, QGlyphs());
+
+ QGlyphs &target = glyphsHash[fontEngine];
+ target += glyphIndexes;
+ target.setFont(font);
+ }
+ }
+
+ return glyphsHash.values();
+}
+
/*!
\fn void QTextLine::draw(QPainter *painter, const QPointF &position, const QTextLayout::FormatRange *selection) const
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index 8c93ed65b6..f6aaf22d0f 100644
--- a/src/gui/text/qtextlayout.h
+++ b/src/gui/text/qtextlayout.h
@@ -49,6 +49,7 @@
#include <QtCore/qobject.h>
#include <QtGui/qevent.h>
#include <QtGui/qtextformat.h>
+#include <QtGui/qglyphs.h>
QT_BEGIN_HEADER
@@ -166,6 +167,8 @@ public:
qreal minimumWidth() const;
qreal maximumWidth() const;
+ QList<QGlyphs> glyphs() const;
+
QTextEngine *engine() const { return d; }
void setFlags(int flags);
private:
@@ -236,6 +239,8 @@ public:
private:
QTextLine(int line, QTextEngine *e) : i(line), eng(e) {}
void layout_helper(int numGlyphs);
+ QList<QGlyphs> glyphs() const;
+
friend class QTextLayout;
int i;
QTextEngine *eng;
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index 9ec314299c..4e1e9fa029 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -39,7 +39,9 @@ HEADERS += \
text/qzipwriter_p.h \
text/qtextodfwriter_p.h \
text/qstatictext_p.h \
- text/qstatictext.h
+ text/qstatictext.h \
+ text/qglyphs.h \
+ text/qglyphs_p.h
SOURCES += \
text/qfont.cpp \
@@ -69,7 +71,8 @@ SOURCES += \
text/qcssparser.cpp \
text/qzip.cpp \
text/qtextodfwriter.cpp \
- text/qstatictext.cpp
+ text/qstatictext.cpp \
+ text/qglyphs.cpp
win32 {
SOURCES += \