Add support for QRawFont in QTextLayout.
The purpose of this change is to allow shaping complex text while using QRawFont. This is needed for WebKit so that we can switch to using QRawFont everywhere and be more in line with what other WebKit ports do. Since this change slightly bends the aim of QRawFont, let's reserve this for internal use for now. Change-Id: I5ec0881f50ce288350bd277570cb5f1fb70c355c Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
This commit is contained in:
parent
6e483e8385
commit
10ac807085
@ -162,6 +162,7 @@ private:
|
|||||||
friend class QFontEngineMultiXLFD;
|
friend class QFontEngineMultiXLFD;
|
||||||
friend class QFontEngineMultiQWS;
|
friend class QFontEngineMultiQWS;
|
||||||
friend class QFontEngineMultiQPA;
|
friend class QFontEngineMultiQPA;
|
||||||
|
friend class QTextEngine;
|
||||||
#ifdef QT_BUILD_INTERNAL
|
#ifdef QT_BUILD_INTERNAL
|
||||||
friend class ::tst_QFont;
|
friend class ::tst_QFont;
|
||||||
#endif
|
#endif
|
||||||
|
@ -138,6 +138,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
friend class QRawFontPrivate;
|
friend class QRawFontPrivate;
|
||||||
friend class QTextLayout;
|
friend class QTextLayout;
|
||||||
|
friend class QTextEngine;
|
||||||
|
|
||||||
QExplicitlySharedDataPointer<QRawFontPrivate> d;
|
QExplicitlySharedDataPointer<QRawFontPrivate> d;
|
||||||
};
|
};
|
||||||
|
@ -53,6 +53,8 @@
|
|||||||
#include "qstring.h"
|
#include "qstring.h"
|
||||||
#include <private/qunicodetables_p.h>
|
#include <private/qunicodetables_p.h>
|
||||||
#include "qtextdocument_p.h"
|
#include "qtextdocument_p.h"
|
||||||
|
#include "qrawfont.h"
|
||||||
|
#include "qrawfont_p.h"
|
||||||
#include <qguiapplication.h>
|
#include <qguiapplication.h>
|
||||||
#include <qinputmethod.h>
|
#include <qinputmethod.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -60,6 +62,8 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
static const float smallCapsFraction = 0.7;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Helper class used in QTextEngine::itemize
|
// Helper class used in QTextEngine::itemize
|
||||||
// keep it out here to allow us to keep supporting various compilers.
|
// keep it out here to allow us to keep supporting various compilers.
|
||||||
@ -900,13 +904,25 @@ void QTextEngine::shapeText(int item) const
|
|||||||
return;
|
return;
|
||||||
QGlyphLayout glyphs = shapedGlyphs(&si);
|
QGlyphLayout glyphs = shapedGlyphs(&si);
|
||||||
|
|
||||||
|
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);
|
QFont font = this->font(si);
|
||||||
bool letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute;
|
letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute;
|
||||||
QFixed letterSpacing = font.d->letterSpacing;
|
letterSpacing = font.d->letterSpacing;
|
||||||
QFixed wordSpacing = font.d->wordSpacing;
|
wordSpacing = font.d->wordSpacing;
|
||||||
|
|
||||||
if (letterSpacingIsAbsolute && letterSpacing.value())
|
if (letterSpacingIsAbsolute && letterSpacing.value())
|
||||||
letterSpacing *= font.d->dpi / qt_defaultDpiY();
|
letterSpacing *= font.d->dpi / qt_defaultDpiY();
|
||||||
|
}
|
||||||
|
|
||||||
if (letterSpacing != 0) {
|
if (letterSpacing != 0) {
|
||||||
for (int i = 1; i < si.num_glyphs; ++i) {
|
for (int i = 1; i < si.num_glyphs; ++i) {
|
||||||
@ -973,7 +989,14 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
|
|||||||
|
|
||||||
QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading);
|
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;
|
HB_ShaperItem entire_shaper_item;
|
||||||
qMemSet(&entire_shaper_item, 0, sizeof(entire_shaper_item));
|
qMemSet(&entire_shaper_item, 0, sizeof(entire_shaper_item));
|
||||||
@ -1159,6 +1182,9 @@ static void init(QTextEngine *e)
|
|||||||
e->underlinePositions = 0;
|
e->underlinePositions = 0;
|
||||||
e->specialData = 0;
|
e->specialData = 0;
|
||||||
e->stackEngine = false;
|
e->stackEngine = false;
|
||||||
|
#ifndef QT_NO_RAWFONT
|
||||||
|
e->useRawFont = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QTextEngine::QTextEngine()
|
QTextEngine::QTextEngine()
|
||||||
@ -1401,6 +1427,20 @@ void QTextEngine::itemize() const
|
|||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#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));
|
itemizer.generate(0, length, static_cast<QFont::Capitalization> (fnt.d->capital));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1663,6 +1703,31 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix
|
|||||||
int script = si.analysis.script;
|
int script = si.analysis.script;
|
||||||
|
|
||||||
QFont font = fnt;
|
QFont font = fnt;
|
||||||
|
#ifndef QT_NO_RAWFONT
|
||||||
|
if (useRawFont && rawFont.isValid()) {
|
||||||
|
if (feCache.prevFontEngine && feCache.prevFontEngine->type() == QFontEngine::Multi && feCache.prevScript == script) {
|
||||||
|
engine = feCache.prevFontEngine;
|
||||||
|
} else {
|
||||||
|
engine = QFontDatabase::findFont(script, /*fontPrivate*/0, rawFont.d->fontEngine->fontDef, true);
|
||||||
|
feCache.prevFontEngine = engine;
|
||||||
|
feCache.prevScript = script;
|
||||||
|
engine->ref.ref();
|
||||||
|
if (feCache.prevScaledFontEngine)
|
||||||
|
releaseCachedFontEngine(feCache.prevScaledFontEngine);
|
||||||
|
}
|
||||||
|
if (si.analysis.flags & QFont::SmallCaps) {
|
||||||
|
if (feCache.prevScaledFontEngine) {
|
||||||
|
scaledEngine = feCache.prevScaledFontEngine;
|
||||||
|
} else {
|
||||||
|
QFontEngine *scEngine = rawFont.d->fontEngine->cloneWithSize(smallCapsFraction * rawFont.pixelSize());
|
||||||
|
scaledEngine = QFontDatabase::findFont(script, /*fontPrivate*/0, scEngine->fontDef, true);
|
||||||
|
scaledEngine->ref.ref();
|
||||||
|
feCache.prevScaledFontEngine = scaledEngine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
if (hasFormats()) {
|
if (hasFormats()) {
|
||||||
if (feCache.prevFontEngine && feCache.prevPosition == si.position && feCache.prevLength == length(&si) && feCache.prevScript == script) {
|
if (feCache.prevFontEngine && feCache.prevPosition == si.position && feCache.prevLength == length(&si) && feCache.prevScript == script) {
|
||||||
engine = feCache.prevFontEngine;
|
engine = feCache.prevFontEngine;
|
||||||
@ -1717,6 +1782,7 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix
|
|||||||
QFontPrivate *p = font.d->smallCapsFontPrivate();
|
QFontPrivate *p = font.d->smallCapsFontPrivate();
|
||||||
scaledEngine = p->engineForScript(script);
|
scaledEngine = p->engineForScript(script);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ascent) {
|
if (ascent) {
|
||||||
*ascent = engine->ascent();
|
*ascent = engine->ascent();
|
||||||
|
@ -581,7 +581,10 @@ public:
|
|||||||
mutable FontEngineCache feCache;
|
mutable FontEngineCache feCache;
|
||||||
|
|
||||||
QString text;
|
QString text;
|
||||||
QFont fnt;
|
mutable QFont fnt;
|
||||||
|
#ifndef QT_NO_RAWFONT
|
||||||
|
QRawFont rawFont;
|
||||||
|
#endif
|
||||||
QTextBlock block;
|
QTextBlock block;
|
||||||
|
|
||||||
QTextOption option;
|
QTextOption option;
|
||||||
@ -594,6 +597,9 @@ public:
|
|||||||
uint stackEngine : 1;
|
uint stackEngine : 1;
|
||||||
uint forceJustification : 1;
|
uint forceJustification : 1;
|
||||||
uint visualMovement : 1;
|
uint visualMovement : 1;
|
||||||
|
#ifndef QT_NO_RAWFONT
|
||||||
|
uint useRawFont : 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
int *underlinePositions;
|
int *underlinePositions;
|
||||||
|
|
||||||
|
@ -361,6 +361,22 @@ QTextLayout::~QTextLayout()
|
|||||||
delete d;
|
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
|
Sets the layout's font to the given \a font. The layout is
|
||||||
invalidated and must be laid out again.
|
invalidated and must be laid out again.
|
||||||
@ -370,6 +386,9 @@ QTextLayout::~QTextLayout()
|
|||||||
void QTextLayout::setFont(const QFont &font)
|
void QTextLayout::setFont(const QFont &font)
|
||||||
{
|
{
|
||||||
d->fnt = font;
|
d->fnt = font;
|
||||||
|
#ifndef QT_NO_RAWFONT
|
||||||
|
d->useRawFont = false;
|
||||||
|
#endif
|
||||||
d->resetFontEngineCache();
|
d->resetFontEngineCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2204,15 +2223,17 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QFont font = eng->font(si);
|
QFont font;
|
||||||
|
|
||||||
QGlyphRun::GlyphRunFlags flags;
|
QGlyphRun::GlyphRunFlags flags;
|
||||||
|
if (!eng->useRawFont) {
|
||||||
|
font = eng->font(si);
|
||||||
if (font.overline())
|
if (font.overline())
|
||||||
flags |= QGlyphRun::Overline;
|
flags |= QGlyphRun::Overline;
|
||||||
if (font.underline())
|
if (font.underline())
|
||||||
flags |= QGlyphRun::Underline;
|
flags |= QGlyphRun::Underline;
|
||||||
if (font.strikeOut())
|
if (font.strikeOut())
|
||||||
flags |= QGlyphRun::StrikeOut;
|
flags |= QGlyphRun::StrikeOut;
|
||||||
|
}
|
||||||
|
|
||||||
bool rtl = false;
|
bool rtl = false;
|
||||||
if (si.analysis.bidiLevel % 2) {
|
if (si.analysis.bidiLevel % 2) {
|
||||||
@ -2264,7 +2285,8 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
|
|||||||
iterator.getSelectionBounds(&x, &width);
|
iterator.getSelectionBounds(&x, &width);
|
||||||
|
|
||||||
if (glyphLayout.numGlyphs > 0) {
|
if (glyphLayout.numGlyphs > 0) {
|
||||||
QFontEngine *mainFontEngine = font.d->engineForScript(si.analysis.script);
|
QFontEngine *mainFontEngine = eng->fontEngine(si);
|
||||||
|
|
||||||
if (mainFontEngine->type() == QFontEngine::Multi) {
|
if (mainFontEngine->type() == QFontEngine::Multi) {
|
||||||
QFontEngineMulti *multiFontEngine = static_cast<QFontEngineMulti *>(mainFontEngine);
|
QFontEngineMulti *multiFontEngine = static_cast<QFontEngineMulti *>(mainFontEngine);
|
||||||
int end = rtl ? glyphLayout.numGlyphs : 0;
|
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
|
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];
|
const QScriptLine &line = eng->lines[index];
|
||||||
QPen pen = p->pen();
|
QPen pen = p->pen();
|
||||||
|
|
||||||
|
@ -59,6 +59,9 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
class QTextEngine;
|
class QTextEngine;
|
||||||
class QFont;
|
class QFont;
|
||||||
|
#ifndef QT_NO_RAWFONT
|
||||||
|
class QRawFont;
|
||||||
|
#endif
|
||||||
class QRect;
|
class QRect;
|
||||||
class QRegion;
|
class QRegion;
|
||||||
class QTextFormat;
|
class QTextFormat;
|
||||||
@ -114,6 +117,10 @@ public:
|
|||||||
void setFont(const QFont &f);
|
void setFont(const QFont &f);
|
||||||
QFont font() const;
|
QFont font() const;
|
||||||
|
|
||||||
|
#ifndef QT_NO_RAWFONT
|
||||||
|
void setRawFont(const QRawFont &rawFont);
|
||||||
|
#endif
|
||||||
|
|
||||||
void setText(const QString& string);
|
void setText(const QString& string);
|
||||||
QString text() const;
|
QString text() const;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user