📄 qfontengine_x11.cpp
字号:
overall.height = ymax - overall.y; overall.width = xmax - overall.x; return overall;}glyph_metrics_t QFontEngineXLFD::boundingBox(glyph_t glyph){ glyph_metrics_t gm; XCharStruct *xcs = charStruct(_fs, glyph); if (xcs) { gm = glyph_metrics_t(xcs->lbearing, -xcs->ascent, xcs->rbearing- xcs->lbearing, xcs->ascent + xcs->descent, xcs->width, 0); } else { QFixed size = ascent(); gm = glyph_metrics_t(0, size, size, size, size, 0); } return gm;}QFixed QFontEngineXLFD::ascent() const{ return _fs->ascent;}QFixed QFontEngineXLFD::descent() const{ return (_fs->descent-1);}QFixed QFontEngineXLFD::leading() const{ QFixed l = QFixed(qMin<int>(_fs->ascent, _fs->max_bounds.ascent) + qMin<int>(_fs->descent, _fs->max_bounds.descent)) * QFixed::fromReal(0.15); return l.ceil();}qreal QFontEngineXLFD::maxCharWidth() const{ return _fs->max_bounds.width;}// Loads the font for the specified scriptstatic inline int maxIndex(XFontStruct *f) { return (((f->max_byte1 - f->min_byte1) * (f->max_char_or_byte2 - f->min_char_or_byte2 + 1)) + f->max_char_or_byte2 - f->min_char_or_byte2);}qreal QFontEngineXLFD::minLeftBearing() const{ if (lbearing == SHRT_MIN) { if (_fs->per_char) { XCharStruct *cs = _fs->per_char; int nc = maxIndex(_fs) + 1; int mx = cs->lbearing; for (int c = 1; c < nc; c++) { // ignore the bearings for characters whose ink is // completely outside the normal bounding box if ((cs[c].lbearing <= 0 && cs[c].rbearing <= 0) || (cs[c].lbearing >= cs[c].width && cs[c].rbearing >= cs[c].width)) continue; int nmx = cs[c].lbearing; if (nmx < mx) mx = nmx; } ((QFontEngineXLFD *)this)->lbearing = mx; } else ((QFontEngineXLFD *)this)->lbearing = _fs->min_bounds.lbearing; } return lbearing;}qreal QFontEngineXLFD::minRightBearing() const{ if (rbearing == SHRT_MIN) { if (_fs->per_char) { XCharStruct *cs = _fs->per_char; int nc = maxIndex(_fs) + 1; int mx = cs->rbearing; for (int c = 1; c < nc; c++) { // ignore the bearings for characters whose ink is // completely outside the normal bounding box if ((cs[c].lbearing <= 0 && cs[c].rbearing <= 0) || (cs[c].lbearing >= cs[c].width && cs[c].rbearing >= cs[c].width)) continue; int nmx = cs[c].rbearing; if (nmx < mx) mx = nmx; } ((QFontEngineXLFD *)this)->rbearing = mx; } else ((QFontEngineXLFD *)this)->rbearing = _fs->min_bounds.rbearing; } return rbearing;}const char *QFontEngineXLFD::name() const{ return _name;}bool QFontEngineXLFD::canRender(const QChar *string, int len){ QVarLengthArray<QGlyphLayout, 256> glyphs(len); int nglyphs = len; if (stringToCMap(string, len, glyphs.data(), &nglyphs, 0) == false) { glyphs.resize(nglyphs); stringToCMap(string, len, glyphs.data(), &nglyphs, 0); } bool allExist = true; for (int i = 0; i < nglyphs; i++) { if (!glyphs[i].glyph || !charStruct(_fs, glyphs[i].glyph)) { allExist = false; break; } } return allExist;}void QFontEngineXLFD::addOutlineToPath(qreal x, qreal y, const QGlyphLayout *glyphs, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags flags){ addBitmapFontToPath(x, y, glyphs, numGlyphs, path, flags);}QFontEngine::FaceId QFontEngineXLFD::faceId() const{#ifndef QT_NO_FREETYPE if (face_id.index == -1) { face_id = ::fontFile(_name, &freetype, &synth); if (_codec) face_id.encoding = _codec->mibEnum(); if (freetype) const_cast<QFontEngineXLFD *>(this)->fsType = freetype->fsType(); }#endif return face_id;}QFontEngine::Properties QFontEngineXLFD::properties() const{ if (face_id.index == -1) (void)faceId();#ifndef QT_NO_FREETYPE if (freetype) return freetype->properties();#endif return Properties();}#ifndef QT_NO_FREETYPEvoid QFontEngineXLFD::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics){ if (face_id.index == -1) (void)faceId(); if (!freetype) return; freetype->lock(); FT_Face face = freetype->face; FT_Set_Transform(face, 0, 0); glyph = glyphIndexToFreetypeGlyphIndex(glyph); 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-bottom); metrics->x = QFixed::fromFixed(left); metrics->y = QFixed::fromFixed(-top); metrics->xoff = QFixed::fromFixed(face->glyph->advance.x); ::addBitmapToPath(face->glyph, p, path); } else { metrics->width = right-left; metrics->height = top-bottom; metrics->x = left; metrics->y = -top; metrics->xoff = face->glyph->advance.x; ::addGlyphToPath(face->glyph, p, path, true /* no_scale */); } FT_Set_Transform(face, &freetype->matrix, 0); freetype->unlock();}#endif // QT_NO_FREETYPEQByteArray QFontEngineXLFD::getSfntTable(uint tag) const{#ifndef QT_NO_FREETYPE if (face_id.index == -1) (void)faceId(); if (!freetype) return QByteArray(); return freetype->getSfntTable(tag);#else Q_UNUSED(tag); return QByteArray();#endif}int QFontEngineXLFD::synthesized() const{ return synth;}#ifndef QT_NO_FREETYPEFT_Face QFontEngineXLFD::non_locked_face() const{ return freetype ? freetype->face : 0;}uint QFontEngineXLFD::toUnicode(glyph_t g) const{ if (_codec) { QTextCodec::ConverterState state; state.flags = QTextCodec::ConvertInvalidToNull; uchar data[2]; int l = 1; if (g > 255) { data[0] = (g >> 8); data[1] = (g & 255); l = 2; } else { data[0] = g; } QString s = _codec->toUnicode((char *)data, l, &state); Q_ASSERT(s.length() == 1); g = s.at(0).unicode(); } return g;}glyph_t QFontEngineXLFD::glyphIndexToFreetypeGlyphIndex(glyph_t g) const{ return FT_Get_Char_Index(freetype->face, toUnicode(g));}#endif#ifndef QT_NO_FONTCONFIG// ------------------------------------------------------------------// Multi FT engine// ------------------------------------------------------------------QFontEngineMultiFT::QFontEngineMultiFT(FcFontSet *fs, int s, const QFontDef &request) : QFontEngineMulti(fs->nfont), fontSet(fs), screen(s){ fontDef = request; loadEngine(0); fontDef = engines[0]->fontDef; cache_cost = 100;}QFontEngineMultiFT::~QFontEngineMultiFT(){ FcFontSetDestroy(fontSet);}void QFontEngineMultiFT::loadEngine(int at){ Q_ASSERT(at < engines.size()); Q_ASSERT(engines.at(at) == 0); FcPattern *pattern = fontSet->fonts[at]; extern QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &); QFontDef fontDef = qt_FcPatternToQFontDef(fontSet->fonts[at], this->fontDef); // note: we use -1 for the script to make sure that we keep real // FT engines separate from Multi engines in the font cache QFontCache::Key key(fontDef, -1, screen); QFontEngine *fontEngine = QFontCache::instance->findEngine(key); if (!fontEngine) { FcConfigSubstitute(0, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult res; FcPattern *match = FcFontMatch(0, pattern, &res); QFontEngineFT *engine = new QFontEngineFT(match, fontDef, screen); if (engine->invalid()) delete engine; else fontEngine = engine; if (!fontEngine) { fontEngine = new QFontEngineBox(fontDef.pixelSize); fontEngine->fontDef = fontDef; } QFontCache::instance->insertEngine(key, fontEngine); } fontEngine->ref.ref(); engines[at] = fontEngine;}// ------------------------------------------------------------------// FT font engine// ------------------------------------------------------------------QFontEngineFT::Glyph::~Glyph(){ delete [] data;}static QFontEngine::FaceId face_id(FcPattern *pattern){ char *file_name; FcPatternGetString(pattern, FC_FILE, 0, (FcChar8 **)&file_name); int face_index; if (!FcPatternGetInteger(pattern, FC_INDEX, 0, &face_index)) face_index = 0; QFontEngine::FaceId face_id; face_id.filename = file_name; face_id.index = face_index; return face_id;}QFontEngineFT::QFontEngineFT(FcPattern *pattern, const QFontDef &fd, int screen){ cache_cost = 100; fontDef = fd; _pattern = pattern; transform = false; matrix.xx = 0x10000; matrix.yy = 0x10000; matrix.xy = 0; matrix.yx = 0;// FcPatternPrint(pattern); antialias = X11->fc_antialias; FcBool b; if (FcPatternGetBool(pattern, FC_ANTIALIAS, 0, &b) == FcResultMatch) antialias = b; if (FcPatternGetInteger(pattern, FC_RGBA, 0, &subpixel) == FcResultNoMatch) subpixel = X11->screens[screen].subpixel; if (!antialias || subpixel == FC_RGBA_UNKNOWN) subpixel = FC_RGBA_NONE;#ifdef FC_HINT_STYLE if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch) hint_style = X11->fc_hint_style;#endif autohint = false;#ifdef FC_AUTOHINT if (FcPatternGetBool(pattern, FC_AUTOHINT, 0, &b) == FcResultMatch) autohint = b;#endif face_id = ::face_id(pattern); freetype = QFreetypeFace::getFace(face_id); if (!freetype->charset) { FcCharSet *cs; FcPatternGetCharSet (pattern, FC_CHARSET, 0, &cs); freetype->charset = FcCharSetCopy(cs); } lbearing = rbearing = SHRT_MIN; freetype->computeSize(fontDef, &xsize, &ysize); outline_drawing = xsize > (64<<6) || ysize > (64<<6); 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -