📄 qfontengine_x11.cpp
字号:
} Glyph *g = new Glyph; g->linearAdvance = slot->linearHoriAdvance >> 10; g->width = TRUNC(right - left); g->height = TRUNC(top - bottom); g->x = TRUNC(left); g->y = TRUNC(top); g->advance = TRUNC(ROUND(slot->advance.x)); g->format = add_to_glyphset ? Format_None : format; g->data = buffer; // make sure we delete the old cached glyph delete glyph_data.value(glyph); glyph_data[glyph] = g; return g;}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::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 = QUnicodeTables::mirroredChar(uc); glyphs[glyph_pos].glyph = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0; if ( !glyphs[glyph_pos].glyph ) { glyph_t glyph; if (FcCharSetHasChar(freetype->charset, uc)) { 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 = QUnicodeTables::mirroredChar(uc); glyphs[glyph_pos].glyph = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0; if (!glyphs[glyph_pos].glyph && FcCharSetHasChar(freetype->charset, uc)) { 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; 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 = glyph_data.value(glyphs[i].glyph); if (!g) { if (!face) face = lockFace(); g = loadGlyph(glyphs[i].glyph); } // for uncachable glyph, get advance from glyphslot glyphs[i].advance.x = QFixed::fromFixed(g ? g->linearAdvance : (face->glyph->linearHoriAdvance >> 10)); glyphs[i].advance.y = 0; } } else { for (int i = 0; i < len; i++) { Glyph *g = glyph_data.value(glyphs[i].glyph); if (!g) { if (!face) face = lockFace(); g = loadGlyph(glyphs[i].glyph); } // for uncachable glyph, get advance from glyphslot glyphs[i].advance.x = g ? QFixed(g->advance) : 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; QFixed ymax = 0; QFixed xmax = 0; for (int i = 0; i < numGlyphs; i++) { Glyph *g = 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 = 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 = 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;}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::doKerning(int num_glyphs, QGlyphLayout *g, QTextEngine::ShaperFlags flags) const{ if (!FT_HAS_KERNING(freetype->face)) return; FT_Face face = lockFace(); uint f = (flags == QTextEngine::DesignMetrics ? FT_KERNING_UNFITTED : FT_KERNING_DEFAULT); for (int i = 0; i < num_glyphs-1; ++i) { FT_Vector kerning; FT_Get_Kerning(face, g[i].glyph, g[i+1].glyph, f, &kerning); g[i].advance.x += QFixed::fromFixed(kerning.x); g[i].advance.y += QFixed::fromFixed(kerning.y); } unlockFace();}void QFontEngineFT::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags){ FT_Face face = lockFace(); for (int gl = 0; gl < numGlyphs; gl++) { FT_UInt glyph = glyphs[gl]; FT_Load_Glyph(face, glyph, FT_LOAD_NO_HINTING|FT_LOAD_NO_BITMAP); FT_GlyphSlot g = face->glyph; if (g->format != FT_GLYPH_FORMAT_OUTLINE) continue; addGlyphToPath(g, positions[gl], path); } unlockFace();}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); }}QFixed QFontEngineFT::ascent() const{ return QFixed::fromFixed(metrics.ascender);}QFixed QFontEngineFT::descent() const{ return QFixed::fromFixed(-metrics.descender + (1<<6));}QFixed QFontEngineFT::leading() const{ return QFixed::fromFixed(metrics.height - metrics.ascender + metrics.descender);}QFixed QFontEngineFT::xHeight() const{ TT_PCLT *pct = (TT_PCLT *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_pclt); if (pct && pct->xHeight) { return QFixed(pct->xHeight*freetype->face->size->metrics.y_ppem)/freetype->face->units_per_EM; } return QFontEngine::xHeight();}qreal QFontEngineFT::maxCharWidth() const{ return metrics.max_advance >> 6;}static const ushort char_table[] = { 40, 67, 70, 75, 86, 88, 89, 91, 102, 114, 124, 127, 205, 645, 884, 922, 1070, 12386};static const int char_table_entries = sizeof(char_table)/sizeof(ushort);qreal QFontEngineFT::minLeftBearing() const{ if (lbearing == SHRT_MIN) (void) minRightBearing(); // calculates both return lbearing.toReal();}qreal QFontEngineFT::minRightBearing() const{ if (rbearing == SHRT_MIN) { lbearing = rbearing = 0; const QChar *ch = (const QChar *)char_table; QGlyphLayout glyphs[char_table_entries]; int ng = char_table_entries; stringToCMap(ch, char_table_entries, glyphs, &ng, 0); while (--ng) { if (glyphs[ng].glyph) { glyph_metrics_t gi = ((QFontEngineFT *)this)->boundingBox(glyphs[ng].glyph); lbearing = qMin(lbearing, gi.x); rbearing = qMin(rbearing, (gi.xoff - gi.x - gi.width)); } } } return rbearing.toReal();}QFixed QFontEngineFT::lineThickness() const{ return line_thickness;}QFixed QFontEngineFT::underlinePosition() const{ return underline_position;}QFontEngine::FaceId QFontEngineFT::faceId() const{ return face_id;}QFontEngine::Properties QFontEngineFT::properties() const{ Properties p = freetype->properties(); if (p.postscriptName.isEmpty()) { p.postscriptName = fontDef.family.toUtf8(); p.postscriptName.replace(" ", ""); } return freetype->properties();}void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics){ FT_Face face = lockFace(); FT_Set_Transform(face, 0, 0); FT_Load_Glyph(face, glyph, FT_LOAD_NO_HINTING|FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE); int left = face->glyph->metrics.horiBearingX; int right = face->glyph->metrics.horiBearingX + face->glyph->metrics.width; int top = face->glyph->metrics.horiBearingY; int bottom = face->glyph->metrics.horiBearingY - face->glyph->metrics.height; QFixedPoint p; p.x = 0; p.y = 0; if (!FT_IS_SCALABLE(freetype->face)) { metrics->width = QFixed::fromFixed(right-left); metrics->height = QFixed::fromFixed(top-b
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -