1/*
2    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3                  2004, 2005 Rob Buis <buis@kde.org>
4    Copyright (C) 2005, 2006 Apple Computer, Inc.
5    Copyright (C) Research In Motion Limited 2010. All rights reserved.
6
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public
9    License as published by the Free Software Foundation; either
10    version 2 of the License, or (at your option) any later version.
11
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Library General Public License for more details.
16
17    You should have received a copy of the GNU Library General Public License
18    along with this library; see the file COPYING.LIB.  If not, write to
19    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20    Boston, MA 02110-1301, USA.
21*/
22
23#ifndef SVGRenderStyle_h
24#define SVGRenderStyle_h
25
26#include "bindings/v8/ExceptionStatePlaceholder.h"
27#include "core/css/CSSValueList.h"
28#include "core/rendering/style/DataRef.h"
29#include "core/rendering/style/RenderStyleConstants.h"
30#include "core/rendering/style/SVGRenderStyleDefs.h"
31#include "core/svg/SVGPaint.h"
32#include "platform/graphics/GraphicsTypes.h"
33#include "platform/graphics/Path.h"
34
35namespace WebCore {
36
37class FloatRect;
38class IntRect;
39class RenderObject;
40
41class SVGRenderStyle : public RefCounted<SVGRenderStyle> {
42public:
43    static PassRefPtr<SVGRenderStyle> create() { return adoptRef(new SVGRenderStyle); }
44    PassRefPtr<SVGRenderStyle> copy() const { return adoptRef(new SVGRenderStyle(*this));}
45    ~SVGRenderStyle();
46
47    bool inheritedNotEqual(const SVGRenderStyle*) const;
48    void inheritFrom(const SVGRenderStyle*);
49    void copyNonInheritedFrom(const SVGRenderStyle*);
50
51    StyleDifference diff(const SVGRenderStyle*) const;
52
53    bool operator==(const SVGRenderStyle&) const;
54    bool operator!=(const SVGRenderStyle& o) const { return !(*this == o); }
55
56    // Initial values for all the properties
57    static EAlignmentBaseline initialAlignmentBaseline() { return AB_AUTO; }
58    static EDominantBaseline initialDominantBaseline() { return DB_AUTO; }
59    static EBaselineShift initialBaselineShift() { return BS_BASELINE; }
60    static EVectorEffect initialVectorEffect() { return VE_NONE; }
61    static EBufferedRendering initialBufferedRendering() { return BR_AUTO; }
62    static LineCap initialCapStyle() { return ButtCap; }
63    static WindRule initialClipRule() { return RULE_NONZERO; }
64    static EColorInterpolation initialColorInterpolation() { return CI_SRGB; }
65    static EColorInterpolation initialColorInterpolationFilters() { return CI_LINEARRGB; }
66    static EColorRendering initialColorRendering() { return CR_AUTO; }
67    static WindRule initialFillRule() { return RULE_NONZERO; }
68    static LineJoin initialJoinStyle() { return MiterJoin; }
69    static EShapeRendering initialShapeRendering() { return SR_AUTO; }
70    static ETextAnchor initialTextAnchor() { return TA_START; }
71    static SVGWritingMode initialWritingMode() { return WM_LRTB; }
72    static EGlyphOrientation initialGlyphOrientationHorizontal() { return GO_0DEG; }
73    static EGlyphOrientation initialGlyphOrientationVertical() { return GO_AUTO; }
74    static float initialFillOpacity() { return 1; }
75    static SVGPaint::SVGPaintType initialFillPaintType() { return SVGPaint::SVG_PAINTTYPE_RGBCOLOR; }
76    static Color initialFillPaintColor() { return Color::black; }
77    static String initialFillPaintUri() { return String(); }
78    static float initialStrokeOpacity() { return 1; }
79    static SVGPaint::SVGPaintType initialStrokePaintType() { return SVGPaint::SVG_PAINTTYPE_NONE; }
80    static Color initialStrokePaintColor() { return Color(); }
81    static String initialStrokePaintUri() { return String(); }
82    static Vector<SVGLength> initialStrokeDashArray() { return Vector<SVGLength>(); }
83    static float initialStrokeMiterLimit() { return 4; }
84    static float initialStopOpacity() { return 1; }
85    static Color initialStopColor() { return Color(0, 0, 0); }
86    static float initialFloodOpacity() { return 1; }
87    static Color initialFloodColor() { return Color(0, 0, 0); }
88    static Color initialLightingColor() { return Color(255, 255, 255); }
89    static String initialClipperResource() { return String(); }
90    static String initialFilterResource() { return String(); }
91    static String initialMaskerResource() { return String(); }
92    static String initialMarkerStartResource() { return String(); }
93    static String initialMarkerMidResource() { return String(); }
94    static String initialMarkerEndResource() { return String(); }
95    static EMaskType initialMaskType() { return MT_LUMINANCE; }
96    static EPaintOrder initialPaintOrder() { return PO_NORMAL; }
97
98    static SVGLength initialBaselineShiftValue()
99    {
100        SVGLength length;
101        length.newValueSpecifiedUnits(LengthTypeNumber, 0, ASSERT_NO_EXCEPTION);
102        return length;
103    }
104
105    static SVGLength initialKerning()
106    {
107        SVGLength length;
108        length.newValueSpecifiedUnits(LengthTypeNumber, 0, ASSERT_NO_EXCEPTION);
109        return length;
110    }
111
112    static SVGLength initialStrokeDashOffset()
113    {
114        SVGLength length;
115        length.newValueSpecifiedUnits(LengthTypeNumber, 0, ASSERT_NO_EXCEPTION);
116        return length;
117    }
118
119    static SVGLength initialStrokeWidth()
120    {
121        SVGLength length;
122        length.newValueSpecifiedUnits(LengthTypeNumber, 1, ASSERT_NO_EXCEPTION);
123        return length;
124    }
125
126    // SVG CSS Property setters
127    void setAlignmentBaseline(EAlignmentBaseline val) { svg_noninherited_flags.f._alignmentBaseline = val; }
128    void setDominantBaseline(EDominantBaseline val) { svg_noninherited_flags.f._dominantBaseline = val; }
129    void setBaselineShift(EBaselineShift val) { svg_noninherited_flags.f._baselineShift = val; }
130    void setVectorEffect(EVectorEffect val) { svg_noninherited_flags.f._vectorEffect = val; }
131    void setBufferedRendering(EBufferedRendering val) { svg_noninherited_flags.f.bufferedRendering = val; }
132    void setCapStyle(LineCap val) { svg_inherited_flags._capStyle = val; }
133    void setClipRule(WindRule val) { svg_inherited_flags._clipRule = val; }
134    void setColorInterpolation(EColorInterpolation val) { svg_inherited_flags._colorInterpolation = val; }
135    void setColorInterpolationFilters(EColorInterpolation val) { svg_inherited_flags._colorInterpolationFilters = val; }
136    void setColorRendering(EColorRendering val) { svg_inherited_flags._colorRendering = val; }
137    void setFillRule(WindRule val) { svg_inherited_flags._fillRule = val; }
138    void setJoinStyle(LineJoin val) { svg_inherited_flags._joinStyle = val; }
139    void setShapeRendering(EShapeRendering val) { svg_inherited_flags._shapeRendering = val; }
140    void setTextAnchor(ETextAnchor val) { svg_inherited_flags._textAnchor = val; }
141    void setWritingMode(SVGWritingMode val) { svg_inherited_flags._writingMode = val; }
142    void setGlyphOrientationHorizontal(EGlyphOrientation val) { svg_inherited_flags._glyphOrientationHorizontal = val; }
143    void setGlyphOrientationVertical(EGlyphOrientation val) { svg_inherited_flags._glyphOrientationVertical = val; }
144    void setMaskType(EMaskType val) { svg_noninherited_flags.f.maskType = val; }
145    void setPaintOrder(EPaintOrder val) { svg_inherited_flags._paintOrder = (int)val; }
146
147    void setFillOpacity(float obj)
148    {
149        if (!(fill->opacity == obj))
150            fill.access()->opacity = obj;
151    }
152
153    void setFillPaint(SVGPaint::SVGPaintType type, const Color& color, const String& uri, bool applyToRegularStyle = true, bool applyToVisitedLinkStyle = false)
154    {
155        if (applyToRegularStyle) {
156            if (!(fill->paintType == type))
157                fill.access()->paintType = type;
158            if (!(fill->paintColor == color))
159                fill.access()->paintColor = color;
160            if (!(fill->paintUri == uri))
161                fill.access()->paintUri = uri;
162        }
163        if (applyToVisitedLinkStyle) {
164            if (!(fill->visitedLinkPaintType == type))
165                fill.access()->visitedLinkPaintType = type;
166            if (!(fill->visitedLinkPaintColor == color))
167                fill.access()->visitedLinkPaintColor = color;
168            if (!(fill->visitedLinkPaintUri == uri))
169                fill.access()->visitedLinkPaintUri = uri;
170        }
171    }
172
173    void setStrokeOpacity(float obj)
174    {
175        if (!(stroke->opacity == obj))
176            stroke.access()->opacity = obj;
177    }
178
179    void setStrokePaint(SVGPaint::SVGPaintType type, const Color& color, const String& uri, bool applyToRegularStyle = true, bool applyToVisitedLinkStyle = false)
180    {
181        if (applyToRegularStyle) {
182            if (!(stroke->paintType == type))
183                stroke.access()->paintType = type;
184            if (!(stroke->paintColor == color))
185                stroke.access()->paintColor = color;
186            if (!(stroke->paintUri == uri))
187                stroke.access()->paintUri = uri;
188        }
189        if (applyToVisitedLinkStyle) {
190            if (!(stroke->visitedLinkPaintType == type))
191                stroke.access()->visitedLinkPaintType = type;
192            if (!(stroke->visitedLinkPaintColor == color))
193                stroke.access()->visitedLinkPaintColor = color;
194            if (!(stroke->visitedLinkPaintUri == uri))
195                stroke.access()->visitedLinkPaintUri = uri;
196        }
197    }
198
199    void setStrokeDashArray(const Vector<SVGLength>& obj)
200    {
201        if (!(stroke->dashArray == obj))
202            stroke.access()->dashArray = obj;
203    }
204
205    void setStrokeMiterLimit(float obj)
206    {
207        if (!(stroke->miterLimit == obj))
208            stroke.access()->miterLimit = obj;
209    }
210
211    void setStrokeWidth(const SVGLength& obj)
212    {
213        if (!(stroke->width == obj))
214            stroke.access()->width = obj;
215    }
216
217    void setStrokeDashOffset(const SVGLength& obj)
218    {
219        if (!(stroke->dashOffset == obj))
220            stroke.access()->dashOffset = obj;
221    }
222
223    void setKerning(const SVGLength& obj)
224    {
225        if (!(text->kerning == obj))
226            text.access()->kerning = obj;
227    }
228
229    void setStopOpacity(float obj)
230    {
231        if (!(stops->opacity == obj))
232            stops.access()->opacity = obj;
233    }
234
235    void setStopColor(const Color& obj)
236    {
237        if (!(stops->color == obj))
238            stops.access()->color = obj;
239    }
240
241    void setFloodOpacity(float obj)
242    {
243        if (!(misc->floodOpacity == obj))
244            misc.access()->floodOpacity = obj;
245    }
246
247    void setFloodColor(const Color& obj)
248    {
249        if (!(misc->floodColor == obj))
250            misc.access()->floodColor = obj;
251    }
252
253    void setLightingColor(const Color& obj)
254    {
255        if (!(misc->lightingColor == obj))
256            misc.access()->lightingColor = obj;
257    }
258
259    void setBaselineShiftValue(const SVGLength& obj)
260    {
261        if (!(misc->baselineShiftValue == obj))
262            misc.access()->baselineShiftValue = obj;
263    }
264
265    // Setters for non-inherited resources
266    void setClipperResource(const String& obj)
267    {
268        if (!(resources->clipper == obj))
269            resources.access()->clipper = obj;
270    }
271
272    void setFilterResource(const String& obj)
273    {
274        if (!(resources->filter == obj))
275            resources.access()->filter = obj;
276    }
277
278    void setMaskerResource(const String& obj)
279    {
280        if (!(resources->masker == obj))
281            resources.access()->masker = obj;
282    }
283
284    // Setters for inherited resources
285    void setMarkerStartResource(const String& obj)
286    {
287        if (!(inheritedResources->markerStart == obj))
288            inheritedResources.access()->markerStart = obj;
289    }
290
291    void setMarkerMidResource(const String& obj)
292    {
293        if (!(inheritedResources->markerMid == obj))
294            inheritedResources.access()->markerMid = obj;
295    }
296
297    void setMarkerEndResource(const String& obj)
298    {
299        if (!(inheritedResources->markerEnd == obj))
300            inheritedResources.access()->markerEnd = obj;
301    }
302
303    // Read accessors for all the properties
304    EAlignmentBaseline alignmentBaseline() const { return (EAlignmentBaseline) svg_noninherited_flags.f._alignmentBaseline; }
305    EDominantBaseline dominantBaseline() const { return (EDominantBaseline) svg_noninherited_flags.f._dominantBaseline; }
306    EBaselineShift baselineShift() const { return (EBaselineShift) svg_noninherited_flags.f._baselineShift; }
307    EVectorEffect vectorEffect() const { return (EVectorEffect) svg_noninherited_flags.f._vectorEffect; }
308    EBufferedRendering bufferedRendering() const { return (EBufferedRendering) svg_noninherited_flags.f.bufferedRendering; }
309    LineCap capStyle() const { return (LineCap) svg_inherited_flags._capStyle; }
310    WindRule clipRule() const { return (WindRule) svg_inherited_flags._clipRule; }
311    EColorInterpolation colorInterpolation() const { return (EColorInterpolation) svg_inherited_flags._colorInterpolation; }
312    EColorInterpolation colorInterpolationFilters() const { return (EColorInterpolation) svg_inherited_flags._colorInterpolationFilters; }
313    EColorRendering colorRendering() const { return (EColorRendering) svg_inherited_flags._colorRendering; }
314    WindRule fillRule() const { return (WindRule) svg_inherited_flags._fillRule; }
315    LineJoin joinStyle() const { return (LineJoin) svg_inherited_flags._joinStyle; }
316    EShapeRendering shapeRendering() const { return (EShapeRendering) svg_inherited_flags._shapeRendering; }
317    ETextAnchor textAnchor() const { return (ETextAnchor) svg_inherited_flags._textAnchor; }
318    SVGWritingMode writingMode() const { return (SVGWritingMode) svg_inherited_flags._writingMode; }
319    EGlyphOrientation glyphOrientationHorizontal() const { return (EGlyphOrientation) svg_inherited_flags._glyphOrientationHorizontal; }
320    EGlyphOrientation glyphOrientationVertical() const { return (EGlyphOrientation) svg_inherited_flags._glyphOrientationVertical; }
321    float fillOpacity() const { return fill->opacity; }
322    const SVGPaint::SVGPaintType& fillPaintType() const { return fill->paintType; }
323    const Color& fillPaintColor() const { return fill->paintColor; }
324    const String& fillPaintUri() const { return fill->paintUri; }
325    float strokeOpacity() const { return stroke->opacity; }
326    const SVGPaint::SVGPaintType& strokePaintType() const { return stroke->paintType; }
327    const Color& strokePaintColor() const { return stroke->paintColor; }
328    const String& strokePaintUri() const { return stroke->paintUri; }
329    Vector<SVGLength> strokeDashArray() const { return stroke->dashArray; }
330    float strokeMiterLimit() const { return stroke->miterLimit; }
331    SVGLength strokeWidth() const { return stroke->width; }
332    SVGLength strokeDashOffset() const { return stroke->dashOffset; }
333    SVGLength kerning() const { return text->kerning; }
334    float stopOpacity() const { return stops->opacity; }
335    const Color& stopColor() const { return stops->color; }
336    float floodOpacity() const { return misc->floodOpacity; }
337    const Color& floodColor() const { return misc->floodColor; }
338    const Color& lightingColor() const { return misc->lightingColor; }
339    SVGLength baselineShiftValue() const { return misc->baselineShiftValue; }
340    String clipperResource() const { return resources->clipper; }
341    String filterResource() const { return resources->filter; }
342    String maskerResource() const { return resources->masker; }
343    String markerStartResource() const { return inheritedResources->markerStart; }
344    String markerMidResource() const { return inheritedResources->markerMid; }
345    String markerEndResource() const { return inheritedResources->markerEnd; }
346    EMaskType maskType() const { return (EMaskType) svg_noninherited_flags.f.maskType; }
347    EPaintOrder paintOrder() const { return (EPaintOrder) svg_inherited_flags._paintOrder; }
348    EPaintOrderType paintOrderType(unsigned index) const;
349
350    const SVGPaint::SVGPaintType& visitedLinkFillPaintType() const { return fill->visitedLinkPaintType; }
351    const Color& visitedLinkFillPaintColor() const { return fill->visitedLinkPaintColor; }
352    const String& visitedLinkFillPaintUri() const { return fill->visitedLinkPaintUri; }
353    const SVGPaint::SVGPaintType& visitedLinkStrokePaintType() const { return stroke->visitedLinkPaintType; }
354    const Color& visitedLinkStrokePaintColor() const { return stroke->visitedLinkPaintColor; }
355    const String& visitedLinkStrokePaintUri() const { return stroke->visitedLinkPaintUri; }
356
357    // convenience
358    bool hasClipper() const { return !clipperResource().isEmpty(); }
359    bool hasMasker() const { return !maskerResource().isEmpty(); }
360    bool hasFilter() const { return !filterResource().isEmpty(); }
361    bool hasMarkers() const { return !markerStartResource().isEmpty() || !markerMidResource().isEmpty() || !markerEndResource().isEmpty(); }
362    bool hasStroke() const { return strokePaintType() != SVGPaint::SVG_PAINTTYPE_NONE; }
363    bool hasVisibleStroke() const { return hasStroke() && !strokeWidth().isZero(); }
364    bool hasFill() const { return fillPaintType() != SVGPaint::SVG_PAINTTYPE_NONE; }
365    bool isVerticalWritingMode() const { return writingMode() == WM_TBRL || writingMode() == WM_TB; }
366
367protected:
368    // inherit
369    struct InheritedFlags {
370        bool operator==(const InheritedFlags& other) const
371        {
372            return (_colorRendering == other._colorRendering)
373                && (_shapeRendering == other._shapeRendering)
374                && (_clipRule == other._clipRule)
375                && (_fillRule == other._fillRule)
376                && (_capStyle == other._capStyle)
377                && (_joinStyle == other._joinStyle)
378                && (_textAnchor == other._textAnchor)
379                && (_colorInterpolation == other._colorInterpolation)
380                && (_colorInterpolationFilters == other._colorInterpolationFilters)
381                && (_writingMode == other._writingMode)
382                && (_glyphOrientationHorizontal == other._glyphOrientationHorizontal)
383                && (_glyphOrientationVertical == other._glyphOrientationVertical)
384                && (_paintOrder == other._paintOrder);
385        }
386
387        bool operator!=(const InheritedFlags& other) const
388        {
389            return !(*this == other);
390        }
391
392        unsigned _colorRendering : 2; // EColorRendering
393        unsigned _shapeRendering : 2; // EShapeRendering
394        unsigned _clipRule : 1; // WindRule
395        unsigned _fillRule : 1; // WindRule
396        unsigned _capStyle : 2; // LineCap
397        unsigned _joinStyle : 2; // LineJoin
398        unsigned _textAnchor : 2; // ETextAnchor
399        unsigned _colorInterpolation : 2; // EColorInterpolation
400        unsigned _colorInterpolationFilters : 2; // EColorInterpolation
401        unsigned _writingMode : 3; // SVGWritingMode
402        unsigned _glyphOrientationHorizontal : 3; // EGlyphOrientation
403        unsigned _glyphOrientationVertical : 3; // EGlyphOrientation
404        unsigned _paintOrder : 6; // EPaintOrder
405    } svg_inherited_flags;
406
407    // don't inherit
408    struct NonInheritedFlags {
409        // 32 bit non-inherited, don't add to the struct, or the operator will break.
410        bool operator==(const NonInheritedFlags &other) const { return _niflags == other._niflags; }
411        bool operator!=(const NonInheritedFlags &other) const { return _niflags != other._niflags; }
412
413        union {
414            struct {
415                unsigned _alignmentBaseline : 4; // EAlignmentBaseline
416                unsigned _dominantBaseline : 4; // EDominantBaseline
417                unsigned _baselineShift : 2; // EBaselineShift
418                unsigned _vectorEffect: 1; // EVectorEffect
419                unsigned bufferedRendering: 2; // EBufferedRendering
420                unsigned maskType: 1; // EMaskType
421                // 18 bits unused
422            } f;
423            uint32_t _niflags;
424        };
425    } svg_noninherited_flags;
426
427    // inherited attributes
428    DataRef<StyleFillData> fill;
429    DataRef<StyleStrokeData> stroke;
430    DataRef<StyleTextData> text;
431    DataRef<StyleInheritedResourceData> inheritedResources;
432
433    // non-inherited attributes
434    DataRef<StyleStopData> stops;
435    DataRef<StyleMiscData> misc;
436    DataRef<StyleResourceData> resources;
437
438private:
439    enum CreateDefaultType { CreateDefault };
440
441    SVGRenderStyle();
442    SVGRenderStyle(const SVGRenderStyle&);
443    SVGRenderStyle(CreateDefaultType); // Used to create the default style.
444
445    void setBitDefaults()
446    {
447        svg_inherited_flags._clipRule = initialClipRule();
448        svg_inherited_flags._colorRendering = initialColorRendering();
449        svg_inherited_flags._fillRule = initialFillRule();
450        svg_inherited_flags._shapeRendering = initialShapeRendering();
451        svg_inherited_flags._textAnchor = initialTextAnchor();
452        svg_inherited_flags._capStyle = initialCapStyle();
453        svg_inherited_flags._joinStyle = initialJoinStyle();
454        svg_inherited_flags._colorInterpolation = initialColorInterpolation();
455        svg_inherited_flags._colorInterpolationFilters = initialColorInterpolationFilters();
456        svg_inherited_flags._writingMode = initialWritingMode();
457        svg_inherited_flags._glyphOrientationHorizontal = initialGlyphOrientationHorizontal();
458        svg_inherited_flags._glyphOrientationVertical = initialGlyphOrientationVertical();
459        svg_inherited_flags._paintOrder = initialPaintOrder();
460
461        svg_noninherited_flags._niflags = 0;
462        svg_noninherited_flags.f._alignmentBaseline = initialAlignmentBaseline();
463        svg_noninherited_flags.f._dominantBaseline = initialDominantBaseline();
464        svg_noninherited_flags.f._baselineShift = initialBaselineShift();
465        svg_noninherited_flags.f._vectorEffect = initialVectorEffect();
466        svg_noninherited_flags.f.bufferedRendering = initialBufferedRendering();
467        svg_noninherited_flags.f.maskType = initialMaskType();
468    }
469};
470
471} // namespace WebCore
472
473#endif // SVGRenderStyle_h
474