diff options
Diffstat (limited to 'src/gui/text/qfontengine_qpf2.cpp')
-rw-r--r-- | src/gui/text/qfontengine_qpf2.cpp | 626 |
1 files changed, 0 insertions, 626 deletions
diff --git a/src/gui/text/qfontengine_qpf2.cpp b/src/gui/text/qfontengine_qpf2.cpp deleted file mode 100644 index 7178ef2928..0000000000 --- a/src/gui/text/qfontengine_qpf2.cpp +++ /dev/null @@ -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 0; \ - } \ - 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 0; \ - } - -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 |