⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qfontengine.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************** Copyright (C) 1992-2007 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://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** 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 <qdebug.h>#include <private/qfontengine_p.h>#include "qbitmap.h"#include "qpainter.h"#include "qpainterpath.h"#include "qvarlengtharray.h"#include <private/qpdf_p.h>#include <private/qmath_p.h>#include <qendian.h>QFontEngine::QFontEngine()    : QObject(){    ref = 0;    cache_count = 0;    fsType = 0;#if defined(Q_WS_WIN)    script_cache = 0;    cmap = 0;#endif    symbol = false;}#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, QTextEngine::GlyphIndicesOnly);    glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyphs[0].glyph);    return bb.height;}QFixed QFontEngine::averageCharWidth() const{    QGlyphLayout glyphs[8];    int nglyphs = 7;    QChar x((ushort)'x');    stringToCMap(&x, 1, glyphs, &nglyphs, QTextEngine::GlyphIndicesOnly);    glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyphs[0].glyph);    return bb.xoff;}void QFontEngine::getGlyphPositions(const QGlyphLayout *glyphs, int nglyphs, const QTransform &matrix, QTextItem::RenderFlags flags,                                    QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions){    QFixed xpos;    QFixed ypos;    const bool transform = matrix.m11() != 1.                           || matrix.m12() != 0.                           || matrix.m21() != 0.                           || matrix.m22() != 1.;    if (!transform) {        xpos = QFixed::fromReal(matrix.dx());        ypos = QFixed::fromReal(matrix.dy());    }    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;        if (!transform) {            while (i < nglyphs) {                if (!glyphs[i].attributes.dontPrint) {                    positions[current].x = xpos + glyphs[i].offset.x;                    positions[current].y = ypos + glyphs[i].offset.y;                    glyphs_out[current] = glyphs[i].glyph;                    xpos += glyphs[i].advance.x + QFixed::fromFixed(glyphs[i].space_18d6);                    ypos += glyphs[i].advance.y;                    ++current;                }                ++i;            }        } else {            positions.resize(nglyphs);            glyphs_out.resize(nglyphs);            int i = 0;            while (i < nglyphs) {                if (!glyphs[i].attributes.dontPrint) {                    QFixed gpos_x = xpos + glyphs[i].offset.x;                    QFixed gpos_y = ypos + glyphs[i].offset.y;                    QPointF gpos(gpos_x.toReal(), gpos_y.toReal());                    gpos = gpos * matrix;                    positions[current].x = QFixed::fromReal(gpos.x());                    positions[current].y = QFixed::fromReal(gpos.y());                    glyphs_out[current] = glyphs[i].glyph;                    xpos += glyphs[i].advance.x + QFixed::fromFixed(glyphs[i].space_18d6);                    ypos += glyphs[i].advance.y;                    ++current;                }                ++i;            }        }    }    positions.resize(current);    glyphs_out.resize(current);    Q_ASSERT(positions.size() == glyphs_out.size());}glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout *glyphs, int numGlyphs){    glyph_metrics_t overall;    QFixed ymax = 0;    QFixed xmax = 0;    for (int i = 0; i < numGlyphs; i++) {        glyph_metrics_t bb = boundingBox(glyphs[i].glyph);        QFixed x = overall.xoff + glyphs[i].offset.x + bb.x;        QFixed y = overall.yoff + glyphs[i].offset.y + bb.y;        overall.x = qMin(overall.x, x);        overall.y = qMin(overall.y, y);        xmax = qMax(xmax, x + bb.width);        ymax = qMax(ymax, y + bb.height);        overall.xoff += bb.xoff;        overall.yoff += bb.yoff;    }    overall.height = qMax(overall.height, ymax - overall.y);    overall.width = xmax - overall.x;    return overall;}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;    QTransform matrix;    matrix.translate(x, y);    getGlyphPositions(glyphs, numGlyphs, matrix, flags, positioned_glyphs, positions);    addGlyphsToPath(positioned_glyphs.data(), positions.data(), positioned_glyphs.size(), path, flags);}#define GRID(x, y) grid[(y)*(w+1) + (x)]#define SET(x, y) (*(image_data + (y)*bpl + ((x) >> 3)) & (0x80 >> ((x) & 7)))enum { EdgeRight = 0x1,       EdgeDown = 0x2,       EdgeLeft = 0x4,       EdgeUp = 0x8};static void collectSingleContour(qreal x0, qreal y0, uint *grid, int x, int y, int w, int h, QPainterPath *path){    Q_UNUSED(h);    path->moveTo(x + x0, y + y0);    while (GRID(x, y)) {        if (GRID(x, y) & EdgeRight) {            while (GRID(x, y) & EdgeRight) {                GRID(x, y) &= ~EdgeRight;                ++x;            }            Q_ASSERT(x <= w);            path->lineTo(x + x0, y + y0);            continue;        }        if (GRID(x, y) & EdgeDown) {            while (GRID(x, y) & EdgeDown) {                GRID(x, y) &= ~EdgeDown;                ++y;            }            Q_ASSERT(y <= h);            path->lineTo(x + x0, y + y0);            continue;        }        if (GRID(x, y) & EdgeLeft) {            while (GRID(x, y) & EdgeLeft) {                GRID(x, y) &= ~EdgeLeft;                --x;            }            Q_ASSERT(x >= 0);            path->lineTo(x + x0, y + y0);            continue;        }        if (GRID(x, y) & EdgeUp) {            while (GRID(x, y) & EdgeUp) {                GRID(x, y) &= ~EdgeUp;                --y;            }            Q_ASSERT(y >= 0);            path->lineTo(x + x0, y + y0);            continue;        }    }    path->closeSubpath();}void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path){    uint *grid = new uint[(w+1)*(h+1)];    // set up edges    for (int y = 0; y <= h; ++y) {        for (int x = 0; x <= w; ++x) {            bool topLeft = (x == 0)|(y == 0) ? false : SET(x - 1, y - 1);            bool topRight = (x == w)|(y == 0) ? false : SET(x, y - 1);            bool bottomLeft = (x == 0)|(y == h) ? false : SET(x - 1, y);            bool bottomRight = (x == w)|(y == h) ? false : SET(x, y);            GRID(x, y) = 0;            if ((!topRight) & bottomRight)                GRID(x, y) |= EdgeRight;            if ((!bottomRight) & bottomLeft)                GRID(x, y) |= EdgeDown;            if ((!bottomLeft) & topLeft)                GRID(x, y) |= EdgeLeft;            if ((!topLeft) & topRight)                GRID(x, y) |= EdgeUp;        }    }    // collect edges    for (int y = 0; y < h; ++y) {        for (int x = 0; x < w; ++x) {            if (!GRID(x, y))                continue;            // found start of a contour, follow it            collectSingleContour(x0, y0, grid, x, y, w, h, path);        }    }    delete [] grid;}#undef GRID#undef SETvoid QFontEngine::addBitmapFontToPath(qreal x, qreal y, const QGlyphLayout *glyphs, int numGlyphs,                                      QPainterPath *path, QTextItem::RenderFlags flags){    glyph_metrics_t metrics = boundingBox(glyphs, numGlyphs);    int w = metrics.width.toInt();    int h = metrics.height.toInt();    if (w <= 0 || h <= 0)        return;    QBitmap bm(w, h);    QPainter p(&bm);    p.fillRect(0, 0, w, h, 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(-metrics.x.toReal(), item.ascent.toReal()), item);    p.end();    QImage image = bm.toImage();    image = image.convertToFormat(QImage::Format_Mono);    const uchar *image_data = image.bits();    uint bpl = image.bytesPerLine();    qt_addBitmapToPath(x, y - item.ascent.toReal(), image_data, bpl, w, h, path);}void QFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nGlyphs,                                  QPainterPath *path, QTextItem::RenderFlags flags){    qreal x = positions[0].x.toReal();    qreal y = positions[0].y.toReal();    QVarLengthArray<QGlyphLayout> g(nGlyphs);    memset(g.data(), 0, nGlyphs*sizeof(QGlyphLayout));    for (int i = 0; i < nGlyphs; ++i) {        g[i].glyph = glyphs[i];        if (i < nGlyphs - 1) {            g[i].advance.x = positions[i+1].x - positions[i].x;            g[i].advance.y = positions[i+1].y - positions[i].y;        } else {            g[i].advance.x = QFixed::fromReal(maxCharWidth());            g[i].advance.y = 0;        }    }    addBitmapFontToPath(x, y, g.data(), nGlyphs, path, flags);}QImage QFontEngine::alphaMapForGlyph(glyph_t glyph){    glyph_metrics_t gm = boundingBox(glyph);    int glyph_x = qFloor(gm.x.toReal());    int glyph_y = qFloor(gm.y.toReal());    int glyph_width = qCeil((gm.x + gm.width).toReal()) -  glyph_x;    int glyph_height = qCeil((gm.y + gm.height).toReal()) - glyph_y;    if (glyph_width <= 0 || glyph_height <= 0)        return QImage();    QFixedPoint pt;    pt.x = 0;    pt.y = -glyph_y; // the baseline    QPainterPath path;    QImage im(glyph_width + qAbs(glyph_x) + 4, glyph_height, QImage::Format_ARGB32_Premultiplied);    im.fill(Qt::transparent);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -