diff options
Diffstat (limited to 'src/gui/text')
-rw-r--r-- | src/gui/text/qabstracttextdocumentlayout.cpp | 20 | ||||
-rw-r--r-- | src/gui/text/qfont.cpp | 103 | ||||
-rw-r--r-- | src/gui/text/qfont_p.h | 5 | ||||
-rw-r--r-- | src/gui/text/qfontdatabase.cpp | 2 | ||||
-rw-r--r-- | src/gui/text/qfontengine_ft.cpp | 2 | ||||
-rw-r--r-- | src/gui/text/qfontengine_p.h | 2 | ||||
-rw-r--r-- | src/gui/text/qfontengine_qpa.cpp | 85 | ||||
-rw-r--r-- | src/gui/text/qfontengine_qpa_p.h | 5 | ||||
-rw-r--r-- | src/gui/text/qfontmetrics.cpp | 78 | ||||
-rw-r--r-- | src/gui/text/qrawfont.cpp | 6 | ||||
-rw-r--r-- | src/gui/text/qrawfont.h | 1 | ||||
-rw-r--r-- | src/gui/text/qtextcursor.cpp | 10 | ||||
-rw-r--r-- | src/gui/text/qtextdocument.cpp | 14 | ||||
-rw-r--r-- | src/gui/text/qtextdocumentwriter.cpp | 8 | ||||
-rw-r--r-- | src/gui/text/qtextengine.cpp | 175 | ||||
-rw-r--r-- | src/gui/text/qtextengine_p.h | 8 | ||||
-rw-r--r-- | src/gui/text/qtextlayout.cpp | 44 | ||||
-rw-r--r-- | src/gui/text/qtextlayout.h | 7 | ||||
-rw-r--r-- | src/gui/text/qtextlist.cpp | 2 | ||||
-rw-r--r-- | src/gui/text/qtexttable.cpp | 12 |
20 files changed, 391 insertions, 198 deletions
diff --git a/src/gui/text/qabstracttextdocumentlayout.cpp b/src/gui/text/qabstracttextdocumentlayout.cpp index 86de48b1dc..589c0f701f 100644 --- a/src/gui/text/qabstracttextdocumentlayout.cpp +++ b/src/gui/text/qabstracttextdocumentlayout.cpp @@ -100,14 +100,14 @@ QT_BEGIN_NAMESPACE custom text object into a document: \list - \o Choose an \a objectType. The \a objectType is an integer with a + \li Choose an \a objectType. The \a objectType is an integer with a value greater or equal to QTextFormat::UserObject. - \o Create a QTextCharFormat object and set the object type to the + \li Create a QTextCharFormat object and set the object type to the chosen type using the setObjectType() function. - \o Implement the QTextObjectInterface class. - \o Call QAbstractTextDocumentLayout::registerHandler() with an instance of your + \li Implement the QTextObjectInterface class. + \li Call QAbstractTextDocumentLayout::registerHandler() with an instance of your QTextObjectInterface subclass to register your object type. - \o Insert QChar::ObjectReplacementCharacter with the aforementioned + \li Insert QChar::ObjectReplacementCharacter with the aforementioned QTextCharFormat of the chosen object type into the document. As mentioned, the functions of QTextObjectInterface \l{QTextObjectInterface::}{intrinsicSize()} and @@ -269,17 +269,17 @@ QT_BEGIN_NAMESPACE implementation of this function would have to do the following: \list - \o Determine the list of changed \l{QTextBlock}(s) using the parameters + \li Determine the list of changed \l{QTextBlock}(s) using the parameters provided. - \o Each QTextBlock object's corresponding QTextLayout object needs to + \li Each QTextBlock object's corresponding QTextLayout object needs to be processed. You can access the \l{QTextBlock}'s layout using the QTextBlock::layout() function. This processing should take the document's page size into consideration. - \o If the total number of pages changed, the pageCountChanged() signal + \li If the total number of pages changed, the pageCountChanged() signal should be emitted. - \o If the total size changed, the documentSizeChanged() signal should + \li If the total size changed, the documentSizeChanged() signal should be emitted. - \o The update() signal should be emitted to schedule a repaint of areas + \li The update() signal should be emitted to schedule a repaint of areas in the layout that require repainting. \endlist diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index ee833a06cf..c68452d55a 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -419,14 +419,14 @@ QFontEngineData::~QFontEngineData() \target fontmatching The font matching algorithm works as follows: \list 1 - \o The specified font family is searched for. - \o If not found, the styleHint() is used to select a replacement + \li The specified font family is searched for. + \li If not found, the styleHint() is used to select a replacement family. - \o Each replacement font family is searched for. - \o If none of these are found or there was no styleHint(), "helvetica" + \li Each replacement font family is searched for. + \li If none of these are found or there was no styleHint(), "helvetica" will be searched for. - \o If "helvetica" isn't found Qt will try the lastResortFamily(). - \o If the lastResortFamily() isn't found Qt will try the + \li If "helvetica" isn't found Qt will try the lastResortFamily(). + \li If the lastResortFamily() isn't found Qt will try the lastResortFont() which will always return a name of some kind. \endlist @@ -440,10 +440,10 @@ QFontEngineData::~QFontEngineData() Once a font is found, the remaining attributes are matched in order of priority: \list 1 - \o fixedPitch() - \o pointSize() (see below) - \o weight() - \o style() + \li fixedPitch() + \li pointSize() (see below) + \li weight() + \li style() \endlist If you have a font which matches on family, even if none of the @@ -861,35 +861,35 @@ int QFont::pointSize() const \table \header - \o - \o PreferDefaultHinting - \o PreferNoHinting - \o PreferVerticalHinting - \o PreferFullHinting + \li + \li PreferDefaultHinting + \li PreferNoHinting + \li PreferVerticalHinting + \li PreferFullHinting \row - \o Windows Vista (w/o Platform Update) and earlier - \o Full hinting - \o Full hinting - \o Full hinting - \o Full hinting + \li Windows Vista (w/o Platform Update) and earlier + \li Full hinting + \li Full hinting + \li Full hinting + \li Full hinting \row - \o Windows 7 and Windows Vista (w/Platform Update) and DirectWrite enabled in Qt - \o Full hinting - \o Vertical hinting - \o Vertical hinting - \o Full hinting + \li Windows 7 and Windows Vista (w/Platform Update) and DirectWrite enabled in Qt + \li Full hinting + \li Vertical hinting + \li Vertical hinting + \li Full hinting \row - \o FreeType - \o Operating System setting - \o No hinting - \o Vertical hinting (light) - \o Full hinting + \li FreeType + \li Operating System setting + \li No hinting + \li Vertical hinting (light) + \li Full hinting \row - \o Cocoa on Mac OS X - \o No hinting - \o No hinting - \o No hinting - \o No hinting + \li Cocoa on Mac OS X + \li No hinting + \li No hinting + \li No hinting + \li No hinting \endtable \note Please be aware that altering the hinting preference on Windows is available through @@ -2277,7 +2277,7 @@ QDataStream &operator>>(QDataStream &s, QFont &font) There are three ways to create a QFontInfo object. \list 1 - \o Calling the QFontInfo constructor with a QFont creates a font + \li Calling the QFontInfo constructor with a QFont creates a font info object for a screen-compatible font, i.e. the font cannot be a printer font. If the font is changed later, the font info object is \e not updated. @@ -2286,12 +2286,12 @@ QDataStream &operator>>(QDataStream &s, QFont &font) inaccurate. Printer fonts are not always accessible so the nearest screen font is used if a printer font is supplied.) - \o QWidget::fontInfo() returns the font info for a widget's font. + \li QWidget::fontInfo() returns the font info for a widget's font. This is equivalent to calling QFontInfo(widget->font()). If the widget's font is changed later, the font info object is \e not updated. - \o QPainter::fontInfo() returns the font info for a painter's + \li QPainter::fontInfo() returns the font info for a painter's current font. If the painter's font is changed later, the font info object is \e not updated. \endlist @@ -2715,18 +2715,22 @@ QFontEngine *QFontCache::findEngine(const Key &key) EngineCache::Iterator it = engineCache.find(key), end = engineCache.end(); if (it == end) return 0; - // found... update the hitcount and timestamp - it.value().hits++; - it.value().timestamp = ++current_timestamp; + updateHitCountAndTimeStamp(it.value()); + + return it.value().data; +} + +void QFontCache::updateHitCountAndTimeStamp(Engine &value) +{ + value.hits++; + value.timestamp = ++current_timestamp; FC_DEBUG("QFontCache: found font engine\n" " %p: timestamp %4u hits %3u ref %2d/%2d, type '%s'", - it.value().data, it.value().timestamp, it.value().hits, - it.value().data->ref.load(), it.value().data->cache_count, - it.value().data->name()); - - return it.value().data; + value.data, value.timestamp, value.hits, + value.data->ref.load(), value.data->cache_count, + value.data->name()); } void QFontCache::removeEngine(QFontEngine *engine) @@ -2743,14 +2747,17 @@ void QFontCache::removeEngine(QFontEngine *engine) } } -void QFontCache::insertEngine(const Key &key, QFontEngine *engine) +void QFontCache::insertEngine(const Key &key, QFontEngine *engine, bool insertMulti) { FC_DEBUG("QFontCache: inserting new engine %p", engine); Engine data(engine); data.timestamp = ++current_timestamp; - engineCache.insert(key, data); + if (insertMulti) + engineCache.insertMulti(key, data); + else + engineCache.insert(key, data); // only increase the cost if this is the first time we insert the engine if (engine->cache_count == 0) diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h index d10249201a..06cf787880 100644 --- a/src/gui/text/qfont_p.h +++ b/src/gui/text/qfont_p.h @@ -242,9 +242,10 @@ public: EngineCache engineCache; QFontEngine *findEngine(const Key &key); - void insertEngine(const Key &key, QFontEngine *engine); - void removeEngine(QFontEngine *engine); + void updateHitCountAndTimeStamp(Engine &value); + void insertEngine(const Key &key, QFontEngine *engine, bool insertMulti = false); + void removeEngine(QFontEngine *engine); private: void increaseCost(uint cost); diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 7fa486e1ee..468d029cf2 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -2244,7 +2244,7 @@ int QFontDatabase::addApplicationFont(const QString &fileName) Currently only TrueType fonts and TrueType font collections are supported. - \bold{Note:} Adding application fonts on Unix/X11 platforms without fontconfig is + \b{Note:} Adding application fonts on Unix/X11 platforms without fontconfig is currently not supported. \sa addApplicationFont(), applicationFontFamilies(), removeApplicationFont() diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 14e2dba364..8880eb7cb3 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -877,7 +877,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, if (err != FT_Err_Ok) qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph); - if (!set || set->outline_drawing || fetchMetricsOnly) + if ((!set || set->outline_drawing) && fetchMetricsOnly) return 0; FT_GlyphSlot slot = face->glyph; diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index cf9c26f2a4..44464ee788 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -85,6 +85,7 @@ struct QGlyphLayout; class Q_GUI_EXPORT QFontEngine : public QObject { + Q_OBJECT public: enum Type { Box, @@ -343,6 +344,7 @@ private: class Q_GUI_EXPORT QFontEngineMulti : public QFontEngine { + Q_OBJECT public: explicit QFontEngineMulti(int engineCount); ~QFontEngineMulti(); diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp index 33657367fa..48679824a4 100644 --- a/src/gui/text/qfontengine_qpa.cpp +++ b/src/gui/text/qfontengine_qpa.cpp @@ -46,8 +46,10 @@ #include <QtCore/QDir> #include <QtCore/QBuffer> -#include <QtGui/QPlatformFontDatabase> #include <QtGui/private/qpaintengine_raster_p.h> +#include <QtGui/private/qguiapplication_p.h> +#include <QtGui/QPlatformFontDatabase> +#include <QtGui/QPlatformIntegration> QT_BEGIN_NAMESPACE @@ -662,6 +664,20 @@ void QPAGenerator::writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value 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) +{ + init(fe); +} + +void QFontEngineMultiQPA::init(QFontEngine *fe) { Q_ASSERT(fe && fe->type() != QFontEngine::Multi); engines[0] = fe; @@ -672,18 +688,73 @@ QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script, const QSt void QFontEngineMultiQPA::loadEngine(int at) { + bool canLoadFallbackEngine = true; + if (!fallbacksQueried) { + // Original FontEngine to restore after the fill. + QFontEngine *fe = engines[0]; + fallbackFamilies = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fallbacksForFamily(fe->fontDef.family, QFont::Style(fe->fontDef.style) + , QFont::AnyStyle, QUnicodeTables::Script(script)); + if (fallbackFamilies.size() > 1) { + engines.fill(0, fallbackFamilies.size() + 1); + engines[0] = fe; + } else { + // Turns out we lied about having any fallback at all. + canLoadFallbackEngine = false; + engines[1] = fe; + } + fallbacksQueried = true; + } 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, false); + if (canLoadFallbackEngine) { + request.styleStrategy |= QFont::NoFontMerging; + request.family = fallbackFamilies.at(at-1); + engines[at] = QFontDatabase::findFont(script, + /*fontprivate = */0, + request, /*multi = */false); + } Q_ASSERT(engines[at]); engines[at]->ref.ref(); engines[at]->fontDef = request; } +/* + This is used indirectly by QtWebKit when using QTextLayout::setRawFont + + The purpose of this is to provide the necessary font fallbacks when drawing complex + text. Since QtWebKit 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) { + QFontEngineMulti *cachedEngine = qobject_cast<QFontEngineMulti *>(it.value().data); + if (faceIsLocal || (cachedEngine && fe == cachedEngine->engine(0))) { + engine = cachedEngine; + fc->updateHitCountAndTimeStamp(it.value()); + break; + } + it++; + } + if (!engine) { + engine = new QFontEngineMultiQPA(fe, 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_qpa_p.h index ed2e071ac2..16991ad2ca 100644 --- a/src/gui/text/qfontengine_qpa_p.h +++ b/src/gui/text/qfontengine_qpa_p.h @@ -249,13 +249,18 @@ public: QFontEngineMultiQPA(QFontEngine *fe, int script, const QStringList &fallbacks); 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); } private: + QFontEngineMultiQPA(QFontEngine *fe, int script); + void init(QFontEngine *fe); + QStringList fallbackFamilies; int script; + bool fallbacksQueried; }; QT_END_NAMESPACE diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index 283494e316..7209fbdfc3 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -76,7 +76,7 @@ extern void qt_format_text(const QFont& font, const QRectF &_r, QFontMetrics object: \list 1 - \o Calling the QFontMetrics constructor with a QFont creates a + \li Calling the QFontMetrics constructor with a QFont creates a font metrics object for a screen-compatible font, i.e. the font cannot be a printer font. If the font is changed later, the font metrics object is \e not updated. @@ -85,12 +85,12 @@ extern void qt_format_text(const QFont& font, const QRectF &_r, inaccurate. Printer fonts are not always accessible so the nearest screen font is used if a printer font is supplied.) - \o QWidget::fontMetrics() returns the font metrics for a widget's + \li QWidget::fontMetrics() returns the font metrics for a widget's font. This is equivalent to QFontMetrics(widget->font()). If the widget's font is changed later, the font metrics object is \e not updated. - \o QPainter::fontMetrics() returns the font metrics for a + \li QPainter::fontMetrics() returns the font metrics for a painter's current font. If the painter's font is changed later, the font metrics object is \e not updated. \endlist @@ -713,20 +713,20 @@ QRect QFontMetrics::boundingRect(QChar ch) const The \a flags argument is the bitwise OR of the following flags: \list - \o Qt::AlignLeft aligns to the left border, except for + \li Qt::AlignLeft aligns to the left border, except for Arabic and Hebrew where it aligns to the right. - \o Qt::AlignRight aligns to the right border, except for + \li Qt::AlignRight aligns to the right border, except for Arabic and Hebrew where it aligns to the left. - \o Qt::AlignJustify produces justified text. - \o Qt::AlignHCenter aligns horizontally centered. - \o Qt::AlignTop aligns to the top border. - \o Qt::AlignBottom aligns to the bottom border. - \o Qt::AlignVCenter aligns vertically centered - \o Qt::AlignCenter (== \c{Qt::AlignHCenter | Qt::AlignVCenter}) - \o Qt::TextSingleLine ignores newline characters in the text. - \o Qt::TextExpandTabs expands tabs (see below) - \o Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. - \o Qt::TextWordWrap breaks the text to fit the rectangle. + \li Qt::AlignJustify produces justified text. + \li Qt::AlignHCenter aligns horizontally centered. + \li Qt::AlignTop aligns to the top border. + \li Qt::AlignBottom aligns to the bottom border. + \li Qt::AlignVCenter aligns vertically centered + \li Qt::AlignCenter (== \c{Qt::AlignHCenter | Qt::AlignVCenter}) + \li Qt::TextSingleLine ignores newline characters in the text. + \li Qt::TextExpandTabs expands tabs (see below) + \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. + \li Qt::TextWordWrap breaks the text to fit the rectangle. \endlist Qt::Horizontal alignment defaults to Qt::AlignLeft and vertical @@ -780,10 +780,10 @@ QRect QFontMetrics::boundingRect(const QRect &rect, int flags, const QString &te The \a flags argument is the bitwise OR of the following flags: \list - \o Qt::TextSingleLine ignores newline characters. - \o Qt::TextExpandTabs expands tabs (see below) - \o Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. - \o Qt::TextWordBreak breaks the text to fit the rectangle. + \li Qt::TextSingleLine ignores newline characters. + \li Qt::TextExpandTabs expands tabs (see below) + \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. + \li Qt::TextWordBreak breaks the text to fit the rectangle. \endlist If Qt::TextExpandTabs is set in \a flags, then: if \a tabArray is @@ -1490,20 +1490,20 @@ QRectF QFontMetricsF::boundingRect(QChar ch) const The \a flags argument is the bitwise OR of the following flags: \list - \o Qt::AlignLeft aligns to the left border, except for + \li Qt::AlignLeft aligns to the left border, except for Arabic and Hebrew where it aligns to the right. - \o Qt::AlignRight aligns to the right border, except for + \li Qt::AlignRight aligns to the right border, except for Arabic and Hebrew where it aligns to the left. - \o Qt::AlignJustify produces justified text. - \o Qt::AlignHCenter aligns horizontally centered. - \o Qt::AlignTop aligns to the top border. - \o Qt::AlignBottom aligns to the bottom border. - \o Qt::AlignVCenter aligns vertically centered - \o Qt::AlignCenter (== \c{Qt::AlignHCenter | Qt::AlignVCenter}) - \o Qt::TextSingleLine ignores newline characters in the text. - \o Qt::TextExpandTabs expands tabs (see below) - \o Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. - \o Qt::TextWordWrap breaks the text to fit the rectangle. + \li Qt::AlignJustify produces justified text. + \li Qt::AlignHCenter aligns horizontally centered. + \li Qt::AlignTop aligns to the top border. + \li Qt::AlignBottom aligns to the bottom border. + \li Qt::AlignVCenter aligns vertically centered + \li Qt::AlignCenter (== \c{Qt::AlignHCenter | Qt::AlignVCenter}) + \li Qt::TextSingleLine ignores newline characters in the text. + \li Qt::TextExpandTabs expands tabs (see below) + \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. + \li Qt::TextWordWrap breaks the text to fit the rectangle. \endlist Qt::Horizontal alignment defaults to Qt::AlignLeft and vertical @@ -1517,9 +1517,9 @@ QRectF QFontMetricsF::boundingRect(QChar ch) const If Qt::TextExpandTabs is set in \a flags, the following behavior is used to interpret tab characters in the text: \list - \o If \a tabArray is non-null, it specifies a 0-terminated sequence of + \li If \a tabArray is non-null, it specifies a 0-terminated sequence of pixel-positions for tabs in the text. - \o If \a tabStops is non-zero, it is used as the tab spacing (in pixels). + \li If \a tabStops is non-zero, it is used as the tab spacing (in pixels). \endlist Note that the bounding rectangle may extend to the left of (0, 0), @@ -1559,10 +1559,10 @@ QRectF QFontMetricsF::boundingRect(const QRectF &rect, int flags, const QString& The \a flags argument is the bitwise OR of the following flags: \list - \o Qt::TextSingleLine ignores newline characters. - \o Qt::TextExpandTabs expands tabs (see below) - \o Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. - \o Qt::TextWordBreak breaks the text to fit the rectangle. + \li Qt::TextSingleLine ignores newline characters. + \li Qt::TextExpandTabs expands tabs (see below) + \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. + \li Qt::TextWordBreak breaks the text to fit the rectangle. \endlist These flags are defined in \l{Qt::TextFlags}. @@ -1570,9 +1570,9 @@ QRectF QFontMetricsF::boundingRect(const QRectF &rect, int flags, const QString& If Qt::TextExpandTabs is set in \a flags, the following behavior is used to interpret tab characters in the text: \list - \o If \a tabArray is non-null, it specifies a 0-terminated sequence of + \li If \a tabArray is non-null, it specifies a 0-terminated sequence of pixel-positions for tabs in the text. - \o If \a tabStops is non-zero, it is used as the tab spacing (in pixels). + \li If \a tabStops is non-zero, it is used as the tab spacing (in pixels). \endlist Newline characters are processed as line breaks. diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp index 79793d5845..9fbeef4685 100644 --- a/src/gui/text/qrawfont.cpp +++ b/src/gui/text/qrawfont.cpp @@ -86,13 +86,13 @@ QT_BEGIN_NAMESPACE QRawFont can be constructed in a number of ways: \list - \o It can be constructed by calling QTextLayout::glyphs() or QTextFragment::glyphs(). The + \li It can be constructed by calling QTextLayout::glyphs() or QTextFragment::glyphs(). The returned QGlyphs objects will contain QRawFont objects which represent the actual fonts used to render each portion of the text. - \o It can be constructed by passing a QFont object to QRawFont::fromFont(). The function + \li It can be constructed by passing a QFont object to QRawFont::fromFont(). The function will return a QRawFont object representing the font that will be selected as response to the QFont query and the selected writing system. - \o It can be constructed by passing a file name or QByteArray directly to the QRawFont + \li It can be constructed by passing a file name or QByteArray directly to the QRawFont constructor, or by calling loadFromFile() or loadFromData(). In this case, the font will not be registered in QFontDatabase, and it will not be available as part of regular font selection. diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h index 5cd996e705..bc5f6621c8 100644 --- a/src/gui/text/qrawfont.h +++ b/src/gui/text/qrawfont.h @@ -138,6 +138,7 @@ public: private: friend class QRawFontPrivate; friend class QTextLayout; + friend class QTextEngine; QExplicitlySharedDataPointer<QRawFontPrivate> d; }; diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp index cbffc4315f..02fd921fac 100644 --- a/src/gui/text/qtextcursor.cpp +++ b/src/gui/text/qtextcursor.cpp @@ -950,15 +950,15 @@ QTextLayout *QTextCursorPrivate::blockLayout(QTextBlock &block) const{ document with the cursor: \list - \i Lists are ordered sequences of block elements that are decorated with + \li Lists are ordered sequences of block elements that are decorated with bullet points or symbols. These are inserted in a specified format with insertList(). - \i Tables are inserted with the insertTable() function, and can be + \li Tables are inserted with the insertTable() function, and can be given an optional format. These contain an array of cells that can be traversed using the cursor. - \i Inline images are inserted with insertImage(). The image to be + \li Inline images are inserted with insertImage(). The image to be used can be specified in an image format, or by name. - \i Frames are inserted by calling insertFrame() with a specified format. + \li Frames are inserted by calling insertFrame() with a specified format. \endlist Actions can be grouped (i.e. treated as a single action for @@ -1621,7 +1621,7 @@ void QTextCursor::selectedTableCells(int *firstRow, int *numRows, int *firstColu /*! Clears the current selection by setting the anchor to the cursor position. - Note that it does \bold{not} delete the text of the selection. + Note that it does \b{not} delete the text of the selection. \sa removeSelectedText() hasSelection() */ diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 1fad064b5c..a8991d5428 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -261,14 +261,14 @@ QTextCodec *Qt::codecForHtml(const QByteArray &ba) system. The following are the undo/redo operations of a QTextDocument: \list - \o Insertion or removal of characters. A sequence of insertions or removals + \li Insertion or removal of characters. A sequence of insertions or removals within the same text block are regarded as a single undo/redo operation. - \o Insertion or removal of text blocks. Sequences of insertion or removals + \li Insertion or removal of text blocks. Sequences of insertion or removals in a single operation (e.g., by selecting and then deleting text) are regarded as a single undo/redo operation. - \o Text character format changes. - \o Text block format changes. - \o Text block group format changes. + \li Text character format changes. + \li Text block format changes. + \li Text block group format changes. \endlist \sa QTextCursor, QTextEdit, \link richtext.html Rich Text Processing\endlink , {Text Object Example} @@ -887,7 +887,7 @@ QChar QTextDocument::characterAt(int pos) const The style sheet needs to be compliant to CSS 2.1 syntax. - \bold{Note:} Changing the default style sheet does not have any effect to the existing content + \b{Note:} Changing the default style sheet does not have any effect to the existing content of the document. \sa {Supported HTML Subset} @@ -1169,7 +1169,7 @@ void QTextDocument::setPlainText(const QString &text) The HTML formatting is respected as much as possible; for example, "<b>bold</b> text" will produce text where the first word has a font - weight that gives it a bold appearance: "\bold{bold} text". + weight that gives it a bold appearance: "\b{bold} text". \note It is the responsibility of the caller to make sure that the text is correctly decoded when a QString containing HTML is created diff --git a/src/gui/text/qtextdocumentwriter.cpp b/src/gui/text/qtextdocumentwriter.cpp index d43a61866d..b0bbeb7a47 100644 --- a/src/gui/text/qtextdocumentwriter.cpp +++ b/src/gui/text/qtextdocumentwriter.cpp @@ -345,10 +345,10 @@ QTextCodec *QTextDocumentWriter::codec() const By default, Qt can write the following formats: \table - \header \o Format \o Description - \row \o plaintext \o Plain text - \row \o HTML \o HyperText Markup Language - \row \o ODF \o OpenDocument Format + \header \li Format \li Description + \row \li plaintext \li Plain text + \row \li HTML \li HyperText Markup Language + \row \li ODF \li OpenDocument Format \endtable \sa setFormat() diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index c63f0fede8..0460db14d5 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -53,13 +53,18 @@ #include "qstring.h" #include <private/qunicodetables_p.h> #include "qtextdocument_p.h" +#include "qrawfont.h" +#include "qrawfont_p.h" #include <qguiapplication.h> #include <qinputmethod.h> #include <stdlib.h> +#include "qfontengine_qpa_p.h" QT_BEGIN_NAMESPACE +static const float smallCapsFraction = 0.7; + namespace { // Helper class used in QTextEngine::itemize // keep it out here to allow us to keep supporting various compilers. @@ -900,13 +905,25 @@ void QTextEngine::shapeText(int item) const return; QGlyphLayout glyphs = shapedGlyphs(&si); - QFont font = this->font(si); - bool letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute; - QFixed letterSpacing = font.d->letterSpacing; - QFixed wordSpacing = font.d->wordSpacing; + bool letterSpacingIsAbsolute; + QFixed letterSpacing, wordSpacing; +#ifndef QT_NO_RAWFONT + if (useRawFont) { + QTextCharFormat f = format(&si); + wordSpacing = QFixed::fromReal(f.fontWordSpacing()); + letterSpacing = QFixed::fromReal(f.fontLetterSpacing()); + letterSpacingIsAbsolute = true; + } else +#endif + { + QFont font = this->font(si); + letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute; + letterSpacing = font.d->letterSpacing; + wordSpacing = font.d->wordSpacing; - if (letterSpacingIsAbsolute && letterSpacing.value()) - letterSpacing *= font.d->dpi / qt_defaultDpiY(); + if (letterSpacingIsAbsolute && letterSpacing.value()) + letterSpacing *= font.d->dpi / qt_defaultDpiY(); + } if (letterSpacing != 0) { for (int i = 1; i < si.num_glyphs; ++i) { @@ -973,7 +990,14 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading); - bool kerningEnabled = this->font(si).d->kerning; + bool kerningEnabled; +#ifndef QT_NO_RAWFONT + if (useRawFont) { + QTextCharFormat f = format(&si); + kerningEnabled = f.fontKerning(); + } else +#endif + kerningEnabled = this->font(si).d->kerning; HB_ShaperItem entire_shaper_item; qMemSet(&entire_shaper_item, 0, sizeof(entire_shaper_item)); @@ -1159,6 +1183,9 @@ static void init(QTextEngine *e) e->underlinePositions = 0; e->specialData = 0; e->stackEngine = false; +#ifndef QT_NO_RAWFONT + e->useRawFont = false; +#endif } QTextEngine::QTextEngine() @@ -1401,7 +1428,21 @@ void QTextEngine::itemize() const ++it; } } else { - itemizer.generate(0, length, static_cast<QFont::Capitalization> (fnt.d->capital)); +#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); + if (range.format.fontCapitalization()) { + itemizer.generate(lastIndex, range.start - lastIndex, QFont::MixedCase); + itemizer.generate(range.start, range.length, range.format.fontCapitalization()); + lastIndex = range.start + range.length; + } + } + itemizer.generate(lastIndex, length - lastIndex, QFont::MixedCase); + } else +#endif + itemizer.generate(0, length, static_cast<QFont::Capitalization> (fnt.d->capital)); } addRequiredBoundaries(); @@ -1663,59 +1704,85 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix int script = si.analysis.script; QFont font = fnt; - if (hasFormats()) { - if (feCache.prevFontEngine && feCache.prevPosition == si.position && feCache.prevLength == length(&si) && feCache.prevScript == script) { +#ifndef QT_NO_RAWFONT + if (useRawFont && rawFont.isValid()) { + if (feCache.prevFontEngine && feCache.prevFontEngine->type() == QFontEngine::Multi && feCache.prevScript == script) { engine = feCache.prevFontEngine; - scaledEngine = feCache.prevScaledFontEngine; } else { - QTextCharFormat f = format(&si); - font = f.font(); - - if (block.docHandle() && block.docHandle()->layout()) { - // Make sure we get the right dpi on printers - QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); - if (pdev) - font = QFont(font, pdev); - } else { - font = font.resolve(fnt); - } - engine = font.d->engineForScript(script); - QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); - if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { - if (font.pointSize() != -1) - font.setPointSize((font.pointSize() * 2) / 3); - else - font.setPixelSize((font.pixelSize() * 2) / 3); - scaledEngine = font.d->engineForScript(script); - } + engine = QFontEngineMultiQPA::createMultiFontEngine(rawFont.d->fontEngine, script); feCache.prevFontEngine = engine; - if (engine) - engine->ref.ref(); - feCache.prevScaledFontEngine = scaledEngine; - if (scaledEngine) - scaledEngine->ref.ref(); feCache.prevScript = script; - feCache.prevPosition = si.position; - feCache.prevLength = length(&si); + engine->ref.ref(); + if (feCache.prevScaledFontEngine) + releaseCachedFontEngine(feCache.prevScaledFontEngine); } - } else { - if (feCache.prevFontEngine && feCache.prevScript == script && feCache.prevPosition == -1) - engine = feCache.prevFontEngine; - else { - engine = font.d->engineForScript(script); - feCache.prevFontEngine = engine; - if (engine) - engine->ref.ref(); - feCache.prevScript = script; - feCache.prevPosition = -1; - feCache.prevLength = -1; - feCache.prevScaledFontEngine = 0; + if (si.analysis.flags & QFont::SmallCaps) { + if (feCache.prevScaledFontEngine) { + scaledEngine = feCache.prevScaledFontEngine; + } else { + QFontEngine *scEngine = rawFont.d->fontEngine->cloneWithSize(smallCapsFraction * rawFont.pixelSize()); + scaledEngine = QFontEngineMultiQPA::createMultiFontEngine(scEngine, script); + scaledEngine->ref.ref(); + feCache.prevScaledFontEngine = scaledEngine; + } + } + } else +#endif + { + if (hasFormats()) { + if (feCache.prevFontEngine && feCache.prevPosition == si.position && feCache.prevLength == length(&si) && feCache.prevScript == script) { + engine = feCache.prevFontEngine; + scaledEngine = feCache.prevScaledFontEngine; + } else { + QTextCharFormat f = format(&si); + font = f.font(); + + if (block.docHandle() && block.docHandle()->layout()) { + // Make sure we get the right dpi on printers + QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); + if (pdev) + font = QFont(font, pdev); + } else { + font = font.resolve(fnt); + } + engine = font.d->engineForScript(script); + QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); + if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { + if (font.pointSize() != -1) + font.setPointSize((font.pointSize() * 2) / 3); + else + font.setPixelSize((font.pixelSize() * 2) / 3); + scaledEngine = font.d->engineForScript(script); + } + feCache.prevFontEngine = engine; + if (engine) + engine->ref.ref(); + feCache.prevScaledFontEngine = scaledEngine; + if (scaledEngine) + scaledEngine->ref.ref(); + feCache.prevScript = script; + feCache.prevPosition = si.position; + feCache.prevLength = length(&si); + } + } else { + if (feCache.prevFontEngine && feCache.prevScript == script && feCache.prevPosition == -1) + engine = feCache.prevFontEngine; + else { + engine = font.d->engineForScript(script); + feCache.prevFontEngine = engine; + if (engine) + engine->ref.ref(); + feCache.prevScript = script; + feCache.prevPosition = -1; + feCache.prevLength = -1; + feCache.prevScaledFontEngine = 0; + } } - } - if (si.analysis.flags == QScriptAnalysis::SmallCaps) { - QFontPrivate *p = font.d->smallCapsFontPrivate(); - scaledEngine = p->engineForScript(script); + if (si.analysis.flags == QScriptAnalysis::SmallCaps) { + QFontPrivate *p = font.d->smallCapsFontPrivate(); + scaledEngine = p->engineForScript(script); + } } if (ascent) { diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index b29f626b68..6f1fd713f1 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -581,7 +581,10 @@ public: mutable FontEngineCache feCache; QString text; - QFont fnt; + mutable QFont fnt; +#ifndef QT_NO_RAWFONT + QRawFont rawFont; +#endif QTextBlock block; QTextOption option; @@ -594,6 +597,9 @@ public: uint stackEngine : 1; uint forceJustification : 1; uint visualMovement : 1; +#ifndef QT_NO_RAWFONT + uint useRawFont : 1; +#endif int *underlinePositions; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 943caea644..d5b05a8957 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -361,6 +361,22 @@ QTextLayout::~QTextLayout() delete d; } +#ifndef QT_NO_RAWFONT +/*! + \internal + Sets a raw font, to be used with QTextLayout::glyphRuns. + Note that this only supports the needs of WebKit. + Use of this function with e.g. QTextLayout::draw will result + in undefined behaviour. +*/ +void QTextLayout::setRawFont(const QRawFont &rawFont) +{ + d->rawFont = rawFont; + d->useRawFont = true; + d->resetFontEngineCache(); +} +#endif + /*! Sets the layout's font to the given \a font. The layout is invalidated and must be laid out again. @@ -370,6 +386,9 @@ QTextLayout::~QTextLayout() void QTextLayout::setFont(const QFont &font) { d->fnt = font; +#ifndef QT_NO_RAWFONT + d->useRawFont = false; +#endif d->resetFontEngineCache(); } @@ -2204,15 +2223,17 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const continue; } - QFont font = eng->font(si); - + QFont font; QGlyphRun::GlyphRunFlags flags; - if (font.overline()) - flags |= QGlyphRun::Overline; - if (font.underline()) - flags |= QGlyphRun::Underline; - if (font.strikeOut()) - flags |= QGlyphRun::StrikeOut; + if (!eng->useRawFont) { + font = eng->font(si); + if (font.overline()) + flags |= QGlyphRun::Overline; + if (font.underline()) + flags |= QGlyphRun::Underline; + if (font.strikeOut()) + flags |= QGlyphRun::StrikeOut; + } bool rtl = false; if (si.analysis.bidiLevel % 2) { @@ -2264,7 +2285,8 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const iterator.getSelectionBounds(&x, &width); if (glyphLayout.numGlyphs > 0) { - QFontEngine *mainFontEngine = font.d->engineForScript(si.analysis.script); + QFontEngine *mainFontEngine = eng->fontEngine(si); + if (mainFontEngine->type() == QFontEngine::Multi) { QFontEngineMulti *multiFontEngine = static_cast<QFontEngineMulti *>(mainFontEngine); int end = rtl ? glyphLayout.numGlyphs : 0; @@ -2331,6 +2353,10 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const */ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatRange *selection) const { +#ifndef QT_NO_RAWFONT + // Not intended to work with rawfont + Q_ASSERT(!eng->useRawFont); +#endif const QScriptLine &line = eng->lines[index]; QPen pen = p->pen(); diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h index a3bc79dc52..2c38973371 100644 --- a/src/gui/text/qtextlayout.h +++ b/src/gui/text/qtextlayout.h @@ -59,6 +59,9 @@ QT_BEGIN_NAMESPACE class QTextEngine; class QFont; +#ifndef QT_NO_RAWFONT +class QRawFont; +#endif class QRect; class QRegion; class QTextFormat; @@ -114,6 +117,10 @@ public: void setFont(const QFont &f); QFont font() const; +#ifndef QT_NO_RAWFONT + void setRawFont(const QRawFont &rawFont); +#endif + void setText(const QString& string); QString text() const; diff --git a/src/gui/text/qtextlist.cpp b/src/gui/text/qtextlist.cpp index 5a642e90ef..c3c71bc021 100644 --- a/src/gui/text/qtextlist.cpp +++ b/src/gui/text/qtextlist.cpp @@ -107,7 +107,7 @@ public: Returns true if the list has no items; otherwise returns false. - \bold{Note:} Empty lists are automatically deleted by the QTextDocument that owns + \b{Note:} Empty lists are automatically deleted by the QTextDocument that owns them. \sa count() diff --git a/src/gui/text/qtexttable.cpp b/src/gui/text/qtexttable.cpp index 12af933fd0..65bc8fde1e 100644 --- a/src/gui/text/qtexttable.cpp +++ b/src/gui/text/qtexttable.cpp @@ -541,22 +541,22 @@ void QTextTablePrivate::update() const \table 80% \row - \o \inlineimage texttable-split.png Original Table - \o Suppose we have a 2x3 table of names and addresses. To merge both + \li \inlineimage texttable-split.png Original Table + \li Suppose we have a 2x3 table of names and addresses. To merge both columns in the first row we invoke mergeCells() with \a row = 0, \a column = 0, \a numRows = 1 and \a numColumns = 2. \snippet doc/src/snippets/textdocument-texttable/main.cpp 0 \row - \o \inlineimage texttable-merge.png - \o This gives us the following table. To split the first row of the table + \li \inlineimage texttable-merge.png + \li This gives us the following table. To split the first row of the table back into two cells, we invoke the splitCell() function with \a numRows and \a numCols = 1. \snippet doc/src/snippets/textdocument-texttable/main.cpp 1 \row - \o \inlineimage texttable-split.png Split Table - \o This results in the original table. + \li \inlineimage texttable-split.png Split Table + \li This results in the original table. \endtable \sa QTextTableFormat |