WebCore/rendering/style/RenderStyle.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
       
     3  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
       
     4  *
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Library General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  * Library General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Library General Public License
       
    16  * along with this library; see the file COPYING.LIB.  If not, write to
       
    17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    18  * Boston, MA 02110-1301, USA.
       
    19  *
       
    20  */
       
    21 
       
    22 #include "config.h"
       
    23 #include "RenderStyle.h"
       
    24 
       
    25 #include "CSSPropertyNames.h"
       
    26 #include "CSSStyleSelector.h"
       
    27 #include "CachedImage.h"
       
    28 #include "CounterContent.h"
       
    29 #include "FontSelector.h"
       
    30 #include "RenderArena.h"
       
    31 #include "RenderObject.h"
       
    32 #include "StyleImage.h"
       
    33 #include <wtf/StdLibExtras.h>
       
    34 #include <algorithm>
       
    35 
       
    36 using namespace std;
       
    37 
       
    38 namespace WebCore {
       
    39 
       
    40 inline RenderStyle* defaultStyle()
       
    41 {
       
    42     static RenderStyle* s_defaultStyle = RenderStyle::createDefaultStyle().releaseRef();
       
    43     return s_defaultStyle;
       
    44 }
       
    45 
       
    46 PassRefPtr<RenderStyle> RenderStyle::create()
       
    47 {
       
    48     return adoptRef(new RenderStyle());
       
    49 }
       
    50 
       
    51 PassRefPtr<RenderStyle> RenderStyle::createDefaultStyle()
       
    52 {
       
    53     return adoptRef(new RenderStyle(true));
       
    54 }
       
    55 
       
    56 PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other)
       
    57 {
       
    58     return adoptRef(new RenderStyle(*other));
       
    59 }
       
    60 
       
    61 ALWAYS_INLINE RenderStyle::RenderStyle()
       
    62     : m_affectedByAttributeSelectors(false)
       
    63     , m_unique(false)
       
    64     , m_affectedByEmpty(false)
       
    65     , m_emptyState(false)
       
    66     , m_childrenAffectedByFirstChildRules(false)
       
    67     , m_childrenAffectedByLastChildRules(false)
       
    68     , m_childrenAffectedByDirectAdjacentRules(false)
       
    69     , m_childrenAffectedByForwardPositionalRules(false)
       
    70     , m_childrenAffectedByBackwardPositionalRules(false)
       
    71     , m_firstChildState(false)
       
    72     , m_lastChildState(false)
       
    73     , m_childIndex(0)
       
    74     , m_box(defaultStyle()->m_box)
       
    75     , visual(defaultStyle()->visual)
       
    76     , m_background(defaultStyle()->m_background)
       
    77     , surround(defaultStyle()->surround)
       
    78     , rareNonInheritedData(defaultStyle()->rareNonInheritedData)
       
    79     , rareInheritedData(defaultStyle()->rareInheritedData)
       
    80     , inherited(defaultStyle()->inherited)
       
    81 #if ENABLE(SVG)
       
    82     , m_svgStyle(defaultStyle()->m_svgStyle)
       
    83 #endif
       
    84 {
       
    85     setBitDefaults(); // Would it be faster to copy this from the default style?
       
    86 }
       
    87 
       
    88 ALWAYS_INLINE RenderStyle::RenderStyle(bool)
       
    89     : m_affectedByAttributeSelectors(false)
       
    90     , m_unique(false)
       
    91     , m_affectedByEmpty(false)
       
    92     , m_emptyState(false)
       
    93     , m_childrenAffectedByFirstChildRules(false)
       
    94     , m_childrenAffectedByLastChildRules(false)
       
    95     , m_childrenAffectedByDirectAdjacentRules(false)
       
    96     , m_childrenAffectedByForwardPositionalRules(false)
       
    97     , m_childrenAffectedByBackwardPositionalRules(false)
       
    98     , m_firstChildState(false)
       
    99     , m_lastChildState(false)
       
   100     , m_childIndex(0)
       
   101 {
       
   102     setBitDefaults();
       
   103 
       
   104     m_box.init();
       
   105     visual.init();
       
   106     m_background.init();
       
   107     surround.init();
       
   108     rareNonInheritedData.init();
       
   109     rareNonInheritedData.access()->flexibleBox.init();
       
   110     rareNonInheritedData.access()->marquee.init();
       
   111     rareNonInheritedData.access()->m_multiCol.init();
       
   112     rareNonInheritedData.access()->m_transform.init();
       
   113     rareInheritedData.init();
       
   114     inherited.init();
       
   115 
       
   116 #if ENABLE(SVG)
       
   117     m_svgStyle.init();
       
   118 #endif
       
   119 }
       
   120 
       
   121 ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o)
       
   122     : RefCounted<RenderStyle>()
       
   123     , m_affectedByAttributeSelectors(false)
       
   124     , m_unique(false)
       
   125     , m_affectedByEmpty(false)
       
   126     , m_emptyState(false)
       
   127     , m_childrenAffectedByFirstChildRules(false)
       
   128     , m_childrenAffectedByLastChildRules(false)
       
   129     , m_childrenAffectedByDirectAdjacentRules(false)
       
   130     , m_childrenAffectedByForwardPositionalRules(false)
       
   131     , m_childrenAffectedByBackwardPositionalRules(false)
       
   132     , m_firstChildState(false)
       
   133     , m_lastChildState(false)
       
   134     , m_childIndex(0)
       
   135     , m_box(o.m_box)
       
   136     , visual(o.visual)
       
   137     , m_background(o.m_background)
       
   138     , surround(o.surround)
       
   139     , rareNonInheritedData(o.rareNonInheritedData)
       
   140     , rareInheritedData(o.rareInheritedData)
       
   141     , inherited(o.inherited)
       
   142 #if ENABLE(SVG)
       
   143     , m_svgStyle(o.m_svgStyle)
       
   144 #endif
       
   145     , inherited_flags(o.inherited_flags)
       
   146     , noninherited_flags(o.noninherited_flags)
       
   147 {
       
   148 }
       
   149 
       
   150 void RenderStyle::inheritFrom(const RenderStyle* inheritParent)
       
   151 {
       
   152     rareInheritedData = inheritParent->rareInheritedData;
       
   153     inherited = inheritParent->inherited;
       
   154     inherited_flags = inheritParent->inherited_flags;
       
   155 #if ENABLE(SVG)
       
   156     if (m_svgStyle != inheritParent->m_svgStyle)
       
   157         m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
       
   158 #endif
       
   159 }
       
   160 
       
   161 RenderStyle::~RenderStyle()
       
   162 {
       
   163 }
       
   164 
       
   165 bool RenderStyle::operator==(const RenderStyle& o) const
       
   166 {
       
   167     // compare everything except the pseudoStyle pointer
       
   168     return inherited_flags == o.inherited_flags &&
       
   169             noninherited_flags == o.noninherited_flags &&
       
   170             m_box == o.m_box &&
       
   171             visual == o.visual &&
       
   172             m_background == o.m_background &&
       
   173             surround == o.surround &&
       
   174             rareNonInheritedData == o.rareNonInheritedData &&
       
   175             rareInheritedData == o.rareInheritedData &&
       
   176             inherited == o.inherited
       
   177 #if ENABLE(SVG)
       
   178             && m_svgStyle == o.m_svgStyle
       
   179 #endif
       
   180             ;
       
   181 }
       
   182 
       
   183 bool RenderStyle::isStyleAvailable() const
       
   184 {
       
   185     return this != CSSStyleSelector::styleNotYetAvailable();
       
   186 }
       
   187 
       
   188 static inline int pseudoBit(PseudoId pseudo)
       
   189 {
       
   190     return 1 << (pseudo - 1);
       
   191 }
       
   192 
       
   193 bool RenderStyle::hasAnyPublicPseudoStyles() const
       
   194 {
       
   195     return PUBLIC_PSEUDOID_MASK & noninherited_flags._pseudoBits;
       
   196 }
       
   197 
       
   198 bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
       
   199 {
       
   200     ASSERT(pseudo > NOPSEUDO);
       
   201     ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
       
   202     return pseudoBit(pseudo) & noninherited_flags._pseudoBits;
       
   203 }
       
   204 
       
   205 void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
       
   206 {
       
   207     ASSERT(pseudo > NOPSEUDO);
       
   208     ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
       
   209     noninherited_flags._pseudoBits |= pseudoBit(pseudo);
       
   210 }
       
   211 
       
   212 RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
       
   213 {
       
   214     ASSERT(styleType() != VISITED_LINK);
       
   215 
       
   216     if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
       
   217         return 0;
       
   218 
       
   219     if (styleType() != NOPSEUDO) {
       
   220         if (pid == VISITED_LINK)
       
   221             return m_cachedPseudoStyles->at(0)->styleType() == VISITED_LINK ? m_cachedPseudoStyles->at(0).get() : 0;
       
   222         return 0;
       
   223     }
       
   224 
       
   225     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
       
   226         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
       
   227         if (pseudoStyle->styleType() == pid)
       
   228             return pseudoStyle;
       
   229     }
       
   230 
       
   231     return 0;
       
   232 }
       
   233 
       
   234 RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
       
   235 {
       
   236     if (!pseudo)
       
   237         return 0;
       
   238     
       
   239     RenderStyle* result = pseudo.get();
       
   240 
       
   241     if (!m_cachedPseudoStyles)
       
   242         m_cachedPseudoStyles.set(new PseudoStyleCache);
       
   243 
       
   244     m_cachedPseudoStyles->append(pseudo);
       
   245 
       
   246     return result;
       
   247 }
       
   248 
       
   249 bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
       
   250 {
       
   251     return inherited_flags != other->inherited_flags ||
       
   252            inherited != other->inherited ||
       
   253 #if ENABLE(SVG)
       
   254            m_svgStyle->inheritedNotEqual(other->m_svgStyle.get()) ||
       
   255 #endif
       
   256            rareInheritedData != other->rareInheritedData;
       
   257 }
       
   258 
       
   259 static bool positionedObjectMoved(const LengthBox& a, const LengthBox& b)
       
   260 {
       
   261     // If any unit types are different, then we can't guarantee
       
   262     // that this was just a movement.
       
   263     if (a.left().type() != b.left().type() ||
       
   264         a.right().type() != b.right().type() ||
       
   265         a.top().type() != b.top().type() ||
       
   266         a.bottom().type() != b.bottom().type())
       
   267         return false;
       
   268 
       
   269     // Only one unit can be non-auto in the horizontal direction and
       
   270     // in the vertical direction.  Otherwise the adjustment of values
       
   271     // is changing the size of the box.
       
   272     if (!a.left().isIntrinsicOrAuto() && !a.right().isIntrinsicOrAuto())
       
   273         return false;
       
   274     if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
       
   275         return false;
       
   276 
       
   277     // One of the units is fixed or percent in both directions and stayed
       
   278     // that way in the new style.  Therefore all we are doing is moving.
       
   279     return true;
       
   280 }
       
   281 
       
   282 /*
       
   283   compares two styles. The result gives an idea of the action that
       
   284   needs to be taken when replacing the old style with a new one.
       
   285 
       
   286   CbLayout: The containing block of the object needs a relayout.
       
   287   Layout: the RenderObject needs a relayout after the style change
       
   288   Visible: The change is visible, but no relayout is needed
       
   289   NonVisible: The object does need neither repaint nor relayout after
       
   290        the change.
       
   291 
       
   292   ### TODO:
       
   293   A lot can be optimised here based on the display type, lots of
       
   294   optimisations are unimplemented, and currently result in the
       
   295   worst case result causing a relayout of the containing block.
       
   296 */
       
   297 StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
       
   298 {
       
   299     changedContextSensitiveProperties = ContextSensitivePropertyNone;
       
   300 
       
   301 #if ENABLE(SVG)
       
   302     if (m_svgStyle != other->m_svgStyle)
       
   303         return m_svgStyle->diff(other->m_svgStyle.get());
       
   304 #endif
       
   305 
       
   306     if (m_box->width() != other->m_box->width() ||
       
   307         m_box->minWidth() != other->m_box->minWidth() ||
       
   308         m_box->maxWidth() != other->m_box->maxWidth() ||
       
   309         m_box->height() != other->m_box->height() ||
       
   310         m_box->minHeight() != other->m_box->minHeight() ||
       
   311         m_box->maxHeight() != other->m_box->maxHeight())
       
   312         return StyleDifferenceLayout;
       
   313 
       
   314     if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
       
   315         return StyleDifferenceLayout;
       
   316 
       
   317     if (m_box->boxSizing() != other->m_box->boxSizing())
       
   318         return StyleDifferenceLayout;
       
   319 
       
   320     if (surround->margin != other->surround->margin)
       
   321         return StyleDifferenceLayout;
       
   322 
       
   323     if (surround->padding != other->surround->padding)
       
   324         return StyleDifferenceLayout;
       
   325 
       
   326     if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
       
   327         if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance ||
       
   328             rareNonInheritedData->marginTopCollapse != other->rareNonInheritedData->marginTopCollapse ||
       
   329             rareNonInheritedData->marginBottomCollapse != other->rareNonInheritedData->marginBottomCollapse ||
       
   330             rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp ||
       
   331             rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
       
   332             return StyleDifferenceLayout;
       
   333 
       
   334         if (rareNonInheritedData->flexibleBox.get() != other->rareNonInheritedData->flexibleBox.get() &&
       
   335             *rareNonInheritedData->flexibleBox.get() != *other->rareNonInheritedData->flexibleBox.get())
       
   336             return StyleDifferenceLayout;
       
   337 
       
   338         // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
       
   339         if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
       
   340             return StyleDifferenceLayout;
       
   341 
       
   342         if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
       
   343             return StyleDifferenceLayout;
       
   344 
       
   345         if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get() &&
       
   346             *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
       
   347             return StyleDifferenceLayout;
       
   348 
       
   349         if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get() &&
       
   350             *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
       
   351 #if USE(ACCELERATED_COMPOSITING)
       
   352             changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
       
   353             // Don't return; keep looking for another change
       
   354 #else
       
   355             return StyleDifferenceLayout;
       
   356 #endif
       
   357         }
       
   358 
       
   359 #if !USE(ACCELERATED_COMPOSITING)
       
   360         if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
       
   361             if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D ||
       
   362                 rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility ||
       
   363                 rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective ||
       
   364                 rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX ||
       
   365                 rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
       
   366                 return StyleDifferenceLayout;
       
   367         }
       
   368 #endif
       
   369 
       
   370 #if ENABLE(DASHBOARD_SUPPORT)
       
   371         // If regions change, trigger a relayout to re-calc regions.
       
   372         if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions)
       
   373             return StyleDifferenceLayout;
       
   374 #endif
       
   375     }
       
   376 
       
   377     if (rareInheritedData.get() != other->rareInheritedData.get()) {
       
   378         if (rareInheritedData->highlight != other->rareInheritedData->highlight ||
       
   379             rareInheritedData->indent != other->rareInheritedData->indent ||
       
   380             rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom ||
       
   381             rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust ||
       
   382             rareInheritedData->wordBreak != other->rareInheritedData->wordBreak ||
       
   383             rareInheritedData->wordWrap != other->rareInheritedData->wordWrap ||
       
   384             rareInheritedData->nbspMode != other->rareInheritedData->nbspMode ||
       
   385             rareInheritedData->khtmlLineBreak != other->rareInheritedData->khtmlLineBreak ||
       
   386             rareInheritedData->textSecurity != other->rareInheritedData->textSecurity ||
       
   387             rareInheritedData->hyphens != other->rareInheritedData->hyphens ||
       
   388             rareInheritedData->hyphenateCharacter != other->rareInheritedData->hyphenateCharacter)
       
   389             return StyleDifferenceLayout;
       
   390 
       
   391         if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
       
   392             return StyleDifferenceLayout;
       
   393 
       
   394         if (textStrokeWidth() != other->textStrokeWidth())
       
   395             return StyleDifferenceLayout;
       
   396     }
       
   397 
       
   398     if (inherited->line_height != other->inherited->line_height ||
       
   399         inherited->list_style_image != other->inherited->list_style_image ||
       
   400         inherited->font != other->inherited->font ||
       
   401         inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing ||
       
   402         inherited->vertical_border_spacing != other->inherited->vertical_border_spacing ||
       
   403         inherited_flags._box_direction != other->inherited_flags._box_direction ||
       
   404         inherited_flags._visuallyOrdered != other->inherited_flags._visuallyOrdered ||
       
   405         inherited_flags._htmlHacks != other->inherited_flags._htmlHacks ||
       
   406         noninherited_flags._position != other->noninherited_flags._position ||
       
   407         noninherited_flags._floating != other->noninherited_flags._floating ||
       
   408         noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
       
   409         return StyleDifferenceLayout;
       
   410 
       
   411 
       
   412     if (((int)noninherited_flags._effectiveDisplay) >= TABLE) {
       
   413         if (inherited_flags._border_collapse != other->inherited_flags._border_collapse ||
       
   414             inherited_flags._empty_cells != other->inherited_flags._empty_cells ||
       
   415             inherited_flags._caption_side != other->inherited_flags._caption_side ||
       
   416             noninherited_flags._table_layout != other->noninherited_flags._table_layout)
       
   417             return StyleDifferenceLayout;
       
   418 
       
   419         // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
       
   420         // does not, so these style differences can be width differences.
       
   421         if (inherited_flags._border_collapse &&
       
   422             ((borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE) ||
       
   423              (borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN) ||
       
   424              (borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE) ||
       
   425              (borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN) ||
       
   426              (borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE) ||
       
   427              (borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN) ||
       
   428              (borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE) ||
       
   429              (borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN)))
       
   430             return StyleDifferenceLayout;
       
   431     }
       
   432 
       
   433     if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
       
   434         if (inherited_flags._list_style_type != other->inherited_flags._list_style_type ||
       
   435             inherited_flags._list_style_position != other->inherited_flags._list_style_position)
       
   436             return StyleDifferenceLayout;
       
   437     }
       
   438 
       
   439     if (inherited_flags._text_align != other->inherited_flags._text_align ||
       
   440         inherited_flags._text_transform != other->inherited_flags._text_transform ||
       
   441         inherited_flags._direction != other->inherited_flags._direction ||
       
   442         inherited_flags._white_space != other->inherited_flags._white_space ||
       
   443         noninherited_flags._clear != other->noninherited_flags._clear)
       
   444         return StyleDifferenceLayout;
       
   445 
       
   446     // Overflow returns a layout hint.
       
   447     if (noninherited_flags._overflowX != other->noninherited_flags._overflowX ||
       
   448         noninherited_flags._overflowY != other->noninherited_flags._overflowY)
       
   449         return StyleDifferenceLayout;
       
   450 
       
   451     // If our border widths change, then we need to layout.  Other changes to borders
       
   452     // only necessitate a repaint.
       
   453     if (borderLeftWidth() != other->borderLeftWidth() ||
       
   454         borderTopWidth() != other->borderTopWidth() ||
       
   455         borderBottomWidth() != other->borderBottomWidth() ||
       
   456         borderRightWidth() != other->borderRightWidth())
       
   457         return StyleDifferenceLayout;
       
   458 
       
   459     // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
       
   460     const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
       
   461     const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
       
   462     if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
       
   463         return StyleDifferenceLayout;
       
   464     if (rareNonInheritedData->m_counterIncrement != other->rareNonInheritedData->m_counterIncrement ||
       
   465         rareNonInheritedData->m_counterReset != other->rareNonInheritedData->m_counterReset)
       
   466         return StyleDifferenceLayout;
       
   467 
       
   468     if ((rareNonInheritedData->opacity == 1 && other->rareNonInheritedData->opacity < 1) ||
       
   469         (rareNonInheritedData->opacity < 1 && other->rareNonInheritedData->opacity == 1)) {
       
   470         // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
       
   471         return StyleDifferenceLayout;
       
   472     }
       
   473 
       
   474     // Make sure these left/top/right/bottom checks stay below all layout checks and above
       
   475     // all visible checks.
       
   476     if (position() != StaticPosition) {
       
   477         if (surround->offset != other->surround->offset) {
       
   478              // Optimize for the case where a positioned layer is moving but not changing size.
       
   479             if (position() == AbsolutePosition && positionedObjectMoved(surround->offset, other->surround->offset))
       
   480                 return StyleDifferenceLayoutPositionedMovementOnly;
       
   481 
       
   482             // FIXME: We will need to do a bit of work in RenderObject/Box::setStyle before we
       
   483             // can stop doing a layout when relative positioned objects move.  In particular, we'll need
       
   484             // to update scrolling positions and figure out how to do a repaint properly of the updated layer.
       
   485             //if (other->position() == RelativePosition)
       
   486             //    return RepaintLayer;
       
   487             //else
       
   488                 return StyleDifferenceLayout;
       
   489         } else if (m_box->zIndex() != other->m_box->zIndex() || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex() ||
       
   490                  visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip)
       
   491             return StyleDifferenceRepaintLayer;
       
   492     }
       
   493 
       
   494     if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
       
   495 #if USE(ACCELERATED_COMPOSITING)
       
   496         changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
       
   497         // Don't return; keep looking for another change.
       
   498 #else
       
   499         return StyleDifferenceRepaintLayer;
       
   500 #endif
       
   501     }
       
   502 
       
   503     if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask ||
       
   504         rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
       
   505         return StyleDifferenceRepaintLayer;
       
   506 
       
   507     if (inherited->color != other->inherited->color ||
       
   508         inherited_flags._visibility != other->inherited_flags._visibility ||
       
   509         inherited_flags._text_decorations != other->inherited_flags._text_decorations ||
       
   510         inherited_flags._force_backgrounds_to_white != other->inherited_flags._force_backgrounds_to_white ||
       
   511         inherited_flags._insideLink != other->inherited_flags._insideLink ||
       
   512         surround->border != other->surround->border ||
       
   513         *m_background.get() != *other->m_background.get() ||
       
   514         visual->textDecoration != other->visual->textDecoration ||
       
   515         rareInheritedData->userModify != other->rareInheritedData->userModify ||
       
   516         rareInheritedData->userSelect != other->rareInheritedData->userSelect ||
       
   517         rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag ||
       
   518         rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit ||
       
   519         rareInheritedData->textFillColor != other->rareInheritedData->textFillColor ||
       
   520         rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor)
       
   521         return StyleDifferenceRepaint;
       
   522 
       
   523 #if USE(ACCELERATED_COMPOSITING)
       
   524     if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
       
   525         if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D ||
       
   526             rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility ||
       
   527             rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective ||
       
   528             rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX ||
       
   529             rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
       
   530             return StyleDifferenceRecompositeLayer;
       
   531     }
       
   532 #endif
       
   533 
       
   534     // Cursors are not checked, since they will be set appropriately in response to mouse events,
       
   535     // so they don't need to cause any repaint or layout.
       
   536 
       
   537     // 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
       
   538     // the resulting transition properly.
       
   539     return StyleDifferenceEqual;
       
   540 }
       
   541 
       
   542 void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
       
   543 {
       
   544     StyleVisualData* data = visual.access();
       
   545     data->clip.m_top = top;
       
   546     data->clip.m_right = right;
       
   547     data->clip.m_bottom = bottom;
       
   548     data->clip.m_left = left;
       
   549 }
       
   550 
       
   551 void RenderStyle::addCursor(CachedImage* image, const IntPoint& hotSpot)
       
   552 {
       
   553     if (!rareInheritedData.access()->cursorData)
       
   554         rareInheritedData.access()->cursorData = CursorList::create();
       
   555     rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
       
   556 }
       
   557 
       
   558 void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
       
   559 {
       
   560     rareInheritedData.access()->cursorData = other;
       
   561 }
       
   562 
       
   563 void RenderStyle::clearCursorList()
       
   564 {
       
   565     if (rareInheritedData->cursorData)
       
   566         rareInheritedData.access()->cursorData = 0;
       
   567 }
       
   568 
       
   569 void RenderStyle::clearContent()
       
   570 {
       
   571     if (rareNonInheritedData->m_content)
       
   572         rareNonInheritedData->m_content->clear();
       
   573 }
       
   574 
       
   575 void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
       
   576 {
       
   577     if (!image)
       
   578         return; // The object is null. Nothing to do. Just bail.
       
   579 
       
   580     OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
       
   581     ContentData* lastContent = content.get();
       
   582     while (lastContent && lastContent->next())
       
   583         lastContent = lastContent->next();
       
   584 
       
   585     bool reuseContent = !add;
       
   586     ContentData* newContentData;
       
   587     if (reuseContent && content) {
       
   588         content->clear();
       
   589         newContentData = content.leakPtr();
       
   590     } else
       
   591         newContentData = new ContentData;
       
   592 
       
   593     if (lastContent && !reuseContent)
       
   594         lastContent->setNext(newContentData);
       
   595     else
       
   596         content.set(newContentData);
       
   597 
       
   598     newContentData->setImage(image);
       
   599 }
       
   600 
       
   601 void RenderStyle::setContent(PassRefPtr<StringImpl> s, bool add)
       
   602 {
       
   603     if (!s)
       
   604         return; // The string is null. Nothing to do. Just bail.
       
   605 
       
   606     OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
       
   607     ContentData* lastContent = content.get();
       
   608     while (lastContent && lastContent->next())
       
   609         lastContent = lastContent->next();
       
   610 
       
   611     bool reuseContent = !add;
       
   612     if (add && lastContent) {
       
   613         if (lastContent->isText()) {
       
   614             // We can augment the existing string and share this ContentData node.
       
   615             String newStr = lastContent->text();
       
   616             newStr.append(s.get());
       
   617             lastContent->setText(newStr.impl());
       
   618             return;
       
   619         }
       
   620     }
       
   621 
       
   622     ContentData* newContentData = 0;
       
   623     if (reuseContent && content) {
       
   624         content->clear();
       
   625         newContentData = content.leakPtr();
       
   626     } else
       
   627         newContentData = new ContentData;
       
   628 
       
   629     if (lastContent && !reuseContent)
       
   630         lastContent->setNext(newContentData);
       
   631     else
       
   632         content.set(newContentData);
       
   633 
       
   634     newContentData->setText(s);
       
   635 }
       
   636 
       
   637 void RenderStyle::setContent(CounterContent* c, bool add)
       
   638 {
       
   639     if (!c)
       
   640         return;
       
   641 
       
   642     OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
       
   643     ContentData* lastContent = content.get();
       
   644     while (lastContent && lastContent->next())
       
   645         lastContent = lastContent->next();
       
   646 
       
   647     bool reuseContent = !add;
       
   648     ContentData* newContentData = 0;
       
   649     if (reuseContent && content) {
       
   650         content->clear();
       
   651         newContentData = content.leakPtr();
       
   652     } else
       
   653         newContentData = new ContentData;
       
   654 
       
   655     if (lastContent && !reuseContent)
       
   656         lastContent->setNext(newContentData);
       
   657     else
       
   658         content.set(newContentData);
       
   659 
       
   660     newContentData->setCounter(c);
       
   661 }
       
   662 
       
   663 void RenderStyle::applyTransform(TransformationMatrix& transform, const IntSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const
       
   664 {
       
   665     // transform-origin brackets the transform with translate operations.
       
   666     // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
       
   667     // in that case.
       
   668     bool applyTransformOrigin = false;
       
   669     unsigned s = rareNonInheritedData->m_transform->m_operations.operations().size();
       
   670     unsigned i;
       
   671     if (applyOrigin == IncludeTransformOrigin) {
       
   672         for (i = 0; i < s; i++) {
       
   673             TransformOperation::OperationType type = rareNonInheritedData->m_transform->m_operations.operations()[i]->getOperationType();
       
   674             if (type != TransformOperation::TRANSLATE_X &&
       
   675                     type != TransformOperation::TRANSLATE_Y &&
       
   676                     type != TransformOperation::TRANSLATE && 
       
   677                     type != TransformOperation::TRANSLATE_Z && 
       
   678                     type != TransformOperation::TRANSLATE_3D
       
   679                     ) {
       
   680                 applyTransformOrigin = true;
       
   681                 break;
       
   682             }
       
   683         }
       
   684     }
       
   685 
       
   686     if (applyTransformOrigin) {
       
   687         transform.translate3d(transformOriginX().calcFloatValue(borderBoxSize.width()), transformOriginY().calcFloatValue(borderBoxSize.height()), transformOriginZ());
       
   688     }
       
   689 
       
   690     for (i = 0; i < s; i++)
       
   691         rareNonInheritedData->m_transform->m_operations.operations()[i]->apply(transform, borderBoxSize);
       
   692 
       
   693     if (applyTransformOrigin) {
       
   694         transform.translate3d(-transformOriginX().calcFloatValue(borderBoxSize.width()), -transformOriginY().calcFloatValue(borderBoxSize.height()), -transformOriginZ());
       
   695     }
       
   696 }
       
   697 
       
   698 #if ENABLE(XBL)
       
   699 void RenderStyle::addBindingURI(StringImpl* uri)
       
   700 {
       
   701     BindingURI* binding = new BindingURI(uri);
       
   702     if (!bindingURIs())
       
   703         SET_VAR(rareNonInheritedData, bindingURI, binding)
       
   704     else
       
   705         for (BindingURI* b = bindingURIs(); b; b = b->next()) {
       
   706             if (!b->next())
       
   707                 b->setNext(binding);
       
   708         }
       
   709 }
       
   710 #endif
       
   711 
       
   712 void RenderStyle::setTextShadow(ShadowData* val, bool add)
       
   713 {
       
   714     ASSERT(!val || (!val->spread() && val->style() == Normal));
       
   715 
       
   716     StyleRareInheritedData* rareData = rareInheritedData.access();
       
   717     if (!add) {
       
   718         delete rareData->textShadow;
       
   719         rareData->textShadow = val;
       
   720         return;
       
   721     }
       
   722 
       
   723     val->setNext(rareData->textShadow);
       
   724     rareData->textShadow = val;
       
   725 }
       
   726 
       
   727 void RenderStyle::setBoxShadow(ShadowData* shadowData, bool add)
       
   728 {
       
   729     StyleRareNonInheritedData* rareData = rareNonInheritedData.access();
       
   730     if (!add) {
       
   731         rareData->m_boxShadow.set(shadowData);
       
   732         return;
       
   733     }
       
   734 
       
   735     shadowData->setNext(rareData->m_boxShadow.leakPtr());
       
   736     rareData->m_boxShadow.set(shadowData);
       
   737 }
       
   738 
       
   739 static void constrainCornerRadiiForRect(const IntRect& r, IntSize& topLeft, IntSize& topRight, IntSize& bottomLeft, IntSize& bottomRight)
       
   740 {
       
   741     // Constrain corner radii using CSS3 rules:
       
   742     // http://www.w3.org/TR/css3-background/#the-border-radius
       
   743     
       
   744     float factor = 1;
       
   745     unsigned radiiSum;
       
   746 
       
   747     // top
       
   748     radiiSum = static_cast<unsigned>(topLeft.width()) + static_cast<unsigned>(topRight.width()); // Casts to avoid integer overflow.
       
   749     if (radiiSum > static_cast<unsigned>(r.width()))
       
   750         factor = min(static_cast<float>(r.width()) / radiiSum, factor);
       
   751 
       
   752     // bottom
       
   753     radiiSum = static_cast<unsigned>(bottomLeft.width()) + static_cast<unsigned>(bottomRight.width());
       
   754     if (radiiSum > static_cast<unsigned>(r.width()))
       
   755         factor = min(static_cast<float>(r.width()) / radiiSum, factor);
       
   756     
       
   757     // left
       
   758     radiiSum = static_cast<unsigned>(topLeft.height()) + static_cast<unsigned>(bottomLeft.height());
       
   759     if (radiiSum > static_cast<unsigned>(r.height()))
       
   760         factor = min(static_cast<float>(r.height()) / radiiSum, factor);
       
   761     
       
   762     // right
       
   763     radiiSum = static_cast<unsigned>(topRight.height()) + static_cast<unsigned>(bottomRight.height());
       
   764     if (radiiSum > static_cast<unsigned>(r.height()))
       
   765         factor = min(static_cast<float>(r.height()) / radiiSum, factor);
       
   766     
       
   767     // Scale all radii by f if necessary.
       
   768     if (factor < 1) {
       
   769         // If either radius on a corner becomes zero, reset both radii on that corner.
       
   770         topLeft.scale(factor);
       
   771         if (!topLeft.width() || !topLeft.height())
       
   772             topLeft = IntSize();
       
   773         topRight.scale(factor);
       
   774         if (!topRight.width() || !topRight.height())
       
   775             topRight = IntSize();
       
   776         bottomLeft.scale(factor);
       
   777         if (!bottomLeft.width() || !bottomLeft.height())
       
   778             bottomLeft = IntSize();
       
   779         bottomRight.scale(factor);
       
   780         if (!bottomRight.width() || !bottomRight.height())
       
   781             bottomRight = IntSize();
       
   782     }
       
   783 }
       
   784 
       
   785 void RenderStyle::getBorderRadiiForRect(const IntRect& r, IntSize& topLeft, IntSize& topRight, IntSize& bottomLeft, IntSize& bottomRight) const
       
   786 {
       
   787     topLeft = surround->border.topLeft();
       
   788     topRight = surround->border.topRight();
       
   789     
       
   790     bottomLeft = surround->border.bottomLeft();
       
   791     bottomRight = surround->border.bottomRight();
       
   792 
       
   793     constrainCornerRadiiForRect(r, topLeft, topRight, bottomLeft, bottomRight);
       
   794 }
       
   795 
       
   796 void RenderStyle::getInnerBorderRadiiForRectWithBorderWidths(const IntRect& innerRect, unsigned short topWidth, unsigned short bottomWidth, unsigned short leftWidth, unsigned short rightWidth, IntSize& innerTopLeft, IntSize& innerTopRight, IntSize& innerBottomLeft, IntSize& innerBottomRight) const
       
   797 {
       
   798     innerTopLeft = surround->border.topLeft();
       
   799     innerTopRight = surround->border.topRight();
       
   800     innerBottomLeft = surround->border.bottomLeft();
       
   801     innerBottomRight = surround->border.bottomRight();
       
   802 
       
   803     innerTopLeft.setWidth(max(0, innerTopLeft.width() - leftWidth));
       
   804     innerTopLeft.setHeight(max(0, innerTopLeft.height() - topWidth));
       
   805 
       
   806     innerTopRight.setWidth(max(0, innerTopRight.width() - rightWidth));
       
   807     innerTopRight.setHeight(max(0, innerTopRight.height() - topWidth));
       
   808 
       
   809     innerBottomLeft.setWidth(max(0, innerBottomLeft.width() - leftWidth));
       
   810     innerBottomLeft.setHeight(max(0, innerBottomLeft.height() - bottomWidth));
       
   811 
       
   812     innerBottomRight.setWidth(max(0, innerBottomRight.width() - rightWidth));
       
   813     innerBottomRight.setHeight(max(0, innerBottomRight.height() - bottomWidth));
       
   814 
       
   815     constrainCornerRadiiForRect(innerRect, innerTopLeft, innerTopRight, innerBottomLeft, innerBottomRight);
       
   816 }
       
   817 
       
   818 const CounterDirectiveMap* RenderStyle::counterDirectives() const
       
   819 {
       
   820     return rareNonInheritedData->m_counterDirectives.get();
       
   821 }
       
   822 
       
   823 CounterDirectiveMap& RenderStyle::accessCounterDirectives()
       
   824 {
       
   825     OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterDirectives;
       
   826     if (!map)
       
   827         map.set(new CounterDirectiveMap);
       
   828     return *map.get();
       
   829 }
       
   830 
       
   831 const AtomicString& RenderStyle::hyphenString() const
       
   832 {
       
   833     ASSERT(hyphens() == HyphensAuto);
       
   834 
       
   835     const AtomicString& hyphenateCharacter = rareInheritedData.get()->hyphenateCharacter;
       
   836     if (!hyphenateCharacter.isNull())
       
   837         return hyphenateCharacter;
       
   838 
       
   839     // FIXME: This should depend on locale.
       
   840     DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphen, 1));
       
   841     return hyphenMinusString;
       
   842 }
       
   843 
       
   844 #if ENABLE(DASHBOARD_SUPPORT)
       
   845 const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
       
   846 {
       
   847     DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ());
       
   848     return emptyList;
       
   849 }
       
   850 
       
   851 const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
       
   852 {
       
   853     DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, noneList, ());
       
   854     static bool noneListInitialized = false;
       
   855 
       
   856     if (!noneListInitialized) {
       
   857         StyleDashboardRegion region;
       
   858         region.label = "";
       
   859         region.offset.m_top  = Length();
       
   860         region.offset.m_right = Length();
       
   861         region.offset.m_bottom = Length();
       
   862         region.offset.m_left = Length();
       
   863         region.type = StyleDashboardRegion::None;
       
   864         noneList.append(region);
       
   865         noneListInitialized = true;
       
   866     }
       
   867     return noneList;
       
   868 }
       
   869 #endif
       
   870 
       
   871 void RenderStyle::adjustAnimations()
       
   872 {
       
   873     AnimationList* animationList = rareNonInheritedData->m_animations.get();
       
   874     if (!animationList)
       
   875         return;
       
   876 
       
   877     // Get rid of empty animations and anything beyond them
       
   878     for (size_t i = 0; i < animationList->size(); ++i) {
       
   879         if (animationList->animation(i)->isEmpty()) {
       
   880             animationList->resize(i);
       
   881             break;
       
   882         }
       
   883     }
       
   884 
       
   885     if (animationList->isEmpty()) {
       
   886         clearAnimations();
       
   887         return;
       
   888     }
       
   889 
       
   890     // Repeat patterns into layers that don't have some properties set.
       
   891     animationList->fillUnsetProperties();
       
   892 }
       
   893 
       
   894 void RenderStyle::adjustTransitions()
       
   895 {
       
   896     AnimationList* transitionList = rareNonInheritedData->m_transitions.get();
       
   897     if (!transitionList)
       
   898         return;
       
   899 
       
   900     // Get rid of empty transitions and anything beyond them
       
   901     for (size_t i = 0; i < transitionList->size(); ++i) {
       
   902         if (transitionList->animation(i)->isEmpty()) {
       
   903             transitionList->resize(i);
       
   904             break;
       
   905         }
       
   906     }
       
   907 
       
   908     if (transitionList->isEmpty()) {
       
   909         clearTransitions();
       
   910         return;
       
   911     }
       
   912 
       
   913     // Repeat patterns into layers that don't have some properties set.
       
   914     transitionList->fillUnsetProperties();
       
   915 
       
   916     // Make sure there are no duplicate properties. This is an O(n^2) algorithm
       
   917     // but the lists tend to be very short, so it is probably ok
       
   918     for (size_t i = 0; i < transitionList->size(); ++i) {
       
   919         for (size_t j = i+1; j < transitionList->size(); ++j) {
       
   920             if (transitionList->animation(i)->property() == transitionList->animation(j)->property()) {
       
   921                 // toss i
       
   922                 transitionList->remove(i);
       
   923                 j = i;
       
   924             }
       
   925         }
       
   926     }
       
   927 }
       
   928 
       
   929 AnimationList* RenderStyle::accessAnimations()
       
   930 {
       
   931     if (!rareNonInheritedData.access()->m_animations)
       
   932         rareNonInheritedData.access()->m_animations.set(new AnimationList());
       
   933     return rareNonInheritedData->m_animations.get();
       
   934 }
       
   935 
       
   936 AnimationList* RenderStyle::accessTransitions()
       
   937 {
       
   938     if (!rareNonInheritedData.access()->m_transitions)
       
   939         rareNonInheritedData.access()->m_transitions.set(new AnimationList());
       
   940     return rareNonInheritedData->m_transitions.get();
       
   941 }
       
   942 
       
   943 const Animation* RenderStyle::transitionForProperty(int property) const
       
   944 {
       
   945     if (transitions()) {
       
   946         for (size_t i = 0; i < transitions()->size(); ++i) {
       
   947             const Animation* p = transitions()->animation(i);
       
   948             if (p->property() == cAnimateAll || p->property() == property) {
       
   949                 return p;
       
   950             }
       
   951         }
       
   952     }
       
   953     return 0;
       
   954 }
       
   955 
       
   956 void RenderStyle::setBlendedFontSize(int size)
       
   957 {
       
   958     FontSelector* currentFontSelector = font().fontSelector();
       
   959     FontDescription desc(fontDescription());
       
   960     desc.setSpecifiedSize(size);
       
   961     desc.setComputedSize(size);
       
   962     setFontDescription(desc);
       
   963     font().update(currentFontSelector);
       
   964 }
       
   965 
       
   966 void RenderStyle::getBoxShadowExtent(int &top, int &right, int &bottom, int &left) const
       
   967 {
       
   968     top = 0;
       
   969     right = 0;
       
   970     bottom = 0;
       
   971     left = 0;
       
   972 
       
   973     for (const ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next()) {
       
   974         if (boxShadow->style() == Inset)
       
   975             continue;
       
   976         int blurAndSpread = boxShadow->blur() + boxShadow->spread();
       
   977 
       
   978         top = min(top, boxShadow->y() - blurAndSpread);
       
   979         right = max(right, boxShadow->x() + blurAndSpread);
       
   980         bottom = max(bottom, boxShadow->y() + blurAndSpread);
       
   981         left = min(left, boxShadow->x() - blurAndSpread);
       
   982     }
       
   983 }
       
   984 
       
   985 void RenderStyle::getBoxShadowHorizontalExtent(int &left, int &right) const
       
   986 {
       
   987     left = 0;
       
   988     right = 0;
       
   989 
       
   990     for (const ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next()) {
       
   991         if (boxShadow->style() == Inset)
       
   992             continue;
       
   993         int blurAndSpread = boxShadow->blur() + boxShadow->spread();
       
   994 
       
   995         left = min(left, boxShadow->x() - blurAndSpread);
       
   996         right = max(right, boxShadow->x() + blurAndSpread);
       
   997     }
       
   998 }
       
   999 
       
  1000 void RenderStyle::getBoxShadowVerticalExtent(int &top, int &bottom) const
       
  1001 {
       
  1002     top = 0;
       
  1003     bottom = 0;
       
  1004 
       
  1005     for (const ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next()) {
       
  1006         if (boxShadow->style() == Inset)
       
  1007             continue;
       
  1008         int blurAndSpread = boxShadow->blur() + boxShadow->spread();
       
  1009 
       
  1010         top = min(top, boxShadow->y() - blurAndSpread);
       
  1011         bottom = max(bottom, boxShadow->y() + blurAndSpread);
       
  1012     }
       
  1013 }
       
  1014 
       
  1015 static EBorderStyle borderStyleForColorProperty(const RenderStyle* style, int colorProperty)
       
  1016 {
       
  1017     EBorderStyle borderStyle;
       
  1018     switch (colorProperty) {
       
  1019     case CSSPropertyBorderLeftColor:
       
  1020         borderStyle = style->borderLeftStyle();
       
  1021         break;
       
  1022     case CSSPropertyBorderRightColor:
       
  1023         borderStyle = style->borderRightStyle();
       
  1024         break;
       
  1025     case CSSPropertyBorderTopColor:
       
  1026         borderStyle = style->borderTopStyle();
       
  1027         break;
       
  1028     case CSSPropertyBorderBottomColor:
       
  1029         borderStyle = style->borderBottomStyle();
       
  1030         break;
       
  1031     default:
       
  1032         borderStyle = BNONE;
       
  1033         break;
       
  1034     }
       
  1035     return borderStyle;
       
  1036 }
       
  1037 
       
  1038 const Color RenderStyle::colorIncludingFallback(int colorProperty, EBorderStyle borderStyle) const
       
  1039 {
       
  1040     Color result;
       
  1041     switch (colorProperty) {
       
  1042     case CSSPropertyBackgroundColor:
       
  1043         return backgroundColor(); // Background color doesn't fall back.
       
  1044     case CSSPropertyBorderLeftColor:
       
  1045         result = borderLeftColor();
       
  1046         borderStyle = borderLeftStyle();
       
  1047         break;
       
  1048     case CSSPropertyBorderRightColor:
       
  1049         result = borderRightColor();
       
  1050         borderStyle = borderRightStyle();
       
  1051         break;
       
  1052     case CSSPropertyBorderTopColor:
       
  1053         result = borderTopColor();
       
  1054         borderStyle = borderTopStyle();
       
  1055         break;
       
  1056     case CSSPropertyBorderBottomColor:
       
  1057         result = borderBottomColor();
       
  1058         borderStyle = borderBottomStyle();
       
  1059         break;
       
  1060     case CSSPropertyColor:
       
  1061         result = color();
       
  1062         break;
       
  1063     case CSSPropertyOutlineColor:
       
  1064         result = outlineColor();
       
  1065         break;
       
  1066     case CSSPropertyWebkitColumnRuleColor:
       
  1067         result = columnRuleColor();
       
  1068         break;
       
  1069     case CSSPropertyWebkitTextFillColor:
       
  1070         result = textFillColor();
       
  1071         break;
       
  1072     case CSSPropertyWebkitTextStrokeColor:
       
  1073         result = textStrokeColor();
       
  1074         break;
       
  1075     default:
       
  1076         ASSERT_NOT_REACHED();
       
  1077         break;
       
  1078     }
       
  1079 
       
  1080     if (!result.isValid()) {
       
  1081         if ((colorProperty == CSSPropertyBorderLeftColor || colorProperty == CSSPropertyBorderRightColor
       
  1082             || colorProperty == CSSPropertyBorderTopColor || colorProperty == CSSPropertyBorderBottomColor)
       
  1083             && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
       
  1084             result.setRGB(238, 238, 238);
       
  1085         else
       
  1086             result = color();
       
  1087     }
       
  1088 
       
  1089     return result;
       
  1090 }
       
  1091 
       
  1092 const Color RenderStyle::visitedDependentColor(int colorProperty) const
       
  1093 {
       
  1094     EBorderStyle borderStyle = borderStyleForColorProperty(this, colorProperty);
       
  1095     Color unvisitedColor = colorIncludingFallback(colorProperty, borderStyle);
       
  1096     if (insideLink() != InsideVisitedLink)
       
  1097         return unvisitedColor;
       
  1098 
       
  1099     RenderStyle* visitedStyle = getCachedPseudoStyle(VISITED_LINK);
       
  1100     if (!visitedStyle)
       
  1101         return unvisitedColor;
       
  1102     Color visitedColor = visitedStyle->colorIncludingFallback(colorProperty, borderStyle);
       
  1103 
       
  1104     // Take the alpha from the unvisited color, but get the RGB values from the visited color.
       
  1105     return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
       
  1106 }
       
  1107 
       
  1108 } // namespace WebCore