diff options
Diffstat (limited to 'src/gui/text')
-rw-r--r-- | src/gui/text/qfont.cpp | 240 | ||||
-rw-r--r-- | src/gui/text/qfont.h | 1 | ||||
-rw-r--r-- | src/gui/text/qfont_p.h | 2 | ||||
-rw-r--r-- | src/gui/text/qfont_qpa.cpp | 95 | ||||
-rw-r--r-- | src/gui/text/qfontdatabase.h | 2 | ||||
-rw-r--r-- | src/gui/text/qfontengine.cpp | 115 | ||||
-rw-r--r-- | src/gui/text/qfontengine_p.h | 23 | ||||
-rw-r--r-- | src/gui/text/qfontengine_qpf2.cpp (renamed from src/gui/text/qfontengine_qpa.cpp) | 286 | ||||
-rw-r--r-- | src/gui/text/qfontengine_qpf2_p.h (renamed from src/gui/text/qfontengine_qpa_p.h) | 49 | ||||
-rw-r--r-- | src/gui/text/qplatformfontdatabase.cpp | 18 | ||||
-rw-r--r-- | src/gui/text/qrawfont.cpp | 18 | ||||
-rw-r--r-- | src/gui/text/qrawfont_p.h | 3 | ||||
-rw-r--r-- | src/gui/text/qrawfont_qpa.cpp | 70 | ||||
-rw-r--r-- | src/gui/text/qtextengine.cpp | 266 | ||||
-rw-r--r-- | src/gui/text/qtextengine_p.h | 39 | ||||
-rw-r--r-- | src/gui/text/qtextlayout.cpp | 25 | ||||
-rw-r--r-- | src/gui/text/text.pri | 6 |
17 files changed, 592 insertions, 666 deletions
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index cf40dd028d..cf64c89f2f 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -62,6 +62,8 @@ #include <limits.h> #include <qpa/qplatformscreen.h> +#include <qpa/qplatformintegration.h> +#include <qpa/qplatformfontdatabase.h> #include <QtGui/private/qguiapplication_p.h> #include <QtCore/QMutexLocker> @@ -545,79 +547,6 @@ QFontEngineData::~QFontEngineData() */ /*! - \fn QString QFont::rawName() const - \deprecated - - Returns the name of the font within the underlying window system. - - On X11, this function will return an empty string. - - Using the return value of this function is usually \e not \e - portable. - - \sa setRawName() -*/ - -/*! - \fn void QFont::setRawName(const QString &name) - \deprecated - - Sets a font by its system specific name. - - A font set with setRawName() is still a full-featured QFont. It can - be queried (for example with italic()) or modified (for example with - setItalic()) and is therefore also suitable for rendering rich text. - - If Qt's internal font database cannot resolve the raw name, the - font becomes a raw font with \a name as its family. - - \sa rawName(), setRawMode(), setFamily() -*/ - -/*! - \fn QString QFont::lastResortFamily() const - - Returns the "last resort" font family name. - - The current implementation tries a wide variety of common fonts, - returning the first one it finds. Is is possible that no family is - found in which case an empty string is returned. - - \sa lastResortFont() -*/ - -/*! - \fn QString QFont::defaultFamily() const - - Returns the family name that corresponds to the current style - hint. - - \sa StyleHint, styleHint(), setStyleHint() -*/ - -/*! - \fn QString QFont::lastResortFont() const - - Returns a "last resort" font name for the font matching algorithm. - This is used if the last resort family is not available. It will - always return a name, if necessary returning something like - "fixed" or "system". - - The current implementation tries a wide variety of common fonts, - returning the first one it finds. The implementation may change - at any time, but this function will always return a string - containing something. - - It is theoretically possible that there really isn't a - lastResortFont() in which case Qt will abort with an error - message. We have not been able to identify a case where this - happens. Please \l{bughowto.html}{report it as a bug} if - it does, preferably with a list of the fonts you have installed. - - \sa lastResortFamily(), rawName() -*/ - -/*! Constructs a font from \a font for use on the paint device \a pd. */ QFont::QFont(const QFont &font, QPaintDevice *pd) @@ -1376,6 +1305,7 @@ QFont::StyleHint QFont::styleHint() const \value PreferOutline prefers outline fonts (as opposed to bitmap fonts). \value ForceOutline forces the use of outline fonts. \value NoAntialias don't antialias the fonts. + \value NoSubpixelAntialias avoid subpixel antialiasing on the fonts if possible. \value PreferAntialias antialias if possible. \value OpenGLCompatible forces the use of OpenGL compatible fonts. @@ -1913,20 +1843,6 @@ void QFont::insertSubstitutions(const QString &familyName, } } -/*! \fn void QFont::initialize() - \internal - - Internal function that initializes the font system. The font cache - and font dict do not alloc the keys. The key is a QString which is - shared between QFontPrivate and QXFontName. -*/ - -/*! \fn void QFont::cleanup() - \internal - - Internal function that cleans up the font system. -*/ - /*! Removes all the substitutions for \a familyName. @@ -2041,6 +1957,42 @@ static void set_extended_font_bits(quint8 bits, QFontPrivate *f) } #endif +/*! + \fn QString QFont::rawName() const + \deprecated + + Returns the name of the font within the underlying window system. + + On X11, this function will return an empty string. + + Using the return value of this function is usually \e not \e + portable. + + \sa setRawName() +*/ +QString QFont::rawName() const +{ + return QLatin1String("unknown"); +} + +/*! + \fn void QFont::setRawName(const QString &name) + \deprecated + + Sets a font by its system specific name. + + A font set with setRawName() is still a full-featured QFont. It can + be queried (for example with italic()) or modified (for example with + setItalic()) and is therefore also suitable for rendering rich text. + + If Qt's internal font database cannot resolve the raw name, the + font becomes a raw font with \a name as its family. + + \sa rawName(), setRawMode(), setFamily() +*/ +void QFont::setRawName(const QString &) +{ +} /*! Returns the font's key, a textual representation of a font. It is @@ -2134,17 +2086,96 @@ bool QFont::fromString(const QString &descrip) return true; } +/*! \fn void QFont::initialize() + \internal + + Internal function that initializes the font system. The font cache + and font dict do not alloc the keys. The key is a QString which is + shared between QFontPrivate and QXFontName. +*/ +void QFont::initialize() +{ +} + +/*! \fn void QFont::cleanup() + \internal + + Internal function that cleans up the font system. +*/ +void QFont::cleanup() +{ + QFontCache::cleanup(); +} + /*! \internal Internal function that dumps font cache statistics. */ void QFont::cacheStatistics() { +} + +/*! + \fn QString QFont::lastResortFamily() const + + Returns the "last resort" font family name. + + The current implementation tries a wide variety of common fonts, + returning the first one it finds. Is is possible that no family is + found in which case an empty string is returned. + + \sa lastResortFont() +*/ +QString QFont::lastResortFamily() const +{ + return QString::fromLatin1("helvetica"); +} +/*! + \fn QString QFont::defaultFamily() const + + Returns the family name that corresponds to the current style + hint. + \sa StyleHint, styleHint(), setStyleHint() +*/ +QString QFont::defaultFamily() const +{ + QPlatformFontDatabase *fontDB = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); + const QStringList fallbacks = fontDB->fallbacksForFamily(QString(), QFont::StyleNormal + , QFont::StyleHint(d->request.styleHint), QChar::Script_Common); + if (!fallbacks.isEmpty()) + return fallbacks.first(); + return QString(); } +/*! + \fn QString QFont::lastResortFont() const + Returns a "last resort" font name for the font matching algorithm. + This is used if the last resort family is not available. It will + always return a name, if necessary returning something like + "fixed" or "system". + + The current implementation tries a wide variety of common fonts, + returning the first one it finds. The implementation may change + at any time, but this function will always return a string + containing something. + + It is theoretically possible that there really isn't a + lastResortFont() in which case Qt will abort with an error + message. We have not been able to identify a case where this + happens. Please \l{bughowto.html}{report it as a bug} if + it does, preferably with a list of the fonts you have installed. + + \sa lastResortFamily(), rawName() +*/ +QString QFont::lastResortFont() const +{ + qFatal("QFont::lastResortFont: Cannot find any reasonable font"); + // Shut compiler up + return QString(); +} /***************************************************************************** QFont stream functions @@ -2165,6 +2196,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font) s << font.d->request.family.toLatin1(); } else { s << font.d->request.family; + if (s.version() >= QDataStream::Qt_5_4) + s << font.d->request.styleName; } if (s.version() >= QDataStream::Qt_4_0) { @@ -2185,8 +2218,14 @@ QDataStream &operator<<(QDataStream &s, const QFont &font) } s << (quint8) font.d->request.styleHint; - if (s.version() >= QDataStream::Qt_3_1) - s << (quint8) font.d->request.styleStrategy; + if (s.version() >= QDataStream::Qt_3_1) { + // Continue writing 8 bits for versions < 5.4 so that we don't write too much, + // even though we need 16 to store styleStrategy, so there is some data loss. + if (s.version() >= QDataStream::Qt_5_4) + s << (quint16) font.d->request.styleStrategy; + else + s << (quint8) font.d->request.styleStrategy; + } s << (quint8) 0 << (quint8) font.d->request.weight << get_font_bits(s.version(), font.d.data()); @@ -2198,6 +2237,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font) s << font.d->letterSpacing.value(); s << font.d->wordSpacing.value(); } + if (s.version() >= QDataStream::Qt_5_4) + s << (quint8)font.d->request.hintingPreference; return s; } @@ -2215,7 +2256,8 @@ QDataStream &operator>>(QDataStream &s, QFont &font) font.d = new QFontPrivate; font.resolve_mask = QFont::AllPropertiesResolved; - quint8 styleHint, styleStrategy = QFont::PreferDefault, charSet, weight, bits; + quint8 styleHint, charSet, weight, bits; + quint16 styleStrategy = QFont::PreferDefault; if (s.version() == 1) { QByteArray fam; @@ -2223,6 +2265,8 @@ QDataStream &operator>>(QDataStream &s, QFont &font) font.d->request.family = QString::fromLatin1(fam); } else { s >> font.d->request.family; + if (s.version() >= QDataStream::Qt_5_4) + s >> font.d->request.styleName; } if (s.version() >= QDataStream::Qt_4_0) { @@ -2242,8 +2286,15 @@ QDataStream &operator>>(QDataStream &s, QFont &font) font.d->request.pixelSize = pixelSize; } s >> styleHint; - if (s.version() >= QDataStream::Qt_3_1) - s >> styleStrategy; + if (s.version() >= QDataStream::Qt_3_1) { + if (s.version() >= QDataStream::Qt_5_4) { + s >> styleStrategy; + } else { + quint8 tempStyleStrategy; + s >> tempStyleStrategy; + styleStrategy = tempStyleStrategy; + } + } s >> charSet; s >> weight; @@ -2273,6 +2324,11 @@ QDataStream &operator>>(QDataStream &s, QFont &font) s >> value; font.d->wordSpacing.setValue(value); } + if (s.version() >= QDataStream::Qt_5_4) { + quint8 value; + s >> value; + font.d->request.hintingPreference = QFont::HintingPreference(value); + } return s; } diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h index 7fbaf24861..f48f4cf4c5 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -83,6 +83,7 @@ public: NoAntialias = 0x0100, OpenGLCompatible = 0x0200, ForceIntegerMetrics = 0x0400, + NoSubpixelAntialias = 0x0800, NoFontMerging = 0x8000 }; diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h index 4d8712e76e..be0402b95a 100644 --- a/src/gui/text/qfont_p.h +++ b/src/gui/text/qfont_p.h @@ -92,7 +92,7 @@ struct QFontDef uint weight : 7; // 0-99 uint fixedPitch : 1; uint style : 2; - uint stretch : 12; // 0-400 + uint stretch : 12; // 0-4000 uint hintingPreference : 2; uint ignorePitch : 1; diff --git a/src/gui/text/qfont_qpa.cpp b/src/gui/text/qfont_qpa.cpp deleted file mode 100644 index be432dc52f..0000000000 --- a/src/gui/text/qfont_qpa.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, 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. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtGui/private/qguiapplication_p.h> -#include <qpa/qplatformintegration.h> -#include <qpa/qplatformfontdatabase.h> - -QT_BEGIN_NAMESPACE - -void QFont::initialize() -{ -} - -void QFont::cleanup() -{ - QFontCache::cleanup(); -} - - -/***************************************************************************** - QFont member functions - *****************************************************************************/ - -QString QFont::rawName() const -{ - return QLatin1String("unknown"); -} - -void QFont::setRawName(const QString &) -{ -} - -QString QFont::defaultFamily() const -{ - QPlatformFontDatabase *fontDB = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); - const QStringList fallbacks = fontDB->fallbacksForFamily(QString(), QFont::StyleNormal - , QFont::StyleHint(d->request.styleHint), QChar::Script_Common); - if (!fallbacks.isEmpty()) - return fallbacks.first(); - return QString(); -} - -QString QFont::lastResortFamily() const -{ - return QString::fromLatin1("helvetica"); -} - -QString QFont::lastResortFont() const -{ - qFatal("QFont::lastResortFont: Cannot find any reasonable font"); - // Shut compiler up - return QString(); -} - - -QT_END_NAMESPACE - diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index 833e574707..245d1cf81b 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -167,7 +167,7 @@ private: friend class QFontPrivate; friend class QFontDialog; friend class QFontDialogPrivate; - friend class QFontEngineMultiQPA; + friend class QFontEngineMultiBasicImpl; QFontDatabasePrivate *d; }; diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 8adbb31a55..5f801c3bf4 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -42,6 +42,10 @@ #include <qdebug.h> #include <private/qfontengine_p.h> #include <private/qfontengineglyphcache_p.h> +#include <private/qguiapplication_p.h> + +#include <qpa/qplatformfontdatabase.h> +#include <qpa/qplatformintegration.h> #include "qbitmap.h" #include "qpainter.h" @@ -2000,4 +2004,115 @@ QImage QFontEngineMulti::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosit return engine(which)->alphaRGBMapForGlyph(stripped(glyph), subPixelPosition, t); } +/* + Creates a new multi engine. + + This function takes ownership of the QFontEngine, increasing it's refcount. +*/ +QFontEngineMultiBasicImpl::QFontEngineMultiBasicImpl(QFontEngine *fe, int _script, const QStringList &fallbacks) + : QFontEngineMulti(fallbacks.size() + 1), + fallbackFamilies(fallbacks), script(_script) + , fallbacksQueried(true) +{ + init(fe); +} + +QFontEngineMultiBasicImpl::QFontEngineMultiBasicImpl(QFontEngine *fe, int _script) + : QFontEngineMulti(2) + , script(_script) + , fallbacksQueried(false) +{ + fallbackFamilies << QString(); + init(fe); +} + +void QFontEngineMultiBasicImpl::init(QFontEngine *fe) +{ + Q_ASSERT(fe && fe->type() != QFontEngine::Multi); + engines[0] = fe; + fe->ref.ref(); + fontDef = engines[0]->fontDef; + cache_cost = fe->cache_cost; +} + +void QFontEngineMultiBasicImpl::loadEngine(int at) +{ + ensureFallbackFamiliesQueried(); + Q_ASSERT(at < engines.size()); + Q_ASSERT(engines.at(at) == 0); + QFontDef request = fontDef; + request.styleStrategy |= QFont::NoFontMerging; + request.family = fallbackFamilies.at(at-1); + engines[at] = QFontDatabase::findFont(script, + /*fontprivate = */0, + request, /*multi = */false, true); + Q_ASSERT(engines[at]); + engines[at]->ref.ref(); + engines[at]->fontDef = request; +} +void QFontEngineMultiBasicImpl::ensureFallbackFamiliesQueried() +{ + if (fallbacksQueried) + return; + QStringList fallbacks = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fallbacksForFamily(engine(0)->fontDef.family, QFont::Style(engine(0)->fontDef.style) + , QFont::AnyStyle, QChar::Script(script)); + setFallbackFamiliesList(fallbacks); +} + +void QFontEngineMultiBasicImpl::setFallbackFamiliesList(const QStringList &fallbacks) +{ + // Original FontEngine to restore after the fill. + QFontEngine *fe = engines[0]; + fallbackFamilies = fallbacks; + if (!fallbackFamilies.isEmpty()) { + engines.fill(0, fallbackFamilies.size() + 1); + engines[0] = fe; + } else { + // Turns out we lied about having any fallback at all. + fallbackFamilies << fe->fontDef.family; + engines[1] = fe; + fe->ref.ref(); + } + fallbacksQueried = true; +} + +/* + This is used indirectly by Qt WebKit when using QTextLayout::setRawFont + + The purpose of this is to provide the necessary font fallbacks when drawing complex + text. Since Qt WebKit ends up repeatedly creating QTextLayout instances and passing them + the same raw font over and over again, we want to cache the corresponding multi font engine + as it may contain fallback font engines already. +*/ +QFontEngine* QFontEngineMultiBasicImpl::createMultiFontEngine(QFontEngine *fe, int script) +{ + QFontEngine *engine = 0; + QFontCache::Key key(fe->fontDef, script, /*multi = */true); + QFontCache *fc = QFontCache::instance(); + // We can't rely on the fontDef (and hence the cache Key) + // alone to distinguish webfonts, since these should not be + // accidentally shared, even if the resulting fontcache key + // is strictly identical. See: + // http://www.w3.org/TR/css3-fonts/#font-face-rule + const bool faceIsLocal = !fe->faceId().filename.isEmpty(); + QFontCache::EngineCache::Iterator it = fc->engineCache.find(key), + end = fc->engineCache.end(); + while (it != end && it.key() == key) { + Q_ASSERT(it.value().data->type() == QFontEngine::Multi); + QFontEngineMulti *cachedEngine = static_cast<QFontEngineMulti *>(it.value().data); + if (fe == cachedEngine->engine(0) || (faceIsLocal && fe->faceId().filename == cachedEngine->engine(0)->faceId().filename)) { + engine = cachedEngine; + fc->updateHitCountAndTimeStamp(it.value()); + break; + } + it++; + } + if (!engine) { + engine = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fontEngineMulti(fe, QChar::Script(script)); + QFontCache::instance()->insertEngine(key, engine, /* insertMulti */ !faceIsLocal); + } + Q_ASSERT(engine); + return engine; +} + QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index fc849d788f..5040424c6f 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -433,6 +433,29 @@ protected: QVector<QFontEngine *> engines; }; +class Q_GUI_EXPORT QFontEngineMultiBasicImpl : public QFontEngineMulti +{ +public: + QFontEngineMultiBasicImpl(QFontEngine *fe, int script, const QStringList &fallbacks); + QFontEngineMultiBasicImpl(QFontEngine *fe, int script); + + void loadEngine(int at); + static QFontEngine* createMultiFontEngine(QFontEngine *fe, int script); + + int fallbackFamilyCount() const { return fallbackFamilies.size(); } + QString fallbackFamilyAt(int at) const { return fallbackFamilies.at(at); } + + virtual void ensureFallbackFamiliesQueried(); + virtual void setFallbackFamiliesList(const QStringList &fallbacks); + +private: + void init(QFontEngine *fe); + + mutable QStringList fallbackFamilies; + int script; + mutable bool fallbacksQueried; +}; + class QTestFontEngine : public QFontEngineBox { public: diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpf2.cpp index a115d2a901..bcb128baac 100644 --- a/src/gui/text/qfontengine_qpa.cpp +++ b/src/gui/text/qfontengine_qpf2.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qfontengine_qpa_p.h" +#include "qfontengine_qpf2_p.h" #include <QtCore/QFile> #include <QtCore/QFileInfo> @@ -57,28 +57,28 @@ QT_BEGIN_NAMESPACE //#define DEBUG_HEADER //#define DEBUG_FONTENGINE -static QFontEngineQPA::TagType tagTypes[QFontEngineQPA::NumTags] = { - QFontEngineQPA::StringType, // FontName - QFontEngineQPA::StringType, // FileName - QFontEngineQPA::UInt32Type, // FileIndex - QFontEngineQPA::UInt32Type, // FontRevision - QFontEngineQPA::StringType, // FreeText - QFontEngineQPA::FixedType, // Ascent - QFontEngineQPA::FixedType, // Descent - QFontEngineQPA::FixedType, // Leading - QFontEngineQPA::FixedType, // XHeight - QFontEngineQPA::FixedType, // AverageCharWidth - QFontEngineQPA::FixedType, // MaxCharWidth - QFontEngineQPA::FixedType, // LineThickness - QFontEngineQPA::FixedType, // MinLeftBearing - QFontEngineQPA::FixedType, // MinRightBearing - QFontEngineQPA::FixedType, // UnderlinePosition - QFontEngineQPA::UInt8Type, // GlyphFormat - QFontEngineQPA::UInt8Type, // PixelSize - QFontEngineQPA::UInt8Type, // Weight - QFontEngineQPA::UInt8Type, // Style - QFontEngineQPA::StringType, // EndOfHeader - QFontEngineQPA::BitFieldType// WritingSystems +static QFontEngineQPF2::TagType tagTypes[QFontEngineQPF2::NumTags] = { + QFontEngineQPF2::StringType, // FontName + QFontEngineQPF2::StringType, // FileName + QFontEngineQPF2::UInt32Type, // FileIndex + QFontEngineQPF2::UInt32Type, // FontRevision + QFontEngineQPF2::StringType, // FreeText + QFontEngineQPF2::FixedType, // Ascent + QFontEngineQPF2::FixedType, // Descent + QFontEngineQPF2::FixedType, // Leading + QFontEngineQPF2::FixedType, // XHeight + QFontEngineQPF2::FixedType, // AverageCharWidth + QFontEngineQPF2::FixedType, // MaxCharWidth + QFontEngineQPF2::FixedType, // LineThickness + QFontEngineQPF2::FixedType, // MinLeftBearing + QFontEngineQPF2::FixedType, // MinRightBearing + QFontEngineQPF2::FixedType, // UnderlinePosition + QFontEngineQPF2::UInt8Type, // GlyphFormat + QFontEngineQPF2::UInt8Type, // PixelSize + QFontEngineQPF2::UInt8Type, // Weight + QFontEngineQPF2::UInt8Type, // Style + QFontEngineQPF2::StringType, // EndOfHeader + QFontEngineQPF2::BitFieldType// WritingSystems }; @@ -122,21 +122,21 @@ static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr) quint16 tag, length; READ_VERIFY(quint16, tag); READ_VERIFY(quint16, length); - if (tag == QFontEngineQPA::Tag_EndOfHeader) + if (tag == QFontEngineQPF2::Tag_EndOfHeader) return endPtr; - if (tag < QFontEngineQPA::NumTags) { + if (tag < QFontEngineQPF2::NumTags) { switch (tagTypes[tag]) { - case QFontEngineQPA::BitFieldType: - case QFontEngineQPA::StringType: + case QFontEngineQPF2::BitFieldType: + case QFontEngineQPF2::StringType: // can't do anything... break; - case QFontEngineQPA::UInt32Type: + case QFontEngineQPF2::UInt32Type: VERIFY_TAG(length == sizeof(quint32)); break; - case QFontEngineQPA::FixedType: + case QFontEngineQPF2::FixedType: VERIFY_TAG(length == sizeof(quint32)); break; - case QFontEngineQPA::UInt8Type: + case QFontEngineQPF2::UInt8Type: VERIFY_TAG(length == sizeof(quint8)); break; } @@ -150,7 +150,7 @@ static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr) return tagPtr + length; } -const QFontEngineQPA::Glyph *QFontEngineQPA::findGlyph(glyph_t g) const +const QFontEngineQPF2::Glyph *QFontEngineQPF2::findGlyph(glyph_t g) const { if (!g || g >= glyphMapEntries) return 0; @@ -168,7 +168,7 @@ const QFontEngineQPA::Glyph *QFontEngineQPA::findGlyph(glyph_t g) const return reinterpret_cast<const Glyph *>(fontData + glyphDataOffset + glyphPos); } -bool QFontEngineQPA::verifyHeader(const uchar *data, int size) +bool QFontEngineQPF2::verifyHeader(const uchar *data, int size) { VERIFY(quintptr(data) % Q_ALIGNOF(Header) == 0); VERIFY(size >= int(sizeof(Header))); @@ -194,7 +194,7 @@ bool QFontEngineQPA::verifyHeader(const uchar *data, int size) return true; } -QVariant QFontEngineQPA::extractHeaderField(const uchar *data, HeaderTag requestedTag) +QVariant QFontEngineQPF2::extractHeaderField(const uchar *data, HeaderTag requestedTag) { const Header *header = reinterpret_cast<const Header *>(data); const uchar *tagPtr = data + sizeof(Header); @@ -226,7 +226,7 @@ QVariant QFontEngineQPA::extractHeaderField(const uchar *data, HeaderTag request } -QFontEngineQPA::QFontEngineQPA(const QFontDef &def, const QByteArray &data) +QFontEngineQPF2::QFontEngineQPF2(const QFontDef &def, const QByteArray &data) : QFontEngine(QPF2), fontData(reinterpret_cast<const uchar *>(data.constData())), dataSize(data.size()) { @@ -243,7 +243,7 @@ QFontEngineQPA::QFontEngineQPA(const QFontDef &def, const QByteArray &data) readOnly = true; #if defined(DEBUG_FONTENGINE) - qDebug() << "QFontEngineQPA::QFontEngineQPA( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ')'; + qDebug() << "QFontEngineQPF2::QFontEngineQPF2( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ')'; #endif if (!verifyHeader(fontData, dataSize)) { @@ -312,11 +312,11 @@ QFontEngineQPA::QFontEngineQPA(const QFontDef &def, const QByteArray &data) #endif } -QFontEngineQPA::~QFontEngineQPA() +QFontEngineQPF2::~QFontEngineQPF2() { } -bool QFontEngineQPA::getSfntTableData(uint tag, uchar *buffer, uint *length) const +bool QFontEngineQPF2::getSfntTableData(uint tag, uchar *buffer, uint *length) const { if (tag != MAKE_TAG('c', 'm', 'a', 'p') || !cmap) return false; @@ -328,7 +328,7 @@ bool QFontEngineQPA::getSfntTableData(uint tag, uchar *buffer, uint *length) con return true; } -glyph_t QFontEngineQPA::glyphIndex(uint ucs4) const +glyph_t QFontEngineQPF2::glyphIndex(uint ucs4) const { glyph_t glyph = getTrueTypeGlyphIndex(cmap, ucs4); if (glyph == 0 && symbol && ucs4 < 0x100) @@ -339,7 +339,7 @@ glyph_t QFontEngineQPA::glyphIndex(uint ucs4) const return glyph; } -bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const +bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const { Q_ASSERT(glyphs->numGlyphs >= *nglyphs); if (*nglyphs < len) { @@ -386,7 +386,7 @@ bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph return true; } -void QFontEngineQPA::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const +void QFontEngineQPF2::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const { for (int i = 0; i < glyphs->numGlyphs; ++i) { const Glyph *g = findGlyph(glyphs->glyphs[i]); @@ -396,7 +396,7 @@ void QFontEngineQPA::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFla } } -QImage QFontEngineQPA::alphaMapForGlyph(glyph_t g) +QImage QFontEngineQPF2::alphaMapForGlyph(glyph_t g) { const Glyph *glyph = findGlyph(g); if (!glyph) @@ -409,12 +409,12 @@ QImage QFontEngineQPA::alphaMapForGlyph(glyph_t g) return image; } -void QFontEngineQPA::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) +void QFontEngineQPF2::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) { addBitmapFontToPath(x, y, glyphs, path, flags); } -glyph_metrics_t QFontEngineQPA::boundingBox(const QGlyphLayout &glyphs) +glyph_metrics_t QFontEngineQPF2::boundingBox(const QGlyphLayout &glyphs) { glyph_metrics_t overall; // initialize with line height, we get the same behaviour on all platforms @@ -442,7 +442,7 @@ glyph_metrics_t QFontEngineQPA::boundingBox(const QGlyphLayout &glyphs) return overall; } -glyph_metrics_t QFontEngineQPA::boundingBox(glyph_t glyph) +glyph_metrics_t QFontEngineQPF2::boundingBox(glyph_t glyph) { glyph_metrics_t overall; const Glyph *g = findGlyph(glyph); @@ -456,107 +456,107 @@ glyph_metrics_t QFontEngineQPA::boundingBox(glyph_t glyph) return overall; } -QFixed QFontEngineQPA::ascent() const +QFixed QFontEngineQPF2::ascent() const { return QFixed::fromReal(extractHeaderField(fontData, Tag_Ascent).value<qreal>()); } -QFixed QFontEngineQPA::descent() const +QFixed QFontEngineQPF2::descent() const { return QFixed::fromReal(extractHeaderField(fontData, Tag_Descent).value<qreal>()); } -QFixed QFontEngineQPA::leading() const +QFixed QFontEngineQPF2::leading() const { return QFixed::fromReal(extractHeaderField(fontData, Tag_Leading).value<qreal>()); } -qreal QFontEngineQPA::maxCharWidth() const +qreal QFontEngineQPF2::maxCharWidth() const { return extractHeaderField(fontData, Tag_MaxCharWidth).value<qreal>(); } -qreal QFontEngineQPA::minLeftBearing() const +qreal QFontEngineQPF2::minLeftBearing() const { return extractHeaderField(fontData, Tag_MinLeftBearing).value<qreal>(); } -qreal QFontEngineQPA::minRightBearing() const +qreal QFontEngineQPF2::minRightBearing() const { return extractHeaderField(fontData, Tag_MinRightBearing).value<qreal>(); } -QFixed QFontEngineQPA::underlinePosition() const +QFixed QFontEngineQPF2::underlinePosition() const { return QFixed::fromReal(extractHeaderField(fontData, Tag_UnderlinePosition).value<qreal>()); } -QFixed QFontEngineQPA::lineThickness() const +QFixed QFontEngineQPF2::lineThickness() const { return QFixed::fromReal(extractHeaderField(fontData, Tag_LineThickness).value<qreal>()); } -bool QFontEngineQPA::isValid() const +bool QFontEngineQPF2::isValid() const { return fontData && dataSize && cmapOffset && glyphMapOffset && glyphDataOffset && glyphDataSize > 0; } -void QPAGenerator::generate() +void QPF2Generator::generate() { writeHeader(); writeGMap(); - writeBlock(QFontEngineQPA::GlyphBlock, QByteArray()); + writeBlock(QFontEngineQPF2::GlyphBlock, QByteArray()); dev->seek(4); // position of header.lock writeUInt32(0); } -void QPAGenerator::writeHeader() +void QPF2Generator::writeHeader() { - QFontEngineQPA::Header header; + QFontEngineQPF2::Header header; header.magic[0] = 'Q'; header.magic[1] = 'P'; header.magic[2] = 'F'; header.magic[3] = '2'; header.lock = 1; - header.majorVersion = QFontEngineQPA::CurrentMajorVersion; - header.minorVersion = QFontEngineQPA::CurrentMinorVersion; + header.majorVersion = QFontEngineQPF2::CurrentMajorVersion; + header.minorVersion = QFontEngineQPF2::CurrentMinorVersion; header.dataSize = 0; dev->write((const char *)&header, sizeof(header)); - writeTaggedString(QFontEngineQPA::Tag_FontName, fe->fontDef.family.toUtf8()); + writeTaggedString(QFontEngineQPF2::Tag_FontName, fe->fontDef.family.toUtf8()); QFontEngine::FaceId face = fe->faceId(); - writeTaggedString(QFontEngineQPA::Tag_FileName, face.filename); - writeTaggedUInt32(QFontEngineQPA::Tag_FileIndex, face.index); + writeTaggedString(QFontEngineQPF2::Tag_FileName, face.filename); + writeTaggedUInt32(QFontEngineQPF2::Tag_FileIndex, face.index); { const QByteArray head = fe->getSfntTable(MAKE_TAG('h', 'e', 'a', 'd')); if (head.size() >= 4) { const quint32 revision = qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(head.constData())); - writeTaggedUInt32(QFontEngineQPA::Tag_FontRevision, revision); + writeTaggedUInt32(QFontEngineQPF2::Tag_FontRevision, revision); } } - writeTaggedQFixed(QFontEngineQPA::Tag_Ascent, fe->ascent()); - writeTaggedQFixed(QFontEngineQPA::Tag_Descent, fe->descent()); - writeTaggedQFixed(QFontEngineQPA::Tag_Leading, fe->leading()); - writeTaggedQFixed(QFontEngineQPA::Tag_XHeight, fe->xHeight()); - writeTaggedQFixed(QFontEngineQPA::Tag_AverageCharWidth, fe->averageCharWidth()); - writeTaggedQFixed(QFontEngineQPA::Tag_MaxCharWidth, QFixed::fromReal(fe->maxCharWidth())); - writeTaggedQFixed(QFontEngineQPA::Tag_LineThickness, fe->lineThickness()); - writeTaggedQFixed(QFontEngineQPA::Tag_MinLeftBearing, QFixed::fromReal(fe->minLeftBearing())); - writeTaggedQFixed(QFontEngineQPA::Tag_MinRightBearing, QFixed::fromReal(fe->minRightBearing())); - writeTaggedQFixed(QFontEngineQPA::Tag_UnderlinePosition, fe->underlinePosition()); - writeTaggedUInt8(QFontEngineQPA::Tag_PixelSize, fe->fontDef.pixelSize); - writeTaggedUInt8(QFontEngineQPA::Tag_Weight, fe->fontDef.weight); - writeTaggedUInt8(QFontEngineQPA::Tag_Style, fe->fontDef.style); - - writeTaggedUInt8(QFontEngineQPA::Tag_GlyphFormat, QFontEngineQPA::AlphamapGlyphs); - - writeTaggedString(QFontEngineQPA::Tag_EndOfHeader, QByteArray()); + writeTaggedQFixed(QFontEngineQPF2::Tag_Ascent, fe->ascent()); + writeTaggedQFixed(QFontEngineQPF2::Tag_Descent, fe->descent()); + writeTaggedQFixed(QFontEngineQPF2::Tag_Leading, fe->leading()); + writeTaggedQFixed(QFontEngineQPF2::Tag_XHeight, fe->xHeight()); + writeTaggedQFixed(QFontEngineQPF2::Tag_AverageCharWidth, fe->averageCharWidth()); + writeTaggedQFixed(QFontEngineQPF2::Tag_MaxCharWidth, QFixed::fromReal(fe->maxCharWidth())); + writeTaggedQFixed(QFontEngineQPF2::Tag_LineThickness, fe->lineThickness()); + writeTaggedQFixed(QFontEngineQPF2::Tag_MinLeftBearing, QFixed::fromReal(fe->minLeftBearing())); + writeTaggedQFixed(QFontEngineQPF2::Tag_MinRightBearing, QFixed::fromReal(fe->minRightBearing())); + writeTaggedQFixed(QFontEngineQPF2::Tag_UnderlinePosition, fe->underlinePosition()); + writeTaggedUInt8(QFontEngineQPF2::Tag_PixelSize, fe->fontDef.pixelSize); + writeTaggedUInt8(QFontEngineQPF2::Tag_Weight, fe->fontDef.weight); + writeTaggedUInt8(QFontEngineQPF2::Tag_Style, fe->fontDef.style); + + writeTaggedUInt8(QFontEngineQPF2::Tag_GlyphFormat, QFontEngineQPF2::AlphamapGlyphs); + + writeTaggedString(QFontEngineQPF2::Tag_EndOfHeader, QByteArray()); align4(); const quint64 size = dev->pos(); @@ -566,11 +566,11 @@ void QPAGenerator::writeHeader() dev->seek(size); } -void QPAGenerator::writeGMap() +void QPF2Generator::writeGMap() { const quint16 glyphCount = fe->glyphCount(); - writeUInt16(QFontEngineQPA::GMapBlock); + writeUInt16(QFontEngineQPF2::GMapBlock); writeUInt16(0); // padding writeUInt32(glyphCount * 4); @@ -582,7 +582,7 @@ void QPAGenerator::writeGMap() dev->seek(pos + numBytes); } -void QPAGenerator::writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &data) +void QPF2Generator::writeBlock(QFontEngineQPF2::BlockTag tag, const QByteArray &data) { writeUInt16(tag); writeUInt16(0); // padding @@ -593,144 +593,32 @@ void QPAGenerator::writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &da writeUInt8(0); } -void QPAGenerator::writeTaggedString(QFontEngineQPA::HeaderTag tag, const QByteArray &string) +void QPF2Generator::writeTaggedString(QFontEngineQPF2::HeaderTag tag, const QByteArray &string) { writeUInt16(tag); writeUInt16(string.length()); dev->write(string); } -void QPAGenerator::writeTaggedUInt32(QFontEngineQPA::HeaderTag tag, quint32 value) +void QPF2Generator::writeTaggedUInt32(QFontEngineQPF2::HeaderTag tag, quint32 value) { writeUInt16(tag); writeUInt16(sizeof(value)); writeUInt32(value); } -void QPAGenerator::writeTaggedUInt8(QFontEngineQPA::HeaderTag tag, quint8 value) +void QPF2Generator::writeTaggedUInt8(QFontEngineQPF2::HeaderTag tag, quint8 value) { writeUInt16(tag); writeUInt16(sizeof(value)); writeUInt8(value); } -void QPAGenerator::writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value) +void QPF2Generator::writeTaggedQFixed(QFontEngineQPF2::HeaderTag tag, QFixed value) { writeUInt16(tag); writeUInt16(sizeof(quint32)); writeUInt32(value.value()); } - -/* - Creates a new multi QPA engine. - - This function takes ownership of the QFontEngine, increasing it's refcount. -*/ -QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script, const QStringList &fallbacks) - : QFontEngineMulti(fallbacks.size() + 1), - fallbackFamilies(fallbacks), script(_script) - , fallbacksQueried(true) -{ - init(fe); -} - -QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script) - : QFontEngineMulti(2) - , script(_script) - , fallbacksQueried(false) -{ - fallbackFamilies << QString(); - init(fe); -} - -void QFontEngineMultiQPA::init(QFontEngine *fe) -{ - Q_ASSERT(fe && fe->type() != QFontEngine::Multi); - engines[0] = fe; - fe->ref.ref(); - fontDef = engines[0]->fontDef; - cache_cost = fe->cache_cost; -} - -void QFontEngineMultiQPA::loadEngine(int at) -{ - ensureFallbackFamiliesQueried(); - Q_ASSERT(at < engines.size()); - Q_ASSERT(engines.at(at) == 0); - QFontDef request = fontDef; - request.styleStrategy |= QFont::NoFontMerging; - request.family = fallbackFamilies.at(at-1); - engines[at] = QFontDatabase::findFont(script, - /*fontprivate = */0, - request, /*multi = */false, true); - Q_ASSERT(engines[at]); - engines[at]->ref.ref(); - engines[at]->fontDef = request; -} -void QFontEngineMultiQPA::ensureFallbackFamiliesQueried() -{ - if (fallbacksQueried) - return; - QStringList fallbacks = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fallbacksForFamily(engine(0)->fontDef.family, QFont::Style(engine(0)->fontDef.style) - , QFont::AnyStyle, QChar::Script(script)); - setFallbackFamiliesList(fallbacks); -} - -void QFontEngineMultiQPA::setFallbackFamiliesList(const QStringList &fallbacks) -{ - // Original FontEngine to restore after the fill. - QFontEngine *fe = engines[0]; - fallbackFamilies = fallbacks; - if (!fallbackFamilies.isEmpty()) { - engines.fill(0, fallbackFamilies.size() + 1); - engines[0] = fe; - } else { - // Turns out we lied about having any fallback at all. - fallbackFamilies << fe->fontDef.family; - engines[1] = fe; - fe->ref.ref(); - } - fallbacksQueried = true; -} - -/* - This is used indirectly by Qt WebKit when using QTextLayout::setRawFont - - The purpose of this is to provide the necessary font fallbacks when drawing complex - text. Since Qt WebKit ends up repeatedly creating QTextLayout instances and passing them - the same raw font over and over again, we want to cache the corresponding multi font engine - as it may contain fallback font engines already. -*/ -QFontEngine* QFontEngineMultiQPA::createMultiFontEngine(QFontEngine *fe, int script) -{ - QFontEngine *engine = 0; - QFontCache::Key key(fe->fontDef, script, /*multi = */true); - QFontCache *fc = QFontCache::instance(); - // We can't rely on the fontDef (and hence the cache Key) - // alone to distinguish webfonts, since these should not be - // accidentally shared, even if the resulting fontcache key - // is strictly identical. See: - // http://www.w3.org/TR/css3-fonts/#font-face-rule - const bool faceIsLocal = !fe->faceId().filename.isEmpty(); - QFontCache::EngineCache::Iterator it = fc->engineCache.find(key), - end = fc->engineCache.end(); - while (it != end && it.key() == key) { - Q_ASSERT(it.value().data->type() == QFontEngine::Multi); - QFontEngineMulti *cachedEngine = static_cast<QFontEngineMulti *>(it.value().data); - if (faceIsLocal || fe == cachedEngine->engine(0)) { - engine = cachedEngine; - fc->updateHitCountAndTimeStamp(it.value()); - break; - } - it++; - } - if (!engine) { - engine = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fontEngineMulti(fe, QChar::Script(script)); - QFontCache::instance()->insertEngine(key, engine, /* insertMulti */ !faceIsLocal); - } - Q_ASSERT(engine); - return engine; -} - QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_qpa_p.h b/src/gui/text/qfontengine_qpf2_p.h index e84b067c68..a616cc3300 100644 --- a/src/gui/text/qfontengine_qpa_p.h +++ b/src/gui/text/qfontengine_qpf2_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QFONTENGINE_QPA_P_H -#define QFONTENGINE_QPA_P_H +#ifndef QFONTENGINE_QPF2_P_H +#define QFONTENGINE_QPF2_P_H // // W A R N I N G @@ -67,7 +67,7 @@ class QFontEngine; class QFreetypeFace; class QBuffer; -class Q_GUI_EXPORT QFontEngineQPA : public QFontEngine +class Q_GUI_EXPORT QFontEngineQPF2 : public QFontEngine { public: // if you add new tags please make sure to update the tables in @@ -157,8 +157,8 @@ public: qint8 advance; }; - QFontEngineQPA(const QFontDef &def, const QByteArray &data); - ~QFontEngineQPA(); + QFontEngineQPF2(const QFontDef &def, const QByteArray &data); + ~QFontEngineQPF2(); FaceId faceId() const { return face_id; } bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; @@ -211,20 +211,20 @@ private: mutable bool kerning_pairs_loaded; }; -struct QPAGenerator +struct QPF2Generator { - QPAGenerator(QBuffer *device, QFontEngine *engine) + QPF2Generator(QBuffer *device, QFontEngine *engine) : dev(device), fe(engine) {} void generate(); void writeHeader(); void writeGMap(); - void writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &data); + void writeBlock(QFontEngineQPF2::BlockTag tag, const QByteArray &data); - void writeTaggedString(QFontEngineQPA::HeaderTag tag, const QByteArray &string); - void writeTaggedUInt32(QFontEngineQPA::HeaderTag tag, quint32 value); - void writeTaggedUInt8(QFontEngineQPA::HeaderTag tag, quint8 value); - void writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value); + void writeTaggedString(QFontEngineQPF2::HeaderTag tag, const QByteArray &string); + void writeTaggedUInt32(QFontEngineQPF2::HeaderTag tag, quint32 value); + void writeTaggedUInt8(QFontEngineQPF2::HeaderTag tag, quint8 value); + void writeTaggedQFixed(QFontEngineQPF2::HeaderTag tag, QFixed value); void writeUInt16(quint16 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); } void writeUInt32(quint32 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); } @@ -237,29 +237,6 @@ struct QPAGenerator QFontEngine *fe; }; -class Q_GUI_EXPORT QFontEngineMultiQPA : public QFontEngineMulti -{ -public: - QFontEngineMultiQPA(QFontEngine *fe, int script, const QStringList &fallbacks); - QFontEngineMultiQPA(QFontEngine *fe, int script); - - void loadEngine(int at); - static QFontEngine* createMultiFontEngine(QFontEngine *fe, int script); - - int fallbackFamilyCount() const { return fallbackFamilies.size(); } - QString fallbackFamilyAt(int at) const { return fallbackFamilies.at(at); } - - virtual void ensureFallbackFamiliesQueried(); - virtual void setFallbackFamiliesList(const QStringList &fallbacks); - -private: - void init(QFontEngine *fe); - - mutable QStringList fallbackFamilies; - int script; - mutable bool fallbacksQueried; -}; - QT_END_NAMESPACE -#endif // QFONTENGINE_QPA_P_H +#endif // QFONTENGINE_QPF2_P_H diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp index 33301005c6..e9ffa68591 100644 --- a/src/gui/text/qplatformfontdatabase.cpp +++ b/src/gui/text/qplatformfontdatabase.cpp @@ -41,7 +41,7 @@ #include "qplatformfontdatabase.h" #include <QtGui/private/qfontengine_p.h> -#include <QtGui/private/qfontengine_qpa_p.h> +#include <QtGui/private/qfontengine_qpf2_p.h> #include <QtCore/QLibraryInfo> #include <QtCore/QDir> @@ -69,12 +69,12 @@ void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void * return; const uchar *data = reinterpret_cast<const uchar *>(dataArray.constData()); - if (QFontEngineQPA::verifyHeader(data, dataArray.size())) { - QString fontName = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_FontName).toString(); - int pixelSize = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_PixelSize).toInt(); - QVariant weight = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Weight); - QVariant style = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Style); - QByteArray writingSystemBits = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_WritingSystems).toByteArray(); + if (QFontEngineQPF2::verifyHeader(data, dataArray.size())) { + QString fontName = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_FontName).toString(); + int pixelSize = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_PixelSize).toInt(); + QVariant weight = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_Weight); + QVariant style = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_Style); + QByteArray writingSystemBits = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_WritingSystems).toByteArray(); if (!fontName.isEmpty() && pixelSize) { QFont::Weight fontWeight = QFont::Normal; @@ -322,7 +322,7 @@ void QPlatformFontDatabase::invalidate() */ QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script) { - return new QFontEngineMultiQPA(fontEngine, script); + return new QFontEngineMultiBasicImpl(fontEngine, script); } /*! @@ -332,7 +332,7 @@ QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, void *handle) { QByteArray *fileDataPtr = static_cast<QByteArray *>(handle); - QFontEngineQPA *engine = new QFontEngineQPA(fontDef,*fileDataPtr); + QFontEngineQPF2 *engine = new QFontEngineQPF2(fontDef,*fileDataPtr); //qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family; return engine; } diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp index f789ec596b..9b24742823 100644 --- a/src/gui/text/qrawfont.cpp +++ b/src/gui/text/qrawfont.cpp @@ -47,6 +47,10 @@ #include "qrawfont_p.h" #include "qplatformfontdatabase.h" +#include <private/qguiapplication_p.h> +#include <qpa/qplatformintegration.h> +#include <qpa/qplatformfontdatabase.h> + #include <QtCore/qendian.h> QT_BEGIN_NAMESPACE @@ -252,7 +256,7 @@ void QRawFont::loadFromData(const QByteArray &fontData, d->cleanUp(); d->hintingPreference = hintingPreference; d->thread = QThread::currentThread(); - d->platformLoadFromData(fontData, pixelSize, hintingPreference); + d->loadFromData(fontData, pixelSize, hintingPreference); } /*! @@ -735,7 +739,6 @@ void QRawFont::setPixelSize(qreal pixelSize) */ void QRawFontPrivate::cleanUp() { - platformCleanUp(); if (fontEngine != 0) { if (!fontEngine->ref.deref()) delete fontEngine; @@ -744,6 +747,17 @@ void QRawFontPrivate::cleanUp() hintingPreference = QFont::PreferDefaultHinting; } +void QRawFontPrivate::loadFromData(const QByteArray &fontData, qreal pixelSize, + QFont::HintingPreference hintingPreference) +{ + Q_ASSERT(fontEngine == 0); + + QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); + fontEngine = pfdb->fontEngine(fontData, pixelSize, hintingPreference); + if (fontEngine != 0) + fontEngine->ref.ref(); +} + /*! Returns the smallest rectangle containing the glyph with the given \a glyphIndex. diff --git a/src/gui/text/qrawfont_p.h b/src/gui/text/qrawfont_p.h index c9c15717cc..b13454c391 100644 --- a/src/gui/text/qrawfont_p.h +++ b/src/gui/text/qrawfont_p.h @@ -95,8 +95,7 @@ public: } void cleanUp(); - void platformCleanUp(); - void platformLoadFromData(const QByteArray &fontData, + void loadFromData(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); diff --git a/src/gui/text/qrawfont_qpa.cpp b/src/gui/text/qrawfont_qpa.cpp deleted file mode 100644 index 7de6ef0e8b..0000000000 --- a/src/gui/text/qrawfont_qpa.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, 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. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/qglobal.h> - -#if !defined(QT_NO_RAWFONT) - -#include "qrawfont_p.h" -#include <qpa/qplatformintegration.h> -#include <qpa/qplatformfontdatabase.h> -#include <private/qguiapplication_p.h> - -QT_BEGIN_NAMESPACE - -void QRawFontPrivate::platformCleanUp() -{ -} - -void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, qreal pixelSize, - QFont::HintingPreference hintingPreference) -{ - Q_ASSERT(fontEngine == 0); - - QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); - fontEngine = pfdb->fontEngine(fontData, pixelSize, hintingPreference); - if (fontEngine != 0) - fontEngine->ref.ref(); -} - -QT_END_NAMESPACE - -#endif // QT_NO_RAWFONT diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index a3059008be..17bc4fde98 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -59,10 +59,6 @@ #include <algorithm> #include <stdlib.h> -#ifndef QT_NO_RAWFONT -#include "qfontengine_qpa_p.h" -#endif - QT_BEGIN_NAMESPACE static const float smallCapsFraction = 0.7f; @@ -88,7 +84,7 @@ public: /// The caps parameter is used to choose the algoritm of splitting text and assiging roles to the textitems void generate(int start, int length, QFont::Capitalization caps) { - if ((int)caps == (int)QFont::SmallCaps) + if (caps == QFont::SmallCaps) generateScriptItemsSmallCaps(reinterpret_cast<const ushort *>(m_string.unicode()), start, length); else if(caps == QFont::Capitalize) generateScriptItemsCapitalize(start, length); @@ -122,9 +118,7 @@ private: return; const int end = start + length; for (int i = start + 1; i < end; ++i) { - if (m_analysis[i].bidiLevel == m_analysis[start].bidiLevel - && m_analysis[i].flags == m_analysis[start].flags - && m_analysis[i].script == m_analysis[start].script + if (m_analysis[i] == m_analysis[start] && m_analysis[i].flags < QScriptAnalysis::SpaceTabOrObject && i - start < MaxItemLength) continue; @@ -843,6 +837,81 @@ enum JustificationClass { Justification_Arabic_Kashida = 13 // User-inserted Kashida(U+0640) }; +#ifdef QT_ENABLE_HARFBUZZ_NG + +/* + Adds an inter character justification opportunity after the number or letter + character and a space justification opportunity after the space character. +*/ +static inline void qt_getDefaultJustificationOpportunities(const ushort *string, int length, QGlyphLayout g, ushort *log_clusters, int spaceAs) +{ + int str_pos = 0; + while (str_pos < length) { + int glyph_pos = log_clusters[str_pos]; + + Q_ASSERT(glyph_pos < g.numGlyphs && g.attributes[glyph_pos].clusterStart); + + uint ucs4 = string[str_pos]; + if (QChar::isHighSurrogate(ucs4) && str_pos + 1 < length) { + ushort low = string[str_pos + 1]; + if (QChar::isLowSurrogate(low)) { + ++str_pos; + ucs4 = QChar::surrogateToUcs4(ucs4, low); + } + } + + // skip whole cluster + do { + ++str_pos; + } while (str_pos < length && log_clusters[str_pos] == glyph_pos); + do { + ++glyph_pos; + } while (glyph_pos < g.numGlyphs && !g.attributes[glyph_pos].clusterStart); + --glyph_pos; + + // justification opportunity at the end of cluster + if (Q_LIKELY(QChar::isLetterOrNumber(ucs4))) + g.attributes[glyph_pos].justification = Justification_Character; + else if (Q_LIKELY(QChar::isSpace(ucs4))) + g.attributes[glyph_pos].justification = spaceAs; + } +} + +static inline void qt_getJustificationOpportunities(const ushort *string, int length, const QScriptItem &si, QGlyphLayout g, ushort *log_clusters) +{ + Q_ASSERT(length > 0 && g.numGlyphs > 0); + + for (int glyph_pos = 0; glyph_pos < g.numGlyphs; ++glyph_pos) + g.attributes[glyph_pos].justification = Justification_Prohibited; + + int spaceAs; + + switch (si.analysis.script) { + case QChar::Script_Nko: + case QChar::Script_Mandaic: + case QChar::Script_Mongolian: + case QChar::Script_PhagsPa: + // same as default but inter character justification takes precedence + spaceAs = Justification_Arabic_Space; + break; + + case QChar::Script_Hiragana: + case QChar::Script_Katakana: + case QChar::Script_Han: + // same as default but inter character justification is the only option + spaceAs = Justification_Character; + break; + + default: + spaceAs = Justification_Space; + break; + } + + qt_getDefaultJustificationOpportunities(string, length, g, log_clusters, spaceAs); +} + +#endif // QT_ENABLE_HARFBUZZ_NG + // shape all the items that intersect with the line, taking tab widths into account to find out what text actually fits in the line. void QTextEngine::shapeLine(const QScriptLine &line) @@ -853,7 +922,7 @@ void QTextEngine::shapeLine(const QScriptLine &line) int item = findItem(line.from); if (item == -1) return; - for (item = findItem(line.from); item <= end; ++item) { + for ( ; item <= end; ++item) { QScriptItem &si = layoutData->items[item]; if (si.analysis.flags == QScriptAnalysis::Tab) { ensureSpace(1); @@ -1003,6 +1072,11 @@ void QTextEngine::shapeText(int item) const QGlyphLayout glyphs = shapedGlyphs(&si); +#ifdef QT_ENABLE_HARFBUZZ_NG + if (useHarfbuzzNG) + qt_getJustificationOpportunities(string, itemLength, si, glyphs, logClusters(&si)); +#endif + if (letterSpacing != 0) { for (int i = 1; i < si.num_glyphs; ++i) { if (glyphs.attributes[i].clusterStart) { @@ -1082,7 +1156,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st hb_buffer_set_segment_properties(buffer, &props); hb_buffer_guess_segment_properties(buffer); - uint buffer_flags = 0; // HB_BUFFER_FLAG_DEFAULT + uint buffer_flags = HB_BUFFER_FLAG_DEFAULT; // Symbol encoding used to encode various crap in the 32..255 character code range, // and thus might override U+00AD [SHY]; avoid hiding default ignorables if (actualFontEngine->symbol) @@ -1424,8 +1498,6 @@ void QTextEngine::invalidate() freeMemory(); minWidth = 0; maxWidth = 0; - if (specialData) - specialData->resolvedFormats.clear(); resetFontEngineCache(); } @@ -1586,9 +1658,9 @@ void QTextEngine::itemize() const } Q_ASSERT(position <= length); QFont::Capitalization capitalization = - formats()->charFormat(format).hasProperty(QTextFormat::FontCapitalization) - ? formats()->charFormat(format).fontCapitalization() - : formats()->defaultFont().capitalization(); + formatCollection()->charFormat(format).hasProperty(QTextFormat::FontCapitalization) + ? formatCollection()->charFormat(format).fontCapitalization() + : formatCollection()->defaultFont().capitalization(); itemizer.generate(prevPosition, position - prevPosition, capitalization); if (it == end) { if (position < length) @@ -1605,8 +1677,8 @@ void QTextEngine::itemize() const #ifndef QT_NO_RAWFONT if (useRawFont && specialData) { int lastIndex = 0; - for (int i = 0; i < specialData->addFormats.size(); ++i) { - const QTextLayout::FormatRange &range = specialData->addFormats.at(i); + for (int i = 0; i < specialData->formats.size(); ++i) { + const QTextLayout::FormatRange &range = specialData->formats.at(i); const QTextCharFormat &format = range.format; if (format.hasProperty(QTextFormat::FontCapitalization)) { itemizer.generate(lastIndex, range.start - lastIndex, QFont::MixedCase); @@ -1621,7 +1693,7 @@ void QTextEngine::itemize() const } addRequiredBoundaries(); - resolveAdditionalFormats(); + resolveFormats(); } bool QTextEngine::isRightToLeft() const @@ -1646,6 +1718,9 @@ bool QTextEngine::isRightToLeft() const int QTextEngine::findItem(int strPos) const { itemize(); + if (strPos < 0 || strPos >= layoutData->string.size()) + return -1; + int left = 1; int right = layoutData->items.size()-1; while(left <= right) { @@ -1884,7 +1959,7 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix if (feCache.prevFontEngine && feCache.prevFontEngine->type() == QFontEngine::Multi && feCache.prevScript == script) { engine = feCache.prevFontEngine; } else { - engine = QFontEngineMultiQPA::createMultiFontEngine(rawFont.d->fontEngine, script); + engine = QFontEngineMultiBasicImpl::createMultiFontEngine(rawFont.d->fontEngine, script); feCache.prevFontEngine = engine; feCache.prevScript = script; engine->ref.ref(); @@ -1893,13 +1968,13 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix feCache.prevScaledFontEngine = 0; } } - if (si.analysis.flags & QFont::SmallCaps) { + if (si.analysis.flags == QScriptAnalysis::SmallCaps) { if (feCache.prevScaledFontEngine) { scaledEngine = feCache.prevScaledFontEngine; } else { QFontEngine *scEngine = rawFont.d->fontEngine->cloneWithSize(smallCapsFraction * rawFont.pixelSize()); scEngine->ref.ref(); - scaledEngine = QFontEngineMultiQPA::createMultiFontEngine(scEngine, script); + scaledEngine = QFontEngineMultiBasicImpl::createMultiFontEngine(scEngine, script); scaledEngine->ref.ref(); feCache.prevScaledFontEngine = scaledEngine; // If scEngine is not ref'ed by scaledEngine, make sure it is deallocated and not leaked. @@ -2065,7 +2140,8 @@ void QTextEngine::justify(const QScriptLine &line) return; int firstItem = findItem(line.from); - int nItems = findItem(line.from + line_length - 1) - firstItem + 1; + int lastItem = findItem(line.from + line_length - 1); + int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0; QVarLengthArray<QJustificationPoint> justificationPoints; int nPoints = 0; @@ -2367,6 +2443,8 @@ void QTextEngine::freeMemory() layoutData->haveCharAttributes = false; layoutData->items.clear(); } + if (specialData) + specialData->resolvedFormats.clear(); for (int i = 0; i < lines.size(); ++i) { lines[i].justified = 0; lines[i].gridfitted = 0; @@ -2376,7 +2454,7 @@ void QTextEngine::freeMemory() int QTextEngine::formatIndex(const QScriptItem *si) const { if (specialData && !specialData->resolvedFormats.isEmpty()) { - QTextFormatCollection *collection = formats(); + QTextFormatCollection *collection = formatCollection(); Q_ASSERT(collection); return collection->indexForFormat(specialData->resolvedFormats.at(si - &layoutData->items[0])); } @@ -2398,16 +2476,16 @@ int QTextEngine::formatIndex(const QScriptItem *si) const QTextCharFormat QTextEngine::format(const QScriptItem *si) const { - if (const QTextFormatCollection *formats = this->formats()) - return formats->charFormat(formatIndex(si)); + if (const QTextFormatCollection *collection = formatCollection()) + return collection->charFormat(formatIndex(si)); return QTextCharFormat(); } void QTextEngine::addRequiredBoundaries() const { if (specialData) { - for (int i = 0; i < specialData->addFormats.size(); ++i) { - const QTextLayout::FormatRange &r = specialData->addFormats.at(i); + for (int i = 0; i < specialData->formats.size(); ++i) { + const QTextLayout::FormatRange &r = specialData->formats.at(i); setBoundary(r.start); setBoundary(r.start + r.length); //qDebug("adding boundaries %d %d", r.start, r.start+r.length); @@ -2476,7 +2554,7 @@ void QTextEngine::setPreeditArea(int position, const QString &preeditText) if (preeditText.isEmpty()) { if (!specialData) return; - if (specialData->addFormats.isEmpty()) { + if (specialData->formats.isEmpty()) { delete specialData; specialData = 0; } else { @@ -2493,41 +2571,41 @@ void QTextEngine::setPreeditArea(int position, const QString &preeditText) clearLineData(); } -void QTextEngine::setAdditionalFormats(const QList<QTextLayout::FormatRange> &formatList) +void QTextEngine::setFormats(const QList<QTextLayout::FormatRange> &formats) { - if (formatList.isEmpty()) { + if (formats.isEmpty()) { if (!specialData) return; if (specialData->preeditText.isEmpty()) { delete specialData; specialData = 0; } else { - specialData->addFormats.clear(); + specialData->formats.clear(); } } else { if (!specialData) { specialData = new SpecialData; specialData->preeditPosition = -1; } - specialData->addFormats = formatList; - indexAdditionalFormats(); + specialData->formats = formats; + indexFormats(); } invalidate(); clearLineData(); } -void QTextEngine::indexAdditionalFormats() +void QTextEngine::indexFormats() { - QTextFormatCollection *collection = formats(); + QTextFormatCollection *collection = formatCollection(); if (!collection) { Q_ASSERT(!block.docHandle()); - specialData->formats.reset(new QTextFormatCollection); - collection = specialData->formats.data(); + specialData->formatCollection.reset(new QTextFormatCollection); + collection = specialData->formatCollection.data(); } // replace with shared copies - for (int i = 0; i < specialData->addFormats.count(); ++i) { - QTextCharFormat &format = specialData->addFormats[i].format; + for (int i = 0; i < specialData->formats.size(); ++i) { + QTextCharFormat &format = specialData->formats[i].format; format = collection->charFormat(collection->indexForFormat(format)); } } @@ -2755,64 +2833,17 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int return layoutData->string.mid(from, to - from); } -namespace { -struct QScriptItemComparator { - bool operator()(int p, const QScriptItem &b) { return p < b.position; } -#if defined(Q_CC_MSVC) && _MSC_VER < 1600 -//The STL implementation of MSVC 2008 requires the definition - bool operator()(const QScriptItem &a, int p) { return a.position < p; } - bool operator()(const QScriptItem &a, const QScriptItem &b) { return a.position < b.position; } -#endif -}; -} - void QTextEngine::setBoundary(int strPos) const { - if (strPos <= 0 || strPos >= layoutData->string.length()) + const int item = findItem(strPos); + if (item < 0) return; - const QScriptItem* it = std::upper_bound(layoutData->items.constBegin(), layoutData->items.constEnd(), - strPos, QScriptItemComparator()); - Q_ASSERT(it > layoutData->items.constBegin()); - --it; - if (it->position == strPos) { - // already a split at the requested position - return; + QScriptItem newItem = layoutData->items.at(item); + if (newItem.position != strPos) { + newItem.position = strPos; + layoutData->items.insert(item + 1, newItem); } - splitItem(it - layoutData->items.constBegin(), strPos - it->position); -} - -void QTextEngine::splitItem(int item, int pos) const -{ - if (pos <= 0) - return; - - layoutData->items.insert(item + 1, layoutData->items[item]); - QScriptItem &oldItem = layoutData->items[item]; - QScriptItem &newItem = layoutData->items[item+1]; - newItem.position += pos; - - if (oldItem.num_glyphs) { - // already shaped, break glyphs aswell - int breakGlyph = logClusters(&oldItem)[pos]; - - newItem.num_glyphs = oldItem.num_glyphs - breakGlyph; - oldItem.num_glyphs = breakGlyph; - newItem.glyph_data_offset = oldItem.glyph_data_offset + breakGlyph; - - for (int i = 0; i < newItem.num_glyphs; i++) - logClusters(&newItem)[i] -= breakGlyph; - - QFixed w = 0; - const QGlyphLayout g = shapedGlyphs(&oldItem); - for(int j = 0; j < breakGlyph; ++j) - w += g.advances[j] * !g.attributes[j].dontPrint; - - newItem.width = oldItem.width - w; - oldItem.width = w; - } - -// qDebug("split at position %d itempos=%d", pos, item); } QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const @@ -2932,45 +2963,44 @@ public: }; } -void QTextEngine::resolveAdditionalFormats() const +void QTextEngine::resolveFormats() const { - if (!specialData || specialData->addFormats.isEmpty() - || !specialData->resolvedFormats.isEmpty()) + if (!specialData || specialData->formats.isEmpty()) return; + Q_ASSERT(specialData->resolvedFormats.isEmpty()); - QTextFormatCollection *collection = formats(); + QTextFormatCollection *collection = formatCollection(); - specialData->resolvedFormats.clear(); QVector<QTextCharFormat> resolvedFormats(layoutData->items.count()); - QVarLengthArray<int, 64> addFormatSortedByStart; - addFormatSortedByStart.reserve(specialData->addFormats.count()); - for (int i = 0; i < specialData->addFormats.count(); ++i) { - if (specialData->addFormats.at(i).length >= 0) - addFormatSortedByStart.append(i); + QVarLengthArray<int, 64> formatsSortedByStart; + formatsSortedByStart.reserve(specialData->formats.size()); + for (int i = 0; i < specialData->formats.size(); ++i) { + if (specialData->formats.at(i).length >= 0) + formatsSortedByStart.append(i); } - QVarLengthArray<int, 64> addFormatSortedByEnd = addFormatSortedByStart; - std::sort(addFormatSortedByStart.begin(), addFormatSortedByStart.end(), - FormatRangeComparatorByStart(specialData->addFormats)); - std::sort(addFormatSortedByEnd.begin(), addFormatSortedByEnd.end(), - FormatRangeComparatorByEnd(specialData->addFormats)); + QVarLengthArray<int, 64> formatsSortedByEnd = formatsSortedByStart; + std::sort(formatsSortedByStart.begin(), formatsSortedByStart.end(), + FormatRangeComparatorByStart(specialData->formats)); + std::sort(formatsSortedByEnd.begin(), formatsSortedByEnd.end(), + FormatRangeComparatorByEnd(specialData->formats)); QVarLengthArray<int, 16> currentFormats; - const int *startIt = addFormatSortedByStart.constBegin(); - const int *endIt = addFormatSortedByEnd.constBegin(); + const int *startIt = formatsSortedByStart.constBegin(); + const int *endIt = formatsSortedByEnd.constBegin(); for (int i = 0; i < layoutData->items.count(); ++i) { const QScriptItem *si = &layoutData->items.at(i); int end = si->position + length(si); - while (startIt != addFormatSortedByStart.constEnd() && - specialData->addFormats.at(*startIt).start <= si->position) { + while (startIt != formatsSortedByStart.constEnd() && + specialData->formats.at(*startIt).start <= si->position) { currentFormats.insert(std::upper_bound(currentFormats.begin(), currentFormats.end(), *startIt), *startIt); ++startIt; } - while (endIt != addFormatSortedByEnd.constEnd() && - specialData->addFormats.at(*endIt).start + specialData->addFormats.at(*endIt).length < end) { + while (endIt != formatsSortedByEnd.constEnd() && + specialData->formats.at(*endIt).start + specialData->formats.at(*endIt).length < end) { int *currentFormatIterator = std::lower_bound(currentFormats.begin(), currentFormats.end(), *endIt); if (*endIt < *currentFormatIterator) currentFormatIterator = currentFormats.end(); @@ -2986,7 +3016,7 @@ void QTextEngine::resolveAdditionalFormats() const } if (!currentFormats.isEmpty()) { foreach (int cur, currentFormats) { - const QTextLayout::FormatRange &range = specialData->addFormats.at(cur); + const QTextLayout::FormatRange &range = specialData->formats.at(cur); Q_ASSERT(range.start <= si->position && range.start + range.length >= end); format.merge(range.format); } @@ -3486,15 +3516,15 @@ QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int _lineNum, co logicalItem(-1), item(-1), visualOrder(nItems), - levels(nItems), selection(_selection) { - pos_x = x = QFixed::fromReal(pos.x()); + x = QFixed::fromReal(pos.x()); x += line.x; x += eng->alignLine(line); + QVarLengthArray<uchar> levels(nItems); for (int i = 0; i < nItems; ++i) levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel; QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data()); @@ -3565,7 +3595,7 @@ bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selec return false; int start_glyph = logClusters[from]; - int end_glyph = (to == eng->length(item)) ? si->num_glyphs : logClusters[to]; + int end_glyph = (to == itemLength) ? si->num_glyphs : logClusters[to]; QFixed soff; QFixed swidth; if (si->analysis.bidiLevel %2) { @@ -3590,7 +3620,7 @@ bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selec // If the ending character is also part of a ligature, swidth does // not contain that part yet, we also need to find out the width of // that left part - *selectionWidth += eng->offsetInLigature(si, to, eng->length(item), end_glyph); + *selectionWidth += eng->offsetInLigature(si, to, itemLength, end_glyph); } return true; } diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 342a94de66..13879912d3 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -505,10 +505,10 @@ public: void freeMemory(); int findItem(int strPos) const; - inline QTextFormatCollection *formats() const { + inline QTextFormatCollection *formatCollection() const { if (block.docHandle()) return block.docHandle()->formatCollection(); - return specialData ? specialData->formats.data() : 0; + return specialData ? specialData->formatCollection.data() : 0; } QTextCharFormat format(const QScriptItem *si) const; inline QAbstractTextDocumentLayout *docLayout() const { @@ -572,19 +572,17 @@ public: ItemDecorationList overlineList; inline bool visualCursorMovement() const - { - return (visualMovement || - (block.docHandle() ? block.docHandle()->defaultCursorMoveStyle == Qt::VisualMoveStyle : false)); - } + { return visualMovement || (block.docHandle() && block.docHandle()->defaultCursorMoveStyle == Qt::VisualMoveStyle); } inline int preeditAreaPosition() const { return specialData ? specialData->preeditPosition : -1; } inline QString preeditAreaText() const { return specialData ? specialData->preeditText : QString(); } void setPreeditArea(int position, const QString &text); - inline bool hasFormats() const { return block.docHandle() || (specialData && !specialData->addFormats.isEmpty()); } - inline QList<QTextLayout::FormatRange> additionalFormats() const - { return specialData ? specialData->addFormats : QList<QTextLayout::FormatRange>(); } - void setAdditionalFormats(const QList<QTextLayout::FormatRange> &formatList); + inline bool hasFormats() const + { return block.docHandle() || (specialData && !specialData->formats.isEmpty()); } + inline QList<QTextLayout::FormatRange> formats() const + { return specialData ? specialData->formats : QList<QTextLayout::FormatRange>(); } + void setFormats(const QList<QTextLayout::FormatRange> &formats); private: static void init(QTextEngine *e); @@ -592,15 +590,15 @@ private: struct SpecialData { int preeditPosition; QString preeditText; - QList<QTextLayout::FormatRange> addFormats; + QList<QTextLayout::FormatRange> formats; QVector<QTextCharFormat> resolvedFormats; // only used when no docHandle is available - QScopedPointer<QTextFormatCollection> formats; + QScopedPointer<QTextFormatCollection> formatCollection; }; SpecialData *specialData; - void indexAdditionalFormats(); - void resolveAdditionalFormats() const; + void indexFormats(); + void resolveFormats() const; public: bool atWordSeparator(int position) const; @@ -643,7 +641,6 @@ private: int shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const; #endif int shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const; - void splitItem(int item, int pos) const; int endOfLine(int lineNum); int beginningOfLine(int lineNum); @@ -676,15 +673,14 @@ struct QTextLineItemIterator QTextEngine *eng; QFixed x; - QFixed pos_x; const QScriptLine &line; QScriptItem *si; - int lineNum; - int lineEnd; - int firstItem; - int lastItem; - int nItems; + const int lineNum; + const int lineEnd; + const int firstItem; + const int lastItem; + const int nItems; int logicalItem; int item; int itemLength; @@ -697,7 +693,6 @@ struct QTextLineItemIterator QFixed itemWidth; QVarLengthArray<int> visualOrder; - QVarLengthArray<uchar> levels; const QTextLayout::FormatRange *selection; }; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 4879ae51d7..9919ce6bb4 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -505,7 +505,7 @@ QString QTextLayout::preeditAreaText() const */ void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList) { - d->setAdditionalFormats(formatList); + d->setFormats(formatList); if (d->block.docHandle()) d->block.docHandle()->documentChange(d->block.position(), d->block.length()); @@ -518,7 +518,7 @@ void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList) */ QList<QTextLayout::FormatRange> QTextLayout::additionalFormats() const { - return d->additionalFormats(); + return d->formats(); } /*! @@ -567,7 +567,7 @@ bool QTextLayout::cacheEnabled() const */ void QTextLayout::setCursorMoveStyle(Qt::CursorMoveStyle style) { - d->visualMovement = style == Qt::VisualMoveStyle ? true : false; + d->visualMovement = style == Qt::VisualMoveStyle; } /*! @@ -1735,6 +1735,7 @@ void QTextLine::layout_helper(int maxGlyphs) int item = -1; int newItem = eng->findItem(line.from); + Q_ASSERT(newItem >= 0); LB_DEBUG("from: %d: item=%d, total %d, width available %f", line.from, newItem, eng->layoutData->items.size(), line.width.toReal()); @@ -2212,14 +2213,10 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const if (si.analysis.flags >= QScriptAnalysis::TabOrObject) continue; - QPointF pos(iterator.x.toReal(), y); - if (from >= 0 && length >= 0 && - (from >= si.position + eng->length(&si) - || from + length <= si.position - || from + length <= iterator.itemStart - || from >= iterator.itemEnd)) { + if (from >= 0 && length >= 0 && (from >= iterator.itemEnd || from + length <= iterator.itemStart)) continue; - } + + QPointF pos(iterator.x.toReal(), y); QFont font; QGlyphRun::GlyphRunFlags flags; @@ -2240,15 +2237,13 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const } int relativeFrom = qMax(iterator.itemStart, from) - si.position; - int relativeTo = qMin(iterator.itemEnd - 1, from + length - 1) - si.position; + int relativeTo = qMin(iterator.itemEnd, from + length) - 1 - si.position; unsigned short *logClusters = eng->logClusters(&si); int glyphsStart = logClusters[relativeFrom]; - int glyphsEnd = (relativeTo == eng->length(&si)) - ? si.num_glyphs - 1 - : logClusters[relativeTo]; + int glyphsEnd = (relativeTo == iterator.itemLength) ? si.num_glyphs - 1 : logClusters[relativeTo]; // the glyph index right next to the requested range - int nextGlyphIndex = relativeTo < eng->length(&si) - 1 ? logClusters[relativeTo + 1] : si.num_glyphs; + int nextGlyphIndex = (relativeTo < iterator.itemLength - 1) ? logClusters[relativeTo + 1] : si.num_glyphs; if (nextGlyphIndex - 1 > glyphsEnd) glyphsEnd = nextGlyphIndex - 1; bool startsInsideLigature = relativeFrom > 0 && logClusters[relativeFrom - 1] == glyphsStart; diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index c67769ad48..091129f5be 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -77,10 +77,8 @@ SOURCES += \ text/qdistancefield.cpp SOURCES += \ - text/qfont_qpa.cpp \ - text/qfontengine_qpa.cpp \ - text/qplatformfontdatabase.cpp \ - text/qrawfont_qpa.cpp + text/qfontengine_qpf2.cpp \ + text/qplatformfontdatabase.cpp HEADERS += \ text/qplatformfontdatabase.h |