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

source code of qtbase/src/gui/text/qglyphrun.cpp