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

📄 qfontsubset.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        }        case QPainterPath::CurveToDataElement:            Q_ASSERT(false);            break;        }//         qDebug() << "   appending oncurve point " << QPoint(p.x, p.y);        points->append(p);    }    int start = endPoints->size() ? endPoints->at(endPoints->size()-1) + 1 : 0;    int end = points->size() - 1;    if (points->at(end).x == points->at(start).x        && points->at(end).y == points->at(start).y)        points->takeLast();    endPoints->append(points->size() - 1);}static void getBounds(const QList<TTF_POINT> &points, qint16 *xmin, qint16 *xmax, qint16 *ymin, qint16 *ymax){    *xmin = points.at(0).x;    *xmax = *xmin;    *ymin = points.at(0).y;    *ymax = *ymin;    for (int i = 1; i < points.size(); ++i) {        *xmin = qMin(*xmin, points.at(i).x);        *xmax = qMax(*xmax, points.at(i).x);        *ymin = qMin(*ymin, points.at(i).y);        *ymax = qMax(*ymax, points.at(i).y);    }}static int convertToRelative(QList<TTF_POINT> *points){    // convert points to relative and setup flags//     qDebug() << "relative points:";    qint16 prev_x = 0;    qint16 prev_y = 0;    int point_array_size = 0;    for (int i = 0; i < points->size(); ++i) {        const int x = points->at(i).x;        const int y = points->at(i).y;        TTF_POINT rel;        rel.x = x - prev_x;        rel.y = y - prev_y;        rel.flags = points->at(i).flags;        Q_ASSERT(rel.flags < 2);        if (!rel.x) {            rel.flags |= XSame;        } else if (rel.x > 0 && rel.x < 256) {            rel.flags |= XShortVector|XShortPositive;            point_array_size++;        } else if (rel.x < 0 && rel.x > -256) {            rel.flags |= XShortVector;            rel.x = -rel.x;            point_array_size++;        } else {            point_array_size += 2;        }        if (!rel.y) {            rel.flags |= YSame;        } else if (rel.y > 0 && rel.y < 256) {            rel.flags |= YShortVector|YShortPositive;            point_array_size++;        } else if (rel.y < 0 && rel.y > -256) {            rel.flags |= YShortVector;            rel.y = -rel.y;            point_array_size++;        } else {            point_array_size += 2;        }        (*points)[i] = rel;// #define toString(x) ((rel.flags & x) ? #x : "")//         qDebug() << "    " << QPoint(rel.x, rel.y) << "flags="//                  << toString(OnCurve) << toString(XShortVector)//                  << (rel.flags & XShortVector ? toString(XShortPositive) : toString(XSame))//                  << toString(YShortVector)//                  << (rel.flags & YShortVector ? toString(YShortPositive) : toString(YSame));        prev_x = x;        prev_y = y;    }    return point_array_size;}static void getGlyphData(QTtfGlyph *glyph, const QList<TTF_POINT> &points, const QList<int> &endPoints, int point_array_size){    const int max_size = 5*sizeof(qint16) // header                         + endPoints.size()*sizeof(quint16) // end points of contours                         + sizeof(quint16) // instruction length == 0                         + points.size()*(1) // flags                         + point_array_size; // coordinates    glyph->data.resize(max_size);    QTtfStream s(glyph->data);    s << qint16(endPoints.size())      << glyph->xMin << glyph->yMin << glyph->xMax << glyph->yMax;    for (int i = 0; i < endPoints.size(); ++i)        s << quint16(endPoints.at(i));    s << quint16(0); // instruction length    // emit flags    for (int i = 0; i < points.size(); ++i)        s << quint8(points.at(i).flags);    // emit points    for (int i = 0; i < points.size(); ++i) {        quint8 flags = points.at(i).flags;        qint16 x = points.at(i).x;        if (flags & XShortVector)            s << quint8(x);        else if (!(flags & XSame))            s << qint16(x);    }    for (int i = 0; i < points.size(); ++i) {        quint8 flags = points.at(i).flags;        qint16 y = points.at(i).y;        if (flags & YShortVector)            s << quint8(y);        else if (!(flags & YSame))            s << qint16(y);    }//     qDebug() << "offset=" << s.offset() << "max_size=" << max_size << "point_array_size=" << point_array_size;    Q_ASSERT(s.offset() == max_size);    glyph->numContours = endPoints.size();    glyph->numPoints = points.size();}static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem){    QList<TTF_POINT> points;    QList<int> endPoints;    QTtfGlyph glyph;    glyph.index = index;    glyph.advanceWidth = qRound(advance * 2048. / ppem);    glyph.lsb = qRound(lsb * 2048. / ppem);    if (!path.elementCount()) {        //qDebug("glyph %d is empty", index);        lsb = 0;        glyph.xMin = glyph.xMax = glyph.yMin = glyph.yMax = 0;        glyph.numContours = 0;        glyph.numPoints = 0;        return glyph;    }    convertPath(path, &points, &endPoints, ppem);//     qDebug() << "number of contours=" << endPoints.size();//     for (int i = 0; i < points.size(); ++i)//         qDebug() << "  point[" << i << "] = " << QPoint(points.at(i).x, points.at(i).y) << " flags=" << points.at(i).flags;//     qDebug() << "endPoints:";//     for (int i = 0; i < endPoints.size(); ++i)//         qDebug() << endPoints.at(i);    getBounds(points, &glyph.xMin, &glyph.xMax, &glyph.yMin, &glyph.yMax);    int point_array_size = convertToRelative(&points);    getGlyphData(&glyph, points, endPoints, point_array_size);    return glyph;}static bool operator <(const QTtfGlyph &g1, const QTtfGlyph &g2){    return g1.index < g2.index;}static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QList<QTtfGlyph> &_glyphs){    const int max_size_small = 65536*2;    QList<QTtfGlyph> glyphs = _glyphs;    qSort(glyphs);    Q_ASSERT(tables.maxp.numGlyphs == glyphs.at(glyphs.size()-1).index + 1);    int nGlyphs = tables.maxp.numGlyphs;    int glyf_size = 0;    for (int i = 0; i < glyphs.size(); ++i)        glyf_size += (glyphs.at(i).data.size() + 3) & ~3;    tables.head.indexToLocFormat = glyf_size < max_size_small ? 0 : 1;    tables.hhea.numberOfHMetrics = nGlyphs;    QTtfTable glyf;    glyf.tag = MAKE_TAG('g', 'l', 'y', 'f');    QTtfTable loca;    loca.tag = MAKE_TAG('l', 'o', 'c', 'a');    loca.data.resize(glyf_size < max_size_small ? (nGlyphs+1)*sizeof(quint16) : (nGlyphs+1)*sizeof(quint32));    QTtfStream ls(loca.data);    QTtfTable hmtx;    hmtx.tag = MAKE_TAG('h', 'm', 't', 'x');    hmtx.data.resize(nGlyphs*4);    QTtfStream hs(hmtx.data);    int pos = 0;    for (int i = 0; i < nGlyphs; ++i) {        int gpos = glyf.data.size();        quint16 advance = 0;        qint16 lsb = 0;        if (glyphs[pos].index == i) {            // emit glyph//             qDebug("emitting glyph %d: size=%d", i, glyphs.at(i).data.size());            glyf.data += glyphs.at(pos).data;            while (glyf.data.size() & 1)                glyf.data.append('\0');            advance = glyphs.at(pos).advanceWidth;            lsb = glyphs.at(pos).lsb;            ++pos;        }        if (glyf_size < max_size_small) {            // use short loca format            ls << quint16(gpos>>1);        } else {            // use long loca format            ls << quint32(gpos);        }        hs << advance           << lsb;    }    if (glyf_size < max_size_small) {        // use short loca format        ls << quint16(glyf.data.size()>>1);    } else {        // use long loca format        ls << quint32(glyf.data.size());    }    Q_ASSERT(loca.data.size() == ls.offset());    Q_ASSERT(hmtx.data.size() == hs.offset());    QList<QTtfTable> list;    list.append(glyf);    list.append(loca);    list.append(hmtx);    return list;}static bool operator <(const QTtfTable &t1, const QTtfTable &t2){    return t1.tag < t2.tag;}static QByteArray bindFont(const QList<QTtfTable>& _tables){    QList<QTtfTable> tables = _tables;    qSort(tables);    QByteArray font;    const int header_size = sizeof(qint32) + 4*sizeof(quint16);    const int directory_size = 4*sizeof(quint32)*tables.size();    font.resize(header_size + directory_size);    int log2 = 0;    int pow = 1;    int n = tables.size() >> 1;    while (n) {        ++log2;        pow <<= 1;        n >>= 1;    }    quint32 head_offset = 0;    {        QTtfStream f(font);// Offset Table// Type  Name  Description//   qint32  sfnt version  0x00010000 for version 1.0.//   quint16   numTables  Number of tables.//   quint16   searchRange  (Maximum power of 2 <= numTables) x 16.//   quint16   entrySelector  Log2(maximum power of 2 <= numTables).//   quint16   rangeShift  NumTables x 16-searchRange.        f << qint32(0x00010000)          << quint16(tables.size())          << quint16(16*pow)          << quint16(log2)          << quint16(16*(tables.size() - pow));// Table Directory// Type  Name  Description//   quint32  tag  4 -byte identifier.//   quint32  checkSum  CheckSum for this table.//   quint32  offset  Offset from beginning of TrueType font file.//   quint32  length  Length of this table.        quint32 table_offset = header_size + directory_size;        for (int i = 0; i < tables.size(); ++i) {            const QTtfTable &t = tables.at(i);            const quint32 size = (t.data.size() + 3) & ~3;            if (t.tag == MAKE_TAG('h', 'e', 'a', 'd'))                head_offset = table_offset;            f << t.tag              << checksum(t.data)              << table_offset              << t.data.size();            table_offset += size;#define TAG(x) char(t.tag >> 24) << char((t.tag >> 16) & 0xff) << char((t.tag >> 8) & 0xff) << char(t.tag & 0xff)            //qDebug() << "table " << TAG(t.tag) << "has size " << t.data.size() << "stream at " << f.offset();        }    }    for (int i = 0; i < tables.size(); ++i) {        const QByteArray &t = tables.at(i).data;        font += t;        int s = t.size();        while (s & 3) { font += '\0'; ++s; }    }    if (!head_offset) {        qWarning("QFontSubset: Font misses 'head' table");        return QByteArray();    }    // calculate the fonts checksum and qToBigEndian into 'head's checksum_adjust    quint32 checksum_adjust = 0xB1B0AFBA - checksum(font);    qToBigEndian(checksum_adjust, (uchar *)font.data() + head_offset + 8);    return font;}/*  PDF requires the following tables:  head, hhea, loca, maxp, cvt , prep, glyf, hmtx, fpgm  This means we don't have to add a os/2, post or name table. cvt , prep and fpgm could be empty  if really required.*/QByteArray QFontSubset::toTruetype() const{    qttf_font_tables font;    memset(&font, 0, sizeof(qttf_font_tables));    qreal ppem = fontEngine->fontDef.pixelSize;#define TO_TTF(x) qRound(x * 2048. / ppem)    QList<QTtfGlyph> glyphs;    QFontEngine::Properties properties = fontEngine->properties();    // initialize some stuff needed in createWidthArray    emSquare = 2048;    widths.resize(nGlyphs());

⌨️ 快捷键说明

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