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