📄 qfontengine_qpf.cpp
字号:
if (!fontData || fontData == (const uchar *)MAP_FAILED) {#if defined(DEBUG_FONTENGINE) perror("mmap failed");#endif fontData = 0; return; } if (!verifyHeader(fontData, st.st_size)) {#if defined(DEBUG_FONTENGINE) qDebug() << "verifyHeader failed!";#endif return; } const Header *header = reinterpret_cast<const Header *>(fontData); readOnly = (header->lock == 0xffffffff); const uchar *data = fontData + sizeof(Header) + qFromBigEndian<quint16>(header->dataSize); const uchar *endPtr = fontData + dataSize; while (data <= endPtr - 8) { quint16 blockTag = readValue<quint16>(data); data += 2; // skip padding quint32 blockSize = readValue<quint32>(data); if (blockTag == CMapBlock) { cmapOffset = data - fontData; cmapSize = blockSize; } else if (blockTag == GMapBlock) { glyphMapOffset = data - fontData; glyphMapEntries = blockSize / 4; } else if (blockTag == GlyphBlock) { glyphDataOffset = data - fontData; glyphDataSize = blockSize; } data += blockSize; } face_id.filename = QFile::encodeName(extractHeaderField(fontData, Tag_FileName).toString()); face_id.index = extractHeaderField(fontData, Tag_FileIndex).toInt();#if !defined(QT_NO_FREETYPE) freetype = QFreetypeFace::getFace(face_id); if (!freetype) { QString newPath =#ifndef QT_NO_SETTINGS QLibraryInfo::location(QLibraryInfo::LibrariesPath) +#endif QLatin1String("/fonts/") + QFileInfo(QFile::decodeName(face_id.filename)).fileName(); face_id.filename = QFile::encodeName(newPath); freetype = QFreetypeFace::getFace(face_id); } if (freetype) { const quint32 qpfTtfRevision = extractHeaderField(fontData, Tag_FontRevision).toUInt(); const QByteArray head = freetype->getSfntTable(MAKE_TAG('h', 'e', 'a', 'd')); if (head.size() < 8 || qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(head.constData()) + 4) != qpfTtfRevision) { freetype->release(face_id); freetype = 0; } } if (!cmapOffset && freetype) { freetypeCMapTable = freetype->getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); externalCMap = reinterpret_cast<const uchar *>(freetypeCMapTable.constData()); cmapSize = freetypeCMapTable.size(); }#endif // get the real cmap if (cmapOffset) { int tableSize = cmapSize; const uchar *cmapPtr = getCMap(fontData + cmapOffset, tableSize, &symbol, &cmapSize); if (cmapPtr) cmapOffset = cmapPtr - fontData; else cmapOffset = 0; } else if (externalCMap) { int tableSize = cmapSize; externalCMap = getCMap(externalCMap, tableSize, &symbol, &cmapSize); } // verify all the positions in the glyphMap if (glyphMapOffset) { const quint32 *gmapPtr = reinterpret_cast<const quint32 *>(fontData + glyphMapOffset); for (uint i = 0; i < glyphMapEntries; ++i) { quint32 glyphDataPos = qFromBigEndian<quint32>(gmapPtr[i]); if (glyphDataPos == 0xffffffff) continue; if (glyphDataPos >= glyphDataSize) { // error glyphMapOffset = 0; glyphMapEntries = 0; break; } } }#if defined(DEBUG_FONTENGINE) if (!isValid()) qDebug() << "fontData" << fontData << "dataSize" << dataSize << "externalCMap" << externalCMap << "cmapOffset" << cmapOffset << "glyphMapOffset" << glyphMapOffset << "glyphDataOffset" << glyphDataOffset << "fd" << fd << "glyphDataSize" << glyphDataSize;#endif#if defined(Q_WS_QWS) if (isValid() && renderingFontEngine) qt_fbdpy->sendFontCommand(QWSFontCommand::StartedUsingFont, QFile::encodeName(fileName));#endif}QFontEngineQPF::~QFontEngineQPF(){#if defined(Q_WS_QWS) if (isValid() && renderingFontEngine) qt_fbdpy->sendFontCommand(QWSFontCommand::StoppedUsingFont, QFile::encodeName(fileName));#endif delete renderingFontEngine; if (fontData) munmap((void *)fontData, dataSize); if (fd != -1) ::close(fd);#if !defined(QT_NO_FREETYPE) delete _openType; _openType = 0; if (freetype) freetype->release(face_id);#endif}QByteArray QFontEngineQPF::getSfntTable(uint tag) const{#if !defined(QT_NO_FREETYPE) if (freetype) return freetype->getSfntTable(tag);#else Q_UNUSED(tag);#endif return QByteArray();}bool QFontEngineQPF::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const{ if (!externalCMap && !cmapOffset && renderingFontEngine) { if (!renderingFontEngine->stringToCMap(str, len, glyphs, nglyphs, flags)) return false;#ifndef QT_NO_FREETYPE const_cast<QFontEngineQPF *>(this)->ensureGlyphsLoaded(glyphs, *nglyphs);#endif return true; } if (*nglyphs < len) { *nglyphs = len; return false; }#if defined(DEBUG_FONTENGINE) QSet<QChar> seenGlyphs;#endif const uchar *cmap = externalCMap ? externalCMap : (fontData + cmapOffset); int glyph_pos = 0; if (symbol) { for (int i = 0; i < len; ++i) { unsigned int uc = getChar(str, i, len); glyphs[glyph_pos].glyph = getTrueTypeGlyphIndex(cmap, uc); if(!glyphs[glyph_pos].glyph && uc < 0x100) glyphs[glyph_pos].glyph = getTrueTypeGlyphIndex(cmap, uc + 0xf000); ++glyph_pos; } } else { for (int i = 0; i < len; ++i) { unsigned int uc = getChar(str, i, len); glyphs[glyph_pos].glyph = getTrueTypeGlyphIndex(cmap, uc);#if 0 && defined(DEBUG_FONTENGINE) QChar c(uc); if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c)) qDebug() << "glyph for character" << c << "/" << hex << uc << "is" << dec << glyphs[glyph_pos].glyph; seenGlyphs.insert(c);#endif ++glyph_pos; } } *nglyphs = glyph_pos; recalcAdvances(*nglyphs, glyphs, flags); return true;}void QFontEngineQPF::recalcAdvances(int len, QGlyphLayout *glyphs, QTextEngine::ShaperFlags) const{#ifndef QT_NO_FREETYPE const_cast<QFontEngineQPF *>(this)->ensureGlyphsLoaded(glyphs, len);#endif for (int i = 0; i < len; ++i) { const Glyph *g = findGlyph(glyphs[i].glyph); if (!g) { glyphs[i].glyph = 0; continue; } glyphs[i].advance.x = g->advance; glyphs[i].advance.y = 0; }}void QFontEngineQPF::draw(QPaintEngine *p, qreal _x, qreal _y, const QTextItemInt &si){ QPaintEngineState *pState = p->state; QRasterPaintEngine *paintEngine = static_cast<QRasterPaintEngine*>(p); QTransform matrix = pState->transform(); matrix.translate(_x, _y); QFixed x = QFixed::fromReal(matrix.dx()); QFixed y = QFixed::fromReal(matrix.dy()); QVarLengthArray<QFixedPoint> positions; QVarLengthArray<glyph_t> glyphs; getGlyphPositions(si.glyphs, si.num_glyphs, matrix, si.flags, glyphs, positions); if (glyphs.size() == 0) return; for(int i = 0; i < glyphs.size(); i++) { const Glyph *glyph = findGlyph(glyphs[i]); if (!glyph) continue; const bool mono = false; // ### paintEngine->alphaPenBlt(reinterpret_cast<const uchar *>(glyph) + sizeof(Glyph), glyph->bytesPerLine, mono, qRound(positions[i].x) + glyph->x, qRound(positions[i].y) + glyph->y, glyph->width, glyph->height); }}void QFontEngineQPF::addOutlineToPath(qreal x, qreal y, const QGlyphLayout *glyphs, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags flags){ if (renderingFontEngine && (renderingFontEngine->type() != QFontEngine::Proxy || static_cast<QProxyFontEngine *>(renderingFontEngine)->capabilities() & QAbstractFontEngine::CanOutlineGlyphs)) { renderingFontEngine->addOutlineToPath(x, y, glyphs, numGlyphs, path, flags); return; } addBitmapFontToPath(x, y, glyphs, numGlyphs, path, flags);}glyph_metrics_t QFontEngineQPF::boundingBox(const QGlyphLayout *glyphs, int numGlyphs){#ifndef QT_NO_FREETYPE const_cast<QFontEngineQPF *>(this)->ensureGlyphsLoaded(glyphs, numGlyphs);#endif glyph_metrics_t overall; // initialize with line height, we get the same behaviour on all platforms overall.y = -ascent(); overall.height = ascent() + descent() + 1; QFixed ymax = 0; QFixed xmax = 0; for (int i = 0; i < numGlyphs; i++) { const Glyph *g = findGlyph(glyphs[i].glyph); if (!g) continue; QFixed x = overall.xoff + glyphs[i].offset.x + g->x; QFixed y = overall.yoff + glyphs[i].offset.y + g->y; overall.x = qMin(overall.x, x); overall.y = qMin(overall.y, y); xmax = qMax(xmax, x + g->width); ymax = qMax(ymax, y + g->height); overall.xoff += g->advance; } overall.height = qMax(overall.height, ymax - overall.y); overall.width = xmax - overall.x; return overall;}glyph_metrics_t QFontEngineQPF::boundingBox(glyph_t glyph){#ifndef QT_NO_FREETYPE { QGlyphLayout tmp; tmp.glyph = glyph; const_cast<QFontEngineQPF *>(this)->ensureGlyphsLoaded(&tmp, 1); }#endif glyph_metrics_t overall; const Glyph *g = findGlyph(glyph); if (!g) return overall; overall.x = g->x; overall.y = g->y; overall.width = g->width; overall.height = g->height; overall.xoff = g->advance; return overall;}QFixed QFontEngineQPF::ascent() const{ return QFixed::fromReal(extractHeaderField(fontData, Tag_Ascent).value<qreal>());}QFixed QFontEngineQPF::descent() const{ return QFixed::fromReal(extractHeaderField(fontData, Tag_Descent).value<qreal>());}QFixed QFontEngineQPF::leading() const{ return QFixed::fromReal(extractHeaderField(fontData, Tag_Leading).value<qreal>());}qreal QFontEngineQPF::maxCharWidth() const{ return extractHeaderField(fontData, Tag_MaxCharWidth).value<qreal>();}qreal QFontEngineQPF::minLeftBearing() const{ return extractHeaderField(fontData, Tag_MinLeftBearing).value<qreal>();}qreal QFontEngineQPF::minRightBearing() const{ return extractHeaderField(fontData, Tag_MinRightBearing).value<qreal>();}QFixed QFontEngineQPF::underlinePosition() const{ return QFixed::fromReal(extractHeaderField(fontData, Tag_UnderlinePosition).value<qreal>());}QFixed QFontEngineQPF::lineThickness() const{ return QFixed::fromReal(extractHeaderField(fontData, Tag_LineThickness).value<qreal>());}QFontEngine::Type QFontEngineQPF::type() const{ return QFontEngine::QPF2;}bool QFontEngineQPF::canRender(const QChar *string, int len){ const uchar *cmap = externalCMap ? externalCMap : (fontData + cmapOffset); if (symbol) { for (int i = 0; i < len; ++i) { unsigned int uc = getChar(string, i, len); glyph_t g = getTrueTypeGlyphIndex(cmap, uc); if(!g && uc < 0x100) g = getTrueTypeGlyphIndex(cmap, uc + 0xf000); if (!g) return false; } } else { for (int i = 0; i < len; ++i) { unsigned int uc = getChar(string, i, len); if (!getTrueTypeGlyphIndex(cmap, uc)) return false; } } return true;}bool QFontEngineQPF::isValid() const{ return fontData && dataSize && (cmapOffset || externalCMap || renderingFontEngine) && glyphMapOffset && glyphDataOffset && (fd >= 0 || glyphDataSize > 0);}#if !defined(QT_NO_FREETYPE)FT_Face QFontEngineQPF::lockFace() const{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -