⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qfontsubset.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    Q_ASSERT(!widths.isEmpty());    QFontEngine::Properties properties = fontEngine->properties();    QByteArray width;    QPdf::ByteStream s(&width);    QFixed scale = QFixed(1000)/emSquare;    QFixed defWidth = widths[0];    //qDebug("defWidth=%d, scale=%f", defWidth.toInt(), scale.toReal());    for (int i = 0; i < nGlyphs(); ++i) {        if (defWidth != widths[i])            defWidth = 0;    }    if (defWidth > 0) {        s << "/DW " << (defWidth*scale).toInt();    } else {        s << "/W [";        for (int g = 0; g < nGlyphs();) {            QFixed w = widths[g];            int start = g;            int startLinear = 0;            ++g;            while (g < nGlyphs()) {                QFixed nw = widths[g];                if (nw == w) {                if (!startLinear)                    startLinear = g - 1;                } else {                    if (startLinear > 0 && g - startLinear >= 10)                        break;                    startLinear = 0;                }                w = nw;                ++g;            }            // qDebug("start=%x startLinear=%x g-1=%x",start,startLinear,g-1);            if (g - startLinear < 10)                startLinear = 0;            int endnonlinear = startLinear ? startLinear : g;            // qDebug("    startLinear=%x endnonlinear=%x", startLinear,endnonlinear);            if (endnonlinear > start) {                s << start << "[";                for (int i = start; i < endnonlinear; ++i)                    s << (widths[i]*scale).toInt();                s << "]\n";            }            if (startLinear)                s << startLinear << g - 1 << (widths[startLinear]*scale).toInt() << "\n";        }        s << "]\n";    }    return width;}static void checkRanges(QPdf::ByteStream &ts, QByteArray &ranges, int &nranges){    if (++nranges > 100) {        ts << nranges << "beginbfrange\n"           << ranges << "endbfrange\n";        ranges = QByteArray();        nranges = 0;    }}QVector<int> QFontSubset::getReverseMap() const{    QVector<int> reverseMap;    reverseMap.resize(0x10000);    for (uint i = 0; i < 0x10000; ++i)        reverseMap[i] = 0;    QGlyphLayout glyphs[10];    for (uint uc = 0; uc < 0x10000; ++uc) {        QChar ch(uc);        int nglyphs = 10;        fontEngine->stringToCMap(&ch, 1, glyphs, &nglyphs, QTextEngine::GlyphIndicesOnly);        int idx = glyph_indices.indexOf(glyphs[0].glyph);        if (idx >= 0 && !reverseMap.at(idx))            reverseMap[idx] = uc;    }    return reverseMap;}QByteArray QFontSubset::createToUnicodeMap() const{    QVector<int> reverseMap = getReverseMap();    QByteArray touc;    QPdf::ByteStream ts(&touc);    ts << "/CIDInit /ProcSet findresource begin\n"        "12 dict begin\n"        "begincmap\n"        "/CIDSystemInfo << /Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def\n"        "/CMapName /Adobe-Identity-UCS def\n"        "/CMapType 2 def\n"        "1 begincodespacerange\n"        "<0000> <FFFF>\n"        "endcodespacerange\n";    int nranges = 1;    QByteArray ranges = "<0000> <0000> <0000>\n";    QPdf::ByteStream s(&ranges);    char buf[5];    for (int g = 1; g < nGlyphs(); ) {        int uc0 = reverseMap.at(g);        if (!uc0) {            ++g;            continue;        }        int start = g;        int startLinear = 0;        ++g;        while (g < nGlyphs()) {            int uc = reverseMap[g];            // cmaps can't have the high byte changing within one range, so we need to break on that as well            if (!uc || (g>>8) != (start >> 8))                break;            if (uc == uc0 + 1) {                if (!startLinear)                    startLinear = g - 1;            } else {                if (startLinear > 0 && g - startLinear >= 10)                    break;                startLinear = 0;            }            uc0 = uc;            ++g;        }        // qDebug("start=%x startLinear=%x g-1=%x",start,startLinear,g-1);        if (g - startLinear < 10)            startLinear = 0;        int endnonlinear = startLinear ? startLinear : g;        // qDebug("    startLinear=%x endnonlinear=%x", startLinear,endnonlinear);        if (endnonlinear > start) {            s << "<" << QPdf::toHex((ushort)start, buf) << "> <";            s << QPdf::toHex((ushort)(endnonlinear - 1), buf) << "> ";            if (endnonlinear == start + 1) {                s << "<" << QPdf::toHex((ushort)reverseMap[start], buf) << ">\n";            } else {                s << "[";                for (int i = start; i < endnonlinear; ++i) {                    s << "<" << QPdf::toHex((ushort)reverseMap[i], buf) << "> ";                }                s << "]\n";            }            checkRanges(ts, ranges, nranges);        }        if (startLinear) {            while (startLinear < g) {                int len = g - startLinear;                int uc_start = reverseMap[startLinear];                int uc_end = uc_start + len - 1;                if ((uc_end >> 8) != (uc_start >> 8))                    len = 256 - (uc_start & 0xff);                s << "<" << QPdf::toHex((ushort)startLinear, buf) << "> <";                s << QPdf::toHex((ushort)(startLinear + len - 1), buf) << "> ";                s << "<" << QPdf::toHex((ushort)reverseMap[startLinear], buf) << ">\n";                checkRanges(ts, ranges, nranges);                startLinear += len;            }        }    }    if (nranges) {        ts << nranges << "beginbfrange\n"           << ranges << "endbfrange\n";    }    ts << "endcmap\n"        "CMapName currentdict /CMap defineresource pop\n"        "end\n"        "end\n";    return touc;}int QFontSubset::addGlyph(int index){    int idx = glyph_indices.indexOf(index);    if (idx < 0) {        idx = glyph_indices.size();        glyph_indices.append(index);    }    return idx;}// ------------------------------ Truetype generation ----------------------------------------------typedef qint16 F2DOT14;typedef quint32 Tag;typedef quint16 GlyphID;typedef quint16 Offset;class QTtfStream {public:    QTtfStream(QByteArray &ba) : data((uchar *)ba.data()) { start = data; }    QTtfStream &operator <<(quint8 v) { *data = v; ++data; return *this; }    QTtfStream &operator <<(quint16 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }    QTtfStream &operator <<(quint32 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }    QTtfStream &operator <<(qint8 v) { *data = quint8(v); ++data; return *this; }    QTtfStream &operator <<(qint16 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }    QTtfStream &operator <<(qint32 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }    QTtfStream &operator <<(qint64 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }    int offset() const { return data - start; }    void setOffset(int o) { data = start + o; }    void align4() { while (offset() & 3) { *data = '\0'; ++data; } }private:    uchar *data;    uchar *start;};struct QTtfTable {    Tag tag;    QByteArray data;};Q_DECLARE_TYPEINFO(QTtfTable, Q_MOVABLE_TYPE);struct qttf_head_table {    qint32 font_revision;    quint16 flags;    qint64 created;    qint64 modified;    qint16 xMin;    qint16 yMin;    qint16 xMax;    qint16 yMax;    quint16 macStyle;    qint16 indexToLocFormat;};struct qttf_hhea_table {    qint16 ascender;    qint16 descender;    qint16 lineGap;    quint16 maxAdvanceWidth;    qint16 minLeftSideBearing;    qint16 minRightSideBearing;    qint16 xMaxExtent;    quint16 numberOfHMetrics;};struct qttf_maxp_table {    quint16 numGlyphs;    quint16 maxPoints;    quint16 maxContours;    quint16 maxCompositePoints;    quint16 maxCompositeContours;    quint16 maxComponentElements;    quint16 maxComponentDepth;};struct qttf_name_table {    QString copyright;    QString family;    QString subfamily;    QString postscript_name;};static QTtfTable generateHead(const qttf_head_table &head);static QTtfTable generateHhea(const qttf_hhea_table &hhea);static QTtfTable generateMaxp(const qttf_maxp_table &maxp);static QTtfTable generateName(const qttf_name_table &name);struct qttf_font_tables{    qttf_head_table head;    qttf_hhea_table hhea;    qttf_maxp_table maxp;};struct QTtfGlyph {    quint16 index;    qint16 xMin;    qint16 xMax;    qint16 yMin;    qint16 yMax;    quint16 advanceWidth;    qint16 lsb;    quint16 numContours;    quint16 numPoints;    QByteArray data;};Q_DECLARE_TYPEINFO(QTtfGlyph, Q_MOVABLE_TYPE);static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem);// generates glyf, loca and hmtxstatic QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QList<QTtfGlyph> &_glyphs);static QByteArray bindFont(const QList<QTtfTable>& _tables);static quint32 checksum(const QByteArray &table){    quint32 sum = 0;    int offset = 0;    const uchar *d = (uchar *)table.constData();    while (offset <= table.size()-3) {        sum += qFromBigEndian<quint32>(d + offset);        offset += 4;    }    int shift = 24;    quint32 x = 0;    while (offset < table.size()) {        x |= ((quint32)d[offset]) << shift;        ++offset;        shift -= 8;    }    sum += x;    return sum;}static QTtfTable generateHead(const qttf_head_table &head){    const int head_size = 54;    QTtfTable t;    t.tag = MAKE_TAG('h', 'e', 'a', 'd');    t.data.resize(head_size);    QTtfStream s(t.data);// qint32  Table version number  0x00010000 for version 1.0.// qint32  fontRevision  Set by font manufacturer.    s << qint32(0x00010000)      << head.font_revision// quint32  checkSumAdjustment  To compute: set it to 0, sum the entire font as quint32, then store 0xB1B0AFBA - sum.      << quint32(0)// quint32  magicNumber  Set to 0x5F0F3CF5.      << quint32(0x5F0F3CF5)// quint16  flags  Bit 0: Baseline for font at y=0;// Bit 1: Left sidebearing point at x=0;// Bit 2: Instructions may depend on point size;// Bit 3: Force ppem to integer values for all internal scaler math; may use fractional ppem sizes if this bit is clear;// Bit 4: Instructions may alter advance width (the advance widths might not scale linearly);// Bits 5-10: These should be set according to  Apple's specification . However, they are not implemented in OpenType.// Bit 11: Font data is 'lossless,' as a result of having been compressed and decompressed with the Agfa MicroType Express engine.// Bit 12: Font converted (produce compatible metrics)// Bit 13: Font optimised for ClearType// Bit 14: Reserved, set to 0// Bit 15: Reserved, set to 0

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -