summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp1
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp41
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp4
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp11
-rw-r--r--src/gui/painting/qtextureglyphcache_p.h5
-rw-r--r--src/gui/text/qcssparser.cpp1
-rw-r--r--src/gui/text/qcssparser_p.h1
-rw-r--r--src/gui/text/qfontdatabase.cpp3
-rw-r--r--src/gui/text/qfontdatabase_x11.cpp23
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp38
-rw-r--r--src/gui/text/qtextformat.cpp67
-rw-r--r--src/gui/text/qtextformat.h35
-rw-r--r--src/gui/text/qtexthtmlparser.cpp14
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp20
-rw-r--r--tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp17
15 files changed, 255 insertions, 26 deletions
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp
index 4a618da..bbf479e 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp
@@ -1683,6 +1683,7 @@ static bool indic_shape_syllable(HB_Bool openType, HB_ShaperItem *item, bool inv
}
item->glyphs[j] = item->glyphs[i];
item->attributes[j] = item->attributes[i];
+ item->advances[j] = item->advances[i];
++i;
++j;
}
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
index ce4d4ac..ef86144 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
@@ -538,8 +538,20 @@ void HB_HeuristicSetGlyphAttributes(HB_ShaperItem *item)
#ifndef NO_OPENTYPE
static const HB_OpenTypeFeature basic_features[] = {
{ HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },
- { HB_MAKE_TAG('l', 'i', 'g', 'a'), CcmpProperty },
- { HB_MAKE_TAG('c', 'l', 'i', 'g'), CcmpProperty },
+ { HB_MAKE_TAG('l', 'i', 'g', 'a'), LigaProperty },
+ { HB_MAKE_TAG('c', 'l', 'i', 'g'), CligProperty },
+ {0, 0}
+};
+
+static const HB_OpenTypeFeature disabled_features[] = {
+ { HB_MAKE_TAG('c', 'p', 'c', 't'), PositioningProperties },
+ { HB_MAKE_TAG('h', 'a', 'l', 't'), PositioningProperties },
+ // TODO: we need to add certain HB_ShaperFlag for vertical
+ // writing mode to enable these vertical writing features:
+ { HB_MAKE_TAG('v', 'a', 'l', 't'), PositioningProperties },
+ { HB_MAKE_TAG('v', 'h', 'a', 'l'), PositioningProperties },
+ { HB_MAKE_TAG('v', 'k', 'r', 'n'), PositioningProperties },
+ { HB_MAKE_TAG('v', 'p', 'a', 'l'), PositioningProperties },
{0, 0}
};
#endif
@@ -1110,12 +1122,29 @@ HB_Bool HB_SelectScript(HB_ShaperItem *shaper_item, const HB_OpenTypeFeature *fe
HB_UInt *feature_tag_list = feature_tag_list_buffer;
while (*feature_tag_list) {
HB_UShort feature_index;
+ bool skip = false;
if (*feature_tag_list == HB_MAKE_TAG('k', 'e', 'r', 'n')) {
- if (face->current_flags & HB_ShaperFlag_NoKerning) {
- ++feature_tag_list;
- continue;
+ if (face->current_flags & HB_ShaperFlag_NoKerning)
+ skip = true;
+ else
+ face->has_opentype_kerning = true;
+ }
+ features = disabled_features;
+ while (features->tag) {
+ if (*feature_tag_list == features->tag) {
+ skip = true;
+ break;
}
- face->has_opentype_kerning = true;
+ ++features;
+ }
+ // 'palt' should be turned off by default unless 'kern' is on
+ if (!face->has_opentype_kerning &&
+ *feature_tag_list == HB_MAKE_TAG('p', 'a', 'l', 't'))
+ skip = true;
+
+ if (skip) {
+ ++feature_tag_list;
+ continue;
}
error = HB_GPOS_Select_Feature(face->gpos, *feature_tag_list, script_index, 0xffff, &feature_index);
if (!error)
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index cdcd092..5a8ca3d 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -3116,7 +3116,9 @@ void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
if (supportsSubPixelPositions)
subPixelPosition = cache->subPixelPositionForX(positions[i].x);
QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphs[i], subPixelPosition);
- const QTextureGlyphCache::Coord &c = cache->coords.value(glyph);
+ const QTextureGlyphCache::Coord &c = cache->coords[glyph];
+ if (c.isNull())
+ continue;
int x = qFloor(positions[i].x) + c.baseLineX - margin;
int y = qFloor(positions[i].y) - c.baseLineY - margin;
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index 60300c3..670ca95 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -175,11 +175,16 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
metrics.yoff.toReal(),
metrics.x.toReal(),
metrics.y.toReal());
-#endif
+#endif
+ GlyphAndSubPixelPosition key(glyph, subPixelPosition);
int glyph_width = metrics.width.ceil().toInt();
int glyph_height = metrics.height.ceil().toInt();
- if (glyph_height == 0 || glyph_width == 0)
+ if (glyph_height == 0 || glyph_width == 0) {
+ // Avoid multiple calls to boundingBox() for non-printable characters
+ Coord c = { 0, 0, 0, 0, 0, 0 };
+ coords.insert(key, c);
continue;
+ }
glyph_width += margin * 2 + 4;
glyph_height += margin * 2 + 4;
// align to 8-bit boundary
@@ -192,7 +197,7 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
metrics.x.round().truncate(),
-metrics.y.truncate() }; // baseline for horizontal scripts
- listItemCoordinates.insert(GlyphAndSubPixelPosition(glyph, subPixelPosition), c);
+ listItemCoordinates.insert(key, c);
rowHeight = qMax(rowHeight, glyph_height);
}
if (listItemCoordinates.isEmpty())
diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h
index 4227e9a..7a0bdfd 100644
--- a/src/gui/painting/qtextureglyphcache_p.h
+++ b/src/gui/painting/qtextureglyphcache_p.h
@@ -107,6 +107,11 @@ public:
int baseLineX;
int baseLineY;
+
+ bool isNull() const
+ {
+ return w == 0 || h == 0;
+ }
};
bool populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs,
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index dafc8e7..edb08ae 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -122,6 +122,7 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "image", QtImage },
{ "image-position", QtImageAlignment },
{ "left", Left },
+ { "line-height", LineHeight },
{ "list-style", ListStyle },
{ "list-style-type", ListStyleType },
{ "margin" , Margin },
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index ca9688e..6bcbdab 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -180,6 +180,7 @@ enum Property {
TextTransform,
QtListNumberPrefix,
QtListNumberSuffix,
+ LineHeight,
NumProperties
};
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index bae2a20..ec94de9 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -664,6 +664,9 @@ public:
}
int count;
+#if defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)
+ QString systemLang;
+#endif
QtFontFamily **families;
struct ApplicationFont {
diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp
index 635d2cf..c67558b 100644
--- a/src/gui/text/qfontdatabase_x11.cpp
+++ b/src/gui/text/qfontdatabase_x11.cpp
@@ -1018,6 +1018,13 @@ static void loadFontConfig()
QFontDatabasePrivate *db = privateDb();
FcFontSet *fonts;
+ FcPattern *pattern = FcPatternCreate();
+ FcDefaultSubstitute(pattern);
+ FcChar8 *lang = 0;
+ if (FcPatternGetString(pattern, FC_LANG, 0, &lang) == FcResultMatch)
+ db->systemLang = QString::fromUtf8((const char *) lang);
+ FcPatternDestroy(pattern);
+
QString familyName;
FcChar8 *value = 0;
int weight_value;
@@ -2037,6 +2044,7 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
int count = 0;
QStringList families;
+ QFontDatabasePrivate *db = privateDb();
FcPattern *pattern = 0;
do {
@@ -2048,8 +2056,19 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
FcPatternDel(pattern, FC_FILE);
FcPatternAddString(pattern, FC_FILE, (const FcChar8 *)fnt->fileName.toUtf8().constData());
- FcChar8 *fam = 0;
- if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) {
+ FcChar8 *fam = 0, *familylang = 0;
+ int i, n = 0;
+ for (i = 0; ; i++) {
+ if (FcPatternGetString(pattern, FC_FAMILYLANG, i, &familylang) != FcResultMatch)
+ break;
+ QString familyLang = QString::fromUtf8((const char *) familylang);
+ if (familyLang.compare(db->systemLang, Qt::CaseInsensitive) == 0) {
+ n = i;
+ break;
+ }
+ }
+
+ if (FcPatternGetString(pattern, FC_FAMILY, n, &fam) == FcResultMatch) {
QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam));
families << family;
}
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index ff14490..c0f3fb4 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -2506,6 +2506,23 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
fd->currentLayoutStruct = 0;
}
+static inline void getLineHeightParams(const QTextBlockFormat &blockFormat, const QTextLine &line, qreal scaling,
+ QFixed *lineAdjustment, QFixed *lineBreakHeight, QFixed *lineHeight)
+{
+ *lineHeight = QFixed::fromReal(blockFormat.lineHeight(line.height(), scaling));
+ if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight || blockFormat.lineHeightType() == QTextBlockFormat::MinimumHeight) {
+ *lineBreakHeight = *lineHeight;
+ if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight)
+ *lineAdjustment = QFixed::fromReal(line.ascent() + qMax(line.leading(), qreal(0.0))) - ((*lineHeight * 4) / 5);
+ else
+ *lineAdjustment = QFixed::fromReal(line.height()) - *lineHeight;
+ }
+ else {
+ *lineBreakHeight = QFixed::fromReal(line.height());
+ *lineAdjustment = 0;
+ }
+}
+
void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosition, const QTextBlockFormat &blockFormat,
QTextLayoutStruct *layoutStruct, int layoutFrom, int layoutTo, const QTextBlockFormat *previousBlockFormat)
{
@@ -2639,8 +2656,12 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
}
- QFixed lineHeight = QFixed::fromReal(line.height());
- if (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineHeight > layoutStruct->pageBottom) {
+ QFixed lineBreakHeight, lineHeight, lineAdjustment;
+ qreal scaling = (q->paintDevice() && q->paintDevice()->logicalDpiY() != qt_defaultDpi()) ?
+ qreal(q->paintDevice()->logicalDpiY()) / qreal(qt_defaultDpi()) : 1;
+ getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight);
+
+ if (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom) {
layoutStruct->newPage();
floatMargins(layoutStruct->y, layoutStruct, &left, &right);
@@ -2652,7 +2673,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
right -= text_indent;
}
- line.setPosition(QPointF((left - layoutStruct->x_left).toReal(), (layoutStruct->y - cy).toReal()));
+ line.setPosition(QPointF((left - layoutStruct->x_left).toReal(), (layoutStruct->y - cy - lineAdjustment).toReal()));
layoutStruct->y += lineHeight;
layoutStruct->contentsWidth
= qMax<QFixed>(layoutStruct->contentsWidth, QFixed::fromReal(line.x() + line.naturalTextWidth()) + totalRightMargin);
@@ -2672,11 +2693,16 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
QTextLine line = tl->lineAt(i);
layoutStruct->contentsWidth
= qMax(layoutStruct->contentsWidth, QFixed::fromReal(line.x() + tl->lineAt(i).naturalTextWidth()) + totalRightMargin);
- const QFixed lineHeight = QFixed::fromReal(line.height());
+
+ QFixed lineBreakHeight, lineHeight, lineAdjustment;
+ qreal scaling = (q->paintDevice() && q->paintDevice()->logicalDpiY() != qt_defaultDpi()) ?
+ qreal(q->paintDevice()->logicalDpiY()) / qreal(qt_defaultDpi()) : 1;
+ getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight);
+
if (layoutStruct->pageHeight != QFIXED_MAX) {
- if (layoutStruct->absoluteY() + lineHeight > layoutStruct->pageBottom)
+ if (layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom)
layoutStruct->newPage();
- line.setPosition(QPointF(line.position().x(), layoutStruct->y.toReal() - tl->position().y()));
+ line.setPosition(QPointF(line.position().x(), (layoutStruct->y - lineAdjustment).toReal() - tl->position().y()));
}
layoutStruct->y += lineHeight;
}
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 945b012..b05a830 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -541,6 +541,8 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
\value TabPositions Specifies the tab positions. The tab positions are structs of QTextOption::Tab which are stored in
a QList (internally, in a QList<QVariant>).
\value BlockIndent
+ \value LineHeight
+ \value LineHeightType
\value BlockNonBreakableLines
\value BlockTrailingHorizontalRulerWidth The width of a horizontal ruler element.
@@ -1856,6 +1858,10 @@ QFont QTextCharFormat::font() const
indentation is set with setIndent(), the indentation of the first
line with setTextIndent().
+ Line spacing is set with setLineHeight() and retreived via lineHeight()
+ and lineHeightType(). The types of line spacing available are in the
+ LineHeightTypes enum.
+
Line breaking can be enabled and disabled with setNonBreakableLines().
The brush used to paint the paragraph's background
@@ -1872,6 +1878,22 @@ QFont QTextCharFormat::font() const
*/
/*!
+ \since 4.8
+ \enum QTextBlockFormat::LineHeightTypes
+
+ This enum describes the various types of line spacing support paragraphs can have.
+
+ \value SingleHeight This is the default line height: single spacing.
+ \value ProportionalHeight This sets the spacing proportional to the line (in percentage).
+ For example, set to 200 for double spacing.
+ \value FixedHeight This sets the line height to a fixed line height (in pixels).
+ \value MinimumHeight This sets the minimum line height (in pixels).
+ \value LineDistanceHeight This adds the specified height between lines (in pixels).
+
+ \sa lineHeight(), lineHeightType(), setLineHeight()
+*/
+
+/*!
\fn QTextBlockFormat::QTextBlockFormat()
Constructs a new QTextBlockFormat.
@@ -2089,6 +2111,51 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
/*!
+ \fn void QTextBlockFormat::setLineHeight(qreal height, int heightType)
+ \since 4.8
+
+ This sets the line height for the paragraph to the value in height
+ which is dependant on heightType, described by the LineHeightTypes enum.
+
+ \sa LineHeightTypes, lineHeight(), lineHeightType()
+*/
+
+
+/*!
+ \fn qreal QTextBlockFormat::lineHeight(qreal scriptLineHeight, qreal scaling) const
+ \since 4.8
+
+ This returns what the height of the lines in the paragraph will be depending
+ on the given height of the script line and the scaling. The value that is returned
+ is also dependant on the given LineHeightType of the paragraph as well as the LineHeight
+ setting that has been set for the paragraph. The scaling is needed for the heights
+ that include a fixed number of pixels, to scale them appropriately for printing.
+
+ \sa LineHeightTypes, setLineHeight(), lineHeightType()
+*/
+
+
+/*!
+ \fn qreal QTextBlockFormat::lineHeight() const
+ \since 4.8
+
+ This returns the LineHeight property for the paragraph.
+
+ \sa LineHeightTypes, setLineHeight(), lineHeightType()
+*/
+
+
+/*!
+ \fn qreal QTextBlockFormat::lineHeightType() const
+ \since 4.8
+
+ This returns the LineHeightType property of the paragraph.
+
+ \sa LineHeightTypes, setLineHeight(), lineHeight()
+*/
+
+
+/*!
\fn void QTextBlockFormat::setNonBreakableLines(bool b)
If \a b is true, the lines in the paragraph are treated as
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index bb6e71d..81b053b 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -164,6 +164,8 @@ public:
TextIndent = 0x1034,
TabPositions = 0x1035,
BlockIndent = 0x1040,
+ LineHeight = 0x1048,
+ LineHeightType = 0x1049,
BlockNonBreakableLines = 0x1050,
BlockTrailingHorizontalRulerWidth = 0x1060,
@@ -531,6 +533,14 @@ inline void QTextCharFormat::setTableCellColumnSpan(int _tableCellColumnSpan)
class Q_GUI_EXPORT QTextBlockFormat : public QTextFormat
{
public:
+ enum LineHeightTypes {
+ SingleHeight = 0,
+ ProportionalHeight = 1,
+ FixedHeight = 2,
+ MinimumHeight = 3,
+ LineDistanceHeight = 4
+ };
+
QTextBlockFormat();
bool isValid() const { return isBlockFormat(); }
@@ -568,6 +578,14 @@ public:
inline int indent() const
{ return intProperty(BlockIndent); }
+ inline void setLineHeight(qreal height, int heightType)
+ { setProperty(LineHeight, height); setProperty(LineHeightType, heightType); }
+ inline qreal lineHeight(qreal scriptLineHeight, qreal scaling) const;
+ inline qreal lineHeight() const
+ { return doubleProperty(LineHeight); }
+ inline int lineHeightType() const
+ { return intProperty(LineHeightType); }
+
inline void setNonBreakableLines(bool b)
{ setProperty(BlockNonBreakableLines, b); }
inline bool nonBreakableLines() const
@@ -592,6 +610,23 @@ inline void QTextBlockFormat::setAlignment(Qt::Alignment aalignment)
inline void QTextBlockFormat::setIndent(int aindent)
{ setProperty(BlockIndent, aindent); }
+inline qreal QTextBlockFormat::lineHeight(qreal scriptLineHeight, qreal scaling = 1.0) const
+{
+ switch(intProperty(LineHeightType)) {
+ case SingleHeight:
+ return(scriptLineHeight);
+ case ProportionalHeight:
+ return(scriptLineHeight * doubleProperty(LineHeight) / 100.0);
+ case FixedHeight:
+ return(doubleProperty(LineHeight) * scaling);
+ case MinimumHeight:
+ return(qMax(scriptLineHeight, doubleProperty(LineHeight) * scaling));
+ case LineDistanceHeight:
+ return(scriptLineHeight + doubleProperty(LineHeight) * scaling);
+ }
+ return(0);
+}
+
class Q_GUI_EXPORT QTextListFormat : public QTextFormat
{
public:
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 5b9ab90..5d5e2b6 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -1250,6 +1250,20 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
case QCss::QtBlockIndent:
blockFormat.setIndent(decl.d->values.first().variant.toInt());
break;
+ case QCss::LineHeight: {
+ qreal lineHeight;
+ if (decl.realValue(&lineHeight, "px")) {
+ blockFormat.setLineHeight(lineHeight, QTextBlockFormat::FixedHeight);
+ } else {
+ bool ok;
+ QString value = decl.d->values.first().toString();
+ lineHeight = value.toDouble(&ok);
+ if (ok)
+ blockFormat.setLineHeight(lineHeight, QTextBlockFormat::ProportionalHeight);
+ else
+ blockFormat.setLineHeight(0, QTextBlockFormat::SingleHeight);
+ }
+ break; }
case QCss::TextIndent: {
qreal indent = 0;
if (decl.realValue(&indent, "px"))
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index cf63626..0cb6f85 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -1592,7 +1592,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
}
}
-
if (recreateVertexArrays) {
vertexCoordinates->clear();
textureCoordinates->clear();
@@ -1605,7 +1604,10 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
QTextureGlyphCache::GlyphAndSubPixelPosition glyph(staticTextItem->glyphs[i], subPixelPosition);
- const QTextureGlyphCache::Coord &c = cache->coords.value(glyph);
+ const QTextureGlyphCache::Coord &c = cache->coords[glyph];
+ if (c.isNull())
+ continue;
+
int x = staticTextItem->glyphPositions[i].x.toInt() + c.baseLineX - margin;
int y = staticTextItem->glyphPositions[i].y.toInt() - c.baseLineY - margin;
@@ -1616,10 +1618,12 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
staticTextItem->userDataNeedsUpdate = false;
}
- if (elementIndices.size() < staticTextItem->numGlyphs*6) {
+ int numGlyphs = vertexCoordinates->vertexCount() / 4;
+
+ if (elementIndices.size() < numGlyphs*6) {
Q_ASSERT(elementIndices.size() % 6 == 0);
int j = elementIndices.size() / 6 * 4;
- while (j < staticTextItem->numGlyphs*4) {
+ while (j < numGlyphs*4) {
elementIndices.append(j + 0);
elementIndices.append(j + 0);
elementIndices.append(j + 1);
@@ -1708,9 +1712,9 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO)
- glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, 0);
+ glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0);
#else
- glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data());
+ glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data());
#endif
shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMaskPass2);
@@ -1758,10 +1762,10 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
}
#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO)
- glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, 0);
+ glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#else
- glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data());
+ glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data());
#endif
}
diff --git a/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp b/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp
index 0a7458f..b0b6b1e 100644
--- a/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp
+++ b/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp
@@ -103,6 +103,7 @@ private slots:
void khmer();
void linearB();
+ void controlInSyllable_qtbug14204();
};
tst_QTextScriptEngine::tst_QTextScriptEngine()
@@ -1111,6 +1112,22 @@ void tst_QTextScriptEngine::greek()
#endif
}
+void tst_QTextScriptEngine::controlInSyllable_qtbug14204()
+{
+ QString s;
+ s.append(QChar(0x0915));
+ s.append(QChar(0x094d));
+ s.append(QChar(0x200d));
+ s.append(QChar(0x0915));
+
+ QTextLayout layout(s);
+ QTextEngine *e = layout.d;
+ e->itemize();
+ e->shape(0);
+
+ QVERIFY(e->layoutData->items[0].num_glyphs == 2);
+ QVERIFY(e->layoutData->glyphLayout.advances_x[1] != 0);
+}
QTEST_MAIN(tst_QTextScriptEngine)
#include "tst_qtextscriptengine.moc"