Changeset 846 for trunk/src/gui/text
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 95 edited
- 3 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/src/gui/text/qabstractfontengine_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qabstractfontengine_qws.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qabstractfontengine_qws.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qabstracttextdocumentlayout.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qabstracttextdocumentlayout.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qabstracttextdocumentlayout_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qcssparser.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qcssparser_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qcssscanner.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qfont.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 78 78 #endif 79 79 #ifdef Q_OS_SYMBIAN 80 #include "qt_s60_p.h"80 #include <private/qt_s60_p.h> 81 81 #endif 82 82 … … 1283 1283 \value Decorative is a synonym for \c OldEnglish. 1284 1284 1285 \value Monospace the font matcher prefers fonts that map to the 1286 CSS generic font-family 'monospace'. 1287 1288 \value Fantasy the font matcher prefers fonts that map to the 1289 CSS generic font-family 'fantasy'. 1290 1291 \value Cursive the font matcher prefers fonts that map to the 1292 CSS generic font-family 'cursive'. 1293 1285 1294 \value System the font matcher prefers system fonts. 1286 1295 */ … … 1306 1315 \value OpenGLCompatible forces the use of OpenGL compatible 1307 1316 fonts. 1308 \value NoFontMerging If a font does not contain a character requested 1309 to draw then Qt automatically chooses a similar looking for that contains 1310 the character. This flag disables this feature. 1317 \value NoFontMerging If the font selected for a certain writing system 1318 does not contain a character requested to draw, then Qt automatically chooses a similar 1319 looking font that contains the character. The NoFontMerging flag disables this feature. 1320 Please note that enabling this flag will not prevent Qt from automatically picking a 1321 suitable font when the selected font does not support the writing system of the text. 1311 1322 1312 1323 Any of these may be OR-ed with one of these flags: … … 1317 1328 will use the nearest standard point size that the font 1318 1329 supports. 1330 \value ForceIntegerMetrics forces the use of integer values in font engines that support fractional 1331 font metrics. 1319 1332 */ 1320 1333 -
trunk/src/gui/text/qfont.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 73 73 OldEnglish, Decorative = OldEnglish, 74 74 System, 75 AnyStyle 75 AnyStyle, 76 Cursive, 77 Monospace, 78 Fantasy 76 79 }; 77 80 78 81 enum StyleStrategy { 79 PreferDefault = 0x0001, 80 PreferBitmap = 0x0002, 81 PreferDevice = 0x0004, 82 PreferOutline = 0x0008, 83 ForceOutline = 0x0010, 84 PreferMatch = 0x0020, 85 PreferQuality = 0x0040, 86 PreferAntialias = 0x0080, 87 NoAntialias = 0x0100, 88 OpenGLCompatible = 0x0200, 89 NoFontMerging = 0x8000 82 PreferDefault = 0x0001, 83 PreferBitmap = 0x0002, 84 PreferDevice = 0x0004, 85 PreferOutline = 0x0008, 86 ForceOutline = 0x0010, 87 PreferMatch = 0x0020, 88 PreferQuality = 0x0040, 89 PreferAntialias = 0x0080, 90 NoAntialias = 0x0100, 91 OpenGLCompatible = 0x0200, 92 ForceIntegerMetrics = 0x0400, 93 NoFontMerging = 0x8000 90 94 }; 91 95 … … 292 296 friend class QFontInfo; 293 297 friend class QPainter; 298 friend class QPainterPrivate; 294 299 friend class QPSPrintEngineFont; 295 300 friend class QApplication; -
trunk/src/gui/text/qfont_mac.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 137 137 case QFont::Courier: 138 138 return QString::fromLatin1("Courier New"); 139 case QFont::Monospace: 140 return QString::fromLatin1("Courier"); 139 141 case QFont::Decorative: 140 142 return QString::fromLatin1("Bookman Old Style"); 143 case QFont::Cursive: 144 return QString::fromLatin1("Apple Chancery"); 145 case QFont::Fantasy: 146 return QString::fromLatin1("Papyrus"); 141 147 case QFont::Helvetica: 142 148 case QFont::System: -
trunk/src/gui/text/qfont_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qfont_qws.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 109 109 return QString::fromLatin1("times"); 110 110 case QFont::Courier: 111 case QFont::Monospace: 111 112 return QString::fromLatin1("courier"); 112 113 case QFont::Decorative: -
trunk/src/gui/text/qfont_s60.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 41 41 42 42 #include "qfont.h" 43 #include "qt_s60_p.h" 44 #include "qpixmap_s60_p.h" 43 #include "qfont_p.h" 44 #include <private/qt_s60_p.h> 45 #include <private/qpixmap_s60_p.h> 45 46 #include "qmutex.h" 46 47 47 48 QT_BEGIN_NAMESPACE 48 49 49 #if 150 50 #ifdef QT_NO_FREETYPE 51 51 Q_GLOBAL_STATIC(QMutex, lastResortFamilyMutex); 52 extern QStringList qt_symbian_fontFamiliesOnFontServer(); // qfontdatabase_s60.cpp 53 Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, fontFamiliesOnFontServer, { 54 // We are only interested in the initial font families. No Application fonts. 55 // Therefore, we are allowed to cache the list. 56 x->append(qt_symbian_fontFamiliesOnFontServer()); 57 }); 52 58 #endif // QT_NO_FREETYPE 59 60 QString QFont::lastResortFont() const 61 { 62 // Symbian's font Api does not distinguish between font and family. 63 // Therefore we try to get a "Family" first, then fall back to "Sans". 64 static QString font = lastResortFamily(); 65 if (font.isEmpty()) 66 font = QLatin1String("Sans"); 67 return font; 68 } 53 69 54 70 QString QFont::lastResortFamily() const … … 71 87 } 72 88 return family; 73 #else 89 #else // QT_NO_FREETYPE 74 90 // For the FreeType case we just hard code the face name, since otherwise on 75 91 // East Asian systems we may get a name for a stroke based (non-ttf) font. … … 83 99 #endif // QT_NO_FREETYPE 84 100 } 85 #else // 086 QString QFont::lastResortFamily() const87 {88 return QLatin1String("Series 60 Sans");89 }90 #endif // 091 101 92 102 QString QFont::defaultFamily() const 93 103 { 104 #ifdef QT_NO_FREETYPE 105 switch(d->request.styleHint) { 106 case QFont::SansSerif: { 107 static const char* const preferredSansSerif[] = {"Nokia Sans S60", "Series 60 Sans"}; 108 for (int i = 0; i < sizeof preferredSansSerif / sizeof preferredSansSerif[0]; ++i) { 109 const QString sansSerif = QLatin1String(preferredSansSerif[i]); 110 if (fontFamiliesOnFontServer()->contains(sansSerif)) 111 return sansSerif; 112 } 113 } 114 // No break. Intentional fall through. 115 default: 116 return lastResortFamily(); 117 } 118 #endif // QT_NO_FREETYPE 94 119 return lastResortFamily(); 95 120 } -
trunk/src/gui/text/qfont_win.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 149 149 return QString::fromLatin1("Times New Roman"); 150 150 case QFont::Courier: 151 case QFont::Monospace: 151 152 return QString::fromLatin1("Courier New"); 152 153 case QFont::Decorative: 153 154 return QString::fromLatin1("Bookman Old Style"); 155 case QFont::Cursive: 156 return QString::fromLatin1("Comic Sans MS"); 157 case QFont::Fantasy: 158 return QString::fromLatin1("Impact"); 154 159 case QFont::Helvetica: 155 160 return QString::fromLatin1("Arial"); -
trunk/src/gui/text/qfont_x11.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 281 281 case QFont::Courier: 282 282 return QString::fromLatin1("Courier"); 283 284 case QFont::Monospace: 285 return QString::fromLatin1("Courier New"); 286 287 case QFont::Cursive: 288 return QString::fromLatin1("Comic Sans MS"); 289 290 case QFont::Fantasy: 291 return QString::fromLatin1("Impact"); 283 292 284 293 case QFont::Decorative: -
trunk/src/gui/text/qfontdatabase.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 149 149 struct QtFontSize 150 150 { 151 unsigned short pixelSize;152 153 151 #ifdef Q_WS_X11 154 int count;155 152 QtFontEncoding *encodings; 156 153 QtFontEncoding *encodingID(int id, uint xpoint = 0, uint xres = 0, 157 154 uint yres = 0, uint avgwidth = 0, bool add = false); 155 unsigned short count : 16; 158 156 #endif // Q_WS_X11 159 157 #ifdef Q_WS_PM … … 164 162 int fileIndex; 165 163 #endif // defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) 164 165 unsigned short pixelSize : 16; 166 166 }; 167 167 … … 294 294 return 0; 295 295 296 if (!(count % 8)) { 296 if (!pixelSizes) { 297 // Most style have only one font size, we avoid waisting memory 298 QtFontSize *newPixelSizes = (QtFontSize *)malloc(sizeof(QtFontSize)); 299 Q_CHECK_PTR(newPixelSizes); 300 pixelSizes = newPixelSizes; 301 } else if (!(count % 8) || count == 1) { 297 302 QtFontSize *newPixelSizes = (QtFontSize *) 298 303 realloc(pixelSizes, … … 421 426 #endif 422 427 #ifdef Q_WS_X11 423 bool symbol_checked ;428 bool symbol_checked : 1; 424 429 #endif 425 430 … … 635 640 ~QFontDatabasePrivate() { 636 641 free(); 642 #if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) 643 if (symbianExtras) 644 delete symbianExtras; 645 #endif 637 646 } 638 647 QtFontFamily *family(const QString &f, bool = false); … … 643 652 families = 0; 644 653 count = 0; 645 #if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)646 if (symbianExtras) {647 delete symbianExtras;648 symbianExtras = 0;649 }650 #endif651 654 // don't clear the memory fonts! 652 655 } … … 664 667 #elif defined(Q_WS_MAC) 665 668 ATSFontContainerRef handle; 669 #elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) 670 QString temporaryFileName; 671 TInt screenDeviceFontFileId; 672 TUid fontStoreFontFileUid; 666 673 #endif 667 674 QStringList families; … … 691 698 QStringList fallbackFamilies; 692 699 #elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) 693 constQSymbianFontDatabaseExtras *symbianExtras;700 QSymbianFontDatabaseExtras *symbianExtras; 694 701 #endif 695 702 … … 2592 2599 currently not supported. 2593 2600 2601 \note On Symbian, the font family names get truncated to a length of 20 characters. 2602 2594 2603 \sa addApplicationFontFromData(), applicationFontFamilies(), removeApplicationFont() 2595 2604 */ … … 2622 2631 currently not supported. 2623 2632 2633 \note On Symbian, the font family names get truncated to a length of 20 characters. 2634 2624 2635 \sa addApplicationFont(), applicationFontFamilies(), removeApplicationFont() 2625 2636 */ -
trunk/src/gui/text/qfontdatabase.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qfontdatabase_mac.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qfontdatabase_qws.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 633 633 634 634 QScopedPointer<QFontEngineFT> fte(new QFontEngineFT(def)); 635 if (fte->init(faceId, style->antialiased, 636 style->antialiased ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono)) { 635 bool antialias = style->antialiased && !(request.styleStrategy & QFont::NoAntialias); 636 if (fte->init(faceId, antialias, 637 antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono)) { 637 638 #ifdef QT_NO_QWS_QPF2 638 639 return fte.take(); … … 794 795 " weight: %d, style: %d\n" 795 796 " stretch: %d\n" 796 " pixelSize: % d\n"797 " pixelSize: %g\n" 797 798 " pitch: %c", 798 799 family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(), -
trunk/src/gui/text/qfontdatabase_s60.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 46 46 #include "qabstractfileengine.h" 47 47 #include "qdesktopservices.h" 48 #include "qpixmap_s60_p.h" 49 #include "qt_s60_p.h" 48 #include "qtemporaryfile.h" 49 #include "qtextcodec.h" 50 #include <private/qpixmap_s60_p.h> 51 #include <private/qt_s60_p.h> 50 52 #include "qendian.h" 51 53 #include <private/qcore_symbian_p.h> 52 #if defined(QT_NO_FREETYPE)54 #ifdef QT_NO_FREETYPE 53 55 #include <openfont.h> 54 56 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS 55 57 #include <graphics/openfontrasterizer.h> // COpenFontRasterizer has moved to a new header file 56 58 #endif // SYMBIAN_ENABLE_SPLIT_HEADERS 57 #endif 59 #endif // QT_NO_FREETYPE 58 60 59 61 QT_BEGIN_NAMESPACE 62 63 QStringList qt_symbian_fontFamiliesOnFontServer() // Also used in qfont_s60.cpp 64 { 65 QStringList result; 66 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); 67 const int numTypeFaces = S60->screenDevice()->NumTypefaces(); 68 for (int i = 0; i < numTypeFaces; i++) { 69 TTypefaceSupport typefaceSupport; 70 S60->screenDevice()->TypefaceSupport(typefaceSupport, i); 71 const QString familyName((const QChar *)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length()); 72 result.append(familyName); 73 } 74 lock.relock(); 75 return result; 76 } 60 77 61 78 QFileInfoList alternativeFilePaths(const QString &path, const QStringList &nameFilters, … … 92 109 } 93 110 94 #if defined(QT_NO_FREETYPE)111 #ifdef QT_NO_FREETYPE 95 112 class QSymbianFontDatabaseExtrasImplementation : public QSymbianFontDatabaseExtras 96 113 { … … 100 117 101 118 const QSymbianTypeFaceExtras *extras(const QString &typeface, bool bold, bool italic) const; 102 103 private: 119 void removeAppFontData(QFontDatabasePrivate::ApplicationFont *fnt); 120 static inline bool appFontLimitReached(); 121 TUid addFontFileToFontStore(const QFileInfo &fontFileInfo); 122 static void clear(); 123 124 static inline QString tempAppFontFolder(); 125 static const QString appFontMarkerPrefix; 126 static QString appFontMarker(); // 'qaf<shortUid[+shortPid]>' 127 128 struct CFontFromFontStoreReleaser { 129 static inline void cleanup(CFont *font) 130 { 131 if (!font) 132 return; 133 const QSymbianFontDatabaseExtrasImplementation *dbExtras = 134 static_cast<const QSymbianFontDatabaseExtrasImplementation*>(privateDb()->symbianExtras); 135 dbExtras->m_store->ReleaseFont(font); 136 } 137 }; 138 139 struct CFontFromScreenDeviceReleaser { 140 static inline void cleanup(CFont *font) 141 { 142 if (!font) 143 return; 144 S60->screenDevice()->ReleaseFont(font); 145 } 146 }; 147 148 // m_heap, m_store, m_rasterizer and m_extras are used if Symbian 149 // does not provide the Font Table API 104 150 RHeap* m_heap; 105 151 CFontStore *m_store; 106 152 COpenFontRasterizer *m_rasterizer; 107 153 mutable QList<const QSymbianTypeFaceExtras *> m_extras; 154 108 155 mutable QHash<QString, const QSymbianTypeFaceExtras *> m_extrasHash; 156 mutable QSet<QString> m_applicationFontFamilies; 109 157 }; 110 158 159 const QString QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix = 160 QLatin1String("Q"); 161 162 inline QString QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder() 163 { 164 return QDir::toNativeSeparators(QDir::tempPath()) + QLatin1Char('\\'); 165 } 166 167 QString QSymbianFontDatabaseExtrasImplementation::appFontMarker() 168 { 169 static QString result; 170 if (result.isEmpty()) { 171 quint16 id = 0; 172 if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { 173 // We are allowed to load app fonts even from previous, crashed runs 174 // of this application, since we can access the font tables. 175 const quint32 uid = RProcess().Type().MostDerived().iUid; 176 id = static_cast<quint16>(uid + (uid >> 16)); 177 } else { 178 // If no font table Api is available, we must not even load a font 179 // from a previous (crashed) run of this application. Reason: we 180 // won't get the font tables, they are not in the CFontStore. 181 // So, we use the pid, for more uniqueness. 182 id = static_cast<quint16>(RProcess().Id().Id()); 183 } 184 result = appFontMarkerPrefix + QString::fromLatin1("%1").arg(id & 0x7fff, 3, 32, QLatin1Char('0')); 185 Q_ASSERT(appFontMarkerPrefix.length() == 1 && result.length() == 4); 186 } 187 return result; 188 } 189 190 static inline bool qt_symbian_fontNameHasAppFontMarker(const QString &fontName) 191 { 192 const int idLength = 3; // Keep in sync with id length in appFontMarker(). 193 const QString &prefix = QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix; 194 if (fontName.length() < prefix.length() + idLength 195 || fontName.mid(fontName.length() - idLength - prefix.length(), prefix.length()) != prefix) 196 return false; 197 // Testing if the the id is base32 data 198 for (int i = fontName.length() - idLength; i < fontName.length(); ++i) { 199 const QChar &c = fontName.at(i); 200 if (!(c >= QLatin1Char('0') && c <= QLatin1Char('9') 201 || c >= QLatin1Char('a') && c <= QLatin1Char('v'))) 202 return false; 203 } 204 return true; 205 } 206 207 // If fontName is an application font of this app, prepend the app font marker 208 QString qt_symbian_fontNameWithAppFontMarker(const QString &fontName) 209 { 210 QFontDatabasePrivate *db = privateDb(); 211 Q_ASSERT(db); 212 const QSymbianFontDatabaseExtrasImplementation *dbExtras = 213 static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); 214 return dbExtras->m_applicationFontFamilies.contains(fontName) ? 215 fontName + QSymbianFontDatabaseExtrasImplementation::appFontMarker() 216 : fontName; 217 } 218 219 static inline QString qt_symbian_appFontNameWithoutMarker(const QString &markedFontName) 220 { 221 return markedFontName.left(markedFontName.length() 222 - QSymbianFontDatabaseExtrasImplementation::appFontMarker().length()); 223 } 224 111 225 QSymbianFontDatabaseExtrasImplementation::QSymbianFontDatabaseExtrasImplementation() 112 226 { 113 QStringList filters; 114 filters.append(QLatin1String("*.ttf")); 115 filters.append(QLatin1String("*.ccc")); 116 filters.append(QLatin1String("*.ltt")); 117 const QFileInfoList fontFiles = alternativeFilePaths(QLatin1String("resource\\Fonts"), filters); 118 119 const TInt heapMinLength = 0x1000; 120 const TInt heapMaxLength = qMax(0x20000 * fontFiles.count(), heapMinLength); 121 m_heap = User::ChunkHeap(NULL, heapMinLength, heapMaxLength); 122 QT_TRAP_THROWING( 123 m_store = CFontStore::NewL(m_heap); 124 m_rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E)); 125 CleanupStack::PushL(m_rasterizer); 126 m_store->InstallRasterizerL(m_rasterizer); 127 CleanupStack::Pop(m_rasterizer);); 128 129 foreach (const QFileInfo &fontFileInfo, fontFiles) { 130 const QString fontFile = QDir::toNativeSeparators(fontFileInfo.absoluteFilePath()); 131 TPtrC fontFilePtr(qt_QString2TPtrC(fontFile)); 132 QT_TRAP_THROWING(m_store->AddFileL(fontFilePtr)); 227 if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { 228 QStringList filters; 229 filters.append(QLatin1String("*.ttf")); 230 filters.append(QLatin1String("*.ccc")); 231 filters.append(QLatin1String("*.ltt")); 232 const QFileInfoList fontFiles = alternativeFilePaths(QLatin1String("resource\\Fonts"), filters); 233 234 const TInt heapMinLength = 0x1000; 235 const TInt heapMaxLength = qMax(0x20000 * fontFiles.count(), heapMinLength); 236 m_heap = User::ChunkHeap(NULL, heapMinLength, heapMaxLength); 237 QT_TRAP_THROWING( 238 m_store = CFontStore::NewL(m_heap); 239 m_rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E)); 240 CleanupStack::PushL(m_rasterizer); 241 m_store->InstallRasterizerL(m_rasterizer); 242 CleanupStack::Pop(m_rasterizer);); 243 244 foreach (const QFileInfo &fontFileInfo, fontFiles) 245 addFontFileToFontStore(fontFileInfo); 246 } 247 } 248 249 void QSymbianFontDatabaseExtrasImplementation::clear() 250 { 251 QFontDatabasePrivate *db = privateDb(); 252 if (!db) 253 return; 254 const QSymbianFontDatabaseExtrasImplementation *dbExtras = 255 static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); 256 if (!dbExtras) 257 return; // initializeDb() has never been called 258 if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { 259 qDeleteAll(dbExtras->m_extrasHash); 260 } else { 261 typedef QList<const QSymbianTypeFaceExtras *>::iterator iterator; 262 for (iterator p = dbExtras->m_extras.begin(); p != dbExtras->m_extras.end(); ++p) { 263 dbExtras->m_store->ReleaseFont((*p)->fontOwner()); 264 delete *p; 265 } 266 dbExtras->m_extras.clear(); 267 } 268 dbExtras->m_extrasHash.clear(); 269 } 270 271 void qt_cleanup_symbianFontDatabase() 272 { 273 QFontDatabasePrivate *db = privateDb(); 274 if (!db) 275 return; 276 277 QSymbianFontDatabaseExtrasImplementation::clear(); 278 279 if (!db->applicationFonts.isEmpty()) { 280 QFontDatabase::removeAllApplicationFonts(); 281 // We remove the left over temporary font files of Qt application. 282 // Active fonts are undeletable since the font server holds a handle 283 // on them, so we do not need to worry to delete other running 284 // applications' fonts. 285 const QDir dir(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder()); 286 const QStringList filter( 287 QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix + QLatin1String("*.ttf")); 288 foreach (const QFileInfo &ttfFile, dir.entryInfoList(filter)) 289 QFile(ttfFile.absoluteFilePath()).remove(); 290 db->applicationFonts.clear(); 133 291 } 134 292 } … … 136 294 QSymbianFontDatabaseExtrasImplementation::~QSymbianFontDatabaseExtrasImplementation() 137 295 { 138 typedef QList<const QSymbianTypeFaceExtras *>::iterator iterator; 139 for (iterator p = m_extras.begin(); p != m_extras.end(); ++p) { 140 m_store->ReleaseFont((*p)->fontOwner()); 141 delete *p; 142 } 143 144 delete m_store; 145 m_heap->Close(); 296 qt_cleanup_symbianFontDatabase(); 297 if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { 298 delete m_store; 299 m_heap->Close(); 300 } 146 301 } 147 302 … … 163 318 #endif // FNTSTORE_H_INLINES_SUPPORT_FMM 164 319 165 const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(const QString & typeface,320 const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(const QString &aTypeface, 166 321 bool bold, bool italic) const 167 322 { 323 const QString typeface = qt_symbian_fontNameWithAppFontMarker(aTypeface); 168 324 const QString searchKey = typeface + QString::number(int(bold)) + QString::number(int(italic)); 169 325 if (!m_extrasHash.contains(searchKey)) { 170 CFont* font = NULL;171 326 TFontSpec searchSpec(qt_QString2TPtrC(typeface), 1); 172 327 if (bold) … … 174 329 if (italic) 175 330 searchSpec.iFontStyle.SetPosture(EPostureItalic); 176 const TInt err = m_store->GetNearestFontToDesignHeightInPixels(font, searchSpec); 177 Q_ASSERT(err == KErrNone && font); 178 const CBitmapFont *bitmapFont = static_cast<CBitmapFont*>(font); 179 COpenFont *openFont = 331 332 CFont* font = NULL; 333 if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { 334 const TInt err = S60->screenDevice()->GetNearestFontToDesignHeightInPixels(font, searchSpec); 335 Q_ASSERT(err == KErrNone && font); 336 QScopedPointer<CFont, CFontFromScreenDeviceReleaser> sFont(font); 337 QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font); 338 sFont.take(); 339 m_extrasHash.insert(searchKey, extras); 340 } else { 341 const TInt err = m_store->GetNearestFontToDesignHeightInPixels(font, searchSpec); 342 Q_ASSERT(err == KErrNone && font); 343 const CBitmapFont *bitmapFont = static_cast<CBitmapFont*>(font); 344 COpenFont *openFont = 180 345 #ifdef FNTSTORE_H_INLINES_SUPPORT_FMM 181 bitmapFont->openFont();182 #else 183 OpenFontFromBitmapFont(bitmapFont);346 bitmapFont->OpenFont(); 347 #else // FNTSTORE_H_INLINES_SUPPORT_FMM 348 OpenFontFromBitmapFont(bitmapFont); 184 349 #endif // FNTSTORE_H_INLINES_SUPPORT_FMM 185 const TOpenFontFaceAttrib* const attrib = openFont->FaceAttrib(); 186 const QString foundKey = 187 QString((const QChar*)attrib->FullName().Ptr(), attrib->FullName().Length()); 188 if (!m_extrasHash.contains(foundKey)) { 189 QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font, openFont); 190 m_extras.append(extras); 191 m_extrasHash.insert(searchKey, extras); 192 m_extrasHash.insert(foundKey, extras); 193 } else { 194 m_store->ReleaseFont(font); 195 m_extrasHash.insert(searchKey, m_extrasHash.value(foundKey)); 350 const TOpenFontFaceAttrib* const attrib = openFont->FaceAttrib(); 351 const QString foundKey = 352 QString((const QChar*)attrib->FullName().Ptr(), attrib->FullName().Length()); 353 if (!m_extrasHash.contains(foundKey)) { 354 QScopedPointer<CFont, CFontFromFontStoreReleaser> sFont(font); 355 QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font, openFont); 356 sFont.take(); 357 m_extras.append(extras); 358 m_extrasHash.insert(searchKey, extras); 359 m_extrasHash.insert(foundKey, extras); 360 } else { 361 m_store->ReleaseFont(font); 362 m_extrasHash.insert(searchKey, m_extrasHash.value(foundKey)); 363 } 196 364 } 197 365 } 198 366 return m_extrasHash.value(searchKey); 199 367 } 200 #else 368 369 void QSymbianFontDatabaseExtrasImplementation::removeAppFontData( 370 QFontDatabasePrivate::ApplicationFont *fnt) 371 { 372 clear(); 373 if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable() 374 && fnt->fontStoreFontFileUid.iUid != 0) 375 m_store->RemoveFile(fnt->fontStoreFontFileUid); 376 if (!fnt->families.isEmpty()) 377 m_applicationFontFamilies.remove(fnt->families.first()); 378 if (fnt->screenDeviceFontFileId != 0) 379 S60->screenDevice()->RemoveFile(fnt->screenDeviceFontFileId); 380 QFile::remove(fnt->temporaryFileName); 381 *fnt = QFontDatabasePrivate::ApplicationFont(); 382 } 383 384 bool QSymbianFontDatabaseExtrasImplementation::appFontLimitReached() 385 { 386 QFontDatabasePrivate *db = privateDb(); 387 if (!db) 388 return false; 389 const int maxAppFonts = 5; 390 int registeredAppFonts = 0; 391 foreach (const QFontDatabasePrivate::ApplicationFont &appFont, db->applicationFonts) 392 if (!appFont.families.isEmpty() && ++registeredAppFonts == maxAppFonts) 393 return true; 394 return false; 395 } 396 397 TUid QSymbianFontDatabaseExtrasImplementation::addFontFileToFontStore(const QFileInfo &fontFileInfo) 398 { 399 Q_ASSERT(!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()); 400 const QString fontFile = QDir::toNativeSeparators(fontFileInfo.absoluteFilePath()); 401 const TPtrC fontFilePtr(qt_QString2TPtrC(fontFile)); 402 TUid fontUid = {0}; 403 TRAP_IGNORE(fontUid = m_store->AddFileL(fontFilePtr)); 404 return fontUid; 405 } 406 407 #else // QT_NO_FREETYPE 201 408 class QFontEngineFTS60 : public QFontEngineFT 202 409 { … … 210 417 default_hint_style = HintFull; 211 418 } 212 #endif // defined(QT_NO_FREETYPE)419 #endif // QT_NO_FREETYPE 213 420 214 421 /* … … 219 426 qreal QFontEngineS60::pixelsToPoints(qreal pixels, Qt::Orientation orientation) 220 427 { 428 CWsScreenDevice* device = S60->screenDevice(); 221 429 return (orientation == Qt::Horizontal? 222 S60->screenDevice()->HorizontalPixelsToTwips(pixels)223 : S60->screenDevice()->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint;430 device->HorizontalPixelsToTwips(pixels) 431 :device->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint; 224 432 } 225 433 226 434 qreal QFontEngineS60::pointsToPixels(qreal points, Qt::Orientation orientation) 227 435 { 436 CWsScreenDevice* device = S60->screenDevice(); 228 437 const int twips = points * KTwipsPerPoint; 229 438 return orientation == Qt::Horizontal? 230 S60->screenDevice()->HorizontalTwipsToPixels(twips)231 : S60->screenDevice()->VerticalTwipsToPixels(twips);439 device->HorizontalTwipsToPixels(twips) 440 :device->VerticalTwipsToPixels(twips); 232 441 } 233 442 … … 256 465 } 257 466 467 static bool registerScreenDeviceFont(int screenDeviceFontIndex, 468 const QSymbianFontDatabaseExtrasImplementation *dbExtras) 469 { 470 TTypefaceSupport typefaceSupport; 471 S60->screenDevice()->TypefaceSupport(typefaceSupport, screenDeviceFontIndex); 472 473 QString familyName((const QChar*)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length()); 474 if (qt_symbian_fontNameHasAppFontMarker(familyName)) { 475 const QString &marker = QSymbianFontDatabaseExtrasImplementation::appFontMarker(); 476 if (familyName.endsWith(marker)) { 477 familyName = qt_symbian_appFontNameWithoutMarker(familyName); 478 dbExtras->m_applicationFontFamilies.insert(familyName); 479 } else { 480 return false; // This was somebody else's application font. Skip it. 481 } 482 } 483 484 CFont *font; // We have to get a font instance in order to know all the details 485 TFontSpec fontSpec(typefaceSupport.iTypeface.iName, 11); 486 if (S60->screenDevice()->GetNearestFontInPixels(font, fontSpec) != KErrNone) 487 return false; 488 QScopedPointer<CFont, QSymbianFontDatabaseExtrasImplementation::CFontFromScreenDeviceReleaser> sFont(font); 489 if (font->TypeUid() != KCFbsFontUid) 490 return false; 491 TOpenFontFaceAttrib faceAttrib; 492 const CFbsFont *cfbsFont = static_cast<const CFbsFont *>(font); 493 cfbsFont->GetFaceAttrib(faceAttrib); 494 495 QtFontStyle::Key styleKey; 496 styleKey.style = faceAttrib.IsItalic()?QFont::StyleItalic:QFont::StyleNormal; 497 styleKey.weight = faceAttrib.IsBold()?QFont::Bold:QFont::Normal; 498 499 QtFontFamily *family = privateDb()->family(familyName, true); 500 family->fixedPitch = faceAttrib.IsMonoWidth(); 501 QtFontFoundry *foundry = family->foundry(QString(), true); 502 QtFontStyle *style = foundry->style(styleKey, true); 503 style->smoothScalable = typefaceSupport.iIsScalable; 504 style->pixelSize(0, true); 505 506 const QSymbianTypeFaceExtras *typeFaceExtras = 507 dbExtras->extras(familyName, faceAttrib.IsBold(), faceAttrib.IsItalic()); 508 const QByteArray os2Table = typeFaceExtras->getSfntTable(MAKE_TAG('O', 'S', '/', '2')); 509 const unsigned char* data = reinterpret_cast<const unsigned char*>(os2Table.constData()); 510 const unsigned char* ulUnicodeRange = data + 42; 511 quint32 unicodeRange[4] = { 512 qFromBigEndian<quint32>(ulUnicodeRange), 513 qFromBigEndian<quint32>(ulUnicodeRange + 4), 514 qFromBigEndian<quint32>(ulUnicodeRange + 8), 515 qFromBigEndian<quint32>(ulUnicodeRange + 12) 516 }; 517 const unsigned char* ulCodePageRange = data + 78; 518 quint32 codePageRange[2] = { 519 qFromBigEndian<quint32>(ulCodePageRange), 520 qFromBigEndian<quint32>(ulCodePageRange + 4) 521 }; 522 const QList<QFontDatabase::WritingSystem> writingSystems = 523 determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange); 524 foreach (const QFontDatabase::WritingSystem system, writingSystems) 525 family->writingSystems[system] = QtFontFamily::Supported; 526 return true; 527 } 528 258 529 static void initializeDb() 259 530 { … … 262 533 return; 263 534 264 #if defined(QT_NO_FREETYPE)535 #ifdef QT_NO_FREETYPE 265 536 if (!db->symbianExtras) 266 537 db->symbianExtras = new QSymbianFontDatabaseExtrasImplementation; 267 538 268 539 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); 269 270 const int numTypeFaces = QS60Data::screenDevice()->NumTypefaces();540 541 const int numTypeFaces = S60->screenDevice()->NumTypefaces(); 271 542 const QSymbianFontDatabaseExtrasImplementation *dbExtras = 272 543 static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); 273 bool fontAdded = false; 274 for (int i = 0; i < numTypeFaces; i++) { 275 TTypefaceSupport typefaceSupport; 276 QS60Data::screenDevice()->TypefaceSupport(typefaceSupport, i); 277 CFont *font; // We have to get a font instance in order to know all the details 278 TFontSpec fontSpec(typefaceSupport.iTypeface.iName, 11); 279 if (QS60Data::screenDevice()->GetNearestFontInPixels(font, fontSpec) != KErrNone) 280 continue; 281 if (font->TypeUid() == KCFbsFontUid) { 282 TOpenFontFaceAttrib faceAttrib; 283 const CFbsFont *cfbsFont = static_cast<const CFbsFont *>(font); 284 cfbsFont->GetFaceAttrib(faceAttrib); 285 286 QtFontStyle::Key styleKey; 287 styleKey.style = faceAttrib.IsItalic()?QFont::StyleItalic:QFont::StyleNormal; 288 styleKey.weight = faceAttrib.IsBold()?QFont::Bold:QFont::Normal; 289 290 QString familyName((const QChar *)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length()); 291 QtFontFamily *family = db->family(familyName, true); 292 family->fixedPitch = faceAttrib.IsMonoWidth(); 293 QtFontFoundry *foundry = family->foundry(QString(), true); 294 QtFontStyle *style = foundry->style(styleKey, true); 295 style->smoothScalable = typefaceSupport.iIsScalable; 296 style->pixelSize(0, true); 297 298 const QSymbianTypeFaceExtras *typeFaceExtras = 299 dbExtras->extras(familyName, faceAttrib.IsBold(), faceAttrib.IsItalic()); 300 const QByteArray os2Table = typeFaceExtras->getSfntTable(MAKE_TAG('O', 'S', '/', '2')); 301 const unsigned char* data = reinterpret_cast<const unsigned char*>(os2Table.constData()); 302 const unsigned char* ulUnicodeRange = data + 42; 303 quint32 unicodeRange[4] = { 304 qFromBigEndian<quint32>(ulUnicodeRange), 305 qFromBigEndian<quint32>(ulUnicodeRange + 4), 306 qFromBigEndian<quint32>(ulUnicodeRange + 8), 307 qFromBigEndian<quint32>(ulUnicodeRange + 12) 308 }; 309 const unsigned char* ulCodePageRange = data + 78; 310 quint32 codePageRange[2] = { 311 qFromBigEndian<quint32>(ulCodePageRange), 312 qFromBigEndian<quint32>(ulCodePageRange + 4) 313 }; 314 const QList<QFontDatabase::WritingSystem> writingSystems = 315 determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange); 316 foreach (const QFontDatabase::WritingSystem system, writingSystems) 317 family->writingSystems[system] = QtFontFamily::Supported; 318 319 fontAdded = true; 320 } 321 QS60Data::screenDevice()->ReleaseFont(font); 322 } 323 324 Q_ASSERT(fontAdded); 325 326 lock.relock(); 327 328 #else // defined(QT_NO_FREETYPE) 544 for (int i = 0; i < numTypeFaces; i++) 545 registerScreenDeviceFont(i, dbExtras); 546 547 // We have to clear/release all CFonts, here, in case one of the fonts is 548 // an application font of another running Qt app. Otherwise the other Qt app 549 // cannot remove it's application font, anymore -> "Zombie Font". 550 QSymbianFontDatabaseExtrasImplementation::clear(); 551 552 lock.relock(); 553 554 #else // QT_NO_FREETYPE 329 555 QDir dir(QDesktopServices::storageLocation(QDesktopServices::FontsLocation)); 330 556 dir.setNameFilters(QStringList() << QLatin1String("*.ttf") … … 335 561 db->addTTFile(file); 336 562 } 337 #endif // defined(QT_NO_FREETYPE)563 #endif // QT_NO_FREETYPE 338 564 } 339 565 … … 345 571 } 346 572 573 struct OffsetTable { 574 quint32 sfntVersion; 575 quint16 numTables, searchRange, entrySelector, rangeShift; 576 }; 577 578 struct TableRecord { 579 quint32 tag, checkSum, offset, length; 580 }; 581 582 struct NameTableHead { 583 quint16 format, count, stringOffset; 584 }; 585 586 struct NameRecord { 587 quint16 platformID, encodingID, languageID, nameID, length, offset; 588 }; 589 590 static quint32 ttfCalcChecksum(const char *data, quint32 bytesCount) 591 { 592 quint32 result = 0; 593 const quint32 *ptr = reinterpret_cast<const quint32*>(data); 594 const quint32 *endPtr = 595 ptr + (bytesCount + sizeof(quint32) - 1) / sizeof(quint32); 596 while (ptr < endPtr) { 597 const quint32 unit32Value = *ptr++; 598 result += qFromBigEndian(unit32Value); 599 } 600 return result; 601 } 602 603 static inline quint32 toDWordBoundary(quint32 value) 604 { 605 return (value + 3) & ~3; 606 } 607 608 static inline quint32 dWordPadding(quint32 value) 609 { 610 return (4 - (value & 3)) & 3; 611 } 612 613 static inline bool ttfMarkNameTable(QByteArray &table, const QString &marker) 614 { 615 const quint32 tableLength = static_cast<quint32>(table.size()); 616 617 if (tableLength > 50000 // hard limit 618 || tableLength < sizeof(NameTableHead)) // corrupt name table 619 return false; 620 621 const NameTableHead *head = reinterpret_cast<const NameTableHead*>(table.constData()); 622 const quint16 count = qFromBigEndian(head->count); 623 const quint16 stringOffset = qFromBigEndian(head->stringOffset); 624 if (count > 200 // hard limit 625 || stringOffset >= tableLength // corrupt name table 626 || sizeof(NameTableHead) + count * sizeof(NameRecord) >= tableLength) // corrupt name table 627 return false; 628 629 QTextEncoder encoder(QTextCodec::codecForName("UTF-16BE"), QTextCodec::IgnoreHeader); 630 const QByteArray markerUtf16BE = encoder.fromUnicode(marker); 631 const QByteArray markerAscii = marker.toAscii(); 632 633 QByteArray markedTable; 634 markedTable.reserve(tableLength + marker.length() * 20); // Original size plus some extra 635 markedTable.append(table, stringOffset); 636 QByteArray markedStrings; 637 quint32 stringDataCount = stringOffset; 638 for (quint16 i = 0; i < count; ++i) { 639 const quint32 nameRecordOffset = sizeof(NameTableHead) + sizeof(NameRecord) * i; 640 NameRecord *nameRecord = 641 reinterpret_cast<NameRecord*>(markedTable.data() + nameRecordOffset); 642 const quint16 nameID = qFromBigEndian(nameRecord->nameID); 643 const quint16 platformID = qFromBigEndian(nameRecord->platformID); 644 const quint16 encodingID = qFromBigEndian(nameRecord->encodingID); 645 const quint16 offset = qFromBigEndian(nameRecord->offset); 646 const quint16 length = qFromBigEndian(nameRecord->length); 647 stringDataCount += length; 648 if (stringDataCount > 80000 // hard limit. String data may be > name table size. Multiple records can reference the same string. 649 || static_cast<quint32>(stringOffset + offset + length) > tableLength) // String outside bounds 650 return false; 651 const bool needsMarker = 652 nameID == 1 || nameID == 3 || nameID == 4 || nameID == 16 || nameID == 21; 653 const bool isUnicode = 654 platformID == 0 || platformID == 3 && encodingID == 1; 655 const QByteArray originalString = 656 QByteArray::fromRawData(table.constData() + stringOffset + offset, length); 657 QByteArray markedString; 658 if (needsMarker) { 659 const int maxBytesLength = (KMaxTypefaceNameLength - marker.length()) * (isUnicode ? 2 : 1); 660 markedString = originalString.left(maxBytesLength) + (isUnicode ? markerUtf16BE : markerAscii); 661 } else { 662 markedString = originalString; 663 } 664 nameRecord->offset = qToBigEndian(static_cast<quint16>(markedStrings.length())); 665 nameRecord->length = qToBigEndian(static_cast<quint16>(markedString.length())); 666 markedStrings.append(markedString); 667 } 668 markedTable.append(markedStrings); 669 table = markedTable; 670 return true; 671 } 672 673 const quint32 ttfMaxFileSize = 3500000; 674 675 static inline bool ttfMarkAppFont(QByteArray &ttf, const QString &marker) 676 { 677 const quint32 ttfChecksumNumber = 0xb1b0afba; 678 const quint32 alignment = 4; 679 const quint32 ttfLength = static_cast<quint32>(ttf.size()); 680 if (ttfLength > ttfMaxFileSize // hard limit 681 || ttfLength % alignment != 0 // ttf sizes are always factors of 4 682 || ttfLength <= sizeof(OffsetTable) // ttf too short 683 || ttfCalcChecksum(ttf.constData(), ttf.size()) != ttfChecksumNumber) // ttf checksum is invalid 684 return false; 685 686 const OffsetTable *offsetTable = reinterpret_cast<const OffsetTable*>(ttf.constData()); 687 const quint16 numTables = qFromBigEndian(offsetTable->numTables); 688 const quint32 recordsLength = 689 toDWordBoundary(sizeof(OffsetTable) + numTables * sizeof(TableRecord)); 690 if (numTables > 30 // hard limit 691 || recordsLength + numTables * alignment > ttfLength) // Corrupt ttf. Tables would not fit, even if empty. 692 return false; 693 694 QByteArray markedTtf; 695 markedTtf.reserve(ttfLength + marker.length() * 20); // Original size plus some extra 696 markedTtf.append(ttf.constData(), recordsLength); 697 698 const quint32 ttfCheckSumAdjustmentOffset = 8; // Offset from the start of 'head' 699 int indexOfHeadTable = -1; 700 quint32 ttfDataSize = recordsLength; 701 typedef QPair<quint32, quint32> Range; 702 QList<Range> memoryRanges; 703 memoryRanges.reserve(numTables); 704 for (int i = 0; i < numTables; ++i) { 705 TableRecord *tableRecord = 706 reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + i * sizeof(TableRecord)); 707 const quint32 offset = qFromBigEndian(tableRecord->offset); 708 const quint32 length = qFromBigEndian(tableRecord->length); 709 const quint32 lengthAligned = toDWordBoundary(length); 710 ttfDataSize += lengthAligned; 711 if (offset < recordsLength // must not intersect ttf header/records 712 || offset % alignment != 0 // must be aligned 713 || offset > ttfLength - alignment // table out of bounds 714 || offset + lengthAligned > ttfLength // table out of bounds 715 || ttfDataSize > ttfLength) // tables would not fit into the ttf 716 return false; 717 718 foreach (const Range &range, memoryRanges) 719 if (offset < range.first + range.second && offset + lengthAligned > range.first) 720 return false; // Overlaps with another table 721 memoryRanges.append(Range(offset, lengthAligned)); 722 723 quint32 checkSum = qFromBigEndian(tableRecord->checkSum); 724 if (tableRecord->tag == qToBigEndian(static_cast<quint32>('head'))) { 725 if (length < ttfCheckSumAdjustmentOffset + sizeof(quint32)) 726 return false; // Invalid 'head' table 727 const quint32 *checkSumAdjustmentTag = 728 reinterpret_cast<const quint32*>(ttf.constData() + offset + ttfCheckSumAdjustmentOffset); 729 const quint32 checkSumAdjustment = qFromBigEndian(*checkSumAdjustmentTag); 730 checkSum += checkSumAdjustment; 731 indexOfHeadTable = i; // For the ttf checksum re-calculation, later 732 } 733 if (checkSum != ttfCalcChecksum(ttf.constData() + offset, length)) 734 return false; // Table checksum is invalid 735 736 bool updateTableChecksum = false; 737 QByteArray table; 738 if (tableRecord->tag == qToBigEndian(static_cast<quint32>('name'))) { 739 table = QByteArray(ttf.constData() + offset, length); 740 if (!ttfMarkNameTable(table, marker)) 741 return false; // Name table was not markable. 742 updateTableChecksum = true; 743 } else { 744 table = QByteArray::fromRawData(ttf.constData() + offset, length); 745 } 746 747 tableRecord->offset = qToBigEndian(markedTtf.size()); 748 tableRecord->length = qToBigEndian(table.size()); 749 markedTtf.append(table); 750 markedTtf.append(QByteArray(dWordPadding(table.size()), 0)); // 0-padding 751 if (updateTableChecksum) { 752 TableRecord *tableRecord = // Need to recalculate, since markedTtf changed 753 reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + i * sizeof(TableRecord)); 754 const quint32 offset = qFromBigEndian(tableRecord->offset); 755 const quint32 length = qFromBigEndian(tableRecord->length); 756 tableRecord->checkSum = qToBigEndian(ttfCalcChecksum(markedTtf.constData() + offset, length)); 757 } 758 } 759 if (indexOfHeadTable == -1 // 'head' table is mandatory 760 || ttfDataSize != ttfLength) // We do not allow ttf data "holes". Neither does Symbian. 761 return false; 762 TableRecord *headRecord = 763 reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + indexOfHeadTable * sizeof(TableRecord)); 764 quint32 *checkSumAdjustmentTag = 765 reinterpret_cast<quint32*>(markedTtf.data() + qFromBigEndian(headRecord->offset) + ttfCheckSumAdjustmentOffset); 766 *checkSumAdjustmentTag = 0; 767 const quint32 ttfChecksum = ttfCalcChecksum(markedTtf.constData(), markedTtf.count()); 768 *checkSumAdjustmentTag = qToBigEndian(ttfChecksumNumber - ttfChecksum); 769 ttf = markedTtf; 770 return true; 771 } 772 773 static inline bool ttfCanSymbianLoadFont(const QByteArray &data, const QString &fileName) 774 { 775 bool result = false; 776 QString ttfFileName; 777 QFile tempFileGuard; 778 QFileInfo info(fileName); 779 if (!data.isEmpty()) { 780 QTemporaryFile tempfile(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder() 781 + QSymbianFontDatabaseExtrasImplementation::appFontMarker() 782 + QLatin1String("XXXXXX.ttf")); 783 if (!tempfile.open() || tempfile.write(data) == -1) 784 return false; 785 ttfFileName = QDir::toNativeSeparators(QFileInfo(tempfile).canonicalFilePath()); 786 tempfile.setAutoRemove(false); 787 tempfile.close(); 788 tempFileGuard.setFileName(ttfFileName); 789 if (!tempFileGuard.open(QIODevice::ReadOnly)) 790 return false; 791 } else if (info.isFile()) { 792 ttfFileName = QDir::toNativeSeparators(info.canonicalFilePath()); 793 } else { 794 return false; 795 } 796 797 CFontStore *store = 0; 798 RHeap* heap = User::ChunkHeap(NULL, 0x1000, 0x20000); 799 if (heap) { 800 QT_TRAP_THROWING( 801 CleanupClosePushL(*heap); 802 store = CFontStore::NewL(heap); 803 CleanupStack::PushL(store); 804 COpenFontRasterizer *rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E)); 805 CleanupStack::PushL(rasterizer); 806 store->InstallRasterizerL(rasterizer); 807 CleanupStack::Pop(rasterizer); 808 TUid fontUid = {-1}; 809 TRAP_IGNORE(fontUid = store->AddFileL(qt_QString2TPtrC(ttfFileName))); 810 if (fontUid.iUid != -1) 811 result = true; 812 CleanupStack::PopAndDestroy(2, heap); // heap, store 813 ); 814 } 815 816 if (tempFileGuard.isOpen()) 817 tempFileGuard.remove(); 818 819 return result; 820 } 821 347 822 static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) 348 823 { 349 Q_UNUSED(fnt); 824 if (QSymbianFontDatabaseExtrasImplementation::appFontLimitReached() 825 || fnt->data.size() > ttfMaxFileSize // hard limit 826 || fnt->data.isEmpty() && (!fnt->fileName.endsWith(QLatin1String(".ttf"), Qt::CaseInsensitive) // Only buffer or .ttf 827 || QFileInfo(fnt->fileName).size() > ttfMaxFileSize)) // hard limit 828 return; 829 830 // Using ttfCanSymbianLoadFont() causes crashes on app destruction (Symbian^3|PR1 and lower). 831 // Therefore, not using it for now, but eventually in a later version. 832 // if (!ttfCanSymbianLoadFont(fnt->data, fnt->fileName)) 833 // return; 834 835 QFontDatabasePrivate *db = privateDb(); 836 if (!db) 837 return; 838 839 if (!db->count) 840 initializeDb(); 841 842 QSymbianFontDatabaseExtrasImplementation *dbExtras = 843 static_cast<QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); 844 if (!dbExtras) 845 return; 846 847 const QString &marker = QSymbianFontDatabaseExtrasImplementation::appFontMarker(); 848 849 // The QTemporaryFile object being used in the following section must be 850 // destructed before letting Symbian load the TTF file. Symbian would not 851 // load it otherwise, because QTemporaryFile will still keep some handle 852 // on it. The scope is used to reduce the life time of the QTemporaryFile. 853 // In order to prevent other processes from modifying the file between the 854 // moment where the QTemporaryFile is destructed and the file is loaded by 855 // Symbian, we have a QFile "tempFileGuard" outside the scope which opens 856 // the file in ReadOnly mode while the QTemporaryFile is still alive. 857 QFile tempFileGuard; 858 { 859 QTemporaryFile tempfile(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder() 860 + marker + QLatin1String("XXXXXX.ttf")); 861 if (!tempfile.open()) 862 return; 863 const QString tempFileName = QFileInfo(tempfile).canonicalFilePath(); 864 if (fnt->data.isEmpty()) { 865 QFile sourceFile(fnt->fileName); 866 if (!sourceFile.open(QIODevice::ReadOnly)) 867 return; 868 fnt->data = sourceFile.readAll(); 869 } 870 if (!ttfMarkAppFont(fnt->data, marker) || tempfile.write(fnt->data) == -1) 871 return; 872 tempfile.setAutoRemove(false); 873 tempfile.close(); // Tempfile still keeps a file handle, forbidding write access 874 fnt->data.clear(); // The TTF data was marked and saved. Not needed in memory, anymore. 875 tempFileGuard.setFileName(tempFileName); 876 if (!tempFileGuard.open(QIODevice::ReadOnly)) 877 return; 878 fnt->temporaryFileName = tempFileName; 879 } 880 881 const QString fullFileName = QDir::toNativeSeparators(fnt->temporaryFileName); 882 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); 883 const QStringList fontsOnServerBefore = qt_symbian_fontFamiliesOnFontServer(); 884 const TInt err = 885 S60->screenDevice()->AddFile(qt_QString2TPtrC(fullFileName), fnt->screenDeviceFontFileId); 886 tempFileGuard.close(); // Did its job 887 const QStringList fontsOnServerAfter = qt_symbian_fontFamiliesOnFontServer(); 888 if (err == KErrNone && fontsOnServerBefore.count() < fontsOnServerAfter.count()) { // Added to screen device? 889 int fontOnServerIndex = fontsOnServerAfter.count() - 1; 890 for (int i = 0; i < fontsOnServerBefore.count(); i++) { 891 if (fontsOnServerBefore.at(i) != fontsOnServerAfter.at(i)) { 892 fontOnServerIndex = i; 893 break; 894 } 895 } 896 897 // Must remove all font engines with their CFonts, first. 898 QFontCache::instance()->clear(); 899 db->free(); 900 QSymbianFontDatabaseExtrasImplementation::clear(); 901 902 if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) 903 fnt->fontStoreFontFileUid = dbExtras->addFontFileToFontStore(QFileInfo(fullFileName)); 904 905 const QString &appFontName = fontsOnServerAfter.at(fontOnServerIndex); 906 fnt->families.append(qt_symbian_appFontNameWithoutMarker(appFontName)); 907 if (!qt_symbian_fontNameHasAppFontMarker(appFontName) 908 || !registerScreenDeviceFont(fontOnServerIndex, dbExtras)) 909 dbExtras->removeAppFontData(fnt); 910 } else { 911 if (fnt->screenDeviceFontFileId > 0) 912 S60->screenDevice()->RemoveFile(fnt->screenDeviceFontFileId); // May still have the file open! 913 QFile::remove(fnt->temporaryFileName); 914 *fnt = QFontDatabasePrivate::ApplicationFont(); 915 } 916 lock.relock(); 350 917 } 351 918 352 919 bool QFontDatabase::removeApplicationFont(int handle) 353 920 { 354 Q_UNUSED(handle); 355 return false; 921 QMutexLocker locker(fontDatabaseMutex()); 922 923 QFontDatabasePrivate *db = privateDb(); 924 if (!db || handle < 0 || handle >= db->applicationFonts.count()) 925 return false; 926 QSymbianFontDatabaseExtrasImplementation *dbExtras = 927 static_cast<QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); 928 if (!dbExtras) 929 return false; 930 931 QFontDatabasePrivate::ApplicationFont *fnt = &db->applicationFonts[handle]; 932 if (fnt->families.isEmpty()) 933 return true; // Nothing to remove. Return peacefully. 934 935 // Must remove all font engines with their CFonts, first 936 QFontCache::instance()->clear(); 937 db->free(); 938 dbExtras->removeAppFontData(fnt); 939 940 db->invalidate(); // This will just emit 'fontDatabaseChanged()' 941 return true; 356 942 } 357 943 358 944 bool QFontDatabase::removeAllApplicationFonts() 359 945 { 360 return false; 946 QMutexLocker locker(fontDatabaseMutex()); 947 948 const int applicationFontsCount = privateDb()->applicationFonts.count(); 949 for (int i = 0; i < applicationFontsCount; ++i) 950 if (!removeApplicationFont(i)) 951 return false; 952 return true; 361 953 } 362 954 … … 377 969 } 378 970 379 QFontEngine *QFontDatabase::findFont(int script, const QFontPrivate * , const QFontDef &req)971 QFontEngine *QFontDatabase::findFont(int script, const QFontPrivate *d, const QFontDef &req) 380 972 { 381 973 const QFontCache::Key key(cleanedFontDef(req), script); … … 391 983 QtFontDesc desc; 392 984 QList<int> blacklistedFamilies; 393 match(script, req, req.family, QString(), -1, &desc, blacklistedFamilies);985 match(script, key.def, key.def.family, QString(), -1, &desc, blacklistedFamilies); 394 986 if (!desc.family) // falling back to application font 395 987 desc.family = db->family(QApplication::font().defaultFamily()); … … 417 1009 QFontDef request = req; 418 1010 request.family = fontFamily; 419 #if defined(QT_NO_FREETYPE)1011 #ifdef QT_NO_FREETYPE 420 1012 const QSymbianFontDatabaseExtrasImplementation *dbExtras = 421 1013 static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); 422 1014 const QSymbianTypeFaceExtras *typeFaceExtras = 423 1015 dbExtras->extras(fontFamily, request.weight > QFont::Normal, request.style != QFont::StyleNormal); 1016 1017 // We need a valid pixelSize, e.g. for lineThickness() 1018 if (request.pixelSize < 0) 1019 request.pixelSize = request.pointSize * d->dpi / 72; 1020 424 1021 fe = new QFontEngineS60(request, typeFaceExtras); 425 #else 1022 #else // QT_NO_FREETYPE 1023 Q_UNUSED(d) 426 1024 QFontEngine::FaceId faceId; 427 1025 const QtFontFamily * const reqQtFontFamily = db->family(fontFamily); … … 434 1032 else 435 1033 delete fte; 436 #endif 1034 #endif // QT_NO_FREETYPE 437 1035 438 1036 Q_ASSERT(fe); -
trunk/src/gui/text/qfontdatabase_win.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 46 46 #include "qfontengine_p.h" 47 47 #include "qpaintdevice.h" 48 #include "qlibrary.h"48 #include <private/qsystemlibrary_p.h> 49 49 #include "qabstractfileengine.h" 50 50 #include "qendian.h" … … 1050 1050 if(!fnt->data.isEmpty()) { 1051 1051 #ifndef Q_OS_WINCE 1052 PtrAddFontMemResourceEx ptrAddFontMemResourceEx = (PtrAddFontMemResourceEx)Q Library::resolve(QLatin1String("gdi32"),1052 PtrAddFontMemResourceEx ptrAddFontMemResourceEx = (PtrAddFontMemResourceEx)QSystemLibrary::resolve(QLatin1String("gdi32"), 1053 1053 "AddFontMemResourceEx"); 1054 1054 if (!ptrAddFontMemResourceEx) … … 1112 1112 return; 1113 1113 #else 1114 // supported from 2000 on, so no need to deal with the *A variant 1115 PtrAddFontResourceExW ptrAddFontResourceExW = (PtrAddFontResourceExW)QLibrary::resolve(QLatin1String("gdi32"), 1114 PtrAddFontResourceExW ptrAddFontResourceExW = (PtrAddFontResourceExW)QSystemLibrary::resolve(QLatin1String("gdi32"), 1116 1115 "AddFontResourceExW"); 1117 1116 if (!ptrAddFontResourceExW … … 1142 1141 return false; 1143 1142 #else 1144 PtrRemoveFontMemResourceEx ptrRemoveFontMemResourceEx = (PtrRemoveFontMemResourceEx)Q Library::resolve(QLatin1String("gdi32"),1143 PtrRemoveFontMemResourceEx ptrRemoveFontMemResourceEx = (PtrRemoveFontMemResourceEx)QSystemLibrary::resolve(QLatin1String("gdi32"), 1145 1144 "RemoveFontMemResourceEx"); 1146 1145 if (!ptrRemoveFontMemResourceEx … … 1153 1152 return false; 1154 1153 #else 1155 PtrRemoveFontResourceExW ptrRemoveFontResourceExW = (PtrRemoveFontResourceExW)Q Library::resolve(QLatin1String("gdi32"),1154 PtrRemoveFontResourceExW ptrRemoveFontResourceExW = (PtrRemoveFontResourceExW)QSystemLibrary::resolve(QLatin1String("gdi32"), 1156 1155 "RemoveFontResourceExW"); 1157 1156 if (!ptrRemoveFontResourceExW -
trunk/src/gui/text/qfontdatabase_x11.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 42 42 #include <qplatformdefs.h> 43 43 44 #include <qdatetime.h>45 44 #include <qdebug.h> 46 45 #include <qpaintdevice.h> 46 #include <qelapsedtimer.h> 47 47 48 48 #include <private/qt_x11_p.h> … … 78 78 extern double qt_pointSize(double pixelSize, int dpi); 79 79 extern double qt_pixelSize(double pointSize, int dpi); 80 81 // from qapplication.cpp 82 extern bool qt_is_gui_used; 80 83 81 84 static inline void capitalize (char *s) … … 1219 1222 1220 1223 #ifdef QFONTDATABASE_DEBUG 1221 Q Timet;1224 QElapsedTimer t; 1222 1225 t.start(); 1223 1226 #endif … … 1302 1305 return; 1303 1306 1304 Q Timet;1307 QElapsedTimer t; 1305 1308 t.start(); 1306 1309 … … 1315 1318 1316 1319 loadFontConfig(); 1317 FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", t.elapsed());1320 FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", int(t.elapsed())); 1318 1321 #endif 1319 1322 … … 1889 1892 } 1890 1893 1894 #if (defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6)) && defined(Q_CC_GNU) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3) 1895 #define NEEDS_GCC_BUG_WORKAROUND 1896 #endif 1897 1898 #ifdef NEEDS_GCC_BUG_WORKAROUND 1899 static inline void gccBugWorkaround(const QFontDef &req) 1900 { 1901 char buffer[8]; 1902 snprintf(buffer, 8, "%f", req.pixelSize); 1903 } 1904 #endif 1905 1891 1906 /*! \internal 1892 1907 Loads a QFontEngine for the specified \a script that matches the … … 1900 1915 QFontDef req = d->request; 1901 1916 if (req.pixelSize <= 0) 1902 req.pixelSize = floor(qt_pixelSize(req.pointSize, d->dpi) * 100 + 0.5) / 100;1917 req.pixelSize = qFloor(qt_pixelSize(req.pointSize, d->dpi) * 100.0 + 0.5) * 0.01; 1903 1918 if (req.pixelSize < 1) 1904 1919 req.pixelSize = 1; 1920 1921 #ifdef NEEDS_GCC_BUG_WORKAROUND 1922 // req.pixelSize ends up with a bogus value unless this workaround is called 1923 gccBugWorkaround(req); 1924 #endif 1925 1905 1926 if (req.weight == 0) 1906 1927 req.weight = QFont::Normal; … … 1938 1959 } else if (X11->has_fontconfig) { 1939 1960 fe = loadFc(d, script, req); 1940 1941 if (fe != 0 && fe->fontDef.pixelSize != req.pixelSize) { 1942 delete fe; 1943 fe = loadXlfd(d->screen, script, req); 1961 if (fe != 0 && fe->fontDef.pixelSize != req.pixelSize && mainThread && qt_is_gui_used) { 1962 QFontEngine *xlfdFontEngine = loadXlfd(d->screen, script, req); 1963 if (xlfdFontEngine->fontDef.family == fe->fontDef.family) { 1964 delete fe; 1965 fe = xlfdFontEngine; 1966 } else { 1967 delete xlfdFontEngine; 1968 } 1944 1969 } 1945 1970 1946 1971 1947 1972 #endif 1948 } else if (mainThread ) {1973 } else if (mainThread && qt_is_gui_used) { 1949 1974 fe = loadXlfd(d->screen, script, req); 1950 1975 } … … 1982 2007 FcFontSet *set = FcConfigGetFonts(config, FcSetApplication); 1983 2008 if (!set) { 1984 FcConfigAppFontAddFile(config, (const FcChar8 *)":/non-exist ant");2009 FcConfigAppFontAddFile(config, (const FcChar8 *)":/non-existent"); 1985 2010 set = FcConfigGetFonts(config, FcSetApplication); // try again 1986 2011 if (!set) -
trunk/src/gui/text/qfontengine.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 47 47 #include "qpainterpath.h" 48 48 #include "qvarlengtharray.h" 49 #include <private/qpdf_p.h>50 49 #include <qmath.h> 51 50 #include <qendian.h> … … 597 596 QImage i = alphaMapForGlyph(glyph); 598 597 if (t.type() > QTransform::TxTranslate) 599 i = i.transformed(t) ;598 i = i.transformed(t).convertToFormat(QImage::Format_Indexed8); 600 599 Q_ASSERT(i.depth() <= 8); // To verify that transformed didn't change the format... 600 601 601 return i; 602 602 } … … 607 607 QImage rgbMask(alphaMask.width(), alphaMask.height(), QImage::Format_RGB32); 608 608 609 QVector<QRgb> colorTable = alphaMask.colorTable(); 609 610 for (int y=0; y<alphaMask.height(); ++y) { 610 611 uint *dst = (uint *) rgbMask.scanLine(y); 611 612 uchar *src = (uchar *) alphaMask.scanLine(y); 612 for (int x=0; x<alphaMask.width(); ++x) 613 dst[x] = qRgb(src[x], src[x], src[x]); 613 for (int x=0; x<alphaMask.width(); ++x) { 614 int val = qAlpha(colorTable.at(src[x])); 615 dst[x] = qRgb(val, val, val); 616 } 614 617 } 615 618 … … 628 631 return QImage(); 629 632 QFixedPoint pt; 630 pt.x = 0;633 pt.x = -glyph_x; 631 634 pt.y = -glyph_y; // the baseline 632 635 QPainterPath path; 633 QImage im(glyph_width + qAbs(glyph_x) +4, glyph_height, QImage::Format_ARGB32_Premultiplied);636 QImage im(glyph_width + 4, glyph_height, QImage::Format_ARGB32_Premultiplied); 634 637 im.fill(Qt::transparent); 635 638 QPainter p(&im); … … 664 667 { 665 668 Properties p; 666 #ifndef QT_NO_PRINTER 667 QByteArray psname = QPdf::stripSpecialCharacters(fontDef.family.toUtf8()); 668 #else 669 QByteArray psname = fontDef.family.toUtf8(); 670 #endif 669 QByteArray psname = QFontEngine::convertToPostscriptFontFamilyName(fontDef.family.toUtf8()); 671 670 psname += '-'; 672 671 psname += QByteArray::number(fontDef.style); … … 718 717 719 718 // Limit the glyph caches to 4. This covers all 90 degree rotations and limits 720 // memory use when there is contin ous or random rotation719 // memory use when there is continuous or random rotation 721 720 if (m_glyphCaches.size() == 4) 722 721 delete m_glyphCaches.takeLast().cache; … … 871 870 enum { 872 871 Invalid, 872 AppleRoman, 873 873 Symbol, 874 AppleRoman,875 874 Unicode11, 876 875 Unicode, … … 936 935 937 936 resolveTable: 938 *isSymbolFont = (s core == Symbol);937 *isSymbolFont = (symbolTable > -1); 939 938 940 939 unsigned int unicode_table = qFromBigEndian<quint32>(maps + 8*tableToUse + 4); … … 1078 1077 } 1079 1078 1079 QByteArray QFontEngine::convertToPostscriptFontFamilyName(const QByteArray &family) 1080 { 1081 QByteArray f = family; 1082 f.replace(' ', ""); 1083 f.replace('(', ""); 1084 f.replace(')', ""); 1085 f.replace('<', ""); 1086 f.replace('>', ""); 1087 f.replace('[', ""); 1088 f.replace(']', ""); 1089 f.replace('{', ""); 1090 f.replace('}', ""); 1091 f.replace('/', ""); 1092 f.replace('%', ""); 1093 return f; 1094 } 1095 1080 1096 Q_GLOBAL_STATIC_WITH_INITIALIZER(QVector<QRgb>, qt_grayPalette, { 1081 1097 x->resize(256); … … 1088 1104 { 1089 1105 return *qt_grayPalette(); 1106 } 1107 1108 QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round) 1109 { 1110 if (glyphs.numGlyphs >= 1) { 1111 glyph_t glyph = glyphs.glyphs[glyphs.numGlyphs - 1]; 1112 glyph_metrics_t gi = boundingBox(glyph); 1113 if (gi.isValid()) 1114 return round ? QFixed(qRound(gi.xoff - gi.x - gi.width)) 1115 : QFixed(gi.xoff - gi.x - gi.width); 1116 } 1117 return 0; 1090 1118 } 1091 1119 -
trunk/src/gui/text/qfontengine_ft.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 52 52 #include "qthreadstorage.h" 53 53 #include <qmath.h> 54 #include <private/qpdf_p.h>55 54 #include <private/qharfbuzz_p.h> 56 55 … … 59 58 #include FT_FREETYPE_H 60 59 #include FT_OUTLINE_H 60 #include FT_SYNTHESIS_H 61 61 #include FT_TRUETYPE_TABLES_H 62 62 #include FT_TYPE1_TABLES_H … … 92 92 #define X_SIZE(face,i) ((face)->available_sizes[i].width << 6) 93 93 #define Y_SIZE(face,i) ((face)->available_sizes[i].height << 6) 94 #endif 95 96 /* FreeType 2.1.10 starts to provide FT_GlyphSlot_Embolden */ 97 #if (FREETYPE_MAJOR*10000+FREETYPE_MINOR*100+FREETYPE_PATCH) >= 20110 98 #define Q_FT_GLYPHSLOT_EMBOLDEN(slot) FT_GlyphSlot_Embolden(slot) 99 #else 100 #define Q_FT_GLYPHSLOT_EMBOLDEN(slot) 94 101 #endif 95 102 … … 618 625 kerning_pairs_loaded = false; 619 626 transform = false; 627 embolden = false; 620 628 antialias = true; 621 629 freetype = 0; 622 default_load_flags = 0;630 default_load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; 623 631 default_hint_style = HintNone; 624 632 subpixelType = Subpixel_None; … … 680 688 FT_Face face = lockFace(); 681 689 682 //underline metrics683 690 if (FT_IS_SCALABLE(face)) { 684 line_thickness = QFixed::fromFixed(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale));685 underline_position = QFixed::fromFixed(-FT_MulFix(face->underline_position, face->size->metrics.y_scale));686 691 bool fake_oblique = (fontDef.style != QFont::StyleNormal) && !(face->style_flags & FT_STYLE_FLAG_ITALIC); 687 692 if (fake_oblique) … … 691 696 if (fake_oblique) 692 697 transform = true; 698 // fake bold 699 if ((fontDef.weight == QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face)) 700 embolden = true; 701 // underline metrics 702 line_thickness = QFixed::fromFixed(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale)); 703 underline_position = QFixed::fromFixed(-FT_MulFix(face->underline_position, face->size->metrics.y_scale)); 693 704 } else { 694 705 // copied from QFontEngineQPF … … 747 758 QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph) const 748 759 { 749 Glyph *g = set->g lyph_data.value(glyph);760 Glyph *g = set->getGlyph(glyph); 750 761 if (g) 751 762 return g; … … 790 801 791 802 FT_GlyphSlot slot = face->glyph; 803 if (embolden) Q_FT_GLYPHSLOT_EMBOLDEN(slot); 792 804 int left = slot->metrics.horiBearingX; 793 805 int right = slot->metrics.horiBearingX + slot->metrics.width; … … 859 871 } 860 872 861 Glyph *g = set->g lyph_data.value(glyph);873 Glyph *g = set->getGlyph(glyph); 862 874 if (g && g->format == format) { 863 875 if (uploadToServer && !g->uploadedToServer) { 864 set-> glyph_data[glyph] = 0;876 set->setGlyph(glyph, 0); 865 877 delete g; 866 878 g = 0; … … 935 947 936 948 FT_GlyphSlot slot = face->glyph; 949 if (embolden) Q_FT_GLYPHSLOT_EMBOLDEN(slot); 937 950 FT_Library library = qt_getFreetype(); 938 951 … … 1159 1172 } 1160 1173 1161 set-> glyph_data[glyph] = g;1174 set->setGlyph(glyph, g); 1162 1175 1163 1176 return g; … … 1183 1196 Properties p = freetype->properties(); 1184 1197 if (p.postscriptName.isEmpty()) { 1185 p.postscriptName = fontDef.family.toUtf8(); 1186 #ifndef QT_NO_PRINTER 1187 p.postscriptName = QPdf::stripSpecialCharacters(p.postscriptName); 1188 #endif 1198 p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(fontDef.family.toUtf8()); 1189 1199 } 1190 1200 … … 1210 1220 if ((fontDef.style != QFont::StyleNormal) && !(freetype->face->style_flags & FT_STYLE_FLAG_ITALIC)) 1211 1221 s = SynthesizedItalic; 1222 if ((fontDef.weight == QFont::Bold) && !(freetype->face->style_flags & FT_STYLE_FLAG_BOLD)) 1223 s |= SynthesizedBold; 1212 1224 if (fontDef.stretch != 100 && FT_IS_SCALABLE(freetype->face)) 1213 1225 s |= SynthesizedStretch; … … 1369 1381 if (!gs) { 1370 1382 // don't try to load huge fonts 1371 bool draw_as_outline = fontDef.pixelSize * qSqrt( matrix.det()) >= 64;1383 bool draw_as_outline = fontDef.pixelSize * qSqrt(qAbs(matrix.det())) >= 64; 1372 1384 if (draw_as_outline) 1373 1385 return 0; … … 1382 1394 gs = &transformedGlyphSets[0]; 1383 1395 1384 qDeleteAll(gs->glyph_data); 1385 gs->glyph_data.clear(); 1396 gs->clear(); 1386 1397 1387 1398 gs->id = allocateServerGlyphSet(); … … 1399 1410 1400 1411 for (int i = 0; i < num_glyphs; ++i) { 1401 Glyph *glyph = gs->g lyph_data.value(glyphs[i]);1412 Glyph *glyph = gs->getGlyph(glyphs[i]); 1402 1413 if (glyph == 0 || glyph->format != format) { 1403 1414 if (!face) { … … 1551 1562 for ( int i = 0; i < len; ++i ) { 1552 1563 unsigned int uc = getChar(str, i, len); 1553 if (mirrored)1554 uc = QChar::mirroredChar(uc);1555 1564 glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0; 1556 1565 if ( !glyphs->glyphs[glyph_pos] ) { … … 1636 1645 if (flags & QTextEngine::DesignMetrics) { 1637 1646 for (int i = 0; i < glyphs->numGlyphs; i++) { 1638 Glyph *g = defaultGlyphSet.g lyph_data.value(glyphs->glyphs[i]);1647 Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]); 1639 1648 if (g) { 1640 1649 glyphs->advances_x[i] = QFixed::fromFixed(g->linearAdvance); … … 1649 1658 } else { 1650 1659 for (int i = 0; i < glyphs->numGlyphs; i++) { 1651 Glyph *g = defaultGlyphSet.g lyph_data.value(glyphs->glyphs[i]);1660 Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]); 1652 1661 if (g) { 1653 1662 glyphs->advances_x[i] = QFixed(g->advance); … … 1678 1687 QFixed xmax = 0; 1679 1688 for (int i = 0; i < glyphs.numGlyphs; i++) { 1680 Glyph *g = defaultGlyphSet.g lyph_data.value(glyphs.glyphs[i]);1689 Glyph *g = defaultGlyphSet.getGlyph(glyphs.glyphs[i]); 1681 1690 if (!g) { 1682 1691 if (!face) … … 1720 1729 FT_Face face = 0; 1721 1730 glyph_metrics_t overall; 1722 Glyph *g = defaultGlyphSet.g lyph_data.value(glyph);1731 Glyph *g = defaultGlyphSet.getGlyph(glyph); 1723 1732 if (!g) { 1724 1733 face = lockFace(); … … 1784 1793 } 1785 1794 glyphSet = &transformedGlyphSets[0]; 1786 qDeleteAll(glyphSet->glyph_data); 1787 glyphSet->glyph_data.clear(); 1795 glyphSet->clear(); 1788 1796 glyphSet->id = allocateServerGlyphSet(); 1789 1797 glyphSet->transformationMatrix = m; … … 1793 1801 glyphSet = &defaultGlyphSet; 1794 1802 } 1795 Glyph * g = glyphSet->g lyph_data.value(glyph);1803 Glyph * g = glyphSet->getGlyph(glyph); 1796 1804 if (!g) { 1797 1805 face = lockFace(); … … 1882 1890 void QFontEngineFT::removeGlyphFromCache(glyph_t glyph) 1883 1891 { 1884 de lete defaultGlyphSet.glyph_data.take(glyph);1892 defaultGlyphSet.removeGlyphFromCache(glyph); 1885 1893 } 1886 1894 … … 1938 1946 transformationMatrix.xy = 0; 1939 1947 transformationMatrix.yx = 0; 1948 memset(fast_glyph_data, 0, sizeof(fast_glyph_data)); 1949 fast_glyph_count = 0; 1940 1950 } 1941 1951 1942 1952 QFontEngineFT::QGlyphSet::~QGlyphSet() 1943 1953 { 1954 clear(); 1955 } 1956 1957 void QFontEngineFT::QGlyphSet::clear() 1958 { 1959 if (fast_glyph_count > 0) { 1960 for (int i = 0; i < 256; ++i) { 1961 if (fast_glyph_data[i]) { 1962 delete fast_glyph_data[i]; 1963 fast_glyph_data[i] = 0; 1964 } 1965 } 1966 fast_glyph_count = 0; 1967 } 1944 1968 qDeleteAll(glyph_data); 1969 glyph_data.clear(); 1970 } 1971 1972 void QFontEngineFT::QGlyphSet::removeGlyphFromCache(int index) 1973 { 1974 if (index < 256) { 1975 if (fast_glyph_data[index]) { 1976 delete fast_glyph_data[index]; 1977 fast_glyph_data[index] = 0; 1978 if (fast_glyph_count > 0) 1979 --fast_glyph_count; 1980 } 1981 } else { 1982 delete glyph_data.take(index); 1983 } 1984 } 1985 1986 void QFontEngineFT::QGlyphSet::setGlyph(int index, Glyph *glyph) 1987 { 1988 if (index < 256) { 1989 if (!fast_glyph_data[index]) 1990 ++fast_glyph_count; 1991 fast_glyph_data[index] = glyph; 1992 } else { 1993 glyph_data.insert(index, glyph); 1994 } 1945 1995 } 1946 1996 -
trunk/src/gui/text/qfontengine_ft_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 181 181 unsigned long id; // server sided id, GlyphSet for X11 182 182 bool outline_drawing; 183 184 void removeGlyphFromCache(int index); 185 void clear(); 186 inline Glyph *getGlyph(int index) const 187 { 188 if (index < 256) 189 return fast_glyph_data[index]; 190 return glyph_data.value(index); 191 } 192 void setGlyph(int index, Glyph *glyph); 193 194 private: 183 195 mutable QHash<int, Glyph *> glyph_data; // maps from glyph index to glyph data 196 mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256 197 mutable int fast_glyph_count; 184 198 }; 185 199 … … 253 267 GlyphFormat defaultGlyphFormat() const { return defaultFormat; } 254 268 255 inline Glyph *cachedGlyph(glyph_t g) const { return defaultGlyphSet.g lyph_data.value(g); }269 inline Glyph *cachedGlyph(glyph_t g) const { return defaultGlyphSet.getGlyph(g); } 256 270 257 271 QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix); … … 291 305 bool antialias; 292 306 bool transform; 307 bool embolden; 293 308 SubpixelAntialiasingType subpixelType; 294 309 int lcdFilterType; -
trunk/src/gui/text/qfontengine_mac.mm
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 47 47 #include <private/qpaintengine_mac_p.h> 48 48 #include <private/qprintengine_mac_p.h> 49 #include <private/qpdf_p.h>50 49 #include <qglobal.h> 51 50 #include <qpixmap.h> … … 54 53 #include <qdebug.h> 55 54 #include <qendian.h> 55 #include <qmath.h> 56 56 57 57 #include <ApplicationServices/ApplicationServices.h> … … 162 162 ATSFontGetName(atsFontRef, kATSOptionFlagsDefault, &name); 163 163 164 transform = CGAffineTransformIdentity; 165 if (fontDef.stretch != 100) { 166 transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); 167 } 168 164 169 QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithNameAndSize(name, fontDef.pixelSize); 165 QCFType<CTFontRef> baseFont = CTFontCreateWithFontDescriptor(descriptor, fontDef.pixelSize, 0);166 ctfont = CTFontCreateCopyWithSymbolicTraits(baseFont, fontDef.pixelSize, 0, symbolicTraits, symbolicTraits);170 QCFType<CTFontRef> baseFont = CTFontCreateWithFontDescriptor(descriptor, fontDef.pixelSize, &transform); 171 ctfont = CTFontCreateCopyWithSymbolicTraits(baseFont, fontDef.pixelSize, &transform, symbolicTraits, symbolicTraits); 167 172 168 173 // CTFontCreateCopyWithSymbolicTraits returns NULL if we ask for a trait that does … … 226 231 glyph_t *initialGlyph = outGlyphs; 227 232 228 if (arraySize == 0) 229 return false; 233 if (arraySize == 0) { 234 // CoreText failed to shape the text we gave it, so we assume one glyph 235 // per character and build a list of invalid glyphs with zero advance 236 *nglyphs = len; 237 for (int i = 0; i < len; ++i) { 238 outGlyphs[i] = 0; 239 if (logClusters) 240 logClusters[i] = i; 241 outAdvances_x[i] = QFixed(); 242 outAdvances_y[i] = QFixed(); 243 outAttributes[i].clusterStart = true; 244 } 245 return true; 246 } 230 247 231 248 const bool rtl = (CTRunGetStatus(static_cast<CTRunRef>(CFArrayGetValueAtIndex(array, 0))) & kCTRunStatusRightToLeft); … … 304 321 outAdvances_x[idx] = QFixed::fromReal(tmpPoints[i + 1].x - tmpPoints[i].x); 305 322 outAdvances_y[idx] = QFixed::fromReal(tmpPoints[i + 1].y - tmpPoints[i].y); 323 324 if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { 325 outAdvances_x[idx] = outAdvances_x[idx].round(); 326 outAdvances_y[idx] = outAdvances_y[idx].round(); 327 } 306 328 } 307 329 CGSize lastGlyphAdvance; … … 309 331 310 332 outGlyphs[rtl ? 0 : (glyphCount - 1)] = tmpGlyphs[glyphCount - 1] | fontIndex; 311 outAdvances_x[rtl ? 0 : (glyphCount - 1)] = QFixed::fromReal(lastGlyphAdvance.width).ceil(); 333 outAdvances_x[rtl ? 0 : (glyphCount - 1)] = 334 (fontDef.styleStrategy & QFont::ForceIntegerMetrics) 335 ? QFixed::fromReal(lastGlyphAdvance.width).round() 336 : QFixed::fromReal(lastGlyphAdvance.width); 312 337 } 313 338 outGlyphs += glyphCount; … … 323 348 int *nglyphs, QTextEngine::ShaperFlags flags) const 324 349 { 325 return stringToCMap(str, len, glyphs, nglyphs, flags, 0, 0); 350 *nglyphs = len; 351 QCFType<CFStringRef> cfstring; 352 353 QVarLengthArray<CGGlyph> cgGlyphs(len); 354 CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len); 355 356 for (int i = 0; i < len; ++i) { 357 if (cgGlyphs[i]) { 358 glyphs->glyphs[i] = cgGlyphs[i]; 359 } else { 360 if (!cfstring) 361 cfstring = CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar *>(str), len, kCFAllocatorNull); 362 QCFType<CTFontRef> substituteFont = CTFontCreateForString(ctfont, cfstring, CFRangeMake(i, 1)); 363 CGGlyph substituteGlyph = 0; 364 CTFontGetGlyphsForCharacters(substituteFont, (const UniChar*)str + i, &substituteGlyph, 1); 365 if (substituteGlyph) { 366 const uint fontIndex = (fontIndexForFont(substituteFont) << 24); 367 glyphs->glyphs[i] = substituteGlyph | fontIndex; 368 if (!(flags & QTextEngine::GlyphIndicesOnly)) { 369 CGSize advance; 370 CTFontGetAdvancesForGlyphs(substituteFont, kCTFontHorizontalOrientation, &substituteGlyph, &advance, 1); 371 glyphs->advances_x[i] = QFixed::fromReal(advance.width); 372 glyphs->advances_y[i] = QFixed::fromReal(advance.height); 373 } 374 } 375 } 376 } 377 378 if (flags & QTextEngine::GlyphIndicesOnly) 379 return true; 380 381 QVarLengthArray<CGSize> advances(len); 382 CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), len); 383 384 for (int i = 0; i < len; ++i) { 385 if (glyphs->glyphs[i] & 0xff000000) 386 continue; 387 glyphs->advances_x[i] = QFixed::fromReal(advances[i].width); 388 glyphs->advances_y[i] = QFixed::fromReal(advances[i].height); 389 } 390 391 if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { 392 for (int i = 0; i < len; ++i) { 393 glyphs->advances_x[i] = glyphs->advances_x[i].round(); 394 glyphs->advances_y[i] = glyphs->advances_y[i].round(); 395 } 396 } 397 398 return true; 326 399 } 327 400 … … 359 432 synthesisFlags |= SynthesizedItalic; 360 433 } 361 434 transform = CGAffineTransformIdentity; 435 if (fontDef.stretch != 100) { 436 transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); 437 } 362 438 QByteArray os2Table = getSfntTable(MAKE_TAG('O', 'S', '/', '2')); 363 439 if (os2Table.size() >= 10) … … 379 455 { 380 456 QFixed w; 381 for (int i = 0; i < glyphs.numGlyphs; ++i) 382 w += glyphs.effectiveAdvance(i); 383 return glyph_metrics_t(0, -(ascent()), w, ascent()+descent(), w, 0); 457 bool round = fontDef.styleStrategy & QFont::ForceIntegerMetrics; 458 459 for (int i = 0; i < glyphs.numGlyphs; ++i) { 460 w += round ? glyphs.effectiveAdvance(i).round() 461 : glyphs.effectiveAdvance(i); 462 } 463 return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs, round), ascent()+descent(), w, 0); 384 464 } 385 465 glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph) … … 394 474 CGSize advances[1]; 395 475 CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, advances, 1); 396 ret.xoff = QFixed::fromReal(advances[0].width).ceil(); 397 ret.yoff = QFixed::fromReal(advances[0].height).ceil(); 476 ret.xoff = QFixed::fromReal(advances[0].width); 477 ret.yoff = QFixed::fromReal(advances[0].height); 478 479 if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { 480 ret.xoff = ret.xoff.round(); 481 ret.yoff = ret.yoff.round(); 482 } 483 398 484 return ret; 399 485 } … … 401 487 QFixed QCoreTextFontEngine::ascent() const 402 488 { 403 return QFixed::fromReal(CTFontGetAscent(ctfont)).ceil(); 489 return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) 490 ? QFixed::fromReal(CTFontGetAscent(ctfont)).round() 491 : QFixed::fromReal(CTFontGetAscent(ctfont)); 404 492 } 405 493 QFixed QCoreTextFontEngine::descent() const 406 494 { 495 QFixed d = QFixed::fromReal(CTFontGetDescent(ctfont)); 496 if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) 497 d = d.round(); 498 407 499 // subtract a pixel to even out the historical +1 in QFontMetrics::height(). 408 500 // Fix in Qt 5. 409 return QFixed::fromReal(CTFontGetDescent(ctfont)).ceil()- 1;501 return d - 1; 410 502 } 411 503 QFixed QCoreTextFontEngine::leading() const 412 504 { 413 return QFixed::fromReal(CTFontGetLeading(ctfont)).ceil(); 505 return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) 506 ? QFixed::fromReal(CTFontGetLeading(ctfont)).round() 507 : QFixed::fromReal(CTFontGetLeading(ctfont)); 414 508 } 415 509 QFixed QCoreTextFontEngine::xHeight() const 416 510 { 417 return QFixed::fromReal(CTFontGetXHeight(ctfont)).ceil(); 511 return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) 512 ? QFixed::fromReal(CTFontGetXHeight(ctfont)).round() 513 : QFixed::fromReal(CTFontGetXHeight(ctfont)); 418 514 } 419 515 QFixed QCoreTextFontEngine::averageCharWidth() const 420 516 { 421 517 // ### Need to implement properly and get the information from the OS/2 Table. 422 return QFontEngine::averageCharWidth(); 518 return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) 519 ? QFontEngine::averageCharWidth().round() 520 : QFontEngine::averageCharWidth(); 423 521 } 424 522 … … 463 561 cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0)); 464 562 465 // ###cgMatrix = CGAffineTransformConcat(cgMatrix, transform);563 cgMatrix = CGAffineTransformConcat(cgMatrix, transform); 466 564 467 565 CGContextSetTextMatrix(ctx, cgMatrix); … … 586 684 cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, tanf(14 * acosf(0) / 90), 1, 0, 0)); 587 685 588 // ###cgMatrix = CGAffineTransformConcat(cgMatrix, transform);686 cgMatrix = CGAffineTransformConcat(cgMatrix, transform); 589 687 590 688 CGContextSetTextMatrix(ctx, cgMatrix); … … 788 886 QTextEngine::ShaperFlags flags; 789 887 QFontEngineMacMulti::ShaperItem *shaperItem; 888 unsigned int styleStrategy; 790 889 }; 791 890 … … 856 955 QFixed yAdvance = FixedToQFixed(baselineDeltas[glyphIdx]); 857 956 QFixed xAdvance = FixedToQFixed(layoutData[glyphIdx + 1].realPos - layoutData[glyphIdx].realPos); 957 958 if (nfo->styleStrategy & QFont::ForceIntegerMetrics) { 959 yAdvance = yAdvance.round(); 960 xAdvance = xAdvance.round(); 961 } 858 962 859 963 if (glyphId != 0xffff || i == 0) { … … 1033 1137 nfo.flags = flags; 1034 1138 nfo.shaperItem = shaperItem; 1139 nfo.styleStrategy = fontDef.styleStrategy; 1035 1140 1036 1141 int prevNumGlyphs = *nglyphs; … … 1061 1166 | kATSLineDisableAllJustification 1062 1167 ; 1063 1064 layopts |= kATSLineUseDeviceMetrics;1065 1168 1066 1169 if (fontDef.styleStrategy & QFont::NoAntialias) … … 1367 1470 glyphs->advances_x[i] = QFixed::fromReal(metrics[i].deviceAdvance.x); 1368 1471 glyphs->advances_y[i] = QFixed::fromReal(metrics[i].deviceAdvance.y); 1472 1473 if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { 1474 glyphs->advances_x[i] = glyphs->advances_x[i].round(); 1475 glyphs->advances_y[i] = glyphs->advances_y[i].round(); 1476 } 1369 1477 } 1370 1478 } … … 1373 1481 { 1374 1482 QFixed w; 1375 for (int i = 0; i < glyphs.numGlyphs; ++i) 1376 w += glyphs.effectiveAdvance(i); 1377 return glyph_metrics_t(0, -(ascent()), w, ascent()+descent(), w, 0); 1483 bool round = fontDef.styleStrategy & QFont::ForceIntegerMetrics; 1484 for (int i = 0; i < glyphs.numGlyphs; ++i) { 1485 w += round ? glyphs.effectiveAdvance(i).round() 1486 : glyphs.effectiveAdvance(i); 1487 } 1488 return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs, round), ascent()+descent(), w, 0); 1378 1489 } 1379 1490 … … 1399 1510 gm.yoff = QFixed::fromReal(metrics.deviceAdvance.y); 1400 1511 1512 if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { 1513 gm.x = gm.x.floor(); 1514 gm.y = gm.y.floor(); 1515 gm.xoff = gm.xoff.round(); 1516 gm.yoff = gm.yoff.round(); 1517 } 1518 1401 1519 return gm; 1402 1520 } … … 1404 1522 QFixed QFontEngineMac::ascent() const 1405 1523 { 1406 return m_ascent; 1524 return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) 1525 ? m_ascent.round() 1526 : m_ascent; 1407 1527 } 1408 1528 … … 1411 1531 // subtract a pixel to even out the historical +1 in QFontMetrics::height(). 1412 1532 // Fix in Qt 5. 1413 return m_descent - 1; 1533 return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) 1534 ? m_descent.round() - 1 1535 : m_descent; 1414 1536 } 1415 1537 1416 1538 QFixed QFontEngineMac::leading() const 1417 1539 { 1418 return m_leading; 1540 return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) 1541 ? m_leading.round() 1542 : m_leading; 1419 1543 } 1420 1544 1421 1545 qreal QFontEngineMac::maxCharWidth() const 1422 1546 { 1423 return m_maxCharWidth; 1547 return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) 1548 ? qRound(m_maxCharWidth) 1549 : m_maxCharWidth; 1424 1550 } 1425 1551 1426 1552 QFixed QFontEngineMac::xHeight() const 1427 1553 { 1428 return m_xHeight; 1554 return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) 1555 ? m_xHeight.round() 1556 : m_xHeight; 1429 1557 } 1430 1558 1431 1559 QFixed QFontEngineMac::averageCharWidth() const 1432 1560 { 1433 return m_averageCharWidth; 1561 return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) 1562 ? m_averageCharWidth.round() 1563 : m_averageCharWidth; 1434 1564 } 1435 1565 … … 1723 1853 if (ATSFontGetPostScriptName(FMGetATSFontRefFromFont(fontID), kATSOptionFlagsDefault, &psName) == noErr) 1724 1854 props.postscriptName = QString(psName).toUtf8(); 1725 props.postscriptName = Q Pdf::stripSpecialCharacters(props.postscriptName);1855 props.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(props.postscriptName); 1726 1856 return props; 1727 1857 } -
trunk/src/gui/text/qfontengine_p.h
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 159 159 virtual QFixed emSquareSize() const { return ascent(); } 160 160 161 /* returns 0 as glyph index for non exist ant glyphs */161 /* returns 0 as glyph index for non existent glyphs */ 162 162 virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const = 0; 163 163 … … 181 181 /** 182 182 * Create a qimage with the alpha values for the glyph. 183 * Returns an image indexed_8 with index values ranging from 0=fully transpar ant to 255=opaque183 * Returns an image indexed_8 with index values ranging from 0=fully transparent to 255=opaque 184 184 */ 185 185 virtual QImage alphaMapForGlyph(glyph_t); … … 227 227 static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize); 228 228 static quint32 getTrueTypeGlyphIndex(const uchar *cmap, uint unicode); 229 230 static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily); 229 231 230 232 QAtomicInt ref; … … 254 256 protected: 255 257 static const QVector<QRgb> &grayPalette(); 258 QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round = false); 256 259 257 260 private: … … 463 466 QCoreTextFontEngineMulti *parentEngine; 464 467 int synthesisFlags; 468 CGAffineTransform transform; 465 469 friend class QCoreTextFontEngineMulti; 466 470 }; … … 494 498 CTFontRef ctfont; 495 499 mutable QCFType<CFMutableDictionaryRef> attributeDict; 496 500 CGAffineTransform transform; 497 501 friend class QFontDialogPrivate; 498 502 }; -
trunk/src/gui/text/qfontengine_qpf.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 579 579 for (int i = 0; i < len; ++i) { 580 580 unsigned int uc = getChar(str, i, len); 581 if (mirrored)582 uc = QChar::mirroredChar(uc);583 581 glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); 584 582 if(!glyphs->glyphs[glyph_pos] && uc < 0x100) … … 921 919 if (!renderingFontEngine) 922 920 return; 923 924 QImage img = renderingFontEngine->alphaMapForGlyph(glyph).convertToFormat(QImage::Format_Indexed8); 921 QImage img = renderingFontEngine->alphaMapForGlyph(glyph); 922 if (img.format() != QImage::Format_Indexed8) { 923 bool mono = img.depth() == 1; 924 img = img.convertToFormat(QImage::Format_Indexed8); 925 if (mono) { 926 //### we know that 1 is opaque and 0 is transparent 927 uchar *byte = img.bits(); 928 int count = img.byteCount(); 929 while (count--) 930 *byte++ *= 0xff; 931 } 932 } 925 933 glyph_metrics_t metrics = renderingFontEngine->boundingBox(glyph); 926 934 renderingFontEngine->removeGlyphFromCache(glyph); -
trunk/src/gui/text/qfontengine_qpf_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qfontengine_qws.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 558 558 for (int i = 0; i < glyphs.numGlyphs; ++i) 559 559 w += glyphs.effectiveAdvance(i); 560 return glyph_metrics_t(0, -ascent(), w , ascent()+descent()+1, w, 0);560 return glyph_metrics_t(0, -ascent(), w - lastRightBearing(glyphs), ascent()+descent()+1, w, 0); 561 561 } 562 562 -
trunk/src/gui/text/qfontengine_s60.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 42 42 #include "qfontengine_s60_p.h" 43 43 #include "qtextengine_p.h" 44 #include "qendian.h" 44 45 #include "qglobal.h" 45 46 #include <private/qapplication_p.h> 46 47 #include "qimage.h" 47 48 #include <private/qt_s60_p.h> 49 #include <private/qpixmap_s60_p.h> 48 50 49 51 #include <e32base.h> … … 51 53 #include <eikenv.h> 52 54 #include <gdi.h> 55 #if defined(Q_SYMBIAN_HAS_GLYPHOUTLINE_API) 56 #include <graphics/gdi/gdiplatapi.h> 57 #endif // Q_SYMBIAN_HAS_GLYPHOUTLINE_API 58 59 // Replication of TGetFontTableParam & friends. 60 // There is unfortunately no compile time flag like SYMBIAN_FONT_TABLE_API 61 // that would help us to only replicate these things for Symbian versions 62 // that do not yet have the font table Api. Symbian's public SDK does 63 // generally not define any usable macros. 64 class QSymbianTGetFontTableParam 65 { 66 public: 67 TUint32 iTag; 68 TAny *iContent; 69 TInt iLength; 70 }; 71 const TUid QSymbianKFontGetFontTable = {0x102872C1}; 72 const TUid QSymbianKFontReleaseFontTable = {0x2002AC24}; 53 73 54 74 QT_BEGIN_NAMESPACE 55 75 56 QSymbianTypeFaceExtras::QSymbianTypeFaceExtras(CFont* fontOwner, COpenFont *font) 57 : m_font(font) 58 , m_cmap(0) 76 QSymbianTypeFaceExtras::QSymbianTypeFaceExtras(CFont* cFont, COpenFont *openFont) 77 : m_cFont(cFont) 59 78 , m_symbolCMap(false) 60 , m_fontOwner(fontOwner) 61 { 62 TAny *trueTypeExtension = NULL; 63 m_font->ExtendedInterface(KUidOpenFontTrueTypeExtension, trueTypeExtension); 64 m_trueTypeExtension = static_cast<MOpenFontTrueTypeExtension*>(trueTypeExtension); 65 Q_ASSERT(m_trueTypeExtension); 79 , m_openFont(openFont) 80 { 81 if (!symbianFontTableApiAvailable()) { 82 TAny *trueTypeExtension = NULL; 83 m_openFont->ExtendedInterface(KUidOpenFontTrueTypeExtension, trueTypeExtension); 84 m_trueTypeExtension = static_cast<MOpenFontTrueTypeExtension*>(trueTypeExtension); 85 Q_ASSERT(m_trueTypeExtension); 86 } 87 } 88 89 QSymbianTypeFaceExtras::~QSymbianTypeFaceExtras() 90 { 91 if (symbianFontTableApiAvailable()) 92 S60->screenDevice()->ReleaseFont(m_cFont); 66 93 } 67 94 68 95 QByteArray QSymbianTypeFaceExtras::getSfntTable(uint tag) const 69 96 { 70 Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag)); 71 TInt error = KErrNone; 72 TInt tableByteLength = 0; 73 TAny *table = q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength)); 74 QByteArray result(static_cast<const char*>(table), tableByteLength); 75 m_trueTypeExtension->ReleaseTrueTypeTable(table); 97 if (symbianFontTableApiAvailable()) { 98 QSymbianTGetFontTableParam fontTableParams = { tag, 0, 0 }; 99 if (m_cFont->ExtendedFunction(QSymbianKFontGetFontTable, &fontTableParams) == KErrNone) { 100 const char* const fontTableContent = 101 static_cast<const char *>(fontTableParams.iContent); 102 const QByteArray fontTable(fontTableContent, fontTableParams.iLength); 103 m_cFont->ExtendedFunction(QSymbianKFontReleaseFontTable, &fontTableParams); 104 return fontTable; 105 } 106 return QByteArray(); 107 } else { 108 Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag)); 109 TInt error = KErrNone; 110 TInt tableByteLength = 0; 111 TAny *table = q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength)); 112 const QByteArray result(static_cast<const char*>(table), tableByteLength); 113 m_trueTypeExtension->ReleaseTrueTypeTable(table); 114 return result; 115 } 116 } 117 118 bool QSymbianTypeFaceExtras::getSfntTableData(uint tag, uchar *buffer, uint *length) const 119 { 120 bool result = true; 121 if (symbianFontTableApiAvailable()) { 122 QSymbianTGetFontTableParam fontTableParams = { tag, 0, 0 }; 123 if (m_cFont->ExtendedFunction(QSymbianKFontGetFontTable, &fontTableParams) == KErrNone) { 124 if (*length > 0 && *length < fontTableParams.iLength) { 125 result = false; // Caller did not allocate enough memory 126 } else { 127 *length = fontTableParams.iLength; 128 if (buffer) 129 memcpy(buffer, fontTableParams.iContent, fontTableParams.iLength); 130 } 131 m_cFont->ExtendedFunction(QSymbianKFontReleaseFontTable, &fontTableParams); 132 } else { 133 result = false; 134 } 135 } else { 136 if (!m_trueTypeExtension->HasTrueTypeTable(tag)) 137 return false; 138 139 TInt error = KErrNone; 140 TInt tableByteLength; 141 TAny *table = 142 q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength)); 143 144 if (error != KErrNone) { 145 return false; 146 } else if (*length > 0 && *length < tableByteLength) { 147 result = false; // Caller did not allocate enough memory 148 } else { 149 *length = tableByteLength; 150 if (buffer) 151 memcpy(buffer, table, tableByteLength); 152 } 153 154 m_trueTypeExtension->ReleaseTrueTypeTable(table); 155 } 76 156 return result; 77 157 } 78 158 79 bool QSymbianTypeFaceExtras::getSfntTableData(uint tag, uchar *buffer, uint *length) const 80 { 81 if (!m_trueTypeExtension->HasTrueTypeTable(tag)) 82 return false; 83 84 bool result = true; 85 TInt error = KErrNone; 86 TInt tableByteLength; 87 TAny *table = 88 q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength)); 89 90 if (error != KErrNone) { 91 return false; 92 } else if (*length > 0 && *length < tableByteLength) { 93 result = false; // Caller did not allocate enough memory 159 const uchar *QSymbianTypeFaceExtras::cmap() const 160 { 161 if (m_cmapTable.isNull()) { 162 const QByteArray cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); 163 int size = 0; 164 const uchar *cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *> 165 (cmapTable.constData()), cmapTable.size(), &m_symbolCMap, &size); 166 m_cmapTable = QByteArray(reinterpret_cast<const char *>(cmap), size); 167 } 168 return reinterpret_cast<const uchar *>(m_cmapTable.constData()); 169 } 170 171 bool QSymbianTypeFaceExtras::isSymbolCMap() const 172 { 173 return m_symbolCMap; 174 } 175 176 CFont *QSymbianTypeFaceExtras::fontOwner() const 177 { 178 return m_cFont; 179 } 180 181 QFixed QSymbianTypeFaceExtras::unitsPerEm() const 182 { 183 if (m_unitsPerEm.value() != 0) 184 return m_unitsPerEm; 185 const QByteArray head = getSfntTable(MAKE_TAG('h', 'e', 'a', 'd')); 186 const int unitsPerEmOffset = 18; 187 if (head.size() > unitsPerEmOffset + sizeof(quint16)) { 188 const uchar* tableData = reinterpret_cast<const uchar*>(head.constData()); 189 const uchar* unitsPerEm = tableData + unitsPerEmOffset; 190 m_unitsPerEm = qFromBigEndian<quint16>(unitsPerEm); 94 191 } else { 95 *length = tableByteLength; 96 if (buffer) 97 qMemCopy(buffer, table, tableByteLength); 98 } 99 100 m_trueTypeExtension->ReleaseTrueTypeTable(table); 101 return result; 102 } 103 104 const unsigned char *QSymbianTypeFaceExtras::cmap() const 105 { 106 if (!m_cmap) { 107 m_cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); 108 int size = 0; 109 m_cmap = QFontEngineS60::getCMap(reinterpret_cast<const uchar *>(m_cmapTable.constData()), m_cmapTable.size(), &m_symbolCMap, &size); 110 } 111 return m_cmap; 112 } 113 114 CFont *QSymbianTypeFaceExtras::fontOwner() const 115 { 116 return m_fontOwner; 117 } 118 192 // Bitmap font? Corrupt font? 193 // We return -1 and let the QFontEngineS60 return the pixel size. 194 m_unitsPerEm = -1; 195 } 196 return m_unitsPerEm; 197 } 198 199 bool QSymbianTypeFaceExtras::symbianFontTableApiAvailable() 200 { 201 enum FontTableApiAvailability { 202 Unknown, 203 Available, 204 Unavailable 205 }; 206 static FontTableApiAvailability availability = 207 QSysInfo::symbianVersion() < QSysInfo::SV_SF_3 ? 208 Unavailable : Unknown; 209 if (availability == Unknown) { 210 // Actually, we should ask CFeatureDiscovery::IsFeatureSupportedL() 211 // with FfFontTable here. But since at the time of writing, the 212 // FfFontTable flag check either gave false positives or false 213 // negatives. Here comes an implicit check via CFont::ExtendedFunction. 214 QSymbianTGetFontTableParam fontTableParams = { 215 MAKE_TAG('O', 'S', '/', '2'), 0, 0 }; 216 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); 217 CFont *font; 218 const TInt getFontErr = S60->screenDevice()->GetNearestFontInTwips(font, TFontSpec()); 219 Q_ASSERT(getFontErr == KErrNone); 220 if (font->ExtendedFunction(QSymbianKFontGetFontTable, &fontTableParams) == KErrNone) { 221 font->ExtendedFunction(QSymbianKFontReleaseFontTable, &fontTableParams); 222 availability = Available; 223 } else { 224 availability = Unavailable; 225 } 226 S60->screenDevice()->ReleaseFont(font); 227 lock.relock(); 228 } 229 return availability == Available; 230 } 119 231 120 232 // duplicated from qfontengine_xyz.cpp … … 132 244 } 133 245 246 extern QString qt_symbian_fontNameWithAppFontMarker(const QString &fontName); // qfontdatabase_s60.cpp 247 134 248 CFont *QFontEngineS60::fontWithSize(qreal size) const 135 249 { 136 250 CFont *result = 0; 137 TFontSpec fontSpec(qt_QString2TPtrC(QFontEngine::fontDef.family), TInt(size)); 251 const QString family = qt_symbian_fontNameWithAppFontMarker(QFontEngine::fontDef.family); 252 TFontSpec fontSpec(qt_QString2TPtrC(family), TInt(size)); 138 253 fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap); 139 254 fontSpec.iFontStyle.SetPosture(QFontEngine::fontDef.style == QFont::StyleNormal?EPostureUpright:EPostureItalic); … … 190 305 } 191 306 307 QFixed QFontEngineS60::emSquareSize() const 308 { 309 const QFixed unitsPerEm = m_extras->unitsPerEm(); 310 return unitsPerEm.toInt() == -1 ? 311 QFixed::fromReal(m_originalFontSizeInPixels) : unitsPerEm; 312 } 313 192 314 bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const 193 315 { … … 203 325 const unsigned int uc = getChar(characters, i, len); 204 326 *g++ = QFontEngine::getTrueTypeGlyphIndex(cmap, 205 isRtl? QChar::mirroredChar(uc) : uc);327 (isRtl && !m_extras->isSymbolCMap()) ? QChar::mirroredChar(uc) : uc); 206 328 } 207 329 … … 219 341 { 220 342 Q_UNUSED(flags); 343 TOpenFontCharMetrics metrics; 344 const TUint8 *glyphBitmapBytes; 345 TSize glyphBitmapSize; 221 346 for (int i = 0; i < glyphs->numGlyphs; i++) { 222 const glyph_metrics_t bbox = boundingBox_const(glyphs->glyphs[i]); 223 glyphs->advances_x[i] = bbox.xoff; 224 glyphs->advances_y[i] = bbox.yoff; 225 } 347 getCharacterData(glyphs->glyphs[i], metrics, glyphBitmapBytes, glyphBitmapSize); 348 glyphs->advances_x[i] = metrics.HorizAdvance(); 349 glyphs->advances_y[i] = 0; 350 } 351 } 352 353 #ifdef Q_SYMBIAN_HAS_GLYPHOUTLINE_API 354 static bool parseGlyphPathData(const char *dataStr, const char *dataEnd, QPainterPath &path, 355 qreal fontPixelSize, const QPointF &offset, bool hinted); 356 #endif //Q_SYMBIAN_HAS_GLYPHOUTLINE_API 357 358 void QFontEngineS60::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, 359 int nglyphs, QPainterPath *path, 360 QTextItem::RenderFlags flags) 361 { 362 #ifdef Q_SYMBIAN_HAS_GLYPHOUTLINE_API 363 Q_UNUSED(flags) 364 RGlyphOutlineIterator iterator; 365 const TInt error = iterator.Open(*m_activeFont, glyphs, nglyphs); 366 if (KErrNone != error) 367 return; 368 const qreal fontSizeInPixels = qreal(m_activeFont->HeightInPixels()); 369 int count = 0; 370 do { 371 const TUint8* outlineUint8 = iterator.Outline(); 372 const char* const outlineChar = reinterpret_cast<const char*>(outlineUint8); 373 const char* const outlineEnd = outlineChar + iterator.OutlineLength(); 374 parseGlyphPathData(outlineChar, outlineEnd, *path, fontSizeInPixels, 375 positions[count++].toPointF(), false); 376 } while(KErrNone == iterator.Next() && count <= nglyphs); 377 iterator.Close(); 378 #else // Q_SYMBIAN_HAS_GLYPHOUTLINE_API 379 QFontEngine::addGlyphsToPath(glyphs, positions, nglyphs, path, flags); 380 #endif //Q_SYMBIAN_HAS_GLYPHOUTLINE_API 226 381 } 227 382 228 383 QImage QFontEngineS60::alphaMapForGlyph(glyph_t glyph) 229 384 { 385 // Note: On some Symbian versions (apparently <= Symbian^1), this 386 // function will return gray values 0x00, 0x10 ... 0xe0, 0xf0 due 387 // to a bug. The glyphs are nowhere perfectly opaque. 388 // This has been fixed for Symbian^3. 389 230 390 TOpenFontCharMetrics metrics; 231 391 const TUint8 *glyphBitmapBytes; … … 234 394 QImage result(glyphBitmapBytes, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight, glyphBitmapSize.iWidth, QImage::Format_Indexed8); 235 395 result.setColorTable(grayPalette()); 236 237 // The above setColorTable() call detached the image data anyway, so why not shape tha data a bit, while we can.238 // CFont::GetCharacterData() returns 8-bit data that obviously was 4-bit data before, and converted to 8-bit incorrectly.239 // The data values are 0x00, 0x10 ... 0xe0, 0xf0. So, a real opaque 0xff is never reached, which we get punished240 // for every time we want to blit this glyph in the raster paint engine.241 // "Fix" is to convert all 0xf0 to 0xff. Is fine, quality wise, and I assume faster than correcting all values.242 // Blitting is however, evidentially faster now.243 const int bpl = result.bytesPerLine();244 for (int row = 0; row < result.height(); ++row) {245 uchar *scanLine = result.scanLine(row);246 for (int column = 0; column < bpl; ++column) {247 if (*scanLine == 0xf0)248 *scanLine = 0xff;249 scanLine++;250 }251 }252 253 396 return result; 254 397 } … … 263 406 w += glyphs.effectiveAdvance(i); 264 407 265 return glyph_metrics_t(0, -ascent(), w , ascent()+descent()+1, w, 0);408 return glyph_metrics_t(0, -ascent(), w - lastRightBearing(glyphs), ascent()+descent()+1, w, 0); 266 409 } 267 410 … … 272 415 TSize glyphBitmapSize; 273 416 getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize); 274 TRect glyphBounds;275 metrics.GetHorizBounds(glyphBounds);276 417 const glyph_metrics_t result( 277 glyphBounds.iTl.iX,278 glyphBounds.iTl.iY,279 glyphBounds.Width(),280 glyphBounds.Height(),418 metrics.HorizBearingX(), 419 -metrics.HorizBearingY(), 420 metrics.Width(), 421 metrics.Height(), 281 422 metrics.HorizAdvance(), 282 423 0 … … 292 433 QFixed QFontEngineS60::ascent() const 293 434 { 294 return m_originalFont->FontMaxAscent(); 435 // Workaround for QTBUG-8013 436 // Stroke based fonts may return an incorrect FontMaxAscent of 0. 437 const QFixed ascent = m_originalFont->FontMaxAscent(); 438 return (ascent > 0) ? ascent : QFixed::fromReal(m_originalFontSizeInPixels) - descent(); 295 439 } 296 440 … … 357 501 } 358 502 503 #ifdef Q_SYMBIAN_HAS_GLYPHOUTLINE_API 504 static inline void skipSpacesAndComma(const char* &str, const char* const strEnd) 505 { 506 while (str <= strEnd && (*str == ' ' || *str == ',')) 507 ++str; 508 } 509 510 static bool parseGlyphPathData(const char *svgPath, const char *svgPathEnd, QPainterPath &path, 511 qreal fontPixelSize, const QPointF &offset, bool hinted) 512 { 513 Q_UNUSED(hinted) 514 QPointF p1, p2, firstSubPathPoint; 515 qreal *elementValues[] = 516 {&p1.rx(), &p1.ry(), &p2.rx(), &p2.ry()}; 517 const int unitsPerEm = 2048; // See: http://en.wikipedia.org/wiki/Em_%28typography%29 518 const qreal resizeFactor = fontPixelSize / unitsPerEm; 519 520 while (svgPath < svgPathEnd) { 521 skipSpacesAndComma(svgPath, svgPathEnd); 522 const char pathElem = *svgPath++; 523 skipSpacesAndComma(svgPath, svgPathEnd); 524 525 if (pathElem != 'Z') { 526 char *endStr = 0; 527 int elementValuesCount = 0; 528 for (int i = 0; i < 4; ++i) { // 4 = size of elementValues[] 529 qreal coordinateValue = strtod(svgPath, &endStr); 530 if (svgPath == endStr) 531 break; 532 if (i % 2) // Flip vertically 533 coordinateValue = -coordinateValue; 534 *elementValues[i] = coordinateValue * resizeFactor; 535 elementValuesCount++; 536 svgPath = endStr; 537 skipSpacesAndComma(svgPath, svgPathEnd); 538 } 539 p1 += offset; 540 if (elementValuesCount == 2) 541 p2 = firstSubPathPoint; 542 else 543 p2 += offset; 544 } 545 546 switch (pathElem) { 547 case 'M': 548 firstSubPathPoint = p1; 549 path.moveTo(p1); 550 break; 551 case 'Z': 552 path.closeSubpath(); 553 break; 554 case 'L': 555 path.lineTo(p1); 556 break; 557 case 'Q': 558 path.quadTo(p1, p2); 559 break; 560 default: 561 return false; 562 } 563 } 564 return true; 565 } 566 #endif // Q_SYMBIAN_HAS_GLYPHOUTLINE_API 567 359 568 QT_END_NAMESPACE -
trunk/src/gui/text/qfontengine_s60_p.h
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 55 55 56 56 #include "qconfig.h" 57 #include "qfontengine_p.h"57 #include <private/qfontengine_p.h> 58 58 #include "qsize.h" 59 59 #include <openfont.h> 60 61 // The glyph outline code is intentionally disabled. It will be reactivated as 62 // soon as the glyph outline API is backported from Symbian(^4) to Symbian(^3). 63 #if 0 64 #define Q_SYMBIAN_HAS_GLYPHOUTLINE_API 65 #endif 60 66 61 67 class CFont; … … 67 73 { 68 74 public: 69 QSymbianTypeFaceExtras(CFont* fontOwner, COpenFont *font); 75 QSymbianTypeFaceExtras(CFont* cFont, COpenFont *openFont = 0); 76 ~QSymbianTypeFaceExtras(); 70 77 71 78 QByteArray getSfntTable(uint tag) const; 72 79 bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; 73 const u nsignedchar *cmap() const;80 const uchar *cmap() const; 74 81 CFont *fontOwner() const; 82 bool isSymbolCMap() const; 83 QFixed unitsPerEm() const; 84 static bool symbianFontTableApiAvailable(); 75 85 76 86 private: 77 COpenFont *m_font; 78 mutable MOpenFontTrueTypeExtension *m_trueTypeExtension; 79 mutable const unsigned char *m_cmap; 87 CFont* m_cFont; 80 88 mutable bool m_symbolCMap; 81 89 mutable QByteArray m_cmapTable; 82 CFont* m_fontOwner; 90 mutable QFixed m_unitsPerEm; 91 92 // m_openFont and m_openFont are used if Symbian does not provide 93 // the Font Table API 94 COpenFont *m_openFont; 95 mutable MOpenFontTrueTypeExtension *m_trueTypeExtension; 83 96 }; 84 97 … … 89 102 ~QFontEngineS60(); 90 103 104 QFixed emSquareSize() const; 91 105 bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; 92 106 void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const; 107 108 void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, 109 QPainterPath *path, QTextItem::RenderFlags flags); 93 110 94 111 QImage alphaMapForGlyph(glyph_t glyph); … … 122 139 private: 123 140 friend class QFontPrivate; 141 friend class QSymbianVGFontGlyphCache; 124 142 125 143 QFixed glyphAdvance(HB_Glyph glyph) const; -
trunk/src/gui/text/qfontengine_win.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 51 51 #include <private/qapplication_p.h> 52 52 53 #include < qlibrary.h>53 #include <private/qsystemlibrary_p.h> 54 54 #include <qpaintdevice.h> 55 55 #include <qpainter.h> … … 64 64 65 65 #include <private/qpainter_p.h> 66 #include <private/qpdf_p.h>67 66 #include "qpaintengine.h" 68 67 #include "qvarlengtharray.h" … … 141 140 return; 142 141 resolvedGetCharWidthI = true; 143 ptrGetCharWidthI = (PtrGetCharWidthI)Q Library::resolve(QLatin1String("gdi32"), "GetCharWidthI");142 ptrGetCharWidthI = (PtrGetCharWidthI)QSystemLibrary::resolve(QLatin1String("gdi32"), "GetCharWidthI"); 144 143 } 145 144 #endif // !defined(Q_WS_WINCE) … … 214 213 x_height = (int)otm->otmsXHeight; 215 214 loadKerningPairs(designToDevice); 216 _faceId.filename = QString::fromWCharArray((wchar_t *)((char *)otm + ( int)otm->otmpFullName)).toLatin1();215 _faceId.filename = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFullName)).toLatin1(); 217 216 lineWidth = otm->otmsUnderscoreSize; 218 217 fsType = otm->otmfsType; … … 488 487 w += glyphs.effectiveAdvance(i); 489 488 490 return glyph_metrics_t(0, -tm.tmAscent, w , tm.tmHeight, w, 0);489 return glyph_metrics_t(0, -tm.tmAscent, w - lastRightBearing(glyphs), tm.tmHeight, w, 0); 491 490 } 492 491 … … 1038 1037 p.emSquare = unitsPerEm; 1039 1038 p.italicAngle = otm->otmItalicAngle; 1040 p.postscriptName = QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpFamilyName)).toLatin1(); 1041 p.postscriptName += QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpStyleName)).toLatin1(); 1042 #ifndef QT_NO_PRINTER 1043 p.postscriptName = QPdf::stripSpecialCharacters(p.postscriptName); 1044 #endif 1039 p.postscriptName = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFamilyName)).toLatin1(); 1040 p.postscriptName += QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpStyleName)).toLatin1(); 1041 p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(p.postscriptName); 1045 1042 p.boundingBox = QRectF(otm->otmrcFontBox.left, -otm->otmrcFontBox.top, 1046 1043 otm->otmrcFontBox.right - otm->otmrcFontBox.left, … … 1213 1210 QImage indexed(mask->width(), mask->height(), QImage::Format_Indexed8); 1214 1211 1215 // ### This part is kinda pointless, but we'll crash later if we don t because some1212 // ### This part is kinda pointless, but we'll crash later if we don't because some 1216 1213 // code paths expects there to be colortables for index8-bit... 1217 1214 QVector<QRgb> colors(256); … … 1297 1294 first->ref.ref(); 1298 1295 fontDef = engines[0]->fontDef; 1296 cache_cost = first->cache_cost; 1299 1297 } 1300 1298 … … 1318 1316 engines[at]->ref.ref(); 1319 1317 engines[at]->fontDef = fontDef; 1318 1319 // TODO: increase cost in QFontCache for the font engine loaded here 1320 1320 } 1321 1321 -
trunk/src/gui/text/qfontengine_win_p.h
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qfontengine_x11.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 430 430 int i = glyphs->numGlyphs; 431 431 XCharStruct *xcs; 432 // inlined for better perfo mance432 // inlined for better performance 433 433 if (!_fs->per_char) { 434 434 xcs = &_fs->min_bounds; -
trunk/src/gui/text/qfontengine_x11_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qfontengineglyphcache_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qfontinfo.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qfontmetrics.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 329 329 QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); 330 330 Q_ASSERT(engine != 0); 331 return qRound(engine->ascent() +engine->descent()) + 1;331 return qRound(engine->ascent()) + qRound(engine->descent()) + 1; 332 332 } 333 333 … … 357 357 QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); 358 358 Q_ASSERT(engine != 0); 359 return qRound(engine->leading() + engine->ascent() +engine->descent()) + 1;359 return qRound(engine->leading()) + qRound(engine->ascent()) + qRound(engine->descent()) + 1; 360 360 } 361 361 … … 526 526 */ 527 527 int QFontMetrics::width(const QString &text, int len) const 528 { 529 return width(text, len, 0); 530 } 531 532 /*! 533 \internal 534 */ 535 int QFontMetrics::width(const QString &text, int len, int flags) const 528 536 { 529 537 int pos = text.indexOf(QLatin1Char('\x9c')); … … 536 544 return 0; 537 545 538 QTextEngine layout(text, d.data()); 546 if (flags & Qt::TextBypassShaping) { 547 // Skip harfbuzz complex shaping, only use advances 548 int numGlyphs = len; 549 QVarLengthGlyphLayoutArray glyphs(numGlyphs); 550 QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); 551 if (!engine->stringToCMap(text.data(), len, &glyphs, &numGlyphs, 0)) { 552 glyphs.resize(numGlyphs); 553 if (!engine->stringToCMap(text.data(), len, &glyphs, &numGlyphs, 0)) 554 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice"); 555 } 556 557 QFixed width; 558 for (int i = 0; i < numGlyphs; ++i) 559 width += glyphs.advances_x[i]; 560 return qRound(width); 561 } 562 563 QStackTextEngine layout(text, d.data()); 539 564 layout.ignoreBidi = true; 540 565 return qRound(layout.width(0, len)); … … 612 637 int to = qMin(text.length(), pos + 8); 613 638 QString cstr = QString::fromRawData(text.unicode() + from, to - from); 614 Q TextEngine layout(cstr, d.data());639 QStackTextEngine layout(cstr, d.data()); 615 640 layout.ignoreBidi = true; 616 641 layout.itemize(); … … 661 686 return QRect(); 662 687 663 Q TextEngine layout(text, d.data());688 QStackTextEngine layout(text, d.data()); 664 689 layout.ignoreBidi = true; 665 690 layout.itemize(); … … 831 856 return QRect(); 832 857 833 Q TextEngine layout(text, d.data());858 QStackTextEngine layout(text, d.data()); 834 859 layout.ignoreBidi = true; 835 860 layout.itemize(); … … 1376 1401 int len = (pos != -1) ? pos : text.length(); 1377 1402 1378 Q TextEngine layout(text, d.data());1403 QStackTextEngine layout(text, d.data()); 1379 1404 layout.ignoreBidi = true; 1380 1405 layout.itemize(); … … 1453 1478 return QRectF(); 1454 1479 1455 Q TextEngine layout(text, d.data());1480 QStackTextEngine layout(text, d.data()); 1456 1481 layout.ignoreBidi = true; 1457 1482 layout.itemize(); … … 1626 1651 return QRect(); 1627 1652 1628 Q TextEngine layout(text, d.data());1653 QStackTextEngine layout(text, d.data()); 1629 1654 layout.ignoreBidi = true; 1630 1655 layout.itemize(); -
trunk/src/gui/text/qfontmetrics.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 90 90 int rightBearing(QChar) const; 91 91 int width(const QString &, int len = -1) const; 92 int width(const QString &, int len, int flags) const; 92 93 93 94 int width(QChar) const; -
trunk/src/gui/text/qfontsubset.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 698 698 // Bit 11: Font data is 'lossless,' as a result of having been compressed and decompressed with the Agfa MicroType Express engine. 699 699 // Bit 12: Font converted (produce compatible metrics) 700 // Bit 13: Font optimi sed for ClearType700 // Bit 13: Font optimized for ClearType 701 701 // Bit 14: Reserved, set to 0 702 702 // Bit 15: Reserved, set to 0 … … 1009 1009 np.y = (i1_y + i2_y) >> 1; 1010 1010 if (try_reduce) { 1011 // see if we can optimi se out the last onCurve point1011 // see if we can optimize out the last onCurve point 1012 1012 int mx = (points->at(points->size() - 2).x + base[2].x) >> 1; 1013 1013 int my = (points->at(points->size() - 2).y + base[2].y) >> 1; -
trunk/src/gui/text/qfontsubset_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qfragmentmap.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qfragmentmap_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qpfutil.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qsyntaxhighlighter.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 60 60 Q_DECLARE_PUBLIC(QSyntaxHighlighter) 61 61 public: 62 inline QSyntaxHighlighterPrivate() : rehighlightPending(false) {} 62 inline QSyntaxHighlighterPrivate() 63 : rehighlightPending(false), inReformatBlocks(false) 64 {} 63 65 64 66 QPointer<QTextDocument> doc; 65 67 66 68 void _q_reformatBlocks(int from, int charsRemoved, int charsAdded); 67 void reformatBlock(QTextBlock block); 68 69 void reformatBlocks(int from, int charsRemoved, int charsAdded); 70 void reformatBlock(const QTextBlock &block); 71 69 72 inline void rehighlight(QTextCursor &cursor, QTextCursor::MoveOperation operation) { 70 QObject::disconnect(doc, SIGNAL(contentsChange(int,int,int)), 71 q_func(), SLOT(_q_reformatBlocks(int,int,int))); 73 inReformatBlocks = true; 72 74 cursor.beginEditBlock(); 73 75 int from = cursor.position(); 74 76 cursor.movePosition(operation); 75 _q_reformatBlocks(from, 0, cursor.position() - from);77 reformatBlocks(from, 0, cursor.position() - from); 76 78 cursor.endEditBlock(); 77 QObject::connect(doc, SIGNAL(contentsChange(int,int,int)), 78 q_func(), SLOT(_q_reformatBlocks(int,int,int))); 79 inReformatBlocks = false; 79 80 } 80 81 … … 84 85 rehighlightPending = false; 85 86 q_func()->rehighlight(); 86 return;87 87 } 88 88 … … 91 91 QTextBlock currentBlock; 92 92 bool rehighlightPending; 93 bool inReformatBlocks; 93 94 }; 94 95 95 96 void QSyntaxHighlighterPrivate::applyFormatChanges() 96 97 { 98 bool formatsChanged = false; 99 97 100 QTextLayout *layout = currentBlock.layout(); 98 101 … … 102 105 const int preeditAreaLength = layout->preeditAreaText().length(); 103 106 104 QList<QTextLayout::FormatRange>::Iterator it = ranges.begin(); 105 while (it != ranges.end()) { 106 if (it->start >= preeditAreaStart 107 && it->start + it->length <= preeditAreaStart + preeditAreaLength) 108 ++it; 109 else 110 it = ranges.erase(it); 107 if (preeditAreaLength != 0) { 108 QList<QTextLayout::FormatRange>::Iterator it = ranges.begin(); 109 while (it != ranges.end()) { 110 if (it->start >= preeditAreaStart 111 && it->start + it->length <= preeditAreaStart + preeditAreaLength) { 112 ++it; 113 } else { 114 it = ranges.erase(it); 115 formatsChanged = true; 116 } 117 } 118 } else if (!ranges.isEmpty()) { 119 ranges.clear(); 120 formatsChanged = true; 111 121 } 112 122 … … 114 124 115 125 QTextLayout::FormatRange r; 116 r.start = r.length =-1;126 r.start = -1; 117 127 118 128 int i = 0; … … 136 146 r.length = i - r.start; 137 147 138 if (r.start >= preeditAreaStart) { 139 r.start += preeditAreaLength; 140 } else if (r.start + r.length >= preeditAreaStart) { 141 r.length += preeditAreaLength; 148 if (preeditAreaLength != 0) { 149 if (r.start >= preeditAreaStart) 150 r.start += preeditAreaLength; 151 else if (r.start + r.length >= preeditAreaStart) 152 r.length += preeditAreaLength; 142 153 } 143 154 144 155 ranges << r; 145 r.start = r.length = -1; 156 formatsChanged = true; 157 r.start = -1; 146 158 } 147 159 … … 149 161 r.length = formatChanges.count() - r.start; 150 162 151 if (r.start >= preeditAreaStart) { 152 r.start += preeditAreaLength; 153 } else if (r.start + r.length >= preeditAreaStart) { 154 r.length += preeditAreaLength; 163 if (preeditAreaLength != 0) { 164 if (r.start >= preeditAreaStart) 165 r.start += preeditAreaLength; 166 else if (r.start + r.length >= preeditAreaStart) 167 r.length += preeditAreaLength; 155 168 } 156 169 157 170 ranges << r; 158 } 159 160 layout->setAdditionalFormats(ranges); 171 formatsChanged = true; 172 } 173 174 if (formatsChanged) { 175 layout->setAdditionalFormats(ranges); 176 doc->markContentsDirty(currentBlock.position(), currentBlock.length()); 177 } 161 178 } 162 179 163 180 void QSyntaxHighlighterPrivate::_q_reformatBlocks(int from, int charsRemoved, int charsAdded) 164 181 { 165 Q_UNUSED(charsRemoved); 182 if (!inReformatBlocks) 183 reformatBlocks(from, charsRemoved, charsAdded); 184 } 185 186 void QSyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded) 187 { 166 188 rehighlightPending = false; 167 189 … … 192 214 } 193 215 194 void QSyntaxHighlighterPrivate::reformatBlock( QTextBlockblock)216 void QSyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block) 195 217 { 196 218 Q_Q(QSyntaxHighlighter); … … 199 221 200 222 currentBlock = block; 201 QTextBlock previous = block.previous();202 223 203 224 formatChanges.fill(QTextCharFormat(), block.length() - 1); 204 225 q->highlightBlock(block.text()); 205 226 applyFormatChanges(); 206 207 doc->markContentsDirty(block.position(), block.length());208 227 209 228 currentBlock = QTextBlock(); … … 350 369 connect(d->doc, SIGNAL(contentsChange(int,int,int)), 351 370 this, SLOT(_q_reformatBlocks(int,int,int))); 371 d->rehighlightPending = true; 352 372 QTimer::singleShot(0, this, SLOT(_q_delayedRehighlight())); 353 d->rehighlightPending = true;354 373 } 355 374 } … … 392 411 { 393 412 Q_D(QSyntaxHighlighter); 394 if (!d->doc )413 if (!d->doc || !block.isValid() || block.document() != d->doc) 395 414 return; 415 416 const bool rehighlightPending = d->rehighlightPending; 396 417 397 418 QTextCursor cursor(block); 398 419 d->rehighlight(cursor, QTextCursor::EndOfBlock); 420 421 if (rehighlightPending) 422 d->rehighlightPending = rehighlightPending; 399 423 } 400 424 … … 461 485 { 462 486 Q_D(QSyntaxHighlighter); 463 464 487 if (start < 0 || start >= d->formatChanges.count()) 465 488 return; … … 629 652 630 653 Returns the current text block. 631 654 */ 632 655 QTextBlock QSyntaxHighlighter::currentBlock() const 633 656 { -
trunk/src/gui/text/qsyntaxhighlighter.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextcontrol.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 92 92 93 93 #ifndef QT_NO_CONTEXTMENU 94 #if defined(Q_WS_WIN) 94 #if defined(Q_WS_WIN) || defined(Q_WS_X11) 95 95 extern bool qt_use_rtl_extensions; 96 96 #endif … … 405 405 setContent(format, text, document); 406 406 407 QWidget *parentWidget = qobject_cast<QWidget*>(parent);408 if (parentWidget) {409 QTextOption opt = doc->defaultTextOption();410 opt.setTextDirection(parentWidget->layoutDirection());411 doc->setDefaultTextOption(opt);412 }413 407 doc->setUndoRedoEnabled(interactionFlags & Qt::TextEditable); 414 408 q->setCursorWidth(-1); … … 442 436 443 437 // convenience signal forwards 444 QObject::connect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged()));445 438 QObject::connect(doc, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool))); 446 439 QObject::connect(doc, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool))); … … 453 446 doc->setUndoRedoEnabled(false); 454 447 448 //Saving the index save some time. 449 static int contentsChangedIndex = QTextDocument::staticMetaObject.indexOfSignal("contentsChanged()"); 450 static int textChangedIndex = QTextControl::staticMetaObject.indexOfSignal("textChanged()"); 455 451 // avoid multiple textChanged() signals being emitted 456 Q Object::disconnect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged()));452 QMetaObject::disconnect(doc, contentsChangedIndex, q, textChangedIndex); 457 453 458 454 if (!text.isEmpty()) { … … 489 485 cursor.setCharFormat(charFormatForInsertion); 490 486 491 Q Object::connect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged()));487 QMetaObject::connect(doc, contentsChangedIndex, q, textChangedIndex); 492 488 emit q->textChanged(); 493 489 if (!document) … … 746 742 Q_D(QTextControl); 747 743 d->repaintSelection(); 744 const int oldCursorPos = d->cursor.position(); 748 745 d->doc->undo(&d->cursor); 746 if (d->cursor.position() != oldCursorPos) 747 emit cursorPositionChanged(); 748 emit microFocusChanged(); 749 749 ensureCursorVisible(); 750 750 } … … 754 754 Q_D(QTextControl); 755 755 d->repaintSelection(); 756 const int oldCursorPos = d->cursor.position(); 756 757 d->doc->redo(&d->cursor); 758 if (d->cursor.position() != oldCursorPos) 759 emit cursorPositionChanged(); 760 emit microFocusChanged(); 757 761 ensureCursorVisible(); 758 762 } … … 847 851 } 848 852 849 void QTextControl::paste( )850 { 851 const QMimeData *md = QApplication::clipboard()->mimeData( );853 void QTextControl::paste(QClipboard::Mode mode) 854 { 855 const QMimeData *md = QApplication::clipboard()->mimeData(mode); 852 856 if (md) 853 857 insertFromMimeData(md); … … 884 888 { 885 889 Q_D(QTextControl); 886 if (d->interactionFlags & Qt::NoTextInteraction) 887 return; 890 if (d->interactionFlags == Qt::NoTextInteraction) { 891 e->ignore(); 892 return; 893 } 888 894 889 895 d->contextWidget = contextWidget; … … 1090 1096 } 1091 1097 break; 1092 case QEvent::LayoutDirectionChange: {1093 if (contextWidget) {1094 QTextOption opt = document()->defaultTextOption();1095 opt.setTextDirection(contextWidget->layoutDirection());1096 document()->setDefaultTextOption(opt);1097 }1098 }1099 // FALL THROUGH1100 1098 default: 1101 1099 break; … … 1230 1228 } 1231 1229 else if (e == QKeySequence::Paste) { 1232 q->paste(); 1230 QClipboard::Mode mode = QClipboard::Clipboard; 1231 #ifdef Q_WS_X11 1232 if (e->modifiers() == (Qt::CTRL | Qt::SHIFT) && e->key() == Qt::Key_Insert) 1233 mode = QClipboard::Selection; 1234 #endif 1235 q->paste(mode); 1233 1236 } 1234 1237 #endif … … 1765 1768 if (!menu) 1766 1769 return; 1767 menu-> exec(screenPos);1768 delete menu;1770 menu->setAttribute(Qt::WA_DeleteOnClose); 1771 menu->popup(screenPos); 1769 1772 #endif 1770 1773 } … … 2076 2079 #endif 2077 2080 2078 #if defined(Q_WS_WIN) 2081 #if defined(Q_WS_WIN) || defined(Q_WS_X11) 2079 2082 if ((d->interactionFlags & Qt::TextEditable) && qt_use_rtl_extensions) { 2080 2083 #else -
trunk/src/gui/text/qtextcontrol_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 63 63 #include <QtGui/qabstracttextdocumentlayout.h> 64 64 #include <QtGui/qtextdocumentfragment.h> 65 #include <QtGui/qclipboard.h> 65 66 66 67 #ifdef QT3_SUPPORT … … 192 193 void cut(); 193 194 void copy(); 194 void paste( );195 void paste(QClipboard::Mode mode = QClipboard::Clipboard); 195 196 #endif 196 197 -
trunk/src/gui/text/qtextcontrol_p_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextcursor.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 65 65 QTextCursorPrivate::QTextCursorPrivate(QTextDocumentPrivate *p) 66 66 : priv(p), x(0), position(0), anchor(0), adjusted_anchor(0), 67 currentCharFormat(-1), visualNavigation(false) 67 currentCharFormat(-1), visualNavigation(false), keepPositionOnInsert(false), 68 changed(false) 68 69 { 69 70 priv->addCursor(this); … … 80 81 currentCharFormat = rhs.currentCharFormat; 81 82 visualNavigation = rhs.visualNavigation; 83 keepPositionOnInsert = rhs.keepPositionOnInsert; 84 changed = rhs.changed; 82 85 priv->addCursor(this); 83 86 } … … 96 99 || (position == positionOfChange 97 100 && (op == QTextUndoCommand::KeepCursor 98 || anchor < position)101 || keepPositionOnInsert) 99 102 ) 100 103 ) { … … 361 364 QTextBlock blockIt = block(); 362 365 366 if (!blockIt.isValid()) 367 return false; 368 363 369 if (op >= QTextCursor::Left && op <= QTextCursor::WordRight 364 && blockIt. blockFormat().layoutDirection() == Qt::RightToLeft) {370 && blockIt.textDirection() == Qt::RightToLeft) { 365 371 if (op == QTextCursor::Left) 366 372 op = QTextCursor::NextCharacter; … … 1146 1152 The cursor is positioned between characters. 1147 1153 1148 \sa setPosition() movePosition() anchor() 1154 \sa setPosition() movePosition() anchor() positionInBlock() 1149 1155 */ 1150 1156 int QTextCursor::position() const … … 1153 1159 return -1; 1154 1160 return d->position; 1161 } 1162 1163 /*! 1164 \since 4.7 1165 Returns the relative position of the cursor within the block. 1166 The cursor is positioned between characters. 1167 1168 This is equivalent to \c{ position() - block().position()}. 1169 1170 \sa position() 1171 */ 1172 int QTextCursor::positionInBlock() const 1173 { 1174 if (!d || !d->priv) 1175 return 0; 1176 return d->position - d->block().position(); 1155 1177 } 1156 1178 … … 1261 1283 } 1262 1284 1285 1286 /*! 1287 \since 4.7 1288 1289 Sets the visual x position for vertical cursor movements to \a x. 1290 1291 The vertical movement x position is cleared automatically when the cursor moves horizontally, and kept 1292 unchanged when the cursor moves vertically. The mechanism allows the cursor to move up and down on a 1293 visually straight line with proportional fonts, and to gently "jump" over short lines. 1294 1295 A value of -1 indicates no predefined x position. It will then be set automatically the next time the 1296 cursor moves up or down. 1297 1298 \sa verticalMovementX() 1299 */ 1300 void QTextCursor::setVerticalMovementX(int x) 1301 { 1302 if (d) 1303 d->x = x; 1304 } 1305 1306 /*! \since 4.7 1307 1308 Returns the visual x position for vertical cursor movements. 1309 1310 A value of -1 indicates no predefined x position. It will then be set automatically the next time the 1311 cursor moves up or down. 1312 1313 \sa setVerticalMovementX() 1314 */ 1315 int QTextCursor::verticalMovementX() const 1316 { 1317 return d ? d->x : -1; 1318 } 1319 1320 /*! 1321 \since 4.7 1322 1323 Returns whether the cursor should keep its current position when text gets inserted at the position of the 1324 cursor. 1325 1326 The default is false; 1327 1328 \sa setKeepPositionOnInsert() 1329 */ 1330 bool QTextCursor::keepPositionOnInsert() const 1331 { 1332 return d ? d->keepPositionOnInsert : false; 1333 } 1334 1335 /*! 1336 \since 4.7 1337 1338 Defines whether the cursor should keep its current position when text gets inserted at the current position of the 1339 cursor. 1340 1341 If \a b is true, the cursor keeps its current position when text gets inserted at the positing of the cursor. 1342 If \a b is false, the cursor moves along with the inserted text. 1343 1344 The default is false. 1345 1346 Note that a cursor always moves when text is inserted before the current position of the cursor, and it 1347 always keeps its position when text is inserted after the current position of the cursor. 1348 1349 \sa keepPositionOnInsert() 1350 */ 1351 void QTextCursor::setKeepPositionOnInsert(bool b) 1352 { 1353 if (d) 1354 d->keepPositionOnInsert = b; 1355 } 1356 1357 1358 1263 1359 /*! 1264 1360 Inserts \a text at the current position, using the current … … 1393 1489 if (!d || !d->priv) 1394 1490 return; 1395 1491 1396 1492 if (d->position != d->anchor) { 1397 1493 removeSelectedText(); 1398 1494 return; 1399 1495 } 1400 1496 1401 1497 if (d->anchor < 1 || !d->canDelete(d->anchor-1)) 1402 1498 return; 1403 1499 d->anchor--; 1404 1500 1405 1501 QTextDocumentPrivate::FragmentIterator fragIt = d->priv->find(d->anchor); 1406 1502 const QTextFragmentData * const frag = fragIt.value(); … … 1414 1510 --d->anchor; 1415 1511 } 1416 1512 1417 1513 d->adjusted_anchor = d->anchor; 1418 1514 d->remove(); … … 2347 2443 return; 2348 2444 2445 if (d->priv->editBlock == 0) // we are the initial edit block, store current cursor position for undo 2446 d->priv->editBlockCursorPosition = d->position; 2447 2349 2448 d->priv->beginEditBlock(); 2350 2449 } … … 2415 2514 } 2416 2515 2516 2417 2517 /*! 2418 2518 \since 4.2 2419 2519 Returns the position of the cursor within its containing line. 2520 2521 Note that this is the column number relative to a wrapped line, 2522 not relative to the block (i.e. the paragraph). 2523 2524 You probably want to call positionInBlock() instead. 2525 2526 \sa positionInBlock() 2420 2527 */ 2421 2528 int QTextCursor::columnNumber() const -
trunk/src/gui/text/qtextcursor.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 90 90 void setPosition(int pos, MoveMode mode = MoveAnchor); 91 91 int position() const; 92 int positionInBlock() const; 92 93 93 94 int anchor() const; … … 132 133 void setVisualNavigation(bool b); 133 134 135 void setVerticalMovementX(int x); 136 int verticalMovementX() const; 137 138 void setKeepPositionOnInsert(bool b); 139 bool keepPositionOnInsert() const; 140 134 141 void deleteChar(); 135 142 void deletePreviousChar(); -
trunk/src/gui/text/qtextcursor_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 113 113 int adjusted_anchor; 114 114 int currentCharFormat; 115 bool visualNavigation; 115 uint visualNavigation : 1; 116 uint keepPositionOnInsert : 1; 117 uint changed : 1; 116 118 }; 117 119 -
trunk/src/gui/text/qtextdocument.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 62 62 #include "qtextcontrol_p.h" 63 63 #include "private/qtextedit_p.h" 64 #include "private/qdataurl_p.h" 64 65 65 66 #include "qtextdocument_p.h" … … 126 127 tag += text[i]; 127 128 else if (!tag.isEmpty() && text[i].isSpace()) 129 break; 130 else if (!tag.isEmpty() && text[i] == QLatin1Char('/') && i + 1 == close) 128 131 break; 129 132 else if (!text[i].isSpace() && (!tag.isEmpty() || text[i] != QLatin1Char('!'))) … … 289 292 provides contentsChanged(), undoAvailable(), and redoAvailable() signals 290 293 that inform connected editor widgets about the state of the undo/redo 291 system. 294 system. The following are the undo/redo operations of a QTextDocument: 295 296 \list 297 \o Insertion or removal of characters. A sequence of insertions or removals 298 within the same text block are regarded as a single undo/redo operation. 299 \o Insertion or removal of text blocks. Sequences of insertion or removals 300 in a single operation (e.g., by selecting and then deleting text) are 301 regarded as a single undo/redo operation. 302 \o Text character format changes. 303 \o Text block format changes. 304 \o Text block group format changes. 305 \endlist 292 306 293 307 \sa QTextCursor, QTextEdit, \link richtext.html Rich Text Processing\endlink , {Text Object Example} … … 435 449 } 436 450 451 /*! \enum QTextDocument::Stacks 452 453 \value UndoStack The undo stack. 454 \value RedoStack The redo stack. 455 \value UndoAndRedoStacks Both the undo and redo stacks. 456 */ 457 458 /*! 459 \since 4.7 460 Clears the stacks specified by \a stacksToClear. 461 462 This method clears any commands on the undo stack, the redo stack, 463 or both (the default). If commands are cleared, the appropriate 464 signals are emitted, QTextDocument::undoAvailable() or 465 QTextDocument::redoAvailable(). 466 467 \sa QTextDocument::undoAvailable() QTextDocument::redoAvailable() 468 */ 469 void QTextDocument::clearUndoRedoStacks(Stacks stacksToClear) 470 { 471 Q_D(QTextDocument); 472 d->clearUndoRedoStacks(stacksToClear, true); 473 } 474 437 475 /*! 438 476 \overload … … 557 595 { 558 596 Q_D(QTextDocument); 559 if (!d->inContentsChange)560 d->beginEditBlock();561 597 d->documentChange(from, length); 562 if (!d->inContentsChange) 563 d->endEditBlock(); 598 if (!d->inContentsChange) { 599 if (d->lout) { 600 d->lout->documentChanged(d->docChangeFrom, d->docChangeOldLength, d->docChangeLength); 601 d->docChangeFrom = -1; 602 } 603 } 564 604 } 565 605 … … 1750 1790 if (printer->collateCopies() == true){ 1751 1791 docCopies = 1; 1752 pageCopies = printer-> numCopies();1792 pageCopies = printer->supportsMultipleCopies() ? 1 : printer->copyCount(); 1753 1793 } else { 1754 docCopies = printer-> numCopies();1794 docCopies = printer->supportsMultipleCopies() ? 1 : printer->copyCount(); 1755 1795 pageCopies = 1; 1756 1796 } … … 1921 1961 } 1922 1962 #endif 1963 1964 // handle data: URLs 1965 if (r.isNull() && name.scheme().compare(QLatin1String("data"), Qt::CaseInsensitive) == 0) 1966 r = qDecodeDataUrl(name).second; 1923 1967 1924 1968 // if resource was not loaded try to load it here … … 2468 2512 emitAlignment(format.alignment()); 2469 2513 2470 Qt::LayoutDirection dir = format.layoutDirection(); 2471 if (dir == Qt::LeftToRight) { 2472 // assume default to not bloat the html too much 2473 // html += QLatin1String(" dir='ltr'"); 2474 } else { 2514 // assume default to not bloat the html too much 2515 // html += QLatin1String(" dir='ltr'"); 2516 if (block.textDirection() == Qt::RightToLeft) 2475 2517 html += QLatin1String(" dir='rtl'"); 2476 }2477 2518 2478 2519 QLatin1String style(" style=\""); -
trunk/src/gui/text/qtextdocument.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 257 257 void redo(QTextCursor *cursor); 258 258 259 enum Stacks { 260 UndoStack = 0x01, 261 RedoStack = 0x02, 262 UndoAndRedoStacks = UndoStack | RedoStack 263 }; 264 void clearUndoRedoStacks(Stacks historyToClear = UndoAndRedoStacks); 265 259 266 int maximumBlockCount() const; 260 267 void setMaximumBlockCount(int maximum); -
trunk/src/gui/text/qtextdocument_p.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 64 64 #if !defined(Q_CC_DIAB) 65 65 # define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \ 66 QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6, { a7 }, a8 }66 QTextUndoCommand c = { a1, a2, 0, 0, quint8(a3), a4, a5, a6, { a7 }, a8 } 67 67 #else 68 68 # define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \ … … 92 92 93 93 Lists are not in here, as they are treated specially. A list is just 94 a collection of (not nec cessarily connected) blocks, that share the94 a collection of (not necessarily connected) blocks, that share the 95 95 same objectIndex() in the format that refers to the list format and 96 96 object. … … 193 193 { 194 194 editBlock = 0; 195 editBlockCursorPosition = -1; 195 196 docChangeFrom = -1; 196 197 … … 205 206 undoEnabled = true; 206 207 inContentsChange = false; 208 blockCursorAdjustment = false; 207 209 208 210 defaultTextOption.setTabStop(80); // same as in qtextengine.cpp … … 234 236 { 235 237 Q_Q(QTextDocument); 236 for (int i = 0; i < cursors.count(); ++i) { 237 cursors.at(i)->setPosition(0); 238 cursors.at(i)->currentCharFormat = -1; 239 cursors.at(i)->anchor = 0; 240 cursors.at(i)->adjusted_anchor = 0; 238 239 foreach (QTextCursorPrivate *curs, cursors) { 240 curs->setPosition(0); 241 curs->currentCharFormat = -1; 242 curs->anchor = 0; 243 curs->adjusted_anchor = 0; 241 244 } 242 245 … … 244 247 QT_TRY{ 245 248 cursors.clear(); 246 changedCursors.clear();247 249 248 250 QMap<int, QTextObject *>::Iterator objectIt = objects.begin(); … … 260 262 261 263 title.clear(); 262 undoState = 0; 263 truncateUndoStack(); 264 clearUndoRedoStacks(QTextDocument::UndoAndRedoStacks); 264 265 text = QString(); 265 266 unreachableCharacterCount = 0; … … 288 289 QTextDocumentPrivate::~QTextDocumentPrivate() 289 290 { 290 for (int i = 0; i < cursors.count(); ++i)291 curs ors.at(i)->priv = 0;291 foreach (QTextCursorPrivate *curs, cursors) 292 curs->priv = 0; 292 293 cursors.clear(); 293 294 undoState = 0; 294 295 undoEnabled = true; 295 truncateUndoStack();296 clearUndoRedoStacks(QTextDocument::RedoStack); 296 297 } 297 298 … … 320 321 void QTextDocumentPrivate::insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op) 321 322 { 322 // ##### optimi se when only appending to the fragment!323 // ##### optimize when only appending to the fragment! 323 324 Q_ASSERT(noBlockInString(text.mid(strPos, length))); 324 325 … … 663 664 Q_ASSERT(blocks.length() == fragments.length()); 664 665 665 finishEdit(); 666 if (!blockCursorAdjustment) 667 finishEdit(); 666 668 } 667 669 … … 670 672 if (length == 0) 671 673 return; 674 blockCursorAdjustment = true; 672 675 move(pos, -1, length, op); 676 blockCursorAdjustment = false; 677 foreach (QTextCursorPrivate *curs, cursors) { 678 if (curs->adjustPosition(pos, -length, op) == QTextCursorPrivate::CursorMoved) { 679 curs->changed = true; 680 } 681 } 682 finishEdit(); 673 683 } 674 684 … … 872 882 beginEditBlock(); 873 883 int editPos = -1; 884 int editLength = -1; 874 885 while (1) { 875 886 if (undo) … … 884 895 c.command = QTextUndoCommand::Removed; 885 896 editPos = c.pos; 897 editLength = 0; 886 898 break; 887 899 case QTextUndoCommand::Removed: … … 889 901 insert_string(c.pos, c.strPos, c.length, c.format, (QTextUndoCommand::Operation)c.operation); 890 902 c.command = QTextUndoCommand::Inserted; 891 editPos = c.pos + c.length; 903 if (editPos != (int)c.pos) 904 editLength = 0; 905 editPos = c.pos; 906 editLength += c.length; 892 907 break; 893 908 case QTextUndoCommand::BlockInserted: … … 900 915 c.command = QTextUndoCommand::BlockDeleted; 901 916 editPos = c.pos; 917 editLength = 0; 902 918 break; 903 919 case QTextUndoCommand::BlockRemoved: … … 910 926 else 911 927 c.command = QTextUndoCommand::BlockAdded; 912 editPos = c.pos + 1; 928 if (editPos != (int)c.pos) 929 editLength = 0; 930 editPos = c.pos; 931 editLength += 1; 913 932 break; 914 933 case QTextUndoCommand::CharFormatChanged: { … … 921 940 setCharFormat(c.pos, c.length, formats.charFormat(c.format)); 922 941 c.format = oldFormat; 923 editPos = c.pos + c.length; 942 if (editPos != (int)c.pos) 943 editLength = 0; 944 editPos = c.pos; 945 editLength += c.length; 924 946 break; 925 947 } … … 957 979 break; 958 980 } 981 case QTextUndoCommand::CursorMoved: 982 editPos = c.pos; 983 editLength = 0; 984 break; 959 985 case QTextUndoCommand::Custom: 960 986 resetBlockRevision = -1; // ## TODO … … 989 1015 } 990 1016 undoEnabled = true; 991 if (editPos < 0 && docChangeFrom >= 0) { 992 editPos = qMin(docChangeFrom + docChangeLength, length() - 1); 993 } 1017 1018 int newCursorPos = -1; 1019 1020 if (editPos >=0) 1021 newCursorPos = editPos + editLength; 1022 else if (docChangeFrom >= 0) 1023 newCursorPos= qMin(docChangeFrom + docChangeLength, length() - 1); 1024 994 1025 endEditBlock(); 995 1026 emitUndoAvailable(isUndoAvailable()); 996 1027 emitRedoAvailable(isRedoAvailable()); 997 return editPos; 1028 1029 return newCursorPos; 998 1030 } 999 1031 … … 1028 1060 return; 1029 1061 if (undoState < undoStack.size()) 1030 truncateUndoStack(); 1062 clearUndoRedoStacks(QTextDocument::RedoStack); 1063 1064 if (editBlock != 0 && editBlockCursorPosition >= 0) { // we had a beginEditBlock() with a cursor position 1065 if (c.pos != (quint32) editBlockCursorPosition) { // and that cursor position is different from the command 1066 // generate a CursorMoved undo item 1067 QT_INIT_TEXTUNDOCOMMAND(cc, QTextUndoCommand::CursorMoved, true, QTextUndoCommand::MoveCursor, 1068 0, 0, editBlockCursorPosition, 0, 0); 1069 undoStack.append(cc); 1070 undoState++; 1071 editBlockCursorPosition = -1; 1072 } 1073 } 1074 1031 1075 1032 1076 if (!undoStack.isEmpty() && modified) { … … 1051 1095 } 1052 1096 1053 void QTextDocumentPrivate::truncateUndoStack() 1054 { 1055 if (undoState == undoStack.size()) 1056 return; 1057 1058 for (int i = undoState; i < undoStack.size(); ++i) { 1059 QTextUndoCommand c = undoStack[i]; 1060 if (c.command & QTextUndoCommand::Removed) { 1061 // ######## 1062 // QTextFragment *f = c.fragment_list; 1063 // while (f) { 1064 // QTextFragment *n = f->right; 1065 // delete f; 1066 // f = n; 1067 // } 1068 } else if (c.command & QTextUndoCommand::Custom) { 1069 delete c.custom; 1070 } 1071 } 1072 undoStack.resize(undoState); 1097 void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToClear, 1098 bool emitSignals) 1099 { 1100 bool undoCommandsAvailable = undoState != 0; 1101 bool redoCommandsAvailable = undoState != undoStack.size(); 1102 if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) { 1103 for (int i = 0; i < undoState; ++i) { 1104 QTextUndoCommand c = undoStack[undoState]; 1105 if (c.command & QTextUndoCommand::Custom) 1106 delete c.custom; 1107 } 1108 undoStack.remove(0, undoState); 1109 undoStack.resize(undoStack.size() - undoState); 1110 undoState = 0; 1111 if (emitSignals) 1112 emitUndoAvailable(false); 1113 } else if (stacksToClear == QTextDocument::RedoStack 1114 && redoCommandsAvailable) { 1115 for (int i = undoState; i < undoStack.size(); ++i) { 1116 QTextUndoCommand c = undoStack[i]; 1117 if (c.command & QTextUndoCommand::Custom) 1118 delete c.custom; 1119 } 1120 undoStack.resize(undoState); 1121 if (emitSignals) 1122 emitRedoAvailable(false); 1123 } else if (stacksToClear == QTextDocument::UndoAndRedoStacks 1124 && !undoStack.isEmpty()) { 1125 for (int i = 0; i < undoStack.size(); ++i) { 1126 QTextUndoCommand c = undoStack[i]; 1127 if (c.command & QTextUndoCommand::Custom) 1128 delete c.custom; 1129 } 1130 undoState = 0; 1131 undoStack.resize(0); 1132 if (emitSignals && undoCommandsAvailable) 1133 emitUndoAvailable(false); 1134 if (emitSignals && redoCommandsAvailable) 1135 emitRedoAvailable(false); 1136 } 1073 1137 } 1074 1138 … … 1098 1162 if (!enable) { 1099 1163 undoState = 0; 1100 truncateUndoStack();1164 clearUndoRedoStacks(QTextDocument::RedoStack); 1101 1165 emitUndoAvailable(false); 1102 1166 emitRedoAvailable(false); … … 1130 1194 } 1131 1195 } 1196 1197 editBlockCursorPosition = -1; 1132 1198 1133 1199 finishEdit(); … … 1166 1232 } 1167 1233 1168 while (!changedCursors.isEmpty()) { 1169 QTextCursorPrivate *curs = changedCursors.takeFirst(); 1170 emit q->cursorPositionChanged(QTextCursor(curs)); 1171 } 1234 QList<QTextCursor> changedCursors; 1235 foreach (QTextCursorPrivate *curs, cursors) { 1236 if (curs->changed) { 1237 curs->changed = false; 1238 changedCursors.append(QTextCursor(curs)); 1239 } 1240 } 1241 foreach (const QTextCursor &cursor, changedCursors) 1242 emit q->cursorPositionChanged(cursor); 1172 1243 1173 1244 contentsChanged(); … … 1211 1282 ++revision; 1212 1283 1213 for (int i = 0; i < cursors.size(); ++i) { 1214 QTextCursorPrivate *curs = cursors.at(i); 1215 if (curs->adjustPosition(from, addedOrRemoved, op) == QTextCursorPrivate::CursorMoved) { 1216 if (!changedCursors.contains(curs)) 1217 changedCursors.append(curs); 1284 if (blockCursorAdjustment) { 1285 ; // postpone, will be called again from QTextDocumentPrivate::remove() 1286 } else { 1287 foreach (QTextCursorPrivate *curs, cursors) { 1288 if (curs->adjustPosition(from, addedOrRemoved, op) == QTextCursorPrivate::CursorMoved) { 1289 curs->changed = true; 1290 } 1218 1291 } 1219 1292 } … … 1376 1449 void QTextDocumentPrivate::scan_frames(int pos, int charsRemoved, int charsAdded) 1377 1450 { 1378 // ###### optimi se1451 // ###### optimize 1379 1452 Q_UNUSED(pos); 1380 1453 Q_UNUSED(charsRemoved); … … 1579 1652 1580 1653 for (FragmentMap::Iterator it = fragments.begin(); !it.atEnd(); ++it) { 1581 qMemCopy(newTextPtr, text.constData() + it->stringPosition, it->size_array[0] * sizeof(QChar));1654 memcpy(newTextPtr, text.constData() + it->stringPosition, it->size_array[0] * sizeof(QChar)); 1582 1655 it->stringPosition = newLen; 1583 1656 newTextPtr += it->size_array[0]; … … 1638 1711 { 1639 1712 Q_ASSERT(from <= to); 1640 for (int i = 0; i < cursors.size(); ++i)1641 curs ors.at(i)->aboutToRemoveCell(from, to);1713 foreach (QTextCursorPrivate *curs, cursors) 1714 curs->aboutToRemoveCell(from, to); 1642 1715 } 1643 1716 -
trunk/src/gui/text/qtextdocument_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 133 133 BlockDeleted = 7, 134 134 GroupFormatChange = 8, 135 CursorMoved = 9, 135 136 Custom = 256 136 137 }; … … 253 254 inline void setDefaultFont(const QFont &f) { formats.setDefaultFont(f); } 254 255 256 void clearUndoRedoStacks(QTextDocument::Stacks stacksToClear, bool emitSignals = false); 257 255 258 private: 256 259 bool split(int pos); 257 260 bool unite(uint f); 258 void truncateUndoStack();259 261 260 262 void insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op); … … 276 278 277 279 inline void addCursor(QTextCursorPrivate *c) { cursors.append(c); } 278 inline void removeCursor(QTextCursorPrivate *c) { cursors.removeAll(c); changedCursors.removeAll(c);}280 inline void removeCursor(QTextCursorPrivate *c) { cursors.removeAll(c); } 279 281 280 282 QTextFrame *frameAt(int pos) const; … … 315 317 316 318 int editBlock; 319 int editBlockCursorPosition; 317 320 int docChangeFrom; 318 321 int docChangeOldLength; … … 327 330 int initialBlockCharFormatIndex; 328 331 329 QList<QTextCursorPrivate*> cursors; 330 QList<QTextCursorPrivate*> changedCursors; 332 QList<QTextCursorPrivate *> cursors; 331 333 QMap<int, QTextObject *> objects; 332 334 QMap<QUrl, QVariant> resources; … … 344 346 uint needsEnsureMaximumBlockCount : 1; 345 347 uint inContentsChange : 1; 348 uint blockCursorAdjustment : 1; 346 349 QSizeF pageSize; 347 350 QString title; -
trunk/src/gui/text/qtextdocumentfragment.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 44 44 #include "qtextcursor_p.h" 45 45 #include "qtextlist.h" 46 #include "private/qunicodetables_p.h"47 46 48 47 #include <qdebug.h> -
trunk/src/gui/text/qtextdocumentfragment.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextdocumentfragment_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextdocumentlayout.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 80 80 // ################ should probably add frameFormatChange notification! 81 81 82 struct Q LayoutStruct;82 struct QTextLayoutStruct; 83 83 84 84 class QTextFrameData : public QTextFrameLayoutData … … 110 110 QFixed maximumWidth; 111 111 112 Q LayoutStruct *currentLayoutStruct;112 QTextLayoutStruct *currentLayoutStruct; 113 113 114 114 bool sizeDirty; … … 124 124 } 125 125 126 struct Q LayoutStruct {127 Q LayoutStruct() : maximumWidth(QFIXED_MAX), fullLayout(false)126 struct QTextLayoutStruct { 127 QTextLayoutStruct() : maximumWidth(QFIXED_MAX), fullLayout(false) 128 128 {} 129 129 QTextFrame *frame; … … 328 328 /* 329 329 330 Optimi sation strategies:330 Optimization strategies: 331 331 332 332 HTML layout: … … 478 478 HitPoint hitTest(QTextBlock bl, const QFixedPoint &point, int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const; 479 479 480 Q LayoutStruct layoutCell(QTextTable *t, const QTextTableCell &cell, QFixed width,481 int layoutFrom, int layoutTo, QTextTableData *tableData, QFixed absoluteTableY,482 bool withPageBreaks);480 QTextLayoutStruct layoutCell(QTextTable *t, const QTextTableCell &cell, QFixed width, 481 int layoutFrom, int layoutTo, QTextTableData *tableData, QFixed absoluteTableY, 482 bool withPageBreaks); 483 483 void setCellPosition(QTextTable *t, const QTextTableCell &cell, const QPointF &pos); 484 484 QRectF layoutTable(QTextTable *t, int layoutFrom, int layoutTo, QFixed parentY); … … 491 491 492 492 void layoutBlock(const QTextBlock &bl, int blockPosition, const QTextBlockFormat &blockFormat, 493 Q LayoutStruct *layoutStruct, int layoutFrom, int layoutTo, const QTextBlockFormat *previousBlockFormat);494 void layoutFlow(QTextFrame::Iterator it, Q LayoutStruct *layoutStruct, int layoutFrom, int layoutTo, QFixed width = 0);495 void pageBreakInsideTable(QTextTable *table, Q LayoutStruct *layoutStruct);496 497 498 void floatMargins(const QFixed &y, const Q LayoutStruct *layoutStruct, QFixed *left, QFixed *right) const;499 QFixed findY(QFixed yFrom, const Q LayoutStruct *layoutStruct, QFixed requiredWidth) const;493 QTextLayoutStruct *layoutStruct, int layoutFrom, int layoutTo, const QTextBlockFormat *previousBlockFormat); 494 void layoutFlow(QTextFrame::Iterator it, QTextLayoutStruct *layoutStruct, int layoutFrom, int layoutTo, QFixed width = 0); 495 void pageBreakInsideTable(QTextTable *table, QTextLayoutStruct *layoutStruct); 496 497 498 void floatMargins(const QFixed &y, const QTextLayoutStruct *layoutStruct, QFixed *left, QFixed *right) const; 499 QFixed findY(QFixed yFrom, const QTextLayoutStruct *layoutStruct, QFixed requiredWidth) const; 500 500 501 501 QVector<QCheckPoint> checkPoints; … … 1370 1370 Q_ASSERT(firstLine.isValid()); 1371 1371 QPointF pos = (offset + layout->position()).toPoint(); 1372 Qt::LayoutDirection dir = docPrivate->defaultTextOption.textDirection(); 1373 if (blockFormat.hasProperty(QTextFormat::LayoutDirection)) 1374 dir = blockFormat.layoutDirection(); 1372 Qt::LayoutDirection dir = bl.textDirection(); 1375 1373 { 1376 1374 QRectF textRect = firstLine.naturalTextRect(); … … 1488 1486 } 1489 1487 1490 Q LayoutStruct QTextDocumentLayoutPrivate::layoutCell(QTextTable *t, const QTextTableCell &cell, QFixed width,1491 int layoutFrom, int layoutTo, QTextTableData *td,1492 QFixed absoluteTableY, bool withPageBreaks)1488 QTextLayoutStruct QTextDocumentLayoutPrivate::layoutCell(QTextTable *t, const QTextTableCell &cell, QFixed width, 1489 int layoutFrom, int layoutTo, QTextTableData *td, 1490 QFixed absoluteTableY, bool withPageBreaks) 1493 1491 { 1494 1492 LDEBUG << "layoutCell"; 1495 Q LayoutStruct layoutStruct;1493 QTextLayoutStruct layoutStruct; 1496 1494 layoutStruct.frame = t; 1497 1495 layoutStruct.minimumWidth = 0; … … 1642 1640 // maximum width. otherwise the maxwidth calculation sometimes 1643 1641 // returns wrong values 1644 Q LayoutStruct layoutStruct = layoutCell(table, cell, QFIXED_MAX, layoutFrom,1645 layoutTo, td, absoluteTableY,1646 /*withPageBreaks =*/false);1642 QTextLayoutStruct layoutStruct = layoutCell(table, cell, QFIXED_MAX, layoutFrom, 1643 layoutTo, td, absoluteTableY, 1644 /*withPageBreaks =*/false); 1647 1645 1648 1646 // distribute the minimum width over all columns the cell spans … … 1869 1867 1870 1868 const QFixed width = td->cellWidth(c, cspan) - widthPadding; 1871 Q LayoutStruct layoutStruct = layoutCell(table, cell, width,1872 layoutFrom, layoutTo,1873 td, absoluteTableY,1874 /*withPageBreaks =*/true);1869 QTextLayoutStruct layoutStruct = layoutCell(table, cell, width, 1870 layoutFrom, layoutTo, 1871 td, absoluteTableY, 1872 /*withPageBreaks =*/true); 1875 1873 1876 1874 const QFixed height = layoutStruct.y + bottomPadding + topPadding; … … 1977 1975 Q_ASSERT(pd && pd->currentLayoutStruct); 1978 1976 1979 Q LayoutStruct *layoutStruct = pd->currentLayoutStruct;1977 QTextLayoutStruct *layoutStruct = pd->currentLayoutStruct; 1980 1978 1981 1979 if (!pd->floats.contains(frame)) … … 2117 2115 fd->contentsWidth = newContentsWidth; 2118 2116 2119 Q LayoutStruct layoutStruct;2117 QTextLayoutStruct layoutStruct; 2120 2118 layoutStruct.frame = f; 2121 2119 layoutStruct.x_left = fd->leftMargin + fd->border + fd->padding; … … 2180 2178 } 2181 2179 2182 void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, Q LayoutStruct *layoutStruct,2180 void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayoutStruct *layoutStruct, 2183 2181 int layoutFrom, int layoutTo, QFixed width) 2184 2182 { … … 2510 2508 2511 2509 void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosition, const QTextBlockFormat &blockFormat, 2512 Q LayoutStruct *layoutStruct, int layoutFrom, int layoutTo, const QTextBlockFormat *previousBlockFormat)2510 QTextLayoutStruct *layoutStruct, int layoutFrom, int layoutTo, const QTextBlockFormat *previousBlockFormat) 2513 2511 { 2514 2512 Q_Q(QTextDocumentLayout); … … 2531 2529 //QTextFrameData *fd = data(layoutStruct->frame); 2532 2530 2533 Qt::LayoutDirection dir = docPrivate->defaultTextOption.textDirection(); 2534 if (blockFormat.hasProperty(QTextFormat::LayoutDirection)) 2535 dir = blockFormat.layoutDirection(); 2531 Qt::LayoutDirection dir = bl.textDirection(); 2536 2532 2537 2533 QFixed extraMargin; … … 2719 2715 } 2720 2716 2721 void QTextDocumentLayoutPrivate::floatMargins(const QFixed &y, const Q LayoutStruct *layoutStruct,2717 void QTextDocumentLayoutPrivate::floatMargins(const QFixed &y, const QTextLayoutStruct *layoutStruct, 2722 2718 QFixed *left, QFixed *right) const 2723 2719 { … … 2741 2737 } 2742 2738 2743 QFixed QTextDocumentLayoutPrivate::findY(QFixed yFrom, const Q LayoutStruct *layoutStruct, QFixed requiredWidth) const2739 QFixed QTextDocumentLayoutPrivate::findY(QFixed yFrom, const QTextLayoutStruct *layoutStruct, QFixed requiredWidth) const 2744 2740 { 2745 2741 QFixed right, left; -
trunk/src/gui/text/qtextdocumentlayout_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextdocumentwriter.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextdocumentwriter.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextengine.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 886 886 QFixed wordSpacing = font.d->wordSpacing; 887 887 888 if (letterSpacingIsAbsolute )888 if (letterSpacingIsAbsolute && letterSpacing.value()) 889 889 letterSpacing *= font.d->dpi / qt_defaultDpiY(); 890 890 … … 895 895 glyphs.advances_x[i-1] += letterSpacing; 896 896 else { 897 const QFixedadvance = glyphs.advances_x[i-1];898 glyphs.advances_x[i-1]+= (letterSpacing - 100) * advance / 100;897 QFixed &advance = glyphs.advances_x[i-1]; 898 advance += (letterSpacing - 100) * advance / 100; 899 899 } 900 900 } … … 903 903 glyphs.advances_x[si.num_glyphs-1] += letterSpacing; 904 904 else { 905 const QFixedadvance = glyphs.advances_x[si.num_glyphs-1];906 glyphs.advances_x[si.num_glyphs-1]+= (letterSpacing - 100) * advance / 100;905 QFixed &advance = glyphs.advances_x[si.num_glyphs-1]; 906 advance += (letterSpacing - 100) * advance / 100; 907 907 } 908 908 } … … 922 922 for (int i = 0; i < si.num_glyphs; ++i) 923 923 si.width += glyphs.advances_x[i]; 924 } 925 926 static inline bool hasCaseChange(const QScriptItem &si) 927 { 928 return si.analysis.flags == QScriptAnalysis::SmallCaps || 929 si.analysis.flags == QScriptAnalysis::Uppercase || 930 si.analysis.flags == QScriptAnalysis::Lowercase; 924 931 } 925 932 … … 1051 1058 flags |= DesignMetrics; 1052 1059 1053 attributes(); // pre-initialize char attributes 1060 // pre-initialize char attributes 1061 if (! attributes()) 1062 return; 1054 1063 1055 1064 const int len = length(item); … … 1057 1066 const QChar *str = layoutData->string.unicode() + si.position; 1058 1067 ushort upperCased[256]; 1059 if (si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase 1060 || si.analysis.flags == QScriptAnalysis::Lowercase) { 1068 if (hasCaseChange(si)) { 1061 1069 ushort *uc = upperCased; 1062 1070 if (len > 256) … … 1072 1080 1073 1081 while (true) { 1074 ensureSpace(num_glyphs); 1082 if (! ensureSpace(num_glyphs)) { 1083 // If str is converted to uppercase/lowercase form with a new buffer, 1084 // we need to delete that buffer before return for error 1085 const ushort *uc = reinterpret_cast<const ushort *>(str); 1086 if (hasCaseChange(si) && uc != upperCased) 1087 delete [] uc; 1088 return; 1089 } 1075 1090 num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used; 1076 1091 … … 1093 1108 1094 1109 const ushort *uc = reinterpret_cast<const ushort *>(str); 1095 if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase 1096 || si.analysis.flags == QScriptAnalysis::Lowercase) 1097 && uc != upperCased) 1110 if (hasCaseChange(si) && uc != upperCased) 1098 1111 delete [] uc; 1099 1112 } … … 1125 1138 1126 1139 HB_ShaperItem entire_shaper_item; 1127 entire_shaper_item.kerning_applied = false;1140 qMemSet(&entire_shaper_item, 0, sizeof(entire_shaper_item)); 1128 1141 entire_shaper_item.string = reinterpret_cast<const HB_UChar16 *>(layoutData->string.constData()); 1129 1142 entire_shaper_item.stringLength = layoutData->string.length(); … … 1132 1145 entire_shaper_item.item.length = length(item); 1133 1146 entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel; 1134 entire_shaper_item.glyphIndicesPresent = false;1135 1147 1136 1148 HB_UChar16 upperCased[256]; // XXX what about making this 4096, so we don't have to extend it ever. 1137 if (si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase 1138 || si.analysis.flags == QScriptAnalysis::Lowercase) { 1149 if (hasCaseChange(si)) { 1139 1150 HB_UChar16 *uc = upperCased; 1140 1151 if (entire_shaper_item.item.length > 256) … … 1158 1169 1159 1170 entire_shaper_item.num_glyphs = qMax(layoutData->glyphLayout.numGlyphs - layoutData->used, int(entire_shaper_item.item.length)); 1160 ensureSpace(entire_shaper_item.num_glyphs); 1171 if (! ensureSpace(entire_shaper_item.num_glyphs)) { 1172 if (hasCaseChange(si)) 1173 delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string); 1174 return; 1175 } 1161 1176 QGlyphLayout initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs); 1162 1177 1163 1178 if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) { 1164 ensureSpace(entire_shaper_item.num_glyphs); 1179 if (! ensureSpace(entire_shaper_item.num_glyphs)) { 1180 if (hasCaseChange(si)) 1181 delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string); 1182 return; 1183 } 1165 1184 initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs); 1166 1185 1167 1186 if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) { 1168 1187 // ############ if this happens there's a bug in the fontengine 1169 if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase 1170 || si.analysis.flags == QScriptAnalysis::Lowercase) && entire_shaper_item.string != upperCased) 1188 if (hasCaseChange(si) && entire_shaper_item.string != upperCased) 1171 1189 delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string); 1172 1190 return; … … 1233 1251 1234 1252 do { 1235 ensureSpace(glyph_pos + shaper_item.num_glyphs + remaining_glyphs); 1253 if (! ensureSpace(glyph_pos + shaper_item.num_glyphs + remaining_glyphs)) { 1254 if (hasCaseChange(si)) 1255 delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string); 1256 return; 1257 } 1236 1258 1237 1259 const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos); … … 1273 1295 layoutData->used += si.num_glyphs; 1274 1296 1275 if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase) 1276 && entire_shaper_item.string != upperCased) 1297 if (hasCaseChange(si) && entire_shaper_item.string != upperCased) 1277 1298 delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string); 1278 1299 } … … 1300 1321 1301 1322 QTextEngine::QTextEngine(const QString &str, const QFont &f) 1302 : fnt(f) 1323 : text(str), 1324 fnt(f) 1303 1325 { 1304 1326 init(this); 1305 text = str;1306 1327 } 1307 1328 … … 1319 1340 1320 1341 itemize(); 1321 ensureSpace(layoutData->string.length()); 1342 if (! ensureSpace(layoutData->string.length())) 1343 return NULL; 1322 1344 1323 1345 QVarLengthArray<HB_ScriptItem> hbScriptItems(layoutData->items.size()); … … 1406 1428 bool ignore = ignoreBidi; 1407 1429 #endif 1408 if (!ignore && option.textDirection() == Qt::LeftToRight) { 1430 1431 bool rtl = isRightToLeft(); 1432 1433 if (!ignore && !rtl) { 1409 1434 ignore = true; 1410 1435 const QChar *start = layoutData->string.unicode(); … … 1422 1447 QScriptAnalysis *analysis = scriptAnalysis.data(); 1423 1448 1424 QBidiControl control( option.textDirection() == Qt::RightToLeft);1449 QBidiControl control(rtl); 1425 1450 1426 1451 if (ignore) { … … 1517 1542 } 1518 1543 1544 bool QTextEngine::isRightToLeft() const 1545 { 1546 switch (option.textDirection()) { 1547 case Qt::LeftToRight: 1548 return false; 1549 case Qt::RightToLeft: 1550 return true; 1551 default: 1552 break; 1553 } 1554 // this places the cursor in the right position depending on the keyboard layout 1555 if (layoutData->string.isEmpty()) 1556 return QApplication::keyboardInputDirection() == Qt::RightToLeft; 1557 return layoutData->string.isRightToLeft(); 1558 } 1559 1560 1519 1561 int QTextEngine::findItem(int strPos) const 1520 1562 { 1521 1563 itemize(); 1522 1523 // ##### use binary search 1524 int item; 1525 for (item = layoutData->items.size()-1; item > 0; --item) { 1526 if (layoutData->items[item].position <= strPos) 1527 break; 1528 } 1529 return item; 1564 int left = 0; 1565 int right = layoutData->items.size()-1; 1566 while(left <= right) { 1567 int middle = ((right-left)/2)+left; 1568 if (strPos > layoutData->items[middle].position) 1569 left = middle+1; 1570 else if(strPos < layoutData->items[middle].position) 1571 right = middle-1; 1572 else { 1573 return middle; 1574 } 1575 } 1576 return right; 1530 1577 } 1531 1578 … … 1600 1647 for (int i = 0; i < layoutData->items.size(); i++) { 1601 1648 const QScriptItem *si = layoutData->items.constData() + i; 1602 QFontEngine *fe = fontEngine(*si);1603 1649 1604 1650 int pos = si->position; … … 1630 1676 charFrom++; 1631 1677 if (charFrom < ilen) { 1678 QFontEngine *fe = fontEngine(*si); 1632 1679 glyphStart = logClusters[charFrom]; 1633 1680 int charEnd = from + len - 1 - pos; … … 1648 1695 } 1649 1696 } 1650 1651 glyph_t glyph = glyphs.glyphs[logClusters[ilen - 1]];1652 glyph_metrics_t gi = fe->boundingBox(glyph);1653 if (gi.isValid())1654 gm.width -= qRound(gi.xoff - gi.x - gi.width);1655 1697 } 1656 1698 } … … 1838 1880 return; // no justification at end of paragraph 1839 1881 if (end && layoutData->items[findItem(end-1)].analysis.flags == QScriptAnalysis::LineOrParagraphSeparator) 1840 return; // no justification at the end of an explicit ely separated line1882 return; // no justification at the end of an explicitly separated line 1841 1883 } 1842 1884 … … 1846 1888 // don't include trailing white spaces when doing justification 1847 1889 int line_length = line.length; 1848 const HB_CharAttributes *a = attributes()+line.from; 1890 const HB_CharAttributes *a = attributes(); 1891 if (! a) 1892 return; 1893 a += line.from; 1849 1894 while (line_length && a[line_length-1].whiteSpace) 1850 1895 --line_length; … … 1905 1950 // qDebug("kashida position at %d in word", kashida_pos); 1906 1951 set(&justificationPoints[nPoints], kashida_type, g.mid(kashida_pos), fontEngine(si)); 1907 minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth); 1908 maxJustify = qMax(maxJustify, justificationPoints[nPoints].type); 1909 ++nPoints; 1952 if (justificationPoints[nPoints].kashidaWidth > 0) { 1953 minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth); 1954 maxJustify = qMax(maxJustify, justificationPoints[nPoints].type); 1955 ++nPoints; 1956 } 1910 1957 } 1911 1958 kashida_pos = -1; … … 1931 1978 if (kashida_pos >= 0) { 1932 1979 set(&justificationPoints[nPoints], kashida_type, g.mid(kashida_pos), fontEngine(si)); 1933 minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth); 1934 maxJustify = qMax(maxJustify, justificationPoints[nPoints].type); 1935 ++nPoints; 1980 if (justificationPoints[nPoints].kashidaWidth > 0) { 1981 minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth); 1982 maxJustify = qMax(maxJustify, justificationPoints[nPoints].type); 1983 ++nPoints; 1984 } 1936 1985 } 1937 1986 } … … 2027 2076 used = 0; 2028 2077 hasBidi = false; 2029 inLayout = false;2078 layoutState = LayoutEmpty; 2030 2079 haveCharAttributes = false; 2031 2080 logClustersPtr = 0; … … 2061 2110 used = 0; 2062 2111 hasBidi = false; 2063 inLayout = false;2112 layoutState = LayoutEmpty; 2064 2113 haveCharAttributes = false; 2065 2114 } … … 2072 2121 } 2073 2122 2074 voidQTextEngine::LayoutData::reallocate(int totalGlyphs)2123 bool QTextEngine::LayoutData::reallocate(int totalGlyphs) 2075 2124 { 2076 2125 Q_ASSERT(totalGlyphs >= glyphLayout.numGlyphs); 2077 2126 if (memory_on_stack && available_glyphs >= totalGlyphs) { 2078 2127 glyphLayout.grow(glyphLayout.data(), totalGlyphs); 2079 return ;2128 return true; 2080 2129 } 2081 2130 … … 2085 2134 2086 2135 int newAllocated = space_charAttributes + space_glyphs + space_logClusters; 2087 Q_ASSERT(newAllocated >= allocated); 2136 // These values can be negative if the length of string/glyphs causes overflow, 2137 // we can't layout such a long string all at once, so return false here to 2138 // indicate there is a failure 2139 if (space_charAttributes < 0 || space_logClusters < 0 || space_glyphs < 0 || newAllocated < allocated) { 2140 layoutState = LayoutFailed; 2141 return false; 2142 } 2143 2088 2144 void **newMem = memory; 2089 2145 newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *)); 2090 Q_CHECK_PTR(newMem); 2091 if (memory_on_stack && newMem) 2146 if (!newMem) { 2147 layoutState = LayoutFailed; 2148 return false; 2149 } 2150 if (memory_on_stack) 2092 2151 memcpy(newMem, memory, allocated*sizeof(void *)); 2093 2152 memory = newMem; … … 2106 2165 2107 2166 allocated = newAllocated; 2167 return true; 2108 2168 } 2109 2169 … … 2137 2197 layoutData->used = 0; 2138 2198 layoutData->hasBidi = false; 2139 layoutData-> inLayout = false;2199 layoutData->layoutState = LayoutEmpty; 2140 2200 layoutData->haveCharAttributes = false; 2141 2201 } … … 2208 2268 case '?': 2209 2269 case '!': 2270 case '@': 2271 case '#': 2272 case '$': 2210 2273 case ':': 2211 2274 case ';': … … 2228 2291 case '\'': 2229 2292 case '"': 2293 case '`': 2230 2294 case '~': 2231 2295 case '|': … … 2296 2360 2297 2361 HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes()); 2362 if (!attributes) 2363 return QString(); 2364 2298 2365 unsigned short *logClusters = this->logClusters(&si); 2299 2366 QGlyphLayout glyphs = shapedGlyphs(&si); … … 2367 2434 2368 2435 const HB_CharAttributes *attributes = this->attributes(); 2436 if (!attributes) 2437 return QString(); 2369 2438 2370 2439 if (mode == Qt::ElideRight) { … … 2453 2522 2454 2523 int itemToSplit = 0; 2455 while (itemToSplit < layoutData->items.size() && layoutData->items [itemToSplit].position <= strPos)2524 while (itemToSplit < layoutData->items.size() && layoutData->items.at(itemToSplit).position <= strPos) 2456 2525 itemToSplit++; 2457 2526 itemToSplit--; 2458 if (layoutData->items [itemToSplit].position == strPos) {2527 if (layoutData->items.at(itemToSplit).position == strPos) { 2459 2528 // already a split at the requested position 2460 2529 return; 2461 2530 } 2462 splitItem(itemToSplit, strPos - layoutData->items [itemToSplit].position);2531 splitItem(itemToSplit, strPos - layoutData->items.at(itemToSplit).position); 2463 2532 } 2464 2533 … … 2468 2537 return; 2469 2538 2470 layoutData->items.insert(item + 1, QScriptItem(layoutData->items[item]));2539 layoutData->items.insert(item + 1, layoutData->items[item]); 2471 2540 QScriptItem &oldItem = layoutData->items[item]; 2472 2541 QScriptItem &newItem = layoutData->items[item+1]; … … 2513 2582 QList<QTextOption::Tab> tabArray = option.tabs(); 2514 2583 if (!tabArray.isEmpty()) { 2515 if ( option.textDirection() == Qt::RightToLeft) { // rebase the tabArray positions.2584 if (isRightToLeft()) { // rebase the tabArray positions. 2516 2585 QList<QTextOption::Tab> newTabs; 2517 2586 QList<QTextOption::Tab>::Iterator iter = tabArray.begin(); … … 2611 2680 2612 2681 QStackTextEngine::QStackTextEngine(const QString &string, const QFont &f) 2613 : _layoutData(string, _memory, MemSize) 2614 { 2615 fnt = f; 2616 text = string; 2682 : QTextEngine(string, f), 2683 _layoutData(string, _memory, MemSize) 2684 { 2617 2685 stackEngine = true; 2618 2686 layoutData = &_layoutData; … … 2651 2719 } 2652 2720 2721 QTextItemInt::QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars_, int numChars, QFontEngine *fe) 2722 : flags(0), justified(false), underlineStyle(QTextCharFormat::NoUnderline), 2723 num_chars(numChars), chars(chars_), logClusters(0), f(font), glyphs(g), fontEngine(fe) 2724 { 2725 } 2726 2653 2727 QTextItemInt QTextItemInt::midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const 2654 2728 { -
trunk/src/gui/text/qtextengine_mac.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextengine_p.h
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 312 312 {} 313 313 QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFormat &format = QTextCharFormat()); 314 QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars, int numChars, QFontEngine *fe); 314 315 315 316 /// copy the structure items, adjusting the glyphs arrays to the right subarrays. … … 390 391 uint hasTrailingSpaces : 1; 391 392 uint leadingIncluded : 1; 392 QFixed height() const { return ascent + descent+ 1393 QFixed height() const { return (ascent + descent).ceil() + 1 393 394 + (leadingIncluded? qMax(QFixed(),leading) : QFixed()); } 394 395 QFixed base() const { return ascent … … 416 417 class Q_GUI_EXPORT QTextEngine { 417 418 public: 419 enum LayoutState { 420 LayoutEmpty, 421 InLayout, 422 LayoutFailed, 423 }; 418 424 struct LayoutData { 419 425 LayoutData(const QString &str, void **stack_memory, int mem_size); … … 428 434 mutable int used; 429 435 uint hasBidi : 1; 430 uint inLayout : 1;436 uint layoutState : 2; 431 437 uint memory_on_stack : 1; 432 438 bool haveCharAttributes; 433 439 QString string; 434 voidreallocate(int totalGlyphs);440 bool reallocate(int totalGlyphs); 435 441 }; 436 442 … … 458 464 void itemize() const; 459 465 466 bool isRightToLeft() const; 460 467 static void bidiReorder(int numRuns, const quint8 *levels, int *visualOrder); 461 468 … … 519 526 } 520 527 521 inline voidensureSpace(int nGlyphs) const {528 inline bool ensureSpace(int nGlyphs) const { 522 529 if (layoutData->glyphLayout.numGlyphs - layoutData->used < nGlyphs) 523 layoutData->reallocate((((layoutData->used + nGlyphs)*3/2 + 15) >> 4) << 4); 530 return layoutData->reallocate((((layoutData->used + nGlyphs)*3/2 + 15) >> 4) << 4); 531 return true; 524 532 } 525 533 -
trunk/src/gui/text/qtextformat.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 266 266 }; 267 267 268 // this is only safe ifsizeof(int) == sizeof(float)268 // this is only safe because sizeof(int) == sizeof(float) 269 269 static inline uint hash(float d) 270 270 { 271 #ifdef Q_CC_GNU 272 // this is a GCC extension and isn't guaranteed to work in other compilers 273 // the reinterpret_cast below generates a strict-aliasing warning with GCC 274 union { float f; uint u; } cvt; 275 cvt.f = d; 276 return cvt.u; 277 #else 271 278 return reinterpret_cast<uint&>(d); 279 #endif 272 280 } 273 281 … … 901 909 int QTextFormat::intProperty(int propertyId) const 902 910 { 911 // required, since the default layout direction has to be LayoutDirectionAuto, which is not integer 0 912 int def = (propertyId == QTextFormat::LayoutDirection) ? int(Qt::LayoutDirectionAuto) : 0; 913 903 914 if (!d) 904 return 0;915 return def; 905 916 const QVariant prop = d->property(propertyId); 906 917 if (prop.userType() != QVariant::Int) 907 return 0;918 return def; 908 919 return prop.toInt(); 909 920 } -
trunk/src/gui/text/qtextformat.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextformat_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtexthtmlparser.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 54 54 #include "qtextcursor.h" 55 55 #include "qfont_p.h" 56 #include "private/qunicodetables_p.h"57 56 #include "private/qfunctions_p.h" 58 57 -
trunk/src/gui/text/qtexthtmlparser_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextimagehandler.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextimagehandler_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextlayout.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 70 70 || (eng->option.flags() & QTextOption::IncludeTrailingSpaces) 71 71 || !(eng->option.alignment() & Qt::AlignRight) 72 || (eng->option.textDirection() != Qt::RightToLeft))72 || !eng->isRightToLeft()) 73 73 return QFixed(); 74 74 75 75 int pos = line.length; 76 76 const HB_CharAttributes *attributes = eng->attributes(); 77 if (!attributes) 78 return QFixed(); 77 79 while (pos > 0 && attributes[line.from + pos - 1].whiteSpace) 78 80 --pos; … … 87 89 if (!line.justified && line.width != QFIXED_MAX) { 88 90 int align = eng->option.alignment(); 89 if (align & Qt::AlignJustify && eng-> option.textDirection() == Qt::RightToLeft)91 if (align & Qt::AlignJustify && eng->isRightToLeft()) 90 92 align = Qt::AlignRight; 91 93 if (align & Qt::AlignRight) … … 283 285 \reentrant 284 286 285 \brief The QTextLayout class is used to lay out and paint a single 286 paragraph of text. 287 \brief The QTextLayout class is used to lay out and render text. 287 288 288 289 \ingroup richtext-processing 289 290 290 It offers m ostfeatures expected from a modern text layout291 It offers many features expected from a modern text layout 291 292 engine, including Unicode compliant rendering, line breaking and 292 293 handling of cursor positioning. It can also produce and render … … 298 299 probably won't need to use it directly. 299 300 300 QTextLayout can currently deal with plain text and rich text 301 paragraphs that are part of a QTextDocument. 302 303 QTextLayout can be used to create a sequence of QTextLine's with 304 given widths and can position them independently on the screen. 305 Once the layout is done, these lines can be drawn on a paint 306 device. 307 308 Here's some pseudo code that presents the layout phase: 301 QTextLayout can be used with both plain and rich text. 302 303 QTextLayout can be used to create a sequence of QTextLine 304 instances with given widths and can position them independently 305 on the screen. Once the layout is done, these lines can be drawn 306 on a paint device. 307 308 The text to be laid out can be provided in the constructor or set with 309 setText(). 310 311 The layout can be seen as a sequence of QTextLine objects; use createLine() 312 to create a QTextLine instance, and lineAt() or lineForTextPosition() to retrieve 313 created lines. 314 315 Here is a code snippet that demonstrates the layout phase: 309 316 \snippet doc/src/snippets/code/src_gui_text_qtextlayout.cpp 0 310 317 311 The text can be drawnby calling the layout's draw() function:318 The text can then be rendered by calling the layout's draw() function: 312 319 \snippet doc/src/snippets/code/src_gui_text_qtextlayout.cpp 1 313 320 314 The text layout's text is set in the constructor or with 315 setText(). The layout can be seen as a sequence of QTextLine 316 objects; use lineAt() or lineForTextPosition() to get a QTextLine, 317 createLine() to create one. For a given position in the text you 318 can find a valid cursor position with isValidCursorPosition(), 319 nextCursorPosition(), and previousCursorPosition(). The layout 320 itself can be positioned with setPosition(); it has a 321 boundingRect(), and a minimumWidth() and a maximumWidth(). A text 322 layout can be drawn on a painter device using draw(). 321 For a given position in the text you can find a valid cursor position with 322 isValidCursorPosition(), nextCursorPosition(), and previousCursorPosition(). 323 324 The QTextLayout itself can be positioned with setPosition(); it has a 325 boundingRect(), and a minimumWidth() and a maximumWidth(). 326 327 \sa QStaticText 323 328 324 329 */ … … 599 604 { 600 605 #ifndef QT_NO_DEBUG 601 if (d->layoutData && d->layoutData-> inLayout) {606 if (d->layoutData && d->layoutData->layoutState == QTextEngine::InLayout) { 602 607 qWarning("QTextLayout::beginLayout: Called while already doing layout"); 603 608 return; … … 607 612 d->clearLineData(); 608 613 d->itemize(); 609 d->layoutData-> inLayout = true;614 d->layoutData->layoutState = QTextEngine::InLayout; 610 615 } 611 616 … … 616 621 { 617 622 #ifndef QT_NO_DEBUG 618 if (!d->layoutData || !d->layoutData->inLayout) {623 if (!d->layoutData || d->layoutData->layoutState == QTextEngine::LayoutEmpty) { 619 624 qWarning("QTextLayout::endLayout: Called without beginLayout()"); 620 625 return; … … 625 630 QTextLine(l-1, d).setNumColumns(INT_MAX); 626 631 } 627 d->layoutData-> inLayout = false;632 d->layoutData->layoutState = QTextEngine::LayoutEmpty; 628 633 if (!d->cacheGlyphs) 629 634 d->freeMemory(); … … 755 760 { 756 761 #ifndef QT_NO_DEBUG 757 if (!d->layoutData || !d->layoutData->inLayout) {762 if (!d->layoutData || d->layoutData->layoutState == QTextEngine::LayoutEmpty) { 758 763 qWarning("QTextLayout::createLine: Called without layouting"); 759 764 return QTextLine(); 760 765 } 761 766 #endif 767 if (d->layoutData->layoutState == QTextEngine::LayoutFailed) 768 return QTextLine(); 769 762 770 int l = d->lines.size(); 763 771 if (l && d->lines.at(l-1).length < 0) { … … 859 867 xmin = qMin(xmin, si.x); 860 868 ymin = qMin(ymin, si.y); 861 xmax = qMax(xmax, si.x+qMax(si.width, si.textWidth)); 869 QFixed lineWidth = si.width < QFIXED_MAX ? qMax(si.width, si.textWidth) : si.textWidth; 870 xmax = qMax(xmax, si.x+lineWidth); 862 871 // ### shouldn't the ascent be used in ymin??? 863 872 ymax = qMax(ymax, si.y+si.height()); … … 1209 1218 bool hasText = (selection.format.foreground().style() != Qt::NoBrush); 1210 1219 bool hasBackground= (selection.format.background().style() != Qt::NoBrush); 1211 1220 1212 1221 if (hasBackground) { 1213 1222 selection.format.setProperty(ObjectSelectionBrush, selection.format.property(QTextFormat::BackgroundBrush)); … … 1337 1346 QFixed base = sl.base(); 1338 1347 QFixed descent = sl.descent; 1339 bool rightToLeft = (d->option.textDirection() == Qt::RightToLeft);1348 bool rightToLeft = d->isRightToLeft(); 1340 1349 if (itm >= 0) { 1341 1350 const QScriptItem &si = d->layoutData->items.at(itm); … … 1571 1580 } 1572 1581 1582 /*! \since 4.7 1583 Returns the horizontal advance of the text. The advance of the text 1584 is the distance from its position to the next position at which 1585 text would naturally be drawn. 1586 1587 By adding the advance to the position of the text line and using this 1588 as the position of a second text line, you will be able to position 1589 the two lines side-by-side without gaps in-between. 1590 */ 1591 qreal QTextLine::horizontalAdvance() const 1592 { 1593 return eng->lines[i].textAdvance.toReal(); 1594 } 1595 1573 1596 /*! 1574 1597 Lays out the line with the given \a width. The line is filled from … … 1593 1616 && line.textWidth <= line.width 1594 1617 && line.from + line.length == eng->layoutData->string.length()) 1595 // no need to do anything if the line is already layouted and the last one. This optimi sation helps1618 // no need to do anything if the line is already layouted and the last one. This optimization helps 1596 1619 // when using things in a single line layout. 1597 1620 return; … … 1647 1670 LineBreakHelper() 1648 1671 : glyphCount(0), maxGlyphs(0), currentPosition(0), fontEngine(0), logClusters(0), 1649 manualWrap(false) 1672 manualWrap(false), whiteSpaceOrObject(true) 1650 1673 { 1651 1674 } … … 1670 1693 1671 1694 bool manualWrap; 1695 bool whiteSpaceOrObject; 1672 1696 1673 1697 bool checkFullOtherwiseExtend(QScriptLine &line); … … 1679 1703 1680 1704 inline glyph_t currentGlyph() const 1705 { 1706 Q_ASSERT(currentPosition > 0); 1707 Q_ASSERT(logClusters[currentPosition - 1] < glyphs.numGlyphs); 1708 1709 return glyphs.glyphs[logClusters[currentPosition - 1]]; 1710 } 1711 1712 inline void adjustRightBearing(glyph_t glyph) 1681 1713 { 1682 Q_ASSERT(currentPosition > 0); 1683 return glyphs.glyphs[logClusters[currentPosition - 1]]; 1714 qreal rb; 1715 fontEngine->getGlyphBearings(glyph, 0, &rb); 1716 rightBearing = qMin(QFixed(), QFixed::fromReal(rb)); 1684 1717 } 1685 1718 … … 1688 1721 if (currentPosition <= 0) 1689 1722 return; 1690 1691 qreal rb; 1692 fontEngine->getGlyphBearings(currentGlyph(), 0, &rb); 1693 rightBearing = qMin(QFixed(), QFixed::fromReal(rb)); 1723 adjustRightBearing(currentGlyph()); 1694 1724 } 1695 1725 … … 1702 1732 1703 1733 inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line) 1704 { 1734 { 1705 1735 LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal()); 1706 1736 … … 1768 1798 lbh.manualWrap = (wrapMode == QTextOption::ManualWrap || wrapMode == QTextOption::NoWrap); 1769 1799 1770 // #### binary search!1771 1800 int item = -1; 1772 int newItem; 1773 for (newItem = eng->layoutData->items.size()-1; newItem > 0; --newItem) { 1774 if (eng->layoutData->items[newItem].position <= line.from) 1801 int newItem = -1; 1802 int left = 0; 1803 int right = eng->layoutData->items.size()-1; 1804 while(left <= right) { 1805 int middle = ((right-left)/2)+left; 1806 if (line.from > eng->layoutData->items[middle].position) 1807 left = middle+1; 1808 else if(line.from < eng->layoutData->items[middle].position) 1809 right = middle-1; 1810 else { 1811 newItem = middle; 1775 1812 break; 1776 } 1813 } 1814 } 1815 if (newItem == -1) 1816 newItem = right; 1777 1817 1778 1818 LB_DEBUG("from: %d: item=%d, total %d, width available %f", line.from, newItem, eng->layoutData->items.size(), line.width.toReal()); … … 1781 1821 1782 1822 const HB_CharAttributes *attributes = eng->attributes(); 1823 if (!attributes) 1824 return; 1783 1825 lbh.currentPosition = line.from; 1784 1826 int end = 0; … … 1794 1836 eng->shape(item); 1795 1837 attributes = eng->attributes(); 1838 if (!attributes) 1839 return; 1796 1840 lbh.logClusters = eng->layoutData->logClustersPtr; 1797 1841 } … … 1815 1859 1816 1860 if (current.analysis.flags == QScriptAnalysis::Tab && (alignment & (Qt::AlignLeft | Qt::AlignRight | Qt::AlignCenter | Qt::AlignJustify))) { 1861 lbh.whiteSpaceOrObject = true; 1817 1862 if (lbh.checkFullOtherwiseExtend(line)) 1818 1863 goto found; … … 1831 1876 goto found; 1832 1877 } else if (current.analysis.flags == QScriptAnalysis::LineOrParagraphSeparator) { 1878 lbh.whiteSpaceOrObject = true; 1833 1879 // if the line consists only of the line separator make sure 1834 1880 // we have a sane height … … 1844 1890 goto found; 1845 1891 } else if (current.analysis.flags == QScriptAnalysis::Object) { 1892 lbh.whiteSpaceOrObject = true; 1846 1893 lbh.tmpData.length++; 1847 1894 … … 1857 1904 goto found; 1858 1905 } else if (attributes[lbh.currentPosition].whiteSpace) { 1906 lbh.whiteSpaceOrObject = true; 1859 1907 while (lbh.currentPosition < end && attributes[lbh.currentPosition].whiteSpace) 1860 1908 addNextCluster(lbh.currentPosition, end, lbh.spaceData, lbh.glyphCount, … … 1866 1914 } 1867 1915 } else { 1916 lbh.whiteSpaceOrObject = false; 1868 1917 bool sb_or_ws = false; 1918 glyph_t previousGlyph = 0; 1919 if (lbh.currentPosition > 0 && lbh.logClusters[lbh.currentPosition - 1] <lbh.glyphs.numGlyphs) 1920 previousGlyph = lbh.currentGlyph(); // needed to calculate right bearing later 1869 1921 do { 1870 1922 addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount, … … 1910 1962 // expand the text beyond the edge. 1911 1963 if (sb_or_ws|breakany) { 1912 if (lbh.calculateNewWidth(line) + lbh.minimumRightBearing > line.width) 1964 QFixed rightBearing = lbh.rightBearing; // store previous right bearing 1965 #if !defined(Q_WS_MAC) 1966 if (lbh.calculateNewWidth(line) - lbh.minimumRightBearing > line.width) 1967 #endif 1913 1968 lbh.adjustRightBearing(); 1914 1969 if (lbh.checkFullOtherwiseExtend(line)) { 1970 // we are too wide, fix right bearing 1971 if (rightBearing <= 0) 1972 lbh.rightBearing = rightBearing; // take from cache 1973 else if (previousGlyph > 0) 1974 lbh.adjustRightBearing(previousGlyph); 1915 1975 if (!breakany) { 1916 1976 line.textWidth += lbh.softHyphenWidth; … … 1926 1986 LB_DEBUG("reached end of line"); 1927 1987 lbh.checkFullOtherwiseExtend(line); 1928 found: 1929 if (lbh.rightBearing > 0 ) // If right bearing has not yet been adjusted1988 found: 1989 if (lbh.rightBearing > 0 && !lbh.whiteSpaceOrObject) // If right bearing has not yet been adjusted 1930 1990 lbh.adjustRightBearing(); 1931 1991 line.textAdvance = line.textWidth; -
trunk/src/gui/text/qtextlayout.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 203 203 204 204 qreal naturalTextWidth() const; 205 qreal horizontalAdvance() const; 205 206 QRectF naturalTextRect() const; 206 207 -
trunk/src/gui/text/qtextlist.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 236 236 // c[i] == 4|5|9|40|50|90|400|500|900 237 237 if ((i-2) % 4) { 238 // c[i] == 4|9|40|90|400|900 => with sub straction (IV, IX, XL, XC, ...)238 // c[i] == 4|9|40|90|400|900 => with subtraction (IV, IX, XL, XC, ...) 239 239 numDigits = 2; 240 240 } … … 263 263 Q_ASSERT(false); 264 264 } 265 if (block Format.layoutDirection() == Qt::RightToLeft)265 if (blockIt.textDirection() == Qt::RightToLeft) 266 266 return result.prepend(QLatin1Char('.')); 267 267 return result + QLatin1Char('.'); -
trunk/src/gui/text/qtextlist.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextobject.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 617 617 /*! 618 618 Returns an iterator pointing to the first document element inside the frame. 619 Please see the document \l{STL-style-Iterators} for more information. 619 620 620 621 \sa end() … … 629 630 630 631 /*! 631 Returns an iterator pointing to the last document element inside the frame.632 632 Returns an iterator pointing to the position past the last document element inside the frame. 633 Please see the document \l{STL-Style Iterators} for more information. 633 634 \sa begin() 634 635 */ … … 1141 1142 1142 1143 /*! 1144 \since 4.7 1145 1146 Returns the resolved text direction. 1147 1148 If the block has no explicit direction set, it will resolve the 1149 direction from the blocks content. Returns either Qt::LeftToRight 1150 or Qt::RightToLeft. 1151 1152 \sa QTextFormat::layoutDirection(), QString::isRightToLeft(), Qt::LayoutDirection 1153 */ 1154 Qt::LayoutDirection QTextBlock::textDirection() const 1155 { 1156 Qt::LayoutDirection dir = blockFormat().layoutDirection(); 1157 if (dir != Qt::LayoutDirectionAuto) 1158 return dir; 1159 1160 dir = p->defaultTextOption.textDirection(); 1161 if (dir != Qt::LayoutDirectionAuto) 1162 return dir; 1163 1164 const QString buffer = p->buffer(); 1165 1166 const int pos = position(); 1167 QTextDocumentPrivate::FragmentIterator it = p->find(pos); 1168 QTextDocumentPrivate::FragmentIterator end = p->find(pos + length() - 1); // -1 to omit the block separator char 1169 for (; it != end; ++it) { 1170 const QTextFragmentData * const frag = it.value(); 1171 const QChar *p = buffer.constData() + frag->stringPosition; 1172 const QChar * const end = p + frag->size_array[0]; 1173 while (p < end) { 1174 switch(QChar::direction(p->unicode())) 1175 { 1176 case QChar::DirL: 1177 return Qt::LeftToRight; 1178 case QChar::DirR: 1179 case QChar::DirAL: 1180 return Qt::RightToLeft; 1181 default: 1182 break; 1183 } 1184 ++p; 1185 } 1186 } 1187 return Qt::LeftToRight; 1188 } 1189 1190 /*! 1143 1191 Returns the block's contents as plain text. 1144 1192 … … 1441 1489 QTextBlock QTextBlock::next() const 1442 1490 { 1443 if (! p)1491 if (!isValid()) 1444 1492 return QTextBlock(); 1445 1493 … … 1457 1505 QTextBlock QTextBlock::previous() const 1458 1506 { 1459 if (! p)1507 if (!isValid()) 1460 1508 return QTextBlock(); 1461 1509 -
trunk/src/gui/text/qtextobject.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 221 221 QTextCharFormat charFormat() const; 222 222 int charFormatIndex() const; 223 224 Qt::LayoutDirection textDirection() const; 223 225 224 226 QString text() const; -
trunk/src/gui/text/qtextobject_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextodfwriter.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 494 494 if (format.hasProperty(QTextFormat::TabPositions)) { 495 495 QList<QTextOption::Tab> tabs = format.tabPositions(); 496 writer.writeStartElement(styleNS, QString::fromLatin1(" style-tab-stops"));496 writer.writeStartElement(styleNS, QString::fromLatin1("tab-stops")); 497 497 QList<QTextOption::Tab>::Iterator iterator = tabs.begin(); 498 498 while(iterator != tabs.end()) { 499 writer.writeEmptyElement(styleNS, QString::fromLatin1(" style-tab-stop"));499 writer.writeEmptyElement(styleNS, QString::fromLatin1("tab-stop")); 500 500 writer.writeAttribute(styleNS, QString::fromLatin1("position"), pixelToPoint(iterator->position) ); 501 501 QString type; … … 512 512 } 513 513 514 writer.writeEndElement(); // style-tab-stops514 writer.writeEndElement(); // tab-stops 515 515 } 516 516 … … 699 699 writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(padding)); 700 700 if (format.bottomPadding() > 0) 701 writer.writeAttribute(foNS, QString::fromLatin1("padding- top"), pixelToPoint(format.bottomPadding()));701 writer.writeAttribute(foNS, QString::fromLatin1("padding-bottom"), pixelToPoint(format.bottomPadding())); 702 702 if (format.leftPadding() > 0) 703 writer.writeAttribute(foNS, QString::fromLatin1("padding- top"), pixelToPoint(format.leftPadding()));703 writer.writeAttribute(foNS, QString::fromLatin1("padding-left"), pixelToPoint(format.leftPadding())); 704 704 if (format.rightPadding() > 0) 705 writer.writeAttribute(foNS, QString::fromLatin1("padding- top"), pixelToPoint(format.rightPadding()));705 writer.writeAttribute(foNS, QString::fromLatin1("padding-right"), pixelToPoint(format.rightPadding())); 706 706 } 707 707 -
trunk/src/gui/text/qtextodfwriter_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtextoption.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 66 66 d(0) 67 67 { 68 direction = Q Application::layoutDirection();68 direction = Qt::LayoutDirectionAuto; 69 69 } 70 70 … … 146 146 \sa tabArray(), setTabStop(), setTabs() 147 147 */ 148 void QTextOption::setTabArray(QList<qreal> tabStops) 148 void QTextOption::setTabArray(QList<qreal> tabStops) // Qt5: const ref 149 149 { 150 150 if (!d) … … 166 166 \sa tabStops() 167 167 */ 168 void QTextOption::setTabs(QList<QTextOption::Tab> tabStops) 168 void QTextOption::setTabs(QList<QTextOption::Tab> tabStops) // Qt5: const ref 169 169 { 170 170 if (!d) … … 392 392 393 393 /*! 394 \fn Tab::Tab(qreal pos, TabType tabType, QChar delim = QChar()) 395 396 Creates a tab with the given position, tab type, and delimiter 397 (\a pos, \a tabType, \a delim). 398 399 \note \a delim is only used when \a tabType is DelimiterTab. 400 401 \since 4.7 402 */ 403 404 /*! 394 405 \fn bool Tab::operator==(const Tab &other) const 395 406 -
trunk/src/gui/text/qtextoption.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 69 69 struct Q_GUI_EXPORT Tab { 70 70 inline Tab() : position(80), type(QTextOption::LeftTab) { } 71 inline Tab(qreal pos, TabType tabType, QChar delim = QChar()) 72 : position(pos), type(tabType), delimiter(delim) {} 71 73 72 74 inline bool operator==(const Tab &other) const { … … 135 137 uint wordWrap : 4; 136 138 uint design : 1; 137 uint direction : 1;138 uint unused : 1 9;139 uint direction : 2; 140 uint unused : 18; 139 141 uint f; 140 142 qreal tab; -
trunk/src/gui/text/qtexttable.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 755 755 p->beginEditBlock(); 756 756 757 QList<int> extendedSpans; 757 758 for (int i = 0; i < d->nRows; ++i) { 758 759 int cell; … … 761 762 else 762 763 cell = d->grid[i*d->nCols + pos]; 763 QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), cell);764 QTextCharFormat fmt = c->charFormat(it->format);765 764 if (pos > 0 && pos < d->nCols && cell == d->grid[i*d->nCols + pos - 1]) { 766 765 // cell spans the insertion place, extend it 767 fmt.setTableCellColumnSpan(fmt.tableCellColumnSpan() + num); 768 p->setCharFormat(it.position(), 1, fmt); 766 if (!extendedSpans.contains(cell)) { 767 QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), cell); 768 QTextCharFormat fmt = c->charFormat(it->format); 769 fmt.setTableCellColumnSpan(fmt.tableCellColumnSpan() + num); 770 p->setCharFormat(it.position(), 1, fmt); 771 d->dirty = true; 772 extendedSpans << cell; 773 } 769 774 } else { 775 /* If the next cell is spanned from the row above, we need to find the right position 776 to insert to */ 777 if (i > 0 && pos < d->nCols && cell == d->grid[(i-1) * d->nCols + pos]) { 778 int gridIndex = i*d->nCols + pos; 779 const int gridEnd = d->nRows * d->nCols - 1; 780 while (gridIndex < gridEnd && cell == d->grid[gridIndex]) { 781 ++gridIndex; 782 } 783 if (gridIndex == gridEnd) 784 cell = d->fragment_end; 785 else 786 cell = d->grid[gridIndex]; 787 } 788 QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), cell); 789 QTextCharFormat fmt = c->charFormat(it->format); 770 790 fmt.setTableCellRowSpan(1); 771 791 fmt.setTableCellColumnSpan(1); … … 916 936 for (int c = pos; c < pos + num; ++c) { 917 937 int cell = d->grid[r*d->nCols + c]; 918 if (touchedCells.contains(cell))919 continue;920 touchedCells << cell;921 938 QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), cell); 922 939 QTextCharFormat fmt = collection->charFormat(it->format); 923 940 int span = fmt.tableCellColumnSpan(); 941 if (touchedCells.contains(cell) && span <= 1) 942 continue; 943 touchedCells << cell; 944 924 945 if (span > 1) { 925 946 fmt.setTableCellColumnSpan(span - 1); -
trunk/src/gui/text/qtexttable.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qtexttable_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/gui/text/qzip.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 281 281 } 282 282 283 static QDateTime readMSDosDate(const uchar *src) 284 { 285 uint dosDate = readUInt(src); 286 quint64 uDate; 287 uDate = (quint64)(dosDate >> 16); 288 uint tm_mday = (uDate & 0x1f); 289 uint tm_mon = ((uDate & 0x1E0) >> 5); 290 uint tm_year = (((uDate & 0x0FE00) >> 9) + 1980); 291 uint tm_hour = ((dosDate & 0xF800) >> 11); 292 uint tm_min = ((dosDate & 0x7E0) >> 5); 293 uint tm_sec = ((dosDate & 0x1f) << 1); 294 295 return QDateTime(QDate(tm_year, tm_mon, tm_mday), QTime(tm_hour, tm_min, tm_sec)); 296 } 297 283 298 struct LocalFileHeader 284 299 { … … 344 359 345 360 QZipReader::FileInfo::FileInfo() 346 : isDir(false), isFile( true), isSymLink(false), crc32(0), size(0)361 : isDir(false), isFile(false), isSymLink(false), crc32(0), size(0) 347 362 { 348 363 } … … 366 381 crc32 = other.crc32; 367 382 size = other.size; 383 lastModified = other.lastModified; 368 384 return *this; 385 } 386 387 bool QZipReader::FileInfo::isValid() const 388 { 389 return isDir || isFile || isSymLink; 369 390 } 370 391 … … 404 425 fileInfo.crc32 = readUInt(header.h.crc_32); 405 426 fileInfo.size = readUInt(header.h.uncompressed_size); 427 fileInfo.lastModified = readMSDosDate(header.h.last_mod_file); 406 428 } 407 429 … … 751 773 752 774 /*! 775 Returns device used for reading zip archive. 776 */ 777 QIODevice* QZipReader::device() const 778 { 779 return d->device; 780 } 781 782 /*! 753 783 Returns true if the user can read the file; otherwise returns false. 754 784 */ … … 796 826 /*! 797 827 Returns a FileInfo of an entry in the zipfile. 798 The \a index is the index into the directoy listing of the zipfile. 828 The \a index is the index into the directory listing of the zipfile. 829 Returns an invalid FileInfo if \a index is out of boundaries. 799 830 800 831 \sa fileInfoList() … … 804 835 d->scanFiles(); 805 836 QZipReader::FileInfo fi; 806 d->fillFileInfo(index, fi); 837 if (index >= 0 && index < d->fileHeaders.count()) 838 d->fillFileInfo(index, fi); 807 839 return fi; 808 840 } … … 1023 1055 1024 1056 /*! 1057 Returns device used for writing zip archive. 1058 */ 1059 QIODevice* QZipWriter::device() const 1060 { 1061 return d->device; 1062 } 1063 1064 /*! 1025 1065 Returns true if the user can write to the archive; otherwise returns false. 1026 1066 */ -
trunk/src/gui/text/qzipreader_p.h
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 56 56 // 57 57 58 #include <QtCore/qdatetime.h> 58 59 #include <QtCore/qfile.h> 59 60 #include <QtCore/qstring.h> … … 63 64 class QZipReaderPrivate; 64 65 65 class Q_ AUTOTEST_EXPORT QZipReader66 class Q_GUI_EXPORT QZipReader 66 67 { 67 68 public: … … 71 72 ~QZipReader(); 72 73 74 QIODevice* device() const; 75 73 76 bool isReadable() const; 74 77 bool exists() const; 75 78 76 struct Q_ AUTOTEST_EXPORT FileInfo79 struct Q_GUI_EXPORT FileInfo 77 80 { 78 81 FileInfo(); … … 80 83 ~FileInfo(); 81 84 FileInfo &operator=(const FileInfo &other); 85 bool isValid() const; 82 86 QString filePath; 83 87 uint isDir : 1; … … 87 91 uint crc32; 88 92 qint64 size; 93 QDateTime lastModified; 89 94 void *d; 90 95 }; -
trunk/src/gui/text/qzipwriter_p.h
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 70 70 ~QZipWriter(); 71 71 72 QIODevice* device() const; 73 72 74 bool isWritable() const; 73 75 bool exists() const; -
trunk/src/gui/text/text.pri
r569 r846 38 38 text/qzipreader_p.h \ 39 39 text/qzipwriter_p.h \ 40 text/qtextodfwriter_p.h 40 text/qtextodfwriter_p.h \ 41 text/qstatictext_p.h \ 42 text/qstatictext.h 41 43 42 44 SOURCES += \ … … 67 69 text/qcssparser.cpp \ 68 70 text/qzip.cpp \ 69 text/qtextodfwriter.cpp 71 text/qtextodfwriter.cpp \ 72 text/qstatictext.cpp 70 73 71 74 win32 { … … 146 149 ../3rdparty/freetype/src/base/ftmm.c \ 147 150 ../3rdparty/freetype/src/base/fttype1.c \ 148 ../3rdparty/freetype/src/base/ftbitmap.c\ 151 ../3rdparty/freetype/src/base/ftsynth.c \ 152 ../3rdparty/freetype/src/base/ftbitmap.c \ 149 153 ../3rdparty/freetype/src/bdf/bdf.c \ 150 154 ../3rdparty/freetype/src/cache/ftcache.c \ … … 211 215 include($$QT_SOURCE_TREE/config.tests/unix/freetype/freetype.pri) 212 216 LIBS_PRIVATE += -lfreetype 213 } else {214 DEFINES *= QT_NO_FREETYPE215 217 } 216 218
Note:
See TracChangeset
for help on using the changeset viewer.