From 0189fc2335c891373ce595a4a01e4a9d73cc5fe4 Mon Sep 17 00:00:00 2001
From: Jiang Jiang <jiang.jiang@nokia.com>
Date: Sun, 12 Dec 2010 17:33:12 +0100
Subject: Move advances for control character in Indic syllable shaping

When handling control characters (ZWJ, ZWNJ) in Indic syllables,
we only moved glyphs and attributes of the item, advances should
also be moved forward, otherwise we will use the advance of ZWJ/
ZWNJ for the part of syllable, which is normally zero, it results
some positioning problems.

Task-number: QTBUG-14204
Reviewed-by: Lars Knoll
---
 src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp           |  1 +
 tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp | 17 +++++++++++++++++
 2 files changed, 18 insertions(+)

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/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"
-- 
cgit v0.12


From ad0841dfd89d08140b719098ecfec82881df63e6 Mon Sep 17 00:00:00 2001
From: Jiang Jiang <jiang.jiang@nokia.com>
Date: Tue, 14 Dec 2010 18:18:35 +0100
Subject: Disable certain GPOS features by default

According to OpenType Layout tag registry, these features should be
turned off by default. Leaving them on will cause some text layout
problems in common UI widgets -- they are usually designed for better
positioning in print publishing or full featured text layout programs,
not for general usage.

There is no way to turn them on in HarfBuzz now, it should be
addressed later. Features like 'valt' are intended for vertical
writing mode are also turned off, since HarfBuzz doesn't support it
properly yet.

Task-number: QTBUG-15754
Reviewed-by: Lars Knoll
---
 src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp | 41 +++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 6 deletions(-)

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)
-- 
cgit v0.12


From 5d68753927ac6ba1445ceb6831da7e2346d91bf9 Mon Sep 17 00:00:00 2001
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
Date: Tue, 21 Dec 2010 13:26:54 +0100
Subject: Optimize texture glyph cache

To avoid calling the bounding box function for the same non-printable
characters in every call, we cache them as empty in the coords table
and bail out before painting them. This patch also fixes some possible
reads of uninitialized memory (reference to return value) and reference
to a default constructed object consisting of uninitialized pods.

Reviewed-by: Samuel
---
 src/gui/painting/qpaintengine_raster.cpp             |  4 +++-
 src/gui/painting/qtextureglyphcache.cpp              | 11 ++++++++---
 src/gui/painting/qtextureglyphcache_p.h              |  5 +++++
 .../gl2paintengineex/qpaintengineex_opengl2.cpp      | 20 ++++++++++++--------
 4 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 97dfddf..ec5cef0 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -3111,7 +3111,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/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index cdd785a..771d33f 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -1556,7 +1556,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
         }
     }
 
-
     if (recreateVertexArrays) {
         vertexCoordinates->clear();
         textureCoordinates->clear();
@@ -1569,7 +1568,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;
 
@@ -1580,10 +1582,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);
@@ -1672,9 +1676,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);
@@ -1722,10 +1726,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
 }
 
-- 
cgit v0.12


From 254281dae38b932998eb8014a55177948842b78d Mon Sep 17 00:00:00 2001
From: Joshua Grauman <jnfo@grauman.com>
Date: Tue, 4 Jan 2011 11:03:32 +0100
Subject: Add line spacing to QTextBlockFormat, get/set functions, CSS support

The patch adds line spacing options to Qt, as in all modern word
processors. I primarily checked OpenOffice as a reference for how to
position the lines based on the various types of line spacing as well
as where to do the page breaks. The following functions were added:

void QTextBlockFormat::setLineHeight(qreal height, int heightType)
qreal QTextBlockFormat::lineHeight()
int QTextBlockFormat::lineHeightType()
qreal QTextBlockFormat::lineHeight(qreal scriptLineHeight, qreal scaling)

Here are the HeightTypes available:
QTextBlockFormat::SingleHeight
QTextBlockFormat::ProportionalHeight
QTextBlockFormat::FixedHeight
QTextBlockFormat::AtLeastHeight
QTextBlockFormat::LineDistanceHeight

The following CSS syntax was added:
line-height:150%
line-height:40px
line-height:normal
line-height:40al
line-height:40ld

