From 9485bb616286bbc8e04d0add08d8e82e9558a766 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Wed, 13 Jul 2022 10:42:05 +0200 Subject: Let CSS attributes have higher priority than the plain XML attributes Although seemingly not well specified, the common behavior of web browsers and other SVG renderers is to give priority to attribute values specified in the CSS style attribute, in case of conflict. So make qtsvg do the same, by moving the CSS parsing block to after the XML attribute parsing block. Fixes: QTBUG-100068 Pick-to: 6.4 Change-Id: I769303d69509511103d96e8d26e2cfeac1f19494 Reviewed-by: Shawn Rutledge Reviewed-by: Edward Welbourne --- src/svg/qsvghandler.cpp | 215 ++++++++++++++++++++++++------------------------ 1 file changed, 107 insertions(+), 108 deletions(-) (limited to 'src') diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index e730eed..677dc97 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -195,112 +195,6 @@ struct QSvgAttributes QSvgAttributes::QSvgAttributes(const QXmlStreamAttributes &xmlAttributes, QSvgHandler *handler) { -#ifndef QT_NO_CSSPARSER - QStringView style = xmlAttributes.value(QLatin1String("style")); - if (!style.isEmpty()) { - handler->parseCSStoXMLAttrs(style.toString(), &m_cssAttributes); - for (int j = 0; j < m_cssAttributes.count(); ++j) { - const QSvgCssAttribute &attribute = m_cssAttributes.at(j); - QStringView name = attribute.name; - QStringView value = attribute.value; - if (name.isEmpty()) - continue; - - switch (name.at(0).unicode()) { - - case 'c': - if (name == QLatin1String("color")) - color = value; - else if (name == QLatin1String("color-opacity")) - colorOpacity = value; - else if (name == QLatin1String("comp-op")) - compOp = value; - break; - - case 'd': - if (name == QLatin1String("display")) - display = value; - break; - - case 'f': - if (name == QLatin1String("fill")) - fill = value; - else if (name == QLatin1String("fill-rule")) - fillRule = value; - else if (name == QLatin1String("fill-opacity")) - fillOpacity = value; - else if (name == QLatin1String("font-family")) - fontFamily = value; - else if (name == QLatin1String("font-size")) - fontSize = value; - else if (name == QLatin1String("font-style")) - fontStyle = value; - else if (name == QLatin1String("font-weight")) - fontWeight = value; - else if (name == QLatin1String("font-variant")) - fontVariant = value; - break; - case 'i': - if (name == QLatin1String("image-rendering")) - imageRendering = value; - break; - - case 'o': - if (name == QLatin1String("opacity")) - opacity = value; - else if (name == QLatin1String("offset")) - offset = value; - break; - - case 's': - if (name.length() > 5 && name.mid(1, 5) == QLatin1String("troke")) { - QStringView strokeRef = name.mid(6, name.length() - 6); - if (strokeRef.isEmpty()) - stroke = value; - else if (strokeRef == QLatin1String("-dasharray")) - strokeDashArray = value; - else if (strokeRef == QLatin1String("-dashoffset")) - strokeDashOffset = value; - else if (strokeRef == QLatin1String("-linecap")) - strokeLineCap = value; - else if (strokeRef == QLatin1String("-linejoin")) - strokeLineJoin = value; - else if (strokeRef == QLatin1String("-miterlimit")) - strokeMiterLimit = value; - else if (strokeRef == QLatin1String("-opacity")) - strokeOpacity = value; - else if (strokeRef == QLatin1String("-width")) - strokeWidth = value; - } - else if (name == QLatin1String("stop-color")) - stopColor = value; - else if (name == QLatin1String("stop-opacity")) - stopOpacity = value; - break; - - case 't': - if (name == QLatin1String("text-anchor")) - textAnchor = value; - else if (name == QLatin1String("transform")) - transform = value; - break; - - case 'v': - if (name == QLatin1String("vector-effect")) - vectorEffect = value; - else if (name == QLatin1String("visibility")) - visibility = value; - break; - - default: - break; - } - } - } -#else - Q_UNUSED(handler); -#endif // QT_NO_CSSPARSER - for (int i = 0; i < xmlAttributes.count(); ++i) { const QXmlStreamAttribute &attribute = xmlAttributes.at(i); QStringView name = attribute.qualifiedName(); @@ -376,8 +270,7 @@ QSvgAttributes::QSvgAttributes(const QXmlStreamAttributes &xmlAttributes, QSvgHa strokeOpacity = value; else if (strokeRef == QLatin1String("-width")) strokeWidth = value; - } - else if (name == QLatin1String("stop-color")) + } else if (name == QLatin1String("stop-color")) stopColor = value; else if (name == QLatin1String("stop-opacity")) stopOpacity = value; @@ -407,6 +300,112 @@ QSvgAttributes::QSvgAttributes(const QXmlStreamAttributes &xmlAttributes, QSvgHa } } + // If a style attribute is present, let its attribute settings override the plain attribute + // values. The spec seems to indicate that, and it is common behavior in svg renderers. +#ifndef QT_NO_CSSPARSER + QStringView style = xmlAttributes.value(QLatin1String("style")); + if (!style.isEmpty()) { + handler->parseCSStoXMLAttrs(style.toString(), &m_cssAttributes); + for (int j = 0; j < m_cssAttributes.count(); ++j) { + const QSvgCssAttribute &attribute = m_cssAttributes.at(j); + QStringView name = attribute.name; + QStringView value = attribute.value; + if (name.isEmpty()) + continue; + + switch (name.at(0).unicode()) { + + case 'c': + if (name == QLatin1String("color")) + color = value; + else if (name == QLatin1String("color-opacity")) + colorOpacity = value; + else if (name == QLatin1String("comp-op")) + compOp = value; + break; + + case 'd': + if (name == QLatin1String("display")) + display = value; + break; + + case 'f': + if (name == QLatin1String("fill")) + fill = value; + else if (name == QLatin1String("fill-rule")) + fillRule = value; + else if (name == QLatin1String("fill-opacity")) + fillOpacity = value; + else if (name == QLatin1String("font-family")) + fontFamily = value; + else if (name == QLatin1String("font-size")) + fontSize = value; + else if (name == QLatin1String("font-style")) + fontStyle = value; + else if (name == QLatin1String("font-weight")) + fontWeight = value; + else if (name == QLatin1String("font-variant")) + fontVariant = value; + break; + case 'i': + if (name == QLatin1String("image-rendering")) + imageRendering = value; + break; + + case 'o': + if (name == QLatin1String("opacity")) + opacity = value; + else if (name == QLatin1String("offset")) + offset = value; + break; + + case 's': + if (name.length() > 5 && name.mid(1, 5) == QLatin1String("troke")) { + QStringView strokeRef = name.mid(6, name.length() - 6); + if (strokeRef.isEmpty()) + stroke = value; + else if (strokeRef == QLatin1String("-dasharray")) + strokeDashArray = value; + else if (strokeRef == QLatin1String("-dashoffset")) + strokeDashOffset = value; + else if (strokeRef == QLatin1String("-linecap")) + strokeLineCap = value; + else if (strokeRef == QLatin1String("-linejoin")) + strokeLineJoin = value; + else if (strokeRef == QLatin1String("-miterlimit")) + strokeMiterLimit = value; + else if (strokeRef == QLatin1String("-opacity")) + strokeOpacity = value; + else if (strokeRef == QLatin1String("-width")) + strokeWidth = value; + } else if (name == QLatin1String("stop-color")) + stopColor = value; + else if (name == QLatin1String("stop-opacity")) + stopOpacity = value; + break; + + case 't': + if (name == QLatin1String("text-anchor")) + textAnchor = value; + else if (name == QLatin1String("transform")) + transform = value; + break; + + case 'v': + if (name == QLatin1String("vector-effect")) + vectorEffect = value; + else if (name == QLatin1String("visibility")) + visibility = value; + break; + + default: + break; + } + } + } +#else + Q_UNUSED(handler); +#endif // QT_NO_CSSPARSER } #ifndef QT_NO_CSSPARSER -- cgit v1.2.1