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

📄 qfontengine_ft.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/******************************************************************************** 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 "qdir.h"#include "qmetatype.h"#include "qtextstream.h"#include "qvariant.h"#include "qfontengine_ft_p.h"#ifndef QT_NO_FREETYPE#include "qfile.h"#include "qabstractfileengine.h"#include "qopentype_p.h"#include <private/qpdf_p.h>#include <private/qmath_p.h>#include "qfontengine_ft_p.h"#include <ft2build.h>#include FT_FREETYPE_H#include FT_OUTLINE_H#include FT_TRUETYPE_TABLES_H#include FT_TYPE1_TABLES_H#include FT_GLYPH_H/* * Freetype 2.1.7 and earlier used width/height * for matching sizes in the BDF and PCF loaders. * This has been fixed for 2.1.8. */#if (FREETYPE_MAJOR*10000+FREETYPE_MINOR*100+FREETYPE_PATCH) >= 20105#define X_SIZE(face,i) ((face)->available_sizes[i].x_ppem)#define Y_SIZE(face,i) ((face)->available_sizes[i].y_ppem)#else#define X_SIZE(face,i) ((face)->available_sizes[i].width << 6)#define Y_SIZE(face,i) ((face)->available_sizes[i].height << 6)#endif#define FLOOR(x)    ((x) & -64)#define CEIL(x)	    (((x)+63) & -64)#define TRUNC(x)    ((x) >> 6)#define ROUND(x)    (((x)+32) & -64)// -------------------------- Freetype support ------------------------------static FT_Library library = 0;FT_Library qt_getFreetype(){    if (!library)        FT_Init_FreeType(&library);    return library;}static QHash<QFontEngine::FaceId, QFreetypeFace *> *freetypeFaces = 0;int QFreetypeFace::fsType() const{    int fsType = 0;    TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);    if (os2)        fsType = os2->fsType;    return fsType;}QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id){    if (face_id.filename.isEmpty())        return 0;    if (!library)        FT_Init_FreeType(&library);    if (!freetypeFaces)        freetypeFaces = new QHash<QFontEngine::FaceId, QFreetypeFace *>();    QFreetypeFace *freetype = freetypeFaces->value(face_id, 0);    if (!freetype) {        freetype = new QFreetypeFace;        FT_Face face;        QFile file(QString::fromUtf8(face_id.filename));        if (face_id.filename.startsWith(":qmemoryfonts/")) {            // from qfontdatabase.cpp            extern QByteArray qt_fontdata_from_index(int);            QByteArray idx = face_id.filename;            idx.remove(0, 14); // remove ':qmemoryfonts/'            bool ok = false;            freetype->fontData = qt_fontdata_from_index(idx.toInt(&ok));            if (!ok)                freetype->fontData = QByteArray();        } else if (!(file.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {            if (!file.open(QIODevice::ReadOnly)) {                delete freetype;                return 0;            }            freetype->fontData = file.readAll();        }        if (!freetype->fontData.isEmpty()) {            if (FT_New_Memory_Face(library, (const FT_Byte *)freetype->fontData.constData(), freetype->fontData.size(), face_id.index, &face)) {                delete freetype;                return 0;            }        } else if (FT_New_Face(library, face_id.filename, face_id.index, &face)) {            delete freetype;            return 0;        }        freetype->face = face;        freetype->ref = 0;        freetype->xsize = 0;        freetype->ysize = 0;        freetype->matrix.xx = 0x10000;        freetype->matrix.yy = 0x10000;        freetype->matrix.xy = 0;        freetype->matrix.yx = 0;        freetype->unicode_map = 0;        freetype->symbol_map = 0;#ifndef QT_NO_FONTCONFIG        freetype->charset = 0;#endif        memset(freetype->cmapCache, 0, sizeof(freetype->cmapCache));        for (int i = 0; i < freetype->face->num_charmaps; ++i) {            FT_CharMap cm = freetype->face->charmaps[i];            switch(cm->encoding) {            case ft_encoding_unicode:                freetype->unicode_map = cm;                break;            case ft_encoding_apple_roman:            case ft_encoding_latin_1:                if (!freetype->unicode_map || freetype->unicode_map->encoding != ft_encoding_unicode)                    freetype->unicode_map = cm;                break;            case ft_encoding_adobe_custom:            case ft_encoding_symbol:                if (!freetype->symbol_map)                    freetype->symbol_map = cm;                break;            default:                break;            }        }        if (!FT_IS_SCALABLE(freetype->face) && freetype->face->num_fixed_sizes == 1)            FT_Set_Char_Size (face, X_SIZE(freetype->face, 0), Y_SIZE(freetype->face, 0), 0, 0);# if 0        FcChar8 *name;        FcPatternGetString(pattern, FC_FAMILY, 0, &name);        qDebug("%s: using maps: default: %x unicode: %x, symbol: %x", name,               freetype->face->charmap ? freetype->face->charmap->encoding : 0,               freetype->unicode_map ? freetype->unicode_map->encoding : 0,               freetype->symbol_map ? freetype->symbol_map->encoding : 0);        for (int i = 0; i < 256; i += 8)            qDebug("    %x: %d %d %d %d %d %d %d %d", i,                   FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i),                   FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i),                   FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i),                   FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i));#endif        FT_Set_Charmap(freetype->face, freetype->unicode_map);        freetypeFaces->insert(face_id, freetype);    }    freetype->ref.ref();    return freetype;}void QFreetypeFace::release(const QFontEngine::FaceId &face_id){    if (!ref.deref()) {        FT_Done_Face(face);#ifndef QT_NO_FONTCONFIG        if (charset)            FcCharSetDestroy(charset);#endif        freetypeFaces->take(face_id);        delete this;    }    if (!freetypeFaces->size()) {        delete freetypeFaces;        freetypeFaces = 0;        FT_Done_FreeType(library);        library = 0;    }}void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing){    *ysize = fontDef.pixelSize << 6;    *xsize = *ysize * fontDef.stretch / 100;    *outline_drawing = false;    /*     * Bitmap only faces must match exactly, so find the closest     * one (height dominant search)     */    if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) {        int best = 0;        for (int i = 1; i < face->num_fixed_sizes; i++) {            if (qAbs(*ysize -  Y_SIZE(face,i)) <                qAbs (*ysize - Y_SIZE(face, best)) ||                (qAbs (*ysize - Y_SIZE(face, i)) ==                 qAbs (*ysize - Y_SIZE(face, best)) &&                 qAbs (*xsize - X_SIZE(face, i)) <                 qAbs (*xsize - X_SIZE(face, best)))) {                best = i;            }        }        if (FT_Set_Char_Size (face, X_SIZE(face, best), Y_SIZE(face, best), 0, 0) == 0) {            *xsize = X_SIZE(face, best);            *ysize = Y_SIZE(face, best);        } else {            int err = 1;            if (!(face->face_flags & FT_FACE_FLAG_SCALABLE) && ysize == 0 && face->num_fixed_sizes >= 1) {                // work around FT 2.1.10 problem with BDF without PIXEL_SIZE property                err = FT_Set_Pixel_Sizes(face, face->available_sizes[0].width, face->available_sizes[0].height);                if (err && face->num_fixed_sizes == 1)                    err = 0; //even more of a workaround...            }            if (err)                *xsize = *ysize = 0;        }    } else {        *outline_drawing = (*xsize > (64<<6) || *ysize > (64<<6));    }}QFontEngine::Properties QFreetypeFace::properties() const{    QFontEngine::Properties p;    p.postscriptName = FT_Get_Postscript_Name(face);    PS_FontInfoRec font_info;    if (FT_Get_PS_Font_Info(face, &font_info) == 0)        p.copyright = font_info.notice;    if (FT_IS_SCALABLE(face)) {        p.ascent = face->ascender;        p.descent = -face->descender;        p.leading = face->height - face->ascender + face->descender;        p.emSquare = face->units_per_EM;        p.boundingBox = QRectF(face->bbox.xMin, -face->bbox.yMax,                               face->bbox.xMax - face->bbox.xMin,                               face->bbox.yMax - face->bbox.yMin);    } else {        p.ascent = QFixed::fromFixed(face->size->metrics.ascender);        p.descent = QFixed::fromFixed(-face->size->metrics.descender);        p.leading = QFixed::fromFixed(face->size->metrics.height - face->size->metrics.ascender + face->size->metrics.descender);        p.emSquare = face->size->metrics.y_ppem;        p.boundingBox = QRectF(-p.ascent.toReal(), 0, (p.ascent + p.descent).toReal(), face->size->metrics.max_advance/64.);    }    p.italicAngle = 0;    p.capHeight = p.ascent;    p.lineWidth = face->underline_thickness;    return p;}QByteArray QFreetypeFace::getSfntTable(uint tag) const{    QByteArray table;#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) > 20103    if (FT_IS_SFNT(face)) {        FT_ULong length = 0;        FT_Load_Sfnt_Table(face, tag, 0, 0, &length);        if (length != 0) {            table.resize(length);            FT_Load_Sfnt_Table(face, tag, 0, (FT_Byte *)table.data(), &length);        }    }#endif    return table;}/* Some fonts (such as MingLiu rely on hinting to scale different   components to their correct sizes. While this is really broken (it   should be done in the component glyph itself, not the hinter) we   will have to live with it.   This means we can not use FT_LOAD_NO_HINTING to get the glyph   outline. All we can do is to load the unscaled glyph and scale it   down manually when required.*/static void scaleOutline(FT_Face face, FT_GlyphSlot g, FT_Fixed x_scale, FT_Fixed y_scale){    x_scale = FT_MulDiv(x_scale, 1 << 10, face->units_per_EM);    y_scale = FT_MulDiv(y_scale, 1 << 10, face->units_per_EM);    FT_Vector *p = g->outline.points;    const FT_Vector *e = p + g->outline.n_points;    while (p < e) {        p->x = FT_MulFix(p->x, x_scale);        p->y = FT_MulFix(p->y, y_scale);        ++p;    }}void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale){    const qreal factor = 1/64.;    scaleOutline(face, g, x_scale, y_scale);    QPointF cp = point.toPointF();    // convert the outline to a painter path    int i = 0;    for (int j = 0; j < g->outline.n_contours; ++j) {        int last_point = g->outline.contours[j];        QPointF start = cp + QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor);        if(!(g->outline.tags[i] & 1)) {            start += cp + QPointF(g->outline.points[last_point].x*factor, -g->outline.points[last_point].y*factor);            start /= 2;        }//         qDebug("contour: %d -- %d", i, g->outline.contours[j]);//         qDebug("first point at %f %f", start.x(), start.y());        path->moveTo(start);        QPointF c[4];        c[0] = start;        int n = 1;        while (i < last_point) {            ++i;            c[n] = cp + QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor);//             qDebug() << "    i=" << i << " flag=" << (int)g->outline.tags[i] << "point=" << c[n];            ++n;            switch (g->outline.tags[i] & 3) {            case 2:                // cubic bezier element                if (n < 4)                    continue;                c[3] = (c[3] + c[2])/2;                --i;                break;            case 0:                // quadratic bezier element                if (n < 3)                    continue;                c[3] = (c[1] + c[2])/2;                c[2] = (2*c[1] + c[3])/3;                c[1] = (2*c[1] + c[0])/3;                --i;                break;            case 1:            case 3:                if (n == 2) {//                     qDebug() << "lineTo" << c[1];                    path->lineTo(c[1]);                    c[0] = c[1];                    n = 1;                    continue;                } else if (n == 3) {                    c[3] = c[2];

⌨️ 快捷键说明

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