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

📄 qfontengine_x11.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************** 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 "qbitmap.h"// #define FONTENGINE_DEBUG#include <qbytearray.h>#include <qdebug.h>#include <qtextcodec.h>#include "qfontdatabase.h"#include "qpaintdevice.h"#include "qpainter.h"#include "qvarlengtharray.h"#include "qwidget.h"#include "qsettings.h"#include "qfile.h"#include <private/qpaintengine_x11_p.h>#include "qfont.h"#include "qfont_p.h"#include "qfontengine_p.h"#include "qopentype_p.h"#include <qhash.h>#include <private/qpainter_p.h>#include <private/qunicodetables_p.h>#include <private/qt_x11_p.h>#include "qx11info_x11.h"#include <math.h>#include <limits.h>#ifndef QT_NO_FREETYPE#include <ft2build.h>#include FT_FREETYPE_H#include FT_OUTLINE_H#include FT_TRUETYPE_TABLES_H#include FT_TYPE1_TABLES_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 ------------------------------struct QFreetypeFace{    void computeSize(const QFontDef &fontDef, int *xsize, int *ysize);    QFontEngine::Properties properties() const;    QByteArray getSfntTable(uint tag) const;    static QFreetypeFace *getFace(const QFontEngine::FaceId &face_id);    void release(const QFontEngine::FaceId &face_id);    void lock() {        Q_ASSERT(_lock == 0);        while (!_lock.testAndSet(0, 1))            usleep(100);    }    void unlock() {        if (!_lock.testAndSet(1, 0))            Q_ASSERT(false);    }    FT_Face face;#ifndef QT_NO_FONTCONFIG    FcCharSet *charset;#endif    int xsize; // 26.6    int ysize; // 26.6    FT_Matrix matrix;    FT_CharMap unicode_map;    FT_CharMap symbol_map;    enum { cmapCacheSize = 0x200 };    glyph_t cmapCache[cmapCacheSize];    int fsType() const;private:    QFreetypeFace() {}    ~QFreetypeFace() {}    QAtomic ref;    QAtomic _lock;};static FT_Library library = 0;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) {        FT_Face face;        if (FT_New_Face(library, face_id.filename, face_id.index, &face))            return 0;        freetype = new QFreetypeFace;        freetype->face = face;        freetype->ref = 0;        freetype->_lock = 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){    *ysize = fontDef.pixelSize << 6;    *xsize = *ysize * fontDef.stretch / 100;    /*     * 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            *xsize = *ysize = 0;    }}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;}static void addGlyphToPath(FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, bool no_scale = false){    qreal factor = no_scale ? 1. : 1./64.;    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[c]);//                 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];                    c[2] = (2*c[1] + c[3])/3;                    c[1] = (2*c[1] + c[0])/3;                }                break;            }//                     qDebug() << "cubicTo" << c[1] << c[2] << c[3];            path->cubicTo(c[1], c[2], c[3]);            c[0] = c[3];            n = 1;        }        if (n == 1) {//                     qDebug() << "closeSubpath";            path->closeSubpath();        } else {            c[3] = start;            if (n == 2) {                c[2] = (2*c[1] + c[3])/3;                c[1] = (2*c[1] + c[0])/3;            }//                     qDebug() << "cubicTo" << c[1] << c[2] << c[3];            path->cubicTo(c[1], c[2], c[3]);        }        ++i;    }}static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path, bool = false){    if (slot->format != FT_GLYPH_FORMAT_BITMAP        || slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)        return;    QPointF cp = point.toPointF();    uchar *src = slot->bitmap.buffer;    int h = slot->bitmap.rows;    int w = slot->bitmap.width;    for (int y = 0; y < h; ++y) {        for (int x = 0; x < w; ++x) {            uchar pixel = src[x >> 3];            if (!pixel) {                x += 8;                continue;

⌨️ 快捷键说明

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