diff options
Diffstat (limited to 'src/gui/text')
26 files changed, 1478 insertions, 302 deletions
diff --git a/src/gui/text/qabstractfontengine_p.h b/src/gui/text/qabstractfontengine_p.h index 4752de5..59b54bd 100644 --- a/src/gui/text/qabstractfontengine_p.h +++ b/src/gui/text/qabstractfontengine_p.h @@ -91,7 +91,7 @@ public: virtual Type type() const { return Proxy; } virtual const char *name() const { return "proxy engine"; } -#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) +#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_WS_S60) virtual void draw(QPaintEngine *, qreal, qreal, const QTextItemInt &); #endif diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index a05e5a1..e1b39a0 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -48,6 +48,7 @@ #include <qfontmetrics.h> #include <qbrush.h> #include <qimagereader.h> +#include "private/qfunctions_p.h" #ifndef QT_NO_CSSPARSER @@ -338,12 +339,12 @@ static const QCssKnownValue styleFeatures[NumKnownStyleFeatures - 1] = { { "none", StyleFeature_None } }; -static bool operator<(const QString &name, const QCssKnownValue &prop) +Q_STATIC_GLOBAL_OPERATOR bool operator<(const QString &name, const QCssKnownValue &prop) { return QString::compare(name, QLatin1String(prop.name), Qt::CaseInsensitive) < 0; } -static bool operator<(const QCssKnownValue &prop, const QString &name) +Q_STATIC_GLOBAL_OPERATOR bool operator<(const QCssKnownValue &prop, const QString &name) { return QString::compare(QLatin1String(prop.name), name, Qt::CaseInsensitive) < 0; } diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index c5096bf..e324db6 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -72,6 +72,9 @@ #include "qfontengine_qpf_p.h" #endif #endif +#ifdef Q_WS_S60 +#include "qt_s60_p.h" +#endif #include <QMutexLocker> @@ -169,6 +172,8 @@ Q_GUI_EXPORT int qt_defaultDpiX() if (!subScreens.isEmpty()) screen = subScreens.at(0); dpi = qRound(screen->width() / (screen->physicalWidth() / qreal(25.4))); +#elif defined(Q_WS_S60) + dpi = S60->defaultDpiX; #endif // Q_WS_X11 return dpi; @@ -195,6 +200,8 @@ Q_GUI_EXPORT int qt_defaultDpiY() if (!subScreens.isEmpty()) screen = subScreens.at(0); dpi = qRound(screen->height() / (screen->physicalHeight() / qreal(25.4))); +#elif defined(Q_WS_S60) + dpi = S60->defaultDpiY; #endif // Q_WS_X11 return dpi; @@ -307,7 +314,7 @@ QFontPrivate *QFontPrivate::smallCapsFontPrivate() const font.setPointSizeF(pointSize * .7); else font.setPixelSize((font.pixelSize() * 7 + 5) / 10); - scFont = font.d; + scFont = font.d.data(); if (scFont != this) scFont->ref.ref(); return scFont; @@ -714,12 +721,11 @@ QFont::QFont(const QFont &font, QPaintDevice *pd) const int screen = 0; #endif if (font.d->dpi != dpi || font.d->screen != screen ) { - d = new QFontPrivate(*font.d); + d.reset(new QFontPrivate(*font.d)); d->dpi = dpi; d->screen = screen; } else { - d = font.d; - d->ref.ref(); + d.assign(font.d.data()); } #ifdef Q_WS_WIN if (pd->devType() == QInternal::Printer && pd->getDC()) @@ -733,8 +739,7 @@ QFont::QFont(const QFont &font, QPaintDevice *pd) QFont::QFont(QFontPrivate *data) : resolve_mask(QFont::AllPropertiesResolved) { - d = data; - d->ref.ref(); + d.assign(data); } /*! \internal @@ -746,13 +751,13 @@ void QFont::detach() if (d->engineData) d->engineData->ref.deref(); d->engineData = 0; - if (d->scFont && d->scFont != d) + if (d->scFont && d->scFont != d.data()) d->scFont->ref.deref(); d->scFont = 0; return; } - qAtomicDetach(d); + d.detach(); } /*! @@ -761,9 +766,9 @@ void QFont::detach() \sa QApplication::setFont(), QApplication::font() */ QFont::QFont() - :d(QApplication::font().d), resolve_mask(0) + :resolve_mask(0) { - d->ref.ref(); + d.assign(QApplication::font().d.data()); } /*! @@ -783,12 +788,16 @@ QFont::QFont() setStyleHint() QApplication::font() */ QFont::QFont(const QString &family, int pointSize, int weight, bool italic) - :d(new QFontPrivate) { + d.reset(new QFontPrivate()); resolve_mask = QFont::FamilyResolved; if (pointSize <= 0) { +#ifdef Q_WS_S60 + pointSize = 7; +#else pointSize = 12; +#endif } else { resolve_mask |= QFont::SizeResolved; } @@ -811,8 +820,7 @@ QFont::QFont(const QString &family, int pointSize, int weight, bool italic) */ QFont::QFont(const QFont &font) { - d = font.d; - d->ref.ref(); + d.assign(font.d.data()); resolve_mask = font.resolve_mask; } @@ -821,8 +829,6 @@ QFont::QFont(const QFont &font) */ QFont::~QFont() { - if (!d->ref.deref()) - delete d; } /*! @@ -830,7 +836,7 @@ QFont::~QFont() */ QFont &QFont::operator=(const QFont &font) { - qAtomicAssign(d, font.d); + d.assign(font.d.data()); resolve_mask = font.resolve_mask; return *this; } @@ -1713,7 +1719,7 @@ QFont QFont::resolve(const QFont &other) const QFont font(*this); font.detach(); - font.d->resolve(resolve_mask, other.d); + font.d->resolve(resolve_mask, other.d.data()); return font; } @@ -2166,11 +2172,11 @@ QDataStream &operator<<(QDataStream &s, const QFont &font) s << (quint8) font.d->request.styleStrategy; s << (quint8) 0 << (quint8) font.d->request.weight - << get_font_bits(s.version(), font.d); + << get_font_bits(s.version(), font.d.data()); if (s.version() >= QDataStream::Qt_4_3) s << (quint16)font.d->request.stretch; if (s.version() >= QDataStream::Qt_4_4) - s << get_extended_font_bits(font.d); + s << get_extended_font_bits(font.d.data()); if (s.version() >= QDataStream::Qt_4_5) { s << font.d->letterSpacing.value(); s << font.d->wordSpacing.value(); @@ -2189,10 +2195,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font) */ QDataStream &operator>>(QDataStream &s, QFont &font) { - if (!font.d->ref.deref()) - delete font.d; - - font.d = new QFontPrivate; + font.d.assign(0); + font.d.reset(new QFontPrivate); font.resolve_mask = QFont::AllPropertiesResolved; quint8 styleHint, styleStrategy = QFont::PreferDefault, charSet, weight, bits; @@ -2233,7 +2237,7 @@ QDataStream &operator>>(QDataStream &s, QFont &font) font.d->request.styleStrategy = styleStrategy; font.d->request.weight = weight; - set_font_bits(s.version(), bits, font.d); + set_font_bits(s.version(), bits, font.d.data()); if (s.version() >= QDataStream::Qt_4_3) { quint16 stretch; @@ -2244,7 +2248,7 @@ QDataStream &operator>>(QDataStream &s, QFont &font) if (s.version() >= QDataStream::Qt_4_4) { quint8 extendedBits; s >> extendedBits; - set_extended_font_bits(extendedBits, font.d); + set_extended_font_bits(extendedBits, font.d.data()); } if (s.version() >= QDataStream::Qt_4_5) { int value; @@ -2326,7 +2330,7 @@ QDataStream &operator>>(QDataStream &s, QFont &font) that is not screen-compatible. */ QFontInfo::QFontInfo(const QFont &font) - : d(font.d) + : d(font.d.data()) { d->ref.ref(); } /*! @@ -2599,7 +2603,14 @@ QFontCache *QFontCache::instance() void QFontCache::cleanup() { - theFontCache()->setLocalData(0); + QThreadStorage<QFontCache *> *cache = 0; + QT_TRY { + cache = theFontCache(); + } QT_CATCH (const std::bad_alloc &) { + // no cache - just ignore + } + if (cache && cache->hasLocalData()) + cache->setLocalData(0); } #endif // QT_NO_THREAD @@ -2612,8 +2623,8 @@ QFontCache::QFontCache() QFontCache::~QFontCache() { { - EngineDataCache::Iterator it = engineDataCache.begin(), - end = engineDataCache.end(); + EngineDataCache::ConstIterator it = engineDataCache.constBegin(), + end = engineDataCache.constEnd(); while (it != end) { if (it.value()->ref == 0) delete it.value(); @@ -2623,8 +2634,8 @@ QFontCache::~QFontCache() ++it; } } - EngineCache::Iterator it = engineCache.begin(), - end = engineCache.end(); + EngineCache::ConstIterator it = engineCache.constBegin(), + end = engineCache.constEnd(); while (it != end) { if (--it.value().data->cache_count == 0) { if (it.value().data->ref == 0) { diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h index eec83b5..a513b7a 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -44,6 +44,7 @@ #include <QtGui/qwindowdefs.h> #include <QtCore/qstring.h> +#include <QtCore/qscopedpointer.h> #if defined(Q_WS_X11) || defined(Q_WS_QWS) typedef struct FT_FaceRec_* FT_Face; @@ -312,7 +313,7 @@ private: friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QFont &); #endif - QFontPrivate *d; + QScopedSharedPointer<QFontPrivate> d; uint resolve_mask; }; diff --git a/src/gui/text/qfont_s60.cpp b/src/gui/text/qfont_s60.cpp new file mode 100644 index 0000000..533e51f --- /dev/null +++ b/src/gui/text/qfont_s60.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfont.h" +#include "qt_s60_p.h" +#include <private/qwindowsurface_s60_p.h> +#include "qmutex.h" + +QT_BEGIN_NAMESPACE + +#if 1 +#ifdef QT_NO_FREETYPE +Q_GLOBAL_STATIC(QMutex, lastResortFamilyMutex); +#endif // QT_NO_FREETYPE + +QString QFont::lastResortFamily() const +{ +#ifdef QT_NO_FREETYPE + QMutexLocker locker(lastResortFamilyMutex()); + static QString family; + if (family.isEmpty()) { + QS60WindowSurface::unlockBitmapHeap(); + CFont *font; + const TInt err = S60->screenDevice()->GetNearestFontInTwips(font, TFontSpec()); + Q_ASSERT(err == KErrNone); + const TFontSpec spec = font->FontSpecInTwips(); + family = QString((const QChar *)spec.iTypeface.iName.Ptr(), spec.iTypeface.iName.Length()); + S60->screenDevice()->ReleaseFont(font); + QS60WindowSurface::lockBitmapHeap(); + } + return family; +#else + // For the FreeType case we just hard code the face name, since otherwise on + // East Asian systems we may get a name for a stroke based (non-ttf) font. + + // TODO: Get the type face name in a proper way + + const bool isJapaneseOrChineseSystem = + User::Language() == ELangJapanese || User::Language() == ELangPrcChinese; + + return QLatin1String(isJapaneseOrChineseSystem?"Heisei Kaku Gothic S60":"Series 60 Sans"); +#endif // QT_NO_FREETYPE +} +#else // 0 +QString QFont::lastResortFamily() const +{ + return QLatin1String("Series 60 Sans"); +} +#endif // 0 + +QString QFont::defaultFamily() const +{ + return lastResortFamily(); +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index e9f067a..76f5c39 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -56,6 +56,11 @@ #include <stdlib.h> #include <limits.h> +#if (defined(Q_WS_QWS) || defined(Q_WS_S60)) && !defined(QT_NO_FREETYPE) +# include <ft2build.h> +# include FT_TRUETYPE_TABLES_H +#endif + // #define QFONTDATABASE_DEBUG #ifdef QFONTDATABASE_DEBUG # define FD_DEBUG qDebug @@ -76,6 +81,8 @@ QT_BEGIN_NAMESPACE +#define SMOOTH_SCALABLE 0xffff + extern int qt_defaultDpiY(); // in qfont.cpp Q_GUI_EXPORT bool qt_enable_test_font = false; @@ -141,10 +148,10 @@ struct QtFontSize QtFontEncoding *encodingID(int id, uint xpoint = 0, uint xres = 0, uint yres = 0, uint avgwidth = 0, bool add = false); #endif // Q_WS_X11 -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_S60) QByteArray fileName; int fileIndex; -#endif +#endif // defined(Q_WS_QWS) || defined(Q_WS_S60) }; @@ -160,10 +167,13 @@ QtFontEncoding *QtFontSize::encodingID(int id, uint xpoint, uint xres, if (!add) return 0; - if (!(count % 4)) - encodings = (QtFontEncoding *) + if (!(count % 4)) { + QtFontEncoding *newEncodings = (QtFontEncoding *) realloc(encodings, (((count+4) >> 2) << 2) * sizeof(QtFontEncoding)); + Q_CHECK_PTR(newEncodings); + encodings = newEncodings; + } encodings[count].encoding = id; encodings[count].xpoint = xpoint; encodings[count].xres = xres; @@ -215,12 +225,12 @@ struct QtFontStyle delete [] weightName; delete [] setwidthName; #endif -#if defined(Q_WS_X11) || defined(Q_WS_QWS) +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_S60) while (count--) { #ifdef Q_WS_X11 free(pixelSizes[count].encodings); #endif -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_S60) pixelSizes[count].fileName.~QByteArray(); #endif } @@ -238,7 +248,7 @@ struct QtFontStyle const char *weightName; const char *setwidthName; #endif // Q_WS_X11 -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_S60) bool antialiased; #endif @@ -267,16 +277,19 @@ QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add) if (!add) return 0; - if (!(count % 8)) - pixelSizes = (QtFontSize *) + if (!(count % 8)) { + QtFontSize *newPixelSizes = (QtFontSize *) realloc(pixelSizes, (((count+8) >> 3) << 3) * sizeof(QtFontSize)); + Q_CHECK_PTR(newPixelSizes); + pixelSizes = newPixelSizes; + } pixelSizes[count].pixelSize = size; #ifdef Q_WS_X11 pixelSizes[count].count = 0; pixelSizes[count].encodings = 0; #endif -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_S60) new (&pixelSizes[count].fileName) QByteArray; pixelSizes[count].fileIndex = 0; #endif @@ -321,12 +334,16 @@ QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create) return 0; // qDebug("adding key (weight=%d, style=%d, oblique=%d stretch=%d) at %d", key.weight, key.style, key.oblique, key.stretch, pos); - if (!(count % 8)) - styles = (QtFontStyle **) + if (!(count % 8)) { + QtFontStyle **newStyles = (QtFontStyle **) realloc(styles, (((count+8) >> 3) << 3) * sizeof(QtFontStyle *)); + Q_CHECK_PTR(newStyles); + styles = newStyles; + } + QtFontStyle *style = new QtFontStyle(key); memmove(styles + pos + 1, styles + pos, (count-pos)*sizeof(QtFontStyle *)); - styles[pos] = new QtFontStyle(key); + styles[pos] = style; count++; return styles[pos]; } @@ -358,7 +375,7 @@ struct QtFontFamily fixedPitchComputed(false), #endif name(n), count(0), foundries(0) -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_S60) && !defined(QT_NO_FREETYPE) , bogusWritingSystems(false) #endif { @@ -388,7 +405,7 @@ struct QtFontFamily #endif QString name; -#ifdef Q_WS_X11 +#if defined(Q_WS_X11) || defined(Q_WS_S60) && !defined(QT_NO_FREETYPE) QByteArray fontFilename; int fontFileIndex; #endif @@ -398,7 +415,7 @@ struct QtFontFamily int count; QtFontFoundry **foundries; -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_S60) && !defined(QT_NO_FREETYPE) bool bogusWritingSystems; QStringList fallbackFamilies; #endif @@ -431,10 +448,13 @@ QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create) if (!create) return 0; - if (!(count % 8)) - foundries = (QtFontFoundry **) + if (!(count % 8)) { + QtFontFoundry **newFoundries = (QtFontFoundry **) realloc(foundries, (((count+8) >> 3) << 3) * sizeof(QtFontFoundry *)); + Q_CHECK_PTR(newFoundries); + foundries = newFoundries; + } foundries[count] = new QtFontFoundry(f); return foundries[count++]; @@ -442,7 +462,7 @@ QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create) // ### copied to tools/makeqpf/qpf2.cpp -#if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_WS_MAC) +#if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_WS_S60) // see the Unicode subset bitfields in the MSDN docs static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = { // Any, @@ -563,6 +583,15 @@ static QList<QFontDatabase::WritingSystem> determineWritingSystemsFromTrueTypeBi } #endif +#if defined(Q_WS_S60) && defined(QT_NO_FREETYPE) +// class with virtual destructor, derived in qfontdatabase_s60.cpp +class QFontDatabaseS60Store +{ +public: + virtual ~QFontDatabaseS60Store() {}; +}; +#endif + class QFontDatabasePrivate { public: @@ -571,6 +600,9 @@ public: #if defined(Q_WS_QWS) , stream(0) #endif +#if defined(Q_WS_S60) && defined(QT_NO_FREETYPE) + , s60Store(0) +#endif { } ~QFontDatabasePrivate() { free(); @@ -582,6 +614,12 @@ public: ::free(families); families = 0; count = 0; +#if defined(Q_WS_S60) && defined(QT_NO_FREETYPE) + if (s60Store) { + delete s60Store; + s60Store = 0; + } +#endif // don't clear the memory fonts! } @@ -609,17 +647,22 @@ public: #if defined(Q_WS_QWS) bool loadFromCache(const QString &fontPath); + void addQPF2File(const QByteArray &file); +#endif // Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_S60) && !defined(QT_NO_FREETYPE) void addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize, const QByteArray &file, int fileIndex, bool antialiased, const QList<QFontDatabase::WritingSystem> &writingSystems = QList<QFontDatabase::WritingSystem>()); - void addQPF2File(const QByteArray &file); #ifndef QT_NO_FREETYPE QStringList addTTFile(const QByteArray &file, const QByteArray &fontData = QByteArray()); +#endif // QT_NO_FREETYPE #endif - +#if defined(Q_WS_QWS) QDataStream *stream; QStringList fallbackFamilies; +#elif defined(Q_WS_S60) && defined(QT_NO_FREETYPE) + const QFontDatabaseS60Store *s60Store; #endif }; @@ -654,17 +697,133 @@ QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create) pos++; // qDebug("adding family %s at %d total=%d", f.latin1(), pos, count); - if (!(count % 8)) - families = (QtFontFamily **) + if (!(count % 8)) { + QtFontFamily **newFamilies = (QtFontFamily **) realloc(families, (((count+8) >> 3) << 3) * sizeof(QtFontFamily *)); + Q_CHECK_PTR(newFamilies); + families = newFamilies; + } + QtFontFamily *family = new QtFontFamily(f); memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *)); - families[pos] = new QtFontFamily(f); + families[pos] = family; count++; return families[pos]; } +#if defined(Q_WS_QWS) || defined(Q_WS_S60) && !defined(QT_NO_FREETYPE) +void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize, + const QByteArray &file, int fileIndex, bool antialiased, + const QList<QFontDatabase::WritingSystem> &writingSystems) +{ +// qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased; + QtFontStyle::Key styleKey; + styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal; + styleKey.weight = weight; + styleKey.stretch = 100; + QtFontFamily *f = family(familyname, true); + + if (writingSystems.isEmpty()) { + for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) { + f->writingSystems[ws] = QtFontFamily::Supported; + } + f->bogusWritingSystems = true; + } else { + for (int i = 0; i < writingSystems.count(); ++i) { + f->writingSystems[writingSystems.at(i)] = QtFontFamily::Supported; + } + } + + QtFontFoundry *foundry = f->foundry(QString::fromLatin1(foundryname), true); + QtFontStyle *style = foundry->style(styleKey, true); + style->smoothScalable = (pixelSize == 0); + style->antialiased = antialiased; + QtFontSize *size = style->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true); + size->fileName = file; + size->fileIndex = fileIndex; + +#if defined(Q_WS_QWS) + if (stream) { + *stream << familyname << foundry->name << weight << quint8(italic) << pixelSize + << file << fileIndex << quint8(antialiased); + *stream << quint8(writingSystems.count()); + for (int i = 0; i < writingSystems.count(); ++i) + *stream << quint8(writingSystems.at(i)); + } +#else // ..in case of defined(Q_WS_S60) && !defined(QT_NO_FREETYPE) + f->fontFilename = file; + f->fontFileIndex = fileIndex; +#endif +} +#endif + +#if (defined(Q_WS_QWS) || defined(Q_WS_S60)) && !defined(QT_NO_FREETYPE) +QStringList QFontDatabasePrivate::addTTFile(const QByteArray &file, const QByteArray &fontData) +{ + QStringList families; + extern FT_Library qt_getFreetype(); + FT_Library library = qt_getFreetype(); + + int index = 0; + int numFaces = 0; + do { + FT_Face face; + FT_Error error; + if (!fontData.isEmpty()) { + error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face); + } else { + error = FT_New_Face(library, file, index, &face); + } + if (error != FT_Err_Ok) { + qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error; + break; + } + numFaces = face->num_faces; + + int weight = QFont::Normal; + bool italic = face->style_flags & FT_STYLE_FLAG_ITALIC; + + if (face->style_flags & FT_STYLE_FLAG_BOLD) + weight = QFont::Bold; + + QList<QFontDatabase::WritingSystem> writingSystems; + // detect symbol fonts + for (int i = 0; i < face->num_charmaps; ++i) { + FT_CharMap cm = face->charmaps[i]; + if (cm->encoding == ft_encoding_adobe_custom + || cm->encoding == ft_encoding_symbol) { + writingSystems.append(QFontDatabase::Symbol); + break; + } + } + if (writingSystems.isEmpty()) { + TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2); + if (os2) { + quint32 unicodeRange[4] = { + os2->ulUnicodeRange1, os2->ulUnicodeRange2, os2->ulUnicodeRange3, os2->ulUnicodeRange4 + }; + quint32 codePageRange[2] = { + os2->ulCodePageRange1, os2->ulCodePageRange2 + }; + + writingSystems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange); + //for (int i = 0; i < writingSystems.count(); ++i) + // qDebug() << QFontDatabase::writingSystemName(writingSystems.at(i)); + } + } + + QString family = QString::fromAscii(face->family_name); + families.append(family); + addFont(family, /*foundry*/ "", weight, italic, + /*pixelsize*/ 0, file, index, /*antialias*/ true, writingSystems); + + FT_Done_Face(face); + ++index; + } while (index < numFaces); + return families; +} +#endif static const int scriptForWritingSystem[] = { QUnicodeTables::Common, // Any @@ -814,7 +973,7 @@ static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDe #endif #endif -#if defined(Q_WS_X11) || defined(Q_WS_WIN) +#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_WS_S60) static void getEngineData(const QFontPrivate *d, const QFontCache::Key &key) { // look for the requested font in the engine data cache @@ -866,8 +1025,6 @@ QMutex *qt_fontdatabase_mutex() return fontDatabaseMutex(); } -#define SMOOTH_SCALABLE 0xffff - QT_BEGIN_INCLUDE_NAMESPACE #if defined(Q_WS_X11) # include "qfontdatabase_x11.cpp" @@ -877,6 +1034,8 @@ QT_BEGIN_INCLUDE_NAMESPACE # include "qfontdatabase_win.cpp" #elif defined(Q_WS_QWS) # include "qfontdatabase_qws.cpp" +#elif defined(Q_WS_S60) +# include "qfontdatabase_s60.cpp" #endif QT_END_INCLUDE_NAMESPACE @@ -2254,7 +2413,16 @@ QString QFontDatabase::writingSystemSample(WritingSystem writingSystem) sample += QChar(0xac2f); break; case Vietnamese: + { + static const char vietnameseUtf8[] = { + char(0xef), char(0xbb), char(0xbf), char(0xe1), char(0xbb), char(0x97), + char(0xe1), char(0xbb), char(0x99), + char(0xe1), char(0xbb), char(0x91), + char(0xe1), char(0xbb), char(0x93), + }; + sample += QString::fromUtf8(vietnameseUtf8, sizeof(vietnameseUtf8)); break; + } case Ogham: sample += QChar(0x1681); sample += QChar(0x1682); diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index eadb6ba..c169e29 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -151,7 +151,7 @@ public: private: static void createDatabase(); static void parseFontName(const QString &name, QString &foundry, QString &family); -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_S60) static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request); #endif static void load(const QFontPrivate *d, int script); @@ -165,6 +165,7 @@ private: friend class QFontDialogPrivate; friend class QFontEngineMultiXLFD; friend class QFontEngineMultiQWS; + friend class QFontEngineMultiS60; QFontDatabasePrivate *d; }; diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp index 9a29de2..7f97cf2 100644 --- a/src/gui/text/qfontdatabase_qws.cpp +++ b/src/gui/text/qfontdatabase_qws.cpp @@ -50,7 +50,6 @@ #include <ft2build.h> #include FT_FREETYPE_H -#include FT_TRUETYPE_TABLES_H #endif #include "qfontengine_qpf_p.h" @@ -82,44 +81,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, const quint8 DatabaseVersion = 4; -void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize, - const QByteArray &file, int fileIndex, bool antialiased, - const QList<QFontDatabase::WritingSystem> &writingSystems) -{ -// qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased; - QtFontStyle::Key styleKey; - styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal; - styleKey.weight = weight; - styleKey.stretch = 100; - QtFontFamily *f = family(familyname, true); - - if (writingSystems.isEmpty()) { - for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) { - f->writingSystems[ws] = QtFontFamily::Supported; - } - f->bogusWritingSystems = true; - } else { - for (int i = 0; i < writingSystems.count(); ++i) { - f->writingSystems[writingSystems.at(i)] = QtFontFamily::Supported; - } - } - - QtFontFoundry *foundry = f->foundry(QString::fromLatin1(foundryname), true); - QtFontStyle *style = foundry->style(styleKey, true); - style->smoothScalable = (pixelSize == 0); - style->antialiased = antialiased; - QtFontSize *size = style->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true); - size->fileName = file; - size->fileIndex = fileIndex; - - if (stream) { - *stream << familyname << foundry->name << weight << quint8(italic) << pixelSize - << file << fileIndex << quint8(antialiased); - *stream << quint8(writingSystems.count()); - for (int i = 0; i < writingSystems.count(); ++i) - *stream << quint8(writingSystems.at(i)); - } -} +// QFontDatabasePrivate::addFont() went into qfontdatabase.cpp #ifndef QT_NO_QWS_QPF2 void QFontDatabasePrivate::addQPF2File(const QByteArray &file) @@ -179,74 +141,9 @@ void QFontDatabasePrivate::addQPF2File(const QByteArray &file) ::close(f); #endif } -#endif - -#ifndef QT_NO_FREETYPE -QStringList QFontDatabasePrivate::addTTFile(const QByteArray &file, const QByteArray &fontData) -{ - QStringList families; - extern FT_Library qt_getFreetype(); - FT_Library library = qt_getFreetype(); - - int index = 0; - int numFaces = 0; - do { - FT_Face face; - FT_Error error; - if (!fontData.isEmpty()) { - error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face); - } else { - error = FT_New_Face(library, file, index, &face); - } - if (error != FT_Err_Ok) { - qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error; - break; - } - numFaces = face->num_faces; - - int weight = QFont::Normal; - bool italic = face->style_flags & FT_STYLE_FLAG_ITALIC; - - if (face->style_flags & FT_STYLE_FLAG_BOLD) - weight = QFont::Bold; - - QList<QFontDatabase::WritingSystem> writingSystems; - // detect symbol fonts - for (int i = 0; i < face->num_charmaps; ++i) { - FT_CharMap cm = face->charmaps[i]; - if (cm->encoding == ft_encoding_adobe_custom - || cm->encoding == ft_encoding_symbol) { - writingSystems.append(QFontDatabase::Symbol); - break; - } - } - if (writingSystems.isEmpty()) { - TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2); - if (os2) { - quint32 unicodeRange[4] = { - os2->ulUnicodeRange1, os2->ulUnicodeRange2, os2->ulUnicodeRange3, os2->ulUnicodeRange4 - }; - quint32 codePageRange[2] = { - os2->ulCodePageRange1, os2->ulCodePageRange2 - }; - - writingSystems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange); - //for (int i = 0; i < writingSystems.count(); ++i) - // qDebug() << QFontDatabase::writingSystemName(writingSystems.at(i)); - } - } +#endif // QT_NO_QWS_QPF2 - QString family = QString::fromAscii(face->family_name); - families.append(family); - addFont(family, /*foundry*/ "", weight, italic, - /*pixelsize*/ 0, file, index, /*antialias*/ true, writingSystems); - - FT_Done_Face(face); - ++index; - } while (index < numFaces); - return families; -} -#endif +// QFontDatabasePrivate::addTTFile() went into qfontdatabase.cpp static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt); @@ -670,8 +567,8 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp, QFontEngineQPF *fe = new QFontEngineQPF(request, res.data(), res.size()); if (fe->isValid()) return fe; - qDebug() << "fontengine is not valid! " << size->fileName; delete fe; + qDebug() << "fontengine is not valid! " << size->fileName; } else { qDebug() << "Resource not valid" << size->fileName; } @@ -681,8 +578,8 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp, QFontEngineQPF *fe = new QFontEngineQPF(request, f); if (fe->isValid()) return fe; - qDebug() << "fontengine is not valid!"; delete fe; // will close f + qDebug() << "fontengine is not valid!"; } #endif } else @@ -696,70 +593,67 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp, static bool dontShareFonts = !qgetenv("QWS_NO_SHARE_FONTS").isEmpty(); bool shareFonts = !dontShareFonts; - QFontEngine *engine = 0; + QScopedPointer<QFontEngine> engine; #ifndef QT_NO_LIBRARY QFontEngineFactoryInterface *factory = qobject_cast<QFontEngineFactoryInterface *>(loader()->instance(foundry->name)); - if (factory) { - QFontEngineInfo info; - info.setFamily(request.family); - info.setPixelSize(request.pixelSize); - info.setStyle(QFont::Style(request.style)); - info.setWeight(request.weight); - // #### antialiased - - QAbstractFontEngine *customEngine = factory->create(info); - if (customEngine) { - engine = new QProxyFontEngine(customEngine, def); - - if (shareFonts) { - QVariant hint = customEngine->fontProperty(QAbstractFontEngine::CacheGlyphsHint); - if (hint.isValid()) - shareFonts = hint.toBool(); - else - shareFonts = (pixelSize < 64); - } + if (factory) { + QFontEngineInfo info; + info.setFamily(request.family); + info.setPixelSize(request.pixelSize); + info.setStyle(QFont::Style(request.style)); + info.setWeight(request.weight); + // #### antialiased + + QAbstractFontEngine *customEngine = factory->create(info); + if (customEngine) { + engine.reset(new QProxyFontEngine(customEngine, def)); + + if (shareFonts) { + QVariant hint = customEngine->fontProperty(QAbstractFontEngine::CacheGlyphsHint); + if (hint.isValid()) + shareFonts = hint.toBool(); + else + shareFonts = (pixelSize < 64); } + } } #endif // QT_NO_LIBRARY - if (!engine && !file.isEmpty() && QFile::exists(file) || privateDb()->isApplicationFont(file)) { + if ((engine.isNull() && !file.isEmpty() && QFile::exists(file)) || privateDb()->isApplicationFont(file)) { QFontEngine::FaceId faceId; faceId.filename = file.toLocal8Bit(); faceId.index = size->fileIndex; #ifndef QT_NO_FREETYPE - QFontEngineFT *fte = new QFontEngineFT(def); + QScopedPointer<QFontEngineFT> fte(new QFontEngineFT(def)); if (fte->init(faceId, style->antialiased, style->antialiased ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono)) { #ifdef QT_NO_QWS_QPF2 - return fte; + return fte.take(); #else - engine = fte; // try to distinguish between bdf and ttf fonts we can pre-render // and don't try to share outline fonts shareFonts = shareFonts && !fte->defaultGlyphs()->outline_drawing && !fte->getSfntTable(MAKE_TAG('h', 'e', 'a', 'd')).isEmpty(); + engine.reset(fte.take()); #endif - } else { - delete fte; } #endif // QT_NO_FREETYPE } - if (engine) { + if (!engine.isNull()) { #if !defined(QT_NO_QWS_QPF2) && !defined(QT_FONTS_ARE_RESOURCES) if (shareFonts) { - QFontEngineQPF *fe = new QFontEngineQPF(def, -1, engine); - engine = 0; + QScopedPointer<QFontEngineQPF> fe(new QFontEngineQPF(def, -1, engine.data())); + engine.take(); if (fe->isValid()) - return fe; + return fe.take(); qWarning("Initializing QFontEngineQPF failed for %s", qPrintable(file)); - engine = fe->takeRenderingEngine(); - delete fe; + engine.reset(fe->takeRenderingEngine()); } #endif - return engine; + return engine.take(); } } else { @@ -786,20 +680,22 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, QtFontFamily *family, QtFontFoundry *foundry, QtFontStyle *style, QtFontSize *size) { - QFontEngine *fe = loadSingleEngine(script, fp, request, family, foundry, - style, size); - if (fe + QScopedPointer<QFontEngine> engine(loadSingleEngine(script, fp, request, family, foundry, + style, size)); + if (!engine.isNull() && script == QUnicodeTables::Common - && !(request.styleStrategy & QFont::NoFontMerging) && !fe->symbol) { + && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) { QStringList fallbacks = privateDb()->fallbackFamilies; if (family && !family->fallbackFamilies.isEmpty()) fallbacks = family->fallbackFamilies; - fe = new QFontEngineMultiQWS(fe, script, fallbacks); + QFontEngine *fe = new QFontEngineMultiQWS(engine.data(), script, fallbacks); + engine.take(); + engine.reset(fe); } - return fe; + return engine.take(); } static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp new file mode 100644 index 0000000..416c3d1 --- /dev/null +++ b/src/gui/text/qfontdatabase_s60.cpp @@ -0,0 +1,414 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <private/qapplication_p.h> +#include "qdir.h" +#include "qfont_p.h" +#include "qfontengine_s60_p.h" +#include "qabstractfileengine.h" +#include "qdesktopservices.h" +#include "qt_s60_p.h" +#include "qendian.h" +#include <private/qwindowsurface_s60_p.h> +#include <private/qcore_symbian_p.h> +#if defined(QT_NO_FREETYPE) +#include <OPENFONT.H> +#endif + +QT_BEGIN_NAMESPACE + +QFileInfoList alternativeFilePaths(const QString &path, const QStringList &nameFilters, + QDir::Filters filters = QDir::NoFilter, QDir::SortFlags sort = QDir::NoSort, + bool uniqueFileNames = true) +{ + QFileInfoList result; + + // Prepare a 'soft to hard' drive list: W:, X: ... A:, Z: + QStringList driveStrings; + foreach (const QFileInfo &drive, QDir::drives()) + driveStrings.append(drive.absolutePath()); + driveStrings.sort(); + const QString zDriveString("Z:/"); + driveStrings.removeAll(zDriveString); + driveStrings.prepend(zDriveString); + + QStringList uniqueFileNameList; + for (int i = driveStrings.count() - 1; i >= 0; --i) { + const QDir dirOnDrive(driveStrings.at(i) + path); + const QFileInfoList entriesOnDrive = dirOnDrive.entryInfoList(nameFilters, filters, sort); + if (uniqueFileNames) { + foreach(const QFileInfo &entry, entriesOnDrive) { + if (!uniqueFileNameList.contains(entry.fileName())) { + uniqueFileNameList.append(entry.fileName()); + result.append(entry); + } + } + } else { + result.append(entriesOnDrive); + } + } + return result; +} + +#if defined(QT_NO_FREETYPE) +class QFontDatabaseS60StoreImplementation : public QFontDatabaseS60Store +{ +public: + QFontDatabaseS60StoreImplementation(); + ~QFontDatabaseS60StoreImplementation(); + + const QFontEngineS60Extensions *extension(const QString &typeface) const; + +private: + RHeap* m_heap; + CFontStore *m_store; + COpenFontRasterizer *m_rasterizer; + mutable QHash<QString, const QFontEngineS60Extensions *> m_extensions; +}; + +QFontDatabaseS60StoreImplementation::QFontDatabaseS60StoreImplementation() +{ + m_heap = User::ChunkHeap(NULL, 0x1000, 0x100000); + m_store = CFontStore::NewL(m_heap); + m_rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E)); + m_store->InstallRasterizerL(m_rasterizer); + + QStringList filters; + filters.append(QString::fromLatin1("*.ttf")); + filters.append(QString::fromLatin1("*.ccc")); + const QFileInfoList fontFiles = alternativeFilePaths(QString::fromLatin1("resource\\Fonts"), filters); + foreach (const QFileInfo &fontFileInfo, fontFiles) { + const QString fontFile = QDir::toNativeSeparators(fontFileInfo.absoluteFilePath()); + m_store->AddFileL(qt_QString2TPtrC(fontFile)); + } +} +QFontDatabaseS60StoreImplementation::~QFontDatabaseS60StoreImplementation() +{ + qDeleteAll(m_extensions); + delete m_rasterizer; + delete m_store; + m_heap->Close(); +} + +const QFontEngineS60Extensions *QFontDatabaseS60StoreImplementation::extension(const QString &typeface) const +{ + if (!m_extensions.contains(typeface)) { + CFont* font = NULL; + TFontSpec spec(qt_QString2TPtrC(typeface), 1); + spec.iHeight = 1; + const TInt err = m_store->GetNearestFontToDesignHeightInPixels(font, spec); + Q_ASSERT(err == KErrNone && font); + CBitmapFont *bitmapFont = static_cast<CBitmapFont*>(font); + m_extensions.insert(typeface, new QFontEngineS60Extensions(bitmapFont->OpenFont())); + } + return m_extensions.value(typeface); +} +#else +class QFontEngineFTS60 : public QFontEngineFT +{ +public: + QFontEngineFTS60(const QFontDef &fd); +}; + +QFontEngineFTS60::QFontEngineFTS60(const QFontDef &fd) + : QFontEngineFT(fd) +{ + default_hint_style = HintFull; +} +#endif // defined(QT_NO_FREETYPE) + +/* + QFontEngineS60::pixelsToPoints, QFontEngineS60::pointsToPixels, QFontEngineMultiS60::QFontEngineMultiS60 + and QFontEngineMultiS60::QFontEngineMultiS60 should be in qfontengine_s60.cpp. But since also the + Freetype based font rendering need them, they are here. +*/ +qreal QFontEngineS60::pixelsToPoints(qreal pixels, Qt::Orientation orientation) +{ + return (orientation == Qt::Horizontal? + S60->screenDevice()->HorizontalPixelsToTwips(pixels) + :S60->screenDevice()->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint; +} + +qreal QFontEngineS60::pointsToPixels(qreal points, Qt::Orientation orientation) +{ + const int twips = points * KTwipsPerPoint; + return orientation == Qt::Horizontal? + S60->screenDevice()->HorizontalTwipsToPixels(twips) + :S60->screenDevice()->VerticalTwipsToPixels(twips); +} + +QFontEngineMultiS60::QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies) + : QFontEngineMulti(fallbackFamilies.size() + 1) + , m_script(script) + , m_fallbackFamilies(fallbackFamilies) +{ + engines[0] = first; + first->ref.ref(); + fontDef = engines[0]->fontDef; +} + +void QFontEngineMultiS60::loadEngine(int at) +{ + Q_ASSERT(at < engines.size()); + Q_ASSERT(engines.at(at) == 0); + + QFontDef request = fontDef; + request.styleStrategy |= QFont::NoFontMerging; + request.family = m_fallbackFamilies.at(at-1); + engines[at] = QFontDatabase::findFont(m_script, + /*fontprivate*/0, + request); + Q_ASSERT(engines[at]); +} + +static void initializeDb() +{ + QFontDatabasePrivate *db = privateDb(); + if(!db || db->count) + return; + +#if defined(QT_NO_FREETYPE) + if (!db->s60Store) + db->s60Store = new QFontDatabaseS60StoreImplementation; + + QS60WindowSurface::unlockBitmapHeap(); + const int numTypeFaces = QS60Data::screenDevice()->NumTypefaces(); + const QFontDatabaseS60StoreImplementation *store = dynamic_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store); + Q_ASSERT(store); + for (int i = 0; i < numTypeFaces; i++) { + TTypefaceSupport typefaceSupport; + QS60Data::screenDevice()->TypefaceSupport(typefaceSupport, i); + CFont *font; // We have to get a font instance in order to know all the details + TFontSpec fontSpec(typefaceSupport.iTypeface.iName, 11); + QS60Data::screenDevice()->GetNearestFontInPixels(font, fontSpec); + if (font->TypeUid() == KCFbsFontUid) { + TOpenFontFaceAttrib faceAttrib; + const CFbsFont *cfbsFont = dynamic_cast<const CFbsFont *>(font); + Q_ASSERT(cfbsFont); + cfbsFont->GetFaceAttrib(faceAttrib); + + QtFontStyle::Key styleKey; + styleKey.style = faceAttrib.IsItalic()?QFont::StyleItalic:QFont::StyleNormal; + styleKey.weight = faceAttrib.IsBold()?QFont::Bold:QFont::Normal; + + QString familyName((const QChar *)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length()); + QtFontFamily *family = db->family(familyName, true); + family->fixedPitch = faceAttrib.IsMonoWidth(); + QtFontFoundry *foundry = family->foundry(QString(), true); + QtFontStyle *style = foundry->style(styleKey, true); + style->smoothScalable = typefaceSupport.iIsScalable; + style->pixelSize(0, true); + + const QFontEngineS60Extensions *extension = store->extension(familyName); + const QByteArray os2Table = extension->getSfntTable(MAKE_TAG('O', 'S', '/', '2')); + const unsigned char* data = reinterpret_cast<const unsigned char*>(os2Table.constData()); + const unsigned char* ulUnicodeRange = data + 42; + quint32 unicodeRange[4] = { + qFromBigEndian<quint32>(ulUnicodeRange), + qFromBigEndian<quint32>(ulUnicodeRange + 4), + qFromBigEndian<quint32>(ulUnicodeRange + 8), + qFromBigEndian<quint32>(ulUnicodeRange + 12) + }; + const unsigned char* ulCodePageRange = data + 78; + quint32 codePageRange[2] = { + qFromBigEndian<quint32>(ulCodePageRange), + qFromBigEndian<quint32>(ulCodePageRange + 4) + }; + const QList<QFontDatabase::WritingSystem> writingSystems = + determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange); + foreach (const QFontDatabase::WritingSystem system, writingSystems) + family->writingSystems[system] = QtFontFamily::Supported; + } + QS60Data::screenDevice()->ReleaseFont(font); + } + QS60WindowSurface::lockBitmapHeap(); +#else // defined(QT_NO_FREETYPE) + QDir dir(QDesktopServices::storageLocation(QDesktopServices::FontsLocation)); + dir.setNameFilters(QStringList() << QLatin1String("*.ttf") + << QLatin1String("*.ttc") << QLatin1String("*.pfa") + << QLatin1String("*.pfb")); + for (int i = 0; i < int(dir.count()); ++i) { + const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i])); + db->addTTFile(file); + } +#endif // defined(QT_NO_FREETYPE) +} + +static inline void load(const QString &family = QString(), int script = -1) +{ + Q_UNUSED(family) + Q_UNUSED(script) + initializeDb(); +} + +static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) +{ + Q_UNUSED(fnt); +} + +bool QFontDatabase::supportsThreadedFontRendering() +{ + return false; +} + +static +QFontDef cleanedFontDef(const QFontDef &req) +{ + QFontDef result = req; + if (result.pixelSize <= 0) { + result.pixelSize = QFontEngineS60::pointsToPixels(qMax(qreal(1.0), result.pointSize)); + result.pointSize = 0; + } + return result; +} + +QFontEngine *QFontDatabase::findFont(int script, const QFontPrivate *, const QFontDef &req) +{ + const QFontCache::Key key(cleanedFontDef(req), script); + + if (!privateDb()->count) + initializeDb(); + + QFontEngine *fe = QFontCache::instance()->findEngine(key); + if (!fe) { + // Making sure that fe->fontDef.family will be an existing font. + initializeDb(); + QFontDatabasePrivate *db = privateDb(); + QtFontDesc desc; + QList<int> blacklistedFamilies; + match(script, req, req.family, QString(), -1, &desc, blacklistedFamilies); + if (!desc.family) // falling back to application font + desc.family = db->family(QApplication::font().defaultFamily()); + Q_ASSERT(desc.family); + + // Making sure that desc.family supports the requested script + QtFontDesc mappedDesc; + bool supportsScript = false; + do { + match(script, req, QString(), QString(), -1, &mappedDesc, blacklistedFamilies); + if (mappedDesc.family == desc.family) { + supportsScript = true; + break; + } + blacklistedFamilies.append(mappedDesc.familyIndex); + } while (mappedDesc.family); + if (!supportsScript) { + blacklistedFamilies.clear(); + match(script, req, QString(), QString(), -1, &mappedDesc, blacklistedFamilies); + if (mappedDesc.family) + desc = mappedDesc; + } + + const QString fontFamily = desc.family->name; + QFontDef request = req; + request.family = fontFamily; +#if defined(QT_NO_FREETYPE) + const QFontDatabaseS60StoreImplementation *store = dynamic_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store); + Q_ASSERT(store); + const QFontEngineS60Extensions *extension = store->extension(fontFamily); + fe = new QFontEngineS60(request, extension); +#else + QFontEngine::FaceId faceId; + const QtFontFamily * const reqQtFontFamily = db->family(fontFamily); + faceId.filename = reqQtFontFamily->fontFilename; + faceId.index = reqQtFontFamily->fontFileIndex; + + QFontEngineFTS60 *fte = new QFontEngineFTS60(cleanedFontDef(request)); + if (fte->init(faceId, true, QFontEngineFT::Format_A8)) + fe = fte; + else + delete fte; +#endif + + Q_ASSERT(fe); + if (script == QUnicodeTables::Common + && !(req.styleStrategy & QFont::NoFontMerging) + && !fe->symbol) { + + QStringList commonFonts; + for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) { + if (scriptForWritingSystem[ws] != script) + continue; + for (int i = 0; i < db->count; ++i) { + if (db->families[i]->writingSystems[ws] & QtFontFamily::Supported) + commonFonts.append(db->families[i]->name); + } + } + + // Hack: Prioritize .ccc fonts + const QString niceEastAsianFont(QLatin1String("Sans MT 936_S60")); + if (commonFonts.removeAll(niceEastAsianFont) > 0) + commonFonts.prepend(niceEastAsianFont); + + fe = new QFontEngineMultiS60(fe, script, commonFonts); + } + } + fe->ref.ref(); + QFontCache::instance()->insertEngine(key, fe); + return fe; +} + +void QFontDatabase::load(const QFontPrivate *d, int script) +{ + QFontEngine *fe = 0; + QFontDef req = d->request; + + if (!d->engineData) { + const QFontCache::Key key(cleanedFontDef(req), script); + getEngineData(d, key); + } + + // the cached engineData could have already loaded the engine we want + if (d->engineData->engines[script]) + fe = d->engineData->engines[script]; + + if (!fe) { + if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) { + fe = new QTestFontEngine(req.pixelSize); + fe->fontDef = req; + } else { + fe = findFont(script, d, req); + } + d->engineData->engines[script] = fe; + } +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 79e341a..f09e726 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -185,18 +185,20 @@ QFontEngine::QFontEngine() QFontEngine::~QFontEngine() { - for (GlyphPointerHash::iterator it = m_glyphPointerHash.begin(), end = m_glyphPointerHash.end(); - it != end; ++it) { - for (QList<QFontEngineGlyphCache*>::iterator it2 = it.value().begin(), end2 = it.value().end(); - it2 != end2; ++it2) - delete *it2; + for (GlyphPointerHash::const_iterator it = m_glyphPointerHash.constBegin(), + end = m_glyphPointerHash.constEnd(); it != end; ++it) { + for (QList<QFontEngineGlyphCache*>::const_iterator it2 = it.value().constBegin(), + end2 = it.value().constEnd(); it2 != end2; ++it2) { + delete *it2; + } } m_glyphPointerHash.clear(); - for (GlyphIntHash::iterator it = m_glyphIntHash.begin(), end = m_glyphIntHash.end(); - it != end; ++it) { - for (QList<QFontEngineGlyphCache*>::iterator it2 = it.value().begin(), end2 = it.value().end(); - it2 != end2; ++it2) - delete *it2; + for (GlyphIntHash::const_iterator it = m_glyphIntHash.constBegin(), + end = m_glyphIntHash.constEnd(); it != end; ++it) { + for (QList<QFontEngineGlyphCache*>::const_iterator it2 = it.value().constBegin(), + end2 = it.value().constEnd(); it2 != end2; ++it2) { + delete *it2; + } } m_glyphIntHash.clear(); qHBFreeFace(hbFace); @@ -813,7 +815,7 @@ QFontEngineGlyphCache *QFontEngine::glyphCache(QFontEngineGlyphCache::Type key, return 0; } -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_S60) static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs) { uint left_right = (left << 16) + right; @@ -1104,6 +1106,18 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) return 0; } +Q_GLOBAL_STATIC_WITH_INITIALIZER(QVector<QRgb>, qt_grayPalette, { + x->resize(256); + QRgb *it = x->data(); + for (int i = 0; i < x->size(); ++i, ++it) + *it = 0xff000000 | i | (i<<8) | (i<<16); +}); + +const QVector<QRgb> &QFontEngine::grayPalette() +{ + return *qt_grayPalette(); +} + // ------------------------------------------------------------------ // The box font engine // ------------------------------------------------------------------ diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index a93c391..ef0cdca 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -191,6 +191,9 @@ HB_Error QFreetypeFace::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 p /* * One font file can contain more than one font (bold/italic for example) * find the right one and return it. + * + * Returns the freetype face or 0 in case of an empty file or any other problems + * (like not being able to open the file) */ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id) { @@ -203,7 +206,7 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id) QFreetypeFace *freetype = freetypeData->faces.value(face_id, 0); if (!freetype) { - freetype = new QFreetypeFace; + QScopedPointer<QFreetypeFace> newFreetype(new QFreetypeFace); FT_Face face; QFile file(QString::fromUtf8(face_id.filename)); if (face_id.filename.startsWith(":qmemoryfonts/")) { @@ -212,84 +215,82 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id) QByteArray idx = face_id.filename; idx.remove(0, 14); // remove ':qmemoryfonts/' bool ok = false; - freetype->fontData = qt_fontdata_from_index(idx.toInt(&ok)); + newFreetype->fontData = qt_fontdata_from_index(idx.toInt(&ok)); if (!ok) - freetype->fontData = QByteArray(); + newFreetype->fontData = QByteArray(); } else if (!(file.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) { if (!file.open(QIODevice::ReadOnly)) { - delete freetype; return 0; } - freetype->fontData = file.readAll(); + newFreetype->fontData = file.readAll(); } - if (!freetype->fontData.isEmpty()) { - if (FT_New_Memory_Face(freetypeData->library, (const FT_Byte *)freetype->fontData.constData(), freetype->fontData.size(), face_id.index, &face)) { - delete freetype; + if (!newFreetype->fontData.isEmpty()) { + if (FT_New_Memory_Face(freetypeData->library, (const FT_Byte *)newFreetype->fontData.constData(), newFreetype->fontData.size(), face_id.index, &face)) { return 0; } } else if (FT_New_Face(freetypeData->library, face_id.filename, face_id.index, &face)) { - delete freetype; return 0; } - freetype->face = face; - - freetype->hbFace = qHBNewFace(face, hb_getSFntTable); - freetype->ref = 0; - freetype->xsize = 0; - freetype->ysize = 0; - freetype->matrix.xx = 0x10000; - freetype->matrix.yy = 0x10000; - freetype->matrix.xy = 0; - freetype->matrix.yx = 0; - freetype->unicode_map = 0; - freetype->symbol_map = 0; + newFreetype->face = face; + + newFreetype->hbFace = qHBNewFace(face, hb_getSFntTable); + newFreetype->ref = 0; + newFreetype->xsize = 0; + newFreetype->ysize = 0; + newFreetype->matrix.xx = 0x10000; + newFreetype->matrix.yy = 0x10000; + newFreetype->matrix.xy = 0; + newFreetype->matrix.yx = 0; + newFreetype->unicode_map = 0; + newFreetype->symbol_map = 0; #ifndef QT_NO_FONTCONFIG - freetype->charset = 0; + newFreetype->charset = 0; #endif - memset(freetype->cmapCache, 0, sizeof(freetype->cmapCache)); + memset(newFreetype->cmapCache, 0, sizeof(newFreetype->cmapCache)); - for (int i = 0; i < freetype->face->num_charmaps; ++i) { - FT_CharMap cm = freetype->face->charmaps[i]; + for (int i = 0; i < newFreetype->face->num_charmaps; ++i) { + FT_CharMap cm = newFreetype->face->charmaps[i]; switch(cm->encoding) { case FT_ENCODING_UNICODE: - freetype->unicode_map = cm; + newFreetype->unicode_map = cm; break; case FT_ENCODING_APPLE_ROMAN: case FT_ENCODING_ADOBE_LATIN_1: - if (!freetype->unicode_map || freetype->unicode_map->encoding != FT_ENCODING_UNICODE) - freetype->unicode_map = cm; + if (!newFreetype->unicode_map || newFreetype->unicode_map->encoding != FT_ENCODING_UNICODE) + newFreetype->unicode_map = cm; break; case FT_ENCODING_ADOBE_CUSTOM: case FT_ENCODING_MS_SYMBOL: - if (!freetype->symbol_map) - freetype->symbol_map = cm; + if (!newFreetype->symbol_map) + newFreetype->symbol_map = cm; break; default: break; } } - if (!FT_IS_SCALABLE(freetype->face) && freetype->face->num_fixed_sizes == 1) - FT_Set_Char_Size (face, X_SIZE(freetype->face, 0), Y_SIZE(freetype->face, 0), 0, 0); + if (!FT_IS_SCALABLE(newFreetype->face) && newFreetype->face->num_fixed_sizes == 1) + FT_Set_Char_Size (face, X_SIZE(newFreetype->face, 0), Y_SIZE(newFreetype->face, 0), 0, 0); # if 0 FcChar8 *name; FcPatternGetString(pattern, FC_FAMILY, 0, &name); qDebug("%s: using maps: default: %x unicode: %x, symbol: %x", name, - freetype->face->charmap ? freetype->face->charmap->encoding : 0, - freetype->unicode_map ? freetype->unicode_map->encoding : 0, - freetype->symbol_map ? freetype->symbol_map->encoding : 0); + newFreetype->face->charmap ? newFreetype->face->charmap->encoding : 0, + newFreetype->unicode_map ? newFreetype->unicode_map->encoding : 0, + newFreetype->symbol_map ? newFreetype->symbol_map->encoding : 0); for (int i = 0; i < 256; i += 8) qDebug(" %x: %d %d %d %d %d %d %d %d", i, - FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i), - FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i), - FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i), - FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i)); + FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i), + FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i), + FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i), + FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i)); #endif - FT_Set_Charmap(freetype->face, freetype->unicode_map); - freetypeData->faces.insert(face_id, freetype); + FT_Set_Charmap(newFreetype->face, newFreetype->unicode_map); + freetypeData->faces.insert(face_id, newFreetype.data()); + freetype = newFreetype.take(); } freetype->ref.ref(); return freetype; @@ -606,6 +607,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd) kerning_pairs_loaded = false; transform = false; antialias = true; + freetype = 0; default_load_flags = 0; default_hint_style = HintNone; subpixelType = Subpixel_None; diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 284904b..b67895b 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -119,6 +119,7 @@ struct QFreetypeFace static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path, bool = false); private: + friend class QScopedPointer<QFreetypeFace>; QFreetypeFace() : _lock(QMutex::Recursive) {} ~QFreetypeFace() {} QAtomicInt ref; @@ -255,7 +256,7 @@ public: QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix); bool loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, GlyphFormat format = Format_Render); -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_S60) virtual void draw(QPaintEngine * /*p*/, qreal /*x*/, qreal /*y*/, const QTextItemInt & /*si*/) {} #endif diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 3ef9d5f..fc5ff20 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -112,6 +112,10 @@ public: QPF1, QPF2, Proxy, + + // S60 types + S60FontEngine, // Cannot be simply called "S60". Reason is qt_s60Data.h + TestFontEngine = 0x1000 }; @@ -163,7 +167,7 @@ public: virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const {} virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const; -#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) +#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_WS_S60) virtual void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si) = 0; #endif virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, @@ -230,7 +234,7 @@ public: bool symbol; mutable HB_FontRec hbFont; mutable HB_Face hbFace; -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_S60) struct KernPair { uint left_right; QFixed adjust; @@ -246,6 +250,9 @@ public: int glyphFormat; +protected: + static const QVector<QRgb> &grayPalette(); + private: /// remove old entries from the glyph cache. Helper method for the setGlyphCache ones. void expireGlyphCache(); @@ -321,7 +328,7 @@ public: virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; -#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) +#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_WS_S60) void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si); #endif virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags); @@ -618,4 +625,8 @@ QT_END_NAMESPACE # include "private/qfontengine_win_p.h" #endif +#if defined(Q_WS_S60) && !defined(QT_NO_FREETYPE) +# include "private/qfontengine_ft_p.h" +#endif + #endif // QFONTENGINE_P_H diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp index 8222b7f..97d3847 100644 --- a/src/gui/text/qfontengine_qpf.cpp +++ b/src/gui/text/qfontengine_qpf.cpp @@ -325,21 +325,21 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng fileName.replace(QLatin1Char(' '), QLatin1Char('_')); fileName.prepend(qws_fontCacheDir()); - const QByteArray encodedName = QFile::encodeName(fileName); - if (::access(encodedName, F_OK) == 0) { + encodedFileName = QFile::encodeName(fileName); + if (::access(encodedFileName, F_OK) == 0) { #if defined(DEBUG_FONTENGINE) qDebug() << "found existing qpf:" << fileName; #endif - if (::access(encodedName, W_OK | R_OK) == 0) - fd = ::open(encodedName, O_RDWR, 0); - else if (::access(encodedName, R_OK) == 0) - fd = ::open(encodedName, O_RDONLY, 0); + if (::access(encodedFileName, W_OK | R_OK) == 0) + fd = ::open(encodedFileName, O_RDWR, 0); + else if (::access(encodedFileName, R_OK) == 0) + fd = ::open(encodedFileName, O_RDONLY, 0); } else { #if defined(DEBUG_FONTENGINE) qDebug() << "creating qpf on the fly:" << fileName; #endif if (::access(QFile::encodeName(qws_fontCacheDir()), W_OK) == 0) { - fd = ::open(encodedName, O_RDWR | O_EXCL | O_CREAT, 0644); + fd = ::open(encodedFileName, O_RDWR | O_EXCL | O_CREAT, 0644); QBuffer buffer; buffer.open(QIODevice::ReadWrite); @@ -474,15 +474,21 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng #endif #if defined(Q_WS_QWS) if (isValid() && renderingFontEngine) - qt_fbdpy->sendFontCommand(QWSFontCommand::StartedUsingFont, QFile::encodeName(fileName)); + qt_fbdpy->sendFontCommand(QWSFontCommand::StartedUsingFont, encodedFileName); #endif } QFontEngineQPF::~QFontEngineQPF() { #if defined(Q_WS_QWS) - if (isValid() && renderingFontEngine) - qt_fbdpy->sendFontCommand(QWSFontCommand::StoppedUsingFont, QFile::encodeName(fileName)); + if (isValid() && renderingFontEngine) { + QT_TRY { + qt_fbdpy->sendFontCommand(QWSFontCommand::StoppedUsingFont, encodedFileName); + } QT_CATCH(...) { + qDebug("QFontEngineQPF::~QFontEngineQPF: Out of memory"); + // ignore. + } + } #endif delete renderingFontEngine; if (fontData) @@ -1128,6 +1134,11 @@ void QPFGenerator::writeTaggedQFixed(QFontEngineQPF::HeaderTag tag, QFixed value #endif // QT_NO_QWS_QPF2 +/* + Creates a new multi qws engine. + + This function takes ownership of the QFontEngine, increasing it's refcount. +*/ QFontEngineMultiQWS::QFontEngineMultiQWS(QFontEngine *fe, int _script, const QStringList &fallbacks) : QFontEngineMulti(fallbacks.size() + 1), fallbackFamilies(fallbacks), script(_script) diff --git a/src/gui/text/qfontengine_qpf_p.h b/src/gui/text/qfontengine_qpf_p.h index a9b87ff..629f5c6 100644 --- a/src/gui/text/qfontengine_qpf_p.h +++ b/src/gui/text/qfontengine_qpf_p.h @@ -243,6 +243,7 @@ private: quint32 glyphDataOffset; quint32 glyphDataSize; QString fileName; + QByteArray encodedFileName; bool readOnly; QFreetypeFace *freetype; diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp new file mode 100644 index 0000000..2e1abb2 --- /dev/null +++ b/src/gui/text/qfontengine_s60.cpp @@ -0,0 +1,326 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfontengine_s60_p.h" +#include "qtextengine_p.h" +#include "qglobal.h" +#include <private/qapplication_p.h> +#include <private/qwindowsurface_s60_p.h> +#include "qimage.h" +#include "qt_s60_p.h" + +#include <e32base.h> +#include <e32std.h> +#include <EIKENV.H> +#include <GDI.H> + +QT_BEGIN_NAMESPACE + +static const int maxFontSizeInPixels = 60; + +QFontEngineS60Extensions::QFontEngineS60Extensions(COpenFont *font) + : m_font(font) + , m_cmap(0) + , m_symbolCMap(false) +{ + TAny *shapingExtension = NULL; + m_font->ExtendedInterface(KUidOpenFontShapingExtension, shapingExtension); + m_shapingExtension = static_cast<MOpenFontShapingExtension*>(shapingExtension); + TAny *trueTypeExtension = NULL; + m_font->ExtendedInterface(KUidOpenFontTrueTypeExtension, trueTypeExtension); + m_trueTypeExtension = static_cast<MOpenFontTrueTypeExtension*>(trueTypeExtension); + Q_ASSERT(m_shapingExtension && m_trueTypeExtension); +} + +QByteArray QFontEngineS60Extensions::getSfntTable(uint tag) const +{ + Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag)); + TInt error = KErrNone; + TInt tableByteLength = 0; + TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength); + QByteArray result(static_cast<const char*>(table), tableByteLength); + m_trueTypeExtension->ReleaseTrueTypeTable(table); + return result; +} + +const unsigned char *QFontEngineS60Extensions::cmap() const +{ + if (!m_cmap) { + m_cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); + int size = 0; + m_cmap = QFontEngineS60::getCMap(reinterpret_cast<const uchar *>(m_cmapTable.constData()), m_cmapTable.size(), &m_symbolCMap, &size); + } + return m_cmap; +} + +QPainterPath QFontEngineS60Extensions::glyphOutline(glyph_t glyph) const +{ + QPainterPath result; + QPolygonF polygon; + TInt glyphIndex = glyph; + TInt pointNumber = 0; + TInt x, y; + while (m_shapingExtension->GlyphPointInFontUnits(glyphIndex, pointNumber++, x, y)) { + const QPointF point(qreal(x) / 0xffff, qreal(y) / 0xffff); + if (polygon.contains(point)) { + result.addPolygon(polygon); + result.closeSubpath(); + polygon.clear(); + } else { + polygon.append(point); + } + } + return result; +} + +// duplicated from qfontengine_xyz.cpp +static inline unsigned int getChar(const QChar *str, int &i, const int len) +{ + unsigned int uc = str[i].unicode(); + if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { + uint low = str[i+1].unicode(); + if (low >= 0xdc00 && low < 0xe000) { + uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; + ++i; + } + } + return uc; +} + +QFontEngineS60::QFontEngineS60(const QFontDef &request, const QFontEngineS60Extensions *extensions) + : m_extensions(extensions) +{ + QFontEngine::fontDef = request; + m_fontSizeInPixels = (request.pixelSize >= 0)? + request.pixelSize:pointsToPixels(request.pointSize); + QS60WindowSurface::unlockBitmapHeap(); + m_textRenderBitmap = new (ELeave) CFbsBitmap(); + const TSize bitmapSize(1, 1); // It is just a dummy bitmap that I need to keep the font alive (or maybe not) + User::LeaveIfError(m_textRenderBitmap->Create(bitmapSize, EGray256)); + m_textRenderBitmapDevice = CFbsBitmapDevice::NewL(m_textRenderBitmap); + User::LeaveIfError(m_textRenderBitmapDevice->CreateContext(m_textRenderBitmapGc)); + cache_cost = sizeof(QFontEngineS60) + bitmapSize.iHeight * bitmapSize.iWidth * 4; + + TFontSpec fontSpec(qt_QString2TPtrC(request.family), m_fontSizeInPixels); + fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap); + fontSpec.iFontStyle.SetPosture(request.style == QFont::StyleNormal?EPostureUpright:EPostureItalic); + fontSpec.iFontStyle.SetStrokeWeight(request.weight > QFont::Normal?EStrokeWeightBold:EStrokeWeightNormal); + const TInt errorCode = m_textRenderBitmapDevice->GetNearestFontInPixels(m_font, fontSpec); + Q_ASSERT(errorCode == 0); + m_textRenderBitmapGc->UseFont(m_font); + QS60WindowSurface::lockBitmapHeap(); +} + +QFontEngineS60::~QFontEngineS60() +{ + QS60WindowSurface::unlockBitmapHeap(); + m_textRenderBitmapGc->DiscardFont(); + delete m_textRenderBitmapGc; + m_textRenderBitmapGc = NULL; + m_textRenderBitmapDevice->ReleaseFont(m_font); + delete m_textRenderBitmapDevice; + m_textRenderBitmapDevice = NULL; + delete m_textRenderBitmap; + m_textRenderBitmap = NULL; + QS60WindowSurface::lockBitmapHeap(); +} + +bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const +{ + if (*nglyphs < len) { + *nglyphs = len; + return false; + } + + HB_Glyph *g = glyphs->glyphs; + const unsigned char* cmap = m_extensions->cmap(); + for (int i = 0; i < len; ++i) { + const unsigned int uc = getChar(characters, i, len); + *g++ = QFontEngine::getTrueTypeGlyphIndex(cmap, uc); + } + + glyphs->numGlyphs = g - glyphs->glyphs; + *nglyphs = glyphs->numGlyphs; + + if (flags & QTextEngine::GlyphIndicesOnly) + return true; + + recalcAdvances(glyphs, flags); + return true; +} + +void QFontEngineS60::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const +{ + Q_UNUSED(flags); + for (int i = 0; i < glyphs->numGlyphs; i++) { + const glyph_metrics_t bbox = boundingBox_const(glyphs->glyphs[i]); + glyphs->advances_x[i] = glyphs->offsets[i].x = bbox.xoff; + glyphs->advances_y[i] = glyphs->offsets[i].y = bbox.yoff; + } +} + +QImage QFontEngineS60::alphaMapForGlyph(glyph_t glyph) +{ + TOpenFontCharMetrics metrics; + const TUint8 *glyphBitmapBytes; + TSize glyphBitmapSize; + getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize); + QImage result(glyphBitmapBytes, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight, glyphBitmapSize.iWidth, QImage::Format_Indexed8); + result.setColorTable(grayPalette()); + + // The above setColorTable() call detached the image data anyway, so why not shape tha data a bit, while we can. + // CFont::GetCharacterData() returns 8-bit data that obviously was 4-bit data before, and converted to 8-bit incorrectly. + // The data values are 0x00, 0x10 ... 0xe0, 0xf0. So, a real opaque 0xff is never reached, which we get punished + // for every time we want to blit this glyph in the raster paint engine. + // "Fix" is to convert all 0xf0 to 0xff. Is fine, quality wise, and I assume faster than correcting all values. + // Blitting is however, evidentially faster now. + const int bpl = result.bytesPerLine(); + for (int row = 0; row < result.height(); ++row) { + uchar *scanLine = result.scanLine(row); + for (int column = 0; column < bpl; ++column) { + if (*scanLine == 0xf0) + *scanLine = 0xff; + scanLine++; + } + } + + return result; +} + +glyph_metrics_t QFontEngineS60::boundingBox(const QGlyphLayout &glyphs) +{ + if (glyphs.numGlyphs == 0) + return glyph_metrics_t(); + + QFixed w = 0; + for (int i = 0; i < glyphs.numGlyphs; ++i) + w += glyphs.effectiveAdvance(i); + + return glyph_metrics_t(0, -ascent(), w, ascent()+descent()+1, w, 0); +} + +glyph_metrics_t QFontEngineS60::boundingBox_const(glyph_t glyph) const +{ + TOpenFontCharMetrics metrics; + const TUint8 *glyphBitmapBytes; + TSize glyphBitmapSize; + getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize); + TRect glyphBounds; + metrics.GetHorizBounds(glyphBounds); + const glyph_metrics_t result( + glyphBounds.iTl.iX, + glyphBounds.iTl.iY, + glyphBounds.Width(), + glyphBounds.Height(), + metrics.HorizAdvance(), + 0 + ); + return result; +} + +glyph_metrics_t QFontEngineS60::boundingBox(glyph_t glyph) +{ + return boundingBox_const(glyph); +} + +QFixed QFontEngineS60::ascent() const +{ + return m_font->FontMaxAscent(); +} + +QFixed QFontEngineS60::descent() const +{ + return m_font->FontMaxDescent(); +} + +QFixed QFontEngineS60::leading() const +{ + return 0; +} + +qreal QFontEngineS60::maxCharWidth() const +{ + return m_font->MaxCharWidthInPixels(); +} + +const char *QFontEngineS60::name() const +{ + return "QFontEngineS60"; +} + +bool QFontEngineS60::canRender(const QChar *string, int len) +{ + const unsigned char *cmap = m_extensions->cmap(); + for (int i = 0; i < len; ++i) { + const unsigned int uc = getChar(string, i, len); + if (QFontEngine::getTrueTypeGlyphIndex(cmap, uc) == 0) + return false; + } + return true; +} + +QByteArray QFontEngineS60::getSfntTable(uint tag) const +{ + return m_extensions->getSfntTable(tag); +} + +QFontEngine::Type QFontEngineS60::type() const +{ + return QFontEngine::S60FontEngine; +} + +void QFontEngineS60::getCharacterData(glyph_t glyph, TOpenFontCharMetrics& metrics, const TUint8*& bitmap, TSize& bitmapSize) const +{ + // Setting the most significant bit tells GetCharacterData + // that 'code' is a Glyph ID, rather than a UTF-16 value + const TUint specialCode = (TUint)glyph | 0x80000000; + + const CFont::TCharacterDataAvailability availability = + m_font->GetCharacterData(specialCode, metrics, bitmap, bitmapSize); + const glyph_t fallbackGlyph = '?'; + if (availability != CFont::EAllCharacterData) { + const CFont::TCharacterDataAvailability fallbackAvailability = + m_font->GetCharacterData(fallbackGlyph, metrics, bitmap, bitmapSize); + Q_ASSERT(fallbackAvailability == CFont::EAllCharacterData); + } +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h new file mode 100644 index 0000000..2998de8 --- /dev/null +++ b/src/gui/text/qfontengine_s60_p.h @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFONTENGINE_S60_P_H +#define QFONTENGINE_S60_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qconfig.h" +#include "qfontengine_p.h" +#include "qsize.h" +#include <OPENFONT.H> + +class CFbsBitmap; +class CFbsBitmapDevice; +class CFbsBitGc; +class CFont; + +QT_BEGIN_NAMESPACE + +// ..gives us access to truetype tables, UTF-16<->GlyphID mapping, and glyph outlines +class QFontEngineS60Extensions +{ +public: + QFontEngineS60Extensions(COpenFont *font); + + QByteArray getSfntTable(uint tag) const; + const unsigned char *cmap() const; + QPainterPath glyphOutline(glyph_t glyph) const; + +private: + COpenFont *m_font; + const MOpenFontShapingExtension *m_shapingExtension; + mutable MOpenFontTrueTypeExtension *m_trueTypeExtension; + mutable const unsigned char *m_cmap; + mutable bool m_symbolCMap; + mutable QByteArray m_cmapTable; +}; + +class QFontEngineS60 : public QFontEngine +{ +public: + QFontEngineS60(const QFontDef &fontDef, const QFontEngineS60Extensions *extensions); + ~QFontEngineS60(); + + bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; + void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const; + + QImage alphaMapForGlyph(glyph_t glyph); + + glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); + glyph_metrics_t boundingBox_const(glyph_t glyph) const; // Const correctnes quirk. + glyph_metrics_t boundingBox(glyph_t glyph); + + QFixed ascent() const; + QFixed descent() const; + QFixed leading() const; + qreal maxCharWidth() const; + qreal minLeftBearing() const { return 0; } + qreal minRightBearing() const { return 0; } + + QByteArray getSfntTable(uint tag) const; + + static qreal pixelsToPoints(qreal pixels, Qt::Orientation orientation = Qt::Horizontal); + static qreal pointsToPixels(qreal points, Qt::Orientation orientation = Qt::Horizontal); + + const char *name() const; + + bool canRender(const QChar *string, int len); + + Type type() const; + +private: + friend class QFontPrivate; + + QFixed glyphAdvance(HB_Glyph glyph) const; + void getCharacterData(glyph_t glyph, TOpenFontCharMetrics& metrics, const TUint8*& bitmap, TSize& bitmapSize) const; + + CFbsBitmap *m_textRenderBitmap; + CFbsBitmapDevice *m_textRenderBitmapDevice; + CFbsBitGc *m_textRenderBitmapGc; + CFont* m_font; + const QFontEngineS60Extensions *m_extensions; + qreal m_fontSizeInPixels; +}; + +class QFontEngineMultiS60 : public QFontEngineMulti +{ +public: + QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies); + void loadEngine(int at); + + int m_script; + QStringList m_fallbackFamilies; +}; + +QT_END_NAMESPACE + +#endif // QFONTENGINE_S60_P_H diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index 87da628..991fed7 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -164,7 +164,7 @@ extern int qt_defaultDpi(); metrics that are compatible with a certain paint device. */ QFontMetrics::QFontMetrics(const QFont &font) - : d(font.d) + : d(font.d.data()) { d->ref.ref(); } @@ -196,7 +196,7 @@ QFontMetrics::QFontMetrics(const QFont &font, QPaintDevice *paintdevice) d->dpi = dpi; d->screen = screen; } else { - d = font.d; + d = font.d.data(); d->ref.ref(); } @@ -1006,7 +1006,7 @@ QFontMetricsF &QFontMetricsF::operator=(const QFontMetrics &other) metrics that are compatible with a certain paint device. */ QFontMetricsF::QFontMetricsF(const QFont &font) - : d(font.d) + : d(font.d.data()) { d->ref.ref(); } @@ -1038,7 +1038,7 @@ QFontMetricsF::QFontMetricsF(const QFont &font, QPaintDevice *paintdevice) d->dpi = dpi; d->screen = screen; } else { - d = font.d; + d = font.d.data(); d->ref.ref(); } diff --git a/src/gui/text/qfragmentmap_p.h b/src/gui/text/qfragmentmap_p.h index 737a717..0f0e0ff 100644 --- a/src/gui/text/qfragmentmap_p.h +++ b/src/gui/text/qfragmentmap_p.h @@ -214,6 +214,7 @@ private: template <class Fragment> QFragmentMapData<Fragment>::QFragmentMapData() + : fragments(0) { init(); } @@ -222,6 +223,7 @@ template <class Fragment> void QFragmentMapData<Fragment>::init() { fragments = (Fragment *)malloc(64*fragmentSize); + Q_CHECK_PTR(fragments); head->tag = (((quint32)'p') << 24) | (((quint32)'m') << 16) | (((quint32)'a') << 8) | 'p'; //TAG('p', 'm', 'a', 'p'); head->root = 0; head->freelist = 1; @@ -247,7 +249,9 @@ uint QFragmentMapData<Fragment>::createFragment() // need to create some free space uint needed = qAllocMore((freePos+1)*fragmentSize, 0); Q_ASSERT(needed/fragmentSize > head->allocated); - fragments = (Fragment *)realloc(fragments, needed); + Fragment *newFragments = (Fragment *)realloc(fragments, needed); + Q_CHECK_PTR(newFragments); + fragments = newFragments; head->allocated = needed/fragmentSize; F(freePos).right = 0; } @@ -787,6 +791,8 @@ public: QFragmentMap() {} ~QFragmentMap() { + if (!data.fragments) + return; // in case of out-of-memory, we won't have fragments for (Iterator it = begin(); !it.atEnd(); ++it) it.value()->free(); } diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 8573fc9..a3b6085 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -1611,6 +1611,9 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF if (cursor.position() != oldCursorPos) emit q->cursorPositionChanged(); _q_updateCurrentCharFormatAndSelection(); + if (QInputContext *ic = inputContext()) { + ic->update(); + } } else { //emit q->visibilityRequest(QRectF(mousePos, QSizeF(1, 1))); if (cursor.position() != oldCursorPos) @@ -1813,13 +1816,18 @@ bool QTextControlPrivate::dropEvent(const QMimeData *mimeData, const QPointF &po void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) { + Q_Q(QTextControl); if (!(interactionFlags & Qt::TextEditable) || cursor.isNull()) { e->ignore(); return; } - cursor.beginEditBlock(); + bool isGettingInput = !e->commitString().isEmpty() || !e->preeditString().isEmpty() + || e->replacementLength() > 0; - cursor.removeSelectedText(); + if (isGettingInput) { + cursor.beginEditBlock(); + cursor.removeSelectedText(); + } // insert commit string if (!e->commitString().isEmpty() || e->replacementLength()) { @@ -1829,6 +1837,18 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) c.insertText(e->commitString()); } + for (int i = 0; i < e->attributes().size(); ++i) { + const QInputMethodEvent::Attribute &a = e->attributes().at(i); + if (a.type == QInputMethodEvent::Selection) { + QTextCursor oldCursor = cursor; + int blockStart = a.start + cursor.block().position(); + cursor.setPosition(blockStart, QTextCursor::MoveAnchor); + cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor); + q->ensureCursorVisible(); + repaintOldAndNewSelection(oldCursor); + } + } + QTextBlock block = cursor.block(); QTextLayout *layout = block.layout(); layout->setPreeditArea(cursor.position() - block.position(), e->preeditString()); @@ -1852,7 +1872,9 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) } } layout->setAdditionalFormats(overrides); - cursor.endEditBlock(); + + if (isGettingInput) + cursor.endEditBlock(); } QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const @@ -1865,11 +1887,15 @@ QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const case Qt::ImFont: return QVariant(d->cursor.charFormat().font()); case Qt::ImCursorPosition: - return QVariant(d->cursor.selectionEnd() - block.position()); + return QVariant(d->cursor.position() - block.position()); case Qt::ImSurroundingText: return QVariant(block.text()); case Qt::ImCurrentSelection: return QVariant(d->cursor.selectedText()); + case Qt::ImMaximumTextLength: + return QVariant(); // No limit. + case Qt::ImAnchorPosition: + return QVariant(qBound(0, d->cursor.anchor() - block.position(), block.length())); default: return QVariant(); } diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index a28c655..3b102c3 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2069,10 +2069,12 @@ void QTextEngine::LayoutData::reallocate(int totalGlyphs) int newAllocated = space_charAttributes + space_glyphs + space_logClusters; Q_ASSERT(newAllocated >= allocated); - void **old_mem = memory; - memory = (void **)::realloc(memory_on_stack ? 0 : old_mem, newAllocated*sizeof(void *)); - if (memory_on_stack && memory) - memcpy(memory, old_mem, allocated*sizeof(void *)); + void **newMem = memory; + newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *)); + Q_CHECK_PTR(newMem); + if (memory_on_stack && newMem) + memcpy(newMem, memory, allocated*sizeof(void *)); + memory = newMem; memory_on_stack = false; void **m = memory; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index fa624ef..6c67a68 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -367,7 +367,7 @@ QTextLayout::QTextLayout(const QString& text, const QFont &font, QPaintDevice *p QFont f(font); if (paintdevice) f = QFont(font, paintdevice); - d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f.d); + d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f.d.data()); } /*! diff --git a/src/gui/text/qtextoption.cpp b/src/gui/text/qtextoption.cpp index e1b9844..0f24d9b 100644 --- a/src/gui/text/qtextoption.cpp +++ b/src/gui/text/qtextoption.cpp @@ -117,7 +117,13 @@ QTextOption &QTextOption::operator=(const QTextOption &o) { if (this == &o) return *this; - delete d; d = 0; + + QTextOptionPrivate* dNew = 0; + if (o.d) + dNew = new QTextOptionPrivate(*o.d); + delete d; + d = dNew; + align = o.align; wordWrap = o.wordWrap; design = o.design; @@ -125,8 +131,6 @@ QTextOption &QTextOption::operator=(const QTextOption &o) unused = o.unused; f = o.f; tab = o.tab; - if (o.d) - d = new QTextOptionPrivate(*o.d); return *this; } diff --git a/src/gui/text/qtexttable.cpp b/src/gui/text/qtexttable.cpp index 48708c9..edba2c4 100644 --- a/src/gui/text/qtexttable.cpp +++ b/src/gui/text/qtexttable.cpp @@ -432,6 +432,13 @@ void QTextTablePrivate::fragmentRemoved(const QChar &type, uint fragment) QTextFramePrivate::fragmentRemoved(type, fragment); } +/*! + /fn void QTextTablePrivate::update() const + + This function is usually called when the table is "dirty". + It seems to update all kind of table information. + +*/ void QTextTablePrivate::update() const { Q_Q(const QTextTable); @@ -439,7 +446,9 @@ void QTextTablePrivate::update() const nRows = (cells.size() + nCols-1)/nCols; // qDebug(">>>> QTextTablePrivate::update, nRows=%d, nCols=%d", nRows, nCols); - grid = (int *)realloc(grid, nRows*nCols*sizeof(int)); + int* newGrid = (int *)realloc(grid, nRows*nCols*sizeof(int)); + Q_CHECK_PTR(newGrid); + grid = newGrid; memset(grid, 0, nRows*nCols*sizeof(int)); QTextDocumentPrivate *p = pieceTable; @@ -463,7 +472,9 @@ void QTextTablePrivate::update() const cellIndices[i] = cell; if (r + rowspan > nRows) { - grid = (int *)realloc(grid, sizeof(int)*(r + rowspan)*nCols); + newGrid = (int *)realloc(grid, sizeof(int)*(r + rowspan)*nCols); + Q_CHECK_PTR(newGrid); + grid = newGrid; memset(grid + (nRows*nCols), 0, sizeof(int)*(r+rowspan-nRows)*nCols); nRows = r + rowspan; } diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp index c6c2e69..04f081e 100644 --- a/src/gui/text/qzip.cpp +++ b/src/gui/text/qzip.cpp @@ -695,7 +695,7 @@ void QZipWriterPrivate::addEntry(EntryType type, const QString &fileName, const */ QZipReader::QZipReader(const QString &archive, QIODevice::OpenMode mode) { - QFile *f = new QFile(archive); + QScopedPointer<QFile> f(new QFile(archive)); f->open(mode); QZipReader::Status status; if (f->error() == QFile::NoError) @@ -711,7 +711,8 @@ QZipReader::QZipReader(const QString &archive, QIODevice::OpenMode mode) status = FileError; } - d = new QZipReaderPrivate(f, /*ownDevice=*/true); + d = new QZipReaderPrivate(f.data(), /*ownDevice=*/true); + f.take(); d->status = status; } @@ -969,7 +970,7 @@ void QZipReader::close() */ QZipWriter::QZipWriter(const QString &fileName, QIODevice::OpenMode mode) { - QFile *f = new QFile(fileName); + QScopedPointer<QFile> f(new QFile(fileName)); f->open(mode); QZipWriter::Status status; if (f->error() == QFile::NoError) @@ -985,7 +986,8 @@ QZipWriter::QZipWriter(const QString &fileName, QIODevice::OpenMode mode) status = QZipWriter::FileError; } - d = new QZipWriterPrivate(f, /*ownDevice=*/true); + d = new QZipWriterPrivate(f.data(), /*ownDevice=*/true); + f.take(); d->status = status; } diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index fc33d43..e4d24ff 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -106,9 +106,27 @@ embedded { DEFINES += QT_NO_FONTCONFIG } +symbian { + SOURCES += \ + text/qfont_s60.cpp + contains(QT_CONFIG, freetype) { + SOURCES += \ + text/qfontengine_ft.cpp + HEADERS += \ + text/qfontengine_ft_p.h + DEFINES += \ + QT_NO_FONTCONFIG + } else { + SOURCES += \ + text/qfontengine_s60.cpp + HEADERS += \ + text/qfontengine_s60_p.h + LIBS += -lfntstr -lecom + } +} + contains(QT_CONFIG, freetype) { SOURCES += \ - ../3rdparty/freetype/builds/unix/ftsystem.c \ ../3rdparty/freetype/src/base/ftbase.c \ ../3rdparty/freetype/src/base/ftbbox.c \ ../3rdparty/freetype/src/base/ftdebug.c \ @@ -152,10 +170,19 @@ contains(QT_CONFIG, freetype) { ../3rdparty/freetype/src/autofit/afloader.c\ ../3rdparty/freetype/src/autofit/autofit.c + symbian { + SOURCES += \ + ../3rdparty/freetype/src/base/ftsystem.c + } else { + SOURCES += \ + ../3rdparty/freetype/builds/unix/ftsystem.c + INCLUDEPATH += \ + ../3rdparty/freetype/builds/unix + } + INCLUDEPATH += \ ../3rdparty/freetype/src \ - ../3rdparty/freetype/include \ - ../3rdparty/freetype/builds/unix + ../3rdparty/freetype/include DEFINES += FT2_BUILD_LIBRARY FT_CONFIG_OPTION_SYSTEM_ZLIB |