Merge-request: 2305
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
---
 src/gui/text/qcssparser.cpp          |  1 +
 src/gui/text/qcssparser_p.h          |  1 +
 src/gui/text/qtextdocumentlayout.cpp | 38 ++++++++++++++++----
 src/gui/text/qtextformat.cpp         | 67 ++++++++++++++++++++++++++++++++++++
 src/gui/text/qtextformat.h           | 35 +++++++++++++++++++
 src/gui/text/qtexthtmlparser.cpp     | 18 ++++++++++
 6 files changed, 154 insertions(+), 6 deletions(-)

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/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index ff14490..5334ae8 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::AtLeastHeight) {
+        *lineBreakHeight = *lineHeight;
+        if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight)
+            *lineAdjustment = QFixed::fromReal(line.ascent() + qMax(line.leading(), 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..719db7a 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.7
+    \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 AtLeastHeight 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.7
+
+    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.7
+
+    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.7
+
+    This returns the LineHeight property for the paragraph.
+
+    \sa LineHeightTypes, setLineHeight(), lineHeightType()
+*/
+
+
+/*!
+    \fn qreal QTextBlockFormat::lineHeightType() const
+    \since 4.7
+
+    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..41cc1d9 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,
+        AtLeastHeight = 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 AtLeastHeight:
+      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..769a509 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -1250,6 +1250,24 @@ 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 if (decl.realValue(&lineHeight, "al"))
+                blockFormat.setLineHeight(lineHeight, QTextBlockFormat::AtLeastHeight);
+            else if (decl.realValue(&lineHeight, "ld"))
+                blockFormat.setLineHeight(lineHeight, QTextBlockFormat::LineDistanceHeight);
+            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"))
-- 
cgit v0.12


From 09b06552f98f8ee8be4d156049a6a37a4abed6bd Mon Sep 17 00:00:00 2001
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
Date: Tue, 4 Jan 2011 11:09:38 +0100
Subject: Rename QTextBlockFormat::AtLeastHeight -> MinimumHeight

Make some alterations to merge request 2305:
1. Rename enum for consistency with other APIs in Qt.
2. Correct documentation with actual version number of features.
3. Remove unstandard css syntax in line-height specification.

Reviewed-by: Jiang Jiang
---
 src/gui/text/qtextdocumentlayout.cpp |  2 +-
 src/gui/text/qtextformat.cpp         | 12 ++++++------
 src/gui/text/qtextformat.h           |  4 ++--
 src/gui/text/qtexthtmlparser.cpp     |  8 ++------
 4 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index 5334ae8..22c6b8c 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -2510,7 +2510,7 @@ static inline void getLineHeightParams(const QTextBlockFormat &blockFormat, cons
                                        QFixed *lineAdjustment, QFixed *lineBreakHeight, QFixed *lineHeight)
 {
     *lineHeight = QFixed::fromReal(blockFormat.lineHeight(line.height(), scaling));
-    if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight || blockFormat.lineHeightType() == QTextBlockFormat::AtLeastHeight) {
+    if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight || blockFormat.lineHeightType() == QTextBlockFormat::MinimumHeight) {
         *lineBreakHeight = *lineHeight;
         if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight)
             *lineAdjustment = QFixed::fromReal(line.ascent() + qMax(line.leading(), 0.0)) - ((*lineHeight * 4) / 5);
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 719db7a..b05a830 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -1878,7 +1878,7 @@ QFont QTextCharFormat::font() const
 */
 
 /*!
-    \since 4.7
+    \since 4.8
     \enum QTextBlockFormat::LineHeightTypes
 
     This enum describes the various types of line spacing support paragraphs can have.
@@ -1887,7 +1887,7 @@ QFont QTextCharFormat::font() const
     \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 AtLeastHeight This sets the minimum 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()
@@ -2112,7 +2112,7 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
 
 /*!
     \fn void QTextBlockFormat::setLineHeight(qreal height, int heightType)
-    \since 4.7
+    \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.
@@ -2123,7 +2123,7 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
 
 /*!
     \fn qreal QTextBlockFormat::lineHeight(qreal scriptLineHeight, qreal scaling) const
-    \since 4.7
+    \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
@@ -2137,7 +2137,7 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
 
 /*!
     \fn qreal QTextBlockFormat::lineHeight() const
-    \since 4.7
+    \since 4.8
 
     This returns the LineHeight property for the paragraph.
 
@@ -2147,7 +2147,7 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
 
 /*!
     \fn qreal QTextBlockFormat::lineHeightType() const
-    \since 4.7
+    \since 4.8
 
     This returns the LineHeightType property of the paragraph.
 
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index 41cc1d9..81b053b 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -537,7 +537,7 @@ public:
         SingleHeight = 0,
         ProportionalHeight = 1,
         FixedHeight = 2,
-        AtLeastHeight = 3,
+        MinimumHeight = 3,
         LineDistanceHeight = 4
     };
 
@@ -619,7 +619,7 @@ inline qreal QTextBlockFormat::lineHeight(qreal scriptLineHeight, qreal scaling
       return(scriptLineHeight * doubleProperty(LineHeight) / 100.0);
     case FixedHeight:
       return(doubleProperty(LineHeight) * scaling);
-    case AtLeastHeight:
+    case MinimumHeight:
       return(qMax(scriptLineHeight, doubleProperty(LineHeight) * scaling));
     case LineDistanceHeight:
       return(scriptLineHeight + doubleProperty(LineHeight) * scaling);
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 769a509..5d5e2b6 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -1252,13 +1252,9 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
             break;
        case QCss::LineHeight: {
             qreal lineHeight;
-            if (decl.realValue(&lineHeight, "px"))
+            if (decl.realValue(&lineHeight, "px")) {
                 blockFormat.setLineHeight(lineHeight, QTextBlockFormat::FixedHeight);
-            else if (decl.realValue(&lineHeight, "al"))
-                blockFormat.setLineHeight(lineHeight, QTextBlockFormat::AtLeastHeight);
-            else if (decl.realValue(&lineHeight, "ld"))
-                blockFormat.setLineHeight(lineHeight, QTextBlockFormat::LineDistanceHeight);
-            else {
+            } else {
                 bool ok;
                 QString value = decl.d->values.first().toString();
                 lineHeight = value.toDouble(&ok);
-- 
cgit v0.12


From 18447df1d021cfed69472b867cb7593401be27a6 Mon Sep 17 00:00:00 2001
From: Jiang Jiang <jiang.jiang@nokia.com>
Date: Wed, 5 Jan 2011 19:39:00 +0100
Subject: Make application font family names locale sensitive in X11

So that they will match the family names returned by
QFontDatabase::families. Because the family names returned
by FcFreeTypeQueryFace are not sorted with locale as the
names returned by FcFontList, we have to find out the
family name matching the system language in the former case.

Task-number: QTBUG-14269
Reviewed-by: Eskil
---
 src/gui/text/qfontdatabase.cpp     |  3 +++
 src/gui/text/qfontdatabase_x11.cpp | 23 +++++++++++++++++++++--
 2 files changed, 24 insertions(+), 2 deletions(-)

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;
         }
-- 
cgit v0.12


From 0faab4442040fdfe3790e3c02808fd45993f0265 Mon Sep 17 00:00:00 2001
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
Date: Mon, 10 Jan 2011 10:25:42 +0100
Subject: Compile when qreal != double

Compile fix for devices where qreals are floats.

Reviewed-by: Fabien Freling
---
 src/gui/text/qtextdocumentlayout.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index 22c6b8c..c0f3fb4 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -2513,7 +2513,7 @@ static inline void getLineHeightParams(const QTextBlockFormat &blockFormat, cons
     if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight || blockFormat.lineHeightType() == QTextBlockFormat::MinimumHeight) {
         *lineBreakHeight = *lineHeight;
         if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight)
-            *lineAdjustment = QFixed::fromReal(line.ascent() + qMax(line.leading(), 0.0)) - ((*lineHeight * 4) / 5);
+            *lineAdjustment = QFixed::fromReal(line.ascent() + qMax(line.leading(), qreal(0.0))) - ((*lineHeight * 4) / 5);
         else
             *lineAdjustment = QFixed::fromReal(line.height()) - *lineHeight;
     }
-- 
cgit v0.12


From 1e4197d2f2994d524116761046626bd430a2df3f Mon Sep 17 00:00:00 2001
From: Jiang Jiang <jiang.jiang@nokia.com>
Date: Tue, 11 Jan 2011 09:45:03 +0100
Subject: Only test control character handling in X11

It was a issue in HarfBuzz only.

Reviewed-by: Andy Shaw
---
 tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp b/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp
index b0b6b1e..88212c6 100644
--- a/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp
+++ b/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp
@@ -1114,6 +1114,7 @@ void tst_QTextScriptEngine::greek()
 
 void tst_QTextScriptEngine::controlInSyllable_qtbug14204()
 {
+#if defined(Q_WS_X11)
     QString s;
     s.append(QChar(0x0915));
     s.append(QChar(0x094d));
@@ -1127,6 +1128,9 @@ void tst_QTextScriptEngine::controlInSyllable_qtbug14204()
 
     QVERIFY(e->layoutData->items[0].num_glyphs == 2);
     QVERIFY(e->layoutData->glyphLayout.advances_x[1] != 0);
+#else
+    QSKIP("X11 specific test", SkipAll);
+#endif
 }
 
 QTEST_MAIN(tst_QTextScriptEngine)
-- 
cgit v0.12