1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qglobal.h"
41 
42 #if !defined(QT_NO_RAWFONT)
43 
44 #include "qglyphrun.h"
45 #include "qglyphrun_p.h"
46 #include <qdebug.h>
47 
48 QT_BEGIN_NAMESPACE
49 
50 /*!
51     \class QGlyphRun
52     \brief The QGlyphRun class provides direct access to the internal glyphs in a font.
53     \since 4.8
54     \inmodule QtGui
55 
56     \ingroup text
57     \ingroup shared
58 
59     When Qt displays a string of text encoded in Unicode, it will first convert the Unicode points
60     into a list of glyph indexes and a list of positions based on one or more fonts. The Unicode
61     representation of the text and the QFont object will in this case serve as a convenient
62     abstraction that hides the details of what actually takes place when displaying the text
63     on-screen. For instance, by the time the text actually reaches the screen, it may be represented
64     by a set of fonts in addition to the one specified by the user, e.g. in case the originally
65     selected font did not support all the writing systems contained in the text.
66 
67     Under certain circumstances, it can be useful as an application developer to have more low-level
68     control over which glyphs in a specific font are drawn to the screen. This could for instance
69     be the case in applications that use an external font engine and text shaper together with Qt.
70     QGlyphRun provides an interface to the raw data needed to get text on the screen. It
71     contains a list of glyph indexes, a position for each glyph and a font.
72 
73     It is the user's responsibility to ensure that the selected font actually contains the
74     provided glyph indexes.
75 
76     QTextLayout::glyphRuns() or QTextFragment::glyphRuns() can be used to convert unicode encoded
77     text into a list of QGlyphRun objects, and QPainter::drawGlyphRun() can be used to draw the
78     glyphs.
79 
80     \note Please note that QRawFont is considered local to the thread in which it is constructed.
81     This in turn means that a new QRawFont will have to be created and set on the QGlyphRun if it is
82     moved to a different thread. If the QGlyphRun contains a reference to a QRawFont from a different
83     thread than the current, it will not be possible to draw the glyphs using a QPainter, as the
84     QRawFont is considered invalid and inaccessible in this case.
85 */
86 
87 /*!
88   \enum QGlyphRun::GlyphRunFlag
89   \since 5.0
90 
91   This enum describes flags that alter the way the run of glyphs might be presented or behave in
92   a visual layout. The layout which generates the glyph runs can set these flags based on relevant
93   internal data, to retain information needed to present the text as intended by the user of the
94   layout.
95 
96   \value Overline Indicates that the glyphs should be visualized together with an overline.
97   \value Underline Indicates that the glyphs should be visualized together with an underline.
98   \value StrikeOut Indicates that the glyphs should be struck out visually.
99   \value RightToLeft Indicates that the glyphs are ordered right to left. This can affect the
100   positioning of other screen elements that are relative to the glyph run, such as an inline
101   text object.
102   \value SplitLigature Indicates that the glyph run splits a ligature glyph. This means
103   that a ligature glyph is included in the run, but the characters represented by it corresponds
104   only to part of that ligature. The glyph run's boundingRect() function can in this case be used
105   to retrieve the area covered by glyphs that correspond to the characters represented by the
106   glyph run. When visualizing the glyphs, care needs to be taken to clip to this bounding rect to
107   ensure that only the corresponding part of the ligature is painted. In particular, this can be
108   the case when retrieving a glyph run from a QTextLayout for a specific character range, e.g.
109   when retrieving the selected area of a QTextLayout.
110 */
111 
112 /*!
113     Constructs an empty QGlyphRun object.
114 */
QGlyphRun()115 QGlyphRun::QGlyphRun() : d(new QGlyphRunPrivate)
116 {
117 }
118 
119 /*!
120     Constructs a QGlyphRun object which is a copy of \a other.
121 */
QGlyphRun(const QGlyphRun & other)122 QGlyphRun::QGlyphRun(const QGlyphRun &other)
123 {
124     d = other.d;
125 }
126 
127 /*!
128     Destroys the QGlyphRun.
129 */
~QGlyphRun()130 QGlyphRun::~QGlyphRun()
131 {
132     // Required for QExplicitlySharedDataPointer
133 }
134 
135 /*!
136     \internal
137 */
detach()138 void QGlyphRun::detach()
139 {
140     if (d->ref.loadRelaxed() != 1)
141         d.detach();
142 }
143 
144 /*!
145     Assigns \a other to this QGlyphRun object.
146 */
operator =(const QGlyphRun & other)147 QGlyphRun &QGlyphRun::operator=(const QGlyphRun &other)
148 {
149     d = other.d;
150     return *this;
151 }
152 
153 /*!
154     \fn void QGlyphRun::swap(QGlyphRun &other)
155     \since 5.0
156 
157     Swaps this glyph run instance with \a other. This function is very
158     fast and never fails.
159 */
160 
161 /*!
162     Compares \a other to this QGlyphRun object. Returns \c true if the list of glyph indexes,
163     the list of positions and the font are all equal, otherwise returns \c false.
164 */
operator ==(const QGlyphRun & other) const165 bool QGlyphRun::operator==(const QGlyphRun &other) const
166 {
167     if (d == other.d)
168         return true;
169 
170     if ((d->glyphIndexDataSize != other.d->glyphIndexDataSize)
171      || (d->glyphPositionDataSize != other.d->glyphPositionDataSize)) {
172         return false;
173     }
174 
175     if (d->glyphIndexData != other.d->glyphIndexData) {
176         for (int i = 0; i < d->glyphIndexDataSize; ++i) {
177             if (d->glyphIndexData[i] != other.d->glyphIndexData[i])
178                return false;
179         }
180     }
181     if (d->glyphPositionData != other.d->glyphPositionData) {
182         for (int i = 0; i < d->glyphPositionDataSize; ++i) {
183             if (d->glyphPositionData[i] != other.d->glyphPositionData[i])
184                return false;
185         }
186     }
187 
188     return (d->flags == other.d->flags && d->rawFont == other.d->rawFont);
189 }
190 
191 /*!
192     \fn bool QGlyphRun::operator!=(const QGlyphRun &other) const
193 
194     Compares \a other to this QGlyphRun object. Returns \c true if any of the list of glyph
195     indexes, the list of positions or the font are different, otherwise returns \c false.
196 */
197 
198 /*!
199     Returns the font selected for this QGlyphRun object.
200 
201     \sa setRawFont()
202 */
rawFont() const203 QRawFont QGlyphRun::rawFont() const
204 {
205     return d->rawFont;
206 }
207 
208 /*!
209     Sets the font in which to look up the glyph indexes to the \a rawFont
210     specified.
211 
212     \sa rawFont(), setGlyphIndexes()
213 */
setRawFont(const QRawFont & rawFont)214 void QGlyphRun::setRawFont(const QRawFont &rawFont)
215 {
216     detach();
217     d->rawFont = rawFont;
218 }
219 
220 /*!
221     Returns the glyph indexes for this QGlyphRun object.
222 
223     \sa setGlyphIndexes(), setPositions()
224 */
glyphIndexes() const225 QVector<quint32> QGlyphRun::glyphIndexes() const
226 {
227     if (d->glyphIndexes.constData() == d->glyphIndexData) {
228         return d->glyphIndexes;
229     } else {
230         QVector<quint32> indexes(d->glyphIndexDataSize);
231         memcpy(indexes.data(), d->glyphIndexData, d->glyphIndexDataSize * sizeof(quint32));
232         return indexes;
233     }
234 }
235 
236 /*!
237     Set the glyph indexes for this QGlyphRun object to \a glyphIndexes. The glyph indexes must
238     be valid for the selected font.
239 */
setGlyphIndexes(const QVector<quint32> & glyphIndexes)240 void QGlyphRun::setGlyphIndexes(const QVector<quint32> &glyphIndexes)
241 {
242     detach();
243     d->glyphIndexes = glyphIndexes; // Keep a reference to the QVector to avoid copying
244     d->glyphIndexData = glyphIndexes.constData();
245     d->glyphIndexDataSize = glyphIndexes.size();
246 }
247 
248 /*!
249     Returns the position of the edge of the baseline for each glyph in this set of glyph indexes.
250 */
positions() const251 QVector<QPointF> QGlyphRun::positions() const
252 {
253     if (d->glyphPositions.constData() == d->glyphPositionData) {
254         return d->glyphPositions;
255     } else {
256         QVector<QPointF> glyphPositions(d->glyphPositionDataSize);
257         memcpy(glyphPositions.data(), d->glyphPositionData,
258                  d->glyphPositionDataSize * sizeof(QPointF));
259         return glyphPositions;
260     }
261 }
262 
263 /*!
264     Sets the positions of the edge of the baseline for each glyph in this set of glyph indexes to
265     \a positions.
266 */
setPositions(const QVector<QPointF> & positions)267 void QGlyphRun::setPositions(const QVector<QPointF> &positions)
268 {
269     detach();
270     d->glyphPositions = positions; // Keep a reference to the vector to avoid copying
271     d->glyphPositionData = positions.constData();
272     d->glyphPositionDataSize = positions.size();
273 }
274 
275 /*!
276     Clears all data in the QGlyphRun object.
277 */
clear()278 void QGlyphRun::clear()
279 {
280     detach();
281     d->rawFont = QRawFont();
282     d->flags = { };
283 
284     setPositions(QVector<QPointF>());
285     setGlyphIndexes(QVector<quint32>());
286 }
287 
288 /*!
289     Sets the glyph indexes and positions of this QGlyphRun to use the first \a size
290     elements in the arrays \a glyphIndexArray and \a glyphPositionArray. The data is
291     \e not copied. The caller must guarantee that the arrays are not deleted as long
292     as this QGlyphRun and any copies of it exists.
293 
294     \sa setGlyphIndexes(), setPositions()
295 */
setRawData(const quint32 * glyphIndexArray,const QPointF * glyphPositionArray,int size)296 void QGlyphRun::setRawData(const quint32 *glyphIndexArray, const QPointF *glyphPositionArray,
297                            int size)
298 {
299     detach();
300     d->glyphIndexes.clear();
301     d->glyphPositions.clear();
302 
303     d->glyphIndexData = glyphIndexArray;
304     d->glyphPositionData = glyphPositionArray;
305     d->glyphIndexDataSize = d->glyphPositionDataSize = size;
306 }
307 
308 /*!
309    Returns \c true if this QGlyphRun should be painted with an overline decoration.
310 
311    \sa setOverline(), flags()
312 */
overline() const313 bool QGlyphRun::overline() const
314 {
315     return d->flags & Overline;
316 }
317 
318 /*!
319   Indicates that this QGlyphRun should be painted with an overline decoration if \a overline is true.
320   Otherwise the QGlyphRun should be painted with no overline decoration.
321 
322   \sa overline(), setFlag(), setFlags()
323 */
setOverline(bool overline)324 void QGlyphRun::setOverline(bool overline)
325 {
326     setFlag(Overline, overline);
327 }
328 
329 /*!
330    Returns \c true if this QGlyphRun should be painted with an underline decoration.
331 
332    \sa setUnderline(), flags()
333 */
underline() const334 bool QGlyphRun::underline() const
335 {
336     return d->flags & Underline;
337 }
338 
339 /*!
340   Indicates that this QGlyphRun should be painted with an underline decoration if \a underline is
341   true. Otherwise the QGlyphRun should be painted with no underline decoration.
342 
343   \sa underline(), setFlag(), setFlags()
344 */
setUnderline(bool underline)345 void QGlyphRun::setUnderline(bool underline)
346 {
347     setFlag(Underline, underline);
348 }
349 
350 /*!
351    Returns \c true if this QGlyphRun should be painted with a strike out decoration.
352 
353    \sa setStrikeOut(), flags()
354 */
strikeOut() const355 bool QGlyphRun::strikeOut() const
356 {
357     return d->flags & StrikeOut;
358 }
359 
360 /*!
361   Indicates that this QGlyphRun should be painted with an strike out decoration if \a strikeOut is
362   true. Otherwise the QGlyphRun should be painted with no strike out decoration.
363 
364   \sa strikeOut(), setFlag(), setFlags()
365 */
setStrikeOut(bool strikeOut)366 void QGlyphRun::setStrikeOut(bool strikeOut)
367 {
368     setFlag(StrikeOut, strikeOut);
369 }
370 
371 /*!
372   Returns \c true if this QGlyphRun contains glyphs that are painted from the right to the left.
373 
374   \since 5.0
375   \sa setRightToLeft(), flags()
376 */
isRightToLeft() const377 bool QGlyphRun::isRightToLeft() const
378 {
379     return d->flags & RightToLeft;
380 }
381 
382 /*!
383   Indicates that this QGlyphRun contains glyphs that should be ordered from the right to left
384   if \a rightToLeft is true. Otherwise the order of the glyphs is assumed to be left to right.
385 
386   \since 5.0
387   \sa isRightToLeft(), setFlag(), setFlags()
388 */
setRightToLeft(bool rightToLeft)389 void QGlyphRun::setRightToLeft(bool rightToLeft)
390 {
391     setFlag(RightToLeft, rightToLeft);
392 }
393 
394 /*!
395   Returns the flags set for this QGlyphRun.
396 
397   \since 5.0
398   \sa setFlag(), setFlag()
399 */
flags() const400 QGlyphRun::GlyphRunFlags QGlyphRun::flags() const
401 {
402     return d->flags;
403 }
404 
405 /*!
406   If \a enabled is true, then \a flag is enabled; otherwise, it is disabled.
407 
408   \since 5.0
409   \sa flags(), setFlags()
410 */
setFlag(GlyphRunFlag flag,bool enabled)411 void QGlyphRun::setFlag(GlyphRunFlag flag, bool enabled)
412 {
413     if (d->flags.testFlag(flag) == enabled)
414         return;
415 
416     detach();
417     d->flags.setFlag(flag, enabled);
418 }
419 
420 /*!
421   Sets the flags of this QGlyphRun to \a flags.
422 
423   \since 5.0
424   \sa setFlag(), flags()
425 */
setFlags(GlyphRunFlags flags)426 void QGlyphRun::setFlags(GlyphRunFlags flags)
427 {
428     if (d->flags == flags)
429         return;
430 
431     detach();
432     d->flags = flags;
433 }
434 
435 /*!
436   Sets the bounding rect of the glyphs in this QGlyphRun to be \a boundingRect. This rectangle
437   will be returned by boundingRect() unless it is empty, in which case the bounding rectangle of the
438   glyphs in the glyph run will be returned instead.
439 
440   \note Unless you are implementing text shaping, you should not have to use this function.
441   It is used specifically when the QGlyphRun should represent an area which is smaller than the
442   area of the glyphs it contains. This could happen e.g. if the glyph run is retrieved by calling
443   QTextLayout::glyphRuns() and the specified range only includes part of a ligature (where two or
444   more characters are combined to a single glyph.) When this is the case, the bounding rect should
445   only include the appropriate part of the ligature glyph, based on a calculation of the average
446   width of the characters in the ligature.
447 
448   In order to support such a case (an example is selections which should be drawn with a different
449   color than the main text color), it is necessary to clip the painting mechanism to the rectangle
450   returned from boundingRect() to avoid drawing the entire ligature glyph.
451 
452   \sa boundingRect()
453 
454   \since 5.0
455 */
setBoundingRect(const QRectF & boundingRect)456 void QGlyphRun::setBoundingRect(const QRectF &boundingRect)
457 {
458     detach();
459     d->boundingRect = boundingRect;
460 }
461 
462 /*!
463   Returns the smallest rectangle that contains all glyphs in this QGlyphRun. If a bounding rect
464   has been set using setBoundingRect(), then this will be returned. Otherwise the bounding rect
465   will be calculated based on the font metrics of the glyphs in the glyph run.
466 
467   \since 5.0
468 */
boundingRect() const469 QRectF QGlyphRun::boundingRect() const
470 {
471     if (!d->boundingRect.isEmpty() || !d->rawFont.isValid())
472         return d->boundingRect;
473 
474     qreal minX, minY, maxX, maxY;
475     minX = minY = maxX = maxY = 0;
476 
477     for (int i = 0, n = qMin(d->glyphIndexDataSize, d->glyphPositionDataSize); i < n; ++i) {
478         QRectF glyphRect = d->rawFont.boundingRect(d->glyphIndexData[i]);
479         glyphRect.translate(d->glyphPositionData[i]);
480 
481         if (i == 0) {
482             minX = glyphRect.left();
483             minY = glyphRect.top();
484             maxX = glyphRect.right();
485             maxY = glyphRect.bottom();
486         } else {
487             minX = qMin(glyphRect.left(), minX);
488             minY = qMin(glyphRect.top(), minY);
489             maxX = qMax(glyphRect.right(),maxX);
490             maxY = qMax(glyphRect.bottom(), maxY);
491         }
492     }
493 
494     return QRectF(QPointF(minX, minY), QPointF(maxX, maxY));
495 }
496 
497 /*!
498   Returns \c true if the QGlyphRun does not contain any glyphs.
499 
500   \since 5.0
501 */
isEmpty() const502 bool QGlyphRun::isEmpty() const
503 {
504     return d->glyphIndexDataSize == 0;
505 }
506 
507 QT_END_NAMESPACE
508 
509 #endif // QT_NO_RAWFONT
510