summaryrefslogtreecommitdiffstats
path: root/src/svg
diff options
context:
space:
mode:
authorKim Motoyoshi Kalland <kim.kalland@nokia.com>2009-09-14 15:50:30 (GMT)
committerKim Motoyoshi Kalland <kim.kalland@nokia.com>2009-09-14 15:57:15 (GMT)
commitab35f0f8b0d872bc2e963c6ef869fade71b83e3f (patch)
treeaf58509d936d6656fd6340c5f5da04aec85e912f /src/svg
parent886feff55f48ebdff0440278e611f822e6326c91 (diff)
downloadQt-ab35f0f8b0d872bc2e963c6ef869fade71b83e3f.zip
Qt-ab35f0f8b0d872bc2e963c6ef869fade71b83e3f.tar.gz
Qt-ab35f0f8b0d872bc2e963c6ef869fade71b83e3f.tar.bz2
Fixed gradient referencing in SVGs.
An SVG element can now reference a gradient or solid-color defined anywhere in the same SVG file. Task-number: 245602 Reviewed-by: Trond
Diffstat (limited to 'src/svg')
-rw-r--r--src/svg/qsvghandler.cpp94
-rw-r--r--src/svg/qsvghandler_p.h1
-rw-r--r--src/svg/qsvgnode.cpp110
-rw-r--r--src/svg/qsvgnode_p.h6
-rw-r--r--src/svg/qsvgstructure.cpp50
-rw-r--r--src/svg/qsvgstructure_p.h3
-rw-r--r--src/svg/qsvgstyle.cpp4
-rw-r--r--src/svg/qsvgtinydocument.cpp20
-rw-r--r--src/svg/qsvgtinydocument_p.h6
9 files changed, 135 insertions, 159 deletions
diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp
index f287d5e..a6e4855 100644
--- a/src/svg/qsvghandler.cpp
+++ b/src/svg/qsvghandler.cpp
@@ -975,15 +975,7 @@ static void parseColor(QSvgNode *,
static QSvgStyleProperty *styleFromUrl(QSvgNode *node, const QString &url)
{
- while (node && (node->type() != QSvgNode::DOC &&
- node->type() != QSvgNode::G &&
- node->type() != QSvgNode::DEFS &&
- node->type() != QSvgNode::SWITCH)) {
- node = node->parent();
- }
- if (!node)
- return 0;
- return static_cast<QSvgStructureNode*>(node)->scopeStyle(idFromUrl(url));
+ return node ? node->styleProperty(idFromUrl(url)) : 0;
}
static void parseBrush(QSvgNode *node,
@@ -3559,10 +3551,9 @@ void QSvgHandler::parse()
case QXmlStreamReader::ProcessingInstruction:
processingInstruction(xml->processingInstructionTarget().toString(), xml->processingInstructionData().toString());
break;
- default:
- ;
}
}
+ resolveGradients(m_doc);
}
bool QSvgHandler::startElement(const QString &localName,
@@ -3672,7 +3663,7 @@ bool QSvgHandler::startElement(const QString &localName,
QSvgStyleProperty *prop = method(m_nodes.top(), attributes, this);
if (prop) {
m_style = prop;
- m_nodes.top()->appendStyleProperty(prop, someId(attributes), true);
+ m_nodes.top()->appendStyleProperty(prop, someId(attributes));
} else {
qWarning("Could not parse node: %s", qPrintable(localName));
}
@@ -3713,53 +3704,52 @@ bool QSvgHandler::endElement(const QStringRef &localName)
if (m_inStyle && localName == QLatin1String("style"))
m_inStyle = false;
- if (node == Graphics) {
- // Iterate through the m_renderers to resolve any unresolved gradients.
- QSvgNode* curNode = static_cast<QSvgNode*>(m_nodes.top());
- if (curNode->type() == QSvgNode::DOC ||
- curNode->type() == QSvgNode::G ||
- curNode->type() == QSvgNode::DEFS ||
- curNode->type() == QSvgNode::SWITCH) {
- QSvgStructureNode* structureNode = static_cast<QSvgStructureNode*>(curNode);
- QList<QSvgNode*> ren = structureNode->renderers();
- QList<QSvgNode*>::iterator itr = ren.begin();
- while (itr != ren.end()) {
- QSvgNode *eleNode = *itr++;
- QSvgFillStyle *fill = static_cast<QSvgFillStyle*>(eleNode->styleProperty(QSvgStyleProperty::FILL));
- if (fill && !(fill->isGradientResolved())) {
- QString id = fill->gradientId();
- QSvgStyleProperty *style = structureNode->scopeStyle(id);
- if (style) {
- if (style->type() == QSvgStyleProperty::SOLID_COLOR || style->type() == QSvgStyleProperty::GRADIENT)
- fill->setFillStyle(reinterpret_cast<QSvgFillStyleProperty *>(style));
- } else {
- qWarning("Could not resolve property : %s",qPrintable(id));
- fill->setBrush(QBrush(Qt::NoBrush));
- }
- }
- QSvgStrokeStyle *stroke = static_cast<QSvgStrokeStyle*>(eleNode->styleProperty(QSvgStyleProperty::STROKE));
- if (stroke && !(stroke->isGradientResolved())) {
- QString id = stroke->gradientId();
- QSvgStyleProperty *style = structureNode->scopeStyle(id);
- if (style) {
- if (style->type() == QSvgStyleProperty::SOLID_COLOR || style->type() == QSvgStyleProperty::GRADIENT)
- stroke->setStyle(reinterpret_cast<QSvgFillStyleProperty *>(style));
- } else {
- qWarning("Could not resolve property : %s",qPrintable(id));
- stroke->setStroke(QBrush(Qt::NoBrush));
- }
- }
- }
- }
+ if (node == Graphics)
m_nodes.pop();
- }
-
else if (m_style && !m_skipNodes.isEmpty() && m_skipNodes.top() != Style)
m_style = 0;
return true;
}
+void QSvgHandler::resolveGradients(QSvgNode *node)
+{
+ if (!node || (node->type() != QSvgNode::DOC && node->type() != QSvgNode::G
+ && node->type() != QSvgNode::DEFS && node->type() != QSvgNode::SWITCH)) {
+ return;
+ }
+ QSvgStructureNode *structureNode = static_cast<QSvgStructureNode *>(node);
+
+ QList<QSvgNode *> ren = structureNode->renderers();
+ for (QList<QSvgNode *>::iterator it = ren.begin(); it != ren.end(); ++it) {
+ QSvgFillStyle *fill = static_cast<QSvgFillStyle *>((*it)->styleProperty(QSvgStyleProperty::FILL));
+ if (fill && !fill->isGradientResolved()) {
+ QString id = fill->gradientId();
+ QSvgFillStyleProperty *style = structureNode->styleProperty(id);
+ if (style) {
+ fill->setFillStyle(style);
+ } else {
+ qWarning("Could not resolve property : %s", qPrintable(id));
+ fill->setBrush(Qt::NoBrush);
+ }
+ }
+
+ QSvgStrokeStyle *stroke = static_cast<QSvgStrokeStyle *>((*it)->styleProperty(QSvgStyleProperty::STROKE));
+ if (stroke && !stroke->isGradientResolved()) {
+ QString id = stroke->gradientId();
+ QSvgFillStyleProperty *style = structureNode->styleProperty(id);
+ if (style) {
+ stroke->setStyle(style);
+ } else {
+ qWarning("Could not resolve property : %s", qPrintable(id));
+ stroke->setStroke(Qt::NoBrush);
+ }
+ }
+
+ resolveGradients(*it);
+ }
+}
+
bool QSvgHandler::characters(const QStringRef &str)
{
if (m_inStyle) {
diff --git a/src/svg/qsvghandler_p.h b/src/svg/qsvghandler_p.h
index aff6f1d..daf1b1c 100644
--- a/src/svg/qsvghandler_p.h
+++ b/src/svg/qsvghandler_p.h
@@ -172,6 +172,7 @@ private:
QXmlStreamReader *const xml;
QCss::Parser m_cssParser;
void parse();
+ void resolveGradients(QSvgNode *node);
QPen m_defaultPen;
/**
diff --git a/src/svg/qsvgnode.cpp b/src/svg/qsvgnode.cpp
index 6b8254e..2e27cd5 100644
--- a/src/svg/qsvgnode.cpp
+++ b/src/svg/qsvgnode.cpp
@@ -60,56 +60,57 @@ QSvgNode::~QSvgNode()
}
-void QSvgNode::appendStyleProperty(QSvgStyleProperty *prop, const QString &id,
- bool justLink)
+void QSvgNode::appendStyleProperty(QSvgStyleProperty *prop, const QString &id)
{
//qDebug()<<"appending "<<prop->type()<< " ("<< id <<") "<<"to "<<this<<this->type();
- if (!justLink) {
- switch (prop->type()) {
- case QSvgStyleProperty::QUALITY:
- m_style.quality = static_cast<QSvgQualityStyle*>(prop);
- break;
- case QSvgStyleProperty::FILL:
- m_style.fill = static_cast<QSvgFillStyle*>(prop);
- break;
- case QSvgStyleProperty::VIEWPORT_FILL:
- m_style.viewportFill = static_cast<QSvgViewportFillStyle*>(prop);
- break;
- case QSvgStyleProperty::FONT:
- m_style.font = static_cast<QSvgFontStyle*>(prop);
- break;
- case QSvgStyleProperty::STROKE:
- m_style.stroke = static_cast<QSvgStrokeStyle*>(prop);
- break;
- case QSvgStyleProperty::SOLID_COLOR:
- m_style.solidColor = static_cast<QSvgSolidColorStyle*>(prop);
- break;
- case QSvgStyleProperty::GRADIENT:
- m_style.gradient = static_cast<QSvgGradientStyle*>(prop);
- break;
- case QSvgStyleProperty::TRANSFORM:
- m_style.transform = static_cast<QSvgTransformStyle*>(prop);
- break;
- case QSvgStyleProperty::ANIMATE_COLOR:
- m_style.animateColor = static_cast<QSvgAnimateColor*>(prop);
- break;
- case QSvgStyleProperty::ANIMATE_TRANSFORM:
- m_style.animateTransforms.append(
- static_cast<QSvgAnimateTransform*>(prop));
- break;
- case QSvgStyleProperty::OPACITY:
- m_style.opacity = static_cast<QSvgOpacityStyle*>(prop);
- break;
- case QSvgStyleProperty::COMP_OP:
- m_style.compop = static_cast<QSvgCompOpStyle*>(prop);
- break;
- default:
- qDebug("QSvgNode: Trying to append unknown property!");
- break;
- }
- }
- if (!id.isEmpty()) {
- m_styles.insert(id, prop);
+ QSvgTinyDocument *doc;
+ switch (prop->type()) {
+ case QSvgStyleProperty::QUALITY:
+ m_style.quality = static_cast<QSvgQualityStyle*>(prop);
+ break;
+ case QSvgStyleProperty::FILL:
+ m_style.fill = static_cast<QSvgFillStyle*>(prop);
+ break;
+ case QSvgStyleProperty::VIEWPORT_FILL:
+ m_style.viewportFill = static_cast<QSvgViewportFillStyle*>(prop);
+ break;
+ case QSvgStyleProperty::FONT:
+ m_style.font = static_cast<QSvgFontStyle*>(prop);
+ break;
+ case QSvgStyleProperty::STROKE:
+ m_style.stroke = static_cast<QSvgStrokeStyle*>(prop);
+ break;
+ case QSvgStyleProperty::SOLID_COLOR:
+ m_style.solidColor = static_cast<QSvgSolidColorStyle*>(prop);
+ doc = document();
+ if (doc && !id.isEmpty())
+ doc->addNamedStyle(id, m_style.solidColor);
+ break;
+ case QSvgStyleProperty::GRADIENT:
+ m_style.gradient = static_cast<QSvgGradientStyle*>(prop);
+ doc = document();
+ if (doc && !id.isEmpty())
+ doc->addNamedStyle(id, m_style.gradient);
+ break;
+ case QSvgStyleProperty::TRANSFORM:
+ m_style.transform = static_cast<QSvgTransformStyle*>(prop);
+ break;
+ case QSvgStyleProperty::ANIMATE_COLOR:
+ m_style.animateColor = static_cast<QSvgAnimateColor*>(prop);
+ break;
+ case QSvgStyleProperty::ANIMATE_TRANSFORM:
+ m_style.animateTransforms.append(
+ static_cast<QSvgAnimateTransform*>(prop));
+ break;
+ case QSvgStyleProperty::OPACITY:
+ m_style.opacity = static_cast<QSvgOpacityStyle*>(prop);
+ break;
+ case QSvgStyleProperty::COMP_OP:
+ m_style.compop = static_cast<QSvgCompOpStyle*>(prop);
+ break;
+ default:
+ qDebug("QSvgNode: Trying to append unknown property!");
+ break;
}
}
@@ -185,20 +186,13 @@ QSvgStyleProperty * QSvgNode::styleProperty(QSvgStyleProperty::Type type) const
return 0;
}
-QSvgStyleProperty * QSvgNode::styleProperty(const QString &id) const
+QSvgFillStyleProperty * QSvgNode::styleProperty(const QString &id) const
{
QString rid = id;
if (rid.startsWith(QLatin1Char('#')))
rid.remove(0, 1);
- const QSvgNode *node = this;
- while (node) {
- QSvgStyleProperty *style = node->m_styles[rid];
- if (style)
- return style;
- node = node->parent();
- }
-
- return 0;
+ QSvgTinyDocument *doc = document();
+ return doc ? doc->namedStyle(rid) : 0;
}
QRectF QSvgNode::bounds() const
diff --git a/src/svg/qsvgnode_p.h b/src/svg/qsvgnode_p.h
index 2831e65..1f5606a 100644
--- a/src/svg/qsvgnode_p.h
+++ b/src/svg/qsvgnode_p.h
@@ -117,12 +117,11 @@ public:
QSvgNode *parent() const;
- void appendStyleProperty(QSvgStyleProperty *prop, const QString &id,
- bool justLink=false);
+ void appendStyleProperty(QSvgStyleProperty *prop, const QString &id);
void applyStyle(QPainter *p, QSvgExtraStates &states);
void revertStyle(QPainter *p, QSvgExtraStates &states);
QSvgStyleProperty *styleProperty(QSvgStyleProperty::Type type) const;
- QSvgStyleProperty *styleProperty(const QString &id) const;
+ QSvgFillStyleProperty *styleProperty(const QString &id) const;
QSvgTinyDocument *document() const;
@@ -162,7 +161,6 @@ protected:
qreal strokeWidth() const;
private:
QSvgNode *m_parent;
- QHash<QString, QSvgRefCounter<QSvgStyleProperty> > m_styles;
QStringList m_requiredFeatures;
QStringList m_requiredExtensions;
diff --git a/src/svg/qsvgstructure.cpp b/src/svg/qsvgstructure.cpp
index 47a544f..82c800d 100644
--- a/src/svg/qsvgstructure.cpp
+++ b/src/svg/qsvgstructure.cpp
@@ -45,6 +45,7 @@
#include "qsvgnode_p.h"
#include "qsvgstyle_p.h"
+#include "qsvgtinydocument_p.h"
#include "qpainter.h"
#include "qlocale.h"
@@ -90,35 +91,20 @@ QSvgStructureNode::QSvgStructureNode(QSvgNode *parent)
QSvgNode * QSvgStructureNode::scopeNode(const QString &id) const
{
- const QSvgStructureNode *group = this;
- while (group && group->type() != QSvgNode::DOC) {
- group = static_cast<QSvgStructureNode*>(group->parent());
- }
- if (group)
- return group->m_scope[id];
- return 0;
+ QSvgTinyDocument *doc = document();
+ return doc ? doc->namedNode(id) : 0;
}
-void QSvgStructureNode::addChild(QSvgNode *child, const QString &id, bool def)
+void QSvgStructureNode::addChild(QSvgNode *child, const QString &id)
{
- if (!def)
- m_renderers.append(child);
-
- if (child->type() == QSvgNode::DEFS) {
- QSvgDefs *defs =
- static_cast<QSvgDefs*>(child);
- m_linkedScopes.append(defs);
- }
+ m_renderers.append(child);
if (id.isEmpty())
return; //we can't add it to scope without id
- QSvgStructureNode *group = this;
- while (group && group->type() != QSvgNode::DOC) {
- group = static_cast<QSvgStructureNode*>(group->parent());
- }
- if (group)
- group->m_scope.insert(id, child);
+ QSvgTinyDocument *doc = document();
+ if (doc)
+ doc->addNamedNode(id, child);
}
QSvgDefs::QSvgDefs(QSvgNode *parent)
@@ -136,26 +122,6 @@ QSvgNode::Type QSvgDefs::type() const
return DEFS;
}
-QSvgStyleProperty * QSvgStructureNode::scopeStyle(const QString &id) const
-{
- const QSvgStructureNode *group = this;
- while (group) {
- QSvgStyleProperty *prop = group->styleProperty(id);
- if (prop)
- return prop;
- QList<QSvgStructureNode*>::const_iterator itr = group->m_linkedScopes.constBegin();
- while (itr != group->m_linkedScopes.constEnd()) {
- prop = (*itr)->styleProperty(id);
- if (prop)
- return prop;
- ++itr;
- }
- group = static_cast<QSvgStructureNode*>(group->parent());
- }
- return 0;
-}
-
-
/*
Below is a lookup function based on the gperf output using the following set:
diff --git a/src/svg/qsvgstructure_p.h b/src/svg/qsvgstructure_p.h
index d873f54..444f885 100644
--- a/src/svg/qsvgstructure_p.h
+++ b/src/svg/qsvgstructure_p.h
@@ -73,8 +73,7 @@ public:
QSvgStructureNode(QSvgNode *parent);
~QSvgStructureNode();
QSvgNode *scopeNode(const QString &id) const;
- QSvgStyleProperty *scopeStyle(const QString &id) const;
- void addChild(QSvgNode *child, const QString &id, bool def = false);
+ void addChild(QSvgNode *child, const QString &id);
virtual QRectF bounds() const;
QSvgNode *previousSiblingNode(QSvgNode *n) const;
QList<QSvgNode*> renderers() const { return m_renderers; }
diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp
index 564bf24..f834016 100644
--- a/src/svg/qsvgstyle.cpp
+++ b/src/svg/qsvgstyle.cpp
@@ -934,7 +934,7 @@ void QSvgGradientStyle::setStopLink(const QString &link, QSvgTinyDocument *doc)
void QSvgGradientStyle::resolveStops()
{
if (!m_link.isEmpty() && m_doc) {
- QSvgStyleProperty *prop = m_doc->scopeStyle(m_link);
+ QSvgStyleProperty *prop = m_doc->styleProperty(m_link);
if (prop) {
if (prop->type() == QSvgStyleProperty::GRADIENT) {
QSvgGradientStyle *st =
@@ -943,6 +943,8 @@ void QSvgGradientStyle::resolveStops()
m_gradient->setStops(st->qgradient()->stops());
m_gradientStopsSet = st->gradientStopsSet();
}
+ } else {
+ qWarning("Could not resolve property : %s", qPrintable(m_link));
}
m_link = QString();
}
diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp
index 5d58f79..e2cefeb 100644
--- a/src/svg/qsvgtinydocument.cpp
+++ b/src/svg/qsvgtinydocument.cpp
@@ -350,6 +350,26 @@ QSvgFont * QSvgTinyDocument::svgFont(const QString &family) const
return m_fonts[family];
}
+void QSvgTinyDocument::addNamedNode(const QString &id, QSvgNode *node)
+{
+ m_namedNodes.insert(id, node);
+}
+
+QSvgNode *QSvgTinyDocument::namedNode(const QString &id) const
+{
+ return m_namedNodes.value(id);
+}
+
+void QSvgTinyDocument::addNamedStyle(const QString &id, QSvgFillStyleProperty *style)
+{
+ m_namedStyles.insert(id, style);
+}
+
+QSvgFillStyleProperty *QSvgTinyDocument::namedStyle(const QString &id) const
+{
+ return m_namedStyles.value(id);
+}
+
void QSvgTinyDocument::restartAnimation()
{
m_time.restart();
diff --git a/src/svg/qsvgtinydocument_p.h b/src/svg/qsvgtinydocument_p.h
index bde28c7..38a1f92 100644
--- a/src/svg/qsvgtinydocument_p.h
+++ b/src/svg/qsvgtinydocument_p.h
@@ -108,6 +108,10 @@ public:
void addSvgFont(QSvgFont *);
QSvgFont *svgFont(const QString &family) const;
+ void addNamedNode(const QString &id, QSvgNode *node);
+ QSvgNode *namedNode(const QString &id) const;
+ void addNamedStyle(const QString &id, QSvgFillStyleProperty *style);
+ QSvgFillStyleProperty *namedStyle(const QString &id) const;
void restartAnimation();
int currentElapsed() const;
@@ -127,6 +131,8 @@ private:
mutable QRectF m_viewBox;
QHash<QString, QSvgRefCounter<QSvgFont> > m_fonts;
+ QHash<QString, QSvgNode *> m_namedNodes;
+ QHash<QString, QSvgRefCounter<QSvgFillStyleProperty> > m_namedStyles;
QTime m_time;
bool m_animated;