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