Coverage Report

Created: 2026-11-10 07:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/text/qglyphrun.cpp
Line
Count
Source
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
12
QT_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
*/
79
0
QGlyphRun::QGlyphRun() : d(new QGlyphRunPrivate)
80
0
{
81
0
}
82
83
/*!
84
    Constructs a QGlyphRun object which is a copy of \a other.
85
*/
86
QGlyphRun::QGlyphRun(const QGlyphRun &other)
87
0
{
88
0
    d = other.d;
89
0
}
90
91
/*!
92
    Destroys the QGlyphRun.
93
*/
94
QGlyphRun::~QGlyphRun()
95
0
{
96
    // Required for QExplicitlySharedDataPointer
97
0
}
98
99
/*!
100
    \internal
101
*/
102
void QGlyphRun::detach()
103
0
{
104
0
    if (d->ref.loadRelaxed() != 1)
105
0
        d.detach();
106
0
}
107
108
/*!
109
    Assigns \a other to this QGlyphRun object.
110
*/
111
QGlyphRun &QGlyphRun::operator=(const QGlyphRun &other)
112
0
{
113
0
    d = other.d;
114
0
    return *this;
115
0
}
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
*/
127
bool QGlyphRun::operator==(const QGlyphRun &other) const
128
0
{
129
0
    if (d == other.d)
130
0
        return true;
131
132
0
    if ((d->glyphIndexDataSize != other.d->glyphIndexDataSize)
133
0
     || (d->glyphPositionDataSize != other.d->glyphPositionDataSize)) {
134
0
        return false;
135
0
    }
136
137
0
    if (d->glyphIndexData != other.d->glyphIndexData) {
138
0
        for (int i = 0; i < d->glyphIndexDataSize; ++i) {
139
0
            if (d->glyphIndexData[i] != other.d->glyphIndexData[i])
140
0
               return false;
141
0
        }
142
0
    }
143
0
    if (d->glyphPositionData != other.d->glyphPositionData) {
144
0
        for (int i = 0; i < d->glyphPositionDataSize; ++i) {
145
0
            if (d->glyphPositionData[i] != other.d->glyphPositionData[i])
146
0
               return false;
147
0
        }
148
0
    }
149
150
0
    return (d->flags == other.d->flags && d->rawFont == other.d->rawFont);
151
0
}
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
*/
165
QRawFont QGlyphRun::rawFont() const
166
0
{
167
0
    return d->rawFont;
168
0
}
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
*/
176
void QGlyphRun::setRawFont(const QRawFont &rawFont)
177
0
{
178
0
    detach();
179
0
    d->rawFont = rawFont;
180
0
}
181
182
/*!
183
    Returns the glyph indexes for this QGlyphRun object.
184
185
    \sa setGlyphIndexes(), setPositions()
186
*/
187
QList<quint32> QGlyphRun::glyphIndexes() const
188
0
{
189
0
    if (d->glyphIndexes.constData() == d->glyphIndexData) {
190
0
        return d->glyphIndexes;
191
0
    } else {
192
0
        QList<quint32> indexes(d->glyphIndexDataSize);
193
0
        memcpy(indexes.data(), d->glyphIndexData, d->glyphIndexDataSize * sizeof(quint32));
194
0
        return indexes;
195
0
    }
196
0
}
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
*/
202
void QGlyphRun::setGlyphIndexes(const QList<quint32> &glyphIndexes)
203
0
{
204
0
    detach();
205
0
    d->glyphIndexes = glyphIndexes; // Keep a reference to the QList to avoid copying
206
0
    d->glyphIndexData = glyphIndexes.constData();
207
0
    d->glyphIndexDataSize = glyphIndexes.size();
208
0
}
209
210
/*!
211
    Returns the position of the edge of the baseline for each glyph in this set of glyph indexes.
212
*/
213
QList<QPointF> QGlyphRun::positions() const
214
0
{
215
0
    if (d->glyphPositions.constData() == d->glyphPositionData) {
216
0
        return d->glyphPositions;
217
0
    } else {
218
0
        QList<QPointF> glyphPositions(d->glyphPositionDataSize);
219
0
        memcpy(glyphPositions.data(), d->glyphPositionData,
220
0
                 d->glyphPositionDataSize * sizeof(QPointF));
221
0
        return glyphPositions;
222
0
    }
223
0
}
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
*/
229
void QGlyphRun::setPositions(const QList<QPointF> &positions)
230
0
{
231
0
    detach();
232
0
    d->glyphPositions = positions; // Keep a reference to the list to avoid copying
233
0
    d->glyphPositionData = positions.constData();
234
0
    d->glyphPositionDataSize = positions.size();
235
0
}
236
237
/*!
238
    Clears all data in the QGlyphRun object.
239
*/
240
void QGlyphRun::clear()
241
0
{
242
0
    detach();
243
0
    d->rawFont = QRawFont();
244
0
    d->flags = { };
245
246
0
    setPositions(QList<QPointF>());
247
0
    setGlyphIndexes(QList<quint32>());
248
0
}
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
*/
258
void QGlyphRun::setRawData(const quint32 *glyphIndexArray, const QPointF *glyphPositionArray,
259
                           int size)
