1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
44 #if !defined(QT_NO_RAWFONT)
47 #include "qrawfont_p.h"
49 #include <QtCore/qendian.h>
55 \brief The QRawFont class provides access to a single physical instance of a font.
61 \note QRawFont is a low level class. For most purposes QFont is a more appropriate class.
63 Most commonly, when presenting text in a user interface, the exact fonts used
64 to render the characters is to some extent unknown. This can be the case for several
65 reasons: For instance, the actual, physical fonts present on the target system could be
66 unexpected to the developers, or the text could contain user selected styles, sizes or
67 writing systems that are not supported by font chosen in the code.
69 Therefore, Qt's QFont class really represents a query for fonts. When text is interpreted,
70 Qt will do its best to match the text to the query, but depending on the support, different
71 fonts can be used behind the scenes.
73 For most use cases, this is both expected and necessary, as it minimizes the possibility of
74 text in the user interface being undisplayable. In some cases, however, more direct control
75 over the process might be useful. It is for these use cases the QRawFont class exists.
77 A QRawFont object represents a single, physical instance of a given font in a given pixel size.
78 I.e. in the typical case it represents a set of TrueType or OpenType font tables and uses a
79 user specified pixel size to convert metrics into logical pixel units. It can be used in
80 combination with the QGlyphRun class to draw specific glyph indexes at specific positions, and
81 also have accessors to some relevant data in the physical font.
83 QRawFont only provides support for the main font technologies: GDI and DirectWrite on Windows
84 platforms, FreeType on Symbian and Linux platforms and CoreText on Mac OS X. For other
85 font back-ends, the APIs will be disabled.
87 QRawFont can be constructed in a number of ways:
89 \o It can be constructed by calling QTextLayout::glyphs() or QTextFragment::glyphs(). The
90 returned QGlyphs objects will contain QRawFont objects which represent the actual fonts
91 used to render each portion of the text.
92 \o It can be constructed by passing a QFont object to QRawFont::fromFont(). The function
93 will return a QRawFont object representing the font that will be selected as response to
94 the QFont query and the selected writing system.
95 \o It can be constructed by passing a file name or QByteArray directly to the QRawFont
96 constructor, or by calling loadFromFile() or loadFromData(). In this case, the
97 font will not be registered in QFontDatabase, and it will not be available as part of
98 regular font selection.
101 QRawFont is considered local to the thread in which it is constructed (either using a
102 constructor, or by calling loadFromData() or loadFromFile()). The QRawFont cannot be moved to a
103 different thread, but will have to be recreated in the thread in question.
105 \note For the requirement of caching glyph indexes and font selections for static text to avoid
106 reshaping and relayouting in the inner loop of an application, a better choice is the QStaticText
107 class, since it optimizes the memory cost of the cache and also provides the possibility of paint
108 engine specific caches for an additional speed-up.
112 \enum QRawFont::AntialiasingType
114 This enum represents the different ways a glyph can be rasterized in the function
117 \value PixelAntialiasing Will rasterize by measuring the coverage of the shape on whole pixels.
118 The returned image contains the alpha values of each pixel based on the coverage of
120 \value SubPixelAntialiasing Will rasterize by measuring the coverage of each subpixel,
121 returning a separate alpha value for each of the red, green and blue components of
126 Constructs an invalid QRawFont.
129 : d(new QRawFontPrivate)
134 Constructs a QRawFont representing the font contained in the file referenced
135 by \a fileName for the size (in pixels) given by \a pixelSize, and using the
136 hinting preference specified by \a hintingPreference.
138 \note The referenced file must contain a TrueType or OpenType font.
140 QRawFont::QRawFont(const QString &fileName,
142 QFont::HintingPreference hintingPreference)
143 : d(new QRawFontPrivate)
145 loadFromFile(fileName, pixelSize, hintingPreference);
149 Constructs a QRawFont representing the font contained in the supplied
150 \a fontData for the size (in pixels) given by \a pixelSize, and using the
151 hinting preference specified by \a hintingPreference.
153 \note The data must contain a TrueType or OpenType font.
155 QRawFont::QRawFont(const QByteArray &fontData,
157 QFont::HintingPreference hintingPreference)
158 : d(new QRawFontPrivate)
160 loadFromData(fontData, pixelSize, hintingPreference);
164 Creates a QRawFont which is a copy of \a other.
166 QRawFont::QRawFont(const QRawFont &other)
172 Destroys the QRawFont
174 QRawFont::~QRawFont()
179 Assigns \a other to this QRawFont.
181 QRawFont &QRawFont::operator=(const QRawFont &other)
188 Returns true if the QRawFont is valid and false otherwise.
190 bool QRawFont::isValid() const
196 Replaces the current QRawFont with the contents of the file referenced
197 by \a fileName for the size (in pixels) given by \a pixelSize, and using the
198 hinting preference specified by \a hintingPreference.
200 The file must reference a TrueType or OpenType font.
204 void QRawFont::loadFromFile(const QString &fileName,
206 QFont::HintingPreference hintingPreference)
208 QFile file(fileName);
209 if (file.open(QIODevice::ReadOnly))
210 loadFromData(file.readAll(), pixelSize, hintingPreference);
214 Replaces the current QRawFont with the font contained in the supplied
215 \a fontData for the size (in pixels) given by \a pixelSize, and using the
216 hinting preference specified by \a hintingPreference.
218 The \a fontData must contain a TrueType or OpenType font.
222 void QRawFont::loadFromData(const QByteArray &fontData,
224 QFont::HintingPreference hintingPreference)
228 d->hintingPreference = hintingPreference;
229 d->thread = QThread::currentThread();
230 d->platformLoadFromData(fontData, pixelSize, hintingPreference);
234 This function returns a rasterized image of the glyph at the given
235 \a glyphIndex in the underlying font, using the \a transform specified.
236 If the QRawFont is not valid, this function will return an invalid QImage.
238 If \a antialiasingType is set to QRawFont::SubPixelAntialiasing, then the resulting image will be
239 in QImage::Format_RGB32 and the RGB values of each pixel will represent the subpixel opacities of
240 the pixel in the rasterization of the glyph. Otherwise, the image will be in the format of
241 QImage::Format_Indexed8 and each pixel will contain the opacity of the pixel in the
244 \sa pathForGlyph(), QPainter::drawGlyphRun()
246 QImage QRawFont::alphaMapForGlyph(quint32 glyphIndex, AntialiasingType antialiasingType,
247 const QTransform &transform) const
252 if (antialiasingType == SubPixelAntialiasing)
253 return d->fontEngine->alphaRGBMapForGlyph(glyphIndex, QFixed(), 0, transform);
255 return d->fontEngine->alphaMapForGlyph(glyphIndex, QFixed(), transform);
259 This function returns the shape of the glyph at a given \a glyphIndex in the underlying font
260 if the QRawFont is valid. Otherwise, it returns an empty QPainterPath.
262 The returned glyph will always be unhinted.
264 \sa alphaMapForGlyph(), QPainterPath::addText()
266 QPainterPath QRawFont::pathForGlyph(quint32 glyphIndex) const
269 return QPainterPath();
271 QFixedPoint position;
273 d->fontEngine->addGlyphsToPath(&glyphIndex, &position, 1, &path, 0);
278 Returns true if this QRawFont is equal to \a other. Otherwise, returns false.
280 bool QRawFont::operator==(const QRawFont &other) const
282 return d->fontEngine == other.d->fontEngine;
286 \fn bool QRawFont::operator!=(const QRawFont &other) const
288 Returns true if this QRawFont is not equal to \a other. Otherwise, returns false.
292 Returns the ascent of this QRawFont in pixel units.
294 \sa QFontMetricsF::ascent()
296 qreal QRawFont::ascent() const
298 return d->isValid() ? d->fontEngine->ascent().toReal() : 0.0;
302 Returns the descent of this QRawFont in pixel units.
304 \sa QFontMetricsF::descent()
306 qreal QRawFont::descent() const
308 return d->isValid() ? d->fontEngine->descent().toReal() : 0.0;
312 Returns the xHeight of this QRawFont in pixel units.
314 \sa QFontMetricsF::xHeight()
316 qreal QRawFont::xHeight() const
318 return d->isValid() ? d->fontEngine->xHeight().toReal() : 0.0;
322 Returns the leading of this QRawFont in pixel units.
324 \sa QFontMetricsF::leading()
326 qreal QRawFont::leading() const
328 return d->isValid() ? d->fontEngine->leading().toReal() : 0.0;
332 Returns the average character width of this QRawFont in pixel units.
334 \sa QFontMetricsF::averageCharWidth()
336 qreal QRawFont::averageCharWidth() const
338 return d->isValid() ? d->fontEngine->averageCharWidth().toReal() : 0.0;
342 Returns the width of the widest character in the font.
344 \sa QFontMetricsF::maxWidth()
346 qreal QRawFont::maxCharWidth() const
348 return d->isValid() ? d->fontEngine->maxCharWidth() : 0.0;
352 Returns the pixel size set for this QRawFont. The pixel size affects how glyphs are
353 rasterized, the size of glyphs returned by pathForGlyph(), and is used to convert
354 internal metrics from design units to logical pixel units.
358 qreal QRawFont::pixelSize() const
360 return d->isValid() ? d->fontEngine->fontDef.pixelSize : 0.0;
364 Returns the number of design units define the width and height of the em square
365 for this QRawFont. This value is used together with the pixel size when converting design metrics
366 to pixel units, as the internal metrics are specified in design units and the pixel size gives
367 the size of 1 em in pixels.
369 \sa pixelSize(), setPixelSize()
371 qreal QRawFont::unitsPerEm() const
373 return d->isValid() ? d->fontEngine->emSquareSize().toReal() : 0.0;
377 Returns the thickness for drawing lines (underline, overline, etc.)
378 along with text drawn in this font.
380 qreal QRawFont::lineThickness() const
385 return d->fontEngine->lineThickness().toReal();
389 Returns the position from baseline for drawing underlines below the text
390 rendered with this font.
392 qreal QRawFont::underlinePosition() const
397 return d->fontEngine->underlinePosition().toReal();
401 Returns the family name of this QRawFont.
403 QString QRawFont::familyName() const
405 return d->isValid() ? d->fontEngine->fontDef.family : QString();
409 Returns the style name of this QRawFont.
411 \sa QFont::styleName()
413 QString QRawFont::styleName() const
415 return d->isValid() ? d->fontEngine->fontDef.styleName : QString();
419 Returns the style of this QRawFont.
423 QFont::Style QRawFont::style() const
425 return d->isValid() ? QFont::Style(d->fontEngine->fontDef.style) : QFont::StyleNormal;
429 Returns the weight of this QRawFont.
433 int QRawFont::weight() const
435 return d->isValid() ? int(d->fontEngine->fontDef.weight) : -1;
439 Converts the string of unicode points given by \a text to glyph indexes
440 using the CMAP table in the underlying font, and returns a vector containing
443 Note that, in cases where there are other tables in the font that affect the
444 shaping of the text, the returned glyph indexes will not correctly represent
445 the rendering of the text. To get the correctly shaped text, you can use
446 QTextLayout to lay out and shape the text, then call QTextLayout::glyphs()
447 to get the set of glyph index list and QRawFont pairs.
449 \sa advancesForGlyphIndexes(), glyphIndexesForChars(), QGlyphRun, QTextLayout::glyphRuns(), QTextFragment::glyphRuns()
451 QVector<quint32> QRawFont::glyphIndexesForString(const QString &text) const
454 return QVector<quint32>();
456 int nglyphs = text.size();
457 QVarLengthGlyphLayoutArray glyphs(nglyphs);
458 if (!glyphIndexesForChars(text.data(), text.size(), glyphs.glyphs, &nglyphs)) {
459 glyphs.resize(nglyphs);
460 if (!glyphIndexesForChars(text.data(), text.size(), glyphs.glyphs, &nglyphs)) {
461 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
462 return QVector<quint32>();
466 QVector<quint32> glyphIndexes;
467 for (int i=0; i<nglyphs; ++i)
468 glyphIndexes.append(glyphs.glyphs[i]);
474 Converts a string of unicode points to glyph indexes using the CMAP table in the
475 underlying font. The function works like glyphIndexesForString() except it take
476 an array (\a chars), the results will be returned though \a glyphIndexes array
477 and number of glyphs will be set in \a numGlyphs. The size of \a glyphIndexes array
478 must be at least \a numChars, if that's still not enough, this function will return
479 false, then you can resize \a glyphIndexes from the size returned in \a numGlyphs.
481 \sa glyphIndexesForString(), advancesForGlyphIndexes(), QGlyphs, QTextLayout::glyphs(), QTextFragment::glyphs()
483 bool QRawFont::glyphIndexesForChars(const QChar *chars, int numChars, quint32 *glyphIndexes, int *numGlyphs) const
489 glyphs.glyphs = glyphIndexes;
490 return d->fontEngine->stringToCMap(chars, numChars, &glyphs, numGlyphs, QTextEngine::GlyphIndicesOnly);
494 Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances
495 give the distance from the position of a given glyph to where the next glyph should be drawn
496 to make it appear as if the two glyphs are unspaced.
498 \sa QTextLine::horizontalAdvance(), QFontMetricsF::width()
500 QVector<QPointF> QRawFont::advancesForGlyphIndexes(const QVector<quint32> &glyphIndexes) const
503 return QVector<QPointF>();
505 int numGlyphs = glyphIndexes.size();
506 QVarLengthGlyphLayoutArray glyphs(numGlyphs);
507 qMemCopy(glyphs.glyphs, glyphIndexes.data(), numGlyphs * sizeof(quint32));
509 d->fontEngine->recalcAdvances(&glyphs, 0);
511 QVector<QPointF> advances;
512 for (int i=0; i<numGlyphs; ++i)
513 advances.append(QPointF(glyphs.advances_x[i].toReal(), glyphs.advances_y[i].toReal()));
519 Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances
520 give the distance from the position of a given glyph to where the next glyph should be drawn
521 to make it appear as if the two glyphs are unspaced. The glyph indexes are given with the
522 array \a glyphIndexes while the results are returned through \a advances, both of them must
523 have \a numGlyphs elements.
525 \sa QTextLine::horizontalAdvance(), QFontMetricsF::width()
527 bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *advances, int numGlyphs) const
533 glyphs.glyphs = const_cast<HB_Glyph *>(glyphIndexes);
534 glyphs.numGlyphs = numGlyphs;
535 QVarLengthArray<QFixed> advances_x(numGlyphs);
536 QVarLengthArray<QFixed> advances_y(numGlyphs);
537 glyphs.advances_x = advances_x.data();
538 glyphs.advances_y = advances_y.data();
540 d->fontEngine->recalcAdvances(&glyphs, 0);
542 for (int i=0; i<numGlyphs; ++i)
543 advances[i] = QPointF(glyphs.advances_x[i].toReal(), glyphs.advances_y[i].toReal());
549 Returns the hinting preference used to construct this QRawFont.
551 \sa QFont::hintingPreference()
553 QFont::HintingPreference QRawFont::hintingPreference() const
555 return d->isValid() ? d->hintingPreference : QFont::PreferDefaultHinting;
559 Retrieves the sfnt table named \a tagName from the underlying physical font, or an empty
560 byte array if no such table was found. The returned font table's byte order is Big Endian, like
561 the sfnt format specifies. The \a tagName must be four characters long and should be formatted
562 in the default endianness of the current platform.
564 QByteArray QRawFont::fontTable(const char *tagName) const
569 const quint32 *tagId = reinterpret_cast<const quint32 *>(tagName);
570 return d->fontEngine->getSfntTable(qToBigEndian(*tagId));
573 // From qfontdatabase.cpp
574 extern QList<QFontDatabase::WritingSystem> qt_determine_writing_systems_from_truetype_bits(quint32 unicodeRange[4], quint32 codePageRange[2]);
577 Returns a list of writing systems supported by the font according to designer supplied
578 information in the font file. Please note that this does not guarantee support for a
579 specific unicode point in the font. You can use the supportsCharacter() to check support
580 for a single, specific character.
582 \note The list is determined based on the unicode ranges and codepage ranges set in the font's
583 OS/2 table and requires such a table to be present in the underlying font file.
585 \sa supportsCharacter()
587 QList<QFontDatabase::WritingSystem> QRawFont::supportedWritingSystems() const
590 QByteArray os2Table = fontTable("OS/2");
591 if (os2Table.size() > 86) {
592 char *data = os2Table.data();
593 quint32 *bigEndianUnicodeRanges = reinterpret_cast<quint32 *>(data + 42);
594 quint32 *bigEndianCodepageRanges = reinterpret_cast<quint32 *>(data + 78);
596 quint32 unicodeRanges[4];
597 quint32 codepageRanges[2];
599 for (int i=0; i<4; ++i) {
601 codepageRanges[i] = qFromBigEndian(bigEndianCodepageRanges[i]);
602 unicodeRanges[i] = qFromBigEndian(bigEndianUnicodeRanges[i]);
605 return qt_determine_writing_systems_from_truetype_bits(unicodeRanges, codepageRanges);
609 return QList<QFontDatabase::WritingSystem>();
613 Returns true if the font has a glyph that corresponds to the given \a character.
615 \sa supportedWritingSystems()
617 bool QRawFont::supportsCharacter(const QChar &character) const
619 return d->isValid() && d->fontEngine->canRender(&character, 1);
623 Returns true if the font has a glyph that corresponds to the UCS-4 encoded character \a ucs4.
625 \sa supportedWritingSystems()
627 bool QRawFont::supportsCharacter(quint32 ucs4) const
632 QString str = QString::fromUcs4(&ucs4, 1);
633 return d->fontEngine->canRender(str.constData(), str.size());
637 extern int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSystem);
640 Fetches the physical representation based on a \a font query. The physical font returned is
641 the font that will be preferred by Qt in order to display text in the selected \a writingSystem.
643 \warning This function is potentially expensive and should not be called in performance
646 QRawFont QRawFont::fromFont(const QFont &font, QFontDatabase::WritingSystem writingSystem)
649 #if defined(Q_WS_MAC)
650 QTextLayout layout(QFontDatabase::writingSystemSample(writingSystem), font);
651 layout.beginLayout();
652 QTextLine line = layout.createLine();
654 QList<QGlyphRun> list = layout.glyphRuns();
656 // Pick the one matches the family name we originally requested,
657 // if none of them match, just pick the first one
658 for (int i = 0; i < list.size(); i++) {
659 rawfont = list.at(i).rawFont();
660 if (rawfont.familyName() == font.family())
663 return list.at(0).rawFont();
666 QFontPrivate *font_d = QFontPrivate::get(font);
667 int script = qt_script_for_writing_system(writingSystem);
668 QFontEngine *fe = font_d->engineForScript(script);
670 if (fe != 0 && fe->type() == QFontEngine::Multi) {
671 QFontEngineMulti *multiEngine = static_cast<QFontEngineMulti *>(fe);
672 fe = multiEngine->engine(0);
674 multiEngine->loadEngine(0);
675 fe = multiEngine->engine(0);
680 rawFont.d.data()->fontEngine = fe;
681 rawFont.d.data()->fontEngine->ref.ref();
682 rawFont.d.data()->hintingPreference = font.hintingPreference();
689 Sets the pixel size with which this font should be rendered to \a pixelSize.
691 void QRawFont::setPixelSize(qreal pixelSize)
693 if (d->fontEngine == 0)
697 QFontEngine *oldFontEngine = d->fontEngine;
699 d->fontEngine = d->fontEngine->cloneWithSize(pixelSize);
700 if (d->fontEngine != 0)
701 d->fontEngine->ref.ref();
703 oldFontEngine->ref.deref();
704 if (oldFontEngine->cache_count == 0 && oldFontEngine->ref == 0)
705 delete oldFontEngine;
711 void QRawFontPrivate::cleanUp()
714 if (fontEngine != 0) {
715 fontEngine->ref.deref();
716 if (fontEngine->cache_count == 0 && fontEngine->ref == 0)
720 hintingPreference = QFont::PreferDefaultHinting;
724 Returns the smallest rectangle containing the glyph with the given \a glyphIndex.
728 QRectF QRawFont::boundingRect(quint32 glyphIndex) const
733 glyph_metrics_t gm = d->fontEngine->boundingBox(glyphIndex);
734 return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
737 #endif // QT_NO_RAWFONT