📄 qfontengine.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include <private/qfontengine_p.h>#include "qbitmap.h"#include "qpainter.h"#include "qpainterpath.h"#include "qvarlengtharray.h"#include <math.h>#ifndef Q_WS_WINQFontEngine::~QFontEngine(){}QFixed QFontEngine::lineThickness() const{ // ad hoc algorithm int score = fontDef.weight * fontDef.pixelSize; int lw = score / 700; // looks better with thicker line for small pointsizes if (lw < 2 && score >= 1050) lw = 2; if (lw == 0) lw = 1; return lw;}QFixed QFontEngine::underlinePosition() const{ return ((lineThickness() * 2) + 3) / 6;}#endifQFixed QFontEngine::xHeight() const{ QGlyphLayout glyphs[8]; int nglyphs = 7; QChar x((ushort)'x'); stringToCMap(&x, 1, glyphs, &nglyphs, 0); glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyphs[0].glyph); return bb.height;}void QFontEngine::addGlyphsToPath(glyph_t *, QFixedPoint *, int , QPainterPath *, QTextItem::RenderFlags){}void QFontEngine::getGlyphPositions(const QGlyphLayout *glyphs, int nglyphs, const QMatrix &matrix, QTextItem::RenderFlags flags, QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions){ QFixed xpos = QFixed::fromReal(matrix.dx()); QFixed ypos = QFixed::fromReal(matrix.dy()); bool transform = matrix.m11() != 1. || matrix.m12() != 0. || matrix.m21() != 0. || matrix.m22() != 1.; int current = 0; if (flags & QTextItem::RightToLeft) { int i = nglyphs; int totalKashidas = 0; while(i--) { xpos += glyphs[i].advance.x + QFixed::fromFixed(glyphs[i].space_18d6); ypos += glyphs[i].advance.y; totalKashidas += glyphs[i].nKashidas; } positions.resize(nglyphs+totalKashidas); glyphs_out.resize(nglyphs+totalKashidas); i = 0; while(i < nglyphs) { if (glyphs[i].attributes.dontPrint) { ++i; continue; } xpos -= glyphs[i].advance.x; ypos -= glyphs[i].advance.y; QFixed gpos_x = xpos + glyphs[i].offset.x; QFixed gpos_y = ypos + glyphs[i].offset.y; if (transform) { QPointF gpos(gpos_x.toReal(), gpos_y.toReal()); gpos = gpos * matrix; gpos_x = QFixed::fromReal(gpos.x()); gpos_y = QFixed::fromReal(gpos.y()); } positions[current].x = gpos_x; positions[current].y = gpos_y; glyphs_out[current] = glyphs[i].glyph; ++current; if (glyphs[i].nKashidas) { QChar ch(0x640); // Kashida character QGlyphLayout g[8]; int nglyphs = 7; stringToCMap(&ch, 1, g, &nglyphs, 0); for (uint k = 0; k < glyphs[i].nKashidas; ++k) { xpos -= g[0].advance.x; ypos -= g[0].advance.y; QFixed gpos_x = xpos + glyphs[i].offset.x; QFixed gpos_y = ypos + glyphs[i].offset.y; if (transform) { QPointF gpos(gpos_x.toReal(), gpos_y.toReal()); gpos = gpos * matrix; gpos_x = QFixed::fromReal(gpos.x()); gpos_y = QFixed::fromReal(gpos.y()); } positions[current].x = gpos_x; positions[current].y = gpos_y; glyphs_out[current] = g[0].glyph; ++current; } } else { xpos -= QFixed::fromFixed(glyphs[i].space_18d6); } ++i; } } else { positions.resize(nglyphs); glyphs_out.resize(nglyphs); int i = 0; while (i < nglyphs) { if (glyphs[i].attributes.dontPrint) { ++i; continue; } QFixed gpos_x = xpos + glyphs[i].offset.x; QFixed gpos_y = ypos + glyphs[i].offset.y; if (transform) { QPointF gpos(gpos_x.toReal(), gpos_y.toReal()); gpos = gpos * matrix; gpos_x = QFixed::fromReal(gpos.x()); gpos_y = QFixed::fromReal(gpos.y()); } positions[current].x = gpos_x; positions[current].y = gpos_y; glyphs_out[current] = glyphs[i].glyph; xpos += glyphs[i].advance.x + QFixed::fromFixed(glyphs[i].space_18d6); ypos += glyphs[i].advance.y; ++i; ++current; } } positions.resize(current); glyphs_out.resize(current); Q_ASSERT(positions.size() == glyphs_out.size());}void QFontEngine::addOutlineToPath(qreal x, qreal y, const QGlyphLayout *glyphs, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags flags){ if (!numGlyphs) return; QVarLengthArray<QFixedPoint> positions; QVarLengthArray<glyph_t> positioned_glyphs; QMatrix matrix; matrix.translate(x, y); getGlyphPositions(glyphs, numGlyphs, matrix, flags, positioned_glyphs, positions); addGlyphsToPath(positioned_glyphs.data(), positions.data(), positioned_glyphs.size(), path, flags);}void QFontEngine::addBitmapFontToPath(qreal x, qreal y, const QGlyphLayout *glyphs, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags flags){ glyph_metrics_t metrics = boundingBox(glyphs, numGlyphs); QBitmap bm(metrics.width.toInt(), metrics.height.toInt()); QPainter p(&bm); p.fillRect(0, 0, metrics.width.toInt(), metrics.height.toInt(), Qt::color0); p.setPen(Qt::color1); QTextItemInt item; item.flags = flags; item.ascent = -metrics.y; item.descent = metrics.height - item.ascent; item.width = metrics.width; item.chars = 0; item.num_chars = 0; item.logClusters = 0; item.glyphs = const_cast<QGlyphLayout *>(glyphs); item.num_glyphs = numGlyphs; item.fontEngine = this; item.f = 0; p.drawTextItem(QPointF(0, item.ascent.toReal()), item); p.end(); QRegion region(bm); region.translate(qRound(x), qRound(y - item.ascent.toReal())); path->addRegion(region);}QFontEngine::Properties QFontEngine::properties() const{ Properties p; QByteArray psname = fontDef.family.toUtf8(); psname.replace(" ", ""); p.postscriptName = psname; p.ascent = ascent(); p.descent = descent(); p.leading = leading(); p.emSquare = p.ascent; p.boundingBox = QRectF(0, p.ascent.toReal(), maxCharWidth(), (p.ascent + p.descent).toReal()); p.italicAngle = 0; p.capHeight = p.ascent; p.lineWidth = lineThickness(); return p;}void QFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) { *metrics = boundingBox(glyph); QFixedPoint p; p.x = 0; p.y = 0; addGlyphsToPath(&glyph, &p, 1, path, QFlag(0));}// ------------------------------------------------------------------// The box font engine// ------------------------------------------------------------------#ifdef Q_WS_WIN#include "qt_windows.h"#endifQFontEngineBox::QFontEngineBox(int size) : _size(size){ cache_cost = sizeof(QFontEngineBox);#ifdef Q_WS_WIN#ifndef Q_OS_TEMP hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);#endif stockFont = true; ttf = false; cmap = 0; script_cache = 0;#endif}QFontEngineBox::~QFontEngineBox(){}bool QFontEngineBox::stringToCMap(const QChar *, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags) const{ if (*nglyphs < len) { *nglyphs = len; return false; } for (int i = 0; i < len; i++) { glyphs[i].glyph = 0; glyphs[i].advance.x = _size; glyphs[i].advance.y = 0; } *nglyphs = len; return true;}void QFontEngineBox::addOutlineToPath(qreal x, qreal y, const QGlyphLayout *glyphs, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags flags){ if (!numGlyphs) return; QVarLengthArray<QFixedPoint> positions; QVarLengthArray<glyph_t> positioned_glyphs; QMatrix matrix; matrix.translate(x, y); getGlyphPositions(glyphs, numGlyphs, matrix, flags, positioned_glyphs, positions); addGlyphsToPath(positioned_glyphs.data(), positions.data(), positioned_glyphs.size(), path, flags); int size = qRound(ascent()); QSize s(size - 3, size - 3); for (int k = 0; k < positions.size(); k++) path->addRect(QRectF(positions[k].toPointF(), s));}glyph_metrics_t QFontEngineBox::boundingBox(const QGlyphLayout *, int numGlyphs){ glyph_metrics_t overall; overall.width = _size*numGlyphs; overall.height = _size; overall.xoff = overall.width; return overall;}#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC)void QFontEngineBox::draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si){ Q_UNUSED(p); Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(si); //qDebug("QFontEngineBox::draw(%d, %d, numglyphs=%d", x, y, numGlyphs);}#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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -