Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/text/qfontengine.cpp

    r125 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtGui module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    7171}
    7272
    73 
    74 
    75 QFontEngineGlyphCache::~QFontEngineGlyphCache()
    76 {
    77 }
    78 
    7973// Harfbuzz helper functions
    8074
     
    192186QFontEngine::~QFontEngine()
    193187{
    194     for (GlyphPointerHash::iterator it = m_glyphPointerHash.begin(), end = m_glyphPointerHash.end();
    195          it != end; ++it) {
    196         for (QList<QFontEngineGlyphCache*>::iterator it2 = it.value().begin(), end2 = it.value().end();
    197             it2 != end2; ++it2)
    198                 delete *it2;
    199     }
    200     m_glyphPointerHash.clear();
    201     for (GlyphIntHash::iterator it = m_glyphIntHash.begin(), end = m_glyphIntHash.end();
    202          it != end; ++it) {
    203         for (QList<QFontEngineGlyphCache*>::iterator it2 = it.value().begin(), end2 = it.value().end();
    204             it2 != end2; ++it2)
    205                 delete *it2;
    206     }
    207     m_glyphIntHash.clear();
     188    for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(),
     189            end = m_glyphCaches.constEnd(); it != end; ++it) {
     190        delete it->cache;
     191    }
     192    m_glyphCaches.clear();
    208193    qHBFreeFace(hbFace);
    209194}
     
    241226HB_Face QFontEngine::harfbuzzFace() const
    242227{
    243     if (!hbFace)
     228    if (!hbFace) {
    244229        hbFace = qHBNewFace(const_cast<QFontEngine *>(this), hb_getSFntTable);
     230        Q_CHECK_PTR(hbFace);
     231    }
    245232    return hbFace;
    246233}
     
    429416    QVarLengthArray<QFixedPoint> positions;
    430417    QVarLengthArray<glyph_t> positioned_glyphs;
    431     QTransform matrix;
    432     matrix.translate(x, y);
     418    QTransform matrix = QTransform::fromTranslate(x, y);
    433419    getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);
    434420    addGlyphsToPath(positioned_glyphs.data(), positions.data(), positioned_glyphs.size(), path, flags);
     
    625611}
    626612
     613QImage QFontEngine::alphaMapForGlyph(glyph_t glyph)
     614{
     615    glyph_metrics_t gm = boundingBox(glyph);
     616    int glyph_x = qFloor(gm.x.toReal());
     617    int glyph_y = qFloor(gm.y.toReal());
     618    int glyph_width = qCeil((gm.x + gm.width).toReal()) -  glyph_x;
     619    int glyph_height = qCeil((gm.y + gm.height).toReal()) - glyph_y;
     620
     621    if (glyph_width <= 0 || glyph_height <= 0)
     622        return QImage();
     623    QFixedPoint pt;
     624    pt.x = 0;
     625    pt.y = -glyph_y; // the baseline
     626    QPainterPath path;
     627    QImage im(glyph_width + qAbs(glyph_x) + 4, glyph_height, QImage::Format_ARGB32_Premultiplied);
     628    im.fill(Qt::transparent);
     629    QPainter p(&im);
     630    p.setRenderHint(QPainter::Antialiasing);
     631    addGlyphsToPath(&glyph, &pt, 1, &path, 0);
     632    p.setPen(Qt::NoPen);
     633    p.setBrush(Qt::black);
     634    p.drawPath(path);
     635    p.end();
     636
     637    QImage indexed(im.width(), im.height(), QImage::Format_Indexed8);
     638    QVector<QRgb> colors(256);
     639    for (int i=0; i<256; ++i)
     640        colors[i] = qRgba(0, 0, 0, i);
     641    indexed.setColorTable(colors);
     642
     643    for (int y=0; y<im.height(); ++y) {
     644        uchar *dst = (uchar *) indexed.scanLine(y);
     645        uint *src = (uint *) im.scanLine(y);
     646        for (int x=0; x<im.width(); ++x)
     647            dst[x] = qAlpha(src[x]);
     648    }
     649
     650    return indexed;
     651}
    627652
    628653void QFontEngine::removeGlyphFromCache(glyph_t)
     
    678703}
    679704
    680 void QFontEngine::expireGlyphCache()
    681 {
    682     if (m_glyphCacheQueue.count() > 10) { // hold only 10 caches in memory.
    683         QFontEngineGlyphCache *old = m_glyphCacheQueue.takeFirst();
    684         // remove the value from either of our hashes
    685         for (GlyphPointerHash::iterator i = m_glyphPointerHash.begin(); i != m_glyphPointerHash.end(); ++i) {
    686             QList<QFontEngineGlyphCache *> list = i.value();
    687             if (list.removeAll(old)) {
    688                 if (list.isEmpty())
    689                     m_glyphPointerHash.remove(i.key());
    690                 else
    691                     m_glyphPointerHash.insert(i.key(), list);
    692                 break;
    693             }
    694         }
    695         for (GlyphIntHash::iterator i = m_glyphIntHash.begin(); i != m_glyphIntHash.end(); ++i) {
    696             QList<QFontEngineGlyphCache *> list = i.value();
    697             if (list.removeAll(old)) {
    698                 if (list.isEmpty())
    699                     m_glyphIntHash.remove(i.key());
    700                 else
    701                     m_glyphIntHash.insert(i.key(), list);
    702                 break;
    703             }
    704         }
    705         delete old;
    706     }
    707 }
    708 
    709705void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data)
    710706{
    711707    Q_ASSERT(data);
    712     QList<QFontEngineGlyphCache*> items = m_glyphPointerHash.value(key);
    713 
    714     for (QList<QFontEngineGlyphCache*>::iterator it = items.begin(), end = items.end(); it != end; ++it) {
    715         QFontEngineGlyphCache *c = *it;
    716         if (qtransform_equals_no_translate(c->m_transform, data->m_transform)) {
    717             if (c == data)
    718                 return;
    719             items.removeAll(c);
    720             delete c;
    721             break;
    722         }
    723     }
    724     items.append(data);
    725     m_glyphPointerHash.insert(key, items);
    726 
    727     m_glyphCacheQueue.append(data);
    728     expireGlyphCache();
    729 }
    730 
    731 void QFontEngine::setGlyphCache(QFontEngineGlyphCache::Type key, QFontEngineGlyphCache *data)
    732 {
    733     Q_ASSERT(data);
    734     QList<QFontEngineGlyphCache*> items = m_glyphIntHash.value(key);
    735 
    736     for (QList<QFontEngineGlyphCache*>::iterator it = items.begin(), end = items.end(); it != end; ++it) {
    737         QFontEngineGlyphCache *c = *it;
    738         if (qtransform_equals_no_translate(c->m_transform, data->m_transform)) {
    739             if (c == data)
    740                 return;
    741             items.removeAll(c);
    742             delete c;
    743             break;
    744         }
    745     }
    746     items.append(data);
    747     m_glyphIntHash.insert(key, items);
    748 
    749     m_glyphCacheQueue.append(data);
    750     expireGlyphCache();
    751 }
    752 
    753 QFontEngineGlyphCache *QFontEngine::glyphCache(void *key, const QTransform &transform) const
    754 {
    755     QList<QFontEngineGlyphCache*> items = m_glyphPointerHash.value(key);
    756 
    757     for (QList<QFontEngineGlyphCache*>::iterator it = items.begin(), end = items.end(); it != end; ++it) {
    758         QFontEngineGlyphCache *c = *it;
    759         if (qtransform_equals_no_translate(c->m_transform, transform)) {
    760             m_glyphCacheQueue.removeAll(c); // last used, move it up
    761             m_glyphCacheQueue.append(c);
     708
     709    GlyphCacheEntry entry = { key, data };
     710    if (m_glyphCaches.contains(entry))
     711        return;
     712
     713    // Limit the glyph caches to 4. This covers all 90 degree rotations and limits
     714    // memory use when there is continous or random rotation
     715    if (m_glyphCaches.size() == 4)
     716        delete m_glyphCaches.takeLast().cache;
     717
     718    m_glyphCaches.push_front(entry);
     719
     720}
     721
     722QFontEngineGlyphCache *QFontEngine::glyphCache(void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const
     723{
     724    for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(), end = m_glyphCaches.constEnd(); it != end; ++it) {
     725        QFontEngineGlyphCache *c = it->cache;
     726        if (key == it->context
     727            && type == c->cacheType()
     728            && qtransform_equals_no_translate(c->m_transform, transform)) {
    762729            return c;
    763730        }
     
    766733}
    767734
    768 QFontEngineGlyphCache *QFontEngine::glyphCache(QFontEngineGlyphCache::Type key, const QTransform &transform) const
    769 {
    770     QList<QFontEngineGlyphCache*> items = m_glyphIntHash.value(key);
    771 
    772     for (QList<QFontEngineGlyphCache*>::iterator it = items.begin(), end = items.end(); it != end; ++it) {
    773         QFontEngineGlyphCache *c = *it;
    774         if (qtransform_equals_no_translate(c->m_transform, transform)) {
    775             m_glyphCacheQueue.removeAll(c); // last used, move it up
    776             m_glyphCacheQueue.append(c);
    777             return c;
    778         }
    779     }
    780     return 0;
    781 }
    782 
    783 #if defined(Q_WS_WIN) || defined(Q_WS_PM) || defined(Q_WS_X11) || defined(Q_WS_QWS)
     735#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) || defined(Q_WS_PM) || defined(Q_WS_PM)
    784736static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs)
    785737{
     
    877829    qSort(kerning_pairs);
    878830//    for (int i = 0; i < kerning_pairs.count(); ++i)
    879 //        qDebug() << "i" << i << "left_right" << hex << kerning_pairs.at(i).left_right;
     831//        qDebug() << 'i' << i << "left_right" << hex << kerning_pairs.at(i).left_right;
    880832}
    881833
     
    911863        return 0;
    912864
     865    enum {
     866        Invalid,
     867        Symbol,
     868        AppleRoman,
     869        Unicode11,
     870        Unicode,
     871        MicrosoftUnicode,
     872        MicrosoftUnicodeExtended
     873    };
     874
     875    int symbolTable = -1;
    913876    int tableToUse = -1;
    914     int score = 0;
     877    int score = Invalid;
    915878    for (int n = 0; n < numTables; ++n) {
    916879        const quint16 platformId = qFromBigEndian<quint16>(maps + 8 * n);
     
    918881        switch (platformId) {
    919882        case 0: // Unicode
    920             if (score < 4 &&
     883            if (score < Unicode &&
    921884                (platformSpecificId == 0 ||
    922885                 platformSpecificId == 2 ||
    923886                 platformSpecificId == 3)) {
    924887                tableToUse = n;
    925                 score = 4;
    926             } else if (score < 3 && platformSpecificId == 1) {
     888                score = Unicode;
     889            } else if (score < Unicode11 && platformSpecificId == 1) {
    927890                tableToUse = n;
    928                 score = 3;
     891                score = Unicode11;
    929892            }
    930893            break;
    931894        case 1: // Apple
    932             if (score < 2 && platformSpecificId == 0) { // Apple Roman
     895            if (score < AppleRoman && platformSpecificId == 0) { // Apple Roman
    933896                tableToUse = n;
    934                 score = 2;
     897                score = AppleRoman;
    935898            }
    936899            break;
     
    938901            switch (platformSpecificId) {
    939902            case 0:
    940                 if (score < 1) {
     903                symbolTable = n;
     904                if (score < Symbol) {
    941905                    tableToUse = n;
    942                     score = 1;
     906                    score = Symbol;
    943907                }
    944908                break;
    945909            case 1:
    946                 if (score < 5) {
     910                if (score < MicrosoftUnicode) {
    947911                    tableToUse = n;
    948                     score = 5;
     912                    score = MicrosoftUnicode;
    949913                }
    950914                break;
    951915            case 0xa:
    952                 if (score < 6) {
     916                if (score < MicrosoftUnicodeExtended) {
    953917                    tableToUse = n;
    954                     score = 6;
     918                    score = MicrosoftUnicodeExtended;
    955919                }
    956920                break;
     
    964928    if(tableToUse < 0)
    965929        return 0;
    966     *isSymbolFont = (score == 1);
     930
     931resolveTable:
     932    *isSymbolFont = (score == Symbol);
    967933
    968934    unsigned int unicode_table = qFromBigEndian<quint32>(maps + 8*tableToUse + 4);
     
    984950        return 0;
    985951    *cmapSize = length;
     952
     953    // To support symbol fonts that contain a unicode table for the symbol area
     954    // we check the cmap tables and fall back to symbol font unless that would
     955    // involve losing information from the unicode table
     956    if (symbolTable > -1 && ((score == Unicode) || (score == Unicode11))) {
     957        const uchar *selectedTable = table + unicode_table;
     958
     959        // Check that none of the latin1 range are in the unicode table
     960        bool unicodeTableHasLatin1 = false;
     961        for (int uc=0x00; uc<0x100; ++uc) {
     962            if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) {
     963                unicodeTableHasLatin1 = true;
     964                break;
     965            }
     966        }
     967
     968        // Check that at least one symbol char is in the unicode table
     969        bool unicodeTableHasSymbols = false;
     970        if (!unicodeTableHasLatin1) {
     971            for (int uc=0xf000; uc<0xf100; ++uc) {
     972                if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) {
     973                    unicodeTableHasSymbols = true;
     974                    break;
     975                }
     976            }
     977        }
     978
     979        // Fall back to symbol table
     980        if (!unicodeTableHasLatin1 && unicodeTableHasSymbols) {
     981            tableToUse = symbolTable;
     982            score = Symbol;
     983            goto resolveTable;
     984        }
     985    }
     986
    986987    return table + unicode_table;
    987988}
     
    10031004        quint16 segCountX2 = qFromBigEndian<quint16>(cmap + 6);
    10041005        const unsigned char *ends = cmap + 14;
    1005         quint16 endIndex = 0;
    10061006        int i = 0;
    1007         for (; i < segCountX2/2 && (endIndex = qFromBigEndian<quint16>(ends + 2*i)) < unicode; i++) {}
     1007        for (; i < segCountX2/2 && qFromBigEndian<quint16>(ends + 2*i) < unicode; i++) {}
    10081008
    10091009        const unsigned char *idx = ends + segCountX2 + 2 + 2*i;
     
    10721072}
    10731073
     1074Q_GLOBAL_STATIC_WITH_INITIALIZER(QVector<QRgb>, qt_grayPalette, {
     1075    x->resize(256);
     1076    QRgb *it = x->data();
     1077    for (int i = 0; i < x->size(); ++i, ++it)
     1078        *it = 0xff000000 | i | (i<<8) | (i<<16);
     1079})
     1080
     1081const QVector<QRgb> &QFontEngine::grayPalette()
     1082{
     1083    return *qt_grayPalette();
     1084}
     1085
    10741086// ------------------------------------------------------------------
    10751087// The box font engine
     
    11191131    QVarLengthArray<QFixedPoint> positions;
    11201132    QVarLengthArray<glyph_t> positioned_glyphs;
    1121     QTransform matrix;
    1122     matrix.translate(x, y - _size);
     1133    QTransform matrix = QTransform::fromTranslate(x, y - _size);
    11231134    getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);
    11241135
     
    11481159    QVarLengthArray<QFixedPoint> positions;
    11491160    QVarLengthArray<glyph_t> glyphs;
    1150     QTransform matrix;
    1151     matrix.translate(x, y - _size);
     1161    QTransform matrix = QTransform::fromTranslate(x, y - _size);
    11521162    ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
    11531163    if (glyphs.size() == 0)
     
    12771287        bool surrogate = (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00 && i < len-1
    12781288                          && str[i+1].unicode() >= 0xdc00 && str[i+1].unicode() < 0xe000);
    1279         if (glyphs->glyphs[glyph_pos] == 0) {
    1280 
     1289
     1290        if (glyphs->glyphs[glyph_pos] == 0 && str[i].category() != QChar::Separator_Line) {
    12811291            QGlyphLayoutInstance tmp = glyphs->instance(glyph_pos);
    12821292            for (int x = 1; x < engines.size(); ++x) {
     
    16081618}
    16091619
    1610 QFontEngine *QFontEngineMulti::engine(int at) const
    1611 {
    1612     Q_ASSERT(at < engines.size());
    1613     return engines.at(at);
    1614 }
    1615 
    16161620QImage QFontEngineMulti::alphaMapForGlyph(glyph_t)
    16171621{
Note: See TracChangeset for help on using the changeset viewer.