📄 qfontengine.cpp
字号:
QPainter p(&im); p.setRenderHint(QPainter::Antialiasing); addGlyphsToPath(&glyph, &pt, 1, &path, 0); p.setPen(Qt::NoPen); p.setBrush(Qt::black); p.drawPath(path); p.end(); QImage indexed(im.width(), im.height(), QImage::Format_Indexed8); QVector<QRgb> colors(256); for (int i=0; i<256; ++i) colors[i] = qRgba(0, 0, 0, i); indexed.setColorTable(colors); for (int y=0; y<im.height(); ++y) { uchar *dst = (uchar *) indexed.scanLine(y); uint *src = (uint *) im.scanLine(y); for (int x=0; x<im.width(); ++x) dst[x] = qAlpha(src[x]); } return indexed;}void QFontEngine::removeGlyphFromCache(glyph_t){}QFontEngine::Properties QFontEngine::properties() const{ Properties p;#ifndef QT_NO_PRINTER QByteArray psname = QPdf::stripSpecialCharacters(fontDef.family.toUtf8());#else QByteArray psname = fontDef.family.toUtf8();#endif psname += '-'; psname += QByteArray::number(fontDef.style); psname += '-'; psname += QByteArray::number(fontDef.weight); p.postscriptName = psname; p.ascent = ascent(); p.descent = descent(); p.leading = leading(); p.emSquare = p.ascent; p.boundingBox = QRectF(0, -p.ascent.toReal(), maxCharWidth(), (p.ascent + p.descent).toReal()); p.italicAngle = 0; p.capHeight = p.ascent; p.lineWidth = lineThickness(); return p;}void QFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics){ *metrics = boundingBox(glyph); QFixedPoint p; p.x = 0; p.y = 0; addGlyphsToPath(&glyph, &p, 1, path, QFlag(0));}#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS)static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs){ uint left_right = (left << 16) + right; left = 0, right = numPairs - 1; while (left <= right) { int middle = left + ( ( right - left ) >> 1 ); if(pairs[middle].left_right == left_right) return pairs[middle].adjust; if (pairs[middle].left_right < left_right) left = middle + 1; else right = middle - 1; } return 0;}void QFontEngine::doKerning(int num_glyphs, QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const{ int numPairs = kerning_pairs.size(); if(!numPairs) return; const KernPair *pairs = kerning_pairs.constData(); if(flags & QTextEngine::DesignMetrics) { for(int i = 0; i < num_glyphs - 1; ++i) glyphs[i].advance.x += kerning(glyphs[i].glyph, glyphs[i+1].glyph , pairs, numPairs); } else { for(int i = 0; i < num_glyphs - 1; ++i) glyphs[i].advance.x += qRound(kerning(glyphs[i].glyph, glyphs[i+1].glyph , pairs, numPairs)); }}static inline bool operator<(const QFontEngine::KernPair &p1, const QFontEngine::KernPair &p2){ return p1.left_right < p2.left_right;}void QFontEngine::loadKerningPairs(QFixed scalingFactor){ kerning_pairs.clear(); QByteArray tab = getSfntTable(MAKE_TAG('k', 'e', 'r', 'n')); if (tab.isEmpty()) return; const uchar *table = reinterpret_cast<const uchar *>(tab.constData()); unsigned short version = qFromBigEndian<quint16>(table); if (version != 0) {// qDebug("wrong version"); return; } unsigned short numTables = qFromBigEndian<quint16>(table + 2); { int offset = 4; for(int i = 0; i < numTables; ++i) { if (offset + 6 > tab.size()) {// qDebug("offset out of bounds"); goto end; } const uchar *header = table + offset; ushort version = qFromBigEndian<quint16>(header); ushort length = qFromBigEndian<quint16>(header+2); ushort coverage = qFromBigEndian<quint16>(header+4);// qDebug("subtable: version=%d, coverage=%x",version, coverage); if(version == 0 && coverage == 0x0001) { if (offset + length > tab.size()) {// qDebug("length ouf ot bounds"); goto end; } const uchar *data = table + offset + 6; ushort nPairs = qFromBigEndian<quint16>(data); if(nPairs * 6 + 8 > length - 6) {// qDebug("corrupt table!"); // corrupt table goto end; } int off = 8; for(int i = 0; i < nPairs; ++i) { QFontEngine::KernPair p; p.left_right = (((uint)qFromBigEndian<quint16>(data+off)) << 16) + qFromBigEndian<quint16>(data+off+2); p.adjust = QFixed(((int)(short)qFromBigEndian<quint16>(data+off+4))) / scalingFactor; kerning_pairs.append(p); off += 6; } } offset += length; } }end: qSort(kerning_pairs);// for (int i = 0; i < kerning_pairs.count(); ++i)// qDebug() << "i" << i << "left_right" << hex << kerning_pairs.at(i).left_right;}#elsevoid QFontEngine::doKerning(int, QGlyphLayout *, QTextEngine::ShaperFlags) const{}#endifint QFontEngine::glyphCount() const{ QByteArray maxpTable = getSfntTable(MAKE_TAG('m', 'a', 'x', 'p')); if (maxpTable.size() < 6) return 0; return qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(maxpTable.constData() + 4));}const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize){ const uchar *header = table; if (tableSize < 4) return 0; const uchar *endPtr = table + tableSize; // version check if (qFromBigEndian<quint16>(header) != 0) return 0; unsigned short numTables = qFromBigEndian<quint16>(header + 2); const uchar *maps = table + 4; if (maps + 8 * numTables > endPtr) return 0; int tableToUse = -1; int score = 0; for (int n = 0; n < numTables; ++n) { const quint16 platformId = qFromBigEndian<quint16>(maps + 8 * n); const quint16 platformSpecificId = qFromBigEndian<quint16>(maps + 8 * n + 2); switch (platformId) { case 0: // Unicode if (score < 4 && (platformSpecificId == 0 || platformSpecificId == 2 || platformSpecificId == 3)) { tableToUse = n; score = 4; } else if (score < 3 && platformSpecificId == 1) { tableToUse = n; score = 3; } break; case 1: // Apple if (score < 2 && platformSpecificId == 0) { // Apple Roman tableToUse = n; score = 2; } break; case 3: // Microsoft switch (platformSpecificId) { case 0: if (score < 1) { tableToUse = n; score = 1; } break; case 1: if (score < 5) { tableToUse = n; score = 5; } break; case 0xa: if (score < 6) { tableToUse = n; score = 6; } break; default: break; } default: break; } } if(tableToUse < 0) return 0; *isSymbolFont = (score == 1); unsigned int unicode_table = qFromBigEndian<quint32>(maps + 8*tableToUse + 4); if (!unicode_table || unicode_table + 8 > tableSize) return 0; // get the header of the unicode table header = table + unicode_table; unsigned short format = qFromBigEndian<quint16>(header); unsigned int length; if(format < 8) length = qFromBigEndian<quint16>(header + 2); else length = qFromBigEndian<quint32>(header + 4); if (table + unicode_table + length > endPtr) return 0; *cmapSize = length; return table + unicode_table;}quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode){ unsigned short format = qFromBigEndian<quint16>(cmap); if (format == 0) { if (unicode < 256) return (int) *(cmap+6+unicode); } else if (format == 4) { /* some fonts come with invalid cmap tables, where the last segment specified end = start = rangeoffset = 0xffff, delta = 0x0001 Since 0xffff is never a valid Unicode char anyway, we just get rid of the issue by returning 0 for 0xffff */ if(unicode >= 0xffff) return 0; quint16 segCountX2 = qFromBigEndian<quint16>(cmap + 6); const unsigned char *ends = cmap + 14; quint16 endIndex = 0; int i = 0; for (; i < segCountX2/2 && (endIndex = qFromBigEndian<quint16>(ends + 2*i)) < unicode; i++); const unsigned char *idx = ends + segCountX2 + 2 + 2*i; quint16 startIndex = qFromBigEndian<quint16>(idx); if (startIndex > unicode) return 0; idx += segCountX2; qint16 idDelta = (qint16)qFromBigEndian<quint16>(idx); idx += segCountX2; quint16 idRangeoffset_t = (quint16)qFromBigEndian<quint16>(idx); quint16 glyphIndex; if (idRangeoffset_t) { quint16 id = qFromBigEndian<quint16>(idRangeoffset_t + 2*(unicode - startIndex) + idx); if (id) glyphIndex = (idDelta + id) % 0x10000; else glyphIndex = 0; } else { glyphIndex = (idDelta + unicode) % 0x10000; } return glyphIndex; } else if (format == 12) { quint32 nGroups = qFromBigEndian<quint32>(cmap + 12); cmap += 16; // move to start of groups int left = 0, right = nGroups - 1; while (left <= right) { int middle = left + ( ( right - left ) >> 1 ); quint32 startCharCode = qFromBigEndian<quint32>(cmap + 12*middle); if(unicode < startCharCode) right = middle - 1; else { quint32 endCharCode = qFromBigEndian<quint32>(cmap + 12*middle + 4); if(unicode <= endCharCode) return qFromBigEndian<quint32>(cmap + 12*middle + 8) + unicode - startCharCode; left = middle + 1; } } } else { qDebug("cmap table of format %d not implemented", format); } return 0;}// ------------------------------------------------------------------// The box font engine// ------------------------------------------------------------------#ifdef Q_WS_WIN#include "qt_windows.h"#endifQFontEngineBox::QFontEngineBox(int size) : _size(size){ cache_cost = sizeof(QFontEngineBox);#ifdef Q_WS_WIN#ifndef Q_OS_TEMP hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);#endif stockFont = true; ttf = false; cmap = 0; script_cache = 0;#endif}QFontEngineBox::~QFontEngineBox(){}bool QFontEngineBox::stringToCMap(const QChar *, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags) const{ if (*nglyphs < len) { *nglyphs = len; return false; } for (int i = 0; i < len; i++) { glyphs[i].glyph = 0; glyphs[i].advance.x = _size; glyphs[i].advance.y = 0; } *nglyphs = len; return true;}void QFontEngineBox::addOutlineToPath(qreal x, qreal y, const QGlyphLayout *glyphs, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags flags){ if (!numGlyphs) return; QVarLengthArray<QFixedPoint> positions; QVarLengthArray<glyph_t> positioned_glyphs; QTransform matrix; matrix.translate(x, y); getGlyphPositions(glyphs, numGlyphs, matrix, flags, positioned_glyphs, positions); addGlyphsToPath(positioned_glyphs.data(), positions.data(), positioned_glyphs.size(), path, flags); int size = qRound(ascent()); QSize s(size - 3, size - 3); for (int k = 0; k < positions.size(); k++) path->addRect(QRectF(positions[k].toPointF(), s));}glyph_metrics_t QFontEngineBox::boundingBox(const QGlyphLayout *, int numGlyphs){ glyph_metrics_t overall; overall.width = _size*numGlyphs; overall.height = _size; overall.xoff = overall.width; return overall;}#if defined(Q_WS_QWS)void QFontEngineBox::draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &ti){ if (!ti.num_glyphs) return; int size = qRound(ascent()); QSize s(size - 3, size - 3); QVarLengthArray<QFixedPoint> positions; QVarLengthArray<glyph_t> glyphs; QTransform matrix; matrix.translate(x, y - size); ti.fontEngine->getGlyphPositions(ti.glyphs, ti.num_glyphs, matrix, ti.flags, glyphs, positions); if (glyphs.size() == 0) return; QPainter *painter = p->painter();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -