| OLD | NEW |
| 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 |
| OLD | NEW |