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