822 lines
28 KiB
C++
822 lines
28 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the QtGui module of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 3 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU Lesser General Public License version 3 requirements
|
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 2.0 or (at your option) the GNU General
|
|
** Public license version 3 or any later version approved by the KDE Free
|
|
** Qt Foundation. The licenses are as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
|
** included in the packaging of this file. Please review the following
|
|
** information to ensure the GNU General Public License requirements will
|
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "qglobal.h"
|
|
|
|
#if !defined(QT_NO_RAWFONT)
|
|
|
|
#include "qrawfont.h"
|
|
#include "qrawfont_p.h"
|
|
#include "qplatformfontdatabase.h"
|
|
|
|
#include <private/qguiapplication_p.h>
|
|
#include <qpa/qplatformintegration.h>
|
|
#include <qpa/qplatformfontdatabase.h>
|
|
|
|
#include <QtCore/qendian.h>
|
|
#include <QtCore/qfile.h>
|
|
#include <QtGui/qpainterpath.h>
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
/*!
|
|
\class QRawFont
|
|
\brief The QRawFont class provides access to a single physical instance of a font.
|
|
\since 4.8
|
|
\inmodule QtGui
|
|
|
|
\ingroup text
|
|
\ingroup shared
|
|
|
|
\note QRawFont is a low level class. For most purposes QFont is a more appropriate class.
|
|
|
|
Most commonly, when presenting text in a user interface, the exact fonts used
|
|
to render the characters is to some extent unknown. This can be the case for several
|
|
reasons: For instance, the actual, physical fonts present on the target system could be
|
|
unexpected to the developers, or the text could contain user selected styles, sizes or
|
|
writing systems that are not supported by font chosen in the code.
|
|
|
|
Therefore, Qt's QFont class really represents a query for fonts. When text is interpreted,
|
|
Qt will do its best to match the text to the query, but depending on the support, different
|
|
fonts can be used behind the scenes.
|
|
|
|
For most use cases, this is both expected and necessary, as it minimizes the possibility of
|
|
text in the user interface being undisplayable. In some cases, however, more direct control
|
|
over the process might be useful. It is for these use cases the QRawFont class exists.
|
|
|
|
A QRawFont object represents a single, physical instance of a given font in a given pixel size.
|
|
I.e. in the typical case it represents a set of TrueType or OpenType font tables and uses a
|
|
user specified pixel size to convert metrics into logical pixel units. It can be used in
|
|
combination with the QGlyphRun class to draw specific glyph indexes at specific positions, and
|
|
also have accessors to some relevant data in the physical font.
|
|
|
|
QRawFont only provides support for the main font technologies: GDI and DirectWrite on Windows
|
|
platforms, FreeType on Linux platforms and CoreText on \macos. For other
|
|
font back-ends, the APIs will be disabled.
|
|
|
|
QRawFont can be constructed in a number of ways:
|
|
\list
|
|
\li It can be constructed by calling QTextLayout::glyphs() or QTextFragment::glyphs(). The
|
|
returned QGlyphs objects will contain QRawFont objects which represent the actual fonts
|
|
used to render each portion of the text.
|
|
\li It can be constructed by passing a QFont object to QRawFont::fromFont(). The function
|
|
will return a QRawFont object representing the font that will be selected as response to
|
|
the QFont query and the selected writing system.
|
|
\li It can be constructed by passing a file name or QByteArray directly to the QRawFont
|
|
constructor, or by calling loadFromFile() or loadFromData(). In this case, the
|
|
font will not be registered in QFontDatabase, and it will not be available as part of
|
|
regular font selection.
|
|
\endlist
|
|
|
|
QRawFont is considered local to the thread in which it is constructed (either using a
|
|
constructor, or by calling loadFromData() or loadFromFile()). The QRawFont cannot be moved to a
|
|
different thread, but will have to be recreated in the thread in question.
|
|
|
|
\note For the requirement of caching glyph indexes and font selections for static text to avoid
|
|
reshaping and relayouting in the inner loop of an application, a better choice is the QStaticText
|
|
class, since it optimizes the memory cost of the cache and also provides the possibility of paint
|
|
engine specific caches for an additional speed-up.
|
|
*/
|
|
|
|
/*!
|
|
\enum QRawFont::AntialiasingType
|
|
|
|
This enum represents the different ways a glyph can be rasterized in the function
|
|
alphaMapForGlyph().
|
|
|
|
\value PixelAntialiasing Will rasterize by measuring the coverage of the shape on whole pixels.
|
|
The returned image contains the alpha values of each pixel based on the coverage of
|
|
the glyph shape.
|
|
\value SubPixelAntialiasing Will rasterize by measuring the coverage of each subpixel,
|
|
returning a separate alpha value for each of the red, green and blue components of
|
|
each pixel.
|
|
*/
|
|
|
|
/*!
|
|
\enum QRawFont::LayoutFlag
|
|
\since 5.1
|
|
|
|
This enum tells the function advancesForGlyphIndexes() how to calculate the advances.
|
|
|
|
\value SeparateAdvances Will calculate the advance for each glyph separately.
|
|
\value KernedAdvances Will apply kerning between adjacent glyphs. Note that OpenType GPOS based
|
|
kerning is currently not supported.
|
|
\value UseDesignMetrics Use design metrics instead of hinted metrics adjusted to the resolution
|
|
of the paint device.
|
|
Can be OR-ed with any of the options above.
|
|
*/
|
|
|
|
/*!
|
|
Constructs an invalid QRawFont.
|
|
*/
|
|
QRawFont::QRawFont()
|
|
: d(new QRawFontPrivate)
|
|
{
|
|
}
|
|
|
|
/*!
|
|
Constructs a QRawFont representing the font contained in the file referenced
|
|
by \a fileName for the size (in pixels) given by \a pixelSize, and using the
|
|
hinting preference specified by \a hintingPreference.
|
|
|
|
\note The referenced file must contain a TrueType or OpenType font.
|
|
*/
|
|
QRawFont::QRawFont(const QString &fileName,
|
|
qreal pixelSize,
|
|
QFont::HintingPreference hintingPreference)
|
|
: d(new QRawFontPrivate)
|
|
{
|
|
loadFromFile(fileName, pixelSize, hintingPreference);
|
|
}
|
|
|
|
/*!
|
|
Constructs a QRawFont representing the font contained in the supplied
|
|
\a fontData for the size (in pixels) given by \a pixelSize, and using the
|
|
hinting preference specified by \a hintingPreference.
|
|
|
|
\note The data must contain a TrueType or OpenType font.
|
|
*/
|
|
QRawFont::QRawFont(const QByteArray &fontData,
|
|
qreal pixelSize,
|
|
QFont::HintingPreference hintingPreference)
|
|
: d(new QRawFontPrivate)
|
|
{
|
|
loadFromData(fontData, pixelSize, hintingPreference);
|
|
}
|
|
|
|
/*!
|
|
Creates a QRawFont which is a copy of \a other.
|
|
*/
|
|
QRawFont::QRawFont(const QRawFont &other)
|
|
{
|
|
d = other.d;
|
|
}
|
|
|
|
/*!
|
|
Destroys the QRawFont
|
|
*/
|
|
QRawFont::~QRawFont()
|
|
{
|
|
}
|
|
|
|
/*!
|
|
Assigns \a other to this QRawFont.
|
|
*/
|
|
QRawFont &QRawFont::operator=(const QRawFont &other)
|
|
{
|
|
d = other.d;
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
\fn void QRawFont::swap(QRawFont &other)
|
|
\since 5.0
|
|
|
|
Swaps this raw font with \a other. This function is very fast and
|
|
never fails.
|
|
*/
|
|
|
|
/*!
|
|
Returns \c true if the QRawFont is valid and false otherwise.
|
|
*/
|
|
bool QRawFont::isValid() const
|
|
{
|
|
return d->isValid();
|
|
}
|
|
|
|
/*!
|
|
Replaces the current QRawFont with the contents of the file referenced
|
|
by \a fileName for the size (in pixels) given by \a pixelSize, and using the
|
|
hinting preference specified by \a hintingPreference.
|
|
|
|
The file must reference a TrueType or OpenType font.
|
|
|
|
\sa loadFromData()
|
|
*/
|
|
void QRawFont::loadFromFile(const QString &fileName,
|
|
qreal pixelSize,
|
|
QFont::HintingPreference hintingPreference)
|
|
{
|
|
QFile file(fileName);
|
|
if (file.open(QIODevice::ReadOnly))
|
|
loadFromData(file.readAll(), pixelSize, hintingPreference);
|
|
}
|
|
|
|
/*!
|
|
Replaces the current QRawFont with the font contained in the supplied
|
|
\a fontData for the size (in pixels) given by \a pixelSize, and using the
|
|
hinting preference specified by \a hintingPreference.
|
|
|
|
The \a fontData must contain a TrueType or OpenType font.
|
|
|
|
\sa loadFromFile()
|
|
*/
|
|
void QRawFont::loadFromData(const QByteArray &fontData,
|
|
qreal pixelSize,
|
|
QFont::HintingPreference hintingPreference)
|
|
{
|
|
d.detach();
|
|
d->cleanUp();
|
|
d->hintingPreference = hintingPreference;
|
|
d->loadFromData(fontData, pixelSize, hintingPreference);
|
|
}
|
|
|
|
/*!
|
|
This function returns a rasterized image of the glyph at the given
|
|
\a glyphIndex in the underlying font, using the \a transform specified.
|
|
If the QRawFont is not valid, this function will return an invalid QImage.
|
|
|
|
If the font is a color font, then the resulting image will contain the rendered
|
|
glyph at the current pixel size. In this case, the \a antialiasingType will be
|
|
ignored.
|
|
|
|
Otherwise, if \a antialiasingType is set to QRawFont::SubPixelAntialiasing, then the resulting image
|
|
will be in QImage::Format_RGB32 and the RGB values of each pixel will represent the subpixel opacities
|
|
of the pixel in the rasterization of the glyph. Otherwise, the image will be in the format of
|
|
QImage::Format_Indexed8 and each pixel will contain the opacity of the pixel in the
|
|
rasterization.
|
|
|
|
\sa pathForGlyph(), QPainter::drawGlyphRun()
|
|
*/
|
|
QImage QRawFont::alphaMapForGlyph(quint32 glyphIndex, AntialiasingType antialiasingType,
|
|
const QTransform &transform) const
|
|
{
|
|
if (!d->isValid())
|
|
return QImage();
|
|
|
|
if (d->fontEngine->glyphFormat == QFontEngine::Format_ARGB)
|
|
return d->fontEngine->bitmapForGlyph(glyphIndex, QFixed(), transform);
|
|
|
|
if (antialiasingType == SubPixelAntialiasing)
|
|
return d->fontEngine->alphaRGBMapForGlyph(glyphIndex, QFixed(), transform);
|
|
|
|
return d->fontEngine->alphaMapForGlyph(glyphIndex, QFixed(), transform);
|
|
}
|
|
|
|
/*!
|
|
This function returns the shape of the glyph at a given \a glyphIndex in the underlying font
|
|
if the QRawFont is valid. Otherwise, it returns an empty QPainterPath.
|
|
|
|
The returned glyph will always be unhinted.
|
|
|
|
\sa alphaMapForGlyph(), QPainterPath::addText()
|
|
*/
|
|
QPainterPath QRawFont::pathForGlyph(quint32 glyphIndex) const
|
|
{
|
|
if (!d->isValid())
|
|
return QPainterPath();
|
|
|
|
QFixedPoint position;
|
|
QPainterPath path;
|
|
d->fontEngine->addGlyphsToPath(&glyphIndex, &position, 1, &path, { });
|
|
return path;
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if this QRawFont is equal to \a other. Otherwise, returns \c false.
|
|
*/
|
|
bool QRawFont::operator==(const QRawFont &other) const
|
|
{
|
|
return d->fontEngine == other.d->fontEngine;
|
|
}
|
|
|
|
/*!
|
|
Returns the hash value for \a font. If specified, \a seed is used
|
|
to initialize the hash.
|
|
|
|
\relates QRawFont
|
|
\since 5.8
|
|
*/
|
|
size_t qHash(const QRawFont &font, size_t seed) noexcept
|
|
{
|
|
return qHash(QRawFontPrivate::get(font)->fontEngine, seed);
|
|
}
|
|
|
|
|
|
/*!
|
|
\fn bool QRawFont::operator!=(const QRawFont &other) const
|
|
|
|
Returns \c true if this QRawFont is not equal to \a other. Otherwise, returns \c false.
|
|
*/
|
|
|
|
/*!
|
|
Returns the ascent of this QRawFont in pixel units.
|
|
|
|
The ascent of a font is the distance from the baseline to the
|
|
highest position characters extend to. In practice, some font
|
|
designers break this rule, e.g. when they put more than one accent
|
|
on top of a character, or to accommodate an unusual character in
|
|
an exotic language, so it is possible (though rare) that this
|
|
value will be too small.
|
|
|
|
\sa QFontMetricsF::ascent()
|
|
*/
|
|
qreal QRawFont::ascent() const
|
|
{
|
|
return d->isValid() ? d->fontEngine->ascent().toReal() : 0.0;
|
|
}
|
|
|
|
/*!
|
|
Returns the cap height of this QRawFont in pixel units.
|
|
|
|
\since 5.8
|
|
|
|
The cap height of a font is the height of a capital letter above
|
|
the baseline. It specifically is the height of capital letters
|
|
that are flat - such as H or I - as opposed to round letters such
|
|
as O, or pointed letters like A, both of which may display overshoot.
|
|
|
|
\sa QFontMetricsF::capHeight()
|
|
*/
|
|
qreal QRawFont::capHeight() const
|
|
{
|
|
return d->isValid() ? d->fontEngine->capHeight().toReal() : 0.0;
|
|
}
|
|
|
|
/*!
|
|
Returns the descent of this QRawFont in pixel units.
|
|
|
|
The descent is the distance from the base line to the lowest point
|
|
characters extend to. In practice, some font designers break this rule,
|
|
e.g. to accommodate an unusual character in an exotic language, so
|
|
it is possible (though rare) that this value will be too small.
|
|
|
|
\sa QFontMetricsF::descent()
|
|
*/
|
|
qreal QRawFont::descent() const
|
|
{
|
|
return d->isValid() ? d->fontEngine->descent().toReal() : 0.0;
|
|
}
|
|
|
|
/*!
|
|
Returns the xHeight of this QRawFont in pixel units.
|
|
|
|
This is often but not always the same as the height of the character 'x'.
|
|
|
|
\sa QFontMetricsF::xHeight()
|
|
*/
|
|
qreal QRawFont::xHeight() const
|
|
{
|
|
return d->isValid() ? d->fontEngine->xHeight().toReal() : 0.0;
|
|
}
|
|
|
|
/*!
|
|
Returns the leading of this QRawFont in pixel units.
|
|
|
|
This is the natural inter-line spacing.
|
|
|
|
\sa QFontMetricsF::leading()
|
|
*/
|
|
qreal QRawFont::leading() const
|
|
{
|
|
return d->isValid() ? d->fontEngine->leading().toReal() : 0.0;
|
|
}
|
|
|
|
/*!
|
|
Returns the average character width of this QRawFont in pixel units.
|
|
|
|
\sa QFontMetricsF::averageCharWidth()
|
|
*/
|
|
qreal QRawFont::averageCharWidth() const
|
|
{
|
|
return d->isValid() ? d->fontEngine->averageCharWidth().toReal() : 0.0;
|
|
}
|
|
|
|
/*!
|
|
Returns the width of the widest character in the font.
|
|
|
|
\sa QFontMetricsF::maxWidth()
|
|
*/
|
|
qreal QRawFont::maxCharWidth() const
|
|
{
|
|
return d->isValid() ? d->fontEngine->maxCharWidth() : 0.0;
|
|
}
|
|
|
|
/*!
|
|
Returns the pixel size set for this QRawFont. The pixel size affects how glyphs are
|
|
rasterized, the size of glyphs returned by pathForGlyph(), and is used to convert
|
|
internal metrics from design units to logical pixel units.
|
|
|
|
\sa setPixelSize()
|
|
*/
|
|
qreal QRawFont::pixelSize() const
|
|
{
|
|
return d->isValid() ? d->fontEngine->fontDef.pixelSize : 0.0;
|
|
}
|
|
|
|
/*!
|
|
Returns the number of design units define the width and height of the em square
|
|
for this QRawFont. This value is used together with the pixel size when converting design metrics
|
|
to pixel units, as the internal metrics are specified in design units and the pixel size gives
|
|
the size of 1 em in pixels.
|
|
|
|
\sa pixelSize(), setPixelSize()
|
|
*/
|
|
qreal QRawFont::unitsPerEm() const
|
|
{
|
|
return d->isValid() ? d->fontEngine->emSquareSize().toReal() : 0.0;
|
|
}
|
|
|
|
/*!
|
|
Returns the thickness for drawing lines (underline, overline, etc.)
|
|
along with text drawn in this font.
|
|
*/
|
|
qreal QRawFont::lineThickness() const
|
|
{
|
|
return d->isValid() ? d->fontEngine->lineThickness().toReal() : 0.0;
|
|
}
|
|
|
|
/*!
|
|
Returns the position from baseline for drawing underlines below the text
|
|
rendered with this font.
|
|
*/
|
|
qreal QRawFont::underlinePosition() const
|
|
{
|
|
return d->isValid() ? d->fontEngine->underlinePosition().toReal() : 0.0;
|
|
}
|
|
|
|
/*!
|
|
Returns the family name of this QRawFont.
|
|
*/
|
|
QString QRawFont::familyName() const
|
|
{
|
|
return d->isValid() ? d->fontEngine->fontDef.family : QString();
|
|
}
|
|
|
|
/*!
|
|
Returns the style name of this QRawFont.
|
|
|
|
\sa QFont::styleName()
|
|
*/
|
|
QString QRawFont::styleName() const
|
|
{
|
|
return d->isValid() ? d->fontEngine->fontDef.styleName : QString();
|
|
}
|
|
|
|
/*!
|
|
Returns the style of this QRawFont.
|
|
|
|
\sa QFont::style()
|
|
*/
|
|
QFont::Style QRawFont::style() const
|
|
{
|
|
return d->isValid() ? QFont::Style(d->fontEngine->fontDef.style) : QFont::StyleNormal;
|
|
}
|
|
|
|
/*!
|
|
Returns the weight of this QRawFont.
|
|
|
|
\sa QFont::weight()
|
|
*/
|
|
int QRawFont::weight() const
|
|
{
|
|
return d->isValid() ? int(d->fontEngine->fontDef.weight) : -1;
|
|
}
|
|
|
|
/*!
|
|
Converts the string of unicode points given by \a text to glyph indexes
|
|
using the CMAP table in the underlying font, and returns a vector containing
|
|
the result.
|
|
|
|
Note that, in cases where there are other tables in the font that affect the
|
|
shaping of the text, the returned glyph indexes will not correctly represent
|
|
the rendering of the text. To get the correctly shaped text, you can use
|
|
QTextLayout to lay out and shape the text, then call QTextLayout::glyphs()
|
|
to get the set of glyph index list and QRawFont pairs.
|
|
|
|
\sa advancesForGlyphIndexes(), glyphIndexesForChars(), QGlyphRun, QTextLayout::glyphRuns(), QTextFragment::glyphRuns()
|
|
*/
|
|
QVector<quint32> QRawFont::glyphIndexesForString(const QString &text) const
|
|
{
|
|
QVector<quint32> glyphIndexes;
|
|
if (!d->isValid() || text.isEmpty())
|
|
return glyphIndexes;
|
|
|
|
int numGlyphs = text.size();
|
|
glyphIndexes.resize(numGlyphs);
|
|
|
|
QGlyphLayout glyphs;
|
|
glyphs.numGlyphs = numGlyphs;
|
|
glyphs.glyphs = glyphIndexes.data();
|
|
if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly))
|
|
Q_UNREACHABLE();
|
|
|
|
glyphIndexes.resize(numGlyphs);
|
|
return glyphIndexes;
|
|
}
|
|
|
|
/*!
|
|
Converts a string of unicode points to glyph indexes using the CMAP table in the
|
|
underlying font. The function works like glyphIndexesForString() except it take
|
|
an array (\a chars), the results will be returned though \a glyphIndexes array
|
|
and number of glyphs will be set in \a numGlyphs. The size of \a glyphIndexes array
|
|
must be at least \a numChars, if that's still not enough, this function will return
|
|
false, then you can resize \a glyphIndexes from the size returned in \a numGlyphs.
|
|
|
|
\sa glyphIndexesForString(), advancesForGlyphIndexes(), QGlyphRun, QTextLayout::glyphRuns(), QTextFragment::glyphRuns()
|
|
*/
|
|
bool QRawFont::glyphIndexesForChars(const QChar *chars, int numChars, quint32 *glyphIndexes, int *numGlyphs) const
|
|
{
|
|
Q_ASSERT(numGlyphs);
|
|
if (!d->isValid() || numChars <= 0) {
|
|
*numGlyphs = 0;
|
|
return false;
|
|
}
|
|
|
|
if (*numGlyphs <= 0 || !glyphIndexes) {
|
|
*numGlyphs = numChars;
|
|
return false;
|
|
}
|
|
|
|
QGlyphLayout glyphs;
|
|
glyphs.numGlyphs = *numGlyphs;
|
|
glyphs.glyphs = glyphIndexes;
|
|
return d->fontEngine->stringToCMap(chars, numChars, &glyphs, numGlyphs, QFontEngine::GlyphIndicesOnly);
|
|
}
|
|
|
|
/*!
|
|
\fn QVector<QPointF> QRawFont::advancesForGlyphIndexes(const QVector<quint32> &glyphIndexes, LayoutFlags layoutFlags) const
|
|
\since 5.1
|
|
|
|
Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances
|
|
give the distance from the position of a given glyph to where the next glyph should be drawn
|
|
to make it appear as if the two glyphs are unspaced. How the advances are calculated is
|
|
controlled by \a layoutFlags.
|
|
|
|
\sa QTextLine::horizontalAdvance(), QFontMetricsF::width()
|
|
*/
|
|
|
|
/*!
|
|
\fn QVector<QPointF> QRawFont::advancesForGlyphIndexes(const QVector<quint32> &glyphIndexes) const
|
|
|
|
\overload
|
|
|
|
Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances
|
|
give the distance from the position of a given glyph to where the next glyph should be drawn
|
|
to make it appear as if the two glyphs are unspaced. The advance of each glyph is calculated
|
|
separately.
|
|
|
|
\sa QTextLine::horizontalAdvance(), QFontMetricsF::width()
|
|
*/
|
|
|
|
/*!
|
|
\since 5.1
|
|
|
|
Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances
|
|
give the distance from the position of a given glyph to where the next glyph should be drawn
|
|
to make it appear as if the two glyphs are unspaced. The glyph indexes are given with the
|
|
array \a glyphIndexes while the results are returned through \a advances, both of them must
|
|
have \a numGlyphs elements. How the advances are calculated is controlled by \a layoutFlags.
|
|
|
|
\sa QTextLine::horizontalAdvance(), QFontMetricsF::width()
|
|
*/
|
|
bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *advances, int numGlyphs, LayoutFlags layoutFlags) const
|
|
{
|
|
Q_ASSERT(glyphIndexes && advances);
|
|
if (!d->isValid() || numGlyphs <= 0)
|
|
return false;
|
|
|
|
QVarLengthArray<QFixed> tmpAdvances(numGlyphs);
|
|
|
|
QGlyphLayout glyphs;
|
|
glyphs.glyphs = const_cast<glyph_t *>(glyphIndexes);
|
|
glyphs.numGlyphs = numGlyphs;
|
|
glyphs.advances = tmpAdvances.data();
|
|
|
|
bool design = layoutFlags & UseDesignMetrics;
|
|
|
|
d->fontEngine->recalcAdvances(&glyphs, design ? QFontEngine::DesignMetrics : QFontEngine::ShaperFlag(0));
|
|
if (layoutFlags & KernedAdvances)
|
|
d->fontEngine->doKerning(&glyphs, design ? QFontEngine::DesignMetrics : QFontEngine::ShaperFlag(0));
|
|
|
|
for (int i=0; i<numGlyphs; ++i)
|
|
advances[i] = QPointF(tmpAdvances[i].toReal(), 0.0);
|
|
|
|
return true;
|
|
}
|
|
|
|
/*!
|
|
\overload
|
|
|
|
Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances
|
|
give the distance from the position of a given glyph to where the next glyph should be drawn
|
|
to make it appear as if the two glyphs are unspaced. The glyph indexes are given with the
|
|
array \a glyphIndexes while the results are returned through \a advances, both of them must
|
|
have \a numGlyphs elements. The advance of each glyph is calculated separately
|
|
|
|
\sa QTextLine::horizontalAdvance(), QFontMetricsF::width()
|
|
*/
|
|
bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *advances, int numGlyphs) const
|
|
{
|
|
return QRawFont::advancesForGlyphIndexes(glyphIndexes, advances, numGlyphs, SeparateAdvances);
|
|
}
|
|
|
|
/*!
|
|
Returns the hinting preference used to construct this QRawFont.
|
|
|
|
\sa QFont::hintingPreference()
|
|
*/
|
|
QFont::HintingPreference QRawFont::hintingPreference() const
|
|
{
|
|
return d->isValid() ? d->hintingPreference : QFont::PreferDefaultHinting;
|
|
}
|
|
|
|
/*!
|
|
Retrieves the sfnt table named \a tagName from the underlying physical font, or an empty
|
|
byte array if no such table was found. The returned font table's byte order is Big Endian, like
|
|
the sfnt format specifies. The \a tagName must be four characters long and should be formatted
|
|
in the default endianness of the current platform.
|
|
*/
|
|
QByteArray QRawFont::fontTable(const char *tagName) const
|
|
{
|
|
if (!d->isValid())
|
|
return QByteArray();
|
|
|
|
return d->fontEngine->getSfntTable(MAKE_TAG(tagName[0], tagName[1], tagName[2], tagName[3]));
|
|
}
|
|
|
|
/*!
|
|
Returns a list of writing systems supported by the font according to designer supplied
|
|
information in the font file. Please note that this does not guarantee support for a
|
|
specific unicode point in the font. You can use the supportsCharacter() to check support
|
|
for a single, specific character.
|
|
|
|
\note The list is determined based on the unicode ranges and codepage ranges set in the font's
|
|
OS/2 table and requires such a table to be present in the underlying font file.
|
|
|
|
\sa supportsCharacter()
|
|
*/
|
|
QList<QFontDatabase::WritingSystem> QRawFont::supportedWritingSystems() const
|
|
{
|
|
QList<QFontDatabase::WritingSystem> writingSystems;
|
|
if (d->isValid()) {
|
|
QByteArray os2Table = fontTable("OS/2");
|
|
if (os2Table.size() > 86) {
|
|
const uchar * const data = reinterpret_cast<const uchar *>(os2Table.constData());
|
|
const uchar * const bigEndianUnicodeRanges = data + 42;
|
|
const uchar * const bigEndianCodepageRanges = data + 78;
|
|
|
|
quint32 unicodeRanges[4];
|
|
quint32 codepageRanges[2];
|
|
|
|
for (size_t i = 0; i < sizeof unicodeRanges / sizeof *unicodeRanges; ++i)
|
|
unicodeRanges[i] = qFromBigEndian<quint32>(bigEndianUnicodeRanges + i * sizeof(quint32));
|
|
|
|
for (size_t i = 0; i < sizeof codepageRanges / sizeof *codepageRanges; ++i)
|
|
codepageRanges[i] = qFromBigEndian<quint32>(bigEndianCodepageRanges + i * sizeof(quint32));
|
|
|
|
QSupportedWritingSystems ws = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRanges, codepageRanges);
|
|
for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
|
|
if (ws.supported(QFontDatabase::WritingSystem(i)))
|
|
writingSystems.append(QFontDatabase::WritingSystem(i));
|
|
}
|
|
}
|
|
}
|
|
|
|
return writingSystems;
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if the font has a glyph that corresponds to the given \a character.
|
|
|
|
\sa supportedWritingSystems()
|
|
*/
|
|
bool QRawFont::supportsCharacter(QChar character) const
|
|
{
|
|
return supportsCharacter(character.unicode());
|
|
}
|
|
|
|
/*!
|
|
\overload
|
|
|
|
Returns \c true if the font has a glyph that corresponds to the UCS-4 encoded character \a ucs4.
|
|
|
|
\sa supportedWritingSystems()
|
|
*/
|
|
bool QRawFont::supportsCharacter(uint ucs4) const
|
|
{
|
|
return d->isValid() && d->fontEngine->canRender(ucs4);
|
|
}
|
|
|
|
// qfontdatabase.cpp
|
|
extern int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSystem);
|
|
|
|
/*!
|
|
Fetches the physical representation based on a \a font query. The physical font returned is
|
|
the font that will be preferred by Qt in order to display text in the selected \a writingSystem.
|
|
|
|
\warning This function is potentially expensive and should not be called in performance
|
|
sensitive code.
|
|
*/
|
|
QRawFont QRawFont::fromFont(const QFont &font, QFontDatabase::WritingSystem writingSystem)
|
|
{
|
|
QRawFont rawFont;
|
|
const QFontPrivate *font_d = QFontPrivate::get(font);
|
|
int script = qt_script_for_writing_system(writingSystem);
|
|
QFontEngine *fe = font_d->engineForScript(script);
|
|
|
|
if (fe != nullptr && fe->type() == QFontEngine::Multi) {
|
|
QFontEngineMulti *multiEngine = static_cast<QFontEngineMulti *>(fe);
|
|
fe = multiEngine->engine(0);
|
|
|
|
if (script > QChar::Script_Latin) {
|
|
// keep in sync with QFontEngineMulti::loadEngine()
|
|
QFontDef request(multiEngine->fontDef);
|
|
request.styleStrategy |= QFont::NoFontMerging;
|
|
|
|
if (QFontEngine *engine = QFontDatabase::findFont(request, script)) {
|
|
if (request.weight > QFont::Normal)
|
|
engine->fontDef.weight = request.weight;
|
|
if (request.style > QFont::StyleNormal)
|
|
engine->fontDef.style = request.style;
|
|
fe = engine;
|
|
}
|
|
}
|
|
Q_ASSERT(fe);
|
|
}
|
|
|
|
if (fe != nullptr) {
|
|
rawFont.d.data()->setFontEngine(fe);
|
|
rawFont.d.data()->hintingPreference = font.hintingPreference();
|
|
}
|
|
return rawFont;
|
|
}
|
|
|
|
/*!
|
|
Sets the pixel size with which this font should be rendered to \a pixelSize.
|
|
*/
|
|
void QRawFont::setPixelSize(qreal pixelSize)
|
|
{
|
|
if (!d->isValid() || qFuzzyCompare(d->fontEngine->fontDef.pixelSize, pixelSize))
|
|
return;
|
|
|
|
d.detach();
|
|
d->setFontEngine(d->fontEngine->cloneWithSize(pixelSize));
|
|
}
|
|
|
|
/*!
|
|
\internal
|
|
*/
|
|
void QRawFontPrivate::loadFromData(const QByteArray &fontData, qreal pixelSize,
|
|
QFont::HintingPreference hintingPreference)
|
|
{
|
|
Q_ASSERT(fontEngine == nullptr);
|
|
|
|
QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
|
|
setFontEngine(pfdb->fontEngine(fontData, pixelSize, hintingPreference));
|
|
}
|
|
|
|
/*!
|
|
Returns the smallest rectangle containing the glyph with the given \a glyphIndex.
|
|
|
|
\since 5.0
|
|
*/
|
|
QRectF QRawFont::boundingRect(quint32 glyphIndex) const
|
|
{
|
|
if (!d->isValid())
|
|
return QRectF();
|
|
|
|
glyph_metrics_t gm = d->fontEngine->boundingBox(glyphIndex);
|
|
return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
|
|
}
|
|
|
|
#endif // QT_NO_RAWFONT
|
|
|
|
QT_END_NAMESPACE
|