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 + -
显示快捷键?