Move CSS3 text decoration implementation behind ENABLE(CSS3_TEXT_DECORATION)
[WebKit-https.git] / Source / WebCore / rendering / style / RenderStyle.cpp
1 /*
2  * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
3  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
4  * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #include "config.h"
24 #include "RenderStyle.h"
25
26 #include "ContentData.h"
27 #include "CursorList.h"
28 #include "CSSPropertyNames.h"
29 #include "Font.h"
30 #include "FontSelector.h"
31 #include "Pagination.h"
32 #include "QuotesData.h"
33 #include "RenderArena.h"
34 #include "RenderObject.h"
35 #include "ScaleTransformOperation.h"
36 #include "ShadowData.h"
37 #include "StyleImage.h"
38 #include "StyleInheritedData.h"
39 #include "StyleResolver.h"
40 #if ENABLE(TOUCH_EVENTS)
41 #include "RenderTheme.h"
42 #endif
43 #include <wtf/MathExtras.h>
44 #include <wtf/StdLibExtras.h>
45 #include <algorithm>
46
47 #if ENABLE(IOS_TEXT_AUTOSIZING)
48 #include <wtf/text/StringHash.h>
49 #endif
50
51 #if ENABLE(TEXT_AUTOSIZING)
52 #include "TextAutosizer.h"
53 #endif
54
55 using namespace std;
56
57 namespace WebCore {
58
59 struct SameSizeAsBorderValue {
60     RGBA32 m_color;
61     unsigned m_width;
62 };
63
64 COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow);
65
66 struct SameSizeAsRenderStyle : public RefCounted<SameSizeAsRenderStyle> {
67     void* dataRefs[7];
68     void* ownPtrs[1];
69 #if ENABLE(SVG)
70     void* dataRefSvgStyle;
71 #endif
72     struct InheritedFlags {
73         unsigned m_bitfields[2];
74     } inherited_flags;
75
76     struct NonInheritedFlags {
77         unsigned m_bitfields[2];
78     } noninherited_flags;
79 };
80
81 COMPILE_ASSERT(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small);
82
83 inline RenderStyle& defaultStyle()
84 {
85     static RenderStyle& style = RenderStyle::createDefaultStyle().leakRef();
86     return style;
87 }
88
89 PassRef<RenderStyle> RenderStyle::create()
90 {
91     return adoptRef(*new RenderStyle());
92 }
93
94 PassRef<RenderStyle> RenderStyle::createDefaultStyle()
95 {
96     return adoptRef(*new RenderStyle(true));
97 }
98
99 PassRef<RenderStyle> RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay display)
100 {
101     auto newStyle = RenderStyle::create();
102     newStyle.get().inheritFrom(parentStyle);
103     newStyle.get().inheritUnicodeBidiFrom(parentStyle);
104     newStyle.get().setDisplay(display);
105     return newStyle;
106 }
107
108 PassRef<RenderStyle> RenderStyle::clone(const RenderStyle* other)
109 {
110     return adoptRef(*new RenderStyle(*other));
111 }
112
113 ALWAYS_INLINE RenderStyle::RenderStyle()
114     : m_box(defaultStyle().m_box)
115     , visual(defaultStyle().visual)
116     , m_background(defaultStyle().m_background)
117     , surround(defaultStyle().surround)
118     , rareNonInheritedData(defaultStyle().rareNonInheritedData)
119     , rareInheritedData(defaultStyle().rareInheritedData)
120     , inherited(defaultStyle().inherited)
121 #if ENABLE(SVG)
122     , m_svgStyle(defaultStyle().m_svgStyle)
123 #endif
124 {
125     setBitDefaults(); // Would it be faster to copy this from the default style?
126     COMPILE_ASSERT((sizeof(InheritedFlags) <= 8), InheritedFlags_does_not_grow);
127     COMPILE_ASSERT((sizeof(NonInheritedFlags) <= 8), NonInheritedFlags_does_not_grow);
128 }
129
130 ALWAYS_INLINE RenderStyle::RenderStyle(bool)
131     : m_box(StyleBoxData::create())
132     , visual(StyleVisualData::create())
133     , m_background(StyleBackgroundData::create())
134     , surround(StyleSurroundData::create())
135     , rareNonInheritedData(StyleRareNonInheritedData::create())
136     , rareInheritedData(StyleRareInheritedData::create())
137     , inherited(StyleInheritedData::create())
138 #if ENABLE(SVG)
139     , m_svgStyle(SVGRenderStyle::create())
140 #endif
141 {
142     setBitDefaults();
143 }
144
145 ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o)
146     : RefCounted<RenderStyle>()
147     , m_box(o.m_box)
148     , visual(o.visual)
149     , m_background(o.m_background)
150     , surround(o.surround)
151     , rareNonInheritedData(o.rareNonInheritedData)
152     , rareInheritedData(o.rareInheritedData)
153     , inherited(o.inherited)
154 #if ENABLE(SVG)
155     , m_svgStyle(o.m_svgStyle)
156 #endif
157     , inherited_flags(o.inherited_flags)
158     , noninherited_flags(o.noninherited_flags)
159 {
160 }
161
162 void RenderStyle::inheritFrom(const RenderStyle* inheritParent, IsAtShadowBoundary isAtShadowBoundary)
163 {
164     if (isAtShadowBoundary == AtShadowBoundary) {
165         // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable
166         EUserModify currentUserModify = userModify();
167         rareInheritedData = inheritParent->rareInheritedData;
168         setUserModify(currentUserModify);
169     } else
170         rareInheritedData = inheritParent->rareInheritedData;
171     inherited = inheritParent->inherited;
172     inherited_flags = inheritParent->inherited_flags;
173 #if ENABLE(SVG)
174     if (m_svgStyle != inheritParent->m_svgStyle)
175         m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
176 #endif
177 }
178
179 void RenderStyle::copyNonInheritedFrom(const RenderStyle* other)
180 {
181     m_box = other->m_box;
182     visual = other->visual;
183     m_background = other->m_background;
184     surround = other->surround;
185     rareNonInheritedData = other->rareNonInheritedData;
186     // The flags are copied one-by-one because noninherited_flags contains a bunch of stuff other than real style data.
187     noninherited_flags._effectiveDisplay = other->noninherited_flags._effectiveDisplay;
188     noninherited_flags._originalDisplay = other->noninherited_flags._originalDisplay;
189     noninherited_flags._overflowX = other->noninherited_flags._overflowX;
190     noninherited_flags._overflowY = other->noninherited_flags._overflowY;
191     noninherited_flags._vertical_align = other->noninherited_flags._vertical_align;
192     noninherited_flags._clear = other->noninherited_flags._clear;
193     noninherited_flags._position = other->noninherited_flags._position;
194     noninherited_flags._floating = other->noninherited_flags._floating;
195     noninherited_flags._table_layout = other->noninherited_flags._table_layout;
196     noninherited_flags._unicodeBidi = other->noninherited_flags._unicodeBidi;
197     noninherited_flags._page_break_before = other->noninherited_flags._page_break_before;
198     noninherited_flags._page_break_after = other->noninherited_flags._page_break_after;
199     noninherited_flags._page_break_inside = other->noninherited_flags._page_break_inside;
200     noninherited_flags.explicitInheritance = other->noninherited_flags.explicitInheritance;
201 #if ENABLE(SVG)
202     if (m_svgStyle != other->m_svgStyle)
203         m_svgStyle.access()->copyNonInheritedFrom(other->m_svgStyle.get());
204 #endif
205     ASSERT(zoom() == initialZoom());
206 }
207
208 bool RenderStyle::operator==(const RenderStyle& o) const
209 {
210     // compare everything except the pseudoStyle pointer
211     return inherited_flags == o.inherited_flags
212         && noninherited_flags == o.noninherited_flags
213         && m_box == o.m_box
214         && visual == o.visual
215         && m_background == o.m_background
216         && surround == o.surround
217         && rareNonInheritedData == o.rareNonInheritedData
218         && rareInheritedData == o.rareInheritedData
219         && inherited == o.inherited
220 #if ENABLE(SVG)
221         && m_svgStyle == o.m_svgStyle
222 #endif
223             ;
224 }
225
226 bool RenderStyle::isStyleAvailable() const
227 {
228     return this != StyleResolver::styleNotYetAvailable();
229 }
230
231 static inline int pseudoBit(PseudoId pseudo)
232 {
233     return 1 << (pseudo - 1);
234 }
235
236 bool RenderStyle::hasAnyPublicPseudoStyles() const
237 {
238     return PUBLIC_PSEUDOID_MASK & noninherited_flags._pseudoBits;
239 }
240
241 bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
242 {
243     ASSERT(pseudo > NOPSEUDO);
244     ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
245     return pseudoBit(pseudo) & noninherited_flags._pseudoBits;
246 }
247
248 void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
249 {
250     ASSERT(pseudo > NOPSEUDO);
251     ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
252     noninherited_flags._pseudoBits |= pseudoBit(pseudo);
253 }
254
255 bool RenderStyle::hasUniquePseudoStyle() const
256 {
257     if (!m_cachedPseudoStyles || styleType() != NOPSEUDO)
258         return false;
259
260     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
261         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
262         if (pseudoStyle->unique())
263             return true;
264     }
265
266     return false;
267 }
268
269 RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
270 {
271     if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
272         return 0;
273
274     if (styleType() != NOPSEUDO) 
275         return 0;
276
277     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
278         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
279         if (pseudoStyle->styleType() == pid)
280             return pseudoStyle;
281     }
282
283     return 0;
284 }
285
286 RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
287 {
288     if (!pseudo)
289         return 0;
290
291     ASSERT(pseudo->styleType() > NOPSEUDO);
292
293     RenderStyle* result = pseudo.get();
294
295     if (!m_cachedPseudoStyles)
296         m_cachedPseudoStyles = adoptPtr(new PseudoStyleCache);
297
298     m_cachedPseudoStyles->append(pseudo);
299
300     return result;
301 }
302
303 void RenderStyle::removeCachedPseudoStyle(PseudoId pid)
304 {
305     if (!m_cachedPseudoStyles)
306         return;
307     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
308         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
309         if (pseudoStyle->styleType() == pid) {
310             m_cachedPseudoStyles->remove(i);
311             return;
312         }
313     }
314 }
315
316 bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
317 {
318     return inherited_flags != other->inherited_flags
319            || inherited != other->inherited
320 #if ENABLE(SVG)
321            || m_svgStyle->inheritedNotEqual(other->m_svgStyle.get())
322 #endif
323            || rareInheritedData != other->rareInheritedData;
324 }
325
326 #if ENABLE(IOS_TEXT_AUTOSIZING)
327 inline unsigned computeFontHash(const Font& font)
328 {
329     unsigned hashCodes[2] = {
330         CaseFoldingHash::hash(font.fontDescription().firstFamily().impl()),
331         static_cast<unsigned>(font.fontDescription().specifiedSize())
332     };
333     return StringHasher::computeHash(reinterpret_cast<UChar*>(hashCodes), 2 * sizeof(unsigned) / sizeof(UChar));
334 }
335
336 uint32_t RenderStyle::hashForTextAutosizing() const
337 {
338     // FIXME: Not a very smart hash. Could be improved upon. See <https://bugs.webkit.org/show_bug.cgi?id=121131>.
339     uint32_t hash = 0;
340     
341     hash ^= rareNonInheritedData->m_appearance;
342     hash ^= rareNonInheritedData->marginBeforeCollapse;
343     hash ^= rareNonInheritedData->marginAfterCollapse;
344     hash ^= rareNonInheritedData->lineClamp.value();
345     hash ^= rareInheritedData->overflowWrap;
346     hash ^= rareInheritedData->nbspMode;
347     hash ^= rareInheritedData->lineBreak;
348     hash ^= WTF::FloatHash<float>::hash(inherited->specifiedLineHeight.value());
349     hash ^= computeFontHash(inherited->font);
350     hash ^= inherited->horizontal_border_spacing;
351     hash ^= inherited->vertical_border_spacing;
352     hash ^= inherited_flags._box_direction;
353     hash ^= inherited_flags.m_rtlOrdering;
354     hash ^= noninherited_flags._position;
355     hash ^= noninherited_flags._floating;
356     hash ^= rareNonInheritedData->textOverflow;
357     hash ^= rareInheritedData->textSecurity;
358     return hash;
359 }
360
361 bool RenderStyle::equalForTextAutosizing(const RenderStyle* other) const
362 {
363     return rareNonInheritedData->m_appearance == other->rareNonInheritedData->m_appearance
364         && rareNonInheritedData->marginBeforeCollapse == other->rareNonInheritedData->marginBeforeCollapse
365         && rareNonInheritedData->marginAfterCollapse == other->rareNonInheritedData->marginAfterCollapse
366         && rareNonInheritedData->lineClamp == other->rareNonInheritedData->lineClamp
367         && rareInheritedData->textSizeAdjust == other->rareInheritedData->textSizeAdjust
368         && rareInheritedData->overflowWrap == other->rareInheritedData->overflowWrap
369         && rareInheritedData->nbspMode == other->rareInheritedData->nbspMode
370         && rareInheritedData->lineBreak == other->rareInheritedData->lineBreak
371         && rareInheritedData->textSecurity == other->rareInheritedData->textSecurity
372         && inherited->specifiedLineHeight == other->inherited->specifiedLineHeight
373         && inherited->font.equalForTextAutoSizing(other->inherited->font)
374         && inherited->horizontal_border_spacing == other->inherited->horizontal_border_spacing
375         && inherited->vertical_border_spacing == other->inherited->vertical_border_spacing
376         && inherited_flags._box_direction == other->inherited_flags._box_direction
377         && inherited_flags.m_rtlOrdering == other->inherited_flags.m_rtlOrdering
378         && noninherited_flags._position == other->noninherited_flags._position
379         && noninherited_flags._floating == other->noninherited_flags._floating
380         && rareNonInheritedData->textOverflow == other->rareNonInheritedData->textOverflow;
381 }
382 #endif // ENABLE(IOS_TEXT_AUTOSIZING)
383
384 bool RenderStyle::inheritedDataShared(const RenderStyle* other) const
385 {
386     // This is a fast check that only looks if the data structures are shared.
387     return inherited_flags == other->inherited_flags
388         && inherited.get() == other->inherited.get()
389 #if ENABLE(SVG)
390         && m_svgStyle.get() == other->m_svgStyle.get()
391 #endif
392         && rareInheritedData.get() == other->rareInheritedData.get();
393 }
394
395 static bool positionChangeIsMovementOnly(const LengthBox& a, const LengthBox& b, const Length& width)
396 {
397     // If any unit types are different, then we can't guarantee
398     // that this was just a movement.
399     if (a.left().type() != b.left().type()
400         || a.right().type() != b.right().type()
401         || a.top().type() != b.top().type()
402         || a.bottom().type() != b.bottom().type())
403         return false;
404
405     // Only one unit can be non-auto in the horizontal direction and
406     // in the vertical direction.  Otherwise the adjustment of values
407     // is changing the size of the box.
408     if (!a.left().isIntrinsicOrAuto() && !a.right().isIntrinsicOrAuto())
409         return false;
410     if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
411         return false;
412     // If our width is auto and left or right is specified then this 
413     // is not just a movement - we need to resize to our container.
414     if ((!a.left().isIntrinsicOrAuto() || !a.right().isIntrinsicOrAuto()) && width.isIntrinsicOrAuto())
415         return false;
416
417     // One of the units is fixed or percent in both directions and stayed
418     // that way in the new style.  Therefore all we are doing is moving.
419     return true;
420 }
421
422 bool RenderStyle::changeRequiresLayout(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
423 {
424     if (m_box->width() != other->m_box->width()
425         || m_box->minWidth() != other->m_box->minWidth()
426         || m_box->maxWidth() != other->m_box->maxWidth()
427         || m_box->height() != other->m_box->height()
428         || m_box->minHeight() != other->m_box->minHeight()
429         || m_box->maxHeight() != other->m_box->maxHeight())
430         return true;
431
432     if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
433         return true;
434
435     if (m_box->boxSizing() != other->m_box->boxSizing())
436         return true;
437
438     if (surround->margin != other->surround->margin)
439         return true;
440
441     if (surround->padding != other->surround->padding)
442         return true;
443
444     if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
445         if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance 
446             || rareNonInheritedData->marginBeforeCollapse != other->rareNonInheritedData->marginBeforeCollapse
447             || rareNonInheritedData->marginAfterCollapse != other->rareNonInheritedData->marginAfterCollapse
448             || rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp
449             || rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
450             return true;
451
452         if (rareNonInheritedData->m_regionFragment != other->rareNonInheritedData->m_regionFragment)
453             return true;
454
455         if (rareNonInheritedData->m_wrapFlow != other->rareNonInheritedData->m_wrapFlow
456             || rareNonInheritedData->m_wrapThrough != other->rareNonInheritedData->m_wrapThrough)
457             return true;
458
459 #if ENABLE(CSS_SHAPES)
460         if (rareNonInheritedData->m_shapeMargin != other->rareNonInheritedData->m_shapeMargin
461             || rareNonInheritedData->m_shapePadding != other->rareNonInheritedData->m_shapePadding)
462             return true;
463 #endif
464
465         if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get()
466             && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other->rareNonInheritedData->m_deprecatedFlexibleBox.get())
467             return true;
468
469         if (rareNonInheritedData->m_flexibleBox.get() != other->rareNonInheritedData->m_flexibleBox.get()
470             && *rareNonInheritedData->m_flexibleBox.get() != *other->rareNonInheritedData->m_flexibleBox.get())
471             return true;
472         if (rareNonInheritedData->m_order != other->rareNonInheritedData->m_order
473             || rareNonInheritedData->m_alignContent != other->rareNonInheritedData->m_alignContent
474             || rareNonInheritedData->m_alignItems != other->rareNonInheritedData->m_alignItems
475             || rareNonInheritedData->m_alignSelf != other->rareNonInheritedData->m_alignSelf
476             || rareNonInheritedData->m_justifyContent != other->rareNonInheritedData->m_justifyContent)
477             return true;
478
479         // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
480         if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
481             return true;
482
483         if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
484             return true;
485
486         if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get()
487             && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
488             return true;
489
490         if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get()
491             && *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
492 #if USE(ACCELERATED_COMPOSITING)
493             changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
494             // Don't return; keep looking for another change
495 #else
496             return true;
497 #endif
498         }
499
500         if (rareNonInheritedData->m_grid.get() != other->rareNonInheritedData->m_grid.get()
501             || rareNonInheritedData->m_gridItem.get() != other->rareNonInheritedData->m_gridItem.get())
502             return true;
503
504 #if !USE(ACCELERATED_COMPOSITING)
505         if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
506             if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
507                 || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
508                 || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
509                 || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
510                 || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
511                 return true;
512         }
513 #endif
514
515 #if ENABLE(DASHBOARD_SUPPORT)
516         // If regions change, trigger a relayout to re-calc regions.
517         if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions)
518             return true;
519 #endif
520
521 #if ENABLE(CSS_SHAPES)
522         if (rareNonInheritedData->m_shapeInside != other->rareNonInheritedData->m_shapeInside)
523             return true;
524 #endif
525     }
526
527     if (rareInheritedData.get() != other->rareInheritedData.get()) {
528         if (rareInheritedData->highlight != other->rareInheritedData->highlight
529             || rareInheritedData->indent != other->rareInheritedData->indent
530 #if ENABLE(CSS3_TEXT)
531             || rareInheritedData->m_textIndentLine != other->rareInheritedData->m_textIndentLine
532 #endif
533             || rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom
534 #if ENABLE(IOS_TEXT_AUTOSIZING)
535             || rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust
536 #endif
537             || rareInheritedData->wordBreak != other->rareInheritedData->wordBreak
538             || rareInheritedData->overflowWrap != other->rareInheritedData->overflowWrap
539             || rareInheritedData->nbspMode != other->rareInheritedData->nbspMode
540             || rareInheritedData->lineBreak != other->rareInheritedData->lineBreak
541             || rareInheritedData->textSecurity != other->rareInheritedData->textSecurity
542             || rareInheritedData->hyphens != other->rareInheritedData->hyphens
543             || rareInheritedData->hyphenationLimitBefore != other->rareInheritedData->hyphenationLimitBefore
544             || rareInheritedData->hyphenationLimitAfter != other->rareInheritedData->hyphenationLimitAfter
545             || rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString
546             || rareInheritedData->locale != other->rareInheritedData->locale
547             || rareInheritedData->m_rubyPosition != other->rareInheritedData->m_rubyPosition
548             || rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark
549             || rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition
550             || rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark
551             || rareInheritedData->m_textOrientation != other->rareInheritedData->m_textOrientation
552             || rareInheritedData->m_tabSize != other->rareInheritedData->m_tabSize
553             || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain
554             || rareInheritedData->m_lineGrid != other->rareInheritedData->m_lineGrid
555 #if ENABLE(CSS_IMAGE_ORIENTATION)
556             || rareInheritedData->m_imageOrientation != other->rareInheritedData->m_imageOrientation
557 #endif
558 #if ENABLE(CSS_IMAGE_RESOLUTION)
559             || rareInheritedData->m_imageResolutionSource != other->rareInheritedData->m_imageResolutionSource
560             || rareInheritedData->m_imageResolutionSnap != other->rareInheritedData->m_imageResolutionSnap
561             || rareInheritedData->m_imageResolution != other->rareInheritedData->m_imageResolution
562 #endif
563             || rareInheritedData->m_lineSnap != other->rareInheritedData->m_lineSnap
564             || rareInheritedData->m_lineAlign != other->rareInheritedData->m_lineAlign
565 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
566             || rareInheritedData->useTouchOverflowScrolling != other->rareInheritedData->useTouchOverflowScrolling
567 #endif
568             || rareInheritedData->listStyleImage != other->rareInheritedData->listStyleImage)
569             return true;
570
571         if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
572             return true;
573
574         if (textStrokeWidth() != other->textStrokeWidth())
575             return true;
576     }
577
578 #if ENABLE(TEXT_AUTOSIZING)
579     if (visual->m_textAutosizingMultiplier != other->visual->m_textAutosizingMultiplier)
580         return true;
581 #endif
582
583     if (inherited->line_height != other->inherited->line_height
584 #if ENABLE(IOS_TEXT_AUTOSIZING)
585         || inherited->specifiedLineHeight != other->inherited->specifiedLineHeight
586 #endif
587         || inherited->font != other->inherited->font
588         || inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing
589         || inherited->vertical_border_spacing != other->inherited->vertical_border_spacing
590         || inherited_flags._box_direction != other->inherited_flags._box_direction
591         || inherited_flags.m_rtlOrdering != other->inherited_flags.m_rtlOrdering
592         || noninherited_flags._position != other->noninherited_flags._position
593         || noninherited_flags._floating != other->noninherited_flags._floating
594         || noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
595         return true;
596
597
598     if (((int)noninherited_flags._effectiveDisplay) >= TABLE) {
599         if (inherited_flags._border_collapse != other->inherited_flags._border_collapse
600             || inherited_flags._empty_cells != other->inherited_flags._empty_cells
601             || inherited_flags._caption_side != other->inherited_flags._caption_side
602             || noninherited_flags._table_layout != other->noninherited_flags._table_layout)
603             return true;
604
605         // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
606         // does not, so these style differences can be width differences.
607         if (inherited_flags._border_collapse
608             && ((borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE)
609                 || (borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN)
610                 || (borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE)
611                 || (borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN)
612                 || (borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE)
613                 || (borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN)
614                 || (borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE)
615                 || (borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN)))
616             return true;
617     }
618
619     if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
620         if (inherited_flags._list_style_type != other->inherited_flags._list_style_type
621             || inherited_flags._list_style_position != other->inherited_flags._list_style_position)
622             return true;
623     }
624
625     if (inherited_flags._text_align != other->inherited_flags._text_align
626         || inherited_flags._text_transform != other->inherited_flags._text_transform
627         || inherited_flags._direction != other->inherited_flags._direction
628         || inherited_flags._white_space != other->inherited_flags._white_space
629         || noninherited_flags._clear != other->noninherited_flags._clear
630         || noninherited_flags._unicodeBidi != other->noninherited_flags._unicodeBidi)
631         return true;
632
633     // Check block flow direction.
634     if (inherited_flags.m_writingMode != other->inherited_flags.m_writingMode)
635         return true;
636
637     // Check text combine mode.
638     if (rareNonInheritedData->m_textCombine != other->rareNonInheritedData->m_textCombine)
639         return true;
640
641     // Overflow returns a layout hint.
642     if (noninherited_flags._overflowX != other->noninherited_flags._overflowX
643         || noninherited_flags._overflowY != other->noninherited_flags._overflowY)
644         return true;
645
646     // If our border widths change, then we need to layout.  Other changes to borders
647     // only necessitate a repaint.
648     if (borderLeftWidth() != other->borderLeftWidth()
649         || borderTopWidth() != other->borderTopWidth()
650         || borderBottomWidth() != other->borderBottomWidth()
651         || borderRightWidth() != other->borderRightWidth())
652         return true;
653
654     // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
655     const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
656     const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
657     if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
658         return true;
659
660     if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
661         return true;
662
663     if (rareNonInheritedData->hasOpacity() != other->rareNonInheritedData->hasOpacity()) {
664         // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
665         // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
666         // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
667         // In addition we need to solve the floating object issue when layers come and go. Right now
668         // a full layout is necessary to keep floating object lists sane.
669         return true;
670     }
671
672 #if ENABLE(CSS_FILTERS)
673     if (rareNonInheritedData->hasFilters() != other->rareNonInheritedData->hasFilters())
674         return true;
675 #endif
676
677     const QuotesData* quotesDataA = rareInheritedData->quotes.get();
678     const QuotesData* quotesDataB = other->rareInheritedData->quotes.get();
679     if (!(quotesDataA == quotesDataB || (quotesDataA && quotesDataB && *quotesDataA == *quotesDataB)))
680         return true;
681
682     if (position() != StaticPosition) {
683         if (surround->offset != other->surround->offset) {
684             // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet.
685             // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
686             // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
687             if (position() != AbsolutePosition)
688                 return true;
689
690             // Optimize for the case where a positioned layer is moving but not changing size.
691             if (!positionChangeIsMovementOnly(surround->offset, other->surround->offset, m_box->width()))
692                 return true;
693         }
694     }
695     
696     return false;
697 }
698
699 bool RenderStyle::changeRequiresPositionedLayoutOnly(const RenderStyle* other, unsigned&) const
700 {
701     if (position() == StaticPosition)
702         return false;
703
704     if (surround->offset != other->surround->offset) {
705         // Optimize for the case where a positioned layer is moving but not changing size.
706         if (position() == AbsolutePosition && positionChangeIsMovementOnly(surround->offset, other->surround->offset, m_box->width()))
707             return true;
708     }
709     
710     return false;
711 }
712
713 bool RenderStyle::changeRequiresLayerRepaint(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
714 {
715     if (position() != StaticPosition) {
716         if (m_box->zIndex() != other->m_box->zIndex()
717             || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex()
718             || visual->clip != other->visual->clip
719             || visual->hasClip != other->visual->hasClip)
720             return true;
721     }
722
723 #if ENABLE(CSS_COMPOSITING)
724     if (rareNonInheritedData->m_effectiveBlendMode != other->rareNonInheritedData->m_effectiveBlendMode)
725         return true;
726 #endif
727
728     if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
729 #if USE(ACCELERATED_COMPOSITING)
730         changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
731         // Don't return; keep looking for another change.
732 #else
733         return true;
734 #endif
735     }
736
737 #if ENABLE(CSS_FILTERS)
738     if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get()
739         && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) {
740 #if USE(ACCELERATED_COMPOSITING)
741         changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
742         // Don't return; keep looking for another change.
743 #else
744         return true;
745 #endif
746     }
747 #endif
748
749     if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
750         || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
751         return true;
752
753     return false;
754 }
755
756 bool RenderStyle::changeRequiresRepaint(const RenderStyle* other, unsigned&) const
757 {
758     if (inherited_flags._visibility != other->inherited_flags._visibility
759         || inherited_flags.m_printColorAdjust != other->inherited_flags.m_printColorAdjust
760         || inherited_flags._insideLink != other->inherited_flags._insideLink
761         || surround->border != other->surround->border
762         || !m_background->isEquivalentForPainting(*other->m_background)
763         || rareInheritedData->userModify != other->rareInheritedData->userModify
764         || rareInheritedData->userSelect != other->rareInheritedData->userSelect
765         || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
766         || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
767         || rareNonInheritedData->m_objectFit != other->rareNonInheritedData->m_objectFit
768         || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
769         return true;
770
771 #if ENABLE(CSS_SHAPES)
772     // FIXME: The current spec is being reworked to remove dependencies between exclusions and affected 
773     // content. There's a proposal to use floats instead. In that case, wrap-shape should actually relayout 
774     // the parent container. For sure, I will have to revisit this code, but for now I've added this in order 
775     // to avoid having diff() == StyleDifferenceEqual where wrap-shapes actually differ.
776     // Tracking bug: https://bugs.webkit.org/show_bug.cgi?id=62991
777     if (rareNonInheritedData->m_shapeOutside != other->rareNonInheritedData->m_shapeOutside)
778         return true;
779 #endif
780
781     if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath)
782         return true;
783
784     return false;
785 }
786
787 bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle* other, unsigned&) const
788 {
789     if (inherited->color != other->inherited->color
790         || inherited_flags._text_decorations != other->inherited_flags._text_decorations
791         || visual->textDecoration != other->visual->textDecoration
792 #if ENABLE(CSS3_TEXT_DECORATION)
793         || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle
794         || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor
795 #endif // CSS3_TEXT_DECORATION
796         || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
797         || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
798         || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
799         || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill)
800         return true;
801
802     return false;
803 }
804
805 bool RenderStyle::changeRequiresRecompositeLayer(const RenderStyle* other, unsigned&) const
806 {
807 #if USE(ACCELERATED_COMPOSITING)
808     if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
809         if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
810             || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
811             || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
812             || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
813             || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
814             return true;
815     }
816 #endif
817     return false;
818 }
819
820 StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
821 {
822     changedContextSensitiveProperties = ContextSensitivePropertyNone;
823
824 #if ENABLE(SVG)
825     StyleDifference svgChange = StyleDifferenceEqual;
826     if (m_svgStyle != other->m_svgStyle) {
827         svgChange = m_svgStyle->diff(other->m_svgStyle.get());
828         if (svgChange == StyleDifferenceLayout)
829             return svgChange;
830     }
831 #endif
832
833     if (changeRequiresLayout(other, changedContextSensitiveProperties))
834         return StyleDifferenceLayout;
835
836 #if ENABLE(SVG)
837     // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
838     // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
839     // but have to return StyleDifferenceLayout, that's why  this if branch comes after all branches
840     // that are relevant for SVG and might return StyleDifferenceLayout.
841     if (svgChange != StyleDifferenceEqual)
842         return svgChange;
843 #endif
844
845     if (changeRequiresPositionedLayoutOnly(other, changedContextSensitiveProperties))
846         return StyleDifferenceLayoutPositionedMovementOnly;
847
848     if (changeRequiresLayerRepaint(other, changedContextSensitiveProperties))
849         return StyleDifferenceRepaintLayer;
850
851     if (changeRequiresRepaint(other, changedContextSensitiveProperties))
852         return StyleDifferenceRepaint;
853
854 #if USE(ACCELERATED_COMPOSITING)
855     if (changeRequiresRecompositeLayer(other, changedContextSensitiveProperties))
856         return StyleDifferenceRecompositeLayer;
857 #endif
858
859     if (changeRequiresRepaintIfTextOrBorderOrOutline(other, changedContextSensitiveProperties))
860         return StyleDifferenceRepaintIfTextOrBorderOrOutline;
861
862     // Cursors are not checked, since they will be set appropriately in response to mouse events,
863     // so they don't need to cause any repaint or layout.
864
865     // Animations don't need to be checked either.  We always set the new style on the RenderObject, so we will get a chance to fire off
866     // the resulting transition properly.
867     return StyleDifferenceEqual;
868 }
869
870 bool RenderStyle::diffRequiresRepaint(const RenderStyle* style) const
871 {
872     unsigned changedContextSensitiveProperties = 0;
873     return changeRequiresRepaint(style, changedContextSensitiveProperties);
874 }
875
876 void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
877 {
878     StyleVisualData* data = visual.access();
879     data->clip.m_top = top;
880     data->clip.m_right = right;
881     data->clip.m_bottom = bottom;
882     data->clip.m_left = left;
883 }
884
885 void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
886 {
887     if (!rareInheritedData.access()->cursorData)
888         rareInheritedData.access()->cursorData = CursorList::create();
889     rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
890 }
891
892 void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
893 {
894     rareInheritedData.access()->cursorData = other;
895 }
896
897 void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
898 {
899     if (rareInheritedData->quotes == q || (rareInheritedData->quotes && q && *rareInheritedData->quotes == *q))
900         return;
901
902     rareInheritedData.access()->quotes = q;
903 }
904
905 void RenderStyle::clearCursorList()
906 {
907     if (rareInheritedData->cursorData)
908         rareInheritedData.access()->cursorData = 0;
909 }
910
911 void RenderStyle::clearContent()
912 {
913     if (rareNonInheritedData->m_content)
914         rareNonInheritedData.access()->m_content = nullptr;
915 }
916
917 void RenderStyle::appendContent(std::unique_ptr<ContentData> contentData)
918 {
919     auto& content = rareNonInheritedData.access()->m_content;
920     ContentData* lastContent = content.get();
921     while (lastContent && lastContent->next())
922         lastContent = lastContent->next();
923
924     if (lastContent)
925         lastContent->setNext(std::move(contentData));
926     else
927         content = std::move(contentData);
928 }
929
930 void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
931 {
932     if (!image)
933         return;
934         
935     if (add) {
936         appendContent(std::make_unique<ImageContentData>(image));
937         return;
938     }
939
940     rareNonInheritedData.access()->m_content = std::make_unique<ImageContentData>(image);
941 }
942
943 void RenderStyle::setContent(const String& string, bool add)
944 {
945     auto& content = rareNonInheritedData.access()->m_content;
946     if (add) {
947         ContentData* lastContent = content.get();
948         while (lastContent && lastContent->next())
949             lastContent = lastContent->next();
950
951         if (lastContent) {
952             // We attempt to merge with the last ContentData if possible.
953             if (lastContent->isText()) {
954                 TextContentData* textContent = static_cast<TextContentData*>(lastContent);
955                 textContent->setText(textContent->text() + string);
956             } else
957                 lastContent->setNext(std::make_unique<TextContentData>(string));
958
959             return;
960         }
961     }
962
963     content = std::make_unique<TextContentData>(string);
964 }
965
966 void RenderStyle::setContent(std::unique_ptr<CounterContent> counter, bool add)
967 {
968     if (!counter)
969         return;
970
971     if (add) {
972         appendContent(std::make_unique<CounterContentData>(std::move(counter)));
973         return;
974     }
975
976     rareNonInheritedData.access()->m_content = std::make_unique<CounterContentData>(std::move(counter));
977 }
978
979 void RenderStyle::setContent(QuoteType quote, bool add)
980 {
981     if (add) {
982         appendContent(std::make_unique<QuoteContentData>(quote));
983         return;
984     }
985
986     rareNonInheritedData.access()->m_content = std::make_unique<QuoteContentData>(quote);
987 }
988     
989 inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation>>& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
990 {
991     // transform-origin brackets the transform with translate operations.
992     // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
993     // in that case.
994     if (applyOrigin != RenderStyle::IncludeTransformOrigin)
995         return false;
996
997     unsigned size = transformOperations.size();
998     for (unsigned i = 0; i < size; ++i) {
999         TransformOperation::OperationType type = transformOperations[i]->type();
1000         if (type != TransformOperation::TRANSLATE_X
1001             && type != TransformOperation::TRANSLATE_Y
1002             && type != TransformOperation::TRANSLATE 
1003             && type != TransformOperation::TRANSLATE_Z
1004             && type != TransformOperation::TRANSLATE_3D)
1005             return true;
1006     }
1007     
1008     return false;
1009 }
1010
1011 void RenderStyle::applyTransform(TransformationMatrix& transform, const LayoutSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const
1012 {
1013     // FIXME: when subpixel layout is supported (bug 71143) the body of this function could be replaced by
1014     // applyTransform(transform, FloatRect(FloatPoint(), borderBoxSize), applyOrigin);
1015     
1016     const Vector<RefPtr<TransformOperation>>& transformOperations = rareNonInheritedData->m_transform->m_operations.operations();
1017     bool applyTransformOrigin = requireTransformOrigin(transformOperations, applyOrigin);
1018
1019     if (applyTransformOrigin)
1020         transform.translate3d(floatValueForLength(transformOriginX(), borderBoxSize.width()), floatValueForLength(transformOriginY(), borderBoxSize.height()), transformOriginZ());
1021
1022     unsigned size = transformOperations.size();
1023     for (unsigned i = 0; i < size; ++i)
1024         transformOperations[i]->apply(transform, borderBoxSize);
1025
1026     if (applyTransformOrigin)
1027         transform.translate3d(-floatValueForLength(transformOriginX(), borderBoxSize.width()), -floatValueForLength(transformOriginY(), borderBoxSize.height()), -transformOriginZ()); 
1028 }
1029
1030 void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const
1031 {
1032     const Vector<RefPtr<TransformOperation>>& transformOperations = rareNonInheritedData->m_transform->m_operations.operations();
1033     bool applyTransformOrigin = requireTransformOrigin(transformOperations, applyOrigin);
1034     
1035     float offsetX = transformOriginX().type() == Percent ? boundingBox.x() : 0;
1036     float offsetY = transformOriginY().type() == Percent ? boundingBox.y() : 0;
1037     
1038     if (applyTransformOrigin) {
1039         transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX,
1040                               floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY,
1041                               transformOriginZ());
1042     }
1043     
1044     unsigned size = transformOperations.size();
1045     for (unsigned i = 0; i < size; ++i)
1046         transformOperations[i]->apply(transform, boundingBox.size());
1047     
1048     if (applyTransformOrigin) {
1049         transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX,
1050                               -floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY,
1051                               -transformOriginZ());
1052     }
1053 }
1054
1055 void RenderStyle::setPageScaleTransform(float scale)
1056 {
1057     if (scale == 1)
1058         return;
1059     TransformOperations transform;
1060     transform.operations().append(ScaleTransformOperation::create(scale, scale, ScaleTransformOperation::SCALE));
1061     setTransform(transform);
1062     setTransformOriginX(Length(0, Fixed));
1063     setTransformOriginY(Length(0, Fixed));
1064 }
1065
1066 void RenderStyle::setTextShadow(PassOwnPtr<ShadowData> shadowData, bool add)
1067 {
1068     ASSERT(!shadowData || (!shadowData->spread() && shadowData->style() == Normal));
1069
1070     StyleRareInheritedData* rareData = rareInheritedData.access();
1071     if (!add) {
1072         rareData->textShadow = shadowData;
1073         return;
1074     }
1075
1076     shadowData->setNext(rareData->textShadow.release());
1077     rareData->textShadow = shadowData;
1078 }
1079
1080 void RenderStyle::setBoxShadow(PassOwnPtr<ShadowData> shadowData, bool add)
1081 {
1082     StyleRareNonInheritedData* rareData = rareNonInheritedData.access();
1083     if (!add) {
1084         rareData->m_boxShadow = shadowData;
1085         return;
1086     }
1087
1088     shadowData->setNext(rareData->m_boxShadow.release());
1089     rareData->m_boxShadow = shadowData;
1090 }
1091
1092 static RoundedRect::Radii calcRadiiFor(const BorderData& border, IntSize size, RenderView* renderView)
1093 {
1094     return RoundedRect::Radii(
1095         IntSize(valueForLength(border.topLeft().width(), size.width(), renderView), 
1096                 valueForLength(border.topLeft().height(), size.height(), renderView)),
1097         IntSize(valueForLength(border.topRight().width(), size.width(), renderView),
1098                 valueForLength(border.topRight().height(), size.height(), renderView)),
1099         IntSize(valueForLength(border.bottomLeft().width(), size.width(), renderView), 
1100                 valueForLength(border.bottomLeft().height(), size.height(), renderView)),
1101         IntSize(valueForLength(border.bottomRight().width(), size.width(), renderView), 
1102                 valueForLength(border.bottomRight().height(), size.height(), renderView)));
1103 }
1104
1105 static float calcConstraintScaleFor(const IntRect& rect, const RoundedRect::Radii& radii)
1106 {
1107     // Constrain corner radii using CSS3 rules:
1108     // http://www.w3.org/TR/css3-background/#the-border-radius
1109     
1110     float factor = 1;
1111     unsigned radiiSum;
1112
1113     // top
1114     radiiSum = static_cast<unsigned>(radii.topLeft().width()) + static_cast<unsigned>(radii.topRight().width()); // Casts to avoid integer overflow.
1115     if (radiiSum > static_cast<unsigned>(rect.width()))
1116         factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
1117
1118     // bottom
1119     radiiSum = static_cast<unsigned>(radii.bottomLeft().width()) + static_cast<unsigned>(radii.bottomRight().width());
1120     if (radiiSum > static_cast<unsigned>(rect.width()))
1121         factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
1122     
1123     // left
1124     radiiSum = static_cast<unsigned>(radii.topLeft().height()) + static_cast<unsigned>(radii.bottomLeft().height());
1125     if (radiiSum > static_cast<unsigned>(rect.height()))
1126         factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
1127     
1128     // right
1129     radiiSum = static_cast<unsigned>(radii.topRight().height()) + static_cast<unsigned>(radii.bottomRight().height());
1130     if (radiiSum > static_cast<unsigned>(rect.height()))
1131         factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
1132     
1133     ASSERT(factor <= 1);
1134     return factor;
1135 }
1136
1137 StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); }
1138 void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v)
1139 {
1140     if (rareInheritedData->listStyleImage != v)
1141         rareInheritedData.access()->listStyleImage = v;
1142 }
1143
1144 Color RenderStyle::color() const { return inherited->color; }
1145 Color RenderStyle::visitedLinkColor() const { return inherited->visitedLinkColor; }
1146 void RenderStyle::setColor(const Color& v) { SET_VAR(inherited, color, v); }
1147 void RenderStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visitedLinkColor, v); }
1148
1149 short RenderStyle::horizontalBorderSpacing() const { return inherited->horizontal_border_spacing; }
1150 short RenderStyle::verticalBorderSpacing() const { return inherited->vertical_border_spacing; }
1151 void RenderStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v); }
1152 void RenderStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertical_border_spacing, v); }
1153
1154 RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, RenderView* renderView, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1155 {
1156     IntRect snappedBorderRect(pixelSnappedIntRect(borderRect));
1157     RoundedRect roundedRect(snappedBorderRect);
1158     if (hasBorderRadius()) {
1159         RoundedRect::Radii radii = calcRadiiFor(surround->border, snappedBorderRect.size(), renderView);
1160         radii.scale(calcConstraintScaleFor(snappedBorderRect, radii));
1161         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1162     }
1163     return roundedRect;
1164 }
1165
1166 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1167 {
1168     bool horizontal = isHorizontalWritingMode();
1169
1170     int leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
1171     int rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
1172     int topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
1173     int bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;
1174
1175     return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
1176 }
1177
1178 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect,
1179     int topWidth, int bottomWidth, int leftWidth, int rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1180 {
1181     LayoutRect innerRect(borderRect.x() + leftWidth, 
1182                borderRect.y() + topWidth, 
1183                borderRect.width() - leftWidth - rightWidth, 
1184                borderRect.height() - topWidth - bottomWidth);
1185
1186     RoundedRect roundedRect(pixelSnappedIntRect(innerRect));
1187
1188     if (hasBorderRadius()) {
1189         RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii();
1190         radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
1191         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1192     }
1193     return roundedRect;
1194 }
1195
1196 static bool allLayersAreFixed(const FillLayer* layer)
1197 {
1198     bool allFixed = true;
1199     
1200     for (const FillLayer* currLayer = layer; currLayer; currLayer = currLayer->next())
1201         allFixed &= (currLayer->image() && currLayer->attachment() == FixedBackgroundAttachment);
1202
1203     return layer && allFixed;
1204 }
1205
1206 bool RenderStyle::hasEntirelyFixedBackground() const
1207 {
1208     return allLayersAreFixed(backgroundLayers());
1209 }
1210
1211 const CounterDirectiveMap* RenderStyle::counterDirectives() const
1212 {
1213     return rareNonInheritedData->m_counterDirectives.get();
1214 }
1215
1216 CounterDirectiveMap& RenderStyle::accessCounterDirectives()
1217 {
1218     OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterDirectives;
1219     if (!map)
1220         map = adoptPtr(new CounterDirectiveMap);
1221     return *map;
1222 }
1223
1224 const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const
1225 {
1226     if (const CounterDirectiveMap* directives = counterDirectives())
1227         return directives->get(identifier);
1228     return CounterDirectives();
1229 }
1230
1231 const AtomicString& RenderStyle::hyphenString() const
1232 {
1233     ASSERT(hyphens() != HyphensNone);
1234
1235     const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString;
1236     if (!hyphenationString.isNull())
1237         return hyphenationString;
1238
1239     // FIXME: This should depend on locale.
1240     DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinus, 1));
1241     DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphen, 1));
1242     return font().primaryFontHasGlyphForCharacter(hyphen) ? hyphenString : hyphenMinusString;
1243 }
1244
1245 const AtomicString& RenderStyle::textEmphasisMarkString() const
1246 {
1247     switch (textEmphasisMark()) {
1248     case TextEmphasisMarkNone:
1249         return nullAtom;
1250     case TextEmphasisMarkCustom:
1251         return textEmphasisCustomMark();
1252     case TextEmphasisMarkDot: {
1253         DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1));
1254         DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1));
1255         return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
1256     }
1257     case TextEmphasisMarkCircle: {
1258         DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1));
1259         DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1));
1260         return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString;
1261     }
1262     case TextEmphasisMarkDoubleCircle: {
1263         DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1));
1264         DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1));
1265         return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString;
1266     }
1267     case TextEmphasisMarkTriangle: {
1268         DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointingTriangle, 1));
1269         DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingTriangle, 1));
1270         return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString;
1271     }
1272     case TextEmphasisMarkSesame: {
1273         DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1));
1274         DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1));
1275         return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString;
1276     }
1277     case TextEmphasisMarkAuto:
1278         ASSERT_NOT_REACHED();
1279         return nullAtom;
1280     }
1281
1282     ASSERT_NOT_REACHED();
1283     return nullAtom;
1284 }
1285
1286 #if ENABLE(DASHBOARD_SUPPORT)
1287 const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
1288 {
1289     DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ());
1290     return emptyList;
1291 }
1292
1293 const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
1294 {
1295     DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, noneList, ());
1296     static bool noneListInitialized = false;
1297
1298     if (!noneListInitialized) {
1299         StyleDashboardRegion region;
1300         region.label = "";
1301         region.offset.m_top  = Length();
1302         region.offset.m_right = Length();
1303         region.offset.m_bottom = Length();
1304         region.offset.m_left = Length();
1305         region.type = StyleDashboardRegion::None;
1306         noneList.append(region);
1307         noneListInitialized = true;
1308     }
1309     return noneList;
1310 }
1311 #endif
1312
1313 void RenderStyle::adjustAnimations()
1314 {
1315     AnimationList* animationList = rareNonInheritedData->m_animations.get();
1316     if (!animationList)
1317         return;
1318
1319     // Get rid of empty animations and anything beyond them
1320     for (size_t i = 0; i < animationList->size(); ++i) {
1321         if (animationList->animation(i).isEmpty()) {
1322             animationList->resize(i);
1323             break;
1324         }
1325     }
1326
1327     if (animationList->isEmpty()) {
1328         clearAnimations();
1329         return;
1330     }
1331
1332     // Repeat patterns into layers that don't have some properties set.
1333     animationList->fillUnsetProperties();
1334 }
1335
1336 void RenderStyle::adjustTransitions()
1337 {
1338     AnimationList* transitionList = rareNonInheritedData->m_transitions.get();
1339     if (!transitionList)
1340         return;
1341
1342     // Get rid of empty transitions and anything beyond them
1343     for (size_t i = 0; i < transitionList->size(); ++i) {
1344         if (transitionList->animation(i).isEmpty()) {
1345             transitionList->resize(i);
1346             break;
1347         }
1348     }
1349
1350     if (transitionList->isEmpty()) {
1351         clearTransitions();
1352         return;
1353     }
1354
1355     // Repeat patterns into layers that don't have some properties set.
1356     transitionList->fillUnsetProperties();
1357
1358     // Make sure there are no duplicate properties. This is an O(n^2) algorithm
1359     // but the lists tend to be very short, so it is probably ok
1360     for (size_t i = 0; i < transitionList->size(); ++i) {
1361         for (size_t j = i+1; j < transitionList->size(); ++j) {
1362             if (transitionList->animation(i).property() == transitionList->animation(j).property()) {
1363                 // toss i
1364                 transitionList->remove(i);
1365                 j = i;
1366             }
1367         }
1368     }
1369 }
1370
1371 AnimationList* RenderStyle::accessAnimations()
1372 {
1373     if (!rareNonInheritedData.access()->m_animations)
1374         rareNonInheritedData.access()->m_animations = adoptPtr(new AnimationList());
1375     return rareNonInheritedData->m_animations.get();
1376 }
1377
1378 AnimationList* RenderStyle::accessTransitions()
1379 {
1380     if (!rareNonInheritedData.access()->m_transitions)
1381         rareNonInheritedData.access()->m_transitions = adoptPtr(new AnimationList());
1382     return rareNonInheritedData->m_transitions.get();
1383 }
1384
1385 const Animation* RenderStyle::transitionForProperty(CSSPropertyID property) const
1386 {
1387     if (transitions()) {
1388         for (size_t i = 0; i < transitions()->size(); ++i) {
1389             const Animation& p = transitions()->animation(i);
1390             if (p.animationMode() == Animation::AnimateAll || p.property() == property) {
1391                 return &p;
1392             }
1393         }
1394     }
1395     return 0;
1396 }
1397
1398 const Font& RenderStyle::font() const { return inherited->font; }
1399 const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); }
1400 const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); }
1401 float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); }
1402 float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
1403 int RenderStyle::fontSize() const { return inherited->font.pixelSize(); }
1404
1405 int RenderStyle::wordSpacing() const { return inherited->font.wordSpacing(); }
1406 int RenderStyle::letterSpacing() const { return inherited->font.letterSpacing(); }
1407
1408 bool RenderStyle::setFontDescription(const FontDescription& v)
1409 {
1410     if (inherited->font.fontDescription() != v) {
1411         inherited.access()->font = Font(v, inherited->font.letterSpacing(), inherited->font.wordSpacing());
1412         return true;
1413     }
1414     return false;
1415 }
1416
1417 #if ENABLE(IOS_TEXT_AUTOSIZING)
1418 const Length& RenderStyle::specifiedLineHeight() const { return inherited->specifiedLineHeight; }
1419 void RenderStyle::setSpecifiedLineHeight(Length v) { SET_VAR(inherited, specifiedLineHeight, v); }
1420 #else
1421 const Length& RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
1422 #endif
1423
1424 Length RenderStyle::lineHeight() const
1425 {
1426     const Length& lh = inherited->line_height;
1427 #if ENABLE(TEXT_AUTOSIZING)
1428     // Unlike fontDescription().computedSize() and hence fontSize(), this is
1429     // recalculated on demand as we only store the specified line height.
1430     // FIXME: Should consider scaling the fixed part of any calc expressions
1431     // too, though this involves messily poking into CalcExpressionLength.
1432     float multiplier = textAutosizingMultiplier();
1433     if (multiplier > 1 && lh.isFixed())
1434         return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multiplier), Fixed);
1435 #endif
1436     return lh;
1437 }
1438 void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
1439
1440 int RenderStyle::computedLineHeight(RenderView* renderView) const
1441 {
1442     const Length& lh = lineHeight();
1443
1444     // Negative value means the line height is not set. Use the font's built-in spacing.
1445     if (lh.isNegative())
1446         return fontMetrics().lineSpacing();
1447
1448     if (lh.isPercent())
1449         return minimumValueForLength(lh, fontSize());
1450
1451     if (lh.isViewportPercentage())
1452         return valueForLength(lh, 0, renderView);
1453
1454     return lh.value();
1455 }
1456
1457 void RenderStyle::setWordSpacing(int v) { inherited.access()->font.setWordSpacing(v); }
1458 void RenderStyle::setLetterSpacing(int v) { inherited.access()->font.setLetterSpacing(v); }
1459
1460 void RenderStyle::setFontSize(float size)
1461 {
1462     // size must be specifiedSize if Text Autosizing is enabled, but computedSize if text
1463     // zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
1464
1465     ASSERT(std::isfinite(size));
1466     if (!std::isfinite(size) || size < 0)
1467         size = 0;
1468     else
1469         size = min(maximumAllowedFontSize, size);
1470
1471     FontSelector* currentFontSelector = font().fontSelector();
1472     FontDescription desc(fontDescription());
1473     desc.setSpecifiedSize(size);
1474     desc.setComputedSize(size);
1475
1476 #if ENABLE(TEXT_AUTOSIZING)
1477     float multiplier = textAutosizingMultiplier();
1478     if (multiplier > 1) {
1479         float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size, multiplier);
1480         desc.setComputedSize(min(maximumAllowedFontSize, autosizedFontSize));
1481     }
1482 #endif
1483
1484     setFontDescription(desc);
1485     font().update(currentFontSelector);
1486 }
1487
1488 void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
1489 {
1490     top = 0;
1491     right = 0;
1492     bottom = 0;
1493     left = 0;
1494
1495     for ( ; shadow; shadow = shadow->next()) {
1496         if (shadow->style() == Inset)
1497             continue;
1498
1499         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1500         top = min<LayoutUnit>(top, shadow->y() - extentAndSpread);
1501         right = max<LayoutUnit>(right, shadow->x() + extentAndSpread);
1502         bottom = max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
1503         left = min<LayoutUnit>(left, shadow->x() - extentAndSpread);
1504     }
1505 }
1506
1507 LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowData* shadow) const
1508 {
1509     LayoutUnit top = 0;
1510     LayoutUnit right = 0;
1511     LayoutUnit bottom = 0;
1512     LayoutUnit left = 0;
1513
1514     for ( ; shadow; shadow = shadow->next()) {
1515         if (shadow->style() == Normal)
1516             continue;
1517
1518         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1519         top = max<LayoutUnit>(top, shadow->y() + extentAndSpread);
1520         right = min<LayoutUnit>(right, shadow->x() - extentAndSpread);
1521         bottom = min<LayoutUnit>(bottom, shadow->y() - extentAndSpread);
1522         left = max<LayoutUnit>(left, shadow->x() + extentAndSpread);
1523     }
1524
1525     return LayoutBoxExtent(top, right, bottom, left);
1526 }
1527
1528 void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit &left, LayoutUnit &right) const
1529 {
1530     left = 0;
1531     right = 0;
1532
1533     for ( ; shadow; shadow = shadow->next()) {
1534         if (shadow->style() == Inset)
1535             continue;
1536
1537         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1538         left = min<LayoutUnit>(left, shadow->x() - extentAndSpread);
1539         right = max<LayoutUnit>(right, shadow->x() + extentAndSpread);
1540     }
1541 }
1542
1543 void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &bottom) const
1544 {
1545     top = 0;
1546     bottom = 0;
1547
1548     for ( ; shadow; shadow = shadow->next()) {
1549         if (shadow->style() == Inset)
1550             continue;
1551
1552         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1553         top = min<LayoutUnit>(top, shadow->y() - extentAndSpread);
1554         bottom = max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
1555     }
1556 }
1557
1558 Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
1559 {
1560     Color result;
1561     EBorderStyle borderStyle = BNONE;
1562     switch (colorProperty) {
1563     case CSSPropertyBackgroundColor:
1564         return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back.
1565     case CSSPropertyBorderLeftColor:
1566         result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
1567         borderStyle = borderLeftStyle();
1568         break;
1569     case CSSPropertyBorderRightColor:
1570         result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
1571         borderStyle = borderRightStyle();
1572         break;
1573     case CSSPropertyBorderTopColor:
1574         result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
1575         borderStyle = borderTopStyle();
1576         break;
1577     case CSSPropertyBorderBottomColor:
1578         result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
1579         borderStyle = borderBottomStyle();
1580         break;
1581     case CSSPropertyColor:
1582         result = visitedLink ? visitedLinkColor() : color();
1583         break;
1584     case CSSPropertyOutlineColor:
1585         result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
1586         break;
1587     case CSSPropertyWebkitColumnRuleColor:
1588         result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
1589         break;
1590 #if ENABLE(CSS3_TEXT_DECORATION)
1591     case CSSPropertyWebkitTextDecorationColor:
1592         // Text decoration color fallback is handled in RenderObject::decorationColor.
1593         return visitedLink ? visitedLinkTextDecorationColor() : textDecorationColor();
1594 #endif
1595     case CSSPropertyWebkitTextEmphasisColor:
1596         result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
1597         break;
1598     case CSSPropertyWebkitTextFillColor:
1599         result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
1600         break;
1601     case CSSPropertyWebkitTextStrokeColor:
1602         result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
1603         break;
1604     default:
1605         ASSERT_NOT_REACHED();
1606         break;
1607     }
1608
1609     if (!result.isValid()) {
1610         if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
1611             result.setRGB(238, 238, 238);
1612         else
1613             result = visitedLink ? visitedLinkColor() : color();
1614     }
1615     return result;
1616 }
1617
1618 Color RenderStyle::visitedDependentColor(int colorProperty) const
1619 {
1620     Color unvisitedColor = colorIncludingFallback(colorProperty, false);
1621     if (insideLink() != InsideVisitedLink)
1622         return unvisitedColor;
1623
1624     Color visitedColor = colorIncludingFallback(colorProperty, true);
1625
1626 #if ENABLE(CSS3_TEXT_DECORATION)
1627     // Text decoration color validity is preserved (checked in RenderObject::decorationColor).
1628     if (colorProperty == CSSPropertyWebkitTextDecorationColor)
1629         return visitedColor;
1630 #endif
1631
1632     // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
1633     // assume that if the background color is transparent that it wasn't set. Note that it's weird that
1634     // we're returning unvisited info for a visited link, but given our restriction that the alpha values
1635     // have to match, it makes more sense to return the unvisited background color if specified than it
1636     // does to return black. This behavior matches what Firefox 4 does as well.
1637     if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent)
1638         return unvisitedColor;
1639
1640     // Take the alpha from the unvisited color, but get the RGB values from the visited color.
1641     return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
1642 }
1643
1644 const BorderValue& RenderStyle::borderBefore() const
1645 {
1646     switch (writingMode()) {
1647     case TopToBottomWritingMode:
1648         return borderTop();
1649     case BottomToTopWritingMode:
1650         return borderBottom();
1651     case LeftToRightWritingMode:
1652         return borderLeft();
1653     case RightToLeftWritingMode:
1654         return borderRight();
1655     }
1656     ASSERT_NOT_REACHED();
1657     return borderTop();
1658 }
1659
1660 const BorderValue& RenderStyle::borderAfter() const
1661 {
1662     switch (writingMode()) {
1663     case TopToBottomWritingMode:
1664         return borderBottom();
1665     case BottomToTopWritingMode:
1666         return borderTop();
1667     case LeftToRightWritingMode:
1668         return borderRight();
1669     case RightToLeftWritingMode:
1670         return borderLeft();
1671     }
1672     ASSERT_NOT_REACHED();
1673     return borderBottom();
1674 }
1675
1676 const BorderValue& RenderStyle::borderStart() const
1677 {
1678     if (isHorizontalWritingMode())
1679         return isLeftToRightDirection() ? borderLeft() : borderRight();
1680     return isLeftToRightDirection() ? borderTop() : borderBottom();
1681 }
1682
1683 const BorderValue& RenderStyle::borderEnd() const
1684 {
1685     if (isHorizontalWritingMode())
1686         return isLeftToRightDirection() ? borderRight() : borderLeft();
1687     return isLeftToRightDirection() ? borderBottom() : borderTop();
1688 }
1689
1690 unsigned short RenderStyle::borderBeforeWidth() const
1691 {
1692     switch (writingMode()) {
1693     case TopToBottomWritingMode:
1694         return borderTopWidth();
1695     case BottomToTopWritingMode:
1696         return borderBottomWidth();
1697     case LeftToRightWritingMode:
1698         return borderLeftWidth();
1699     case RightToLeftWritingMode:
1700         return borderRightWidth();
1701     }
1702     ASSERT_NOT_REACHED();
1703     return borderTopWidth();
1704 }
1705
1706 unsigned short RenderStyle::borderAfterWidth() const
1707 {
1708     switch (writingMode()) {
1709     case TopToBottomWritingMode:
1710         return borderBottomWidth();
1711     case BottomToTopWritingMode:
1712         return borderTopWidth();
1713     case LeftToRightWritingMode:
1714         return borderRightWidth();
1715     case RightToLeftWritingMode:
1716         return borderLeftWidth();
1717     }
1718     ASSERT_NOT_REACHED();
1719     return borderBottomWidth();
1720 }
1721
1722 unsigned short RenderStyle::borderStartWidth() const
1723 {
1724     if (isHorizontalWritingMode())
1725         return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
1726     return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
1727 }
1728
1729 unsigned short RenderStyle::borderEndWidth() const
1730 {
1731     if (isHorizontalWritingMode())
1732         return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
1733     return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
1734 }
1735
1736 void RenderStyle::setMarginStart(Length margin)
1737 {
1738     if (isHorizontalWritingMode()) {
1739         if (isLeftToRightDirection())
1740             setMarginLeft(margin);
1741         else
1742             setMarginRight(margin);
1743     } else {
1744         if (isLeftToRightDirection())
1745             setMarginTop(margin);
1746         else
1747             setMarginBottom(margin);
1748     }
1749 }
1750
1751 void RenderStyle::setMarginEnd(Length margin)
1752 {
1753     if (isHorizontalWritingMode()) {
1754         if (isLeftToRightDirection())
1755             setMarginRight(margin);
1756         else
1757             setMarginLeft(margin);
1758     } else {
1759         if (isLeftToRightDirection())
1760             setMarginBottom(margin);
1761         else
1762             setMarginTop(margin);
1763     }
1764 }
1765
1766 TextEmphasisMark RenderStyle::textEmphasisMark() const
1767 {
1768     TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark);
1769     if (mark != TextEmphasisMarkAuto)
1770         return mark;
1771
1772     if (isHorizontalWritingMode())
1773         return TextEmphasisMarkDot;
1774
1775     return TextEmphasisMarkSesame;
1776 }
1777
1778 #if ENABLE(TOUCH_EVENTS)
1779 Color RenderStyle::initialTapHighlightColor()
1780 {
1781     return RenderTheme::tapHighlightColor();
1782 }
1783 #endif
1784
1785 LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
1786 {
1787     return LayoutBoxExtent(NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()),
1788                            NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()),
1789                            NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth()),
1790                            NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()));
1791 }
1792
1793 void RenderStyle::getFontAndGlyphOrientation(FontOrientation& fontOrientation, NonCJKGlyphOrientation& glyphOrientation)
1794 {
1795     if (isHorizontalWritingMode()) {
1796         fontOrientation = Horizontal;
1797         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1798         return;
1799     }
1800
1801     switch (textOrientation()) {
1802     case TextOrientationVerticalRight:
1803         fontOrientation = Vertical;
1804         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1805         return;
1806     case TextOrientationUpright:
1807         fontOrientation = Vertical;
1808         glyphOrientation = NonCJKGlyphOrientationUpright;
1809         return;
1810     case TextOrientationSideways:
1811         if (writingMode() == LeftToRightWritingMode) {
1812             // FIXME: This should map to sideways-left, which is not supported yet.
1813             fontOrientation = Vertical;
1814             glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1815             return;
1816         }
1817         fontOrientation = Horizontal;
1818         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1819         return;
1820     case TextOrientationSidewaysRight:
1821         fontOrientation = Horizontal;
1822         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1823         return;
1824     default:
1825         ASSERT_NOT_REACHED();
1826         fontOrientation = Horizontal;
1827         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1828         return;
1829     }
1830 }
1831
1832 void RenderStyle::setBorderImageSource(PassRefPtr<StyleImage> image)
1833 {
1834     if (surround->border.m_image.image() == image.get())
1835         return;
1836     surround.access()->border.m_image.setImage(image);
1837 }
1838
1839 void RenderStyle::setBorderImageSlices(LengthBox slices)
1840 {
1841     if (surround->border.m_image.imageSlices() == slices)
1842         return;
1843     surround.access()->border.m_image.setImageSlices(slices);
1844 }
1845
1846 void RenderStyle::setBorderImageWidth(LengthBox slices)
1847 {
1848     if (surround->border.m_image.borderSlices() == slices)
1849         return;
1850     surround.access()->border.m_image.setBorderSlices(slices);
1851 }
1852
1853 void RenderStyle::setBorderImageOutset(LengthBox outset)
1854 {
1855     if (surround->border.m_image.outset() == outset)
1856         return;
1857     surround.access()->border.m_image.setOutset(outset);
1858 }
1859
1860 #if ENABLE(CSS_SHAPES)
1861 ShapeValue* RenderStyle::initialShapeInside()
1862 {
1863     static ShapeValue* outsideValue = ShapeValue::createOutsideValue().leakRef();
1864     return outsideValue;
1865 }
1866 #endif
1867
1868 void RenderStyle::setColumnStylesFromPaginationMode(const Pagination::Mode& paginationMode)
1869 {
1870     if (paginationMode == Pagination::Unpaginated)
1871         return;
1872         
1873     switch (paginationMode) {
1874     case Pagination::LeftToRightPaginated:
1875         setColumnAxis(HorizontalColumnAxis);
1876         if (isHorizontalWritingMode())
1877             setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1878         else
1879             setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1880         break;
1881     case Pagination::RightToLeftPaginated:
1882         setColumnAxis(HorizontalColumnAxis);
1883         if (isHorizontalWritingMode())
1884             setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1885         else
1886             setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1887         break;
1888     case Pagination::TopToBottomPaginated:
1889         setColumnAxis(VerticalColumnAxis);
1890         if (isHorizontalWritingMode())
1891             setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1892         else
1893             setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1894         break;
1895     case Pagination::BottomToTopPaginated:
1896         setColumnAxis(VerticalColumnAxis);
1897         if (isHorizontalWritingMode())
1898             setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1899         else
1900             setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1901         break;
1902     case Pagination::Unpaginated:
1903         ASSERT_NOT_REACHED();
1904         break;
1905     }
1906 }
1907
1908 } // namespace WebCore