Remove the QPF2 font engine

The QPF2 font engine has been kept around for compatibility
reasons in Qt 5.x, and it is time for it to retire for now. If
we want something like this in the future, we can revive it with
hardware acceleration / Qt Quick as one of the primary use cases,
but for now, it seems that Freetype and our existing caching is
sufficient also for low-end use cases.

[ChangeLog][QtGui][Text] Removed support for the legacy QPF2 font
format as well as the makeqpf tool used to generate those files.

Change-Id: Id43039c92fe5bd95b628cd769e045c029f39a350
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2020-08-20 14:54:39 +02:00
parent 75097c7782
commit f70b955ce8
9 changed files with 7 additions and 945 deletions

1
.gitignore vendored
View File

@ -75,7 +75,6 @@ qt*-config.pri
/bin/linguist
/bin/lrelease
/bin/lupdate
/bin/makeqpf
/bin/moc
/bin/patternist
/bin/phonon

View File

@ -166,7 +166,6 @@ qt_add_module(Gui
text/qfont.cpp text/qfont.h text/qfont_p.h
text/qfontdatabase.cpp text/qfontdatabase.h text/qfontdatabase_p.h
text/qfontengine.cpp text/qfontengine_p.h
text/qfontengine_qpf2.cpp
text/qfontengineglyphcache.cpp text/qfontengineglyphcache_p.h
text/qfontinfo.h
text/qfontmetrics.cpp text/qfontmetrics.h

View File

@ -217,7 +217,6 @@ qt_add_module(Gui
text/qfont.cpp text/qfont.h text/qfont_p.h
text/qfontdatabase.cpp text/qfontdatabase.h text/qfontdatabase_p.h
text/qfontengine.cpp text/qfontengine_p.h
text/qfontengine_qpf2.cpp
text/qfontengineglyphcache.cpp text/qfontengineglyphcache_p.h
text/qfontinfo.h
text/qfontmetrics.cpp text/qfontmetrics.h

View File

@ -58,8 +58,6 @@ class Q_GUI_EXPORT QFontDatabase
{
Q_GADGET
public:
// do not re-order or delete entries from this enum without updating the
// QPF2 format and makeqpf!!
enum WritingSystem {
Any,

View File

@ -1,626 +0,0 @@
/****************************************************************************
**
** 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 "qfontengine_qpf2_p.h"
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QDir>
#include <QtCore/QBuffer>
#include <QtCore/private/qstringiterator_p.h>
#include <QtCore/private/qduplicatetracker_p.h>
#include <QtGui/private/qpaintengine_raster_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformfontdatabase.h>
#include <qpa/qplatformintegration.h>
QT_BEGIN_NAMESPACE
//#define DEBUG_HEADER
//#define DEBUG_FONTENGINE
static const QFontEngineQPF2::TagType tagTypes[QFontEngineQPF2::NumTags] = {
QFontEngineQPF2::StringType, // FontName
QFontEngineQPF2::StringType, // FileName
QFontEngineQPF2::UInt32Type, // FileIndex
QFontEngineQPF2::UInt32Type, // FontRevision
QFontEngineQPF2::StringType, // FreeText
QFontEngineQPF2::FixedType, // Ascent
QFontEngineQPF2::FixedType, // Descent
QFontEngineQPF2::FixedType, // Leading
QFontEngineQPF2::FixedType, // XHeight
QFontEngineQPF2::FixedType, // AverageCharWidth
QFontEngineQPF2::FixedType, // MaxCharWidth
QFontEngineQPF2::FixedType, // LineThickness
QFontEngineQPF2::FixedType, // MinLeftBearing
QFontEngineQPF2::FixedType, // MinRightBearing
QFontEngineQPF2::FixedType, // UnderlinePosition
QFontEngineQPF2::UInt8Type, // GlyphFormat
QFontEngineQPF2::UInt8Type, // PixelSize
QFontEngineQPF2::UInt8Type, // Weight
QFontEngineQPF2::UInt8Type, // Style
QFontEngineQPF2::StringType, // EndOfHeader
QFontEngineQPF2::BitFieldType// WritingSystems
};
#if defined(DEBUG_HEADER)
# define DEBUG_VERIFY qDebug
#else
# define DEBUG_VERIFY if (0) qDebug
#endif
#define READ_VERIFY(type, variable) \
if (tagPtr + sizeof(type) > endPtr) { \
DEBUG_VERIFY() << "read verify failed in line" << __LINE__; \
return nullptr; \
} \
variable = qFromBigEndian<type>(tagPtr); \
DEBUG_VERIFY() << "read value" << variable << "of type " #type; \
tagPtr += sizeof(type)
template <typename T>
T readValue(const uchar *&data)
{
T value = qFromBigEndian<T>(data);
data += sizeof(T);
return value;
}
#define VERIFY(condition) \
if (!(condition)) { \
DEBUG_VERIFY() << "condition " #condition " failed in line" << __LINE__; \
return 0; \
}
#define VERIFY_TAG(condition) \
if (!(condition)) { \
DEBUG_VERIFY() << "verifying tag condition " #condition " failed in line" << __LINE__ << "with tag" << tag; \
return nullptr; \
}
static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr)
{
quint16 tag, length;
READ_VERIFY(quint16, tag);
READ_VERIFY(quint16, length);
if (tag == QFontEngineQPF2::Tag_EndOfHeader)
return endPtr;
if (tag < QFontEngineQPF2::NumTags) {
switch (tagTypes[tag]) {
case QFontEngineQPF2::BitFieldType:
case QFontEngineQPF2::StringType:
// can't do anything...
break;
case QFontEngineQPF2::UInt32Type:
VERIFY_TAG(length == sizeof(quint32));
break;
case QFontEngineQPF2::FixedType:
VERIFY_TAG(length == sizeof(quint32));
break;
case QFontEngineQPF2::UInt8Type:
VERIFY_TAG(length == sizeof(quint8));
break;
}
#if defined(DEBUG_HEADER)
if (length == 1)
qDebug() << "tag data" << Qt::hex << *tagPtr;
else if (length == 4)
qDebug() << "tag data" << Qt::hex << tagPtr[0] << tagPtr[1] << tagPtr[2] << tagPtr[3];
#endif
}
return tagPtr + length;
}
const QFontEngineQPF2::Glyph *QFontEngineQPF2::findGlyph(glyph_t g) const
{
if (!g || g >= glyphMapEntries)
return nullptr;
const quint32 *gmapPtr = reinterpret_cast<const quint32 *>(fontData + glyphMapOffset);
quint32 glyphPos = qFromBigEndian<quint32>(gmapPtr[g]);
if (glyphPos > glyphDataSize) {
if (glyphPos == 0xffffffff)
return nullptr;
#if defined(DEBUG_FONTENGINE)
qDebug() << "glyph" << g << "outside of glyphData, remapping font file";
#endif
if (glyphPos > glyphDataSize)
return nullptr;
}
return reinterpret_cast<const Glyph *>(fontData + glyphDataOffset + glyphPos);
}
bool QFontEngineQPF2::verifyHeader(const uchar *data, int size)
{
VERIFY(quintptr(data) % alignof(Header) == 0);
VERIFY(size >= int(sizeof(Header)));
const Header *header = reinterpret_cast<const Header *>(data);
if (header->magic[0] != 'Q'
|| header->magic[1] != 'P'
|| header->magic[2] != 'F'
|| header->magic[3] != '2')
return false;
VERIFY(header->majorVersion <= CurrentMajorVersion);
const quint16 dataSize = qFromBigEndian<quint16>(header->dataSize);
VERIFY(size >= int(sizeof(Header)) + dataSize);
const uchar *tagPtr = data + sizeof(Header);
const uchar *tagEndPtr = tagPtr + dataSize;
while (tagPtr < tagEndPtr - 3) {
tagPtr = verifyTag(tagPtr, tagEndPtr);
VERIFY(tagPtr);
}
VERIFY(tagPtr <= tagEndPtr);
return true;
}
QVariant QFontEngineQPF2::extractHeaderField(const uchar *data, HeaderTag requestedTag)
{
const Header *header = reinterpret_cast<const Header *>(data);
const uchar *tagPtr = data + sizeof(Header);
const uchar *endPtr = tagPtr + qFromBigEndian<quint16>(header->dataSize);
while (tagPtr < endPtr - 3) {
quint16 tag = readValue<quint16>(tagPtr);
quint16 length = readValue<quint16>(tagPtr);
if (tag == requestedTag) {
switch (tagTypes[requestedTag]) {
case StringType:
return QVariant(QString::fromUtf8(reinterpret_cast<const char *>(tagPtr), length));
case UInt32Type:
return QVariant(readValue<quint32>(tagPtr));
case UInt8Type:
return QVariant(uint(*tagPtr));
case FixedType:
return QVariant(QFixed::fromFixed(readValue<quint32>(tagPtr)).toReal());
case BitFieldType:
return QVariant(QByteArray(reinterpret_cast<const char *>(tagPtr), length));
}
return QVariant();
} else if (tag == Tag_EndOfHeader) {
break;
}
tagPtr += length;
}
return QVariant();
}
QFontEngineQPF2::QFontEngineQPF2(const QFontDef &def, const QByteArray &data)
: QFontEngine(QPF2),
fontData(reinterpret_cast<const uchar *>(data.constData())), dataSize(data.size())
{
fontDef = def;
cache_cost = 100;
cmap = nullptr;
cmapOffset = 0;
cmapSize = 0;
glyphMapOffset = 0;
glyphMapEntries = 0;
glyphDataOffset = 0;
glyphDataSize = 0;
kerning_pairs_loaded = false;
readOnly = true;
#if defined(DEBUG_FONTENGINE)
qDebug() << "QFontEngineQPF2::QFontEngineQPF2( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ')';
#endif
if (!verifyHeader(fontData, dataSize)) {
#if defined(DEBUG_FONTENGINE)
qDebug("verifyHeader failed!");
#endif
return;
}
const Header *header = reinterpret_cast<const Header *>(fontData);
readOnly = (header->lock == 0xffffffff);
const uchar *imgData = fontData + sizeof(Header) + qFromBigEndian<quint16>(header->dataSize);
const uchar *endPtr = fontData + dataSize;
while (imgData <= endPtr - 8) {
quint16 blockTag = readValue<quint16>(imgData);
imgData += 2; // skip padding
quint32 blockSize = readValue<quint32>(imgData);
if (blockTag == CMapBlock) {
cmapOffset = imgData - fontData;
cmapSize = blockSize;
} else if (blockTag == GMapBlock) {
glyphMapOffset = imgData - fontData;
glyphMapEntries = blockSize / 4;
} else if (blockTag == GlyphBlock) {
glyphDataOffset = imgData - fontData;
glyphDataSize = blockSize;
}
imgData += blockSize;
}
face_id.filename = QFile::encodeName(extractHeaderField(fontData, Tag_FileName).toString());
face_id.index = extractHeaderField(fontData, Tag_FileIndex).toInt();
// get the real cmap
if (cmapOffset) {
cmap = QFontEngine::getCMap(fontData + cmapOffset, cmapSize, &symbol, &cmapSize);
cmapOffset = cmap ? cmap - fontData : 0;
}
// verify all the positions in the glyphMap
if (glyphMapOffset) {
const quint32 *gmapPtr = reinterpret_cast<const quint32 *>(fontData + glyphMapOffset);
for (uint i = 0; i < glyphMapEntries; ++i) {
quint32 glyphDataPos = qFromBigEndian<quint32>(gmapPtr[i]);
if (glyphDataPos == 0xffffffff)
continue;
if (glyphDataPos >= glyphDataSize) {
// error
glyphMapOffset = 0;
glyphMapEntries = 0;
break;
}
}
}
#if defined(DEBUG_FONTENGINE)
if (!isValid())
qDebug() << "fontData" << fontData << "dataSize" << dataSize
<< "cmap" << cmap << "cmapOffset" << cmapOffset
<< "glyphMapOffset" << glyphMapOffset << "glyphDataOffset" << glyphDataOffset
<< "fd" << fd << "glyphDataSize" << glyphDataSize;
#endif
}
QFontEngineQPF2::~QFontEngineQPF2()
{
}
bool QFontEngineQPF2::getSfntTableData(uint tag, uchar *buffer, uint *length) const
{
if (tag != MAKE_TAG('c', 'm', 'a', 'p') || !cmap)
return false;
if (buffer && int(*length) >= cmapSize)
memcpy(buffer, cmap, cmapSize);
*length = cmapSize;
Q_ASSERT(int(*length) > 0);
return true;
}
glyph_t QFontEngineQPF2::glyphIndex(uint ucs4) const
{
glyph_t glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
if (glyph == 0 && symbol && ucs4 < 0x100)
glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000);
if (!findGlyph(glyph))
glyph = 0;
return glyph;
}
bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const
{
Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
if (*nglyphs < len) {
*nglyphs = len;
return false;
}
#if defined(DEBUG_FONTENGINE)
QDuplicateTracker<QChar> seenGlyphs;
#endif
int glyph_pos = 0;
if (symbol) {
QStringIterator it(str, str + len);
while (it.hasNext()) {
const uint uc = it.next();
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
if(!glyphs->glyphs[glyph_pos] && uc < 0x100)
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
++glyph_pos;
}
} else {
QStringIterator it(str, str + len);
while (it.hasNext()) {
const uint uc = it.next();
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
#if 0 && defined(DEBUG_FONTENGINE)
QChar c(uc);
if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.hasSeen(c))
qDebug() << "glyph for character" << c << '/' << Qt::hex << uc << "is" << Qt::dec << glyphs[glyph_pos].glyph;
#endif
++glyph_pos;
}
}
*nglyphs = glyph_pos;
glyphs->numGlyphs = glyph_pos;
if (!(flags & GlyphIndicesOnly))
recalcAdvances(glyphs, flags);
return true;
}
void QFontEngineQPF2::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const
{
for (int i = 0; i < glyphs->numGlyphs; ++i) {
const Glyph *g = findGlyph(glyphs->glyphs[i]);
if (!g)
continue;
glyphs->advances[i] = g->advance;
}
}
QImage QFontEngineQPF2::alphaMapForGlyph(glyph_t g)
{
const Glyph *glyph = findGlyph(g);
if (!glyph)
return QImage();
const uchar *bits = ((const uchar *) glyph) + sizeof(Glyph);
QImage image(bits,glyph->width, glyph->height, glyph->bytesPerLine, QImage::Format_Alpha8);
return image;
}
void QFontEngineQPF2::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
{
addBitmapFontToPath(x, y, glyphs, path, flags);
}
glyph_metrics_t QFontEngineQPF2::boundingBox(const QGlyphLayout &glyphs)
{
glyph_metrics_t overall;
// initialize with line height, we get the same behaviour on all platforms
overall.y = -ascent();
overall.height = ascent() + descent() + 1;
QFixed ymax = 0;
QFixed xmax = 0;
for (int i = 0; i < glyphs.numGlyphs; i++) {
const Glyph *g = findGlyph(glyphs.glyphs[i]);
if (!g)
continue;
QFixed x = overall.xoff + glyphs.offsets[i].x + g->x;
QFixed y = overall.yoff + glyphs.offsets[i].y + g->y;
overall.x = qMin(overall.x, x);
overall.y = qMin(overall.y, y);
xmax = qMax(xmax, x + g->width);
ymax = qMax(ymax, y + g->height);
overall.xoff += g->advance;
}
overall.height = qMax(overall.height, ymax - overall.y);
overall.width = xmax - overall.x;
return overall;
}
glyph_metrics_t QFontEngineQPF2::boundingBox(glyph_t glyph)
{
glyph_metrics_t overall;
const Glyph *g = findGlyph(glyph);
if (!g)
return overall;
overall.x = g->x;
overall.y = g->y;
overall.width = g->width;
overall.height = g->height;
overall.xoff = g->advance;
return overall;
}
QFixed QFontEngineQPF2::ascent() const
{
return QFixed::fromReal(qvariant_cast<qreal>(extractHeaderField(fontData, Tag_Ascent)));
}
QFixed QFontEngineQPF2::capHeight() const
{
return calculatedCapHeight();
}
QFixed QFontEngineQPF2::descent() const
{
return QFixed::fromReal(qvariant_cast<qreal>(extractHeaderField(fontData, Tag_Descent)));
}
QFixed QFontEngineQPF2::leading() const
{
return QFixed::fromReal(qvariant_cast<qreal>(extractHeaderField(fontData, Tag_Leading)));
}
qreal QFontEngineQPF2::maxCharWidth() const
{
return qvariant_cast<qreal>(extractHeaderField(fontData, Tag_MaxCharWidth));
}
qreal QFontEngineQPF2::minLeftBearing() const
{
return qvariant_cast<qreal>(extractHeaderField(fontData, Tag_MinLeftBearing));
}
qreal QFontEngineQPF2::minRightBearing() const
{
return qvariant_cast<qreal>(extractHeaderField(fontData, Tag_MinRightBearing));
}
QFixed QFontEngineQPF2::underlinePosition() const
{
return QFixed::fromReal(qvariant_cast<qreal>(extractHeaderField(fontData, Tag_UnderlinePosition)));
}
QFixed QFontEngineQPF2::lineThickness() const
{
return QFixed::fromReal(qvariant_cast<qreal>(extractHeaderField(fontData, Tag_LineThickness)));
}
bool QFontEngineQPF2::isValid() const
{
return fontData && dataSize && cmapOffset
&& glyphMapOffset && glyphDataOffset && glyphDataSize > 0;
}
void QPF2Generator::generate()
{
writeHeader();
writeGMap();
writeBlock(QFontEngineQPF2::GlyphBlock, QByteArray());
dev->seek(4); // position of header.lock
writeUInt32(0);
}
void QPF2Generator::writeHeader()
{
QFontEngineQPF2::Header header;
header.magic[0] = 'Q';
header.magic[1] = 'P';
header.magic[2] = 'F';
header.magic[3] = '2';
header.lock = 1;
header.majorVersion = QFontEngineQPF2::CurrentMajorVersion;
header.minorVersion = QFontEngineQPF2::CurrentMinorVersion;
header.dataSize = 0;
dev->write((const char *)&header, sizeof(header));
writeTaggedString(QFontEngineQPF2::Tag_FontName, fe->fontDef.family.toUtf8());
QFontEngine::FaceId face = fe->faceId();
writeTaggedString(QFontEngineQPF2::Tag_FileName, face.filename);
writeTaggedUInt32(QFontEngineQPF2::Tag_FileIndex, face.index);
{
const QByteArray head = fe->getSfntTable(MAKE_TAG('h', 'e', 'a', 'd'));
if (head.size() >= 4) {
const quint32 revision = qFromBigEndian<quint32>(head.constData());
writeTaggedUInt32(QFontEngineQPF2::Tag_FontRevision, revision);
}
}
writeTaggedQFixed(QFontEngineQPF2::Tag_Ascent, fe->ascent());
writeTaggedQFixed(QFontEngineQPF2::Tag_Descent, fe->descent());
writeTaggedQFixed(QFontEngineQPF2::Tag_Leading, fe->leading());
writeTaggedQFixed(QFontEngineQPF2::Tag_XHeight, fe->xHeight());
writeTaggedQFixed(QFontEngineQPF2::Tag_AverageCharWidth, fe->averageCharWidth());
writeTaggedQFixed(QFontEngineQPF2::Tag_MaxCharWidth, QFixed::fromReal(fe->maxCharWidth()));
writeTaggedQFixed(QFontEngineQPF2::Tag_LineThickness, fe->lineThickness());
writeTaggedQFixed(QFontEngineQPF2::Tag_MinLeftBearing, QFixed::fromReal(fe->minLeftBearing()));
writeTaggedQFixed(QFontEngineQPF2::Tag_MinRightBearing, QFixed::fromReal(fe->minRightBearing()));
writeTaggedQFixed(QFontEngineQPF2::Tag_UnderlinePosition, fe->underlinePosition());
writeTaggedUInt8(QFontEngineQPF2::Tag_PixelSize, fe->fontDef.pixelSize);
writeTaggedUInt8(QFontEngineQPF2::Tag_Weight, fe->fontDef.weight);
writeTaggedUInt8(QFontEngineQPF2::Tag_Style, fe->fontDef.style);
writeTaggedUInt8(QFontEngineQPF2::Tag_GlyphFormat, QFontEngineQPF2::AlphamapGlyphs);
writeTaggedString(QFontEngineQPF2::Tag_EndOfHeader, QByteArray());
align4();
const quint64 size = dev->pos();
header.dataSize = qToBigEndian<quint16>(size - sizeof(header));
dev->seek(0);
dev->write((const char *)&header, sizeof(header));
dev->seek(size);
}
void QPF2Generator::writeGMap()
{
const quint16 glyphCount = fe->glyphCount();
writeUInt16(QFontEngineQPF2::GMapBlock);
writeUInt16(0); // padding
writeUInt32(glyphCount * 4);
QByteArray &buffer = dev->buffer();
const int numBytes = glyphCount * sizeof(quint32);
qint64 pos = buffer.size();
buffer.resize(pos + numBytes);
memset(buffer.data() + pos, 0xff, numBytes);
dev->seek(pos + numBytes);
}
void QPF2Generator::writeBlock(QFontEngineQPF2::BlockTag tag, const QByteArray &data)
{
writeUInt16(tag);
writeUInt16(0); // padding
const int padSize = ((data.size() + 3) / 4) * 4 - data.size();
writeUInt32(data.size() + padSize);
dev->write(data);
for (int i = 0; i < padSize; ++i)
writeUInt8(0);
}
void QPF2Generator::writeTaggedString(QFontEngineQPF2::HeaderTag tag, const QByteArray &string)
{
writeUInt16(tag);
writeUInt16(string.length());
dev->write(string);
}
void QPF2Generator::writeTaggedUInt32(QFontEngineQPF2::HeaderTag tag, quint32 value)
{
writeUInt16(tag);
writeUInt16(sizeof(value));
writeUInt32(value);
}
void QPF2Generator::writeTaggedUInt8(QFontEngineQPF2::HeaderTag tag, quint8 value)
{
writeUInt16(tag);
writeUInt16(sizeof(value));
writeUInt8(value);
}
void QPF2Generator::writeTaggedQFixed(QFontEngineQPF2::HeaderTag tag, QFixed value)
{
writeUInt16(tag);
writeUInt16(sizeof(quint32));
writeUInt32(value.value());
}
QT_END_NAMESPACE

View File

@ -1,241 +0,0 @@
/****************************************************************************
**
** 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$
**
****************************************************************************/
#ifndef QFONTENGINE_QPF2_P_H
#define QFONTENGINE_QPF2_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qconfig.h>
#include <QtCore/qglobal.h>
#include <QtCore/qendian.h>
#include <QtCore/QBuffer>
#include "qfontengine_p.h"
#include <QtCore/QFile>
QT_BEGIN_NAMESPACE
class QFontEngine;
class QFreetypeFace;
class QBuffer;
class Q_GUI_EXPORT QFontEngineQPF2 : public QFontEngine
{
public:
// if you add new tags please make sure to update the tables in
// qpfutil.cpp and tools/makeqpf/qpf2.cpp
enum HeaderTag {
Tag_FontName, // 0 string
Tag_FileName, // 1 string
Tag_FileIndex, // 2 quint32
Tag_FontRevision, // 3 quint32
Tag_FreeText, // 4 string
Tag_Ascent, // 5 QFixed
Tag_Descent, // 6 QFixed
Tag_Leading, // 7 QFixed
Tag_XHeight, // 8 QFixed
Tag_AverageCharWidth, // 9 QFixed
Tag_MaxCharWidth, // 10 QFixed
Tag_LineThickness, // 11 QFixed
Tag_MinLeftBearing, // 12 QFixed
Tag_MinRightBearing, // 13 QFixed
Tag_UnderlinePosition, // 14 QFixed
Tag_GlyphFormat, // 15 quint8
Tag_PixelSize, // 16 quint8
Tag_Weight, // 17 quint8
Tag_Style, // 18 quint8
Tag_EndOfHeader, // 19 string
Tag_WritingSystems, // 20 bitfield
NumTags
};
enum TagType {
StringType,
FixedType,
UInt8Type,
UInt32Type,
BitFieldType
};
struct Tag
{
quint16 tag;
quint16 size;
};
enum GlyphFormat {
BitmapGlyphs = 1,
AlphamapGlyphs = 8
};
enum {
CurrentMajorVersion = 2,
CurrentMinorVersion = 0
};
// The CMap is identical to the TrueType CMap table format
// The GMap table is a normal array with the total number of
// covered glyphs in the TrueType font
enum BlockTag {
CMapBlock,
GMapBlock,
GlyphBlock
};
struct Header
{
char magic[4]; // 'QPF2'
quint32 lock; // values: 0 = unlocked, 0xffffffff = read-only, otherwise qws client id of locking process
quint8 majorVersion;
quint8 minorVersion;
quint16 dataSize;
};
struct Block
{
quint16 tag;
quint16 pad;
quint32 dataSize;
};
struct Glyph
{
quint8 width;
quint8 height;
quint8 bytesPerLine;
qint8 x;
qint8 y;
qint8 advance;
};
QFontEngineQPF2(const QFontDef &def, const QByteArray &data);
~QFontEngineQPF2();
FaceId faceId() const override { return face_id; }
bool getSfntTableData(uint tag, uchar *buffer, uint *length) const override;
virtual glyph_t glyphIndex(uint ucs4) const override;
bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
void recalcAdvances(QGlyphLayout *, ShaperFlags) const override;
void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) override;
QImage alphaMapForGlyph(glyph_t t) override;
glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override;
glyph_metrics_t boundingBox(glyph_t glyph) override;
QFixed ascent() const override;
QFixed capHeight() const override;
QFixed descent() const override;
QFixed leading() const override;
qreal maxCharWidth() const override;
qreal minLeftBearing() const override;
qreal minRightBearing() const override;
QFixed underlinePosition() const override;
QFixed lineThickness() const override;
virtual int glyphCount() const override { return glyphMapEntries; }
bool isValid() const;
const Glyph *findGlyph(glyph_t g) const;
static bool verifyHeader(const uchar *data, int size);
static QVariant extractHeaderField(const uchar *data, HeaderTag tag);
private:
const uchar *fontData;
int dataSize;
const uchar *cmap;
quint32 cmapOffset;
int cmapSize;
quint32 glyphMapOffset;
quint32 glyphMapEntries;
quint32 glyphDataOffset;
quint32 glyphDataSize;
QString internalFileName;
QString encodedFileName;
bool readOnly;
FaceId face_id;
QByteArray freetypeCMapTable;
mutable bool kerning_pairs_loaded;
};
struct QPF2Generator
{
QPF2Generator(QBuffer *device, QFontEngine *engine)
: dev(device), fe(engine) {}
void generate();
void writeHeader();
void writeGMap();
void writeBlock(QFontEngineQPF2::BlockTag tag, const QByteArray &data);
void writeTaggedString(QFontEngineQPF2::HeaderTag tag, const QByteArray &string);
void writeTaggedUInt32(QFontEngineQPF2::HeaderTag tag, quint32 value);
void writeTaggedUInt8(QFontEngineQPF2::HeaderTag tag, quint8 value);
void writeTaggedQFixed(QFontEngineQPF2::HeaderTag tag, QFixed value);
void writeUInt16(quint16 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); }
void writeUInt32(quint32 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); }
void writeUInt8(quint8 value) { dev->write((const char *)&value, sizeof(value)); }
void writeInt8(qint8 value) { dev->write((const char *)&value, sizeof(value)); }
void align4() { while (dev->pos() & 3) { dev->putChar('\0'); } }
QBuffer *dev;
QFontEngine *fe;
};
QT_END_NAMESPACE
#endif // QFONTENGINE_QPF2_P_H

View File

@ -39,7 +39,6 @@
#include "qplatformfontdatabase.h"
#include <QtGui/private/qfontengine_p.h>
#include <QtGui/private/qfontengine_qpf2_p.h>
#include <QtGui/private/qfontdatabase_p.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
@ -47,6 +46,7 @@
#include <QtCore/QLibraryInfo>
#include <QtCore/QDir>
#include <QtCore/QMetaEnum>
#include <QtCore/qendian.h>
#include <algorithm>
#include <iterator>
@ -65,48 +65,6 @@ void qt_registerFontFamily(const QString &familyName);
void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias);
bool qt_isFontFamilyPopulated(const QString &familyName);
/*!
Registers the pre-rendered QPF2 font contained in the given \a dataArray.
\sa registerFont()
*/
void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *handle)
{
if (dataArray.size() == 0)
return;
const uchar *data = reinterpret_cast<const uchar *>(dataArray.constData());
if (QFontEngineQPF2::verifyHeader(data, dataArray.size())) {
QString fontName = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_FontName).toString();
int pixelSize = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_PixelSize).toInt();
QVariant weight = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_Weight);
QVariant style = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_Style);
QByteArray writingSystemBits = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_WritingSystems).toByteArray();
if (!fontName.isEmpty() && pixelSize) {
QFont::Weight fontWeight = QFont::Normal;
if (weight.userType() == QMetaType::Int || weight.userType() == QMetaType::UInt)
fontWeight = QFont::Weight(weight.toInt());
QFont::Style fontStyle = static_cast<QFont::Style>(style.toInt());
QSupportedWritingSystems writingSystems;
for (int i = 0; i < writingSystemBits.count(); ++i) {
uchar currentByte = writingSystemBits.at(i);
for (int j = 0; j < 8; ++j) {
if (currentByte & 1)
writingSystems.setSupported(QFontDatabase::WritingSystem(i * 8 + j));
currentByte >>= 1;
}
}
QFont::Stretch stretch = QFont::Unstretched;
registerFont(fontName,QString(),QString(),fontWeight,fontStyle,stretch,true,false,pixelSize,false,writingSystems,handle);
}
} else {
qDebug("header verification of QPF2 font failed. maybe it is corrupt?");
}
}
/*!
Registers a font with the given set of attributes describing the font's
foundry, family name, style and stretch information, pixel size, and
@ -126,7 +84,7 @@ void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *
The writing systems supported by the font are specified by the
\a writingSystems argument.
\sa registerQPF2Font(), registerFontFamily()
\sa registerFontFamily()
*/
void QPlatformFontDatabase::registerFont(const QString &familyname, const QString &stylename,
const QString &foundryname, QFont::Weight weight,
@ -294,30 +252,10 @@ QPlatformFontDatabase::~QPlatformFontDatabase()
when the required family needs population. You then call registerFont() to
finish population of the family.
The default implementation looks in the fontDir() location and registers all
QPF2 fonts.
The default implementation does nothing.
*/
void QPlatformFontDatabase::populateFontDatabase()
{
QString fontpath = fontDir();
if(!QFile::exists(fontpath)) {
qWarning("QFontDatabase: Cannot find font directory '%s' - is Qt installed correctly?",
qPrintable(QDir::toNativeSeparators(fontpath)));
return;
}
QDir dir(fontpath);
dir.setNameFilters(QStringList() << QLatin1String("*.qpf2"));
dir.refresh();
for (int i = 0; i < int(dir.count()); ++i) {
const QByteArray fileName = QFile::encodeName(dir.absoluteFilePath(dir[i]));
QFile file(QString::fromLocal8Bit(fileName));
if (file.open(QFile::ReadOnly)) {
const QByteArray fileData = file.readAll();
QByteArray *fileDataPtr = new QByteArray(fileData);
registerQPF2Font(fileData, fileDataPtr);
}
}
}
/*!
@ -358,10 +296,10 @@ QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine
*/
QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
{
QByteArray *fileDataPtr = static_cast<QByteArray *>(handle);
QFontEngineQPF2 *engine = new QFontEngineQPF2(fontDef,*fileDataPtr);
//qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family;
return engine;
Q_UNUSED(fontDef);
Q_UNUSED(handle);
qWarning("This plugin does not support loading system fonts.");
return nullptr;
}
QFontEngine *QPlatformFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize,
@ -488,8 +426,6 @@ bool QPlatformFontDatabase::fontsAlwaysScalable() const
return ret;
}
// ### copied to tools/makeqpf/qpf2.cpp
// see the Unicode subset bitfields in the MSDN docs
static const quint8 requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
{ 127, 127 }, // Any

View File

@ -134,7 +134,6 @@ public:
static QFont::Weight weightFromInteger(int weight);
//callback
static void registerQPF2Font(const QByteArray &dataArray, void *handle);
static void registerFont(const QString &familyname, const QString &stylename,
const QString &foundryname, QFont::Weight weight,
QFont::Style style, QFont::Stretch stretch, bool antialiased,

View File

@ -75,7 +75,6 @@ SOURCES += \
text/qinputcontrol.cpp
SOURCES += \
text/qfontengine_qpf2.cpp \
text/qplatformfontdatabase.cpp
HEADERS += \