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