| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org) | |
| 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights
reserved. | |
| 4 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. | |
| 5 * | |
| 6 * This library is free software; you can redistribute it and/or | |
| 7 * modify it under the terms of the GNU Library General Public | |
| 8 * License as published by the Free Software Foundation; either | |
| 9 * version 2 of the License, or (at your option) any later version. | |
| 10 * | |
| 11 * This library is distributed in the hope that it will be useful, | |
| 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 14 * Library General Public License for more details. | |
| 15 * | |
| 16 * You should have received a copy of the GNU Library General Public License | |
| 17 * along with this library; see the file COPYING.LIB. If not, write to | |
| 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
| 19 * Boston, MA 02110-1301, USA. | |
| 20 * | |
| 21 */ | |
| 22 | |
| 23 #include "config.h" | |
| 24 #include "core/layout/style/LayoutStyle.h" | |
| 25 | |
| 26 #include "core/css/resolver/StyleResolver.h" | |
| 27 #include "core/layout/LayoutTheme.h" | |
| 28 #include "core/layout/TextAutosizer.h" | |
| 29 #include "core/layout/style/AppliedTextDecoration.h" | |
| 30 #include "core/layout/style/BorderEdge.h" | |
| 31 #include "core/layout/style/ContentData.h" | |
| 32 #include "core/layout/style/DataEquivalency.h" | |
| 33 #include "core/layout/style/LayoutStyleConstants.h" | |
| 34 #include "core/layout/style/PathStyleMotionPath.h" | |
| 35 #include "core/layout/style/QuotesData.h" | |
| 36 #include "core/layout/style/ShadowList.h" | |
| 37 #include "core/layout/style/StyleImage.h" | |
| 38 #include "core/layout/style/StyleInheritedData.h" | |
| 39 #include "platform/LengthFunctions.h" | |
| 40 #include "platform/RuntimeEnabledFeatures.h" | |
| 41 #include "platform/fonts/Font.h" | |
| 42 #include "platform/fonts/FontSelector.h" | |
| 43 #include "platform/geometry/FloatRoundedRect.h" | |
| 44 #include "wtf/MathExtras.h" | |
| 45 | |
| 46 #include <algorithm> | |
| 47 | |
| 48 namespace blink { | |
| 49 | |
| 50 struct SameSizeAsBorderValue { | |
| 51 RGBA32 m_color; | |
| 52 unsigned m_width; | |
| 53 }; | |
| 54 | |
| 55 static_assert(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), "BorderValue
should stay small"); | |
| 56 | |
| 57 struct SameSizeAsLayoutStyle : public RefCounted<SameSizeAsLayoutStyle> { | |
| 58 void* dataRefs[7]; | |
| 59 void* ownPtrs[1]; | |
| 60 void* dataRefSvgStyle; | |
| 61 | |
| 62 struct InheritedFlags { | |
| 63 unsigned m_bitfields[2]; | |
| 64 } inherited_flags; | |
| 65 | |
| 66 struct NonInheritedFlags { | |
| 67 unsigned m_bitfields[2]; | |
| 68 } noninherited_flags; | |
| 69 }; | |
| 70 | |
| 71 static_assert(sizeof(LayoutStyle) == sizeof(SameSizeAsLayoutStyle), "LayoutStyle
should stay small"); | |
| 72 | |
| 73 PassRefPtr<LayoutStyle> LayoutStyle::create() | |
| 74 { | |
| 75 return adoptRef(new LayoutStyle()); | |
| 76 } | |
| 77 | |
| 78 PassRefPtr<LayoutStyle> LayoutStyle::createInitialStyle() | |
| 79 { | |
| 80 return adoptRef(new LayoutStyle(InitialStyle)); | |
| 81 } | |
| 82 | |
| 83 PassRefPtr<LayoutStyle> LayoutStyle::createAnonymousStyleWithDisplay(const Layou
tStyle& parentStyle, EDisplay display) | |
| 84 { | |
| 85 RefPtr<LayoutStyle> newStyle = LayoutStyle::create(); | |
| 86 newStyle->inheritFrom(parentStyle); | |
| 87 newStyle->inheritUnicodeBidiFrom(parentStyle); | |
| 88 newStyle->setDisplay(display); | |
| 89 return newStyle; | |
| 90 } | |
| 91 | |
| 92 PassRefPtr<LayoutStyle> LayoutStyle::clone(const LayoutStyle& other) | |
| 93 { | |
| 94 return adoptRef(new LayoutStyle(other)); | |
| 95 } | |
| 96 | |
| 97 ALWAYS_INLINE LayoutStyle::LayoutStyle() | |
| 98 : m_box(initialStyle()->m_box) | |
| 99 , visual(initialStyle()->visual) | |
| 100 , m_background(initialStyle()->m_background) | |
| 101 , surround(initialStyle()->surround) | |
| 102 , rareNonInheritedData(initialStyle()->rareNonInheritedData) | |
| 103 , rareInheritedData(initialStyle()->rareInheritedData) | |
| 104 , inherited(initialStyle()->inherited) | |
| 105 , m_svgStyle(initialStyle()->m_svgStyle) | |
| 106 { | |
| 107 setBitDefaults(); // Would it be faster to copy this from the default style? | |
| 108 static_assert((sizeof(InheritedFlags) <= 8), "InheritedFlags should not grow
"); | |
| 109 static_assert((sizeof(NonInheritedFlags) <= 8), "NonInheritedFlags should no
t grow"); | |
| 110 } | |
| 111 | |
| 112 ALWAYS_INLINE LayoutStyle::LayoutStyle(InitialStyleTag) | |
| 113 { | |
| 114 setBitDefaults(); | |
| 115 | |
| 116 m_box.init(); | |
| 117 visual.init(); | |
| 118 m_background.init(); | |
| 119 surround.init(); | |
| 120 rareNonInheritedData.init(); | |
| 121 rareNonInheritedData.access()->m_deprecatedFlexibleBox.init(); | |
| 122 rareNonInheritedData.access()->m_flexibleBox.init(); | |
| 123 rareNonInheritedData.access()->m_multiCol.init(); | |
| 124 rareNonInheritedData.access()->m_transform.init(); | |
| 125 rareNonInheritedData.access()->m_willChange.init(); | |
| 126 rareNonInheritedData.access()->m_filter.init(); | |
| 127 rareNonInheritedData.access()->m_grid.init(); | |
| 128 rareNonInheritedData.access()->m_gridItem.init(); | |
| 129 rareInheritedData.init(); | |
| 130 inherited.init(); | |
| 131 m_svgStyle.init(); | |
| 132 } | |
| 133 | |
| 134 ALWAYS_INLINE LayoutStyle::LayoutStyle(const LayoutStyle& o) | |
| 135 : RefCounted<LayoutStyle>() | |
| 136 , m_box(o.m_box) | |
| 137 , visual(o.visual) | |
| 138 , m_background(o.m_background) | |
| 139 , surround(o.surround) | |
| 140 , rareNonInheritedData(o.rareNonInheritedData) | |
| 141 , rareInheritedData(o.rareInheritedData) | |
| 142 , inherited(o.inherited) | |
| 143 , m_svgStyle(o.m_svgStyle) | |
| 144 , inherited_flags(o.inherited_flags) | |
| 145 , noninherited_flags(o.noninherited_flags) | |
| 146 { | |
| 147 } | |
| 148 | |
| 149 static StyleRecalcChange diffPseudoStyles(const LayoutStyle& oldStyle, const Lay
outStyle& newStyle) | |
| 150 { | |
| 151 // If the pseudoStyles have changed, we want any StyleRecalcChange that is n
ot NoChange | |
| 152 // because setStyle will do the right thing with anything else. | |
| 153 if (!oldStyle.hasAnyPublicPseudoStyles()) | |
| 154 return NoChange; | |
| 155 for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < FIRST_INTERNAL_PS
EUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) { | |
| 156 if (!oldStyle.hasPseudoStyle(pseudoId)) | |
| 157 continue; | |
| 158 const LayoutStyle* newPseudoStyle = newStyle.getCachedPseudoStyle(pseudo
Id); | |
| 159 if (!newPseudoStyle) | |
| 160 return NoInherit; | |
| 161 const LayoutStyle* oldPseudoStyle = oldStyle.getCachedPseudoStyle(pseudo
Id); | |
| 162 if (oldPseudoStyle && *oldPseudoStyle != *newPseudoStyle) | |
| 163 return NoInherit; | |
| 164 } | |
| 165 return NoChange; | |
| 166 } | |
| 167 | |
| 168 StyleRecalcChange LayoutStyle::stylePropagationDiff(const LayoutStyle* oldStyle,
const LayoutStyle* newStyle) | |
| 169 { | |
| 170 if ((!oldStyle && newStyle) || (oldStyle && !newStyle)) | |
| 171 return Reattach; | |
| 172 | |
| 173 if (!oldStyle && !newStyle) | |
| 174 return NoChange; | |
| 175 | |
| 176 if (oldStyle->display() != newStyle->display() | |
| 177 || oldStyle->hasPseudoStyle(FIRST_LETTER) != newStyle->hasPseudoStyle(FI
RST_LETTER) | |
| 178 || oldStyle->columnSpan() != newStyle->columnSpan() | |
| 179 || !oldStyle->contentDataEquivalent(newStyle) | |
| 180 || oldStyle->hasTextCombine() != newStyle->hasTextCombine() | |
| 181 || oldStyle->justifyItems() != newStyle->justifyItems() | |
| 182 || oldStyle->alignItems() != newStyle->alignItems()) | |
| 183 return Reattach; | |
| 184 | |
| 185 if (oldStyle->inheritedNotEqual(*newStyle)) | |
| 186 return Inherit; | |
| 187 | |
| 188 if (*oldStyle == *newStyle) | |
| 189 return diffPseudoStyles(*oldStyle, *newStyle); | |
| 190 | |
| 191 if (oldStyle->hasExplicitlyInheritedProperties()) | |
| 192 return Inherit; | |
| 193 | |
| 194 return NoInherit; | |
| 195 } | |
| 196 | |
| 197 ItemPosition LayoutStyle::resolveAlignment(const LayoutStyle& parentStyle, const
LayoutStyle& childStyle, ItemPosition resolvedAutoPositionForLayoutObject) | |
| 198 { | |
| 199 // The auto keyword computes to the parent's align-items computed value, or
to "stretch", if not set or "auto". | |
| 200 if (childStyle.alignSelf() == ItemPositionAuto) | |
| 201 return (parentStyle.alignItems() == ItemPositionAuto) ? resolvedAutoPosi
tionForLayoutObject : parentStyle.alignItems(); | |
| 202 return childStyle.alignSelf(); | |
| 203 } | |
| 204 | |
| 205 ItemPosition LayoutStyle::resolveJustification(const LayoutStyle& parentStyle, c
onst LayoutStyle& childStyle, ItemPosition resolvedAutoPositionForLayoutObject) | |
| 206 { | |
| 207 if (childStyle.justifySelf() == ItemPositionAuto) | |
| 208 return (parentStyle.justifyItems() == ItemPositionAuto) ? resolvedAutoPo
sitionForLayoutObject : parentStyle.justifyItems(); | |
| 209 return childStyle.justifySelf(); | |
| 210 } | |
| 211 | |
| 212 void LayoutStyle::inheritFrom(const LayoutStyle& inheritParent, IsAtShadowBounda
ry isAtShadowBoundary) | |
| 213 { | |
| 214 if (isAtShadowBoundary == AtShadowBoundary) { | |
| 215 // Even if surrounding content is user-editable, shadow DOM should act a
s a single unit, and not necessarily be editable | |
| 216 EUserModify currentUserModify = userModify(); | |
| 217 rareInheritedData = inheritParent.rareInheritedData; | |
| 218 setUserModify(currentUserModify); | |
| 219 } else { | |
| 220 rareInheritedData = inheritParent.rareInheritedData; | |
| 221 } | |
| 222 inherited = inheritParent.inherited; | |
| 223 inherited_flags = inheritParent.inherited_flags; | |
| 224 if (m_svgStyle != inheritParent.m_svgStyle) | |
| 225 m_svgStyle.access()->inheritFrom(inheritParent.m_svgStyle.get()); | |
| 226 } | |
| 227 | |
| 228 void LayoutStyle::copyNonInheritedFromCached(const LayoutStyle& other) | |
| 229 { | |
| 230 m_box = other.m_box; | |
| 231 visual = other.visual; | |
| 232 m_background = other.m_background; | |
| 233 surround = other.surround; | |
| 234 rareNonInheritedData = other.rareNonInheritedData; | |
| 235 | |
| 236 // The flags are copied one-by-one because noninherited_flags contains a bun
ch of stuff other than real style data. | |
| 237 // See comments for each skipped flag below. | |
| 238 noninherited_flags.effectiveDisplay = other.noninherited_flags.effectiveDisp
lay; | |
| 239 noninherited_flags.originalDisplay = other.noninherited_flags.originalDispla
y; | |
| 240 noninherited_flags.overflowX = other.noninherited_flags.overflowX; | |
| 241 noninherited_flags.overflowY = other.noninherited_flags.overflowY; | |
| 242 noninherited_flags.verticalAlign = other.noninherited_flags.verticalAlign; | |
| 243 noninherited_flags.clear = other.noninherited_flags.clear; | |
| 244 noninherited_flags.position = other.noninherited_flags.position; | |
| 245 noninherited_flags.floating = other.noninherited_flags.floating; | |
| 246 noninherited_flags.tableLayout = other.noninherited_flags.tableLayout; | |
| 247 noninherited_flags.unicodeBidi = other.noninherited_flags.unicodeBidi; | |
| 248 noninherited_flags.hasViewportUnits = other.noninherited_flags.hasViewportUn
its; | |
| 249 noninherited_flags.pageBreakBefore = other.noninherited_flags.pageBreakBefor
e; | |
| 250 noninherited_flags.pageBreakAfter = other.noninherited_flags.pageBreakAfter; | |
| 251 noninherited_flags.pageBreakInside = other.noninherited_flags.pageBreakInsid
e; | |
| 252 | |
| 253 // Correctly set during selector matching: | |
| 254 // noninherited_flags.styleType | |
| 255 // noninherited_flags.pseudoBits | |
| 256 | |
| 257 // Set correctly while computing style for children: | |
| 258 // noninherited_flags.explicitInheritance | |
| 259 | |
| 260 // unique() styles are not cacheable. | |
| 261 ASSERT(!other.noninherited_flags.unique); | |
| 262 | |
| 263 // The following flags are set during matching before we decide that we get
a | |
| 264 // match in the MatchedPropertiesCache which in turn calls this method. The | |
| 265 // reason why we don't copy these flags is that they're already correctly se
t | |
| 266 // and that they may differ between elements which have the same set of matc
hed | |
| 267 // properties. For instance, given the rule: | |
| 268 // | |
| 269 // :-webkit-any(:hover, :focus) { background-color: green }" | |
| 270 // | |
| 271 // A hovered element, and a focused element may use the same cached matched | |
| 272 // properties here, but the affectedBy flags will be set differently based o
n | |
| 273 // the matching order of the :-webkit-any components. | |
| 274 // | |
| 275 // noninherited_flags.emptyState | |
| 276 // noninherited_flags.affectedByFocus | |
| 277 // noninherited_flags.affectedByHover | |
| 278 // noninherited_flags.affectedByActive | |
| 279 // noninherited_flags.affectedByDrag | |
| 280 // noninherited_flags.isLink | |
| 281 | |
| 282 if (m_svgStyle != other.m_svgStyle) | |
| 283 m_svgStyle.access()->copyNonInheritedFromCached(other.m_svgStyle.get()); | |
| 284 ASSERT(zoom() == initialZoom()); | |
| 285 } | |
| 286 | |
| 287 bool LayoutStyle::operator==(const LayoutStyle& o) const | |
| 288 { | |
| 289 // compare everything except the pseudoStyle pointer | |
| 290 return inherited_flags == o.inherited_flags | |
| 291 && noninherited_flags == o.noninherited_flags | |
| 292 && m_box == o.m_box | |
| 293 && visual == o.visual | |
| 294 && m_background == o.m_background | |
| 295 && surround == o.surround | |
| 296 && rareNonInheritedData == o.rareNonInheritedData | |
| 297 && rareInheritedData == o.rareInheritedData | |
| 298 && inherited == o.inherited | |
| 299 && m_svgStyle == o.m_svgStyle; | |
| 300 } | |
| 301 | |
| 302 bool LayoutStyle::isStyleAvailable() const | |
| 303 { | |
| 304 return this != StyleResolver::styleNotYetAvailable(); | |
| 305 } | |
| 306 | |
| 307 bool LayoutStyle::hasUniquePseudoStyle() const | |
| 308 { | |
| 309 if (!m_cachedPseudoStyles || styleType() != NOPSEUDO) | |
| 310 return false; | |
| 311 | |
| 312 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) { | |
| 313 const LayoutStyle& pseudoStyle = *m_cachedPseudoStyles->at(i); | |
| 314 if (pseudoStyle.unique()) | |
| 315 return true; | |
| 316 } | |
| 317 | |
| 318 return false; | |
| 319 } | |
| 320 | |
| 321 LayoutStyle* LayoutStyle::getCachedPseudoStyle(PseudoId pid) const | |
| 322 { | |
| 323 if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size()) | |
| 324 return 0; | |
| 325 | |
| 326 if (styleType() != NOPSEUDO) | |
| 327 return 0; | |
| 328 | |
| 329 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) { | |
| 330 LayoutStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get(); | |
| 331 if (pseudoStyle->styleType() == pid) | |
| 332 return pseudoStyle; | |
| 333 } | |
| 334 | |
| 335 return 0; | |
| 336 } | |
| 337 | |
| 338 LayoutStyle* LayoutStyle::addCachedPseudoStyle(PassRefPtr<LayoutStyle> pseudo) | |
| 339 { | |
| 340 if (!pseudo) | |
| 341 return 0; | |
| 342 | |
| 343 ASSERT(pseudo->styleType() > NOPSEUDO); | |
| 344 | |
| 345 LayoutStyle* result = pseudo.get(); | |
| 346 | |
| 347 if (!m_cachedPseudoStyles) | |
| 348 m_cachedPseudoStyles = adoptPtr(new PseudoStyleCache); | |
| 349 | |
| 350 m_cachedPseudoStyles->append(pseudo); | |
| 351 | |
| 352 return result; | |
| 353 } | |
| 354 | |
| 355 void LayoutStyle::removeCachedPseudoStyle(PseudoId pid) | |
| 356 { | |
| 357 if (!m_cachedPseudoStyles) | |
| 358 return; | |
| 359 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) { | |
| 360 LayoutStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get(); | |
| 361 if (pseudoStyle->styleType() == pid) { | |
| 362 m_cachedPseudoStyles->remove(i); | |
| 363 return; | |
| 364 } | |
| 365 } | |
| 366 } | |
| 367 | |
| 368 bool LayoutStyle::inheritedNotEqual(const LayoutStyle& other) const | |
| 369 { | |
| 370 return inherited_flags != other.inherited_flags | |
| 371 || inherited != other.inherited | |
| 372 || font().loadingCustomFonts() != other.font().loadingCustomFonts() | |
| 373 || m_svgStyle->inheritedNotEqual(other.m_svgStyle.get()) | |
| 374 || rareInheritedData != other.rareInheritedData; | |
| 375 } | |
| 376 | |
| 377 bool LayoutStyle::inheritedDataShared(const LayoutStyle& other) const | |
| 378 { | |
| 379 // This is a fast check that only looks if the data structures are shared. | |
| 380 return inherited_flags == other.inherited_flags | |
| 381 && inherited.get() == other.inherited.get() | |
| 382 && m_svgStyle.get() == other.m_svgStyle.get() | |
| 383 && rareInheritedData.get() == other.rareInheritedData.get(); | |
| 384 } | |
| 385 | |
| 386 static bool dependenceOnContentHeightHasChanged(const LayoutStyle& a, const Layo
utStyle& b) | |
| 387 { | |
| 388 // If top or bottom become auto/non-auto then it means we either have to sol
ve height based | |
| 389 // on the content or stop doing so (http://www.w3.org/TR/CSS2/visudet.html#a
bs-non-replaced-height) | |
| 390 // - either way requires a layout. | |
| 391 return a.logicalTop().isAuto() != b.logicalTop().isAuto() || a.logicalBottom
().isAuto() != b.logicalBottom().isAuto(); | |
| 392 } | |
| 393 | |
| 394 StyleDifference LayoutStyle::visualInvalidationDiff(const LayoutStyle& other) co
nst | |
| 395 { | |
| 396 // Note, we use .get() on each DataRef below because DataRef::operator== wil
l do a deep | |
| 397 // compare, which is duplicate work when we're going to compare each propert
y inside | |
| 398 // this function anyway. | |
| 399 | |
| 400 StyleDifference diff; | |
| 401 if (m_svgStyle.get() != other.m_svgStyle.get()) | |
| 402 diff = m_svgStyle->diff(other.m_svgStyle.get()); | |
| 403 | |
| 404 if ((!diff.needsFullLayout() || !diff.needsPaintInvalidation()) && diffNeeds
FullLayoutAndPaintInvalidation(other)) { | |
| 405 diff.setNeedsFullLayout(); | |
| 406 diff.setNeedsPaintInvalidationObject(); | |
| 407 } | |
| 408 | |
| 409 if (!diff.needsFullLayout() && diffNeedsFullLayout(other)) | |
| 410 diff.setNeedsFullLayout(); | |
| 411 | |
| 412 if (!diff.needsFullLayout() && surround->margin != other.surround->margin) { | |
| 413 // Relative-positioned elements collapse their margins so need a full la
yout. | |
| 414 if (position() == AbsolutePosition || position() == FixedPosition) | |
| 415 diff.setNeedsPositionedMovementLayout(); | |
| 416 else | |
| 417 diff.setNeedsFullLayout(); | |
| 418 } | |
| 419 | |
| 420 if (!diff.needsFullLayout() && position() != StaticPosition && surround->off
set != other.surround->offset) { | |
| 421 // Optimize for the case where a positioned layer is moving but not chan
ging size. | |
| 422 if (dependenceOnContentHeightHasChanged(*this, other)) | |
| 423 diff.setNeedsFullLayout(); | |
| 424 else | |
| 425 diff.setNeedsPositionedMovementLayout(); | |
| 426 } | |
| 427 | |
| 428 if (diffNeedsPaintInvalidationLayer(other)) | |
| 429 diff.setNeedsPaintInvalidationLayer(); | |
| 430 else if (diffNeedsPaintInvalidationObject(other)) | |
| 431 diff.setNeedsPaintInvalidationObject(); | |
| 432 | |
| 433 updatePropertySpecificDifferences(other, diff); | |
| 434 | |
| 435 // Cursors are not checked, since they will be set appropriately in response
to mouse events, | |
| 436 // so they don't need to cause any paint invalidation or layout. | |
| 437 | |
| 438 // 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 | |
| 439 // the resulting transition properly. | |
| 440 | |
| 441 return diff; | |
| 442 } | |
| 443 | |
| 444 bool LayoutStyle::diffNeedsFullLayoutAndPaintInvalidation(const LayoutStyle& oth
er) const | |
| 445 { | |
| 446 // FIXME: Not all cases in this method need both full layout and paint inval
idation. | |
| 447 // Should move cases into diffNeedsFullLayout() if | |
| 448 // - don't need paint invalidation at all; | |
| 449 // - or the layoutObject knows how to exactly invalidate paints caused by th
e layout change | |
| 450 // instead of forced full paint invalidation. | |
| 451 | |
| 452 if (surround.get() != other.surround.get()) { | |
| 453 // If our border widths change, then we need to layout. Other changes to
borders only necessitate a paint invalidation. | |
| 454 if (borderLeftWidth() != other.borderLeftWidth() | |
| 455 || borderTopWidth() != other.borderTopWidth() | |
| 456 || borderBottomWidth() != other.borderBottomWidth() | |
| 457 || borderRightWidth() != other.borderRightWidth()) | |
| 458 return true; | |
| 459 } | |
| 460 | |
| 461 if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) { | |
| 462 if (rareNonInheritedData->m_appearance != other.rareNonInheritedData->m_
appearance | |
| 463 || rareNonInheritedData->marginBeforeCollapse != other.rareNonInheri
tedData->marginBeforeCollapse | |
| 464 || rareNonInheritedData->marginAfterCollapse != other.rareNonInherit
edData->marginAfterCollapse | |
| 465 || rareNonInheritedData->lineClamp != other.rareNonInheritedData->li
neClamp | |
| 466 || rareNonInheritedData->textOverflow != other.rareNonInheritedData-
>textOverflow | |
| 467 || rareNonInheritedData->m_wrapFlow != other.rareNonInheritedData->m
_wrapFlow | |
| 468 || rareNonInheritedData->m_wrapThrough != other.rareNonInheritedData
->m_wrapThrough | |
| 469 || rareNonInheritedData->m_shapeMargin != other.rareNonInheritedData
->m_shapeMargin | |
| 470 || rareNonInheritedData->m_order != other.rareNonInheritedData->m_or
der | |
| 471 || rareNonInheritedData->m_justifyContent != other.rareNonInheritedD
ata->m_justifyContent | |
| 472 || rareNonInheritedData->m_grid.get() != other.rareNonInheritedData-
>m_grid.get() | |
| 473 || rareNonInheritedData->m_gridItem.get() != other.rareNonInheritedD
ata->m_gridItem.get() | |
| 474 || rareNonInheritedData->m_textCombine != other.rareNonInheritedData
->m_textCombine | |
| 475 || rareNonInheritedData->hasFilters() != other.rareNonInheritedData-
>hasFilters()) | |
| 476 return true; | |
| 477 | |
| 478 if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other.rareNon
InheritedData->m_deprecatedFlexibleBox.get() | |
| 479 && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other.ra
reNonInheritedData->m_deprecatedFlexibleBox.get()) | |
| 480 return true; | |
| 481 | |
| 482 if (rareNonInheritedData->m_flexibleBox.get() != other.rareNonInheritedD
ata->m_flexibleBox.get() | |
| 483 && *rareNonInheritedData->m_flexibleBox.get() != *other.rareNonInher
itedData->m_flexibleBox.get()) | |
| 484 return true; | |
| 485 | |
| 486 // FIXME: We should add an optimized form of layout that just recomputes
visual overflow. | |
| 487 if (!rareNonInheritedData->shadowDataEquivalent(*other.rareNonInheritedD
ata.get())) | |
| 488 return true; | |
| 489 | |
| 490 if (!rareNonInheritedData->reflectionDataEquivalent(*other.rareNonInheri
tedData.get())) | |
| 491 return true; | |
| 492 | |
| 493 if (rareNonInheritedData->m_multiCol.get() != other.rareNonInheritedData
->m_multiCol.get() | |
| 494 && *rareNonInheritedData->m_multiCol.get() != *other.rareNonInherite
dData->m_multiCol.get()) | |
| 495 return true; | |
| 496 | |
| 497 // If the counter directives change, trigger a relayout to re-calculate
counter values and rebuild the counter node tree. | |
| 498 const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirecti
ves.get(); | |
| 499 const CounterDirectiveMap* mapB = other.rareNonInheritedData->m_counterD
irectives.get(); | |
| 500 if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB))) | |
| 501 return true; | |
| 502 | |
| 503 // We only need do layout for opacity changes if adding or losing opacit
y could trigger a change | |
| 504 // in us being a stacking context. | |
| 505 if (hasAutoZIndex() != other.hasAutoZIndex() && rareNonInheritedData->ha
sOpacity() != other.rareNonInheritedData->hasOpacity()) { | |
| 506 // FIXME: We would like to use SimplifiedLayout here, but we can't q
uite do that yet. | |
| 507 // We need to make sure SimplifiedLayout can operate correctly on La
youtInlines (we will need | |
| 508 // to add a selfNeedsSimplifiedLayout bit in order to not get confus
ed and taint every line). | |
| 509 // In addition we need to solve the floating object issue when layer
s come and go. Right now | |
| 510 // a full layout is necessary to keep floating object lists sane. | |
| 511 return true; | |
| 512 } | |
| 513 } | |
| 514 | |
| 515 if (rareInheritedData.get() != other.rareInheritedData.get()) { | |
| 516 if (rareInheritedData->highlight != other.rareInheritedData->highlight | |
| 517 || rareInheritedData->indent != other.rareInheritedData->indent | |
| 518 || rareInheritedData->m_textAlignLast != other.rareInheritedData->m_
textAlignLast | |
| 519 || rareInheritedData->m_textIndentLine != other.rareInheritedData->m
_textIndentLine | |
| 520 || rareInheritedData->m_effectiveZoom != other.rareInheritedData->m_
effectiveZoom | |
| 521 || rareInheritedData->wordBreak != other.rareInheritedData->wordBrea
k | |
| 522 || rareInheritedData->overflowWrap != other.rareInheritedData->overf
lowWrap | |
| 523 || rareInheritedData->lineBreak != other.rareInheritedData->lineBrea
k | |
| 524 || rareInheritedData->textSecurity != other.rareInheritedData->textS
ecurity | |
| 525 || rareInheritedData->hyphens != other.rareInheritedData->hyphens | |
| 526 || rareInheritedData->hyphenationLimitBefore != other.rareInheritedD
ata->hyphenationLimitBefore | |
| 527 || rareInheritedData->hyphenationLimitAfter != other.rareInheritedDa
ta->hyphenationLimitAfter | |
| 528 || rareInheritedData->hyphenationString != other.rareInheritedData->
hyphenationString | |
| 529 || rareInheritedData->locale != other.rareInheritedData->locale | |
| 530 || rareInheritedData->m_rubyPosition != other.rareInheritedData->m_r
ubyPosition | |
| 531 || rareInheritedData->textEmphasisMark != other.rareInheritedData->t
extEmphasisMark | |
| 532 || rareInheritedData->textEmphasisPosition != other.rareInheritedDat
a->textEmphasisPosition | |
| 533 || rareInheritedData->textEmphasisCustomMark != other.rareInheritedD
ata->textEmphasisCustomMark | |
| 534 || rareInheritedData->m_textJustify != other.rareInheritedData->m_te
xtJustify | |
| 535 || rareInheritedData->m_textOrientation != other.rareInheritedData->
m_textOrientation | |
| 536 || rareInheritedData->m_tabSize != other.rareInheritedData->m_tabSiz
e | |
| 537 || rareInheritedData->m_lineBoxContain != other.rareInheritedData->m
_lineBoxContain | |
| 538 || rareInheritedData->listStyleImage != other.rareInheritedData->lis
tStyleImage | |
| 539 || rareInheritedData->textStrokeWidth != other.rareInheritedData->te
xtStrokeWidth) | |
| 540 return true; | |
| 541 | |
| 542 if (!rareInheritedData->shadowDataEquivalent(*other.rareInheritedData.ge
t())) | |
| 543 return true; | |
| 544 | |
| 545 if (!rareInheritedData->quotesDataEquivalent(*other.rareInheritedData.ge
t())) | |
| 546 return true; | |
| 547 } | |
| 548 | |
| 549 if (inherited->textAutosizingMultiplier != other.inherited->textAutosizingMu
ltiplier) | |
| 550 return true; | |
| 551 | |
| 552 if (inherited->font.loadingCustomFonts() != other.inherited->font.loadingCus
tomFonts()) | |
| 553 return true; | |
| 554 | |
| 555 if (inherited.get() != other.inherited.get()) { | |
| 556 if (inherited->line_height != other.inherited->line_height | |
| 557 || inherited->font != other.inherited->font | |
| 558 || inherited->horizontal_border_spacing != other.inherited->horizont
al_border_spacing | |
| 559 || inherited->vertical_border_spacing != other.inherited->vertical_b
order_spacing) | |
| 560 return true; | |
| 561 } | |
| 562 | |
| 563 if (inherited_flags._box_direction != other.inherited_flags._box_direction | |
| 564 || inherited_flags.m_rtlOrdering != other.inherited_flags.m_rtlOrdering | |
| 565 || inherited_flags._text_align != other.inherited_flags._text_align | |
| 566 || inherited_flags._text_transform != other.inherited_flags._text_transf
orm | |
| 567 || inherited_flags._direction != other.inherited_flags._direction | |
| 568 || inherited_flags._white_space != other.inherited_flags._white_space | |
| 569 || inherited_flags.m_writingMode != other.inherited_flags.m_writingMode) | |
| 570 return true; | |
| 571 | |
| 572 if (noninherited_flags.overflowX != other.noninherited_flags.overflowX | |
| 573 || noninherited_flags.overflowY != other.noninherited_flags.overflowY | |
| 574 || noninherited_flags.clear != other.noninherited_flags.clear | |
| 575 || noninherited_flags.unicodeBidi != other.noninherited_flags.unicodeBid
i | |
| 576 || noninherited_flags.floating != other.noninherited_flags.floating | |
| 577 || noninherited_flags.originalDisplay != other.noninherited_flags.origin
alDisplay) | |
| 578 return true; | |
| 579 | |
| 580 if (noninherited_flags.effectiveDisplay >= FIRST_TABLE_DISPLAY && noninherit
ed_flags.effectiveDisplay <= LAST_TABLE_DISPLAY) { | |
| 581 if (inherited_flags._border_collapse != other.inherited_flags._border_co
llapse | |
| 582 || inherited_flags._empty_cells != other.inherited_flags._empty_cell
s | |
| 583 || inherited_flags._caption_side != other.inherited_flags._caption_s
ide | |
| 584 || noninherited_flags.tableLayout != other.noninherited_flags.tableL
ayout) | |
| 585 return true; | |
| 586 | |
| 587 // In the collapsing border model, 'hidden' suppresses other borders, wh
ile 'none' | |
| 588 // does not, so these style differences can be width differences. | |
| 589 if (inherited_flags._border_collapse | |
| 590 && ((borderTopStyle() == BHIDDEN && other.borderTopStyle() == BNONE) | |
| 591 || (borderTopStyle() == BNONE && other.borderTopStyle() == BHIDD
EN) | |
| 592 || (borderBottomStyle() == BHIDDEN && other.borderBottomStyle()
== BNONE) | |
| 593 || (borderBottomStyle() == BNONE && other.borderBottomStyle() ==
BHIDDEN) | |
| 594 || (borderLeftStyle() == BHIDDEN && other.borderLeftStyle() == B
NONE) | |
| 595 || (borderLeftStyle() == BNONE && other.borderLeftStyle() == BHI
DDEN) | |
| 596 || (borderRightStyle() == BHIDDEN && other.borderRightStyle() ==
BNONE) | |
| 597 || (borderRightStyle() == BNONE && other.borderRightStyle() == B
HIDDEN))) | |
| 598 return true; | |
| 599 } else if (noninherited_flags.effectiveDisplay == LIST_ITEM) { | |
| 600 if (inherited_flags._list_style_type != other.inherited_flags._list_styl
e_type | |
| 601 || inherited_flags._list_style_position != other.inherited_flags._li
st_style_position) | |
| 602 return true; | |
| 603 } | |
| 604 | |
| 605 if ((visibility() == COLLAPSE) != (other.visibility() == COLLAPSE)) | |
| 606 return true; | |
| 607 | |
| 608 if (!m_background->outline().visuallyEqual(other.m_background->outline())) { | |
| 609 // FIXME: We only really need to recompute the overflow but we don't hav
e an optimized layout for it. | |
| 610 return true; | |
| 611 } | |
| 612 | |
| 613 if (hasPseudoStyle(SCROLLBAR) != other.hasPseudoStyle(SCROLLBAR)) | |
| 614 return true; | |
| 615 | |
| 616 // Movement of non-static-positioned object is special cased in LayoutStyle:
:visualInvalidationDiff(). | |
| 617 | |
| 618 return false; | |
| 619 } | |
| 620 | |
| 621 bool LayoutStyle::diffNeedsFullLayout(const LayoutStyle& other) const | |
| 622 { | |
| 623 if (m_box.get() != other.m_box.get()) { | |
| 624 if (m_box->width() != other.m_box->width() | |
| 625 || m_box->minWidth() != other.m_box->minWidth() | |
| 626 || m_box->maxWidth() != other.m_box->maxWidth() | |
| 627 || m_box->height() != other.m_box->height() | |
| 628 || m_box->minHeight() != other.m_box->minHeight() | |
| 629 || m_box->maxHeight() != other.m_box->maxHeight()) | |
| 630 return true; | |
| 631 | |
| 632 if (m_box->verticalAlign() != other.m_box->verticalAlign()) | |
| 633 return true; | |
| 634 | |
| 635 if (m_box->boxSizing() != other.m_box->boxSizing()) | |
| 636 return true; | |
| 637 } | |
| 638 | |
| 639 if (noninherited_flags.verticalAlign != other.noninherited_flags.verticalAli
gn | |
| 640 || noninherited_flags.position != other.noninherited_flags.position) | |
| 641 return true; | |
| 642 | |
| 643 if (surround.get() != other.surround.get()) { | |
| 644 if (surround->padding != other.surround->padding) | |
| 645 return true; | |
| 646 } | |
| 647 | |
| 648 if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) { | |
| 649 if (rareNonInheritedData->m_alignContent != other.rareNonInheritedData->
m_alignContent | |
| 650 || rareNonInheritedData->m_alignContentDistribution != other.rareNon
InheritedData->m_alignContentDistribution | |
| 651 || rareNonInheritedData->m_alignItems != other.rareNonInheritedData-
>m_alignItems | |
| 652 || rareNonInheritedData->m_alignSelf != other.rareNonInheritedData->
m_alignSelf) | |
| 653 return true; | |
| 654 } | |
| 655 | |
| 656 return false; | |
| 657 } | |
| 658 | |
| 659 bool LayoutStyle::diffNeedsPaintInvalidationLayer(const LayoutStyle& other) cons
t | |
| 660 { | |
| 661 if (position() != StaticPosition && (visual->clip != other.visual->clip || v
isual->hasAutoClip != other.visual->hasAutoClip)) | |
| 662 return true; | |
| 663 | |
| 664 if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) { | |
| 665 if (RuntimeEnabledFeatures::cssCompositingEnabled() | |
| 666 && (rareNonInheritedData->m_effectiveBlendMode != other.rareNonInher
itedData->m_effectiveBlendMode | |
| 667 || rareNonInheritedData->m_isolation != other.rareNonInheritedDa
ta->m_isolation)) | |
| 668 return true; | |
| 669 | |
| 670 if (rareNonInheritedData->m_mask != other.rareNonInheritedData->m_mask | |
| 671 || rareNonInheritedData->m_maskBoxImage != other.rareNonInheritedDat
a->m_maskBoxImage) | |
| 672 return true; | |
| 673 } | |
| 674 | |
| 675 return false; | |
| 676 } | |
| 677 | |
| 678 bool LayoutStyle::diffNeedsPaintInvalidationObject(const LayoutStyle& other) con
st | |
| 679 { | |
| 680 if (inherited_flags._visibility != other.inherited_flags._visibility | |
| 681 || inherited_flags.m_printColorAdjust != other.inherited_flags.m_printCo
lorAdjust | |
| 682 || inherited_flags._insideLink != other.inherited_flags._insideLink | |
| 683 || !surround->border.visuallyEqual(other.surround->border) | |
| 684 || !m_background->visuallyEqual(*other.m_background)) | |
| 685 return true; | |
| 686 | |
| 687 if (rareInheritedData.get() != other.rareInheritedData.get()) { | |
| 688 if (rareInheritedData->userModify != other.rareInheritedData->userModify | |
| 689 || rareInheritedData->userSelect != other.rareInheritedData->userSel
ect | |
| 690 || rareInheritedData->m_imageRendering != other.rareInheritedData->m
_imageRendering) | |
| 691 return true; | |
| 692 } | |
| 693 | |
| 694 if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) { | |
| 695 if (rareNonInheritedData->userDrag != other.rareNonInheritedData->userDr
ag | |
| 696 || rareNonInheritedData->m_objectFit != other.rareNonInheritedData->
m_objectFit | |
| 697 || rareNonInheritedData->m_objectPosition != other.rareNonInheritedD
ata->m_objectPosition | |
| 698 || !rareNonInheritedData->shapeOutsideDataEquivalent(*other.rareNonI
nheritedData.get()) | |
| 699 || !rareNonInheritedData->clipPathDataEquivalent(*other.rareNonInher
itedData.get()) | |
| 700 || (visitedLinkBorderLeftColor() != other.visitedLinkBorderLeftColor
() && borderLeftWidth()) | |
| 701 || (visitedLinkBorderRightColor() != other.visitedLinkBorderRightCol
or() && borderRightWidth()) | |
| 702 || (visitedLinkBorderBottomColor() != other.visitedLinkBorderBottomC
olor() && borderBottomWidth()) | |
| 703 || (visitedLinkBorderTopColor() != other.visitedLinkBorderTopColor()
&& borderTopWidth()) | |
| 704 || (visitedLinkOutlineColor() != other.visitedLinkOutlineColor() &&
outlineWidth()) | |
| 705 || (visitedLinkBackgroundColor() != other.visitedLinkBackgroundColor
())) | |
| 706 return true; | |
| 707 } | |
| 708 | |
| 709 if (resize() != other.resize()) | |
| 710 return true; | |
| 711 | |
| 712 return false; | |
| 713 } | |
| 714 | |
| 715 void LayoutStyle::updatePropertySpecificDifferences(const LayoutStyle& other, St
yleDifference& diff) const | |
| 716 { | |
| 717 // StyleAdjuster has ensured that zIndex is non-auto only if it's applicable
. | |
| 718 if (m_box->zIndex() != other.m_box->zIndex() || m_box->hasAutoZIndex() != ot
her.m_box->hasAutoZIndex()) | |
| 719 diff.setZIndexChanged(); | |
| 720 | |
| 721 if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) { | |
| 722 if (!transformDataEquivalent(other)) | |
| 723 diff.setTransformChanged(); | |
| 724 | |
| 725 if (rareNonInheritedData->opacity != other.rareNonInheritedData->opacity
) | |
| 726 diff.setOpacityChanged(); | |
| 727 | |
| 728 if (rareNonInheritedData->m_filter != other.rareNonInheritedData->m_filt
er) | |
| 729 diff.setFilterChanged(); | |
| 730 } | |
| 731 | |
| 732 if (!diff.needsPaintInvalidation()) { | |
| 733 if (inherited->color != other.inherited->color | |
| 734 || inherited->visitedLinkColor != other.inherited->visitedLinkColor | |
| 735 || inherited_flags.m_textUnderline != other.inherited_flags.m_textUn
derline | |
| 736 || visual->textDecoration != other.visual->textDecoration) { | |
| 737 diff.setTextOrColorChanged(); | |
| 738 } else if (rareNonInheritedData.get() != other.rareNonInheritedData.get(
) | |
| 739 && (rareNonInheritedData->m_textDecorationStyle != other.rareNonInhe
ritedData->m_textDecorationStyle | |
| 740 || rareNonInheritedData->m_textDecorationColor != other.rareNonI
nheritedData->m_textDecorationColor | |
| 741 || rareNonInheritedData->m_visitedLinkTextDecorationColor != oth
er.rareNonInheritedData->m_visitedLinkTextDecorationColor)) { | |
| 742 diff.setTextOrColorChanged(); | |
| 743 } else if (rareInheritedData.get() != other.rareInheritedData.get() | |
| 744 && (rareInheritedData->textFillColor() != other.rareInheritedData->t
extFillColor() | |
| 745 || rareInheritedData->textStrokeColor() != other.rareInheritedDa
ta->textStrokeColor() | |
| 746 || rareInheritedData->textEmphasisColor() != other.rareInherited
Data->textEmphasisColor() | |
| 747 || rareInheritedData->visitedLinkTextFillColor() != other.rareIn
heritedData->visitedLinkTextFillColor() | |
| 748 || rareInheritedData->visitedLinkTextStrokeColor() != other.rare
InheritedData->visitedLinkTextStrokeColor() | |
| 749 || rareInheritedData->visitedLinkTextEmphasisColor() != other.ra
reInheritedData->visitedLinkTextEmphasisColor() | |
| 750 || rareInheritedData->textEmphasisFill != other.rareInheritedDat
a->textEmphasisFill | |
| 751 || rareInheritedData->appliedTextDecorations != other.rareInheri
tedData->appliedTextDecorations)) { | |
| 752 diff.setTextOrColorChanged(); | |
| 753 } | |
| 754 } | |
| 755 } | |
| 756 | |
| 757 void LayoutStyle::addCursor(PassRefPtr<StyleImage> image, bool hotSpotSpecified,
const IntPoint& hotSpot) | |
| 758 { | |
| 759 if (!rareInheritedData.access()->cursorData) | |
| 760 rareInheritedData.access()->cursorData = CursorList::create(); | |
| 761 rareInheritedData.access()->cursorData->append(CursorData(image, hotSpotSpec
ified, hotSpot)); | |
| 762 } | |
| 763 | |
| 764 void LayoutStyle::setCursorList(PassRefPtr<CursorList> other) | |
| 765 { | |
| 766 rareInheritedData.access()->cursorData = other; | |
| 767 } | |
| 768 | |
| 769 void LayoutStyle::setQuotes(PassRefPtr<QuotesData> q) | |
| 770 { | |
| 771 rareInheritedData.access()->quotes = q; | |
| 772 } | |
| 773 | |
| 774 void LayoutStyle::clearCursorList() | |
| 775 { | |
| 776 if (rareInheritedData->cursorData) | |
| 777 rareInheritedData.access()->cursorData = nullptr; | |
| 778 } | |
| 779 | |
| 780 void LayoutStyle::addCallbackSelector(const String& selector) | |
| 781 { | |
| 782 if (!rareNonInheritedData->m_callbackSelectors.contains(selector)) | |
| 783 rareNonInheritedData.access()->m_callbackSelectors.append(selector); | |
| 784 } | |
| 785 | |
| 786 void LayoutStyle::clearContent() | |
| 787 { | |
| 788 if (rareNonInheritedData->m_content) | |
| 789 rareNonInheritedData.access()->m_content = nullptr; | |
| 790 } | |
| 791 | |
| 792 void LayoutStyle::appendContent(PassOwnPtr<ContentData> contentData) | |
| 793 { | |
| 794 OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content; | |
| 795 ContentData* lastContent = content.get(); | |
| 796 while (lastContent && lastContent->next()) | |
| 797 lastContent = lastContent->next(); | |
| 798 | |
| 799 if (lastContent) | |
| 800 lastContent->setNext(contentData); | |
| 801 else | |
| 802 content = contentData; | |
| 803 } | |
| 804 | |
| 805 void LayoutStyle::setContent(PassRefPtr<StyleImage> image, bool add) | |
| 806 { | |
| 807 if (!image) | |
| 808 return; | |
| 809 | |
| 810 if (add) { | |
| 811 appendContent(ContentData::create(image)); | |
| 812 return; | |
| 813 } | |
| 814 | |
| 815 rareNonInheritedData.access()->m_content = ContentData::create(image); | |
| 816 } | |
| 817 | |
| 818 void LayoutStyle::setContent(const String& string, bool add) | |
| 819 { | |
| 820 OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content; | |
| 821 if (add) { | |
| 822 ContentData* lastContent = content.get(); | |
| 823 while (lastContent && lastContent->next()) | |
| 824 lastContent = lastContent->next(); | |
| 825 | |
| 826 if (lastContent) { | |
| 827 // We attempt to merge with the last ContentData if possible. | |
| 828 if (lastContent->isText()) { | |
| 829 TextContentData* textContent = toTextContentData(lastContent); | |
| 830 textContent->setText(textContent->text() + string); | |
| 831 } else { | |
| 832 lastContent->setNext(ContentData::create(string)); | |
| 833 } | |
| 834 | |
| 835 return; | |
| 836 } | |
| 837 } | |
| 838 | |
| 839 content = ContentData::create(string); | |
| 840 } | |
| 841 | |
| 842 void LayoutStyle::setContent(PassOwnPtr<CounterContent> counter, bool add) | |
| 843 { | |
| 844 if (!counter) | |
| 845 return; | |
| 846 | |
| 847 if (add) { | |
| 848 appendContent(ContentData::create(counter)); | |
| 849 return; | |
| 850 } | |
| 851 | |
| 852 rareNonInheritedData.access()->m_content = ContentData::create(counter); | |
| 853 } | |
| 854 | |
| 855 void LayoutStyle::setContent(QuoteType quote, bool add) | |
| 856 { | |
| 857 if (add) { | |
| 858 appendContent(ContentData::create(quote)); | |
| 859 return; | |
| 860 } | |
| 861 | |
| 862 rareNonInheritedData.access()->m_content = ContentData::create(quote); | |
| 863 } | |
| 864 | |
| 865 bool LayoutStyle::hasWillChangeCompositingHint() const | |
| 866 { | |
| 867 for (size_t i = 0; i < rareNonInheritedData->m_willChange->m_properties.size
(); ++i) { | |
| 868 switch (rareNonInheritedData->m_willChange->m_properties[i]) { | |
| 869 case CSSPropertyOpacity: | |
| 870 case CSSPropertyTransform: | |
| 871 case CSSPropertyWebkitTransform: | |
| 872 case CSSPropertyTop: | |
| 873 case CSSPropertyLeft: | |
| 874 case CSSPropertyBottom: | |
| 875 case CSSPropertyRight: | |
| 876 return true; | |
| 877 default: | |
| 878 break; | |
| 879 } | |
| 880 } | |
| 881 return false; | |
| 882 } | |
| 883 | |
| 884 inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation>>& tra
nsformOperations, LayoutStyle::ApplyTransformOrigin applyOrigin, LayoutStyle::Ap
plyMotionPath applyMotionPath) | |
| 885 { | |
| 886 // transform-origin brackets the transform with translate operations. | |
| 887 // Optimize for the case where the only transform is a translation, since th
e transform-origin is irrelevant | |
| 888 // in that case. | |
| 889 if (applyOrigin != LayoutStyle::IncludeTransformOrigin) | |
| 890 return false; | |
| 891 | |
| 892 if (applyMotionPath == LayoutStyle::IncludeMotionPath) | |
| 893 return true; | |
| 894 | |
| 895 unsigned size = transformOperations.size(); | |
| 896 for (unsigned i = 0; i < size; ++i) { | |
| 897 TransformOperation::OperationType type = transformOperations[i]->type(); | |
| 898 if (type != TransformOperation::TranslateX | |
| 899 && type != TransformOperation::TranslateY | |
| 900 && type != TransformOperation::Translate | |
| 901 && type != TransformOperation::TranslateZ | |
| 902 && type != TransformOperation::Translate3D) | |
| 903 return true; | |
| 904 } | |
| 905 | |
| 906 return false; | |
| 907 } | |
| 908 | |
| 909 void LayoutStyle::applyTransform(TransformationMatrix& transform, const LayoutSi
ze& borderBoxSize, ApplyTransformOrigin applyOrigin, ApplyMotionPath applyMotion
Path) const | |
| 910 { | |
| 911 applyTransform(transform, FloatRect(FloatPoint(), FloatSize(borderBoxSize)),
applyOrigin, applyMotionPath); | |
| 912 } | |
| 913 | |
| 914 void LayoutStyle::applyTransform(TransformationMatrix& transform, const FloatRec
t& boundingBox, ApplyTransformOrigin applyOrigin, ApplyMotionPath applyMotionPat
h) const | |
| 915 { | |
| 916 if (!hasMotionPath()) | |
| 917 applyMotionPath = ExcludeMotionPath; | |
| 918 const Vector<RefPtr<TransformOperation>>& transformOperations = rareNonInher
itedData->m_transform->m_operations.operations(); | |
| 919 bool applyTransformOrigin = requireTransformOrigin(transformOperations, appl
yOrigin, applyMotionPath); | |
| 920 | |
| 921 float offsetX = transformOriginX().type() == Percent ? boundingBox.x() : 0; | |
| 922 float offsetY = transformOriginY().type() == Percent ? boundingBox.y() : 0; | |
| 923 | |
| 924 if (applyTransformOrigin) { | |
| 925 transform.translate3d(floatValueForLength(transformOriginX(), boundingBo
x.width()) + offsetX, | |
| 926 floatValueForLength(transformOriginY(), boundingBox.height()) + offs
etY, | |
| 927 transformOriginZ()); | |
| 928 } | |
| 929 | |
| 930 if (applyMotionPath == LayoutStyle::IncludeMotionPath) | |
| 931 applyMotionPathTransform(transform); | |
| 932 | |
| 933 unsigned size = transformOperations.size(); | |
| 934 for (unsigned i = 0; i < size; ++i) | |
| 935 transformOperations[i]->apply(transform, boundingBox.size()); | |
| 936 | |
| 937 if (applyTransformOrigin) { | |
| 938 transform.translate3d(-floatValueForLength(transformOriginX(), boundingB
ox.width()) - offsetX, | |
| 939 -floatValueForLength(transformOriginY(), boundingBox.height()) - off
setY, | |
| 940 -transformOriginZ()); | |
| 941 } | |
| 942 } | |
| 943 | |
| 944 void LayoutStyle::applyMotionPathTransform(TransformationMatrix& transform) cons
t | |
| 945 { | |
| 946 const StyleMotionData& motionData = rareNonInheritedData->m_transform->m_mot
ion; | |
| 947 ASSERT(motionData.m_path && motionData.m_path->isPathStyleMotionPath()); | |
| 948 const PathStyleMotionPath& motionPath = toPathStyleMotionPath(*motionData.m_
path); | |
| 949 float pathLength = motionPath.length(); | |
| 950 float distance = floatValueForLength(motionData.m_offset, pathLength); | |
| 951 float computedDistance; | |
| 952 if (motionPath.isClosed() && pathLength > 0) { | |
| 953 computedDistance = fmod(distance, pathLength); | |
| 954 if (computedDistance < 0) | |
| 955 computedDistance += pathLength; | |
| 956 } else { | |
| 957 computedDistance = clampTo<float>(distance, 0, pathLength); | |
| 958 } | |
| 959 | |
| 960 FloatPoint point; | |
| 961 float angle; | |
| 962 if (!motionPath.path().pointAndNormalAtLength(computedDistance, point, angle
)) | |
| 963 return; | |
| 964 if (motionData.m_rotationType == MotionRotationFixed) | |
| 965 angle = 0; | |
| 966 | |
| 967 transform.translate(point.x(), point.y()); | |
| 968 transform.rotate(angle + motionData.m_rotation); | |
| 969 } | |
| 970 | |
| 971 void LayoutStyle::setTextShadow(PassRefPtr<ShadowList> s) | |
| 972 { | |
| 973 rareInheritedData.access()->textShadow = s; | |
| 974 } | |
| 975 | |
| 976 void LayoutStyle::setBoxShadow(PassRefPtr<ShadowList> s) | |
| 977 { | |
| 978 rareNonInheritedData.access()->m_boxShadow = s; | |
| 979 } | |
| 980 | |
| 981 static FloatRoundedRect::Radii calcRadiiFor(const BorderData& border, LayoutSize
size) | |
| 982 { | |
| 983 return FloatRoundedRect::Radii( | |
| 984 IntSize(valueForLength(border.topLeft().width(), size.width()), | |
| 985 valueForLength(border.topLeft().height(), size.height())), | |
| 986 IntSize(valueForLength(border.topRight().width(), size.width()), | |
| 987 valueForLength(border.topRight().height(), size.height())), | |
| 988 IntSize(valueForLength(border.bottomLeft().width(), size.width()), | |
| 989 valueForLength(border.bottomLeft().height(), size.height())), | |
| 990 IntSize(valueForLength(border.bottomRight().width(), size.width()), | |
| 991 valueForLength(border.bottomRight().height(), size.height()))); | |
| 992 } | |
| 993 | |
| 994 StyleImage* LayoutStyle::listStyleImage() const { return rareInheritedData->list
StyleImage.get(); } | |
| 995 void LayoutStyle::setListStyleImage(PassRefPtr<StyleImage> v) | |
| 996 { | |
| 997 if (rareInheritedData->listStyleImage != v) | |
| 998 rareInheritedData.access()->listStyleImage = v; | |
| 999 } | |
| 1000 | |
| 1001 Color LayoutStyle::color() const { return inherited->color; } | |
| 1002 Color LayoutStyle::visitedLinkColor() const { return inherited->visitedLinkColor
; } | |
| 1003 void LayoutStyle::setColor(const Color& v) { SET_VAR(inherited, color, v); } | |
| 1004 void LayoutStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visit
edLinkColor, v); } | |
| 1005 | |
| 1006 short LayoutStyle::horizontalBorderSpacing() const { return inherited->horizonta
l_border_spacing; } | |
| 1007 short LayoutStyle::verticalBorderSpacing() const { return inherited->vertical_bo
rder_spacing; } | |
| 1008 void LayoutStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horiz
ontal_border_spacing, v); } | |
| 1009 void LayoutStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertica
l_border_spacing, v); } | |
| 1010 | |
| 1011 FloatRoundedRect LayoutStyle::getRoundedBorderFor(const LayoutRect& borderRect,
bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const | |
| 1012 { | |
| 1013 FloatRoundedRect roundedRect(pixelSnappedIntRect(borderRect)); | |
| 1014 if (hasBorderRadius()) { | |
| 1015 FloatRoundedRect::Radii radii = calcRadiiFor(surround->border, borderRec
t.size()); | |
| 1016 roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includ
eLogicalLeftEdge, includeLogicalRightEdge); | |
| 1017 roundedRect.constrainRadii(); | |
| 1018 } | |
| 1019 return roundedRect; | |
| 1020 } | |
| 1021 | |
| 1022 FloatRoundedRect LayoutStyle::getRoundedInnerBorderFor(const LayoutRect& borderR
ect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const | |
| 1023 { | |
| 1024 bool horizontal = isHorizontalWritingMode(); | |
| 1025 | |
| 1026 int leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth()
: 0; | |
| 1027 int rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth
() : 0; | |
| 1028 int topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0
; | |
| 1029 int bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidt
h() : 0; | |
| 1030 | |
| 1031 return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth
, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge); | |
| 1032 } | |
| 1033 | |
| 1034 FloatRoundedRect LayoutStyle::getRoundedInnerBorderFor(const LayoutRect& borderR
ect, | |
| 1035 int topWidth, int bottomWidth, int leftWidth, int rightWidth, bool includeLo
gicalLeftEdge, bool includeLogicalRightEdge) const | |
| 1036 { | |
| 1037 LayoutRect innerRect(borderRect.x() + leftWidth, | |
| 1038 borderRect.y() + topWidth, | |
| 1039 borderRect.width() - leftWidth - rightWidth, | |
| 1040 borderRect.height() - topWidth - bottomWidth); | |
| 1041 | |
| 1042 FloatRoundedRect roundedRect(pixelSnappedIntRect(innerRect)); | |
| 1043 | |
| 1044 if (hasBorderRadius()) { | |
| 1045 FloatRoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii(); | |
| 1046 radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth); | |
| 1047 roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includ
eLogicalLeftEdge, includeLogicalRightEdge); | |
| 1048 } | |
| 1049 return roundedRect; | |
| 1050 } | |
| 1051 | |
| 1052 static bool allLayersAreFixed(const FillLayer& layer) | |
| 1053 { | |
| 1054 for (const FillLayer* currLayer = &layer; currLayer; currLayer = currLayer->
next()) { | |
| 1055 if (!currLayer->image() || currLayer->attachment() != FixedBackgroundAtt
achment) | |
| 1056 return false; | |
| 1057 } | |
| 1058 | |
| 1059 return true; | |
| 1060 } | |
| 1061 | |
| 1062 bool LayoutStyle::hasEntirelyFixedBackground() const | |
| 1063 { | |
| 1064 return allLayersAreFixed(backgroundLayers()); | |
| 1065 } | |
| 1066 | |
| 1067 const CounterDirectiveMap* LayoutStyle::counterDirectives() const | |
| 1068 { | |
| 1069 return rareNonInheritedData->m_counterDirectives.get(); | |
| 1070 } | |
| 1071 | |
| 1072 CounterDirectiveMap& LayoutStyle::accessCounterDirectives() | |
| 1073 { | |
| 1074 OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterD
irectives; | |
| 1075 if (!map) | |
| 1076 map = adoptPtr(new CounterDirectiveMap); | |
| 1077 return *map; | |
| 1078 } | |
| 1079 | |
| 1080 const CounterDirectives LayoutStyle::getCounterDirectives(const AtomicString& id
entifier) const | |
| 1081 { | |
| 1082 if (const CounterDirectiveMap* directives = counterDirectives()) | |
| 1083 return directives->get(identifier); | |
| 1084 return CounterDirectives(); | |
| 1085 } | |
| 1086 | |
| 1087 void LayoutStyle::clearIncrementDirectives() | |
| 1088 { | |
| 1089 if (!counterDirectives()) | |
| 1090 return; | |
| 1091 | |
| 1092 // This makes us copy even if we may not be removing any items. | |
| 1093 CounterDirectiveMap& map = accessCounterDirectives(); | |
| 1094 typedef CounterDirectiveMap::iterator Iterator; | |
| 1095 | |
| 1096 Iterator end = map.end(); | |
| 1097 for (Iterator it = map.begin(); it != end; ++it) | |
| 1098 it->value.clearIncrement(); | |
| 1099 } | |
| 1100 | |
| 1101 void LayoutStyle::clearResetDirectives() | |
| 1102 { | |
| 1103 if (!counterDirectives()) | |
| 1104 return; | |
| 1105 | |
| 1106 // This makes us copy even if we may not be removing any items. | |
| 1107 CounterDirectiveMap& map = accessCounterDirectives(); | |
| 1108 typedef CounterDirectiveMap::iterator Iterator; | |
| 1109 | |
| 1110 Iterator end = map.end(); | |
| 1111 for (Iterator it = map.begin(); it != end; ++it) | |
| 1112 it->value.clearReset(); | |
| 1113 } | |
| 1114 | |
| 1115 const AtomicString& LayoutStyle::hyphenString() const | |
| 1116 { | |
| 1117 const AtomicString& hyphenationString = rareInheritedData.get()->hyphenation
String; | |
| 1118 if (!hyphenationString.isNull()) | |
| 1119 return hyphenationString; | |
| 1120 | |
| 1121 // FIXME: This should depend on locale. | |
| 1122 DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinus, 1)); | |
| 1123 DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphen, 1)); | |
| 1124 return font().primaryFontHasGlyphForCharacter(hyphen) ? hyphenString : hyphe
nMinusString; | |
| 1125 } | |
| 1126 | |
| 1127 const AtomicString& LayoutStyle::textEmphasisMarkString() const | |
| 1128 { | |
| 1129 switch (textEmphasisMark()) { | |
| 1130 case TextEmphasisMarkNone: | |
| 1131 return nullAtom; | |
| 1132 case TextEmphasisMarkCustom: | |
| 1133 return textEmphasisCustomMark(); | |
| 1134 case TextEmphasisMarkDot: { | |
| 1135 DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1)); | |
| 1136 DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1)); | |
| 1137 return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString :
openDotString; | |
| 1138 } | |
| 1139 case TextEmphasisMarkCircle: { | |
| 1140 DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1))
; | |
| 1141 DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1)); | |
| 1142 return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString
: openCircleString; | |
| 1143 } | |
| 1144 case TextEmphasisMarkDoubleCircle: { | |
| 1145 DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1
)); | |
| 1146 DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1)
); | |
| 1147 return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircle
String : openDoubleCircleString; | |
| 1148 } | |
| 1149 case TextEmphasisMarkTriangle: { | |
| 1150 DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointin
gTriangle, 1)); | |
| 1151 DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingT
riangle, 1)); | |
| 1152 return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleStri
ng : openTriangleString; | |
| 1153 } | |
| 1154 case TextEmphasisMarkSesame: { | |
| 1155 DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1)); | |
| 1156 DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1)
); | |
| 1157 return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString
: openSesameString; | |
| 1158 } | |
| 1159 case TextEmphasisMarkAuto: | |
| 1160 ASSERT_NOT_REACHED(); | |
| 1161 return nullAtom; | |
| 1162 } | |
| 1163 | |
| 1164 ASSERT_NOT_REACHED(); | |
| 1165 return nullAtom; | |
| 1166 } | |
| 1167 | |
| 1168 CSSAnimationData& LayoutStyle::accessAnimations() | |
| 1169 { | |
| 1170 if (!rareNonInheritedData.access()->m_animations) | |
| 1171 rareNonInheritedData.access()->m_animations = CSSAnimationData::create()
; | |
| 1172 return *rareNonInheritedData->m_animations; | |
| 1173 } | |
| 1174 | |
| 1175 CSSTransitionData& LayoutStyle::accessTransitions() | |
| 1176 { | |
| 1177 if (!rareNonInheritedData.access()->m_transitions) | |
| 1178 rareNonInheritedData.access()->m_transitions = CSSTransitionData::create
(); | |
| 1179 return *rareNonInheritedData->m_transitions; | |
| 1180 } | |
| 1181 | |
| 1182 const Font& LayoutStyle::font() const { return inherited->font; } | |
| 1183 const FontMetrics& LayoutStyle::fontMetrics() const { return inherited->font.fon
tMetrics(); } | |
| 1184 const FontDescription& LayoutStyle::fontDescription() const { return inherited->
font.fontDescription(); } | |
| 1185 float LayoutStyle::specifiedFontSize() const { return fontDescription().specifie
dSize(); } | |
| 1186 float LayoutStyle::computedFontSize() const { return fontDescription().computedS
ize(); } | |
| 1187 int LayoutStyle::fontSize() const { return fontDescription().computedPixelSize()
; } | |
| 1188 float LayoutStyle::fontSizeAdjust() const { return fontDescription().sizeAdjust(
); } | |
| 1189 bool LayoutStyle::hasFontSizeAdjust() const { return fontDescription().hasSizeAd
just(); } | |
| 1190 FontWeight LayoutStyle::fontWeight() const { return fontDescription().weight();
} | |
| 1191 FontStretch LayoutStyle::fontStretch() const { return fontDescription().stretch(
); } | |
| 1192 | |
| 1193 TextDecoration LayoutStyle::textDecorationsInEffect() const | |
| 1194 { | |
| 1195 int decorations = 0; | |
| 1196 | |
| 1197 const Vector<AppliedTextDecoration>& applied = appliedTextDecorations(); | |
| 1198 | |
| 1199 for (size_t i = 0; i < applied.size(); ++i) | |
| 1200 decorations |= applied[i].line(); | |
| 1201 | |
| 1202 return static_cast<TextDecoration>(decorations); | |
| 1203 } | |
| 1204 | |
| 1205 const Vector<AppliedTextDecoration>& LayoutStyle::appliedTextDecorations() const | |
| 1206 { | |
| 1207 if (!inherited_flags.m_textUnderline && !rareInheritedData->appliedTextDecor
ations) { | |
| 1208 DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, empty, ()); | |
| 1209 return empty; | |
| 1210 } | |
| 1211 if (inherited_flags.m_textUnderline) { | |
| 1212 DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, underline, (1, Applie
dTextDecoration(TextDecorationUnderline))); | |
| 1213 return underline; | |
| 1214 } | |
| 1215 | |
| 1216 return rareInheritedData->appliedTextDecorations->vector(); | |
| 1217 } | |
| 1218 | |
| 1219 float LayoutStyle::wordSpacing() const { return fontDescription().wordSpacing();
} | |
| 1220 float LayoutStyle::letterSpacing() const { return fontDescription().letterSpacin
g(); } | |
| 1221 | |
| 1222 bool LayoutStyle::setFontDescription(const FontDescription& v) | |
| 1223 { | |
| 1224 if (inherited->font.fontDescription() != v) { | |
| 1225 inherited.access()->font = Font(v); | |
| 1226 return true; | |
| 1227 } | |
| 1228 return false; | |
| 1229 } | |
| 1230 | |
| 1231 const Length& LayoutStyle::specifiedLineHeight() const { return inherited->line_
height; } | |
| 1232 Length LayoutStyle::lineHeight() const | |
| 1233 { | |
| 1234 const Length& lh = inherited->line_height; | |
| 1235 // Unlike fontDescription().computedSize() and hence fontSize(), this is | |
| 1236 // recalculated on demand as we only store the specified line height. | |
| 1237 // FIXME: Should consider scaling the fixed part of any calc expressions | |
| 1238 // too, though this involves messily poking into CalcExpressionLength. | |
| 1239 float multiplier = textAutosizingMultiplier(); | |
| 1240 if (multiplier > 1 && lh.isFixed()) | |
| 1241 return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multip
lier), Fixed); | |
| 1242 | |
| 1243 return lh; | |
| 1244 } | |
| 1245 | |
| 1246 void LayoutStyle::setLineHeight(const Length& specifiedLineHeight) { SET_VAR(inh
erited, line_height, specifiedLineHeight); } | |
| 1247 | |
| 1248 int LayoutStyle::computedLineHeight() const | |
| 1249 { | |
| 1250 const Length& lh = lineHeight(); | |
| 1251 | |
| 1252 // Negative value means the line height is not set. Use the font's built-in
spacing. | |
| 1253 if (lh.isNegative()) | |
| 1254 return fontMetrics().lineSpacing(); | |
| 1255 | |
| 1256 if (lh.isPercent()) | |
| 1257 return minimumValueForLength(lh, fontSize()); | |
| 1258 | |
| 1259 return lh.value(); | |
| 1260 } | |
| 1261 | |
| 1262 void LayoutStyle::setWordSpacing(float wordSpacing) | |
| 1263 { | |
| 1264 FontSelector* currentFontSelector = font().fontSelector(); | |
| 1265 FontDescription desc(fontDescription()); | |
| 1266 desc.setWordSpacing(wordSpacing); | |
| 1267 setFontDescription(desc); | |
| 1268 font().update(currentFontSelector); | |
| 1269 } | |
| 1270 | |
| 1271 void LayoutStyle::setLetterSpacing(float letterSpacing) | |
| 1272 { | |
| 1273 FontSelector* currentFontSelector = font().fontSelector(); | |
| 1274 FontDescription desc(fontDescription()); | |
| 1275 desc.setLetterSpacing(letterSpacing); | |
| 1276 setFontDescription(desc); | |
| 1277 font().update(currentFontSelector); | |
| 1278 } | |
| 1279 | |
| 1280 void LayoutStyle::setTextAutosizingMultiplier(float multiplier) | |
| 1281 { | |
| 1282 SET_VAR(inherited, textAutosizingMultiplier, multiplier); | |
| 1283 | |
| 1284 float size = specifiedFontSize(); | |
| 1285 | |
| 1286 ASSERT(std::isfinite(size)); | |
| 1287 if (!std::isfinite(size) || size < 0) | |
| 1288 size = 0; | |
| 1289 else | |
| 1290 size = std::min(maximumAllowedFontSize, size); | |
| 1291 | |
| 1292 FontSelector* currentFontSelector = font().fontSelector(); | |
| 1293 FontDescription desc(fontDescription()); | |
| 1294 desc.setSpecifiedSize(size); | |
| 1295 desc.setComputedSize(size); | |
| 1296 | |
| 1297 if (multiplier > 1) { | |
| 1298 float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size,
multiplier); | |
| 1299 desc.setComputedSize(std::min(maximumAllowedFontSize, autosizedFontSize)
); | |
| 1300 } | |
| 1301 | |
| 1302 setFontDescription(desc); | |
| 1303 font().update(currentFontSelector); | |
| 1304 } | |
| 1305 | |
| 1306 void LayoutStyle::addAppliedTextDecoration(const AppliedTextDecoration& decorati
on) | |
| 1307 { | |
| 1308 RefPtr<AppliedTextDecorationList>& list = rareInheritedData.access()->applie
dTextDecorations; | |
| 1309 | |
| 1310 if (!list) | |
| 1311 list = AppliedTextDecorationList::create(); | |
| 1312 else if (!list->hasOneRef()) | |
| 1313 list = list->copy(); | |
| 1314 | |
| 1315 if (inherited_flags.m_textUnderline) { | |
| 1316 inherited_flags.m_textUnderline = false; | |
| 1317 list->append(AppliedTextDecoration(TextDecorationUnderline)); | |
| 1318 } | |
| 1319 | |
| 1320 list->append(decoration); | |
| 1321 } | |
| 1322 | |
| 1323 void LayoutStyle::applyTextDecorations() | |
| 1324 { | |
| 1325 if (textDecoration() == TextDecorationNone) | |
| 1326 return; | |
| 1327 | |
| 1328 TextDecorationStyle style = textDecorationStyle(); | |
| 1329 StyleColor styleColor = decorationColorIncludingFallback(insideLink() == Ins
ideVisitedLink); | |
| 1330 | |
| 1331 int decorations = textDecoration(); | |
| 1332 | |
| 1333 if (decorations & TextDecorationUnderline) { | |
| 1334 // To save memory, we don't use AppliedTextDecoration objects in the | |
| 1335 // common case of a single simple underline. | |
| 1336 AppliedTextDecoration underline(TextDecorationUnderline, style, styleCol
or); | |
| 1337 | |
| 1338 if (!rareInheritedData->appliedTextDecorations && underline.isSimpleUnde
rline()) | |
| 1339 inherited_flags.m_textUnderline = true; | |
| 1340 else | |
| 1341 addAppliedTextDecoration(underline); | |
| 1342 } | |
| 1343 if (decorations & TextDecorationOverline) | |
| 1344 addAppliedTextDecoration(AppliedTextDecoration(TextDecorationOverline, s
tyle, styleColor)); | |
| 1345 if (decorations & TextDecorationLineThrough) | |
| 1346 addAppliedTextDecoration(AppliedTextDecoration(TextDecorationLineThrough
, style, styleColor)); | |
| 1347 } | |
| 1348 | |
| 1349 void LayoutStyle::clearAppliedTextDecorations() | |
| 1350 { | |
| 1351 inherited_flags.m_textUnderline = false; | |
| 1352 | |
| 1353 if (rareInheritedData->appliedTextDecorations) | |
| 1354 rareInheritedData.access()->appliedTextDecorations = nullptr; | |
| 1355 } | |
| 1356 | |
| 1357 void LayoutStyle::clearMultiCol() | |
| 1358 { | |
| 1359 rareNonInheritedData.access()->m_multiCol = nullptr; | |
| 1360 rareNonInheritedData.access()->m_multiCol.init(); | |
| 1361 } | |
| 1362 | |
| 1363 StyleColor LayoutStyle::decorationColorIncludingFallback(bool visitedLink) const | |
| 1364 { | |
| 1365 StyleColor styleColor = visitedLink ? visitedLinkTextDecorationColor() : tex
tDecorationColor(); | |
| 1366 | |
| 1367 if (!styleColor.isCurrentColor()) | |
| 1368 return styleColor; | |
| 1369 | |
| 1370 if (textStrokeWidth()) { | |
| 1371 // Prefer stroke color if possible, but not if it's fully transparent. | |
| 1372 StyleColor textStrokeStyleColor = visitedLink ? visitedLinkTextStrokeCol
or() : textStrokeColor(); | |
| 1373 if (!textStrokeStyleColor.isCurrentColor() && textStrokeStyleColor.color
().alpha()) | |
| 1374 return textStrokeStyleColor; | |
| 1375 } | |
| 1376 | |
| 1377 return visitedLink ? visitedLinkTextFillColor() : textFillColor(); | |
| 1378 } | |
| 1379 | |
| 1380 Color LayoutStyle::colorIncludingFallback(int colorProperty, bool visitedLink) c
onst | |
| 1381 { | |
| 1382 StyleColor result(StyleColor::currentColor()); | |
| 1383 EBorderStyle borderStyle = BNONE; | |
| 1384 switch (colorProperty) { | |
| 1385 case CSSPropertyBackgroundColor: | |
| 1386 result = visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); | |
| 1387 break; | |
| 1388 case CSSPropertyBorderLeftColor: | |
| 1389 result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor(); | |
| 1390 borderStyle = borderLeftStyle(); | |
| 1391 break; | |
| 1392 case CSSPropertyBorderRightColor: | |
| 1393 result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor(
); | |
| 1394 borderStyle = borderRightStyle(); | |
| 1395 break; | |
| 1396 case CSSPropertyBorderTopColor: | |
| 1397 result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor(); | |
| 1398 borderStyle = borderTopStyle(); | |
| 1399 break; | |
| 1400 case CSSPropertyBorderBottomColor: | |
| 1401 result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColo
r(); | |
| 1402 borderStyle = borderBottomStyle(); | |
| 1403 break; | |
| 1404 case CSSPropertyColor: | |
| 1405 result = visitedLink ? visitedLinkColor() : color(); | |
| 1406 break; | |
| 1407 case CSSPropertyOutlineColor: | |
| 1408 result = visitedLink ? visitedLinkOutlineColor() : outlineColor(); | |
| 1409 break; | |
| 1410 case CSSPropertyWebkitColumnRuleColor: | |
| 1411 result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor(); | |
| 1412 break; | |
| 1413 case CSSPropertyWebkitTextEmphasisColor: | |
| 1414 result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColo
r(); | |
| 1415 break; | |
| 1416 case CSSPropertyWebkitTextFillColor: | |
| 1417 result = visitedLink ? visitedLinkTextFillColor() : textFillColor(); | |
| 1418 break; | |
| 1419 case CSSPropertyWebkitTextStrokeColor: | |
| 1420 result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor(); | |
| 1421 break; | |
| 1422 case CSSPropertyFloodColor: | |
| 1423 result = floodColor(); | |
| 1424 break; | |
| 1425 case CSSPropertyLightingColor: | |
| 1426 result = lightingColor(); | |
| 1427 break; | |
| 1428 case CSSPropertyStopColor: | |
| 1429 result = stopColor(); | |
| 1430 break; | |
| 1431 case CSSPropertyWebkitTapHighlightColor: | |
| 1432 result = tapHighlightColor(); | |
| 1433 break; | |
| 1434 case CSSPropertyTextDecorationColor: | |
| 1435 result = decorationColorIncludingFallback(visitedLink); | |
| 1436 break; | |
| 1437 default: | |
| 1438 ASSERT_NOT_REACHED(); | |
| 1439 break; | |
| 1440 } | |
| 1441 | |
| 1442 if (!result.isCurrentColor()) | |
| 1443 return result.color(); | |
| 1444 | |
| 1445 // FIXME: Treating styled borders with initial color differently causes prob
lems | |
| 1446 // See crbug.com/316559, crbug.com/276231 | |
| 1447 if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || border
Style == RIDGE || borderStyle == GROOVE)) | |
| 1448 return Color(238, 238, 238); | |
| 1449 return visitedLink ? visitedLinkColor() : color(); | |
| 1450 } | |
| 1451 | |
| 1452 Color LayoutStyle::visitedDependentColor(int colorProperty) const | |
| 1453 { | |
| 1454 Color unvisitedColor = colorIncludingFallback(colorProperty, false); | |
| 1455 if (insideLink() != InsideVisitedLink) | |
| 1456 return unvisitedColor; | |
| 1457 | |
| 1458 Color visitedColor = colorIncludingFallback(colorProperty, true); | |
| 1459 | |
| 1460 // FIXME: Technically someone could explicitly specify the color transparent
, but for now we'll just | |
| 1461 // assume that if the background color is transparent that it wasn't set. No
te that it's weird that | |
| 1462 // we're returning unvisited info for a visited link, but given our restrict
ion that the alpha values | |
| 1463 // have to match, it makes more sense to return the unvisited background col
or if specified than it | |
| 1464 // does to return black. This behavior matches what Firefox 4 does as well. | |
| 1465 if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::tr
ansparent) | |
| 1466 return unvisitedColor; | |
| 1467 | |
| 1468 // Take the alpha from the unvisited color, but get the RGB values from the
visited color. | |
| 1469 return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(),
unvisitedColor.alpha()); | |
| 1470 } | |
| 1471 | |
| 1472 const BorderValue& LayoutStyle::borderBefore() const | |
| 1473 { | |
| 1474 switch (writingMode()) { | |
| 1475 case TopToBottomWritingMode: | |
| 1476 return borderTop(); | |
| 1477 case BottomToTopWritingMode: | |
| 1478 return borderBottom(); | |
| 1479 case LeftToRightWritingMode: | |
| 1480 return borderLeft(); | |
| 1481 case RightToLeftWritingMode: | |
| 1482 return borderRight(); | |
| 1483 } | |
| 1484 ASSERT_NOT_REACHED(); | |
| 1485 return borderTop(); | |
| 1486 } | |
| 1487 | |
| 1488 const BorderValue& LayoutStyle::borderAfter() const | |
| 1489 { | |
| 1490 switch (writingMode()) { | |
| 1491 case TopToBottomWritingMode: | |
| 1492 return borderBottom(); | |
| 1493 case BottomToTopWritingMode: | |
| 1494 return borderTop(); | |
| 1495 case LeftToRightWritingMode: | |
| 1496 return borderRight(); | |
| 1497 case RightToLeftWritingMode: | |
| 1498 return borderLeft(); | |
| 1499 } | |
| 1500 ASSERT_NOT_REACHED(); | |
| 1501 return borderBottom(); | |
| 1502 } | |
| 1503 | |
| 1504 const BorderValue& LayoutStyle::borderStart() const | |
| 1505 { | |
| 1506 if (isHorizontalWritingMode()) | |
| 1507 return isLeftToRightDirection() ? borderLeft() : borderRight(); | |
| 1508 return isLeftToRightDirection() ? borderTop() : borderBottom(); | |
| 1509 } | |
| 1510 | |
| 1511 const BorderValue& LayoutStyle::borderEnd() const | |
| 1512 { | |
| 1513 if (isHorizontalWritingMode()) | |
| 1514 return isLeftToRightDirection() ? borderRight() : borderLeft(); | |
| 1515 return isLeftToRightDirection() ? borderBottom() : borderTop(); | |
| 1516 } | |
| 1517 | |
| 1518 unsigned short LayoutStyle::borderBeforeWidth() const | |
| 1519 { | |
| 1520 switch (writingMode()) { | |
| 1521 case TopToBottomWritingMode: | |
| 1522 return borderTopWidth(); | |
| 1523 case BottomToTopWritingMode: | |
| 1524 return borderBottomWidth(); | |
| 1525 case LeftToRightWritingMode: | |
| 1526 return borderLeftWidth(); | |
| 1527 case RightToLeftWritingMode: | |
| 1528 return borderRightWidth(); | |
| 1529 } | |
| 1530 ASSERT_NOT_REACHED(); | |
| 1531 return borderTopWidth(); | |
| 1532 } | |
| 1533 | |
| 1534 unsigned short LayoutStyle::borderAfterWidth() const | |
| 1535 { | |
| 1536 switch (writingMode()) { | |
| 1537 case TopToBottomWritingMode: | |
| 1538 return borderBottomWidth(); | |
| 1539 case BottomToTopWritingMode: | |
| 1540 return borderTopWidth(); | |
| 1541 case LeftToRightWritingMode: | |
| 1542 return borderRightWidth(); | |
| 1543 case RightToLeftWritingMode: | |
| 1544 return borderLeftWidth(); | |
| 1545 } | |
| 1546 ASSERT_NOT_REACHED(); | |
| 1547 return borderBottomWidth(); | |
| 1548 } | |
| 1549 | |
| 1550 unsigned short LayoutStyle::borderStartWidth() const | |
| 1551 { | |
| 1552 if (isHorizontalWritingMode()) | |
| 1553 return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth()
; | |
| 1554 return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth(); | |
| 1555 } | |
| 1556 | |
| 1557 unsigned short LayoutStyle::borderEndWidth() const | |
| 1558 { | |
| 1559 if (isHorizontalWritingMode()) | |
| 1560 return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth()
; | |
| 1561 return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth(); | |
| 1562 } | |
| 1563 | |
| 1564 void LayoutStyle::setMarginStart(const Length& margin) | |
| 1565 { | |
| 1566 if (isHorizontalWritingMode()) { | |
| 1567 if (isLeftToRightDirection()) | |
| 1568 setMarginLeft(margin); | |
| 1569 else | |
| 1570 setMarginRight(margin); | |
| 1571 } else { | |
| 1572 if (isLeftToRightDirection()) | |
| 1573 setMarginTop(margin); | |
| 1574 else | |
| 1575 setMarginBottom(margin); | |
| 1576 } | |
| 1577 } | |
| 1578 | |
| 1579 void LayoutStyle::setMarginEnd(const Length& margin) | |
| 1580 { | |
| 1581 if (isHorizontalWritingMode()) { | |
| 1582 if (isLeftToRightDirection()) | |
| 1583 setMarginRight(margin); | |
| 1584 else | |
| 1585 setMarginLeft(margin); | |
| 1586 } else { | |
| 1587 if (isLeftToRightDirection()) | |
| 1588 setMarginBottom(margin); | |
| 1589 else | |
| 1590 setMarginTop(margin); | |
| 1591 } | |
| 1592 } | |
| 1593 | |
| 1594 void LayoutStyle::setMotionPath(PassRefPtr<StyleMotionPath> path) | |
| 1595 { | |
| 1596 ASSERT(path); | |
| 1597 rareNonInheritedData.access()->m_transform.access()->m_motion.m_path = path; | |
| 1598 } | |
| 1599 | |
| 1600 void LayoutStyle::resetMotionPath() | |
| 1601 { | |
| 1602 rareNonInheritedData.access()->m_transform.access()->m_motion.m_path = nullp
tr; | |
| 1603 } | |
| 1604 | |
| 1605 bool LayoutStyle::columnRuleEquivalent(const LayoutStyle* otherStyle) const | |
| 1606 { | |
| 1607 return columnRuleStyle() == otherStyle->columnRuleStyle() | |
| 1608 && columnRuleWidth() == otherStyle->columnRuleWidth() | |
| 1609 && visitedDependentColor(CSSPropertyWebkitColumnRuleColor) == otherStyle
->visitedDependentColor(CSSPropertyWebkitColumnRuleColor); | |
| 1610 } | |
| 1611 | |
| 1612 TextEmphasisMark LayoutStyle::textEmphasisMark() const | |
| 1613 { | |
| 1614 TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->tex
tEmphasisMark); | |
| 1615 if (mark != TextEmphasisMarkAuto) | |
| 1616 return mark; | |
| 1617 | |
| 1618 if (isHorizontalWritingMode()) | |
| 1619 return TextEmphasisMarkDot; | |
| 1620 | |
| 1621 return TextEmphasisMarkSesame; | |
| 1622 } | |
| 1623 | |
| 1624 Color LayoutStyle::initialTapHighlightColor() | |
| 1625 { | |
| 1626 return LayoutTheme::tapHighlightColor(); | |
| 1627 } | |
| 1628 | |
| 1629 #if ENABLE(OILPAN) | |
| 1630 const FilterOperations& LayoutStyle::initialFilter() | |
| 1631 { | |
| 1632 DEFINE_STATIC_LOCAL(Persistent<FilterOperationsWrapper>, ops, (FilterOperati
onsWrapper::create())); | |
| 1633 return ops->operations(); | |
| 1634 } | |
| 1635 #endif | |
| 1636 | |
| 1637 LayoutRectOutsets LayoutStyle::imageOutsets(const NinePieceImage& image) const | |
| 1638 { | |
| 1639 return LayoutRectOutsets( | |
| 1640 NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()), | |
| 1641 NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()
), | |
| 1642 NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth
()), | |
| 1643 NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()))
; | |
| 1644 } | |
| 1645 | |
| 1646 void LayoutStyle::setBorderImageSource(PassRefPtr<StyleImage> image) | |
| 1647 { | |
| 1648 if (surround->border.m_image.image() == image.get()) | |
| 1649 return; | |
| 1650 surround.access()->border.m_image.setImage(image); | |
| 1651 } | |
| 1652 | |
| 1653 void LayoutStyle::setBorderImageSlices(const LengthBox& slices) | |
| 1654 { | |
| 1655 if (surround->border.m_image.imageSlices() == slices) | |
| 1656 return; | |
| 1657 surround.access()->border.m_image.setImageSlices(slices); | |
| 1658 } | |
| 1659 | |
| 1660 void LayoutStyle::setBorderImageSlicesFill(bool fill) | |
| 1661 { | |
| 1662 if (surround->border.m_image.fill() == fill) | |
| 1663 return; | |
| 1664 surround.access()->border.m_image.setFill(fill); | |
| 1665 } | |
| 1666 | |
| 1667 void LayoutStyle::setBorderImageWidth(const BorderImageLengthBox& slices) | |
| 1668 { | |
| 1669 if (surround->border.m_image.borderSlices() == slices) | |
| 1670 return; | |
| 1671 surround.access()->border.m_image.setBorderSlices(slices); | |
| 1672 } | |
| 1673 | |
| 1674 void LayoutStyle::setBorderImageOutset(const BorderImageLengthBox& outset) | |
| 1675 { | |
| 1676 if (surround->border.m_image.outset() == outset) | |
| 1677 return; | |
| 1678 surround.access()->border.m_image.setOutset(outset); | |
| 1679 } | |
| 1680 | |
| 1681 bool LayoutStyle::borderObscuresBackground() const | |
| 1682 { | |
| 1683 if (!hasBorder()) | |
| 1684 return false; | |
| 1685 | |
| 1686 // Bail if we have any border-image for now. We could look at the image alph
a to improve this. | |
| 1687 if (borderImage().image()) | |
| 1688 return false; | |
| 1689 | |
| 1690 BorderEdge edges[4]; | |
| 1691 getBorderEdgeInfo(edges); | |
| 1692 | |
| 1693 for (int i = BSTop; i <= BSLeft; ++i) { | |
| 1694 const BorderEdge& currEdge = edges[i]; | |
| 1695 if (!currEdge.obscuresBackground()) | |
| 1696 return false; | |
| 1697 } | |
| 1698 | |
| 1699 return true; | |
| 1700 } | |
| 1701 | |
| 1702 void LayoutStyle::getBorderEdgeInfo(BorderEdge edges[], bool includeLogicalLeftE
dge, bool includeLogicalRightEdge) const | |
| 1703 { | |
| 1704 bool horizontal = isHorizontalWritingMode(); | |
| 1705 | |
| 1706 edges[BSTop] = BorderEdge(borderTopWidth(), | |
| 1707 visitedDependentColor(CSSPropertyBorderTopColor), | |
| 1708 borderTopStyle(), | |
| 1709 borderTopIsTransparent(), | |
| 1710 horizontal || includeLogicalLeftEdge); | |
| 1711 | |
| 1712 edges[BSRight] = BorderEdge(borderRightWidth(), | |
| 1713 visitedDependentColor(CSSPropertyBorderRightColor), | |
| 1714 borderRightStyle(), | |
| 1715 borderRightIsTransparent(), | |
| 1716 !horizontal || includeLogicalRightEdge); | |
| 1717 | |
| 1718 edges[BSBottom] = BorderEdge(borderBottomWidth(), | |
| 1719 visitedDependentColor(CSSPropertyBorderBottomColor), | |
| 1720 borderBottomStyle(), | |
| 1721 borderBottomIsTransparent(), | |
| 1722 horizontal || includeLogicalRightEdge); | |
| 1723 | |
| 1724 edges[BSLeft] = BorderEdge(borderLeftWidth(), | |
| 1725 visitedDependentColor(CSSPropertyBorderLeftColor), | |
| 1726 borderLeftStyle(), | |
| 1727 borderLeftIsTransparent(), | |
| 1728 !horizontal || includeLogicalLeftEdge); | |
| 1729 } | |
| 1730 | |
| 1731 } // namespace blink | |
| OLD | NEW |