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 "core/css/resolver/StyleResolver.h"
     28 #include "core/rendering/RenderTheme.h"
     29 #include "core/rendering/TextAutosizer.h"
     30 #include "core/rendering/style/AppliedTextDecoration.h"
     31 #include "core/rendering/style/ContentData.h"
     32 #include "core/rendering/style/QuotesData.h"
     33 #include "core/rendering/style/ShadowList.h"
     34 #include "core/rendering/style/StyleImage.h"
     35 #include "core/rendering/style/StyleInheritedData.h"
     36 #include "platform/LengthFunctions.h"
     37 #include "platform/RuntimeEnabledFeatures.h"
     38 #include "platform/fonts/Font.h"
     39 #include "platform/fonts/FontSelector.h"
     40 #include "platform/geometry/FloatRoundedRect.h"
     41 #include "wtf/MathExtras.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     DEFINE_STATIC_REF(RenderStyle, s_defaultStyle, (RenderStyle::createDefaultStyle()));
     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(DefaultStyle));
     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(DefaultStyleTag)
    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_willChange.init();
    130     rareNonInheritedData.access()->m_filter.init();
    131     rareNonInheritedData.access()->m_grid.init();
    132     rareNonInheritedData.access()->m_gridItem.init();
    133     rareInheritedData.init();
    134     inherited.init();
    135     m_svgStyle.init();
    136 }
    137 
    138 ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o)
    139     : RefCounted<RenderStyle>()
    140     , m_box(o.m_box)
    141     , visual(o.visual)
    142     , m_background(o.m_background)
    143     , surround(o.surround)
    144     , rareNonInheritedData(o.rareNonInheritedData)
    145     , rareInheritedData(o.rareInheritedData)
    146     , inherited(o.inherited)
    147     , m_svgStyle(o.m_svgStyle)
    148     , inherited_flags(o.inherited_flags)
    149     , noninherited_flags(o.noninherited_flags)
    150 {
    151 }
    152 
    153 static StyleRecalcChange diffPseudoStyles(const RenderStyle* oldStyle, const RenderStyle* newStyle)
    154 {
    155     // If the pseudoStyles have changed, we want any StyleRecalcChange that is not NoChange
    156     // because setStyle will do the right thing with anything else.
    157     if (!oldStyle->hasAnyPublicPseudoStyles())
    158         return NoChange;
    159     for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < FIRST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
    160         if (!oldStyle->hasPseudoStyle(pseudoId))
    161             continue;
    162         RenderStyle* newPseudoStyle = newStyle->getCachedPseudoStyle(pseudoId);
    163         if (!newPseudoStyle)
    164             return NoInherit;
    165         RenderStyle* oldPseudoStyle = oldStyle->getCachedPseudoStyle(pseudoId);
    166         if (oldPseudoStyle && *oldPseudoStyle != *newPseudoStyle)
    167             return NoInherit;
    168     }
    169     return NoChange;
    170 }
    171 
    172 StyleRecalcChange RenderStyle::stylePropagationDiff(const RenderStyle* oldStyle, const RenderStyle* newStyle)
    173 {
    174     if ((!oldStyle && newStyle) || (oldStyle && !newStyle))
    175         return Reattach;
    176 
    177     if (!oldStyle && !newStyle)
    178         return NoChange;
    179 
    180     if (oldStyle->display() != newStyle->display()
    181         || oldStyle->hasPseudoStyle(FIRST_LETTER) != newStyle->hasPseudoStyle(FIRST_LETTER)
    182         || oldStyle->columnSpan() != newStyle->columnSpan()
    183         || !oldStyle->contentDataEquivalent(newStyle)
    184         || oldStyle->hasTextCombine() != newStyle->hasTextCombine())
    185         return Reattach;
    186 
    187     if (*oldStyle == *newStyle)
    188         return diffPseudoStyles(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     noninherited_flags.hasViewportUnits = other->noninherited_flags.hasViewportUnits;
    237     if (m_svgStyle != other->m_svgStyle)
    238         m_svgStyle.access()->copyNonInheritedFrom(other->m_svgStyle.get());
    239     ASSERT(zoom() == initialZoom());
    240 }
    241 
    242 bool RenderStyle::operator==(const RenderStyle& o) const
    243 {
    244     // compare everything except the pseudoStyle pointer
    245     return inherited_flags == o.inherited_flags
    246         && noninherited_flags == o.noninherited_flags
    247         && m_box == o.m_box
    248         && visual == o.visual
    249         && m_background == o.m_background
    250         && surround == o.surround
    251         && rareNonInheritedData == o.rareNonInheritedData
    252         && rareInheritedData == o.rareInheritedData
    253         && inherited == o.inherited
    254         && m_svgStyle == o.m_svgStyle;
    255 }
    256 
    257 bool RenderStyle::isStyleAvailable() const
    258 {
    259     return this != StyleResolver::styleNotYetAvailable();
    260 }
    261 
    262 bool RenderStyle::hasUniquePseudoStyle() const
    263 {
    264     if (!m_cachedPseudoStyles || styleType() != NOPSEUDO)
    265         return false;
    266 
    267     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
    268         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
    269         if (pseudoStyle->unique())
    270             return true;
    271     }
    272 
    273     return false;
    274 }
    275 
    276 RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
    277 {
    278     if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
    279         return 0;
    280 
    281     if (styleType() != NOPSEUDO)
    282         return 0;
    283 
    284     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
    285         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
    286         if (pseudoStyle->styleType() == pid)
    287             return pseudoStyle;
    288     }
    289 
    290     return 0;
    291 }
    292 
    293 RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
    294 {
    295     if (!pseudo)
    296         return 0;
    297 
    298     ASSERT(pseudo->styleType() > NOPSEUDO);
    299 
    300     RenderStyle* result = pseudo.get();
    301 
    302     if (!m_cachedPseudoStyles)
    303         m_cachedPseudoStyles = adoptPtr(new PseudoStyleCache);
    304 
    305     m_cachedPseudoStyles->append(pseudo);
    306 
    307     return result;
    308 }
    309 
    310 void RenderStyle::removeCachedPseudoStyle(PseudoId pid)
    311 {
    312     if (!m_cachedPseudoStyles)
    313         return;
    314     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
    315         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
    316         if (pseudoStyle->styleType() == pid) {
    317             m_cachedPseudoStyles->remove(i);
    318             return;
    319         }
    320     }
    321 }
    322 
    323 bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
    324 {
    325     return inherited_flags != other->inherited_flags
    326            || inherited != other->inherited
    327            || m_svgStyle->inheritedNotEqual(other->m_svgStyle.get())
    328            || rareInheritedData != other->rareInheritedData;
    329 }
    330 
    331 bool RenderStyle::inheritedDataShared(const RenderStyle* other) const
    332 {
    333     // This is a fast check that only looks if the data structures are shared.
    334     return inherited_flags == other->inherited_flags
    335         && inherited.get() == other->inherited.get()
    336         && m_svgStyle.get() == other->m_svgStyle.get()
    337         && rareInheritedData.get() == other->rareInheritedData.get();
    338 }
    339 
    340 static bool positionedObjectMovedOnly(const LengthBox& a, const LengthBox& b, const Length& width)
    341 {
    342     // If any unit types are different, then we can't guarantee
    343     // that this was just a movement.
    344     if (a.left().type() != b.left().type()
    345         || a.right().type() != b.right().type()
    346         || a.top().type() != b.top().type()
    347         || a.bottom().type() != b.bottom().type())
    348         return false;
    349 
    350     // Only one unit can be non-auto in the horizontal direction and
    351     // in the vertical direction.  Otherwise the adjustment of values
    352     // is changing the size of the box.
    353     if (!a.left().isIntrinsicOrAuto() && !a.right().isIntrinsicOrAuto())
    354         return false;
    355     if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
    356         return false;
    357     // If our width is auto and left or right is specified and changed then this
    358     // is not just a movement - we need to resize to our container.
    359     if (width.isIntrinsicOrAuto()
    360         && ((!a.left().isIntrinsicOrAuto() && a.left() != b.left())
    361             || (!a.right().isIntrinsicOrAuto() && a.right() != b.right())))
    362         return false;
    363 
    364     // One of the units is fixed or percent in both directions and stayed
    365     // that way in the new style.  Therefore all we are doing is moving.
    366     return true;
    367 }
    368 
    369 StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
    370 {
    371     // Note, we use .get() on each DataRef below because DataRef::operator== will do a deep
    372     // compare, which is duplicate work when we're going to compare each property inside
    373     // this function anyway.
    374 
    375     StyleDifference diff;
    376     if (m_svgStyle.get() != other.m_svgStyle.get())
    377         diff = m_svgStyle->diff(other.m_svgStyle.get());
    378 
    379     if ((!diff.needsFullLayout() || !diff.needsRepaint()) && diffNeedsFullLayoutAndRepaint(other)) {
    380         diff.setNeedsFullLayout();
    381         diff.setNeedsRepaintObject();
    382     }
    383 
    384     if (!diff.needsFullLayout() && diffNeedsFullLayout(other))
    385         diff.setNeedsFullLayout();
    386 
    387     if (!diff.needsFullLayout() && position() != StaticPosition && surround->offset != other.surround->offset) {
    388         // Optimize for the case where a positioned layer is moving but not changing size.
    389         if ((position() == AbsolutePosition || position() == FixedPosition)
    390             && positionedObjectMovedOnly(surround->offset, other.surround->offset, m_box->width())) {
    391             diff.setNeedsPositionedMovementLayout();
    392         } else {
    393             // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet.
    394             // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
    395             // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
    396             diff.setNeedsFullLayout();
    397         }
    398     }
    399 
    400     if (diffNeedsRepaintLayer(other))
    401         diff.setNeedsRepaintLayer();
    402     else if (diffNeedsRepaintObject(other))
    403         diff.setNeedsRepaintObject();
    404 
    405     changedContextSensitiveProperties = computeChangedContextSensitiveProperties(other, diff);
    406 
    407     if (diff.hasNoChange() && diffNeedsRecompositeLayer(other))
    408         diff.setNeedsRecompositeLayer();
    409 
    410     // Cursors are not checked, since they will be set appropriately in response to mouse events,
    411     // so they don't need to cause any repaint or layout.
    412 
    413     // 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
    414     // the resulting transition properly.
    415 
    416     return diff;
    417 }
    418 
    419 bool RenderStyle::diffNeedsFullLayoutAndRepaint(const RenderStyle& other) const
    420 {
    421     // FIXME: Not all cases in this method need both full layout and repaint.
    422     // Should move cases into diffNeedsFullLayout() if
    423     // - don't need repaint at all;
    424     // - or the renderer knows how to exactly repaint caused by the layout change
    425     //   instead of forced full repaint.
    426 
    427     if (m_box.get() != other.m_box.get()) {
    428         if (m_box->width() != other.m_box->width()
    429             || m_box->minWidth() != other.m_box->minWidth()
    430             || m_box->maxWidth() != other.m_box->maxWidth()
    431             || m_box->height() != other.m_box->height()
    432             || m_box->minHeight() != other.m_box->minHeight()
    433             || m_box->maxHeight() != other.m_box->maxHeight())
    434             return true;
    435 
    436         if (m_box->verticalAlign() != other.m_box->verticalAlign())
    437             return true;
    438 
    439         if (m_box->boxSizing() != other.m_box->boxSizing())
    440             return true;
    441     }
    442 
    443     if (surround.get() != other.surround.get()) {
    444         if (surround->margin != other.surround->margin)
    445             return true;
    446 
    447         if (surround->padding != other.surround->padding)
    448             return true;
    449 
    450         // If our border widths change, then we need to layout. Other changes to borders only necessitate a repaint.
    451         if (borderLeftWidth() != other.borderLeftWidth()
    452             || borderTopWidth() != other.borderTopWidth()
    453             || borderBottomWidth() != other.borderBottomWidth()
    454             || borderRightWidth() != other.borderRightWidth())
    455             return true;
    456     }
    457 
    458     if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
    459         if (rareNonInheritedData->m_appearance != other.rareNonInheritedData->m_appearance
    460             || rareNonInheritedData->marginBeforeCollapse != other.rareNonInheritedData->marginBeforeCollapse
    461             || rareNonInheritedData->marginAfterCollapse != other.rareNonInheritedData->marginAfterCollapse
    462             || rareNonInheritedData->lineClamp != other.rareNonInheritedData->lineClamp
    463             || rareNonInheritedData->textOverflow != other.rareNonInheritedData->textOverflow
    464             || rareNonInheritedData->m_wrapFlow != other.rareNonInheritedData->m_wrapFlow
    465             || rareNonInheritedData->m_wrapThrough != other.rareNonInheritedData->m_wrapThrough
    466             || rareNonInheritedData->m_shapeMargin != other.rareNonInheritedData->m_shapeMargin
    467             || rareNonInheritedData->m_order != other.rareNonInheritedData->m_order
    468             || rareNonInheritedData->m_alignContent != other.rareNonInheritedData->m_alignContent
    469             || rareNonInheritedData->m_alignItems != other.rareNonInheritedData->m_alignItems
    470             || rareNonInheritedData->m_alignSelf != other.rareNonInheritedData->m_alignSelf
    471             || rareNonInheritedData->m_justifyContent != other.rareNonInheritedData->m_justifyContent
    472             || rareNonInheritedData->m_grid.get() != other.rareNonInheritedData->m_grid.get()
    473             || rareNonInheritedData->m_gridItem.get() != other.rareNonInheritedData->m_gridItem.get()
    474             || rareNonInheritedData->m_textCombine != other.rareNonInheritedData->m_textCombine
    475             || rareNonInheritedData->hasFilters() != other.rareNonInheritedData->hasFilters())
    476             return true;
    477 
    478         if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other.rareNonInheritedData->m_deprecatedFlexibleBox.get()
    479             && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other.rareNonInheritedData->m_deprecatedFlexibleBox.get())
    480             return true;
    481 
    482         if (rareNonInheritedData->m_flexibleBox.get() != other.rareNonInheritedData->m_flexibleBox.get()
    483             && *rareNonInheritedData->m_flexibleBox.get() != *other.rareNonInheritedData->m_flexibleBox.get())
    484             return true;
    485 
    486         // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
    487         if (!rareNonInheritedData->shadowDataEquivalent(*other.rareNonInheritedData.get()))
    488             return true;
    489 
    490         if (!rareNonInheritedData->reflectionDataEquivalent(*other.rareNonInheritedData.get()))
    491             return true;
    492 
    493         if (rareNonInheritedData->m_multiCol.get() != other.rareNonInheritedData->m_multiCol.get()
    494             && *rareNonInheritedData->m_multiCol.get() != *other.rareNonInheritedData->m_multiCol.get())
    495             return true;
    496 
    497         // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
    498         const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
    499         const CounterDirectiveMap* mapB = other.rareNonInheritedData->m_counterDirectives.get();
    500         if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
    501             return true;
    502 
    503         // We only need do layout for opacity changes if adding or losing opacity could trigger a change
    504         // in us being a stacking context.
    505         if (hasAutoZIndex() != other.hasAutoZIndex() && rareNonInheritedData->hasOpacity() != other.rareNonInheritedData->hasOpacity()) {
    506             // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
    507             // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
    508             // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
    509             // In addition we need to solve the floating object issue when layers come and go. Right now
    510             // a full layout is necessary to keep floating object lists sane.
    511             return true;
    512         }
    513     }
    514 
    515     if (rareInheritedData.get() != other.rareInheritedData.get()) {
    516         if (rareInheritedData->highlight != other.rareInheritedData->highlight
    517             || rareInheritedData->indent != other.rareInheritedData->indent
    518             || rareInheritedData->m_textAlignLast != other.rareInheritedData->m_textAlignLast
    519             || rareInheritedData->m_textIndentLine != other.rareInheritedData->m_textIndentLine
    520             || rareInheritedData->m_effectiveZoom != other.rareInheritedData->m_effectiveZoom
    521             || rareInheritedData->wordBreak != other.rareInheritedData->wordBreak
    522             || rareInheritedData->overflowWrap != other.rareInheritedData->overflowWrap
    523             || rareInheritedData->lineBreak != other.rareInheritedData->lineBreak
    524             || rareInheritedData->textSecurity != other.rareInheritedData->textSecurity
    525             || rareInheritedData->hyphens != other.rareInheritedData->hyphens
    526             || rareInheritedData->hyphenationLimitBefore != other.rareInheritedData->hyphenationLimitBefore
    527             || rareInheritedData->hyphenationLimitAfter != other.rareInheritedData->hyphenationLimitAfter
    528             || rareInheritedData->hyphenationString != other.rareInheritedData->hyphenationString
    529             || rareInheritedData->locale != other.rareInheritedData->locale
    530             || rareInheritedData->m_rubyPosition != other.rareInheritedData->m_rubyPosition
    531             || rareInheritedData->textEmphasisMark != other.rareInheritedData->textEmphasisMark
    532             || rareInheritedData->textEmphasisPosition != other.rareInheritedData->textEmphasisPosition
    533             || rareInheritedData->textEmphasisCustomMark != other.rareInheritedData->textEmphasisCustomMark
    534             || rareInheritedData->m_textJustify != other.rareInheritedData->m_textJustify
    535             || rareInheritedData->m_textOrientation != other.rareInheritedData->m_textOrientation
    536             || rareInheritedData->m_tabSize != other.rareInheritedData->m_tabSize
    537             || rareInheritedData->m_lineBoxContain != other.rareInheritedData->m_lineBoxContain
    538             || rareInheritedData->listStyleImage != other.rareInheritedData->listStyleImage
    539             || rareInheritedData->textStrokeWidth != other.rareInheritedData->textStrokeWidth)
    540             return true;
    541 
    542         if (!rareInheritedData->shadowDataEquivalent(*other.rareInheritedData.get()))
    543             return true;
    544 
    545         if (!rareInheritedData->quotesDataEquivalent(*other.rareInheritedData.get()))
    546             return true;
    547     }
    548 
    549     if (inherited->textAutosizingMultiplier != other.inherited->textAutosizingMultiplier)
    550         return true;
    551 
    552     if (inherited.get() != other.inherited.get()) {
    553         if (inherited->line_height != other.inherited->line_height
    554             || inherited->font != other.inherited->font
    555             || inherited->horizontal_border_spacing != other.inherited->horizontal_border_spacing
    556             || inherited->vertical_border_spacing != other.inherited->vertical_border_spacing)
    557             return true;
    558     }
    559 
    560     if (inherited_flags._box_direction != other.inherited_flags._box_direction
    561         || inherited_flags.m_rtlOrdering != other.inherited_flags.m_rtlOrdering
    562         || inherited_flags._text_align != other.inherited_flags._text_align
    563         || inherited_flags._text_transform != other.inherited_flags._text_transform
    564         || inherited_flags._direction != other.inherited_flags._direction
    565         || inherited_flags._white_space != other.inherited_flags._white_space
    566         || inherited_flags.m_writingMode != other.inherited_flags.m_writingMode)
    567         return true;
    568 
    569     if (noninherited_flags._overflowX != other.noninherited_flags._overflowX
    570         || noninherited_flags._overflowY != other.noninherited_flags._overflowY
    571         || noninherited_flags._clear != other.noninherited_flags._clear
    572         || noninherited_flags._unicodeBidi != other.noninherited_flags._unicodeBidi
    573         || noninherited_flags._position != other.noninherited_flags._position
    574         || noninherited_flags._floating != other.noninherited_flags._floating
    575         || noninherited_flags._originalDisplay != other.noninherited_flags._originalDisplay
    576         || noninherited_flags._vertical_align != other.noninherited_flags._vertical_align)
    577         return true;
    578 
    579     if (noninherited_flags._effectiveDisplay >= FIRST_TABLE_DISPLAY && noninherited_flags._effectiveDisplay <= LAST_TABLE_DISPLAY) {
    580         if (inherited_flags._border_collapse != other.inherited_flags._border_collapse
    581             || inherited_flags._empty_cells != other.inherited_flags._empty_cells
    582             || inherited_flags._caption_side != other.inherited_flags._caption_side
    583             || noninherited_flags._table_layout != other.noninherited_flags._table_layout)
    584             return true;
    585 
    586         // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
    587         // does not, so these style differences can be width differences.
    588         if (inherited_flags._border_collapse
    589             && ((borderTopStyle() == BHIDDEN && other.borderTopStyle() == BNONE)
    590                 || (borderTopStyle() == BNONE && other.borderTopStyle() == BHIDDEN)
    591                 || (borderBottomStyle() == BHIDDEN && other.borderBottomStyle() == BNONE)
    592                 || (borderBottomStyle() == BNONE && other.borderBottomStyle() == BHIDDEN)
    593                 || (borderLeftStyle() == BHIDDEN && other.borderLeftStyle() == BNONE)
    594                 || (borderLeftStyle() == BNONE && other.borderLeftStyle() == BHIDDEN)
    595                 || (borderRightStyle() == BHIDDEN && other.borderRightStyle() == BNONE)
    596                 || (borderRightStyle() == BNONE && other.borderRightStyle() == BHIDDEN)))
    597             return true;
    598     } else if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
    599         if (inherited_flags._list_style_type != other.inherited_flags._list_style_type
    600             || inherited_flags._list_style_position != other.inherited_flags._list_style_position)
    601             return true;
    602     }
    603 
    604     if ((visibility() == COLLAPSE) != (other.visibility() == COLLAPSE))
    605         return true;
    606 
    607     if (!m_background->outline().visuallyEqual(other.m_background->outline())) {
    608         // FIXME: We only really need to recompute the overflow but we don't have an optimized layout for it.
    609         return true;
    610     }
    611 
    612     // Movement of non-static-positioned object is special cased in RenderStyle::visualInvalidationDiff().
    613 
    614     return false;
    615 }
    616 
    617 bool RenderStyle::diffNeedsFullLayout(const RenderStyle& other) const
    618 {
    619     return false;
    620 }
    621 
    622 bool RenderStyle::diffNeedsRepaintLayer(const RenderStyle& other) const
    623 {
    624     if (position() != StaticPosition && (visual->clip != other.visual->clip || visual->hasClip != other.visual->hasClip))
    625         return true;
    626 
    627     if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
    628         if (RuntimeEnabledFeatures::cssCompositingEnabled()
    629             && (rareNonInheritedData->m_effectiveBlendMode != other.rareNonInheritedData->m_effectiveBlendMode
    630                 || rareNonInheritedData->m_isolation != other.rareNonInheritedData->m_isolation))
    631             return true;
    632 
    633         if (rareNonInheritedData->m_mask != other.rareNonInheritedData->m_mask
    634             || rareNonInheritedData->m_maskBoxImage != other.rareNonInheritedData->m_maskBoxImage)
    635             return true;
    636     }
    637 
    638     return false;
    639 }
    640 
    641 bool RenderStyle::diffNeedsRepaintObject(const RenderStyle& other) const
    642 {
    643     if (inherited_flags._visibility != other.inherited_flags._visibility
    644         || inherited_flags.m_printColorAdjust != other.inherited_flags.m_printColorAdjust
    645         || inherited_flags._insideLink != other.inherited_flags._insideLink
    646         || !surround->border.visuallyEqual(other.surround->border)
    647         || !m_background->visuallyEqual(*other.m_background))
    648         return true;
    649 
    650     if (rareInheritedData.get() != other.rareInheritedData.get()) {
    651         if (rareInheritedData->userModify != other.rareInheritedData->userModify
    652             || rareInheritedData->userSelect != other.rareInheritedData->userSelect
    653             || rareInheritedData->m_imageRendering != other.rareInheritedData->m_imageRendering)
    654             return true;
    655     }
    656 
    657     if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
    658         if (rareNonInheritedData->userDrag != other.rareNonInheritedData->userDrag
    659             || rareNonInheritedData->m_borderFit != other.rareNonInheritedData->m_borderFit
    660             || rareNonInheritedData->m_objectFit != other.rareNonInheritedData->m_objectFit
    661             || rareNonInheritedData->m_objectPosition != other.rareNonInheritedData->m_objectPosition
    662             || rareNonInheritedData->m_shapeOutside != other.rareNonInheritedData->m_shapeOutside
    663             || rareNonInheritedData->m_clipPath != other.rareNonInheritedData->m_clipPath)
    664             return true;
    665     }
    666 
    667     return false;
    668 }
    669 
    670 bool RenderStyle::diffNeedsRecompositeLayer(const RenderStyle& other) const
    671 {
    672     if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
    673         if (rareNonInheritedData->m_transformStyle3D != other.rareNonInheritedData->m_transformStyle3D
    674             || rareNonInheritedData->m_backfaceVisibility != other.rareNonInheritedData->m_backfaceVisibility
    675             || rareNonInheritedData->m_perspective != other.rareNonInheritedData->m_perspective
    676             || rareNonInheritedData->m_perspectiveOriginX != other.rareNonInheritedData->m_perspectiveOriginX
    677             || rareNonInheritedData->m_perspectiveOriginY != other.rareNonInheritedData->m_perspectiveOriginY
    678             || hasWillChangeCompositingHint() != other.hasWillChangeCompositingHint())
    679             return true;
    680     }
    681 
    682     return false;
    683 }
    684 
    685 unsigned RenderStyle::computeChangedContextSensitiveProperties(const RenderStyle& other, StyleDifference diff) const
    686 {
    687     unsigned changedContextSensitiveProperties = ContextSensitivePropertyNone;
    688 
    689     // StyleAdjuster has ensured that zIndex is non-auto only if it's applicable.
    690     if (m_box->zIndex() != other.m_box->zIndex() || m_box->hasAutoZIndex() != other.m_box->hasAutoZIndex())
    691         changedContextSensitiveProperties |= ContextSensitivePropertyZIndex;
    692 
    693     if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
    694         if (!transformDataEquivalent(other))
    695             changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
    696 
    697         if (rareNonInheritedData->opacity != other.rareNonInheritedData->opacity)
    698             changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
    699 
    700         if (rareNonInheritedData->m_filter != other.rareNonInheritedData->m_filter)
    701             changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
    702     }
    703 
    704     if (!diff.needsRepaint()) {
    705         if (inherited->color != other.inherited->color
    706             || inherited_flags.m_textUnderline != other.inherited_flags.m_textUnderline
    707             || visual->textDecoration != other.visual->textDecoration) {
    708             changedContextSensitiveProperties |= ContextSensitivePropertyTextOrColor;
    709         } else if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
    710             if (rareNonInheritedData->m_textDecorationStyle != other.rareNonInheritedData->m_textDecorationStyle
    711                 || rareNonInheritedData->m_textDecorationColor != other.rareNonInheritedData->m_textDecorationColor)
    712                 changedContextSensitiveProperties |= ContextSensitivePropertyTextOrColor;
    713         } else if (rareInheritedData.get() != other.rareInheritedData.get()) {
    714             if (rareInheritedData->textFillColor() != other.rareInheritedData->textFillColor()
    715                 || rareInheritedData->textStrokeColor() != other.rareInheritedData->textStrokeColor()
    716                 || rareInheritedData->textEmphasisColor() != other.rareInheritedData->textEmphasisColor()
    717                 || rareInheritedData->textEmphasisFill != other.rareInheritedData->textEmphasisFill
    718                 || rareInheritedData->appliedTextDecorations != other.rareInheritedData->appliedTextDecorations)
    719                 changedContextSensitiveProperties |= ContextSensitivePropertyTextOrColor;
    720         }
    721     }
    722 
    723     return changedContextSensitiveProperties;
    724 }
    725 
    726 void RenderStyle::setClip(const Length& top, const Length& right, const Length& bottom, const Length& left)
    727 {
    728     StyleVisualData* data = visual.access();
    729     data->clip.m_top = top;
    730     data->clip.m_right = right;
    731     data->clip.m_bottom = bottom;
    732     data->clip.m_left = left;
    733 }
    734 
    735 void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
    736 {
    737     if (!rareInheritedData.access()->cursorData)
    738         rareInheritedData.access()->cursorData = CursorList::create();
    739     rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
    740 }
    741 
    742 void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
    743 {
    744     rareInheritedData.access()->cursorData = other;
    745 }
    746 
    747 void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
    748 {
    749     rareInheritedData.access()->quotes = q;
    750 }
    751 
    752 void RenderStyle::clearCursorList()
    753 {
    754     if (rareInheritedData->cursorData)
    755         rareInheritedData.access()->cursorData = nullptr;
    756 }
    757 
    758 void RenderStyle::addCallbackSelector(const String& selector)
    759 {
    760     if (!rareNonInheritedData->m_callbackSelectors.contains(selector))
    761         rareNonInheritedData.access()->m_callbackSelectors.append(selector);
    762 }
    763 
    764 void RenderStyle::clearContent()
    765 {
    766     if (rareNonInheritedData->m_content)
    767         rareNonInheritedData.access()->m_content = nullptr;
    768 }
    769 
    770 void RenderStyle::appendContent(PassOwnPtr<ContentData> contentData)
    771 {
    772     OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
    773     ContentData* lastContent = content.get();
    774     while (lastContent && lastContent->next())
    775         lastContent = lastContent->next();
    776 
    777     if (lastContent)
    778         lastContent->setNext(contentData);
    779     else
    780         content = contentData;
    781 }
    782 
    783 void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
    784 {
    785     if (!image)
    786         return;
    787 
    788     if (add) {
    789         appendContent(ContentData::create(image));
    790         return;
    791     }
    792 
    793     rareNonInheritedData.access()->m_content = ContentData::create(image);
    794 }
    795 
    796 void RenderStyle::setContent(const String& string, bool add)
    797 {
    798     OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
    799     if (add) {
    800         ContentData* lastContent = content.get();
    801         while (lastContent && lastContent->next())
    802             lastContent = lastContent->next();
    803 
    804         if (lastContent) {
    805             // We attempt to merge with the last ContentData if possible.
    806             if (lastContent->isText()) {
    807                 TextContentData* textContent = static_cast<TextContentData*>(lastContent);
    808                 textContent->setText(textContent->text() + string);
    809             } else
    810                 lastContent->setNext(ContentData::create(string));
    811 
    812             return;
    813         }
    814     }
    815 
    816     content = ContentData::create(string);
    817 }
    818 
    819 void RenderStyle::setContent(PassOwnPtr<CounterContent> counter, bool add)
    820 {
    821     if (!counter)
    822         return;
    823 
    824     if (add) {
    825         appendContent(ContentData::create(counter));
    826         return;
    827     }
    828 
    829     rareNonInheritedData.access()->m_content = ContentData::create(counter);
    830 }
    831 
    832 void RenderStyle::setContent(QuoteType quote, bool add)
    833 {
    834     if (add) {
    835         appendContent(ContentData::create(quote));
    836         return;
    837     }
    838 
    839     rareNonInheritedData.access()->m_content = ContentData::create(quote);
    840 }
    841 
    842 blink::WebBlendMode RenderStyle::blendMode() const
    843 {
    844     if (RuntimeEnabledFeatures::cssCompositingEnabled())
    845         return static_cast<blink::WebBlendMode>(rareNonInheritedData->m_effectiveBlendMode);
    846     return blink::WebBlendModeNormal;
    847 }
    848 
    849 void RenderStyle::setBlendMode(blink::WebBlendMode v)
    850 {
    851     if (RuntimeEnabledFeatures::cssCompositingEnabled())
    852         rareNonInheritedData.access()->m_effectiveBlendMode = v;
    853 }
    854 
    855 bool RenderStyle::hasBlendMode() const
    856 {
    857     if (RuntimeEnabledFeatures::cssCompositingEnabled())
    858         return static_cast<blink::WebBlendMode>(rareNonInheritedData->m_effectiveBlendMode) != blink::WebBlendModeNormal;
    859     return false;
    860 }
    861 
    862 EIsolation RenderStyle::isolation() const
    863 {
    864     if (RuntimeEnabledFeatures::cssCompositingEnabled())
    865         return static_cast<EIsolation>(rareNonInheritedData->m_isolation);
    866     return IsolationAuto;
    867 }
    868 
    869 void RenderStyle::setIsolation(EIsolation v)
    870 {
    871     if (RuntimeEnabledFeatures::cssCompositingEnabled())
    872         rareNonInheritedData.access()->m_isolation = v;
    873 }
    874 
    875 bool RenderStyle::hasIsolation() const
    876 {
    877     if (RuntimeEnabledFeatures::cssCompositingEnabled())
    878         return rareNonInheritedData->m_isolation != IsolationAuto;
    879     return false;
    880 }
    881 
    882 bool RenderStyle::hasWillChangeCompositingHint() const
    883 {
    884     for (size_t i = 0; i < rareNonInheritedData->m_willChange->m_properties.size(); ++i) {
    885         switch (rareNonInheritedData->m_willChange->m_properties[i]) {
    886         case CSSPropertyOpacity:
    887         case CSSPropertyTransform:
    888         case CSSPropertyWebkitTransform:
    889         case CSSPropertyTop:
    890         case CSSPropertyLeft:
    891         case CSSPropertyBottom:
    892         case CSSPropertyRight:
    893             return true;
    894         default:
    895             break;
    896         }
    897     }
    898     return false;
    899 }
    900 
    901 inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation> >& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
    902 {
    903     // transform-origin brackets the transform with translate operations.
    904     // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
    905     // in that case.
    906     if (applyOrigin != RenderStyle::IncludeTransformOrigin)
    907         return false;
    908 
    909     unsigned size = transformOperations.size();
    910     for (unsigned i = 0; i < size; ++i) {
    911         TransformOperation::OperationType type = transformOperations[i]->type();
    912         if (type != TransformOperation::TranslateX
    913             && type != TransformOperation::TranslateY
    914             && type != TransformOperation::Translate
    915             && type != TransformOperation::TranslateZ
    916             && type != TransformOperation::Translate3D)
    917             return true;
    918     }
    919 
    920     return false;
    921 }
    922 
    923 void RenderStyle::applyTransform(TransformationMatrix& transform, const LayoutSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const
    924 {
    925     applyTransform(transform, FloatRect(FloatPoint(), borderBoxSize), applyOrigin);
    926 }
    927 
    928 void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const
    929 {
    930     const Vector<RefPtr<TransformOperation> >& transformOperations = rareNonInheritedData->m_transform->m_operations.operations();
    931     bool applyTransformOrigin = requireTransformOrigin(transformOperations, applyOrigin);
    932 
    933     float offsetX = transformOriginX().type() == Percent ? boundingBox.x() : 0;
    934     float offsetY = transformOriginY().type() == Percent ? boundingBox.y() : 0;
    935 
    936     if (applyTransformOrigin) {
    937         transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX,
    938             floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY,
    939             transformOriginZ());
    940     }
    941 
    942     unsigned size = transformOperations.size();
    943     for (unsigned i = 0; i < size; ++i)
    944         transformOperations[i]->apply(transform, boundingBox.size());
    945 
    946     if (applyTransformOrigin) {
    947         transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX,
    948             -floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY,
    949             -transformOriginZ());
    950     }
    951 }
    952 
    953 void RenderStyle::setTextShadow(PassRefPtr<ShadowList> s)
    954 {
    955     rareInheritedData.access()->textShadow = s;
    956 }
    957 
    958 void RenderStyle::setBoxShadow(PassRefPtr<ShadowList> s)
    959 {
    960     rareNonInheritedData.access()->m_boxShadow = s;
    961 }
    962 
    963 static RoundedRect::Radii calcRadiiFor(const BorderData& border, IntSize size)
    964 {
    965     return RoundedRect::Radii(
    966         IntSize(valueForLength(border.topLeft().width(), size.width()),
    967             valueForLength(border.topLeft().height(), size.height())),
    968         IntSize(valueForLength(border.topRight().width(), size.width()),
    969             valueForLength(border.topRight().height(), size.height())),
    970         IntSize(valueForLength(border.bottomLeft().width(), size.width()),
    971             valueForLength(border.bottomLeft().height(), size.height())),
    972         IntSize(valueForLength(border.bottomRight().width(), size.width()),
    973             valueForLength(border.bottomRight().height(), size.height())));
    974 }
    975 
    976 StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); }
    977 void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v)
    978 {
    979     if (rareInheritedData->listStyleImage != v)
    980         rareInheritedData.access()->listStyleImage = v;
    981 }
    982 
    983 Color RenderStyle::color() const { return inherited->color; }
    984 Color RenderStyle::visitedLinkColor() const { return inherited->visitedLinkColor; }
    985 void RenderStyle::setColor(const Color& v) { SET_VAR(inherited, color, v); }
    986 void RenderStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visitedLinkColor, v); }
    987 
    988 short RenderStyle::horizontalBorderSpacing() const { return inherited->horizontal_border_spacing; }
    989 short RenderStyle::verticalBorderSpacing() const { return inherited->vertical_border_spacing; }
    990 void RenderStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v); }
    991 void RenderStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertical_border_spacing, v); }
    992 
    993 RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
    994 {
    995     IntRect snappedBorderRect(pixelSnappedIntRect(borderRect));
    996     RoundedRect roundedRect(snappedBorderRect);
    997     if (hasBorderRadius()) {
    998         RoundedRect::Radii radii = calcRadiiFor(surround->border, snappedBorderRect.size());
    999         radii.scale(calcBorderRadiiConstraintScaleFor(borderRect, radii));
   1000         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
   1001     }
   1002     return roundedRect;
   1003 }
   1004 
   1005 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
   1006 {
   1007     bool horizontal = isHorizontalWritingMode();
   1008 
   1009     int leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
   1010     int rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
   1011     int topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
   1012     int bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;
   1013 
   1014     return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
   1015 }
   1016 
   1017 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect,
   1018     int topWidth, int bottomWidth, int leftWidth, int rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
   1019 {
   1020     LayoutRect innerRect(borderRect.x() + leftWidth,
   1021                borderRect.y() + topWidth,
   1022                borderRect.width() - leftWidth - rightWidth,
   1023                borderRect.height() - topWidth - bottomWidth);
   1024 
   1025     RoundedRect roundedRect(pixelSnappedIntRect(innerRect));
   1026 
   1027     if (hasBorderRadius()) {
   1028         RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii();
   1029         radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
   1030         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
   1031     }
   1032     return roundedRect;
   1033 }
   1034 
   1035 static bool allLayersAreFixed(const FillLayer* layer)
   1036 {
   1037     bool allFixed = true;
   1038 
   1039     for (const FillLayer* currLayer = layer; currLayer; currLayer = currLayer->next())
   1040         allFixed &= (currLayer->image() && currLayer->attachment() == FixedBackgroundAttachment);
   1041 
   1042     return layer && allFixed;
   1043 }
   1044 
   1045 bool RenderStyle::hasEntirelyFixedBackground() const
   1046 {
   1047     return allLayersAreFixed(backgroundLayers());
   1048 }
   1049 
   1050 const CounterDirectiveMap* RenderStyle::counterDirectives() const
   1051 {
   1052     return rareNonInheritedData->m_counterDirectives.get();
   1053 }
   1054 
   1055 CounterDirectiveMap& RenderStyle::accessCounterDirectives()
   1056 {
   1057     OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterDirectives;
   1058     if (!map)
   1059         map = adoptPtr(new CounterDirectiveMap);
   1060     return *map;
   1061 }
   1062 
   1063 const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const
   1064 {
   1065     if (const CounterDirectiveMap* directives = counterDirectives())
   1066         return directives->get(identifier);
   1067     return CounterDirectives();
   1068 }
   1069 
   1070 const AtomicString& RenderStyle::hyphenString() const
   1071 {
   1072     const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString;
   1073     if (!hyphenationString.isNull())
   1074         return hyphenationString;
   1075 
   1076     // FIXME: This should depend on locale.
   1077     DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinus, 1));
   1078     DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphen, 1));
   1079     return font().primaryFontHasGlyphForCharacter(hyphen) ? hyphenString : hyphenMinusString;
   1080 }
   1081 
   1082 const AtomicString& RenderStyle::textEmphasisMarkString() const
   1083 {
   1084     switch (textEmphasisMark()) {
   1085     case TextEmphasisMarkNone:
   1086         return nullAtom;
   1087     case TextEmphasisMarkCustom:
   1088         return textEmphasisCustomMark();
   1089     case TextEmphasisMarkDot: {
   1090         DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1));
   1091         DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1));
   1092         return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
   1093     }
   1094     case TextEmphasisMarkCircle: {
   1095         DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1));
   1096         DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1));
   1097         return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString;
   1098     }
   1099     case TextEmphasisMarkDoubleCircle: {
   1100         DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1));
   1101         DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1));
   1102         return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString;
   1103     }
   1104     case TextEmphasisMarkTriangle: {
   1105         DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointingTriangle, 1));
   1106         DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingTriangle, 1));
   1107         return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString;
   1108     }
   1109     case TextEmphasisMarkSesame: {
   1110         DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1));
   1111         DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1));
   1112         return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString;
   1113     }
   1114     case TextEmphasisMarkAuto:
   1115         ASSERT_NOT_REACHED();
   1116         return nullAtom;
   1117     }
   1118 
   1119     ASSERT_NOT_REACHED();
   1120     return nullAtom;
   1121 }
   1122 
   1123 CSSAnimationData& RenderStyle::accessAnimations()
   1124 {
   1125     if (!rareNonInheritedData.access()->m_animations)
   1126         rareNonInheritedData.access()->m_animations = CSSAnimationData::create();
   1127     return *rareNonInheritedData->m_animations;
   1128 }
   1129 
   1130 CSSTransitionData& RenderStyle::accessTransitions()
   1131 {
   1132     if (!rareNonInheritedData.access()->m_transitions)
   1133         rareNonInheritedData.access()->m_transitions = CSSTransitionData::create();
   1134     return *rareNonInheritedData->m_transitions;
   1135 }
   1136 
   1137 const Font& RenderStyle::font() const { return inherited->font; }
   1138 const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); }
   1139 const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); }
   1140 float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); }
   1141 float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
   1142 int RenderStyle::fontSize() const { return fontDescription().computedPixelSize(); }
   1143 FontWeight RenderStyle::fontWeight() const { return fontDescription().weight(); }
   1144 
   1145 TextDecoration RenderStyle::textDecorationsInEffect() const
   1146 {
   1147     int decorations = 0;
   1148 
   1149     const Vector<AppliedTextDecoration>& applied = appliedTextDecorations();
   1150 
   1151     for (size_t i = 0; i < applied.size(); ++i)
   1152         decorations |= applied[i].line();
   1153 
   1154     return static_cast<TextDecoration>(decorations);
   1155 }
   1156 
   1157 const Vector<AppliedTextDecoration>& RenderStyle::appliedTextDecorations() const
   1158 {
   1159     if (!inherited_flags.m_textUnderline && !rareInheritedData->appliedTextDecorations) {
   1160         DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, empty, ());
   1161         return empty;
   1162     }
   1163     if (inherited_flags.m_textUnderline) {
   1164         DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, underline, (1, AppliedTextDecoration(TextDecorationUnderline)));
   1165         return underline;
   1166     }
   1167 
   1168     return rareInheritedData->appliedTextDecorations->vector();
   1169 }
   1170 
   1171 float RenderStyle::wordSpacing() const { return fontDescription().wordSpacing(); }
   1172 float RenderStyle::letterSpacing() const { return fontDescription().letterSpacing(); }
   1173 
   1174 bool RenderStyle::setFontDescription(const FontDescription& v)
   1175 {
   1176     if (inherited->font.fontDescription() != v) {
   1177         inherited.access()->font = Font(v);
   1178         return true;
   1179     }
   1180     return false;
   1181 }
   1182 
   1183 const Length& RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
   1184 Length RenderStyle::lineHeight() const
   1185 {
   1186     const Length& lh = inherited->line_height;
   1187     // Unlike fontDescription().computedSize() and hence fontSize(), this is
   1188     // recalculated on demand as we only store the specified line height.
   1189     // FIXME: Should consider scaling the fixed part of any calc expressions
   1190     // too, though this involves messily poking into CalcExpressionLength.
   1191     float multiplier = textAutosizingMultiplier();
   1192     if (multiplier > 1 && lh.isFixed())
   1193         return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multiplier), Fixed);
   1194 
   1195     return lh;
   1196 }
   1197 
   1198 void RenderStyle::setLineHeight(const Length& specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
   1199 
   1200 int RenderStyle::computedLineHeight() const
   1201 {
   1202     const Length& lh = lineHeight();
   1203 
   1204     // Negative value means the line height is not set. Use the font's built-in spacing.
   1205     if (lh.isNegative())
   1206         return fontMetrics().lineSpacing();
   1207 
   1208     if (lh.isPercent())
   1209         return minimumValueForLength(lh, fontSize());
   1210 
   1211     return lh.value();
   1212 }
   1213 
   1214 void RenderStyle::setWordSpacing(float wordSpacing)
   1215 {
   1216     FontSelector* currentFontSelector = font().fontSelector();
   1217     FontDescription desc(fontDescription());
   1218     desc.setWordSpacing(wordSpacing);
   1219     setFontDescription(desc);
   1220     font().update(currentFontSelector);
   1221 }
   1222 
   1223 void RenderStyle::setLetterSpacing(float letterSpacing)
   1224 {
   1225     FontSelector* currentFontSelector = font().fontSelector();
   1226     FontDescription desc(fontDescription());
   1227     desc.setLetterSpacing(letterSpacing);
   1228     setFontDescription(desc);
   1229     font().update(currentFontSelector);
   1230 }
   1231 
   1232 void RenderStyle::setFontSize(float size)
   1233 {
   1234     // size must be specifiedSize if Text Autosizing is enabled, but computedSize if text
   1235     // zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
   1236 
   1237     ASSERT(std::isfinite(size));
   1238     if (!std::isfinite(size) || size < 0)
   1239         size = 0;
   1240     else
   1241         size = min(maximumAllowedFontSize, size);
   1242 
   1243     FontSelector* currentFontSelector = font().fontSelector();
   1244     FontDescription desc(fontDescription());
   1245     desc.setSpecifiedSize(size);
   1246     desc.setComputedSize(size);
   1247 
   1248     float multiplier = textAutosizingMultiplier();
   1249     if (multiplier > 1) {
   1250         float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size, multiplier);
   1251         desc.setComputedSize(min(maximumAllowedFontSize, autosizedFontSize));
   1252     }
   1253 
   1254     setFontDescription(desc);
   1255     font().update(currentFontSelector);
   1256 }
   1257 
   1258 void RenderStyle::setFontWeight(FontWeight weight)
   1259 {
   1260     FontSelector* currentFontSelector = font().fontSelector();
   1261     FontDescription desc(fontDescription());
   1262     desc.setWeight(weight);
   1263     setFontDescription(desc);
   1264     font().update(currentFontSelector);
   1265 }
   1266 
   1267 void RenderStyle::addAppliedTextDecoration(const AppliedTextDecoration& decoration)
   1268 {
   1269     RefPtr<AppliedTextDecorationList>& list = rareInheritedData.access()->appliedTextDecorations;
   1270 
   1271     if (!list)
   1272         list = AppliedTextDecorationList::create();
   1273     else if (!list->hasOneRef())
   1274         list = list->copy();
   1275 
   1276     if (inherited_flags.m_textUnderline) {
   1277         inherited_flags.m_textUnderline = false;
   1278         list->append(AppliedTextDecoration(TextDecorationUnderline));
   1279     }
   1280 
   1281     list->append(decoration);
   1282 }
   1283 
   1284 void RenderStyle::applyTextDecorations()
   1285 {
   1286     if (textDecoration() == TextDecorationNone)
   1287         return;
   1288 
   1289     TextDecorationStyle style = textDecorationStyle();
   1290     StyleColor styleColor = visitedDependentDecorationStyleColor();
   1291 
   1292     int decorations = textDecoration();
   1293 
   1294     if (decorations & TextDecorationUnderline) {
   1295         // To save memory, we don't use AppliedTextDecoration objects in the
   1296         // common case of a single simple underline.
   1297         AppliedTextDecoration underline(TextDecorationUnderline, style, styleColor);
   1298 
   1299         if (!rareInheritedData->appliedTextDecorations && underline.isSimpleUnderline())
   1300             inherited_flags.m_textUnderline = true;
   1301         else
   1302             addAppliedTextDecoration(underline);
   1303     }
   1304     if (decorations & TextDecorationOverline)
   1305         addAppliedTextDecoration(AppliedTextDecoration(TextDecorationOverline, style, styleColor));
   1306     if (decorations & TextDecorationLineThrough)
   1307         addAppliedTextDecoration(AppliedTextDecoration(TextDecorationLineThrough, style, styleColor));
   1308 }
   1309 
   1310 void RenderStyle::clearAppliedTextDecorations()
   1311 {
   1312     inherited_flags.m_textUnderline = false;
   1313 
   1314     if (rareInheritedData->appliedTextDecorations)
   1315         rareInheritedData.access()->appliedTextDecorations = nullptr;
   1316 }
   1317 
   1318 void RenderStyle::getShadowExtent(const ShadowList* shadowList, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
   1319 {
   1320     top = 0;
   1321     right = 0;
   1322     bottom = 0;
   1323     left = 0;
   1324 
   1325     size_t shadowCount = shadowList ? shadowList->shadows().size() : 0;
   1326     for (size_t i = 0; i < shadowCount; ++i) {
   1327         const ShadowData& shadow = shadowList->shadows()[i];
   1328         if (shadow.style() == Inset)
   1329             continue;
   1330         float blurAndSpread = shadow.blur() + shadow.spread();
   1331 
   1332         top = min<LayoutUnit>(top, shadow.y() - blurAndSpread);
   1333         right = max<LayoutUnit>(right, shadow.x() + blurAndSpread);
   1334         bottom = max<LayoutUnit>(bottom, shadow.y() + blurAndSpread);
   1335         left = min<LayoutUnit>(left, shadow.x() - blurAndSpread);
   1336     }
   1337 }
   1338 
   1339 LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowList* shadowList) const
   1340 {
   1341     LayoutUnit top = 0;
   1342     LayoutUnit right = 0;
   1343     LayoutUnit bottom = 0;
   1344     LayoutUnit left = 0;
   1345 
   1346     size_t shadowCount = shadowList ? shadowList->shadows().size() : 0;
   1347     for (size_t i = 0; i < shadowCount; ++i) {
   1348         const ShadowData& shadow = shadowList->shadows()[i];
   1349         if (shadow.style() == Normal)
   1350             continue;
   1351         float blurAndSpread = shadow.blur() + shadow.spread();
   1352         top = max<LayoutUnit>(top, shadow.y() + blurAndSpread);
   1353         right = min<LayoutUnit>(right, shadow.x() - blurAndSpread);
   1354         bottom = min<LayoutUnit>(bottom, shadow.y() - blurAndSpread);
   1355         left = max<LayoutUnit>(left, shadow.x() + blurAndSpread);
   1356     }
   1357 
   1358     return LayoutBoxExtent(top, right, bottom, left);
   1359 }
   1360 
   1361 void RenderStyle::getShadowHorizontalExtent(const ShadowList* shadowList, LayoutUnit &left, LayoutUnit &right) const
   1362 {
   1363     left = 0;
   1364     right = 0;
   1365 
   1366     size_t shadowCount = shadowList ? shadowList->shadows().size() : 0;
   1367     for (size_t i = 0; i < shadowCount; ++i) {
   1368         const ShadowData& shadow = shadowList->shadows()[i];
   1369         if (shadow.style() == Inset)
   1370             continue;
   1371         float blurAndSpread = shadow.blur() + shadow.spread();
   1372 
   1373         left = min<LayoutUnit>(left, shadow.x() - blurAndSpread);
   1374         right = max<LayoutUnit>(right, shadow.x() + blurAndSpread);
   1375     }
   1376 }
   1377 
   1378 void RenderStyle::getShadowVerticalExtent(const ShadowList* shadowList, LayoutUnit &top, LayoutUnit &bottom) const
   1379 {
   1380     top = 0;
   1381     bottom = 0;
   1382 
   1383     size_t shadowCount = shadowList ? shadowList->shadows().size() : 0;
   1384     for (size_t i = 0; i < shadowCount; ++i) {
   1385         const ShadowData& shadow = shadowList->shadows()[i];
   1386         if (shadow.style() == Inset)
   1387             continue;
   1388         float blurAndSpread = shadow.blur() + shadow.spread();
   1389 
   1390         top = min<LayoutUnit>(top, shadow.y() - blurAndSpread);
   1391         bottom = max<LayoutUnit>(bottom, shadow.y() + blurAndSpread);
   1392     }
   1393 }
   1394 
   1395 StyleColor RenderStyle::visitedDependentDecorationStyleColor() const
   1396 {
   1397     bool isVisited = insideLink() == InsideVisitedLink;
   1398 
   1399     StyleColor styleColor = isVisited ? visitedLinkTextDecorationColor() : textDecorationColor();
   1400 
   1401     if (!styleColor.isCurrentColor())
   1402         return styleColor;
   1403 
   1404     if (textStrokeWidth()) {
   1405         // Prefer stroke color if possible, but not if it's fully transparent.
   1406         StyleColor textStrokeStyleColor = isVisited ? visitedLinkTextStrokeColor() : textStrokeColor();
   1407         if (!textStrokeStyleColor.isCurrentColor() && textStrokeStyleColor.color().alpha())
   1408             return textStrokeStyleColor;
   1409     }
   1410 
   1411     return isVisited ? visitedLinkTextFillColor() : textFillColor();
   1412 }
   1413 
   1414 Color RenderStyle::visitedDependentDecorationColor() const
   1415 {
   1416     bool isVisited = insideLink() == InsideVisitedLink;
   1417     return visitedDependentDecorationStyleColor().resolve(isVisited ? visitedLinkColor() : color());
   1418 }
   1419 
   1420 Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
   1421 {
   1422     StyleColor result(StyleColor::currentColor());
   1423     EBorderStyle borderStyle = BNONE;
   1424     switch (colorProperty) {
   1425     case CSSPropertyBackgroundColor:
   1426         result = visitedLink ? visitedLinkBackgroundColor() : backgroundColor();
   1427         break;
   1428     case CSSPropertyBorderLeftColor:
   1429         result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
   1430         borderStyle = borderLeftStyle();
   1431         break;
   1432     case CSSPropertyBorderRightColor:
   1433         result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
   1434         borderStyle = borderRightStyle();
   1435         break;
   1436     case CSSPropertyBorderTopColor:
   1437         result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
   1438         borderStyle = borderTopStyle();
   1439         break;
   1440     case CSSPropertyBorderBottomColor:
   1441         result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
   1442         borderStyle = borderBottomStyle();
   1443         break;
   1444     case CSSPropertyColor:
   1445         result = visitedLink ? visitedLinkColor() : color();
   1446         break;
   1447     case CSSPropertyOutlineColor:
   1448         result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
   1449         break;
   1450     case CSSPropertyWebkitColumnRuleColor:
   1451         result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
   1452         break;
   1453     case CSSPropertyWebkitTextEmphasisColor:
   1454         result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
   1455         break;
   1456     case CSSPropertyWebkitTextFillColor:
   1457         result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
   1458         break;
   1459     case CSSPropertyWebkitTextStrokeColor:
   1460         result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
   1461         break;
   1462     case CSSPropertyFloodColor:
   1463         result = floodColor();
   1464         break;
   1465     case CSSPropertyLightingColor:
   1466         result = lightingColor();
   1467         break;
   1468     case CSSPropertyStopColor:
   1469         result = stopColor();
   1470         break;
   1471     case CSSPropertyWebkitTapHighlightColor:
   1472         result = tapHighlightColor();
   1473         break;
   1474     default:
   1475         ASSERT_NOT_REACHED();
   1476         break;
   1477     }
   1478 
   1479     if (!result.isCurrentColor())
   1480         return result.color();
   1481 
   1482     // FIXME: Treating styled borders with initial color differently causes problems
   1483     // See crbug.com/316559, crbug.com/276231
   1484     if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
   1485         return Color(238, 238, 238);
   1486     return visitedLink ? visitedLinkColor() : color();
   1487 }
   1488 
   1489 Color RenderStyle::visitedDependentColor(int colorProperty) const
   1490 {
   1491     Color unvisitedColor = colorIncludingFallback(colorProperty, false);
   1492     if (insideLink() != InsideVisitedLink)
   1493         return unvisitedColor;
   1494 
   1495     Color visitedColor = colorIncludingFallback(colorProperty, true);
   1496 
   1497     // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
   1498     // assume that if the background color is transparent that it wasn't set. Note that it's weird that
   1499     // we're returning unvisited info for a visited link, but given our restriction that the alpha values
   1500     // have to match, it makes more sense to return the unvisited background color if specified than it
   1501     // does to return black. This behavior matches what Firefox 4 does as well.
   1502     if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent)
   1503         return unvisitedColor;
   1504 
   1505     // Take the alpha from the unvisited color, but get the RGB values from the visited color.
   1506     return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
   1507 }
   1508 
   1509 const BorderValue& RenderStyle::borderBefore() const
   1510 {
   1511     switch (writingMode()) {
   1512     case TopToBottomWritingMode:
   1513         return borderTop();
   1514     case BottomToTopWritingMode:
   1515         return borderBottom();
   1516     case LeftToRightWritingMode:
   1517         return borderLeft();
   1518     case RightToLeftWritingMode:
   1519         return borderRight();
   1520     }
   1521     ASSERT_NOT_REACHED();
   1522     return borderTop();
   1523 }
   1524 
   1525 const BorderValue& RenderStyle::borderAfter() const
   1526 {
   1527     switch (writingMode()) {
   1528     case TopToBottomWritingMode:
   1529         return borderBottom();
   1530     case BottomToTopWritingMode:
   1531         return borderTop();
   1532     case LeftToRightWritingMode:
   1533         return borderRight();
   1534     case RightToLeftWritingMode:
   1535         return borderLeft();
   1536     }
   1537     ASSERT_NOT_REACHED();
   1538     return borderBottom();
   1539 }
   1540 
   1541 const BorderValue& RenderStyle::borderStart() const
   1542 {
   1543     if (isHorizontalWritingMode())
   1544         return isLeftToRightDirection() ? borderLeft() : borderRight();
   1545     return isLeftToRightDirection() ? borderTop() : borderBottom();
   1546 }
   1547 
   1548 const BorderValue& RenderStyle::borderEnd() const
   1549 {
   1550     if (isHorizontalWritingMode())
   1551         return isLeftToRightDirection() ? borderRight() : borderLeft();
   1552     return isLeftToRightDirection() ? borderBottom() : borderTop();
   1553 }
   1554 
   1555 unsigned short RenderStyle::borderBeforeWidth() const
   1556 {
   1557     switch (writingMode()) {
   1558     case TopToBottomWritingMode:
   1559         return borderTopWidth();
   1560     case BottomToTopWritingMode:
   1561         return borderBottomWidth();
   1562     case LeftToRightWritingMode:
   1563         return borderLeftWidth();
   1564     case RightToLeftWritingMode:
   1565         return borderRightWidth();
   1566     }
   1567     ASSERT_NOT_REACHED();
   1568     return borderTopWidth();
   1569 }
   1570 
   1571 unsigned short RenderStyle::borderAfterWidth() const
   1572 {
   1573     switch (writingMode()) {
   1574     case TopToBottomWritingMode:
   1575         return borderBottomWidth();
   1576     case BottomToTopWritingMode:
   1577         return borderTopWidth();
   1578     case LeftToRightWritingMode:
   1579         return borderRightWidth();
   1580     case RightToLeftWritingMode:
   1581         return borderLeftWidth();
   1582     }
   1583     ASSERT_NOT_REACHED();
   1584     return borderBottomWidth();
   1585 }
   1586 
   1587 unsigned short RenderStyle::borderStartWidth() const
   1588 {
   1589     if (isHorizontalWritingMode())
   1590         return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
   1591     return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
   1592 }
   1593 
   1594 unsigned short RenderStyle::borderEndWidth() const
   1595 {
   1596     if (isHorizontalWritingMode())
   1597         return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
   1598     return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
   1599 }
   1600 
   1601 void RenderStyle::setMarginStart(const Length& margin)
   1602 {
   1603     if (isHorizontalWritingMode()) {
   1604         if (isLeftToRightDirection())
   1605             setMarginLeft(margin);
   1606         else
   1607             setMarginRight(margin);
   1608     } else {
   1609         if (isLeftToRightDirection())
   1610             setMarginTop(margin);
   1611         else
   1612             setMarginBottom(margin);
   1613     }
   1614 }
   1615 
   1616 void RenderStyle::setMarginEnd(const Length& margin)
   1617 {
   1618     if (isHorizontalWritingMode()) {
   1619         if (isLeftToRightDirection())
   1620             setMarginRight(margin);
   1621         else
   1622             setMarginLeft(margin);
   1623     } else {
   1624         if (isLeftToRightDirection())
   1625             setMarginBottom(margin);
   1626         else
   1627             setMarginTop(margin);
   1628     }
   1629 }
   1630 
   1631 TextEmphasisMark RenderStyle::textEmphasisMark() const
   1632 {
   1633     TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark);
   1634     if (mark != TextEmphasisMarkAuto)
   1635         return mark;
   1636 
   1637     if (isHorizontalWritingMode())
   1638         return TextEmphasisMarkDot;
   1639 
   1640     return TextEmphasisMarkSesame;
   1641 }
   1642 
   1643 Color RenderStyle::initialTapHighlightColor()
   1644 {
   1645     return RenderTheme::tapHighlightColor();
   1646 }
   1647 
   1648 LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
   1649 {
   1650     return LayoutBoxExtent(NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()),
   1651                            NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()),
   1652                            NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth()),
   1653                            NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()));
   1654 }
   1655 
   1656 void RenderStyle::setBorderImageSource(PassRefPtr<StyleImage> image)
   1657 {
   1658     if (surround->border.m_image.image() == image.get())
   1659         return;
   1660     surround.access()->border.m_image.setImage(image);
   1661 }
   1662 
   1663 void RenderStyle::setBorderImageSlices(const LengthBox& slices)
   1664 {
   1665     if (surround->border.m_image.imageSlices() == slices)
   1666         return;
   1667     surround.access()->border.m_image.setImageSlices(slices);
   1668 }
   1669 
   1670 void RenderStyle::setBorderImageWidth(const BorderImageLengthBox& slices)
   1671 {
   1672     if (surround->border.m_image.borderSlices() == slices)
   1673         return;
   1674     surround.access()->border.m_image.setBorderSlices(slices);
   1675 }
   1676 
   1677 void RenderStyle::setBorderImageOutset(const BorderImageLengthBox& outset)
   1678 {
   1679     if (surround->border.m_image.outset() == outset)
   1680         return;
   1681     surround.access()->border.m_image.setOutset(outset);
   1682 }
   1683 
   1684 float calcBorderRadiiConstraintScaleFor(const FloatRect& rect, const FloatRoundedRect::Radii& radii)
   1685 {
   1686     // Constrain corner radii using CSS3 rules:
   1687     // http://www.w3.org/TR/css3-background/#the-border-radius
   1688 
   1689     float factor = 1;
   1690     float radiiSum;
   1691 
   1692     // top
   1693     radiiSum = radii.topLeft().width() + radii.topRight().width(); // Casts to avoid integer overflow.
   1694     if (radiiSum > rect.width())
   1695         factor = std::min(rect.width() / radiiSum, factor);
   1696 
   1697     // bottom
   1698     radiiSum = radii.bottomLeft().width() + radii.bottomRight().width();
   1699     if (radiiSum > rect.width())
   1700         factor = std::min(rect.width() / radiiSum, factor);
   1701 
   1702     // left
   1703     radiiSum = radii.topLeft().height() + radii.bottomLeft().height();
   1704     if (radiiSum > rect.height())
   1705         factor = std::min(rect.height() / radiiSum, factor);
   1706 
   1707     // right
   1708     radiiSum = radii.topRight().height() + radii.bottomRight().height();
   1709     if (radiiSum > rect.height())
   1710         factor = std::min(rect.height() / radiiSum, factor);
   1711 
   1712     ASSERT(factor <= 1);
   1713     return factor;
   1714 }
   1715 
   1716 } // namespace WebCore
   1717