Implement support for stroke color and width in CSS parser

CSS does not have text outline properties, instead different
browsers have custom properties for this. That currently means
that you can have a QTextDocument where you applied a stroke to
text and textEdit.setHtml(textEdit.toHtml()) will remove it.

Since a primary goal of the HTML support in QTextDocument is that
it can be used to save and faithfully restore its contents, we
implement qt specific properties for stroke.

Task-number: QTBUG-123357
Change-Id: Id9cf63abfabe2109ffb6fd74f9cb013304763ccb
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2024-03-15 12:25:41 +01:00
parent 58796ac177
commit e205edfff6
5 changed files with 59 additions and 0 deletions

View File

@ -44,6 +44,8 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "-qt-list-number-prefix", QtListNumberPrefix },
{ "-qt-list-number-suffix", QtListNumberSuffix },
{ "-qt-paragraph-type", QtParagraphType },
{ "-qt-stroke-color", QtStrokeColor },
{ "-qt-stroke-width", QtStrokeWidth },
{ "-qt-style-features", QtStyleFeatures },
{ "-qt-table-type", QtTableType },
{ "-qt-user-state", QtUserState },

View File

@ -167,6 +167,8 @@ enum Property {
TextDecorationColor,
QtPlaceHolderTextColor,
QtAccent,
QtStrokeWidth,
QtStrokeColor,
NumProperties
};

View File

@ -2701,6 +2701,18 @@ bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format)
attributesEmitted = true;
}
if (format.hasProperty(QTextFormat::TextOutline)) {
QPen outlinePen = format.textOutline();
html += " -qt-stroke-color:"_L1;
html += colorValue(outlinePen.color());
html += u';';
html += " -qt-stroke-width:"_L1;
html += QString::number(outlinePen.widthF());
html += "px;"_L1;
attributesEmitted = true;
}
return attributesEmitted;
}

View File

@ -1387,6 +1387,24 @@ void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &d
}
break;
}
case QCss::QtStrokeColor:
{
QPen pen = charFormat.textOutline();
pen.setStyle(Qt::SolidLine);
pen.setColor(decl.colorValue());
charFormat.setTextOutline(pen);
break;
}
case QCss::QtStrokeWidth:
{
qreal width;
if (decl.realValue(&width, "px")) {
QPen pen = charFormat.textOutline();
pen.setWidthF(width);
charFormat.setTextOutline(pen);
}
break;
}
default: break;
}
}

View File

@ -183,6 +183,8 @@ private slots:
void delayedLayout();
void undoContentChangeIndices();
void restoreStrokeFromHtml();
private:
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
void buildRegExpData();
@ -4045,5 +4047,28 @@ void tst_QTextDocument::undoContentChangeIndices() // QTBUG-113865
QVERIFY(documentLength >= changeEnd);
}
void tst_QTextDocument::restoreStrokeFromHtml()
{
QTextDocument document;
QTextCursor textCursor(&document);
QTextCharFormat textOutline;
textOutline.setTextOutline(QPen(Qt::red, 2.3));
textCursor.insertText("Outlined text", textOutline);
{
QTextDocument otherDocument;
otherDocument.setHtml(document.toHtml());
QCOMPARE(otherDocument.blockCount(), 1);
QTextBlock block = otherDocument.firstBlock();
QTextFragment fragment = block.begin().fragment();
QCOMPARE(fragment.text(), QStringLiteral("Outlined text"));
QTextCharFormat fmt = fragment.charFormat();
QVERIFY(fmt.hasProperty(QTextCharFormat::TextOutline));
QPen pen = fmt.textOutline();
QCOMPARE(pen.color(), QColor(Qt::red));
QCOMPARE(pen.widthF(), 2.3);
}
}
QTEST_MAIN(tst_QTextDocument)
#include "tst_qtextdocument.moc"