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