qpf2.cpp
来自「奇趣公司比较新的qt/emd版本」· C++ 代码 · 共 759 行 · 第 1/2 页
CPP
759 行
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the tools applications of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qpf2.h"#include <math.h>#include <private/qfontengine_p.h>#include <QFile>#include <qendian.h>#include "../../src/gui/text/qpfutil.cpp"int QPF::debugVerbosity = 0;// ### copied from qfontdatabase.cpp// see the Unicode subset bitfields in the MSDN docsstatic int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = { // Any, { 127, 127 }, // Latin, { 0, 127 }, // Greek, { 7, 127 }, // Cyrillic, { 9, 127 }, // Armenian, { 10, 127 }, // Hebrew, { 11, 127 }, // Arabic, { 13, 127 }, // Syriac, { 71, 127 }, //Thaana, { 72, 127 }, //Devanagari, { 15, 127 }, //Bengali, { 16, 127 }, //Gurmukhi, { 17, 127 }, //Gujarati, { 18, 127 }, //Oriya, { 19, 127 }, //Tamil, { 20, 127 }, //Telugu, { 21, 127 }, //Kannada, { 22, 127 }, //Malayalam, { 23, 127 }, //Sinhala, { 73, 127 }, //Thai, { 24, 127 }, //Lao, { 25, 127 }, //Tibetan, { 70, 127 }, //Myanmar, { 74, 127 }, // Georgian, { 26, 127 }, // Khmer, { 80, 127 }, // SimplifiedChinese, { 126, 127 }, // TraditionalChinese, { 126, 127 }, // Japanese, { 126, 127 }, // Korean, { 56, 127 }, // Vietnamese, { 0, 127 }, // same as latin1 // Other, { 126, 127 }};#define SimplifiedChineseCsbBit 18#define TraditionalChineseCsbBit 20#define JapaneseCsbBit 17#define KoreanCsbBit 21static QList<QFontDatabase::WritingSystem> determineWritingSystemsFromTrueTypeBits(quint32 unicodeRange[4], quint32 codePageRange[2]){ QList<QFontDatabase::WritingSystem> writingSystems; bool hasScript = false; int i; for(i = 0; i < QFontDatabase::WritingSystemsCount; i++) { int bit = requiredUnicodeBits[i][0]; int index = bit/32; int flag = 1 << (bit&31); if (bit != 126 && unicodeRange[index] & flag) { bit = requiredUnicodeBits[i][1]; index = bit/32; flag = 1 << (bit&31); if (bit == 127 || unicodeRange[index] & flag) { writingSystems.append(QFontDatabase::WritingSystem(i)); hasScript = true; // qDebug("font %s: index=%d, flag=%8x supports script %d", familyName.latin1(), index, flag, i); } } } if(codePageRange[0] & (1 << SimplifiedChineseCsbBit)) { writingSystems.append(QFontDatabase::SimplifiedChinese); hasScript = true; //qDebug("font %s supports Simplified Chinese", familyName.latin1()); } if(codePageRange[0] & (1 << TraditionalChineseCsbBit)) { writingSystems.append(QFontDatabase::TraditionalChinese); hasScript = true; //qDebug("font %s supports Traditional Chinese", familyName.latin1()); } if(codePageRange[0] & (1 << JapaneseCsbBit)) { writingSystems.append(QFontDatabase::Japanese); hasScript = true; //qDebug("font %s supports Japanese", familyName.latin1()); } if(codePageRange[0] & (1 << KoreanCsbBit)) { writingSystems.append(QFontDatabase::Korean); hasScript = true; //qDebug("font %s supports Korean", familyName.latin1()); } if (!hasScript) writingSystems.append(QFontDatabase::Symbol); return writingSystems;}static QByteArray getWritingSystems(QFontEngine *fontEngine){ QByteArray os2Table = fontEngine->getSfntTable(MAKE_TAG('O', 'S', '/', '2')); if (os2Table.isEmpty()) return QByteArray(); const uchar *data = reinterpret_cast<const uchar *>(os2Table.constData()); quint32 unicodeRange[4] = { qFromBigEndian<quint32>(data + 42), qFromBigEndian<quint32>(data + 46), qFromBigEndian<quint32>(data + 50), qFromBigEndian<quint32>(data + 54) }; quint32 codePageRange[2] = { qFromBigEndian<quint32>(data + 78), qFromBigEndian<quint32>(data + 82) }; QList<QFontDatabase::WritingSystem> systems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange); QByteArray bitField((QFontDatabase::WritingSystemsCount + 7) / 8, 0); for (int i = 0; i < systems.count(); ++i) { int bitPos = systems.at(i); bitField[bitPos / 8] = bitField.at(bitPos / 8) | (1 << (bitPos % 8)); } return bitField;}static QString stringify(const QByteArray &bits){ QString result; for (int i = 0; i < bits.count(); ++i) { uchar currentByte = bits.at(i); for (int j = 0; j < 8; ++j) { if (currentByte & 1) result += '1'; else result += '0'; currentByte >>= 1; } } return result;}static void dumpWritingSystems(const QByteArray &bits){ QStringList writingSystems; QString bitString = stringify(bits); for (int i = 0; i < qMin(int(QFontDatabase::WritingSystemsCount), bitString.length()); ++i) { if (bitString.at(i) == QLatin1Char('1')) writingSystems << QFontDatabase::writingSystemName(QFontDatabase::WritingSystem(i)); } qDebug() << "Supported writing systems:" << writingSystems;}static const char *headerTagNames[QFontEngineQPF::NumTags] = { "FontName", "FileName", "FileIndex", "FontRevision", "FreeText", "Ascent", "Descent", "Leading", "XHeight", "AverageCharWidth", "MaxCharWidth", "LineThickness", "MinLeftBearing", "MinRightBearing", "UnderlinePosition", "GlyphFormat", "PixelSize", "Weight", "Style", "EndOfHeader", "WritingSystems"};QString QPF::fileNameForFont(const QFont &f){ QString fileName = f.family().toLower() + "_" + QString::number(f.pixelSize()) + "_" + QString::number(f.weight()) + (f.italic() ? "_italic" : "") + ".qpf2"; fileName.replace(QLatin1Char(' '), QLatin1Char('_')); return fileName;}QByteArray QPF::generate(const QFont &font, int options, const QList<CharacterRange> &ranges, QString *originalFontFile){ QTextEngine engine("Test", font); engine.itemize(); engine.shape(0); QFontEngine *fontEngine = engine.fontEngine(engine.layoutData->items[0]); if (fontEngine->type() == QFontEngine::Multi) fontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(0); if (originalFontFile) *originalFontFile = QFile::decodeName(fontEngine->faceId().filename); return generate(fontEngine, options, ranges);}QByteArray QPF::generate(QFontEngine *fontEngine, int options, const QList<CharacterRange> &ranges){ QPF font; font.options = options; font.addHeader(fontEngine); if (options & IncludeCMap) font.addCMap(fontEngine); font.addGlyphs(fontEngine, ranges); return font.qpf;}void QPF::addHeader(QFontEngine *fontEngine){ QFontEngineQPF::Header *header = reinterpret_cast<QFontEngineQPF::Header *>(addBytes(sizeof(QFontEngineQPF::Header))); header->magic[0] = 'Q'; header->magic[1] = 'P'; header->magic[2] = 'F'; header->magic[3] = '2'; if (options & RenderGlyphs) header->lock = 0xffffffff; else header->lock = 0; header->majorVersion = QFontEngineQPF::CurrentMajorVersion; header->minorVersion = QFontEngineQPF::CurrentMinorVersion; header->dataSize = 0; int oldSize = qpf.size(); addTaggedString(QFontEngineQPF::Tag_FontName, fontEngine->fontDef.family.toUtf8()); QFontEngine::FaceId face = fontEngine->faceId(); addTaggedString(QFontEngineQPF::Tag_FileName, face.filename); addTaggedUInt32(QFontEngineQPF::Tag_FileIndex, face.index); { const QByteArray head = fontEngine->getSfntTable(MAKE_TAG('h', 'e', 'a', 'd')); const quint32 revision = qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(head.constData()) + 4); addTaggedUInt32(QFontEngineQPF::Tag_FontRevision, revision); } addTaggedQFixed(QFontEngineQPF::Tag_Ascent, fontEngine->ascent()); addTaggedQFixed(QFontEngineQPF::Tag_Descent, fontEngine->descent()); addTaggedQFixed(QFontEngineQPF::Tag_Leading, fontEngine->leading()); addTaggedQFixed(QFontEngineQPF::Tag_XHeight, fontEngine->xHeight()); addTaggedQFixed(QFontEngineQPF::Tag_AverageCharWidth, fontEngine->averageCharWidth()); addTaggedQFixed(QFontEngineQPF::Tag_MaxCharWidth, QFixed::fromReal(fontEngine->maxCharWidth())); addTaggedQFixed(QFontEngineQPF::Tag_LineThickness, fontEngine->lineThickness()); addTaggedQFixed(QFontEngineQPF::Tag_MinLeftBearing, QFixed::fromReal(fontEngine->minLeftBearing())); addTaggedQFixed(QFontEngineQPF::Tag_MinRightBearing, QFixed::fromReal(fontEngine->minRightBearing())); addTaggedQFixed(QFontEngineQPF::Tag_UnderlinePosition, fontEngine->underlinePosition()); addTaggedUInt8(QFontEngineQPF::Tag_PixelSize, fontEngine->fontDef.pixelSize); addTaggedUInt8(QFontEngineQPF::Tag_Weight, fontEngine->fontDef.weight); addTaggedUInt8(QFontEngineQPF::Tag_Style, fontEngine->fontDef.style); QByteArray writingSystemBitField = getWritingSystems(fontEngine); if (!writingSystemBitField.isEmpty()) addTaggedString(QFontEngineQPF::Tag_WritingSystems, writingSystemBitField); addTaggedUInt8(QFontEngineQPF::Tag_GlyphFormat, QFontEngineQPF::AlphamapGlyphs); addTaggedString(QFontEngineQPF::Tag_EndOfHeader, QByteArray()); align4(); header = reinterpret_cast<QFontEngineQPF::Header *>(qpf.data()); header->dataSize = qToBigEndian<quint16>(qpf.size() - oldSize);}static uchar *appendBytes(QByteArray &array, int size){ int oldSize = array.size(); array.resize(array.size() + size); return reinterpret_cast<uchar *>(array.data() + oldSize);}#define APPEND(type, value) \ qToBigEndian<type>(value, appendBytes(cmap, sizeof(type)))struct CMapSegment{ int start; // codepoints int end; int startGlyphIndex;};static QByteArray generateTrueTypeCMap(QFontEngine *fe){ QByteArray cmap; const int glyphCount = fe->glyphCount(); if (!glyphCount) return cmap; // cmap header APPEND(quint16, 0); // table version number APPEND(quint16, 1); // number of tables // encoding record APPEND(quint16, 3); // platform-id APPEND(quint16, 10); // encoding-id (ucs-4) const int cmapOffset = cmap.size() + sizeof(quint32); APPEND(quint32, cmapOffset); // offset to sub-table APPEND(quint16, 4); // subtable format const int cmapTableLengthOffset = cmap.size(); APPEND(quint16, 0); // length in bytes, will fill in later APPEND(quint16, 0); // language field QList<CMapSegment> segments;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?