Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: third_party/WebKit/Source/core/style/ComputedStyle.cpp

Issue 2345543002: debugging for crbug.com/646539
Patch Set: 3 TUs, 2 .h Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org) 2 * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. 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. 4 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
5 * 5 *
6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public 7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either 8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version. 9 * version 2 of the License, or (at your option) any later version.
10 * 10 *
11 * This library is distributed in the hope that it will be useful, 11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details. 14 * Library General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU Library General Public License 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 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, 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA. 19 * Boston, MA 02110-1301, USA.
20 * 20 *
21 */ 21 */
22 22
23 #include "core/style/ComputedStyle.h" 23 #include "core/style/ComputedStyle.h"
24 24
25 #include "core/animation/css/CSSAnimationData.h" 25 blink::Color secretColor();
26 #include "core/animation/css/CSSTransitionData.h"
27 #include "core/css/CSSPaintValue.h"
28 #include "core/css/CSSPrimitiveValue.h"
29 #include "core/css/CSSPropertyEquality.h"
30 #include "core/css/resolver/StyleResolver.h"
31 #include "core/layout/LayoutTheme.h"
32 #include "core/layout/TextAutosizer.h"
33 #include "core/style/AppliedTextDecoration.h"
34 #include "core/style/BorderEdge.h"
35 #include "core/style/ComputedStyleConstants.h"
36 #include "core/style/ContentData.h"
37 #include "core/style/CursorData.h"
38 #include "core/style/DataEquivalency.h"
39 #include "core/style/QuotesData.h"
40 #include "core/style/ShadowList.h"
41 #include "core/style/StyleImage.h"
42 #include "core/style/StyleInheritedData.h"
43 #include "core/style/StyleVariableData.h"
44 #include "platform/LengthFunctions.h"
45 #include "platform/RuntimeEnabledFeatures.h"
46 #include "platform/fonts/Font.h"
47 #include "platform/fonts/FontSelector.h"
48 #include "platform/geometry/FloatRoundedRect.h"
49 #include "platform/graphics/GraphicsContext.h"
50 #include "platform/transforms/RotateTransformOperation.h"
51 #include "platform/transforms/ScaleTransformOperation.h"
52 #include "platform/transforms/TranslateTransformOperation.h"
53 #include "wtf/MathExtras.h"
54 #include "wtf/PtrUtil.h"
55 #include "wtf/SaturatedArithmetic.h"
56 #include <algorithm>
57 #include <memory>
58 26
59 namespace blink { 27 namespace blink {
60 28
61 struct SameSizeAsBorderValue { 29 ComputedStyle::ComputedStyle()
62 RGBA32 m_color;
63 unsigned m_width;
64 };
65
66 static_assert(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), "BorderValue should stay small");
67
68 // Since different compilers/architectures pack ComputedStyle differently,
69 // re-create the same structure for an accurate size comparison.
70 struct SameSizeAsComputedStyle : public RefCounted<SameSizeAsComputedStyle> {
71 void* dataRefs[7];
72 void* ownPtrs[1];
73 void* dataRefSvgStyle;
74
75 struct InheritedData {
76 unsigned m_bitfields[2];
77 } m_inheritedData;
78
79 struct NonInheritedData {
80 unsigned m_bitfields[3];
81 } m_nonInheritedData;
82 };
83
84 static_assert(sizeof(ComputedStyle) == sizeof(SameSizeAsComputedStyle), "Compute dStyle should stay small");
85
86 PassRefPtr<ComputedStyle> ComputedStyle::create()
87 {
88 return adoptRef(new ComputedStyle());
89 }
90
91 PassRefPtr<ComputedStyle> ComputedStyle::createInitialStyle()
92 {
93 return adoptRef(new ComputedStyle(InitialStyle));
94 }
95
96 void ComputedStyle::invalidateInitialStyle()
97 {
98 mutableInitialStyle().setTapHighlightColor(initialTapHighlightColor());
99 }
100
101 PassRefPtr<ComputedStyle> ComputedStyle::createAnonymousStyleWithDisplay(const C omputedStyle& parentStyle, EDisplay display)
102 {
103 RefPtr<ComputedStyle> newStyle = ComputedStyle::create();
104 newStyle->inheritFrom(parentStyle);
105 newStyle->inheritUnicodeBidiFrom(parentStyle);
106 newStyle->setDisplay(display);
107 return newStyle;
108 }
109
110 PassRefPtr<ComputedStyle> ComputedStyle::clone(const ComputedStyle& other)
111 {
112 return adoptRef(new ComputedStyle(other));
113 }
114
115 ALWAYS_INLINE ComputedStyle::ComputedStyle()
116 : m_box(initialStyle().m_box)
117 , m_visual(initialStyle().m_visual)
118 , m_background(initialStyle().m_background)
119 , m_surround(initialStyle().m_surround)
120 , m_rareNonInheritedData(initialStyle().m_rareNonInheritedData)
121 , m_rareInheritedData(initialStyle().m_rareInheritedData)
122 , m_styleInheritedData(initialStyle().m_styleInheritedData)
123 , m_svgStyle(initialStyle().m_svgStyle)
124 {
125 setBitDefaults(); // Would it be faster to copy this from the default style?
126 static_assert((sizeof(InheritedData) <= 8), "InheritedData should not grow") ;
127 static_assert((sizeof(NonInheritedData) <= 12), "NonInheritedData should not grow");
128 }
129
130 ALWAYS_INLINE ComputedStyle::ComputedStyle(InitialStyleTag)
131 {
132 setBitDefaults();
133
134 m_box.init();
135 m_visual.init();
136 m_background.init();
137 m_surround.init();
138 m_rareNonInheritedData.init();
139 m_rareNonInheritedData.access()->m_deprecatedFlexibleBox.init();
140 m_rareNonInheritedData.access()->m_flexibleBox.init();
141 m_rareNonInheritedData.access()->m_multiCol.init();
142 m_rareNonInheritedData.access()->m_transform.init();
143 m_rareNonInheritedData.access()->m_willChange.init();
144 m_rareNonInheritedData.access()->m_filter.init();
145 m_rareNonInheritedData.access()->m_backdropFilter.init();
146 m_rareNonInheritedData.access()->m_grid.init();
147 m_rareNonInheritedData.access()->m_gridItem.init();
148 m_rareNonInheritedData.access()->m_scrollSnap.init();
149 m_rareInheritedData.init();
150 m_styleInheritedData.init();
151 m_svgStyle.init();
152 }
153
154 ALWAYS_INLINE ComputedStyle::ComputedStyle(const ComputedStyle& o)
155 : RefCounted<ComputedStyle>()
156 , m_box(o.m_box)
157 , m_visual(o.m_visual)
158 , m_background(o.m_background)
159 , m_surround(o.m_surround)
160 , m_rareNonInheritedData(o.m_rareNonInheritedData)
161 , m_rareInheritedData(o.m_rareInheritedData)
162 , m_styleInheritedData(o.m_styleInheritedData)
163 , m_svgStyle(o.m_svgStyle)
164 , m_inheritedData(o.m_inheritedData)
165 , m_nonInheritedData(o.m_nonInheritedData)
166 { 30 {
167 } 31 }
168 32
169 static StyleRecalcChange diffPseudoStyles(const ComputedStyle& oldStyle, const C omputedStyle& newStyle)
170 {
171 // If the pseudoStyles have changed, we want any StyleRecalcChange that is n ot NoChange
172 // because setStyle will do the right thing with anything else.
173 if (!oldStyle.hasAnyPublicPseudoStyles())
174 return NoChange;
175 for (PseudoId pseudoId = FirstPublicPseudoId; pseudoId < FirstInternalPseudo Id; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
176 if (!oldStyle.hasPseudoStyle(pseudoId))
177 continue;
178 const ComputedStyle* newPseudoStyle = newStyle.getCachedPseudoStyle(pseu doId);
179 if (!newPseudoStyle)
180 return NoInherit;
181 const ComputedStyle* oldPseudoStyle = oldStyle.getCachedPseudoStyle(pseu doId);
182 if (oldPseudoStyle && *oldPseudoStyle != *newPseudoStyle)
183 return NoInherit;
184 }
185 return NoChange;
186 }
187
188 StyleRecalcChange ComputedStyle::stylePropagationDiff(const ComputedStyle* oldSt yle, const ComputedStyle* newStyle)
189 {
190 if ((!oldStyle && newStyle) || (oldStyle && !newStyle))
191 return Reattach;
192
193 if (!oldStyle && !newStyle)
194 return NoChange;
195
196 if (oldStyle->display() != newStyle->display()
197 || oldStyle->hasPseudoStyle(PseudoIdFirstLetter) != newStyle->hasPseudoS tyle(PseudoIdFirstLetter)
198 || !oldStyle->contentDataEquivalent(newStyle)
199 || oldStyle->hasTextCombine() != newStyle->hasTextCombine())
200 return Reattach;
201
202 bool independentEqual = oldStyle->independentInheritedEqual(*newStyle);
203 bool nonIndependentEqual = oldStyle->nonIndependentInheritedEqual(*newStyle) ;
204 if (!independentEqual || !nonIndependentEqual) {
205 if (nonIndependentEqual && !oldStyle->hasExplicitlyInheritedProperties() )
206 return IndependentInherit;
207 return Inherit;
208 }
209
210 if (!oldStyle->loadingCustomFontsEqual(*newStyle)
211 || oldStyle->alignItems() != newStyle->alignItems()
212 || oldStyle->justifyItems() != newStyle->justifyItems())
213 return Inherit;
214
215 if (*oldStyle == *newStyle)
216 return diffPseudoStyles(*oldStyle, *newStyle);
217
218 if (oldStyle->hasExplicitlyInheritedProperties())
219 return Inherit;
220
221 return NoInherit;
222 }
223
224 // TODO(sashab): Generate this function.
225 void ComputedStyle::propagateIndependentInheritedProperties(const ComputedStyle& parentStyle)
226 {
227 if (m_nonInheritedData.m_isPointerEventsInherited)
228 setPointerEvents(parentStyle.pointerEvents());
229 if (m_nonInheritedData.m_isVisibilityInherited)
230 setVisibility(parentStyle.visibility());
231 }
232
233 StyleSelfAlignmentData resolvedSelfAlignment(const StyleSelfAlignmentData& value , ItemPosition normalValueBehavior)
234 {
235 // To avoid needing to copy the RareNonInheritedData, we repurpose the 'auto ' flag to not just mean 'auto' prior to running the StyleAdjuster but also mean 'normal' after running it.
236 if (value.position() == ItemPositionNormal || value.position() == ItemPositi onAuto)
237 return {normalValueBehavior, OverflowAlignmentDefault};
238 return value;
239 }
240
241 StyleSelfAlignmentData ComputedStyle::resolvedAlignItems(ItemPosition normalValu eBehaviour) const
242 {
243 // We will return the behaviour of 'normal' value if needed, which is specif ic of each layout model.
244 return resolvedSelfAlignment(alignItems(), normalValueBehaviour);
245 }
246
247 StyleSelfAlignmentData ComputedStyle::resolvedAlignSelf(ItemPosition normalValue Behaviour, const ComputedStyle* parentStyle) const
248 {
249 // We will return the behaviour of 'normal' value if needed, which is specif ic of each layout model.
250 if (!parentStyle || alignSelfPosition() != ItemPositionAuto)
251 return resolvedSelfAlignment(alignSelf(), normalValueBehaviour);
252
253 // We shouldn't need to resolve any 'auto' value in post-adjusment ComputedS tyle, but some layout models
254 // can generate anonymous boxes that may need 'auto' value resolution during layout.
255 // The 'auto' keyword computes to the parent's align-items computed value.
256 return parentStyle->resolvedAlignItems(normalValueBehaviour);
257 }
258
259 StyleSelfAlignmentData ComputedStyle::resolvedJustifyItems(ItemPosition normalVa lueBehaviour) const
260 {
261 // We will return the behaviour of 'normal' value if needed, which is specif ic of each layout model.
262 return resolvedSelfAlignment(justifyItems(), normalValueBehaviour);
263 }
264
265 StyleSelfAlignmentData ComputedStyle::resolvedJustifySelf(ItemPosition normalVal ueBehaviour, const ComputedStyle* parentStyle) const
266 {
267 // We will return the behaviour of 'normal' value if needed, which is specif ic of each layout model.
268 if (!parentStyle || justifySelfPosition() != ItemPositionAuto)
269 return resolvedSelfAlignment(justifySelf(), normalValueBehaviour);
270
271 // We shouldn't need to resolve any 'auto' value in post-adjusment ComputedS tyle, but some layout models
272 // can generate anonymous boxes that may need 'auto' value resolution during layout.
273 // The auto keyword computes to the parent's justify-items computed value.
274 return parentStyle->resolvedJustifyItems(normalValueBehaviour);
275 }
276
277 static inline ContentPosition resolvedContentAlignmentPosition(const StyleConten tAlignmentData& value, const StyleContentAlignmentData& normalValueBehavior)
278 {
279 return (value.position() == ContentPositionNormal && value.distribution() == ContentDistributionDefault) ? normalValueBehavior.position() : value.position() ;
280 }
281
282 static inline ContentDistributionType resolvedContentAlignmentDistribution(const StyleContentAlignmentData& value, const StyleContentAlignmentData& normalValueB ehavior)
283 {
284 return (value.position() == ContentPositionNormal && value.distribution() == ContentDistributionDefault) ? normalValueBehavior.distribution() : value.distri bution();
285 }
286
287 ContentPosition ComputedStyle::resolvedJustifyContentPosition(const StyleContent AlignmentData& normalValueBehavior) const
288 {
289 return resolvedContentAlignmentPosition(justifyContent(), normalValueBehavio r);
290 }
291
292 ContentDistributionType ComputedStyle::resolvedJustifyContentDistribution(const StyleContentAlignmentData& normalValueBehavior) const
293 {
294 return resolvedContentAlignmentDistribution(justifyContent(), normalValueBeh avior);
295 }
296
297 ContentPosition ComputedStyle::resolvedAlignContentPosition(const StyleContentAl ignmentData& normalValueBehavior) const
298 {
299 return resolvedContentAlignmentPosition(alignContent(), normalValueBehavior) ;
300 }
301
302 ContentDistributionType ComputedStyle::resolvedAlignContentDistribution(const St yleContentAlignmentData& normalValueBehavior) const
303 {
304 return resolvedContentAlignmentDistribution(alignContent(), normalValueBehav ior);
305 }
306
307 void ComputedStyle::inheritFrom(const ComputedStyle& inheritParent, IsAtShadowBo undary isAtShadowBoundary)
308 {
309 if (isAtShadowBoundary == AtShadowBoundary) {
310 // Even if surrounding content is user-editable, shadow DOM should act a s a single unit, and not necessarily be editable
311 EUserModify currentUserModify = userModify();
312 m_rareInheritedData = inheritParent.m_rareInheritedData;
313 setUserModify(currentUserModify);
314 } else {
315 m_rareInheritedData = inheritParent.m_rareInheritedData;
316 }
317 m_styleInheritedData = inheritParent.m_styleInheritedData;
318 m_inheritedData = inheritParent.m_inheritedData;
319 if (m_svgStyle != inheritParent.m_svgStyle)
320 m_svgStyle.access()->inheritFrom(inheritParent.m_svgStyle.get());
321 }
322
323 void ComputedStyle::copyNonInheritedFromCached(const ComputedStyle& other)
324 {
325 m_box = other.m_box;
326 m_visual = other.m_visual;
327 m_background = other.m_background;
328 m_surround = other.m_surround;
329 m_rareNonInheritedData = other.m_rareNonInheritedData;
330
331 // The flags are copied one-by-one because m_nonInheritedData.m_contains a b unch of stuff other than real style data.
332 // See comments for each skipped flag below.
333 m_nonInheritedData.m_effectiveDisplay = other.m_nonInheritedData.m_effective Display;
334 m_nonInheritedData.m_originalDisplay = other.m_nonInheritedData.m_originalDi splay;
335 m_nonInheritedData.m_overflowAnchor = other.m_nonInheritedData.m_overflowAnc hor;
336 m_nonInheritedData.m_overflowX = other.m_nonInheritedData.m_overflowX;
337 m_nonInheritedData.m_overflowY = other.m_nonInheritedData.m_overflowY;
338 m_nonInheritedData.m_verticalAlign = other.m_nonInheritedData.m_verticalAlig n;
339 m_nonInheritedData.m_clear = other.m_nonInheritedData.m_clear;
340 m_nonInheritedData.m_position = other.m_nonInheritedData.m_position;
341 m_nonInheritedData.m_floating = other.m_nonInheritedData.m_floating;
342 m_nonInheritedData.m_tableLayout = other.m_nonInheritedData.m_tableLayout;
343 m_nonInheritedData.m_unicodeBidi = other.m_nonInheritedData.m_unicodeBidi;
344 m_nonInheritedData.m_hasViewportUnits = other.m_nonInheritedData.m_hasViewpo rtUnits;
345 m_nonInheritedData.m_breakBefore = other.m_nonInheritedData.m_breakBefore;
346 m_nonInheritedData.m_breakAfter = other.m_nonInheritedData.m_breakAfter;
347 m_nonInheritedData.m_breakInside = other.m_nonInheritedData.m_breakInside;
348 m_nonInheritedData.m_hasRemUnits = other.m_nonInheritedData.m_hasRemUnits;
349
350 // Correctly set during selector matching:
351 // m_nonInheritedData.m_styleType
352 // m_nonInheritedData.m_pseudoBits
353
354 // Set correctly while computing style for children:
355 // m_nonInheritedData.m_explicitInheritance
356
357 // unique() styles are not cacheable.
358 DCHECK(!other.m_nonInheritedData.m_unique);
359
360 // styles with non inherited properties that reference variables are not
361 // cacheable.
362 DCHECK(!other.m_nonInheritedData.m_variableReference);
363
364 // The following flags are set during matching before we decide that we get a
365 // match in the MatchedPropertiesCache which in turn calls this method. The
366 // reason why we don't copy these flags is that they're already correctly se t
367 // and that they may differ between elements which have the same set of matc hed
368 // properties. For instance, given the rule:
369 //
370 // :-webkit-any(:hover, :focus) { background-color: green }"
371 //
372 // A hovered element, and a focused element may use the same cached matched
373 // properties here, but the affectedBy flags will be set differently based o n
374 // the matching order of the :-webkit-any components.
375 //
376 // m_nonInheritedData.m_emptyState
377 // m_nonInheritedData.m_affectedByFocus
378 // m_nonInheritedData.m_affectedByHover
379 // m_nonInheritedData.m_affectedByActive
380 // m_nonInheritedData.m_affectedByDrag
381 // m_nonInheritedData.m_isLink
382
383 // Any properties that are inherited on a style are also inherited on elemen ts
384 // that share this style.
385 m_nonInheritedData.m_isPointerEventsInherited = other.m_nonInheritedData.m_i sPointerEventsInherited;
386 m_nonInheritedData.m_isVisibilityInherited = other.m_nonInheritedData.m_isVi sibilityInherited;
387
388 if (m_svgStyle != other.m_svgStyle)
389 m_svgStyle.access()->copyNonInheritedFromCached(other.m_svgStyle.get());
390 DCHECK_EQ(zoom(), initialZoom());
391 }
392
393 bool ComputedStyle::operator==(const ComputedStyle& o) const
394 {
395 return inheritedEqual(o)
396 && nonInheritedEqual(o);
397 }
398
399 bool ComputedStyle::isStyleAvailable() const
400 {
401 return this != StyleResolver::styleNotYetAvailable();
402 }
403
404 bool ComputedStyle::hasUniquePseudoStyle() const
405 {
406 if (!m_cachedPseudoStyles || styleType() != PseudoIdNone)
407 return false;
408
409 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
410 const ComputedStyle& pseudoStyle = *m_cachedPseudoStyles->at(i);
411 if (pseudoStyle.unique())
412 return true;
413 }
414
415 return false;
416 }
417
418 ComputedStyle* ComputedStyle::getCachedPseudoStyle(PseudoId pid) const
419 {
420 if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
421 return 0;
422
423 if (styleType() != PseudoIdNone)
424 return 0;
425
426 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
427 ComputedStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
428 if (pseudoStyle->styleType() == pid)
429 return pseudoStyle;
430 }
431
432 return 0;
433 }
434
435 ComputedStyle* ComputedStyle::addCachedPseudoStyle(PassRefPtr<ComputedStyle> pse udo)
436 {
437 if (!pseudo)
438 return 0;
439
440 ASSERT(pseudo->styleType() > PseudoIdNone);
441
442 ComputedStyle* result = pseudo.get();
443
444 if (!m_cachedPseudoStyles)
445 m_cachedPseudoStyles = wrapUnique(new PseudoStyleCache);
446
447 m_cachedPseudoStyles->append(pseudo);
448
449 return result;
450 }
451
452 void ComputedStyle::removeCachedPseudoStyle(PseudoId pid)
453 {
454 if (!m_cachedPseudoStyles)
455 return;
456 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
457 ComputedStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
458 if (pseudoStyle->styleType() == pid) {
459 m_cachedPseudoStyles->remove(i);
460 return;
461 }
462 }
463 }
464
465 bool ComputedStyle::inheritedEqual(const ComputedStyle& other) const
466 {
467 return independentInheritedEqual(other)
468 && nonIndependentInheritedEqual(other);
469 }
470
471 bool ComputedStyle::independentInheritedEqual(const ComputedStyle& other) const
472 {
473 return m_inheritedData.compareEqualIndependent(other.m_inheritedData);
474 }
475
476 bool ComputedStyle::nonIndependentInheritedEqual(const ComputedStyle& other) con st
477 {
478 return m_inheritedData.compareEqualNonIndependent(other.m_inheritedData)
479 && m_styleInheritedData == other.m_styleInheritedData
480 && m_svgStyle->inheritedEqual(*other.m_svgStyle)
481 && m_rareInheritedData == other.m_rareInheritedData;
482 }
483
484 bool ComputedStyle::loadingCustomFontsEqual(const ComputedStyle& other) const
485 {
486 return font().loadingCustomFonts() == other.font().loadingCustomFonts();
487 }
488
489 bool ComputedStyle::nonInheritedEqual(const ComputedStyle& other) const
490 {
491 // compare everything except the pseudoStyle pointer
492 return m_nonInheritedData == other.m_nonInheritedData
493 && m_box == other.m_box
494 && m_visual == other.m_visual
495 && m_background == other.m_background
496 && m_surround == other.m_surround
497 && m_rareNonInheritedData == other.m_rareNonInheritedData
498 && m_svgStyle->nonInheritedEqual(*other.m_svgStyle);
499 }
500
501 bool ComputedStyle::inheritedDataShared(const ComputedStyle& other) const
502 {
503 // This is a fast check that only looks if the data structures are shared.
504 return m_inheritedData == other.m_inheritedData
505 && m_styleInheritedData.get() == other.m_styleInheritedData.get()
506 && m_svgStyle.get() == other.m_svgStyle.get()
507 && m_rareInheritedData.get() == other.m_rareInheritedData.get();
508 }
509
510 static bool dependenceOnContentHeightHasChanged(const ComputedStyle& a, const Co mputedStyle& b)
511 {
512 // If top or bottom become auto/non-auto then it means we either have to sol ve height based
513 // on the content or stop doing so (http://www.w3.org/TR/CSS2/visudet.html#a bs-non-replaced-height)
514 // - either way requires a layout.
515 return a.logicalTop().isAuto() != b.logicalTop().isAuto() || a.logicalBottom ().isAuto() != b.logicalBottom().isAuto();
516 }
517
518 StyleDifference ComputedStyle::visualInvalidationDiff(const ComputedStyle& other ) const
519 {
520 // Note, we use .get() on each DataRef below because DataRef::operator== wil l do a deep
521 // compare, which is duplicate work when we're going to compare each propert y inside
522 // this function anyway.
523
524 StyleDifference diff;
525 if (m_svgStyle.get() != other.m_svgStyle.get())
526 diff = m_svgStyle->diff(other.m_svgStyle.get());
527
528 if ((!diff.needsFullLayout() || !diff.needsPaintInvalidation()) && diffNeeds FullLayoutAndPaintInvalidation(other)) {
529 diff.setNeedsFullLayout();
530 diff.setNeedsPaintInvalidationObject();
531 }
532
533 if (!diff.needsFullLayout() && diffNeedsFullLayout(other))
534 diff.setNeedsFullLayout();
535
536 if (!diff.needsFullLayout() && m_surround->margin != other.m_surround->margi n) {
537 // Relative-positioned elements collapse their margins so need a full la yout.
538 if (hasOutOfFlowPosition())
539 diff.setNeedsPositionedMovementLayout();
540 else
541 diff.setNeedsFullLayout();
542 }
543
544 if (!diff.needsFullLayout() && position() != StaticPosition && m_surround->o ffset != other.m_surround->offset) {
545 // Optimize for the case where a positioned layer is moving but not chan ging size.
546 if (dependenceOnContentHeightHasChanged(*this, other))
547 diff.setNeedsFullLayout();
548 else
549 diff.setNeedsPositionedMovementLayout();
550 }
551
552 if (diffNeedsPaintInvalidationSubtree(other))
553 diff.setNeedsPaintInvalidationSubtree();
554 else if (diffNeedsPaintInvalidationObject(other))
555 diff.setNeedsPaintInvalidationObject();
556
557 updatePropertySpecificDifferences(other, diff);
558
559 // TODO(skobes): Refine the criteria for ScrollAnchor-disabling properties.
560 // Some things set needsLayout but shouldn't disable scroll anchoring.
561 if (diff.needsLayout() || diff.transformChanged())
562 diff.setScrollAnchorDisablingPropertyChanged();
563
564 // Cursors are not checked, since they will be set appropriately in response to mouse events,
565 // so they don't need to cause any paint invalidation or layout.
566
567 // Animations don't need to be checked either. We always set the new style o n the layoutObject, so we will get a chance to fire off
568 // the resulting transition properly.
569
570 return diff;
571 }
572
573 bool ComputedStyle::diffNeedsFullLayoutAndPaintInvalidation(const ComputedStyle& other) const
574 {
575 // FIXME: Not all cases in this method need both full layout and paint inval idation.
576 // Should move cases into diffNeedsFullLayout() if
577 // - don't need paint invalidation at all;
578 // - or the layoutObject knows how to exactly invalidate paints caused by th e layout change
579 // instead of forced full paint invalidation.
580
581 if (m_surround.get() != other.m_surround.get()) {
582 // If our border widths change, then we need to layout. Other changes to borders only necessitate a paint invalidation.
583 if (borderLeftWidth() != other.borderLeftWidth()
584 || borderTopWidth() != other.borderTopWidth()
585 || borderBottomWidth() != other.borderBottomWidth()
586 || borderRightWidth() != other.borderRightWidth())
587 return true;
588 }
589
590 if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
591 if (m_rareNonInheritedData->m_appearance != other.m_rareNonInheritedData ->m_appearance
592 || m_rareNonInheritedData->marginBeforeCollapse != other.m_rareNonIn heritedData->marginBeforeCollapse
593 || m_rareNonInheritedData->marginAfterCollapse != other.m_rareNonInh eritedData->marginAfterCollapse
594 || m_rareNonInheritedData->lineClamp != other.m_rareNonInheritedData ->lineClamp
595 || m_rareNonInheritedData->textOverflow != other.m_rareNonInheritedD ata->textOverflow
596 || m_rareNonInheritedData->m_shapeMargin != other.m_rareNonInherited Data->m_shapeMargin
597 || m_rareNonInheritedData->m_order != other.m_rareNonInheritedData-> m_order
598 || m_rareNonInheritedData->hasFilters() != other.m_rareNonInheritedD ata->hasFilters())
599 return true;
600
601 if (m_rareNonInheritedData->m_grid.get() != other.m_rareNonInheritedData ->m_grid.get()
602 && *m_rareNonInheritedData->m_grid.get() != *other.m_rareNonInherite dData->m_grid.get())
603 return true;
604
605 if (m_rareNonInheritedData->m_gridItem.get() != other.m_rareNonInherited Data->m_gridItem.get()
606 && *m_rareNonInheritedData->m_gridItem.get() != *other.m_rareNonInhe ritedData->m_gridItem.get())
607 return true;
608
609 if (m_rareNonInheritedData->m_deprecatedFlexibleBox.get() != other.m_rar eNonInheritedData->m_deprecatedFlexibleBox.get()
610 && *m_rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other. m_rareNonInheritedData->m_deprecatedFlexibleBox.get())
611 return true;
612
613 if (m_rareNonInheritedData->m_flexibleBox.get() != other.m_rareNonInheri tedData->m_flexibleBox.get()
614 && *m_rareNonInheritedData->m_flexibleBox.get() != *other.m_rareNonI nheritedData->m_flexibleBox.get())
615 return true;
616
617 if (m_rareNonInheritedData->m_multiCol.get() != other.m_rareNonInherited Data->m_multiCol.get()
618 && *m_rareNonInheritedData->m_multiCol.get() != *other.m_rareNonInhe ritedData->m_multiCol.get())
619 return true;
620
621 // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
622 const CounterDirectiveMap* mapA = m_rareNonInheritedData->m_counterDirec tives.get();
623 const CounterDirectiveMap* mapB = other.m_rareNonInheritedData->m_counte rDirectives.get();
624 if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
625 return true;
626
627 // We only need do layout for opacity changes if adding or losing opacit y could trigger a change
628 // in us being a stacking context.
629 if (isStackingContext() != other.isStackingContext() && m_rareNonInherit edData->hasOpacity() != other.m_rareNonInheritedData->hasOpacity()) {
630 // FIXME: We would like to use SimplifiedLayout here, but we can't q uite do that yet.
631 // We need to make sure SimplifiedLayout can operate correctly on La youtInlines (we will need
632 // to add a selfNeedsSimplifiedLayout bit in order to not get confus ed and taint every line).
633 // In addition we need to solve the floating object issue when layer s come and go. Right now
634 // a full layout is necessary to keep floating object lists sane.
635 return true;
636 }
637 }
638
639 if (m_rareInheritedData.get() != other.m_rareInheritedData.get()) {
640 if (m_rareInheritedData->highlight != other.m_rareInheritedData->highlig ht
641 || m_rareInheritedData->indent != other.m_rareInheritedData->indent
642 || m_rareInheritedData->m_textAlignLast != other.m_rareInheritedData ->m_textAlignLast
643 || m_rareInheritedData->m_textIndentLine != other.m_rareInheritedDat a->m_textIndentLine
644 || m_rareInheritedData->m_effectiveZoom != other.m_rareInheritedData ->m_effectiveZoom
645 || m_rareInheritedData->wordBreak != other.m_rareInheritedData->word Break
646 || m_rareInheritedData->overflowWrap != other.m_rareInheritedData->o verflowWrap
647 || m_rareInheritedData->lineBreak != other.m_rareInheritedData->line Break
648 || m_rareInheritedData->textSecurity != other.m_rareInheritedData->t extSecurity
649 || m_rareInheritedData->hyphens != other.m_rareInheritedData->hyphen s
650 || m_rareInheritedData->hyphenationLimitBefore != other.m_rareInheri tedData->hyphenationLimitBefore
651 || m_rareInheritedData->hyphenationLimitAfter != other.m_rareInherit edData->hyphenationLimitAfter
652 || m_rareInheritedData->hyphenationString != other.m_rareInheritedDa ta->hyphenationString
653 || m_rareInheritedData->m_respectImageOrientation != other.m_rareInh eritedData->m_respectImageOrientation
654 || m_rareInheritedData->m_rubyPosition != other.m_rareInheritedData- >m_rubyPosition
655 || m_rareInheritedData->textEmphasisMark != other.m_rareInheritedDat a->textEmphasisMark
656 || m_rareInheritedData->textEmphasisPosition != other.m_rareInherite dData->textEmphasisPosition
657 || m_rareInheritedData->textEmphasisCustomMark != other.m_rareInheri tedData->textEmphasisCustomMark
658 || m_rareInheritedData->m_textJustify != other.m_rareInheritedData-> m_textJustify
659 || m_rareInheritedData->m_textOrientation != other.m_rareInheritedDa ta->m_textOrientation
660 || m_rareInheritedData->m_textCombine != other.m_rareInheritedData-> m_textCombine
661 || m_rareInheritedData->m_tabSize != other.m_rareInheritedData->m_ta bSize
662 || m_rareInheritedData->m_textSizeAdjust != other.m_rareInheritedDat a->m_textSizeAdjust
663 || m_rareInheritedData->listStyleImage != other.m_rareInheritedData- >listStyleImage
664 || m_rareInheritedData->m_snapHeightUnit != other.m_rareInheritedDat a->m_snapHeightUnit
665 || m_rareInheritedData->m_snapHeightPosition != other.m_rareInherite dData->m_snapHeightPosition
666 || m_rareInheritedData->textStrokeWidth != other.m_rareInheritedData ->textStrokeWidth)
667 return true;
668
669 if (!m_rareInheritedData->shadowDataEquivalent(*other.m_rareInheritedDat a.get()))
670 return true;
671
672 if (!m_rareInheritedData->quotesDataEquivalent(*other.m_rareInheritedDat a.get()))
673 return true;
674 }
675
676 if (m_styleInheritedData->textAutosizingMultiplier != other.m_styleInherited Data->textAutosizingMultiplier)
677 return true;
678
679 if (m_styleInheritedData->font.loadingCustomFonts() != other.m_styleInherite dData->font.loadingCustomFonts())
680 return true;
681
682 if (m_styleInheritedData.get() != other.m_styleInheritedData.get()) {
683 if (m_styleInheritedData->line_height != other.m_styleInheritedData->lin e_height
684 || m_styleInheritedData->font != other.m_styleInheritedData->font
685 || m_styleInheritedData->horizontal_border_spacing != other.m_styleI nheritedData->horizontal_border_spacing
686 || m_styleInheritedData->vertical_border_spacing != other.m_styleInh eritedData->vertical_border_spacing)
687 return true;
688 }
689
690 if (m_inheritedData.m_boxDirection != other.m_inheritedData.m_boxDirection
691 || m_inheritedData.m_rtlOrdering != other.m_inheritedData.m_rtlOrdering
692 || m_inheritedData.m_textAlign != other.m_inheritedData.m_textAlign
693 || m_inheritedData.m_textTransform != other.m_inheritedData.m_textTransf orm
694 || m_inheritedData.m_direction != other.m_inheritedData.m_direction
695 || m_inheritedData.m_whiteSpace != other.m_inheritedData.m_whiteSpace
696 || m_inheritedData.m_writingMode != other.m_inheritedData.m_writingMode)
697 return true;
698
699 if (m_nonInheritedData.m_overflowX != other.m_nonInheritedData.m_overflowX
700 || m_nonInheritedData.m_overflowY != other.m_nonInheritedData.m_overflow Y
701 || m_nonInheritedData.m_clear != other.m_nonInheritedData.m_clear
702 || m_nonInheritedData.m_unicodeBidi != other.m_nonInheritedData.m_unicod eBidi
703 || m_nonInheritedData.m_floating != other.m_nonInheritedData.m_floating
704 || m_nonInheritedData.m_originalDisplay != other.m_nonInheritedData.m_or iginalDisplay)
705 return true;
706
707 if (m_nonInheritedData.m_effectiveDisplay >= FIRST_TABLE_DISPLAY && m_nonInh eritedData.m_effectiveDisplay <= LAST_TABLE_DISPLAY) {
708 if (m_inheritedData.m_borderCollapse != other.m_inheritedData.m_borderCo llapse
709 || m_inheritedData.m_emptyCells != other.m_inheritedData.m_emptyCell s
710 || m_inheritedData.m_captionSide != other.m_inheritedData.m_captionS ide
711 || m_nonInheritedData.m_tableLayout != other.m_nonInheritedData.m_ta bleLayout)
712 return true;
713
714 // In the collapsing border model, 'hidden' suppresses other borders, wh ile 'none'
715 // does not, so these style differences can be width differences.
716 if (m_inheritedData.m_borderCollapse
717 && ((borderTopStyle() == BorderStyleHidden && other.borderTopStyle() == BorderStyleNone)
718 || (borderTopStyle() == BorderStyleNone && other.borderTopStyle( ) == BorderStyleHidden)
719 || (borderBottomStyle() == BorderStyleHidden && other.borderBott omStyle() == BorderStyleNone)
720 || (borderBottomStyle() == BorderStyleNone && other.borderBottom Style() == BorderStyleHidden)
721 || (borderLeftStyle() == BorderStyleHidden && other.borderLeftSt yle() == BorderStyleNone)
722 || (borderLeftStyle() == BorderStyleNone && other.borderLeftStyl e() == BorderStyleHidden)
723 || (borderRightStyle() == BorderStyleHidden && other.borderRight Style() == BorderStyleNone)
724 || (borderRightStyle() == BorderStyleNone && other.borderRightSt yle() == BorderStyleHidden)))
725 return true;
726 } else if (m_nonInheritedData.m_effectiveDisplay == LIST_ITEM) {
727 if (m_inheritedData.m_listStyleType != other.m_inheritedData.m_listStyle Type
728 || m_inheritedData.m_listStylePosition != other.m_inheritedData.m_li stStylePosition)
729 return true;
730 }
731
732 if ((visibility() == EVisibility::Collapse) != (other.visibility() == EVisib ility::Collapse))
733 return true;
734
735 if (hasPseudoStyle(PseudoIdScrollbar) != other.hasPseudoStyle(PseudoIdScroll bar))
736 return true;
737
738 // Movement of non-static-positioned object is special cased in ComputedStyl e::visualInvalidationDiff().
739
740 return false;
741 }
742
743 bool ComputedStyle::diffNeedsFullLayout(const ComputedStyle& other) const
744 {
745 if (m_box.get() != other.m_box.get()) {
746 if (m_box->width() != other.m_box->width()
747 || m_box->minWidth() != other.m_box->minWidth()
748 || m_box->maxWidth() != other.m_box->maxWidth()
749 || m_box->height() != other.m_box->height()
750 || m_box->minHeight() != other.m_box->minHeight()
751 || m_box->maxHeight() != other.m_box->maxHeight())
752 return true;
753
754 if (m_box->verticalAlign() != other.m_box->verticalAlign())
755 return true;
756
757 if (m_box->boxSizing() != other.m_box->boxSizing())
758 return true;
759 }
760
761 if (m_nonInheritedData.m_verticalAlign != other.m_nonInheritedData.m_vertica lAlign
762 || m_nonInheritedData.m_position != other.m_nonInheritedData.m_position)
763 return true;
764
765 if (m_surround.get() != other.m_surround.get()) {
766 if (m_surround->padding != other.m_surround->padding)
767 return true;
768 }
769
770 if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
771 if (m_rareNonInheritedData->m_alignContent != other.m_rareNonInheritedDa ta->m_alignContent
772 || m_rareNonInheritedData->m_alignItems != other.m_rareNonInheritedD ata->m_alignItems
773 || m_rareNonInheritedData->m_alignSelf != other.m_rareNonInheritedDa ta->m_alignSelf
774 || m_rareNonInheritedData->m_justifyContent != other.m_rareNonInheri tedData->m_justifyContent
775 || m_rareNonInheritedData->m_justifyItems != other.m_rareNonInherite dData->m_justifyItems
776 || m_rareNonInheritedData->m_justifySelf != other.m_rareNonInherited Data->m_justifySelf
777 || m_rareNonInheritedData->m_contain != other.m_rareNonInheritedData ->m_contain)
778 return true;
779
780 if (!RuntimeEnabledFeatures::cssBoxReflectFilterEnabled() && !m_rareNonI nheritedData->reflectionDataEquivalent(*other.m_rareNonInheritedData.get()))
781 return true;
782 }
783
784 return false;
785 }
786
787 bool ComputedStyle::diffNeedsPaintInvalidationSubtree(const ComputedStyle& other ) const
788 {
789 if (position() != StaticPosition && (m_visual->clip != other.m_visual->clip || m_visual->hasAutoClip != other.m_visual->hasAutoClip))
790 return true;
791
792 if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
793 if (m_rareNonInheritedData->m_effectiveBlendMode != other.m_rareNonInher itedData->m_effectiveBlendMode
794 || m_rareNonInheritedData->m_isolation != other.m_rareNonInheritedDa ta->m_isolation)
795 return true;
796
797 if (m_rareNonInheritedData->m_mask != other.m_rareNonInheritedData->m_ma sk
798 || m_rareNonInheritedData->m_maskBoxImage != other.m_rareNonInherite dData->m_maskBoxImage)
799 return true;
800
801 if (!RuntimeEnabledFeatures::cssBoxReflectFilterEnabled() && !m_rareNonI nheritedData->reflectionDataEquivalent(*other.m_rareNonInheritedData.get()))
802 return true;
803 }
804
805 return false;
806 }
807
808 bool ComputedStyle::diffNeedsPaintInvalidationObject(const ComputedStyle& other) const
809 {
810 if (!m_background->outline().visuallyEqual(other.m_background->outline()))
811 return true;
812
813 if (m_inheritedData.m_visibility != other.m_inheritedData.m_visibility
814 || m_inheritedData.m_printColorAdjust != other.m_inheritedData.m_printCo lorAdjust
815 || m_inheritedData.m_insideLink != other.m_inheritedData.m_insideLink
816 || !m_surround->border.visuallyEqual(other.m_surround->border)
817 || !m_background->visuallyEqual(*other.m_background))
818 return true;
819
820 if (m_rareInheritedData.get() != other.m_rareInheritedData.get()) {
821 if (m_rareInheritedData->userModify != other.m_rareInheritedData->userMo dify
822 || m_rareInheritedData->userSelect != other.m_rareInheritedData->use rSelect
823 || m_rareInheritedData->m_imageRendering != other.m_rareInheritedDat a->m_imageRendering)
824 return true;
825 }
826
827 if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
828 if (m_rareNonInheritedData->userDrag != other.m_rareNonInheritedData->us erDrag
829 || m_rareNonInheritedData->m_objectFit != other.m_rareNonInheritedDa ta->m_objectFit
830 || m_rareNonInheritedData->m_objectPosition != other.m_rareNonInheri tedData->m_objectPosition
831 || !m_rareNonInheritedData->shadowDataEquivalent(*other.m_rareNonInh eritedData.get())
832 || !m_rareNonInheritedData->shapeOutsideDataEquivalent(*other.m_rare NonInheritedData.get())
833 || !m_rareNonInheritedData->clipPathDataEquivalent(*other.m_rareNonI nheritedData.get())
834 || (visitedLinkBorderLeftColor() != other.visitedLinkBorderLeftColor () && borderLeftWidth())
835 || (visitedLinkBorderRightColor() != other.visitedLinkBorderRightCol or() && borderRightWidth())
836 || (visitedLinkBorderBottomColor() != other.visitedLinkBorderBottomC olor() && borderBottomWidth())
837 || (visitedLinkBorderTopColor() != other.visitedLinkBorderTopColor() && borderTopWidth())
838 || (visitedLinkOutlineColor() != other.visitedLinkOutlineColor() && outlineWidth())
839 || (visitedLinkBackgroundColor() != other.visitedLinkBackgroundColor ()))
840 return true;
841 }
842
843 if (resize() != other.resize())
844 return true;
845
846 if (m_rareNonInheritedData->m_paintImages) {
847 for (const auto& image : *m_rareNonInheritedData->m_paintImages) {
848 if (diffNeedsPaintInvalidationObjectForPaintImage(image, other))
849 return true;
850 }
851 }
852
853 return false;
854 }
855
856 bool ComputedStyle::diffNeedsPaintInvalidationObjectForPaintImage(const StyleIma ge* image, const ComputedStyle& other) const
857 {
858 CSSPaintValue* value = toCSSPaintValue(image->cssValue());
859
860 // NOTE: If the invalidation properties vectors are null, we are invalid as
861 // we haven't yet been painted (and can't provide the invalidation
862 // properties yet).
863 if (!value->nativeInvalidationProperties() || !value->customInvalidationProp erties())
864 return true;
865
866 for (CSSPropertyID propertyID : *value->nativeInvalidationProperties()) {
867 // TODO(ikilpatrick): remove isInterpolableProperty check once
868 // CSSPropertyEquality::propertiesEqual correctly handles all properties .
869 if (!CSSPropertyMetadata::isInterpolableProperty(propertyID) || !CSSProp ertyEquality::propertiesEqual(propertyID, *this, other))
870 return true;
871 }
872
873 if (variables() || other.variables()) {
874 for (const AtomicString& property : *value->customInvalidationProperties ()) {
875 CSSVariableData* thisVar = variables() ? variables()->getVariable(pr operty) : nullptr;
876 CSSVariableData* otherVar = other.variables() ? other.variables()->g etVariable(property) : nullptr;
877
878 if (!dataEquivalent(thisVar, otherVar))
879 return true;
880 }
881 }
882
883 return false;
884 }
885
886 void ComputedStyle::updatePropertySpecificDifferences(const ComputedStyle& other , StyleDifference& diff) const
887 {
888 if (m_box->zIndex() != other.m_box->zIndex() || isStackingContext() != other .isStackingContext())
889 diff.setZIndexChanged();
890
891 if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
892 if (!transformDataEquivalent(other))
893 diff.setTransformChanged();
894
895 if (m_rareNonInheritedData->opacity != other.m_rareNonInheritedData->opa city)
896 diff.setOpacityChanged();
897
898 if (m_rareNonInheritedData->m_filter != other.m_rareNonInheritedData->m_ filter)
899 diff.setFilterChanged();
900
901 if (!m_rareNonInheritedData->shadowDataEquivalent(*other.m_rareNonInheri tedData.get()))
902 diff.setNeedsRecomputeOverflow();
903
904 if (m_rareNonInheritedData->m_backdropFilter != other.m_rareNonInherited Data->m_backdropFilter)
905 diff.setBackdropFilterChanged();
906
907 if (RuntimeEnabledFeatures::cssBoxReflectFilterEnabled() && !m_rareNonIn heritedData->reflectionDataEquivalent(*other.m_rareNonInheritedData.get()))
908 diff.setFilterChanged();
909 }
910
911 if (!m_background->outline().visuallyEqual(other.m_background->outline()) || !m_surround->border.visualOverflowEqual(other.m_surround->border))
912 diff.setNeedsRecomputeOverflow();
913
914 if (!diff.needsPaintInvalidation()) {
915 if (m_styleInheritedData->color != other.m_styleInheritedData->color
916 || m_styleInheritedData->visitedLinkColor != other.m_styleInheritedD ata->visitedLinkColor
917 || m_inheritedData.m_textUnderline != other.m_inheritedData.m_textUn derline
918 || m_visual->textDecoration != other.m_visual->textDecoration) {
919 diff.setTextDecorationOrColorChanged();
920 } else if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData. get()
921 && (m_rareNonInheritedData->m_textDecorationStyle != other.m_rareNon InheritedData->m_textDecorationStyle
922 || m_rareNonInheritedData->m_textDecorationColor != other.m_rare NonInheritedData->m_textDecorationColor
923 || m_rareNonInheritedData->m_visitedLinkTextDecorationColor != o ther.m_rareNonInheritedData->m_visitedLinkTextDecorationColor)) {
924 diff.setTextDecorationOrColorChanged();
925 } else if (m_rareInheritedData.get() != other.m_rareInheritedData.get()
926 && (m_rareInheritedData->textFillColor() != other.m_rareInheritedDat a->textFillColor()
927 || m_rareInheritedData->textStrokeColor() != other.m_rareInherit edData->textStrokeColor()
928 || m_rareInheritedData->textEmphasisColor() != other.m_rareInher itedData->textEmphasisColor()
929 || m_rareInheritedData->visitedLinkTextFillColor() != other.m_ra reInheritedData->visitedLinkTextFillColor()
930 || m_rareInheritedData->visitedLinkTextStrokeColor() != other.m_ rareInheritedData->visitedLinkTextStrokeColor()
931 || m_rareInheritedData->visitedLinkTextEmphasisColor() != other. m_rareInheritedData->visitedLinkTextEmphasisColor()
932 || m_rareInheritedData->textEmphasisFill != other.m_rareInherite dData->textEmphasisFill
933 || m_rareInheritedData->appliedTextDecorations != other.m_rareIn heritedData->appliedTextDecorations)) {
934 diff.setTextDecorationOrColorChanged();
935 }
936 }
937 }
938
939 void ComputedStyle::addPaintImage(StyleImage* image)
940 {
941 if (!m_rareNonInheritedData.access()->m_paintImages)
942 m_rareNonInheritedData.access()->m_paintImages = WTF::wrapUnique(new Vec tor<Persistent<StyleImage>>());
943 m_rareNonInheritedData.access()->m_paintImages->append(image);
944 }
945
946 void ComputedStyle::addCursor(StyleImage* image, bool hotSpotSpecified, const In tPoint& hotSpot)
947 {
948 if (!m_rareInheritedData.access()->cursorData)
949 m_rareInheritedData.access()->cursorData = new CursorList;
950 m_rareInheritedData.access()->cursorData->append(CursorData(image, hotSpotSp ecified, hotSpot));
951 }
952
953 void ComputedStyle::setCursorList(CursorList* other)
954 {
955 m_rareInheritedData.access()->cursorData = other;
956 }
957
958 void ComputedStyle::setQuotes(PassRefPtr<QuotesData> q)
959 {
960 m_rareInheritedData.access()->quotes = q;
961 }
962
963 void ComputedStyle::clearCursorList()
964 {
965 if (m_rareInheritedData->cursorData)
966 m_rareInheritedData.access()->cursorData = nullptr;
967 }
968
969 static bool hasPropertyThatCreatesStackingContext(const Vector<CSSPropertyID>& p roperties)
970 {
971 for (CSSPropertyID property : properties) {
972 switch (property) {
973 case CSSPropertyOpacity:
974 case CSSPropertyTransform:
975 case CSSPropertyAliasWebkitTransform:
976 case CSSPropertyTransformStyle:
977 case CSSPropertyAliasWebkitTransformStyle:
978 case CSSPropertyPerspective:
979 case CSSPropertyAliasWebkitPerspective:
980 case CSSPropertyWebkitMask:
981 case CSSPropertyWebkitMaskBoxImage:
982 case CSSPropertyWebkitClipPath:
983 case CSSPropertyWebkitBoxReflect:
984 case CSSPropertyFilter:
985 case CSSPropertyAliasWebkitFilter:
986 case CSSPropertyBackdropFilter:
987 case CSSPropertyZIndex:
988 case CSSPropertyPosition:
989 case CSSPropertyMixBlendMode:
990 case CSSPropertyIsolation:
991 return true;
992 default:
993 break;
994 }
995 }
996 return false;
997 }
998
999 void ComputedStyle::updateIsStackingContext(bool isDocumentElement, bool isInTop Layer)
1000 {
1001 if (isStackingContext())
1002 return;
1003
1004 if (isDocumentElement
1005 || isInTopLayer
1006 || styleType() == PseudoIdBackdrop
1007 || hasOpacity()
1008 || hasTransformRelatedProperty()
1009 || hasMask()
1010 || clipPath()
1011 || boxReflect()
1012 || hasFilterInducingProperty()
1013 || hasBlendMode()
1014 || hasIsolation()
1015 || hasViewportConstrainedPosition()
1016 || hasPropertyThatCreatesStackingContext(willChangeProperties())
1017 || containsPaint()) {
1018 setIsStackingContext(true);
1019 }
1020 }
1021
1022 void ComputedStyle::addCallbackSelector(const String& selector)
1023 {
1024 if (!m_rareNonInheritedData->m_callbackSelectors.contains(selector))
1025 m_rareNonInheritedData.access()->m_callbackSelectors.append(selector);
1026 }
1027
1028 void ComputedStyle::setContent(ContentData* contentData)
1029 {
1030 SET_VAR(m_rareNonInheritedData, m_content, contentData);
1031 }
1032
1033 bool ComputedStyle::hasWillChangeCompositingHint() const
1034 {
1035 for (size_t i = 0; i < m_rareNonInheritedData->m_willChange->m_properties.si ze(); ++i) {
1036 switch (m_rareNonInheritedData->m_willChange->m_properties[i]) {
1037 case CSSPropertyOpacity:
1038 case CSSPropertyTransform:
1039 case CSSPropertyAliasWebkitTransform:
1040 case CSSPropertyTop:
1041 case CSSPropertyLeft:
1042 case CSSPropertyBottom:
1043 case CSSPropertyRight:
1044 return true;
1045 default:
1046 break;
1047 }
1048 }
1049 return false;
1050 }
1051
1052 bool ComputedStyle::hasWillChangeTransformHint() const
1053 {
1054 for (const auto& property: m_rareNonInheritedData->m_willChange->m_propertie s) {
1055 switch (property) {
1056 case CSSPropertyTransform:
1057 case CSSPropertyAliasWebkitTransform:
1058 return true;
1059 default:
1060 break;
1061 }
1062 }
1063 return false;
1064 }
1065
1066 bool ComputedStyle::requireTransformOrigin(ApplyTransformOrigin applyOrigin, App lyMotionPath applyMotionPath) const
1067 {
1068 const Vector<RefPtr<TransformOperation>>& transformOperations = transform(). operations();
1069
1070 // transform-origin brackets the transform with translate operations.
1071 // Optimize for the case where the only transform is a translation, since th e transform-origin is irrelevant
1072 // in that case.
1073 if (applyOrigin != IncludeTransformOrigin)
1074 return false;
1075
1076 if (applyMotionPath == IncludeMotionPath)
1077 return true;
1078
1079 unsigned size = transformOperations.size();
1080 for (unsigned i = 0; i < size; ++i) {
1081 TransformOperation::OperationType type = transformOperations[i]->type();
1082 if (type != TransformOperation::TranslateX
1083 && type != TransformOperation::TranslateY
1084 && type != TransformOperation::Translate
1085 && type != TransformOperation::TranslateZ
1086 && type != TransformOperation::Translate3D)
1087 return true;
1088 }
1089
1090 return scale() || rotate();
1091 }
1092
1093 void ComputedStyle::applyTransform(TransformationMatrix& result, const LayoutSiz e& borderBoxSize, ApplyTransformOrigin applyOrigin, ApplyMotionPath applyMotionP ath, ApplyIndependentTransformProperties applyIndependentTransformProperties) co nst
1094 {
1095 applyTransform(result, FloatRect(FloatPoint(), FloatSize(borderBoxSize)), ap plyOrigin, applyMotionPath, applyIndependentTransformProperties);
1096 }
1097
1098 void ComputedStyle::applyTransform(TransformationMatrix& result, const FloatRect & boundingBox, ApplyTransformOrigin applyOrigin, ApplyMotionPath applyMotionPath , ApplyIndependentTransformProperties applyIndependentTransformProperties) const
1099 {
1100 if (!hasMotionPath())
1101 applyMotionPath = ExcludeMotionPath;
1102 bool applyTransformOrigin = requireTransformOrigin(applyOrigin, applyMotionP ath);
1103
1104 float offsetX = transformOriginX().type() == Percent ? boundingBox.x() : 0;
1105 float offsetY = transformOriginY().type() == Percent ? boundingBox.y() : 0;
1106
1107 float originX = 0;
1108 float originY = 0;
1109 float originZ = 0;
1110
1111 if (applyTransformOrigin) {
1112 originX = floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX;
1113 originY = floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY;
1114 originZ = transformOriginZ();
1115 result.translate3d(originX, originY, originZ);
1116 }
1117
1118 if (applyIndependentTransformProperties == IncludeIndependentTransformProper ties) {
1119 if (translate())
1120 translate()->apply(result, boundingBox.size());
1121
1122 if (rotate())
1123 rotate()->apply(result, boundingBox.size());
1124
1125 if (scale())
1126 scale()->apply(result, boundingBox.size());
1127 }
1128
1129 if (applyMotionPath == ComputedStyle::IncludeMotionPath)
1130 applyMotionPathTransform(originX, originY, result);
1131
1132 const Vector<RefPtr<TransformOperation>>& transformOperations = transform(). operations();
1133 unsigned size = transformOperations.size();
1134 for (unsigned i = 0; i < size; ++i)
1135 transformOperations[i]->apply(result, boundingBox.size());
1136
1137 if (applyTransformOrigin) {
1138 result.translate3d(-originX, -originY, -originZ);
1139 }
1140 }
1141
1142 void ComputedStyle::applyMotionPathTransform(float originX, float originY, Trans formationMatrix& transform) const
1143 {
1144 const StyleMotionData& motionData = m_rareNonInheritedData->m_transform->m_m otion;
1145 ASSERT(motionData.m_path);
1146 const StylePath& motionPath = *motionData.m_path;
1147 float pathLength = motionPath.length();
1148 float distance = floatValueForLength(motionData.m_offset, pathLength);
1149 float computedDistance;
1150 if (motionPath.isClosed() && pathLength > 0) {
1151 computedDistance = fmod(distance, pathLength);
1152 if (computedDistance < 0)
1153 computedDistance += pathLength;
1154 } else {
1155 computedDistance = clampTo<float>(distance, 0, pathLength);
1156 }
1157
1158 FloatPoint point;
1159 float angle;
1160 motionPath.path().pointAndNormalAtLength(computedDistance, point, angle);
1161
1162 if (motionData.m_rotation.type == MotionRotationFixed)
1163 angle = 0;
1164
1165 transform.translate(point.x() - originX, point.y() - originY);
1166 transform.rotate(angle + motionData.m_rotation.angle);
1167 }
1168
1169 void ComputedStyle::setTextShadow(PassRefPtr<ShadowList> s)
1170 {
1171 m_rareInheritedData.access()->textShadow = s;
1172 }
1173
1174 void ComputedStyle::setBoxShadow(PassRefPtr<ShadowList> s)
1175 {
1176 m_rareNonInheritedData.access()->m_boxShadow = s;
1177 }
1178
1179 static FloatRoundedRect::Radii calcRadiiFor(const BorderData& border, LayoutSize size)
1180 {
1181 return FloatRoundedRect::Radii(
1182 FloatSize(floatValueForLength(border.topLeft().width(), size.width().toF loat()),
1183 floatValueForLength(border.topLeft().height(), size.height().toFloat ())),
1184 FloatSize(floatValueForLength(border.topRight().width(), size.width().to Float()),
1185 floatValueForLength(border.topRight().height(), size.height().toFloa t())),
1186 FloatSize(floatValueForLength(border.bottomLeft().width(), size.width(). toFloat()),
1187 floatValueForLength(border.bottomLeft().height(), size.height().toFl oat())),
1188 FloatSize(floatValueForLength(border.bottomRight().width(), size.width() .toFloat()),
1189 floatValueForLength(border.bottomRight().height(), size.height().toF loat())));
1190 }
1191
1192 StyleImage* ComputedStyle::listStyleImage() const { return m_rareInheritedData-> listStyleImage.get(); }
1193 void ComputedStyle::setListStyleImage(StyleImage* v)
1194 {
1195 if (m_rareInheritedData->listStyleImage != v)
1196 m_rareInheritedData.access()->listStyleImage = v;
1197 }
1198
1199 Color ComputedStyle::color() const { return m_styleInheritedData->color; }
1200 Color ComputedStyle::visitedLinkColor() const { return m_styleInheritedData->vis itedLinkColor; }
1201 void ComputedStyle::setColor(const Color& v) { SET_VAR(m_styleInheritedData, col or, v); }
1202 void ComputedStyle::setVisitedLinkColor(const Color& v) { SET_VAR(m_styleInherit edData, visitedLinkColor, v); }
1203
1204 short ComputedStyle::horizontalBorderSpacing() const { return m_styleInheritedDa ta->horizontal_border_spacing; }
1205 short ComputedStyle::verticalBorderSpacing() const { return m_styleInheritedData ->vertical_border_spacing; }
1206 void ComputedStyle::setHorizontalBorderSpacing(short v) { SET_VAR(m_styleInherit edData, horizontal_border_spacing, v); }
1207 void ComputedStyle::setVerticalBorderSpacing(short v) { SET_VAR(m_styleInherited Data, vertical_border_spacing, v); }
1208
1209 FloatRoundedRect ComputedStyle::getRoundedBorderFor(const LayoutRect& borderRect ,
1210 bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1211 {
1212 FloatRoundedRect roundedRect(pixelSnappedIntRect(borderRect));
1213 if (hasBorderRadius()) {
1214 FloatRoundedRect::Radii radii = calcRadiiFor(m_surround->border, borderR ect.size());
1215 roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includ eLogicalLeftEdge, includeLogicalRightEdge);
1216 roundedRect.constrainRadii();
1217 }
1218 return roundedRect;
1219 }
1220
1221 FloatRoundedRect ComputedStyle::getRoundedInnerBorderFor(const LayoutRect& borde rRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1222 {
1223 bool horizontal = isHorizontalWritingMode();
1224
1225 int leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
1226 int rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth () : 0;
1227 int topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0 ;
1228 int bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidt h() : 0;
1229
1230 return getRoundedInnerBorderFor(borderRect,
1231 LayoutRectOutsets(-topWidth, -rightWidth, -bottomWidth, -leftWidth),
1232 includeLogicalLeftEdge, includeLogicalRightEdge);
1233 }
1234
1235 FloatRoundedRect ComputedStyle::getRoundedInnerBorderFor(const LayoutRect& borde rRect,
1236 const LayoutRectOutsets insets, bool includeLogicalLeftEdge, bool includeLog icalRightEdge) const
1237 {
1238 LayoutRect innerRect(borderRect);
1239 innerRect.expand(insets);
1240
1241 FloatRoundedRect roundedRect(pixelSnappedIntRect(innerRect));
1242
1243 if (hasBorderRadius()) {
1244 FloatRoundedRect::Radii radii = getRoundedBorderFor(borderRect).getRadii ();
1245 // Insets use negative values.
1246 radii.shrink(
1247 -insets.top().toFloat(),
1248 -insets.bottom().toFloat(),
1249 -insets.left().toFloat(),
1250 -insets.right().toFloat());
1251 roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includ eLogicalLeftEdge, includeLogicalRightEdge);
1252 }
1253 return roundedRect;
1254 }
1255
1256 static bool allLayersAreFixed(const FillLayer& layer)
1257 {
1258 for (const FillLayer* currLayer = &layer; currLayer; currLayer = currLayer-> next()) {
1259 if (!currLayer->image() || currLayer->attachment() != FixedBackgroundAtt achment)
1260 return false;
1261 }
1262
1263 return true;
1264 }
1265
1266 bool ComputedStyle::hasEntirelyFixedBackground() const
1267 {
1268 return allLayersAreFixed(backgroundLayers());
1269 }
1270
1271 const CounterDirectiveMap* ComputedStyle::counterDirectives() const
1272 {
1273 return m_rareNonInheritedData->m_counterDirectives.get();
1274 }
1275
1276 CounterDirectiveMap& ComputedStyle::accessCounterDirectives()
1277 {
1278 std::unique_ptr<CounterDirectiveMap>& map = m_rareNonInheritedData.access()- >m_counterDirectives;
1279 if (!map)
1280 map = wrapUnique(new CounterDirectiveMap);
1281 return *map;
1282 }
1283
1284 const CounterDirectives ComputedStyle::getCounterDirectives(const AtomicString& identifier) const
1285 {
1286 if (const CounterDirectiveMap* directives = counterDirectives())
1287 return directives->get(identifier);
1288 return CounterDirectives();
1289 }
1290
1291 void ComputedStyle::clearIncrementDirectives()
1292 {
1293 if (!counterDirectives())
1294 return;
1295
1296 // This makes us copy even if we may not be removing any items.
1297 CounterDirectiveMap& map = accessCounterDirectives();
1298 typedef CounterDirectiveMap::iterator Iterator;
1299
1300 Iterator end = map.end();
1301 for (Iterator it = map.begin(); it != end; ++it)
1302 it->value.clearIncrement();
1303 }
1304
1305 void ComputedStyle::clearResetDirectives()
1306 {
1307 if (!counterDirectives())
1308 return;
1309
1310 // This makes us copy even if we may not be removing any items.
1311 CounterDirectiveMap& map = accessCounterDirectives();
1312 typedef CounterDirectiveMap::iterator Iterator;
1313
1314 Iterator end = map.end();
1315 for (Iterator it = map.begin(); it != end; ++it)
1316 it->value.clearReset();
1317 }
1318
1319 Hyphenation* ComputedStyle::getHyphenation() const
1320 {
1321 return getHyphens() == HyphensAuto
1322 ? getFontDescription().localeOrDefault().getHyphenation() : nullptr;
1323 }
1324
1325 const AtomicString& ComputedStyle::hyphenString() const
1326 {
1327 const AtomicString& hyphenationString = m_rareInheritedData.get()->hyphenati onString;
1328 if (!hyphenationString.isNull())
1329 return hyphenationString;
1330
1331 // FIXME: This should depend on locale.
1332 DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinusCharacter, 1));
1333 DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphenCharacter, 1));
1334 const SimpleFontData* primaryFont = font().primaryFont();
1335 ASSERT(primaryFont);
1336 return primaryFont->glyphForCharacter(hyphenCharacter) ? hyphenString : hyph enMinusString;
1337 }
1338
1339 const AtomicString& ComputedStyle::textEmphasisMarkString() const
1340 {
1341 switch (getTextEmphasisMark()) {
1342 case TextEmphasisMarkNone:
1343 return nullAtom;
1344 case TextEmphasisMarkCustom:
1345 return textEmphasisCustomMark();
1346 case TextEmphasisMarkDot: {
1347 DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bulletCharacter, 1) );
1348 DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBulletCharacter, 1));
1349 return getTextEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
1350 }
1351 case TextEmphasisMarkCircle: {
1352 DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircleChara cter, 1));
1353 DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircleCharact er, 1));
1354 return getTextEmphasisFill() == TextEmphasisFillFilled ? filledCircleStr ing : openCircleString;
1355 }
1356 case TextEmphasisMarkDoubleCircle: {
1357 DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheyeCha racter, 1));
1358 DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseyeChar acter, 1));
1359 return getTextEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCir cleString : openDoubleCircleString;
1360 }
1361 case TextEmphasisMarkTriangle: {
1362 DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointin gTriangleCharacter, 1));
1363 DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingT riangleCharacter, 1));
1364 return getTextEmphasisFill() == TextEmphasisFillFilled ? filledTriangleS tring : openTriangleString;
1365 }
1366 case TextEmphasisMarkSesame: {
1367 DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDotCharact er, 1));
1368 DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDotChar acter, 1));
1369 return getTextEmphasisFill() == TextEmphasisFillFilled ? filledSesameStr ing : openSesameString;
1370 }
1371 case TextEmphasisMarkAuto:
1372 ASSERT_NOT_REACHED();
1373 return nullAtom;
1374 }
1375
1376 ASSERT_NOT_REACHED();
1377 return nullAtom;
1378 }
1379
1380 CSSAnimationData& ComputedStyle::accessAnimations()
1381 {
1382 if (!m_rareNonInheritedData.access()->m_animations)
1383 m_rareNonInheritedData.access()->m_animations = CSSAnimationData::create ();
1384 return *m_rareNonInheritedData->m_animations;
1385 }
1386
1387 CSSTransitionData& ComputedStyle::accessTransitions()
1388 {
1389 if (!m_rareNonInheritedData.access()->m_transitions)
1390 m_rareNonInheritedData.access()->m_transitions = CSSTransitionData::crea te();
1391 return *m_rareNonInheritedData->m_transitions;
1392 }
1393
1394 const Font& ComputedStyle::font() const { return m_styleInheritedData->font; }
1395 const FontMetrics& ComputedStyle::getFontMetrics() const { return m_styleInherit edData->font.getFontMetrics(); }
1396 const FontDescription& ComputedStyle::getFontDescription() const { return m_styl eInheritedData->font.getFontDescription(); }
1397 float ComputedStyle::specifiedFontSize() const { return getFontDescription().spe cifiedSize(); }
1398 float ComputedStyle::computedFontSize() const { return getFontDescription().comp utedSize(); }
1399 int ComputedStyle::fontSize() const { return getFontDescription().computedPixelS ize(); }
1400 float ComputedStyle::fontSizeAdjust() const { return getFontDescription().sizeAd just(); }
1401 bool ComputedStyle::hasFontSizeAdjust() const { return getFontDescription().hasS izeAdjust(); }
1402 FontWeight ComputedStyle::fontWeight() const { return getFontDescription().weigh t(); }
1403 FontStretch ComputedStyle::fontStretch() const { return getFontDescription().str etch(); }
1404
1405 TextDecoration ComputedStyle::textDecorationsInEffect() const
1406 {
1407 int decorations = 0;
1408
1409 const Vector<AppliedTextDecoration>& applied = appliedTextDecorations();
1410
1411 for (size_t i = 0; i < applied.size(); ++i)
1412 decorations |= applied[i].line();
1413
1414 return static_cast<TextDecoration>(decorations);
1415 }
1416
1417 const Vector<AppliedTextDecoration>& ComputedStyle::appliedTextDecorations() con st
1418 {
1419 if (!m_inheritedData.m_textUnderline && !m_rareInheritedData->appliedTextDec orations) {
1420 DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, empty, ());
1421 return empty;
1422 }
1423 if (m_inheritedData.m_textUnderline) {
1424 DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, underline, (1, Applie dTextDecoration(TextDecorationUnderline)));
1425 return underline;
1426 }
1427
1428 return m_rareInheritedData->appliedTextDecorations->vector();
1429 }
1430
1431 StyleVariableData* ComputedStyle::variables() const
1432 {
1433 return m_rareInheritedData->variables.get();
1434 }
1435
1436 void ComputedStyle::setVariable(const AtomicString& name, PassRefPtr<CSSVariable Data> value)
1437 {
1438 RefPtr<StyleVariableData>& variables = m_rareInheritedData.access()->variabl es;
1439 if (!variables)
1440 variables = StyleVariableData::create();
1441 else if (!variables->hasOneRef())
1442 variables = variables->copy();
1443 variables->setVariable(name, std::move(value));
1444 }
1445
1446 void ComputedStyle::setRegisteredInheritedProperty(const AtomicString& name, con st CSSValue* parsedValue)
1447 {
1448 RefPtr<StyleVariableData>& variables = m_rareInheritedData.access()->variabl es;
1449 // The CSSVariableData needs to be set before calling this function
1450 DCHECK(variables);
1451 DCHECK(!!parsedValue == !!variables->getVariable(name));
1452 DCHECK(!(variables->getVariable(name) && variables->getVariable(name)->needs VariableResolution()));
1453
1454 if (!variables->hasOneRef())
1455 variables = variables->copy();
1456 variables->setRegisteredInheritedProperty(name, parsedValue);
1457 }
1458
1459 void ComputedStyle::removeVariable(const AtomicString& name)
1460 {
1461 RefPtr<StyleVariableData>& variables = m_rareInheritedData.access()->variabl es;
1462 if (!variables)
1463 return;
1464 if (!variables->hasOneRef())
1465 variables = variables->copy();
1466 variables->removeVariable(name);
1467 }
1468
1469 float ComputedStyle::wordSpacing() const { return getFontDescription().wordSpaci ng(); }
1470 float ComputedStyle::letterSpacing() const { return getFontDescription().letterS pacing(); }
1471
1472 bool ComputedStyle::setFontDescription(const FontDescription& v)
1473 {
1474 if (m_styleInheritedData->font.getFontDescription() != v) {
1475 m_styleInheritedData.access()->font = Font(v);
1476 return true;
1477 }
1478 return false;
1479 }
1480
1481 void ComputedStyle::setFont(const Font& font)
1482 {
1483 m_styleInheritedData.access()->font = font;
1484 }
1485
1486 const Length& ComputedStyle::specifiedLineHeight() const { return m_styleInherit edData->line_height; }
1487 Length ComputedStyle::lineHeight() const
1488 {
1489 const Length& lh = m_styleInheritedData->line_height;
1490 // Unlike getFontDescription().computedSize() and hence fontSize(), this is
1491 // recalculated on demand as we only store the specified line height.
1492 // FIXME: Should consider scaling the fixed part of any calc expressions
1493 // too, though this involves messily poking into CalcExpressionLength.
1494 if (lh.isFixed()) {
1495 float multiplier = textAutosizingMultiplier();
1496 return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multip lier), Fixed);
1497 }
1498
1499 return lh;
1500 }
1501
1502 void ComputedStyle::setLineHeight(const Length& specifiedLineHeight) { SET_VAR(m _styleInheritedData, line_height, specifiedLineHeight); }
1503
1504 int ComputedStyle::computedLineHeight() const
1505 {
1506 const Length& lh = lineHeight();
1507
1508 // Negative value means the line height is not set. Use the font's built-in
1509 // spacing, if avalible.
1510 if (lh.isNegative() && font().primaryFont())
1511 return getFontMetrics().lineSpacing();
1512
1513 if (lh.isPercentOrCalc())
1514 return minimumValueForLength(lh, LayoutUnit(computedFontSize())).toInt() ;
1515
1516 return std::min(lh.value(), LayoutUnit::max().toFloat());
1517 }
1518
1519 void ComputedStyle::setWordSpacing(float wordSpacing)
1520 {
1521 FontSelector* currentFontSelector = font().getFontSelector();
1522 FontDescription desc(getFontDescription());
1523 desc.setWordSpacing(wordSpacing);
1524 setFontDescription(desc);
1525 font().update(currentFontSelector);
1526 }
1527
1528 void ComputedStyle::setLetterSpacing(float letterSpacing)
1529 {
1530 FontSelector* currentFontSelector = font().getFontSelector();
1531 FontDescription desc(getFontDescription());
1532 desc.setLetterSpacing(letterSpacing);
1533 setFontDescription(desc);
1534 font().update(currentFontSelector);
1535 }
1536
1537 void ComputedStyle::setTextAutosizingMultiplier(float multiplier)
1538 {
1539 SET_VAR(m_styleInheritedData, textAutosizingMultiplier, multiplier);
1540
1541 float size = specifiedFontSize();
1542
1543 ASSERT(std::isfinite(size));
1544 if (!std::isfinite(size) || size < 0)
1545 size = 0;
1546 else
1547 size = std::min(maximumAllowedFontSize, size);
1548
1549 FontSelector* currentFontSelector = font().getFontSelector();
1550 FontDescription desc(getFontDescription());
1551 desc.setSpecifiedSize(size);
1552 desc.setComputedSize(size);
1553
1554 float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size, mult iplier);
1555 desc.setComputedSize(std::min(maximumAllowedFontSize, autosizedFontSize));
1556
1557 setFontDescription(desc);
1558 font().update(currentFontSelector);
1559 }
1560
1561 void ComputedStyle::addAppliedTextDecoration(const AppliedTextDecoration& decora tion)
1562 {
1563 RefPtr<AppliedTextDecorationList>& list = m_rareInheritedData.access()->appl iedTextDecorations;
1564
1565 if (!list)
1566 list = AppliedTextDecorationList::create();
1567 else if (!list->hasOneRef())
1568 list = list->copy();
1569
1570 if (m_inheritedData.m_textUnderline) {
1571 m_inheritedData.m_textUnderline = false;
1572 list->append(AppliedTextDecoration(TextDecorationUnderline));
1573 }
1574
1575 list->append(decoration);
1576 }
1577
1578 void ComputedStyle::applyTextDecorations()
1579 {
1580 if (getTextDecoration() == TextDecorationNone)
1581 return;
1582
1583 TextDecorationStyle style = getTextDecorationStyle();
1584 StyleColor styleColor = decorationColorIncludingFallback(insideLink() == Ins ideVisitedLink);
1585
1586 int decorations = getTextDecoration();
1587
1588 if (decorations & TextDecorationUnderline) {
1589 // To save memory, we don't use AppliedTextDecoration objects in the
1590 // common case of a single simple underline.
1591 AppliedTextDecoration underline(TextDecorationUnderline, style, styleCol or);
1592
1593 if (!m_rareInheritedData->appliedTextDecorations && underline.isSimpleUn derline())
1594 m_inheritedData.m_textUnderline = true;
1595 else
1596 addAppliedTextDecoration(underline);
1597 }
1598 if (decorations & TextDecorationOverline)
1599 addAppliedTextDecoration(AppliedTextDecoration(TextDecorationOverline, s tyle, styleColor));
1600 if (decorations & TextDecorationLineThrough)
1601 addAppliedTextDecoration(AppliedTextDecoration(TextDecorationLineThrough , style, styleColor));
1602 }
1603
1604 void ComputedStyle::clearAppliedTextDecorations()
1605 {
1606 m_inheritedData.m_textUnderline = false;
1607
1608 if (m_rareInheritedData->appliedTextDecorations)
1609 m_rareInheritedData.access()->appliedTextDecorations = nullptr;
1610 }
1611
1612 void ComputedStyle::restoreParentTextDecorations(const ComputedStyle& parentStyl e)
1613 {
1614 m_inheritedData.m_textUnderline = parentStyle.m_inheritedData.m_textUnderlin e;
1615 if (m_rareInheritedData->appliedTextDecorations != parentStyle.m_rareInherit edData->appliedTextDecorations)
1616 m_rareInheritedData.access()->appliedTextDecorations = parentStyle.m_rar eInheritedData->appliedTextDecorations;
1617 }
1618
1619 void ComputedStyle::clearMultiCol()
1620 {
1621 m_rareNonInheritedData.access()->m_multiCol = nullptr;
1622 m_rareNonInheritedData.access()->m_multiCol.init();
1623 }
1624
1625 StyleColor ComputedStyle::decorationColorIncludingFallback(bool visitedLink) con st 33 StyleColor ComputedStyle::decorationColorIncludingFallback(bool visitedLink) con st
1626 { 34 {
1627 StyleColor styleColor = visitedLink ? visitedLinkTextDecorationColor() : tex tDecorationColor(); 35 StyleColor styleColor = visitedLink ? visitedLinkTextDecorationColor() : tex tDecorationColor();
1628 36
1629 if (!styleColor.isCurrentColor()) 37 if (!styleColor.isCurrentColor())
1630 return styleColor; 38 return styleColor;
1631 39
1632 if (textStrokeWidth()) { 40 if (textStrokeWidth()) {
1633 // Prefer stroke color if possible, but not if it's fully transparent. 41 // Prefer stroke color if possible, but not if it's fully transparent.
1634 StyleColor textStrokeStyleColor = visitedLink ? visitedLinkTextStrokeCol or() : textStrokeColor(); 42 StyleColor textStrokeStyleColor = visitedLink ? visitedLinkTextDecoratio nColor() : textStrokeColor();
1635 if (!textStrokeStyleColor.isCurrentColor() && textStrokeStyleColor.getCo lor().alpha()) 43 if (!textStrokeStyleColor.isCurrentColor() && textStrokeStyleColor.getCo lor().alpha())
1636 return textStrokeStyleColor; 44 return textStrokeStyleColor;
1637 } 45 }
1638 46
1639 return visitedLink ? visitedLinkTextFillColor() : textFillColor(); 47 return visitedLink ? visitedLinkTextFillColor() : textFillColor();
1640 } 48 }
1641 49
1642 Color ComputedStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const 50 Color ComputedStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
1643 { 51 {
1644 StyleColor result(StyleColor::currentColor()); 52 StyleColor result(StyleColor::currentColor());
1645 EBorderStyle borderStyle = BorderStyleNone;
1646 switch (colorProperty) { 53 switch (colorProperty) {
1647 case CSSPropertyBackgroundColor: 54 case CSSPropertyWebkitTextFillColor: // XXX fails with the ternary but not without it
1648 result = visitedLink ? visitedLinkBackgroundColor() : backgroundColor();
1649 break;
1650 case CSSPropertyBorderLeftColor:
1651 result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
1652 borderStyle = borderLeftStyle();
1653 break;
1654 case CSSPropertyBorderRightColor:
1655 result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor( );
1656 borderStyle = borderRightStyle();
1657 break;
1658 case CSSPropertyBorderTopColor:
1659 result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
1660 borderStyle = borderTopStyle();
1661 break;
1662 case CSSPropertyBorderBottomColor:
1663 result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColo r();
1664 borderStyle = borderBottomStyle();
1665 break;
1666 case CSSPropertyColor:
1667 result = visitedLink ? visitedLinkColor() : color();
1668 break;
1669 case CSSPropertyOutlineColor:
1670 result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
1671 break;
1672 case CSSPropertyColumnRuleColor:
1673 result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
1674 break;
1675 case CSSPropertyWebkitTextEmphasisColor:
1676 result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColo r();
1677 break;
1678 case CSSPropertyWebkitTextFillColor:
1679 result = visitedLink ? visitedLinkTextFillColor() : textFillColor(); 55 result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
1680 break; 56 break;
1681 case CSSPropertyWebkitTextStrokeColor:
1682 result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
1683 break;
1684 case CSSPropertyFloodColor:
1685 result = floodColor();
1686 break;
1687 case CSSPropertyLightingColor:
1688 result = lightingColor();
1689 break;
1690 case CSSPropertyStopColor: 57 case CSSPropertyStopColor:
1691 result = stopColor(); 58 result = Color(244, 0, 0);
1692 break;
1693 case CSSPropertyWebkitTapHighlightColor:
1694 result = tapHighlightColor();
1695 break; 59 break;
1696 case CSSPropertyTextDecorationColor: 60 case CSSPropertyTextDecorationColor:
1697 result = decorationColorIncludingFallback(visitedLink); 61 result = decorationColorIncludingFallback(visitedLink);
1698 break; 62 break;
1699 default: 63 default:
1700 ASSERT_NOT_REACHED(); 64 //ASSERT_NOT_REACHED();
1701 break; 65 break;
1702 } 66 }
1703 67
68 //fprintf(stderr, "what %d %x\n", result.isCurrentColor(), result.resolve(Color( )).rgb()); // This also makes things go :-/
1704 if (!result.isCurrentColor()) 69 if (!result.isCurrentColor())
1705 return result.getColor(); 70 return result.getColor();
1706 71
1707 // FIXME: Treating styled borders with initial color differently causes prob lems 72 return secretColor();
1708 // See crbug.com/316559, crbug.com/276231 73 //return Color(0xffff0000); // passes with this
1709 if (!visitedLink && (borderStyle == BorderStyleInset || borderStyle == Borde rStyleOutset || borderStyle == BorderStyleRidge || borderStyle == BorderStyleGro ove)) 74 //return Color(); // passes with this too??
1710 return Color(238, 238, 238);
1711 return visitedLink ? visitedLinkColor() : color();
1712 }
1713
1714 Color ComputedStyle::visitedDependentColor(int colorProperty) const
1715 {
1716 Color unvisitedColor = colorIncludingFallback(colorProperty, false);
1717 if (insideLink() != InsideVisitedLink)
1718 return unvisitedColor;
1719
1720 Color visitedColor = colorIncludingFallback(colorProperty, true);
1721
1722 // FIXME: Technically someone could explicitly specify the color transparent , but for now we'll just
1723 // assume that if the background color is transparent that it wasn't set. No te that it's weird that
1724 // we're returning unvisited info for a visited link, but given our restrict ion that the alpha values
1725 // have to match, it makes more sense to return the unvisited background col or if specified than it
1726 // does to return black. This behavior matches what Firefox 4 does as well.
1727 if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::tr ansparent)
1728 return unvisitedColor;
1729
1730 // Take the alpha from the unvisited color, but get the RGB values from the visited color.
1731 return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
1732 }
1733
1734 const BorderValue& ComputedStyle::borderBefore() const
1735 {
1736 switch (getWritingMode()) {
1737 case TopToBottomWritingMode:
1738 return borderTop();
1739 case LeftToRightWritingMode:
1740 return borderLeft();
1741 case RightToLeftWritingMode:
1742 return borderRight();
1743 }
1744 ASSERT_NOT_REACHED();
1745 return borderTop();
1746 }
1747
1748 const BorderValue& ComputedStyle::borderAfter() const
1749 {
1750 switch (getWritingMode()) {
1751 case TopToBottomWritingMode:
1752 return borderBottom();
1753 case LeftToRightWritingMode:
1754 return borderRight();
1755 case RightToLeftWritingMode:
1756 return borderLeft();
1757 }
1758 ASSERT_NOT_REACHED();
1759 return borderBottom();
1760 }
1761
1762 const BorderValue& ComputedStyle::borderStart() const
1763 {
1764 if (isHorizontalWritingMode())
1765 return isLeftToRightDirection() ? borderLeft() : borderRight();
1766 return isLeftToRightDirection() ? borderTop() : borderBottom();
1767 }
1768
1769 const BorderValue& ComputedStyle::borderEnd() const
1770 {
1771 if (isHorizontalWritingMode())
1772 return isLeftToRightDirection() ? borderRight() : borderLeft();
1773 return isLeftToRightDirection() ? borderBottom() : borderTop();
1774 }
1775
1776 int ComputedStyle::borderBeforeWidth() const
1777 {
1778 switch (getWritingMode()) {
1779 case TopToBottomWritingMode:
1780 return borderTopWidth();
1781 case LeftToRightWritingMode:
1782 return borderLeftWidth();
1783 case RightToLeftWritingMode:
1784 return borderRightWidth();
1785 }
1786 ASSERT_NOT_REACHED();
1787 return borderTopWidth();
1788 }
1789
1790 int ComputedStyle::borderAfterWidth() const
1791 {
1792 switch (getWritingMode()) {
1793 case TopToBottomWritingMode:
1794 return borderBottomWidth();
1795 case LeftToRightWritingMode:
1796 return borderRightWidth();
1797 case RightToLeftWritingMode:
1798 return borderLeftWidth();
1799 }
1800 ASSERT_NOT_REACHED();
1801 return borderBottomWidth();
1802 }
1803
1804 int ComputedStyle::borderStartWidth() const
1805 {
1806 if (isHorizontalWritingMode())
1807 return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth() ;
1808 return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
1809 }
1810
1811 int ComputedStyle::borderEndWidth() const
1812 {
1813 if (isHorizontalWritingMode())
1814 return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth() ;
1815 return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
1816 }
1817
1818 int ComputedStyle::borderOverWidth() const
1819 {
1820 return isHorizontalWritingMode() ? borderTopWidth() : borderRightWidth();
1821 }
1822
1823 int ComputedStyle::borderUnderWidth() const
1824 {
1825 return isHorizontalWritingMode() ? borderBottomWidth() : borderLeftWidth();
1826 }
1827
1828 void ComputedStyle::setMarginStart(const Length& margin)
1829 {
1830 if (isHorizontalWritingMode()) {
1831 if (isLeftToRightDirection())
1832 setMarginLeft(margin);
1833 else
1834 setMarginRight(margin);
1835 } else {
1836 if (isLeftToRightDirection())
1837 setMarginTop(margin);
1838 else
1839 setMarginBottom(margin);
1840 }
1841 }
1842
1843 void ComputedStyle::setMarginEnd(const Length& margin)
1844 {
1845 if (isHorizontalWritingMode()) {
1846 if (isLeftToRightDirection())
1847 setMarginRight(margin);
1848 else
1849 setMarginLeft(margin);
1850 } else {
1851 if (isLeftToRightDirection())
1852 setMarginBottom(margin);
1853 else
1854 setMarginTop(margin);
1855 }
1856 }
1857
1858 void ComputedStyle::setMotionPath(PassRefPtr<StylePath> path)
1859 {
1860 m_rareNonInheritedData.access()->m_transform.access()->m_motion.m_path = pat h;
1861 }
1862
1863 int ComputedStyle::outlineOutsetExtent() const
1864 {
1865 if (!hasOutline())
1866 return 0;
1867 if (outlineStyleIsAuto())
1868 return GraphicsContext::focusRingOutsetExtent(outlineOffset(), outlineWi dth());
1869 return std::max(0, saturatedAddition(outlineWidth(), outlineOffset()));
1870 }
1871
1872 bool ComputedStyle::columnRuleEquivalent(const ComputedStyle* otherStyle) const
1873 {
1874 return columnRuleStyle() == otherStyle->columnRuleStyle()
1875 && columnRuleWidth() == otherStyle->columnRuleWidth()
1876 && visitedDependentColor(CSSPropertyColumnRuleColor) == otherStyle->visi tedDependentColor(CSSPropertyColumnRuleColor);
1877 }
1878
1879 TextEmphasisMark ComputedStyle::getTextEmphasisMark() const
1880 {
1881 TextEmphasisMark mark = static_cast<TextEmphasisMark>(m_rareInheritedData->t extEmphasisMark);
1882 if (mark != TextEmphasisMarkAuto)
1883 return mark;
1884
1885 if (isHorizontalWritingMode())
1886 return TextEmphasisMarkDot;
1887
1888 return TextEmphasisMarkSesame;
1889 }
1890
1891 Color ComputedStyle::initialTapHighlightColor()
1892 {
1893 return LayoutTheme::tapHighlightColor();
1894 }
1895
1896 const FilterOperations& ComputedStyle::initialFilter()
1897 {
1898 DEFINE_STATIC_LOCAL(FilterOperationsWrapper, ops, (FilterOperationsWrapper:: create()));
1899 return ops.operations();
1900 }
1901
1902 const FilterOperations& ComputedStyle::initialBackdropFilter()
1903 {
1904 DEFINE_STATIC_LOCAL(FilterOperationsWrapper, ops, (FilterOperationsWrapper:: create()));
1905 return ops.operations();
1906 }
1907
1908 LayoutRectOutsets ComputedStyle::imageOutsets(const NinePieceImage& image) const
1909 {
1910 return LayoutRectOutsets(
1911 NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()),
1912 NinePieceImage::computeOutset(image.outset().right(), borderRightWidth() ),
1913 NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth ()),
1914 NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth())) ;
1915 }
1916
1917 void ComputedStyle::setBorderImageSource(StyleImage* image)
1918 {
1919 if (m_surround->border.m_image.image() == image)
1920 return;
1921 m_surround.access()->border.m_image.setImage(image);
1922 }
1923
1924 void ComputedStyle::setBorderImageSlices(const LengthBox& slices)
1925 {
1926 if (m_surround->border.m_image.imageSlices() == slices)
1927 return;
1928 m_surround.access()->border.m_image.setImageSlices(slices);
1929 }
1930
1931 void ComputedStyle::setBorderImageSlicesFill(bool fill)
1932 {
1933 if (m_surround->border.m_image.fill() == fill)
1934 return;
1935 m_surround.access()->border.m_image.setFill(fill);
1936 }
1937
1938 void ComputedStyle::setBorderImageWidth(const BorderImageLengthBox& slices)
1939 {
1940 if (m_surround->border.m_image.borderSlices() == slices)
1941 return;
1942 m_surround.access()->border.m_image.setBorderSlices(slices);
1943 }
1944
1945 void ComputedStyle::setBorderImageOutset(const BorderImageLengthBox& outset)
1946 {
1947 if (m_surround->border.m_image.outset() == outset)
1948 return;
1949 m_surround.access()->border.m_image.setOutset(outset);
1950 }
1951
1952 bool ComputedStyle::borderObscuresBackground() const
1953 {
1954 if (!hasBorder())
1955 return false;
1956
1957 // Bail if we have any border-image for now. We could look at the image alph a to improve this.
1958 if (borderImage().image())
1959 return false;
1960
1961 BorderEdge edges[4];
1962 getBorderEdgeInfo(edges);
1963
1964 for (int i = BSTop; i <= BSLeft; ++i) {
1965 const BorderEdge& currEdge = edges[i];
1966 if (!currEdge.obscuresBackground())
1967 return false;
1968 }
1969
1970 return true;
1971 }
1972
1973 void ComputedStyle::getBorderEdgeInfo(BorderEdge edges[], bool includeLogicalLef tEdge, bool includeLogicalRightEdge) const
1974 {
1975 bool horizontal = isHorizontalWritingMode();
1976
1977 edges[BSTop] = BorderEdge(borderTopWidth(),
1978 visitedDependentColor(CSSPropertyBorderTopColor),
1979 borderTopStyle(),
1980 horizontal || includeLogicalLeftEdge);
1981
1982 edges[BSRight] = BorderEdge(borderRightWidth(),
1983 visitedDependentColor(CSSPropertyBorderRightColor),
1984 borderRightStyle(),
1985 !horizontal || includeLogicalRightEdge);
1986
1987 edges[BSBottom] = BorderEdge(borderBottomWidth(),
1988 visitedDependentColor(CSSPropertyBorderBottomColor),
1989 borderBottomStyle(),
1990 horizontal || includeLogicalRightEdge);
1991
1992 edges[BSLeft] = BorderEdge(borderLeftWidth(),
1993 visitedDependentColor(CSSPropertyBorderLeftColor),
1994 borderLeftStyle(),
1995 !horizontal || includeLogicalLeftEdge);
1996 }
1997
1998 void ComputedStyle::copyChildDependentFlagsFrom(const ComputedStyle& other)
1999 {
2000 setEmptyState(other.emptyState());
2001 if (other.hasExplicitlyInheritedProperties())
2002 setHasExplicitlyInheritedProperties();
2003 }
2004
2005 bool ComputedStyle::shadowListHasCurrentColor(const ShadowList* shadowList)
2006 {
2007 if (!shadowList)
2008 return false;
2009 for (size_t i = shadowList->shadows().size(); i--; ) {
2010 if (shadowList->shadows()[i].color().isCurrentColor())
2011 return true;
2012 }
2013 return false;
2014 }
2015
2016 static inline Vector<GridTrackSize> initialGridAutoTracks()
2017 {
2018 Vector<GridTrackSize> trackSizeList;
2019 trackSizeList.reserveInitialCapacity(1);
2020 trackSizeList.uncheckedAppend(GridTrackSize(Length(Auto)));
2021 return trackSizeList;
2022 }
2023
2024 Vector<GridTrackSize> ComputedStyle::initialGridAutoColumns()
2025 {
2026 return initialGridAutoTracks();
2027 }
2028
2029 Vector<GridTrackSize> ComputedStyle::initialGridAutoRows()
2030 {
2031 return initialGridAutoTracks();
2032 }
2033
2034 int adjustForAbsoluteZoom(int value, float zoomFactor)
2035 {
2036 if (zoomFactor == 1)
2037 return value;
2038 // Needed because computeLengthInt truncates (rather than rounds) when scali ng up.
2039 float fvalue = value;
2040 if (zoomFactor > 1) {
2041 if (value < 0)
2042 fvalue -= 0.5f;
2043 else
2044 fvalue += 0.5f;
2045 }
2046
2047 return roundForImpreciseConversion<int>(fvalue / zoomFactor);
2048 } 75 }
2049 76
2050 } // namespace blink 77 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/style/ComputedStyle.h ('k') | third_party/WebKit/Source/core/style/DataRef.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698