📄 qfontengine_ft.cpp
字号:
QFreetypeFace::addBitmapToPath(face->glyph, p, path); else QFreetypeFace::addGlyphToPath(face, face->glyph, p, path, face->units_per_EM << 6, face->units_per_EM << 6); FT_Set_Transform(face, &freetype->matrix, 0); unlockFace();}static inline unsigned int getChar(const QChar *str, int &i, const int len){ unsigned int uc = str[i].unicode(); if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { uint low = str[i+1].unicode(); if (low >= 0xdc00 && low < 0xe000) { uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; ++i; } } return uc;}bool QFontEngineFT::canRender(const QChar *string, int len){ FT_Face face = freetype->face;#if 0 if (_cmap != -1) { lockFace(); for ( int i = 0; i < len; i++ ) { unsigned int uc = getChar(string, i, len); if (!FcCharSetHasChar (_font->charset, uc) && getAdobeCharIndex(face, _cmap, uc) == 0) { allExist = false; break; } } unlockFace(); } else#endif { for ( int i = 0; i < len; i++ ) { unsigned int uc = getChar(string, i, len); if (!FT_Get_Char_Index(face, uc)) return false; } } return true;}void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout *glyphs, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags flags){ if (FT_IS_SCALABLE(freetype->face)) { QFontEngine::addOutlineToPath(x, y, glyphs, numGlyphs, path, flags); } else { addBitmapFontToPath(x, y, glyphs, numGlyphs, path, flags); }}void QFontEngineFT::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags){ FT_Face face = lockFace(Unscaled); for (int gl = 0; gl < numGlyphs; gl++) { FT_UInt glyph = glyphs[gl]; FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP); FT_GlyphSlot g = face->glyph; if (g->format != FT_GLYPH_FORMAT_OUTLINE) continue; QFreetypeFace::addGlyphToPath(face, g, positions[gl], path, xsize, ysize); } unlockFace();}bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const{ if (*nglyphs < len) { *nglyphs = len; return false; } bool mirrored = flags & QTextEngine::RightToLeft; int glyph_pos = 0; if (freetype->symbol_map) { FT_Face face = freetype->face; for ( int i = 0; i < len; ++i ) { unsigned int uc = getChar(str, i, len); if (mirrored) uc = QChar::mirroredChar(uc); glyphs[glyph_pos].glyph = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0; if ( !glyphs[glyph_pos].glyph ) { glyph_t glyph;#if !defined(QT_NO_FONTCONFIG) if (FcCharSetHasChar(freetype->charset, uc)) {#else if (false) {#endif redo0: glyph = FT_Get_Char_Index(face, uc); if (!glyph && (uc == 0xa0 || uc == 0x9)) { uc = 0x20; goto redo0; } } else { FT_Set_Charmap(face, freetype->symbol_map); glyph = FT_Get_Char_Index(face, uc); FT_Set_Charmap(face, freetype->unicode_map); } glyphs[glyph_pos].glyph = glyph; if (uc < QFreetypeFace::cmapCacheSize) freetype->cmapCache[uc] = glyph; } ++glyph_pos; } } else { FT_Face face = freetype->face; for (int i = 0; i < len; ++i) { unsigned int uc = getChar(str, i, len); if (mirrored) uc = QChar::mirroredChar(uc); glyphs[glyph_pos].glyph = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0; if (!glyphs[glyph_pos].glyph#if !defined(QT_NO_FONTCONFIG) && FcCharSetHasChar(freetype->charset, uc)#endif ) { redo: glyph_t glyph = FT_Get_Char_Index(face, uc); if (!glyph && (uc == 0xa0 || uc == 0x9)) { uc = 0x20; goto redo; } glyphs[glyph_pos].glyph = glyph; if (uc < QFreetypeFace::cmapCacheSize) freetype->cmapCache[uc] = glyph; } ++glyph_pos; } } *nglyphs = glyph_pos; if (flags & QTextEngine::GlyphIndicesOnly) return true; recalcAdvances(*nglyphs, glyphs, flags); return true;}void QFontEngineFT::recalcAdvances(int len, QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const{ FT_Face face = 0; if (flags & QTextEngine::DesignMetrics) { for (int i = 0; i < len; i++) { Glyph *g = defaultGlyphSet.glyph_data.value(glyphs[i].glyph); if (g) { glyphs[i].advance.x = QFixed::fromFixed(g->linearAdvance); } else { if (!face) face = lockFace(); g = loadGlyph(glyphs[i].glyph); glyphs[i].advance.x = QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10); } glyphs[i].advance.y = 0; } } else { for (int i = 0; i < len; i++) { Glyph *g = defaultGlyphSet.glyph_data.value(glyphs[i].glyph); if (g) { glyphs[i].advance.x = QFixed(g->advance); } else { if (!face) face = lockFace(); g = loadGlyph(glyphs[i].glyph); glyphs[i].advance.x = QFixed::fromFixed(face->glyph->metrics.horiAdvance); } glyphs[i].advance.y = 0; } } if (face) unlockFace();}glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout *glyphs, int numGlyphs){ FT_Face face = 0; 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++) { Glyph *g = defaultGlyphSet.glyph_data.value(glyphs[i].glyph); if (!g) { if (!face) face = lockFace(); g = loadGlyph(glyphs[i].glyph); } if (g) { 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 += qRound(g->advance); } else { int left = FLOOR(face->glyph->metrics.horiBearingX); int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width); int top = CEIL(face->glyph->metrics.horiBearingY); int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height); QFixed x = overall.xoff + glyphs[i].offset.x - (-TRUNC(left)); QFixed y = overall.yoff + glyphs[i].offset.y - TRUNC(top); overall.x = qMin(overall.x, x); overall.y = qMin(overall.y, y); xmax = qMax(xmax, x + TRUNC(right - left)); ymax = qMax(ymax, y + TRUNC(top - bottom)); overall.xoff += qRound(TRUNC(ROUND(face->glyph->advance.x))); } } overall.height = qMax(overall.height, ymax - overall.y); overall.width = xmax - overall.x; if (face) unlockFace(); return overall;}glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph){ FT_Face face = 0; glyph_metrics_t overall; Glyph *g = defaultGlyphSet.glyph_data.value(glyph); if (!g) { face = lockFace(); g = loadGlyph(glyph); } if (g) { overall.x = g->x; overall.y = -g->y; overall.width = g->width; overall.height = g->height; overall.xoff = g->advance; } else { int left = FLOOR(face->glyph->metrics.horiBearingX); int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width); int top = CEIL(face->glyph->metrics.horiBearingY); int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height); overall.width = TRUNC(right-left); overall.height = TRUNC(top-bottom); overall.x = TRUNC(left); overall.y = -TRUNC(top); overall.xoff = TRUNC(ROUND(face->glyph->advance.x)); } if (face) unlockFace(); return overall;}QImage QFontEngineFT::alphaMapForGlyph(glyph_t g){ lockFace(); GlyphFormat glyph_format = antialias ? Format_A8 : Format_Mono; Glyph *glyph = loadGlyph(g, glyph_format); if (!glyph) { unlockFace(); return QFontEngine::alphaMapForGlyph(g); } const int pitch = antialias ? (glyph->width + 3) & ~3 : ((glyph->width + 31)/32) * 4; QImage img(glyph->width, glyph->height, antialias ? QImage::Format_Indexed8 : QImage::Format_Mono); if (antialias) { QVector<QRgb> colors(256); for (int i=0; i<256; ++i) colors[i] = qRgba(0, 0, 0, i); img.setColorTable(colors); } else { QVector<QRgb> colors(2); colors[0] = qRgba(0, 0, 0, 0); colors[1] = qRgba(0, 0, 0, 255); img.setColorTable(colors); } Q_ASSERT(img.bytesPerLine() == pitch); if (glyph->width) { for (int y = 0; y < glyph->height; ++y) memcpy(img.scanLine(y), &glyph->data[y * pitch], pitch); } unlockFace(); return img;}void QFontEngineFT::removeGlyphFromCache(glyph_t glyph){ delete defaultGlyphSet.glyph_data.take(glyph);}int QFontEngineFT::glyphCount() const{ int count = 0; FT_Face face = lockFace(); if (face) { count = face->num_glyphs; unlockFace(); } return count;}FT_Face QFontEngineFT::lockFace(Scaling scale) const{ freetype->lock(); FT_Face face = freetype->face; if (scale == Unscaled) { FT_Set_Char_Size(face, face->units_per_EM << 6, face->units_per_EM << 6, 0, 0); freetype->xsize = face->units_per_EM << 6; freetype->ysize = face->units_per_EM << 6; } else if (freetype->xsize != xsize || freetype->ysize != ysize) { FT_Set_Char_Size(face, xsize, ysize, 0, 0); freetype->xsize = xsize; freetype->ysize = ysize; } if (freetype->matrix.xx != matrix.xx || freetype->matrix.yy != matrix.yy || freetype->matrix.xy != matrix.xy || freetype->matrix.yx != matrix.yx) { freetype->matrix = matrix; FT_Set_Transform(face, &freetype->matrix, 0); } return face;}void QFontEngineFT::unlockFace() const{ freetype->unlock();}FT_Face QFontEngineFT::non_locked_face() const{ return freetype->face;}QFontEngineFT::QGlyphSet::QGlyphSet() : id(0){ transformationMatrix.xx = 0x10000; transformationMatrix.yy = 0x10000; transformationMatrix.xy = 0; transformationMatrix.yx = 0;}QFontEngineFT::QGlyphSet::~QGlyphSet(){ qDeleteAll(glyph_data);}unsigned long QFontEngineFT::allocateServerGlyphSet(){ return 0;}void QFontEngineFT::freeServerGlyphSet(unsigned long id){ Q_UNUSED(id);}#endif // QT_NO_FREETYPE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -