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.
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.
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.
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.
24 #include "RenderStyle.h"
26 #include "ContentData.h"
27 #include "CursorList.h"
28 #include "CSSPropertyNames.h"
29 #include "FloatRoundedRect.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"
44 #include <wtf/MathExtras.h>
45 #include <wtf/StdLibExtras.h>
48 #if ENABLE(IOS_TEXT_AUTOSIZING)
49 #include <wtf/text/StringHash.h>
52 #if ENABLE(TEXT_AUTOSIZING)
53 #include "TextAutosizer.h"
58 struct SameSizeAsBorderValue {
64 COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow);
66 struct SameSizeAsRenderStyle : public RefCounted<SameSizeAsRenderStyle> {
69 void* dataRefSvgStyle;
70 struct InheritedFlags {
71 unsigned m_bitfields[2];
74 struct NonInheritedFlags {
79 COMPILE_ASSERT(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small);
81 inline RenderStyle& defaultStyle()
83 static RenderStyle& style = RenderStyle::createDefaultStyle().leakRef();
87 PassRef<RenderStyle> RenderStyle::create()
89 return adoptRef(*new RenderStyle(defaultStyle()));
92 PassRef<RenderStyle> RenderStyle::createDefaultStyle()
94 return adoptRef(*new RenderStyle(true));
97 PassRef<RenderStyle> RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay display)
99 auto newStyle = RenderStyle::create();
100 newStyle.get().inheritFrom(parentStyle);
101 newStyle.get().inheritUnicodeBidiFrom(parentStyle);
102 newStyle.get().setDisplay(display);
106 PassRef<RenderStyle> RenderStyle::clone(const RenderStyle* other)
108 return adoptRef(*new RenderStyle(*other));
111 PassRef<RenderStyle> RenderStyle::createStyleInheritingFromPseudoStyle(const RenderStyle& pseudoStyle)
113 ASSERT(pseudoStyle.styleType() == BEFORE || pseudoStyle.styleType() == AFTER);
115 auto style = RenderStyle::create();
116 style.get().inheritFrom(&pseudoStyle);
120 ALWAYS_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())
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();
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();
152 static_assert((sizeof(InheritedFlags) <= 8), "InheritedFlags does not grow");
153 static_assert((sizeof(NonInheritedFlags) <= 8), "NonInheritedFlags does not grow");
156 ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o)
157 : RefCounted<RenderStyle>()
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)
171 void RenderStyle::inheritFrom(const RenderStyle* inheritParent, IsAtShadowBoundary isAtShadowBoundary)
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);
179 rareInheritedData = inheritParent->rareInheritedData;
180 inherited = inheritParent->inherited;
181 inherited_flags = inheritParent->inherited_flags;
183 if (m_svgStyle != inheritParent->m_svgStyle)
184 m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
187 void RenderStyle::copyNonInheritedFrom(const RenderStyle* other)
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);
196 if (m_svgStyle != other->m_svgStyle)
197 m_svgStyle.access()->copyNonInheritedFrom(other->m_svgStyle.get());
199 ASSERT(zoom() == initialZoom());
202 bool RenderStyle::operator==(const RenderStyle& o) const
204 // compare everything except the pseudoStyle pointer
205 return inherited_flags == o.inherited_flags
206 && noninherited_flags == o.noninherited_flags
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
218 bool RenderStyle::isStyleAvailable() const
220 return this != StyleResolver::styleNotYetAvailable();
223 bool RenderStyle::hasUniquePseudoStyle() const
225 if (!m_cachedPseudoStyles || styleType() != NOPSEUDO)
228 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
229 RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
230 if (pseudoStyle->unique())
237 RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
239 if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
242 if (styleType() != NOPSEUDO)
245 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
246 RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
247 if (pseudoStyle->styleType() == pid)
254 RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
259 ASSERT(pseudo->styleType() > NOPSEUDO);
261 RenderStyle* result = pseudo.get();
263 if (!m_cachedPseudoStyles)
264 m_cachedPseudoStyles = std::make_unique<PseudoStyleCache>();
266 m_cachedPseudoStyles->append(pseudo);
271 void RenderStyle::removeCachedPseudoStyle(PseudoId pid)
273 if (!m_cachedPseudoStyles)
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);
284 bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
286 return inherited_flags != other->inherited_flags
287 || inherited != other->inherited
288 || m_svgStyle->inheritedNotEqual(other->m_svgStyle.get())
289 || rareInheritedData != other->rareInheritedData;
292 #if ENABLE(IOS_TEXT_AUTOSIZING)
293 inline unsigned computeFontHash(const Font& font)
295 unsigned hashCodes[2] = {
296 CaseFoldingHash::hash(font.fontDescription().firstFamily().impl()),
297 static_cast<unsigned>(font.fontDescription().specifiedSize())
299 return StringHasher::computeHash(reinterpret_cast<UChar*>(hashCodes), 2 * sizeof(unsigned) / sizeof(UChar));
302 uint32_t RenderStyle::hashForTextAutosizing() const
304 // FIXME: Not a very smart hash. Could be improved upon. See <https://bugs.webkit.org/show_bug.cgi?id=121131>.
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;
327 bool RenderStyle::equalForTextAutosizing(const RenderStyle* other) const
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;
348 #endif // ENABLE(IOS_TEXT_AUTOSIZING)
350 bool RenderStyle::inheritedDataShared(const RenderStyle* other) const
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();
359 static bool positionChangeIsMovementOnly(const LengthBox& a, const LengthBox& b, const Length& width)
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())
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())
374 if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
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())
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.
386 inline bool RenderStyle::changeAffectsVisualOverflow(const RenderStyle& other) const
388 if (rareNonInheritedData.get() != other.rareNonInheritedData.get()
389 && !rareNonInheritedData->shadowDataEquivalent(*other.rareNonInheritedData.get()))
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)
400 return visualOverflowForDecorations(*this, nullptr) != visualOverflowForDecorations(other, nullptr);
406 bool RenderStyle::changeRequiresLayout(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
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())
416 if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags.verticalAlign() != other->noninherited_flags.verticalAlign())
419 if (m_box->boxSizing() != other->m_box->boxSizing())
422 if (surround->margin != other->surround->margin)
425 if (surround->padding != other->surround->padding)
428 // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
429 if (changeAffectsVisualOverflow(*other))
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)
440 if (rareNonInheritedData->m_regionFragment != other->rareNonInheritedData->m_regionFragment)
443 #if ENABLE(CSS_SHAPES)
444 if (rareNonInheritedData->m_shapeMargin != other->rareNonInheritedData->m_shapeMargin)
448 if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get()
449 && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other->rareNonInheritedData->m_deprecatedFlexibleBox.get())
452 if (rareNonInheritedData->m_flexibleBox.get() != other->rareNonInheritedData->m_flexibleBox.get()
453 && *rareNonInheritedData->m_flexibleBox.get() != *other->rareNonInheritedData->m_flexibleBox.get())
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)
462 if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
465 if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get()
466 && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
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
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())
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)
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
494 || rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom
495 #if ENABLE(IOS_TEXT_AUTOSIZING)
496 || rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust
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
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
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
529 || rareInheritedData->listStyleImage != other->rareInheritedData->listStyleImage)
532 if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
535 if (textStrokeWidth() != other->textStrokeWidth())
539 #if ENABLE(TEXT_AUTOSIZING)
540 if (visual->m_textAutosizingMultiplier != other->visual->m_textAutosizingMultiplier)
544 if (inherited->line_height != other->inherited->line_height
545 #if ENABLE(IOS_TEXT_AUTOSIZING)
546 || inherited->specifiedLineHeight != other->inherited->specifiedLineHeight
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())
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())
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)))
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)
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())
594 // Check block flow direction.
595 if (inherited_flags.m_writingMode != other->inherited_flags.m_writingMode)
598 // Check text combine mode.
599 if (rareNonInheritedData->m_textCombine != other->rareNonInheritedData->m_textCombine)
602 // Overflow returns a layout hint.
603 if (noninherited_flags.overflowX() != other->noninherited_flags.overflowX()
604 || noninherited_flags.overflowY() != other->noninherited_flags.overflowY())
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())
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)))
621 if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
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.
633 #if ENABLE(CSS_FILTERS)
634 if (rareNonInheritedData->hasFilters() != other->rareNonInheritedData->hasFilters())
638 const QuotesData* quotesDataA = rareInheritedData->quotes.get();
639 const QuotesData* quotesDataB = other->rareInheritedData->quotes.get();
640 if (!(quotesDataA == quotesDataB || (quotesDataA && quotesDataB && *quotesDataA == *quotesDataB)))
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)
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()))
660 bool RenderStyle::changeRequiresPositionedLayoutOnly(const RenderStyle* other, unsigned&) const
662 if (position() == StaticPosition)
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()))
674 bool RenderStyle::changeRequiresLayerRepaint(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
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())
680 if (position() != StaticPosition) {
681 if (visual->clip != other->visual->clip
682 || visual->hasClip != other->visual->hasClip)
686 #if ENABLE(CSS_COMPOSITING)
687 if (rareNonInheritedData->m_effectiveBlendMode != other->rareNonInheritedData->m_effectiveBlendMode)
691 if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
692 changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
693 // Don't return; keep looking for another change.
696 #if ENABLE(CSS_FILTERS)
697 if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get()
698 && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) {
699 changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
700 // Don't return; keep looking for another change.
704 if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
705 || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
711 bool RenderStyle::changeRequiresRepaint(const RenderStyle* other, unsigned&) const
713 if (inherited_flags._visibility != other->inherited_flags._visibility
714 || inherited_flags.m_printColorAdjust != other->inherited_flags.m_printColorAdjust
715 || inherited_flags._insideLink != other->inherited_flags._insideLink
716 || surround->border != other->surround->border
717 || !m_background->isEquivalentForPainting(*other->m_background)
718 || rareInheritedData->userModify != other->rareInheritedData->userModify
719 || rareInheritedData->userSelect != other->rareInheritedData->userSelect
720 || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
721 || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
722 || rareNonInheritedData->m_objectFit != other->rareNonInheritedData->m_objectFit
723 || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
726 #if ENABLE(CSS_SHAPES)
727 if (rareNonInheritedData->m_shapeOutside != other->rareNonInheritedData->m_shapeOutside)
731 if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath)
737 bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle* other, unsigned&) const
739 if (inherited->color != other->inherited->color
740 || inherited_flags._text_decorations != other->inherited_flags._text_decorations
741 || visual->textDecoration != other->visual->textDecoration
742 || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle
743 || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor
744 || rareInheritedData->m_textDecorationSkip != other->rareInheritedData->m_textDecorationSkip
745 || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
746 || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
747 || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
748 || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill)
754 bool RenderStyle::changeRequiresRecompositeLayer(const RenderStyle* other, unsigned&) const
756 if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
757 if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
758 || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
759 || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
760 || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
761 || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
768 StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
770 changedContextSensitiveProperties = ContextSensitivePropertyNone;
772 StyleDifference svgChange = StyleDifferenceEqual;
773 if (m_svgStyle != other->m_svgStyle) {
774 svgChange = m_svgStyle->diff(other->m_svgStyle.get());
775 if (svgChange == StyleDifferenceLayout)
779 if (changeRequiresLayout(other, changedContextSensitiveProperties))
780 return StyleDifferenceLayout;
782 // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
783 // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
784 // but have to return StyleDifferenceLayout, that's why this if branch comes after all branches
785 // that are relevant for SVG and might return StyleDifferenceLayout.
786 if (svgChange != StyleDifferenceEqual)
789 if (changeRequiresPositionedLayoutOnly(other, changedContextSensitiveProperties))
790 return StyleDifferenceLayoutPositionedMovementOnly;
792 if (changeRequiresLayerRepaint(other, changedContextSensitiveProperties))
793 return StyleDifferenceRepaintLayer;
795 if (changeRequiresRepaint(other, changedContextSensitiveProperties))
796 return StyleDifferenceRepaint;
798 if (changeRequiresRecompositeLayer(other, changedContextSensitiveProperties))
799 return StyleDifferenceRecompositeLayer;
801 if (changeRequiresRepaintIfTextOrBorderOrOutline(other, changedContextSensitiveProperties))
802 return StyleDifferenceRepaintIfTextOrBorderOrOutline;
804 // Cursors are not checked, since they will be set appropriately in response to mouse events,
805 // so they don't need to cause any repaint or layout.
807 // 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
808 // the resulting transition properly.
809 return StyleDifferenceEqual;
812 bool RenderStyle::diffRequiresRepaint(const RenderStyle* style) const
814 unsigned changedContextSensitiveProperties = 0;
815 return changeRequiresRepaint(style, changedContextSensitiveProperties);
818 void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
820 StyleVisualData* data = visual.access();
821 data->clip.m_top = top;
822 data->clip.m_right = right;
823 data->clip.m_bottom = bottom;
824 data->clip.m_left = left;
827 void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
829 if (!rareInheritedData.access()->cursorData)
830 rareInheritedData.access()->cursorData = CursorList::create();
831 rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
834 void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
836 rareInheritedData.access()->cursorData = other;
839 void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
841 if (rareInheritedData->quotes == q || (rareInheritedData->quotes && q && *rareInheritedData->quotes == *q))
844 rareInheritedData.access()->quotes = q;
847 void RenderStyle::clearCursorList()
849 if (rareInheritedData->cursorData)
850 rareInheritedData.access()->cursorData = 0;
853 void RenderStyle::clearContent()
855 if (rareNonInheritedData->m_content)
856 rareNonInheritedData.access()->m_content = nullptr;
859 void RenderStyle::appendContent(std::unique_ptr<ContentData> contentData)
861 auto& content = rareNonInheritedData.access()->m_content;
862 ContentData* lastContent = content.get();
863 while (lastContent && lastContent->next())
864 lastContent = lastContent->next();
867 lastContent->setNext(std::move(contentData));
869 content = std::move(contentData);
872 void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
878 appendContent(std::make_unique<ImageContentData>(image));
882 rareNonInheritedData.access()->m_content = std::make_unique<ImageContentData>(image);
883 if (!rareNonInheritedData.access()->m_altText.isNull())
884 rareNonInheritedData.access()->m_content->setAltText(rareNonInheritedData.access()->m_altText);
887 void RenderStyle::setContent(const String& string, bool add)
889 auto& content = rareNonInheritedData.access()->m_content;
891 ContentData* lastContent = content.get();
892 while (lastContent && lastContent->next())
893 lastContent = lastContent->next();
896 // We attempt to merge with the last ContentData if possible.
897 if (lastContent->isText()) {
898 TextContentData* textContent = toTextContentData(lastContent);
899 textContent->setText(textContent->text() + string);
901 lastContent->setNext(std::make_unique<TextContentData>(string));
903 if (!rareNonInheritedData.access()->m_altText.isNull())
904 lastContent->setAltText(rareNonInheritedData.access()->m_altText);
909 content = std::make_unique<TextContentData>(string);
910 if (!rareNonInheritedData.access()->m_altText.isNull())
911 content->setAltText(rareNonInheritedData.access()->m_altText);
914 void RenderStyle::setContent(std::unique_ptr<CounterContent> counter, bool add)
920 appendContent(std::make_unique<CounterContentData>(std::move(counter)));
924 rareNonInheritedData.access()->m_content = std::make_unique<CounterContentData>(std::move(counter));
927 void RenderStyle::setContent(QuoteType quote, bool add)
930 appendContent(std::make_unique<QuoteContentData>(quote));
934 rareNonInheritedData.access()->m_content = std::make_unique<QuoteContentData>(quote);
937 void RenderStyle::setContentAltText(const String& string)
939 rareNonInheritedData.access()->m_altText = string;
941 if (rareNonInheritedData.access()->m_content)
942 rareNonInheritedData.access()->m_content->setAltText(string);
945 const String& RenderStyle::contentAltText() const
947 return rareNonInheritedData->m_altText;
950 static inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation>>& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
952 // transform-origin brackets the transform with translate operations.
953 // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
955 if (applyOrigin != RenderStyle::IncludeTransformOrigin)
958 for (auto& operation : transformOperations) {
959 TransformOperation::OperationType type = operation->type();
960 if (type != TransformOperation::TRANSLATE_X
961 && type != TransformOperation::TRANSLATE_Y
962 && type != TransformOperation::TRANSLATE
963 && type != TransformOperation::TRANSLATE_Z
964 && type != TransformOperation::TRANSLATE_3D)
971 void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const
973 auto& operations = rareNonInheritedData->m_transform->m_operations.operations();
974 bool applyTransformOrigin = requireTransformOrigin(operations, applyOrigin);
976 float offsetX = transformOriginX().isPercentNotCalculated() ? boundingBox.x() : 0;
977 float offsetY = transformOriginY().isPercentNotCalculated() ? boundingBox.y() : 0;
979 if (applyTransformOrigin) {
980 transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX,
981 floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY,
985 for (auto& operation : operations)
986 operation->apply(transform, boundingBox.size());
988 if (applyTransformOrigin) {
989 transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX,
990 -floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY,
991 -transformOriginZ());
995 void RenderStyle::setPageScaleTransform(float scale)
999 TransformOperations transform;
1000 transform.operations().append(ScaleTransformOperation::create(scale, scale, ScaleTransformOperation::SCALE));
1001 setTransform(transform);
1002 setTransformOriginX(Length(0, Fixed));
1003 setTransformOriginY(Length(0, Fixed));
1006 void RenderStyle::setTextShadow(std::unique_ptr<ShadowData> shadowData, bool add)
1008 ASSERT(!shadowData || (!shadowData->spread() && shadowData->style() == Normal));
1010 StyleRareInheritedData* rareData = rareInheritedData.access();
1012 rareData->textShadow = std::move(shadowData);
1016 shadowData->setNext(std::move(rareData->textShadow));
1017 rareData->textShadow = std::move(shadowData);
1020 void RenderStyle::setBoxShadow(std::unique_ptr<ShadowData> shadowData, bool add)
1022 StyleRareNonInheritedData* rareData = rareNonInheritedData.access();
1024 rareData->m_boxShadow = std::move(shadowData);
1028 shadowData->setNext(std::move(rareData->m_boxShadow));
1029 rareData->m_boxShadow = std::move(shadowData);
1032 static RoundedRect::Radii calcRadiiFor(const BorderData& border, const LayoutSize& size)
1034 return RoundedRect::Radii(
1035 LayoutSize(valueForLength(border.topLeft().width(), size.width()),
1036 valueForLength(border.topLeft().height(), size.height())),
1037 LayoutSize(valueForLength(border.topRight().width(), size.width()),
1038 valueForLength(border.topRight().height(), size.height())),
1039 LayoutSize(valueForLength(border.bottomLeft().width(), size.width()),
1040 valueForLength(border.bottomLeft().height(), size.height())),
1041 LayoutSize(valueForLength(border.bottomRight().width(), size.width()),
1042 valueForLength(border.bottomRight().height(), size.height())));
1045 StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); }
1046 void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v)
1048 if (rareInheritedData->listStyleImage != v)
1049 rareInheritedData.access()->listStyleImage = v;
1052 Color RenderStyle::color() const { return inherited->color; }
1053 Color RenderStyle::visitedLinkColor() const { return inherited->visitedLinkColor; }
1054 void RenderStyle::setColor(const Color& v) { SET_VAR(inherited, color, v); }
1055 void RenderStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visitedLinkColor, v); }
1057 short RenderStyle::horizontalBorderSpacing() const { return inherited->horizontal_border_spacing; }
1058 short RenderStyle::verticalBorderSpacing() const { return inherited->vertical_border_spacing; }
1059 void RenderStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v); }
1060 void RenderStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertical_border_spacing, v); }
1062 RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1064 RoundedRect roundedRect(borderRect);
1065 if (hasBorderRadius()) {
1066 RoundedRect::Radii radii = calcRadiiFor(surround->border, borderRect.size());
1067 radii.scale(calcBorderRadiiConstraintScaleFor(borderRect, radii));
1068 roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1073 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1075 bool horizontal = isHorizontalWritingMode();
1077 LayoutUnit leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
1078 LayoutUnit rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
1079 LayoutUnit topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
1080 LayoutUnit bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;
1082 return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
1085 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, LayoutUnit topWidth, LayoutUnit bottomWidth,
1086 LayoutUnit leftWidth, LayoutUnit rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1088 LayoutRect innerRect(borderRect.x() + leftWidth,
1089 borderRect.y() + topWidth,
1090 borderRect.width() - leftWidth - rightWidth,
1091 borderRect.height() - topWidth - bottomWidth);
1093 RoundedRect roundedRect(innerRect);
1095 if (hasBorderRadius()) {
1096 RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii();
1097 radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
1098 roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1103 static bool allLayersAreFixed(const FillLayer* layer)
1105 bool allFixed = true;
1107 for (const FillLayer* currLayer = layer; currLayer; currLayer = currLayer->next())
1108 allFixed &= (currLayer->image() && currLayer->attachment() == FixedBackgroundAttachment);
1110 return layer && allFixed;
1113 bool RenderStyle::hasEntirelyFixedBackground() const
1115 return allLayersAreFixed(backgroundLayers());
1118 const CounterDirectiveMap* RenderStyle::counterDirectives() const
1120 return rareNonInheritedData->m_counterDirectives.get();
1123 CounterDirectiveMap& RenderStyle::accessCounterDirectives()
1125 auto& map = rareNonInheritedData.access()->m_counterDirectives;
1127 map = std::make_unique<CounterDirectiveMap>();
1131 const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const
1133 if (const CounterDirectiveMap* directives = counterDirectives())
1134 return directives->get(identifier);
1135 return CounterDirectives();
1138 const AtomicString& RenderStyle::hyphenString() const
1140 ASSERT(hyphens() != HyphensNone);
1142 const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString;
1143 if (!hyphenationString.isNull())
1144 return hyphenationString;
1146 // FIXME: This should depend on locale.
1147 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinus, 1));
1148 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphen, 1));
1149 return font().primaryFontHasGlyphForCharacter(hyphen) ? hyphenString : hyphenMinusString;
1152 const AtomicString& RenderStyle::textEmphasisMarkString() const
1154 switch (textEmphasisMark()) {
1155 case TextEmphasisMarkNone:
1157 case TextEmphasisMarkCustom:
1158 return textEmphasisCustomMark();
1159 case TextEmphasisMarkDot: {
1160 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1));
1161 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1));
1162 return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
1164 case TextEmphasisMarkCircle: {
1165 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1));
1166 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1));
1167 return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString;
1169 case TextEmphasisMarkDoubleCircle: {
1170 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1));
1171 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1));
1172 return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString;
1174 case TextEmphasisMarkTriangle: {
1175 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointingTriangle, 1));
1176 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingTriangle, 1));
1177 return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString;
1179 case TextEmphasisMarkSesame: {
1180 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1));
1181 DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1));
1182 return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString;
1184 case TextEmphasisMarkAuto:
1185 ASSERT_NOT_REACHED();
1189 ASSERT_NOT_REACHED();
1193 #if ENABLE(DASHBOARD_SUPPORT)
1194 const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
1196 DEPRECATED_DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ());
1200 const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
1202 DEPRECATED_DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, noneList, ());
1203 static bool noneListInitialized = false;
1205 if (!noneListInitialized) {
1206 StyleDashboardRegion region;
1208 region.offset.m_top = Length();
1209 region.offset.m_right = Length();
1210 region.offset.m_bottom = Length();
1211 region.offset.m_left = Length();
1212 region.type = StyleDashboardRegion::None;
1213 noneList.append(region);
1214 noneListInitialized = true;
1220 void RenderStyle::adjustAnimations()
1222 AnimationList* animationList = rareNonInheritedData->m_animations.get();
1226 // Get rid of empty animations and anything beyond them
1227 for (size_t i = 0; i < animationList->size(); ++i) {
1228 if (animationList->animation(i).isEmpty()) {
1229 animationList->resize(i);
1234 if (animationList->isEmpty()) {
1239 // Repeat patterns into layers that don't have some properties set.
1240 animationList->fillUnsetProperties();
1243 void RenderStyle::adjustTransitions()
1245 AnimationList* transitionList = rareNonInheritedData->m_transitions.get();
1246 if (!transitionList)
1249 // Get rid of empty transitions and anything beyond them
1250 for (size_t i = 0; i < transitionList->size(); ++i) {
1251 if (transitionList->animation(i).isEmpty()) {
1252 transitionList->resize(i);
1257 if (transitionList->isEmpty()) {
1262 // Repeat patterns into layers that don't have some properties set.
1263 transitionList->fillUnsetProperties();
1265 // Make sure there are no duplicate properties. This is an O(n^2) algorithm
1266 // but the lists tend to be very short, so it is probably ok
1267 for (size_t i = 0; i < transitionList->size(); ++i) {
1268 for (size_t j = i+1; j < transitionList->size(); ++j) {
1269 if (transitionList->animation(i).property() == transitionList->animation(j).property()) {
1271 transitionList->remove(i);
1278 AnimationList* RenderStyle::accessAnimations()
1280 if (!rareNonInheritedData.access()->m_animations)
1281 rareNonInheritedData.access()->m_animations = std::make_unique<AnimationList>();
1282 return rareNonInheritedData->m_animations.get();
1285 AnimationList* RenderStyle::accessTransitions()
1287 if (!rareNonInheritedData.access()->m_transitions)
1288 rareNonInheritedData.access()->m_transitions = std::make_unique<AnimationList>();
1289 return rareNonInheritedData->m_transitions.get();
1292 const Animation* RenderStyle::transitionForProperty(CSSPropertyID property) const
1294 if (transitions()) {
1295 for (size_t i = 0; i < transitions()->size(); ++i) {
1296 const Animation& p = transitions()->animation(i);
1297 if (p.animationMode() == Animation::AnimateAll || p.property() == property) {
1305 const Font& RenderStyle::font() const { return inherited->font; }
1306 const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); }
1307 const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); }
1308 float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); }
1309 float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
1310 int RenderStyle::fontSize() const { return inherited->font.pixelSize(); }
1312 const Length& RenderStyle::wordSpacing() const { return rareInheritedData->wordSpacing; }
1313 float RenderStyle::letterSpacing() const { return inherited->font.letterSpacing(); }
1315 bool RenderStyle::setFontDescription(const FontDescription& v)
1317 if (inherited->font.fontDescription() != v) {
1318 inherited.access()->font = Font(v, inherited->font.letterSpacing(), inherited->font.wordSpacing());
1324 #if ENABLE(IOS_TEXT_AUTOSIZING)
1325 const Length& RenderStyle::specifiedLineHeight() const { return inherited->specifiedLineHeight; }
1326 void RenderStyle::setSpecifiedLineHeight(Length v) { SET_VAR(inherited, specifiedLineHeight, v); }
1328 const Length& RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
1331 Length RenderStyle::lineHeight() const
1333 const Length& lh = inherited->line_height;
1334 #if ENABLE(TEXT_AUTOSIZING)
1335 // Unlike fontDescription().computedSize() and hence fontSize(), this is
1336 // recalculated on demand as we only store the specified line height.
1337 // FIXME: Should consider scaling the fixed part of any calc expressions
1338 // too, though this involves messily poking into CalcExpressionLength.
1339 float multiplier = textAutosizingMultiplier();
1340 if (multiplier > 1 && lh.isFixed())
1341 return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multiplier), Fixed);
1345 void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
1347 int RenderStyle::computedLineHeight() const
1349 const Length& lh = lineHeight();
1351 // Negative value means the line height is not set. Use the font's built-in spacing.
1352 if (lh.isNegative())
1353 return fontMetrics().lineSpacing();
1356 return minimumValueForLength(lh, fontSize());
1361 void RenderStyle::setWordSpacing(Length value)
1363 float fontWordSpacing;
1364 switch (value.type()) {
1366 fontWordSpacing = 0;
1369 fontWordSpacing = value.percent() * font().spaceWidth() / 100;
1372 fontWordSpacing = value.value();
1375 ASSERT_NOT_REACHED();
1376 fontWordSpacing = 0;
1379 inherited.access()->font.setWordSpacing(fontWordSpacing);
1380 rareInheritedData.access()->wordSpacing = std::move(value);
1383 void RenderStyle::setLetterSpacing(float v) { inherited.access()->font.setLetterSpacing(v); }
1385 void RenderStyle::setFontSize(float size)
1387 // size must be specifiedSize if Text Autosizing is enabled, but computedSize if text
1388 // zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
1390 ASSERT(std::isfinite(size));
1391 if (!std::isfinite(size) || size < 0)
1394 size = std::min(maximumAllowedFontSize, size);
1396 FontSelector* currentFontSelector = font().fontSelector();
1397 FontDescription desc(fontDescription());
1398 desc.setSpecifiedSize(size);
1399 desc.setComputedSize(size);
1401 #if ENABLE(TEXT_AUTOSIZING)
1402 float multiplier = textAutosizingMultiplier();
1403 if (multiplier > 1) {
1404 float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size, multiplier);
1405 desc.setComputedSize(min(maximumAllowedFontSize, autosizedFontSize));
1409 setFontDescription(desc);
1410 font().update(currentFontSelector);
1413 void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
1420 for ( ; shadow; shadow = shadow->next()) {
1421 if (shadow->style() == Inset)
1424 int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1425 top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread);
1426 right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread);
1427 bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
1428 left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread);
1432 LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowData* shadow) const
1435 LayoutUnit right = 0;
1436 LayoutUnit bottom = 0;
1437 LayoutUnit left = 0;
1439 for ( ; shadow; shadow = shadow->next()) {
1440 if (shadow->style() == Normal)
1443 int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1444 top = std::max<LayoutUnit>(top, shadow->y() + extentAndSpread);
1445 right = std::min<LayoutUnit>(right, shadow->x() - extentAndSpread);
1446 bottom = std::min<LayoutUnit>(bottom, shadow->y() - extentAndSpread);
1447 left = std::max<LayoutUnit>(left, shadow->x() + extentAndSpread);
1450 return LayoutBoxExtent(top, right, bottom, left);
1453 void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit &left, LayoutUnit &right) const
1458 for ( ; shadow; shadow = shadow->next()) {
1459 if (shadow->style() == Inset)
1462 int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1463 left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread);
1464 right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread);
1468 void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &bottom) const
1473 for ( ; shadow; shadow = shadow->next()) {
1474 if (shadow->style() == Inset)
1477 int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1478 top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread);
1479 bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
1483 Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
1486 EBorderStyle borderStyle = BNONE;
1487 switch (colorProperty) {
1488 case CSSPropertyBackgroundColor:
1489 return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back.
1490 case CSSPropertyBorderLeftColor:
1491 result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
1492 borderStyle = borderLeftStyle();
1494 case CSSPropertyBorderRightColor:
1495 result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
1496 borderStyle = borderRightStyle();
1498 case CSSPropertyBorderTopColor:
1499 result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
1500 borderStyle = borderTopStyle();
1502 case CSSPropertyBorderBottomColor:
1503 result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
1504 borderStyle = borderBottomStyle();
1506 case CSSPropertyColor:
1507 result = visitedLink ? visitedLinkColor() : color();
1509 case CSSPropertyOutlineColor:
1510 result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
1512 case CSSPropertyWebkitColumnRuleColor:
1513 result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
1515 case CSSPropertyWebkitTextDecorationColor:
1516 // Text decoration color fallback is handled in RenderObject::decorationColor.
1517 return visitedLink ? visitedLinkTextDecorationColor() : textDecorationColor();
1518 case CSSPropertyWebkitTextEmphasisColor:
1519 result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
1521 case CSSPropertyWebkitTextFillColor:
1522 result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
1524 case CSSPropertyWebkitTextStrokeColor:
1525 result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
1528 ASSERT_NOT_REACHED();
1532 if (!result.isValid()) {
1533 if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
1534 result.setRGB(238, 238, 238);
1536 result = visitedLink ? visitedLinkColor() : color();
1541 Color RenderStyle::visitedDependentColor(int colorProperty) const
1543 Color unvisitedColor = colorIncludingFallback(colorProperty, false);
1544 if (insideLink() != InsideVisitedLink)
1545 return unvisitedColor;
1547 Color visitedColor = colorIncludingFallback(colorProperty, true);
1549 // Text decoration color validity is preserved (checked in RenderObject::decorationColor).
1550 if (colorProperty == CSSPropertyWebkitTextDecorationColor)
1551 return visitedColor;
1553 // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
1554 // assume that if the background color is transparent that it wasn't set. Note that it's weird that
1555 // we're returning unvisited info for a visited link, but given our restriction that the alpha values
1556 // have to match, it makes more sense to return the unvisited background color if specified than it
1557 // does to return black. This behavior matches what Firefox 4 does as well.
1558 if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent)
1559 return unvisitedColor;
1561 // Take the alpha from the unvisited color, but get the RGB values from the visited color.
1562 return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
1565 const BorderValue& RenderStyle::borderBefore() const
1567 switch (writingMode()) {
1568 case TopToBottomWritingMode:
1570 case BottomToTopWritingMode:
1571 return borderBottom();
1572 case LeftToRightWritingMode:
1573 return borderLeft();
1574 case RightToLeftWritingMode:
1575 return borderRight();
1577 ASSERT_NOT_REACHED();
1581 const BorderValue& RenderStyle::borderAfter() const
1583 switch (writingMode()) {
1584 case TopToBottomWritingMode:
1585 return borderBottom();
1586 case BottomToTopWritingMode:
1588 case LeftToRightWritingMode:
1589 return borderRight();
1590 case RightToLeftWritingMode:
1591 return borderLeft();
1593 ASSERT_NOT_REACHED();
1594 return borderBottom();
1597 const BorderValue& RenderStyle::borderStart() const
1599 if (isHorizontalWritingMode())
1600 return isLeftToRightDirection() ? borderLeft() : borderRight();
1601 return isLeftToRightDirection() ? borderTop() : borderBottom();
1604 const BorderValue& RenderStyle::borderEnd() const
1606 if (isHorizontalWritingMode())
1607 return isLeftToRightDirection() ? borderRight() : borderLeft();
1608 return isLeftToRightDirection() ? borderBottom() : borderTop();
1611 float RenderStyle::borderBeforeWidth() const
1613 switch (writingMode()) {
1614 case TopToBottomWritingMode:
1615 return borderTopWidth();
1616 case BottomToTopWritingMode:
1617 return borderBottomWidth();
1618 case LeftToRightWritingMode:
1619 return borderLeftWidth();
1620 case RightToLeftWritingMode:
1621 return borderRightWidth();
1623 ASSERT_NOT_REACHED();
1624 return borderTopWidth();
1627 float RenderStyle::borderAfterWidth() const
1629 switch (writingMode()) {
1630 case TopToBottomWritingMode:
1631 return borderBottomWidth();
1632 case BottomToTopWritingMode:
1633 return borderTopWidth();
1634 case LeftToRightWritingMode:
1635 return borderRightWidth();
1636 case RightToLeftWritingMode:
1637 return borderLeftWidth();
1639 ASSERT_NOT_REACHED();
1640 return borderBottomWidth();
1643 float RenderStyle::borderStartWidth() const
1645 if (isHorizontalWritingMode())
1646 return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
1647 return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
1650 float RenderStyle::borderEndWidth() const
1652 if (isHorizontalWritingMode())
1653 return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
1654 return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
1657 void RenderStyle::setMarginStart(Length margin)
1659 if (isHorizontalWritingMode()) {
1660 if (isLeftToRightDirection())
1661 setMarginLeft(margin);
1663 setMarginRight(margin);
1665 if (isLeftToRightDirection())
1666 setMarginTop(margin);
1668 setMarginBottom(margin);
1672 void RenderStyle::setMarginEnd(Length margin)
1674 if (isHorizontalWritingMode()) {
1675 if (isLeftToRightDirection())
1676 setMarginRight(margin);
1678 setMarginLeft(margin);
1680 if (isLeftToRightDirection())
1681 setMarginBottom(margin);
1683 setMarginTop(margin);
1687 TextEmphasisMark RenderStyle::textEmphasisMark() const
1689 TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark);
1690 if (mark != TextEmphasisMarkAuto)
1693 if (isHorizontalWritingMode())
1694 return TextEmphasisMarkDot;
1696 return TextEmphasisMarkSesame;
1699 #if ENABLE(TOUCH_EVENTS)
1700 Color RenderStyle::initialTapHighlightColor()
1702 return RenderTheme::tapHighlightColor();
1706 LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
1708 return LayoutBoxExtent(NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()),
1709 NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()),
1710 NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth()),
1711 NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()));
1714 void RenderStyle::getFontAndGlyphOrientation(FontOrientation& fontOrientation, NonCJKGlyphOrientation& glyphOrientation)
1716 if (isHorizontalWritingMode()) {
1717 fontOrientation = Horizontal;
1718 glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1722 switch (textOrientation()) {
1723 case TextOrientationVerticalRight:
1724 fontOrientation = Vertical;
1725 glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1727 case TextOrientationUpright:
1728 fontOrientation = Vertical;
1729 glyphOrientation = NonCJKGlyphOrientationUpright;
1731 case TextOrientationSideways:
1732 if (writingMode() == LeftToRightWritingMode) {
1733 // FIXME: This should map to sideways-left, which is not supported yet.
1734 fontOrientation = Vertical;
1735 glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1738 fontOrientation = Horizontal;
1739 glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1741 case TextOrientationSidewaysRight:
1742 fontOrientation = Horizontal;
1743 glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1746 ASSERT_NOT_REACHED();
1747 fontOrientation = Horizontal;
1748 glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1753 void RenderStyle::setBorderImageSource(PassRefPtr<StyleImage> image)
1755 if (surround->border.m_image.image() == image.get())
1757 surround.access()->border.m_image.setImage(image);
1760 void RenderStyle::setBorderImageSlices(LengthBox slices)
1762 if (surround->border.m_image.imageSlices() == slices)
1764 surround.access()->border.m_image.setImageSlices(slices);
1767 void RenderStyle::setBorderImageWidth(LengthBox slices)
1769 if (surround->border.m_image.borderSlices() == slices)
1771 surround.access()->border.m_image.setBorderSlices(slices);
1774 void RenderStyle::setBorderImageOutset(LengthBox outset)
1776 if (surround->border.m_image.outset() == outset)
1778 surround.access()->border.m_image.setOutset(outset);
1781 void RenderStyle::setColumnStylesFromPaginationMode(const Pagination::Mode& paginationMode)
1783 if (paginationMode == Pagination::Unpaginated)
1786 setColumnFill(ColumnFillAuto);
1788 switch (paginationMode) {
1789 case Pagination::LeftToRightPaginated:
1790 setColumnAxis(HorizontalColumnAxis);
1791 if (isHorizontalWritingMode())
1792 setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1794 setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1796 case Pagination::RightToLeftPaginated:
1797 setColumnAxis(HorizontalColumnAxis);
1798 if (isHorizontalWritingMode())
1799 setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1801 setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1803 case Pagination::TopToBottomPaginated:
1804 setColumnAxis(VerticalColumnAxis);
1805 if (isHorizontalWritingMode())
1806 setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1808 setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1810 case Pagination::BottomToTopPaginated:
1811 setColumnAxis(VerticalColumnAxis);
1812 if (isHorizontalWritingMode())
1813 setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1815 setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1817 case Pagination::Unpaginated:
1818 ASSERT_NOT_REACHED();
1823 } // namespace WebCore