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 
56 QT_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 */
QRawFont()148 QRawFont::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 */
QRawFont(const QString & fileName,qreal pixelSize,QFont::HintingPreference hintingPreference)160 QRawFont::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 */
QRawFont(const QByteArray & fontData,qreal pixelSize,QFont::HintingPreference hintingPreference)175 QRawFont::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 */
QRawFont(const QRawFont & other)186 QRawFont::QRawFont(const QRawFont &other)
187 {
188     d = other.d;
189 }
190 
191 /*!
192    Destroys the QRawFont
193 */
~QRawFont()194 QRawFont::~QRawFont()
195 {
196 }
197 
198 /*!
199   Assigns \a other to this QRawFont.
200 */
operator =(const QRawFont & other)201 QRawFont &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 */
isValid() const218 bool 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 */
loadFromFile(const QString & fileName,qreal pixelSize,QFont::HintingPreference hintingPreference)232 void QRawFont::loadFromFile(const QString &fileName,
233                             qreal pixelSize,
234                             QFont::HintingPreference hintingPreference)
235 {
236     QFile file(fileName);
237     if (file.open(QIODevice::ReadOnly))
238         loadFromData(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 */
loadFromData(const QByteArray & fontData,qreal pixelSize,QFont::HintingPreference hintingPreference)250 void 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 */
alphaMapForGlyph(quint32 glyphIndex,AntialiasingType antialiasingType,const QTransform & transform) const277 QImage 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, QFixed(), transform);
285 
286     if (antialiasingType == SubPixelAntialiasing)
287         return d->fontEngine->alphaRGBMapForGlyph(glyphIndex, QFixed(), transform);
288 
289     return d->fontEngine->alphaMapForGlyph(glyphIndex, QFixed(), 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 */
pathForGlyph(quint32 glyphIndex) const300 QPainterPath QRawFont::pathForGlyph(quint32 glyphIndex) const
301 {
302     if (!d->isValid())
303         return QPainterPath();
304 
305     QFixedPoint position;
306     QPainterPath path;
307     d->fontEngine->addGlyphsToPath(&glyphIndex, &position, 1, &path, { });
308     return path;
309 }
310 
311 /*!
312    Returns \c true if this QRawFont is equal to \a other. Otherwise, returns \c false.
313 */
operator ==(const QRawFont & other) const314 bool 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 */
qHash(const QRawFont & font,uint seed)326 uint qHash(const QRawFont &font, uint seed) noexcept
327 {
328     return qHash(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 */
ascent() const350 qreal 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 */
capHeight() const367 qreal 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 */
descent() const382 qreal 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 */
xHeight() const394 qreal 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 */
leading() const406 qreal 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 */
averageCharWidth() const416 qreal 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 */
maxCharWidth() const426 qreal 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 */
pixelSize() const438 qreal 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 */
unitsPerEm() const451 qreal 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  */
lineThickness() const460 qreal 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  */
underlinePosition() const469 qreal 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 */
familyName() const477 QString 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 */
styleName() const487 QString 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 */
style() const497 QFont::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 */
weight() const507 int 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 */
glyphIndexesForString(const QString & text) const525 QVector<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(numGlyphs);
533 
534     QGlyphLayout glyphs;
535     glyphs.numGlyphs = numGlyphs;
536     glyphs.glyphs = glyphIndexes.data();
537     if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly))
538         Q_UNREACHABLE();
539 
540     glyphIndexes.resize(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 */
glyphIndexesForChars(const QChar * chars,int numChars,quint32 * glyphIndexes,int * numGlyphs) const554 bool 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(chars, numChars, &glyphs, numGlyphs, 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 */
advancesForGlyphIndexes(const quint32 * glyphIndexes,QPointF * advances,int numGlyphs,LayoutFlags layoutFlags) const609 bool 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 */
advancesForGlyphIndexes(const quint32 * glyphIndexes,QPointF * advances,int numGlyphs) const645 bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *advances, int numGlyphs) const
646 {
647     return QRawFont::advancesForGlyphIndexes(glyphIndexes, advances, numGlyphs, SeparateAdvances);
648 }
649 
650 /*!
651    Returns the hinting preference used to construct this QRawFont.
652 
653    \sa QFont::hintingPreference()
654 */
hintingPreference() const655 QFont::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 */
fontTable(const char * tagName) const666 QByteArray 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 */
supportedWritingSystems() const685 QList<QFontDatabase::WritingSystem> QRawFont::supportedWritingSystems() const
686 {
687     QList<QFontDatabase::WritingSystem> writingSystems;
688     if (d->isValid()) {
689         QByteArray os2Table = fontTable("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>(bigEndianUnicodeRanges + i * sizeof(quint32));
700 
701             for (size_t i = 0; i < sizeof codepageRanges / sizeof *codepageRanges; ++i)
702                 codepageRanges[i] = qFromBigEndian<quint32>(bigEndianCodepageRanges + i * sizeof(quint32));
703 
704             QSupportedWritingSystems ws = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRanges, codepageRanges);
705             for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
706                 if (ws.supported(QFontDatabase::WritingSystem(i)))
707                     writingSystems.append(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 */
supportsCharacter(QChar character) const720 bool QRawFont::supportsCharacter(QChar character) const
721 {
722     return supportsCharacter(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 */
supportsCharacter(uint ucs4) const732 bool QRawFont::supportsCharacter(uint ucs4) const
733 {
734     return d->isValid() && d->fontEngine->canRender(ucs4);
735 }
736 
737 // qfontdatabase.cpp
738 extern 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 */
fromFont(const QFont & font,QFontDatabase::WritingSystem writingSystem)747 QRawFont 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(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)) {
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 */
setPixelSize(qreal pixelSize)784 void QRawFont::setPixelSize(qreal pixelSize)
785 {
786     if (!d->isValid() || qFuzzyCompare(d->fontEngine->fontDef.pixelSize, pixelSize))
787         return;
788 
789     d.detach();
790     d->setFontEngine(d->fontEngine->cloneWithSize(pixelSize));
791 }
792 
793 /*!
794     \internal
795 */
loadFromData(const QByteArray & fontData,qreal pixelSize,QFont::HintingPreference hintingPreference)796 void 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 */
boundingRect(quint32 glyphIndex) const810 QRectF QRawFont::boundingRect(quint32 glyphIndex) const
811 {
812     if (!d->isValid())
813         return QRectF();
814 
815     glyph_metrics_t gm = d->fontEngine->boundingBox(glyphIndex);
816     return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
817 }
818 
819 #endif // QT_NO_RAWFONT
820 
821 QT_END_NAMESPACE
822