summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/svg/qsvghandler.cpp57
-rw-r--r--src/svg/qsvgstyle.cpp14
-rw-r--r--src/svg/qsvgstyle_p.h28
-rw-r--r--tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp68
4 files changed, 132 insertions, 35 deletions
diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp
index 5950fac..f64fb3e 100644
--- a/src/svg/qsvghandler.cpp
+++ b/src/svg/qsvghandler.cpp
@@ -631,15 +631,32 @@ static void parseBrush(QSvgNode *node,
QString opacity = attributes.value(QLatin1String("fill-opacity")).toString();
QString myId = someId(attributes);
- value = value.trimmed();
- fillRule = fillRule.trimmed();
- if (!value.isEmpty() || !fillRule.isEmpty()) {
- Qt::FillRule f = Qt::WindingFill;
+ QSvgFillStyle *inherited =
+ static_cast<QSvgFillStyle*>(node->parent()->styleProperty(
+ QSvgStyleProperty::FILL));
+ QSvgFillStyle *prop = new QSvgFillStyle(QColor(Qt::black));
+
+ //fill-rule attribute handling
+ Qt::FillRule f = Qt::WindingFill;
+ if (!fillRule.isEmpty() && fillRule != QLatin1String("inherit")) {
if (fillRule == QLatin1String("evenodd"))
f = Qt::OddEvenFill;
+ } else if (inherited) {
+ f = inherited->fillRule();
+ }
+
+ //fill-opacity atttribute handling
+ qreal fillOpacity = 1.0;
+ if (!opacity.isEmpty() && opacity != QLatin1String("inherit")) {
+ fillOpacity = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity)));
+ } else if (inherited) {
+ fillOpacity = inherited->fillOpacity();
+ }
+
+ //fill attribute handling
+ if ((!value.isEmpty()) && (value != QLatin1String("inherit")) ) {
if (value.startsWith(QLatin1String("url"))) {
value = value.remove(0, 3);
- QSvgFillStyle *prop = new QSvgFillStyle(0);
QSvgStyleProperty *style = styleFromUrl(node, value);
if (style) {
prop->setFillStyle(style);
@@ -648,30 +665,26 @@ static void parseBrush(QSvgNode *node,
prop->setGradientId(id);
prop->setGradientResolved(false);
}
- if (!opacity.isEmpty()) {
- qreal clampedOpacity = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity)));
- prop->setFillOpacity(clampedOpacity);
- }
- if (!fillRule.isEmpty())
- prop->setFillRule(f);
- node->appendStyleProperty(prop,myId);
} else if (value != QLatin1String("none")) {
QColor color;
- if (constructColor(value, opacity, color, handler)) {
- QSvgFillStyle *prop = new QSvgFillStyle(QBrush(color));
- if (!fillRule.isEmpty())
- prop->setFillRule(f);
- node->appendStyleProperty(prop, myId);
- }
+ if (resolveColor(value, color, handler))
+ prop->setBrush(QBrush(color));
} else {
- QSvgFillStyle *prop = new QSvgFillStyle(QBrush(Qt::NoBrush));
- if (!fillRule.isEmpty())
- prop->setFillRule(f);
- node->appendStyleProperty(prop, myId);
+ prop->setBrush(QBrush(Qt::NoBrush));
+ }
+ } else if (inherited) {
+ if (inherited->style()) {
+ prop->setFillStyle(inherited->style());
+ } else {
+ prop->setBrush(inherited->qbrush());
}
}
+ prop->setFillOpacity(fillOpacity);
+ prop->setFillRule(f);
+ node->appendStyleProperty(prop,myId);
}
+
static void parseQPen(QPen &pen, QSvgNode *node,
const QSvgAttributes &attributes,
QSvgHandler *handler)
diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp
index 556201b..4c8247b 100644
--- a/src/svg/qsvgstyle.cpp
+++ b/src/svg/qsvgstyle.cpp
@@ -81,12 +81,12 @@ void QSvgQualityStyle::revert(QPainter *, QSvgExtraStates &)
}
QSvgFillStyle::QSvgFillStyle(const QBrush &brush)
- : m_fill(brush), m_style(0), m_fillRuleSet(false), m_fillOpacitySet(false), m_gradientResolved (true)
+ : m_fill(brush), m_style(0), m_fillRuleSet(false), m_fillOpacitySet(false), m_fillRule(Qt::WindingFill), m_fillOpacity(1.0), m_gradientResolved (true)
{
}
QSvgFillStyle::QSvgFillStyle(QSvgStyleProperty *style)
- : m_style(style), m_fillRuleSet(false), m_fillOpacitySet(false), m_gradientResolved (true)
+ : m_style(style), m_fillRuleSet(false), m_fillOpacitySet(false), m_fillRule(Qt::WindingFill), m_fillOpacity(1.0), m_gradientResolved (true)
{
}
@@ -102,6 +102,16 @@ void QSvgFillStyle::setFillOpacity(qreal opacity)
m_fillOpacity = opacity;
}
+void QSvgFillStyle::setFillStyle(QSvgStyleProperty* style)
+{
+ m_style = style;
+}
+
+void QSvgFillStyle::setBrush(QBrush brush)
+{
+ m_fill = brush;
+}
+
static void recursivelySetFill(QSvgNode *node, Qt::FillRule f)
{
if (node->type() == QSvgNode::PATH) {
diff --git a/src/svg/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h
index f1d0811..ac5e109 100644
--- a/src/svg/qsvgstyle_p.h
+++ b/src/svg/qsvgstyle_p.h
@@ -224,12 +224,29 @@ public:
void setFillRule(Qt::FillRule f);
void setFillOpacity(qreal opacity);
+ void setFillStyle(QSvgStyleProperty* style);
+ void setBrush(QBrush brush);
const QBrush & qbrush() const
{
return m_fill;
}
+ qreal fillOpacity() const
+ {
+ return m_fillOpacity;
+ }
+
+ Qt::FillRule fillRule() const
+ {
+ return m_fillRule;
+ }
+
+ QSvgStyleProperty* style() const
+ {
+ return m_style;
+ }
+
void setGradientId(const QString &Id)
{
m_gradientId = Id;
@@ -240,7 +257,6 @@ public:
return m_gradientId;
}
-
void setGradientResolved(bool resolved)
{
m_gradientResolved = resolved;
@@ -251,16 +267,6 @@ public:
return m_gradientResolved;
}
- void setFillStyle(QSvgStyleProperty* style)
- {
- m_style = style;
- }
-
- void setBrush(QBrush brush)
- {
- m_fill = brush;
- }
-
private:
// fill v v 'inherit' | <Paint.datatype>
// fill-opacity v v 'inherit' | <OpacityValue.datatype>
diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
index 3f658ec..68539ef 100644
--- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
+++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
@@ -81,6 +81,7 @@ private slots:
void paths();
void displayMode();
void strokeInherit();
+ void testFillInheritance();
#ifndef QT_NO_COMPRESS
void testGzLoading();
@@ -1053,5 +1054,72 @@ void tst_QSvgRenderer::strokeInherit()
}
}
+void tst_QSvgRenderer::testFillInheritance()
+{
+ static const char *svgs[] = {
+ //reference
+ "<svg viewBox = \"0 0 200 200\">"
+ " <polygon points=\"20,20 50,120 100,10 40,80 50,80\" fill= \"red\" stroke = \"blue\" fill-opacity = \"0.5\" fill-rule = \"evenodd\"/>"
+ "</svg>",
+ "<svg viewBox = \"0 0 200 200\">"
+ " <polygon points=\"20,20 50,120 100,10 40,80 50,80\" fill= \"red\" stroke = \"blue\" fill-opacity = \"0.5\" fill-rule = \"evenodd\"/>"
+ " <rect x = \"40\" y = \"40\" width = \"70\" height =\"20\" fill = \"green\" fill-opacity = \"0\"/>"
+ "</svg>",
+ "<svg viewBox = \"0 0 200 200\">"
+ " <g fill = \"red\" fill-opacity = \"0.5\" fill-rule = \"evenodd\">"
+ " <polygon points=\"20,20 50,120 100,10 40,80 50,80\" stroke = \"blue\"/>"
+ " </g>"
+ " <rect x = \"40\" y = \"40\" width = \"70\" height =\"20\" fill = \"green\" fill-opacity = \"0\"/>"
+ "</svg>",
+ "<svg viewBox = \"0 0 200 200\">"
+ " <g fill = \"green\" fill-rule = \"nonzero\">"
+ " <polygon points=\"20,20 50,120 100,10 40,80 50,80\" stroke = \"blue\" fill = \"red\" fill-opacity = \"0.5\" fill-rule = \"evenodd\"/>"
+ " </g>"
+ " <g fill-opacity = \"0.8\" fill = \"red\">"
+ " <rect x = \"40\" y = \"40\" width = \"70\" height =\"20\" fill = \"green\" fill-opacity = \"0\"/>"
+ " </g>"
+ "</svg>",
+ "<svg viewBox = \"0 0 200 200\">"
+ " <g fill = \"red\" >"
+ " <g fill-opacity = \"0.5\">"
+ " <g fill-rule = \"evenodd\">"
+ " <g>"
+ " <polygon points=\"20,20 50,120 100,10 40,80 50,80\" stroke = \"blue\"/>"
+ " </g>"
+ " </g>"
+ " </g>"
+ " </g>"
+ " <g fill-opacity = \"0.8\" >"
+ " <rect x = \"40\" y = \"40\" width = \"70\" height =\"20\" fill = \"none\"/>"
+ " </g>"
+ "</svg>",
+ "<svg viewBox = \"0 0 200 200\">"
+ " <g fill = \"none\" fill-opacity = \"0\">"
+ " <polygon points=\"20,20 50,120 100,10 40,80 50,80\" stroke = \"blue\" fill = \"red\" fill-opacity = \"0.5\" fill-rule = \"evenodd\"/>"
+ " </g>"
+ " <g fill-opacity = \"0\" >"
+ " <rect x = \"40\" y = \"40\" width = \"70\" height =\"20\" fill = \"green\"/>"
+ " </g>"
+ "</svg>"
+ };
+
+ const int COUNT = sizeof(svgs) / sizeof(svgs[0]);
+ QImage images[COUNT];
+ QPainter p;
+
+ for (int i = 0; i < COUNT; ++i) {
+ QByteArray data(svgs[i]);
+ QSvgRenderer renderer(data);
+ QVERIFY(renderer.isValid());
+ images[i] = QImage(200, 200, QImage::Format_ARGB32_Premultiplied);
+ images[i].fill(-1);
+ p.begin(&images[i]);
+ renderer.render(&p);
+ p.end();
+ if (i != 0) {
+ QCOMPARE(images[0], images[i]);
+ }
+ }
+}
QTEST_MAIN(tst_QSvgRenderer)
#include "tst_qsvgrenderer.moc"