summaryrefslogtreecommitdiffstats
path: root/src/svg
diff options
context:
space:
mode:
authorFrans Englich <frans.englich@nokia.com>2009-09-23 13:16:51 (GMT)
committerFrans Englich <frans.englich@nokia.com>2009-09-23 13:16:51 (GMT)
commit902ceabbca3cd3f3a06180aba64b0f81b3f1dba4 (patch)
tree64efeee683cd31c2a0f7511fecc3c124c91249fe /src/svg
parent9161598b9cb374889ca6c69831c035c1eaa4d56e (diff)
parentbbcef4e4b596324aeda80e0aa7d313c586454740 (diff)
downloadQt-902ceabbca3cd3f3a06180aba64b0f81b3f1dba4.zip
Qt-902ceabbca3cd3f3a06180aba64b0f81b3f1dba4.tar.gz
Qt-902ceabbca3cd3f3a06180aba64b0f81b3f1dba4.tar.bz2
Merge commit 'qt/4.6' into mmfphonon
Conflicts: demos/embedded/fluidlauncher/config_s60/config.xml demos/embedded/fluidlauncher/fluidlauncher.pro src/corelib/io/io.pri src/gui/kernel/qapplication_s60.cpp src/gui/kernel/qwidget_s60.cpp src/s60installs/qt_libs.pro
Diffstat (limited to 'src/svg')
-rw-r--r--src/svg/qgraphicssvgitem.cpp60
-rw-r--r--src/svg/qgraphicssvgitem.h44
-rw-r--r--src/svg/qsvgfont.cpp30
-rw-r--r--src/svg/qsvgfont_p.h30
-rw-r--r--src/svg/qsvggenerator.cpp33
-rw-r--r--src/svg/qsvggenerator.h30
-rw-r--r--src/svg/qsvggraphics.cpp112
-rw-r--r--src/svg/qsvggraphics_p.h37
-rw-r--r--src/svg/qsvghandler.cpp1419
-rw-r--r--src/svg/qsvghandler_p.h33
-rw-r--r--src/svg/qsvgnode.cpp146
-rw-r--r--src/svg/qsvgnode_p.h36
-rw-r--r--src/svg/qsvgrenderer.cpp30
-rw-r--r--src/svg/qsvgrenderer.h30
-rw-r--r--src/svg/qsvgstructure.cpp80
-rw-r--r--src/svg/qsvgstructure_p.h33
-rw-r--r--src/svg/qsvgstyle.cpp410
-rw-r--r--src/svg/qsvgstyle_p.h260
-rw-r--r--src/svg/qsvgtinydocument.cpp58
-rw-r--r--src/svg/qsvgtinydocument_p.h36
-rw-r--r--src/svg/qsvgwidget.cpp30
-rw-r--r--src/svg/qsvgwidget.h30
22 files changed, 1793 insertions, 1214 deletions
diff --git a/src/svg/qgraphicssvgitem.cpp b/src/svg/qgraphicssvgitem.cpp
index a287baa..bcdd821 100644
--- a/src/svg/qgraphicssvgitem.cpp
+++ b/src/svg/qgraphicssvgitem.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -52,7 +52,7 @@
QT_BEGIN_NAMESPACE
-class QGraphicsSvgItemPrivate : public QObjectPrivate
+class QGraphicsSvgItemPrivate : public QGraphicsItemPrivate
{
public:
Q_DECLARE_PUBLIC(QGraphicsSvgItem)
@@ -62,9 +62,10 @@ public:
{
}
- void init()
+ void init(QGraphicsItem *parent)
{
Q_Q(QGraphicsSvgItem);
+ q->setParentItem(parent);
renderer = new QSvgRenderer(q);
QObject::connect(renderer, SIGNAL(repaintNeeded()),
q, SLOT(_q_repaintItem()));
@@ -137,10 +138,10 @@ public:
Constructs a new SVG item with the given \a parent.
*/
QGraphicsSvgItem::QGraphicsSvgItem(QGraphicsItem *parent)
- : QObject(*new QGraphicsSvgItemPrivate(), 0), QGraphicsItem(parent)
+ : QGraphicsObject(*new QGraphicsSvgItemPrivate(), 0, 0)
{
Q_D(QGraphicsSvgItem);
- d->init();
+ d->init(parent);
}
/*!
@@ -148,10 +149,10 @@ QGraphicsSvgItem::QGraphicsSvgItem(QGraphicsItem *parent)
SVG file with the specified \a fileName.
*/
QGraphicsSvgItem::QGraphicsSvgItem(const QString &fileName, QGraphicsItem *parent)
- : QObject(*new QGraphicsSvgItemPrivate(), 0), QGraphicsItem(parent)
+ : QGraphicsObject(*new QGraphicsSvgItemPrivate(), 0, 0)
{
Q_D(QGraphicsSvgItem);
- d->init();
+ d->init(parent);
d->renderer->load(fileName);
d->updateDefaultSize();
}
@@ -264,6 +265,12 @@ int QGraphicsSvgItem::type() const
return Type;
}
+/*!
+ \property QGraphicsSvgItem::maximumCacheSize
+
+ This property holds the maximum size of the device coordinate cache
+ for this item.
+ */
/*!
Sets the maximum device coordinate cache size of the item to \a size.
@@ -304,8 +311,13 @@ QSize QGraphicsSvgItem::maximumCacheSize() const
}
/*!
- Sets the XML ID of the element that this item should render to \a
- id.
+ \property QGraphicsSvgItem::elementId
+
+ This property holds the element's XML ID.
+ */
+
+/*!
+ Sets the XML ID of the element to \a id.
*/
void QGraphicsSvgItem::setElementId(const QString &id)
{
@@ -317,7 +329,7 @@ void QGraphicsSvgItem::setElementId(const QString &id)
/*!
Returns the XML ID the element that is currently
- being renderer. Returns an empty string if the whole
+ being rendered. Returns an empty string if the whole
file is being rendered.
*/
QString QGraphicsSvgItem::elementId() const
diff --git a/src/svg/qgraphicssvgitem.h b/src/svg/qgraphicssvgitem.h
index 738ea06..e304c0c 100644
--- a/src/svg/qgraphicssvgitem.h
+++ b/src/svg/qgraphicssvgitem.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,28 +21,26 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGRAPHICSSVGITEM_H
#define QGRAPHICSSVGITEM_H
-#include <QtCore/qobject.h>
#include <QtGui/qgraphicsitem.h>
#ifndef QT_NO_GRAPHICSSVGITEM
@@ -55,9 +54,12 @@ QT_MODULE(Svg)
class QSvgRenderer;
class QGraphicsSvgItemPrivate;
-class Q_SVG_EXPORT QGraphicsSvgItem : public QObject, public QGraphicsItem
+class Q_SVG_EXPORT QGraphicsSvgItem : public QGraphicsObject
{
Q_OBJECT
+ Q_INTERFACES(QGraphicsItem)
+ Q_PROPERTY(QString elementId READ elementId WRITE setElementId)
+ Q_PROPERTY(QSize maximumCacheSize READ maximumCacheSize WRITE setMaximumCacheSize)
public:
QGraphicsSvgItem(QGraphicsItem *parentItem=0);
@@ -86,13 +88,7 @@ public:
private:
Q_DISABLE_COPY(QGraphicsSvgItem)
-
- // Q_DECLARE_PRIVATE_WITH_BASE(QGraphicsSvgItem, QObject)
- inline QGraphicsSvgItemPrivate *d_func()
- { return reinterpret_cast<QGraphicsSvgItemPrivate *>(QObject::d_ptr.data()); }
- inline const QGraphicsSvgItemPrivate *d_func() const
- { return reinterpret_cast<const QGraphicsSvgItemPrivate *>(QObject::d_ptr.data()); }
- friend class QGraphicsSvgItemPrivate;
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsSvgItem)
Q_PRIVATE_SLOT(d_func(), void _q_repaintItem())
};
diff --git a/src/svg/qsvgfont.cpp b/src/svg/qsvgfont.cpp
index bb23991..de8d5d5 100644
--- a/src/svg/qsvgfont.cpp
+++ b/src/svg/qsvgfont.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/svg/qsvgfont_p.h b/src/svg/qsvgfont_p.h
index f52e84a..d6b23c2 100644
--- a/src/svg/qsvgfont_p.h
+++ b/src/svg/qsvgfont_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/svg/qsvggenerator.cpp b/src/svg/qsvggenerator.cpp
index 2936c3f..da3123f 100644
--- a/src/svg/qsvggenerator.cpp
+++ b/src/svg/qsvggenerator.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -920,7 +920,8 @@ void QSvgPaintEngine::drawImage(const QRectF &r, const QImage &image,
stream() << "x=\""<<r.x()<<"\" "
"y=\""<<r.y()<<"\" "
"width=\""<<r.width()<<"\" "
- "height=\""<<r.height()<<"\" ";
+ "height=\""<<r.height()<<"\" "
+ "preserveAspectRatio=\"none\" ";
QByteArray data;
QBuffer buffer(&data);
diff --git a/src/svg/qsvggenerator.h b/src/svg/qsvggenerator.h
index 5bbaa81..df0adac 100644
--- a/src/svg/qsvggenerator.h
+++ b/src/svg/qsvggenerator.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/svg/qsvggraphics.cpp b/src/svg/qsvggraphics.cpp
index 40cf06b..6552b69 100644
--- a/src/svg/qsvggraphics.cpp
+++ b/src/svg/qsvggraphics.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -56,20 +56,21 @@
QT_BEGIN_NAMESPACE
-#define QT_SVG_DRAW_SHAPE(command) \
- applyStyle(p, states); \
- qreal oldOpacity = p->opacity(); \
- QBrush oldBrush = p->brush(); \
- QPen oldPen = p->pen(); \
- p->setPen(Qt::NoPen); \
- p->setOpacity(oldOpacity * states.fillOpacity); \
- command; \
- p->setOpacity(oldOpacity); \
- p->setPen(oldPen); \
- p->setBrush(Qt::NoBrush); \
- command; \
- p->setBrush(oldBrush); \
- revertStyle(p, states);
+#define QT_SVG_DRAW_SHAPE(command) \
+ qreal oldOpacity = p->opacity(); \
+ QBrush oldBrush = p->brush(); \
+ QPen oldPen = p->pen(); \
+ p->setPen(Qt::NoPen); \
+ p->setOpacity(oldOpacity * states.fillOpacity); \
+ command; \
+ p->setPen(oldPen); \
+ if (oldPen.widthF() != 0) { \
+ p->setOpacity(oldOpacity * states.strokeOpacity); \
+ p->setBrush(Qt::NoBrush); \
+ command; \
+ p->setBrush(oldBrush); \
+ } \
+ p->setOpacity(oldOpacity);
void QSvgAnimation::draw(QPainter *, QSvgExtraStates &)
@@ -105,7 +106,9 @@ QRectF QSvgCircle::bounds() const
void QSvgCircle::draw(QPainter *p, QSvgExtraStates &states)
{
+ applyStyle(p, states);
QT_SVG_DRAW_SHAPE(p->drawEllipse(m_bounds));
+ revertStyle(p, states);
}
QSvgArc::QSvgArc(QSvgNode *parent, const QPainterPath &path)
@@ -117,7 +120,12 @@ QSvgArc::QSvgArc(QSvgNode *parent, const QPainterPath &path)
void QSvgArc::draw(QPainter *p, QSvgExtraStates &states)
{
applyStyle(p, states);
- p->drawPath(cubic);
+ if (p->pen().widthF() != 0) {
+ qreal oldOpacity = p->opacity();
+ p->setOpacity(oldOpacity * states.strokeOpacity);
+ p->drawPath(cubic);
+ p->setOpacity(oldOpacity);
+ }
revertStyle(p, states);
}
@@ -140,7 +148,9 @@ QRectF QSvgEllipse::bounds() const
void QSvgEllipse::draw(QPainter *p, QSvgExtraStates &states)
{
+ applyStyle(p, states);
QT_SVG_DRAW_SHAPE(p->drawEllipse(m_bounds));
+ revertStyle(p, states);
}
QSvgImage::QSvgImage(QSvgNode *parent, const QImage &image,
@@ -171,34 +181,45 @@ QSvgLine::QSvgLine(QSvgNode *parent, const QLineF &line)
void QSvgLine::draw(QPainter *p, QSvgExtraStates &states)
{
applyStyle(p, states);
- p->drawLine(m_bounds);
+ if (p->pen().widthF() != 0) {
+ qreal oldOpacity = p->opacity();
+ p->setOpacity(oldOpacity * states.strokeOpacity);
+ p->drawLine(m_bounds);
+ p->setOpacity(oldOpacity);
+ }
revertStyle(p, states);
}
QSvgPath::QSvgPath(QSvgNode *parent, const QPainterPath &qpath)
: QSvgNode(parent), m_path(qpath)
{
- //m_cachedBounds = m_path.controlPointRect();
- m_cachedBounds = m_path.boundingRect();
}
void QSvgPath::draw(QPainter *p, QSvgExtraStates &states)
{
+ applyStyle(p, states);
+ m_path.setFillRule(states.fillRule);
QT_SVG_DRAW_SHAPE(p->drawPath(m_path));
+ revertStyle(p, states);
}
QRectF QSvgPath::bounds() const
{
qreal sw = strokeWidth();
- if (qFuzzyIsNull(sw))
+ if (qFuzzyIsNull(sw)) {
+ if (m_cachedBounds.isNull())
+ //m_cachedBounds = m_path.controlPointRect();
+ m_cachedBounds = m_path.boundingRect();
+
return m_cachedBounds;
+ }
else {
return boundsOnStroke(m_path, sw);
}
}
QSvgPolygon::QSvgPolygon(QSvgNode *parent, const QPolygonF &poly)
- : QSvgNode(parent), m_poly(poly), m_fillRule(Qt::WindingFill)
+ : QSvgNode(parent), m_poly(poly)
{
}
@@ -216,7 +237,9 @@ QRectF QSvgPolygon::bounds() const
void QSvgPolygon::draw(QPainter *p, QSvgExtraStates &states)
{
- QT_SVG_DRAW_SHAPE(p->drawPolygon(m_poly, m_fillRule));
+ applyStyle(p, states);
+ QT_SVG_DRAW_SHAPE(p->drawPolygon(m_poly, states.fillRule));
+ revertStyle(p, states);
}
@@ -229,13 +252,19 @@ QSvgPolyline::QSvgPolyline(QSvgNode *parent, const QPolygonF &poly)
void QSvgPolyline::draw(QPainter *p, QSvgExtraStates &states)
{
applyStyle(p, states);
+ qreal oldOpacity = p->opacity();
if (p->brush().style() != Qt::NoBrush) {
QPen save = p->pen();
p->setPen(QPen(Qt::NoPen));
- p->drawPolygon(m_poly);
+ p->setOpacity(oldOpacity * states.fillOpacity);
+ p->drawPolygon(m_poly, states.fillRule);
p->setPen(save);
}
- p->drawPolyline(m_poly);
+ if (p->pen().widthF() != 0) {
+ p->setOpacity(oldOpacity * states.strokeOpacity);
+ p->drawPolyline(m_poly);
+ }
+ p->setOpacity(oldOpacity);
revertStyle(p, states);
}
@@ -259,11 +288,13 @@ QRectF QSvgRect::bounds() const
void QSvgRect::draw(QPainter *p, QSvgExtraStates &states)
{
+ applyStyle(p, states);
if (m_rx || m_ry) {
QT_SVG_DRAW_SHAPE(p->drawRoundedRect(m_rect, m_rx, m_ry, Qt::RelativeSize));
} else {
QT_SVG_DRAW_SHAPE(p->drawRect(m_rect));
}
+ revertStyle(p, states);
}
QSvgTspan * const QSvgText::LINEBREAK = 0;
@@ -296,6 +327,8 @@ void QSvgText::setTextArea(const QSizeF &size)
void QSvgText::draw(QPainter *p, QSvgExtraStates &states)
{
applyStyle(p, states);
+ qreal oldOpacity = p->opacity();
+ p->setOpacity(oldOpacity * states.fillOpacity);
// Force the font to have a size of 100 pixels to avoid truncation problems
// when the font is very small.
@@ -401,7 +434,7 @@ void QSvgText::draw(QPainter *p, QSvgExtraStates &states)
text.append(QLatin1Char('\n'));
text.append(paragraphs[i]);
}
- states.svgFont->draw(p, m_coord, text, p->font().pointSizeF() * scale, states.textAnchor);
+ states.svgFont->draw(p, m_coord * scale, text, p->font().pointSizeF() * scale, states.textAnchor);
} else {
for (int i = 0; i < paragraphs.size(); ++i) {
QTextLayout tl(paragraphs[i]);
@@ -456,6 +489,7 @@ void QSvgText::draw(QPainter *p, QSvgExtraStates &states)
}
p->setWorldTransform(oldTransform, false);
+ p->setOpacity(oldOpacity);
revertStyle(p, states);
}
diff --git a/src/svg/qsvggraphics_p.h b/src/svg/qsvggraphics_p.h
index 20310e3..b9c825a 100644
--- a/src/svg/qsvggraphics_p.h
+++ b/src/svg/qsvggraphics_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -145,7 +145,7 @@ public:
}
private:
QPainterPath m_path;
- QRectF m_cachedBounds;
+ mutable QRectF m_cachedBounds;
};
class QSvgPolygon : public QSvgNode
@@ -155,13 +155,8 @@ public:
virtual void draw(QPainter *p, QSvgExtraStates &states);
virtual Type type() const;
virtual QRectF bounds() const;
- void setFillRule(Qt::FillRule f)
- {
- m_fillRule = f;
- }
private:
QPolygonF m_poly;
- Qt::FillRule m_fillRule;
};
class QSvgPolyline : public QSvgNode
diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp
index a79e4a0..a6e4855 100644
--- a/src/svg/qsvghandler.cpp
+++ b/src/svg/qsvghandler.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -64,6 +64,7 @@
#include "qdebug.h"
#include "qmath.h"
#include "qnumeric.h"
+#include "qvarlengtharray.h"
#include "private/qmath_p.h"
#include "float.h"
@@ -75,66 +76,330 @@ static const char *qt_inherit_text = "inherit";
double qstrtod(const char *s00, char const **se, bool *ok);
+// ======== duplicated from qcolor_p
+
+static inline int qsvg_h2i(char hex)
+{
+ if (hex >= '0' && hex <= '9')
+ return hex - '0';
+ if (hex >= 'a' && hex <= 'f')
+ return hex - 'a' + 10;
+ if (hex >= 'A' && hex <= 'F')
+ return hex - 'A' + 10;
+ return -1;
+}
+
+static inline int qsvg_hex2int(const char *s)
+{
+ return (qsvg_h2i(s[0]) << 4) | qsvg_h2i(s[1]);
+}
+
+static inline int qsvg_hex2int(char s)
+{
+ int h = qsvg_h2i(s);
+ return (h << 4) | h;
+}
+
+bool qsvg_get_hex_rgb(const char *name, QRgb *rgb)
+{
+ if(name[0] != '#')
+ return false;
+ name++;
+ int len = qstrlen(name);
+ int r, g, b;
+ if (len == 12) {
+ r = qsvg_hex2int(name);
+ g = qsvg_hex2int(name + 4);
+ b = qsvg_hex2int(name + 8);
+ } else if (len == 9) {
+ r = qsvg_hex2int(name);
+ g = qsvg_hex2int(name + 3);
+ b = qsvg_hex2int(name + 6);
+ } else if (len == 6) {
+ r = qsvg_hex2int(name);
+ g = qsvg_hex2int(name + 2);
+ b = qsvg_hex2int(name + 4);
+ } else if (len == 3) {
+ r = qsvg_hex2int(name[0]);
+ g = qsvg_hex2int(name[1]);
+ b = qsvg_hex2int(name[2]);
+ } else {
+ r = g = b = -1;
+ }
+ if ((uint)r > 255 || (uint)g > 255 || (uint)b > 255) {
+ *rgb = 0;
+ return false;
+ }
+ *rgb = qRgb(r, g ,b);
+ return true;
+}
+
+bool qsvg_get_hex_rgb(const QChar *str, int len, QRgb *rgb)
+{
+ if (len > 13)
+ return false;
+ char tmp[16];
+ for(int i = 0; i < len; ++i)
+ tmp[i] = str[i].toLatin1();
+ tmp[len] = 0;
+ return qsvg_get_hex_rgb(tmp, rgb);
+}
+
+// ======== end of qcolor_p duplicate
+
static bool parsePathDataFast(const QStringRef &data, QPainterPath &path);
+static inline QString someId(const QXmlStreamAttributes &attributes)
+{
+ QString id = attributes.value(QLatin1String("id")).toString();
+ if (id.isEmpty())
+ id = attributes.value(QLatin1String("xml:id")).toString();
+ return id;
+}
+
struct QSvgAttributes
{
QSvgAttributes(const QXmlStreamAttributes &xmlAttributes, QSvgHandler *handler);
- QStringRef value(const QLatin1String &name) const;
- QStringRef value(const QString &namespaceUri, const QLatin1String &name) const;
+ QString id;
+
+ QStringRef color;
+ QStringRef colorOpacity;
+ QStringRef fill;
+ QStringRef fillRule;
+ QStringRef fillOpacity;
+ QStringRef stroke;
+ QStringRef strokeDashArray;
+ QStringRef strokeDashOffset;
+ QStringRef strokeLineCap;
+ QStringRef strokeLineJoin;
+ QStringRef strokeMiterLimit;
+ QStringRef strokeOpacity;
+ QStringRef strokeWidth;
+ QStringRef vectorEffect;
+ QStringRef fontFamily;
+ QStringRef fontSize;
+ QStringRef fontStyle;
+ QStringRef fontWeight;
+ QStringRef fontVariant;
+ QStringRef textAnchor;
+ QStringRef transform;
+ QStringRef visibility;
+ QStringRef opacity;
+ QStringRef compOp;
+ QStringRef display;
+ QStringRef offset;
+ QStringRef stopColor;
+ QStringRef stopOpacity;
- QXmlStreamAttributes m_xmlAttributes;
QVector<QSvgCssAttribute> m_cssAttributes;
};
QSvgAttributes::QSvgAttributes(const QXmlStreamAttributes &xmlAttributes, QSvgHandler *handler)
- : m_xmlAttributes(xmlAttributes)
{
QStringRef style = xmlAttributes.value(QLatin1String("style"));
- if (!style.isEmpty())
+ 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);
+ QStringRef name = attribute.name;
+ QStringRef 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;
-QStringRef QSvgAttributes::value(const QLatin1String &name) const
-{
- QStringRef v = m_xmlAttributes.value(name);
- if (v.isEmpty()) {
- for (int i = 0; i < m_cssAttributes.count(); ++i) {
- if (m_cssAttributes.at(i).name == name) {
- v = m_cssAttributes.at(i).value;
+ 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 'o':
+ if (name == QLatin1String("opacity"))
+ opacity = value;
+ else if (name == QLatin1String("offset"))
+ offset = value;
+ break;
+
+ case 's':
+ if (name.length() > 5 && QStringRef(name.string(), name.position() + 1, 5) == QLatin1String("troke")) {
+ QStringRef strokeRef(name.string(), name.position() + 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;
+ }
}
}
- return v;
-}
-QStringRef QSvgAttributes::value(const QString &namespaceUri, const QLatin1String &name) const
-{
- QStringRef v = m_xmlAttributes.value(namespaceUri, name);
- if (v.isEmpty()) {
- for (int i = 0; i < m_cssAttributes.count(); ++i) {
- if (m_cssAttributes.at(i).name == name) {
- v = m_cssAttributes.at(i).value;
- break;
+ for (int i = 0; i < xmlAttributes.count(); ++i) {
+ const QXmlStreamAttribute &attribute = xmlAttributes.at(i);
+ QStringRef name = attribute.qualifiedName();
+ if (name.isEmpty())
+ continue;
+ QStringRef value = attribute.value();
+
+ 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("id"))
+ id = value.toString();
+ break;
+
+ case 'o':
+ if (name == QLatin1String("opacity"))
+ opacity = value;
+ if (name == QLatin1String("offset"))
+ offset = value;
+ break;
+
+ case 's':
+ if (name.length() > 5 && QStringRef(name.string(), name.position() + 1, 5) == QLatin1String("troke")) {
+ QStringRef strokeRef(name.string(), name.position() + 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;
+
+ case 'x':
+ if (name == QLatin1String("xml:id") && id.isEmpty())
+ id = value.toString();
+ break;
+
+ default:
+ break;
}
}
- return v;
-}
-static inline QString someId(const QXmlStreamAttributes &attributes)
-{
- QString id = attributes.value(QLatin1String("id")).toString();
- if (id.isEmpty())
- id = attributes.value(QLatin1String("xml:id")).toString();
- return id;
}
-static inline QString someId(const QSvgAttributes &attributes)
-{ return someId(attributes.m_xmlAttributes); }
-
-
static const char * QSvgStyleSelector_nodeString[] = {
"svg",
@@ -287,6 +552,13 @@ public:
}
};
+// '0' is 0x30 and '9' is 0x39
+static inline bool isDigit(ushort ch)
+{
+ static quint16 magic = 0x3ff;
+ return ((ch >> 4) == 3) && (magic >> (ch & 15));
+}
+
static qreal toDouble(const QChar *&str)
{
const int maxLen = 255;//technically doubles can go til 308+ but whatever
@@ -299,7 +571,7 @@ static qreal toDouble(const QChar *&str)
} else if (*str == QLatin1Char('+')) {
++str;
}
- while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
+ while (isDigit(str->unicode()) && pos < maxLen) {
temp[pos++] = str->toLatin1();
++str;
}
@@ -307,7 +579,7 @@ static qreal toDouble(const QChar *&str)
temp[pos++] = '.';
++str;
}
- while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
+ while (isDigit(str->unicode()) && pos < maxLen) {
temp[pos++] = str->toLatin1();
++str;
}
@@ -320,7 +592,7 @@ static qreal toDouble(const QChar *&str)
temp[pos++] = str->toLatin1();
++str;
}
- while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
+ while (isDigit(str->unicode()) && pos < maxLen) {
temp[pos++] = str->toLatin1();
++str;
}
@@ -398,27 +670,48 @@ static QVector<qreal> parseNumbersList(const QChar *&str)
return points;
points.reserve(32);
- while (*str == QLatin1Char(' '))
+ while (str->isSpace())
++str;
- while ((*str >= QLatin1Char('0') && *str <= QLatin1Char('9')) ||
+ while (isDigit(str->unicode()) ||
*str == QLatin1Char('-') || *str == QLatin1Char('+') ||
*str == QLatin1Char('.')) {
points.append(toDouble(str));
- while (*str == QLatin1Char(' '))
+ while (str->isSpace())
++str;
if (*str == QLatin1Char(','))
++str;
//eat the rest of space
- while (*str == QLatin1Char(' '))
+ while (str->isSpace())
++str;
}
return points;
}
+static inline void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points)
+{
+ while (str->isSpace())
+ ++str;
+ while (isDigit(str->unicode()) ||
+ *str == QLatin1Char('-') || *str == QLatin1Char('+') ||
+ *str == QLatin1Char('.')) {
+
+ points.append(toDouble(str));
+
+ while (str->isSpace())
+ ++str;
+ if (*str == QLatin1Char(','))
+ ++str;
+
+ //eat the rest of space
+ while (str->isSpace())
+ ++str;
+ }
+}
+
static QVector<qreal> parsePercentageList(const QChar *&str)
{
QVector<qreal> points;
@@ -433,17 +726,17 @@ static QVector<qreal> parsePercentageList(const QChar *&str)
points.append(toDouble(str));
- while (*str == QLatin1Char(' '))
+ while (str->isSpace())
++str;
if (*str == QLatin1Char('%'))
++str;
- while (*str == QLatin1Char(' '))
+ while (str->isSpace())
++str;
if (*str == QLatin1Char(','))
++str;
//eat the rest of space
- while (*str == QLatin1Char(' '))
+ while (str->isSpace())
++str;
}
@@ -469,43 +762,98 @@ static QString idFromUrl(const QString &url)
return id;
}
+static inline QStringRef trimRef(const QStringRef &str)
+{
+ if (str.isEmpty())
+ return QStringRef();
+ const QChar *s = str.string()->constData() + str.position();
+ int end = str.length() - 1;
+ if (!s[0].isSpace() && !s[end].isSpace())
+ return str;
+
+ int start = 0;
+ while (start<=end && s[start].isSpace()) // skip white space from start
+ start++;
+ if (start <= end) { // only white space
+ while (s[end].isSpace()) // skip white space from end
+ end--;
+ }
+ int l = end - start + 1;
+ if (l <= 0)
+ return QStringRef();
+ return QStringRef(str.string(), str.position() + start, l);
+}
+
/**
* returns true when successfuly set the color. false signifies
* that the color should be inherited
*/
-static bool resolveColor(const QString &colorStr, QColor &color, QSvgHandler *handler)
-{
- QString colorStrTr = colorStr.trimmed();
- if (colorStr.startsWith(QLatin1String("rgb("))) {
- const QChar *s = colorStr.constData() + 4;
- QVector<qreal> compo = parseNumbersList(s);
- //1 means that it failed after reaching non-parsable
- //character which is going to be "%"
- if (compo.size() == 1) {
- const QChar *s = colorStr.constData() + 4;
- compo = parsePercentageList(s);
- compo[0] *= (qreal)2.55;
- compo[1] *= (qreal)2.55;
- compo[2] *= (qreal)2.55;
- }
-
- color = QColor(int(compo[0]),
- int(compo[1]),
- int(compo[2]));
- return true;
- } else if (colorStr == QLatin1String("inherited") ||
- colorStr == QT_INHERIT) {
+static bool resolveColor(const QStringRef &colorStr, QColor &color, QSvgHandler *handler)
+{
+ QStringRef colorStrTr = trimRef(colorStr);
+ if (colorStrTr.isEmpty())
return false;
- } else if (colorStr == QLatin1String("currentColor")) {
- color = handler->currentColor();
- return true;
+
+ switch(colorStrTr.at(0).unicode()) {
+
+ case '#':
+ {
+ // #rrggbb is very very common, so let's tackle it here
+ // rather than falling back to QColor
+ QRgb rgb;
+ bool ok = qsvg_get_hex_rgb(colorStrTr.unicode(), colorStrTr.length(), &rgb);
+ if (ok)
+ color.setRgb(rgb);
+ return ok;
+ }
+ break;
+
+ case 'r':
+ {
+ // starts with "rgb(", ends with ")" and consists of at least 7 characters "rgb(,,)"
+ if (colorStrTr.length() >= 7 && colorStrTr.at(colorStrTr.length() - 1) == QLatin1Char(')')
+ && QStringRef(colorStrTr.string(), colorStrTr.position(), 4) == QLatin1String("rgb(")) {
+ const QChar *s = colorStrTr.constData() + 4;
+ QVector<qreal> compo = parseNumbersList(s);
+ //1 means that it failed after reaching non-parsable
+ //character which is going to be "%"
+ if (compo.size() == 1) {
+ s = colorStrTr.constData() + 4;
+ compo = parsePercentageList(s);
+ for (int i = 0; i < compo.size(); ++i)
+ compo[i] *= (qreal)2.55;
+ }
+
+ if (compo.size() == 3) {
+ color = QColor(int(compo[0]),
+ int(compo[1]),
+ int(compo[2]));
+ return true;
+ }
+ return false;
+ }
+ }
+ break;
+
+ case 'c':
+ if (colorStrTr == QLatin1String("currentColor")) {
+ color = handler->currentColor();
+ return true;
+ }
+ break;
+ case 'i':
+ if (colorStrTr == QT_INHERIT)
+ return false;
+ break;
+ default:
+ break;
}
- color = QColor(colorStrTr);
+ color = QColor(colorStrTr.toString());
return color.isValid();
}
-static bool constructColor(const QString &colorStr, const QString &opacity,
+static bool constructColor(const QStringRef &colorStr, const QStringRef &opacity,
QColor &color, QSvgHandler *handler)
{
if (!resolveColor(colorStr, color, handler))
@@ -618,84 +966,77 @@ static void parseColor(QSvgNode *,
const QSvgAttributes &attributes,
QSvgHandler *handler)
{
- QString colorStr = attributes.value(QLatin1String("color")).toString();
- QString opacity = attributes.value(QLatin1String("color-opacity")).toString();
QColor color;
- if (constructColor(colorStr, opacity, color, handler)) {
+ if (constructColor(attributes.color, attributes.colorOpacity, color, handler)) {
+ handler->popColor();
handler->pushColor(color);
}
}
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,
const QSvgAttributes &attributes,
QSvgHandler *handler)
{
- QString value = attributes.value(QLatin1String("fill")).toString();
- QString fillRule = attributes.value(QLatin1String("fill-rule")).toString();
- QString opacity = attributes.value(QLatin1String("fill-opacity")).toString();
- QString myId = someId(attributes);
-
- if (!value.isEmpty() || !fillRule.isEmpty() || !opacity.isEmpty()) {
- QSvgFillStyle *prop = new QSvgFillStyle(0);
+ if (!attributes.fill.isEmpty() || !attributes.fillRule.isEmpty() || !attributes.fillOpacity.isEmpty()) {
+ QSvgFillStyle *prop = new QSvgFillStyle;
//fill-rule attribute handling
- if (!fillRule.isEmpty() && fillRule != QT_INHERIT) {
- if (fillRule == QLatin1String("evenodd"))
+ if (!attributes.fillRule.isEmpty() && attributes.fillRule != QT_INHERIT) {
+ if (attributes.fillRule == QLatin1String("evenodd"))
prop->setFillRule(Qt::OddEvenFill);
- else if (fillRule == QLatin1String("nonzero"))
+ else if (attributes.fillRule == QLatin1String("nonzero"))
prop->setFillRule(Qt::WindingFill);
}
//fill-opacity atttribute handling
- if (!opacity.isEmpty() && opacity != QT_INHERIT) {
- prop->setFillOpacity(qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity))));
+ if (!attributes.fillOpacity.isEmpty() && attributes.fillOpacity != QT_INHERIT) {
+ prop->setFillOpacity(qMin(qreal(1.0), qMax(qreal(0.0), toDouble(attributes.fillOpacity))));
}
//fill attribute handling
- if ((!value.isEmpty()) && (value != QT_INHERIT) ) {
- if (value.startsWith(QLatin1String("url"))) {
- value = value.remove(0, 3);
+ if ((!attributes.fill.isEmpty()) && (attributes.fill != QT_INHERIT) ) {
+ if (attributes.fill.length() > 3 &&
+ QStringRef(attributes.fill.string(), attributes.fill.position(), 3) == QLatin1String("url")) {
+ QStringRef urlRef(attributes.fill.string(), attributes.fill.position() + 3, attributes.fill.length() - 3);
+ QString value = urlRef.toString();
QSvgStyleProperty *style = styleFromUrl(node, value);
if (style) {
- prop->setFillStyle(style);
+ if (style->type() == QSvgStyleProperty::SOLID_COLOR || style->type() == QSvgStyleProperty::GRADIENT)
+ prop->setFillStyle(reinterpret_cast<QSvgFillStyleProperty *>(style));
} else {
QString id = idFromUrl(value);
prop->setGradientId(id);
prop->setGradientResolved(false);
}
- } else if (value != QLatin1String("none")) {
+ } else if (attributes.fill != QLatin1String("none")) {
QColor color;
- if (resolveColor(value, color, handler))
+ if (resolveColor(attributes.fill, color, handler))
prop->setBrush(QBrush(color));
} else {
prop->setBrush(QBrush(Qt::NoBrush));
}
}
- node->appendStyleProperty(prop, myId);
+ node->appendStyleProperty(prop, attributes.id);
}
}
-static QMatrix parseTransformationMatrix(const QString &value)
+static QMatrix parseTransformationMatrix(const QStringRef &value)
{
+ if (value.isEmpty())
+ return QMatrix();
+
QMatrix matrix;
const QChar *str = value.constData();
+ const QChar *end = str + value.length();
- while (*str != QLatin1Char(0)) {
+ while (str < end) {
if (str->isSpace() || *str == QLatin1Char(',')) {
++str;
continue;
@@ -760,12 +1101,13 @@ static QMatrix parseTransformationMatrix(const QString &value)
}
- while (str->isSpace())
+ while (str < end && str->isSpace())
++str;
if (*str != QLatin1Char('('))
goto error;
++str;
- QVector<qreal> points = parseNumbersList(str);
+ QVarLengthArray<qreal, 8> points;
+ parseNumbersArray(str, points);
if (*str != QLatin1Char(')'))
goto error;
++str;
@@ -821,168 +1163,100 @@ static void parsePen(QSvgNode *node,
const QSvgAttributes &attributes,
QSvgHandler *handler)
{
- QString value = attributes.value(QLatin1String("stroke")).toString();
- QString dashArray = attributes.value(QLatin1String("stroke-dasharray")).toString();
- QString dashOffset = attributes.value(QLatin1String("stroke-dashoffset")).toString();
- QString linecap = attributes.value(QLatin1String("stroke-linecap")).toString();
- QString linejoin = attributes.value(QLatin1String("stroke-linejoin")).toString();
- QString miterlimit = attributes.value(QLatin1String("stroke-miterlimit")).toString();
- QString opacity = attributes.value(QLatin1String("stroke-opacity")).toString();
- QString width = attributes.value(QLatin1String("stroke-width")).toString();
- QString vectorEffect = attributes.value(QLatin1String("vector-effect")).toString();
- QString myId = someId(attributes);
-
//qDebug()<<"Node "<<node->type()<<", attrs are "<<value<<width;
- if (!value.isEmpty() || !width.isEmpty() || !dashArray.isEmpty() || !linecap.isEmpty() ||
- !linejoin.isEmpty() || !miterlimit.isEmpty() || !opacity.isEmpty() ||
- !dashOffset.isEmpty() || !vectorEffect.isEmpty()) {
+ if (!attributes.stroke.isEmpty() || !attributes.strokeDashArray.isEmpty() || !attributes.strokeDashOffset.isEmpty() || !attributes.strokeLineCap.isEmpty()
+ || !attributes.strokeLineJoin.isEmpty() || !attributes.strokeMiterLimit.isEmpty() || !attributes.strokeOpacity.isEmpty() || !attributes.strokeWidth.isEmpty()
+ || !attributes.vectorEffect.isEmpty()) {
- QSvgStrokeStyle *inherited =
- static_cast<QSvgStrokeStyle*>(node->parent()->styleProperty(
- QSvgStyleProperty::STROKE));
-
- QPen pen(handler->defaultPen());
- bool stroke = false;
- if (inherited) {
- pen = inherited->qpen();
- stroke = inherited->strokePresent();
- }
-
- // stroke-opacity attribute handling
- qreal strokeAlpha;
- if (!opacity.isEmpty() && opacity != QT_INHERIT) {
- strokeAlpha = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity)));
- } else {
- strokeAlpha = pen.color().alphaF();
- }
+ QSvgStrokeStyle *prop = new QSvgStrokeStyle;
//stroke attribute handling
- if (!value.isEmpty() && value != QT_INHERIT) {
- if (value.startsWith(QLatin1String("url"))) {
- value = value.remove(0, 3);
- QSvgStyleProperty *style = styleFromUrl(node, value);
- if (style) {
- if (style->type() == QSvgStyleProperty::GRADIENT) {
- QBrush b(*((QSvgGradientStyle*)style)->qgradient());
- pen.setBrush(b);
- } else if (style->type() == QSvgStyleProperty::SOLID_COLOR) {
- pen.setColor(
- ((QSvgSolidColorStyle*)style)->qcolor());
+ if ((!attributes.stroke.isEmpty()) && (attributes.stroke != QT_INHERIT) ) {
+ if (attributes.stroke.length() > 3 &&
+ QStringRef(attributes.stroke.string(), attributes.stroke.position(), 3) == QLatin1String("url")) {
+ QStringRef urlRef(attributes.stroke.string(), attributes.stroke.position() + 3, attributes.stroke.length() - 3);
+ QString value = urlRef.toString();
+ QSvgStyleProperty *style = styleFromUrl(node, value);
+ if (style) {
+ if (style->type() == QSvgStyleProperty::SOLID_COLOR || style->type() == QSvgStyleProperty::GRADIENT)
+ prop->setStyle(reinterpret_cast<QSvgFillStyleProperty *>(style));
+ } else {
+ QString id = idFromUrl(value);
+ prop->setGradientId(id);
+ prop->setGradientResolved(false);
}
- stroke = true;
- } else {
- qWarning() << "QSvgHandler::parsePen could not resolve property" << idFromUrl(value);
- }
- } else if (value == QLatin1String("none")) {
- QColor color; //### fixme: dafalut value for color.
- color.setAlphaF(strokeAlpha);
- pen.setColor(color);
- stroke = false; // This is required because, parent may have a valid stroke but the child may have stroke = "none"
- } else {
+ } else if (attributes.stroke != QLatin1String("none")) {
QColor color;
- if (resolveColor(value, color, handler)) {
- color.setAlphaF(strokeAlpha);
- pen.setColor(color);
- }
- stroke = true;
+ if (resolveColor(attributes.stroke, color, handler))
+ prop->setStroke(QBrush(color));
+ } else {
+ prop->setStroke(QBrush(Qt::NoBrush));
}
- } else {
- QColor color = pen.color();
- color.setAlphaF(strokeAlpha);
- pen.setColor(color);
}
//stroke-width handling
- if (!width.isEmpty() && width != QT_INHERIT) {
- qreal widthF;
+ if (!attributes.strokeWidth.isEmpty() && attributes.strokeWidth != QT_INHERIT) {
QSvgHandler::LengthType lt;
- widthF = parseLength(width, lt, handler);
- pen.setWidthF(widthF);
+ prop->setWidth(parseLength(attributes.strokeWidth.toString(), lt, handler));
}
- //stroke-linejoin attribute handling
- if (!linejoin.isEmpty()) {
- if (linejoin == QLatin1String("miter"))
- pen.setJoinStyle(Qt::SvgMiterJoin);
- else if (linejoin == QLatin1String("round"))
- pen.setJoinStyle(Qt::RoundJoin);
- else if (linejoin == QLatin1String("bevel"))
- pen.setJoinStyle(Qt::BevelJoin);
+ //stroke-dasharray
+ if (!attributes.strokeDashArray.isEmpty() && attributes.strokeDashArray != QT_INHERIT) {
+ if (attributes.strokeDashArray == QLatin1String("none")) {
+ prop->setDashArrayNone();
+ } else {
+ QString dashArray = attributes.strokeDashArray.toString();
+ const QChar *s = dashArray.constData();
+ QVector<qreal> dashes = parseNumbersList(s);
+ // if the dash count is odd the dashes should be duplicated
+ if ((dashes.size() & 1) != 0)
+ dashes << QVector<qreal>(dashes);
+ prop->setDashArray(dashes);
+ }
}
- //stroke-linecap attribute handling
- if (!linecap.isEmpty()) {
- if (linecap == QLatin1String("butt"))
- pen.setCapStyle(Qt::FlatCap);
- else if (linecap == QLatin1String("round"))
- pen.setCapStyle(Qt::RoundCap);
- else if (linecap == QLatin1String("square"))
- pen.setCapStyle(Qt::SquareCap);
+ //stroke-linejoin attribute handling
+ if (!attributes.strokeLineJoin.isEmpty()) {
+ if (attributes.strokeLineJoin == QLatin1String("miter"))
+ prop->setLineJoin(Qt::SvgMiterJoin);
+ else if (attributes.strokeLineJoin == QLatin1String("round"))
+ prop->setLineJoin(Qt::RoundJoin);
+ else if (attributes.strokeLineJoin == QLatin1String("bevel"))
+ prop->setLineJoin(Qt::BevelJoin);
}
- //strok-dasharray attribute handling
- qreal penw = pen.widthF();
- if (!dashArray.isEmpty() && dashArray != QT_INHERIT) {
- const QChar *s = dashArray.constData();
- QVector<qreal> dashes = parseNumbersList(s);
- qreal *d = dashes.data();
- if (penw != 0)
- for (int i = 0; i < dashes.size(); ++i) {
- *d /= penw;
- ++d;
- }
- // if the dash count is odd the dashes should be duplicated
- if (dashes.size() % 2 != 0)
- dashes << QVector<qreal>(dashes);
- pen.setDashPattern(dashes);
- } else if (inherited) {
- QVector<qreal> dashes(inherited->qpen().dashPattern());
- qreal *d = dashes.data();
- if (!penw)
- penw = 1.0;
- qreal inheritpenw = inherited->qpen().widthF();
- if (!inheritpenw)
- inheritpenw = 1.0;
- for ( int i = 0; i < dashes.size(); ++i) {
- *d *= (inheritpenw/ penw);
- ++d;
- }
- pen.setDashPattern(dashes);
+ //stroke-linecap attribute handling
+ if (!attributes.strokeLineCap.isEmpty()) {
+ if (attributes.strokeLineCap == QLatin1String("butt"))
+ prop->setLineCap(Qt::FlatCap);
+ else if (attributes.strokeLineCap == QLatin1String("round"))
+ prop->setLineCap(Qt::RoundCap);
+ else if (attributes.strokeLineCap == QLatin1String("square"))
+ prop->setLineCap(Qt::SquareCap);
}
-
//stroke-dashoffset attribute handling
- if (!dashOffset.isEmpty() && dashOffset != QT_INHERIT) {
- qreal doffset = toDouble(dashOffset);
- if (penw != 0)
- doffset /= penw;
- pen.setDashOffset(doffset);
- } else if (inherited) {
- qreal doffset = pen.dashOffset();
- if (!penw)
- penw = 1.0;
- qreal inheritpenw = inherited->qpen().widthF();
- if (!inheritpenw)
- inheritpenw = 1.0;
- doffset *= (inheritpenw/ penw);
- pen.setDashOffset(doffset);
- }
+ if (!attributes.strokeDashOffset.isEmpty() && attributes.strokeDashOffset != QT_INHERIT)
+ prop->setDashOffset(toDouble(attributes.strokeDashOffset));
//vector-effect attribute handling
- if (!vectorEffect.isEmpty()) {
- if (vectorEffect == QLatin1String("non-scaling-stroke"))
- pen.setCosmetic(true);
- else if (vectorEffect == QLatin1String("none"))
- pen.setCosmetic(false);
+ if (!attributes.vectorEffect.isEmpty()) {
+ if (attributes.vectorEffect == QLatin1String("non-scaling-stroke"))
+ prop->setVectorEffect(true);
+ else if (attributes.vectorEffect == QLatin1String("none"))
+ prop->setVectorEffect(false);
}
- if (!miterlimit.isEmpty() && miterlimit != QT_INHERIT)
- pen.setMiterLimit(toDouble(miterlimit));
+ //stroke-miterlimit
+ if (!attributes.strokeMiterLimit.isEmpty() && attributes.strokeMiterLimit != QT_INHERIT)
+ prop->setMiterLimit(toDouble(attributes.strokeMiterLimit));
+
+ //stroke-opacity atttribute handling
+ if (!attributes.strokeOpacity.isEmpty() && attributes.strokeOpacity != QT_INHERIT)
+ prop->setOpacity(qMin(qreal(1.0), qMax(qreal(0.0), toDouble(attributes.strokeOpacity))));
- QSvgStrokeStyle *prop = new QSvgStrokeStyle(pen);
- prop->setStroke(stroke);
- node->appendStyleProperty(prop, myId);
+ node->appendStyleProperty(prop, attributes.id);
}
}
@@ -990,95 +1264,85 @@ static void parseFont(QSvgNode *node,
const QSvgAttributes &attributes,
QSvgHandler *handler)
{
- QString family = attributes.value(QLatin1String("font-family")).toString();
- QString size = attributes.value(QLatin1String("font-size")).toString();
- QString style = attributes.value(QLatin1String("font-style")).toString();
- QString weight = attributes.value(QLatin1String("font-weight")).toString();
- QString variant = attributes.value(QLatin1String("font-variant")).toString();
- QString anchor = attributes.value(QLatin1String("text-anchor")).toString();
-
- if (family.isEmpty() && size.isEmpty() && style.isEmpty() && weight.isEmpty() && variant.isEmpty() && anchor.isEmpty())
+ if (attributes.fontFamily.isEmpty() && attributes.fontSize.isEmpty() && attributes.fontStyle.isEmpty() &&
+ attributes.fontWeight.isEmpty() && attributes.fontVariant.isEmpty() && attributes.textAnchor.isEmpty())
return;
- QString id = someId(attributes);
QSvgTinyDocument *doc = node->document();
QSvgFontStyle *fontStyle = 0;
- if (!family.isEmpty()) {
- QSvgFont *svgFont = doc->svgFont(family);
+ if (!attributes.fontFamily.isEmpty()) {
+ QSvgFont *svgFont = doc->svgFont(attributes.fontFamily.toString());
if (svgFont)
fontStyle = new QSvgFontStyle(svgFont, doc);
}
if (!fontStyle)
fontStyle = new QSvgFontStyle;
- if (!family.isEmpty() && family != QT_INHERIT)
- fontStyle->setFamily(family.trimmed());
+ if (!attributes.fontFamily.isEmpty() && attributes.fontFamily != QT_INHERIT)
+ fontStyle->setFamily(attributes.fontFamily.toString().trimmed());
- if (!size.isEmpty() && size != QT_INHERIT) {
+ if (!attributes.fontSize.isEmpty() && attributes.fontSize != QT_INHERIT) {
QSvgHandler::LengthType dummy; // should always be pixel size
- fontStyle->setSize(parseLength(size, dummy, handler));
+ fontStyle->setSize(parseLength(attributes.fontSize.toString(), dummy, handler));
}
- if (!style.isEmpty() && style != QT_INHERIT) {
- if (style == QLatin1String("normal")) {
+ if (!attributes.fontStyle.isEmpty() && attributes.fontStyle != QT_INHERIT) {
+ if (attributes.fontStyle == QLatin1String("normal")) {
fontStyle->setStyle(QFont::StyleNormal);
- } else if (style == QLatin1String("italic")) {
+ } else if (attributes.fontStyle == QLatin1String("italic")) {
fontStyle->setStyle(QFont::StyleItalic);
- } else if (style == QLatin1String("oblique")) {
+ } else if (attributes.fontStyle == QLatin1String("oblique")) {
fontStyle->setStyle(QFont::StyleOblique);
}
}
- if (!weight.isEmpty() && weight != QT_INHERIT) {
+ if (!attributes.fontWeight.isEmpty() && attributes.fontWeight != QT_INHERIT) {
bool ok = false;
- int weightNum = weight.toInt(&ok);
+ int weightNum = attributes.fontWeight.toString().toInt(&ok);
if (ok) {
fontStyle->setWeight(weightNum);
} else {
- if (weight == QLatin1String("normal")) {
+ if (attributes.fontWeight == QLatin1String("normal")) {
fontStyle->setWeight(400);
- } else if (weight == QLatin1String("bold")) {
+ } else if (attributes.fontWeight == QLatin1String("bold")) {
fontStyle->setWeight(700);
- } else if (weight == QLatin1String("bolder")) {
+ } else if (attributes.fontWeight == QLatin1String("bolder")) {
fontStyle->setWeight(QSvgFontStyle::BOLDER);
- } else if (weight == QLatin1String("lighter")) {
+ } else if (attributes.fontWeight == QLatin1String("lighter")) {
fontStyle->setWeight(QSvgFontStyle::LIGHTER);
}
}
}
- if (!variant.isEmpty() && variant != QT_INHERIT) {
- if (variant == QLatin1String("normal"))
+ if (!attributes.fontVariant.isEmpty() && attributes.fontVariant != QT_INHERIT) {
+ if (attributes.fontVariant == QLatin1String("normal"))
fontStyle->setVariant(QFont::MixedCase);
- else if (variant == QLatin1String("small-caps"))
+ else if (attributes.fontVariant == QLatin1String("small-caps"))
fontStyle->setVariant(QFont::SmallCaps);
}
- if (!anchor.isEmpty() && anchor != QT_INHERIT) {
- if (anchor == QLatin1String("start"))
+ if (!attributes.textAnchor.isEmpty() && attributes.textAnchor != QT_INHERIT) {
+ if (attributes.textAnchor == QLatin1String("start"))
fontStyle->setTextAnchor(Qt::AlignLeft);
- if (anchor == QLatin1String("middle"))
+ if (attributes.textAnchor == QLatin1String("middle"))
fontStyle->setTextAnchor(Qt::AlignHCenter);
- else if (anchor == QLatin1String("end"))
+ else if (attributes.textAnchor == QLatin1String("end"))
fontStyle->setTextAnchor(Qt::AlignRight);
}
- node->appendStyleProperty(fontStyle, id);
+ node->appendStyleProperty(fontStyle, attributes.id);
}
static void parseTransform(QSvgNode *node,
const QSvgAttributes &attributes,
QSvgHandler *)
{
- QString value = attributes.value(QLatin1String("transform")).toString();
- QString myId = someId(attributes);
- value = value.trimmed();
- if (value.isEmpty())
+ if (attributes.transform.isEmpty())
return;
- QMatrix matrix = parseTransformationMatrix(value);
+ QMatrix matrix = parseTransformationMatrix(trimRef(attributes.transform));
if (!matrix.isIdentity()) {
- node->appendStyleProperty(new QSvgTransformStyle(QTransform(matrix)), myId);
+ node->appendStyleProperty(new QSvgTransformStyle(QTransform(matrix)), attributes.id);
}
}
@@ -1087,12 +1351,11 @@ static void parseVisibility(QSvgNode *node,
const QSvgAttributes &attributes,
QSvgHandler *)
{
- QString value = attributes.value(QLatin1String("visibility")).toString();
QSvgNode *parent = node->parent();
- if (parent && (value.isEmpty() || value == QT_INHERIT))
+ if (parent && (attributes.visibility.isEmpty() || attributes.visibility == QT_INHERIT))
node->setVisible(parent->isVisible());
- else if (value == QLatin1String("hidden") || value == QLatin1String("collapse")) {
+ else if (attributes.visibility == QLatin1String("hidden") || attributes.visibility == QLatin1String("collapse")) {
node->setVisible(false);
} else
node->setVisible(true);
@@ -1247,29 +1510,34 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
const QChar *end = str + dataStr.size();
while (str != end) {
- while (*str == QLatin1Char(' '))
+ while (str->isSpace())
++str;
QChar pathElem = *str;
++str;
QChar endc = *end;
- *const_cast<QChar *>(end) = 0; // parseNumbersList requires 0-termination that QStringRef cannot guarantee
- QVector<qreal> arg = parseNumbersList(str);
+ *const_cast<QChar *>(end) = 0; // parseNumbersArray requires 0-termination that QStringRef cannot guarantee
+ QVarLengthArray<qreal, 8> arg;
+ parseNumbersArray(str, arg);
*const_cast<QChar *>(end) = endc;
if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))
arg.append(0);//dummy
- while (!arg.isEmpty()) {
+ const qreal *num = arg.constData();
+ int count = arg.count();
+ while (count > 0) {
qreal offsetX = x; // correction offsets
qreal offsetY = y; // for relative commands
switch (pathElem.unicode()) {
case 'm': {
- if (arg.count() < 2) {
- arg.pop_front();
+ if (count < 2) {
+ num++;
+ count--;
break;
}
- x = x0 = arg[0] + offsetX;
- y = y0 = arg[1] + offsetY;
+ x = x0 = num[0] + offsetX;
+ y = y0 = num[1] + offsetY;
+ num += 2;
+ count -= 2;
path.moveTo(x0, y0);
- arg.pop_front(); arg.pop_front();
// As per 1.2 spec 8.3.2 The "moveto" commands
// If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
@@ -1278,15 +1546,16 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
}
break;
case 'M': {
- if (arg.count() < 2) {
- arg.pop_front();
+ if (count < 2) {
+ num++;
+ count--;
break;
}
- x = x0 = arg[0];
- y = y0 = arg[1];
-
+ x = x0 = num[0];
+ y = y0 = num[1];
+ num += 2;
+ count -= 2;
path.moveTo(x0, y0);
- arg.pop_front(); arg.pop_front();
// As per 1.2 spec 8.3.2 The "moveto" commands
// If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
@@ -1298,96 +1567,104 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
case 'Z': {
x = x0;
y = y0;
+ count--; // skip dummy
+ num++;
path.closeSubpath();
- arg.pop_front();//pop dummy
}
break;
case 'l': {
- if (arg.count() < 2) {
- arg.pop_front();
+ if (count < 2) {
+ num++;
+ count--;
break;
}
- x = arg.front() + offsetX;
- arg.pop_front();
- y = arg.front() + offsetY;
- arg.pop_front();
+ x = x0 = num[0] + offsetX;
+ y = y0 = num[1] + offsetY;
+ num += 2;
+ count -= 2;
path.lineTo(x, y);
}
break;
case 'L': {
- if (arg.count() < 2) {
- arg.pop_front();
+ if (count < 2) {
+ num++;
+ count--;
break;
}
- x = arg.front(); arg.pop_front();
- y = arg.front(); arg.pop_front();
+ x = x0 = num[0];
+ y = y0 = num[1];
+ num += 2;
+ count -= 2;
path.lineTo(x, y);
}
break;
case 'h': {
- x = arg.front() + offsetX; arg.pop_front();
+ x = num[0] + offsetX;
+ num++;
+ count--;
path.lineTo(x, y);
}
break;
case 'H': {
- x = arg[0];
+ x = num[0];
+ num++;
+ count--;
path.lineTo(x, y);
- arg.pop_front();
}
break;
case 'v': {
- y = arg[0] + offsetY;
+ y = num[0] + offsetY;
+ num++;
+ count--;
path.lineTo(x, y);
- arg.pop_front();
}
break;
case 'V': {
- y = arg[0];
+ y = num[0];
+ num++;
+ count--;
path.lineTo(x, y);
- arg.pop_front();
}
break;
case 'c': {
- if (arg.count() < 6) {
- while (arg.count())
- arg.pop_front();
+ if (count < 6) {
+ num += count;
+ count = 0;
break;
}
- QPointF c1(arg[0]+offsetX, arg[1]+offsetY);
- QPointF c2(arg[2]+offsetX, arg[3]+offsetY);
- QPointF e(arg[4]+offsetX, arg[5]+offsetY);
+ QPointF c1(num[0] + offsetX, num[1] + offsetY);
+ QPointF c2(num[2] + offsetX, num[3] + offsetY);
+ QPointF e(num[4] + offsetX, num[5] + offsetY);
+ num += 6;
+ count -= 6;
path.cubicTo(c1, c2, e);
ctrlPt = c2;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
break;
}
case 'C': {
- if (arg.count() < 6) {
- while (arg.count())
- arg.pop_front();
+ if (count < 6) {
+ num += count;
+ count = 0;
break;
}
- QPointF c1(arg[0], arg[1]);
- QPointF c2(arg[2], arg[3]);
- QPointF e(arg[4], arg[5]);
+ QPointF c1(num[0], num[1]);
+ QPointF c2(num[2], num[3]);
+ QPointF e(num[4], num[5]);
+ num += 6;
+ count -= 6;
path.cubicTo(c1, c2, e);
ctrlPt = c2;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
break;
}
case 's': {
- if (arg.count() < 4) {
- while (arg.count())
- arg.pop_front();
+ if (count < 4) {
+ num += count;
+ count = 0;
break;
}
QPointF c1;
@@ -1396,20 +1673,20 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
else
c1 = QPointF(x, y);
- QPointF c2(arg[0]+offsetX, arg[1]+offsetY);
- QPointF e(arg[2]+offsetX, arg[3]+offsetY);
+ QPointF c2(num[0] + offsetX, num[1] + offsetY);
+ QPointF e(num[2] + offsetX, num[3] + offsetY);
+ num += 4;
+ count -= 4;
path.cubicTo(c1, c2, e);
ctrlPt = c2;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
break;
}
case 'S': {
- if (arg.count() < 4) {
- while (arg.count())
- arg.pop_front();
+ if (count < 4) {
+ num += count;
+ count = 0;
break;
}
QPointF c1;
@@ -1418,55 +1695,57 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
else
c1 = QPointF(x, y);
- QPointF c2(arg[0], arg[1]);
- QPointF e(arg[2], arg[3]);
+ QPointF c2(num[0], num[1]);
+ QPointF e(num[2], num[3]);
+ num += 4;
+ count -= 4;
path.cubicTo(c1, c2, e);
ctrlPt = c2;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
break;
}
case 'q': {
- if (arg.count() < 4) {
- while (arg.count())
- arg.pop_front();
+ if (count < 4) {
+ num += count;
+ count = 0;
break;
}
- QPointF c(arg[0]+offsetX, arg[1]+offsetY);
- QPointF e(arg[2]+offsetX, arg[3]+offsetY);
+ QPointF c(num[0] + offsetX, num[1] + offsetY);
+ QPointF e(num[2] + offsetX, num[3] + offsetY);
+ num += 4;
+ count -= 4;
path.quadTo(c, e);
ctrlPt = c;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
break;
}
case 'Q': {
- if (arg.count() < 4) {
- while (arg.count())
- arg.pop_front();
+ if (count < 4) {
+ num += count;
+ count = 0;
break;
}
- QPointF c(arg[0], arg[1]);
- QPointF e(arg[2], arg[3]);
+ QPointF c(num[0], num[1]);
+ QPointF e(num[2], num[3]);
+ num += 4;
+ count -= 4;
path.quadTo(c, e);
ctrlPt = c;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
break;
}
case 't': {
- if (arg.count() < 2) {
- while (arg.count())
- arg.pop_front();
+ if (count < 2) {
+ num += count;
+ count = 0;
break;
}
- QPointF e(arg[0]+offsetX, arg[1]+offsetY);
+ QPointF e(num[0] + offsetX, num[1] + offsetY);
+ num += 2;
+ count -= 2;
QPointF c;
if (lastMode == 'q' || lastMode == 'Q' ||
lastMode == 't' || lastMode == 'T')
@@ -1477,16 +1756,17 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
ctrlPt = c;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
break;
}
case 'T': {
- if (arg.count() < 2) {
- while (arg.count())
- arg.pop_front();
+ if (count < 2) {
+ num += count;
+ count = 0;
break;
}
- QPointF e(arg[0], arg[1]);
+ QPointF e(num[0], num[1]);
+ num += 2;
+ count -= 2;
QPointF c;
if (lastMode == 'q' || lastMode == 'Q' ||
lastMode == 't' || lastMode == 'T')
@@ -1497,22 +1777,22 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
ctrlPt = c;
x = e.x();
y = e.y();
- arg.pop_front(); arg.pop_front();
break;
}
case 'a': {
- if (arg.count() < 7) {
- while (arg.count())
- arg.pop_front();
+ if (count < 7) {
+ num += count;
+ count = 0;
break;
}
- qreal rx = arg[0];
- qreal ry = arg[1];
- qreal xAxisRotation = arg[2];
- qreal largeArcFlag = arg[3];
- qreal sweepFlag = arg[4];
- qreal ex = arg[5] + offsetX;
- qreal ey = arg[6] + offsetY;
+ qreal rx = (*num++);
+ qreal ry = (*num++);
+ qreal xAxisRotation = (*num++);
+ qreal largeArcFlag = (*num++);
+ qreal sweepFlag = (*num++);
+ qreal ex = (*num++) + offsetX;
+ qreal ey = (*num++) + offsetY;
+ count -= 7;
qreal curx = x;
qreal cury = y;
pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
@@ -1520,36 +1800,29 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
x = ex;
y = ey;
-
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
- arg.pop_front();
}
break;
case 'A': {
- if (arg.count() < 7) {
- while (arg.count())
- arg.pop_front();
+ if (count < 7) {
+ num += count;
+ count = 0;
break;
}
- qreal rx = arg[0];
- qreal ry = arg[1];
- qreal xAxisRotation = arg[2];
- qreal largeArcFlag = arg[3];
- qreal sweepFlag = arg[4];
- qreal ex = arg[5];
- qreal ey = arg[6];
+ qreal rx = (*num++);
+ qreal ry = (*num++);
+ qreal xAxisRotation = (*num++);
+ qreal largeArcFlag = (*num++);
+ qreal sweepFlag = (*num++);
+ qreal ex = (*num++);
+ qreal ey = (*num++);
+ count -= 7;
qreal curx = x;
qreal cury = y;
pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
int(sweepFlag), ex, ey, curx, cury);
+
x = ex;
y = ey;
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
- arg.pop_front(); arg.pop_front();
- arg.pop_front();
}
break;
default:
@@ -1710,27 +1983,49 @@ static inline QStringList stringToList(const QString &str)
static bool parseCoreNode(QSvgNode *node,
const QXmlStreamAttributes &attributes)
{
- QString featuresStr = attributes.value(QLatin1String("requiredFeatures")).toString();
- QString extensionsStr = attributes.value(QLatin1String("requiredExtensions")).toString();
- QString languagesStr = attributes.value(QLatin1String("systemLanguage")).toString();
- QString formatsStr = attributes.value(QLatin1String("requiredFormats")).toString();
- QString fontsStr = attributes.value(QLatin1String("requiredFonts")).toString();
- QString nodeIdStr = someId(attributes);
- QString xmlClassStr = attributes.value(QLatin1String("class")).toString();
-
-
- QStringList features = stringToList(featuresStr);
- QStringList extensions = stringToList(extensionsStr);
- QStringList languages = stringToList(languagesStr);
- QStringList formats = stringToList(formatsStr);
- QStringList fonts = stringToList(fontsStr);
+ QStringList features;
+ QStringList extensions;
+ QStringList languages;
+ QStringList formats;
+ QStringList fonts;
+ QString xmlClassStr;
+
+ for (int i = 0; i < attributes.count(); ++i) {
+ const QXmlStreamAttribute &attribute = attributes.at(i);
+ QStringRef name = attribute.qualifiedName();
+ if (name.isEmpty())
+ continue;
+ QStringRef value = attribute.value();
+ switch (name.at(0).unicode()) {
+ case 'c':
+ if (name == QLatin1String("class"))
+ xmlClassStr = value.toString();
+ break;
+ case 'r':
+ if (name == QLatin1String("requiredFeatures"))
+ features = stringToList(value.toString());
+ else if (name == QLatin1String("requiredExtensions"))
+ extensions = stringToList(value.toString());
+ else if (name == QLatin1String("requiredFormats"))
+ formats = stringToList(value.toString());
+ else if (name == QLatin1String("requiredFonts"))
+ fonts = stringToList(value.toString());
+ break;
+ case 's':
+ if (name == QLatin1String("systemLanguage"))
+ languages = stringToList(value.toString());
+ break;
+ default:
+ break;
+ }
+ }
node->setRequiredFeatures(features);
node->setRequiredExtensions(extensions);
node->setRequiredLanguages(languages);
node->setRequiredFormats(formats);
node->setRequiredFonts(fonts);
- node->setNodeId(nodeIdStr);
+ node->setNodeId(someId(attributes));
node->setXmlClass(xmlClassStr);
return true;
@@ -1740,14 +2035,17 @@ static void parseOpacity(QSvgNode *node,
const QSvgAttributes &attributes,
QSvgHandler *)
{
- const QString value = attributes.value(QLatin1String("opacity")).toString().trimmed();
+ if (attributes.opacity.isEmpty())
+ return;
+
+ const QString value = attributes.opacity.toString().trimmed();
bool ok = false;
qreal op = value.toDouble(&ok);
if (ok) {
QSvgOpacityStyle *opacity = new QSvgOpacityStyle(qBound(qreal(0.0), op, qreal(1.0)));
- node->appendStyleProperty(opacity, someId(attributes));
+ node->appendStyleProperty(opacity, attributes.id);
}
}
@@ -1813,12 +2111,13 @@ static void parseCompOp(QSvgNode *node,
const QSvgAttributes &attributes,
QSvgHandler *)
{
- QString value = attributes.value(QLatin1String("comp-op")).toString();
- value = value.trimmed();
+ if (attributes.compOp.isEmpty())
+ return;
+ QString value = attributes.compOp.toString().trimmed();
if (!value.isEmpty()) {
QSvgCompOpStyle *compop = new QSvgCompOpStyle(svgToQtCompositionMode(value));
- node->appendStyleProperty(compop, someId(attributes));
+ node->appendStyleProperty(compop, attributes.id);
}
}
@@ -1868,8 +2167,9 @@ static void parseOthers(QSvgNode *node,
const QSvgAttributes &attributes,
QSvgHandler *)
{
- QString displayStr = attributes.value(QLatin1String("display")).toString();
- displayStr = displayStr.trimmed();
+ if (attributes.display.isEmpty())
+ return;
+ QString displayStr = attributes.display.toString().trimmed();
if (!displayStr.isEmpty()) {
node->setDisplayMode(displayStringToEnum(displayStr));
@@ -1947,8 +2247,8 @@ static bool parseAnimateColorNode(QSvgNode *parent,
QSvgHandler *handler)
{
QString typeStr = attributes.value(QLatin1String("type")).toString();
- QString fromStr = attributes.value(QLatin1String("from")).toString();
- QString toStr = attributes.value(QLatin1String("to")).toString();
+ QStringRef fromStr = attributes.value(QLatin1String("from"));
+ QStringRef toStr = attributes.value(QLatin1String("to"));
QString valuesStr = attributes.value(QLatin1String("values")).toString();
QString beginStr = attributes.value(QLatin1String("begin")).toString();
QString durStr = attributes.value(QLatin1String("dur")).toString();
@@ -1959,8 +2259,8 @@ static bool parseAnimateColorNode(QSvgNode *parent,
QList<QColor> colors;
if (valuesStr.isEmpty()) {
QColor startColor, endColor;
- constructColor(fromStr, QString(), startColor, handler);
- constructColor(toStr, QString(), endColor, handler);
+ resolveColor(fromStr, startColor, handler);
+ resolveColor(toStr, endColor, handler);
colors.append(startColor);
colors.append(endColor);
} else {
@@ -1968,7 +2268,8 @@ static bool parseAnimateColorNode(QSvgNode *parent,
QStringList::const_iterator itr;
for (itr = str.constBegin(); itr != str.constEnd(); ++itr) {
QColor color;
- constructColor(*itr, QString(), color, handler);
+ QString str = *itr;
+ resolveColor(QStringRef(&str), color, handler);
colors.append(color);
}
}
@@ -2012,6 +2313,14 @@ static bool parseAimateMotionNode(QSvgNode *parent,
return true;
}
+static void parseNumberTriplet(QVector<qreal> &values, const QChar *&s)
+{
+ QVector<qreal> list = parseNumbersList(s);
+ values << list;
+ for (int i = 3 - list.size(); i > 0; --i)
+ values.append(0.0);
+}
+
static bool parseAnimateTransformNode(QSvgNode *parent,
const QXmlStreamAttributes &attributes,
QSvgHandler *handler)
@@ -2025,28 +2334,47 @@ static bool parseAnimateTransformNode(QSvgNode *parent,
QString fillStr = attributes.value(QLatin1String("fill")).toString();
QString fromStr = attributes.value(QLatin1String("from")).toString();
QString toStr = attributes.value(QLatin1String("to")).toString();
+ QString byStr = attributes.value(QLatin1String("by")).toString();
+ QString addtv = attributes.value(QLatin1String("additive")).toString();
+
+ QSvgAnimateTransform::Additive additive = QSvgAnimateTransform::Replace;
+ if (addtv == QLatin1String("sum"))
+ additive = QSvgAnimateTransform::Sum;
QVector<qreal> vals;
if (values.isEmpty()) {
- const QChar *s = fromStr.constData();
- QVector<qreal> lst = parseNumbersList(s);
- while (lst.count() < 3)
- lst.append(0.0);
- vals << lst;
-
- s = toStr.constData();
- lst = parseNumbersList(s);
- while (lst.count() < 3)
- lst.append(0.0);
- vals << lst;
+ const QChar *s;
+ if (fromStr.isEmpty()) {
+ if (!byStr.isEmpty()) {
+ // By-animation.
+ additive = QSvgAnimateTransform::Sum;
+ vals.append(0.0);
+ vals.append(0.0);
+ vals.append(0.0);
+ parseNumberTriplet(vals, s = byStr.constData());
+ } else {
+ // To-animation not defined.
+ return false;
+ }
+ } else {
+ if (!toStr.isEmpty()) {
+ // From-to-animation.
+ parseNumberTriplet(vals, s = fromStr.constData());
+ parseNumberTriplet(vals, s = toStr.constData());
+ } else if (!byStr.isEmpty()) {
+ // From-by-animation.
+ parseNumberTriplet(vals, s = fromStr.constData());
+ parseNumberTriplet(vals, s = byStr.constData());
+ for (int i = vals.size() - 3; i < vals.size(); ++i)
+ vals[i] += vals[i - 3];
+ } else {
+ return false;
+ }
+ }
} else {
const QChar *s = values.constData();
while (s && *s != QLatin1Char(0)) {
- QVector<qreal> tmpVals = parseNumbersList(s);
- while (tmpVals.count() < 3)
- tmpVals.append(0.0);
-
- vals << tmpVals;
+ parseNumberTriplet(vals, s);
if (*s == QLatin1Char(0))
break;
++s;
@@ -2088,7 +2416,7 @@ static bool parseAnimateTransformNode(QSvgNode *parent,
}
QSvgAnimateTransform *anim = new QSvgAnimateTransform(begin, end, 0);
- anim->setArgs(type, vals);
+ anim->setArgs(type, additive, vals);
anim->setFreeze(fillStr == QLatin1String("freeze"));
anim->setRepeatCount(
(repeatStr == QLatin1String("indefinite"))? -1 :
@@ -2390,9 +2718,17 @@ static void parseBaseGradient(QSvgNode *node,
QSvgHandler *handler)
{
QString link = attributes.value(QLatin1String("xlink:href")).toString();
- QString trans = attributes.value(QLatin1String("gradientTransform")).toString();
+ QStringRef trans = attributes.value(QLatin1String("gradientTransform"));
QString spread = attributes.value(QLatin1String("spreadMethod")).toString();
QString units = attributes.value(QLatin1String("gradientUnits")).toString();
+ QStringRef colorStr = attributes.value(QLatin1String("color"));
+ QStringRef colorOpacityStr = attributes.value(QLatin1String("color-opacity"));
+
+ QColor color;
+ if (constructColor(colorStr, colorOpacityStr, color, handler)) {
+ handler->popColor();
+ handler->pushColor(color);
+ }
QMatrix matrix;
QGradient *grad = gradProp->qgradient();
@@ -2676,11 +3012,11 @@ static QSvgStyleProperty *createSolidColorNode(QSvgNode *parent,
QSvgHandler *handler)
{
Q_UNUSED(parent); Q_UNUSED(attributes);
- QString solidColorStr = attributes.value(QLatin1String("solid-color")).toString();
- QString solidOpacityStr = attributes.value(QLatin1String("solid-opacity")).toString();
+ QStringRef solidColorStr = attributes.value(QLatin1String("solid-color"));
+ QStringRef solidOpacityStr = attributes.value(QLatin1String("solid-opacity"));
if (solidOpacityStr.isEmpty())
- solidOpacityStr = attributes.value(QLatin1String("opacity")).toString();
+ solidOpacityStr = attributes.value(QLatin1String("opacity"));
QColor color;
if (!constructColor(solidColorStr, solidOpacityStr, color, handler))
@@ -2710,8 +3046,7 @@ static bool parseStopNode(QSvgStyleProperty *parent,
cssNode.ptr = &anim;
QVector<QCss::Declaration> decls = handler->selector()->declarationsForNode(cssNode);
- QSvgAttributes attrs(attributes, handler);
-
+ QXmlStreamAttributes xmlAttr = attributes;
for (int i = 0; i < decls.count(); ++i) {
const QCss::Declaration &decl = decls.at(i);
@@ -2725,25 +3060,26 @@ static bool parseStopNode(QSvgStyleProperty *parent,
valueStr.prepend(QLatin1String("url("));
valueStr.append(QLatin1Char(')'));
}
- attrs.m_xmlAttributes.append(QString(), decl.d->property, valueStr);
+ xmlAttr.append(QString(), decl.d->property, valueStr);
}
+ QSvgAttributes attrs(xmlAttr, handler);
QSvgGradientStyle *style =
static_cast<QSvgGradientStyle*>(parent);
- QString offsetStr = attrs.value(QString(), QLatin1String("offset")).toString();
- QString colorStr = attrs.value(QString(), QLatin1String("stop-color")).toString();
- QString opacityStr = attrs.value(QString(), QLatin1String("stop-opacity")).toString();
+ QString offsetStr = attrs.offset.toString();
+ QStringRef colorStr = attrs.stopColor;
QColor color;
bool ok = true;
qreal offset = convertToNumber(offsetStr, handler, &ok);
if (!ok)
offset = 0.0;
+ QString black = QString::fromLatin1("#000000");
if (colorStr.isEmpty()) {
- colorStr = QLatin1String("#000000");
+ colorStr = QStringRef(&black);
}
- bool colorOK = constructColor(colorStr, opacityStr, color, handler);
+ constructColor(colorStr, attrs.stopOpacity, color, handler);
QGradient *grad = style->qgradient();
@@ -2767,8 +3103,6 @@ static bool parseStopNode(QSvgStyleProperty *parent,
grad->setColorAt(offset, color);
style->setGradientStopsSet(true);
- if (!colorOK)
- style->addResolve(offset);
return true;
}
@@ -2822,19 +3156,19 @@ static QSvgNode *createSvgNode(QSvgNode *parent,
node->setHeight(int(height), type == QSvgHandler::LT_PERCENT);
}
+ QStringList viewBoxValues;
if (!viewBoxStr.isEmpty()) {
- QStringList lst = viewBoxStr.split(QLatin1Char(' '), QString::SkipEmptyParts);
- if (lst.count() != 4)
- lst = viewBoxStr.split(QLatin1Char(','), QString::SkipEmptyParts);
- int count = lst.count();
- while (count < 4) {
- lst.append(QLatin1String(""));
- count++;
- }
- QString xStr = lst.at(0).trimmed();
- QString yStr = lst.at(1).trimmed();
- QString widthStr = lst.at(2).trimmed();
- QString heightStr = lst.at(3).trimmed();
+ viewBoxStr = viewBoxStr.replace(QLatin1Char(' '), QLatin1Char(','));
+ viewBoxStr = viewBoxStr.replace(QLatin1Char('\r'), QLatin1Char(','));
+ viewBoxStr = viewBoxStr.replace(QLatin1Char('\n'), QLatin1Char(','));
+ viewBoxStr = viewBoxStr.replace(QLatin1Char('\t'), QLatin1Char(','));
+ viewBoxValues = viewBoxStr.split(QLatin1Char(','), QString::SkipEmptyParts);
+ }
+ if (viewBoxValues.count() == 4) {
+ QString xStr = viewBoxValues.at(0).trimmed();
+ QString yStr = viewBoxValues.at(1).trimmed();
+ QString widthStr = viewBoxValues.at(2).trimmed();
+ QString heightStr = viewBoxValues.at(3).trimmed();
QSvgHandler::LengthType lt;
qreal x = parseLength(xStr, lt, handler);
@@ -3217,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,
@@ -3228,11 +3561,7 @@ bool QSvgHandler::startElement(const QString &localName,
{
QSvgNode *node = 0;
- if (m_colorTagCount.count()) {
- int top = m_colorTagCount.pop();
- ++top;
- m_colorTagCount.push(top);
- }
+ pushColorCopy();
/* The xml:space attribute may appear on any element. We do
* a lookup by the qualified name here, but this is namespace aware, since
@@ -3334,9 +3663,9 @@ 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("Couldn't parse node: %s", qPrintable(localName));
+ qWarning("Could not parse node: %s", qPrintable(localName));
}
} else if (StyleParseMethod method = findStyleUtilFactoryMethod(localName)) {
if (m_style) {
@@ -3366,15 +3695,7 @@ bool QSvgHandler::endElement(const QStringRef &localName)
m_skipNodes.pop();
m_whitespaceMode.pop();
- if (m_colorTagCount.count()) {
- int top = m_colorTagCount.pop();
- --top;
- if (!top) {
- m_colorStack.pop();
- } else {
- m_colorTagCount.push(top);
- }
- }
+ popColor();
if (node == Unknown) {
return true;
@@ -3383,40 +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 *prop = static_cast<QSvgFillStyle*>(eleNode->styleProperty(QSvgStyleProperty::FILL));
- if (prop && !(prop->isGradientResolved())) {
- QString id = prop->getGradientId();
- QSvgStyleProperty *style = structureNode->scopeStyle(id);
- if (style) {
- prop->setFillStyle(style);
- } else {
- qWarning("Couldn't resolve property : %s",qPrintable(id));
- prop->setBrush(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) {
@@ -3458,6 +3791,24 @@ void QSvgHandler::pushColor(const QColor &color)
m_colorTagCount.push(1);
}
+void QSvgHandler::pushColorCopy()
+{
+ if (m_colorTagCount.count())
+ ++m_colorTagCount.top();
+ else
+ pushColor(Qt::black);
+}
+
+void QSvgHandler::popColor()
+{
+ if (m_colorTagCount.count()) {
+ if (!--m_colorTagCount.top()) {
+ m_colorStack.pop();
+ m_colorTagCount.pop();
+ }
+ }
+}
+
QColor QSvgHandler::currentColor() const
{
if (!m_colorStack.isEmpty())
diff --git a/src/svg/qsvghandler_p.h b/src/svg/qsvghandler_p.h
index 7049719..daf1b1c 100644
--- a/src/svg/qsvghandler_p.h
+++ b/src/svg/qsvghandler_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -111,6 +111,8 @@ public:
LengthType defaultCoordinateSystem() const;
void pushColor(const QColor &color);
+ void pushColorCopy();
+ void popColor();
QColor currentColor() const;
void setInStyle(bool b);
@@ -170,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 33907fd..2e27cd5 100644
--- a/src/svg/qsvgnode.cpp
+++ b/src/svg/qsvgnode.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -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
@@ -320,9 +314,11 @@ qreal QSvgNode::strokeWidth() const
{
QSvgStrokeStyle *stroke = static_cast<QSvgStrokeStyle*>(
styleProperty(QSvgStyleProperty::STROKE));
- if (!stroke || !stroke->strokePresent())
+ if (!stroke)
+ return 0;
+ if (stroke->stroke().brush().style() == Qt::NoBrush)
return 0;
- return stroke->qpen().widthF();
+ return stroke->width();
}
QT_END_NAMESPACE
diff --git a/src/svg/qsvgnode_p.h b/src/svg/qsvgnode_p.h
index 62d2937..1f5606a 100644
--- a/src/svg/qsvgnode_p.h
+++ b/src/svg/qsvgnode_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -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/qsvgrenderer.cpp b/src/svg/qsvgrenderer.cpp
index 573b4a4..59e3bdc 100644
--- a/src/svg/qsvgrenderer.cpp
+++ b/src/svg/qsvgrenderer.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/svg/qsvgrenderer.h b/src/svg/qsvgrenderer.h
index 48dc650..cea6e5c 100644
--- a/src/svg/qsvgrenderer.h
+++ b/src/svg/qsvgrenderer.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/svg/qsvgstructure.cpp b/src/svg/qsvgstructure.cpp
index 9d48b54..82c800d 100644
--- a/src/svg/qsvgstructure.cpp
+++ b/src/svg/qsvgstructure.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -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 53c14cd..444f885 100644
--- a/src/svg/qsvgstructure_p.h
+++ b/src/svg/qsvgstructure_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -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 1ecf870..f834016 100644
--- a/src/svg/qsvgstyle.cpp
+++ b/src/svg/qsvgstyle.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -59,9 +59,13 @@ QT_BEGIN_NAMESPACE
QSvgExtraStates::QSvgExtraStates()
: fillOpacity(1.0)
+ , strokeOpacity(1.0)
, svgFont(0)
, textAnchor(Qt::AlignLeft)
, fontWeight(400)
+ , fillRule(Qt::WindingFill)
+ , strokeDashOffset(0)
+ , vectorEffect(false)
{
}
@@ -69,6 +73,17 @@ QSvgStyleProperty::~QSvgStyleProperty()
{
}
+void QSvgFillStyleProperty::apply(QPainter *, const QRectF &, QSvgNode *, QSvgExtraStates &)
+{
+ Q_ASSERT(!"This should not be called!");
+}
+
+void QSvgFillStyleProperty::revert(QPainter *, QSvgExtraStates &)
+{
+ Q_ASSERT(!"This should not be called!");
+}
+
+
QSvgQualityStyle::QSvgQualityStyle(int color)
: m_colorRendering(color)
{
@@ -83,83 +98,55 @@ void QSvgQualityStyle::revert(QPainter *, QSvgExtraStates &)
}
-QSvgFillStyle::QSvgFillStyle(const QBrush &brush)
- : m_fill(brush)
- , m_style(0)
- , m_fillRuleSet(false)
- , m_fillRule(Qt::WindingFill)
- , m_fillOpacitySet(false)
- , m_fillOpacity(1.0)
- , m_oldOpacity(0)
- , m_gradientResolved(true)
- , m_fillSet(true)
-{
-}
-
-QSvgFillStyle::QSvgFillStyle(QSvgStyleProperty *style)
- : m_style(style)
- , m_fillRuleSet(false)
+QSvgFillStyle::QSvgFillStyle()
+ : m_style(0)
, m_fillRule(Qt::WindingFill)
- , m_fillOpacitySet(false)
+ , m_oldFillRule(Qt::WindingFill)
, m_fillOpacity(1.0)
- , m_oldOpacity(0)
- , m_gradientResolved(true)
- , m_fillSet(style != 0)
+ , m_oldFillOpacity(0)
+ , m_gradientResolved(1)
+ , m_fillRuleSet(0)
+ , m_fillOpacitySet(0)
+ , m_fillSet(0)
{
}
void QSvgFillStyle::setFillRule(Qt::FillRule f)
{
- m_fillRuleSet = true;
+ m_fillRuleSet = 1;
m_fillRule = f;
}
void QSvgFillStyle::setFillOpacity(qreal opacity)
{
- m_fillOpacitySet = true;
+ m_fillOpacitySet = 1;
m_fillOpacity = opacity;
}
-void QSvgFillStyle::setFillStyle(QSvgStyleProperty* style)
+void QSvgFillStyle::setFillStyle(QSvgFillStyleProperty* style)
{
m_style = style;
- m_fillSet = true;
+ m_fillSet = 1;
}
void QSvgFillStyle::setBrush(QBrush brush)
{
m_fill = brush;
m_style = 0;
- m_fillSet = true;
+ m_fillSet = 1;
}
-static void recursivelySetFill(QSvgNode *node, Qt::FillRule f)
-{
- if (node->type() == QSvgNode::PATH) {
- QSvgPath *path = static_cast<QSvgPath*>(node);
- path->qpath()->setFillRule(f);
- } else if (node->type() == QSvgNode::POLYGON) {
- QSvgPolygon *polygon = static_cast<QSvgPolygon*>(node);
- polygon->setFillRule(f);
- } else if (node->type() == QSvgNode::G) {
- QList<QSvgNode*> renderers = static_cast<QSvgG*>(node)->renderers();
- foreach(QSvgNode *n, renderers) {
- recursivelySetFill(n, f);
- }
- }
-}
-void QSvgFillStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtraStates &states)
+void QSvgFillStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states)
{
m_oldFill = p->brush();
- m_oldOpacity = states.fillOpacity;
+ m_oldFillRule = states.fillRule;
+ m_oldFillOpacity = states.fillOpacity;
- if (m_fillRuleSet) {
- recursivelySetFill(node, m_fillRule);
- m_fillRuleSet = false;//set it only on the first run
- }
+ if (m_fillRuleSet)
+ states.fillRule = m_fillRule;
if (m_fillSet) {
if (m_style)
- m_style->apply(p, rect, node, states);
+ p->setBrush(m_style->brush(p, states));
else
p->setBrush(m_fill);
}
@@ -170,13 +157,11 @@ void QSvgFillStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgE
void QSvgFillStyle::revert(QPainter *p, QSvgExtraStates &states)
{
if (m_fillOpacitySet)
- states.fillOpacity = m_oldOpacity;
- if (m_fillSet) {
- if (m_style)
- m_style->revert(p, states);
- else
- p->setBrush(m_oldFill);
- }
+ states.fillOpacity = m_oldFillOpacity;
+ if (m_fillSet)
+ p->setBrush(m_oldFill);
+ if (m_fillRuleSet)
+ states.fillRule = m_oldFillRule;
}
QSvgViewportFillStyle::QSvgViewportFillStyle(const QBrush &brush)
@@ -286,47 +271,137 @@ void QSvgFontStyle::revert(QPainter *p, QSvgExtraStates &states)
states.fontWeight = m_oldWeight;
}
-QSvgStrokeStyle::QSvgStrokeStyle(const QPen &pen)
- : m_stroke(pen), m_strokePresent(true)
+QSvgStrokeStyle::QSvgStrokeStyle()
+ : m_strokeOpacity(1.0)
+ , m_oldStrokeOpacity(0.0)
+ , m_strokeDashOffset(0)
+ , m_oldStrokeDashOffset(0)
+ , m_style(0)
+ , m_gradientResolved(1)
+ , m_vectorEffect(0)
+ , m_oldVectorEffect(0)
+ , m_strokeSet(0)
+ , m_strokeDashArraySet(0)
+ , m_strokeDashOffsetSet(0)
+ , m_strokeLineCapSet(0)
+ , m_strokeLineJoinSet(0)
+ , m_strokeMiterLimitSet(0)
+ , m_strokeOpacitySet(0)
+ , m_strokeWidthSet(0)
+ , m_vectorEffectSet(0)
{
}
-void QSvgStrokeStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &)
+void QSvgStrokeStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states)
{
m_oldStroke = p->pen();
- if (!m_strokePresent || !m_stroke.widthF() || !m_stroke.color().alphaF()) {
- p->setPen(Qt::NoPen);
- } else {
- p->setPen(m_stroke);
+ m_oldStrokeOpacity = states.strokeOpacity;
+ m_oldStrokeDashOffset = states.strokeDashOffset;
+ m_oldVectorEffect = states.vectorEffect;
+
+ QPen pen = p->pen();
+
+ qreal oldWidth = pen.widthF();
+ qreal width = m_stroke.widthF();
+ if (oldWidth == 0)
+ oldWidth = 1;
+ if (width == 0)
+ width = 1;
+ qreal scale = oldWidth / width;
+
+ if (m_strokeOpacitySet)
+ states.strokeOpacity = m_strokeOpacity;
+
+ if (m_vectorEffectSet)
+ states.vectorEffect = m_vectorEffect;
+
+ if (m_strokeSet) {
+ if (m_style)
+ pen.setBrush(m_style->brush(p, states));
+ else
+ pen.setBrush(m_stroke.brush());
}
-}
-void QSvgStrokeStyle::revert(QPainter *p, QSvgExtraStates &)
-{
- p->setPen(m_oldStroke);
+ if (m_strokeWidthSet)
+ pen.setWidthF(m_stroke.widthF());
+
+ bool setDashOffsetNeeded = false;
+
+ if (m_strokeDashOffsetSet) {
+ states.strokeDashOffset = m_strokeDashOffset;
+ setDashOffsetNeeded = true;
+ }
+
+ if (m_strokeDashArraySet) {
+ if (m_stroke.style() == Qt::SolidLine) {
+ pen.setStyle(Qt::SolidLine);
+ } else if (m_strokeWidthSet || oldWidth == 1) {
+ // If both width and dash array was set, the dash array is already scaled correctly.
+ pen.setDashPattern(m_stroke.dashPattern());
+ setDashOffsetNeeded = true;
+ } else {
+ // If dash array was set, but not the width, the dash array has to be scaled with respect to the old width.
+ QVector<qreal> dashes = m_stroke.dashPattern();
+ for (int i = 0; i < dashes.size(); ++i)
+ dashes[i] /= oldWidth;
+ pen.setDashPattern(dashes);
+ setDashOffsetNeeded = true;
+ }
+ } else if (m_strokeWidthSet && pen.style() != Qt::SolidLine && scale != 1) {
+ // If the width was set, but not the dash array, the old dash array must be scaled with respect to the new width.
+ QVector<qreal> dashes = pen.dashPattern();
+ for (int i = 0; i < dashes.size(); ++i)
+ dashes[i] *= scale;
+ pen.setDashPattern(dashes);
+ setDashOffsetNeeded = true;
+ }
+
+ if (m_strokeLineCapSet)
+ pen.setCapStyle(m_stroke.capStyle());
+ if (m_strokeLineJoinSet)
+ pen.setJoinStyle(m_stroke.joinStyle());
+ if (m_strokeMiterLimitSet)
+ pen.setMiterLimit(m_stroke.miterLimit());
+
+ if (setDashOffsetNeeded) {
+ qreal currentWidth = pen.widthF();
+ if (currentWidth == 0)
+ currentWidth = 1;
+ pen.setDashOffset(states.strokeDashOffset / currentWidth);
+ }
+
+ pen.setCosmetic(states.vectorEffect);
+
+ p->setPen(pen);
}
-QSvgSolidColorStyle::QSvgSolidColorStyle(const QColor &color)
- : m_solidColor(color)
+void QSvgStrokeStyle::revert(QPainter *p, QSvgExtraStates &states)
{
+ p->setPen(m_oldStroke);
+ states.strokeOpacity = m_oldStrokeOpacity;
+ states.strokeDashOffset = m_oldStrokeDashOffset;
+ states.vectorEffect = m_oldVectorEffect;
}
-void QSvgSolidColorStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &)
+void QSvgStrokeStyle::setDashArray(const QVector<qreal> &dashes)
{
- m_oldFill = p->brush();
- m_oldStroke = p->pen();
- QBrush b = m_oldFill;
- b.setColor(m_solidColor);
- p->setBrush(b);
- QPen pen = m_oldStroke;
- pen.setColor(m_solidColor);
- p->setPen(pen);
+ if (m_strokeWidthSet) {
+ QVector<qreal> d = dashes;
+ qreal w = m_stroke.widthF();
+ if (w != 0 && w != 1) {
+ for (int i = 0; i < d.size(); ++i)
+ d[i] /= w;
+ }
+ m_stroke.setDashPattern(d);
+ } else {
+ m_stroke.setDashPattern(dashes);
+ }
+ m_strokeDashArraySet = 1;
}
-void QSvgSolidColorStyle::revert(QPainter *p, QSvgExtraStates &)
+QSvgSolidColorStyle::QSvgSolidColorStyle(const QColor &color)
+ : m_solidColor(color)
{
- p->setBrush(m_oldFill);
- p->setPen(m_oldStroke);
}
QSvgGradientStyle::QSvgGradientStyle(QGradient *grad)
@@ -334,44 +409,24 @@ QSvgGradientStyle::QSvgGradientStyle(QGradient *grad)
{
}
-void QSvgGradientStyle::apply(QPainter *p, const QRectF &/*rect*/, QSvgNode *, QSvgExtraStates &)
+QBrush QSvgGradientStyle::brush(QPainter *, QSvgExtraStates &)
{
if (!m_link.isEmpty()) {
resolveStops();
}
- m_oldFill = p->brush();
-
- //resolving stop colors
- if (!m_resolvePoints.isEmpty()) {
- QColor color = p->brush().color();
- if (!color.isValid())
- color = p->pen().color();
- QList<qreal>::const_iterator itr = m_resolvePoints.constBegin();
- for (; itr != m_resolvePoints.constEnd(); ++itr) {
- //qDebug()<<"resolving "<<(*itr)<<" to "<<color;
- m_gradient->setColorAt(*itr, color);
- }
- }
-
// If the gradient is marked as empty, insert transparent black
if (!m_gradientStopsSet) {
m_gradient->setStops(QGradientStops() << QGradientStop(0.0, QColor(0, 0, 0, 0)));
m_gradientStopsSet = true;
}
- QBrush brush;
- brush = QBrush(*m_gradient);
+ QBrush b(*m_gradient);
if (!m_matrix.isIdentity())
- brush.setMatrix(m_matrix);
-
- p->setBrush(brush);
-}
+ b.setMatrix(m_matrix);
-void QSvgGradientStyle::revert(QPainter *p, QSvgExtraStates &)
-{
- p->setBrush(m_oldFill);
+ return b;
}
@@ -380,11 +435,6 @@ void QSvgGradientStyle::setMatrix(const QMatrix &mat)
m_matrix = mat;
}
-void QSvgGradientStyle::addResolve(qreal offset)
-{
- m_resolvePoints.append(offset);
-}
-
QSvgTransformStyle::QSvgTransformStyle(const QTransform &trans)
: m_transform(trans)
{
@@ -490,14 +540,6 @@ void QSvgStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtra
stroke->apply(p, rect, node, states);
}
- if (solidColor) {
- solidColor->apply(p, rect, node, states);
- }
-
- if (gradient) {
- gradient->apply(p, rect, node, states);
- }
-
if (transform) {
transform->apply(p, rect, node, states);
}
@@ -509,10 +551,25 @@ void QSvgStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtra
//animated transforms have to be applied
//_after_ the original object transformations
if (!animateTransforms.isEmpty()) {
- QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr;
- for (itr = animateTransforms.constBegin(); itr != animateTransforms.constEnd();
- ++itr) {
- (*itr)->apply(p, rect, node, states);
+ qreal totalTimeElapsed = node->document()->currentElapsed();
+ // Find the last animateTransform with additive="replace", since this will override all
+ // previous animateTransforms.
+ QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr = animateTransforms.constEnd();
+ do {
+ --itr;
+ if ((*itr)->animActive(totalTimeElapsed)
+ && (*itr)->additiveType() == QSvgAnimateTransform::Replace) {
+ // An animateTransform with additive="replace" will replace the transform attribute.
+ if (transform)
+ transform->revert(p, states);
+ break;
+ }
+ } while (itr != animateTransforms.constBegin());
+
+ // Apply the animateTransforms after and including the last one with additive="replace".
+ for (; itr != animateTransforms.constEnd(); ++itr) {
+ if ((*itr)->animActive(totalTimeElapsed))
+ (*itr)->apply(p, rect, node, states);
}
}
@@ -547,24 +604,18 @@ void QSvgStyle::revert(QPainter *p, QSvgExtraStates &states)
stroke->revert(p, states);
}
- if (solidColor) {
- solidColor->revert(p, states);
- }
-
- if (gradient) {
- gradient->revert(p, states);
- }
-
//animated transforms need to be reverted _before_
//the native transforms
if (!animateTransforms.isEmpty()) {
- QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr;
- itr = animateTransforms.constBegin();
- //only need to rever the first one because that
- //one has the original world matrix for the primitve
- if (itr != animateTransforms.constEnd()) {
- (*itr)->revert(p, states);
+ QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr = animateTransforms.constBegin();
+ for (; itr != animateTransforms.constEnd(); ++itr) {
+ if ((*itr)->transformApplied()) {
+ (*itr)->revert(p, states);
+ break;
+ }
}
+ for (; itr != animateTransforms.constEnd(); ++itr)
+ (*itr)->clearTransformApplied();
}
if (transform) {
@@ -587,15 +638,16 @@ void QSvgStyle::revert(QPainter *p, QSvgExtraStates &states)
QSvgAnimateTransform::QSvgAnimateTransform(int startMs, int endMs, int byMs )
: QSvgStyleProperty(),
m_from(startMs), m_to(endMs), m_by(byMs),
- m_type(Empty), m_count(0), m_finished(false)
+ m_type(Empty), m_additive(Replace), m_count(0), m_finished(false), m_transformApplied(false)
{
m_totalRunningTime = m_to - m_from;
}
-void QSvgAnimateTransform::setArgs(TransformType type, const QVector<qreal> &args)
+void QSvgAnimateTransform::setArgs(TransformType type, Additive additive, const QVector<qreal> &args)
{
m_type = type;
m_args = args;
+ m_additive = additive;
Q_ASSERT(!(args.count()%3));
m_count = args.count() / 3;
}
@@ -604,15 +656,14 @@ void QSvgAnimateTransform::apply(QPainter *p, const QRectF &, QSvgNode *node, QS
{
m_oldWorldTransform = p->worldTransform();
resolveMatrix(node);
- if (!m_finished || m_freeze)
- p->setWorldTransform(m_transform, true);
+ p->setWorldTransform(m_transform, true);
+ m_transformApplied = true;
}
void QSvgAnimateTransform::revert(QPainter *p, QSvgExtraStates &)
{
- if (!m_finished || m_freeze) {
- p->setWorldTransform(m_oldWorldTransform, false /* don't combine */);
- }
+ p->setWorldTransform(m_oldWorldTransform, false /* don't combine */);
+ m_transformApplied = false;
}
void QSvgAnimateTransform::resolveMatrix(QSvgNode *node)
@@ -622,11 +673,14 @@ void QSvgAnimateTransform::resolveMatrix(QSvgNode *node)
if (totalTimeElapsed < m_from || m_finished)
return;
- qreal animationFrame = (totalTimeElapsed - m_from) / m_to;
+ qreal animationFrame = 0;
+ if (m_totalRunningTime != 0) {
+ animationFrame = (totalTimeElapsed - m_from) / m_totalRunningTime;
- if (m_repeatCount >= 0 && m_repeatCount < animationFrame) {
- m_finished = true;
- animationFrame = m_repeatCount;
+ if (m_repeatCount >= 0 && m_repeatCount < animationFrame) {
+ m_finished = true;
+ animationFrame = m_repeatCount;
+ }
}
qreal percentOfAnimation = animationFrame;
@@ -643,14 +697,12 @@ void QSvgAnimateTransform::resolveMatrix(QSvgNode *node)
case Translate: {
startElem *= 3;
endElem *= 3;
- qreal from1, from2, from3;
- qreal to1, to2, to3;
+ qreal from1, from2;
+ qreal to1, to2;
from1 = m_args[startElem++];
from2 = m_args[startElem++];
- from3 = m_args[startElem++];
to1 = m_args[endElem++];
to2 = m_args[endElem++];
- to3 = m_args[endElem++];
qreal transXDiff = (to1-from1) * percentOfAnimation;
qreal transX = from1 + transXDiff;
@@ -663,14 +715,12 @@ void QSvgAnimateTransform::resolveMatrix(QSvgNode *node)
case Scale: {
startElem *= 3;
endElem *= 3;
- qreal from1, from2, from3;
- qreal to1, to2, to3;
+ qreal from1, from2;
+ qreal to1, to2;
from1 = m_args[startElem++];
from2 = m_args[startElem++];
- from3 = m_args[startElem++];
to1 = m_args[endElem++];
to2 = m_args[endElem++];
- to3 = m_args[endElem++];
qreal transXDiff = (to1-from1) * percentOfAnimation;
qreal transX = from1 + transXDiff;
@@ -710,14 +760,10 @@ void QSvgAnimateTransform::resolveMatrix(QSvgNode *node)
case SkewX: {
startElem *= 3;
endElem *= 3;
- qreal from1, from2, from3;
- qreal to1, to2, to3;
+ qreal from1;
+ qreal to1;
from1 = m_args[startElem++];
- from2 = m_args[startElem++];
- from3 = m_args[startElem++];
to1 = m_args[endElem++];
- to2 = m_args[endElem++];
- to3 = m_args[endElem++];
qreal transXDiff = (to1-from1) * percentOfAnimation;
qreal transX = from1 + transXDiff;
@@ -728,14 +774,10 @@ void QSvgAnimateTransform::resolveMatrix(QSvgNode *node)
case SkewY: {
startElem *= 3;
endElem *= 3;
- qreal from1, from2, from3;
- qreal to1, to2, to3;
+ qreal from1;
+ qreal to1;
from1 = m_args[startElem++];
- from2 = m_args[startElem++];
- from3 = m_args[startElem++];
to1 = m_args[endElem++];
- to2 = m_args[endElem++];
- to3 = m_args[endElem++];
qreal transYDiff = (to1 - from1) * percentOfAnimation;
@@ -795,7 +837,9 @@ void QSvgAnimateColor::apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgEx
if (totalTimeElapsed < m_from || m_finished)
return;
- qreal animationFrame = (totalTimeElapsed - m_from) / m_to;
+ qreal animationFrame = 0;
+ if (m_totalRunningTime != 0)
+ animationFrame = (totalTimeElapsed - m_from) / m_totalRunningTime;
if (m_repeatCount >= 0 && m_repeatCount < animationFrame) {
m_finished = true;
@@ -890,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 =
@@ -899,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/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h
index c18a265..99a83c3 100644
--- a/src/svg/qsvgstyle_p.h
+++ b/src/svg/qsvgstyle_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -143,9 +143,13 @@ struct QSvgExtraStates
QSvgExtraStates();
qreal fillOpacity;
+ qreal strokeOpacity;
QSvgFont *svgFont;
Qt::Alignment textAnchor;
int fontWeight;
+ Qt::FillRule fillRule;
+ qreal strokeDashOffset;
+ bool vectorEffect; // true if pen is cosmetic
};
class QSvgStyleProperty : public QSvgRefCounted
@@ -173,6 +177,14 @@ public:
virtual Type type() const=0;
};
+class QSvgFillStyleProperty : public QSvgStyleProperty
+{
+public:
+ virtual QBrush brush(QPainter *p, QSvgExtraStates &states) = 0;
+ virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states);
+ virtual void revert(QPainter *p, QSvgExtraStates &states);
+};
+
class QSvgQualityStyle : public QSvgStyleProperty
{
public:
@@ -220,15 +232,14 @@ private:
class QSvgFillStyle : public QSvgStyleProperty
{
public:
- QSvgFillStyle(const QBrush &brush);
- QSvgFillStyle(QSvgStyleProperty *style);
+ QSvgFillStyle();
virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states);
virtual void revert(QPainter *p, QSvgExtraStates &states);
virtual Type type() const;
void setFillRule(Qt::FillRule f);
void setFillOpacity(qreal opacity);
- void setFillStyle(QSvgStyleProperty* style);
+ void setFillStyle(QSvgFillStyleProperty* style);
void setBrush(QBrush brush);
const QBrush & qbrush() const
@@ -246,17 +257,17 @@ public:
return m_fillRule;
}
- QSvgStyleProperty* style() const
+ QSvgFillStyleProperty* style() const
{
return m_style;
}
-
+
void setGradientId(const QString &Id)
{
m_gradientId = Id;
}
- QString getGradientId() const
+ QString gradientId() const
{
return m_gradientId;
}
@@ -276,16 +287,19 @@ private:
// fill-opacity v v 'inherit' | <OpacityValue.datatype>
QBrush m_fill;
QBrush m_oldFill;
- QSvgStyleProperty *m_style;
+ QSvgFillStyleProperty *m_style;
- bool m_fillRuleSet;
Qt::FillRule m_fillRule;
- bool m_fillOpacitySet;
+ Qt::FillRule m_oldFillRule;
qreal m_fillOpacity;
- qreal m_oldOpacity;
+ qreal m_oldFillOpacity;
+
QString m_gradientId;
- bool m_gradientResolved;
- bool m_fillSet;
+ uint m_gradientResolved : 1;
+
+ uint m_fillRuleSet : 1;
+ uint m_fillOpacitySet : 1;
+ uint m_fillSet : 1;
};
class QSvgViewportFillStyle : public QSvgStyleProperty
@@ -384,36 +398,121 @@ private:
Qt::Alignment m_oldTextAnchor;
int m_oldWeight;
- unsigned m_familySet : 1;
- unsigned m_sizeSet : 1;
- unsigned m_styleSet : 1;
- unsigned m_variantSet : 1;
- unsigned m_weightSet : 1;
- unsigned m_textAnchorSet : 1;
+ uint m_familySet : 1;
+ uint m_sizeSet : 1;
+ uint m_styleSet : 1;
+ uint m_variantSet : 1;
+ uint m_weightSet : 1;
+ uint m_textAnchorSet : 1;
};
class QSvgStrokeStyle : public QSvgStyleProperty
{
public:
- QSvgStrokeStyle(const QPen &pen);
+ QSvgStrokeStyle();
virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states);
virtual void revert(QPainter *p, QSvgExtraStates &states);
virtual Type type() const;
- void setStroke(bool stroke)
+ void setStroke(QBrush brush)
{
- m_strokePresent = stroke;
+ m_stroke.setBrush(brush);
+ m_style = 0;
+ m_strokeSet = 1;
}
- bool strokePresent() const
+ void setStyle(QSvgFillStyleProperty *style)
{
- return m_strokePresent;
+ m_style = style;
+ m_strokeSet = 1;
}
- const QPen & qpen() const
+ void setDashArray(const QVector<qreal> &dashes);
+
+ void setDashArrayNone()
+ {
+ m_stroke.setStyle(Qt::SolidLine);
+ m_strokeDashArraySet = 1;
+ }
+
+ void setDashOffset(qreal offset)
+ {
+ m_strokeDashOffset = offset;
+ m_strokeDashOffsetSet = 1;
+ }
+
+ void setLineCap(Qt::PenCapStyle cap)
+ {
+ m_stroke.setCapStyle(cap);
+ m_strokeLineCapSet = 1;
+ }
+
+ void setLineJoin(Qt::PenJoinStyle join)
+ {
+ m_stroke.setJoinStyle(join);
+ m_strokeLineJoinSet = 1;
+ }
+
+ void setMiterLimit(qreal limit)
+ {
+ m_stroke.setMiterLimit(limit);
+ m_strokeMiterLimitSet = 1;
+ }
+
+ void setOpacity(qreal opacity)
+ {
+ m_strokeOpacity = opacity;
+ m_strokeOpacitySet = 1;
+ }
+
+ void setWidth(qreal width)
+ {
+ m_stroke.setWidthF(width);
+ m_strokeWidthSet = 1;
+ Q_ASSERT(!m_strokeDashArraySet); // set width before dash array.
+ }
+
+ qreal width()
+ {
+ return m_stroke.widthF();
+ }
+
+ void setVectorEffect(bool nonScalingStroke)
+ {
+ m_vectorEffect = nonScalingStroke;
+ m_vectorEffectSet = 1;
+ }
+
+ QSvgFillStyleProperty* style() const
+ {
+ return m_style;
+ }
+
+ void setGradientId(const QString &Id)
+ {
+ m_gradientId = Id;
+ }
+
+ QString gradientId() const
+ {
+ return m_gradientId;
+ }
+
+ void setGradientResolved(bool resolved)
+ {
+ m_gradientResolved = resolved;
+ }
+
+ bool isGradientResolved() const
+ {
+ return m_gradientResolved;
+ }
+
+ QPen stroke() const
{
return m_stroke;
}
+
private:
// stroke v v 'inherit' | <Paint.datatype>
// stroke-dasharray v v 'inherit' | <StrokeDashArrayValue.datatype>
@@ -425,22 +524,44 @@ private:
// stroke-width v v 'inherit' | <StrokeWidthValue.datatype>
QPen m_stroke;
QPen m_oldStroke;
- bool m_strokePresent;
-};
+ qreal m_strokeOpacity;
+ qreal m_oldStrokeOpacity;
+ qreal m_strokeDashOffset;
+ qreal m_oldStrokeDashOffset;
+ QSvgFillStyleProperty *m_style;
+ QString m_gradientId;
+ uint m_gradientResolved : 1;
+ uint m_vectorEffect : 1;
+ uint m_oldVectorEffect : 1;
+
+ uint m_strokeSet : 1;
+ uint m_strokeDashArraySet : 1;
+ uint m_strokeDashOffsetSet : 1;
+ uint m_strokeLineCapSet : 1;
+ uint m_strokeLineJoinSet : 1;
+ uint m_strokeMiterLimitSet : 1;
+ uint m_strokeOpacitySet : 1;
+ uint m_strokeWidthSet : 1;
+ uint m_vectorEffectSet : 1;
+};
-class QSvgSolidColorStyle : public QSvgStyleProperty
+class QSvgSolidColorStyle : public QSvgFillStyleProperty
{
public:
QSvgSolidColorStyle(const QColor &color);
- virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states);
- virtual void revert(QPainter *p, QSvgExtraStates &states);
virtual Type type() const;
const QColor & qcolor() const
{
return m_solidColor;
}
+
+ QBrush brush(QPainter *, QSvgExtraStates &)
+ {
+ return m_solidColor;
+ }
+
private:
// solid-color v x 'inherit' | <SVGColor.datatype>
// solid-opacity v x 'inherit' | <OpacityValue.datatype>
@@ -450,13 +571,11 @@ private:
QPen m_oldStroke;
};
-class QSvgGradientStyle : public QSvgStyleProperty
+class QSvgGradientStyle : public QSvgFillStyleProperty
{
public:
QSvgGradientStyle(QGradient *grad);
~QSvgGradientStyle() { delete m_gradient; }
- virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states);
- virtual void revert(QPainter *p, QSvgExtraStates &states);
virtual Type type() const;
void setStopLink(const QString &link, QSvgTinyDocument *doc);
@@ -474,8 +593,6 @@ public:
return m_gradient;
}
- void addResolve(qreal offset);
-
bool gradientStopsSet() const
{
return m_gradientStopsSet;
@@ -485,12 +602,10 @@ public:
{
m_gradientStopsSet = set;
}
+
+ QBrush brush(QPainter *, QSvgExtraStates &);
private:
QGradient *m_gradient;
- QList<qreal> m_resolvePoints;
-
- QBrush m_oldFill;
-
QMatrix m_matrix;
QSvgTinyDocument *m_doc;
@@ -529,20 +644,56 @@ public:
SkewX,
SkewY
};
+ enum Additive
+ {
+ Sum,
+ Replace
+ };
public:
QSvgAnimateTransform(int startMs, int endMs, int by = 0);
- void setArgs(TransformType type, const QVector<qreal> &args);
+ void setArgs(TransformType type, Additive additive, const QVector<qreal> &args);
void setFreeze(bool freeze);
void setRepeatCount(qreal repeatCount);
virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states);
virtual void revert(QPainter *p, QSvgExtraStates &states);
virtual Type type() const;
+ QSvgAnimateTransform::Additive additiveType() const
+ {
+ return m_additive;
+ }
+
+ bool animActive(qreal totalTimeElapsed)
+ {
+ if (totalTimeElapsed < m_from)
+ return false;
+ if (m_freeze || m_repeatCount < 0) // fill="freeze" or repeat="indefinite"
+ return true;
+ if (m_totalRunningTime == 0)
+ return false;
+ qreal animationFrame = (totalTimeElapsed - m_from) / m_totalRunningTime;
+ if (animationFrame > m_repeatCount)
+ return false;
+ return true;
+ }
+
+ bool transformApplied() const
+ {
+ return m_transformApplied;
+ }
+
+ // Call this instead of revert if you know that revert is unnecessary.
+ void clearTransformApplied()
+ {
+ m_transformApplied = false;
+ }
+
protected:
void resolveMatrix(QSvgNode *node);
private:
qreal m_from, m_to, m_by;
qreal m_totalRunningTime;
TransformType m_type;
+ Additive m_additive;
QVector<qreal> m_args;
int m_count;
QTransform m_transform;
@@ -550,6 +701,7 @@ private:
bool m_finished;
bool m_freeze;
qreal m_repeatCount;
+ bool m_transformApplied;
};
diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp
index 614494f..e2cefeb 100644
--- a/src/svg/qsvgtinydocument.cpp
+++ b/src/svg/qsvgtinydocument.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -240,7 +240,9 @@ void QSvgTinyDocument::draw(QPainter *p, const QRectF &bounds)
//sets default style on the painter
//### not the most optimal way
mapSourceToTarget(p, bounds);
- p->setPen(Qt::NoPen);
+ QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
+ pen.setMiterLimit(4);
+ p->setPen(pen);
p->setBrush(Qt::black);
p->setRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::SmoothPixmapTransform);
@@ -281,7 +283,9 @@ void QSvgTinyDocument::draw(QPainter *p, const QString &id,
QTransform originalTransform = p->worldTransform();
//XXX set default style on the painter
- p->setPen(Qt::NoPen);
+ QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
+ pen.setMiterLimit(4);
+ p->setPen(pen);
p->setBrush(Qt::black);
p->setRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::SmoothPixmapTransform);
@@ -346,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 0fd1723..38a1f92 100644
--- a/src/svg/qsvgtinydocument_p.h
+++ b/src/svg/qsvgtinydocument_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -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;
diff --git a/src/svg/qsvgwidget.cpp b/src/svg/qsvgwidget.cpp
index b7b0ab0..0302ded 100644
--- a/src/svg/qsvgwidget.cpp
+++ b/src/svg/qsvgwidget.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/svg/qsvgwidget.h b/src/svg/qsvgwidget.h
index a05a2d8..6abcae3 100644
--- a/src/svg/qsvgwidget.h
+++ b/src/svg/qsvgwidget.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSvg module of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,21 +21,20 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/