📄 qfontengine_ft.cpp
字号:
c[2] = (2*c[1] + c[3])/3; c[1] = (2*c[1] + c[0])/3; } break; }// qDebug() << "cubicTo" << c[1] << c[2] << c[3]; path->cubicTo(c[1], c[2], c[3]); c[0] = c[3]; n = 1; } if (n == 1) {// qDebug() << "closeSubpath"; path->closeSubpath(); } else { c[3] = start; if (n == 2) { c[2] = (2*c[1] + c[3])/3; c[1] = (2*c[1] + c[0])/3; }// qDebug() << "cubicTo" << c[1] << c[2] << c[3]; path->cubicTo(c[1], c[2], c[3]); } ++i; }}extern void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path);void QFreetypeFace::addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path, bool){ if (slot->format != FT_GLYPH_FORMAT_BITMAP || slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO) return; QPointF cp = point.toPointF(); qt_addBitmapToPath(cp.x() + TRUNC(slot->metrics.horiBearingX), cp.y() - TRUNC(slot->metrics.horiBearingY), slot->bitmap.buffer, slot->bitmap.pitch, slot->bitmap.width, slot->bitmap.rows, path);}QFontEngineFT::Glyph::~Glyph(){ delete [] data;}static const uint subpixel_filter[3][3] = { { 180, 60, 16 }, { 38, 180, 38 }, { 16, 60, 180 }};QFontEngineFT::QFontEngineFT(const QFontDef &fd){ _openType = 0; fontDef = fd; matrix.xx = 0x10000; matrix.yy = 0x10000; matrix.xy = 0; matrix.yx = 0; cache_cost = 100; kerning_pairs_loaded = false; transform = false; antialias = true; default_load_flags = 0; subpixelType = Subpixel_None; defaultGlyphFormat = Format_None; canUploadGlyphsToServer = false;}QFontEngineFT::~QFontEngineFT(){#ifndef QT_NO_OPENTYPE delete _openType; _openType = 0;#endif if (freetype) freetype->release(face_id);}void QFontEngineFT::freeGlyphSets(){ freeServerGlyphSet(defaultGlyphSet.id); for (int i = 0; i < transformedGlyphSets.count(); ++i) freeServerGlyphSet(transformedGlyphSets.at(i).id);}bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat defaultFormat){ defaultGlyphFormat = defaultFormat; this->antialias = antialias; face_id = faceId; freetype = QFreetypeFace::getFace(face_id); if (!freetype) { xsize = 0; ysize = 0; return false; } symbol = freetype->symbol_map != 0; PS_FontInfoRec psrec; // don't assume that type1 fonts are symbol fonts by default if (FT_Get_PS_Font_Info(freetype->face, &psrec) == FT_Err_Ok) { symbol = bool(fontDef.family.contains(QLatin1String("symbol"), Qt::CaseInsensitive)); } lbearing = rbearing = SHRT_MIN; freetype->computeSize(fontDef, &xsize, &ysize, &outline_drawing); FT_Face face = lockFace(); //underline metrics if (FT_IS_SCALABLE(face)) { line_thickness = QFixed::fromFixed(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale)); underline_position = QFixed::fromFixed(-FT_MulFix(face->underline_position, face->size->metrics.y_scale)); bool fake_oblique = (fontDef.style != QFont::StyleNormal) && !(face->style_flags & FT_STYLE_FLAG_ITALIC); if (fake_oblique) matrix.xy = 0x10000*3/10; FT_Set_Transform(face, &matrix, 0); if (fake_oblique) transform = true; } else { // copied from QFontEngineQPF // ad hoc algorithm int score = fontDef.weight * fontDef.pixelSize; line_thickness = score / 700; // looks better with thicker line for small pointsizes if (line_thickness < 2 && score >= 1050) line_thickness = 2; underline_position = ((line_thickness * 2) + 3) / 6; } if (line_thickness < 1) line_thickness = 1; metrics = face->size->metrics; unlockFace(); fsType = freetype->fsType(); defaultGlyphSet.id = allocateServerGlyphSet(); return true;}QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, GlyphFormat format) const{// Q_ASSERT(freetype->lock == 1); bool uploadToServer = false; if (format == Format_None) { if (defaultGlyphFormat != Format_None) { format = defaultGlyphFormat; if (canUploadGlyphsToServer) uploadToServer = true; } else { format = Format_Mono; } } Glyph *g = set->glyph_data.value(glyph); if (g && g->format == format) { if (uploadToServer && !g->uploadedToServer) { set->glyph_data[glyph] = 0; delete g; g = 0; } else { return g; } } QFontEngineFT::GlyphInfo info; Q_ASSERT(format != Format_None); bool hsubpixel = false; int vfactor = 1; int load_flags = FT_LOAD_DEFAULT | default_load_flags; if (outline_drawing) { load_flags = FT_LOAD_NO_BITMAP; } else if (format == Format_Mono) { load_flags |= FT_LOAD_TARGET_MONO; } else if (format == Format_A32) { if (subpixelType == QFontEngineFT::Subpixel_RGB || subpixelType == QFontEngineFT::Subpixel_BGR) { load_flags |= FT_LOAD_TARGET_LCD; hsubpixel = true; } else if (subpixelType == QFontEngineFT::Subpixel_VRGB || subpixelType == QFontEngineFT::Subpixel_VBGR) { load_flags |= FT_LOAD_TARGET_LCD_V; vfactor = 3; } }#ifndef Q_WS_QWS if (format != Format_Mono) load_flags |= FT_LOAD_NO_BITMAP;#endif bool transform = this->transform || set->transformationMatrix.xx != 0x10000 || set->transformationMatrix.yy != 0x10000 || set->transformationMatrix.xy != 0 || set->transformationMatrix.yx != 0; if (transform) load_flags |= FT_LOAD_NO_BITMAP; FT_Face face = freetype->face; FT_Error err = FT_Load_Glyph(face, glyph, load_flags); if (err && (load_flags & FT_LOAD_NO_BITMAP)) { load_flags &= ~FT_LOAD_NO_BITMAP; err = FT_Load_Glyph(face, glyph, load_flags); } if (err == FT_Err_Too_Few_Arguments) { // this is an error in the bytecode interpreter, just try to run without it load_flags |= FT_LOAD_FORCE_AUTOHINT; err = FT_Load_Glyph(face, glyph, load_flags); } if (err != FT_Err_Ok) qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph); if (outline_drawing) return 0; FT_GlyphSlot slot = face->glyph; FT_Matrix matrix = freetype->matrix; int left = slot->metrics.horiBearingX; int right = slot->metrics.horiBearingX + slot->metrics.width; int top = slot->metrics.horiBearingY; int bottom = slot->metrics.horiBearingY - slot->metrics.height; if(transform && slot->format != FT_GLYPH_FORMAT_BITMAP) { int l, r, t, b; FT_Vector vector; vector.x = left; vector.y = top; FT_Vector_Transform(&vector, &matrix); l = r = vector.x; t = b = vector.y; vector.x = right; vector.y = top; FT_Vector_Transform(&vector, &matrix); if (l > vector.x) l = vector.x; if (r < vector.x) r = vector.x; if (t < vector.y) t = vector.y; if (b > vector.y) b = vector.y; vector.x = right; vector.y = bottom; FT_Vector_Transform(&vector, &matrix); if (l > vector.x) l = vector.x; if (r < vector.x) r = vector.x; if (t < vector.y) t = vector.y; if (b > vector.y) b = vector.y; vector.x = left; vector.y = bottom; FT_Vector_Transform(&vector, &matrix); if (l > vector.x) l = vector.x; if (r < vector.x) r = vector.x; if (t < vector.y) t = vector.y; if (b > vector.y) b = vector.y; left = l; right = r; top = t; bottom = b; } left = FLOOR(left); right = CEIL(right); bottom = FLOOR(bottom); top = CEIL(top); int hpixels = TRUNC(right - left); if (hsubpixel) hpixels = hpixels*3 + 8; info.width = hpixels; info.height = TRUNC(top - bottom); info.x = -TRUNC(left); info.y = TRUNC(top); info.xOff = TRUNC(ROUND(slot->advance.x)); info.yOff = 0; if (hsubpixel) { info.width /= 3; info.x += 1; } int pitch = (format == Format_Mono ? ((info.width + 31) & ~31) >> 3 : (format == Format_A8 ? (info.width + 3) & ~3 : info.width * 4)); int size = pitch * info.height; uchar *glyph_buffer = new uchar[size]; if (slot->format == FT_GLYPH_FORMAT_OUTLINE) { FT_Bitmap bitmap; bitmap.rows = info.height*vfactor; bitmap.width = hpixels; bitmap.pitch = format == Format_Mono ? (((info.width + 31) & ~31) >> 3) : ((bitmap.width + 3) & ~3); if (!hsubpixel && vfactor == 1) bitmap.buffer = glyph_buffer; else bitmap.buffer = new uchar[bitmap.rows*bitmap.pitch]; memset(bitmap.buffer, 0, bitmap.rows*bitmap.pitch); bitmap.pixel_mode = format == Format_Mono ? ft_pixel_mode_mono : ft_pixel_mode_grays; FT_Matrix matrix; matrix.xx = (hsubpixel ? 3 : 1) << 16; matrix.yy = vfactor << 16; matrix.yx = matrix.xy = 0; FT_Outline_Transform(&slot->outline, &matrix); FT_Outline_Translate (&slot->outline, (hsubpixel ? -3*left +(4<<6) : -left), -bottom*vfactor); FT_Outline_Get_Bitmap(library, &slot->outline, &bitmap); if (hsubpixel) { Q_ASSERT (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY); Q_ASSERT(antialias); const uchar *src = bitmap.buffer; uchar *convoluted = new uchar[bitmap.rows*bitmap.pitch]; uchar *c = convoluted; // convolute the bitmap with a triangle filter to get rid of color fringes // If we take account for a gamma value of 2, we end up with // weights of 1, 4, 9, 4, 1. We use an approximation of 1, 3, 8, 3, 1 here, // as this nicely sums up to 16 :) int h = info.height; while (h--) { c[0] = c[1] = 0; // for (int x = 2; x < bitmap.width - 2; ++x) { uint sum = src[x-2] + 3*src[x-1] + 8*src[x] + 3*src[x+1] + src[x+2]; c[x] = (uchar) (sum >> 4); } c[bitmap.width - 2] = c[bitmap.width -1] = 0; src += bitmap.pitch; c += bitmap.pitch; } uint *dst = (uint *)glyph_buffer; src = convoluted; h = info.height; if (subpixelType == QFontEngineFT::Subpixel_RGB) { while (h--) { uint *dd = dst; for (int x = 1; x < bitmap.width - 1; x += 3) { uint red = src[x]; uint green = src[x+1]; uint blue = src[x+2]; uint alpha = green; uint res = (alpha << 24) + (red << 16) + (green << 8) + blue; *dd = res; ++dd; } dst += info.width; src += bitmap.pitch; } } else { while (h--) { uint *dd = dst; for (int x = 1; x < bitmap.width - 1; x += 3) { uint blue = src[x]; uint green = src[x+1]; uint red = src[x+2]; uint alpha = green; uint res = (alpha << 24) + (red << 16) + (green << 8) + blue; *dd = res; ++dd; } dst += info.width; src += bitmap.pitch; } } delete [] convoluted; delete [] bitmap.buffer; } else if (vfactor != 1) { uchar *src = bitmap.buffer; size = info.width * 4 * info.height; uint *dst = (uint *)glyph_buffer; int h = info.height; if (subpixelType == QFontEngineFT::Subpixel_VRGB) { while (h--) { for (int x = 0; x < info.width; x++) { uint red = src[x]; uint green = src[x+bitmap.pitch]; uint blue = 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -