diff options
author | Frans Englich <frans.englich@nokia.com> | 2009-09-23 13:16:51 (GMT) |
---|---|---|
committer | Frans Englich <frans.englich@nokia.com> | 2009-09-23 13:16:51 (GMT) |
commit | 902ceabbca3cd3f3a06180aba64b0f81b3f1dba4 (patch) | |
tree | 64efeee683cd31c2a0f7511fecc3c124c91249fe /src/svg | |
parent | 9161598b9cb374889ca6c69831c035c1eaa4d56e (diff) | |
parent | bbcef4e4b596324aeda80e0aa7d313c586454740 (diff) | |
download | Qt-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.cpp | 60 | ||||
-rw-r--r-- | src/svg/qgraphicssvgitem.h | 44 | ||||
-rw-r--r-- | src/svg/qsvgfont.cpp | 30 | ||||
-rw-r--r-- | src/svg/qsvgfont_p.h | 30 | ||||
-rw-r--r-- | src/svg/qsvggenerator.cpp | 33 | ||||
-rw-r--r-- | src/svg/qsvggenerator.h | 30 | ||||
-rw-r--r-- | src/svg/qsvggraphics.cpp | 112 | ||||
-rw-r--r-- | src/svg/qsvggraphics_p.h | 37 | ||||
-rw-r--r-- | src/svg/qsvghandler.cpp | 1419 | ||||
-rw-r--r-- | src/svg/qsvghandler_p.h | 33 | ||||
-rw-r--r-- | src/svg/qsvgnode.cpp | 146 | ||||
-rw-r--r-- | src/svg/qsvgnode_p.h | 36 | ||||
-rw-r--r-- | src/svg/qsvgrenderer.cpp | 30 | ||||
-rw-r--r-- | src/svg/qsvgrenderer.h | 30 | ||||
-rw-r--r-- | src/svg/qsvgstructure.cpp | 80 | ||||
-rw-r--r-- | src/svg/qsvgstructure_p.h | 33 | ||||
-rw-r--r-- | src/svg/qsvgstyle.cpp | 410 | ||||
-rw-r--r-- | src/svg/qsvgstyle_p.h | 260 | ||||
-rw-r--r-- | src/svg/qsvgtinydocument.cpp | 58 | ||||
-rw-r--r-- | src/svg/qsvgtinydocument_p.h | 36 | ||||
-rw-r--r-- | src/svg/qsvgwidget.cpp | 30 | ||||
-rw-r--r-- | src/svg/qsvgwidget.h | 30 |
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$ ** ****************************************************************************/ |