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 "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 
     68 inline RenderStyle* defaultStyle()
     69 {
     70     DEFINE_STATIC_REF(RenderStyle, s_defaultStyle, (RenderStyle::createDefaultStyle()));
     71     return s_defaultStyle;
     72 }
     73 
     74 PassRefPtr<RenderStyle> RenderStyle::create()
     75 {
     76     return adoptRef(new RenderStyle());
     77 }
     78 
     79 PassRefPtr<RenderStyle> RenderStyle::createDefaultStyle()
     80 {
     81     return adoptRef(new RenderStyle(DefaultStyle));
     82 }
     83 
     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 
     93 PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other)
     94 {
     95     return adoptRef(new RenderStyle(*other));
     96 }
     97 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    241 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 
    256 bool RenderStyle::isStyleAvailable() const
    257 {
    258     return this != StyleResolver::styleNotYetAvailable();
    259 }
    260 
    261 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 
    275 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 
    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 
    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 
    322 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 
    330 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 
    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 
    366 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 
    608 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 
    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 
    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 
    703 void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
    704 {
    705     rareInheritedData.access()->cursorData = other;
    706 }
    707 
    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 
    715 void RenderStyle::clearCursorList()
    716 {
    717     if (rareInheritedData->cursorData)
    718         rareInheritedData.access()->cursorData = 0;
    719 }
    720 
    721 void RenderStyle::addCallbackSelector(const String& selector)
    722 {
    723     if (!rareNonInheritedData->m_callbackSelectors.contains(selector))
    724         rareNonInheritedData.access()->m_callbackSelectors.append(selector);
    725 }
    726 
    727 void RenderStyle::clearContent()
    728 {
    729     if (rareNonInheritedData->m_content)
    730         rareNonInheritedData.access()->m_content = nullptr;
    731 }
    732 
    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 
    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 
    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 
    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 
    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 
    805 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 
    812 void RenderStyle::setBlendMode(blink::WebBlendMode v)
    813 {
    814     if (RuntimeEnabledFeatures::cssCompositingEnabled())
    815         rareNonInheritedData.access()->m_effectiveBlendMode = v;
    816 }
    817 
    818 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 
    825 EIsolation RenderStyle::isolation() const
    826 {
    827     if (RuntimeEnabledFeatures::cssCompositingEnabled())
    828         return static_cast<EIsolation>(rareNonInheritedData->m_isolation);
    829     return IsolationAuto;
    830 }
    831 
    832 void RenderStyle::setIsolation(EIsolation v)
    833 {
    834     if (RuntimeEnabledFeatures::cssCompositingEnabled())
    835         rareNonInheritedData.access()->m_isolation = v;
    836 }
    837 
    838 bool RenderStyle::hasIsolation() const
    839 {
    840     if (RuntimeEnabledFeatures::cssCompositingEnabled())
    841         return rareNonInheritedData->m_isolation != IsolationAuto;
    842     return false;
    843 }
    844 
    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 
    867 void RenderStyle::applyTransform(TransformationMatrix& transform, const LayoutSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const
    868 {
    869     applyTransform(transform, FloatRect(FloatPoint(), borderBoxSize), applyOrigin);
    870 }
    871 
    872 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 
    897 void RenderStyle::setTextShadow(PassRefPtr<ShadowList> s)
    898 {
    899     rareInheritedData.access()->textShadow = s;
    900 }
    901 
    902 void RenderStyle::setBoxShadow(PassRefPtr<ShadowList> s)
    903 {
    904     rareNonInheritedData.access()->m_boxShadow = s;
    905 }
    906 
    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 
    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 
    952 StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); }
    953 void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v)
    954 {
    955     if (rareInheritedData->listStyleImage != v)
    956         rareInheritedData.access()->listStyleImage = v;
    957 }
    958 
    959 Color RenderStyle::color() const { return inherited->color; }
    960 Color RenderStyle::visitedLinkColor() const { return inherited->visitedLinkColor; }
    961 void RenderStyle::setColor(const Color& v) { SET_VAR(inherited, color, v); }
    962 void RenderStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visitedLinkColor, v); }
    963 
    964 short RenderStyle::horizontalBorderSpacing() const { return inherited->horizontal_border_spacing; }
    965 short RenderStyle::verticalBorderSpacing() const { return inherited->vertical_border_spacing; }
    966 void RenderStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v); }
    967 void RenderStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertical_border_spacing, v); }
    968 
    969 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 
    981 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 
    993 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 
   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 
   1021 bool RenderStyle::hasEntirelyFixedBackground() const
   1022 {
   1023     return allLayersAreFixed(backgroundLayers());
   1024 }
   1025 
   1026 const CounterDirectiveMap* RenderStyle::counterDirectives() const
   1027 {
   1028     return rareNonInheritedData->m_counterDirectives.get();
   1029 }
   1030 
   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 
   1039 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 
   1046 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 
   1058 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 
   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 
   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 
   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 
   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 
   1171 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 
   1184 const Font& RenderStyle::font() const { return inherited->font; }
   1185 const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); }
   1186 const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); }
   1187 float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); }
   1188 float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
   1189 int RenderStyle::fontSize() const { return inherited->font.pixelSize(); }
   1190 
   1191 float RenderStyle::wordSpacing() const { return inherited->font.wordSpacing(); }
   1192 float RenderStyle::letterSpacing() const { return inherited->font.letterSpacing(); }
   1193 
   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 
   1203 Length RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
   1204 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 }
   1217 void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
   1218 
   1219 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 
   1236 void RenderStyle::setWordSpacing(float v) { inherited.access()->font.setWordSpacing(v); }
   1237 void RenderStyle::setLetterSpacing(float v) { inherited.access()->font.setLetterSpacing(v); }
   1238 
   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 
   1265 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 
   1286 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 
   1308 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 
   1325 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 
   1342 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 
   1412 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 
   1436 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 
   1452 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 
   1468 const BorderValue& RenderStyle::borderStart() const
   1469 {
   1470     if (isHorizontalWritingMode())
   1471         return isLeftToRightDirection() ? borderLeft() : borderRight();
   1472     return isLeftToRightDirection() ? borderTop() : borderBottom();
   1473 }
   1474 
   1475 const BorderValue& RenderStyle::borderEnd() const
   1476 {
   1477     if (isHorizontalWritingMode())
   1478         return isLeftToRightDirection() ? borderRight() : borderLeft();
   1479     return isLeftToRightDirection() ? borderBottom() : borderTop();
   1480 }
   1481 
   1482 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 
   1498 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 
   1514 unsigned short RenderStyle::borderStartWidth() const
   1515 {
   1516     if (isHorizontalWritingMode())
   1517         return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
   1518     return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
   1519 }
   1520 
   1521 unsigned short RenderStyle::borderEndWidth() const
   1522 {
   1523     if (isHorizontalWritingMode())
   1524         return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
   1525     return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
   1526 }
   1527 
   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 
   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 
   1558 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 
   1570 Color RenderStyle::initialTapHighlightColor()
   1571 {
   1572     return RenderTheme::tapHighlightColor();
   1573 }
   1574 
   1575 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 
   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 
   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 
   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 
   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