📄 qfontengine_ft.cpp
字号:
} else { while (h--) { for (int x = 0; x < info.width; x++) { uint blue = src[x]; uint green = src[x+bitmap.pitch]; uint red = src[x+2*bitmap.pitch]; uint high = (red*subpixel_filter[0][0] + green*subpixel_filter[0][1] + blue*subpixel_filter[0][2]) >> 8; uint mid = (red*subpixel_filter[1][0] + green*subpixel_filter[1][1] + blue*subpixel_filter[1][2]) >> 8; uint low = (red*subpixel_filter[2][0] + green*subpixel_filter[2][1] + blue*subpixel_filter[2][2]) >> 8; uint res = (mid << 24) + (high << 16) + (mid << 8) + low; dst[x] = res; } dst += info.width; src += 3*bitmap.pitch; } } delete [] bitmap.buffer; } } else if (slot->format == FT_GLYPH_FORMAT_BITMAP) { Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO); uchar *src = slot->bitmap.buffer; uchar *dst = glyph_buffer; int h = slot->bitmap.rows; if (format == Format_Mono) { int bytes = ((info.width + 7) & ~7) >> 3; while (h--) { memcpy (dst, src, bytes); dst += pitch; src += slot->bitmap.pitch; } } else { if (hsubpixel) { while (h--) { uint *dd = (uint *)dst; *dd++ = 0; for (int x = 0; x < slot->bitmap.width; x++) { uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000); *dd++ = a; } *dd++ = 0; dst += pitch; src += slot->bitmap.pitch; } } else if (vfactor != 1) { while (h--) { uint *dd = (uint *)dst; for (int x = 0; x < slot->bitmap.width; x++) { uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000); *dd++ = a; } dst += pitch; src += slot->bitmap.pitch; } } else { while (h--) { for (int x = 0; x < slot->bitmap.width; x++) { unsigned char a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xff : 0x00); dst[x] = a; } dst += pitch; src += slot->bitmap.pitch; } } } } else { qWarning("QFontEngine: Glyph neither outline nor bitmap format=%d", slot->format); delete [] glyph_buffer; return 0; } bool large_glyph = (((signed char)(slot->linearHoriAdvance>>16) != slot->linearHoriAdvance>>16) || ((uchar)(info.width) != info.width) || ((uchar)(info.height) != info.height) || ((signed char)(info.x) != info.x) || ((signed char)(info.y) != info.y) || ((signed char)(info.xOff) != info.xOff)); if (large_glyph) {// qDebug("got a large glyph!"); delete [] glyph_buffer; return 0; } if (!g) { g = new Glyph; g->uploadedToServer = false; g->data = 0; } g->linearAdvance = slot->linearHoriAdvance >> 10; g->width = info.width; g->height = TRUNC(top - bottom); g->x = -info.x; g->y = TRUNC(top); g->advance = TRUNC(ROUND(slot->advance.x)); g->format = format; delete [] g->data; g->data = glyph_buffer; if (uploadToServer) { uploadGlyphToServer(set, glyph, g, &info, size); } set->glyph_data[glyph] = g; return g;}bool QFontEngineFT::uploadGlyphToServer(QGlyphSet *set, uint glyphid, Glyph *g, GlyphInfo *info, int glyphDataSize) const{ Q_UNUSED(set); Q_UNUSED(glyphid); Q_UNUSED(g); Q_UNUSED(info); Q_UNUSED(glyphDataSize); return false;}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();#ifndef QT_NO_PRINTER p.postscriptName = QPdf::stripSpecialCharacters(p.postscriptName);#endif } return freetype->properties();}QByteArray QFontEngineFT::getSfntTable(uint tag) const{ return freetype->getSfntTable(tag);}int QFontEngineFT::synthesized() const{ int s = 0; if ((fontDef.style != QFont::StyleNormal) && !(freetype->face->style_flags & FT_STYLE_FLAG_ITALIC)) s = SynthesizedItalic; if (fontDef.stretch != 100 && FT_IS_SCALABLE(freetype->face)) s |= SynthesizedStretch; return s;}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_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2); if (os2 && os2->sxHeight) return QFixed(os2->sxHeight*freetype->face->size->metrics.y_ppem)/freetype->face->units_per_EM; return QFontEngine::xHeight();}QFixed QFontEngineFT::averageCharWidth() const{ TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2); if (os2 && os2->xAvgCharWidth) return QFixed(os2->xAvgCharWidth*freetype->face->size->metrics.y_ppem)/freetype->face->units_per_EM; return QFontEngine::averageCharWidth();}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 *)(const void*)char_table; QGlyphLayout glyphs[char_table_entries]; int ng = char_table_entries; stringToCMap(ch, char_table_entries, glyphs, &ng, QTextEngine::GlyphIndicesOnly); while (--ng) { if (glyphs[ng].glyph) { glyph_metrics_t gi = const_cast<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;}void QFontEngineFT::doKerning(int num_glyphs, QGlyphLayout *g, QTextEngine::ShaperFlags flags) const{ if (!kerning_pairs_loaded) { kerning_pairs_loaded = true; if (freetype->face->size->metrics.x_ppem != 0) { lockFace(); QFixed scalingFactor(freetype->face->units_per_EM/freetype->face->size->metrics.x_ppem); unlockFace(); const_cast<QFontEngineFT *>(this)->loadKerningPairs(scalingFactor); } } QFontEngine::doKerning(num_glyphs, g, flags);}QOpenType *QFontEngineFT::openType() const{#ifndef QT_NO_OPENTYPE if (_openType) return _openType; FT_Face face = lockFace(); if (!face || !FT_IS_SFNT(face)) { unlockFace(); return 0; } _openType = new QOpenType(const_cast<QFontEngineFT *>(this), face); unlockFace();#endif return _openType;}QFontEngineFT::QGlyphSet *QFontEngineFT::loadTransformedGlyphSet(glyph_t *glyphs, int num_glyphs, const QTransform &matrix, GlyphFormat format){ // FT_Set_Transform only supports scalable fonts if (!FT_IS_SCALABLE(freetype->face)) return 0; // don't try to load huge fonts if (fontDef.pixelSize * qSqrt(matrix.det()) >= 64) return 0; FT_Matrix m; m.xx = FT_Fixed(matrix.m11() * 65536); m.xy = FT_Fixed(-matrix.m21() * 65536); m.yx = FT_Fixed(-matrix.m12() * 65536); m.yy = FT_Fixed(matrix.m22() * 65536); QGlyphSet *gs = 0; for (int i = 0; i < transformedGlyphSets.count(); ++i) { const QGlyphSet &g = transformedGlyphSets.at(i); if (g.transformationMatrix.xx == m.xx && g.transformationMatrix.xy == m.xy && g.transformationMatrix.yx == m.yx && g.transformationMatrix.yy == m.yy) { // found a match, move it to the front transformedGlyphSets.move(i, 0); gs = &transformedGlyphSets[0]; break; } } if (!gs) { // don't cache more than 10 transformations if (transformedGlyphSets.count() >= 10) { transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0); freeServerGlyphSet(transformedGlyphSets.at(0).id); } else { transformedGlyphSets.prepend(QGlyphSet()); } gs = &transformedGlyphSets[0]; qDeleteAll(gs->glyph_data); gs->glyph_data.clear(); gs->id = allocateServerGlyphSet(); gs->transformationMatrix = m; } FT_Face face = 0; bool lockedFace = false; for (int i = 0; i < num_glyphs; ++i) { if (!gs->glyph_data.contains(glyphs[i])) { if (!lockedFace) { face = lockFace(); m = this->matrix; FT_Matrix_Multiply(&gs->transformationMatrix, &m); FT_Set_Transform(face, &m, 0); freetype->matrix = m; lockedFace = true; } if (!loadGlyph(gs, glyphs[i], format)) { FT_Set_Transform(face, &freetype->matrix, 0); unlockFace(); return 0; } } } if (lockedFace) { FT_Set_Transform(face, &freetype->matrix, 0); unlockFace(); } return gs;}void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics){ FT_Face face = lockFace(Unscaled); FT_Set_Transform(face, 0, 0); FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP); 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; metrics->width = QFixed::fromFixed(right-left); metrics->height = QFixed::fromFixed(top-bottom); metrics->x = QFixed::fromFixed(left); metrics->y = QFixed::fromFixed(-top); metrics->xoff = QFixed::fromFixed(face->glyph->advance.x); if (!FT_IS_SCALABLE(freetype->face))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -