• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/rendering/style/RenderStyle.h"
25 
26 #include <algorithm>
27 #include "RuntimeEnabledFeatures.h"
28 #include "core/css/resolver/StyleResolver.h"
29 #include "core/rendering/RenderTheme.h"
30 #include "core/rendering/TextAutosizer.h"
31 #include "core/rendering/style/ContentData.h"
32 #include "core/rendering/style/CursorList.h"
33 #include "core/rendering/style/QuotesData.h"
34 #include "core/rendering/style/ShadowList.h"
35 #include "core/rendering/style/StyleImage.h"
36 #include "core/rendering/style/StyleInheritedData.h"
37 #include "platform/fonts/Font.h"
38 #include "platform/fonts/FontSelector.h"
39 #include "wtf/MathExtras.h"
40 
41 using namespace std;
42 
43 namespace WebCore {
44 
45 struct SameSizeAsBorderValue {
46     RGBA32 m_color;
47     unsigned m_width;
48 };
49 
50 COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow);
51 
52 struct SameSizeAsRenderStyle : public RefCounted<SameSizeAsRenderStyle> {
53     void* dataRefs[7];
54     void* ownPtrs[1];
55     void* dataRefSvgStyle;
56 
57     struct InheritedFlags {
58         unsigned m_bitfields[2];
59     } inherited_flags;
60 
61     struct NonInheritedFlags {
62         unsigned m_bitfields[2];
63     } noninherited_flags;
64 };
65 
66 COMPILE_ASSERT(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small);
67 
defaultStyle()68 inline RenderStyle* defaultStyle()
69 {
70     DEFINE_STATIC_REF(RenderStyle, s_defaultStyle, (RenderStyle::createDefaultStyle()));
71     return s_defaultStyle;
72 }
73 
create()74 PassRefPtr<RenderStyle> RenderStyle::create()
75 {
76     return adoptRef(new RenderStyle());
77 }
78 
createDefaultStyle()79 PassRefPtr<RenderStyle> RenderStyle::createDefaultStyle()
80 {
81     return adoptRef(new RenderStyle(DefaultStyle));
82 }
83 
createAnonymousStyleWithDisplay(const RenderStyle * parentStyle,EDisplay display)84 PassRefPtr<RenderStyle> RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay display)
85 {
86     RefPtr<RenderStyle> newStyle = RenderStyle::create();
87     newStyle->inheritFrom(parentStyle);
88     newStyle->inheritUnicodeBidiFrom(parentStyle);
89     newStyle->setDisplay(display);
90     return newStyle;
91 }
92 
clone(const RenderStyle * other)93 PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other)
94 {
95     return adoptRef(new RenderStyle(*other));
96 }
97 
RenderStyle()98 ALWAYS_INLINE RenderStyle::RenderStyle()
99     : m_box(defaultStyle()->m_box)
100     , visual(defaultStyle()->visual)
101     , m_background(defaultStyle()->m_background)
102     , surround(defaultStyle()->surround)
103     , rareNonInheritedData(defaultStyle()->rareNonInheritedData)
104     , rareInheritedData(defaultStyle()->rareInheritedData)
105     , inherited(defaultStyle()->inherited)
106     , m_svgStyle(defaultStyle()->m_svgStyle)
107 {
108     setBitDefaults(); // Would it be faster to copy this from the default style?
109     COMPILE_ASSERT((sizeof(InheritedFlags) <= 8), InheritedFlags_does_not_grow);
110     COMPILE_ASSERT((sizeof(NonInheritedFlags) <= 8), NonInheritedFlags_does_not_grow);
111 }
112 
RenderStyle(DefaultStyleTag)113 ALWAYS_INLINE RenderStyle::RenderStyle(DefaultStyleTag)
114 {
115     setBitDefaults();
116 
117     m_box.init();
118     visual.init();
119     m_background.init();
120     surround.init();
121     rareNonInheritedData.init();
122     rareNonInheritedData.access()->m_deprecatedFlexibleBox.init();
123     rareNonInheritedData.access()->m_flexibleBox.init();
124     rareNonInheritedData.access()->m_marquee.init();
125     rareNonInheritedData.access()->m_multiCol.init();
126     rareNonInheritedData.access()->m_transform.init();
127     rareNonInheritedData.access()->m_filter.init();
128     rareNonInheritedData.access()->m_grid.init();
129     rareNonInheritedData.access()->m_gridItem.init();
130     rareInheritedData.init();
131     inherited.init();
132     m_svgStyle.init();
133 }
134 
RenderStyle(const RenderStyle & o)135 ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o)
136     : RefCounted<RenderStyle>()
137     , m_box(o.m_box)
138     , visual(o.visual)
139     , m_background(o.m_background)
140     , surround(o.surround)
141     , rareNonInheritedData(o.rareNonInheritedData)
142     , rareInheritedData(o.rareInheritedData)
143     , inherited(o.inherited)
144     , m_svgStyle(o.m_svgStyle)
145     , inherited_flags(o.inherited_flags)
146     , noninherited_flags(o.noninherited_flags)
147 {
148 }
149 
comparePseudoStyles(const RenderStyle * oldStyle,const RenderStyle * newStyle)150 static StyleRecalcChange comparePseudoStyles(const RenderStyle* oldStyle, const RenderStyle* newStyle)
151 {
152     // If the pseudoStyles have changed, we want any StyleRecalcChange that is not NoChange
153     // because setStyle will do the right thing with anything else.
154     if (!oldStyle->hasAnyPublicPseudoStyles())
155         return NoChange;
156     for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < FIRST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
157         if (!oldStyle->hasPseudoStyle(pseudoId))
158             continue;
159         RenderStyle* newPseudoStyle = newStyle->getCachedPseudoStyle(pseudoId);
160         if (!newPseudoStyle)
161             return NoInherit;
162         RenderStyle* oldPseudoStyle = oldStyle->getCachedPseudoStyle(pseudoId);
163         if (oldPseudoStyle && *oldPseudoStyle != *newPseudoStyle)
164             return NoInherit;
165     }
166     return NoChange;
167 }
168 
compare(const RenderStyle * oldStyle,const RenderStyle * newStyle)169 StyleRecalcChange RenderStyle::compare(const RenderStyle* oldStyle, const RenderStyle* newStyle)
170 {
171     if ((!oldStyle && newStyle) || (oldStyle && !newStyle))
172         return Reattach;
173 
174     if (!oldStyle && !newStyle)
175         return NoChange;
176 
177     if (oldStyle->display() != newStyle->display()
178         || oldStyle->hasPseudoStyle(FIRST_LETTER) != newStyle->hasPseudoStyle(FIRST_LETTER)
179         || oldStyle->columnSpan() != newStyle->columnSpan()
180         || oldStyle->specifiesAutoColumns() != newStyle->specifiesAutoColumns()
181         || !oldStyle->contentDataEquivalent(newStyle)
182         || oldStyle->hasTextCombine() != newStyle->hasTextCombine()
183         || oldStyle->flowThread() != newStyle->flowThread()
184         || oldStyle->regionThread() != newStyle->regionThread())
185         return Reattach;
186 
187     if (*oldStyle == *newStyle)
188         return comparePseudoStyles(oldStyle, newStyle);
189 
190     if (oldStyle->inheritedNotEqual(newStyle)
191         || oldStyle->hasExplicitlyInheritedProperties()
192         || newStyle->hasExplicitlyInheritedProperties())
193         return Inherit;
194 
195     return NoInherit;
196 }
197 
inheritFrom(const RenderStyle * inheritParent,IsAtShadowBoundary isAtShadowBoundary)198 void RenderStyle::inheritFrom(const RenderStyle* inheritParent, IsAtShadowBoundary isAtShadowBoundary)
199 {
200     if (isAtShadowBoundary == AtShadowBoundary) {
201         // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable
202         EUserModify currentUserModify = userModify();
203         rareInheritedData = inheritParent->rareInheritedData;
204         setUserModify(currentUserModify);
205     } else
206         rareInheritedData = inheritParent->rareInheritedData;
207     inherited = inheritParent->inherited;
208     inherited_flags = inheritParent->inherited_flags;
209     if (m_svgStyle != inheritParent->m_svgStyle)
210         m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
211 }
212 
copyNonInheritedFrom(const RenderStyle * other)213 void RenderStyle::copyNonInheritedFrom(const RenderStyle* other)
214 {
215     m_box = other->m_box;
216     visual = other->visual;
217     m_background = other->m_background;
218     surround = other->surround;
219     rareNonInheritedData = other->rareNonInheritedData;
220     // The flags are copied one-by-one because noninherited_flags contains a bunch of stuff other than real style data.
221     noninherited_flags._effectiveDisplay = other->noninherited_flags._effectiveDisplay;
222     noninherited_flags._originalDisplay = other->noninherited_flags._originalDisplay;
223     noninherited_flags._overflowX = other->noninherited_flags._overflowX;
224     noninherited_flags._overflowY = other->noninherited_flags._overflowY;
225     noninherited_flags._vertical_align = other->noninherited_flags._vertical_align;
226     noninherited_flags._clear = other->noninherited_flags._clear;
227     noninherited_flags._position = other->noninherited_flags._position;
228     noninherited_flags._floating = other->noninherited_flags._floating;
229     noninherited_flags._table_layout = other->noninherited_flags._table_layout;
230     noninherited_flags._unicodeBidi = other->noninherited_flags._unicodeBidi;
231     noninherited_flags._page_break_before = other->noninherited_flags._page_break_before;
232     noninherited_flags._page_break_after = other->noninherited_flags._page_break_after;
233     noninherited_flags._page_break_inside = other->noninherited_flags._page_break_inside;
234     noninherited_flags.explicitInheritance = other->noninherited_flags.explicitInheritance;
235     noninherited_flags.currentColor = other->noninherited_flags.currentColor;
236     if (m_svgStyle != other->m_svgStyle)
237         m_svgStyle.access()->copyNonInheritedFrom(other->m_svgStyle.get());
238     ASSERT(zoom() == initialZoom());
239 }
240 
operator ==(const RenderStyle & o) const241 bool RenderStyle::operator==(const RenderStyle& o) const
242 {
243     // compare everything except the pseudoStyle pointer
244     return inherited_flags == o.inherited_flags
245         && noninherited_flags == o.noninherited_flags
246         && m_box == o.m_box
247         && visual == o.visual
248         && m_background == o.m_background
249         && surround == o.surround
250         && rareNonInheritedData == o.rareNonInheritedData
251         && rareInheritedData == o.rareInheritedData
252         && inherited == o.inherited
253         && m_svgStyle == o.m_svgStyle;
254 }
255 
isStyleAvailable() const256 bool RenderStyle::isStyleAvailable() const
257 {
258     return this != StyleResolver::styleNotYetAvailable();
259 }
260 
hasUniquePseudoStyle() const261 bool RenderStyle::hasUniquePseudoStyle() const
262 {
263     if (!m_cachedPseudoStyles || styleType() != NOPSEUDO)
264         return false;
265 
266     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
267         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
268         if (pseudoStyle->unique())
269             return true;
270     }
271 
272     return false;
273 }
274 
getCachedPseudoStyle(PseudoId pid) const275 RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
276 {
277     if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
278         return 0;
279 
280     if (styleType() != NOPSEUDO)
281         return 0;
282 
283     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
284         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
285         if (pseudoStyle->styleType() == pid)
286             return pseudoStyle;
287     }
288 
289     return 0;
290 }
291 
addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)292 RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
293 {
294     if (!pseudo)
295         return 0;
296 
297     ASSERT(pseudo->styleType() > NOPSEUDO);
298 
299     RenderStyle* result = pseudo.get();
300 
301     if (!m_cachedPseudoStyles)
302         m_cachedPseudoStyles = adoptPtr(new PseudoStyleCache);
303 
304     m_cachedPseudoStyles->append(pseudo);
305 
306     return result;
307 }
308 
removeCachedPseudoStyle(PseudoId pid)309 void RenderStyle::removeCachedPseudoStyle(PseudoId pid)
310 {
311     if (!m_cachedPseudoStyles)
312         return;
313     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
314         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
315         if (pseudoStyle->styleType() == pid) {
316             m_cachedPseudoStyles->remove(i);
317             return;
318         }
319     }
320 }
321 
inheritedNotEqual(const RenderStyle * other) const322 bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
323 {
324     return inherited_flags != other->inherited_flags
325            || inherited != other->inherited
326            || m_svgStyle->inheritedNotEqual(other->m_svgStyle.get())
327            || rareInheritedData != other->rareInheritedData;
328 }
329 
inheritedDataShared(const RenderStyle * other) const330 bool RenderStyle::inheritedDataShared(const RenderStyle* other) const
331 {
332     // This is a fast check that only looks if the data structures are shared.
333     return inherited_flags == other->inherited_flags
334         && inherited.get() == other->inherited.get()
335         && m_svgStyle.get() == other->m_svgStyle.get()
336         && rareInheritedData.get() == other->rareInheritedData.get();
337 }
338 
positionedObjectMoved(const LengthBox & a,const LengthBox & b,const Length & width)339 static bool positionedObjectMoved(const LengthBox& a, const LengthBox& b, const Length& width)
340 {
341     // If any unit types are different, then we can't guarantee
342     // that this was just a movement.
343     if (a.left().type() != b.left().type()
344         || a.right().type() != b.right().type()
345         || a.top().type() != b.top().type()
346         || a.bottom().type() != b.bottom().type())
347         return false;
348 
349     // Only one unit can be non-auto in the horizontal direction and
350     // in the vertical direction.  Otherwise the adjustment of values
351     // is changing the size of the box.
352     if (!a.left().isIntrinsicOrAuto() && !a.right().isIntrinsicOrAuto())
353         return false;
354     if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
355         return false;
356     // If our width is auto and left or right is specified then this
357     // is not just a movement - we need to resize to our container.
358     if ((!a.left().isIntrinsicOrAuto() || !a.right().isIntrinsicOrAuto()) && width.isIntrinsicOrAuto())
359         return false;
360 
361     // One of the units is fixed or percent in both directions and stayed
362     // that way in the new style.  Therefore all we are doing is moving.
363     return true;
364 }
365 
diff(const RenderStyle * other,unsigned & changedContextSensitiveProperties) const366 StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
367 {
368     changedContextSensitiveProperties = ContextSensitivePropertyNone;
369 
370     StyleDifference svgChange = StyleDifferenceEqual;
371     if (m_svgStyle != other->m_svgStyle) {
372         svgChange = m_svgStyle->diff(other->m_svgStyle.get());
373         if (svgChange == StyleDifferenceLayout)
374             return svgChange;
375     }
376 
377     if (m_box->width() != other->m_box->width()
378         || m_box->minWidth() != other->m_box->minWidth()
379         || m_box->maxWidth() != other->m_box->maxWidth()
380         || m_box->height() != other->m_box->height()
381         || m_box->minHeight() != other->m_box->minHeight()
382         || m_box->maxHeight() != other->m_box->maxHeight())
383         return StyleDifferenceLayout;
384 
385     if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
386         return StyleDifferenceLayout;
387 
388     if (m_box->boxSizing() != other->m_box->boxSizing())
389         return StyleDifferenceLayout;
390 
391     if (surround->margin != other->surround->margin)
392         return StyleDifferenceLayout;
393 
394     if (surround->padding != other->surround->padding)
395         return StyleDifferenceLayout;
396 
397     if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
398         if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance
399             || rareNonInheritedData->marginBeforeCollapse != other->rareNonInheritedData->marginBeforeCollapse
400             || rareNonInheritedData->marginAfterCollapse != other->rareNonInheritedData->marginAfterCollapse
401             || rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp
402             || rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
403             return StyleDifferenceLayout;
404 
405         if (rareNonInheritedData->m_regionFragment != other->rareNonInheritedData->m_regionFragment)
406             return StyleDifferenceLayout;
407 
408         if (rareNonInheritedData->m_wrapFlow != other->rareNonInheritedData->m_wrapFlow
409             || rareNonInheritedData->m_wrapThrough != other->rareNonInheritedData->m_wrapThrough
410             || rareNonInheritedData->m_shapeMargin != other->rareNonInheritedData->m_shapeMargin
411             || rareNonInheritedData->m_shapePadding != other->rareNonInheritedData->m_shapePadding)
412             return StyleDifferenceLayout;
413 
414         if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get()
415             && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other->rareNonInheritedData->m_deprecatedFlexibleBox.get())
416             return StyleDifferenceLayout;
417 
418         if (rareNonInheritedData->m_flexibleBox.get() != other->rareNonInheritedData->m_flexibleBox.get()
419             && *rareNonInheritedData->m_flexibleBox.get() != *other->rareNonInheritedData->m_flexibleBox.get())
420             return StyleDifferenceLayout;
421         if (rareNonInheritedData->m_order != other->rareNonInheritedData->m_order
422             || rareNonInheritedData->m_alignContent != other->rareNonInheritedData->m_alignContent
423             || rareNonInheritedData->m_alignItems != other->rareNonInheritedData->m_alignItems
424             || rareNonInheritedData->m_alignSelf != other->rareNonInheritedData->m_alignSelf
425             || rareNonInheritedData->m_justifyContent != other->rareNonInheritedData->m_justifyContent)
426             return StyleDifferenceLayout;
427 
428         // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
429         if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
430             return StyleDifferenceLayout;
431 
432         if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
433             return StyleDifferenceLayout;
434 
435         if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get()
436             && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
437             return StyleDifferenceLayout;
438 
439         if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get()
440             && *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
441             // Don't return early here; instead take note of the type of
442             // change, and deal with it when looking at compositing.
443             changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
444         }
445 
446         if (rareNonInheritedData->m_grid.get() != other->rareNonInheritedData->m_grid.get()
447             || rareNonInheritedData->m_gridItem.get() != other->rareNonInheritedData->m_gridItem.get())
448             return StyleDifferenceLayout;
449 
450         if (rareNonInheritedData->m_shapeInside != other->rareNonInheritedData->m_shapeInside)
451             return StyleDifferenceLayout;
452     }
453 
454     if (rareInheritedData.get() != other->rareInheritedData.get()) {
455         if (rareInheritedData->highlight != other->rareInheritedData->highlight
456             || rareInheritedData->indent != other->rareInheritedData->indent
457             || rareInheritedData->m_textAlignLast != other->rareInheritedData->m_textAlignLast
458             || rareInheritedData->m_textIndentLine != other->rareInheritedData->m_textIndentLine
459             || rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom
460             || rareInheritedData->wordBreak != other->rareInheritedData->wordBreak
461             || rareInheritedData->overflowWrap != other->rareInheritedData->overflowWrap
462             || rareInheritedData->lineBreak != other->rareInheritedData->lineBreak
463             || rareInheritedData->textSecurity != other->rareInheritedData->textSecurity
464             || rareInheritedData->hyphens != other->rareInheritedData->hyphens
465             || rareInheritedData->hyphenationLimitBefore != other->rareInheritedData->hyphenationLimitBefore
466             || rareInheritedData->hyphenationLimitAfter != other->rareInheritedData->hyphenationLimitAfter
467             || rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString
468             || rareInheritedData->locale != other->rareInheritedData->locale
469             || rareInheritedData->m_rubyPosition != other->rareInheritedData->m_rubyPosition
470             || rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark
471             || rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition
472             || rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark
473             || rareInheritedData->m_textAlignLast != other->rareInheritedData->m_textAlignLast
474             || rareInheritedData->m_textJustify != other->rareInheritedData->m_textJustify
475             || rareInheritedData->m_textOrientation != other->rareInheritedData->m_textOrientation
476             || rareInheritedData->m_tabSize != other->rareInheritedData->m_tabSize
477             || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain
478             || rareInheritedData->m_lineGrid != other->rareInheritedData->m_lineGrid
479             || rareInheritedData->m_lineSnap != other->rareInheritedData->m_lineSnap
480             || rareInheritedData->m_lineAlign != other->rareInheritedData->m_lineAlign
481             || rareInheritedData->listStyleImage != other->rareInheritedData->listStyleImage)
482             return StyleDifferenceLayout;
483 
484         if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
485             return StyleDifferenceLayout;
486 
487         if (textStrokeWidth() != other->textStrokeWidth())
488             return StyleDifferenceLayout;
489     }
490 
491     if (visual->m_textAutosizingMultiplier != other->visual->m_textAutosizingMultiplier)
492         return StyleDifferenceLayout;
493 
494     if (inherited->line_height != other->inherited->line_height
495         || inherited->font != other->inherited->font
496         || inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing
497         || inherited->vertical_border_spacing != other->inherited->vertical_border_spacing
498         || inherited_flags._box_direction != other->inherited_flags._box_direction
499         || inherited_flags.m_rtlOrdering != other->inherited_flags.m_rtlOrdering
500         || noninherited_flags._position != other->noninherited_flags._position
501         || noninherited_flags._floating != other->noninherited_flags._floating
502         || noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
503         return StyleDifferenceLayout;
504 
505 
506     if (((int)noninherited_flags._effectiveDisplay) >= TABLE) {
507         if (inherited_flags._border_collapse != other->inherited_flags._border_collapse
508             || inherited_flags._empty_cells != other->inherited_flags._empty_cells
509             || inherited_flags._caption_side != other->inherited_flags._caption_side
510             || noninherited_flags._table_layout != other->noninherited_flags._table_layout)
511             return StyleDifferenceLayout;
512 
513         // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
514         // does not, so these style differences can be width differences.
515         if (inherited_flags._border_collapse
516             && ((borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE)
517                 || (borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN)
518                 || (borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE)
519                 || (borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN)
520                 || (borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE)
521                 || (borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN)
522                 || (borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE)
523                 || (borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN)))
524             return StyleDifferenceLayout;
525     }
526 
527     if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
528         if (inherited_flags._list_style_type != other->inherited_flags._list_style_type
529             || inherited_flags._list_style_position != other->inherited_flags._list_style_position)
530             return StyleDifferenceLayout;
531     }
532 
533     if (inherited_flags._text_align != other->inherited_flags._text_align
534         || inherited_flags._text_transform != other->inherited_flags._text_transform
535         || inherited_flags._direction != other->inherited_flags._direction
536         || inherited_flags._white_space != other->inherited_flags._white_space
537         || noninherited_flags._clear != other->noninherited_flags._clear
538         || noninherited_flags._unicodeBidi != other->noninherited_flags._unicodeBidi)
539         return StyleDifferenceLayout;
540 
541     // Check block flow direction.
542     if (inherited_flags.m_writingMode != other->inherited_flags.m_writingMode)
543         return StyleDifferenceLayout;
544 
545     // Check text combine mode.
546     if (rareNonInheritedData->m_textCombine != other->rareNonInheritedData->m_textCombine)
547         return StyleDifferenceLayout;
548 
549     // Overflow returns a layout hint.
550     if (noninherited_flags._overflowX != other->noninherited_flags._overflowX
551         || noninherited_flags._overflowY != other->noninherited_flags._overflowY)
552         return StyleDifferenceLayout;
553 
554     // If our border widths change, then we need to layout.  Other changes to borders
555     // only necessitate a repaint.
556     if (borderLeftWidth() != other->borderLeftWidth()
557         || borderTopWidth() != other->borderTopWidth()
558         || borderBottomWidth() != other->borderBottomWidth()
559         || borderRightWidth() != other->borderRightWidth())
560         return StyleDifferenceLayout;
561 
562     // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
563     const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
564     const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
565     if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
566         return StyleDifferenceLayout;
567 
568     if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
569         return StyleDifferenceLayout;
570 
571     if (rareNonInheritedData->hasOpacity() != other->rareNonInheritedData->hasOpacity()) {
572         // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
573         // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
574         // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
575         // In addition we need to solve the floating object issue when layers come and go. Right now
576         // a full layout is necessary to keep floating object lists sane.
577         return StyleDifferenceLayout;
578     }
579 
580     if (rareNonInheritedData->hasFilters() != other->rareNonInheritedData->hasFilters())
581         return StyleDifferenceLayout;
582 
583     if (!QuotesData::equals(rareInheritedData->quotes.get(), other->rareInheritedData->quotes.get()))
584         return StyleDifferenceLayout;
585 
586     // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
587     // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
588     // but have to return StyleDifferenceLayout, that's why  this if branch comes after all branches
589     // that are relevant for SVG and might return StyleDifferenceLayout.
590     if (svgChange != StyleDifferenceEqual)
591         return svgChange;
592 
593     // Make sure these left/top/right/bottom checks stay below all layout checks and above
594     // all visible checks.
595     if (position() != StaticPosition && surround->offset != other->surround->offset) {
596         // Optimize for the case where a positioned layer is moving but not changing size.
597         if (position() == AbsolutePosition && positionedObjectMoved(surround->offset, other->surround->offset, m_box->width()) && repaintOnlyDiff(other, changedContextSensitiveProperties) == StyleDifferenceEqual)
598             return StyleDifferenceLayoutPositionedMovementOnly;
599 
600         // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet.
601         // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
602         // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
603         return StyleDifferenceLayout;
604     }
605     return repaintOnlyDiff(other, changedContextSensitiveProperties);
606 }
607 
repaintOnlyDiff(const RenderStyle * other,unsigned & changedContextSensitiveProperties) const608 StyleDifference RenderStyle::repaintOnlyDiff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
609 {
610     if (position() != StaticPosition && (m_box->zIndex() != other->m_box->zIndex() || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex()
611         || visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip))
612         return StyleDifferenceRepaintLayer;
613 
614     if (RuntimeEnabledFeatures::cssCompositingEnabled() && rareNonInheritedData->m_effectiveBlendMode != other->rareNonInheritedData->m_effectiveBlendMode)
615         return StyleDifferenceRepaintLayer;
616 
617     if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
618         // Don't return early here; instead take note of the type of change,
619         // and deal with it when looking at compositing.
620         changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
621     }
622 
623     if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get()
624         && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) {
625         // Don't return early here; instead take note of the type of change,
626         // and deal with it when looking at compositing.
627         changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
628     }
629 
630     if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
631         || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
632         return StyleDifferenceRepaintLayer;
633 
634     if (inherited_flags._visibility != other->inherited_flags._visibility
635         || inherited_flags.m_printColorAdjust != other->inherited_flags.m_printColorAdjust
636         || inherited_flags._insideLink != other->inherited_flags._insideLink
637         || surround->border != other->surround->border
638         || *m_background.get() != *other->m_background.get()
639         || rareInheritedData->userModify != other->rareInheritedData->userModify
640         || rareInheritedData->userSelect != other->rareInheritedData->userSelect
641         || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
642         || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
643         || rareNonInheritedData->m_objectFit != other->rareNonInheritedData->m_objectFit
644         || rareNonInheritedData->m_objectPosition != other->rareNonInheritedData->m_objectPosition
645         || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
646         return StyleDifferenceRepaint;
647 
648         // FIXME: The current spec is being reworked to remove dependencies between exclusions and affected
649         // content. There's a proposal to use floats instead. In that case, wrap-shape should actually relayout
650         // the parent container. For sure, I will have to revisit this code, but for now I've added this in order
651         // to avoid having diff() == StyleDifferenceEqual where wrap-shapes actually differ.
652         // Tracking bug: https://bugs.webkit.org/show_bug.cgi?id=62991
653         if (rareNonInheritedData->m_shapeOutside != other->rareNonInheritedData->m_shapeOutside)
654             return StyleDifferenceRepaint;
655 
656         if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath)
657             return StyleDifferenceRepaint;
658 
659     if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
660         if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
661             || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
662             || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
663             || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
664             || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
665             return StyleDifferenceRecompositeLayer;
666     }
667 
668     if (inherited->color != other->inherited->color
669         || inherited_flags._text_decorations != other->inherited_flags._text_decorations
670         || visual->textDecoration != other->visual->textDecoration
671         || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle
672         || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor
673         || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
674         || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
675         || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
676         || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill)
677         return StyleDifferenceRepaintIfTextOrColorChange;
678 
679     // Cursors are not checked, since they will be set appropriately in response to mouse events,
680     // so they don't need to cause any repaint or layout.
681 
682     // 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
683     // the resulting transition properly.
684     return StyleDifferenceEqual;
685 }
686 
setClip(Length top,Length right,Length bottom,Length left)687 void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
688 {
689     StyleVisualData* data = visual.access();
690     data->clip.m_top = top;
691     data->clip.m_right = right;
692     data->clip.m_bottom = bottom;
693     data->clip.m_left = left;
694 }
695 
addCursor(PassRefPtr<StyleImage> image,const IntPoint & hotSpot)696 void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
697 {
698     if (!rareInheritedData.access()->cursorData)
699         rareInheritedData.access()->cursorData = CursorList::create();
700     rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
701 }
702 
setCursorList(PassRefPtr<CursorList> other)703 void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
704 {
705     rareInheritedData.access()->cursorData = other;
706 }
707 
setQuotes(PassRefPtr<QuotesData> q)708 void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
709 {
710     if (QuotesData::equals(rareInheritedData->quotes.get(), q.get()))
711         return;
712     rareInheritedData.access()->quotes = q;
713 }
714 
clearCursorList()715 void RenderStyle::clearCursorList()
716 {
717     if (rareInheritedData->cursorData)
718         rareInheritedData.access()->cursorData = 0;
719 }
720 
addCallbackSelector(const String & selector)721 void RenderStyle::addCallbackSelector(const String& selector)
722 {
723     if (!rareNonInheritedData->m_callbackSelectors.contains(selector))
724         rareNonInheritedData.access()->m_callbackSelectors.append(selector);
725 }
726 
clearContent()727 void RenderStyle::clearContent()
728 {
729     if (rareNonInheritedData->m_content)
730         rareNonInheritedData.access()->m_content = nullptr;
731 }
732 
appendContent(PassOwnPtr<ContentData> contentData)733 void RenderStyle::appendContent(PassOwnPtr<ContentData> contentData)
734 {
735     OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
736     ContentData* lastContent = content.get();
737     while (lastContent && lastContent->next())
738         lastContent = lastContent->next();
739 
740     if (lastContent)
741         lastContent->setNext(contentData);
742     else
743         content = contentData;
744 }
745 
setContent(PassRefPtr<StyleImage> image,bool add)746 void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
747 {
748     if (!image)
749         return;
750 
751     if (add) {
752         appendContent(ContentData::create(image));
753         return;
754     }
755 
756     rareNonInheritedData.access()->m_content = ContentData::create(image);
757 }
758 
setContent(const String & string,bool add)759 void RenderStyle::setContent(const String& string, bool add)
760 {
761     OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
762     if (add) {
763         ContentData* lastContent = content.get();
764         while (lastContent && lastContent->next())
765             lastContent = lastContent->next();
766 
767         if (lastContent) {
768             // We attempt to merge with the last ContentData if possible.
769             if (lastContent->isText()) {
770                 TextContentData* textContent = static_cast<TextContentData*>(lastContent);
771                 textContent->setText(textContent->text() + string);
772             } else
773                 lastContent->setNext(ContentData::create(string));
774 
775             return;
776         }
777     }
778 
779     content = ContentData::create(string);
780 }
781 
setContent(PassOwnPtr<CounterContent> counter,bool add)782 void RenderStyle::setContent(PassOwnPtr<CounterContent> counter, bool add)
783 {
784     if (!counter)
785         return;
786 
787     if (add) {
788         appendContent(ContentData::create(counter));
789         return;
790     }
791 
792     rareNonInheritedData.access()->m_content = ContentData::create(counter);
793 }
794 
setContent(QuoteType quote,bool add)795 void RenderStyle::setContent(QuoteType quote, bool add)
796 {
797     if (add) {
798         appendContent(ContentData::create(quote));
799         return;
800     }
801 
802     rareNonInheritedData.access()->m_content = ContentData::create(quote);
803 }
804 
blendMode() const805 blink::WebBlendMode RenderStyle::blendMode() const
806 {
807     if (RuntimeEnabledFeatures::cssCompositingEnabled())
808         return static_cast<blink::WebBlendMode>(rareNonInheritedData->m_effectiveBlendMode);
809     return blink::WebBlendModeNormal;
810 }
811 
setBlendMode(blink::WebBlendMode v)812 void RenderStyle::setBlendMode(blink::WebBlendMode v)
813 {
814     if (RuntimeEnabledFeatures::cssCompositingEnabled())
815         rareNonInheritedData.access()->m_effectiveBlendMode = v;
816 }
817 
hasBlendMode() const818 bool RenderStyle::hasBlendMode() const
819 {
820     if (RuntimeEnabledFeatures::cssCompositingEnabled())
821         return static_cast<blink::WebBlendMode>(rareNonInheritedData->m_effectiveBlendMode) != blink::WebBlendModeNormal;
822     return false;
823 }
824 
isolation() const825 EIsolation RenderStyle::isolation() const
826 {
827     if (RuntimeEnabledFeatures::cssCompositingEnabled())
828         return static_cast<EIsolation>(rareNonInheritedData->m_isolation);
829     return IsolationAuto;
830 }
831 
setIsolation(EIsolation v)832 void RenderStyle::setIsolation(EIsolation v)
833 {
834     if (RuntimeEnabledFeatures::cssCompositingEnabled())
835         rareNonInheritedData.access()->m_isolation = v;
836 }
837 
hasIsolation() const838 bool RenderStyle::hasIsolation() const
839 {
840     if (RuntimeEnabledFeatures::cssCompositingEnabled())
841         return rareNonInheritedData->m_isolation != IsolationAuto;
842     return false;
843 }
844 
requireTransformOrigin(const Vector<RefPtr<TransformOperation>> & transformOperations,RenderStyle::ApplyTransformOrigin applyOrigin)845 inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation> >& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
846 {
847     // transform-origin brackets the transform with translate operations.
848     // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
849     // in that case.
850     if (applyOrigin != RenderStyle::IncludeTransformOrigin)
851         return false;
852 
853     unsigned size = transformOperations.size();
854     for (unsigned i = 0; i < size; ++i) {
855         TransformOperation::OperationType type = transformOperations[i]->type();
856         if (type != TransformOperation::TranslateX
857             && type != TransformOperation::TranslateY
858             && type != TransformOperation::Translate
859             && type != TransformOperation::TranslateZ
860             && type != TransformOperation::Translate3D)
861             return true;
862     }
863 
864     return false;
865 }
866 
applyTransform(TransformationMatrix & transform,const LayoutSize & borderBoxSize,ApplyTransformOrigin applyOrigin) const867 void RenderStyle::applyTransform(TransformationMatrix& transform, const LayoutSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const
868 {
869     applyTransform(transform, FloatRect(FloatPoint(), borderBoxSize), applyOrigin);
870 }
871 
applyTransform(TransformationMatrix & transform,const FloatRect & boundingBox,ApplyTransformOrigin applyOrigin) const872 void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const
873 {
874     const Vector<RefPtr<TransformOperation> >& transformOperations = rareNonInheritedData->m_transform->m_operations.operations();
875     bool applyTransformOrigin = requireTransformOrigin(transformOperations, applyOrigin);
876 
877     float offsetX = transformOriginX().type() == Percent ? boundingBox.x() : 0;
878     float offsetY = transformOriginY().type() == Percent ? boundingBox.y() : 0;
879 
880     if (applyTransformOrigin) {
881         transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width(), 0) + offsetX,
882             floatValueForLength(transformOriginY(), boundingBox.height(), 0) + offsetY,
883             transformOriginZ());
884     }
885 
886     unsigned size = transformOperations.size();
887     for (unsigned i = 0; i < size; ++i)
888         transformOperations[i]->apply(transform, boundingBox.size());
889 
890     if (applyTransformOrigin) {
891         transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width(), 0) - offsetX,
892             -floatValueForLength(transformOriginY(), boundingBox.height(), 0) - offsetY,
893             -transformOriginZ());
894     }
895 }
896 
setTextShadow(PassRefPtr<ShadowList> s)897 void RenderStyle::setTextShadow(PassRefPtr<ShadowList> s)
898 {
899     rareInheritedData.access()->textShadow = s;
900 }
901 
setBoxShadow(PassRefPtr<ShadowList> s)902 void RenderStyle::setBoxShadow(PassRefPtr<ShadowList> s)
903 {
904     rareNonInheritedData.access()->m_boxShadow = s;
905 }
906 
calcRadiiFor(const BorderData & border,IntSize size,RenderView * renderView)907 static RoundedRect::Radii calcRadiiFor(const BorderData& border, IntSize size, RenderView* renderView)
908 {
909     return RoundedRect::Radii(
910         IntSize(valueForLength(border.topLeft().width(), size.width(), renderView),
911                 valueForLength(border.topLeft().height(), size.height(), renderView)),
912         IntSize(valueForLength(border.topRight().width(), size.width(), renderView),
913                 valueForLength(border.topRight().height(), size.height(), renderView)),
914         IntSize(valueForLength(border.bottomLeft().width(), size.width(), renderView),
915                 valueForLength(border.bottomLeft().height(), size.height(), renderView)),
916         IntSize(valueForLength(border.bottomRight().width(), size.width(), renderView),
917                 valueForLength(border.bottomRight().height(), size.height(), renderView)));
918 }
919 
calcConstraintScaleFor(const IntRect & rect,const RoundedRect::Radii & radii)920 static float calcConstraintScaleFor(const IntRect& rect, const RoundedRect::Radii& radii)
921 {
922     // Constrain corner radii using CSS3 rules:
923     // http://www.w3.org/TR/css3-background/#the-border-radius
924 
925     float factor = 1;
926     unsigned radiiSum;
927 
928     // top
929     radiiSum = static_cast<unsigned>(radii.topLeft().width()) + static_cast<unsigned>(radii.topRight().width()); // Casts to avoid integer overflow.
930     if (radiiSum > static_cast<unsigned>(rect.width()))
931         factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
932 
933     // bottom
934     radiiSum = static_cast<unsigned>(radii.bottomLeft().width()) + static_cast<unsigned>(radii.bottomRight().width());
935     if (radiiSum > static_cast<unsigned>(rect.width()))
936         factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
937 
938     // left
939     radiiSum = static_cast<unsigned>(radii.topLeft().height()) + static_cast<unsigned>(radii.bottomLeft().height());
940     if (radiiSum > static_cast<unsigned>(rect.height()))
941         factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
942 
943     // right
944     radiiSum = static_cast<unsigned>(radii.topRight().height()) + static_cast<unsigned>(radii.bottomRight().height());
945     if (radiiSum > static_cast<unsigned>(rect.height()))
946         factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
947 
948     ASSERT(factor <= 1);
949     return factor;
950 }
951 
listStyleImage() const952 StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); }
setListStyleImage(PassRefPtr<StyleImage> v)953 void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v)
954 {
955     if (rareInheritedData->listStyleImage != v)
956         rareInheritedData.access()->listStyleImage = v;
957 }
958 
color() const959 Color RenderStyle::color() const { return inherited->color; }
visitedLinkColor() const960 Color RenderStyle::visitedLinkColor() const { return inherited->visitedLinkColor; }
setColor(const Color & v)961 void RenderStyle::setColor(const Color& v) { SET_VAR(inherited, color, v); }
setVisitedLinkColor(const Color & v)962 void RenderStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visitedLinkColor, v); }
963 
horizontalBorderSpacing() const964 short RenderStyle::horizontalBorderSpacing() const { return inherited->horizontal_border_spacing; }
verticalBorderSpacing() const965 short RenderStyle::verticalBorderSpacing() const { return inherited->vertical_border_spacing; }
setHorizontalBorderSpacing(short v)966 void RenderStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v); }
setVerticalBorderSpacing(short v)967 void RenderStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertical_border_spacing, v); }
968 
getRoundedBorderFor(const LayoutRect & borderRect,RenderView * renderView,bool includeLogicalLeftEdge,bool includeLogicalRightEdge) const969 RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, RenderView* renderView, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
970 {
971     IntRect snappedBorderRect(pixelSnappedIntRect(borderRect));
972     RoundedRect roundedRect(snappedBorderRect);
973     if (hasBorderRadius()) {
974         RoundedRect::Radii radii = calcRadiiFor(surround->border, snappedBorderRect.size(), renderView);
975         radii.scale(calcConstraintScaleFor(snappedBorderRect, radii));
976         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
977     }
978     return roundedRect;
979 }
980 
getRoundedInnerBorderFor(const LayoutRect & borderRect,bool includeLogicalLeftEdge,bool includeLogicalRightEdge) const981 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
982 {
983     bool horizontal = isHorizontalWritingMode();
984 
985     int leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
986     int rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
987     int topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
988     int bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;
989 
990     return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
991 }
992 
getRoundedInnerBorderFor(const LayoutRect & borderRect,int topWidth,int bottomWidth,int leftWidth,int rightWidth,bool includeLogicalLeftEdge,bool includeLogicalRightEdge) const993 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect,
994     int topWidth, int bottomWidth, int leftWidth, int rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
995 {
996     LayoutRect innerRect(borderRect.x() + leftWidth,
997                borderRect.y() + topWidth,
998                borderRect.width() - leftWidth - rightWidth,
999                borderRect.height() - topWidth - bottomWidth);
1000 
1001     RoundedRect roundedRect(pixelSnappedIntRect(innerRect));
1002 
1003     if (hasBorderRadius()) {
1004         RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii();
1005         radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
1006         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1007     }
1008     return roundedRect;
1009 }
1010 
allLayersAreFixed(const FillLayer * layer)1011 static bool allLayersAreFixed(const FillLayer* layer)
1012 {
1013     bool allFixed = true;
1014 
1015     for (const FillLayer* currLayer = layer; currLayer; currLayer = currLayer->next())
1016         allFixed &= (currLayer->image() && currLayer->attachment() == FixedBackgroundAttachment);
1017 
1018     return layer && allFixed;
1019 }
1020 
hasEntirelyFixedBackground() const1021 bool RenderStyle::hasEntirelyFixedBackground() const
1022 {
1023     return allLayersAreFixed(backgroundLayers());
1024 }
1025 
counterDirectives() const1026 const CounterDirectiveMap* RenderStyle::counterDirectives() const
1027 {
1028     return rareNonInheritedData->m_counterDirectives.get();
1029 }
1030 
accessCounterDirectives()1031 CounterDirectiveMap& RenderStyle::accessCounterDirectives()
1032 {
1033     OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterDirectives;
1034     if (!map)
1035         map = adoptPtr(new CounterDirectiveMap);
1036     return *map;
1037 }
1038 
getCounterDirectives(const AtomicString & identifier) const1039 const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const
1040 {
1041     if (const CounterDirectiveMap* directives = counterDirectives())
1042         return directives->get(identifier);
1043     return CounterDirectives();
1044 }
1045 
hyphenString() const1046 const AtomicString& RenderStyle::hyphenString() const
1047 {
1048     const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString;
1049     if (!hyphenationString.isNull())
1050         return hyphenationString;
1051 
1052     // FIXME: This should depend on locale.
1053     DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinus, 1));
1054     DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphen, 1));
1055     return font().primaryFontHasGlyphForCharacter(hyphen) ? hyphenString : hyphenMinusString;
1056 }
1057 
textEmphasisMarkString() const1058 const AtomicString& RenderStyle::textEmphasisMarkString() const
1059 {
1060     switch (textEmphasisMark()) {
1061     case TextEmphasisMarkNone:
1062         return nullAtom;
1063     case TextEmphasisMarkCustom:
1064         return textEmphasisCustomMark();
1065     case TextEmphasisMarkDot: {
1066         DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1));
1067         DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1));
1068         return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
1069     }
1070     case TextEmphasisMarkCircle: {
1071         DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1));
1072         DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1));
1073         return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString;
1074     }
1075     case TextEmphasisMarkDoubleCircle: {
1076         DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1));
1077         DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1));
1078         return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString;
1079     }
1080     case TextEmphasisMarkTriangle: {
1081         DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointingTriangle, 1));
1082         DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingTriangle, 1));
1083         return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString;
1084     }
1085     case TextEmphasisMarkSesame: {
1086         DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1));
1087         DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1));
1088         return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString;
1089     }
1090     case TextEmphasisMarkAuto:
1091         ASSERT_NOT_REACHED();
1092         return nullAtom;
1093     }
1094 
1095     ASSERT_NOT_REACHED();
1096     return nullAtom;
1097 }
1098 
adjustAnimations()1099 void RenderStyle::adjustAnimations()
1100 {
1101     CSSAnimationDataList* animationList = rareNonInheritedData->m_animations.get();
1102     if (!animationList)
1103         return;
1104 
1105     // Get rid of empty animations and anything beyond them
1106     for (size_t i = 0; i < animationList->size(); ++i) {
1107         if (animationList->animation(i)->isEmpty()) {
1108             animationList->resize(i);
1109             break;
1110         }
1111     }
1112 
1113     if (animationList->isEmpty()) {
1114         clearAnimations();
1115         return;
1116     }
1117 
1118     // Repeat patterns into layers that don't have some properties set.
1119     animationList->fillUnsetProperties();
1120 }
1121 
adjustTransitions()1122 void RenderStyle::adjustTransitions()
1123 {
1124     CSSAnimationDataList* transitionList = rareNonInheritedData->m_transitions.get();
1125     if (!transitionList)
1126         return;
1127 
1128     // Get rid of empty transitions and anything beyond them
1129     for (size_t i = 0; i < transitionList->size(); ++i) {
1130         if (transitionList->animation(i)->isEmpty()) {
1131             transitionList->resize(i);
1132             break;
1133         }
1134     }
1135 
1136     if (transitionList->isEmpty()) {
1137         clearTransitions();
1138         return;
1139     }
1140 
1141     // Repeat patterns into layers that don't have some properties set.
1142     transitionList->fillUnsetProperties();
1143 
1144     // Make sure there are no duplicate properties. This is an O(n^2) algorithm
1145     // but the lists tend to be very short, so it is probably ok
1146     for (size_t i = 0; i < transitionList->size(); ++i) {
1147         for (size_t j = i+1; j < transitionList->size(); ++j) {
1148             if (transitionList->animation(i)->property() == transitionList->animation(j)->property()) {
1149                 // toss i
1150                 transitionList->remove(i);
1151                 j = i;
1152             }
1153         }
1154     }
1155 }
1156 
accessAnimations()1157 CSSAnimationDataList* RenderStyle::accessAnimations()
1158 {
1159     if (!rareNonInheritedData.access()->m_animations)
1160         rareNonInheritedData.access()->m_animations = adoptPtr(new CSSAnimationDataList());
1161     return rareNonInheritedData->m_animations.get();
1162 }
1163 
accessTransitions()1164 CSSAnimationDataList* RenderStyle::accessTransitions()
1165 {
1166     if (!rareNonInheritedData.access()->m_transitions)
1167         rareNonInheritedData.access()->m_transitions = adoptPtr(new CSSAnimationDataList());
1168     return rareNonInheritedData->m_transitions.get();
1169 }
1170 
transitionForProperty(CSSPropertyID property) const1171 const CSSAnimationData* RenderStyle::transitionForProperty(CSSPropertyID property) const
1172 {
1173     if (transitions()) {
1174         for (size_t i = 0; i < transitions()->size(); ++i) {
1175             const CSSAnimationData* p = transitions()->animation(i);
1176             if (p->animationMode() == CSSAnimationData::AnimateAll || p->property() == property) {
1177                 return p;
1178             }
1179         }
1180     }
1181     return 0;
1182 }
1183 
font() const1184 const Font& RenderStyle::font() const { return inherited->font; }
fontMetrics() const1185 const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); }
fontDescription() const1186 const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); }
specifiedFontSize() const1187 float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); }
computedFontSize() const1188 float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
fontSize() const1189 int RenderStyle::fontSize() const { return inherited->font.pixelSize(); }
1190 
wordSpacing() const1191 float RenderStyle::wordSpacing() const { return inherited->font.wordSpacing(); }
letterSpacing() const1192 float RenderStyle::letterSpacing() const { return inherited->font.letterSpacing(); }
1193 
setFontDescription(const FontDescription & v)1194 bool RenderStyle::setFontDescription(const FontDescription& v)
1195 {
1196     if (inherited->font.fontDescription() != v) {
1197         inherited.access()->font = Font(v, inherited->font.letterSpacing(), inherited->font.wordSpacing());
1198         return true;
1199     }
1200     return false;
1201 }
1202 
specifiedLineHeight() const1203 Length RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
lineHeight() const1204 Length RenderStyle::lineHeight() const
1205 {
1206     const Length& lh = inherited->line_height;
1207     // Unlike fontDescription().computedSize() and hence fontSize(), this is
1208     // recalculated on demand as we only store the specified line height.
1209     // FIXME: Should consider scaling the fixed part of any calc expressions
1210     // too, though this involves messily poking into CalcExpressionLength.
1211     float multiplier = textAutosizingMultiplier();
1212     if (multiplier > 1 && lh.isFixed())
1213         return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multiplier), Fixed);
1214 
1215     return lh;
1216 }
setLineHeight(Length specifiedLineHeight)1217 void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
1218 
computedLineHeight(RenderView * renderView) const1219 int RenderStyle::computedLineHeight(RenderView* renderView) const
1220 {
1221     const Length& lh = lineHeight();
1222 
1223     // Negative value means the line height is not set. Use the font's built-in spacing.
1224     if (lh.isNegative())
1225         return fontMetrics().lineSpacing();
1226 
1227     if (lh.isPercent())
1228         return minimumValueForLength(lh, fontSize());
1229 
1230     if (lh.isViewportPercentage())
1231         return valueForLength(lh, 0, renderView);
1232 
1233     return lh.value();
1234 }
1235 
setWordSpacing(float v)1236 void RenderStyle::setWordSpacing(float v) { inherited.access()->font.setWordSpacing(v); }
setLetterSpacing(float v)1237 void RenderStyle::setLetterSpacing(float v) { inherited.access()->font.setLetterSpacing(v); }
1238 
setFontSize(float size)1239 void RenderStyle::setFontSize(float size)
1240 {
1241     // size must be specifiedSize if Text Autosizing is enabled, but computedSize if text
1242     // zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
1243 
1244     ASSERT(std::isfinite(size));
1245     if (!std::isfinite(size) || size < 0)
1246         size = 0;
1247     else
1248         size = min(maximumAllowedFontSize, size);
1249 
1250     FontSelector* currentFontSelector = font().fontSelector();
1251     FontDescription desc(fontDescription());
1252     desc.setSpecifiedSize(size);
1253     desc.setComputedSize(size);
1254 
1255     float multiplier = textAutosizingMultiplier();
1256     if (multiplier > 1) {
1257         float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size, multiplier);
1258         desc.setComputedSize(min(maximumAllowedFontSize, autosizedFontSize));
1259     }
1260 
1261     setFontDescription(desc);
1262     font().update(currentFontSelector);
1263 }
1264 
getShadowExtent(const ShadowList * shadowList,LayoutUnit & top,LayoutUnit & right,LayoutUnit & bottom,LayoutUnit & left) const1265 void RenderStyle::getShadowExtent(const ShadowList* shadowList, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
1266 {
1267     top = 0;
1268     right = 0;
1269     bottom = 0;
1270     left = 0;
1271 
1272     size_t shadowCount = shadowList ? shadowList->shadows().size() : 0;
1273     for (size_t i = 0; i < shadowCount; ++i) {
1274         const ShadowData& shadow = shadowList->shadows()[i];
1275         if (shadow.style() == Inset)
1276             continue;
1277         int blurAndSpread = shadow.blur() + shadow.spread();
1278 
1279         top = min<LayoutUnit>(top, shadow.y() - blurAndSpread);
1280         right = max<LayoutUnit>(right, shadow.x() + blurAndSpread);
1281         bottom = max<LayoutUnit>(bottom, shadow.y() + blurAndSpread);
1282         left = min<LayoutUnit>(left, shadow.x() - blurAndSpread);
1283     }
1284 }
1285 
getShadowInsetExtent(const ShadowList * shadowList) const1286 LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowList* shadowList) const
1287 {
1288     LayoutUnit top = 0;
1289     LayoutUnit right = 0;
1290     LayoutUnit bottom = 0;
1291     LayoutUnit left = 0;
1292 
1293     size_t shadowCount = shadowList ? shadowList->shadows().size() : 0;
1294     for (size_t i = 0; i < shadowCount; ++i) {
1295         const ShadowData& shadow = shadowList->shadows()[i];
1296         if (shadow.style() == Normal)
1297             continue;
1298         int blurAndSpread = shadow.blur() + shadow.spread();
1299         top = max<LayoutUnit>(top, shadow.y() + blurAndSpread);
1300         right = min<LayoutUnit>(right, shadow.x() - blurAndSpread);
1301         bottom = min<LayoutUnit>(bottom, shadow.y() - blurAndSpread);
1302         left = max<LayoutUnit>(left, shadow.x() + blurAndSpread);
1303     }
1304 
1305     return LayoutBoxExtent(top, right, bottom, left);
1306 }
1307 
getShadowHorizontalExtent(const ShadowList * shadowList,LayoutUnit & left,LayoutUnit & right) const1308 void RenderStyle::getShadowHorizontalExtent(const ShadowList* shadowList, LayoutUnit &left, LayoutUnit &right) const
1309 {
1310     left = 0;
1311     right = 0;
1312 
1313     size_t shadowCount = shadowList ? shadowList->shadows().size() : 0;
1314     for (size_t i = 0; i < shadowCount; ++i) {
1315         const ShadowData& shadow = shadowList->shadows()[i];
1316         if (shadow.style() == Inset)
1317             continue;
1318         int blurAndSpread = shadow.blur() + shadow.spread();
1319 
1320         left = min<LayoutUnit>(left, shadow.x() - blurAndSpread);
1321         right = max<LayoutUnit>(right, shadow.x() + blurAndSpread);
1322     }
1323 }
1324 
getShadowVerticalExtent(const ShadowList * shadowList,LayoutUnit & top,LayoutUnit & bottom) const1325 void RenderStyle::getShadowVerticalExtent(const ShadowList* shadowList, LayoutUnit &top, LayoutUnit &bottom) const
1326 {
1327     top = 0;
1328     bottom = 0;
1329 
1330     size_t shadowCount = shadowList ? shadowList->shadows().size() : 0;
1331     for (size_t i = 0; i < shadowCount; ++i) {
1332         const ShadowData& shadow = shadowList->shadows()[i];
1333         if (shadow.style() == Inset)
1334             continue;
1335         int blurAndSpread = shadow.blur() + shadow.spread();
1336 
1337         top = min<LayoutUnit>(top, shadow.y() - blurAndSpread);
1338         bottom = max<LayoutUnit>(bottom, shadow.y() + blurAndSpread);
1339     }
1340 }
1341 
colorIncludingFallback(int colorProperty,bool visitedLink) const1342 Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
1343 {
1344     Color result;
1345     EBorderStyle borderStyle = BNONE;
1346     switch (colorProperty) {
1347     case CSSPropertyBackgroundColor:
1348         return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back.
1349     case CSSPropertyBorderLeftColor:
1350         result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
1351         borderStyle = borderLeftStyle();
1352         break;
1353     case CSSPropertyBorderRightColor:
1354         result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
1355         borderStyle = borderRightStyle();
1356         break;
1357     case CSSPropertyBorderTopColor:
1358         result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
1359         borderStyle = borderTopStyle();
1360         break;
1361     case CSSPropertyBorderBottomColor:
1362         result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
1363         borderStyle = borderBottomStyle();
1364         break;
1365     case CSSPropertyColor:
1366         result = visitedLink ? visitedLinkColor() : color();
1367         break;
1368     case CSSPropertyOutlineColor:
1369         result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
1370         break;
1371     case CSSPropertyWebkitColumnRuleColor:
1372         result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
1373         break;
1374     case CSSPropertyTextDecorationColor:
1375         // Text decoration color fallback is handled in RenderObject::decorationColor.
1376         return visitedLink ? visitedLinkTextDecorationColor() : textDecorationColor();
1377     case CSSPropertyWebkitTextEmphasisColor:
1378         result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
1379         break;
1380     case CSSPropertyWebkitTextFillColor:
1381         result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
1382         break;
1383     case CSSPropertyWebkitTextStrokeColor:
1384         result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
1385         break;
1386     case CSSPropertyFloodColor:
1387         result = floodColor();
1388         break;
1389     case CSSPropertyLightingColor:
1390         result = lightingColor();
1391         break;
1392     case CSSPropertyStopColor:
1393         result = stopColor();
1394         break;
1395     case CSSPropertyWebkitTapHighlightColor:
1396         result = tapHighlightColor();
1397         break;
1398     default:
1399         ASSERT_NOT_REACHED();
1400         break;
1401     }
1402 
1403     if (!result.isValid()) {
1404         if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
1405             result.setRGB(238, 238, 238);
1406         else
1407             result = visitedLink ? visitedLinkColor() : color();
1408     }
1409     return result;
1410 }
1411 
visitedDependentColor(int colorProperty) const1412 Color RenderStyle::visitedDependentColor(int colorProperty) const
1413 {
1414     Color unvisitedColor = colorIncludingFallback(colorProperty, false);
1415     if (insideLink() != InsideVisitedLink)
1416         return unvisitedColor;
1417 
1418     Color visitedColor = colorIncludingFallback(colorProperty, true);
1419 
1420     // Text decoration color validity is preserved (checked in RenderObject::decorationColor).
1421     if (colorProperty == CSSPropertyTextDecorationColor)
1422         return visitedColor;
1423 
1424     // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
1425     // assume that if the background color is transparent that it wasn't set. Note that it's weird that
1426     // we're returning unvisited info for a visited link, but given our restriction that the alpha values
1427     // have to match, it makes more sense to return the unvisited background color if specified than it
1428     // does to return black. This behavior matches what Firefox 4 does as well.
1429     if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent)
1430         return unvisitedColor;
1431 
1432     // Take the alpha from the unvisited color, but get the RGB values from the visited color.
1433     return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
1434 }
1435 
borderBefore() const1436 const BorderValue& RenderStyle::borderBefore() const
1437 {
1438     switch (writingMode()) {
1439     case TopToBottomWritingMode:
1440         return borderTop();
1441     case BottomToTopWritingMode:
1442         return borderBottom();
1443     case LeftToRightWritingMode:
1444         return borderLeft();
1445     case RightToLeftWritingMode:
1446         return borderRight();
1447     }
1448     ASSERT_NOT_REACHED();
1449     return borderTop();
1450 }
1451 
borderAfter() const1452 const BorderValue& RenderStyle::borderAfter() const
1453 {
1454     switch (writingMode()) {
1455     case TopToBottomWritingMode:
1456         return borderBottom();
1457     case BottomToTopWritingMode:
1458         return borderTop();
1459     case LeftToRightWritingMode:
1460         return borderRight();
1461     case RightToLeftWritingMode:
1462         return borderLeft();
1463     }
1464     ASSERT_NOT_REACHED();
1465     return borderBottom();
1466 }
1467 
borderStart() const1468 const BorderValue& RenderStyle::borderStart() const
1469 {
1470     if (isHorizontalWritingMode())
1471         return isLeftToRightDirection() ? borderLeft() : borderRight();
1472     return isLeftToRightDirection() ? borderTop() : borderBottom();
1473 }
1474 
borderEnd() const1475 const BorderValue& RenderStyle::borderEnd() const
1476 {
1477     if (isHorizontalWritingMode())
1478         return isLeftToRightDirection() ? borderRight() : borderLeft();
1479     return isLeftToRightDirection() ? borderBottom() : borderTop();
1480 }
1481 
borderBeforeWidth() const1482 unsigned short RenderStyle::borderBeforeWidth() const
1483 {
1484     switch (writingMode()) {
1485     case TopToBottomWritingMode:
1486         return borderTopWidth();
1487     case BottomToTopWritingMode:
1488         return borderBottomWidth();
1489     case LeftToRightWritingMode:
1490         return borderLeftWidth();
1491     case RightToLeftWritingMode:
1492         return borderRightWidth();
1493     }
1494     ASSERT_NOT_REACHED();
1495     return borderTopWidth();
1496 }
1497 
borderAfterWidth() const1498 unsigned short RenderStyle::borderAfterWidth() const
1499 {
1500     switch (writingMode()) {
1501     case TopToBottomWritingMode:
1502         return borderBottomWidth();
1503     case BottomToTopWritingMode:
1504         return borderTopWidth();
1505     case LeftToRightWritingMode:
1506         return borderRightWidth();
1507     case RightToLeftWritingMode:
1508         return borderLeftWidth();
1509     }
1510     ASSERT_NOT_REACHED();
1511     return borderBottomWidth();
1512 }
1513 
borderStartWidth() const1514 unsigned short RenderStyle::borderStartWidth() const
1515 {
1516     if (isHorizontalWritingMode())
1517         return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
1518     return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
1519 }
1520 
borderEndWidth() const1521 unsigned short RenderStyle::borderEndWidth() const
1522 {
1523     if (isHorizontalWritingMode())
1524         return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
1525     return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
1526 }
1527 
setMarginStart(Length margin)1528 void RenderStyle::setMarginStart(Length margin)
1529 {
1530     if (isHorizontalWritingMode()) {
1531         if (isLeftToRightDirection())
1532             setMarginLeft(margin);
1533         else
1534             setMarginRight(margin);
1535     } else {
1536         if (isLeftToRightDirection())
1537             setMarginTop(margin);
1538         else
1539             setMarginBottom(margin);
1540     }
1541 }
1542 
setMarginEnd(Length margin)1543 void RenderStyle::setMarginEnd(Length margin)
1544 {
1545     if (isHorizontalWritingMode()) {
1546         if (isLeftToRightDirection())
1547             setMarginRight(margin);
1548         else
1549             setMarginLeft(margin);
1550     } else {
1551         if (isLeftToRightDirection())
1552             setMarginBottom(margin);
1553         else
1554             setMarginTop(margin);
1555     }
1556 }
1557 
textEmphasisMark() const1558 TextEmphasisMark RenderStyle::textEmphasisMark() const
1559 {
1560     TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark);
1561     if (mark != TextEmphasisMarkAuto)
1562         return mark;
1563 
1564     if (isHorizontalWritingMode())
1565         return TextEmphasisMarkDot;
1566 
1567     return TextEmphasisMarkSesame;
1568 }
1569 
initialTapHighlightColor()1570 Color RenderStyle::initialTapHighlightColor()
1571 {
1572     return RenderTheme::tapHighlightColor();
1573 }
1574 
imageOutsets(const NinePieceImage & image) const1575 LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
1576 {
1577     return LayoutBoxExtent(NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()),
1578                            NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()),
1579                            NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth()),
1580                            NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()));
1581 }
1582 
setBorderImageSource(PassRefPtr<StyleImage> image)1583 void RenderStyle::setBorderImageSource(PassRefPtr<StyleImage> image)
1584 {
1585     if (surround->border.m_image.image() == image.get())
1586         return;
1587     surround.access()->border.m_image.setImage(image);
1588 }
1589 
setBorderImageSlices(LengthBox slices)1590 void RenderStyle::setBorderImageSlices(LengthBox slices)
1591 {
1592     if (surround->border.m_image.imageSlices() == slices)
1593         return;
1594     surround.access()->border.m_image.setImageSlices(slices);
1595 }
1596 
setBorderImageWidth(const BorderImageLengthBox & slices)1597 void RenderStyle::setBorderImageWidth(const BorderImageLengthBox& slices)
1598 {
1599     if (surround->border.m_image.borderSlices() == slices)
1600         return;
1601     surround.access()->border.m_image.setBorderSlices(slices);
1602 }
1603 
setBorderImageOutset(const BorderImageLengthBox & outset)1604 void RenderStyle::setBorderImageOutset(const BorderImageLengthBox& outset)
1605 {
1606     if (surround->border.m_image.outset() == outset)
1607         return;
1608     surround.access()->border.m_image.setOutset(outset);
1609 }
1610 
1611 } // namespace WebCore
1612