1/* 2 * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2014 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 "RenderStyle.h" 25 26#include "ContentData.h" 27#include "CursorList.h" 28#include "CSSPropertyNames.h" 29#include "FloatRoundedRect.h" 30#include "Font.h" 31#include "FontSelector.h" 32#include "InlineTextBoxStyle.h" 33#include "Pagination.h" 34#include "QuotesData.h" 35#include "RenderObject.h" 36#include "ScaleTransformOperation.h" 37#include "ShadowData.h" 38#include "StyleImage.h" 39#include "StyleInheritedData.h" 40#include "StyleResolver.h" 41#if ENABLE(TOUCH_EVENTS) 42#include "RenderTheme.h" 43#endif 44#include <wtf/MathExtras.h> 45#include <wtf/StdLibExtras.h> 46#include <algorithm> 47 48#if ENABLE(IOS_TEXT_AUTOSIZING) 49#include <wtf/text/StringHash.h> 50#endif 51 52#if ENABLE(TEXT_AUTOSIZING) 53#include "TextAutosizer.h" 54#endif 55 56namespace WebCore { 57 58struct SameSizeAsBorderValue { 59 float m_width; 60 RGBA32 m_color; 61 int m_restBits; 62}; 63 64COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow); 65 66struct SameSizeAsRenderStyle : public RefCounted<SameSizeAsRenderStyle> { 67 void* dataRefs[7]; 68 void* ownPtrs[1]; 69 void* dataRefSvgStyle; 70 struct InheritedFlags { 71 unsigned m_bitfields[2]; 72 } inherited_flags; 73 74 struct NonInheritedFlags { 75 uint64_t m_flags; 76 } noninherited_flags; 77}; 78 79COMPILE_ASSERT(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small); 80 81inline RenderStyle& defaultStyle() 82{ 83 static RenderStyle& style = RenderStyle::createDefaultStyle().leakRef(); 84 return style; 85} 86 87PassRef<RenderStyle> RenderStyle::create() 88{ 89 return adoptRef(*new RenderStyle(defaultStyle())); 90} 91 92PassRef<RenderStyle> RenderStyle::createDefaultStyle() 93{ 94 return adoptRef(*new RenderStyle(true)); 95} 96 97PassRef<RenderStyle> RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay display) 98{ 99 auto newStyle = RenderStyle::create(); 100 newStyle.get().inheritFrom(parentStyle); 101 newStyle.get().inheritUnicodeBidiFrom(parentStyle); 102 newStyle.get().setDisplay(display); 103 return newStyle; 104} 105 106PassRef<RenderStyle> RenderStyle::clone(const RenderStyle* other) 107{ 108 return adoptRef(*new RenderStyle(*other)); 109} 110 111PassRef<RenderStyle> RenderStyle::createStyleInheritingFromPseudoStyle(const RenderStyle& pseudoStyle) 112{ 113 ASSERT(pseudoStyle.styleType() == BEFORE || pseudoStyle.styleType() == AFTER); 114 115 auto style = RenderStyle::create(); 116 style.get().inheritFrom(&pseudoStyle); 117 return style; 118} 119 120ALWAYS_INLINE RenderStyle::RenderStyle(bool) 121 : m_box(StyleBoxData::create()) 122 , visual(StyleVisualData::create()) 123 , m_background(StyleBackgroundData::create()) 124 , surround(StyleSurroundData::create()) 125 , rareNonInheritedData(StyleRareNonInheritedData::create()) 126 , rareInheritedData(StyleRareInheritedData::create()) 127 , inherited(StyleInheritedData::create()) 128 , m_svgStyle(SVGRenderStyle::create()) 129{ 130 inherited_flags._empty_cells = initialEmptyCells(); 131 inherited_flags._caption_side = initialCaptionSide(); 132 inherited_flags._list_style_type = initialListStyleType(); 133 inherited_flags._list_style_position = initialListStylePosition(); 134 inherited_flags._visibility = initialVisibility(); 135 inherited_flags._text_align = initialTextAlign(); 136 inherited_flags._text_transform = initialTextTransform(); 137 inherited_flags._text_decorations = initialTextDecoration(); 138 inherited_flags._cursor_style = initialCursor(); 139#if ENABLE(CURSOR_VISIBILITY) 140 inherited_flags.m_cursorVisibility = initialCursorVisibility(); 141#endif 142 inherited_flags._direction = initialDirection(); 143 inherited_flags._white_space = initialWhiteSpace(); 144 inherited_flags._border_collapse = initialBorderCollapse(); 145 inherited_flags.m_rtlOrdering = initialRTLOrdering(); 146 inherited_flags._box_direction = initialBoxDirection(); 147 inherited_flags.m_printColorAdjust = initialPrintColorAdjust(); 148 inherited_flags._pointerEvents = initialPointerEvents(); 149 inherited_flags._insideLink = NotInsideLink; 150 inherited_flags.m_writingMode = initialWritingMode(); 151 152 static_assert((sizeof(InheritedFlags) <= 8), "InheritedFlags does not grow"); 153 static_assert((sizeof(NonInheritedFlags) <= 8), "NonInheritedFlags does not grow"); 154} 155 156ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o) 157 : RefCounted<RenderStyle>() 158 , m_box(o.m_box) 159 , visual(o.visual) 160 , m_background(o.m_background) 161 , surround(o.surround) 162 , rareNonInheritedData(o.rareNonInheritedData) 163 , rareInheritedData(o.rareInheritedData) 164 , inherited(o.inherited) 165 , m_svgStyle(o.m_svgStyle) 166 , inherited_flags(o.inherited_flags) 167 , noninherited_flags(o.noninherited_flags) 168{ 169} 170 171void RenderStyle::inheritFrom(const RenderStyle* inheritParent, IsAtShadowBoundary isAtShadowBoundary) 172{ 173 if (isAtShadowBoundary == AtShadowBoundary) { 174 // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable 175 EUserModify currentUserModify = userModify(); 176 rareInheritedData = inheritParent->rareInheritedData; 177 setUserModify(currentUserModify); 178 } else 179 rareInheritedData = inheritParent->rareInheritedData; 180 inherited = inheritParent->inherited; 181 inherited_flags = inheritParent->inherited_flags; 182 183 if (m_svgStyle != inheritParent->m_svgStyle) 184 m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get()); 185} 186 187void RenderStyle::copyNonInheritedFrom(const RenderStyle* other) 188{ 189 m_box = other->m_box; 190 visual = other->visual; 191 m_background = other->m_background; 192 surround = other->surround; 193 rareNonInheritedData = other->rareNonInheritedData; 194 noninherited_flags.copyNonInheritedFrom(other->noninherited_flags); 195 196 if (m_svgStyle != other->m_svgStyle) 197 m_svgStyle.access()->copyNonInheritedFrom(other->m_svgStyle.get()); 198 199 ASSERT(zoom() == initialZoom()); 200} 201 202bool RenderStyle::operator==(const RenderStyle& o) const 203{ 204 // compare everything except the pseudoStyle pointer 205 return inherited_flags == o.inherited_flags 206 && noninherited_flags == o.noninherited_flags 207 && m_box == o.m_box 208 && visual == o.visual 209 && m_background == o.m_background 210 && surround == o.surround 211 && rareNonInheritedData == o.rareNonInheritedData 212 && rareInheritedData == o.rareInheritedData 213 && inherited == o.inherited 214 && m_svgStyle == o.m_svgStyle 215 ; 216} 217 218bool RenderStyle::isStyleAvailable() const 219{ 220 return this != StyleResolver::styleNotYetAvailable(); 221} 222 223bool RenderStyle::hasUniquePseudoStyle() const 224{ 225 if (!m_cachedPseudoStyles || styleType() != NOPSEUDO) 226 return false; 227 228 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) { 229 RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get(); 230 if (pseudoStyle->unique()) 231 return true; 232 } 233 234 return false; 235} 236 237RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const 238{ 239 if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size()) 240 return 0; 241 242 if (styleType() != NOPSEUDO) 243 return 0; 244 245 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) { 246 RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get(); 247 if (pseudoStyle->styleType() == pid) 248 return pseudoStyle; 249 } 250 251 return 0; 252} 253 254RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo) 255{ 256 if (!pseudo) 257 return 0; 258 259 ASSERT(pseudo->styleType() > NOPSEUDO); 260 261 RenderStyle* result = pseudo.get(); 262 263 if (!m_cachedPseudoStyles) 264 m_cachedPseudoStyles = std::make_unique<PseudoStyleCache>(); 265 266 m_cachedPseudoStyles->append(pseudo); 267 268 return result; 269} 270 271void RenderStyle::removeCachedPseudoStyle(PseudoId pid) 272{ 273 if (!m_cachedPseudoStyles) 274 return; 275 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) { 276 RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get(); 277 if (pseudoStyle->styleType() == pid) { 278 m_cachedPseudoStyles->remove(i); 279 return; 280 } 281 } 282} 283 284bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const 285{ 286 return inherited_flags != other->inherited_flags 287 || inherited != other->inherited 288 || m_svgStyle->inheritedNotEqual(other->m_svgStyle.get()) 289 || rareInheritedData != other->rareInheritedData; 290} 291 292#if ENABLE(IOS_TEXT_AUTOSIZING) 293inline unsigned computeFontHash(const Font& font) 294{ 295 unsigned hashCodes[2] = { 296 CaseFoldingHash::hash(font.fontDescription().firstFamily().impl()), 297 static_cast<unsigned>(font.fontDescription().specifiedSize()) 298 }; 299 return StringHasher::computeHash(reinterpret_cast<UChar*>(hashCodes), 2 * sizeof(unsigned) / sizeof(UChar)); 300} 301 302uint32_t RenderStyle::hashForTextAutosizing() const 303{ 304 // FIXME: Not a very smart hash. Could be improved upon. See <https://bugs.webkit.org/show_bug.cgi?id=121131>. 305 uint32_t hash = 0; 306 307 hash ^= rareNonInheritedData->m_appearance; 308 hash ^= rareNonInheritedData->marginBeforeCollapse; 309 hash ^= rareNonInheritedData->marginAfterCollapse; 310 hash ^= rareNonInheritedData->lineClamp.value(); 311 hash ^= rareInheritedData->overflowWrap; 312 hash ^= rareInheritedData->nbspMode; 313 hash ^= rareInheritedData->lineBreak; 314 hash ^= WTF::FloatHash<float>::hash(inherited->specifiedLineHeight.value()); 315 hash ^= computeFontHash(inherited->font); 316 hash ^= inherited->horizontal_border_spacing; 317 hash ^= inherited->vertical_border_spacing; 318 hash ^= inherited_flags._box_direction; 319 hash ^= inherited_flags.m_rtlOrdering; 320 hash ^= noninherited_flags.position(); 321 hash ^= noninherited_flags.floating(); 322 hash ^= rareNonInheritedData->textOverflow; 323 hash ^= rareInheritedData->textSecurity; 324 return hash; 325} 326 327bool RenderStyle::equalForTextAutosizing(const RenderStyle* other) const 328{ 329 return rareNonInheritedData->m_appearance == other->rareNonInheritedData->m_appearance 330 && rareNonInheritedData->marginBeforeCollapse == other->rareNonInheritedData->marginBeforeCollapse 331 && rareNonInheritedData->marginAfterCollapse == other->rareNonInheritedData->marginAfterCollapse 332 && rareNonInheritedData->lineClamp == other->rareNonInheritedData->lineClamp 333 && rareInheritedData->textSizeAdjust == other->rareInheritedData->textSizeAdjust 334 && rareInheritedData->overflowWrap == other->rareInheritedData->overflowWrap 335 && rareInheritedData->nbspMode == other->rareInheritedData->nbspMode 336 && rareInheritedData->lineBreak == other->rareInheritedData->lineBreak 337 && rareInheritedData->textSecurity == other->rareInheritedData->textSecurity 338 && inherited->specifiedLineHeight == other->inherited->specifiedLineHeight 339 && inherited->font.equalForTextAutoSizing(other->inherited->font) 340 && inherited->horizontal_border_spacing == other->inherited->horizontal_border_spacing 341 && inherited->vertical_border_spacing == other->inherited->vertical_border_spacing 342 && inherited_flags._box_direction == other->inherited_flags._box_direction 343 && inherited_flags.m_rtlOrdering == other->inherited_flags.m_rtlOrdering 344 && noninherited_flags.position() == other->noninherited_flags.position() 345 && noninherited_flags.floating() == other->noninherited_flags.floating() 346 && rareNonInheritedData->textOverflow == other->rareNonInheritedData->textOverflow; 347} 348#endif // ENABLE(IOS_TEXT_AUTOSIZING) 349 350bool RenderStyle::inheritedDataShared(const RenderStyle* other) const 351{ 352 // This is a fast check that only looks if the data structures are shared. 353 return inherited_flags == other->inherited_flags 354 && inherited.get() == other->inherited.get() 355 && m_svgStyle.get() == other->m_svgStyle.get() 356 && rareInheritedData.get() == other->rareInheritedData.get(); 357} 358 359static bool positionChangeIsMovementOnly(const LengthBox& a, const LengthBox& b, const Length& width) 360{ 361 // If any unit types are different, then we can't guarantee 362 // that this was just a movement. 363 if (a.left().type() != b.left().type() 364 || a.right().type() != b.right().type() 365 || a.top().type() != b.top().type() 366 || a.bottom().type() != b.bottom().type()) 367 return false; 368 369 // Only one unit can be non-auto in the horizontal direction and 370 // in the vertical direction. Otherwise the adjustment of values 371 // is changing the size of the box. 372 if (!a.left().isIntrinsicOrAuto() && !a.right().isIntrinsicOrAuto()) 373 return false; 374 if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto()) 375 return false; 376 // If our width is auto and left or right is specified then this 377 // is not just a movement - we need to resize to our container. 378 if ((!a.left().isIntrinsicOrAuto() || !a.right().isIntrinsicOrAuto()) && width.isIntrinsicOrAuto()) 379 return false; 380 381 // One of the units is fixed or percent in both directions and stayed 382 // that way in the new style. Therefore all we are doing is moving. 383 return true; 384} 385 386inline bool RenderStyle::changeAffectsVisualOverflow(const RenderStyle& other) const 387{ 388 if (rareNonInheritedData.get() != other.rareNonInheritedData.get() 389 && !rareNonInheritedData->shadowDataEquivalent(*other.rareNonInheritedData.get())) 390 return true; 391 392 if (inherited_flags._text_decorations != other.inherited_flags._text_decorations 393 || visual->textDecoration != other.visual->textDecoration 394 || rareNonInheritedData->m_textDecorationStyle != other.rareNonInheritedData->m_textDecorationStyle) { 395 // Underlines are always drawn outside of their textbox bounds when text-underline-position: under; 396 // is specified. We can take an early out here. 397 if (textUnderlinePosition() == TextUnderlinePositionUnder 398 || other.textUnderlinePosition() == TextUnderlinePositionUnder) 399 return true; 400 return visualOverflowForDecorations(*this, nullptr) != visualOverflowForDecorations(other, nullptr); 401 } 402 403 return false; 404} 405 406bool RenderStyle::changeRequiresLayout(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const 407{ 408 if (m_box->width() != other->m_box->width() 409 || m_box->minWidth() != other->m_box->minWidth() 410 || m_box->maxWidth() != other->m_box->maxWidth() 411 || m_box->height() != other->m_box->height() 412 || m_box->minHeight() != other->m_box->minHeight() 413 || m_box->maxHeight() != other->m_box->maxHeight()) 414 return true; 415 416 if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags.verticalAlign() != other->noninherited_flags.verticalAlign()) 417 return true; 418 419 if (m_box->boxSizing() != other->m_box->boxSizing()) 420 return true; 421 422 if (surround->margin != other->surround->margin) 423 return true; 424 425 if (surround->padding != other->surround->padding) 426 return true; 427 428 // FIXME: We should add an optimized form of layout that just recomputes visual overflow. 429 if (changeAffectsVisualOverflow(*other)) 430 return true; 431 432 if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) { 433 if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance 434 || rareNonInheritedData->marginBeforeCollapse != other->rareNonInheritedData->marginBeforeCollapse 435 || rareNonInheritedData->marginAfterCollapse != other->rareNonInheritedData->marginAfterCollapse 436 || rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp 437 || rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow) 438 return true; 439 440 if (rareNonInheritedData->m_regionFragment != other->rareNonInheritedData->m_regionFragment) 441 return true; 442 443#if ENABLE(CSS_SHAPES) 444 if (rareNonInheritedData->m_shapeMargin != other->rareNonInheritedData->m_shapeMargin) 445 return true; 446#endif 447 448 if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get() 449 && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other->rareNonInheritedData->m_deprecatedFlexibleBox.get()) 450 return true; 451 452 if (rareNonInheritedData->m_flexibleBox.get() != other->rareNonInheritedData->m_flexibleBox.get() 453 && *rareNonInheritedData->m_flexibleBox.get() != *other->rareNonInheritedData->m_flexibleBox.get()) 454 return true; 455 if (rareNonInheritedData->m_order != other->rareNonInheritedData->m_order 456 || rareNonInheritedData->m_alignContent != other->rareNonInheritedData->m_alignContent 457 || rareNonInheritedData->m_alignItems != other->rareNonInheritedData->m_alignItems 458 || rareNonInheritedData->m_alignSelf != other->rareNonInheritedData->m_alignSelf 459 || rareNonInheritedData->m_justifyContent != other->rareNonInheritedData->m_justifyContent) 460 return true; 461 462 if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get())) 463 return true; 464 465 if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get() 466 && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get()) 467 return true; 468 469 if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get() 470 && *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) { 471 changedContextSensitiveProperties |= ContextSensitivePropertyTransform; 472 // Don't return; keep looking for another change 473 } 474 475#if ENABLE(CSS_GRID_LAYOUT) 476 if (rareNonInheritedData->m_grid.get() != other->rareNonInheritedData->m_grid.get() 477 || rareNonInheritedData->m_gridItem.get() != other->rareNonInheritedData->m_gridItem.get()) 478 return true; 479#endif 480 481#if ENABLE(DASHBOARD_SUPPORT) 482 // If regions change, trigger a relayout to re-calc regions. 483 if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions) 484 return true; 485#endif 486 } 487 488 if (rareInheritedData.get() != other->rareInheritedData.get()) { 489 if (rareInheritedData->indent != other->rareInheritedData->indent 490#if ENABLE(CSS3_TEXT) 491 || rareInheritedData->m_textAlignLast != other->rareInheritedData->m_textAlignLast 492 || rareInheritedData->m_textIndentLine != other->rareInheritedData->m_textIndentLine 493#endif 494 || rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom 495#if ENABLE(IOS_TEXT_AUTOSIZING) 496 || rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust 497#endif 498 || rareInheritedData->wordBreak != other->rareInheritedData->wordBreak 499 || rareInheritedData->overflowWrap != other->rareInheritedData->overflowWrap 500 || rareInheritedData->nbspMode != other->rareInheritedData->nbspMode 501 || rareInheritedData->lineBreak != other->rareInheritedData->lineBreak 502 || rareInheritedData->textSecurity != other->rareInheritedData->textSecurity 503 || rareInheritedData->hyphens != other->rareInheritedData->hyphens 504 || rareInheritedData->hyphenationLimitBefore != other->rareInheritedData->hyphenationLimitBefore 505 || rareInheritedData->hyphenationLimitAfter != other->rareInheritedData->hyphenationLimitAfter 506 || rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString 507 || rareInheritedData->locale != other->rareInheritedData->locale 508 || rareInheritedData->m_rubyPosition != other->rareInheritedData->m_rubyPosition 509 || rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark 510 || rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition 511 || rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark 512 || rareInheritedData->m_textOrientation != other->rareInheritedData->m_textOrientation 513 || rareInheritedData->m_tabSize != other->rareInheritedData->m_tabSize 514 || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain 515 || rareInheritedData->m_lineGrid != other->rareInheritedData->m_lineGrid 516#if ENABLE(CSS_IMAGE_ORIENTATION) 517 || rareInheritedData->m_imageOrientation != other->rareInheritedData->m_imageOrientation 518#endif 519#if ENABLE(CSS_IMAGE_RESOLUTION) 520 || rareInheritedData->m_imageResolutionSource != other->rareInheritedData->m_imageResolutionSource 521 || rareInheritedData->m_imageResolutionSnap != other->rareInheritedData->m_imageResolutionSnap 522 || rareInheritedData->m_imageResolution != other->rareInheritedData->m_imageResolution 523#endif 524 || rareInheritedData->m_lineSnap != other->rareInheritedData->m_lineSnap 525 || rareInheritedData->m_lineAlign != other->rareInheritedData->m_lineAlign 526#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING) 527 || rareInheritedData->useTouchOverflowScrolling != other->rareInheritedData->useTouchOverflowScrolling 528#endif 529 || rareInheritedData->listStyleImage != other->rareInheritedData->listStyleImage) 530 return true; 531 532 if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get())) 533 return true; 534 535 if (textStrokeWidth() != other->textStrokeWidth()) 536 return true; 537 } 538 539#if ENABLE(TEXT_AUTOSIZING) 540 if (visual->m_textAutosizingMultiplier != other->visual->m_textAutosizingMultiplier) 541 return true; 542#endif 543 544 if (inherited->line_height != other->inherited->line_height 545#if ENABLE(IOS_TEXT_AUTOSIZING) 546 || inherited->specifiedLineHeight != other->inherited->specifiedLineHeight 547#endif 548 || inherited->font != other->inherited->font 549 || inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing 550 || inherited->vertical_border_spacing != other->inherited->vertical_border_spacing 551 || inherited_flags._box_direction != other->inherited_flags._box_direction 552 || inherited_flags.m_rtlOrdering != other->inherited_flags.m_rtlOrdering 553 || noninherited_flags.position() != other->noninherited_flags.position() 554 || noninherited_flags.floating() != other->noninherited_flags.floating() 555 || noninherited_flags.originalDisplay() != other->noninherited_flags.originalDisplay()) 556 return true; 557 558 559 if ((noninherited_flags.effectiveDisplay()) >= TABLE) { 560 if (inherited_flags._border_collapse != other->inherited_flags._border_collapse 561 || inherited_flags._empty_cells != other->inherited_flags._empty_cells 562 || inherited_flags._caption_side != other->inherited_flags._caption_side 563 || noninherited_flags.tableLayout() != other->noninherited_flags.tableLayout()) 564 return true; 565 566 // In the collapsing border model, 'hidden' suppresses other borders, while 'none' 567 // does not, so these style differences can be width differences. 568 if (inherited_flags._border_collapse 569 && ((borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE) 570 || (borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN) 571 || (borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE) 572 || (borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN) 573 || (borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE) 574 || (borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN) 575 || (borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE) 576 || (borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN))) 577 return true; 578 } 579 580 if (noninherited_flags.effectiveDisplay() == LIST_ITEM) { 581 if (inherited_flags._list_style_type != other->inherited_flags._list_style_type 582 || inherited_flags._list_style_position != other->inherited_flags._list_style_position) 583 return true; 584 } 585 586 if (inherited_flags._text_align != other->inherited_flags._text_align 587 || inherited_flags._text_transform != other->inherited_flags._text_transform 588 || inherited_flags._direction != other->inherited_flags._direction 589 || inherited_flags._white_space != other->inherited_flags._white_space 590 || noninherited_flags.clear() != other->noninherited_flags.clear() 591 || noninherited_flags.unicodeBidi() != other->noninherited_flags.unicodeBidi()) 592 return true; 593 594 // Check block flow direction. 595 if (inherited_flags.m_writingMode != other->inherited_flags.m_writingMode) 596 return true; 597 598 // Check text combine mode. 599 if (rareNonInheritedData->m_textCombine != other->rareNonInheritedData->m_textCombine) 600 return true; 601 602 // Overflow returns a layout hint. 603 if (noninherited_flags.overflowX() != other->noninherited_flags.overflowX() 604 || noninherited_flags.overflowY() != other->noninherited_flags.overflowY()) 605 return true; 606 607 // If our border widths change, then we need to layout. Other changes to borders 608 // only necessitate a repaint. 609 if (borderLeftWidth() != other->borderLeftWidth() 610 || borderTopWidth() != other->borderTopWidth() 611 || borderBottomWidth() != other->borderBottomWidth() 612 || borderRightWidth() != other->borderRightWidth()) 613 return true; 614 615 // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree. 616 const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get(); 617 const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get(); 618 if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB))) 619 return true; 620 621 if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE)) 622 return true; 623 624 if (rareNonInheritedData->hasOpacity() != other->rareNonInheritedData->hasOpacity()) { 625 // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet. 626 // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need 627 // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line). 628 // In addition we need to solve the floating object issue when layers come and go. Right now 629 // a full layout is necessary to keep floating object lists sane. 630 return true; 631 } 632 633#if ENABLE(CSS_FILTERS) 634 if (rareNonInheritedData->hasFilters() != other->rareNonInheritedData->hasFilters()) 635 return true; 636#endif 637 638 const QuotesData* quotesDataA = rareInheritedData->quotes.get(); 639 const QuotesData* quotesDataB = other->rareInheritedData->quotes.get(); 640 if (!(quotesDataA == quotesDataB || (quotesDataA && quotesDataB && *quotesDataA == *quotesDataB))) 641 return true; 642 643 if (position() != StaticPosition) { 644 if (surround->offset != other->surround->offset) { 645 // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet. 646 // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need 647 // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line). 648 if (position() != AbsolutePosition) 649 return true; 650 651 // Optimize for the case where a positioned layer is moving but not changing size. 652 if (!positionChangeIsMovementOnly(surround->offset, other->surround->offset, m_box->width())) 653 return true; 654 } 655 } 656 657 return false; 658} 659 660bool RenderStyle::changeRequiresPositionedLayoutOnly(const RenderStyle* other, unsigned&) const 661{ 662 if (position() == StaticPosition) 663 return false; 664 665 if (surround->offset != other->surround->offset) { 666 // Optimize for the case where a positioned layer is moving but not changing size. 667 if (position() == AbsolutePosition && positionChangeIsMovementOnly(surround->offset, other->surround->offset, m_box->width())) 668 return true; 669 } 670 671 return false; 672} 673 674bool RenderStyle::changeRequiresLayerRepaint(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const 675{ 676 // StyleResolver has ensured that zIndex is non-auto only if it's applicable. 677 if (m_box->zIndex() != other->m_box->zIndex() || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex()) 678 return true; 679 680 if (position() != StaticPosition) { 681 if (visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip) { 682 changedContextSensitiveProperties |= ContextSensitivePropertyClipRect; 683 return true; 684 } 685 } 686 687#if ENABLE(CSS_COMPOSITING) 688 if (rareNonInheritedData->m_effectiveBlendMode != other->rareNonInheritedData->m_effectiveBlendMode) 689 return true; 690#endif 691 692 if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) { 693 changedContextSensitiveProperties |= ContextSensitivePropertyOpacity; 694 // Don't return; keep looking for another change. 695 } 696 697#if ENABLE(CSS_FILTERS) 698 if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get() 699 && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) { 700 changedContextSensitiveProperties |= ContextSensitivePropertyFilter; 701 // Don't return; keep looking for another change. 702 } 703#endif 704 705 if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask 706 || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage) 707 return true; 708 709 return false; 710} 711 712bool RenderStyle::changeRequiresRepaint(const RenderStyle* other, unsigned&) const 713{ 714 if (inherited_flags._visibility != other->inherited_flags._visibility 715 || inherited_flags.m_printColorAdjust != other->inherited_flags.m_printColorAdjust 716 || inherited_flags._insideLink != other->inherited_flags._insideLink 717 || surround->border != other->surround->border 718 || !m_background->isEquivalentForPainting(*other->m_background) 719 || rareInheritedData->userModify != other->rareInheritedData->userModify 720 || rareInheritedData->userSelect != other->rareInheritedData->userSelect 721 || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag 722 || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit 723 || rareNonInheritedData->m_objectFit != other->rareNonInheritedData->m_objectFit 724 || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering) 725 return true; 726 727#if ENABLE(CSS_SHAPES) 728 if (rareNonInheritedData->m_shapeOutside != other->rareNonInheritedData->m_shapeOutside) 729 return true; 730#endif 731 732 if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath) 733 return true; 734 735 return false; 736} 737 738bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle* other, unsigned&) const 739{ 740 if (inherited->color != other->inherited->color 741 || inherited_flags._text_decorations != other->inherited_flags._text_decorations 742 || visual->textDecoration != other->visual->textDecoration 743 || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle 744 || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor 745 || rareInheritedData->m_textDecorationSkip != other->rareInheritedData->m_textDecorationSkip 746 || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor 747 || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor 748 || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor 749 || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill) 750 return true; 751 752 return false; 753} 754 755bool RenderStyle::changeRequiresRecompositeLayer(const RenderStyle* other, unsigned&) const 756{ 757 if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) { 758 if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D 759 || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility 760 || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective 761 || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX 762 || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY) 763 return true; 764 } 765 766 return false; 767} 768 769StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const 770{ 771 changedContextSensitiveProperties = ContextSensitivePropertyNone; 772 773 StyleDifference svgChange = StyleDifferenceEqual; 774 if (m_svgStyle != other->m_svgStyle) { 775 svgChange = m_svgStyle->diff(other->m_svgStyle.get()); 776 if (svgChange == StyleDifferenceLayout) 777 return svgChange; 778 } 779 780 if (changeRequiresLayout(other, changedContextSensitiveProperties)) 781 return StyleDifferenceLayout; 782 783 // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes. 784 // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint, 785 // but have to return StyleDifferenceLayout, that's why this if branch comes after all branches 786 // that are relevant for SVG and might return StyleDifferenceLayout. 787 if (svgChange != StyleDifferenceEqual) 788 return svgChange; 789 790 if (changeRequiresPositionedLayoutOnly(other, changedContextSensitiveProperties)) 791 return StyleDifferenceLayoutPositionedMovementOnly; 792 793 if (changeRequiresLayerRepaint(other, changedContextSensitiveProperties)) 794 return StyleDifferenceRepaintLayer; 795 796 if (changeRequiresRepaint(other, changedContextSensitiveProperties)) 797 return StyleDifferenceRepaint; 798 799 if (changeRequiresRecompositeLayer(other, changedContextSensitiveProperties)) 800 return StyleDifferenceRecompositeLayer; 801 802 if (changeRequiresRepaintIfTextOrBorderOrOutline(other, changedContextSensitiveProperties)) 803 return StyleDifferenceRepaintIfTextOrBorderOrOutline; 804 805 // Cursors are not checked, since they will be set appropriately in response to mouse events, 806 // so they don't need to cause any repaint or layout. 807 808 // 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 809 // the resulting transition properly. 810 return StyleDifferenceEqual; 811} 812 813bool RenderStyle::diffRequiresLayerRepaint(const RenderStyle& style, bool isComposited) const 814{ 815 unsigned changedContextSensitiveProperties = 0; 816 817 if (changeRequiresRepaint(&style, changedContextSensitiveProperties)) 818 return true; 819 820 if (isComposited && changeRequiresLayerRepaint(&style, changedContextSensitiveProperties)) 821 return changedContextSensitiveProperties & ContextSensitivePropertyClipRect; 822 823 return false; 824} 825 826void RenderStyle::setClip(Length top, Length right, Length bottom, Length left) 827{ 828 StyleVisualData* data = visual.access(); 829 data->clip.m_top = top; 830 data->clip.m_right = right; 831 data->clip.m_bottom = bottom; 832 data->clip.m_left = left; 833} 834 835void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot) 836{ 837 if (!rareInheritedData.access()->cursorData) 838 rareInheritedData.access()->cursorData = CursorList::create(); 839 rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot)); 840} 841 842void RenderStyle::setCursorList(PassRefPtr<CursorList> other) 843{ 844 rareInheritedData.access()->cursorData = other; 845} 846 847void RenderStyle::setQuotes(PassRefPtr<QuotesData> q) 848{ 849 if (rareInheritedData->quotes == q || (rareInheritedData->quotes && q && *rareInheritedData->quotes == *q)) 850 return; 851 852 rareInheritedData.access()->quotes = q; 853} 854 855void RenderStyle::clearCursorList() 856{ 857 if (rareInheritedData->cursorData) 858 rareInheritedData.access()->cursorData = 0; 859} 860 861void RenderStyle::clearContent() 862{ 863 if (rareNonInheritedData->m_content) 864 rareNonInheritedData.access()->m_content = nullptr; 865} 866 867void RenderStyle::appendContent(std::unique_ptr<ContentData> contentData) 868{ 869 auto& content = rareNonInheritedData.access()->m_content; 870 ContentData* lastContent = content.get(); 871 while (lastContent && lastContent->next()) 872 lastContent = lastContent->next(); 873 874 if (lastContent) 875 lastContent->setNext(WTF::move(contentData)); 876 else 877 content = WTF::move(contentData); 878} 879 880void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add) 881{ 882 if (!image) 883 return; 884 885 if (add) { 886 appendContent(std::make_unique<ImageContentData>(image)); 887 return; 888 } 889 890 rareNonInheritedData.access()->m_content = std::make_unique<ImageContentData>(image); 891 if (!rareNonInheritedData.access()->m_altText.isNull()) 892 rareNonInheritedData.access()->m_content->setAltText(rareNonInheritedData.access()->m_altText); 893} 894 895void RenderStyle::setContent(const String& string, bool add) 896{ 897 auto& content = rareNonInheritedData.access()->m_content; 898 if (add) { 899 ContentData* lastContent = content.get(); 900 while (lastContent && lastContent->next()) 901 lastContent = lastContent->next(); 902 903 if (lastContent) { 904 // We attempt to merge with the last ContentData if possible. 905 if (lastContent->isText()) { 906 TextContentData* textContent = toTextContentData(lastContent); 907 textContent->setText(textContent->text() + string); 908 } else 909 lastContent->setNext(std::make_unique<TextContentData>(string)); 910 911 if (!rareNonInheritedData.access()->m_altText.isNull()) 912 lastContent->setAltText(rareNonInheritedData.access()->m_altText); 913 return; 914 } 915 } 916 917 content = std::make_unique<TextContentData>(string); 918 if (!rareNonInheritedData.access()->m_altText.isNull()) 919 content->setAltText(rareNonInheritedData.access()->m_altText); 920} 921 922void RenderStyle::setContent(std::unique_ptr<CounterContent> counter, bool add) 923{ 924 if (!counter) 925 return; 926 927 if (add) { 928 appendContent(std::make_unique<CounterContentData>(WTF::move(counter))); 929 return; 930 } 931 932 rareNonInheritedData.access()->m_content = std::make_unique<CounterContentData>(WTF::move(counter)); 933} 934 935void RenderStyle::setContent(QuoteType quote, bool add) 936{ 937 if (add) { 938 appendContent(std::make_unique<QuoteContentData>(quote)); 939 return; 940 } 941 942 rareNonInheritedData.access()->m_content = std::make_unique<QuoteContentData>(quote); 943} 944 945void RenderStyle::setContentAltText(const String& string) 946{ 947 rareNonInheritedData.access()->m_altText = string; 948 949 if (rareNonInheritedData.access()->m_content) 950 rareNonInheritedData.access()->m_content->setAltText(string); 951} 952 953const String& RenderStyle::contentAltText() const 954{ 955 return rareNonInheritedData->m_altText; 956} 957 958static inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation>>& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin) 959{ 960 // transform-origin brackets the transform with translate operations. 961 // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant 962 // in that case. 963 if (applyOrigin != RenderStyle::IncludeTransformOrigin) 964 return false; 965 966 for (auto& operation : transformOperations) { 967 TransformOperation::OperationType type = operation->type(); 968 if (type != TransformOperation::TRANSLATE_X 969 && type != TransformOperation::TRANSLATE_Y 970 && type != TransformOperation::TRANSLATE 971 && type != TransformOperation::TRANSLATE_Z 972 && type != TransformOperation::TRANSLATE_3D) 973 return true; 974 } 975 976 return false; 977} 978 979void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const 980{ 981 auto& operations = rareNonInheritedData->m_transform->m_operations.operations(); 982 bool applyTransformOrigin = requireTransformOrigin(operations, applyOrigin); 983 984 float offsetX = transformOriginX().isPercentNotCalculated() ? boundingBox.x() : 0; 985 float offsetY = transformOriginY().isPercentNotCalculated() ? boundingBox.y() : 0; 986 987 if (applyTransformOrigin) { 988 transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX, 989 floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY, 990 transformOriginZ()); 991 } 992 993 for (auto& operation : operations) 994 operation->apply(transform, boundingBox.size()); 995 996 if (applyTransformOrigin) { 997 transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX, 998 -floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY, 999 -transformOriginZ()); 1000 } 1001} 1002 1003void RenderStyle::setPageScaleTransform(float scale) 1004{ 1005 if (scale == 1) 1006 return; 1007 TransformOperations transform; 1008 transform.operations().append(ScaleTransformOperation::create(scale, scale, ScaleTransformOperation::SCALE)); 1009 setTransform(transform); 1010 setTransformOriginX(Length(0, Fixed)); 1011 setTransformOriginY(Length(0, Fixed)); 1012} 1013 1014void RenderStyle::setTextShadow(std::unique_ptr<ShadowData> shadowData, bool add) 1015{ 1016 ASSERT(!shadowData || (!shadowData->spread() && shadowData->style() == Normal)); 1017 1018 StyleRareInheritedData* rareData = rareInheritedData.access(); 1019 if (!add) { 1020 rareData->textShadow = WTF::move(shadowData); 1021 return; 1022 } 1023 1024 shadowData->setNext(WTF::move(rareData->textShadow)); 1025 rareData->textShadow = WTF::move(shadowData); 1026} 1027 1028void RenderStyle::setBoxShadow(std::unique_ptr<ShadowData> shadowData, bool add) 1029{ 1030 StyleRareNonInheritedData* rareData = rareNonInheritedData.access(); 1031 if (!add) { 1032 rareData->m_boxShadow = WTF::move(shadowData); 1033 return; 1034 } 1035 1036 shadowData->setNext(WTF::move(rareData->m_boxShadow)); 1037 rareData->m_boxShadow = WTF::move(shadowData); 1038} 1039 1040static RoundedRect::Radii calcRadiiFor(const BorderData& border, const LayoutSize& size) 1041{ 1042 return RoundedRect::Radii( 1043 LayoutSize(valueForLength(border.topLeft().width(), size.width()), 1044 valueForLength(border.topLeft().height(), size.height())), 1045 LayoutSize(valueForLength(border.topRight().width(), size.width()), 1046 valueForLength(border.topRight().height(), size.height())), 1047 LayoutSize(valueForLength(border.bottomLeft().width(), size.width()), 1048 valueForLength(border.bottomLeft().height(), size.height())), 1049 LayoutSize(valueForLength(border.bottomRight().width(), size.width()), 1050 valueForLength(border.bottomRight().height(), size.height()))); 1051} 1052 1053StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); } 1054void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v) 1055{ 1056 if (rareInheritedData->listStyleImage != v) 1057 rareInheritedData.access()->listStyleImage = v; 1058} 1059 1060Color RenderStyle::color() const { return inherited->color; } 1061Color RenderStyle::visitedLinkColor() const { return inherited->visitedLinkColor; } 1062void RenderStyle::setColor(const Color& v) { SET_VAR(inherited, color, v); } 1063void RenderStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visitedLinkColor, v); } 1064 1065short RenderStyle::horizontalBorderSpacing() const { return inherited->horizontal_border_spacing; } 1066short RenderStyle::verticalBorderSpacing() const { return inherited->vertical_border_spacing; } 1067void RenderStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v); } 1068void RenderStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertical_border_spacing, v); } 1069 1070RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const 1071{ 1072 RoundedRect roundedRect(borderRect); 1073 if (hasBorderRadius()) { 1074 RoundedRect::Radii radii = calcRadiiFor(surround->border, borderRect.size()); 1075 radii.scale(calcBorderRadiiConstraintScaleFor(borderRect, radii)); 1076 roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge); 1077 } 1078 return roundedRect; 1079} 1080 1081RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const 1082{ 1083 bool horizontal = isHorizontalWritingMode(); 1084 1085 LayoutUnit leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0; 1086 LayoutUnit rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0; 1087 LayoutUnit topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0; 1088 LayoutUnit bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0; 1089 1090 return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge); 1091} 1092 1093RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, LayoutUnit topWidth, LayoutUnit bottomWidth, 1094 LayoutUnit leftWidth, LayoutUnit rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const 1095{ 1096 LayoutRect innerRect(borderRect.x() + leftWidth, 1097 borderRect.y() + topWidth, 1098 borderRect.width() - leftWidth - rightWidth, 1099 borderRect.height() - topWidth - bottomWidth); 1100 1101 RoundedRect roundedRect(innerRect); 1102 1103 if (hasBorderRadius()) { 1104 RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii(); 1105 radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth); 1106 roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge); 1107 } 1108 return roundedRect; 1109} 1110 1111static bool allLayersAreFixed(const FillLayer* layer) 1112{ 1113 bool allFixed = true; 1114 1115 for (const FillLayer* currLayer = layer; currLayer; currLayer = currLayer->next()) 1116 allFixed &= (currLayer->image() && currLayer->attachment() == FixedBackgroundAttachment); 1117 1118 return layer && allFixed; 1119} 1120 1121bool RenderStyle::hasEntirelyFixedBackground() const 1122{ 1123 return allLayersAreFixed(backgroundLayers()); 1124} 1125 1126const CounterDirectiveMap* RenderStyle::counterDirectives() const 1127{ 1128 return rareNonInheritedData->m_counterDirectives.get(); 1129} 1130 1131CounterDirectiveMap& RenderStyle::accessCounterDirectives() 1132{ 1133 auto& map = rareNonInheritedData.access()->m_counterDirectives; 1134 if (!map) 1135 map = std::make_unique<CounterDirectiveMap>(); 1136 return *map; 1137} 1138 1139const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const 1140{ 1141 if (const CounterDirectiveMap* directives = counterDirectives()) 1142 return directives->get(identifier); 1143 return CounterDirectives(); 1144} 1145 1146const AtomicString& RenderStyle::hyphenString() const 1147{ 1148 ASSERT(hyphens() != HyphensNone); 1149 1150 const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString; 1151 if (!hyphenationString.isNull()) 1152 return hyphenationString; 1153 1154 // FIXME: This should depend on locale. 1155 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinus, 1)); 1156 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphen, 1)); 1157 return font().primaryFontHasGlyphForCharacter(hyphen) ? hyphenString : hyphenMinusString; 1158} 1159 1160const AtomicString& RenderStyle::textEmphasisMarkString() const 1161{ 1162 switch (textEmphasisMark()) { 1163 case TextEmphasisMarkNone: 1164 return nullAtom; 1165 case TextEmphasisMarkCustom: 1166 return textEmphasisCustomMark(); 1167 case TextEmphasisMarkDot: { 1168 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1)); 1169 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1)); 1170 return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString; 1171 } 1172 case TextEmphasisMarkCircle: { 1173 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1)); 1174 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1)); 1175 return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString; 1176 } 1177 case TextEmphasisMarkDoubleCircle: { 1178 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1)); 1179 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1)); 1180 return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString; 1181 } 1182 case TextEmphasisMarkTriangle: { 1183 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointingTriangle, 1)); 1184 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingTriangle, 1)); 1185 return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString; 1186 } 1187 case TextEmphasisMarkSesame: { 1188 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1)); 1189 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1)); 1190 return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString; 1191 } 1192 case TextEmphasisMarkAuto: 1193 ASSERT_NOT_REACHED(); 1194 return nullAtom; 1195 } 1196 1197 ASSERT_NOT_REACHED(); 1198 return nullAtom; 1199} 1200 1201#if ENABLE(DASHBOARD_SUPPORT) 1202const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions() 1203{ 1204 DEPRECATED_DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ()); 1205 return emptyList; 1206} 1207 1208const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions() 1209{ 1210 DEPRECATED_DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, noneList, ()); 1211 static bool noneListInitialized = false; 1212 1213 if (!noneListInitialized) { 1214 StyleDashboardRegion region; 1215 region.label = ""; 1216 region.offset.m_top = Length(); 1217 region.offset.m_right = Length(); 1218 region.offset.m_bottom = Length(); 1219 region.offset.m_left = Length(); 1220 region.type = StyleDashboardRegion::None; 1221 noneList.append(region); 1222 noneListInitialized = true; 1223 } 1224 return noneList; 1225} 1226#endif 1227 1228void RenderStyle::adjustAnimations() 1229{ 1230 AnimationList* animationList = rareNonInheritedData->m_animations.get(); 1231 if (!animationList) 1232 return; 1233 1234 // Get rid of empty animations and anything beyond them 1235 for (size_t i = 0; i < animationList->size(); ++i) { 1236 if (animationList->animation(i).isEmpty()) { 1237 animationList->resize(i); 1238 break; 1239 } 1240 } 1241 1242 if (animationList->isEmpty()) { 1243 clearAnimations(); 1244 return; 1245 } 1246 1247 // Repeat patterns into layers that don't have some properties set. 1248 animationList->fillUnsetProperties(); 1249} 1250 1251void RenderStyle::adjustTransitions() 1252{ 1253 AnimationList* transitionList = rareNonInheritedData->m_transitions.get(); 1254 if (!transitionList) 1255 return; 1256 1257 // Get rid of empty transitions and anything beyond them 1258 for (size_t i = 0; i < transitionList->size(); ++i) { 1259 if (transitionList->animation(i).isEmpty()) { 1260 transitionList->resize(i); 1261 break; 1262 } 1263 } 1264 1265 if (transitionList->isEmpty()) { 1266 clearTransitions(); 1267 return; 1268 } 1269 1270 // Repeat patterns into layers that don't have some properties set. 1271 transitionList->fillUnsetProperties(); 1272 1273 // Make sure there are no duplicate properties. This is an O(n^2) algorithm 1274 // but the lists tend to be very short, so it is probably ok 1275 for (size_t i = 0; i < transitionList->size(); ++i) { 1276 for (size_t j = i+1; j < transitionList->size(); ++j) { 1277 if (transitionList->animation(i).property() == transitionList->animation(j).property()) { 1278 // toss i 1279 transitionList->remove(i); 1280 j = i; 1281 } 1282 } 1283 } 1284} 1285 1286AnimationList* RenderStyle::accessAnimations() 1287{ 1288 if (!rareNonInheritedData.access()->m_animations) 1289 rareNonInheritedData.access()->m_animations = std::make_unique<AnimationList>(); 1290 return rareNonInheritedData->m_animations.get(); 1291} 1292 1293AnimationList* RenderStyle::accessTransitions() 1294{ 1295 if (!rareNonInheritedData.access()->m_transitions) 1296 rareNonInheritedData.access()->m_transitions = std::make_unique<AnimationList>(); 1297 return rareNonInheritedData->m_transitions.get(); 1298} 1299 1300const Animation* RenderStyle::transitionForProperty(CSSPropertyID property) const 1301{ 1302 if (transitions()) { 1303 for (size_t i = 0; i < transitions()->size(); ++i) { 1304 const Animation& p = transitions()->animation(i); 1305 if (p.animationMode() == Animation::AnimateAll || p.property() == property) { 1306 return &p; 1307 } 1308 } 1309 } 1310 return 0; 1311} 1312 1313const Font& RenderStyle::font() const { return inherited->font; } 1314const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); } 1315const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); } 1316float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); } 1317float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); } 1318int RenderStyle::fontSize() const { return inherited->font.pixelSize(); } 1319 1320const Length& RenderStyle::wordSpacing() const { return rareInheritedData->wordSpacing; } 1321float RenderStyle::letterSpacing() const { return inherited->font.letterSpacing(); } 1322 1323bool RenderStyle::setFontDescription(const FontDescription& v) 1324{ 1325 if (inherited->font.fontDescription() != v) { 1326 inherited.access()->font = Font(v, inherited->font.letterSpacing(), inherited->font.wordSpacing()); 1327 return true; 1328 } 1329 return false; 1330} 1331 1332#if ENABLE(IOS_TEXT_AUTOSIZING) 1333const Length& RenderStyle::specifiedLineHeight() const { return inherited->specifiedLineHeight; } 1334void RenderStyle::setSpecifiedLineHeight(Length v) { SET_VAR(inherited, specifiedLineHeight, v); } 1335#else 1336const Length& RenderStyle::specifiedLineHeight() const { return inherited->line_height; } 1337#endif 1338 1339Length RenderStyle::lineHeight() const 1340{ 1341 const Length& lh = inherited->line_height; 1342#if ENABLE(TEXT_AUTOSIZING) 1343 // Unlike fontDescription().computedSize() and hence fontSize(), this is 1344 // recalculated on demand as we only store the specified line height. 1345 // FIXME: Should consider scaling the fixed part of any calc expressions 1346 // too, though this involves messily poking into CalcExpressionLength. 1347 float multiplier = textAutosizingMultiplier(); 1348 if (multiplier > 1 && lh.isFixed()) 1349 return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multiplier), Fixed); 1350#endif 1351 return lh; 1352} 1353void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); } 1354 1355int RenderStyle::computedLineHeight() const 1356{ 1357 const Length& lh = lineHeight(); 1358 1359 // Negative value means the line height is not set. Use the font's built-in spacing. 1360 if (lh.isNegative()) 1361 return fontMetrics().lineSpacing(); 1362 1363 if (lh.isPercent()) 1364 return minimumValueForLength(lh, fontSize()); 1365 1366 return lh.value(); 1367} 1368 1369void RenderStyle::setWordSpacing(Length value) 1370{ 1371 float fontWordSpacing; 1372 switch (value.type()) { 1373 case Auto: 1374 fontWordSpacing = 0; 1375 break; 1376 case Percent: 1377 fontWordSpacing = value.percent() * font().spaceWidth() / 100; 1378 break; 1379 case Fixed: 1380 fontWordSpacing = value.value(); 1381 break; 1382 default: 1383 ASSERT_NOT_REACHED(); 1384 fontWordSpacing = 0; 1385 break; 1386 } 1387 inherited.access()->font.setWordSpacing(fontWordSpacing); 1388 rareInheritedData.access()->wordSpacing = WTF::move(value); 1389} 1390 1391void RenderStyle::setLetterSpacing(float v) { inherited.access()->font.setLetterSpacing(v); } 1392 1393void RenderStyle::setFontSize(float size) 1394{ 1395 // size must be specifiedSize if Text Autosizing is enabled, but computedSize if text 1396 // zoom is enabled (if neither is enabled it's irrelevant as they're probably the same). 1397 1398 ASSERT(std::isfinite(size)); 1399 if (!std::isfinite(size) || size < 0) 1400 size = 0; 1401 else 1402 size = std::min(maximumAllowedFontSize, size); 1403 1404 FontSelector* currentFontSelector = font().fontSelector(); 1405 FontDescription desc(fontDescription()); 1406 desc.setSpecifiedSize(size); 1407 desc.setComputedSize(size); 1408 1409#if ENABLE(TEXT_AUTOSIZING) 1410 float multiplier = textAutosizingMultiplier(); 1411 if (multiplier > 1) { 1412 float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size, multiplier); 1413 desc.setComputedSize(min(maximumAllowedFontSize, autosizedFontSize)); 1414 } 1415#endif 1416 1417 setFontDescription(desc); 1418 font().update(currentFontSelector); 1419} 1420 1421void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const 1422{ 1423 top = 0; 1424 right = 0; 1425 bottom = 0; 1426 left = 0; 1427 1428 for ( ; shadow; shadow = shadow->next()) { 1429 if (shadow->style() == Inset) 1430 continue; 1431 1432 int extentAndSpread = shadow->paintingExtent() + shadow->spread(); 1433 top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread); 1434 right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread); 1435 bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread); 1436 left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread); 1437 } 1438} 1439 1440LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowData* shadow) const 1441{ 1442 LayoutUnit top = 0; 1443 LayoutUnit right = 0; 1444 LayoutUnit bottom = 0; 1445 LayoutUnit left = 0; 1446 1447 for ( ; shadow; shadow = shadow->next()) { 1448 if (shadow->style() == Normal) 1449 continue; 1450 1451 int extentAndSpread = shadow->paintingExtent() + shadow->spread(); 1452 top = std::max<LayoutUnit>(top, shadow->y() + extentAndSpread); 1453 right = std::min<LayoutUnit>(right, shadow->x() - extentAndSpread); 1454 bottom = std::min<LayoutUnit>(bottom, shadow->y() - extentAndSpread); 1455 left = std::max<LayoutUnit>(left, shadow->x() + extentAndSpread); 1456 } 1457 1458 return LayoutBoxExtent(top, right, bottom, left); 1459} 1460 1461void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit &left, LayoutUnit &right) const 1462{ 1463 left = 0; 1464 right = 0; 1465 1466 for ( ; shadow; shadow = shadow->next()) { 1467 if (shadow->style() == Inset) 1468 continue; 1469 1470 int extentAndSpread = shadow->paintingExtent() + shadow->spread(); 1471 left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread); 1472 right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread); 1473 } 1474} 1475 1476void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &bottom) const 1477{ 1478 top = 0; 1479 bottom = 0; 1480 1481 for ( ; shadow; shadow = shadow->next()) { 1482 if (shadow->style() == Inset) 1483 continue; 1484 1485 int extentAndSpread = shadow->paintingExtent() + shadow->spread(); 1486 top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread); 1487 bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread); 1488 } 1489} 1490 1491Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const 1492{ 1493 Color result; 1494 EBorderStyle borderStyle = BNONE; 1495 switch (colorProperty) { 1496 case CSSPropertyBackgroundColor: 1497 return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back. 1498 case CSSPropertyBorderLeftColor: 1499 result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor(); 1500 borderStyle = borderLeftStyle(); 1501 break; 1502 case CSSPropertyBorderRightColor: 1503 result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor(); 1504 borderStyle = borderRightStyle(); 1505 break; 1506 case CSSPropertyBorderTopColor: 1507 result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor(); 1508 borderStyle = borderTopStyle(); 1509 break; 1510 case CSSPropertyBorderBottomColor: 1511 result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor(); 1512 borderStyle = borderBottomStyle(); 1513 break; 1514 case CSSPropertyColor: 1515 result = visitedLink ? visitedLinkColor() : color(); 1516 break; 1517 case CSSPropertyOutlineColor: 1518 result = visitedLink ? visitedLinkOutlineColor() : outlineColor(); 1519 break; 1520 case CSSPropertyWebkitColumnRuleColor: 1521 result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor(); 1522 break; 1523 case CSSPropertyWebkitTextDecorationColor: 1524 // Text decoration color fallback is handled in RenderObject::decorationColor. 1525 return visitedLink ? visitedLinkTextDecorationColor() : textDecorationColor(); 1526 case CSSPropertyWebkitTextEmphasisColor: 1527 result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor(); 1528 break; 1529 case CSSPropertyWebkitTextFillColor: 1530 result = visitedLink ? visitedLinkTextFillColor() : textFillColor(); 1531 break; 1532 case CSSPropertyWebkitTextStrokeColor: 1533 result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor(); 1534 break; 1535 default: 1536 ASSERT_NOT_REACHED(); 1537 break; 1538 } 1539 1540 if (!result.isValid()) { 1541 if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE)) 1542 result.setRGB(238, 238, 238); 1543 else 1544 result = visitedLink ? visitedLinkColor() : color(); 1545 } 1546 return result; 1547} 1548 1549Color RenderStyle::visitedDependentColor(int colorProperty) const 1550{ 1551 Color unvisitedColor = colorIncludingFallback(colorProperty, false); 1552 if (insideLink() != InsideVisitedLink) 1553 return unvisitedColor; 1554 1555 Color visitedColor = colorIncludingFallback(colorProperty, true); 1556 1557 // Text decoration color validity is preserved (checked in RenderObject::decorationColor). 1558 if (colorProperty == CSSPropertyWebkitTextDecorationColor) 1559 return visitedColor; 1560 1561 // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just 1562 // assume that if the background color is transparent that it wasn't set. Note that it's weird that 1563 // we're returning unvisited info for a visited link, but given our restriction that the alpha values 1564 // have to match, it makes more sense to return the unvisited background color if specified than it 1565 // does to return black. This behavior matches what Firefox 4 does as well. 1566 if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent) 1567 return unvisitedColor; 1568 1569 // Take the alpha from the unvisited color, but get the RGB values from the visited color. 1570 return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha()); 1571} 1572 1573const BorderValue& RenderStyle::borderBefore() const 1574{ 1575 switch (writingMode()) { 1576 case TopToBottomWritingMode: 1577 return borderTop(); 1578 case BottomToTopWritingMode: 1579 return borderBottom(); 1580 case LeftToRightWritingMode: 1581 return borderLeft(); 1582 case RightToLeftWritingMode: 1583 return borderRight(); 1584 } 1585 ASSERT_NOT_REACHED(); 1586 return borderTop(); 1587} 1588 1589const BorderValue& RenderStyle::borderAfter() const 1590{ 1591 switch (writingMode()) { 1592 case TopToBottomWritingMode: 1593 return borderBottom(); 1594 case BottomToTopWritingMode: 1595 return borderTop(); 1596 case LeftToRightWritingMode: 1597 return borderRight(); 1598 case RightToLeftWritingMode: 1599 return borderLeft(); 1600 } 1601 ASSERT_NOT_REACHED(); 1602 return borderBottom(); 1603} 1604 1605const BorderValue& RenderStyle::borderStart() const 1606{ 1607 if (isHorizontalWritingMode()) 1608 return isLeftToRightDirection() ? borderLeft() : borderRight(); 1609 return isLeftToRightDirection() ? borderTop() : borderBottom(); 1610} 1611 1612const BorderValue& RenderStyle::borderEnd() const 1613{ 1614 if (isHorizontalWritingMode()) 1615 return isLeftToRightDirection() ? borderRight() : borderLeft(); 1616 return isLeftToRightDirection() ? borderBottom() : borderTop(); 1617} 1618 1619float RenderStyle::borderBeforeWidth() const 1620{ 1621 switch (writingMode()) { 1622 case TopToBottomWritingMode: 1623 return borderTopWidth(); 1624 case BottomToTopWritingMode: 1625 return borderBottomWidth(); 1626 case LeftToRightWritingMode: 1627 return borderLeftWidth(); 1628 case RightToLeftWritingMode: 1629 return borderRightWidth(); 1630 } 1631 ASSERT_NOT_REACHED(); 1632 return borderTopWidth(); 1633} 1634 1635float RenderStyle::borderAfterWidth() const 1636{ 1637 switch (writingMode()) { 1638 case TopToBottomWritingMode: 1639 return borderBottomWidth(); 1640 case BottomToTopWritingMode: 1641 return borderTopWidth(); 1642 case LeftToRightWritingMode: 1643 return borderRightWidth(); 1644 case RightToLeftWritingMode: 1645 return borderLeftWidth(); 1646 } 1647 ASSERT_NOT_REACHED(); 1648 return borderBottomWidth(); 1649} 1650 1651float RenderStyle::borderStartWidth() const 1652{ 1653 if (isHorizontalWritingMode()) 1654 return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth(); 1655 return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth(); 1656} 1657 1658float RenderStyle::borderEndWidth() const 1659{ 1660 if (isHorizontalWritingMode()) 1661 return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth(); 1662 return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth(); 1663} 1664 1665void RenderStyle::setMarginStart(Length margin) 1666{ 1667 if (isHorizontalWritingMode()) { 1668 if (isLeftToRightDirection()) 1669 setMarginLeft(margin); 1670 else 1671 setMarginRight(margin); 1672 } else { 1673 if (isLeftToRightDirection()) 1674 setMarginTop(margin); 1675 else 1676 setMarginBottom(margin); 1677 } 1678} 1679 1680void RenderStyle::setMarginEnd(Length margin) 1681{ 1682 if (isHorizontalWritingMode()) { 1683 if (isLeftToRightDirection()) 1684 setMarginRight(margin); 1685 else 1686 setMarginLeft(margin); 1687 } else { 1688 if (isLeftToRightDirection()) 1689 setMarginBottom(margin); 1690 else 1691 setMarginTop(margin); 1692 } 1693} 1694 1695TextEmphasisMark RenderStyle::textEmphasisMark() const 1696{ 1697 TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark); 1698 if (mark != TextEmphasisMarkAuto) 1699 return mark; 1700 1701 if (isHorizontalWritingMode()) 1702 return TextEmphasisMarkDot; 1703 1704 return TextEmphasisMarkSesame; 1705} 1706 1707#if ENABLE(TOUCH_EVENTS) 1708Color RenderStyle::initialTapHighlightColor() 1709{ 1710 return RenderTheme::tapHighlightColor(); 1711} 1712#endif 1713 1714LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const 1715{ 1716 return LayoutBoxExtent(NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()), 1717 NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()), 1718 NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth()), 1719 NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth())); 1720} 1721 1722void RenderStyle::getFontAndGlyphOrientation(FontOrientation& fontOrientation, NonCJKGlyphOrientation& glyphOrientation) 1723{ 1724 if (isHorizontalWritingMode()) { 1725 fontOrientation = Horizontal; 1726 glyphOrientation = NonCJKGlyphOrientationVerticalRight; 1727 return; 1728 } 1729 1730 switch (textOrientation()) { 1731 case TextOrientationVerticalRight: 1732 fontOrientation = Vertical; 1733 glyphOrientation = NonCJKGlyphOrientationVerticalRight; 1734 return; 1735 case TextOrientationUpright: 1736 fontOrientation = Vertical; 1737 glyphOrientation = NonCJKGlyphOrientationUpright; 1738 return; 1739 case TextOrientationSideways: 1740 if (writingMode() == LeftToRightWritingMode) { 1741 // FIXME: This should map to sideways-left, which is not supported yet. 1742 fontOrientation = Vertical; 1743 glyphOrientation = NonCJKGlyphOrientationVerticalRight; 1744 return; 1745 } 1746 fontOrientation = Horizontal; 1747 glyphOrientation = NonCJKGlyphOrientationVerticalRight; 1748 return; 1749 case TextOrientationSidewaysRight: 1750 fontOrientation = Horizontal; 1751 glyphOrientation = NonCJKGlyphOrientationVerticalRight; 1752 return; 1753 default: 1754 ASSERT_NOT_REACHED(); 1755 fontOrientation = Horizontal; 1756 glyphOrientation = NonCJKGlyphOrientationVerticalRight; 1757 return; 1758 } 1759} 1760 1761void RenderStyle::setBorderImageSource(PassRefPtr<StyleImage> image) 1762{ 1763 if (surround->border.m_image.image() == image.get()) 1764 return; 1765 surround.access()->border.m_image.setImage(image); 1766} 1767 1768void RenderStyle::setBorderImageSlices(LengthBox slices) 1769{ 1770 if (surround->border.m_image.imageSlices() == slices) 1771 return; 1772 surround.access()->border.m_image.setImageSlices(slices); 1773} 1774 1775void RenderStyle::setBorderImageWidth(LengthBox slices) 1776{ 1777 if (surround->border.m_image.borderSlices() == slices) 1778 return; 1779 surround.access()->border.m_image.setBorderSlices(slices); 1780} 1781 1782void RenderStyle::setBorderImageOutset(LengthBox outset) 1783{ 1784 if (surround->border.m_image.outset() == outset) 1785 return; 1786 surround.access()->border.m_image.setOutset(outset); 1787} 1788 1789void RenderStyle::setColumnStylesFromPaginationMode(const Pagination::Mode& paginationMode) 1790{ 1791 if (paginationMode == Pagination::Unpaginated) 1792 return; 1793 1794 setColumnFill(ColumnFillAuto); 1795 1796 switch (paginationMode) { 1797 case Pagination::LeftToRightPaginated: 1798 setColumnAxis(HorizontalColumnAxis); 1799 if (isHorizontalWritingMode()) 1800 setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression); 1801 else 1802 setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression); 1803 break; 1804 case Pagination::RightToLeftPaginated: 1805 setColumnAxis(HorizontalColumnAxis); 1806 if (isHorizontalWritingMode()) 1807 setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression); 1808 else 1809 setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression); 1810 break; 1811 case Pagination::TopToBottomPaginated: 1812 setColumnAxis(VerticalColumnAxis); 1813 if (isHorizontalWritingMode()) 1814 setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression); 1815 else 1816 setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression); 1817 break; 1818 case Pagination::BottomToTopPaginated: 1819 setColumnAxis(VerticalColumnAxis); 1820 if (isHorizontalWritingMode()) 1821 setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression); 1822 else 1823 setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression); 1824 break; 1825 case Pagination::Unpaginated: 1826 ASSERT_NOT_REACHED(); 1827 break; 1828 } 1829} 1830 1831} // namespace WebCore 1832