2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
4 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
5 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
25 #include "core/layout/LayoutReplaced.h"
27 #include "core/editing/PositionWithAffinity.h"
28 #include "core/layout/LayoutAnalyzer.h"
29 #include "core/layout/LayoutBlock.h"
30 #include "core/layout/LayoutImage.h"
31 #include "core/layout/LayoutView.h"
32 #include "core/paint/DeprecatedPaintLayer.h"
33 #include "core/paint/PaintInfo.h"
34 #include "core/paint/ReplacedPainter.h"
35 #include "platform/LengthFunctions.h"
39 const int LayoutReplaced::defaultWidth
= 300;
40 const int LayoutReplaced::defaultHeight
= 150;
42 LayoutReplaced::LayoutReplaced(Element
* element
)
44 , m_intrinsicSize(defaultWidth
, defaultHeight
)
49 LayoutReplaced::LayoutReplaced(Element
* element
, const LayoutSize
& intrinsicSize
)
51 , m_intrinsicSize(intrinsicSize
)
56 LayoutReplaced::~LayoutReplaced()
60 void LayoutReplaced::willBeDestroyed()
62 if (!documentBeingDestroyed() && parent())
63 parent()->dirtyLinesFromChangedChild(this);
65 LayoutBox::willBeDestroyed();
68 void LayoutReplaced::styleDidChange(StyleDifference diff
, const ComputedStyle
* oldStyle
)
70 LayoutBox::styleDidChange(diff
, oldStyle
);
72 bool hadStyle
= (oldStyle
!= 0);
73 float oldZoom
= hadStyle
? oldStyle
->effectiveZoom() : ComputedStyle::initialZoom();
74 if (style() && style()->effectiveZoom() != oldZoom
)
75 intrinsicSizeChanged();
78 void LayoutReplaced::layout()
80 ASSERT(needsLayout());
81 LayoutAnalyzer::Scope
analyzer(*this);
83 LayoutRect oldContentRect
= replacedContentRect();
85 setHeight(minimumReplacedHeight());
88 updateLogicalHeight();
91 addVisualEffectOverflow();
92 updateLayerTransformAfterLayout();
93 invalidateBackgroundObscurationStatus();
97 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && replacedContentRect() != oldContentRect
)
98 setShouldDoFullPaintInvalidation();
101 void LayoutReplaced::intrinsicSizeChanged()
103 int scaledWidth
= static_cast<int>(defaultWidth
* style()->effectiveZoom());
104 int scaledHeight
= static_cast<int>(defaultHeight
* style()->effectiveZoom());
105 m_intrinsicSize
= LayoutSize(scaledWidth
, scaledHeight
);
106 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::SizeChanged
);
109 void LayoutReplaced::paint(const PaintInfo
& paintInfo
, const LayoutPoint
& paintOffset
)
111 ReplacedPainter(*this).paint(paintInfo
, paintOffset
);
114 bool LayoutReplaced::shouldPaint(const PaintInfo
& paintInfo
, const LayoutPoint
& paintOffset
) const
116 if (paintInfo
.phase
!= PaintPhaseForeground
&& paintInfo
.phase
!= PaintPhaseOutline
&& paintInfo
.phase
!= PaintPhaseSelfOutline
117 && paintInfo
.phase
!= PaintPhaseSelection
&& paintInfo
.phase
!= PaintPhaseMask
&& paintInfo
.phase
!= PaintPhaseClippingMask
)
120 if (!paintInfo
.shouldPaintWithinRoot(this))
123 // if we're invisible or haven't received a layout yet, then just bail.
124 if (style()->visibility() != VISIBLE
)
127 LayoutRect
paintRect(visualOverflowRect());
128 paintRect
.moveBy(paintOffset
+ location());
130 // Early exit if the element touches the edges.
131 LayoutUnit top
= paintRect
.y();
132 LayoutUnit bottom
= paintRect
.maxY();
133 if (isSelected() && inlineBoxWrapper()) {
134 LayoutUnit selTop
= paintOffset
.y() + inlineBoxWrapper()->root().selectionTop();
135 LayoutUnit selBottom
= paintOffset
.y() + selTop
+ inlineBoxWrapper()->root().selectionHeight();
136 top
= std::min(selTop
, top
);
137 bottom
= std::max(selBottom
, bottom
);
140 if (paintRect
.x() >= paintInfo
.rect
.maxX() || paintRect
.maxX() <= paintInfo
.rect
.x())
143 if (top
>= paintInfo
.rect
.maxY() || bottom
<= paintInfo
.rect
.y())
149 bool LayoutReplaced::hasReplacedLogicalHeight() const
151 if (style()->logicalHeight().isAuto())
154 if (style()->logicalHeight().isSpecified()) {
155 if (hasAutoHeightOrContainingBlockWithAutoHeight())
160 if (style()->logicalHeight().isIntrinsic())
166 bool LayoutReplaced::needsPreferredWidthsRecalculation() const
168 // If the height is a percentage and the width is auto, then the containingBlocks's height changing can cause
169 // this node to change it's preferred width because it maintains aspect ratio.
170 return hasRelativeLogicalHeight() && style()->logicalWidth().isAuto() && !hasAutoHeightOrContainingBlockWithAutoHeight();
173 static inline bool layoutObjectHasAspectRatio(const LayoutObject
* layoutObject
)
175 ASSERT(layoutObject
);
176 return layoutObject
->isImage() || layoutObject
->isCanvas() || layoutObject
->isVideo();
179 void LayoutReplaced::computeAspectRatioInformationForLayoutBox(LayoutBox
* contentLayoutObject
, FloatSize
& constrainedSize
, double& intrinsicRatio
) const
181 FloatSize intrinsicSize
;
182 if (contentLayoutObject
) {
183 contentLayoutObject
->computeIntrinsicRatioInformation(intrinsicSize
, intrinsicRatio
);
185 // Handle zoom & vertical writing modes here, as the embedded document doesn't know about them.
186 intrinsicSize
.scale(style()->effectiveZoom());
188 intrinsicSize
.scale(toLayoutImage(this)->imageDevicePixelRatio());
190 // Update our intrinsic size to match what the content layoutObject has computed, so that when we
191 // constrain the size below, the correct intrinsic size will be obtained for comparison against
192 // min and max widths.
193 if (intrinsicRatio
&& !intrinsicSize
.isEmpty())
194 m_intrinsicSize
= LayoutSize(intrinsicSize
);
196 if (!isHorizontalWritingMode()) {
198 intrinsicRatio
= 1 / intrinsicRatio
;
199 intrinsicSize
= intrinsicSize
.transposedSize();
202 computeIntrinsicRatioInformation(intrinsicSize
, intrinsicRatio
);
203 if (intrinsicRatio
&& !intrinsicSize
.isEmpty())
204 m_intrinsicSize
= LayoutSize(isHorizontalWritingMode() ? intrinsicSize
: intrinsicSize
.transposedSize());
207 // Now constrain the intrinsic size along each axis according to minimum and maximum width/heights along the
208 // opposite axis. So for example a maximum width that shrinks our width will result in the height we compute here
209 // having to shrink in order to preserve the aspect ratio. Because we compute these values independently along
210 // each axis, the final returned size may in fact not preserve the aspect ratio.
211 // FIXME: In the long term, it might be better to just return this code more to the way it used to be before this
212 // function was added, since all it has done is make the code more unclear.
213 constrainedSize
= intrinsicSize
;
214 if (intrinsicRatio
&& !intrinsicSize
.isEmpty() && style()->logicalWidth().isAuto() && style()->logicalHeight().isAuto()) {
215 // We can't multiply or divide by 'intrinsicRatio' here, it breaks tests, like fast/images/zoomed-img-size.html, which
216 // can only be fixed once subpixel precision is available for things like intrinsicWidth/Height - which include zoom!
217 constrainedSize
.setWidth(LayoutBox::computeReplacedLogicalHeight() * intrinsicSize
.width() / intrinsicSize
.height());
218 constrainedSize
.setHeight(LayoutBox::computeReplacedLogicalWidth() * intrinsicSize
.height() / intrinsicSize
.width());
222 LayoutRect
LayoutReplaced::replacedContentRect(const LayoutSize
* overriddenIntrinsicSize
) const
224 LayoutRect contentRect
= contentBoxRect();
225 ObjectFit objectFit
= style()->objectFit();
227 if (objectFit
== ObjectFitFill
&& style()->objectPosition() == ComputedStyle::initialObjectPosition()) {
231 // TODO(davve): intrinsicSize doubles as both intrinsic size and intrinsic ratio. In the case of
232 // SVG images this isn't correct since they can have intrinsic ratio but no intrinsic size. In
233 // order to maintain aspect ratio, the intrinsic size for SVG might be faked from the aspect
234 // ratio, see SVGImage::containerSize().
235 LayoutSize intrinsicSize
= overriddenIntrinsicSize
? *overriddenIntrinsicSize
: this->intrinsicSize();
236 if (!intrinsicSize
.width() || !intrinsicSize
.height())
239 LayoutRect finalRect
= contentRect
;
241 case ObjectFitContain
:
242 case ObjectFitScaleDown
:
244 finalRect
.setSize(finalRect
.size().fitToAspectRatio(intrinsicSize
, objectFit
== ObjectFitCover
? AspectRatioFitGrow
: AspectRatioFitShrink
));
245 if (objectFit
!= ObjectFitScaleDown
|| finalRect
.width() <= intrinsicSize
.width())
249 finalRect
.setSize(intrinsicSize
);
254 ASSERT_NOT_REACHED();
257 LayoutUnit xOffset
= minimumValueForLength(style()->objectPosition().x(), contentRect
.width() - finalRect
.width());
258 LayoutUnit yOffset
= minimumValueForLength(style()->objectPosition().y(), contentRect
.height() - finalRect
.height());
259 finalRect
.move(xOffset
, yOffset
);
264 void LayoutReplaced::computeIntrinsicRatioInformation(FloatSize
& intrinsicSize
, double& intrinsicRatio
) const
266 // If there's an embeddedContentBox() of a remote, referenced document available, this code-path should never be used.
267 ASSERT(!embeddedContentBox());
268 intrinsicSize
= FloatSize(intrinsicLogicalWidth().toFloat(), intrinsicLogicalHeight().toFloat());
270 // Figure out if we need to compute an intrinsic ratio.
271 if (intrinsicSize
.isEmpty() || !layoutObjectHasAspectRatio(this))
274 intrinsicRatio
= intrinsicSize
.width() / intrinsicSize
.height();
277 LayoutUnit
LayoutReplaced::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred
) const
279 if (style()->logicalWidth().isSpecified() || style()->logicalWidth().isIntrinsic())
280 return computeReplacedLogicalWidthRespectingMinMaxWidth(computeReplacedLogicalWidthUsing(MainOrPreferredSize
, style()->logicalWidth()), shouldComputePreferred
);
282 LayoutBox
* contentLayoutObject
= embeddedContentBox();
284 // 10.3.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-width
285 double intrinsicRatio
= 0;
286 FloatSize constrainedSize
;
287 computeAspectRatioInformationForLayoutBox(contentLayoutObject
, constrainedSize
, intrinsicRatio
);
289 if (style()->logicalWidth().isAuto()) {
290 bool computedHeightIsAuto
= hasAutoHeightOrContainingBlockWithAutoHeight();
291 bool hasIntrinsicWidth
= constrainedSize
.width() > 0;
293 // If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic width, then that intrinsic width is the used value of 'width'.
294 if (computedHeightIsAuto
&& hasIntrinsicWidth
)
295 return computeReplacedLogicalWidthRespectingMinMaxWidth(constrainedSize
.width(), shouldComputePreferred
);
297 bool hasIntrinsicHeight
= constrainedSize
.height() > 0;
298 if (intrinsicRatio
) {
299 // If 'height' and 'width' both have computed values of 'auto' and the element has no intrinsic width, but does have an intrinsic height and intrinsic ratio;
300 // or if 'width' has a computed value of 'auto', 'height' has some other computed value, and the element does have an intrinsic ratio; then the used value
301 // of 'width' is: (used height) * (intrinsic ratio)
302 if (intrinsicRatio
&& ((computedHeightIsAuto
&& !hasIntrinsicWidth
&& hasIntrinsicHeight
) || !computedHeightIsAuto
)) {
303 LayoutUnit logicalHeight
= computeReplacedLogicalHeight();
304 return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(round(logicalHeight
* intrinsicRatio
)), shouldComputePreferred
);
307 // If 'height' and 'width' both have computed values of 'auto' and the element has an intrinsic ratio but no intrinsic height or width, then the used value of
308 // 'width' is undefined in CSS 2.1. However, it is suggested that, if the containing block's width does not itself depend on the replaced element's width, then
309 // the used value of 'width' is calculated from the constraint equation used for block-level, non-replaced elements in normal flow.
310 if (computedHeightIsAuto
&& !hasIntrinsicWidth
&& !hasIntrinsicHeight
) {
311 if (shouldComputePreferred
== ComputePreferred
)
313 // The aforementioned 'constraint equation' used for block-level, non-replaced elements in normal flow:
314 // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
315 LayoutUnit logicalWidth
= containingBlock()->availableLogicalWidth();
317 // This solves above equation for 'width' (== logicalWidth).
318 LayoutUnit marginStart
= minimumValueForLength(style()->marginStart(), logicalWidth
);
319 LayoutUnit marginEnd
= minimumValueForLength(style()->marginEnd(), logicalWidth
);
320 logicalWidth
= std::max
<LayoutUnit
>(0, logicalWidth
- (marginStart
+ marginEnd
+ (size().width() - clientWidth())));
321 return computeReplacedLogicalWidthRespectingMinMaxWidth(logicalWidth
, shouldComputePreferred
);
325 // Otherwise, if 'width' has a computed value of 'auto', and the element has an intrinsic width, then that intrinsic width is the used value of 'width'.
326 if (hasIntrinsicWidth
)
327 return computeReplacedLogicalWidthRespectingMinMaxWidth(constrainedSize
.width(), shouldComputePreferred
);
329 // Otherwise, if 'width' has a computed value of 'auto', but none of the conditions above are met, then the used value of 'width' becomes 300px. If 300px is too
330 // wide to fit the device, UAs should use the width of the largest rectangle that has a 2:1 ratio and fits the device instead.
331 // Note: We fall through and instead return intrinsicLogicalWidth() here - to preserve existing WebKit behavior, which might or might not be correct, or desired.
332 // Changing this to return cDefaultWidth, will affect lots of test results. Eg. some tests assume that a blank <img> tag (which implies width/height=auto)
333 // has no intrinsic size, which is wrong per CSS 2.1, but matches our behavior since a long time.
336 return computeReplacedLogicalWidthRespectingMinMaxWidth(intrinsicLogicalWidth(), shouldComputePreferred
);
339 LayoutUnit
LayoutReplaced::computeReplacedLogicalHeight() const
341 // 10.5 Content height: the 'height' property: http://www.w3.org/TR/CSS21/visudet.html#propdef-height
342 if (hasReplacedLogicalHeight())
343 return computeReplacedLogicalHeightRespectingMinMaxHeight(computeReplacedLogicalHeightUsing(MainOrPreferredSize
, style()->logicalHeight()));
345 LayoutBox
* contentLayoutObject
= embeddedContentBox();
347 // 10.6.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-height
348 double intrinsicRatio
= 0;
349 FloatSize constrainedSize
;
350 computeAspectRatioInformationForLayoutBox(contentLayoutObject
, constrainedSize
, intrinsicRatio
);
352 bool widthIsAuto
= style()->logicalWidth().isAuto();
353 bool hasIntrinsicHeight
= constrainedSize
.height() > 0;
355 // If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic height, then that intrinsic height is the used value of 'height'.
356 if (widthIsAuto
&& hasIntrinsicHeight
)
357 return computeReplacedLogicalHeightRespectingMinMaxHeight(constrainedSize
.height());
359 // Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic ratio then the used value of 'height' is:
360 // (used width) / (intrinsic ratio)
362 return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(round(availableLogicalWidth() / intrinsicRatio
)));
364 // Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic height, then that intrinsic height is the used value of 'height'.
365 if (hasIntrinsicHeight
)
366 return computeReplacedLogicalHeightRespectingMinMaxHeight(constrainedSize
.height());
368 // Otherwise, if 'height' has a computed value of 'auto', but none of the conditions above are met, then the used value of 'height' must be set to the height
369 // of the largest rectangle that has a 2:1 ratio, has a height not greater than 150px, and has a width not greater than the device width.
370 return computeReplacedLogicalHeightRespectingMinMaxHeight(intrinsicLogicalHeight());
373 void LayoutReplaced::computeIntrinsicLogicalWidths(LayoutUnit
& minLogicalWidth
, LayoutUnit
& maxLogicalWidth
) const
375 minLogicalWidth
= maxLogicalWidth
= intrinsicLogicalWidth();
378 void LayoutReplaced::computePreferredLogicalWidths()
380 ASSERT(preferredLogicalWidthsDirty());
382 // We cannot resolve any percent logical width here as the available logical
383 // width may not be set on our containing block.
384 if (style()->logicalWidth().hasPercent())
385 computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth
, m_maxPreferredLogicalWidth
);
387 m_minPreferredLogicalWidth
= m_maxPreferredLogicalWidth
= computeReplacedLogicalWidth(ComputePreferred
);
389 const ComputedStyle
& styleToUse
= styleRef();
390 if (styleToUse
.logicalWidth().hasPercent() || styleToUse
.logicalMaxWidth().hasPercent())
391 m_minPreferredLogicalWidth
= 0;
393 if (styleToUse
.logicalMinWidth().isFixed() && styleToUse
.logicalMinWidth().value() > 0) {
394 m_maxPreferredLogicalWidth
= std::max(m_maxPreferredLogicalWidth
, adjustContentBoxLogicalWidthForBoxSizing(styleToUse
.logicalMinWidth().value()));
395 m_minPreferredLogicalWidth
= std::max(m_minPreferredLogicalWidth
, adjustContentBoxLogicalWidthForBoxSizing(styleToUse
.logicalMinWidth().value()));
398 if (styleToUse
.logicalMaxWidth().isFixed()) {
399 m_maxPreferredLogicalWidth
= std::min(m_maxPreferredLogicalWidth
, adjustContentBoxLogicalWidthForBoxSizing(styleToUse
.logicalMaxWidth().value()));
400 m_minPreferredLogicalWidth
= std::min(m_minPreferredLogicalWidth
, adjustContentBoxLogicalWidthForBoxSizing(styleToUse
.logicalMaxWidth().value()));
403 LayoutUnit borderAndPadding
= borderAndPaddingLogicalWidth();
404 m_minPreferredLogicalWidth
+= borderAndPadding
;
405 m_maxPreferredLogicalWidth
+= borderAndPadding
;
407 clearPreferredLogicalWidthsDirty();
410 PositionWithAffinity
LayoutReplaced::positionForPoint(const LayoutPoint
& point
)
412 // FIXME: This code is buggy if the replaced element is relative positioned.
413 InlineBox
* box
= inlineBoxWrapper();
414 RootInlineBox
* rootBox
= box
? &box
->root() : 0;
416 LayoutUnit top
= rootBox
? rootBox
->selectionTop() : logicalTop();
417 LayoutUnit bottom
= rootBox
? rootBox
->selectionBottom() : logicalBottom();
419 LayoutUnit blockDirectionPosition
= isHorizontalWritingMode() ? point
.y() + location().y() : point
.x() + location().x();
420 LayoutUnit lineDirectionPosition
= isHorizontalWritingMode() ? point
.x() + location().x() : point
.y() + location().y();
422 if (blockDirectionPosition
< top
)
423 return createPositionWithAffinity(caretMinOffset()); // coordinates are above
425 if (blockDirectionPosition
>= bottom
)
426 return createPositionWithAffinity(caretMaxOffset()); // coordinates are below
429 if (lineDirectionPosition
<= logicalLeft() + (logicalWidth() / 2))
430 return createPositionWithAffinity(0);
431 return createPositionWithAffinity(1);
434 return LayoutBox::positionForPoint(point
);
437 LayoutRect
LayoutReplaced::selectionRectForPaintInvalidation(const LayoutBoxModelObject
* paintInvalidationContainer
) const
439 ASSERT(!needsLayout());
444 LayoutRect rect
= localSelectionRect();
445 mapRectToPaintInvalidationBacking(paintInvalidationContainer
, rect
, 0);
446 // FIXME: groupedMapping() leaks the squashing abstraction.
447 if (paintInvalidationContainer
->layer()->groupedMapping())
448 DeprecatedPaintLayer::mapRectToPaintBackingCoordinates(paintInvalidationContainer
, rect
);
452 LayoutRect
LayoutReplaced::localSelectionRect(bool checkWhetherSelected
) const
454 if (checkWhetherSelected
&& !isSelected())
457 if (!inlineBoxWrapper()) {
458 // We're a block-level replaced element. Just return our own dimensions.
459 return LayoutRect(LayoutPoint(), size());
462 RootInlineBox
& root
= inlineBoxWrapper()->root();
463 LayoutUnit newLogicalTop
= root
.block().style()->isFlippedBlocksWritingMode() ? inlineBoxWrapper()->logicalBottom() - root
.selectionBottom() : root
.selectionTop() - inlineBoxWrapper()->logicalTop();
464 if (root
.block().style()->isHorizontalWritingMode())
465 return LayoutRect(0, newLogicalTop
, size().width(), root
.selectionHeight());
466 return LayoutRect(newLogicalTop
, 0, root
.selectionHeight(), size().height());
469 void LayoutReplaced::setSelectionState(SelectionState state
)
471 // The selection state for our containing block hierarchy is updated by the base class call.
472 LayoutBox::setSelectionState(state
);
474 if (!inlineBoxWrapper())
477 // We only include the space below the baseline in our layer's cached paint invalidation rect if the
478 // image is selected. Since the selection state has changed update the rect.
480 setPreviousPaintInvalidationRect(boundsRectForPaintInvalidation(containerForPaintInvalidation()));
482 if (canUpdateSelectionOnRootLineBoxes())
483 inlineBoxWrapper()->root().setHasSelectedChildren(isSelected());
486 bool LayoutReplaced::isSelected() const
488 SelectionState s
= selectionState();
489 if (s
== SelectionNone
)
491 if (s
== SelectionInside
)
494 int selectionStart
, selectionEnd
;
495 selectionStartEnd(selectionStart
, selectionEnd
);
496 if (s
== SelectionStart
)
497 return selectionStart
== 0;
499 int end
= node()->hasChildren() ? node()->countChildren() : 1;
500 if (s
== SelectionEnd
)
501 return selectionEnd
== end
;
502 if (s
== SelectionBoth
)
503 return selectionStart
== 0 && selectionEnd
== end
;
508 LayoutRect
LayoutReplaced::clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject
* paintInvalidationContainer
, const PaintInvalidationState
* paintInvalidationState
) const
510 if (style()->visibility() != VISIBLE
&& !enclosingLayer()->hasVisibleContent())
513 // The selectionRect can project outside of the overflowRect, so take their union
514 // for paint invalidation to avoid selection painting glitches.
515 LayoutRect r
= isSelected() ? localSelectionRect() : visualOverflowRect();
516 mapRectToPaintInvalidationBacking(paintInvalidationContainer
, r
, paintInvalidationState
);