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 "qrawfont.h"
9#include "qrawfont_p.h"
10#include "qplatformfontdatabase.h"
11
12#include <private/qguiapplication_p.h>
13#include <qpa/qplatformintegration.h>
14#include <qpa/qplatformfontdatabase.h>
15
16#include <QtCore/qendian.h>
17#include <QtCore/qfile.h>
18#include <QtGui/qpainterpath.h>
19
20QT_BEGIN_NAMESPACE
21
22/*!
23 \class QRawFont
24 \brief The QRawFont class provides access to a single physical instance of a font.
25 \since 4.8
26 \inmodule QtGui
27
28 \ingroup text
29 \ingroup shared
30
31 \note QRawFont is a low level class. For most purposes QFont is a more appropriate class.
32
33 Most commonly, when presenting text in a user interface, the exact fonts used
34 to render the characters is to some extent unknown. This can be the case for several
35 reasons: For instance, the actual, physical fonts present on the target system could be
36 unexpected to the developers, or the text could contain user selected styles, sizes or
37 writing systems that are not supported by font chosen in the code.
38
39 Therefore, Qt's QFont class really represents a query for fonts. When text is interpreted,
40 Qt will do its best to match the text to the query, but depending on the support, different
41 fonts can be used behind the scenes.
42
43 For most use cases, this is both expected and necessary, as it minimizes the possibility of
44 text in the user interface being undisplayable. In some cases, however, more direct control
45 over the process might be useful. It is for these use cases the QRawFont class exists.
46
47 A QRawFont object represents a single, physical instance of a given font in a given pixel size.
48 I.e. in the typical case it represents a set of TrueType or OpenType font tables and uses a
49 user specified pixel size to convert metrics into logical pixel units. It can be used in
50 combination with the QGlyphRun class to draw specific glyph indexes at specific positions, and
51 also have accessors to some relevant data in the physical font.
52
53 QRawFont only provides support for the main font technologies: GDI and DirectWrite on Windows
54 platforms, FreeType on Linux platforms and CoreText on \macos. For other
55 font back-ends, the APIs will be disabled.
56
57 QRawFont can be constructed in a number of ways:
58 \list
59 \li It can be constructed by calling QTextLayout::glyphs() or QTextFragment::glyphs(). The
60 returned QGlyphs objects will contain QRawFont objects which represent the actual fonts
61 used to render each portion of the text.
62 \li It can be constructed by passing a QFont object to QRawFont::fromFont(). The function
63 will return a QRawFont object representing the font that will be selected as response to
64 the QFont query and the selected writing system.
65 \li It can be constructed by passing a file name or QByteArray directly to the QRawFont
66 constructor, or by calling loadFromFile() or loadFromData(). In this case, the
67 font will not be registered in QFontDatabase, and it will not be available as part of
68 regular font selection.
69 \endlist
70
71 QRawFont is considered local to the thread in which it is constructed (either using a
72 constructor, or by calling loadFromData() or loadFromFile()). The QRawFont cannot be moved to a
73 different thread, but will have to be recreated in the thread in question.
74
75 \note For the requirement of caching glyph indexes and font selections for static text to avoid
76 reshaping and relayouting in the inner loop of an application, a better choice is the QStaticText
77 class, since it optimizes the memory cost of the cache and also provides the possibility of paint
78 engine specific caches for an additional speed-up.
79*/
80
81/*!
82 \enum QRawFont::AntialiasingType
83
84 This enum represents the different ways a glyph can be rasterized in the function
85 alphaMapForGlyph().
86
87 \value PixelAntialiasing Will rasterize by measuring the coverage of the shape on whole pixels.
88 The returned image contains the alpha values of each pixel based on the coverage of
89 the glyph shape.
90 \value SubPixelAntialiasing Will rasterize by measuring the coverage of each subpixel,
91 returning a separate alpha value for each of the red, green and blue components of
92 each pixel.
93*/
94
95/*!
96 \enum QRawFont::LayoutFlag
97 \since 5.1
98
99 This enum tells the function advancesForGlyphIndexes() how to calculate the advances.
100
101 \value SeparateAdvances Will calculate the advance for each glyph separately.
102 \value KernedAdvances Will apply kerning between adjacent glyphs. Note that OpenType GPOS based
103 kerning is currently not supported.
104 \value UseDesignMetrics Use design metrics instead of hinted metrics adjusted to the resolution
105 of the paint device.
106 Can be OR-ed with any of the options above.
107*/
108
109/*!
110 Constructs an invalid QRawFont.
111*/
112QRawFont::QRawFont()
113 : d(new QRawFontPrivate)
114{
115}
116
117/*!
118 Constructs a QRawFont representing the font contained in the file referenced
119 by \a fileName for the size (in pixels) given by \a pixelSize, and using the
120 hinting preference specified by \a hintingPreference.
121
122 \note The referenced file must contain a TrueType or OpenType font.
123*/
124QRawFont::QRawFont(const QString &fileName,
125 qreal pixelSize,
126 QFont::HintingPreference hintingPreference)
127 : d(new QRawFontPrivate)
128{
129 loadFromFile(fileName, pixelSize, hintingPreference);
130}
131
132/*!
133 Constructs a QRawFont representing the font contained in the supplied
134 \a fontData for the size (in pixels) given by \a pixelSize, and using the
135 hinting preference specified by \a hintingPreference.
136
137 \note The data must contain a TrueType or OpenType font.
138*/
139QRawFont::QRawFont(const QByteArray &fontData,
140 qreal pixelSize,
141 QFont::HintingPreference hintingPreference)
142 : d(new QRawFontPrivate)
143{
144 loadFromData(fontData, pixelSize, hintingPreference);
145}
146
147/*!
148 Creates a QRawFont which is a copy of \a other.
149*/
150QRawFont::QRawFont(const QRawFont &other)
151{
152 d = other.d;
153}
154
155/*!
156 Destroys the QRawFont
157*/
158QRawFont::~QRawFont()
159{
160}
161
162/*!
163 Assigns \a other to this QRawFont.
164*/
165QRawFont &QRawFont::operator=(const QRawFont &other)
166{
167 d = other.d;
168 return *this;
169}
170
171/*!
172 \fn void QRawFont::swap(QRawFont &other)
173 \since 5.0
174 \memberswap{raw font}
175*/
176
177/*!
178 Returns \c true if the QRawFont is valid and false otherwise.
179*/
180bool QRawFont::isValid() const
181{
182 return d->isValid();
183}
184
185/*!
186 Replaces the current QRawFont with the contents of the file referenced
187 by \a fileName for the size (in pixels) given by \a pixelSize, and using the
188 hinting preference specified by \a hintingPreference.
189
190 The file must reference a TrueType or OpenType font.
191
192 \sa loadFromData()
193*/
194void QRawFont::loadFromFile(const QString &fileName,
195 qreal pixelSize,
196 QFont::HintingPreference hintingPreference)
197{
198 QFile file(fileName);
199 if (file.open(flags: QIODevice::ReadOnly))
200 loadFromData(fontData: file.readAll(), pixelSize, hintingPreference);
201}
202
203/*!
204 Replaces the current QRawFont with the font contained in the supplied
205 \a fontData for the size (in pixels) given by \a pixelSize, and using the
206 hinting preference specified by \a hintingPreference.
207
208 The \a fontData must contain a TrueType or OpenType font.
209
210 \sa loadFromFile()
211*/
212void QRawFont::loadFromData(const QByteArray &fontData,
213 qreal pixelSize,
214 QFont::HintingPreference hintingPreference)
215{
216 d.detach();
217 d->cleanUp();
218 d->hintingPreference = hintingPreference;
219 d->loadFromData(fontData, pixelSize, hintingPreference);
220}
221
222/*!
223 This function returns a rasterized image of the glyph at the given
224 \a glyphIndex in the underlying font, using the \a transform specified.
225 If the QRawFont is not valid, this function will return an invalid QImage.
226
227 If the font is a color font, then the resulting image will contain the rendered
228 glyph at the current pixel size. In this case, the \a antialiasingType will be
229 ignored.
230
231 Otherwise, if \a antialiasingType is set to QRawFont::SubPixelAntialiasing, then the resulting image
232 will be in QImage::Format_RGB32 and the RGB values of each pixel will represent the subpixel opacities
233 of the pixel in the rasterization of the glyph. Otherwise, the image will be in the format of
234 QImage::Format_Indexed8 and each pixel will contain the opacity of the pixel in the
235 rasterization.
236
237 \sa pathForGlyph(), QPainter::drawGlyphRun()
238*/
239QImage QRawFont::alphaMapForGlyph(quint32 glyphIndex, AntialiasingType antialiasingType,
240 const QTransform &transform) const
241{
242 if (!d->isValid())
243 return QImage();
244
245 if (d->fontEngine->glyphFormat == QFontEngine::Format_ARGB)
246 return d->fontEngine->bitmapForGlyph(glyphIndex, subPixelPosition: QFixedPoint(), t: transform);
247
248 if (antialiasingType == SubPixelAntialiasing)
249 return d->fontEngine->alphaRGBMapForGlyph(glyphIndex, subPixelPosition: QFixedPoint(), t: transform);
250
251 return d->fontEngine->alphaMapForGlyph(glyphIndex, subPixelPosition: QFixedPoint(), t: transform);
252}
253
254/*!
255 This function returns the shape of the glyph at a given \a glyphIndex in the underlying font
256 if the QRawFont is valid. Otherwise, it returns an empty QPainterPath.
257
258 The returned glyph will always be unhinted.
259
260 \sa alphaMapForGlyph(), QPainterPath::addText()
261*/
262QPainterPath QRawFont::pathForGlyph(quint32 glyphIndex) const
263{
264 if (!d->isValid())
265 return QPainterPath();
266
267 QFixedPoint position;
268 QPainterPath path;
269 d->fontEngine->addGlyphsToPath(glyphs: &glyphIndex, positions: &position, nglyphs: 1, path: &path, flags: { });
270 return path;
271}
272
273/*!
274 Returns \c true if this QRawFont is equal to \a other. Otherwise, returns \c false.
275*/
276bool QRawFont::operator==(const QRawFont &other) const
277{
278 return d->fontEngine == other.d->fontEngine;
279}
280
281/*!
282 \fn size_t qHash(const QRawFont &key, size_t seed)
283 \qhashold{QRawFont}
284 \since 5.8
285*/
286size_t qHash(const QRawFont &font, size_t seed) noexcept
287{
288 return qHash(t: QRawFontPrivate::get(font)->fontEngine, seed);
289}
290
291
292/*!
293 \fn bool QRawFont::operator!=(const QRawFont &other) const
294
295 Returns \c true if this QRawFont is not equal to \a other. Otherwise, returns \c false.
296*/
297
298/*!
299 Returns the ascent of this QRawFont in pixel units.
300
301 The ascent of a font is the distance from the baseline to the
302 highest position characters extend to. In practice, some font
303 designers break this rule, e.g. when they put more than one accent
304 on top of a character, or to accommodate an unusual character in
305 an exotic language, so it is possible (though rare) that this
306 value will be too small.
307
308 \sa QFontMetricsF::ascent()
309*/
310qreal QRawFont::ascent() const
311{
312 return d->isValid() ? d->fontEngine->ascent().toReal() : 0.0;
313}
314
315/*!
316 Returns the cap height of this QRawFont in pixel units.
317
318 \since 5.8
319
320 The cap height of a font is the height of a capital letter above
321 the baseline. It specifically is the height of capital letters
322 that are flat - such as H or I - as opposed to round letters such
323 as O, or pointed letters like A, both of which may display overshoot.
324
325 \sa QFontMetricsF::capHeight()
326*/
327qreal QRawFont::capHeight() const
328{
329 return d->isValid() ? d->fontEngine->capHeight().toReal() : 0.0;
330}
331
332/*!
333 Returns the descent of this QRawFont in pixel units.
334
335 The descent is the distance from the base line to the lowest point
336 characters extend to. In practice, some font designers break this rule,
337 e.g. to accommodate an unusual character in an exotic language, so
338 it is possible (though rare) that this value will be too small.
339
340 \sa QFontMetricsF::descent()
341*/
342qreal QRawFont::descent() const
343{
344 return d->isValid() ? d->fontEngine->descent().toReal() : 0.0;
345}
346
347/*!
348 Returns the xHeight of this QRawFont in pixel units.
349
350 This is often but not always the same as the height of the character 'x'.
351
352 \sa QFontMetricsF::xHeight()
353*/
354qreal QRawFont::xHeight() const
355{
356 return d->isValid() ? d->fontEngine->xHeight().toReal() : 0.0;
357}
358
359/*!
360 Returns the leading of this QRawFont in pixel units.
361
362 This is the natural inter-line spacing.
363
364 \sa QFontMetricsF::leading()
365*/
366qreal QRawFont::leading() const
367{
368 return d->isValid() ? d->fontEngine->leading().toReal() : 0.0;
369}
370
371/*!
372 Returns the average character width of this QRawFont in pixel units.
373
374 \sa QFontMetricsF::averageCharWidth()
375*/
376qreal QRawFont::averageCharWidth() const
377{
378 return d->isValid() ? d->fontEngine->averageCharWidth().toReal() : 0.0;
379}
380
381/*!
382 Returns the width of the widest character in the font.
383
384 \sa QFontMetricsF::maxWidth()
385*/
386qreal QRawFont::maxCharWidth() const
387{
388 return d->isValid() ? d->fontEngine->maxCharWidth() : 0.0;
389}
390
391/*!
392 Returns the pixel size set for this QRawFont. The pixel size affects how glyphs are
393 rasterized, the size of glyphs returned by pathForGlyph(), and is used to convert
394 internal metrics from design units to logical pixel units.
395
396 \sa setPixelSize()
397*/
398qreal QRawFont::pixelSize() const
399{
400 return d->isValid() ? d->fontEngine->fontDef.pixelSize : 0.0;
401}
402
403/*!
404 Returns the number of design units define the width and height of the em square
405 for this QRawFont. This value is used together with the pixel size when converting design metrics
406 to pixel units, as the internal metrics are specified in design units and the pixel size gives
407 the size of 1 em in pixels.
408
409 \sa pixelSize(), setPixelSize()
410*/
411qreal QRawFont::unitsPerEm() const
412{
413 return d->isValid() ? d->fontEngine->emSquareSize().toReal() : 0.0;
414}
415
416/*!
417 Returns the thickness for drawing lines (underline, overline, etc.)
418 along with text drawn in this font.
419 */
420qreal QRawFont::lineThickness() const
421{
422 return d->isValid() ? d->fontEngine->lineThickness().toReal() : 0.0;
423}
424
425/*!
426 Returns the position from baseline for drawing underlines below the text
427 rendered with this font.
428 */
429qreal QRawFont::underlinePosition() const
430{
431 return d->isValid() ? d->fontEngine->underlinePosition().toReal() : 0.0;
432}
433
434/*!
435 Returns the family name of this QRawFont.
436*/
437QString QRawFont::familyName() const
438{
439 return d->isValid() ? d->fontEngine->fontDef.families.constFirst() : QString();
440}
441
442/*!
443 Returns the style name of this QRawFont.
444
445 \sa QFont::styleName()
446*/
447QString QRawFont::styleName() const
448{
449 return d->isValid() ? d->fontEngine->fontDef.styleName : QString();
450}
451
452/*!
453 Returns the style of this QRawFont.
454
455 \sa QFont::style()
456*/
457QFont::Style QRawFont::style() const
458{
459 return d->isValid() ? QFont::Style(d->fontEngine->fontDef.style) : QFont::StyleNormal;
460}
461
462/*!
463 Returns the weight of this QRawFont.
464
465 \sa QFont::weight()
466*/
467int QRawFont::weight() const
468{
469 return d->isValid() ? int(d->fontEngine->fontDef.weight) : -1;
470}
471
472/*!
473 Converts the string of unicode points given by \a text to glyph indexes
474 using the CMAP table in the underlying font, and returns a list containing
475 the result.
476
477 Note that, in cases where there are other tables in the font that affect the
478 shaping of the text, the returned glyph indexes will not correctly represent
479 the rendering of the text. To get the correctly shaped text, you can use
480 QTextLayout to lay out and shape the text, then call QTextLayout::glyphs()
481 to get the set of glyph index list and QRawFont pairs.
482
483 \sa advancesForGlyphIndexes(), glyphIndexesForChars(), QGlyphRun, QTextLayout::glyphRuns(), QTextFragment::glyphRuns()
484*/
485QList<quint32> QRawFont::glyphIndexesForString(const QString &text) const
486{
487 QList<quint32> glyphIndexes;
488 if (!d->isValid() || text.isEmpty())
489 return glyphIndexes;
490
491 int numGlyphs = text.size();
492 glyphIndexes.resize(size: numGlyphs);
493
494 QGlyphLayout glyphs;
495 glyphs.numGlyphs = numGlyphs;
496 glyphs.glyphs = glyphIndexes.data();
497 if (d->fontEngine->stringToCMap(str: text.data(), len: text.size(), glyphs: &glyphs, nglyphs: &numGlyphs, flags: QFontEngine::GlyphIndicesOnly) < 0)
498 Q_UNREACHABLE();
499
500 glyphIndexes.resize(size: numGlyphs);
501 return glyphIndexes;
502}
503
504/*!
505 Converts a string of unicode points to glyph indexes using the CMAP table in the
506 underlying font. The function works like glyphIndexesForString() except it take
507 an array (\a chars), the results will be returned though \a glyphIndexes array
508 and number of glyphs will be set in \a numGlyphs. The size of \a glyphIndexes array
509 must be at least \a numChars, if that's still not enough, this function will return
510 false, then you can resize \a glyphIndexes from the size returned in \a numGlyphs.
511
512 \sa glyphIndexesForString(), advancesForGlyphIndexes(), QGlyphRun, QTextLayout::glyphRuns(), QTextFragment::glyphRuns()
513*/
514bool QRawFont::glyphIndexesForChars(const QChar *chars, int numChars, quint32 *glyphIndexes, int *numGlyphs) const
515{
516 Q_ASSERT(numGlyphs);
517 if (!d->isValid() || numChars <= 0) {
518 *numGlyphs = 0;
519 return false;
520 }
521
522 if (*numGlyphs <= 0 || !glyphIndexes) {
523 *numGlyphs = numChars;
524 return false;
525 }
526
527 QGlyphLayout glyphs;
528 glyphs.numGlyphs = *numGlyphs;
529 glyphs.glyphs = glyphIndexes;
530 return d->fontEngine->stringToCMap(str: chars, len: numChars, glyphs: &glyphs, nglyphs: numGlyphs, flags: QFontEngine::GlyphIndicesOnly) >= 0;
531}
532
533/*!
534 \fn QList<QPointF> QRawFont::advancesForGlyphIndexes(const QList<quint32> &glyphIndexes, LayoutFlags layoutFlags) const
535 \since 5.1
536
537 Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances
538 give the distance from the position of a given glyph to where the next glyph should be drawn
539 to make it appear as if the two glyphs are unspaced. How the advances are calculated is
540 controlled by \a layoutFlags.
541
542 \note When \c KernedAdvances is requested, this function will apply kerning rules from the
543 TrueType table \c{KERN}, if this is available in the font. In many modern fonts, kerning is
544 handled through OpenType rules or AAT rules, which requires a full shaping step to be applied.
545 To get the results of fully shaping the text, use \l{QTextLayout}.
546
547 \sa QTextLine::horizontalAdvance(), QFontMetricsF::horizontalAdvance(), QTextLayout::glyphRuns()
548*/
549
550/*!
551 \fn QList<QPointF> QRawFont::advancesForGlyphIndexes(const QList<quint32> &glyphIndexes) const
552
553 \overload
554
555 Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances
556 give the distance from the position of a given glyph to where the next glyph should be drawn
557 to make it appear as if the two glyphs are unspaced. The advance of each glyph is calculated
558 separately.
559
560 \sa QTextLine::horizontalAdvance(), QFontMetricsF::horizontalAdvance()
561*/
562
563/*!
564 \since 5.1
565
566 Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances
567 give the distance from the position of a given glyph to where the next glyph should be drawn
568 to make it appear as if the two glyphs are unspaced. The glyph indexes are given with the
569 array \a glyphIndexes while the results are returned through \a advances, both of them must
570 have \a numGlyphs elements. How the advances are calculated is controlled by \a layoutFlags.
571
572 \note When \c KernedAdvances is requested, this function will apply kerning rules from the
573 TrueType table \c{KERN}, if this is available in the font. In many modern fonts, kerning is
574 handled through OpenType rules or AAT rules, which requires a full shaping step to be applied.
575 To get the results of fully shaping the text, use \l{QTextLayout}.
576
577 \sa QTextLine::horizontalAdvance(), QFontMetricsF::horizontalAdvance(), QTextLayout::glyphRuns()
578*/
579bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *advances, int numGlyphs, LayoutFlags layoutFlags) const
580{
581 if (!d->isValid() || numGlyphs <= 0)
582 return false;
583 Q_ASSERT(glyphIndexes && advances);
584
585 QVarLengthArray<QFixed> tmpAdvances(numGlyphs);
586
587 QGlyphLayout glyphs;
588 glyphs.glyphs = const_cast<glyph_t *>(glyphIndexes);
589 glyphs.numGlyphs = numGlyphs;
590 glyphs.advances = tmpAdvances.data();
591
592 bool design = layoutFlags & UseDesignMetrics;
593
594 d->fontEngine->recalcAdvances(&glyphs, design ? QFontEngine::DesignMetrics : QFontEngine::ShaperFlag(0));
595 if (layoutFlags & KernedAdvances)
596 d->fontEngine->doKerning(&glyphs, design ? QFontEngine::DesignMetrics : QFontEngine::ShaperFlag(0));
597
598 for (int i=0; i<numGlyphs; ++i)
599 advances[i] = QPointF(tmpAdvances[i].toReal(), 0.0);
600
601 return true;
602}
603
604/*!
605 \overload
606
607 Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances
608 give the distance from the position of a given glyph to where the next glyph should be drawn
609 to make it appear as if the two glyphs are unspaced. The glyph indexes are given with the
610 array \a glyphIndexes while the results are returned through \a advances, both of them must
611 have \a numGlyphs elements. The advance of each glyph is calculated separately
612
613 \sa QTextLine::horizontalAdvance(), QFontMetricsF::horizontalAdvance()
614*/
615bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *advances, int numGlyphs) const
616{
617 return QRawFont::advancesForGlyphIndexes(glyphIndexes, advances, numGlyphs, layoutFlags: SeparateAdvances);
618}
619
620/*!
621 Returns the hinting preference used to construct this QRawFont.
622
623 \sa QFont::hintingPreference()
624*/
625QFont::HintingPreference QRawFont::hintingPreference() const
626{
627 return d->isValid() ? d->hintingPreference : QFont::PreferDefaultHinting;
628}
629
630/*!
631 \fn QByteArray QRawFont::fontTable(const char *tag) const
632 \overload fontTable(QFont::Tag)
633
634 The name must be a four-character string.
635*/
636
637/*!
638 \fn QByteArray QRawFont::fontTable(QFont::Tag tag) const
639 \since 6.7
640
641 Retrieves the sfnt table specified by \a tag from the underlying physical font,
642 or an empty byte array if no such table was found. The returned font table's byte order is
643 Big Endian, like the sfnt format specifies.
644*/
645QByteArray QRawFont::fontTable(const char *tag) const
646{
647 if (auto maybeTag = QFont::Tag::fromString(view: tag))
648 return fontTable(tag: *maybeTag);
649 return QByteArray();
650}
651
652QByteArray QRawFont::fontTable(QFont::Tag tag) const
653{
654 if (!d->isValid())
655 return QByteArray();
656
657 return d->fontEngine->getSfntTable(tag: tag.value());
658}
659
660/*!
661 Returns a list of writing systems supported by the font according to designer supplied
662 information in the font file. Please note that this does not guarantee support for a
663 specific unicode point in the font. You can use the supportsCharacter() to check support
664 for a single, specific character.
665
666 \note The list is determined based on the unicode ranges and codepage ranges set in the font's
667 OS/2 table and requires such a table to be present in the underlying font file.
668
669 \sa supportsCharacter()
670*/
671QList<QFontDatabase::WritingSystem> QRawFont::supportedWritingSystems() const
672{
673 QList<QFontDatabase::WritingSystem> writingSystems;
674 if (d->isValid()) {
675 QByteArray os2Table = fontTable(tag: "OS/2");
676 if (os2Table.size() > 86) {
677 const uchar * const data = reinterpret_cast<const uchar *>(os2Table.constData());
678 const uchar * const bigEndianUnicodeRanges = data + 42;
679 const uchar * const bigEndianCodepageRanges = data + 78;
680
681 quint32 unicodeRanges[4];
682 quint32 codepageRanges[2];
683
684 for (size_t i = 0; i < sizeof unicodeRanges / sizeof *unicodeRanges; ++i)
685 unicodeRanges[i] = qFromBigEndian<quint32>(src: bigEndianUnicodeRanges + i * sizeof(quint32));
686
687 for (size_t i = 0; i < sizeof codepageRanges / sizeof *codepageRanges; ++i)
688 codepageRanges[i] = qFromBigEndian<quint32>(src: bigEndianCodepageRanges + i * sizeof(quint32));
689
690 QSupportedWritingSystems ws = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange: unicodeRanges, codePageRange: codepageRanges);
691 for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
692 if (ws.supported(QFontDatabase::WritingSystem(i)))
693 writingSystems.append(t: QFontDatabase::WritingSystem(i));
694 }
695 }
696 }
697
698 return writingSystems;
699}
700
701/*!
702 Returns \c true if the font has a glyph that corresponds to the given \a character.
703
704 \sa supportedWritingSystems()
705*/
706bool QRawFont::supportsCharacter(QChar character) const
707{
708 return supportsCharacter(ucs4: character.unicode());
709}
710
711/*!
712 \overload
713
714 Returns \c true if the font has a glyph that corresponds to the UCS-4 encoded character \a ucs4.
715
716 \sa supportedWritingSystems()
717*/
718bool QRawFont::supportsCharacter(uint ucs4) const
719{
720 return d->isValid() && d->fontEngine->canRender(ucs4);
721}
722
723// qfontdatabase.cpp
724extern int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSystem);
725
726/*!
727 Fetches the physical representation based on a \a font query. The physical font returned is
728 the font that will be preferred by Qt in order to display text in the selected \a writingSystem.
729
730 \warning This function is potentially expensive and should not be called in performance
731 sensitive code.
732*/
733QRawFont QRawFont::fromFont(const QFont &font, QFontDatabase::WritingSystem writingSystem)
734{
735 QRawFont rawFont;
736 const QFontPrivate *font_d = QFontPrivate::get(font);
737 int script = qt_script_for_writing_system(writingSystem);
738 QFontEngine *fe = font_d->engineForScript(script);
739
740 if (fe != nullptr && fe->type() == QFontEngine::Multi) {
741 QFontEngineMulti *multiEngine = static_cast<QFontEngineMulti *>(fe);
742 fe = multiEngine->engine(at: 0);
743
744 if (script > QChar::Script_Latin) {
745 // keep in sync with QFontEngineMulti::loadEngine()
746 QFontDef request(multiEngine->fontDef);
747 request.styleStrategy |= QFont::NoFontMerging;
748
749 if (QFontEngine *engine = QFontDatabasePrivate::findFont(request, script, preferScriptOverFamily: true)) {
750 if (request.weight > QFont::Normal)
751 engine->fontDef.weight = request.weight;
752 if (request.style > QFont::StyleNormal)
753 engine->fontDef.style = request.style;
754 fe = engine;
755 }
756 }
757 Q_ASSERT(fe);
758 }
759
760 if (fe != nullptr) {
761 rawFont.d.data()->setFontEngine(fe);
762 rawFont.d.data()->hintingPreference = font.hintingPreference();
763 }
764 return rawFont;
765}
766
767/*!
768 Sets the pixel size with which this font should be rendered to \a pixelSize.
769*/
770void QRawFont::setPixelSize(qreal pixelSize)
771{
772 if (!d->isValid() || qFuzzyCompare(p1: d->fontEngine->fontDef.pixelSize, p2: pixelSize))
773 return;
774
775 d.detach();
776 d->setFontEngine(d->fontEngine->cloneWithSize(pixelSize));
777}
778
779/*!
780 \internal
781*/
782void QRawFontPrivate::loadFromData(const QByteArray &fontData, qreal pixelSize,
783 QFont::HintingPreference hintingPreference)
784{
785 Q_ASSERT(fontEngine == nullptr);
786
787 QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
788 setFontEngine(pfdb->fontEngine(fontData, pixelSize, hintingPreference));
789}
790
791/*!
792 Returns the smallest rectangle containing the glyph with the given \a glyphIndex.
793
794 \since 5.0
795*/
796QRectF QRawFont::boundingRect(quint32 glyphIndex) const
797{
798 if (!d->isValid())
799 return QRectF();
800
801 glyph_metrics_t gm = d->fontEngine->boundingBox(glyph: glyphIndex);
802 return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
803}
804
805#endif // QT_NO_RAWFONT
806
807QT_END_NAMESPACE
808

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