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