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/qthread.h>
50 #include <QtCore/qendian.h>
56 \brief The QRawFont class provides access to a single physical instance of a font.
62 \note QRawFont is a low level class. For most purposes QFont is a more appropriate class.
64 Most commonly, when presenting text in a user interface, the exact fonts used
65 to render the characters is to some extent unknown. This can be the case for several
66 reasons: For instance, the actual, physical fonts present on the target system could be
67 unexpected to the developers, or the text could contain user selected styles, sizes or
68 writing systems that are not supported by font chosen in the code.
70 Therefore, Qt's QFont class really represents a query for fonts. When text is interpreted,
71 Qt will do its best to match the text to the query, but depending on the support, different
72 fonts can be used behind the scenes.
74 For most use cases, this is both expected and necessary, as it minimizes the possibility of
75 text in the user interface being undisplayable. In some cases, however, more direct control
76 over the process might be useful. It is for these use cases the QRawFont class exists.
78 A QRawFont object represents a single, physical instance of a given font in a given pixel size.
79 I.e. in the typical case it represents a set of TrueType or OpenType font tables and uses a
80 user specified pixel size to convert metrics into logical pixel units. In can be used in
81 combination with the QGlyphRun class to draw specific glyph indexes at specific positions, and
82 also have accessors to some relevant data in the physical font.
84 QRawFont only provides support for the main font technologies: GDI and DirectWrite on Windows
85 platforms, FreeType on Symbian and Linux platforms and CoreText on Mac OS X. For other
86 font back-ends, the APIs will be disabled.
88 QRawFont can be constructed in a number of ways:
90 \o It can be constructed by calling QTextLayout::glyphs() or QTextFragment::glyphs(). The
91 returned QGlyphs objects will contain QRawFont objects which represent the actual fonts
92 used to render each portion of the text.
93 \o It can be constructed by passing a QFont object to QRawFont::fromFont(). The function
94 will return a QRawFont object representing the font that will be selected as response to
95 the QFont query and the selected writing system.
96 \o It can be constructed by passing a file name or QByteArray directly to the QRawFont
97 constructor, or by calling loadFromFile() or loadFromData(). In this case, the
98 font will not be registered in QFontDatabase, and it will not be available as part of
99 regular font selection.
102 QRawFont is considered local to the thread in which it is constructed (either using a
103 constructor, or by calling loadFromData() or loadFromFile()). The QRawFont cannot be moved to a
104 different thread, but will have to be recreated in the thread in question.
106 \note For the requirement of caching glyph indexes and font selections for static text to avoid
107 reshaping and relayouting in the inner loop of an application, a better choice is the QStaticText
108 class, since it optimizes the memory cost of the cache and also provides the possibility of paint
109 engine specific caches for an additional speed-up.
113 \enum QRawFont::AntialiasingType
115 This enum represents the different ways a glyph can be rasterized in the function
118 \value PixelAntialiasing Will rasterize by measuring the coverage of the shape on whole pixels.
119 The returned image contains the alpha values of each pixel based on the coverage of
121 \value SubPixelAntialiasing Will rasterize by measuring the coverage of each subpixel,
122 returning a separate alpha value for each of the red, green and blue components of
127 Constructs an invalid QRawFont.
130 : d(new QRawFontPrivate)
135 Constructs a QRawFont representing the font contained in the file referenced
136 by \a fileName for the size (in pixels) given by \a pixelSize, and using the
137 hinting preference specified by \a hintingPreference.
139 \note The referenced file must contain a TrueType or OpenType font.
141 QRawFont::QRawFont(const QString &fileName,
143 QFont::HintingPreference hintingPreference)
144 : d(new QRawFontPrivate)
146 loadFromFile(fileName, pixelSize, hintingPreference);
150 Constructs a QRawFont representing the font contained in the supplied
151 \a fontData for the size (in pixels) given by \a pixelSize, and using the
152 hinting preference specified by \a hintingPreference.
154 \note The data must contain a TrueType or OpenType font.
156 QRawFont::QRawFont(const QByteArray &fontData,
158 QFont::HintingPreference hintingPreference)
159 : d(new QRawFontPrivate)
161 loadFromData(fontData, pixelSize, hintingPreference);
165 Creates a QRawFont which is a copy of \a other.
167 QRawFont::QRawFont(const QRawFont &other)
173 Destroys the QRawFont
175 QRawFont::~QRawFont()
180 Assigns \a other to this QRawFont.
182 QRawFont &QRawFont::operator=(const QRawFont &other)
189 Returns true if the QRawFont is valid and false otherwise.
191 bool QRawFont::isValid() const
193 Q_ASSERT(d->thread == 0 || d->thread == QThread::currentThread());
194 return d->fontEngine != 0;
198 Replaces the current QRawFont with the contents of the file referenced
199 by \a fileName for the size (in pixels) given by \a pixelSize, and using the
200 hinting preference specified by \a hintingPreference.
202 The file must reference a TrueType or OpenType font.
206 void QRawFont::loadFromFile(const QString &fileName,
208 QFont::HintingPreference hintingPreference)
210 QFile file(fileName);
211 if (file.open(QIODevice::ReadOnly))
212 loadFromData(file.readAll(), pixelSize, hintingPreference);
216 Replaces the current QRawFont with the font contained in the supplied
217 \a fontData for the size (in pixels) given by \a pixelSize, and using the
218 hinting preference specified by \a hintingPreference.
220 The \a fontData must contain a TrueType or OpenType font.
224 void QRawFont::loadFromData(const QByteArray &fontData,
226 QFont::HintingPreference hintingPreference)
230 d->hintingPreference = hintingPreference;
231 d->thread = QThread::currentThread();
232 d->platformLoadFromData(fontData, pixelSize, hintingPreference);
236 This function returns a rasterized image of the glyph at the given
237 \a glyphIndex in the underlying font, using the \a transform specified.
238 If the QRawFont is not valid, this function will return an invalid QImage.
240 If \a antialiasingType is set to QRawFont::SubPixelAntialiasing, then the resulting image will be
241 in QImage::Format_RGB32 and the RGB values of each pixel will represent the subpixel opacities of
242 the pixel in the rasterization of the glyph. Otherwise, the image will be in the format of
243 QImage::Format_A8 and each pixel will contain the opacity of the pixel in the rasterization.
245 \sa pathForGlyph(), QPainter::drawGlyphRun()
247 QImage QRawFont::alphaMapForGlyph(quint32 glyphIndex, AntialiasingType antialiasingType,
248 const QTransform &transform) const
253 if (antialiasingType == SubPixelAntialiasing)
254 return d->fontEngine->alphaRGBMapForGlyph(glyphIndex, QFixed(), 0, transform);
256 return d->fontEngine->alphaMapForGlyph(glyphIndex, QFixed(), transform);
260 This function returns the shape of the glyph at a given \a glyphIndex in the underlying font
261 if the QRawFont is valid. Otherwise, it returns an empty QPainterPath.
263 The returned glyph will always be unhinted.
265 \sa alphaMapForGlyph(), QPainterPath::addText()
267 QPainterPath QRawFont::pathForGlyph(quint32 glyphIndex) const
270 return QPainterPath();
272 QFixedPoint position;
274 d->fontEngine->addGlyphsToPath(&glyphIndex, &position, 1, &path, 0);
279 Returns true if this QRawFont is equal to \a other. Otherwise, returns false.
281 bool QRawFont::operator==(const QRawFont &other) const
283 return d->fontEngine == other.d->fontEngine;
287 Returns the ascent of this QRawFont in pixel units.
289 \sa QFontMetricsF::ascent()
291 qreal QRawFont::ascent() const
296 return d->fontEngine->ascent().toReal();
300 Returns the descent of this QRawFont in pixel units.
302 \sa QFontMetricsF::descent()
304 qreal QRawFont::descent() const
309 return d->fontEngine->descent().toReal();
313 Returns the xHeight of this QRawFont in pixel units.
315 \sa QFontMetricsF::xHeight()
317 qreal QRawFont::xHeight() const
322 return d->fontEngine->xHeight().toReal();
326 Returns the leading of this QRawFont in pixel units.
328 \sa QFontMetricsF::leading()
330 qreal QRawFont::leading() const
335 return d->fontEngine->leading().toReal();
339 Returns the average character width of this QRawFont in pixel units.
341 \sa QFontMetricsF::averageCharWidth()
343 qreal QRawFont::averageCharWidth() const
348 return d->fontEngine->averageCharWidth().toReal();
352 Returns the width of the widest character in the font.
354 \sa QFontMetricsF::maxWidth()
356 qreal QRawFont::maxCharWidth() const
361 return d->fontEngine->maxCharWidth();
365 Returns the pixel size set for this QRawFont. The pixel size affects how glyphs are
366 rasterized, the size of glyphs returned by pathForGlyph(), and is used to convert
367 internal metrics from design units to logical pixel units.
371 qreal QRawFont::pixelSize() const
376 return d->fontEngine->fontDef.pixelSize;
380 Returns the number of design units define the width and height of the em square
381 for this QRawFont. This value is used together with the pixel size when converting design metrics
382 to pixel units, as the internal metrics are specified in design units and the pixel size gives
383 the size of 1 em in pixels.
385 \sa pixelSize(), setPixelSize()
387 qreal QRawFont::unitsPerEm() const
392 return d->fontEngine->emSquareSize().toReal();
396 Returns the family name of this QRawFont.
398 QString QRawFont::familyName() const
403 return d->fontEngine->fontDef.family;
407 Returns the style name of this QRawFont.
409 \sa QFont::styleName()
411 QString QRawFont::styleName() const
416 return d->fontEngine->fontDef.styleName;
420 Returns the style of this QRawFont.
424 QFont::Style QRawFont::style() const
427 return QFont::StyleNormal;
429 return QFont::Style(d->fontEngine->fontDef.style);
433 Returns the weight of this QRawFont.
437 int QRawFont::weight() const
442 return int(d->fontEngine->fontDef.weight);
446 Converts the string of unicode points given by \a text to glyph indexes
447 using the CMAP table in the underlying font, and returns a vector containing
450 Note that, in cases where there are other tables in the font that affect the
451 shaping of the text, the returned glyph indexes will not correctly represent
452 the rendering of the text. To get the correctly shaped text, you can use
453 QTextLayout to lay out and shape the text, then call QTextLayout::glyphs()
454 to get the set of glyph index list and QRawFont pairs.
456 \sa advancesForGlyphIndexes(), glyphIndexesForChars(), QGlyphRun, QTextLayout::glyphRuns(), QTextFragment::glyphRuns()
458 QVector<quint32> QRawFont::glyphIndexesForString(const QString &text) const
461 return QVector<quint32>();
463 int nglyphs = text.size();
464 QVarLengthGlyphLayoutArray glyphs(nglyphs);
465 if (!glyphIndexesForChars(text.data(), text.size(), glyphs.glyphs, &nglyphs)) {
466 glyphs.resize(nglyphs);
467 if (!glyphIndexesForChars(text.data(), text.size(), glyphs.glyphs, &nglyphs)) {
468 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
469 return QVector<quint32>();
473 QVector<quint32> glyphIndexes;
474 for (int i=0; i<nglyphs; ++i)
475 glyphIndexes.append(glyphs.glyphs[i]);
481 Converts a string of unicode points to glyph indexes using the CMAP table in the
482 underlying font. The function works like glyphIndexesForString() except it take
483 an array (\a chars), the results will be returned though \a glyphIndexes array
484 and number of glyphs will be set in \a numGlyphs. The size of \a glyphIndexes array
485 must be at least \a numChars, if that's still not enough, this function will return
486 false, then you can resize \a glyphIndexes from the size returned in \a numGlyphs.
488 \sa glyphIndexesForString(), advancesForGlyphIndexes(), QGlyphs, QTextLayout::glyphs(), QTextFragment::glyphs()
490 bool QRawFont::glyphIndexesForChars(const QChar *chars, int numChars, quint32 *glyphIndexes, int *numGlyphs) const
496 glyphs.glyphs = glyphIndexes;
497 return d->fontEngine->stringToCMap(chars, numChars, &glyphs, numGlyphs, QTextEngine::GlyphIndicesOnly);
501 Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances
502 give the distance from the position of a given glyph to where the next glyph should be drawn
503 to make it appear as if the two glyphs are unspaced.
505 \sa QTextLine::horizontalAdvance(), QFontMetricsF::width()
507 QVector<QPointF> QRawFont::advancesForGlyphIndexes(const QVector<quint32> &glyphIndexes) const
510 return QVector<QPointF>();
512 int numGlyphs = glyphIndexes.size();
513 QVarLengthGlyphLayoutArray glyphs(numGlyphs);
514 qMemCopy(glyphs.glyphs, glyphIndexes.data(), numGlyphs * sizeof(quint32));
516 d->fontEngine->recalcAdvances(&glyphs, 0);
518 QVector<QPointF> advances;
519 for (int i=0; i<numGlyphs; ++i)
520 advances.append(QPointF(glyphs.advances_x[i].toReal(), glyphs.advances_y[i].toReal()));
526 Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances
527 give the distance from the position of a given glyph to where the next glyph should be drawn
528 to make it appear as if the two glyphs are unspaced. The glyph indexes are given with the
529 array \a glyphIndexes while the results are returned through \a advances, both of them must
530 have \a numGlyphs elements.
532 \sa QTextLine::horizontalAdvance(), QFontMetricsF::width()
534 bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *advances, int numGlyphs) const
540 glyphs.glyphs = const_cast<HB_Glyph *>(glyphIndexes);
541 glyphs.numGlyphs = numGlyphs;
542 QVarLengthArray<QFixed> advances_x(numGlyphs);
543 QVarLengthArray<QFixed> advances_y(numGlyphs);
544 glyphs.advances_x = advances_x.data();
545 glyphs.advances_y = advances_y.data();
547 d->fontEngine->recalcAdvances(&glyphs, 0);
549 for (int i=0; i<numGlyphs; ++i)
550 advances[i] = QPointF(glyphs.advances_x[i].toReal(), glyphs.advances_y[i].toReal());
556 Returns the hinting preference used to construct this QRawFont.
558 \sa QFont::hintingPreference()
560 QFont::HintingPreference QRawFont::hintingPreference() const
563 return QFont::PreferDefaultHinting;
565 return d->hintingPreference;
569 Retrieves the sfnt table named \a tagName from the underlying physical font, or an empty
570 byte array if no such table was found. The returned font table's byte order is Big Endian, like
571 the sfnt format specifies. The \a tagName must be four characters long and should be formatted
572 in the default endianness of the current platform.
574 QByteArray QRawFont::fontTable(const char *tagName) const
579 const quint32 *tagId = reinterpret_cast<const quint32 *>(tagName);
580 return d->fontEngine->getSfntTable(qToBigEndian(*tagId));
583 // From qfontdatabase.cpp
584 extern QList<QFontDatabase::WritingSystem> qt_determine_writing_systems_from_truetype_bits(quint32 unicodeRange[4], quint32 codePageRange[2]);
587 Returns a list of writing systems supported by the font according to designer supplied
588 information in the font file. Please note that this does not guarantee support for a
589 specific unicode point in the font. You can use the supportsCharacter() to check support
590 for a single, specific character.
592 \note The list is determined based on the unicode ranges and codepage ranges set in the font's
593 OS/2 table and requires such a table to be present in the underlying font file.
595 \sa supportsCharacter()
597 QList<QFontDatabase::WritingSystem> QRawFont::supportedWritingSystems() const
600 QByteArray os2Table = fontTable("OS/2");
601 if (!os2Table.isEmpty() && os2Table.size() > 86) {
602 char *data = os2Table.data();
603 quint32 *bigEndianUnicodeRanges = reinterpret_cast<quint32 *>(data + 42);
604 quint32 *bigEndianCodepageRanges = reinterpret_cast<quint32 *>(data + 78);
606 quint32 unicodeRanges[4];
607 quint32 codepageRanges[2];
609 for (int i=0; i<4; ++i) {
611 codepageRanges[i] = qFromBigEndian(bigEndianCodepageRanges[i]);
612 unicodeRanges[i] = qFromBigEndian(bigEndianUnicodeRanges[i]);
615 return qt_determine_writing_systems_from_truetype_bits(unicodeRanges, codepageRanges);
619 return QList<QFontDatabase::WritingSystem>();
623 Returns true if the font has a glyph that corresponds to the given \a character.
625 \sa supportedWritingSystems()
627 bool QRawFont::supportsCharacter(const QChar &character) const
632 return d->fontEngine->canRender(&character, 1);
636 Returns true if the font has a glyph that corresponds to the UCS-4 encoded character \a ucs4.
638 \sa supportedWritingSystems()
640 bool QRawFont::supportsCharacter(quint32 ucs4) const
645 QString str = QString::fromUcs4(&ucs4, 1);
646 return d->fontEngine->canRender(str.constData(), str.size());
650 extern int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSystem);
653 Fetches the physical representation based on a \a font query. The physical font returned is
654 the font that will be preferred by Qt in order to display text in the selected \a writingSystem.
656 QRawFont QRawFont::fromFont(const QFont &font, QFontDatabase::WritingSystem writingSystem)
658 #if defined(Q_WS_MAC)
659 QTextLayout layout(QFontDatabase::writingSystemSample(writingSystem), font);
660 layout.beginLayout();
661 QTextLine line = layout.createLine();
663 QList<QGlyphRun> list = layout.glyphRuns();
665 // Pick the one matches the family name we originally requested,
666 // if none of them match, just pick the first one
667 for (int i = 0; i < list.size(); i++) {
668 QGlyphRun glyphs = list.at(i);
669 QRawFont rawfont = glyphs.rawFont();
670 if (rawfont.familyName() == font.family())
673 return list.at(0).rawFont();
677 QFontPrivate *font_d = QFontPrivate::get(font);
678 int script = qt_script_for_writing_system(writingSystem);
679 QFontEngine *fe = font_d->engineForScript(script);
681 if (fe != 0 && fe->type() == QFontEngine::Multi) {
682 QFontEngineMulti *multiEngine = static_cast<QFontEngineMulti *>(fe);
683 fe = multiEngine->engine(0);
685 multiEngine->loadEngine(0);
686 fe = multiEngine->engine(0);
692 rawFont.d.data()->fontEngine = fe;
693 rawFont.d.data()->fontEngine->ref.ref();
694 rawFont.d.data()->hintingPreference = font.hintingPreference();
703 Sets the pixel size with which this font should be rendered to \a pixelSize.
705 void QRawFont::setPixelSize(qreal pixelSize)
707 if (d->fontEngine == 0)
711 QFontEngine *oldFontEngine = d->fontEngine;
713 d->fontEngine = d->fontEngine->cloneWithSize(pixelSize);
714 if (d->fontEngine != 0)
715 d->fontEngine->ref.ref();
717 oldFontEngine->ref.deref();
718 if (oldFontEngine->cache_count == 0 && oldFontEngine->ref == 0)
719 delete oldFontEngine;
725 void QRawFont::detach()
734 void QRawFontPrivate::cleanUp()
737 if (fontEngine != 0) {
738 fontEngine->ref.deref();
739 if (fontEngine->cache_count == 0 && fontEngine->ref == 0)
743 hintingPreference = QFont::PreferDefaultHinting;
747 Returns the smallest rectangle containing the glyph with the given \a glyphIndex.
751 QRectF QRawFont::boundingRect(quint32 glyphIndex) const
756 glyph_metrics_t gm = d->fontEngine->boundingBox(glyphIndex);
757 return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
760 #endif // QT_NO_RAWFONT