260
0
{
261
0
    detach();
262
0
    d->glyphIndexes.clear();
263
0
    d->glyphPositions.clear();
264
265
0
    d->glyphIndexData = glyphIndexArray;
266
0
    d->glyphPositionData = glyphPositionArray;
267
0
    d->glyphIndexDataSize = d->glyphPositionDataSize = size;
268
0
}
269
270
/*!
271
   Returns \c true if this QGlyphRun should be painted with an overline decoration.
272
273
   \sa setOverline(), flags()
274
*/
275
bool QGlyphRun::overline() const
276
0
{
277
0
    return d->flags & Overline;
278
0
}
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
*/
286
void QGlyphRun::setOverline(bool overline)
287
0
{
288
0
    setFlag(Overline, overline);
289
0
}
290
291
/*!
292
   Returns \c true if this QGlyphRun should be painted with an underline decoration.
293
294
   \sa setUnderline(), flags()
295
*/
296
bool QGlyphRun::underline() const
297
0
{
298
0
    return d->flags & Underline;
299
0
}
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
*/
307
void QGlyphRun::setUnderline(bool underline)
308
0
{
309
0
    setFlag(Underline, underline);
310
0
}
311
312
/*!
313
   Returns \c true if this QGlyphRun should be painted with a strike out decoration.
314
315
   \sa setStrikeOut(), flags()
316
*/
317
bool QGlyphRun::strikeOut() const
318
0
{
319
0
    return d->flags & StrikeOut;
320
0
}
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
*/
328
void QGlyphRun::setStrikeOut(bool strikeOut)
329
0
{
330
0
    setFlag(StrikeOut, strikeOut);
331
0
}
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
*/
339
bool QGlyphRun::isRightToLeft() const
340
0
{
341
0
    return d->flags & RightToLeft;
342
0
}
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
*/
351
void QGlyphRun::setRightToLeft(bool rightToLeft)
352
0
{
353
0
    setFlag(RightToLeft, rightToLeft);
354
0
}
355
356
/*!
357
  Returns the flags set for this QGlyphRun.
358
359
  \since 5.0
360
  \sa setFlag()
361
*/
362
QGlyphRun::GlyphRunFlags QGlyphRun::flags() const
363
0
{
364
0
    return d->flags;
365
0
}
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
*/
373
void QGlyphRun::setFlag(GlyphRunFlag flag, bool enabled)
374
0
{
375
0
    if (d->flags.testFlag(flag) == enabled)
376
0
        return;
377
378
0
    detach();
379
0
    d->flags.setFlag(flag, enabled);
380
0
}
381
382
/*!
383
  Sets the flags of this QGlyphRun to \a flags.
384
385
  \since 5.0
386
  \sa setFlag(), flags()
387
*/
388
void QGlyphRun::setFlags(GlyphRunFlags flags)
389
0
{
390
0
    if (d->flags == flags)
391
0
        return;
392
393
0
    detach();
394
0
    d->flags = flags;
395
0
}
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
*/
418
void QGlyphRun::setBoundingRect(const QRectF &boundingRect)
419
0
{
420
0
    detach();
421
0
    d->boundingRect = boundingRect;
422
0
}
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
*/
431
QRectF QGlyphRun::boundingRect() const
432
0
{
433
0
    if (!d->boundingRect.isNull() || !d->rawFont.isValid())
434
0
        return d->boundingRect;
435
436
0
    qreal minX, minY, maxX, maxY;
437
0
    minX = minY = maxX = maxY = 0;
438
439
0
    for (int i = 0, n = qMin(d->glyphIndexDataSize, d->glyphPositionDataSize); i < n; ++i) {
440
0
        QRectF glyphRect = d->rawFont.boundingRect(d->glyphIndexData[i]);
441
0
        glyphRect.translate(d->glyphPositionData[i]);
442
443
0
        if (i == 0) {
444
0
            minX = glyphRect.left();
445
0
            minY = glyphRect.top();
446
0
            maxX = glyphRect.right();
447
0
            maxY = glyphRect.bottom();
448
0
        } else {
449
0
            minX = qMin(glyphRect.left(), minX);
450
0
            minY = qMin(glyphRect.top(), minY);
451
0
            maxX = qMax(glyphRect.right(),maxX);
452
0
            maxY = qMax(glyphRect.bottom(), maxY);
453
0
        }
454
0
    }
455
456
0
    return QRectF(QPointF(minX, minY), QPointF(maxX, maxY));
457
0
}
458
459
/*!
460
  Returns \c true if the QGlyphRun does not contain any glyphs.
461
462
  \since 5.0
463
*/
464
bool QGlyphRun::isEmpty() const
465
0
{
466
0
    return d->glyphIndexDataSize == 0
467
0
            && d->glyphPositionDataSize == 0
468
0
            && d->stringIndexes.isEmpty()
469
0
            && d->sourceString.isEmpty();
470
0
}
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
*/
495
QList<qsizetype> QGlyphRun::stringIndexes() const
496
0
{
497
0
    return d->stringIndexes;
498
0
}
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
 */
509
void QGlyphRun::setStringIndexes(const QList<qsizetype> &stringIndexes)
510
0
{
511
0
    detach();
512
0
    d->stringIndexes = stringIndexes;
513
0
}
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
 */
523
QString QGlyphRun::sourceString() const
524
0
{
525
0
    return d->sourceString;
526
0
}
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
 */
536
void QGlyphRun::setSourceString(const QString &sourceString)
537
0
{
538
0
    detach();
539
0
    d->sourceString = sourceString;
540
0
}
541
542
QT_END_NAMESPACE
543
544
#endif // QT_NO_RAWFONT