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