/**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtSvg module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** 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, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QSVGSTYLE_P_H #define QSVGSTYLE_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "QtGui/qpainter.h" #ifndef QT_NO_SVG #include "QtGui/qpen.h" #include "QtGui/qbrush.h" #include "QtGui/qmatrix.h" #include "QtGui/qcolor.h" #include "QtGui/qfont.h" #include QT_BEGIN_NAMESPACE class QPainter; class QSvgNode; class QSvgFont; class QSvgTinyDocument; template class QSvgRefCounter { public: QSvgRefCounter() { t = 0; } QSvgRefCounter(T *_t) { t = _t; if (t) t->ref(); } QSvgRefCounter(const QSvgRefCounter &other) { t = other.t; if (t) t->ref(); } QSvgRefCounter &operator =(T *_t) { if(_t) _t->ref(); if (t) t->deref(); t = _t; return *this; } QSvgRefCounter &operator =(const QSvgRefCounter &other) { if(other.t) other.t->ref(); if (t) t->deref(); t = other.t; return *this; } ~QSvgRefCounter() { if (t) t->deref(); } inline T *operator->() const { return t; } inline operator T*() const { return t; } private: T *t; }; class QSvgRefCounted { public: QSvgRefCounted() { _ref = 0; } virtual ~QSvgRefCounted() {} void ref() { ++_ref; // qDebug() << this << ": adding ref, now " << _ref; } void deref() { // qDebug() << this << ": removing ref, now " << _ref; if(!--_ref) { // qDebug(" deleting"); delete this; } } private: int _ref; }; struct QSvgExtraStates { QSvgExtraStates(); qreal fillOpacity; qreal strokeOpacity; QSvgFont *svgFont; Qt::Alignment textAnchor; int fontWeight; Qt::FillRule fillRule; qreal strokeDashOffset; bool vectorEffect; // true if pen is cosmetic }; class QSvgStyleProperty : public QSvgRefCounted { public: enum Type { QUALITY, FILL, VIEWPORT_FILL, FONT, STROKE, SOLID_COLOR, GRADIENT, TRANSFORM, ANIMATE_TRANSFORM, ANIMATE_COLOR, OPACITY, COMP_OP }; public: virtual ~QSvgStyleProperty(); virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) = 0; virtual void revert(QPainter *p, QSvgExtraStates &states) =0; virtual Type type() const=0; }; class QSvgFillStyleProperty : public QSvgStyleProperty { public: virtual QBrush brush(QPainter *p, QSvgExtraStates &states) = 0; virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); }; class QSvgQualityStyle : public QSvgStyleProperty { public: QSvgQualityStyle(int color); virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; private: // color-render ing v v 'auto' | 'optimizeSpeed' | // 'optimizeQuality' | 'inherit' int m_colorRendering; // shape-rendering v v 'auto' | 'optimizeSpeed' | 'crispEdges' | // 'geometricPrecision' | 'inherit' //QSvgShapeRendering m_shapeRendering; // text-rendering v v 'auto' | 'optimizeSpeed' | 'optimizeLegibility' // | 'geometricPrecision' | 'inherit' //QSvgTextRendering m_textRendering; // vector-effect v x 'default' | 'non-scaling-stroke' | 'inherit' //QSvgVectorEffect m_vectorEffect; // image-rendering v v 'auto' | 'optimizeSpeed' | 'optimizeQuality' | // 'inherit' //QSvgImageRendering m_imageRendering; }; class QSvgOpacityStyle : public QSvgStyleProperty { public: QSvgOpacityStyle(qreal opacity); virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; private: qreal m_opacity; qreal m_oldOpacity; }; class QSvgFillStyle : public QSvgStyleProperty { public: QSvgFillStyle(); virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; void setFillRule(Qt::FillRule f); void setFillOpacity(qreal opacity); void setFillStyle(QSvgFillStyleProperty* style); void setBrush(QBrush brush); const QBrush & qbrush() const { return m_fill; } qreal fillOpacity() const { return m_fillOpacity; } Qt::FillRule fillRule() const { return m_fillRule; } QSvgFillStyleProperty* style() const { return m_style; } void setGradientId(const QString &Id) { m_gradientId = Id; } QString gradientId() const { return m_gradientId; } void setGradientResolved(bool resolved) { m_gradientResolved = resolved; } bool isGradientResolved() const { return m_gradientResolved; } private: // fill v v 'inherit' | // fill-opacity v v 'inherit' | QBrush m_fill; QBrush m_oldFill; QSvgFillStyleProperty *m_style; Qt::FillRule m_fillRule; Qt::FillRule m_oldFillRule; qreal m_fillOpacity; qreal m_oldFillOpacity; QString m_gradientId; uint m_gradientResolved : 1; uint m_fillRuleSet : 1; uint m_fillOpacitySet : 1; uint m_fillSet : 1; }; class QSvgViewportFillStyle : public QSvgStyleProperty { public: QSvgViewportFillStyle(const QBrush &brush); virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; const QBrush & qbrush() const { return m_viewportFill; } private: // viewport-fill v x 'inherit' | // viewport-fill-opacity v x 'inherit' | QBrush m_viewportFill; QBrush m_oldFill; }; class QSvgFontStyle : public QSvgStyleProperty { public: static const int LIGHTER = -1; static const int BOLDER = 1; QSvgFontStyle(QSvgFont *font, QSvgTinyDocument *doc); QSvgFontStyle(); virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; void setSize(qreal size) { // Store the _pixel_ size in the font. Since QFont::setPixelSize() only takes an int, call // QFont::SetPointSize() instead. Set proper font size just before rendering. m_qfont.setPointSizeF(size); m_sizeSet = 1; } void setTextAnchor(Qt::Alignment anchor) { m_textAnchor = anchor; m_textAnchorSet = 1; } void setFamily(const QString &family) { m_qfont.setFamily(family); m_familySet = 1; } void setStyle(QFont::Style fontStyle) { m_qfont.setStyle(fontStyle); m_styleSet = 1; } void setVariant(QFont::Capitalization fontVariant) { m_qfont.setCapitalization(fontVariant); m_variantSet = 1; } static int SVGToQtWeight(int weight); void setWeight(int weight) { m_weight = weight; m_weightSet = 1; } QSvgFont * svgFont() const { return m_svgFont; } const QFont &qfont() const { return m_qfont; } QSvgTinyDocument *doc() const {return m_doc;} private: QSvgFont *m_svgFont; QSvgTinyDocument *m_doc; QFont m_qfont; int m_weight; Qt::Alignment m_textAnchor; QSvgFont *m_oldSvgFont; QFont m_oldQFont; Qt::Alignment m_oldTextAnchor; int m_oldWeight; uint m_familySet : 1; uint m_sizeSet : 1; uint m_styleSet : 1; uint m_variantSet : 1; uint m_weightSet : 1; uint m_textAnchorSet : 1; }; class QSvgStrokeStyle : public QSvgStyleProperty { public: QSvgStrokeStyle(); virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; void setStroke(QBrush brush) { m_stroke.setBrush(brush); m_style = 0; m_strokeSet = 1; } void setStyle(QSvgFillStyleProperty *style) { m_style = style; m_strokeSet = 1; } void setDashArray(const QVector &dashes); void setDashArrayNone() { m_stroke.setStyle(Qt::SolidLine); m_strokeDashArraySet = 1; } void setDashOffset(qreal offset) { m_strokeDashOffset = offset; m_strokeDashOffsetSet = 1; } void setLineCap(Qt::PenCapStyle cap) { m_stroke.setCapStyle(cap); m_strokeLineCapSet = 1; } void setLineJoin(Qt::PenJoinStyle join) { m_stroke.setJoinStyle(join); m_strokeLineJoinSet = 1; } void setMiterLimit(qreal limit) { m_stroke.setMiterLimit(limit); m_strokeMiterLimitSet = 1; } void setOpacity(qreal opacity) { m_strokeOpacity = opacity; m_strokeOpacitySet = 1; } void setWidth(qreal width) { m_stroke.setWidthF(width); m_strokeWidthSet = 1; Q_ASSERT(!m_strokeDashArraySet); // set width before dash array. } qreal width() { return m_stroke.widthF(); } void setVectorEffect(bool nonScalingStroke) { m_vectorEffect = nonScalingStroke; m_vectorEffectSet = 1; } QSvgFillStyleProperty* style() const { return m_style; } void setGradientId(const QString &Id) { m_gradientId = Id; } QString gradientId() const { return m_gradientId; } void setGradientResolved(bool resolved) { m_gradientResolved = resolved; } bool isGradientResolved() const { return m_gradientResolved; } QPen stroke() const { return m_stroke; } private: // stroke v v 'inherit' | // stroke-dasharray v v 'inherit' | // stroke-dashoffset v v 'inherit' | // stroke-linecap v v 'butt' | 'round' | 'square' | 'inherit' // stroke-linejoin v v 'miter' | 'round' | 'bevel' | 'inherit' // stroke-miterlimit v v 'inherit' | // stroke-opacity v v 'inherit' | // stroke-width v v 'inherit' | QPen m_stroke; QPen m_oldStroke; qreal m_strokeOpacity; qreal m_oldStrokeOpacity; qreal m_strokeDashOffset; qreal m_oldStrokeDashOffset; QSvgFillStyleProperty *m_style; QString m_gradientId; uint m_gradientResolved : 1; uint m_vectorEffect : 1; uint m_oldVectorEffect : 1; uint m_strokeSet : 1; uint m_strokeDashArraySet : 1; uint m_strokeDashOffsetSet : 1; uint m_strokeLineCapSet : 1; uint m_strokeLineJoinSet : 1; uint m_strokeMiterLimitSet : 1; uint m_strokeOpacitySet : 1; uint m_strokeWidthSet : 1; uint m_vectorEffectSet : 1; }; class QSvgSolidColorStyle : public QSvgFillStyleProperty { public: QSvgSolidColorStyle(const QColor &color); virtual Type type() const; const QColor & qcolor() const { return m_solidColor; } QBrush brush(QPainter *, QSvgExtraStates &) { return m_solidColor; } private: // solid-color v x 'inherit' | // solid-opacity v x 'inherit' | QColor m_solidColor; QBrush m_oldFill; QPen m_oldStroke; }; class QSvgGradientStyle : public QSvgFillStyleProperty { public: QSvgGradientStyle(QGradient *grad); ~QSvgGradientStyle() { delete m_gradient; } virtual Type type() const; void setStopLink(const QString &link, QSvgTinyDocument *doc); QString stopLink() const { return m_link; } void resolveStops(); void setMatrix(const QMatrix &matrix); QMatrix qmatrix() const { return m_matrix; } QGradient *qgradient() const { return m_gradient; } bool gradientStopsSet() const { return m_gradientStopsSet; } void setGradientStopsSet(bool set) { m_gradientStopsSet = set; } QBrush brush(QPainter *, QSvgExtraStates &); private: QGradient *m_gradient; QMatrix m_matrix; QSvgTinyDocument *m_doc; QString m_link; bool m_gradientStopsSet; }; class QSvgTransformStyle : public QSvgStyleProperty { public: QSvgTransformStyle(const QTransform &transform); virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; const QTransform & qtransform() const { return m_transform; } private: //7.6 The transform attribute QTransform m_transform; QTransform m_oldWorldTransform; }; class QSvgAnimateTransform : public QSvgStyleProperty { public: enum TransformType { Empty, Translate, Scale, Rotate, SkewX, SkewY }; enum Additive { Sum, Replace }; public: QSvgAnimateTransform(int startMs, int endMs, int by = 0); void setArgs(TransformType type, Additive additive, const QVector &args); void setFreeze(bool freeze); void setRepeatCount(qreal repeatCount); virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; QSvgAnimateTransform::Additive additiveType() const { return m_additive; } bool animActive(qreal totalTimeElapsed) { if (totalTimeElapsed < m_from) return false; if (m_freeze || m_repeatCount < 0) // fill="freeze" or repeat="indefinite" return true; if (m_totalRunningTime == 0) return false; qreal animationFrame = (totalTimeElapsed - m_from) / m_totalRunningTime; if (animationFrame > m_repeatCount) return false; return true; } bool transformApplied() const { return m_transformApplied; } // Call this instead of revert if you know that revert is unnecessary. void clearTransformApplied() { m_transformApplied = false; } protected: void resolveMatrix(const QSvgNode *node); private: qreal m_from, m_to, m_by; qreal m_totalRunningTime; TransformType m_type; Additive m_additive; QVector m_args; int m_count; QTransform m_transform; QTransform m_oldWorldTransform; bool m_finished; bool m_freeze; qreal m_repeatCount; bool m_transformApplied; }; class QSvgAnimateColor : public QSvgStyleProperty { public: QSvgAnimateColor(int startMs, int endMs, int by = 0); void setArgs(bool fill, const QList &colors); void setFreeze(bool freeze); void setRepeatCount(qreal repeatCount); virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; private: qreal m_from, m_to, m_by; qreal m_totalRunningTime; QList m_colors; QBrush m_oldBrush; QPen m_oldPen; bool m_fill; bool m_finished; bool m_freeze; qreal m_repeatCount; }; class QSvgCompOpStyle : public QSvgStyleProperty { public: QSvgCompOpStyle(QPainter::CompositionMode mode); virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; const QPainter::CompositionMode & compOp() const { return m_mode; } private: //comp-op attribute QPainter::CompositionMode m_mode; QPainter::CompositionMode m_oldMode; }; class QSvgStyle { public: QSvgStyle() : quality(0), fill(0), viewportFill(0), font(0), stroke(0), solidColor(0), gradient(0), transform(0), animateColor(0), opacity(0), compop(0) {} ~QSvgStyle(); void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); void revert(QPainter *p, QSvgExtraStates &states); QSvgRefCounter quality; QSvgRefCounter fill; QSvgRefCounter viewportFill; QSvgRefCounter font; QSvgRefCounter stroke; QSvgRefCounter solidColor; QSvgRefCounter gradient; QSvgRefCounter transform; QSvgRefCounter animateColor; QList > animateTransforms; QSvgRefCounter opacity; QSvgRefCounter compop; }; /********************************************************/ // NOT implemented: // color v v 'inherit' | //QColor m_color; // display v x 'inline' | 'block' | 'list-item' // | 'run-in' | 'compact' | 'marker' | // 'table' | 'inline-table' | // 'table-row-group' | 'table-header-group' | // 'table-footer-group' | 'table-row' | // 'table-column-group' | 'table-column' | // 'table-cell' | 'table-caption' | // 'none' | 'inherit' //QSvgDisplayStyle m_display; // display-align v v 'auto' | 'before' | 'center' | 'after' | 'inherit' //QSvgDisplayAlign m_displayAlign; // line-increment v v 'auto' | 'inherit' | //int m_lineIncrement; // text-anchor v v 'start' | 'middle' | 'end' | 'inherit' //QSvgTextAnchor m_textAnchor; // visibility v v 'visible' | 'hidden' | 'inherit' //QSvgVisibility m_visibility; /******************************************************/ // the following do not make sense for us // pointer-events v v 'visiblePainted' | 'visibleFill' | 'visibleStroke' | // 'visible' | 'painted' | 'fill' | 'stroke' | 'all' | // 'none' | 'inherit' //QSvgPointEvents m_pointerEvents; // audio-level v x 'inherit' | QT_END_NAMESPACE #endif // QT_NO_SVG #endif // QSVGSTYLE_P_H