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

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