📄 qfontengine.cpp
字号:
painter->save(); painter->setBrush(Qt::NoBrush); QPen pen = painter->pen(); pen.setWidthF(lineThickness().toReal()); painter->setPen(pen); for (int k = 0; k < positions.size(); k++) painter->drawRect(QRectF(positions[k].toPointF(), s)); painter->restore();}#endifglyph_metrics_t QFontEngineBox::boundingBox(glyph_t){ return glyph_metrics_t(0, _size, _size, _size, _size, 0);}QFixed QFontEngineBox::ascent() const{ return _size;}QFixed QFontEngineBox::descent() const{ return 0;}QFixed QFontEngineBox::leading() const{ QFixed l = _size * QFixed::fromReal(0.15); return l.ceil();}qreal QFontEngineBox::maxCharWidth() const{ return _size;}#ifdef Q_WS_X11int QFontEngineBox::cmap() const{ return -1;}#endifconst char *QFontEngineBox::name() const{ return "null";}bool QFontEngineBox::canRender(const QChar *, int){ return true;}QFontEngine::Type QFontEngineBox::type() const{ return Box;}// ------------------------------------------------------------------// Multi engine// ------------------------------------------------------------------static inline uchar highByte(glyph_t glyph){ return glyph >> 24; }// strip high byte from glyphstatic inline glyph_t stripped(glyph_t glyph){ return glyph & 0x00ffffff; }QFontEngineMulti::QFontEngineMulti(int engineCount){ engines.fill(0, engineCount); cache_cost = 0;}QFontEngineMulti::~QFontEngineMulti(){ for (int i = 0; i < engines.size(); ++i) { QFontEngine *fontEngine = engines.at(i); if (fontEngine) { fontEngine->ref.deref(); if (fontEngine->cache_count == 0 && fontEngine->ref == 0) delete fontEngine; } }}bool QFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const{ int ng = *nglyphs; if (!engine(0)->stringToCMap(str, len, glyphs, &ng, flags)) return false; int glyph_pos = 0; for (int i = 0; i < len; ++i) { bool surrogate = (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00 && i < len-1 && str[i+1].unicode() >= 0xdc00 && str[i+1].unicode() < 0xe000); if (glyphs[glyph_pos].glyph == 0) { QGlyphLayout tmp = glyphs[glyph_pos]; for (int x = 1; x < engines.size(); ++x) { QFontEngine *engine = engines.at(x); if (!engine) { const_cast<QFontEngineMulti *>(this)->loadEngine(x); engine = engines.at(x); } Q_ASSERT(engine != 0); if (engine->type() == Box) continue; glyphs[glyph_pos].advance = glyphs[glyph_pos].offset = QFixedPoint(); int num = 2; engine->stringToCMap(str + i, surrogate ? 2 : 1, glyphs + glyph_pos, &num, flags); Q_ASSERT(num == 1); // surrogates only give 1 glyph if (glyphs[glyph_pos].glyph) { // set the high byte to indicate which engine the glyph came from glyphs[glyph_pos].glyph |= (x << 24); break; } } // ensure we use metrics from the 1st font when we use the fallback image. if (!glyphs[glyph_pos].glyph) glyphs[glyph_pos] = tmp; } if (surrogate) ++i; ++glyph_pos; } *nglyphs = ng; return true;}glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout *glyphs_const, int numGlyphs){ if (numGlyphs <= 0) return glyph_metrics_t(); glyph_metrics_t overall; QGlyphLayout *glyphs = const_cast<QGlyphLayout *>(glyphs_const); int which = highByte(glyphs[0].glyph); int start = 0; int end, i; for (end = 0; end < numGlyphs; ++end) { const int e = highByte(glyphs[end].glyph); if (e == which) continue; // set the high byte to zero for (i = start; i < end; ++i) glyphs[i].glyph = stripped(glyphs[i].glyph); // merge the bounding box for this run const glyph_metrics_t gm = engine(which)->boundingBox(glyphs + start, end - start); overall.x = qMin(overall.x, gm.x); overall.y = qMin(overall.y, gm.y); overall.width = overall.xoff + gm.width; overall.height = qMax(overall.height + overall.y, gm.height + gm.y) - qMin(overall.y, gm.y); overall.xoff += gm.xoff; overall.yoff += gm.yoff; // reset the high byte for all glyphs const int hi = which << 24; for (i = start; i < end; ++i) glyphs[i].glyph = hi | glyphs[i].glyph; // change engine start = end; which = e; } // set the high byte to zero for (i = start; i < end; ++i) glyphs[i].glyph = stripped(glyphs[i].glyph); // merge the bounding box for this run const glyph_metrics_t gm = engine(which)->boundingBox(glyphs + start, end - start); overall.x = qMin(overall.x, gm.x); overall.y = qMin(overall.y, gm.y); overall.width = overall.xoff + gm.width; overall.height = qMax(overall.height + overall.y, gm.height + gm.y) - qMin(overall.y, gm.y); overall.xoff += gm.xoff; overall.yoff += gm.yoff; // reset the high byte for all glyphs const int hi = which << 24; for (i = start; i < end; ++i) glyphs[i].glyph = hi | glyphs[i].glyph; return overall;}void QFontEngineMulti::addOutlineToPath(qreal x, qreal y, const QGlyphLayout *glyphs_const, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags flags){ if (numGlyphs <= 0) return; QGlyphLayout *glyphs = const_cast<QGlyphLayout *>(glyphs_const); int which = highByte(glyphs[0].glyph); int start = 0; int end, i; if (flags & QTextItem::RightToLeft) { for (int gl = 0; gl < numGlyphs; gl++) { x += glyphs[gl].advance.x.toReal(); y += glyphs[gl].advance.y.toReal(); } } for (end = 0; end < numGlyphs; ++end) { const int e = highByte(glyphs[end].glyph); if (e == which) continue; if (flags & QTextItem::RightToLeft) { for (i = start; i < end; ++i) { x -= glyphs[i].advance.x.toReal(); y -= glyphs[i].advance.y.toReal(); } } // set the high byte to zero for (i = start; i < end; ++i) glyphs[i].glyph = stripped(glyphs[i].glyph); engine(which)->addOutlineToPath(x, y, glyphs + start, end - start, path, flags); // reset the high byte for all glyphs and update x and y const int hi = which << 24; for (i = start; i < end; ++i) glyphs[i].glyph = hi | glyphs[i].glyph; if (!(flags & QTextItem::RightToLeft)) { for (i = start; i < end; ++i) { x += glyphs[i].advance.x.toReal(); y += glyphs[i].advance.y.toReal(); } } // change engine start = end; which = e; } if (flags & QTextItem::RightToLeft) { for (i = start; i < end; ++i) { x -= glyphs[i].advance.x.toReal(); y -= glyphs[i].advance.y.toReal(); } } // set the high byte to zero for (i = start; i < end; ++i) glyphs[i].glyph = stripped(glyphs[i].glyph); engine(which)->addOutlineToPath(x, y, glyphs + start, end - start, path, flags); // reset the high byte for all glyphs const int hi = which << 24; for (i = start; i < end; ++i) glyphs[i].glyph = hi | glyphs[i].glyph;}void QFontEngineMulti::recalcAdvances(int numGlyphs, QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const{ if (numGlyphs <= 0) return; int which = highByte(glyphs[0].glyph); int start = 0; int end, i; for (end = 0; end < numGlyphs; ++end) { const int e = highByte(glyphs[end].glyph); if (e == which) continue; // set the high byte to zero for (i = start; i < end; ++i) glyphs[i].glyph = stripped(glyphs[i].glyph); engine(which)->recalcAdvances(end - start, glyphs + start, flags); // reset the high byte for all glyphs and update x and y const int hi = which << 24; for (i = start; i < end; ++i) glyphs[i].glyph = hi | glyphs[i].glyph; // change engine start = end; which = e; } // set the high byte to zero for (i = start; i < end; ++i) glyphs[i].glyph = stripped(glyphs[i].glyph); engine(which)->recalcAdvances(end - start, glyphs + start, flags); // reset the high byte for all glyphs const int hi = which << 24; for (i = start; i < end; ++i) glyphs[i].glyph = hi | glyphs[i].glyph;}void QFontEngineMulti::doKerning(int numGlyphs, QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const{ if (numGlyphs <= 0) return; int which = highByte(glyphs[0].glyph); int start = 0; int end, i; for (end = 0; end < numGlyphs; ++end) { const int e = highByte(glyphs[end].glyph); if (e == which) continue; // set the high byte to zero for (i = start; i < end; ++i) glyphs[i].glyph = stripped(glyphs[i].glyph); engine(which)->doKerning(end - start, glyphs + start, flags); // reset the high byte for all glyphs and update x and y const int hi = which << 24; for (i = start; i < end; ++i) glyphs[i].glyph = hi | glyphs[i].glyph; // change engine start = end; which = e; } // set the high byte to zero for (i = start; i < end; ++i) glyphs[i].glyph = stripped(glyphs[i].glyph); engine(which)->doKerning(end - start, glyphs + start, flags); // reset the high byte for all glyphs const int hi = which << 24; for (i = start; i < end; ++i) glyphs[i].glyph = hi | glyphs[i].glyph;}glyph_metrics_t QFontEngineMulti::boundingBox(glyph_t glyph){ const int which = highByte(glyph); Q_ASSERT(which < engines.size()); return engine(which)->boundingBox(stripped(glyph));}QFixed QFontEngineMulti::ascent() const{ return engine(0)->ascent(); }QFixed QFontEngineMulti::descent() const{ return engine(0)->descent(); }QFixed QFontEngineMulti::leading() const{ return engine(0)->leading();}QFixed QFontEngineMulti::xHeight() const{ return engine(0)->xHeight();}QFixed QFontEngineMulti::averageCharWidth() const{ return engine(0)->averageCharWidth();}QFixed QFontEngineMulti::lineThickness() const{ return engine(0)->lineThickness();}QFixed QFontEngineMulti::underlinePosition() const{ return engine(0)->underlinePosition();}qreal QFontEngineMulti::maxCharWidth() const{ return engine(0)->maxCharWidth();}qreal QFontEngineMulti::minLeftBearing() const{ return engine(0)->minLeftBearing();}qreal QFontEngineMulti::minRightBearing() const{ return engine(0)->minRightBearing();}bool QFontEngineMulti::canRender(const QChar *string, int len){ if (engine(0)->canRender(string, len)) return true; QVarLengthArray<QGlyphLayout, 256> glyphs(len); int nglyphs = len; if (stringToCMap(string, len, glyphs.data(), &nglyphs, QTextEngine::GlyphIndicesOnly) == false) { glyphs.resize(nglyphs); stringToCMap(string, len, glyphs.data(), &nglyphs, QTextEngine::GlyphIndicesOnly); } bool allExist = true; for (int i = 0; i < nglyphs; i++) { if (!glyphs[i].glyph) { allExist = false; break; } } return allExist;}QFontEngine *QFontEngineMulti::engine(int at) const{ Q_ASSERT(at < engines.size()); return engines.at(at);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -