Fix text color in some cases of QML and QStaticText

This reverts 518c2a58ed6fdfd7449cb4476aa8ea0d32ad16e3 which caused a
regression.

When writing systems are mixed and an underline is set on the font,
QPainter will set a pen with the current color and a new width on
itself before drawing the decoration. This would cause the recorder
in QStaticText to mark the pen as dirty, saving the current pen
color in all subsequent text items. The effect was e.g. that in QML
the cached color would override the current one, making it impossible
to change the color on the text without forcing a relayout somehow.

The right fix is to only mark the pen as dirty when its color actually
changes.

Task-number: QTBUG-20159
Change-Id: Ia819b67cccc9eaedd23fde655eab58cd892646f8
Reviewed-by: Jiang Jiang
Reviewed-on: http://codereview.qt.nokia.com/870
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
bb10
Eskil Abrahamsen Blomfeldt 2011-06-28 17:07:13 +02:00 committed by Qt by Nokia
parent 3debd70c08
commit 46c128bbf5
3 changed files with 48 additions and 3 deletions

View File

@ -427,14 +427,17 @@ namespace {
public:
DrawTextItemRecorder(bool untransformedCoordinates, bool useBackendOptimizations)
: m_dirtyPen(false), m_useBackendOptimizations(useBackendOptimizations),
m_untransformedCoordinates(untransformedCoordinates)
m_untransformedCoordinates(untransformedCoordinates), m_currentColor(Qt::black)
{
}
virtual void updateState(const QPaintEngineState &newState)
{
if (newState.state() & QPaintEngine::DirtyPen)
if (newState.state() & QPaintEngine::DirtyPen
&& newState.pen().color() != m_currentColor) {
m_dirtyPen = true;
m_currentColor = newState.pen().color();
}
}
virtual void drawTextItem(const QPointF &position, const QTextItem &textItem)
@ -450,7 +453,7 @@ namespace {
currentItem.positionOffset = m_glyphs.size(); // Offset into position pool
currentItem.useBackendOptimizations = m_useBackendOptimizations;
if (m_dirtyPen)
currentItem.color = state->pen().color();
currentItem.color = m_currentColor;
QTransform matrix = m_untransformedCoordinates ? QTransform() : state->transform();
matrix.translate(position.x(), position.y());
@ -521,6 +524,7 @@ namespace {
bool m_dirtyPen;
bool m_useBackendOptimizations;
bool m_untransformedCoordinates;
QColor m_currentColor;
};
class DrawTextItemDevice: public QPaintDevice

View File

@ -227,6 +227,7 @@ win32:SUBDIRS -= qtextpiecetable
qtextpiecetable \
qtipc \
qtoolbar \
qstatictext \
symbian:SUBDIRS -= \
qsystemtrayicon \

View File

@ -96,6 +96,9 @@ private slots:
void drawUnderlinedText();
void unprintableCharacter_qtbug12614();
void underlinedColor_qtbug20159();
void textDocumentColor();
};
void tst_QStaticText::init()
@ -783,5 +786,42 @@ void tst_QStaticText::unprintableCharacter_qtbug12614()
QVERIFY(staticText.size().isValid()); // Force layout. Should not crash.
}
void tst_QStaticText::underlinedColor_qtbug20159()
{
QString multiScriptText;
multiScriptText += QChar(0x0410); // Cyrillic 'A'
multiScriptText += QLatin1Char('A');
QStaticText staticText(multiScriptText);
QFont font;
font.setUnderline(true);
staticText.prepare(QTransform(), font);
QStaticTextPrivate *d = QStaticTextPrivate::get(&staticText);
QCOMPARE(d->itemCount, 2);
// The pen should not be marked as dirty when drawing the underline
QVERIFY(!d->items[0].color.isValid());
QVERIFY(!d->items[1].color.isValid());
}
void tst_QStaticText::textDocumentColor()
{
QStaticText staticText("A<font color=\"red\">B</font>");
staticText.setTextFormat(Qt::RichText);
staticText.prepare();
QStaticTextPrivate *d = QStaticTextPrivate::get(&staticText);
QCOMPARE(d->itemCount, 2);
// The pen should not be marked as dirty when drawing the underline
QVERIFY(!d->items[0].color.isValid());
QVERIFY(d->items[1].color.isValid());
QCOMPARE(d->items[1].color, QColor(Qt::red));
}
QTEST_MAIN(tst_QStaticText)
#include "tst_qstatictext.moc"