Changeset 561 for trunk/src/gui/text/qfontengine.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/gui/text/qfontengine.cpp
r125 r561 2 2 ** 3 3 ** 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) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 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. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** 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. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 71 71 } 72 72 73 74 75 QFontEngineGlyphCache::~QFontEngineGlyphCache()76 {77 }78 79 73 // Harfbuzz helper functions 80 74 … … 192 186 QFontEngine::~QFontEngine() 193 187 { 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(); 208 193 qHBFreeFace(hbFace); 209 194 } … … 241 226 HB_Face QFontEngine::harfbuzzFace() const 242 227 { 243 if (!hbFace) 228 if (!hbFace) { 244 229 hbFace = qHBNewFace(const_cast<QFontEngine *>(this), hb_getSFntTable); 230 Q_CHECK_PTR(hbFace); 231 } 245 232 return hbFace; 246 233 } … … 429 416 QVarLengthArray<QFixedPoint> positions; 430 417 QVarLengthArray<glyph_t> positioned_glyphs; 431 QTransform matrix; 432 matrix.translate(x, y); 418 QTransform matrix = QTransform::fromTranslate(x, y); 433 419 getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions); 434 420 addGlyphsToPath(positioned_glyphs.data(), positions.data(), positioned_glyphs.size(), path, flags); … … 625 611 } 626 612 613 QImage 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 } 627 652 628 653 void QFontEngine::removeGlyphFromCache(glyph_t) … … 678 703 } 679 704 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 hashes685 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 else691 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 else701 m_glyphIntHash.insert(i.key(), list);702 break;703 }704 }705 delete old;706 }707 }708 709 705 void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data) 710 706 { 711 707 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 722 QFontEngineGlyphCache *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)) { 762 729 return c; 763 730 } … … 766 733 } 767 734 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) 784 736 static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs) 785 737 { … … 877 829 qSort(kerning_pairs); 878 830 // 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; 880 832 } 881 833 … … 911 863 return 0; 912 864 865 enum { 866 Invalid, 867 Symbol, 868 AppleRoman, 869 Unicode11, 870 Unicode, 871 MicrosoftUnicode, 872 MicrosoftUnicodeExtended 873 }; 874 875 int symbolTable = -1; 913 876 int tableToUse = -1; 914 int score = 0;877 int score = Invalid; 915 878 for (int n = 0; n < numTables; ++n) { 916 879 const quint16 platformId = qFromBigEndian<quint16>(maps + 8 * n); … … 918 881 switch (platformId) { 919 882 case 0: // Unicode 920 if (score < 4&&883 if (score < Unicode && 921 884 (platformSpecificId == 0 || 922 885 platformSpecificId == 2 || 923 886 platformSpecificId == 3)) { 924 887 tableToUse = n; 925 score = 4;926 } else if (score < 3&& platformSpecificId == 1) {888 score = Unicode; 889 } else if (score < Unicode11 && platformSpecificId == 1) { 927 890 tableToUse = n; 928 score = 3;891 score = Unicode11; 929 892 } 930 893 break; 931 894 case 1: // Apple 932 if (score < 2&& platformSpecificId == 0) { // Apple Roman895 if (score < AppleRoman && platformSpecificId == 0) { // Apple Roman 933 896 tableToUse = n; 934 score = 2;897 score = AppleRoman; 935 898 } 936 899 break; … … 938 901 switch (platformSpecificId) { 939 902 case 0: 940 if (score < 1) { 903 symbolTable = n; 904 if (score < Symbol) { 941 905 tableToUse = n; 942 score = 1;906 score = Symbol; 943 907 } 944 908 break; 945 909 case 1: 946 if (score < 5) {910 if (score < MicrosoftUnicode) { 947 911 tableToUse = n; 948 score = 5;912 score = MicrosoftUnicode; 949 913 } 950 914 break; 951 915 case 0xa: 952 if (score < 6) {916 if (score < MicrosoftUnicodeExtended) { 953 917 tableToUse = n; 954 score = 6;918 score = MicrosoftUnicodeExtended; 955 919 } 956 920 break; … … 964 928 if(tableToUse < 0) 965 929 return 0; 966 *isSymbolFont = (score == 1); 930 931 resolveTable: 932 *isSymbolFont = (score == Symbol); 967 933 968 934 unsigned int unicode_table = qFromBigEndian<quint32>(maps + 8*tableToUse + 4); … … 984 950 return 0; 985 951 *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 986 987 return table + unicode_table; 987 988 } … … 1003 1004 quint16 segCountX2 = qFromBigEndian<quint16>(cmap + 6); 1004 1005 const unsigned char *ends = cmap + 14; 1005 quint16 endIndex = 0;1006 1006 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++) {} 1008 1008 1009 1009 const unsigned char *idx = ends + segCountX2 + 2 + 2*i; … … 1072 1072 } 1073 1073 1074 Q_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 1081 const QVector<QRgb> &QFontEngine::grayPalette() 1082 { 1083 return *qt_grayPalette(); 1084 } 1085 1074 1086 // ------------------------------------------------------------------ 1075 1087 // The box font engine … … 1119 1131 QVarLengthArray<QFixedPoint> positions; 1120 1132 QVarLengthArray<glyph_t> positioned_glyphs; 1121 QTransform matrix; 1122 matrix.translate(x, y - _size); 1133 QTransform matrix = QTransform::fromTranslate(x, y - _size); 1123 1134 getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions); 1124 1135 … … 1148 1159 QVarLengthArray<QFixedPoint> positions; 1149 1160 QVarLengthArray<glyph_t> glyphs; 1150 QTransform matrix; 1151 matrix.translate(x, y - _size); 1161 QTransform matrix = QTransform::fromTranslate(x, y - _size); 1152 1162 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); 1153 1163 if (glyphs.size() == 0) … … 1277 1287 bool surrogate = (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00 && i < len-1 1278 1288 && 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) { 1281 1291 QGlyphLayoutInstance tmp = glyphs->instance(glyph_pos); 1282 1292 for (int x = 1; x < engines.size(); ++x) { … … 1608 1618 } 1609 1619 1610 QFontEngine *QFontEngineMulti::engine(int at) const1611 {1612 Q_ASSERT(at < engines.size());1613 return engines.at(at);1614 }1615 1616 1620 QImage QFontEngineMulti::alphaMapForGlyph(glyph_t) 1617 1621 {
Note:
See TracChangeset
for help on using the changeset viewer.