diff options
Diffstat (limited to 'src/svg/qsvgnode.cpp')
-rw-r--r-- | src/svg/qsvgnode.cpp | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/src/svg/qsvgnode.cpp b/src/svg/qsvgnode.cpp new file mode 100644 index 0000000..5751f80 --- /dev/null +++ b/src/svg/qsvgnode.cpp @@ -0,0 +1,345 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtSvg module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsvgnode_p.h" +#include "qsvgtinydocument_p.h" + +#ifndef QT_NO_SVG + +#include "qdebug.h" +#include "qstack.h" + +QT_BEGIN_NAMESPACE + +QSvgNode::QSvgNode(QSvgNode *parent) + : m_parent(parent), + m_visible(true), + m_displayMode(BlockMode) +{ +} + +QSvgNode::~QSvgNode() +{ + +} + +void QSvgNode::appendStyleProperty(QSvgStyleProperty *prop, const QString &id) +{ + //qDebug()<<"appending "<<prop->type()<< " ("<< id <<") "<<"to "<<this<<this->type(); + QSvgTinyDocument *doc; + switch (prop->type()) { + case QSvgStyleProperty::QUALITY: + m_style.quality = static_cast<QSvgQualityStyle*>(prop); + break; + case QSvgStyleProperty::FILL: + m_style.fill = static_cast<QSvgFillStyle*>(prop); + break; + case QSvgStyleProperty::VIEWPORT_FILL: + m_style.viewportFill = static_cast<QSvgViewportFillStyle*>(prop); + break; + case QSvgStyleProperty::FONT: + m_style.font = static_cast<QSvgFontStyle*>(prop); + break; + case QSvgStyleProperty::STROKE: + m_style.stroke = static_cast<QSvgStrokeStyle*>(prop); + break; + case QSvgStyleProperty::SOLID_COLOR: + m_style.solidColor = static_cast<QSvgSolidColorStyle*>(prop); + doc = document(); + if (doc && !id.isEmpty()) + doc->addNamedStyle(id, m_style.solidColor); + break; + case QSvgStyleProperty::GRADIENT: + m_style.gradient = static_cast<QSvgGradientStyle*>(prop); + doc = document(); + if (doc && !id.isEmpty()) + doc->addNamedStyle(id, m_style.gradient); + break; + case QSvgStyleProperty::TRANSFORM: + m_style.transform = static_cast<QSvgTransformStyle*>(prop); + break; + case QSvgStyleProperty::ANIMATE_COLOR: + m_style.animateColor = static_cast<QSvgAnimateColor*>(prop); + break; + case QSvgStyleProperty::ANIMATE_TRANSFORM: + m_style.animateTransforms.append( + static_cast<QSvgAnimateTransform*>(prop)); + break; + case QSvgStyleProperty::OPACITY: + m_style.opacity = static_cast<QSvgOpacityStyle*>(prop); + break; + case QSvgStyleProperty::COMP_OP: + m_style.compop = static_cast<QSvgCompOpStyle*>(prop); + break; + default: + qDebug("QSvgNode: Trying to append unknown property!"); + break; + } +} + +void QSvgNode::applyStyle(QPainter *p, QSvgExtraStates &states) const +{ + m_style.apply(p, this, states); +} + +void QSvgNode::revertStyle(QPainter *p, QSvgExtraStates &states) const +{ + m_style.revert(p, states); +} + +QSvgStyleProperty * QSvgNode::styleProperty(QSvgStyleProperty::Type type) const +{ + const QSvgNode *node = this; + while (node) { + switch (type) { + case QSvgStyleProperty::QUALITY: + if (node->m_style.quality) + return node->m_style.quality; + break; + case QSvgStyleProperty::FILL: + if (node->m_style.fill) + return node->m_style.fill; + break; + case QSvgStyleProperty::VIEWPORT_FILL: + if (m_style.viewportFill) + return node->m_style.viewportFill; + break; + case QSvgStyleProperty::FONT: + if (node->m_style.font) + return node->m_style.font; + break; + case QSvgStyleProperty::STROKE: + if (node->m_style.stroke) + return node->m_style.stroke; + break; + case QSvgStyleProperty::SOLID_COLOR: + if (node->m_style.solidColor) + return node->m_style.solidColor; + break; + case QSvgStyleProperty::GRADIENT: + if (node->m_style.gradient) + return node->m_style.gradient; + break; + case QSvgStyleProperty::TRANSFORM: + if (node->m_style.transform) + return node->m_style.transform; + break; + case QSvgStyleProperty::ANIMATE_COLOR: + if (node->m_style.animateColor) + return node->m_style.animateColor; + break; + case QSvgStyleProperty::ANIMATE_TRANSFORM: + if (!node->m_style.animateTransforms.isEmpty()) + return node->m_style.animateTransforms.first(); + break; + case QSvgStyleProperty::OPACITY: + if (node->m_style.opacity) + return node->m_style.opacity; + break; + case QSvgStyleProperty::COMP_OP: + if (node->m_style.compop) + return node->m_style.compop; + break; + default: + break; + } + node = node->parent(); + } + + return 0; +} + +QSvgFillStyleProperty * QSvgNode::styleProperty(const QString &id) const +{ + QString rid = id; + if (rid.startsWith(QLatin1Char('#'))) + rid.remove(0, 1); + QSvgTinyDocument *doc = document(); + return doc ? doc->namedStyle(rid) : 0; +} + +QRectF QSvgNode::bounds(QPainter *, QSvgExtraStates &) const +{ + return QRectF(0, 0, 0, 0); +} + +QRectF QSvgNode::transformedBounds() const +{ + if (!m_cachedBounds.isEmpty()) + return m_cachedBounds; + + QImage dummy(1, 1, QImage::Format_RGB32); + QPainter p(&dummy); + QSvgExtraStates states; + + QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); + pen.setMiterLimit(4); + p.setPen(pen); + + QStack<QSvgNode*> parentApplyStack; + QSvgNode *parent = m_parent; + while (parent) { + parentApplyStack.push(parent); + parent = parent->parent(); + } + + for (int i = parentApplyStack.size() - 1; i >= 0; --i) + parentApplyStack[i]->applyStyle(&p, states); + + p.setWorldTransform(QTransform()); + + m_cachedBounds = transformedBounds(&p, states); + return m_cachedBounds; +} + +QSvgTinyDocument * QSvgNode::document() const +{ + QSvgTinyDocument *doc = 0; + QSvgNode *node = const_cast<QSvgNode*>(this); + while (node && node->type() != QSvgNode::DOC) { + node = node->parent(); + } + doc = static_cast<QSvgTinyDocument*>(node); + + return doc; +} + +void QSvgNode::setRequiredFeatures(const QStringList &lst) +{ + m_requiredFeatures = lst; +} + +const QStringList & QSvgNode::requiredFeatures() const +{ + return m_requiredFeatures; +} + +void QSvgNode::setRequiredExtensions(const QStringList &lst) +{ + m_requiredExtensions = lst; +} + +const QStringList & QSvgNode::requiredExtensions() const +{ + return m_requiredExtensions; +} + +void QSvgNode::setRequiredLanguages(const QStringList &lst) +{ + m_requiredLanguages = lst; +} + +const QStringList & QSvgNode::requiredLanguages() const +{ + return m_requiredLanguages; +} + +void QSvgNode::setRequiredFormats(const QStringList &lst) +{ + m_requiredFormats = lst; +} + +const QStringList & QSvgNode::requiredFormats() const +{ + return m_requiredFormats; +} + +void QSvgNode::setRequiredFonts(const QStringList &lst) +{ + m_requiredFonts = lst; +} + +const QStringList & QSvgNode::requiredFonts() const +{ + return m_requiredFonts; +} + +void QSvgNode::setVisible(bool visible) +{ + //propagate visibility change of true to the parent + //not propagating false is just a small performance + //degradation since we'll iterate over children without + //drawing any of them + if (m_parent && visible && !m_parent->isVisible()) + m_parent->setVisible(true); + + m_visible = visible; +} + +QRectF QSvgNode::transformedBounds(QPainter *p, QSvgExtraStates &states) const +{ + applyStyle(p, states); + QRectF rect = bounds(p, states); + revertStyle(p, states); + return rect; +} + +void QSvgNode::setNodeId(const QString &i) +{ + m_id = i; +} + +void QSvgNode::setXmlClass(const QString &str) +{ + m_class = str; +} + +void QSvgNode::setDisplayMode(DisplayMode mode) +{ + m_displayMode = mode; +} + +QSvgNode::DisplayMode QSvgNode::displayMode() const +{ + return m_displayMode; +} + +qreal QSvgNode::strokeWidth(QPainter *p) +{ + QPen pen = p->pen(); + if (pen.style() == Qt::NoPen || pen.brush().style() == Qt::NoBrush || pen.isCosmetic()) + return 0; + return pen.widthF(); +} + +QT_END_NAMESPACE + +#endif // QT_NO_SVG |