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
48QT_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*/
115QGlyphRun::QGlyphRun() : d(new QGlyphRunPrivate)
116{
117}
118
119/*!
120 Constructs a QGlyphRun object which is a copy of \a other.
121*/
122QGlyphRun::QGlyphRun(const QGlyphRun &other)
123{
124 d = other.d;
125}
126
127/*!
128 Destroys the QGlyphRun.
129*/
130QGlyphRun::~QGlyphRun()
131{
132 // Required for QExplicitlySharedDataPointer
133}
134
135/*!
136 \internal
137*/
138void QGlyphRun::detach()
139{
140 if (d->ref.loadRelaxed() != 1)
141 d.detach();
142}
143
144/*!
145 Assigns \a other to this QGlyphRun object.
146*/
147QGlyphRun &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*/
165bool 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*/
203QRawFont 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*/
214void 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*/
225QList<quint32> QGlyphRun::glyphIndexes() const
226{
227 if (d->glyphIndexes.constData() == d->glyphIndexData) {
228 return d->glyphIndexes;
229 } else {
230 QList<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*/
240void QGlyphRun::setGlyphIndexes(const QList<quint32> &glyphIndexes)
241{
242 detach();
243 d->glyphIndexes = glyphIndexes; // Keep a reference to the QList 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*/
251QList<QPointF> QGlyphRun::positions() const
252{
253 if (d->glyphPositions.constData() == d->glyphPositionData) {
254 return d->glyphPositions;
255 } else {
256 QList<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*/
267void QGlyphRun::setPositions(const QList<QPointF> &positions)
268{
269 detach();
270 d->glyphPositions = positions; // Keep a reference to the list 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*/
278void QGlyphRun::clear()
279{
280 detach();
281 d->rawFont = QRawFont();
282 d->flags = { };
283
284 setPositions(QList<QPointF>());
285 setGlyphIndexes(QList<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*/
296void 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*/
313bool 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*/
324void 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*/
334bool 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*/
345void 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*/
355bool 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*/
366void 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*/
377bool 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*/
389void 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*/
400QGlyphRun::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*/
411void 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*/
426void 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*/
456void 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*/
469QRectF 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*/
502bool QGlyphRun::isEmpty() const
503{
504 return d->glyphIndexDataSize == 0;
505}
506
507QT_END_NAMESPACE
508
509#endif // QT_NO_RAWFONT
510