Changeset 561 for trunk/src/svg
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/svg/qgraphicssvgitem.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 53 53 QT_BEGIN_NAMESPACE 54 54 55 class QGraphicsSvgItemPrivate : public Q ObjectPrivate55 class QGraphicsSvgItemPrivate : public QGraphicsItemPrivate 56 56 { 57 57 public: … … 63 63 } 64 64 65 void init( )65 void init(QGraphicsItem *parent) 66 66 { 67 67 Q_Q(QGraphicsSvgItem); 68 q->setParentItem(parent); 68 69 renderer = new QSvgRenderer(q); 69 70 QObject::connect(renderer, SIGNAL(repaintNeeded()), … … 100 101 /*! 101 102 \class QGraphicsSvgItem 102 \ingroup multimedia103 103 \ingroup graphicsview-api 104 104 \brief The QGraphicsSvgItem class is a QGraphicsItem that can be used to render … … 139 139 */ 140 140 QGraphicsSvgItem::QGraphicsSvgItem(QGraphicsItem *parent) 141 : Q Object(*new QGraphicsSvgItemPrivate(), 0), QGraphicsItem(parent)142 { 143 Q_D(QGraphicsSvgItem); 144 d->init( );141 : QGraphicsObject(*new QGraphicsSvgItemPrivate(), 0, 0) 142 { 143 Q_D(QGraphicsSvgItem); 144 d->init(parent); 145 145 } 146 146 … … 150 150 */ 151 151 QGraphicsSvgItem::QGraphicsSvgItem(const QString &fileName, QGraphicsItem *parent) 152 : Q Object(*new QGraphicsSvgItemPrivate(), 0), QGraphicsItem(parent)153 { 154 Q_D(QGraphicsSvgItem); 155 d->init( );152 : QGraphicsObject(*new QGraphicsSvgItemPrivate(), 0, 0) 153 { 154 Q_D(QGraphicsSvgItem); 155 d->init(parent); 156 156 d->renderer->load(fileName); 157 157 d->updateDefaultSize(); … … 187 187 { 188 188 const QRectF murect = painter->transform().mapRect(QRectF(0, 0, 1, 1)); 189 if (qFuzzy Compare(qMax(murect.width(), murect.height()) + 1, 1))189 if (qFuzzyIsNull(qMax(murect.width(), murect.height()))) 190 190 return; 191 191 … … 266 266 } 267 267 268 /*! 269 \property QGraphicsSvgItem::maximumCacheSize 270 271 This property holds the maximum size of the device coordinate cache 272 for this item. 273 */ 268 274 269 275 /*! … … 306 312 307 313 /*! 308 Sets the XML ID of the element that this item should render to \a 309 id. 314 \property QGraphicsSvgItem::elementId 315 316 This property holds the element's XML ID. 317 */ 318 319 /*! 320 Sets the XML ID of the element to \a id. 310 321 */ 311 322 void QGraphicsSvgItem::setElementId(const QString &id) … … 319 330 /*! 320 331 Returns the XML ID the element that is currently 321 being rendere r. Returns an empty string if the whole332 being rendered. Returns an empty string if the whole 322 333 file is being rendered. 323 334 */ -
trunk/src/svg/qgraphicssvgitem.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 43 43 44 44 #include <QtGui/qgraphicsitem.h> 45 #include <QtCore/qobject.h>46 45 47 46 #ifndef QT_NO_GRAPHICSSVGITEM … … 56 55 class QGraphicsSvgItemPrivate; 57 56 58 class Q_SVG_EXPORT QGraphicsSvgItem : public Q Object, public QGraphicsItem57 class Q_SVG_EXPORT QGraphicsSvgItem : public QGraphicsObject 59 58 { 60 59 Q_OBJECT 60 Q_INTERFACES(QGraphicsItem) 61 Q_PROPERTY(QString elementId READ elementId WRITE setElementId) 62 Q_PROPERTY(QSize maximumCacheSize READ maximumCacheSize WRITE setMaximumCacheSize) 61 63 62 64 public: … … 87 89 private: 88 90 Q_DISABLE_COPY(QGraphicsSvgItem) 89 90 // Q_DECLARE_PRIVATE_WITH_BASE(QGraphicsSvgItem, QObject) 91 inline QGraphicsSvgItemPrivate *d_func() 92 { return reinterpret_cast<QGraphicsSvgItemPrivate *>(QObject::d_ptr); } 93 inline const QGraphicsSvgItemPrivate *d_func() const 94 { return reinterpret_cast<const QGraphicsSvgItemPrivate *>(QObject::d_ptr); } 95 friend class QGraphicsSvgItemPrivate; 91 Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsSvgItem) 96 92 97 93 Q_PRIVATE_SLOT(d_func(), void _q_repaintItem()) -
trunk/src/svg/qsvgfont.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/svg/qsvgfont_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/svg/qsvggenerator.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 262 262 263 263 if (!constantAlpha) { 264 const qreal spacing = 0.02;264 const qreal spacing = qreal(0.02); 265 265 QGradientStops newStops; 266 266 QRgb fromColor = PREMUL(stops.at(0).second.rgba()); … … 363 363 364 364 // SVG uses absolute offset 365 dashOffset = QString:: fromLatin1("%1").arg(spen.dashOffset() * penWidth);365 dashOffset = QString::number(spen.dashOffset() * penWidth); 366 366 367 367 d_func()->attributes.stroke = color; … … 404 404 switch (spen.joinStyle()) { 405 405 case Qt::MiterJoin: 406 stream() << "stroke-linejoin=\"miter\" " ;407 stream() <<"stroke-miterlimit=\""<<spen.miterLimit()<<"\" ";406 stream() << "stroke-linejoin=\"miter\" " 407 "stroke-miterlimit=\""<<spen.miterLimit()<<"\" "; 408 408 break; 409 409 case Qt::BevelJoin: … … 414 414 break; 415 415 case Qt::SvgMiterJoin: 416 stream() << "stroke-linejoin=\"miter\" " ;417 stream() <<"stroke-miterlimit=\""<<spen.miterLimit()<<"\" ";416 stream() << "stroke-linejoin=\"miter\" " 417 "stroke-miterlimit=\""<<spen.miterLimit()<<"\" "; 418 418 break; 419 419 default: … … 428 428 QString color, colorOpacity; 429 429 translate_color(sbrush.color(), &color, &colorOpacity); 430 stream() << "fill=\"" << color << "\" " ;431 stream() <<"fill-opacity=\""430 stream() << "fill=\"" << color << "\" " 431 "fill-opacity=\"" 432 432 << colorOpacity << "\" "; 433 433 d_func()->attributes.fill = color; … … 494 494 495 495 *d->stream << "font-family=\"" << d->attributes.font_family << "\" " 496 <<"font-size=\"" << d->attributes.font_size << "\" "497 <<"font-weight=\"" << d->attributes.font_weight << "\" "498 <<"font-style=\"" << d->attributes.font_style << "\" "496 "font-size=\"" << d->attributes.font_size << "\" " 497 "font-weight=\"" << d->attributes.font_weight << "\" " 498 "font-style=\"" << d->attributes.font_style << "\" " 499 499 << endl; 500 500 } … … 512 512 /*! 513 513 \class QSvgGenerator 514 \ingroup multimedia514 \ingroup painting 515 515 \since 4.3 516 516 \brief The QSvgGenerator class provides a paint device that is used to create SVG drawings. … … 568 568 delete d->engine->outputDevice(); 569 569 delete d->engine; 570 delete d_ptr;571 570 } 572 571 … … 850 849 851 850 if (d->viewBox.isValid()) { 852 *d->stream << " viewBox=\"" << d->viewBox.left() << " "<< d->viewBox.top();853 *d->stream << " " << d->viewBox.width() << " " << d->viewBox.height() << "\""<< endl;851 *d->stream << " viewBox=\"" << d->viewBox.left() << ' ' << d->viewBox.top(); 852 *d->stream << ' ' << d->viewBox.width() << ' ' << d->viewBox.height() << '\"' << endl; 854 853 } 855 854 856 855 *d->stream << " xmlns=\"http://www.w3.org/2000/svg\"" 857 <<" xmlns:xlink=\"http://www.w3.org/1999/xlink\" "858 <<" version=\"1.2\" baseProfile=\"tiny\">" << endl;856 " xmlns:xlink=\"http://www.w3.org/1999/xlink\" " 857 " version=\"1.2\" baseProfile=\"tiny\">" << endl; 859 858 860 859 if (!d->attributes.document_title.isEmpty()) { … … 919 918 Q_UNUSED(flags); 920 919 stream() << "<image "; 921 stream() << "x=\""<<r.x()<<"\" "; 922 stream() << "y=\""<<r.y()<<"\" "; 923 stream() << "width=\""<<r.width()<<"\" "; 924 stream() << "height=\""<<r.height()<<"\" "; 920 stream() << "x=\""<<r.x()<<"\" " 921 "y=\""<<r.y()<<"\" " 922 "width=\""<<r.width()<<"\" " 923 "height=\""<<r.height()<<"\" " 924 "preserveAspectRatio=\"none\" "; 925 925 926 926 QByteArray data; … … 931 931 stream() << "xlink:href=\"data:image/png;base64," 932 932 << data.toBase64() 933 <<"\" "; 934 stream() << "/>\n"; 933 <<"\" />\n"; 935 934 } 936 935 … … 959 958 if (flags & QPaintEngine::DirtyTransform) { 960 959 d->matrix = state.matrix(); 961 *d->stream << "transform=\"matrix(" << d->matrix.m11() << ","962 << d->matrix.m12() << ","963 << d->matrix.m21() << "," << d->matrix.m22() << ","964 << d->matrix.dx() << ","<< d->matrix.dy()960 *d->stream << "transform=\"matrix(" << d->matrix.m11() << ',' 961 << d->matrix.m12() << ',' 962 << d->matrix.m21() << ',' << d->matrix.m22() << ',' 963 << d->matrix.dx() << ',' << d->matrix.dy() 965 964 << ")\"" 966 965 << endl; … … 972 971 973 972 if (flags & QPaintEngine::DirtyOpacity) { 974 if (!qFuzzy Compare(state.opacity(),1))973 if (!qFuzzyIsNull(state.opacity() - 1)) 975 974 stream() << "opacity=\""<<state.opacity()<<"\" "; 976 975 } 977 976 978 *d->stream << ">"<< endl;977 *d->stream << '>' << endl; 979 978 980 979 d->afterFirstUpdate = true; … … 985 984 Q_D(QSvgPaintEngine); 986 985 987 *d->stream << "<path "; 988 989 990 *d->stream << "fill-rule="; 986 *d->stream << "<path " 987 "fill-rule="; 991 988 if (p.fillRule() == Qt::OddEvenFill) 992 989 *d->stream << "\"evenodd\" "; … … 1000 997 switch (e.type) { 1001 998 case QPainterPath::MoveToElement: 1002 *d->stream << "M" << e.x << ","<< e.y;999 *d->stream << 'M' << e.x << ',' << e.y; 1003 1000 break; 1004 1001 case QPainterPath::LineToElement: 1005 *d->stream << "L" << e.x << ","<< e.y;1002 *d->stream << 'L' << e.x << ',' << e.y; 1006 1003 break; 1007 1004 case QPainterPath::CurveToElement: 1008 *d->stream << "C" << e.x << ","<< e.y;1005 *d->stream << 'C' << e.x << ',' << e.y; 1009 1006 ++i; 1010 1007 while (i < p.elementCount()) { … … 1014 1011 break; 1015 1012 } else 1016 *d->stream << " ";1017 *d->stream << e.x << ","<< e.y;1013 *d->stream << ' '; 1014 *d->stream << e.x << ',' << e.y; 1018 1015 ++i; 1019 1016 } … … 1023 1020 } 1024 1021 if (i != p.elementCount() - 1) { 1025 *d->stream << " ";1022 *d->stream << ' '; 1026 1023 } 1027 1024 } … … 1045 1042 for (int i = 0; i < pointCount; ++i) { 1046 1043 const QPointF &pt = points[i]; 1047 stream() << pt.x() << "," << pt.y() << " ";1044 stream() << pt.x() << ',' << pt.y() << ' '; 1048 1045 } 1049 1046 stream() << "\" />" <<endl; … … 1064 1061 1065 1062 *d->stream << "<text " 1066 << "fill=\"" << d->attributes.stroke << "\" " 1067 << "fill-opacity=\"" << d->attributes.strokeOpacity << "\" " 1068 << "stroke=\"none\" " 1069 << "x=\"" << pt.x() << "\" y=\"" << pt.y() << "\" "; 1063 "fill=\"" << d->attributes.stroke << "\" " 1064 "fill-opacity=\"" << d->attributes.strokeOpacity << "\" " 1065 "stroke=\"none\" " 1066 "xml:space=\"preserve\" " 1067 "x=\"" << pt.x() << "\" y=\"" << pt.y() << "\" "; 1070 1068 qfontToSvg(textItem.font()); 1071 1069 *d->stream << " >" -
trunk/src/svg/qsvggenerator.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 50 50 #include <QtCore/qiodevice.h> 51 51 #include <QtCore/qobjectdefs.h> 52 #include <QtCore/qscopedpointer.h> 52 53 53 54 QT_BEGIN_HEADER … … 101 102 102 103 private: 103 QS vgGeneratorPrivate *d_ptr;104 QScopedPointer<QSvgGeneratorPrivate> d_ptr; 104 105 }; 105 106 -
trunk/src/svg/qsvggraphics.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 57 57 QT_BEGIN_NAMESPACE 58 58 59 #define QT_SVG_DRAW_SHAPE(command) \ 60 applyStyle(p, states); \ 61 qreal oldOpacity = p->opacity(); \ 62 QBrush oldBrush = p->brush(); \ 63 QPen oldPen = p->pen(); \ 64 p->setPen(Qt::NoPen); \ 65 p->setOpacity(oldOpacity * states.fillOpacity); \ 66 command; \ 67 p->setOpacity(oldOpacity); \ 68 p->setPen(oldPen); \ 69 p->setBrush(Qt::NoBrush); \ 70 command; \ 71 p->setBrush(oldBrush); \ 72 revertStyle(p, states); 59 #define QT_SVG_DRAW_SHAPE(command) \ 60 qreal oldOpacity = p->opacity(); \ 61 QBrush oldBrush = p->brush(); \ 62 QPen oldPen = p->pen(); \ 63 p->setPen(Qt::NoPen); \ 64 p->setOpacity(oldOpacity * states.fillOpacity); \ 65 command; \ 66 p->setPen(oldPen); \ 67 if (oldPen.widthF() != 0) { \ 68 p->setOpacity(oldOpacity * states.strokeOpacity); \ 69 p->setBrush(Qt::NoBrush); \ 70 command; \ 71 p->setBrush(oldBrush); \ 72 } \ 73 p->setOpacity(oldOpacity); 73 74 74 75 … … 95 96 { 96 97 qreal sw = strokeWidth(); 97 if (qFuzzy Compare(sw + 1, 1))98 if (qFuzzyIsNull(sw)) 98 99 return m_bounds; 99 100 else { … … 106 107 void QSvgCircle::draw(QPainter *p, QSvgExtraStates &states) 107 108 { 109 applyStyle(p, states); 108 110 QT_SVG_DRAW_SHAPE(p->drawEllipse(m_bounds)); 111 revertStyle(p, states); 109 112 } 110 113 … … 118 121 { 119 122 applyStyle(p, states); 120 p->drawPath(cubic); 123 if (p->pen().widthF() != 0) { 124 qreal oldOpacity = p->opacity(); 125 p->setOpacity(oldOpacity * states.strokeOpacity); 126 p->drawPath(cubic); 127 p->setOpacity(oldOpacity); 128 } 121 129 revertStyle(p, states); 122 130 } … … 130 138 { 131 139 qreal sw = strokeWidth(); 132 if (qFuzzy Compare(sw + 1, 1))140 if (qFuzzyIsNull(sw)) 133 141 return m_bounds; 134 142 else { … … 141 149 void QSvgEllipse::draw(QPainter *p, QSvgExtraStates &states) 142 150 { 151 applyStyle(p, states); 143 152 QT_SVG_DRAW_SHAPE(p->drawEllipse(m_bounds)); 153 revertStyle(p, states); 144 154 } 145 155 … … 172 182 { 173 183 applyStyle(p, states); 174 p->drawLine(m_bounds); 184 if (p->pen().widthF() != 0) { 185 qreal oldOpacity = p->opacity(); 186 p->setOpacity(oldOpacity * states.strokeOpacity); 187 p->drawLine(m_bounds); 188 p->setOpacity(oldOpacity); 189 } 175 190 revertStyle(p, states); 176 191 } … … 179 194 : QSvgNode(parent), m_path(qpath) 180 195 { 181 //m_cachedBounds = m_path.controlPointRect();182 m_cachedBounds = m_path.boundingRect();183 196 } 184 197 185 198 void QSvgPath::draw(QPainter *p, QSvgExtraStates &states) 186 199 { 200 applyStyle(p, states); 201 m_path.setFillRule(states.fillRule); 187 202 QT_SVG_DRAW_SHAPE(p->drawPath(m_path)); 203 revertStyle(p, states); 188 204 } 189 205 … … 191 207 { 192 208 qreal sw = strokeWidth(); 193 if (qFuzzyCompare(sw + 1, 1)) 209 if (qFuzzyIsNull(sw)) { 210 if (m_cachedBounds.isNull()) 211 //m_cachedBounds = m_path.controlPointRect(); 212 m_cachedBounds = m_path.boundingRect(); 213 194 214 return m_cachedBounds; 215 } 195 216 else { 196 217 return boundsOnStroke(m_path, sw); … … 201 222 : QSvgNode(parent), m_poly(poly) 202 223 { 203 204 224 } 205 225 … … 207 227 { 208 228 qreal sw = strokeWidth(); 209 if (qFuzzy Compare(sw + 1, 1))229 if (qFuzzyIsNull(sw)) 210 230 return m_poly.boundingRect(); 211 231 else { … … 218 238 void QSvgPolygon::draw(QPainter *p, QSvgExtraStates &states) 219 239 { 220 QT_SVG_DRAW_SHAPE(p->drawPolygon(m_poly)); 240 applyStyle(p, states); 241 QT_SVG_DRAW_SHAPE(p->drawPolygon(m_poly, states.fillRule)); 242 revertStyle(p, states); 221 243 } 222 244 … … 231 253 { 232 254 applyStyle(p, states); 255 qreal oldOpacity = p->opacity(); 233 256 if (p->brush().style() != Qt::NoBrush) { 234 257 QPen save = p->pen(); 235 258 p->setPen(QPen(Qt::NoPen)); 236 p->drawPolygon(m_poly); 259 p->setOpacity(oldOpacity * states.fillOpacity); 260 p->drawPolygon(m_poly, states.fillRule); 237 261 p->setPen(save); 238 262 } 239 p->drawPolyline(m_poly); 263 if (p->pen().widthF() != 0) { 264 p->setOpacity(oldOpacity * states.strokeOpacity); 265 p->drawPolyline(m_poly); 266 } 267 p->setOpacity(oldOpacity); 240 268 revertStyle(p, states); 241 269 } … … 250 278 { 251 279 qreal sw = strokeWidth(); 252 if (qFuzzy Compare(sw + 1, 1))280 if (qFuzzyIsNull(sw)) 253 281 return m_rect; 254 282 else { … … 261 289 void QSvgRect::draw(QPainter *p, QSvgExtraStates &states) 262 290 { 291 applyStyle(p, states); 263 292 if (m_rx || m_ry) { 264 293 QT_SVG_DRAW_SHAPE(p->drawRoundedRect(m_rect, m_rx, m_ry, Qt::RelativeSize)); … … 266 295 QT_SVG_DRAW_SHAPE(p->drawRect(m_rect)); 267 296 } 268 } 297 revertStyle(p, states); 298 } 299 300 QSvgTspan * const QSvgText::LINEBREAK = 0; 269 301 270 302 QSvgText::QSvgText(QSvgNode *parent, const QPointF &coord) 271 303 : QSvgNode(parent) 272 304 , m_coord(coord) 273 , m_textAlignment(Qt::AlignLeft)274 , m_scale(1)275 , m_appendSpace(false)276 305 , m_type(TEXT) 277 306 , m_size(0, 0) 278 { 279 m_paragraphs.push_back(QString()); 280 m_formatRanges.push_back(QList<QTextLayout::FormatRange>()); 307 , m_mode(Default) 308 { 281 309 } 282 310 283 311 QSvgText::~QSvgText() 284 312 { 313 for (int i = 0; i < m_tspans.size(); ++i) { 314 if (m_tspans[i] != LINEBREAK) 315 delete m_tspans[i]; 316 } 285 317 } 286 318 … … 296 328 { 297 329 applyStyle(p, states); 298 299 QSvgFontStyle *fontStyle = static_cast<QSvgFontStyle*>( 300 styleProperty(QSvgStyleProperty::FONT)); 301 if (fontStyle && fontStyle->svgFont()) { 302 // SVG fonts not fully supported... 303 QString text = m_paragraphs.front(); 304 for (int i = 1; i < m_paragraphs.size(); ++i) { 305 text.append(QLatin1Char('\n')); 306 text.append(m_paragraphs[i]); 307 } 308 fontStyle->svgFont()->draw(p, m_coord, text, fontStyle->pointSize(), m_textAlignment); 309 revertStyle(p, states); 310 return; 311 } 312 313 // Scale the font to its correct size. 330 qreal oldOpacity = p->opacity(); 331 p->setOpacity(oldOpacity * states.fillOpacity); 332 333 // Force the font to have a size of 100 pixels to avoid truncation problems 334 // when the font is very small. 335 qreal scale = 100.0 / p->font().pointSizeF(); 336 Qt::Alignment alignment = states.textAnchor; 337 314 338 QTransform oldTransform = p->worldTransform(); 315 p->scale(1 / m_scale, 1 / m_scale);339 p->scale(1 / scale, 1 / scale); 316 340 317 341 qreal y = 0; 318 342 bool initial = true; 319 qreal px = m_coord.x() * m_scale;320 qreal py = m_coord.y() * m_scale;321 QSizeF scaledSize = m_size * m_scale;343 qreal px = m_coord.x() * scale; 344 qreal py = m_coord.y() * scale; 345 QSizeF scaledSize = m_size * scale; 322 346 323 347 if (m_type == TEXTAREA) { 324 if ( m_textAlignment == Qt::AlignHCenter)348 if (alignment == Qt::AlignHCenter) 325 349 px += scaledSize.width() / 2; 326 else if ( m_textAlignment == Qt::AlignRight)350 else if (alignment == Qt::AlignRight) 327 351 px += scaledSize.width(); 328 352 } … … 330 354 QRectF bounds; 331 355 if (m_size.height() != 0) 332 bounds = QRectF(0, 0, 1, scaledSize.height()); 333 334 for (int i = 0; i < m_paragraphs.size(); ++i) { 335 QTextLayout tl(m_paragraphs[i]); 336 QTextOption op = tl.textOption(); 337 op.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); 338 tl.setTextOption(op); 339 tl.setAdditionalFormats(m_formatRanges[i]); 340 tl.beginLayout(); 341 forever { 342 QTextLine line = tl.createLine(); 343 if (!line.isValid()) 356 bounds = QRectF(0, py, 1, scaledSize.height()); // x and width are not used. 357 358 bool appendSpace = false; 359 QVector<QString> paragraphs; 360 QStack<QTextCharFormat> formats; 361 QVector<QList<QTextLayout::FormatRange> > formatRanges; 362 paragraphs.push_back(QString()); 363 formatRanges.push_back(QList<QTextLayout::FormatRange>()); 364 365 for (int i = 0; i < m_tspans.size(); ++i) { 366 if (m_tspans[i] == LINEBREAK) { 367 if (m_type == TEXTAREA) { 368 if (paragraphs.back().isEmpty()) { 369 QFont font = p->font(); 370 font.setPixelSize(font.pointSizeF() * scale); 371 372 QTextLayout::FormatRange range; 373 range.start = 0; 374 range.length = 1; 375 range.format.setFont(font); 376 formatRanges.back().append(range); 377 378 paragraphs.back().append(QLatin1Char(' '));; 379 } 380 appendSpace = false; 381 paragraphs.push_back(QString()); 382 formatRanges.push_back(QList<QTextLayout::FormatRange>()); 383 } 384 } else { 385 WhitespaceMode mode = m_tspans[i]->whitespaceMode(); 386 m_tspans[i]->applyStyle(p, states); 387 388 QFont font = p->font(); 389 font.setPixelSize(font.pointSizeF() * scale); 390 391 QString newText(m_tspans[i]->text()); 392 newText.replace(QLatin1Char('\t'), QLatin1Char(' ')); 393 newText.replace(QLatin1Char('\n'), QLatin1Char(' ')); 394 395 bool prependSpace = !appendSpace && !m_tspans[i]->isTspan() && (mode == Default) && !paragraphs.back().isEmpty() && newText.startsWith(QLatin1Char(' ')); 396 if (appendSpace || prependSpace) 397 paragraphs.back().append(QLatin1Char(' ')); 398 399 bool appendSpaceNext = (!m_tspans[i]->isTspan() && (mode == Default) && newText.endsWith(QLatin1Char(' '))); 400 401 if (mode == Default) { 402 newText = newText.simplified(); 403 if (newText.isEmpty()) 404 appendSpaceNext = false; 405 } 406 407 QTextLayout::FormatRange range; 408 range.start = paragraphs.back().length(); 409 range.length = newText.length(); 410 range.format.setFont(font); 411 range.format.setTextOutline(p->pen()); 412 range.format.setForeground(p->brush()); 413 414 if (appendSpace) { 415 Q_ASSERT(!formatRanges.back().isEmpty()); 416 ++formatRanges.back().back().length; 417 } else if (prependSpace) { 418 --range.start; 419 ++range.length; 420 } 421 formatRanges.back().append(range); 422 423 appendSpace = appendSpaceNext; 424 paragraphs.back() += newText; 425 426 m_tspans[i]->revertStyle(p, states); 427 } 428 } 429 430 if (states.svgFont) { 431 // SVG fonts not fully supported... 432 QString text = paragraphs.front(); 433 for (int i = 1; i < paragraphs.size(); ++i) { 434 text.append(QLatin1Char('\n')); 435 text.append(paragraphs[i]); 436 } 437 states.svgFont->draw(p, m_coord * scale, text, p->font().pointSizeF() * scale, states.textAnchor); 438 } else { 439 for (int i = 0; i < paragraphs.size(); ++i) { 440 QTextLayout tl(paragraphs[i]); 441 QTextOption op = tl.textOption(); 442 op.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); 443 tl.setTextOption(op); 444 tl.setAdditionalFormats(formatRanges[i]); 445 tl.beginLayout(); 446 447 forever { 448 QTextLine line = tl.createLine(); 449 if (!line.isValid()) 450 break; 451 if (m_size.width() != 0) 452 line.setLineWidth(scaledSize.width()); 453 } 454 tl.endLayout(); 455 456 bool endOfBoundsReached = false; 457 for (int i = 0; i < tl.lineCount(); ++i) { 458 QTextLine line = tl.lineAt(i); 459 460 qreal x = 0; 461 if (alignment == Qt::AlignHCenter) 462 x -= 0.5 * line.naturalTextWidth(); 463 else if (alignment == Qt::AlignRight) 464 x -= line.naturalTextWidth(); 465 466 if (initial && m_type == TEXT) 467 y -= line.ascent(); 468 initial = false; 469 470 line.setPosition(QPointF(x, y)); 471 472 // Check if the current line fits into the bounding rectangle. 473 if ((m_size.width() != 0 && line.naturalTextWidth() > scaledSize.width()) 474 || (m_size.height() != 0 && y + line.height() > scaledSize.height())) { 475 // I need to set the bounds height to 'y-epsilon' to avoid drawing the current 476 // line. Since the font is scaled to 100 units, 1 should be a safe epsilon. 477 bounds.setHeight(y - 1); 478 endOfBoundsReached = true; 479 break; 480 } 481 482 y += 1.1 * line.height(); 483 } 484 tl.draw(p, QPointF(px, py), QVector<QTextLayout::FormatRange>(), bounds); 485 486 if (endOfBoundsReached) 344 487 break; 345 346 if (m_size.width() != 0)347 line.setLineWidth(scaledSize.width());348 488 } 349 tl.endLayout();350 351 bool endOfBoundsReached = false;352 for (int i = 0; i < tl.lineCount(); ++i) {353 QTextLine line = tl.lineAt(i);354 355 qreal x = 0;356 if (m_textAlignment == Qt::AlignHCenter)357 x -= line.naturalTextWidth() / 2;358 else if (m_textAlignment == Qt::AlignRight)359 x -= line.naturalTextWidth();360 361 if (initial && m_type == TEXT)362 y -= line.ascent();363 initial = false;364 365 line.setPosition(QPointF(x, y));366 if ((m_size.width() != 0 && line.naturalTextWidth() > scaledSize.width())367 || (m_size.height() != 0 && y + line.height() > scaledSize.height())) {368 bounds.setHeight(y);369 endOfBoundsReached = true;370 break;371 }372 373 y += 1.1 * line.height();374 }375 tl.draw(p, QPointF(px, py), QVector<QTextLayout::FormatRange>(), bounds);376 377 if (endOfBoundsReached)378 break;379 489 } 380 490 381 491 p->setWorldTransform(oldTransform, false); 382 revertStyle(p, states); 383 } 384 385 void QSvgText::insertText(const QString &text, WhitespaceMode mode) 386 { 387 bool isTSpan = (m_formats.count() == 2); 388 QString newText(text); 389 newText.replace(QLatin1Char('\t'), QLatin1Char(' ')); 390 newText.replace(QLatin1Char('\n'), QLatin1Char(' ')); 391 392 bool prependSpace = !m_appendSpace && !isTSpan && (mode == Default) && !m_paragraphs.back().isEmpty() && newText.startsWith(QLatin1Char(' ')); 393 if (m_appendSpace || prependSpace) 394 m_paragraphs.back().append(QLatin1Char(' ')); 395 396 bool appendSpaceNext = (!isTSpan && (mode == Default) && newText.endsWith(QLatin1Char(' '))); 397 398 if (mode == Default) { 399 newText = newText.simplified(); 400 if (newText.isEmpty()) 401 appendSpaceNext = false; 402 } 403 404 if (!m_formats.isEmpty()) { 405 QTextLayout::FormatRange range; 406 range.start = m_paragraphs.back().length(); 407 range.length = newText.length(); 408 range.format = m_formats.top(); 409 if (m_appendSpace) { 410 Q_ASSERT(!m_formatRanges.back().isEmpty()); 411 ++m_formatRanges.back().back().length; 412 } else if (prependSpace) { 413 --range.start; 414 ++range.length; 415 } 416 m_formatRanges.back().append(range); 417 } 418 419 m_appendSpace = appendSpaceNext; 420 m_paragraphs.back() += newText; 421 } 422 423 void QSvgText::insertFormat(const QTextCharFormat &format) 424 { 425 QTextCharFormat mergedFormat = format; 426 if (!m_formats.isEmpty()) { 427 mergedFormat = m_formats.top(); 428 mergedFormat.merge(format); 429 } 430 m_formats.push(mergedFormat); 431 } 432 433 void QSvgText::insertLineBreak() 434 { 435 if (m_type == TEXTAREA) { 436 if (m_paragraphs.back().isEmpty()) 437 insertText(QLatin1String(" "), Preserve); 438 m_appendSpace = false; 439 m_paragraphs.push_back(QString()); 440 m_formatRanges.push_back(QList<QTextLayout::FormatRange>()); 441 } 442 } 443 444 void QSvgText::popFormat() 445 { 446 if (m_formats.count() > 1) 447 m_formats.pop(); 448 } 449 450 qreal QSvgText::scale() const 451 { 452 return m_scale; 453 } 454 455 void QSvgText::setScale(qreal scale) 456 { 457 m_scale = scale; 458 } 459 460 const QTextCharFormat &QSvgText::topFormat() const 461 { 462 return m_formats.top(); 463 } 464 465 void QSvgText::setTextAlignment(const Qt::Alignment &alignment) 466 { 467 m_textAlignment = alignment; 492 p->setOpacity(oldOpacity); 493 revertStyle(p, states); 494 } 495 496 void QSvgText::addText(const QString &text) 497 { 498 m_tspans.append(new QSvgTspan(this, false)); 499 m_tspans.back()->setWhitespaceMode(m_mode); 500 m_tspans.back()->addText(text); 468 501 } 469 502 … … 597 630 { 598 631 qreal sw = strokeWidth(); 599 if (qFuzzy Compare(sw + 1, 1))632 if (qFuzzyIsNull(sw)) 600 633 return m_poly.boundingRect(); 601 634 else { … … 609 642 { 610 643 qreal sw = strokeWidth(); 611 if (qFuzzy Compare(sw + 1, 1))644 if (qFuzzyIsNull(sw)) 612 645 return m_cachedBounds; 613 646 else { … … 624 657 { 625 658 qreal sw = strokeWidth(); 626 if (qFuzzy Compare(sw + 1, 1)) {659 if (qFuzzyIsNull(sw)) { 627 660 qreal minX = qMin(m_bounds.x1(), m_bounds.x2()); 628 661 qreal minY = qMin(m_bounds.y1(), m_bounds.y2()); -
trunk/src/svg/qsvggraphics_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 146 146 private: 147 147 QPainterPath m_path; 148 QRectF m_cachedBounds;148 mutable QRectF m_cachedBounds; 149 149 }; 150 150 … … 182 182 int m_rx, m_ry; 183 183 }; 184 185 class QSvgTspan; 184 186 185 187 class QSvgText : public QSvgNode … … 198 200 virtual void draw(QPainter *p, QSvgExtraStates &states); 199 201 virtual Type type() const; 200 void insertText(const QString &text, WhitespaceMode mode); 201 void insertFormat(const QTextCharFormat &format); 202 void insertLineBreak(); 203 void popFormat(); 204 void setTextAlignment(const Qt::Alignment &alignment); 205 const QTextCharFormat &topFormat() const; 206 qreal scale() const; 207 void setScale(qreal scale); 202 203 void addTspan(QSvgTspan *tspan) {m_tspans.append(tspan);} 204 void addText(const QString &text); 205 void addLineBreak() {m_tspans.append(LINEBREAK);} 206 void setWhitespaceMode(WhitespaceMode mode) {m_mode = mode;} 207 208 208 //virtual QRectF bounds() const; 209 209 private: 210 static QSvgTspan * const LINEBREAK; 211 210 212 QPointF m_coord; 211 213 212 QVector<QString> m_paragraphs; 213 QStack<QTextCharFormat> m_formats; 214 Qt::Alignment m_textAlignment; 215 QVector<QList<QTextLayout::FormatRange> > m_formatRanges; 216 qreal m_scale; 217 bool m_appendSpace; 214 // 'm_tspans' is also used to store characters outside tspans and line breaks. 215 // If a 'm_tspan' item is null, it indicates a line break. 216 QVector<QSvgTspan *> m_tspans; 217 218 218 Type m_type; 219 219 QSizeF m_size; 220 WhitespaceMode m_mode; 221 }; 222 223 class QSvgTspan : public QSvgNode 224 { 225 public: 226 // tspans are also used to store normal text, so the 'isProperTspan' is used to separate text from tspan. 227 QSvgTspan(QSvgNode *parent, bool isProperTspan = true) 228 : QSvgNode(parent), m_mode(QSvgText::Default), m_isTspan(isProperTspan) 229 { 230 } 231 ~QSvgTspan() { }; 232 virtual Type type() const {return TSPAN;} 233 virtual void draw(QPainter *, QSvgExtraStates &) {Q_ASSERT(!"Tspans should be drawn through QSvgText::draw().");} 234 void addText(const QString &text) {m_text += text;} 235 const QString &text() const {return m_text;} 236 bool isTspan() const {return m_isTspan;} 237 void setWhitespaceMode(QSvgText::WhitespaceMode mode) {m_mode = mode;} 238 QSvgText::WhitespaceMode whitespaceMode() const {return m_mode;} 239 private: 240 QString m_text; 241 QSvgText::WhitespaceMode m_mode; 242 bool m_isTspan; 220 243 }; 221 244 -
trunk/src/svg/qsvghandler.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** 40 40 ****************************************************************************/ 41 42 #include "qplatformdefs.h" 41 43 42 44 #include "qsvghandler_p.h" … … 63 65 #include "qmath.h" 64 66 #include "qnumeric.h" 67 #include "qvarlengtharray.h" 65 68 #include "private/qmath_p.h" 66 69 … … 69 72 QT_BEGIN_NAMESPACE 70 73 74 static const char *qt_inherit_text = "inherit"; 75 #define QT_INHERIT QLatin1String(qt_inherit_text) 76 71 77 double qstrtod(const char *s00, char const **se, bool *ok); 72 78 79 // ======== duplicated from qcolor_p 80 81 static inline int qsvg_h2i(char hex) 82 { 83 if (hex >= '0' && hex <= '9') 84 return hex - '0'; 85 if (hex >= 'a' && hex <= 'f') 86 return hex - 'a' + 10; 87 if (hex >= 'A' && hex <= 'F') 88 return hex - 'A' + 10; 89 return -1; 90 } 91 92 static inline int qsvg_hex2int(const char *s) 93 { 94 return (qsvg_h2i(s[0]) << 4) | qsvg_h2i(s[1]); 95 } 96 97 static inline int qsvg_hex2int(char s) 98 { 99 int h = qsvg_h2i(s); 100 return (h << 4) | h; 101 } 102 103 bool qsvg_get_hex_rgb(const char *name, QRgb *rgb) 104 { 105 if(name[0] != '#') 106 return false; 107 name++; 108 int len = qstrlen(name); 109 int r, g, b; 110 if (len == 12) { 111 r = qsvg_hex2int(name); 112 g = qsvg_hex2int(name + 4); 113 b = qsvg_hex2int(name + 8); 114 } else if (len == 9) { 115 r = qsvg_hex2int(name); 116 g = qsvg_hex2int(name + 3); 117 b = qsvg_hex2int(name + 6); 118 } else if (len == 6) { 119 r = qsvg_hex2int(name); 120 g = qsvg_hex2int(name + 2); 121 b = qsvg_hex2int(name + 4); 122 } else if (len == 3) { 123 r = qsvg_hex2int(name[0]); 124 g = qsvg_hex2int(name[1]); 125 b = qsvg_hex2int(name[2]); 126 } else { 127 r = g = b = -1; 128 } 129 if ((uint)r > 255 || (uint)g > 255 || (uint)b > 255) { 130 *rgb = 0; 131 return false; 132 } 133 *rgb = qRgb(r, g ,b); 134 return true; 135 } 136 137 bool qsvg_get_hex_rgb(const QChar *str, int len, QRgb *rgb) 138 { 139 if (len > 13) 140 return false; 141 char tmp[16]; 142 for(int i = 0; i < len; ++i) 143 tmp[i] = str[i].toLatin1(); 144 tmp[len] = 0; 145 return qsvg_get_hex_rgb(tmp, rgb); 146 } 147 148 // ======== end of qcolor_p duplicate 149 73 150 static bool parsePathDataFast(const QStringRef &data, QPainterPath &path); 74 75 struct QSvgAttributes76 {77 QSvgAttributes(const QXmlStreamAttributes &xmlAttributes, QSvgHandler *handler);78 79 QStringRef value(const QLatin1String &name) const;80 QStringRef value(const QString &namespaceUri, const QLatin1String &name) const;81 82 QXmlStreamAttributes m_xmlAttributes;83 QVector<QSvgCssAttribute> m_cssAttributes;84 };85 86 QSvgAttributes::QSvgAttributes(const QXmlStreamAttributes &xmlAttributes, QSvgHandler *handler)87 : m_xmlAttributes(xmlAttributes)88 {89 QStringRef style = xmlAttributes.value(QLatin1String("style"));90 if (!style.isEmpty())91 handler->parseCSStoXMLAttrs(style.toString(), &m_cssAttributes);92 }93 94 QStringRef QSvgAttributes::value(const QLatin1String &name) const95 {96 QStringRef v = m_xmlAttributes.value(name);97 if (v.isEmpty()) {98 for (int i = 0; i < m_cssAttributes.count(); ++i) {99 if (m_cssAttributes.at(i).name == name) {100 v = m_cssAttributes.at(i).value;101 break;102 }103 }104 }105 return v;106 }107 108 QStringRef QSvgAttributes::value(const QString &namespaceUri, const QLatin1String &name) const109 {110 QStringRef v = m_xmlAttributes.value(namespaceUri, name);111 if (v.isEmpty()) {112 for (int i = 0; i < m_cssAttributes.count(); ++i) {113 if (m_cssAttributes.at(i).name == name) {114 v = m_cssAttributes.at(i).value;115 break;116 }117 }118 }119 return v;120 }121 151 122 152 static inline QString someId(const QXmlStreamAttributes &attributes) … … 127 157 return id; 128 158 } 129 static inline QString someId(const QSvgAttributes &attributes) 130 { return someId(attributes.m_xmlAttributes); } 131 132 159 160 struct QSvgAttributes 161 { 162 QSvgAttributes(const QXmlStreamAttributes &xmlAttributes, QSvgHandler *handler); 163 164 QString id; 165 166 QStringRef color; 167 QStringRef colorOpacity; 168 QStringRef fill; 169 QStringRef fillRule; 170 QStringRef fillOpacity; 171 QStringRef stroke; 172 QStringRef strokeDashArray; 173 QStringRef strokeDashOffset; 174 QStringRef strokeLineCap; 175 QStringRef strokeLineJoin; 176 QStringRef strokeMiterLimit; 177 QStringRef strokeOpacity; 178 QStringRef strokeWidth; 179 QStringRef vectorEffect; 180 QStringRef fontFamily; 181 QStringRef fontSize; 182 QStringRef fontStyle; 183 QStringRef fontWeight; 184 QStringRef fontVariant; 185 QStringRef textAnchor; 186 QStringRef transform; 187 QStringRef visibility; 188 QStringRef opacity; 189 QStringRef compOp; 190 QStringRef display; 191 QStringRef offset; 192 QStringRef stopColor; 193 QStringRef stopOpacity; 194 195 QVector<QSvgCssAttribute> m_cssAttributes; 196 }; 197 198 QSvgAttributes::QSvgAttributes(const QXmlStreamAttributes &xmlAttributes, QSvgHandler *handler) 199 { 200 QStringRef style = xmlAttributes.value(QLatin1String("style")); 201 if (!style.isEmpty()) { 202 handler->parseCSStoXMLAttrs(style.toString(), &m_cssAttributes); 203 for (int j = 0; j < m_cssAttributes.count(); ++j) { 204 const QSvgCssAttribute &attribute = m_cssAttributes.at(j); 205 QStringRef name = attribute.name; 206 QStringRef value = attribute.value; 207 if (name.isEmpty()) 208 continue; 209 210 switch (name.at(0).unicode()) { 211 212 case 'c': 213 if (name == QLatin1String("color")) 214 color = value; 215 else if (name == QLatin1String("color-opacity")) 216 colorOpacity = value; 217 else if (name == QLatin1String("comp-op")) 218 compOp = value; 219 break; 220 221 case 'd': 222 if (name == QLatin1String("display")) 223 display = value; 224 break; 225 226 case 'f': 227 if (name == QLatin1String("fill")) 228 fill = value; 229 else if (name == QLatin1String("fill-rule")) 230 fillRule = value; 231 else if (name == QLatin1String("fill-opacity")) 232 fillOpacity = value; 233 else if (name == QLatin1String("font-family")) 234 fontFamily = value; 235 else if (name == QLatin1String("font-size")) 236 fontSize = value; 237 else if (name == QLatin1String("font-style")) 238 fontStyle = value; 239 else if (name == QLatin1String("font-weight")) 240 fontWeight = value; 241 else if (name == QLatin1String("font-variant")) 242 fontVariant = value; 243 break; 244 245 case 'o': 246 if (name == QLatin1String("opacity")) 247 opacity = value; 248 else if (name == QLatin1String("offset")) 249 offset = value; 250 break; 251 252 case 's': 253 if (name.length() > 5 && QStringRef(name.string(), name.position() + 1, 5) == QLatin1String("troke")) { 254 QStringRef strokeRef(name.string(), name.position() + 6, name.length() - 6); 255 if (strokeRef.isEmpty()) 256 stroke = value; 257 else if (strokeRef == QLatin1String("-dasharray")) 258 strokeDashArray = value; 259 else if (strokeRef == QLatin1String("-dashoffset")) 260 strokeDashOffset = value; 261 else if (strokeRef == QLatin1String("-linecap")) 262 strokeLineCap = value; 263 else if (strokeRef == QLatin1String("-linejoin")) 264 strokeLineJoin = value; 265 else if (strokeRef == QLatin1String("-miterlimit")) 266 strokeMiterLimit = value; 267 else if (strokeRef == QLatin1String("-opacity")) 268 strokeOpacity = value; 269 else if (strokeRef == QLatin1String("-width")) 270 strokeWidth = value; 271 } 272 else if (name == QLatin1String("stop-color")) 273 stopColor = value; 274 else if (name == QLatin1String("stop-opacity")) 275 stopOpacity = value; 276 break; 277 278 case 't': 279 if (name == QLatin1String("text-anchor")) 280 textAnchor = value; 281 else if (name == QLatin1String("transform")) 282 transform = value; 283 break; 284 285 case 'v': 286 if (name == QLatin1String("vector-effect")) 287 vectorEffect = value; 288 else if (name == QLatin1String("visibility")) 289 visibility = value; 290 break; 291 292 default: 293 break; 294 } 295 } 296 } 297 298 for (int i = 0; i < xmlAttributes.count(); ++i) { 299 const QXmlStreamAttribute &attribute = xmlAttributes.at(i); 300 QStringRef name = attribute.qualifiedName(); 301 if (name.isEmpty()) 302 continue; 303 QStringRef value = attribute.value(); 304 305 switch (name.at(0).unicode()) { 306 307 case 'c': 308 if (name == QLatin1String("color")) 309 color = value; 310 else if (name == QLatin1String("color-opacity")) 311 colorOpacity = value; 312 else if (name == QLatin1String("comp-op")) 313 compOp = value; 314 break; 315 316 case 'd': 317 if (name == QLatin1String("display")) 318 display = value; 319 break; 320 321 case 'f': 322 if (name == QLatin1String("fill")) 323 fill = value; 324 else if (name == QLatin1String("fill-rule")) 325 fillRule = value; 326 else if (name == QLatin1String("fill-opacity")) 327 fillOpacity = value; 328 else if (name == QLatin1String("font-family")) 329 fontFamily = value; 330 else if (name == QLatin1String("font-size")) 331 fontSize = value; 332 else if (name == QLatin1String("font-style")) 333 fontStyle = value; 334 else if (name == QLatin1String("font-weight")) 335 fontWeight = value; 336 else if (name == QLatin1String("font-variant")) 337 fontVariant = value; 338 break; 339 340 case 'i': 341 if (name == QLatin1String("id")) 342 id = value.toString(); 343 break; 344 345 case 'o': 346 if (name == QLatin1String("opacity")) 347 opacity = value; 348 if (name == QLatin1String("offset")) 349 offset = value; 350 break; 351 352 case 's': 353 if (name.length() > 5 && QStringRef(name.string(), name.position() + 1, 5) == QLatin1String("troke")) { 354 QStringRef strokeRef(name.string(), name.position() + 6, name.length() - 6); 355 if (strokeRef.isEmpty()) 356 stroke = value; 357 else if (strokeRef == QLatin1String("-dasharray")) 358 strokeDashArray = value; 359 else if (strokeRef == QLatin1String("-dashoffset")) 360 strokeDashOffset = value; 361 else if (strokeRef == QLatin1String("-linecap")) 362 strokeLineCap = value; 363 else if (strokeRef == QLatin1String("-linejoin")) 364 strokeLineJoin = value; 365 else if (strokeRef == QLatin1String("-miterlimit")) 366 strokeMiterLimit = value; 367 else if (strokeRef == QLatin1String("-opacity")) 368 strokeOpacity = value; 369 else if (strokeRef == QLatin1String("-width")) 370 strokeWidth = value; 371 } 372 else if (name == QLatin1String("stop-color")) 373 stopColor = value; 374 else if (name == QLatin1String("stop-opacity")) 375 stopOpacity = value; 376 break; 377 378 case 't': 379 if (name == QLatin1String("text-anchor")) 380 textAnchor = value; 381 else if (name == QLatin1String("transform")) 382 transform = value; 383 break; 384 385 case 'v': 386 if (name == QLatin1String("vector-effect")) 387 vectorEffect = value; 388 else if (name == QLatin1String("visibility")) 389 visibility = value; 390 break; 391 392 case 'x': 393 if (name == QLatin1String("xml:id") && id.isEmpty()) 394 id = value.toString(); 395 break; 396 397 default: 398 break; 399 } 400 } 401 402 } 133 403 134 404 static const char * QSvgStyleSelector_nodeString[] = { … … 283 553 }; 284 554 555 // '0' is 0x30 and '9' is 0x39 556 static inline bool isDigit(ushort ch) 557 { 558 static quint16 magic = 0x3ff; 559 return ((ch >> 4) == 3) && (magic >> (ch & 15)); 560 } 561 285 562 static qreal toDouble(const QChar *&str) 286 563 { … … 295 572 ++str; 296 573 } 297 while ( *str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {574 while (isDigit(str->unicode()) && pos < maxLen) { 298 575 temp[pos++] = str->toLatin1(); 299 576 ++str; … … 303 580 ++str; 304 581 } 305 while ( *str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {582 while (isDigit(str->unicode()) && pos < maxLen) { 306 583 temp[pos++] = str->toLatin1(); 307 584 ++str; … … 316 593 ++str; 317 594 } 318 while ( *str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {595 while (isDigit(str->unicode()) && pos < maxLen) { 319 596 temp[pos++] = str->toLatin1(); 320 597 ++str; 321 598 } 322 599 } 600 323 601 temp[pos] = '\0'; 324 602 … … 353 631 val = -val; 354 632 } else { 355 #if def Q_WS_QWS633 #if defined(Q_WS_QWS) && !defined(Q_OS_VXWORKS) 356 634 if(sizeof(qreal) == sizeof(float)) 357 635 val = strtof(temp, 0); … … 366 644 367 645 } 368 static qreal toDouble(const QString &str )646 static qreal toDouble(const QString &str, bool *ok = NULL) 369 647 { 370 648 const QChar *c = str.constData(); 371 return toDouble(c); 372 } 373 374 static qreal toDouble(const QStringRef &str) 649 qreal res = toDouble(c); 650 if (ok) { 651 *ok = ((*c) == QLatin1Char('\0')); 652 } 653 return res; 654 } 655 656 static qreal toDouble(const QStringRef &str, bool *ok = NULL) 375 657 { 376 658 const QChar *c = str.constData(); 377 return toDouble(c); 659 qreal res = toDouble(c); 660 if (ok) { 661 *ok = (c == (str.constData() + str.length())); 662 } 663 return res; 378 664 } 379 665 … … 385 671 points.reserve(32); 386 672 387 while ( *str == QLatin1Char(' '))673 while (str->isSpace()) 388 674 ++str; 389 while ( (*str >= QLatin1Char('0') && *str <= QLatin1Char('9')) ||675 while (isDigit(str->unicode()) || 390 676 *str == QLatin1Char('-') || *str == QLatin1Char('+') || 391 677 *str == QLatin1Char('.')) { … … 393 679 points.append(toDouble(str)); 394 680 395 while ( *str == QLatin1Char(' '))681 while (str->isSpace()) 396 682 ++str; 397 683 if (*str == QLatin1Char(',')) … … 399 685 400 686 //eat the rest of space 401 while ( *str == QLatin1Char(' '))687 while (str->isSpace()) 402 688 ++str; 403 689 } 404 690 405 691 return points; 692 } 693 694 static inline void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points) 695 { 696 while (str->isSpace()) 697 ++str; 698 while (isDigit(str->unicode()) || 699 *str == QLatin1Char('-') || *str == QLatin1Char('+') || 700 *str == QLatin1Char('.')) { 701 702 points.append(toDouble(str)); 703 704 while (str->isSpace()) 705 ++str; 706 if (*str == QLatin1Char(',')) 707 ++str; 708 709 //eat the rest of space 710 while (str->isSpace()) 711 ++str; 712 } 406 713 } 407 714 … … 420 727 points.append(toDouble(str)); 421 728 422 while ( *str == QLatin1Char(' '))729 while (str->isSpace()) 423 730 ++str; 424 731 if (*str == QLatin1Char('%')) 425 732 ++str; 426 while ( *str == QLatin1Char(' '))733 while (str->isSpace()) 427 734 ++str; 428 735 if (*str == QLatin1Char(',')) … … 430 737 431 738 //eat the rest of space 432 while ( *str == QLatin1Char(' '))739 while (str->isSpace()) 433 740 ++str; 434 741 } … … 456 763 } 457 764 765 static inline QStringRef trimRef(const QStringRef &str) 766 { 767 if (str.isEmpty()) 768 return QStringRef(); 769 const QChar *s = str.string()->constData() + str.position(); 770 int end = str.length() - 1; 771 if (!s[0].isSpace() && !s[end].isSpace()) 772 return str; 773 774 int start = 0; 775 while (start<=end && s[start].isSpace()) // skip white space from start 776 start++; 777 if (start <= end) { // only white space 778 while (s[end].isSpace()) // skip white space from end 779 end--; 780 } 781 int l = end - start + 1; 782 if (l <= 0) 783 return QStringRef(); 784 return QStringRef(str.string(), str.position() + start, l); 785 } 786 458 787 /** 459 788 * returns true when successfuly set the color. false signifies 460 789 * that the color should be inherited 461 790 */ 462 static bool resolveColor(const QString &colorStr, QColor &color, QSvgHandler *handler) 463 { 464 QString colorStrTr = colorStr.trimmed(); 465 if (colorStr.startsWith(QLatin1String("rgb("))) { 466 const QChar *s = colorStr.constData() + 4; 467 QVector<qreal> compo = parseNumbersList(s); 468 //1 means that it failed after reaching non-parsable 469 //character which is going to be "%" 470 if (compo.size() == 1) { 471 const QChar *s = colorStr.constData() + 4; 472 compo = parsePercentageList(s); 473 compo[0] *= (qreal)2.55; 474 compo[1] *= (qreal)2.55; 475 compo[2] *= (qreal)2.55; 476 } 477 478 color = QColor(int(compo[0]), 479 int(compo[1]), 480 int(compo[2])); 481 return true; 482 } else if (colorStr == QLatin1String("inherited") || 483 colorStr == QLatin1String("inherit")) { 791 static bool resolveColor(const QStringRef &colorStr, QColor &color, QSvgHandler *handler) 792 { 793 QStringRef colorStrTr = trimRef(colorStr); 794 if (colorStrTr.isEmpty()) 484 795 return false; 485 } else if (colorStr == QLatin1String("currentColor")) { 486 color = handler->currentColor(); 487 return true; 488 } 489 490 color = QColor(colorStrTr); 796 797 switch(colorStrTr.at(0).unicode()) { 798 799 case '#': 800 { 801 // #rrggbb is very very common, so let's tackle it here 802 // rather than falling back to QColor 803 QRgb rgb; 804 bool ok = qsvg_get_hex_rgb(colorStrTr.unicode(), colorStrTr.length(), &rgb); 805 if (ok) 806 color.setRgb(rgb); 807 return ok; 808 } 809 break; 810 811 case 'r': 812 { 813 // starts with "rgb(", ends with ")" and consists of at least 7 characters "rgb(,,)" 814 if (colorStrTr.length() >= 7 && colorStrTr.at(colorStrTr.length() - 1) == QLatin1Char(')') 815 && QStringRef(colorStrTr.string(), colorStrTr.position(), 4) == QLatin1String("rgb(")) { 816 const QChar *s = colorStrTr.constData() + 4; 817 QVector<qreal> compo = parseNumbersList(s); 818 //1 means that it failed after reaching non-parsable 819 //character which is going to be "%" 820 if (compo.size() == 1) { 821 s = colorStrTr.constData() + 4; 822 compo = parsePercentageList(s); 823 for (int i = 0; i < compo.size(); ++i) 824 compo[i] *= (qreal)2.55; 825 } 826 827 if (compo.size() == 3) { 828 color = QColor(int(compo[0]), 829 int(compo[1]), 830 int(compo[2])); 831 return true; 832 } 833 return false; 834 } 835 } 836 break; 837 838 case 'c': 839 if (colorStrTr == QLatin1String("currentColor")) { 840 color = handler->currentColor(); 841 return true; 842 } 843 break; 844 case 'i': 845 if (colorStrTr == QT_INHERIT) 846 return false; 847 break; 848 default: 849 break; 850 } 851 852 color = QColor(colorStrTr.toString()); 491 853 return color.isValid(); 492 854 } 493 855 494 static bool constructColor(const QString &colorStr, const QString&opacity,856 static bool constructColor(const QStringRef &colorStr, const QStringRef &opacity, 495 857 QColor &color, QSvgHandler *handler) 496 858 { … … 498 860 return false; 499 861 if (!opacity.isEmpty()) { 500 qreal op = toDouble(opacity); 501 if (op <= 1) 502 op *= 255; 503 color.setAlpha(int(op)); 862 bool ok = true; 863 qreal op = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity, &ok))); 864 if (!ok) 865 op = 1.0; 866 color.setAlphaF(op); 504 867 } 505 868 return true; … … 507 870 508 871 static qreal parseLength(const QString &str, QSvgHandler::LengthType &type, 509 QSvgHandler *handler )872 QSvgHandler *handler, bool *ok = NULL) 510 873 { 511 874 QString numStr = str.trimmed(); … … 536 899 //type = QSvgHandler::LT_OTHER; 537 900 } 538 qreal len = toDouble(numStr );901 qreal len = toDouble(numStr, ok); 539 902 //qDebug()<<"len is "<<len<<", from '"<<numStr << "'"; 540 903 return len; 541 904 } 542 905 543 static inline qreal convertToNumber(const QString &str, QSvgHandler *handler )906 static inline qreal convertToNumber(const QString &str, QSvgHandler *handler, bool *ok = NULL) 544 907 { 545 908 QSvgHandler::LengthType type; 546 qreal num = parseLength(str, type, handler );909 qreal num = parseLength(str, type, handler, ok); 547 910 if (type == QSvgHandler::LT_PERCENT) { 548 911 num = num/100.0; … … 604 967 QSvgHandler *handler) 605 968 { 606 QString colorStr = attributes.value(QLatin1String("color")).toString();607 QString opacity = attributes.value(QLatin1String("color-opacity")).toString();608 969 QColor color; 609 if (constructColor(colorStr, opacity, color, handler)) { 970 if (constructColor(attributes.color, attributes.colorOpacity, color, handler)) { 971 handler->popColor(); 610 972 handler->pushColor(color); 611 973 } … … 614 976 static QSvgStyleProperty *styleFromUrl(QSvgNode *node, const QString &url) 615 977 { 616 while (node && (node->type() != QSvgNode::DOC && 617 node->type() != QSvgNode::G && 618 node->type() != QSvgNode::DEFS && 619 node->type() != QSvgNode::SWITCH)) { 620 node = node->parent(); 621 } 622 if (!node) 623 return 0; 624 return static_cast<QSvgStructureNode*>(node)->scopeStyle(idFromUrl(url)); 978 return node ? node->styleProperty(idFromUrl(url)) : 0; 625 979 } 626 980 … … 629 983 QSvgHandler *handler) 630 984 { 631 QString value = attributes.value(QLatin1String("fill")).toString(); 632 QString fillRule = attributes.value(QLatin1String("fill-rule")).toString(); 633 QString opacity = attributes.value(QLatin1String("fill-opacity")).toString(); 634 QString myId = someId(attributes); 635 636 value = value.trimmed(); 637 fillRule = fillRule.trimmed(); 638 if (!value.isEmpty() || !fillRule.isEmpty()) { 639 Qt::FillRule f = Qt::WindingFill; 640 if (fillRule == QLatin1String("evenodd")) 641 f = Qt::OddEvenFill; 642 if (value.startsWith(QLatin1String("url"))) { 643 value = value.remove(0, 3); 644 QSvgStyleProperty *style = styleFromUrl(node, value); 645 if (style) { 646 QSvgFillStyle *prop = new QSvgFillStyle(style); 647 if (!opacity.isEmpty()) 648 prop->setFillOpacity(toDouble(opacity)); 649 node->appendStyleProperty(prop, myId); 985 if (!attributes.fill.isEmpty() || !attributes.fillRule.isEmpty() || !attributes.fillOpacity.isEmpty()) { 986 QSvgFillStyle *prop = new QSvgFillStyle; 987 988 //fill-rule attribute handling 989 if (!attributes.fillRule.isEmpty() && attributes.fillRule != QT_INHERIT) { 990 if (attributes.fillRule == QLatin1String("evenodd")) 991 prop->setFillRule(Qt::OddEvenFill); 992 else if (attributes.fillRule == QLatin1String("nonzero")) 993 prop->setFillRule(Qt::WindingFill); 994 } 995 996 //fill-opacity atttribute handling 997 if (!attributes.fillOpacity.isEmpty() && attributes.fillOpacity != QT_INHERIT) { 998 prop->setFillOpacity(qMin(qreal(1.0), qMax(qreal(0.0), toDouble(attributes.fillOpacity)))); 999 } 1000 1001 //fill attribute handling 1002 if ((!attributes.fill.isEmpty()) && (attributes.fill != QT_INHERIT) ) { 1003 if (attributes.fill.length() > 3 && 1004 QStringRef(attributes.fill.string(), attributes.fill.position(), 3) == QLatin1String("url")) { 1005 QStringRef urlRef(attributes.fill.string(), attributes.fill.position() + 3, attributes.fill.length() - 3); 1006 QString value = urlRef.toString(); 1007 QSvgStyleProperty *style = styleFromUrl(node, value); 1008 if (style) { 1009 if (style->type() == QSvgStyleProperty::SOLID_COLOR || style->type() == QSvgStyleProperty::GRADIENT) 1010 prop->setFillStyle(reinterpret_cast<QSvgFillStyleProperty *>(style)); 1011 } else { 1012 QString id = idFromUrl(value); 1013 prop->setGradientId(id); 1014 prop->setGradientResolved(false); 1015 } 1016 } else if (attributes.fill != QLatin1String("none")) { 1017 QColor color; 1018 if (resolveColor(attributes.fill, color, handler)) 1019 prop->setBrush(QBrush(color)); 650 1020 } else { 651 qWarning("Couldn't resolve property: %s", qPrintable(idFromUrl(value))); 652 } 653 } else if (value != QLatin1String("none")) { 654 QColor color; 655 if (constructColor(value, opacity, color, handler)) { 656 QSvgFillStyle *prop = new QSvgFillStyle(QBrush(color)); 657 if (!fillRule.isEmpty()) 658 prop->setFillRule(f); 659 node->appendStyleProperty(prop, myId); 660 } 661 } else { 662 QSvgFillStyle *prop = new QSvgFillStyle(QBrush(Qt::NoBrush)); 663 if (!fillRule.isEmpty()) 664 prop->setFillRule(f); 665 node->appendStyleProperty(prop, myId); 666 } 667 } 668 } 669 670 static void parseQPen(QPen &pen, QSvgNode *node, 671 const QSvgAttributes &attributes, 672 QSvgHandler *handler) 673 { 674 QString value = attributes.value(QLatin1String("stroke")).toString(); 675 QString dashArray = attributes.value(QLatin1String("stroke-dasharray")).toString(); 676 QString dashOffset = attributes.value(QLatin1String("stroke-dashoffset")).toString(); 677 QString linecap = attributes.value(QLatin1String("stroke-linecap")).toString(); 678 QString linejoin = attributes.value(QLatin1String("stroke-linejoin")).toString(); 679 QString miterlimit = attributes.value(QLatin1String("stroke-miterlimit")).toString(); 680 QString opacity = attributes.value(QLatin1String("stroke-opacity")).toString(); 681 QString width = attributes.value(QLatin1String("stroke-width")).toString(); 682 QString myId = someId(attributes); 683 684 if (!value.isEmpty() || !width.isEmpty()) { 685 if (value != QLatin1String("none")) { 686 if (!value.isEmpty()) { 687 if (node && value.startsWith(QLatin1String("url"))) { 688 value = value.remove(0, 3); 689 QSvgStyleProperty *style = styleFromUrl(node, value); 690 if (style) { 691 if (style->type() == QSvgStyleProperty::GRADIENT) { 692 QBrush b(*((QSvgGradientStyle*)style)->qgradient()); 693 pen.setBrush(b); 694 } else if (style->type() == QSvgStyleProperty::SOLID_COLOR) { 695 pen.setColor( 696 ((QSvgSolidColorStyle*)style)->qcolor()); 697 } 698 } else { 699 qWarning()<<"QSvgHandler::parsePen could not resolve property" << idFromUrl(value); 700 } 701 } else { 702 QColor color; 703 if (constructColor(value, opacity, color, handler)) 704 pen.setColor(color); 705 } 706 //since we could inherit stroke="none" 707 //we need to reset the style of our stroke to something 708 pen.setStyle(Qt::SolidLine); 709 } 710 if (!width.isEmpty()) { 711 QSvgHandler::LengthType lt; 712 qreal widthF = parseLength(width, lt, handler); 713 //### fixme 714 if (!widthF) { 715 pen.setStyle(Qt::NoPen); 716 return; 717 } 718 pen.setWidthF(widthF); 719 } 720 qreal penw = pen.widthF(); 721 722 if (!linejoin.isEmpty()) { 723 if (linejoin == QLatin1String("miter")) 724 pen.setJoinStyle(Qt::SvgMiterJoin); 725 else if (linejoin == QLatin1String("round")) 726 pen.setJoinStyle(Qt::RoundJoin); 727 else if (linejoin == QLatin1String("bevel")) 728 pen.setJoinStyle(Qt::BevelJoin); 729 } 730 if (!miterlimit.isEmpty()) 731 pen.setMiterLimit(toDouble(miterlimit)); 732 733 if (!linecap.isEmpty()) { 734 if (linecap == QLatin1String("butt")) 735 pen.setCapStyle(Qt::FlatCap); 736 else if (linecap == QLatin1String("round")) 737 pen.setCapStyle(Qt::RoundCap); 738 else if (linecap == QLatin1String("square")) 739 pen.setCapStyle(Qt::SquareCap); 740 } 741 742 if (!dashArray.isEmpty()) { 743 const QChar *s = dashArray.constData(); 744 QVector<qreal> dashes = parseNumbersList(s); 745 qreal *d = dashes.data(); 746 if (penw != 0) 747 for (int i = 0; i < dashes.size(); ++i) { 748 *d /= penw; 749 ++d; 750 } 751 pen.setDashPattern(dashes); 752 } 753 if (!dashOffset.isEmpty()) { 754 pen.setDashOffset(toDouble(dashOffset)); 755 } 756 757 } else { 758 pen.setStyle(Qt::NoPen); 759 } 760 } 761 } 762 763 static QMatrix parseTransformationMatrix(const QString &value) 764 { 1021 prop->setBrush(QBrush(Qt::NoBrush)); 1022 } 1023 } 1024 node->appendStyleProperty(prop, attributes.id); 1025 } 1026 } 1027 1028 1029 1030 static QMatrix parseTransformationMatrix(const QStringRef &value) 1031 { 1032 if (value.isEmpty()) 1033 return QMatrix(); 1034 765 1035 QMatrix matrix; 766 1036 const QChar *str = value.constData(); 767 768 while (*str != QLatin1Char(0)) { 1037 const QChar *end = str + value.length(); 1038 1039 while (str < end) { 769 1040 if (str->isSpace() || *str == QLatin1Char(',')) { 770 1041 ++str; … … 831 1102 832 1103 833 while (str ->isSpace())1104 while (str < end && str->isSpace()) 834 1105 ++str; 835 1106 if (*str != QLatin1Char('(')) 836 1107 goto error; 837 1108 ++str; 838 QVector<qreal> points = parseNumbersList(str); 1109 QVarLengthArray<qreal, 8> points; 1110 parseNumbersArray(str, points); 839 1111 if (*str != QLatin1Char(')')) 840 1112 goto error; … … 876 1148 goto error; 877 1149 const qreal deg2rad = qreal(0.017453292519943295769); 878 matrix.shear( tan(points[0]*deg2rad), 0);1150 matrix.shear(qTan(points[0]*deg2rad), 0); 879 1151 } else if (state == SkewY) { 880 1152 if (points.count() != 1) 881 1153 goto error; 882 1154 const qreal deg2rad = qreal(0.017453292519943295769); 883 matrix.shear(0, tan(points[0]*deg2rad));1155 matrix.shear(0, qTan(points[0]*deg2rad)); 884 1156 } 885 1157 } … … 892 1164 QSvgHandler *handler) 893 1165 { 894 QString value = attributes.value(QLatin1String("stroke")).toString();895 QString dashArray = attributes.value(QLatin1String("stroke-dasharray")).toString();896 QString dashOffset = attributes.value(QLatin1String("stroke-dashoffset")).toString();897 QString linecap = attributes.value(QLatin1String("stroke-linecap")).toString();898 QString linejoin = attributes.value(QLatin1String("stroke-linejoin")).toString();899 QString miterlimit = attributes.value(QLatin1String("stroke-miterlimit")).toString();900 QString opacity = attributes.value(QLatin1String("stroke-opacity")).toString();901 QString width = attributes.value(QLatin1String("stroke-width")).toString();902 QString myId = someId(attributes);903 904 1166 //qDebug()<<"Node "<<node->type()<<", attrs are "<<value<<width; 905 1167 906 if (!value.isEmpty() || !width.isEmpty() || !linecap.isEmpty() || !linejoin.isEmpty()) { 907 if (value != QLatin1String("none")) { 908 QSvgStrokeStyle *inherited = 909 static_cast<QSvgStrokeStyle*>(node->styleProperty( 910 QSvgStyleProperty::STROKE)); 911 if (!inherited) 912 inherited = static_cast<QSvgStrokeStyle*>(node->parent()->styleProperty( 913 QSvgStyleProperty::STROKE)); 914 QPen pen(handler->defaultPen()); 915 if (inherited) 916 pen = inherited->qpen(); 917 918 if (!value.isEmpty()) { 919 if (value.startsWith(QLatin1String("url"))) { 920 value = value.remove(0, 3); 1168 if (!attributes.stroke.isEmpty() || !attributes.strokeDashArray.isEmpty() || !attributes.strokeDashOffset.isEmpty() || !attributes.strokeLineCap.isEmpty() 1169 || !attributes.strokeLineJoin.isEmpty() || !attributes.strokeMiterLimit.isEmpty() || !attributes.strokeOpacity.isEmpty() || !attributes.strokeWidth.isEmpty() 1170 || !attributes.vectorEffect.isEmpty()) { 1171 1172 QSvgStrokeStyle *prop = new QSvgStrokeStyle; 1173 1174 //stroke attribute handling 1175 if ((!attributes.stroke.isEmpty()) && (attributes.stroke != QT_INHERIT) ) { 1176 if (attributes.stroke.length() > 3 && 1177 QStringRef(attributes.stroke.string(), attributes.stroke.position(), 3) == QLatin1String("url")) { 1178 QStringRef urlRef(attributes.stroke.string(), attributes.stroke.position() + 3, attributes.stroke.length() - 3); 1179 QString value = urlRef.toString(); 921 1180 QSvgStyleProperty *style = styleFromUrl(node, value); 922 1181 if (style) { 923 if (style->type() == QSvgStyleProperty::GRADIENT) { 924 QBrush b(*((QSvgGradientStyle*)style)->qgradient()); 925 pen.setBrush(b); 926 } else if (style->type() == QSvgStyleProperty::SOLID_COLOR) { 927 pen.setColor( 928 ((QSvgSolidColorStyle*)style)->qcolor()); 929 } 1182 if (style->type() == QSvgStyleProperty::SOLID_COLOR || style->type() == QSvgStyleProperty::GRADIENT) 1183 prop->setStyle(reinterpret_cast<QSvgFillStyleProperty *>(style)); 930 1184 } else { 931 qWarning() << "QSvgHandler::parsePen could not resolve property" << idFromUrl(value); 1185 QString id = idFromUrl(value); 1186 prop->setGradientId(id); 1187 prop->setGradientResolved(false); 932 1188 } 933 } else { 934 QColor color; 935 if (constructColor(value, opacity, color, handler)) 936 pen.setColor(color); 937 } 938 //since we could inherit stroke="none" 939 //we need to reset the style of our stroke to something 940 pen.setStyle(Qt::SolidLine); 941 } 942 if (!width.isEmpty()) { 943 QSvgHandler::LengthType lt; 944 qreal widthF = parseLength(width, lt, handler); 945 //### fixme 946 if (!widthF) { 947 pen.setStyle(Qt::NoPen); 948 return; 949 } 950 pen.setWidthF(widthF); 951 } 952 953 if (!linejoin.isEmpty()) { 954 if (linejoin == QLatin1String("miter")) 955 pen.setJoinStyle(Qt::SvgMiterJoin); 956 else if (linejoin == QLatin1String("round")) 957 pen.setJoinStyle(Qt::RoundJoin); 958 else if (linejoin == QLatin1String("bevel")) 959 pen.setJoinStyle(Qt::BevelJoin); 960 } 961 962 if (!linecap.isEmpty()) { 963 if (linecap == QLatin1String("butt")) 964 pen.setCapStyle(Qt::FlatCap); 965 else if (linecap == QLatin1String("round")) 966 pen.setCapStyle(Qt::RoundCap); 967 else if (linecap == QLatin1String("square")) 968 pen.setCapStyle(Qt::SquareCap); 969 } 970 971 qreal penw = pen.widthF(); 972 if (!dashArray.isEmpty()) { 1189 } else if (attributes.stroke != QLatin1String("none")) { 1190 QColor color; 1191 if (resolveColor(attributes.stroke, color, handler)) 1192 prop->setStroke(QBrush(color)); 1193 } else { 1194 prop->setStroke(QBrush(Qt::NoBrush)); 1195 } 1196 } 1197 1198 //stroke-width handling 1199 if (!attributes.strokeWidth.isEmpty() && attributes.strokeWidth != QT_INHERIT) { 1200 QSvgHandler::LengthType lt; 1201 prop->setWidth(parseLength(attributes.strokeWidth.toString(), lt, handler)); 1202 } 1203 1204 //stroke-dasharray 1205 if (!attributes.strokeDashArray.isEmpty() && attributes.strokeDashArray != QT_INHERIT) { 1206 if (attributes.strokeDashArray == QLatin1String("none")) { 1207 prop->setDashArrayNone(); 1208 } else { 1209 QString dashArray = attributes.strokeDashArray.toString(); 973 1210 const QChar *s = dashArray.constData(); 974 1211 QVector<qreal> dashes = parseNumbersList(s); 975 qreal *d = dashes.data();976 if(penw != 0)977 for (int i = 0; i < dashes.size(); ++i) {978 *d /= penw;979 ++d;980 }981 982 1212 // if the dash count is odd the dashes should be duplicated 983 if ( dashes.size() % 2!= 0)1213 if ((dashes.size() & 1) != 0) 984 1214 dashes << QVector<qreal>(dashes); 985 986 pen.setDashPattern(dashes); 987 } 988 if (!dashOffset.isEmpty()) { 989 qreal doffset = toDouble(dashOffset); 990 if (penw != 0) 991 doffset /= penw; 992 pen.setDashOffset(doffset); 993 } 994 if (!miterlimit.isEmpty()) 995 pen.setMiterLimit(toDouble(miterlimit)); 996 997 node->appendStyleProperty(new QSvgStrokeStyle(pen), myId); 998 } else { 999 QPen pen(handler->defaultPen()); 1000 pen.setStyle(Qt::NoPen); 1001 node->appendStyleProperty(new QSvgStrokeStyle(pen), myId); 1002 } 1003 } 1004 } 1005 1006 1007 static bool parseQBrush(const QSvgAttributes &attributes, QSvgNode *node, 1008 QBrush &brush, QSvgHandler *handler) 1009 { 1010 QString value = attributes.value(QLatin1String("fill")).toString(); 1011 QString opacity = attributes.value(QLatin1String("fill-opacity")).toString(); 1012 1013 QColor color; 1014 if (!value.isEmpty() || !opacity.isEmpty()) { 1015 if (value.startsWith(QLatin1String("url"))) { 1016 value = value.remove(0, 3); 1017 QSvgStyleProperty *style = styleFromUrl(node, value); 1018 if (style) { 1019 switch (style->type()) { 1020 case QSvgStyleProperty::FILL: 1021 { 1022 brush = static_cast<QSvgFillStyle*>(style)->qbrush(); 1023 break; 1024 } 1025 case QSvgStyleProperty::SOLID_COLOR: 1026 { 1027 brush = QBrush(static_cast<QSvgSolidColorStyle*>(style)->qcolor()); 1028 break; 1029 } 1030 case QSvgStyleProperty::GRADIENT: 1031 { 1032 brush = QBrush(*static_cast<QSvgGradientStyle*>(style)->qgradient()); 1033 break; 1034 } 1035 default: 1036 qWarning("Cannot use property \"%s\" as brush.", qPrintable(idFromUrl(value))); 1037 } 1038 } else { 1039 qWarning("Couldn't resolve property: %s", qPrintable(idFromUrl(value))); 1040 } 1041 } else if (value != QLatin1String("none")) { 1042 if (constructColor(value, opacity, color, handler)) { 1043 brush.setStyle(Qt::SolidPattern); 1044 brush.setColor(color); 1045 } 1046 } else { 1047 brush = QBrush(Qt::NoBrush); 1048 } 1049 return true; 1050 } 1051 return false; 1052 } 1053 1054 static bool parseQFont(const QSvgAttributes &attributes, 1055 QFont &font, qreal &fontSize, QSvgHandler *handler) 1056 { 1057 QString family = attributes.value(QLatin1String("font-family")).toString(); 1058 QString size = attributes.value(QLatin1String("font-size")).toString(); 1059 QString style = attributes.value(QLatin1String("font-style")).toString(); 1060 QString weight = attributes.value(QLatin1String("font-weight")).toString(); 1061 1062 if (!family.isEmpty() || !size.isEmpty() || 1063 !style.isEmpty() || !weight.isEmpty()) { 1064 1065 if (!family.isEmpty()) { 1066 font.setFamily(family.trimmed()); 1067 } 1068 if (!size.isEmpty()) { 1069 QSvgHandler::LengthType dummy; // should always be pixel size 1070 fontSize = parseLength(size, dummy, handler); 1071 if (fontSize <= 0) 1072 fontSize = 1; 1073 font.setPixelSize(qMax(1, int(fontSize))); 1074 } 1075 if (!style.isEmpty()) { 1076 if (style == QLatin1String("normal")) { 1077 font.setStyle(QFont::StyleNormal); 1078 } else if (style == QLatin1String("italic")) { 1079 font.setStyle(QFont::StyleItalic); 1080 } else if (style == QLatin1String("oblique")) { 1081 font.setStyle(QFont::StyleOblique); 1082 } else if (style == QLatin1String("inherit")) { 1083 //inherited already 1084 } 1085 } 1086 if (!weight.isEmpty()) { 1087 bool ok = false; 1088 int weightNum = weight.toInt(&ok); 1089 if (ok) { 1090 switch (weightNum) { 1091 case 100: 1092 case 200: 1093 font.setWeight(QFont::Light); 1094 break; 1095 case 300: 1096 case 400: 1097 font.setWeight(QFont::Normal); 1098 break; 1099 case 500: 1100 case 600: 1101 font.setWeight(QFont::DemiBold); 1102 break; 1103 case 700: 1104 case 800: 1105 font.setWeight(QFont::Bold); 1106 break; 1107 case 900: 1108 font.setWeight(QFont::Black); 1109 break; 1110 default: 1111 break; 1112 } 1113 } else { 1114 if (weight == QLatin1String("normal")) { 1115 font.setWeight(QFont::Normal); 1116 } else if (weight == QLatin1String("bold")) { 1117 font.setWeight(QFont::Bold); 1118 } else if (weight == QLatin1String("bolder")) { 1119 font.setWeight(QFont::DemiBold); 1120 } else if (weight == QLatin1String("lighter")) { 1121 font.setWeight(QFont::Light); 1122 } 1123 } 1124 } 1125 // QFontInfo fi(font); 1126 // font.setPointSize(fi.pointSize()); 1127 return true; 1128 } 1129 1130 return false; 1215 prop->setDashArray(dashes); 1216 } 1217 } 1218 1219 //stroke-linejoin attribute handling 1220 if (!attributes.strokeLineJoin.isEmpty()) { 1221 if (attributes.strokeLineJoin == QLatin1String("miter")) 1222 prop->setLineJoin(Qt::SvgMiterJoin); 1223 else if (attributes.strokeLineJoin == QLatin1String("round")) 1224 prop->setLineJoin(Qt::RoundJoin); 1225 else if (attributes.strokeLineJoin == QLatin1String("bevel")) 1226 prop->setLineJoin(Qt::BevelJoin); 1227 } 1228 1229 //stroke-linecap attribute handling 1230 if (!attributes.strokeLineCap.isEmpty()) { 1231 if (attributes.strokeLineCap == QLatin1String("butt")) 1232 prop->setLineCap(Qt::FlatCap); 1233 else if (attributes.strokeLineCap == QLatin1String("round")) 1234 prop->setLineCap(Qt::RoundCap); 1235 else if (attributes.strokeLineCap == QLatin1String("square")) 1236 prop->setLineCap(Qt::SquareCap); 1237 } 1238 1239 //stroke-dashoffset attribute handling 1240 if (!attributes.strokeDashOffset.isEmpty() && attributes.strokeDashOffset != QT_INHERIT) 1241 prop->setDashOffset(toDouble(attributes.strokeDashOffset)); 1242 1243 //vector-effect attribute handling 1244 if (!attributes.vectorEffect.isEmpty()) { 1245 if (attributes.vectorEffect == QLatin1String("non-scaling-stroke")) 1246 prop->setVectorEffect(true); 1247 else if (attributes.vectorEffect == QLatin1String("none")) 1248 prop->setVectorEffect(false); 1249 } 1250 1251 //stroke-miterlimit 1252 if (!attributes.strokeMiterLimit.isEmpty() && attributes.strokeMiterLimit != QT_INHERIT) 1253 prop->setMiterLimit(toDouble(attributes.strokeMiterLimit)); 1254 1255 //stroke-opacity atttribute handling 1256 if (!attributes.strokeOpacity.isEmpty() && attributes.strokeOpacity != QT_INHERIT) 1257 prop->setOpacity(qMin(qreal(1.0), qMax(qreal(0.0), toDouble(attributes.strokeOpacity)))); 1258 1259 node->appendStyleProperty(prop, attributes.id); 1260 } 1131 1261 } 1132 1262 … … 1135 1265 QSvgHandler *handler) 1136 1266 { 1137 QFont font; 1138 font.setPixelSize(12); 1139 qreal fontSize = font.pixelSize(); 1140 1141 QSvgFontStyle *inherited = 1142 static_cast<QSvgFontStyle*>(node->styleProperty( 1143 QSvgStyleProperty::FONT)); 1144 if (!inherited) 1145 inherited = 1146 static_cast<QSvgFontStyle*>(node->parent()->styleProperty( 1147 QSvgStyleProperty::FONT)); 1148 if (inherited) { 1149 font = inherited->qfont(); 1150 fontSize = inherited->pointSize(); 1151 } 1152 if (parseQFont(attributes, font, fontSize, handler)) { 1153 QString myId = someId(attributes); 1154 QString anchor = attributes.value(QLatin1String("text-anchor")).toString(); 1155 QSvgTinyDocument *doc = node->document(); 1156 QSvgFontStyle *fontStyle = 0; 1157 QString family = (font.family().isEmpty())?myId:font.family(); 1158 if (!family.isEmpty()) { 1159 QSvgFont *svgFont = doc->svgFont(family); 1160 if (svgFont) { 1161 fontStyle = new QSvgFontStyle(svgFont, doc); 1162 fontStyle->setPointSize(fontSize); 1163 } 1164 } 1165 if (!fontStyle) { 1166 fontStyle = new QSvgFontStyle(font, node->document()); 1167 fontStyle->setPointSize(fontSize); 1168 } 1169 if (!anchor.isEmpty()) 1170 fontStyle->setTextAnchor(anchor); 1171 1172 node->appendStyleProperty(fontStyle, myId); 1173 } 1267 if (attributes.fontFamily.isEmpty() && attributes.fontSize.isEmpty() && attributes.fontStyle.isEmpty() && 1268 attributes.fontWeight.isEmpty() && attributes.fontVariant.isEmpty() && attributes.textAnchor.isEmpty()) 1269 return; 1270 1271 QSvgTinyDocument *doc = node->document(); 1272 QSvgFontStyle *fontStyle = 0; 1273 if (!attributes.fontFamily.isEmpty()) { 1274 QSvgFont *svgFont = doc->svgFont(attributes.fontFamily.toString()); 1275 if (svgFont) 1276 fontStyle = new QSvgFontStyle(svgFont, doc); 1277 } 1278 if (!fontStyle) 1279 fontStyle = new QSvgFontStyle; 1280 1281 if (!attributes.fontFamily.isEmpty() && attributes.fontFamily != QT_INHERIT) 1282 fontStyle->setFamily(attributes.fontFamily.toString().trimmed()); 1283 1284 if (!attributes.fontSize.isEmpty() && attributes.fontSize != QT_INHERIT) { 1285 QSvgHandler::LengthType dummy; // should always be pixel size 1286 fontStyle->setSize(parseLength(attributes.fontSize.toString(), dummy, handler)); 1287 } 1288 1289 if (!attributes.fontStyle.isEmpty() && attributes.fontStyle != QT_INHERIT) { 1290 if (attributes.fontStyle == QLatin1String("normal")) { 1291 fontStyle->setStyle(QFont::StyleNormal); 1292 } else if (attributes.fontStyle == QLatin1String("italic")) { 1293 fontStyle->setStyle(QFont::StyleItalic); 1294 } else if (attributes.fontStyle == QLatin1String("oblique")) { 1295 fontStyle->setStyle(QFont::StyleOblique); 1296 } 1297 } 1298 1299 if (!attributes.fontWeight.isEmpty() && attributes.fontWeight != QT_INHERIT) { 1300 bool ok = false; 1301 int weightNum = attributes.fontWeight.toString().toInt(&ok); 1302 if (ok) { 1303 fontStyle->setWeight(weightNum); 1304 } else { 1305 if (attributes.fontWeight == QLatin1String("normal")) { 1306 fontStyle->setWeight(400); 1307 } else if (attributes.fontWeight == QLatin1String("bold")) { 1308 fontStyle->setWeight(700); 1309 } else if (attributes.fontWeight == QLatin1String("bolder")) { 1310 fontStyle->setWeight(QSvgFontStyle::BOLDER); 1311 } else if (attributes.fontWeight == QLatin1String("lighter")) { 1312 fontStyle->setWeight(QSvgFontStyle::LIGHTER); 1313 } 1314 } 1315 } 1316 1317 if (!attributes.fontVariant.isEmpty() && attributes.fontVariant != QT_INHERIT) { 1318 if (attributes.fontVariant == QLatin1String("normal")) 1319 fontStyle->setVariant(QFont::MixedCase); 1320 else if (attributes.fontVariant == QLatin1String("small-caps")) 1321 fontStyle->setVariant(QFont::SmallCaps); 1322 } 1323 1324 if (!attributes.textAnchor.isEmpty() && attributes.textAnchor != QT_INHERIT) { 1325 if (attributes.textAnchor == QLatin1String("start")) 1326 fontStyle->setTextAnchor(Qt::AlignLeft); 1327 if (attributes.textAnchor == QLatin1String("middle")) 1328 fontStyle->setTextAnchor(Qt::AlignHCenter); 1329 else if (attributes.textAnchor == QLatin1String("end")) 1330 fontStyle->setTextAnchor(Qt::AlignRight); 1331 } 1332 1333 node->appendStyleProperty(fontStyle, attributes.id); 1174 1334 } 1175 1335 … … 1178 1338 QSvgHandler *) 1179 1339 { 1180 QString value = attributes.value(QLatin1String("transform")).toString(); 1181 QString myId = someId(attributes); 1182 value = value.trimmed(); 1183 if (value.isEmpty()) 1340 if (attributes.transform.isEmpty()) 1184 1341 return; 1185 QMatrix matrix = parseTransformationMatrix( value);1342 QMatrix matrix = parseTransformationMatrix(trimRef(attributes.transform)); 1186 1343 1187 1344 if (!matrix.isIdentity()) { 1188 node->appendStyleProperty(new QSvgTransformStyle(QTransform(matrix)), myId);1345 node->appendStyleProperty(new QSvgTransformStyle(QTransform(matrix)), attributes.id); 1189 1346 } 1190 1347 … … 1195 1352 QSvgHandler *) 1196 1353 { 1197 QString value = attributes.value(QLatin1String("visibility")).toString();1198 1354 QSvgNode *parent = node->parent(); 1199 1355 1200 if (parent && ( value.isEmpty() || value == QLatin1String("inherit")))1356 if (parent && (attributes.visibility.isEmpty() || attributes.visibility == QT_INHERIT)) 1201 1357 node->setVisible(parent->isVisible()); 1202 else if ( value == QLatin1String("hidden") || value== QLatin1String("collapse")) {1358 else if (attributes.visibility == QLatin1String("hidden") || attributes.visibility == QLatin1String("collapse")) { 1203 1359 node->setVisible(false); 1204 1360 } else … … 1326 1482 /* (xc, yc) is center of the circle. */ 1327 1483 1328 th0 = atan2(y0 - yc, x0 - xc);1329 th1 = atan2(y1 - yc, x1 - xc);1484 th0 = qAtan2(y0 - yc, x0 - xc); 1485 th1 = qAtan2(y1 - yc, x1 - xc); 1330 1486 1331 1487 th_arc = th1 - th0; … … 1355 1511 1356 1512 while (str != end) { 1357 while ( *str == QLatin1Char(' '))1513 while (str->isSpace()) 1358 1514 ++str; 1359 1515 QChar pathElem = *str; 1360 1516 ++str; 1361 1517 QChar endc = *end; 1362 *const_cast<QChar *>(end) = 0; // parseNumbersList requires 0-termination that QStringRef cannot guarantee 1363 QVector<qreal> arg = parseNumbersList(str); 1518 *const_cast<QChar *>(end) = 0; // parseNumbersArray requires 0-termination that QStringRef cannot guarantee 1519 QVarLengthArray<qreal, 8> arg; 1520 parseNumbersArray(str, arg); 1364 1521 *const_cast<QChar *>(end) = endc; 1365 1522 if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z')) 1366 1523 arg.append(0);//dummy 1367 while (!arg.isEmpty()) { 1524 const qreal *num = arg.constData(); 1525 int count = arg.count(); 1526 while (count > 0) { 1368 1527 qreal offsetX = x; // correction offsets 1369 1528 qreal offsetY = y; // for relative commands 1370 1529 switch (pathElem.unicode()) { 1371 1530 case 'm': { 1372 if (arg.count() < 2) { 1373 arg.pop_front(); 1531 if (count < 2) { 1532 num++; 1533 count--; 1374 1534 break; 1375 1535 } 1376 x = x0 = arg[0] + offsetX; 1377 y = y0 = arg[1] + offsetY; 1536 x = x0 = num[0] + offsetX; 1537 y = y0 = num[1] + offsetY; 1538 num += 2; 1539 count -= 2; 1378 1540 path.moveTo(x0, y0); 1379 arg.pop_front(); arg.pop_front(); 1541 1542 // As per 1.2 spec 8.3.2 The "moveto" commands 1543 // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands, 1544 // the subsequent pairs shall be treated as implicit 'lineto' commands. 1545 pathElem = QLatin1Char('l'); 1380 1546 } 1381 1547 break; 1382 1548 case 'M': { 1383 if (arg.count() < 2) { 1384 arg.pop_front(); 1549 if (count < 2) { 1550 num++; 1551 count--; 1385 1552 break; 1386 1553 } 1387 x = x0 = arg[0]; 1388 y = y0 = arg[1]; 1389 1554 x = x0 = num[0]; 1555 y = y0 = num[1]; 1556 num += 2; 1557 count -= 2; 1390 1558 path.moveTo(x0, y0); 1391 arg.pop_front(); arg.pop_front(); 1559 1560 // As per 1.2 spec 8.3.2 The "moveto" commands 1561 // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands, 1562 // the subsequent pairs shall be treated as implicit 'lineto' commands. 1563 pathElem = QLatin1Char('L'); 1392 1564 } 1393 1565 break; … … 1396 1568 x = x0; 1397 1569 y = y0; 1570 count--; // skip dummy 1571 num++; 1398 1572 path.closeSubpath(); 1399 arg.pop_front();//pop dummy1400 1573 } 1401 1574 break; 1402 1575 case 'l': { 1403 if (arg.count() < 2) { 1404 arg.pop_front(); 1576 if (count < 2) { 1577 num++; 1578 count--; 1405 1579 break; 1406 1580 } 1407 x = arg.front()+ offsetX;1408 arg.pop_front();1409 y = arg.front() + offsetY;1410 arg.pop_front();1581 x = num[0] + offsetX; 1582 y = num[1] + offsetY; 1583 num += 2; 1584 count -= 2; 1411 1585 path.lineTo(x, y); 1412 1586 … … 1414 1588 break; 1415 1589 case 'L': { 1416 if (arg.count() < 2) { 1417 arg.pop_front(); 1590 if (count < 2) { 1591 num++; 1592 count--; 1418 1593 break; 1419 1594 } 1420 x = arg.front(); arg.pop_front(); 1421 y = arg.front(); arg.pop_front(); 1595 x = num[0]; 1596 y = num[1]; 1597 num += 2; 1598 count -= 2; 1422 1599 path.lineTo(x, y); 1423 1600 } 1424 1601 break; 1425 1602 case 'h': { 1426 x = arg.front() + offsetX; arg.pop_front(); 1603 x = num[0] + offsetX; 1604 num++; 1605 count--; 1427 1606 path.lineTo(x, y); 1428 1607 } 1429 1608 break; 1430 1609 case 'H': { 1431 x = arg[0]; 1610 x = num[0]; 1611 num++; 1612 count--; 1432 1613 path.lineTo(x, y); 1433 arg.pop_front();1434 1614 } 1435 1615 break; 1436 1616 case 'v': { 1437 y = arg[0] + offsetY; 1617 y = num[0] + offsetY; 1618 num++; 1619 count--; 1438 1620 path.lineTo(x, y); 1439 arg.pop_front();1440 1621 } 1441 1622 break; 1442 1623 case 'V': { 1443 y = arg[0]; 1624 y = num[0]; 1625 num++; 1626 count--; 1444 1627 path.lineTo(x, y); 1445 arg.pop_front();1446 1628 } 1447 1629 break; 1448 1630 case 'c': { 1449 if ( arg.count()< 6) {1450 while (arg.count())1451 arg.pop_front();1631 if (count < 6) { 1632 num += count; 1633 count = 0; 1452 1634 break; 1453 1635 } 1454 QPointF c1(arg[0]+offsetX, arg[1]+offsetY); 1455 QPointF c2(arg[2]+offsetX, arg[3]+offsetY); 1456 QPointF e(arg[4]+offsetX, arg[5]+offsetY); 1636 QPointF c1(num[0] + offsetX, num[1] + offsetY); 1637 QPointF c2(num[2] + offsetX, num[3] + offsetY); 1638 QPointF e(num[4] + offsetX, num[5] + offsetY); 1639 num += 6; 1640 count -= 6; 1457 1641 path.cubicTo(c1, c2, e); 1458 1642 ctrlPt = c2; 1459 1643 x = e.x(); 1460 1644 y = e.y(); 1461 arg.pop_front(); arg.pop_front();1462 arg.pop_front(); arg.pop_front();1463 arg.pop_front(); arg.pop_front();1464 1645 break; 1465 1646 } 1466 1647 case 'C': { 1467 if ( arg.count()< 6) {1468 while (arg.count())1469 arg.pop_front();1648 if (count < 6) { 1649 num += count; 1650 count = 0; 1470 1651 break; 1471 1652 } 1472 QPointF c1(arg[0], arg[1]); 1473 QPointF c2(arg[2], arg[3]); 1474 QPointF e(arg[4], arg[5]); 1653 QPointF c1(num[0], num[1]); 1654 QPointF c2(num[2], num[3]); 1655 QPointF e(num[4], num[5]); 1656 num += 6; 1657 count -= 6; 1475 1658 path.cubicTo(c1, c2, e); 1476 1659 ctrlPt = c2; 1477 1660 x = e.x(); 1478 1661 y = e.y(); 1479 arg.pop_front(); arg.pop_front();1480 arg.pop_front(); arg.pop_front();1481 arg.pop_front(); arg.pop_front();1482 1662 break; 1483 1663 } 1484 1664 case 's': { 1485 if ( arg.count()< 4) {1486 while (arg.count())1487 arg.pop_front();1665 if (count < 4) { 1666 num += count; 1667 count = 0; 1488 1668 break; 1489 1669 } … … 1494 1674 else 1495 1675 c1 = QPointF(x, y); 1496 QPointF c2(arg[0]+offsetX, arg[1]+offsetY); 1497 QPointF e(arg[2]+offsetX, arg[3]+offsetY); 1676 QPointF c2(num[0] + offsetX, num[1] + offsetY); 1677 QPointF e(num[2] + offsetX, num[3] + offsetY); 1678 num += 4; 1679 count -= 4; 1498 1680 path.cubicTo(c1, c2, e); 1499 1681 ctrlPt = c2; 1500 1682 x = e.x(); 1501 1683 y = e.y(); 1502 arg.pop_front(); arg.pop_front();1503 arg.pop_front(); arg.pop_front();1504 1684 break; 1505 1685 } 1506 1686 case 'S': { 1507 if ( arg.count()< 4) {1508 while (arg.count())1509 arg.pop_front();1687 if (count < 4) { 1688 num += count; 1689 count = 0; 1510 1690 break; 1511 1691 } … … 1516 1696 else 1517 1697 c1 = QPointF(x, y); 1518 QPointF c2(arg[0], arg[1]); 1519 QPointF e(arg[2], arg[3]); 1698 QPointF c2(num[0], num[1]); 1699 QPointF e(num[2], num[3]); 1700 num += 4; 1701 count -= 4; 1520 1702 path.cubicTo(c1, c2, e); 1521 1703 ctrlPt = c2; 1522 1704 x = e.x(); 1523 1705 y = e.y(); 1524 arg.pop_front(); arg.pop_front();1525 arg.pop_front(); arg.pop_front();1526 1706 break; 1527 1707 } 1528 1708 case 'q': { 1529 if ( arg.count()< 4) {1530 while (arg.count())1531 arg.pop_front();1709 if (count < 4) { 1710 num += count; 1711 count = 0; 1532 1712 break; 1533 1713 } 1534 QPointF c(arg[0]+offsetX, arg[1]+offsetY); 1535 QPointF e(arg[2]+offsetX, arg[3]+offsetY); 1714 QPointF c(num[0] + offsetX, num[1] + offsetY); 1715 QPointF e(num[2] + offsetX, num[3] + offsetY); 1716 num += 4; 1717 count -= 4; 1536 1718 path.quadTo(c, e); 1537 1719 ctrlPt = c; 1538 1720 x = e.x(); 1539 1721 y = e.y(); 1540 arg.pop_front(); arg.pop_front();1541 arg.pop_front(); arg.pop_front();1542 1722 break; 1543 1723 } 1544 1724 case 'Q': { 1545 if ( arg.count()< 4) {1546 while (arg.count())1547 arg.pop_front();1725 if (count < 4) { 1726 num += count; 1727 count = 0; 1548 1728 break; 1549 1729 } 1550 QPointF c(arg[0], arg[1]); 1551 QPointF e(arg[2], arg[3]); 1730 QPointF c(num[0], num[1]); 1731 QPointF e(num[2], num[3]); 1732 num += 4; 1733 count -= 4; 1552 1734 path.quadTo(c, e); 1553 1735 ctrlPt = c; 1554 1736 x = e.x(); 1555 1737 y = e.y(); 1556 arg.pop_front(); arg.pop_front();1557 arg.pop_front(); arg.pop_front();1558 1738 break; 1559 1739 } 1560 1740 case 't': { 1561 if ( arg.count()< 2) {1562 while (arg.count())1563 arg.pop_front();1741 if (count < 2) { 1742 num += count; 1743 count = 0; 1564 1744 break; 1565 1745 } 1566 QPointF e(arg[0]+offsetX, arg[1]+offsetY); 1746 QPointF e(num[0] + offsetX, num[1] + offsetY); 1747 num += 2; 1748 count -= 2; 1567 1749 QPointF c; 1568 1750 if (lastMode == 'q' || lastMode == 'Q' || … … 1575 1757 x = e.x(); 1576 1758 y = e.y(); 1577 arg.pop_front(); arg.pop_front();1578 1759 break; 1579 1760 } 1580 1761 case 'T': { 1581 if ( arg.count()< 2) {1582 while (arg.count())1583 arg.pop_front();1762 if (count < 2) { 1763 num += count; 1764 count = 0; 1584 1765 break; 1585 1766 } 1586 QPointF e(arg[0], arg[1]); 1767 QPointF e(num[0], num[1]); 1768 num += 2; 1769 count -= 2; 1587 1770 QPointF c; 1588 1771 if (lastMode == 'q' || lastMode == 'Q' || … … 1595 1778 x = e.x(); 1596 1779 y = e.y(); 1597 arg.pop_front(); arg.pop_front();1598 1780 break; 1599 1781 } 1600 1782 case 'a': { 1601 if ( arg.count()< 7) {1602 while (arg.count())1603 arg.pop_front();1783 if (count < 7) { 1784 num += count; 1785 count = 0; 1604 1786 break; 1605 1787 } 1606 qreal rx = arg[0]; 1607 qreal ry = arg[1]; 1608 qreal xAxisRotation = arg[2]; 1609 qreal largeArcFlag = arg[3]; 1610 qreal sweepFlag = arg[4]; 1611 qreal ex = arg[5] + offsetX; 1612 qreal ey = arg[6] + offsetY; 1788 qreal rx = (*num++); 1789 qreal ry = (*num++); 1790 qreal xAxisRotation = (*num++); 1791 qreal largeArcFlag = (*num++); 1792 qreal sweepFlag = (*num++); 1793 qreal ex = (*num++) + offsetX; 1794 qreal ey = (*num++) + offsetY; 1795 count -= 7; 1613 1796 qreal curx = x; 1614 1797 qreal cury = y; … … 1618 1801 x = ex; 1619 1802 y = ey; 1620 1621 arg.pop_front(); arg.pop_front();1622 arg.pop_front(); arg.pop_front();1623 arg.pop_front(); arg.pop_front();1624 arg.pop_front();1625 1803 } 1626 1804 break; 1627 1805 case 'A': { 1628 if ( arg.count()< 7) {1629 while (arg.count())1630 arg.pop_front();1806 if (count < 7) { 1807 num += count; 1808 count = 0; 1631 1809 break; 1632 1810 } 1633 qreal rx = arg[0]; 1634 qreal ry = arg[1]; 1635 qreal xAxisRotation = arg[2]; 1636 qreal largeArcFlag = arg[3]; 1637 qreal sweepFlag = arg[4]; 1638 qreal ex = arg[5]; 1639 qreal ey = arg[6]; 1811 qreal rx = (*num++); 1812 qreal ry = (*num++); 1813 qreal xAxisRotation = (*num++); 1814 qreal largeArcFlag = (*num++); 1815 qreal sweepFlag = (*num++); 1816 qreal ex = (*num++); 1817 qreal ey = (*num++); 1818 count -= 7; 1640 1819 qreal curx = x; 1641 1820 qreal cury = y; 1642 1821 pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag), 1643 1822 int(sweepFlag), ex, ey, curx, cury); 1823 1644 1824 x = ex; 1645 1825 y = ey; 1646 arg.pop_front(); arg.pop_front();1647 arg.pop_front(); arg.pop_front();1648 arg.pop_front(); arg.pop_front();1649 arg.pop_front();1650 1826 } 1651 1827 break; … … 1674 1850 if (decl.d->property.isEmpty()) 1675 1851 continue; 1676 if (decl.d->values.count() != 1)1677 continue;1678 1852 QCss::Value val = decl.d->values.first(); 1679 QString valueStr = val.toString(); 1853 QString valueStr; 1854 if (decl.d->values.count() != 1) { 1855 for (int i=0; i<decl.d->values.count(); ++i) { 1856 const QString &value = decl.d->values[i].toString(); 1857 if (value.isEmpty()) 1858 valueStr += QLatin1Char(','); 1859 else 1860 valueStr += value; 1861 } 1862 } else { 1863 valueStr = val.toString(); 1864 } 1680 1865 if (val.type == QCss::Value::Uri) { 1681 1866 valueStr.prepend(QLatin1String("url(")); … … 1790 1975 } 1791 1976 1792 static bool parseDefaultTextStyle(QSvgNode *node,1793 const QXmlStreamAttributes &attributes,1794 bool initial,1795 QSvgHandler *handler)1796 {1797 Q_ASSERT(node->type() == QSvgText::TEXT || node->type() == QSvgNode::TEXTAREA);1798 QSvgText *textNode = static_cast<QSvgText*>(node);1799 1800 QSvgAttributes attrs(attributes, handler);1801 1802 QString fontFamily = attrs.value(QString(), QLatin1String("font-family")).toString();1803 1804 QString anchor = attrs.value(QString(), QLatin1String("text-anchor")).toString();1805 1806 QSvgFontStyle *fontStyle = static_cast<QSvgFontStyle*>(1807 node->styleProperty(QSvgStyleProperty::FONT));1808 if (fontStyle) {1809 QSvgTinyDocument *doc = fontStyle->doc();1810 if (doc && fontStyle->svgFont()) {1811 cssStyleLookup(node, handler, handler->selector());1812 parseStyle(node, attrs, handler);1813 return true;1814 }1815 } else if (!fontFamily.isEmpty()) {1816 QSvgTinyDocument *doc = node->document();1817 QSvgFont *svgFont = doc->svgFont(fontFamily);1818 if (svgFont) {1819 cssStyleLookup(node, handler, handler->selector());1820 parseStyle(node, attrs, handler);1821 return true;1822 }1823 }1824 1825 QTextCharFormat format;1826 QBrush brush(QColor(0, 0, 0));1827 QFont font;1828 font.setPixelSize(12);1829 qreal fontSize = font.pixelSize();1830 1831 if (!initial) {1832 font = textNode->topFormat().font();1833 fontSize = font.pixelSize() / textNode->scale();1834 brush = textNode->topFormat().foreground();1835 } else {1836 QSvgFontStyle *fontStyle = static_cast<QSvgFontStyle*>(1837 node->styleProperty(QSvgStyleProperty::FONT));1838 if (!fontStyle)1839 fontStyle = static_cast<QSvgFontStyle*>(1840 node->parent()->styleProperty(QSvgStyleProperty::FONT));1841 if (fontStyle) {1842 font = fontStyle->qfont();1843 fontSize = fontStyle->pointSize();1844 if (anchor.isEmpty())1845 anchor = fontStyle->textAnchor();1846 }1847 1848 Qt::Alignment align = Qt::AlignLeft;1849 if (anchor == QLatin1String("middle"))1850 align = Qt::AlignHCenter;1851 else if (anchor == QLatin1String("end"))1852 align = Qt::AlignRight;1853 textNode->setTextAlignment(align);1854 1855 QSvgFillStyle *fillStyle = static_cast<QSvgFillStyle*>(1856 node->styleProperty(QSvgStyleProperty::FILL));1857 if (fillStyle)1858 brush = fillStyle->qbrush();1859 }1860 1861 if (parseQFont(attrs, font, fontSize, handler) || initial) {1862 if (initial)1863 textNode->setScale(100 / fontSize);1864 font.setPixelSize(qMax(1, int(fontSize * textNode->scale())));1865 format.setFont(font);1866 }1867 1868 if (parseQBrush(attrs, node, brush, handler) || initial) {1869 if (brush.style() != Qt::NoBrush || initial)1870 format.setForeground(brush);1871 }1872 1873 QPen pen(Qt::NoPen);1874 // QSvgStrokeStyle *inherited =1875 // static_cast<QSvgStrokeStyle*>(node->parent()->styleProperty(1876 // QSvgStyleProperty::STROKE));1877 // if (inherited)1878 // pen = inherited->qpen();1879 parseQPen(pen, node, attrs, handler);1880 if (pen.style() != Qt::NoPen) {1881 format.setTextOutline(pen);1882 }1883 1884 parseTransform(node, attrs, handler);1885 1886 textNode->insertFormat(format);1887 1888 return true;1889 }1890 1891 1977 static inline QStringList stringToList(const QString &str) 1892 1978 { … … 1898 1984 const QXmlStreamAttributes &attributes) 1899 1985 { 1900 QString featuresStr = attributes.value(QLatin1String("requiredFeatures")).toString(); 1901 QString extensionsStr = attributes.value(QLatin1String("requiredExtensions")).toString(); 1902 QString languagesStr = attributes.value(QLatin1String("systemLanguage")).toString(); 1903 QString formatsStr = attributes.value(QLatin1String("requiredFormats")).toString(); 1904 QString fontsStr = attributes.value(QLatin1String("requiredFonts")).toString(); 1905 QString nodeIdStr = someId(attributes); 1906 QString xmlClassStr = attributes.value(QLatin1String("class")).toString(); 1907 1908 1909 QStringList features = stringToList(featuresStr); 1910 QStringList extensions = stringToList(extensionsStr); 1911 QStringList languages = stringToList(languagesStr); 1912 QStringList formats = stringToList(formatsStr); 1913 QStringList fonts = stringToList(fontsStr); 1986 QStringList features; 1987 QStringList extensions; 1988 QStringList languages; 1989 QStringList formats; 1990 QStringList fonts; 1991 QString xmlClassStr; 1992 1993 for (int i = 0; i < attributes.count(); ++i) { 1994 const QXmlStreamAttribute &attribute = attributes.at(i); 1995 QStringRef name = attribute.qualifiedName(); 1996 if (name.isEmpty()) 1997 continue; 1998 QStringRef value = attribute.value(); 1999 switch (name.at(0).unicode()) { 2000 case 'c': 2001 if (name == QLatin1String("class")) 2002 xmlClassStr = value.toString(); 2003 break; 2004 case 'r': 2005 if (name == QLatin1String("requiredFeatures")) 2006 features = stringToList(value.toString()); 2007 else if (name == QLatin1String("requiredExtensions")) 2008 extensions = stringToList(value.toString()); 2009 else if (name == QLatin1String("requiredFormats")) 2010 formats = stringToList(value.toString()); 2011 else if (name == QLatin1String("requiredFonts")) 2012 fonts = stringToList(value.toString()); 2013 break; 2014 case 's': 2015 if (name == QLatin1String("systemLanguage")) 2016 languages = stringToList(value.toString()); 2017 break; 2018 default: 2019 break; 2020 } 2021 } 1914 2022 1915 2023 node->setRequiredFeatures(features); … … 1918 2026 node->setRequiredFormats(formats); 1919 2027 node->setRequiredFonts(fonts); 1920 node->setNodeId( nodeIdStr);2028 node->setNodeId(someId(attributes)); 1921 2029 node->setXmlClass(xmlClassStr); 1922 2030 … … 1928 2036 QSvgHandler *) 1929 2037 { 1930 QString value = attributes.value(QLatin1String("opacity")).toString(); 1931 value = value.trimmed(); 2038 if (attributes.opacity.isEmpty()) 2039 return; 2040 2041 const QString value = attributes.opacity.toString().trimmed(); 1932 2042 1933 2043 bool ok = false; … … 1935 2045 1936 2046 if (ok) { 1937 QSvgOpacityStyle *opacity = new QSvgOpacityStyle( op);1938 node->appendStyleProperty(opacity, someId(attributes));2047 QSvgOpacityStyle *opacity = new QSvgOpacityStyle(qBound(qreal(0.0), op, qreal(1.0))); 2048 node->appendStyleProperty(opacity, attributes.id); 1939 2049 } 1940 2050 } … … 2002 2112 QSvgHandler *) 2003 2113 { 2004 QString value = attributes.value(QLatin1String("comp-op")).toString(); 2005 value = value.trimmed(); 2114 if (attributes.compOp.isEmpty()) 2115 return; 2116 QString value = attributes.compOp.toString().trimmed(); 2006 2117 2007 2118 if (!value.isEmpty()) { 2008 2119 QSvgCompOpStyle *compop = new QSvgCompOpStyle(svgToQtCompositionMode(value)); 2009 node->appendStyleProperty(compop, someId(attributes));2120 node->appendStyleProperty(compop, attributes.id); 2010 2121 } 2011 2122 } … … 2047 2158 } else if (str == QLatin1String("none")) { 2048 2159 return QSvgNode::NoneMode; 2049 } else if (str == Q Latin1String("inherit")) {2160 } else if (str == QT_INHERIT) { 2050 2161 return QSvgNode::InheritMode; 2051 2162 } … … 2057 2168 QSvgHandler *) 2058 2169 { 2059 QString displayStr = attributes.value(QLatin1String("display")).toString(); 2060 displayStr = displayStr.trimmed(); 2170 if (attributes.display.isEmpty()) 2171 return; 2172 QString displayStr = attributes.display.toString().trimmed(); 2061 2173 2062 2174 if (!displayStr.isEmpty()) { … … 2136 2248 { 2137 2249 QString typeStr = attributes.value(QLatin1String("type")).toString(); 2138 QString fromStr = attributes.value(QLatin1String("from")).toString();2139 QString toStr = attributes.value(QLatin1String("to")).toString();2250 QStringRef fromStr = attributes.value(QLatin1String("from")); 2251 QStringRef toStr = attributes.value(QLatin1String("to")); 2140 2252 QString valuesStr = attributes.value(QLatin1String("values")).toString(); 2141 2253 QString beginStr = attributes.value(QLatin1String("begin")).toString(); … … 2148 2260 if (valuesStr.isEmpty()) { 2149 2261 QColor startColor, endColor; 2150 constructColor(fromStr, QString(), startColor, handler);2151 constructColor(toStr, QString(), endColor, handler);2262 resolveColor(fromStr, startColor, handler); 2263 resolveColor(toStr, endColor, handler); 2152 2264 colors.append(startColor); 2153 2265 colors.append(endColor); … … 2157 2269 for (itr = str.constBegin(); itr != str.constEnd(); ++itr) { 2158 2270 QColor color; 2159 constructColor(*itr, QString(), color, handler); 2271 QString str = *itr; 2272 resolveColor(QStringRef(&str), color, handler); 2160 2273 colors.append(color); 2161 2274 } … … 2199 2312 Q_UNUSED(parent); Q_UNUSED(attributes); 2200 2313 return true; 2314 } 2315 2316 static void parseNumberTriplet(QVector<qreal> &values, const QChar *&s) 2317 { 2318 QVector<qreal> list = parseNumbersList(s); 2319 values << list; 2320 for (int i = 3 - list.size(); i > 0; --i) 2321 values.append(0.0); 2201 2322 } 2202 2323 … … 2214 2335 QString fromStr = attributes.value(QLatin1String("from")).toString(); 2215 2336 QString toStr = attributes.value(QLatin1String("to")).toString(); 2337 QString byStr = attributes.value(QLatin1String("by")).toString(); 2338 QString addtv = attributes.value(QLatin1String("additive")).toString(); 2339 2340 QSvgAnimateTransform::Additive additive = QSvgAnimateTransform::Replace; 2341 if (addtv == QLatin1String("sum")) 2342 additive = QSvgAnimateTransform::Sum; 2216 2343 2217 2344 QVector<qreal> vals; 2218 2345 if (values.isEmpty()) { 2219 const QChar *s = fromStr.constData(); 2220 QVector<qreal> lst = parseNumbersList(s); 2221 while (lst.count() < 3) 2222 lst.append(0.0); 2223 vals << lst; 2224 2225 s = toStr.constData(); 2226 lst = parseNumbersList(s); 2227 while (lst.count() < 3) 2228 lst.append(0.0); 2229 vals << lst; 2346 const QChar *s; 2347 if (fromStr.isEmpty()) { 2348 if (!byStr.isEmpty()) { 2349 // By-animation. 2350 additive = QSvgAnimateTransform::Sum; 2351 vals.append(0.0); 2352 vals.append(0.0); 2353 vals.append(0.0); 2354 parseNumberTriplet(vals, s = byStr.constData()); 2355 } else { 2356 // To-animation not defined. 2357 return false; 2358 } 2359 } else { 2360 if (!toStr.isEmpty()) { 2361 // From-to-animation. 2362 parseNumberTriplet(vals, s = fromStr.constData()); 2363 parseNumberTriplet(vals, s = toStr.constData()); 2364 } else if (!byStr.isEmpty()) { 2365 // From-by-animation. 2366 parseNumberTriplet(vals, s = fromStr.constData()); 2367 parseNumberTriplet(vals, s = byStr.constData()); 2368 for (int i = vals.size() - 3; i < vals.size(); ++i) 2369 vals[i] += vals[i - 3]; 2370 } else { 2371 return false; 2372 } 2373 } 2230 2374 } else { 2231 2375 const QChar *s = values.constData(); 2232 2376 while (s && *s != QLatin1Char(0)) { 2233 QVector<qreal> tmpVals = parseNumbersList(s); 2234 while (tmpVals.count() < 3) 2235 tmpVals.append(0.0); 2236 2237 vals << tmpVals; 2377 parseNumberTriplet(vals, s); 2238 2378 if (*s == QLatin1Char(0)) 2239 2379 break; … … 2277 2417 2278 2418 QSvgAnimateTransform *anim = new QSvgAnimateTransform(begin, end, 0); 2279 anim->setArgs(type, vals);2419 anim->setArgs(type, additive, vals); 2280 2420 anim->setFreeze(fillStr == QLatin1String("freeze")); 2281 2421 anim->setRepeatCount( … … 2542 2682 } 2543 2683 2684 if (image.format() == QImage::Format_ARGB32) 2685 image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); 2686 2544 2687 QSvgNode *img = new QSvgImage(parent, 2545 2688 image, … … 2576 2719 { 2577 2720 QString link = attributes.value(QLatin1String("xlink:href")).toString(); 2578 QString trans = attributes.value(QLatin1String("gradientTransform")).toString();2721 QStringRef trans = attributes.value(QLatin1String("gradientTransform")); 2579 2722 QString spread = attributes.value(QLatin1String("spreadMethod")).toString(); 2580 2723 QString units = attributes.value(QLatin1String("gradientUnits")).toString(); 2724 QStringRef colorStr = attributes.value(QLatin1String("color")); 2725 QStringRef colorOpacityStr = attributes.value(QLatin1String("color-opacity")); 2726 2727 QColor color; 2728 if (constructColor(colorStr, colorOpacityStr, color, handler)) { 2729 handler->popColor(); 2730 handler->pushColor(color); 2731 } 2581 2732 2582 2733 QMatrix matrix; … … 2714 2865 QVector<qreal> points = parseNumbersList(s); 2715 2866 QPolygonF poly(points.count()/2); 2716 int i = 0; 2717 QVector<qreal>::const_iterator itr = points.constBegin(); 2718 while (itr != points.constEnd()) { 2719 qreal one = *itr; ++itr; 2720 qreal two = *itr; ++itr; 2721 poly[i] = QPointF(one, two); 2722 ++i; 2723 } 2867 for (int i = 0; i < poly.size(); ++i) 2868 poly[i] = QPointF(points.at(2 * i), points.at(2 * i + 1)); 2724 2869 QSvgNode *polygon = new QSvgPolygon(parent, poly); 2725 2870 return polygon; … … 2736 2881 QVector<qreal> points = parseNumbersList(s); 2737 2882 QPolygonF poly(points.count()/2); 2738 int i = 0; 2739 QVector<qreal>::const_iterator itr = points.constBegin(); 2740 while (itr != points.constEnd()) { 2741 qreal one = *itr; ++itr; 2742 qreal two = *itr; ++itr; 2743 poly[i] = QPointF(one, two); 2744 ++i; 2745 } 2883 for (int i = 0; i < poly.size(); ++i) 2884 poly[i] = QPointF(points.at(2 * i), points.at(2 * i + 1)); 2746 2885 2747 2886 QSvgNode *line = new QSvgPolyline(parent, poly); … … 2862 3001 { 2863 3002 Q_UNUSED(parent); Q_UNUSED(attributes); 2864 QString solidColorStr = attributes.value(QLatin1String("solid-color")).toString();2865 QString solidOpacityStr = attributes.value(QLatin1String("solid-opacity")).toString();3003 QStringRef solidColorStr = attributes.value(QLatin1String("solid-color")); 3004 QStringRef solidOpacityStr = attributes.value(QLatin1String("solid-opacity")); 2866 3005 2867 3006 if (solidOpacityStr.isEmpty()) 2868 solidOpacityStr = attributes.value(QLatin1String("opacity")) .toString();3007 solidOpacityStr = attributes.value(QLatin1String("opacity")); 2869 3008 2870 3009 QColor color; … … 2896 3035 QVector<QCss::Declaration> decls = handler->selector()->declarationsForNode(cssNode); 2897 3036 2898 QSvgAttributes attrs(attributes, handler); 2899 3037 QXmlStreamAttributes xmlAttr = attributes; 2900 3038 for (int i = 0; i < decls.count(); ++i) { 2901 3039 const QCss::Declaration &decl = decls.at(i); … … 2911 3049 valueStr.append(QLatin1Char(')')); 2912 3050 } 2913 attrs.m_xmlAttributes.append(QString(), decl.d->property, valueStr); 2914 } 3051 xmlAttr.append(QString(), decl.d->property, valueStr); 3052 } 3053 QSvgAttributes attrs(xmlAttr, handler); 2915 3054 2916 3055 QSvgGradientStyle *style = 2917 3056 static_cast<QSvgGradientStyle*>(parent); 2918 QString offsetStr = attrs.value(QString(), QLatin1String("offset")).toString(); 2919 QString colorStr = attrs.value(QString(), QLatin1String("stop-color")).toString(); 2920 QString opacityStr = attrs.value(QString(), QLatin1String("stop-opacity")).toString(); 3057 QString offsetStr = attrs.offset.toString(); 3058 QStringRef colorStr = attrs.stopColor; 2921 3059 QColor color; 2922 qreal offset = convertToNumber(offsetStr, handler); 3060 3061 bool ok = true; 3062 qreal offset = convertToNumber(offsetStr, handler, &ok); 3063 if (!ok) 3064 offset = 0.0; 3065 QString black = QString::fromLatin1("#000000"); 2923 3066 if (colorStr.isEmpty()) { 2924 colorStr = Q Latin1String("#000000");2925 } 2926 2927 bool colorOK = constructColor(colorStr, opacityStr, color, handler);3067 colorStr = QStringRef(&black); 3068 } 3069 3070 constructColor(colorStr, attrs.stopOpacity, color, handler); 2928 3071 2929 3072 QGradient *grad = style->qgradient(); … … 2949 3092 grad->setColorAt(offset, color); 2950 3093 style->setGradientStopsSet(true); 2951 if (!colorOK)2952 style->addResolve(offset);2953 3094 return true; 2954 3095 } … … 3004 3145 } 3005 3146 3006 3147 QStringList viewBoxValues; 3007 3148 if (!viewBoxStr.isEmpty()) { 3008 QStringList lst = viewBoxStr.split(QLatin1Char(' '), QString::SkipEmptyParts); 3009 if (lst.count() != 4) 3010 lst = viewBoxStr.split(QLatin1Char(','), QString::SkipEmptyParts); 3011 QString xStr = lst.at(0).trimmed(); 3012 QString yStr = lst.at(1).trimmed(); 3013 QString widthStr = lst.at(2).trimmed(); 3014 QString heightStr = lst.at(3).trimmed(); 3015 3149 viewBoxStr = viewBoxStr.replace(QLatin1Char(' '), QLatin1Char(',')); 3150 viewBoxStr = viewBoxStr.replace(QLatin1Char('\r'), QLatin1Char(',')); 3151 viewBoxStr = viewBoxStr.replace(QLatin1Char('\n'), QLatin1Char(',')); 3152 viewBoxStr = viewBoxStr.replace(QLatin1Char('\t'), QLatin1Char(',')); 3153 viewBoxValues = viewBoxStr.split(QLatin1Char(','), QString::SkipEmptyParts); 3154 } 3155 if (viewBoxValues.count() == 4) { 3156 QString xStr = viewBoxValues.at(0).trimmed(); 3157 QString yStr = viewBoxValues.at(1).trimmed(); 3158 QString widthStr = viewBoxValues.at(2).trimmed(); 3159 QString heightStr = viewBoxValues.at(3).trimmed(); 3016 3160 3017 3161 QSvgHandler::LengthType lt; … … 3022 3166 3023 3167 node->setViewBox(QRectF(x, y, w, h)); 3024 } else if (width && height){ 3168 3169 } else if (width && height) { 3025 3170 if (type == QSvgHandler::LT_PT) { 3026 3171 width = convertToPixels(width, false, type); 3027 3172 height = convertToPixels(height, false, type); 3028 3173 } 3029 3030 3174 node->setViewBox(QRectF(0, 0, width, height)); 3031 3175 } 3032 3033 3176 handler->setDefaultCoordinateSystem(QSvgHandler::LT_PX); 3034 3177 … … 3051 3194 if (parent->type() != QSvgNode::TEXTAREA) 3052 3195 return false; 3053 static_cast<QSvgText*>(parent)-> insertLineBreak();3196 static_cast<QSvgText*>(parent)->addLineBreak(); 3054 3197 return true; 3055 3198 } … … 3066 3209 qreal ny = parseLength(y, type, handler); 3067 3210 3068 //### not to pixels but to the default coordinate system3069 // and text should be already in the correct coordinate3070 // system here3071 //nx = convertToPixels(nx, true, type);3072 //ny = convertToPixels(ny, true, type);3073 3074 3211 QSvgNode *text = new QSvgText(parent, QPointF(nx, ny)); 3075 3212 return text; … … 3090 3227 } 3091 3228 3229 static QSvgNode *createTspanNode(QSvgNode *parent, 3230 const QXmlStreamAttributes &, 3231 QSvgHandler *) 3232 { 3233 return new QSvgTspan(parent); 3234 } 3235 3092 3236 static bool parseTitleNode(QSvgNode *parent, 3093 3237 const QXmlStreamAttributes &attributes, … … 3096 3240 Q_UNUSED(parent); Q_UNUSED(attributes); 3097 3241 return true; 3098 }3099 3100 static bool parseTspanNode(QSvgNode *parent,3101 const QXmlStreamAttributes &attributes,3102 QSvgHandler *handler)3103 {3104 3105 cssStyleLookup(parent, handler, handler->selector());3106 return parseDefaultTextStyle(parent, attributes, false, handler);3107 3242 } 3108 3243 … … 3220 3355 if (ref == QLatin1String("ext")) return createTextNode; 3221 3356 if (ref == QLatin1String("extArea")) return createTextAreaNode; 3357 if (ref == QLatin1String("span")) return createTspanNode; 3222 3358 break; 3223 3359 case 'u': … … 3276 3412 if (ref == QLatin1String("break")) return parseTbreakNode; 3277 3413 if (ref == QLatin1String("itle")) return parseTitleNode; 3278 if (ref == QLatin1String("span")) return parseTspanNode;3279 3414 break; 3280 3415 default: … … 3367 3502 m_doc = 0; 3368 3503 m_style = 0; 3504 m_animEnd = 0; 3369 3505 m_defaultCoords = LT_PX; 3370 m_defaultPen = QPen(Qt::black, 1, Qt:: NoPen, Qt::FlatCap, Qt::SvgMiterJoin);3506 m_defaultPen = QPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap, Qt::SvgMiterJoin); 3371 3507 m_defaultPen.setMiterLimit(4); 3372 3508 parse(); … … 3405 3541 break; 3406 3542 default: 3407 ; 3408 } 3409 } 3543 break; 3544 } 3545 } 3546 resolveGradients(m_doc); 3410 3547 } 3411 3548 … … 3415 3552 QSvgNode *node = 0; 3416 3553 3417 if (m_colorTagCount.count()) { 3418 int top = m_colorTagCount.pop(); 3419 ++top; 3420 m_colorTagCount.push(top); 3421 } 3554 pushColorCopy(); 3422 3555 3423 3556 /* The xml:space attribute may appear on any element. We do … … 3425 3558 * the XML namespace can only be bound to prefix "xml." */ 3426 3559 const QStringRef xmlSpace(attributes.value(QLatin1String("xml:space"))); 3427 if(xmlSpace.isNull()) 3428 { 3560 if (xmlSpace.isNull()) { 3429 3561 // This element has no xml:space attribute. 3562 m_whitespaceMode.push(m_whitespaceMode.isEmpty() ? QSvgText::Default : m_whitespaceMode.top()); 3563 } else if (xmlSpace == QLatin1String("preserve")) { 3564 m_whitespaceMode.push(QSvgText::Preserve); 3565 } else if (xmlSpace == QLatin1String("default")) { 3430 3566 m_whitespaceMode.push(QSvgText::Default); 3431 } 3432 else if(xmlSpace == QLatin1String("preserve")) 3433 m_whitespaceMode.push(QSvgText::Preserve); 3434 else if(xmlSpace == QLatin1String("default")) 3435 m_whitespaceMode.push(QSvgText::Default); 3436 else 3437 { 3567 } else { 3438 3568 qWarning() << QString::fromLatin1("\"%1\" is an invalid value for attribute xml:space. " 3439 3569 "Valid values are \"preserve\" and \"default\".").arg(xmlSpace.toString()); 3440 3441 3570 m_whitespaceMode.push(QSvgText::Default); 3442 3571 } … … 3484 3613 } 3485 3614 break; 3615 case QSvgNode::TEXT: 3616 case QSvgNode::TEXTAREA: 3617 if (node->type() == QSvgNode::TSPAN) { 3618 static_cast<QSvgText *>(m_nodes.top())->addTspan(static_cast<QSvgTspan *>(node)); 3619 } else { 3620 qWarning("\'text\' or \'textArea\' element contains invalid element type."); 3621 delete node; 3622 node = 0; 3623 } 3624 break; 3486 3625 default: 3487 Q_ASSERT(!"not a grouping element is the parent"); 3488 } 3489 3490 parseCoreNode(node, attributes); 3491 cssStyleLookup(node, this, m_selector); 3492 if (node->type() != QSvgNode::TEXT && node->type() != QSvgNode::TEXTAREA) 3626 qWarning("Could not add child element to parent element because the types are incorrect."); 3627 delete node; 3628 node = 0; 3629 break; 3630 } 3631 3632 if (node) { 3633 parseCoreNode(node, attributes); 3634 cssStyleLookup(node, this, m_selector); 3493 3635 parseStyle(node, attributes, this); 3494 else 3495 parseDefaultTextStyle(node, attributes, true, this); 3636 if (node->type() == QSvgNode::TEXT || node->type() == QSvgNode::TEXTAREA) { 3637 static_cast<QSvgText *>(node)->setWhitespaceMode(m_whitespaceMode.top()); 3638 } else if (node->type() == QSvgNode::TSPAN) { 3639 static_cast<QSvgTspan *>(node)->setWhitespaceMode(m_whitespaceMode.top()); 3640 } 3641 } 3496 3642 } 3497 3643 } else if (ParseMethod method = findUtilFactory(localName)) { … … 3504 3650 if (prop) { 3505 3651 m_style = prop; 3506 m_nodes.top()->appendStyleProperty(prop, someId(attributes) , true);3652 m_nodes.top()->appendStyleProperty(prop, someId(attributes)); 3507 3653 } else { 3508 qWarning("Could n't parse node: %s", qPrintable(localName));3654 qWarning("Could not parse node: %s", qPrintable(localName)); 3509 3655 } 3510 3656 } else if (StyleParseMethod method = findStyleUtilFactoryMethod(localName)) { … … 3536 3682 m_whitespaceMode.pop(); 3537 3683 3538 if (m_colorTagCount.count()) { 3539 int top = m_colorTagCount.pop(); 3540 --top; 3541 if (!top) { 3542 m_colorStack.pop(); 3543 } else { 3544 m_colorTagCount.push(top); 3545 } 3546 } 3684 popColor(); 3547 3685 3548 3686 if (node == Unknown) { … … 3550 3688 } 3551 3689 3552 if (m_inStyle && localName == QLatin1String("style")) {3690 if (m_inStyle && localName == QLatin1String("style")) 3553 3691 m_inStyle = false; 3554 } else if (m_nodes.top()->type() == QSvgNode::TEXT || m_nodes.top()->type() == QSvgNode::TEXTAREA) {3555 QSvgText *node = static_cast<QSvgText*>(m_nodes.top());3556 if (localName == QLatin1String("tspan"))3557 node->popFormat();3558 }3559 3692 3560 3693 if (node == Graphics) … … 3564 3697 3565 3698 return true; 3699 } 3700 3701 void QSvgHandler::resolveGradients(QSvgNode *node) 3702 { 3703 if (!node || (node->type() != QSvgNode::DOC && node->type() != QSvgNode::G 3704 && node->type() != QSvgNode::DEFS && node->type() != QSvgNode::SWITCH)) { 3705 return; 3706 } 3707 QSvgStructureNode *structureNode = static_cast<QSvgStructureNode *>(node); 3708 3709 QList<QSvgNode *> ren = structureNode->renderers(); 3710 for (QList<QSvgNode *>::iterator it = ren.begin(); it != ren.end(); ++it) { 3711 QSvgFillStyle *fill = static_cast<QSvgFillStyle *>((*it)->styleProperty(QSvgStyleProperty::FILL)); 3712 if (fill && !fill->isGradientResolved()) { 3713 QString id = fill->gradientId(); 3714 QSvgFillStyleProperty *style = structureNode->styleProperty(id); 3715 if (style) { 3716 fill->setFillStyle(style); 3717 } else { 3718 qWarning("Could not resolve property : %s", qPrintable(id)); 3719 fill->setBrush(Qt::NoBrush); 3720 } 3721 } 3722 3723 QSvgStrokeStyle *stroke = static_cast<QSvgStrokeStyle *>((*it)->styleProperty(QSvgStyleProperty::STROKE)); 3724 if (stroke && !stroke->isGradientResolved()) { 3725 QString id = stroke->gradientId(); 3726 QSvgFillStyleProperty *style = structureNode->styleProperty(id); 3727 if (style) { 3728 stroke->setStyle(style); 3729 } else { 3730 qWarning("Could not resolve property : %s", qPrintable(id)); 3731 stroke->setStroke(Qt::NoBrush); 3732 } 3733 } 3734 3735 resolveGradients(*it); 3736 } 3566 3737 } 3567 3738 … … 3578 3749 3579 3750 if (m_nodes.top()->type() == QSvgNode::TEXT || m_nodes.top()->type() == QSvgNode::TEXTAREA) { 3580 QSvgText *node = static_cast<QSvgText*>(m_nodes.top()); 3581 node->insertText(str.toString(), m_whitespaceMode.top()); 3751 static_cast<QSvgText*>(m_nodes.top())->addText(str.toString()); 3752 } else if (m_nodes.top()->type() == QSvgNode::TSPAN) { 3753 static_cast<QSvgTspan*>(m_nodes.top())->addText(str.toString()); 3582 3754 } 3583 3755 … … 3604 3776 m_colorStack.push(color); 3605 3777 m_colorTagCount.push(1); 3778 } 3779 3780 void QSvgHandler::pushColorCopy() 3781 { 3782 if (m_colorTagCount.count()) 3783 ++m_colorTagCount.top(); 3784 else 3785 pushColor(Qt::black); 3786 } 3787 3788 void QSvgHandler::popColor() 3789 { 3790 if (m_colorTagCount.count()) { 3791 if (!--m_colorTagCount.top()) { 3792 m_colorStack.pop(); 3793 m_colorTagCount.pop(); 3794 } 3795 } 3606 3796 } 3607 3797 -
trunk/src/svg/qsvghandler_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 112 112 113 113 void pushColor(const QColor &color); 114 void pushColorCopy(); 115 void popColor(); 114 116 QColor currentColor() const; 115 117 … … 171 173 QCss::Parser m_cssParser; 172 174 void parse(); 175 void resolveGradients(QSvgNode *node); 173 176 174 177 QPen m_defaultPen; -
trunk/src/svg/qsvgnode.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 61 61 } 62 62 63 void QSvgNode::appendStyleProperty(QSvgStyleProperty *prop, const QString &id, 64 bool justLink) 63 void QSvgNode::appendStyleProperty(QSvgStyleProperty *prop, const QString &id) 65 64 { 66 65 //qDebug()<<"appending "<<prop->type()<< " ("<< id <<") "<<"to "<<this<<this->type(); 67 if (!justLink) { 68 switch (prop->type()) { 69 case QSvgStyleProperty::QUALITY: 70 m_style.quality = static_cast<QSvgQualityStyle*>(prop); 71 break; 72 case QSvgStyleProperty::FILL: 73 m_style.fill = static_cast<QSvgFillStyle*>(prop); 74 break; 75 case QSvgStyleProperty::VIEWPORT_FILL: 76 m_style.viewportFill = static_cast<QSvgViewportFillStyle*>(prop); 77 break; 78 case QSvgStyleProperty::FONT: 79 m_style.font = static_cast<QSvgFontStyle*>(prop); 80 break; 81 case QSvgStyleProperty::STROKE: 82 m_style.stroke = static_cast<QSvgStrokeStyle*>(prop); 83 break; 84 case QSvgStyleProperty::SOLID_COLOR: 85 m_style.solidColor = static_cast<QSvgSolidColorStyle*>(prop); 86 break; 87 case QSvgStyleProperty::GRADIENT: 88 m_style.gradient = static_cast<QSvgGradientStyle*>(prop); 89 break; 90 case QSvgStyleProperty::TRANSFORM: 91 m_style.transform = static_cast<QSvgTransformStyle*>(prop); 92 break; 93 case QSvgStyleProperty::ANIMATE_COLOR: 94 m_style.animateColor = static_cast<QSvgAnimateColor*>(prop); 95 break; 96 case QSvgStyleProperty::ANIMATE_TRANSFORM: 97 m_style.animateTransforms.append( 98 static_cast<QSvgAnimateTransform*>(prop)); 99 break; 100 case QSvgStyleProperty::OPACITY: 101 m_style.opacity = static_cast<QSvgOpacityStyle*>(prop); 102 break; 103 case QSvgStyleProperty::COMP_OP: 104 m_style.compop = static_cast<QSvgCompOpStyle*>(prop); 105 break; 106 default: 107 qDebug("QSvgNode: Trying to append unknown property!"); 108 break; 109 } 110 } 111 if (!id.isEmpty()) { 112 m_styles.insert(id, prop); 66 QSvgTinyDocument *doc; 67 switch (prop->type()) { 68 case QSvgStyleProperty::QUALITY: 69 m_style.quality = static_cast<QSvgQualityStyle*>(prop); 70 break; 71 case QSvgStyleProperty::FILL: 72 m_style.fill = static_cast<QSvgFillStyle*>(prop); 73 break; 74 case QSvgStyleProperty::VIEWPORT_FILL: 75 m_style.viewportFill = static_cast<QSvgViewportFillStyle*>(prop); 76 break; 77 case QSvgStyleProperty::FONT: 78 m_style.font = static_cast<QSvgFontStyle*>(prop); 79 break; 80 case QSvgStyleProperty::STROKE: 81 m_style.stroke = static_cast<QSvgStrokeStyle*>(prop); 82 break; 83 case QSvgStyleProperty::SOLID_COLOR: 84 m_style.solidColor = static_cast<QSvgSolidColorStyle*>(prop); 85 doc = document(); 86 if (doc && !id.isEmpty()) 87 doc->addNamedStyle(id, m_style.solidColor); 88 break; 89 case QSvgStyleProperty::GRADIENT: 90 m_style.gradient = static_cast<QSvgGradientStyle*>(prop); 91 doc = document(); 92 if (doc && !id.isEmpty()) 93 doc->addNamedStyle(id, m_style.gradient); 94 break; 95 case QSvgStyleProperty::TRANSFORM: 96 m_style.transform = static_cast<QSvgTransformStyle*>(prop); 97 break; 98 case QSvgStyleProperty::ANIMATE_COLOR: 99 m_style.animateColor = static_cast<QSvgAnimateColor*>(prop); 100 break; 101 case QSvgStyleProperty::ANIMATE_TRANSFORM: 102 m_style.animateTransforms.append( 103 static_cast<QSvgAnimateTransform*>(prop)); 104 break; 105 case QSvgStyleProperty::OPACITY: 106 m_style.opacity = static_cast<QSvgOpacityStyle*>(prop); 107 break; 108 case QSvgStyleProperty::COMP_OP: 109 m_style.compop = static_cast<QSvgCompOpStyle*>(prop); 110 break; 111 default: 112 qDebug("QSvgNode: Trying to append unknown property!"); 113 break; 113 114 } 114 115 } … … 186 187 } 187 188 188 QSvg StyleProperty * QSvgNode::styleProperty(const QString &id) const189 QSvgFillStyleProperty * QSvgNode::styleProperty(const QString &id) const 189 190 { 190 191 QString rid = id; 191 192 if (rid.startsWith(QLatin1Char('#'))) 192 193 rid.remove(0, 1); 193 const QSvgNode *node = this; 194 while (node) { 195 QSvgStyleProperty *style = node->m_styles[rid]; 196 if (style) 197 return style; 198 node = node->parent(); 199 } 200 201 return 0; 194 QSvgTinyDocument *doc = document(); 195 return doc ? doc->namedStyle(rid) : 0; 202 196 } 203 197 … … 321 315 QSvgStrokeStyle *stroke = static_cast<QSvgStrokeStyle*>( 322 316 styleProperty(QSvgStyleProperty::STROKE)); 323 if (!stroke || stroke->qpen().style() == Qt::NoPen)317 if (!stroke) 324 318 return 0; 325 return stroke->qpen().widthF(); 319 if (stroke->stroke().brush().style() == Qt::NoBrush) 320 return 0; 321 return stroke->width(); 326 322 } 327 323 -
trunk/src/svg/qsvgnode_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 87 87 TEXT, 88 88 TEXTAREA, 89 TSPAN, 89 90 USE, 90 91 VIDEO … … 117 118 QSvgNode *parent() const; 118 119 119 void appendStyleProperty(QSvgStyleProperty *prop, const QString &id, 120 bool justLink=false); 120 void appendStyleProperty(QSvgStyleProperty *prop, const QString &id); 121 121 void applyStyle(QPainter *p, QSvgExtraStates &states); 122 122 void revertStyle(QPainter *p, QSvgExtraStates &states); 123 123 QSvgStyleProperty *styleProperty(QSvgStyleProperty::Type type) const; 124 QSvg StyleProperty *styleProperty(const QString &id) const;124 QSvgFillStyleProperty *styleProperty(const QString &id) const; 125 125 126 126 QSvgTinyDocument *document() const; … … 162 162 private: 163 163 QSvgNode *m_parent; 164 QHash<QString, QSvgRefCounter<QSvgStyleProperty> > m_styles;165 164 166 165 QStringList m_requiredFeatures; -
trunk/src/svg/qsvgrenderer.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 56 56 /*! 57 57 \class QSvgRenderer 58 \ingroup multimedia58 \ingroup painting 59 59 60 60 \brief The QSvgRenderer class is used to draw the contents of SVG files onto paint devices. -
trunk/src/svg/qsvgrenderer.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/svg/qsvgstructure.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 46 46 #include "qsvgnode_p.h" 47 47 #include "qsvgstyle_p.h" 48 #include "qsvgtinydocument_p.h" 48 49 49 50 #include "qpainter.h" … … 69 70 applyStyle(p, states); 70 71 71 if (displayMode() != QSvgNode::NoneMode) { 72 while (itr != m_renderers.end()) { 73 QSvgNode *node = *itr; 74 if (node->isVisible()) 75 node->draw(p, states); 76 ++itr; 77 } 72 while (itr != m_renderers.end()) { 73 QSvgNode *node = *itr; 74 if ((node->isVisible()) && (node->displayMode() != QSvgNode::NoneMode)) 75 node->draw(p, states); 76 ++itr; 78 77 } 79 78 revertStyle(p, states); … … 93 92 QSvgNode * QSvgStructureNode::scopeNode(const QString &id) const 94 93 { 95 const QSvgStructureNode *group = this; 96 while (group && group->type() != QSvgNode::DOC) { 97 group = static_cast<QSvgStructureNode*>(group->parent()); 98 } 99 if (group) 100 return group->m_scope[id]; 101 return 0; 102 } 103 104 void QSvgStructureNode::addChild(QSvgNode *child, const QString &id, bool def) 105 { 106 if (!def) 107 m_renderers.append(child); 108 109 if (child->type() == QSvgNode::DEFS) { 110 QSvgDefs *defs = 111 static_cast<QSvgDefs*>(child); 112 m_linkedScopes.append(defs); 113 } 94 QSvgTinyDocument *doc = document(); 95 return doc ? doc->namedNode(id) : 0; 96 } 97 98 void QSvgStructureNode::addChild(QSvgNode *child, const QString &id) 99 { 100 m_renderers.append(child); 114 101 115 102 if (id.isEmpty()) 116 103 return; //we can't add it to scope without id 117 104 118 QSvgStructureNode *group = this; 119 while (group && group->type() != QSvgNode::DOC) { 120 group = static_cast<QSvgStructureNode*>(group->parent()); 121 } 122 if (group) 123 group->m_scope.insert(id, child); 105 QSvgTinyDocument *doc = document(); 106 if (doc) 107 doc->addNamedNode(id, child); 124 108 } 125 109 … … 138 122 return DEFS; 139 123 } 140 141 QSvgStyleProperty * QSvgStructureNode::scopeStyle(const QString &id) const142 {143 const QSvgStructureNode *group = this;144 while (group) {145 QSvgStyleProperty *prop = group->styleProperty(id);146 if (prop)147 return prop;148 QList<QSvgStructureNode*>::const_iterator itr = group->m_linkedScopes.constBegin();149 while (itr != group->m_linkedScopes.constEnd()) {150 prop = (*itr)->styleProperty(id);151 if (prop)152 return prop;153 ++itr;154 }155 group = static_cast<QSvgStructureNode*>(group->parent());156 }157 return 0;158 }159 160 124 161 125 /* … … 322 286 applyStyle(p, states); 323 287 324 if (displayMode() != QSvgNode::NoneMode) { 325 while (itr != m_renderers.end()) { 326 QSvgNode *node = *itr; 327 if (node->isVisible()) { 328 const QStringList &features = node->requiredFeatures(); 329 const QStringList &extensions = node->requiredExtensions(); 330 const QStringList &languages = node->requiredLanguages(); 331 const QStringList &formats = node->requiredFormats(); 332 const QStringList &fonts = node->requiredFonts(); 333 334 bool okToRender = true; 335 if (!features.isEmpty()) { 336 QStringList::const_iterator sitr = features.constBegin(); 337 for (; sitr != features.constEnd(); ++sitr) { 338 if (!isSupportedSvgFeature(*sitr)) { 339 okToRender = false; 340 break; 341 } 288 while (itr != m_renderers.end()) { 289 QSvgNode *node = *itr; 290 if (node->isVisible() && (node->displayMode() != QSvgNode::NoneMode)) { 291 const QStringList &features = node->requiredFeatures(); 292 const QStringList &extensions = node->requiredExtensions(); 293 const QStringList &languages = node->requiredLanguages(); 294 const QStringList &formats = node->requiredFormats(); 295 const QStringList &fonts = node->requiredFonts(); 296 297 bool okToRender = true; 298 if (!features.isEmpty()) { 299 QStringList::const_iterator sitr = features.constBegin(); 300 for (; sitr != features.constEnd(); ++sitr) { 301 if (!isSupportedSvgFeature(*sitr)) { 302 okToRender = false; 303 break; 342 304 } 343 305 } 344 345 if (okToRender && !extensions.isEmpty()) { 346 QStringList::const_iterator sitr = extensions.constBegin();347 for (; sitr != extensions.constEnd(); ++sitr) {348 if (!isSupportedSvgExtension(*sitr)) {349 okToRender = false;350 break;351 }306 } 307 308 if (okToRender && !extensions.isEmpty()) { 309 QStringList::const_iterator sitr = extensions.constBegin(); 310 for (; sitr != extensions.constEnd(); ++sitr) { 311 if (!isSupportedSvgExtension(*sitr)) { 312 okToRender = false; 313 break; 352 314 } 353 315 } 354 355 if (okToRender && !languages.isEmpty()) { 356 QStringList::const_iterator sitr = languages.constBegin();357 okToRender = false;358 for (; sitr != languages.constEnd(); ++sitr) {359 if ((*sitr).startsWith(m_systemLanguagePrefix)) {360 okToRender = true;361 break;362 }316 } 317 318 if (okToRender && !languages.isEmpty()) { 319 QStringList::const_iterator sitr = languages.constBegin(); 320 okToRender = false; 321 for (; sitr != languages.constEnd(); ++sitr) { 322 if ((*sitr).startsWith(m_systemLanguagePrefix)) { 323 okToRender = true; 324 break; 363 325 } 364 326 } 365 366 if (okToRender && !formats.isEmpty()) { 367 okToRender = false; 368 } 369 370 if (okToRender && !fonts.isEmpty()) { 371 okToRender = false; 372 } 373 374 if (okToRender) { 375 node->draw(p, states); 376 break; 377 } 378 } 379 ++itr; 327 } 328 329 if (okToRender && !formats.isEmpty()) { 330 okToRender = false; 331 } 332 333 if (okToRender && !fonts.isEmpty()) { 334 okToRender = false; 335 } 336 337 if (okToRender) { 338 node->draw(p, states); 339 break; 340 } 380 341 } 342 ++itr; 381 343 } 382 344 revertStyle(p, states); -
trunk/src/svg/qsvgstructure_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 74 74 ~QSvgStructureNode(); 75 75 QSvgNode *scopeNode(const QString &id) const; 76 QSvgStyleProperty *scopeStyle(const QString &id) const; 77 void addChild(QSvgNode *child, const QString &id, bool def = false); 76 void addChild(QSvgNode *child, const QString &id); 78 77 virtual QRectF bounds() const; 79 78 QSvgNode *previousSiblingNode(QSvgNode *n) const; -
trunk/src/svg/qsvgstyle.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 60 60 QSvgExtraStates::QSvgExtraStates() 61 61 : fillOpacity(1.0) 62 , strokeOpacity(1.0) 63 , svgFont(0) 64 , textAnchor(Qt::AlignLeft) 65 , fontWeight(400) 66 , fillRule(Qt::WindingFill) 67 , strokeDashOffset(0) 68 , vectorEffect(false) 62 69 { 63 70 } … … 66 73 { 67 74 } 75 76 void QSvgFillStyleProperty::apply(QPainter *, const QRectF &, QSvgNode *, QSvgExtraStates &) 77 { 78 Q_ASSERT(!"This should not be called!"); 79 } 80 81 void QSvgFillStyleProperty::revert(QPainter *, QSvgExtraStates &) 82 { 83 Q_ASSERT(!"This should not be called!"); 84 } 85 68 86 69 87 QSvgQualityStyle::QSvgQualityStyle(int color) … … 81 99 } 82 100 83 QSvgFillStyle::QSvgFillStyle(const QBrush &brush) 84 : m_fill(brush), m_style(0), m_fillRuleSet(false), m_fillOpacitySet(false) 85 { 86 } 87 88 QSvgFillStyle::QSvgFillStyle(QSvgStyleProperty *style) 89 : m_style(style), m_fillRuleSet(false), m_fillOpacitySet(false) 101 QSvgFillStyle::QSvgFillStyle() 102 : m_style(0) 103 , m_fillRule(Qt::WindingFill) 104 , m_oldFillRule(Qt::WindingFill) 105 , m_fillOpacity(1.0) 106 , m_oldFillOpacity(0) 107 , m_gradientResolved(1) 108 , m_fillRuleSet(0) 109 , m_fillOpacitySet(0) 110 , m_fillSet(0) 90 111 { 91 112 } … … 93 114 void QSvgFillStyle::setFillRule(Qt::FillRule f) 94 115 { 95 m_fillRuleSet = true;116 m_fillRuleSet = 1; 96 117 m_fillRule = f; 97 118 } … … 99 120 void QSvgFillStyle::setFillOpacity(qreal opacity) 100 121 { 101 m_fillOpacitySet = true;122 m_fillOpacitySet = 1; 102 123 m_fillOpacity = opacity; 103 124 } 104 125 105 static void recursivelySetFill(QSvgNode *node, Qt::FillRule f) 106 { 107 if (node->type() == QSvgNode::PATH) { 108 QSvgPath *path = static_cast<QSvgPath*>(node); 109 path->qpath()->setFillRule(f); 110 } else if (node->type() == QSvgNode::G) { 111 QList<QSvgNode*> renderers = static_cast<QSvgG*>(node)->renderers(); 112 foreach(QSvgNode *n, renderers) { 113 recursivelySetFill(n, f); 114 } 115 } 116 } 117 void QSvgFillStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtraStates &states) 126 void QSvgFillStyle::setFillStyle(QSvgFillStyleProperty* style) 127 { 128 m_style = style; 129 m_fillSet = 1; 130 } 131 132 void QSvgFillStyle::setBrush(QBrush brush) 133 { 134 m_fill = brush; 135 m_style = 0; 136 m_fillSet = 1; 137 } 138 139 void QSvgFillStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states) 118 140 { 119 141 m_oldFill = p->brush(); 120 m_oldOpacity = states.fillOpacity; 121 122 if (m_fillRuleSet) { 123 recursivelySetFill(node, m_fillRule); 124 m_fillRuleSet = false;//set it only on the first run 125 } 126 p->setBrush(m_fill); 142 m_oldFillRule = states.fillRule; 143 m_oldFillOpacity = states.fillOpacity; 144 145 if (m_fillRuleSet) 146 states.fillRule = m_fillRule; 147 if (m_fillSet) { 148 if (m_style) 149 p->setBrush(m_style->brush(p, states)); 150 else 151 p->setBrush(m_fill); 152 } 127 153 if (m_fillOpacitySet) 128 154 states.fillOpacity = m_fillOpacity; 129 if (m_style)130 m_style->apply(p, rect, node, states);131 155 } 132 156 133 157 void QSvgFillStyle::revert(QPainter *p, QSvgExtraStates &states) 134 158 { 135 if (m_style)136 m_style->revert(p, states);137 p->setBrush(m_oldFill);138 159 if (m_fillOpacitySet) 139 states.fillOpacity = m_oldOpacity; 160 states.fillOpacity = m_oldFillOpacity; 161 if (m_fillSet) 162 p->setBrush(m_oldFill); 163 if (m_fillRuleSet) 164 states.fillRule = m_oldFillRule; 140 165 } 141 166 … … 157 182 158 183 QSvgFontStyle::QSvgFontStyle(QSvgFont *font, QSvgTinyDocument *doc) 159 : m_font(font), m_pointSize(24), m_doc(doc) 160 { 161 } 162 163 QSvgFontStyle::QSvgFontStyle(const QFont &font, QSvgTinyDocument *doc) 164 : m_font(0), m_pointSize(24), m_doc(doc), m_qfont(font) 165 { 166 } 167 168 169 void QSvgFontStyle::setPointSize(qreal size) 170 { 171 m_pointSize = size; 172 } 173 174 qreal QSvgFontStyle::pointSize() const 175 { 176 return m_pointSize; 177 } 178 179 void QSvgFontStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) 180 { 181 if (!m_font) { 182 m_oldFont = p->font(); 183 p->setFont(m_qfont); 184 } 185 } 186 187 void QSvgFontStyle::revert(QPainter *p, QSvgExtraStates &) 188 { 189 if (!m_font) { 190 p->setFont(m_oldFont); 191 } 192 } 193 194 QSvgStrokeStyle::QSvgStrokeStyle(const QPen &pen) 195 : m_stroke(pen) 196 { 197 } 198 199 void QSvgStrokeStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) 184 : m_svgFont(font) 185 , m_doc(doc) 186 , m_familySet(0) 187 , m_sizeSet(0) 188 , m_styleSet(0) 189 , m_variantSet(0) 190 , m_weightSet(0) 191 , m_textAnchorSet(0) 192 { 193 } 194 195 QSvgFontStyle::QSvgFontStyle() 196 : m_svgFont(0) 197 , m_doc(0) 198 , m_familySet(0) 199 , m_sizeSet(0) 200 , m_styleSet(0) 201 , m_variantSet(0) 202 , m_weightSet(0) 203 , m_textAnchorSet(0) 204 { 205 } 206 207 int QSvgFontStyle::SVGToQtWeight(int weight) { 208 switch (weight) { 209 case 100: 210 case 200: 211 return QFont::Light; 212 case 300: 213 case 400: 214 return QFont::Normal; 215 case 500: 216 case 600: 217 return QFont::DemiBold; 218 case 700: 219 case 800: 220 return QFont::Bold; 221 case 900: 222 return QFont::Black; 223 } 224 return QFont::Normal; 225 } 226 227 void QSvgFontStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states) 228 { 229 m_oldQFont = p->font(); 230 m_oldSvgFont = states.svgFont; 231 m_oldTextAnchor = states.textAnchor; 232 m_oldWeight = states.fontWeight; 233 234 if (m_textAnchorSet) 235 states.textAnchor = m_textAnchor; 236 237 QFont font = m_oldQFont; 238 if (m_familySet) { 239 states.svgFont = m_svgFont; 240 font.setFamily(m_qfont.family()); 241 } 242 243 if (m_sizeSet) 244 font.setPointSize(m_qfont.pointSizeF()); 245 246 if (m_styleSet) 247 font.setStyle(m_qfont.style()); 248 249 if (m_variantSet) 250 font.setCapitalization(m_qfont.capitalization()); 251 252 if (m_weightSet) { 253 if (m_weight == BOLDER) { 254 states.fontWeight = qMin(states.fontWeight + 100, 900); 255 } else if (m_weight == LIGHTER) { 256 states.fontWeight = qMax(states.fontWeight - 100, 100); 257 } else { 258 states.fontWeight = m_weight; 259 } 260 font.setWeight(SVGToQtWeight(states.fontWeight)); 261 } 262 263 p->setFont(font); 264 } 265 266 void QSvgFontStyle::revert(QPainter *p, QSvgExtraStates &states) 267 { 268 p->setFont(m_oldQFont); 269 states.svgFont = m_oldSvgFont; 270 states.textAnchor = m_oldTextAnchor; 271 states.fontWeight = m_oldWeight; 272 } 273 274 QSvgStrokeStyle::QSvgStrokeStyle() 275 : m_strokeOpacity(1.0) 276 , m_oldStrokeOpacity(0.0) 277 , m_strokeDashOffset(0) 278 , m_oldStrokeDashOffset(0) 279 , m_style(0) 280 , m_gradientResolved(1) 281 , m_vectorEffect(0) 282 , m_oldVectorEffect(0) 283 , m_strokeSet(0) 284 , m_strokeDashArraySet(0) 285 , m_strokeDashOffsetSet(0) 286 , m_strokeLineCapSet(0) 287 , m_strokeLineJoinSet(0) 288 , m_strokeMiterLimitSet(0) 289 , m_strokeOpacitySet(0) 290 , m_strokeWidthSet(0) 291 , m_vectorEffectSet(0) 292 { 293 } 294 295 void QSvgStrokeStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states) 200 296 { 201 297 m_oldStroke = p->pen(); 202 p->setPen(m_stroke); 203 } 204 205 void QSvgStrokeStyle::revert(QPainter *p, QSvgExtraStates &) 298 m_oldStrokeOpacity = states.strokeOpacity; 299 m_oldStrokeDashOffset = states.strokeDashOffset; 300 m_oldVectorEffect = states.vectorEffect; 301 302 QPen pen = p->pen(); 303 304 qreal oldWidth = pen.widthF(); 305 qreal width = m_stroke.widthF(); 306 if (oldWidth == 0) 307 oldWidth = 1; 308 if (width == 0) 309 width = 1; 310 qreal scale = oldWidth / width; 311 312 if (m_strokeOpacitySet) 313 states.strokeOpacity = m_strokeOpacity; 314 315 if (m_vectorEffectSet) 316 states.vectorEffect = m_vectorEffect; 317 318 if (m_strokeSet) { 319 if (m_style) 320 pen.setBrush(m_style->brush(p, states)); 321 else 322 pen.setBrush(m_stroke.brush()); 323 } 324 325 if (m_strokeWidthSet) 326 pen.setWidthF(m_stroke.widthF()); 327 328 bool setDashOffsetNeeded = false; 329 330 if (m_strokeDashOffsetSet) { 331 states.strokeDashOffset = m_strokeDashOffset; 332 setDashOffsetNeeded = true; 333 } 334 335 if (m_strokeDashArraySet) { 336 if (m_stroke.style() == Qt::SolidLine) { 337 pen.setStyle(Qt::SolidLine); 338 } else if (m_strokeWidthSet || oldWidth == 1) { 339 // If both width and dash array was set, the dash array is already scaled correctly. 340 pen.setDashPattern(m_stroke.dashPattern()); 341 setDashOffsetNeeded = true; 342 } else { 343 // If dash array was set, but not the width, the dash array has to be scaled with respect to the old width. 344 QVector<qreal> dashes = m_stroke.dashPattern(); 345 for (int i = 0; i < dashes.size(); ++i) 346 dashes[i] /= oldWidth; 347 pen.setDashPattern(dashes); 348 setDashOffsetNeeded = true; 349 } 350 } else if (m_strokeWidthSet && pen.style() != Qt::SolidLine && scale != 1) { 351 // If the width was set, but not the dash array, the old dash array must be scaled with respect to the new width. 352 QVector<qreal> dashes = pen.dashPattern(); 353 for (int i = 0; i < dashes.size(); ++i) 354 dashes[i] *= scale; 355 pen.setDashPattern(dashes); 356 setDashOffsetNeeded = true; 357 } 358 359 if (m_strokeLineCapSet) 360 pen.setCapStyle(m_stroke.capStyle()); 361 if (m_strokeLineJoinSet) 362 pen.setJoinStyle(m_stroke.joinStyle()); 363 if (m_strokeMiterLimitSet) 364 pen.setMiterLimit(m_stroke.miterLimit()); 365 366 // You can have dash offset on solid strokes in SVG files, but not in Qt. 367 // QPen::setDashOffset() will set the pen style to Qt::CustomDashLine, 368 // so don't call the method if the pen is solid. 369 if (setDashOffsetNeeded && pen.style() != Qt::SolidLine) { 370 qreal currentWidth = pen.widthF(); 371 if (currentWidth == 0) 372 currentWidth = 1; 373 pen.setDashOffset(states.strokeDashOffset / currentWidth); 374 } 375 376 pen.setCosmetic(states.vectorEffect); 377 378 p->setPen(pen); 379 } 380 381 void QSvgStrokeStyle::revert(QPainter *p, QSvgExtraStates &states) 206 382 { 207 383 p->setPen(m_oldStroke); 384 states.strokeOpacity = m_oldStrokeOpacity; 385 states.strokeDashOffset = m_oldStrokeDashOffset; 386 states.vectorEffect = m_oldVectorEffect; 387 } 388 389 void QSvgStrokeStyle::setDashArray(const QVector<qreal> &dashes) 390 { 391 if (m_strokeWidthSet) { 392 QVector<qreal> d = dashes; 393 qreal w = m_stroke.widthF(); 394 if (w != 0 && w != 1) { 395 for (int i = 0; i < d.size(); ++i) 396 d[i] /= w; 397 } 398 m_stroke.setDashPattern(d); 399 } else { 400 m_stroke.setDashPattern(dashes); 401 } 402 m_strokeDashArraySet = 1; 208 403 } 209 404 … … 213 408 } 214 409 215 void QSvgSolidColorStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &)216 {217 m_oldFill = p->brush();218 m_oldStroke = p->pen();219 QBrush b = m_oldFill;220 b.setColor(m_solidColor);221 p->setBrush(b);222 QPen pen = m_oldStroke;223 pen.setColor(m_solidColor);224 p->setPen(pen);225 }226 227 void QSvgSolidColorStyle::revert(QPainter *p, QSvgExtraStates &)228 {229 p->setBrush(m_oldFill);230 p->setPen(m_oldStroke);231 }232 233 410 QSvgGradientStyle::QSvgGradientStyle(QGradient *grad) 234 411 : m_gradient(grad), m_gradientStopsSet(false) … … 236 413 } 237 414 238 void QSvgGradientStyle::apply(QPainter *p, const QRectF &/*rect*/, QSvgNode*, QSvgExtraStates &)415 QBrush QSvgGradientStyle::brush(QPainter *, QSvgExtraStates &) 239 416 { 240 417 if (!m_link.isEmpty()) { 241 418 resolveStops(); 242 }243 244 m_oldFill = p->brush();245 246 //resolving stop colors247 if (!m_resolvePoints.isEmpty()) {248 QColor color = p->brush().color();249 if (!color.isValid())250 color = p->pen().color();251 QList<qreal>::const_iterator itr = m_resolvePoints.constBegin();252 for (; itr != m_resolvePoints.constEnd(); ++itr) {253 //qDebug()<<"resolving "<<(*itr)<<" to "<<color;254 m_gradient->setColorAt(*itr, color);255 }256 419 } 257 420 … … 262 425 } 263 426 264 QBrush brush; 265 brush = QBrush(*m_gradient); 427 QBrush b(*m_gradient); 266 428 267 429 if (!m_matrix.isIdentity()) 268 brush.setMatrix(m_matrix); 269 270 p->setBrush(brush); 271 } 272 273 void QSvgGradientStyle::revert(QPainter *p, QSvgExtraStates &) 274 { 275 p->setBrush(m_oldFill); 430 b.setMatrix(m_matrix); 431 432 return b; 276 433 } 277 434 … … 280 437 { 281 438 m_matrix = mat; 282 }283 284 void QSvgGradientStyle::addResolve(qreal offset)285 {286 m_resolvePoints.append(offset);287 439 } 288 440 … … 390 542 if (stroke) { 391 543 stroke->apply(p, rect, node, states); 392 }393 394 if (solidColor) {395 solidColor->apply(p, rect, node, states);396 }397 398 if (gradient) {399 gradient->apply(p, rect, node, states);400 544 } 401 545 … … 411 555 //_after_ the original object transformations 412 556 if (!animateTransforms.isEmpty()) { 413 QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr; 414 for (itr = animateTransforms.constBegin(); itr != animateTransforms.constEnd(); 415 ++itr) { 416 (*itr)->apply(p, rect, node, states); 557 qreal totalTimeElapsed = node->document()->currentElapsed(); 558 // Find the last animateTransform with additive="replace", since this will override all 559 // previous animateTransforms. 560 QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr = animateTransforms.constEnd(); 561 do { 562 --itr; 563 if ((*itr)->animActive(totalTimeElapsed) 564 && (*itr)->additiveType() == QSvgAnimateTransform::Replace) { 565 // An animateTransform with additive="replace" will replace the transform attribute. 566 if (transform) 567 transform->revert(p, states); 568 break; 569 } 570 } while (itr != animateTransforms.constBegin()); 571 572 // Apply the animateTransforms after and including the last one with additive="replace". 573 for (; itr != animateTransforms.constEnd(); ++itr) { 574 if ((*itr)->animActive(totalTimeElapsed)) 575 (*itr)->apply(p, rect, node, states); 417 576 } 418 577 } … … 447 606 if (stroke) { 448 607 stroke->revert(p, states); 449 }450 451 if (solidColor) {452 solidColor->revert(p, states);453 }454 455 if (gradient) {456 gradient->revert(p, states);457 608 } 458 609 … … 460 611 //the native transforms 461 612 if (!animateTransforms.isEmpty()) { 462 QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr ;463 itr = animateTransforms.constBegin();464 //only need to rever the first one because that465 //one has the original world matrix for the primitve466 if (itr != animateTransforms.constEnd()) {467 (*itr)->revert(p, states);613 QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr = animateTransforms.constBegin(); 614 for (; itr != animateTransforms.constEnd(); ++itr) { 615 if ((*itr)->transformApplied()) { 616 (*itr)->revert(p, states); 617 break; 618 } 468 619 } 620 for (; itr != animateTransforms.constEnd(); ++itr) 621 (*itr)->clearTransformApplied(); 469 622 } 470 623 … … 489 642 : QSvgStyleProperty(), 490 643 m_from(startMs), m_to(endMs), m_by(byMs), 491 m_type(Empty), m_ count(0), m_finished(false)644 m_type(Empty), m_additive(Replace), m_count(0), m_finished(false), m_transformApplied(false) 492 645 { 493 646 m_totalRunningTime = m_to - m_from; 494 647 } 495 648 496 void QSvgAnimateTransform::setArgs(TransformType type, const QVector<qreal> &args)649 void QSvgAnimateTransform::setArgs(TransformType type, Additive additive, const QVector<qreal> &args) 497 650 { 498 651 m_type = type; 499 652 m_args = args; 653 m_additive = additive; 500 654 Q_ASSERT(!(args.count()%3)); 501 655 m_count = args.count() / 3; … … 506 660 m_oldWorldTransform = p->worldTransform(); 507 661 resolveMatrix(node); 508 if (!m_finished || m_freeze)509 p->setWorldTransform(m_transform, true);662 p->setWorldTransform(m_transform, true); 663 m_transformApplied = true; 510 664 } 511 665 512 666 void QSvgAnimateTransform::revert(QPainter *p, QSvgExtraStates &) 513 667 { 514 if (!m_finished || m_freeze) { 515 p->setWorldTransform(m_oldWorldTransform, false /* don't combine */); 516 } 668 p->setWorldTransform(m_oldWorldTransform, false /* don't combine */); 669 m_transformApplied = false; 517 670 } 518 671 … … 524 677 return; 525 678 526 qreal animationFrame = (totalTimeElapsed - m_from) / m_to; 527 528 if (m_repeatCount >= 0 && m_repeatCount < animationFrame) { 529 m_finished = true; 530 animationFrame = m_repeatCount; 679 qreal animationFrame = 0; 680 if (m_totalRunningTime != 0) { 681 animationFrame = (totalTimeElapsed - m_from) / m_totalRunningTime; 682 683 if (m_repeatCount >= 0 && m_repeatCount < animationFrame) { 684 m_finished = true; 685 animationFrame = m_repeatCount; 686 } 531 687 } 532 688 … … 545 701 startElem *= 3; 546 702 endElem *= 3; 547 qreal from1, from2 , from3;548 qreal to1, to2 , to3;703 qreal from1, from2; 704 qreal to1, to2; 549 705 from1 = m_args[startElem++]; 550 706 from2 = m_args[startElem++]; 551 from3 = m_args[startElem++];552 707 to1 = m_args[endElem++]; 553 708 to2 = m_args[endElem++]; 554 to3 = m_args[endElem++];555 709 556 710 qreal transXDiff = (to1-from1) * percentOfAnimation; … … 565 719 startElem *= 3; 566 720 endElem *= 3; 567 qreal from1, from2 , from3;568 qreal to1, to2 , to3;721 qreal from1, from2; 722 qreal to1, to2; 569 723 from1 = m_args[startElem++]; 570 724 from2 = m_args[startElem++]; 571 from3 = m_args[startElem++];572 725 to1 = m_args[endElem++]; 573 726 to2 = m_args[endElem++]; 574 to3 = m_args[endElem++];575 727 576 728 qreal transXDiff = (to1-from1) * percentOfAnimation; … … 612 764 startElem *= 3; 613 765 endElem *= 3; 614 qreal from1 , from2, from3;615 qreal to1 , to2, to3;766 qreal from1; 767 qreal to1; 616 768 from1 = m_args[startElem++]; 617 from2 = m_args[startElem++];618 from3 = m_args[startElem++];619 769 to1 = m_args[endElem++]; 620 to2 = m_args[endElem++];621 to3 = m_args[endElem++];622 770 623 771 qreal transXDiff = (to1-from1) * percentOfAnimation; 624 772 qreal transX = from1 + transXDiff; 625 773 m_transform = QTransform(); 626 m_transform.shear( tan(transX * deg2rad), 0);774 m_transform.shear(qTan(transX * deg2rad), 0); 627 775 break; 628 776 } … … 630 778 startElem *= 3; 631 779 endElem *= 3; 632 qreal from1 , from2, from3;633 qreal to1 , to2, to3;780 qreal from1; 781 qreal to1; 634 782 from1 = m_args[startElem++]; 635 from2 = m_args[startElem++];636 from3 = m_args[startElem++];637 783 to1 = m_args[endElem++]; 638 to2 = m_args[endElem++];639 to3 = m_args[endElem++];640 784 641 785 … … 643 787 qreal transY = from1 + transYDiff; 644 788 m_transform = QTransform(); 645 m_transform.shear(0, tan(transY * deg2rad));789 m_transform.shear(0, qTan(transY * deg2rad)); 646 790 break; 647 791 } … … 697 841 return; 698 842 699 qreal animationFrame = (totalTimeElapsed - m_from) / m_to; 843 qreal animationFrame = 0; 844 if (m_totalRunningTime != 0) 845 animationFrame = (totalTimeElapsed - m_from) / m_totalRunningTime; 700 846 701 847 if (m_repeatCount >= 0 && m_repeatCount < animationFrame) { … … 761 907 } 762 908 763 QString QSvgFontStyle::textAnchor() const764 {765 return m_textAnchor;766 }767 768 void QSvgFontStyle::setTextAnchor(const QString &anchor)769 {770 m_textAnchor = anchor;771 }772 773 909 QSvgOpacityStyle::QSvgOpacityStyle(qreal opacity) 774 : m_opacity(opacity) 910 : m_opacity(opacity), m_oldOpacity(0) 775 911 { 776 912 … … 802 938 { 803 939 if (!m_link.isEmpty() && m_doc) { 804 QSvgStyleProperty *prop = m_doc->s copeStyle(m_link);940 QSvgStyleProperty *prop = m_doc->styleProperty(m_link); 805 941 if (prop) { 806 942 if (prop->type() == QSvgStyleProperty::GRADIENT) { … … 809 945 st->resolveStops(); 810 946 m_gradient->setStops(st->qgradient()->stops()); 947 m_gradientStopsSet = st->gradientStopsSet(); 811 948 } 949 } else { 950 qWarning("Could not resolve property : %s", qPrintable(m_link)); 812 951 } 813 952 m_link = QString(); -
trunk/src/svg/qsvgstyle_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 142 142 { 143 143 QSvgExtraStates(); 144 144 145 qreal fillOpacity; 146 qreal strokeOpacity; 147 QSvgFont *svgFont; 148 Qt::Alignment textAnchor; 149 int fontWeight; 150 Qt::FillRule fillRule; 151 qreal strokeDashOffset; 152 bool vectorEffect; // true if pen is cosmetic 145 153 }; 146 154 … … 170 178 }; 171 179 180 class QSvgFillStyleProperty : public QSvgStyleProperty 181 { 182 public: 183 virtual QBrush brush(QPainter *p, QSvgExtraStates &states) = 0; 184 virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); 185 virtual void revert(QPainter *p, QSvgExtraStates &states); 186 }; 187 172 188 class QSvgQualityStyle : public QSvgStyleProperty 173 189 { … … 217 233 { 218 234 public: 219 QSvgFillStyle(const QBrush &brush); 220 QSvgFillStyle(QSvgStyleProperty *style); 235 QSvgFillStyle(); 221 236 virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); 222 237 virtual void revert(QPainter *p, QSvgExtraStates &states); … … 225 240 void setFillRule(Qt::FillRule f); 226 241 void setFillOpacity(qreal opacity); 242 void setFillStyle(QSvgFillStyleProperty* style); 243 void setBrush(QBrush brush); 227 244 228 245 const QBrush & qbrush() const … … 230 247 return m_fill; 231 248 } 249 250 qreal fillOpacity() const 251 { 252 return m_fillOpacity; 253 } 254 255 Qt::FillRule fillRule() const 256 { 257 return m_fillRule; 258 } 259 260 QSvgFillStyleProperty* style() const 261 { 262 return m_style; 263 } 264 265 void setGradientId(const QString &Id) 266 { 267 m_gradientId = Id; 268 } 269 270 QString gradientId() const 271 { 272 return m_gradientId; 273 } 274 275 void setGradientResolved(bool resolved) 276 { 277 m_gradientResolved = resolved; 278 } 279 280 bool isGradientResolved() const 281 { 282 return m_gradientResolved; 283 } 284 232 285 private: 233 286 // fill v v 'inherit' | <Paint.datatype> … … 235 288 QBrush m_fill; 236 289 QBrush m_oldFill; 237 QSvgStyleProperty *m_style; 238 239 bool m_fillRuleSet; 290 QSvgFillStyleProperty *m_style; 291 240 292 Qt::FillRule m_fillRule; 241 bool m_fillOpacitySet;293 Qt::FillRule m_oldFillRule; 242 294 qreal m_fillOpacity; 243 qreal m_oldOpacity; 295 qreal m_oldFillOpacity; 296 297 QString m_gradientId; 298 uint m_gradientResolved : 1; 299 300 uint m_fillRuleSet : 1; 301 uint m_fillOpacitySet : 1; 302 uint m_fillSet : 1; 244 303 }; 245 304 … … 267 326 { 268 327 public: 328 static const int LIGHTER = -1; 329 static const int BOLDER = 1; 330 269 331 QSvgFontStyle(QSvgFont *font, QSvgTinyDocument *doc); 270 QSvgFontStyle(const QFont &font, QSvgTinyDocument *doc); 271 virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); 272 virtual void revert(QPainter *p, QSvgExtraStates &states); 273 virtual Type type() const; 274 275 void setPointSize(qreal size); 276 qreal pointSize() const; 277 278 //### hack to avoid having a separate style element for text-anchor 279 QString textAnchor() const; 280 void setTextAnchor(const QString &anchor); 332 QSvgFontStyle(); 333 virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); 334 virtual void revert(QPainter *p, QSvgExtraStates &states); 335 virtual Type type() const; 336 337 void setSize(qreal size) 338 { 339 // Store the _pixel_ size in the font. Since QFont::setPixelSize() only takes an int, call 340 // QFont::SetPointSize() instead. Set proper font size just before rendering. 341 m_qfont.setPointSize(size); 342 m_sizeSet = 1; 343 } 344 345 void setTextAnchor(Qt::Alignment anchor) 346 { 347 m_textAnchor = anchor; 348 m_textAnchorSet = 1; 349 } 350 351 void setFamily(const QString &family) 352 { 353 m_qfont.setFamily(family); 354 m_familySet = 1; 355 } 356 357 void setStyle(QFont::Style fontStyle) { 358 m_qfont.setStyle(fontStyle); 359 m_styleSet = 1; 360 } 361 362 void setVariant(QFont::Capitalization fontVariant) 363 { 364 m_qfont.setCapitalization(fontVariant); 365 m_variantSet = 1; 366 } 367 368 static int SVGToQtWeight(int weight); 369 370 void setWeight(int weight) 371 { 372 m_weight = weight; 373 m_weightSet = 1; 374 } 281 375 282 376 QSvgFont * svgFont() const 283 377 { 284 return m_font; 285 } 286 QSvgTinyDocument *doc() const 287 { 288 return m_doc; 289 } 290 291 const QFont & qfont() const 378 return m_svgFont; 379 } 380 381 const QFont &qfont() const 292 382 { 293 383 return m_qfont; 294 384 } 295 private: 296 QSvgFont *m_font; 297 qreal m_pointSize; 385 386 QSvgTinyDocument *doc() const {return m_doc;} 387 388 private: 389 QSvgFont *m_svgFont; 298 390 QSvgTinyDocument *m_doc; 299 300 QString m_textAnchor;301 302 391 QFont m_qfont; 303 QFont m_oldFont; 392 393 int m_weight; 394 Qt::Alignment m_textAnchor; 395 396 QSvgFont *m_oldSvgFont; 397 QFont m_oldQFont; 398 Qt::Alignment m_oldTextAnchor; 399 int m_oldWeight; 400 401 uint m_familySet : 1; 402 uint m_sizeSet : 1; 403 uint m_styleSet : 1; 404 uint m_variantSet : 1; 405 uint m_weightSet : 1; 406 uint m_textAnchorSet : 1; 304 407 }; 305 408 … … 307 410 { 308 411 public: 309 QSvgStrokeStyle(const QPen &pen); 310 virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); 311 virtual void revert(QPainter *p, QSvgExtraStates &states); 312 virtual Type type() const; 313 314 const QPen & qpen() const 412 QSvgStrokeStyle(); 413 virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); 414 virtual void revert(QPainter *p, QSvgExtraStates &states); 415 virtual Type type() const; 416 417 void setStroke(QBrush brush) 418 { 419 m_stroke.setBrush(brush); 420 m_style = 0; 421 m_strokeSet = 1; 422 } 423 424 void setStyle(QSvgFillStyleProperty *style) 425 { 426 m_style = style; 427 m_strokeSet = 1; 428 } 429 430 void setDashArray(const QVector<qreal> &dashes); 431 432 void setDashArrayNone() 433 { 434 m_stroke.setStyle(Qt::SolidLine); 435 m_strokeDashArraySet = 1; 436 } 437 438 void setDashOffset(qreal offset) 439 { 440 m_strokeDashOffset = offset; 441 m_strokeDashOffsetSet = 1; 442 } 443 444 void setLineCap(Qt::PenCapStyle cap) 445 { 446 m_stroke.setCapStyle(cap); 447 m_strokeLineCapSet = 1; 448 } 449 450 void setLineJoin(Qt::PenJoinStyle join) 451 { 452 m_stroke.setJoinStyle(join); 453 m_strokeLineJoinSet = 1; 454 } 455 456 void setMiterLimit(qreal limit) 457 { 458 m_stroke.setMiterLimit(limit); 459 m_strokeMiterLimitSet = 1; 460 } 461 462 void setOpacity(qreal opacity) 463 { 464 m_strokeOpacity = opacity; 465 m_strokeOpacitySet = 1; 466 } 467 468 void setWidth(qreal width) 469 { 470 m_stroke.setWidthF(width); 471 m_strokeWidthSet = 1; 472 Q_ASSERT(!m_strokeDashArraySet); // set width before dash array. 473 } 474 475 qreal width() 476 { 477 return m_stroke.widthF(); 478 } 479 480 void setVectorEffect(bool nonScalingStroke) 481 { 482 m_vectorEffect = nonScalingStroke; 483 m_vectorEffectSet = 1; 484 } 485 486 QSvgFillStyleProperty* style() const 487 { 488 return m_style; 489 } 490 491 void setGradientId(const QString &Id) 492 { 493 m_gradientId = Id; 494 } 495 496 QString gradientId() const 497 { 498 return m_gradientId; 499 } 500 501 void setGradientResolved(bool resolved) 502 { 503 m_gradientResolved = resolved; 504 } 505 506 bool isGradientResolved() const 507 { 508 return m_gradientResolved; 509 } 510 511 QPen stroke() const 315 512 { 316 513 return m_stroke; 317 514 } 515 318 516 private: 319 517 // stroke v v 'inherit' | <Paint.datatype> … … 326 524 // stroke-width v v 'inherit' | <StrokeWidthValue.datatype> 327 525 QPen m_stroke; 328 329 526 QPen m_oldStroke; 330 }; 331 332 333 class QSvgSolidColorStyle : public QSvgStyleProperty 527 qreal m_strokeOpacity; 528 qreal m_oldStrokeOpacity; 529 qreal m_strokeDashOffset; 530 qreal m_oldStrokeDashOffset; 531 532 QSvgFillStyleProperty *m_style; 533 QString m_gradientId; 534 uint m_gradientResolved : 1; 535 uint m_vectorEffect : 1; 536 uint m_oldVectorEffect : 1; 537 538 uint m_strokeSet : 1; 539 uint m_strokeDashArraySet : 1; 540 uint m_strokeDashOffsetSet : 1; 541 uint m_strokeLineCapSet : 1; 542 uint m_strokeLineJoinSet : 1; 543 uint m_strokeMiterLimitSet : 1; 544 uint m_strokeOpacitySet : 1; 545 uint m_strokeWidthSet : 1; 546 uint m_vectorEffectSet : 1; 547 }; 548 549 class QSvgSolidColorStyle : public QSvgFillStyleProperty 334 550 { 335 551 public: 336 552 QSvgSolidColorStyle(const QColor &color); 337 virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states);338 virtual void revert(QPainter *p, QSvgExtraStates &states);339 553 virtual Type type() const; 340 554 … … 343 557 return m_solidColor; 344 558 } 559 560 QBrush brush(QPainter *, QSvgExtraStates &) 561 { 562 return m_solidColor; 563 } 564 345 565 private: 346 566 // solid-color v x 'inherit' | <SVGColor.datatype> … … 352 572 }; 353 573 354 class QSvgGradientStyle : public QSvg StyleProperty574 class QSvgGradientStyle : public QSvgFillStyleProperty 355 575 { 356 576 public: 357 577 QSvgGradientStyle(QGradient *grad); 358 578 ~QSvgGradientStyle() { delete m_gradient; } 359 virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states);360 virtual void revert(QPainter *p, QSvgExtraStates &states);361 579 virtual Type type() const; 362 580 … … 376 594 } 377 595 378 void addResolve(qreal offset);379 380 596 bool gradientStopsSet() const 381 597 { … … 387 603 m_gradientStopsSet = set; 388 604 } 605 606 QBrush brush(QPainter *, QSvgExtraStates &); 389 607 private: 390 608 QGradient *m_gradient; 391 QList<qreal> m_resolvePoints;392 393 QBrush m_oldFill;394 395 609 QMatrix m_matrix; 396 610 … … 431 645 SkewY 432 646 }; 647 enum Additive 648 { 649 Sum, 650 Replace 651 }; 433 652 public: 434 653 QSvgAnimateTransform(int startMs, int endMs, int by = 0); 435 void setArgs(TransformType type, const QVector<qreal> &args);654 void setArgs(TransformType type, Additive additive, const QVector<qreal> &args); 436 655 void setFreeze(bool freeze); 437 656 void setRepeatCount(qreal repeatCount); … … 439 658 virtual void revert(QPainter *p, QSvgExtraStates &states); 440 659 virtual Type type() const; 660 QSvgAnimateTransform::Additive additiveType() const 661 { 662 return m_additive; 663 } 664 665 bool animActive(qreal totalTimeElapsed) 666 { 667 if (totalTimeElapsed < m_from) 668 return false; 669 if (m_freeze || m_repeatCount < 0) // fill="freeze" or repeat="indefinite" 670 return true; 671 if (m_totalRunningTime == 0) 672 return false; 673 qreal animationFrame = (totalTimeElapsed - m_from) / m_totalRunningTime; 674 if (animationFrame > m_repeatCount) 675 return false; 676 return true; 677 } 678 679 bool transformApplied() const 680 { 681 return m_transformApplied; 682 } 683 684 // Call this instead of revert if you know that revert is unnecessary. 685 void clearTransformApplied() 686 { 687 m_transformApplied = false; 688 } 689 441 690 protected: 442 691 void resolveMatrix(QSvgNode *node); … … 445 694 qreal m_totalRunningTime; 446 695 TransformType m_type; 696 Additive m_additive; 447 697 QVector<qreal> m_args; 448 698 int m_count; … … 452 702 bool m_freeze; 453 703 qreal m_repeatCount; 704 bool m_transformApplied; 454 705 }; 455 706 -
trunk/src/svg/qsvgtinydocument.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 62 62 63 63 QSvgTinyDocument::QSvgTinyDocument() 64 : QSvgStructureNode(0), 65 m_animated(false), 66 m_animationDuration(0), 67 m_fps(30) 64 : QSvgStructureNode(0) 65 , m_widthPercent(false) 66 , m_heightPercent(false) 67 , m_animated(false) 68 , m_animationDuration(0) 69 , m_fps(30) 68 70 { 69 71 } … … 232 234 } 233 235 236 if (displayMode() == QSvgNode::NoneMode) 237 return; 238 234 239 p->save(); 235 236 240 //sets default style on the painter 237 241 //### not the most optimal way 238 242 mapSourceToTarget(p, bounds); 239 p->setPen(Qt::NoPen); 243 QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); 244 pen.setMiterLimit(4); 245 p->setPen(pen); 240 246 p->setBrush(Qt::black); 241 247 p->setRenderHint(QPainter::Antialiasing); … … 245 251 while (itr != m_renderers.end()) { 246 252 QSvgNode *node = *itr; 247 if ( node->isVisible())253 if ((node->isVisible()) && (node->displayMode() != QSvgNode::NoneMode)) 248 254 node->draw(p, m_states); 249 255 ++itr; … … 263 269 return; 264 270 } 271 if (m_time.isNull()) { 272 m_time.start(); 273 } 274 275 if (node->displayMode() == QSvgNode::NoneMode) 276 return; 265 277 266 278 p->save(); … … 272 284 273 285 //XXX set default style on the painter 274 p->setPen(Qt::NoPen); 286 QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); 287 pen.setMiterLimit(4); 288 p->setPen(pen); 275 289 p->setBrush(Qt::black); 276 290 p->setRenderHint(QPainter::Antialiasing); … … 335 349 { 336 350 return m_fonts[family]; 351 } 352 353 void QSvgTinyDocument::addNamedNode(const QString &id, QSvgNode *node) 354 { 355 m_namedNodes.insert(id, node); 356 } 357 358 QSvgNode *QSvgTinyDocument::namedNode(const QString &id) const 359 { 360 return m_namedNodes.value(id); 361 } 362 363 void QSvgTinyDocument::addNamedStyle(const QString &id, QSvgFillStyleProperty *style) 364 { 365 m_namedStyles.insert(id, style); 366 } 367 368 QSvgFillStyleProperty *QSvgTinyDocument::namedStyle(const QString &id) const 369 { 370 return m_namedStyles.value(id); 337 371 } 338 372 -
trunk/src/svg/qsvgtinydocument_p.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 109 109 void addSvgFont(QSvgFont *); 110 110 QSvgFont *svgFont(const QString &family) const; 111 void addNamedNode(const QString &id, QSvgNode *node); 112 QSvgNode *namedNode(const QString &id) const; 113 void addNamedStyle(const QString &id, QSvgFillStyleProperty *style); 114 QSvgFillStyleProperty *namedStyle(const QString &id) const; 111 115 112 116 void restartAnimation(); … … 128 132 129 133 QHash<QString, QSvgRefCounter<QSvgFont> > m_fonts; 134 QHash<QString, QSvgNode *> m_namedNodes; 135 QHash<QString, QSvgRefCounter<QSvgFillStyleProperty> > m_namedStyles; 130 136 131 137 QTime m_time; -
trunk/src/svg/qsvgwidget.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 53 53 /*! 54 54 \class QSvgWidget 55 \ingroup multimedia55 \ingroup painting 56 56 57 57 \brief The QSvgWidget class provides a widget that is used to display the contents of … … 84 84 Q_DECLARE_PUBLIC(QSvgWidget) 85 85 public: 86 QSvgWidgetPrivate()87 : QWidgetPrivate()88 {89 Q_Q(QSvgWidget);90 renderer = new QSvgRenderer(q);91 }92 QSvgWidgetPrivate(const QString &file)93 : QWidgetPrivate()94 {95 Q_Q(QSvgWidget);96 renderer = new QSvgRenderer(file, q);97 }98 86 QSvgRenderer *renderer; 99 87 }; … … 105 93 : QWidget(*new QSvgWidgetPrivate, parent, 0) 106 94 { 95 d_func()->renderer = new QSvgRenderer(this); 107 96 QObject::connect(d_func()->renderer, SIGNAL(repaintNeeded()), 108 97 this, SLOT(update())); … … 114 103 */ 115 104 QSvgWidget::QSvgWidget(const QString &file, QWidget *parent) 116 : QWidget(*new QSvgWidgetPrivate (file), parent, 0)105 : QWidget(*new QSvgWidgetPrivate, parent, 0) 117 106 { 107 d_func()->renderer = new QSvgRenderer(file, this); 118 108 QObject::connect(d_func()->renderer, SIGNAL(repaintNeeded()), 119 109 this, SLOT(update())); -
trunk/src/svg/qsvgwidget.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtSvg module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/svg/svg.pro
r2 r561 41 41 INCLUDEPATH += ../3rdparty/harfbuzz/src 42 42 43 symbian:TARGET.UID3=0x2001B2E2 44 43 45 #zlib support 44 46 contains(QT_CONFIG, zlib) { 45 47 INCLUDEPATH += ../3rdparty/zlib 46 48 } else:!contains(QT_CONFIG, no-zlib) { 47 unix:LIBS += -lz49 unix:LIBS_PRIVATE += -lz 48 50 }
Note:
See TracChangeset
for help on using the changeset viewer.