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

📄 qfontengine_qws.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
字号:
/******************************************************************************** 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 "qfontengine_p.h"#include <private/qunicodetables_p.h>#include <qwsdisplay_qws.h>#include <qvarlengtharray.h>#include <private/qpainter_p.h>#include <private/qpaintengine_raster_p.h>#include <private/qpdf_p.h>#include "qtextengine_p.h"#include "qopentype_p.h"#include <qdebug.h>#ifndef QT_NO_QWS_QPF#include "qfile.h"#include "qdir.h"#define QT_USE_MMAP#include <stdlib.h>#ifdef QT_USE_MMAP// for mmap#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/mman.h>#include <fcntl.h>#include <errno.h>#endif#endif // QT_NO_QWS_QPF#ifndef QT_NO_QWS_QPF#include "qplatformdefs.h"static inline unsigned int getChar(const QChar *str, int &i, const int len){    unsigned int uc = str[i].unicode();    if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) {        uint low = str[i+1].unicode();       if (low >= 0xdc00 && low < 0xe000) {            uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000;            ++i;        }    }    return uc;}#define FM_SMOOTH 1class Q_PACKED QPFGlyphMetrics {public:    quint8 linestep;    quint8 width;    quint8 height;    quint8 flags;    qint8 bearingx;      // Difference from pen position to glyph's left bbox    quint8 advance;       // Difference between pen positions    qint8 bearingy;      // Used for putting characters on baseline    qint8 reserved;      // Do not use    // Flags:    // RendererOwnsData - the renderer is responsible for glyph data    //                    memory deletion otherwise QPFGlyphTree must    //                    delete [] the data when the glyph is deleted.    enum Flags { RendererOwnsData=0x01 };};class QPFGlyph {public:    QPFGlyph() { metrics=0; data=0; }    QPFGlyph(QPFGlyphMetrics* m, uchar* d) :	metrics(m), data(d) { }    ~QPFGlyph() {}    QPFGlyphMetrics* metrics;    uchar* data;};struct Q_PACKED QPFFontMetrics{    qint8 ascent,descent;    qint8 leftbearing,rightbearing;    quint8 maxwidth;    qint8 leading;    quint8 flags;    quint8 underlinepos;    quint8 underlinewidth;    quint8 reserved3;};class QPFGlyphTree {public:    /* reads in a tree like this:       A-Z       /   \       0-9   a-z       etc.    */    glyph_t min,max;    QPFGlyphTree* less;    QPFGlyphTree* more;    QPFGlyph* glyph;public:#ifdef QT_USE_MMAP    QPFGlyphTree(uchar*& data)    {        read(data);    }#else    QPFGlyphTree(QIODevice& f)    {        read(f);    }#endif    ~QPFGlyphTree()    {        // NOTE: does not delete glyph[*].metrics or .data.        //       the caller does this (only they know who owns        //       the data).  See clear().        delete less;        delete more;        delete [] glyph;    }    bool inFont(glyph_t g) const    {        if ( g < min ) {            if ( !less )                return false;            return less->inFont(g);        } else if ( g > max ) {            if ( !more )                return false;            return more->inFont(g);        }        return true;    }    QPFGlyph* get(glyph_t g)    {        if ( g < min ) {            if ( !less )                return 0;            return less->get(g);        } else if ( g > max ) {            if ( !more )                return 0;            return more->get(g);        }        return &glyph[g - min];    }    int totalChars() const    {        if ( !this ) return 0;        return max-min+1 + less->totalChars() + more->totalChars();    }    int weight() const    {        if ( !this ) return 0;        return 1 + less->weight() + more->weight();    }    void dump(int indent=0)    {        for (int i=0; i<indent; i++) printf(" ");        printf("%d..%d",min,max);        //if ( indent == 0 )        printf(" (total %d)",totalChars());        printf("\n");        if ( less ) less->dump(indent+1);        if ( more ) more->dump(indent+1);    }private:    QPFGlyphTree()    {    }#ifdef QT_USE_MMAP    void read(uchar*& data)    {        // All node data first        readNode(data);        // Then all non-video data        readMetrics(data);        // Then all video data        readData(data);    }#else    void read(QIODevice& f)    {        // All node data first        readNode(f);        // Then all non-video data        readMetrics(f);        // Then all video data        readData(f);    }#endif#ifdef QT_USE_MMAP    void readNode(uchar*& data)    {        uchar rw = *data++;        uchar cl = *data++;        min = (rw << 8) | cl;        rw = *data++;        cl = *data++;        max = (rw << 8) | cl;        int flags = *data++;        if ( flags & 1 )            less = new QPFGlyphTree;        else            less = 0;        if ( flags & 2 )            more = new QPFGlyphTree;        else            more = 0;        int n = max-min+1;        glyph = new QPFGlyph[n];        if ( less )            less->readNode(data);        if ( more )            more->readNode(data);    }#else    void readNode(QIODevice& f)    {        uchar rw = f.getch();        uchar cl = f.getch();        min = (rw << 8) | cl;        rw = f.getch();        cl = f.getch();        max = (rw << 8) | cl;        int flags = f.getch();        if ( flags & 1 )            less = new QPFGlyphTree;        else            less = 0;        if ( flags & 2 )            more = new QPFGlyphTree;        else            more = 0;        int n = max-min+1;        glyph = new QPFGlyph[n];        if ( less )            less->readNode(f);        if ( more )            more->readNode(f);    }#endif#ifdef QT_USE_MMAP    void readMetrics(uchar*& data)    {        int n = max-min+1;        for (int i=0; i<n; i++) {            glyph[i].metrics = (QPFGlyphMetrics*)data;            data += sizeof(QPFGlyphMetrics);        }        if ( less )            less->readMetrics(data);        if ( more )            more->readMetrics(data);    }#else    void readMetrics(QIODevice& f)    {        int n = max-min+1;        for (int i=0; i<n; i++) {            glyph[i].metrics = new QPFGlyphMetrics;            f.readBlock((char*)glyph[i].metrics, sizeof(QPFGlyphMetrics));        }        if ( less )            less->readMetrics(f);        if ( more )            more->readMetrics(f);    }#endif#ifdef QT_USE_MMAP    void readData(uchar*& data)    {        int n = max-min+1;        for (int i=0; i<n; i++) {            QSize s( glyph[i].metrics->width, glyph[i].metrics->height );            //######### s = qt_screen->mapToDevice( s );            uint datasize = glyph[i].metrics->linestep * s.height();            glyph[i].data = data; data += datasize;        }        if ( less )            less->readData(data);        if ( more )            more->readData(data);    }#else    void readData(QIODevice& f)    {        int n = max-min+1;        for (int i=0; i<n; i++) {            QSize s( glyph[i].metrics->width, glyph[i].metrics->height );            //############### s = qt_screen->mapToDevice( s );            uint datasize = glyph[i].metrics->linestep * s.height();            glyph[i].data = new uchar[datasize]; // ### deleted?            f.readBlock((char*)glyph[i].data, datasize);        }        if ( less )            less->readData(f);        if ( more )            more->readData(f);    }#endif};class QFontEngineQPF1Data{public:    QPFFontMetrics fm;    QPFGlyphTree *tree;};QFontEngineQPF1::QFontEngineQPF1(const QFontDef&, const QString &fn){    cache_cost = 1;    int f = ::open( QFile::encodeName(fn), O_RDONLY );    Q_ASSERT(f>=0);    QT_STATBUF st;    if ( QT_FSTAT( f, &st ) )        qFatal("Failed to stat %s",QFile::encodeName(fn).data());    uchar* data = (uchar*)mmap( 0, // any address                                st.st_size, // whole file                                PROT_READ, // read-only memory#if !defined(Q_OS_SOLARIS) && !defined(Q_OS_QNX4) && !defined(QT_LSB) && !defined(Q_OS_INTEGRITY)                                MAP_FILE | MAP_PRIVATE, // swap-backed map from file#else                                MAP_PRIVATE,#endif                                f, 0 ); // from offset 0 of f#if defined(Q_OS_QNX4) && !defined(MAP_FAILED)#define MAP_FAILED ((void *)-1)#endif    if ( !data || data == (uchar*)MAP_FAILED )        qFatal("Failed to mmap %s",QFile::encodeName(fn).data());    ::close(f);    d = new QFontEngineQPF1Data;    memcpy(reinterpret_cast<char*>(&d->fm),data,sizeof(d->fm));    data += sizeof(d->fm);    d->tree = new QPFGlyphTree(data);#if 0    qDebug() << "font file" << fn             << "ascent" << d->fm.ascent << "descent" << d->fm.descent             << "leftbearing" << d->fm.leftbearing             << "rightbearing" << d->fm.rightbearing             << "maxwidth" << d->fm.maxwidth             << "leading" << d->fm.leading             << "flags" << d->fm.flags             << "underlinepos" << d->fm.underlinepos             << "underlinewidth" << d->fm.underlinewidth;#endif}QFontEngineQPF1::~QFontEngineQPF1(){    delete d->tree;    delete d;}bool QFontEngineQPF1::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags) const{    if(*nglyphs < len) {        *nglyphs = len;        return false;    }    *nglyphs = 0;    for(int i = 0; i < len; i++) {        unsigned int uc = getChar(str, i, len);        glyphs[*nglyphs].glyph = uc < 0x10000 ? uc : 0;        ++*nglyphs;    }    for(int i = 0; i < len; i++) {        QGlyphLayout &g=glyphs[i];        QPFGlyph *glyph = d->tree->get(g.glyph);        g.advance.x = glyph ? glyph->metrics->advance : 0;        g.advance.y = 0;        if (!glyph)            g.glyph = 0;    }    return true;}void QFontEngineQPF1::draw(QPaintEngine *p, qreal _x, qreal _y, const QTextItemInt &si){    QPaintEngineState *pState = p->state;    QRasterPaintEngine *paintEngine = static_cast<QRasterPaintEngine*>(p);    QTransform matrix = pState->transform();    matrix.translate(_x, _y);    QFixed x = QFixed::fromReal(matrix.dx());    QFixed y = QFixed::fromReal(matrix.dy());    QVarLengthArray<QFixedPoint> positions;    QVarLengthArray<glyph_t> glyphs;    getGlyphPositions(si.glyphs, si.num_glyphs, matrix, si.flags, glyphs, positions);    if (glyphs.size() == 0)        return;    for(int i = 0; i < glyphs.size(); i++) {        const QPFGlyph *glyph = d->tree->get(glyphs[i]);        if (!glyph)            continue;        int mono = !(d->fm.flags & FM_SMOOTH);        int bpl = glyph->metrics->linestep;        if(glyph->data)            paintEngine->alphaPenBlt(glyph->data, bpl, mono,                                     qRound(positions[i].x) + glyph->metrics->bearingx,                                     qRound(positions[i].y) - glyph->metrics->bearingy,                                     glyph->metrics->width,glyph->metrics->height);    }}void QFontEngineQPF1::addOutlineToPath(qreal x, qreal y, const QGlyphLayout *glyphs, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags flags){    addBitmapFontToPath(x, y, glyphs, numGlyphs, path, flags);}glyph_metrics_t QFontEngineQPF1::boundingBox(const QGlyphLayout *glyphs, int numGlyphs){   if (numGlyphs == 0)        return glyph_metrics_t();    QFixed w = 0;    const QGlyphLayout *end = glyphs + numGlyphs;    while(end > glyphs)        w += (--end)->advance.x;    return glyph_metrics_t(0, -ascent(), w, ascent()+descent()+1, w, 0);}glyph_metrics_t QFontEngineQPF1::boundingBox(glyph_t glyph){    const QPFGlyph *g = d->tree->get(glyph);    if (!g)        return glyph_metrics_t();    Q_ASSERT(g);    return glyph_metrics_t(g->metrics->bearingx, -g->metrics->bearingy,                            g->metrics->width, g->metrics->height,                            g->metrics->advance, 0);}QFixed QFontEngineQPF1::ascent() const{    return d->fm.ascent;}QFixed QFontEngineQPF1::descent() const{    return d->fm.descent;}QFixed QFontEngineQPF1::leading() const{    return d->fm.leading;}qreal QFontEngineQPF1::maxCharWidth() const{    return d->fm.maxwidth;}/*const char *QFontEngineQPF1::name() const{    return "qt";}*/bool QFontEngineQPF1::canRender(const QChar *str, int len){    for(int i = 0; i < len; i++)        if (!d->tree->inFont(str[i].unicode()))            return false;    return true;}QFontEngine::Type QFontEngineQPF1::type() const{    return QPF1;}qreal QFontEngineQPF1::minLeftBearing() const{    return d->fm.leftbearing;}qreal QFontEngineQPF1::minRightBearing() const{    return d->fm.rightbearing;}QFixed QFontEngineQPF1::underlinePosition() const{    return d->fm.underlinepos;}QFixed QFontEngineQPF1::lineThickness() const{    return d->fm.underlinewidth;}#endif //QT_NO_QWS_QPF

⌨️ 快捷键说明

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