| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the QtGui module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qglobal.h" |
| |
| #if !defined(QT_NO_RAWFONT) |
| |
| #include "qglyphrun.h" |
| #include "qglyphrun_p.h" |
| #include <qdebug.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| /*! |
| \class QGlyphRun |
| \brief The QGlyphRun class provides direct access to the internal glyphs in a font. |
| \since 4.8 |
| \inmodule QtGui |
| |
| \ingroup text |
| \ingroup shared |
| |
| 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. |
| QGlyphRun 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::glyphRuns() or QTextFragment::glyphRuns() can be used to convert unicode encoded |
| text into a list of QGlyphRun objects, and QPainter::drawGlyphRun() can be used to draw the |
| glyphs. |
| |
| \note Please note that QRawFont is considered local to the thread in which it is constructed. |
| This in turn means that a new QRawFont will have to be created and set on the QGlyphRun if it is |
| moved to a different thread. If the QGlyphRun contains a reference to a QRawFont from a different |
| thread than the current, it will not be possible to draw the glyphs using a QPainter, as the |
| QRawFont is considered invalid and inaccessible in this case. |
| */ |
| |
| /*! |
| \enum QGlyphRun::GlyphRunFlag |
| \since 5.0 |
| |
| This enum describes flags that alter the way the run of glyphs might be presented or behave in |
| a visual layout. The layout which generates the glyph runs can set these flags based on relevant |
| internal data, to retain information needed to present the text as intended by the user of the |
| layout. |
| |
| \value Overline Indicates that the glyphs should be visualized together with an overline. |
| \value Underline Indicates that the glyphs should be visualized together with an underline. |
| \value StrikeOut Indicates that the glyphs should be struck out visually. |
| \value RightToLeft Indicates that the glyphs are ordered right to left. This can affect the |
| positioning of other screen elements that are relative to the glyph run, such as an inline |
| text object. |
| \value SplitLigature Indicates that the glyph run splits a ligature glyph. This means |
| that a ligature glyph is included in the run, but the characters represented by it corresponds |
| only to part of that ligature. The glyph run's boundingRect() function can in this case be used |
| to retrieve the area covered by glyphs that correspond to the characters represented by the |
| glyph run. When visualizing the glyphs, care needs to be taken to clip to this bounding rect to |
| ensure that only the corresponding part of the ligature is painted. In particular, this can be |
| the case when retrieving a glyph run from a QTextLayout for a specific character range, e.g. |
| when retrieving the selected area of a QTextLayout. |
| */ |
| |
| /*! |
| Constructs an empty QGlyphRun object. |
| */ |
| QGlyphRun::QGlyphRun() : d(new QGlyphRunPrivate) |
| { |
| } |
| |
| /*! |
| Constructs a QGlyphRun object which is a copy of \a other. |
| */ |
| QGlyphRun::QGlyphRun(const QGlyphRun &other) |
| { |
| d = other.d; |
| } |
| |
| /*! |
| Destroys the QGlyphRun. |
| */ |
| QGlyphRun::~QGlyphRun() |
| { |
| // Required for QExplicitlySharedDataPointer |
| } |
| |
| /*! |
| \internal |
| */ |
| void QGlyphRun::detach() |
| { |
| if (d->ref.loadRelaxed() != 1) |
| d.detach(); |
| } |
| |
| /*! |
| Assigns \a other to this QGlyphRun object. |
| */ |
| QGlyphRun &QGlyphRun::operator=(const QGlyphRun &other) |
| { |
| d = other.d; |
| return *this; |
| } |
| |
| /*! |
| \fn void QGlyphRun::swap(QGlyphRun &other) |
| \since 5.0 |
| |
| Swaps this glyph run instance with \a other. This function is very |
| fast and never fails. |
| */ |
| |
| /*! |
| Compares \a other to this QGlyphRun object. Returns \c true if the list of glyph indexes, |
| the list of positions and the font are all equal, otherwise returns \c false. |
| */ |
| bool QGlyphRun::operator==(const QGlyphRun &other) const |
| { |
| if (d == other.d) |
| return true; |
| |
| if ((d->glyphIndexDataSize != other.d->glyphIndexDataSize) |
| || (d->glyphPositionDataSize != other.d->glyphPositionDataSize)) { |
| return false; |
| } |
| |
| if (d->glyphIndexData != other.d->glyphIndexData) { |
| for (int i = 0; i < d->glyphIndexDataSize; ++i) { |
| if (d->glyphIndexData[i] != other.d->glyphIndexData[i]) |
| return false; |
| } |
| } |
| if (d->glyphPositionData != other.d->glyphPositionData) { |
| for (int i = 0; i < d->glyphPositionDataSize; ++i) { |
| if (d->glyphPositionData[i] != other.d->glyphPositionData[i]) |
| return false; |
| } |
| } |
| |
| return (d->flags == other.d->flags && d->rawFont == other.d->rawFont); |
| } |
| |
| /*! |
| \fn bool QGlyphRun::operator!=(const QGlyphRun &other) const |
| |
| Compares \a other to this QGlyphRun object. Returns \c true if any of the list of glyph |
| indexes, the list of positions or the font are different, otherwise returns \c false. |
| */ |
| |
| /*! |
| Returns the font selected for this QGlyphRun object. |
| |
| \sa setRawFont() |
| */ |
| QRawFont QGlyphRun::rawFont() const |
| { |
| return d->rawFont; |
| } |
| |
| /*! |
| Sets the font in which to look up the glyph indexes to the \a rawFont |
| specified. |
| |
| \sa rawFont(), setGlyphIndexes() |
| */ |
| void QGlyphRun::setRawFont(const QRawFont &rawFont) |
| { |
| detach(); |
| d->rawFont = rawFont; |
| } |
| |
| /*! |
| Returns the glyph indexes for this QGlyphRun object. |
| |
| \sa setGlyphIndexes(), setPositions() |
| */ |
| QVector<quint32> QGlyphRun::glyphIndexes() const |
| { |
| if (d->glyphIndexes.constData() == d->glyphIndexData) { |
| return d->glyphIndexes; |
| } else { |
| QVector<quint32> indexes(d->glyphIndexDataSize); |
| memcpy(indexes.data(), d->glyphIndexData, d->glyphIndexDataSize * sizeof(quint32)); |
| return indexes; |
| } |
| } |
| |
| /*! |
| Set the glyph indexes for this QGlyphRun object to \a glyphIndexes. The glyph indexes must |
| be valid for the selected font. |
| */ |
| void QGlyphRun::setGlyphIndexes(const QVector<quint32> &glyphIndexes) |
| { |
| detach(); |
| d->glyphIndexes = glyphIndexes; // Keep a reference to the QVector to avoid copying |
| d->glyphIndexData = glyphIndexes.constData(); |
| d->glyphIndexDataSize = glyphIndexes.size(); |
| } |
| |
| /*! |
| Returns the position of the edge of the baseline for each glyph in this set of glyph indexes. |
| */ |
| QVector<QPointF> QGlyphRun::positions() const |
| { |
| if (d->glyphPositions.constData() == d->glyphPositionData) { |
| return d->glyphPositions; |
| } else { |
| QVector<QPointF> glyphPositions(d->glyphPositionDataSize); |
| memcpy(glyphPositions.data(), d->glyphPositionData, |
| d->glyphPositionDataSize * sizeof(QPointF)); |
| return glyphPositions; |
| } |
| } |
| |
| /*! |
| Sets the positions of the edge of the baseline for each glyph in this set of glyph indexes to |
| \a positions. |
| */ |
| void QGlyphRun::setPositions(const QVector<QPointF> &positions) |
| { |
| detach(); |
| d->glyphPositions = positions; // Keep a reference to the vector to avoid copying |
| d->glyphPositionData = positions.constData(); |
| d->glyphPositionDataSize = positions.size(); |
| } |
| |
| /*! |
| Clears all data in the QGlyphRun object. |
| */ |
| void QGlyphRun::clear() |
| { |
| detach(); |
| d->rawFont = QRawFont(); |
| d->flags = 0; |
| |
| setPositions(QVector<QPointF>()); |
| setGlyphIndexes(QVector<quint32>()); |
| } |
| |
| /*! |
| Sets the glyph indexes and positions of this QGlyphRun to use the first \a size |
| elements in the arrays \a glyphIndexArray and \a glyphPositionArray. The data is |
| \e not copied. The caller must guarantee that the arrays are not deleted as long |
| as this QGlyphRun and any copies of it exists. |
| |
| \sa setGlyphIndexes(), setPositions() |
| */ |
| void QGlyphRun::setRawData(const quint32 *glyphIndexArray, const QPointF *glyphPositionArray, |
| int size) |
| { |
| detach(); |
| d->glyphIndexes.clear(); |
| d->glyphPositions.clear(); |
| |
| d->glyphIndexData = glyphIndexArray; |
| d->glyphPositionData = glyphPositionArray; |
| d->glyphIndexDataSize = d->glyphPositionDataSize = size; |
| } |
| |
| /*! |
| Returns \c true if this QGlyphRun should be painted with an overline decoration. |
| |
| \sa setOverline(), flags() |
| */ |
| bool QGlyphRun::overline() const |
| { |
| return d->flags & Overline; |
| } |
| |
| /*! |
| Indicates that this QGlyphRun should be painted with an overline decoration if \a overline is true. |
| Otherwise the QGlyphRun should be painted with no overline decoration. |
| |
| \sa overline(), setFlag(), setFlags() |
| */ |
| void QGlyphRun::setOverline(bool overline) |
| { |
| setFlag(Overline, overline); |
| } |
| |
| /*! |
| Returns \c true if this QGlyphRun should be painted with an underline decoration. |
| |
| \sa setUnderline(), flags() |
| */ |
| bool QGlyphRun::underline() const |
| { |
| return d->flags & Underline; |
| } |
| |
| /*! |
| Indicates that this QGlyphRun should be painted with an underline decoration if \a underline is |
| true. Otherwise the QGlyphRun should be painted with no underline decoration. |
| |
| \sa underline(), setFlag(), setFlags() |
| */ |
| void QGlyphRun::setUnderline(bool underline) |
| { |
| setFlag(Underline, underline); |
| } |
| |
| /*! |
| Returns \c true if this QGlyphRun should be painted with a strike out decoration. |
| |
| \sa setStrikeOut(), flags() |
| */ |
| bool QGlyphRun::strikeOut() const |
| { |
| return d->flags & StrikeOut; |
| } |
| |
| /*! |
| Indicates that this QGlyphRun should be painted with an strike out decoration if \a strikeOut is |
| true. Otherwise the QGlyphRun should be painted with no strike out decoration. |
| |
| \sa strikeOut(), setFlag(), setFlags() |
| */ |
| void QGlyphRun::setStrikeOut(bool strikeOut) |
| { |
| setFlag(StrikeOut, strikeOut); |
| } |
| |
| /*! |
| Returns \c true if this QGlyphRun contains glyphs that are painted from the right to the left. |
| |
| \since 5.0 |
| \sa setRightToLeft(), flags() |
| */ |
| bool QGlyphRun::isRightToLeft() const |
| { |
| return d->flags & RightToLeft; |
| } |
| |
| /*! |
| Indicates that this QGlyphRun contains glyphs that should be ordered from the right to left |
| if \a rightToLeft is true. Otherwise the order of the glyphs is assumed to be left to right. |
| |
| \since 5.0 |
| \sa isRightToLeft(), setFlag(), setFlags() |
| */ |
| void QGlyphRun::setRightToLeft(bool rightToLeft) |
| { |
| setFlag(RightToLeft, rightToLeft); |
| } |
| |
| /*! |
| Returns the flags set for this QGlyphRun. |
| |
| \since 5.0 |
| \sa setFlag(), setFlag() |
| */ |
| QGlyphRun::GlyphRunFlags QGlyphRun::flags() const |
| { |
| return d->flags; |
| } |
| |
| /*! |
| If \a enabled is true, then \a flag is enabled; otherwise, it is disabled. |
| |
| \since 5.0 |
| \sa flags(), setFlags() |
| */ |
| void QGlyphRun::setFlag(GlyphRunFlag flag, bool enabled) |
| { |
| if (d->flags.testFlag(flag) == enabled) |
| return; |
| |
| detach(); |
| d->flags.setFlag(flag, enabled); |
| } |
| |
| /*! |
| Sets the flags of this QGlyphRun to \a flags. |
| |
| \since 5.0 |
| \sa setFlag(), flags() |
| */ |
| void QGlyphRun::setFlags(GlyphRunFlags flags) |
| { |
| if (d->flags == flags) |
| return; |
| |
| detach(); |
| d->flags = flags; |
| } |
| |
| /*! |
| Sets the bounding rect of the glyphs in this QGlyphRun to be \a boundingRect. This rectangle |
| will be returned by boundingRect() unless it is empty, in which case the bounding rectangle of the |
| glyphs in the glyph run will be returned instead. |
| |
| \note Unless you are implementing text shaping, you should not have to use this function. |
| It is used specifically when the QGlyphRun should represent an area which is smaller than the |
| area of the glyphs it contains. This could happen e.g. if the glyph run is retrieved by calling |
| QTextLayout::glyphRuns() and the specified range only includes part of a ligature (where two or |
| more characters are combined to a single glyph.) When this is the case, the bounding rect should |
| only include the appropriate part of the ligature glyph, based on a calculation of the average |
| width of the characters in the ligature. |
| |
| In order to support such a case (an example is selections which should be drawn with a different |
| color than the main text color), it is necessary to clip the painting mechanism to the rectangle |
| returned from boundingRect() to avoid drawing the entire ligature glyph. |
| |
| \sa boundingRect() |
| |
| \since 5.0 |
| */ |
| void QGlyphRun::setBoundingRect(const QRectF &boundingRect) |
| { |
| detach(); |
| d->boundingRect = boundingRect; |
| } |
| |
| /*! |
| Returns the smallest rectangle that contains all glyphs in this QGlyphRun. If a bounding rect |
| has been set using setBoundingRect(), then this will be returned. Otherwise the bounding rect |
| will be calculated based on the font metrics of the glyphs in the glyph run. |
| |
| \since 5.0 |
| */ |
| QRectF QGlyphRun::boundingRect() const |
| { |
| if (!d->boundingRect.isEmpty() || !d->rawFont.isValid()) |
| return d->boundingRect; |
| |
| qreal minX, minY, maxX, maxY; |
| minX = minY = maxX = maxY = 0; |
| |
| for (int i = 0, n = qMin(d->glyphIndexDataSize, d->glyphPositionDataSize); i < n; ++i) { |
| QRectF glyphRect = d->rawFont.boundingRect(d->glyphIndexData[i]); |
| glyphRect.translate(d->glyphPositionData[i]); |
| |
| if (i == 0) { |
| minX = glyphRect.left(); |
| minY = glyphRect.top(); |
| maxX = glyphRect.right(); |
| maxY = glyphRect.bottom(); |
| } else { |
| minX = qMin(glyphRect.left(), minX); |
| minY = qMin(glyphRect.top(), minY); |
| maxX = qMax(glyphRect.right(),maxX); |
| maxY = qMax(glyphRect.bottom(), maxY); |
| } |
| } |
| |
| return QRectF(QPointF(minX, minY), QPointF(maxX, maxY)); |
| } |
| |
| /*! |
| Returns \c true if the QGlyphRun does not contain any glyphs. |
| |
| \since 5.0 |
| */ |
| bool QGlyphRun::isEmpty() const |
| { |
| return d->glyphIndexDataSize == 0; |
| } |
| |
| QT_END_NAMESPACE |
| |
| #endif // QT_NO_RAWFONT |