Bug Summary

File:Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore/rendering/RenderLayerModelObject.cpp
Warning:line 206, column 29
Local variable 'frameView' is uncounted and unsafe

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple arm64-apple-macosx15.5.0 -O2 -Wundef-prefix=TARGET_OS_ -Werror=undef-prefix -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name UnifiedSource413.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=osx -analyzer-checker=security.insecureAPI.decodeValueOfObjCType -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=non-leaf -ffp-contract=on -fno-rounding-math -target-sdk-version=15.5 -fcompatibility-qualified-id-block-type-checking -fvisibility-inlines-hidden-static-local-var -fno-modulemap-allow-subdirectory-search -fdefine-target-os-macros -enable-tlsdesc -target-cpu apple-m1 -target-feature +v8.4a -target-feature +aes -target-feature +altnzcv -target-feature +ccdp -target-feature +ccpp -target-feature +complxnum -target-feature +crc -target-feature +dotprod -target-feature +flagm -target-feature +fp-armv8 -target-feature +fp16fml -target-feature +fptoint -target-feature +fullfp16 -target-feature +jsconv -target-feature +lse -target-feature +neon -target-feature +pauth -target-feature +perfmon -target-feature +predres -target-feature +ras -target-feature +rcpc -target-feature +rdm -target-feature +sb -target-feature +sha2 -target-feature +sha3 -target-feature +specrestrict -target-feature +ssbs -target-abi darwinpcs -dwarf-ext-refs -fmodule-format=obj -debug-info-kind=standalone -dwarf-version=5 -debugger-tuning=lldb -fdebug-compilation-dir=/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore -target-linker-version 1167.5 -fcoverage-compilation-dir=/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore -resource-dir /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/llvm-project/build/lib/clang/21 -dependency-file /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/scan-build-output/StaticAnalyzer/WebCore/WebCore/normal/arm64/UnifiedSource413.d -skip-unused-modulemap-deps -MT dependencies -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk -iquote /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/WebCore-generated-files.hmap -iquote /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/WebCore-project-headers.hmap -isystem /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore/PAL/ThirdParty/dav1d/include -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/PrivateFrameworks -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/Frameworks -include-pch /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/PrecompiledHeaders/SharedPrecompiledHeaders/12902642326230122134/WebCorePrefix.h.gch -D _LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE -D CLANG_WEBKIT_BRANCH=1 -D NDEBUG -D BUILDING_WEBKIT -D GL_SILENCE_DEPRECATION=1 -D GLES_SILENCE_DEPRECATION=1 -D __clang_analyzer__ -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/WebCore-own-target-headers.hmap -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/WebCore-all-target-headers.hmap -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/include -I PAL -I ForwardingHeaders -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include/libxslt -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include/libxml2 -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/DerivedSources/WebCore -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include/WebKitAdditions -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include/WebKitAdditions -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitLibraries/SDKs/macosx15.0-additions.sdk/usr/local/include -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include/webrtc -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include/webrtc -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include/webm -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include/webm -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/PAL.build/PAL.build/DerivedSources -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/PAL.build/Release/PAL.build/DerivedSources -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/DerivedSources-normal/arm64 -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/DerivedSources/arm64 -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/DerivedSources -F/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release -I/usr/local/include -stdlib=libc++ -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include/c++/v1 -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include -internal-isystem /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/llvm-project/build/lib/clang/21/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/Frameworks -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/SubFrameworks -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/Library/Frameworks -Wno-trigraphs -Werror -Wno-missing-field-initializers -Wmissing-prototypes -Wunreachable-code -Wnon-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wunused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wempty-body -Wuninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wno-float-conversion -Wnon-literal-null-conversion -Wobjc-literal-conversion -Wsign-compare -Wno-shorten-64-to-32 -Wnewline-eof -Wno-c++11-extensions -Wno-implicit-fallthrough -Wdeprecated-declarations -Winvalid-offsetof -Wno-sign-conversion -Winfinite-recursion -Wmove -Wcomma -Wblock-capture-autoreleasing -Wstrict-prototypes -Wrange-loop-analysis -Wno-semicolon-before-method-body -Wall -Wc99-designator -Wconditional-uninitialized -Wextra -Wdeprecated-enum-enum-conversion -Wdeprecated-enum-float-conversion -Wenum-float-conversion -Wfinal-dtor-non-final-class -Wformat=2 -Wmisleading-indentation -Wpointer-to-int-cast -Wreorder-init-list -Wundef -Wunused-but-set-variable -Wvla -Werror=unguarded-availability -Wno-elaborated-enum-base -Wcast-qual -Wchar-subscripts -Wextra-tokens -Winit-self -Wmissing-noreturn -Wpacked -Wpointer-arith -Wredundant-decls -Wwrite-strings -Wexit-time-destructors -Wglobal-constructors -Wtautological-compare -Wimplicit-fallthrough -Wvla -Wno-unknown-warning-option -Wliteral-conversion -Wthread-safety -Wno-profile-instr-out-of-date -Wno-profile-instr-unprofiled -Wno-backend-plugin -Wunsafe-buffer-usage -std=c++2b -fdeprecated-macro -ferror-limit 19 -fmacro-backtrace-limit=0 -fvisibility=hidden -fvisibility-inlines-hidden -stack-protector 1 -fblocks -fencode-extended-block-signature -fno-rtti -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fno-cxx-modules -fno-implicit-modules -fskip-odr-check-in-gmf -fpascal-strings -fmax-type-align=16 -fdiagnostics-show-note-include-stack -vectorize-loops -vectorize-slp -fsafe-buffer-usage-suggestions -analyzer-output=html -analyzer-config report-in-main-source-file=true -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true -analyzer-checker optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker security.insecureAPI.UncheckedReturn -analyzer-checker security.insecureAPI.getpw -analyzer-checker security.insecureAPI.gets -analyzer-checker security.insecureAPI.mkstemp -analyzer-checker security.insecureAPI.mktemp -analyzer-disable-checker security.insecureAPI.rand -analyzer-disable-checker security.insecureAPI.strcpy -analyzer-checker security.insecureAPI.vfork -analyzer-disable-checker alpha,apiModeling,core,cplusplus,deadcode,debug,fuchsia,nullability,optin,osx,security,unix,webkit -analyzer-checker alpha.webkit.ForwardDeclChecker,alpha.webkit.MemoryUnsafeCastChecker,alpha.webkit.NoDeleteChecker,alpha.webkit.NoUncheckedPtrMemberChecker,alpha.webkit.NoUnretainedMemberChecker,alpha.webkit.RetainPtrCtorAdoptChecker,alpha.webkit.UncheckedCallArgsChecker,alpha.webkit.UncheckedLocalVarsChecker,alpha.webkit.UncountedCallArgsChecker,alpha.webkit.UncountedLocalVarsChecker,alpha.webkit.UnretainedCallArgsChecker,alpha.webkit.UnretainedLambdaCapturesChecker,alpha.webkit.UnretainedLocalVarsChecker,webkit.NoUncountedMemberChecker,webkit.RefCntblBaseVirtualDtor,webkit.UncountedLambdaCapturesChecker -analyzer-config max-nodes=10000000 -analyzer-config verbose-report-filename=true -fdwarf2-cfi-asm -o /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/scan-build-output/StaticAnalyzer/WebCore/WebCore/normal/arm64/UnifiedSource413.plist -x c++ /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/DerivedSources/WebCore/unified-sources/UnifiedSource413.cpp
1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
6 * Copyright (C) 2005-2025 Apple Inc. All rights reserved.
7 * Copyright (C) 2010-2015 Google Inc. All rights reserved.
8 * Copyright (C) 2023, 2024 Igalia S.L.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 */
25
26#include "config.h"
27#include "RenderLayerModelObject.h"
28
29#include "BlendingKeyframes.h"
30#include "ContainerNodeInlines.h"
31#include "InspectorInstrumentation.h"
32#include "LocalFrameView.h"
33#include "MotionPath.h"
34#include "ReferencedSVGResources.h"
35#include "RenderDescendantIterator.h"
36#include "RenderElementInlines.h"
37#include "RenderLayer.h"
38#include "RenderLayerBacking.h"
39#include "RenderLayerCompositor.h"
40#include "RenderLayerScrollableArea.h"
41#include "RenderMultiColumnSet.h"
42#include "RenderObjectInlines.h"
43#include "RenderSVGBlock.h"
44#include "RenderSVGModelObject.h"
45#include "RenderSVGResourceClipper.h"
46#include "RenderSVGResourceFilter.h"
47#include "RenderSVGResourceLinearGradient.h"
48#include "RenderSVGResourceMarker.h"
49#include "RenderSVGResourceMasker.h"
50#include "RenderSVGResourceRadialGradient.h"
51#include "RenderSVGText.h"
52#include "RenderStyle+GettersInlines.h"
53#include "RenderView.h"
54#include "SVGClipPathElement.h"
55#include "SVGFilterElement.h"
56#include "SVGGraphicsElement.h"
57#include "SVGMarkerElement.h"
58#include "SVGMaskElement.h"
59#include "SVGTextElement.h"
60#include "SVGURIReference.h"
61#include "Settings.h"
62#include "StyleTransformResolver.h"
63#include "TransformOperationData.h"
64#include "TransformState.h"
65#include <wtf/MathExtras.h>
66#include <wtf/TZoneMallocInlines.h>
67
68namespace WebCore {
69
70WTF_MAKE_TZONE_ALLOCATED_IMPL(RenderLayerModelObject)::bmalloc::api::HeapRef RenderLayerModelObject::s_heapRef; const
TZoneSpecification RenderLayerModelObject::s_heapSpec = { &
RenderLayerModelObject::s_heapRef, TZoneSpecification::encodeSize
<RenderLayerModelObject>(), TZoneSpecification::encodeAlignment
<RenderLayerModelObject>(), TZoneSpecification::encodeCategory
<RenderLayerModelObject>(), ::bmalloc::api::compactAllocationMode
<RenderLayerModelObject>(), TZoneSpecification::encodeDescriptor
<RenderLayerModelObject>(), }; void* RenderLayerModelObject
::operatorNewSlow(size_t size) { if constexpr (::bmalloc::api
::compactAllocationMode<RenderLayerModelObject>() == CompactAllocationMode
::Compact) return ::bmalloc::api::tzoneAllocateCompactSlow(size
, s_heapSpec); return ::bmalloc::api::tzoneAllocateNonCompactSlow
(size, s_heapSpec); } using __makeBtzoneMallocedInlineMacroSemicolonifier
__attribute__((unused)) = int
;
71
72bool RenderLayerModelObject::s_wasFloating = false;
73bool RenderLayerModelObject::s_hadLayer = false;
74bool RenderLayerModelObject::s_wasTransformed = false;
75bool RenderLayerModelObject::s_layerWasSelfPainting = false;
76
77RenderLayerModelObject::RenderLayerModelObject(Type type, Element& element, RenderStyle&& style, OptionSet<TypeFlag> baseTypeFlags, TypeSpecificFlags typeSpecificFlags)
78 : RenderElement(type, element, WTF::move(style), baseTypeFlags | TypeFlag::IsLayerModelObject, typeSpecificFlags)
79{
80 ASSERT(isRenderLayerModelObject())((void)0);
81}
82
83RenderLayerModelObject::RenderLayerModelObject(Type type, Document& document, RenderStyle&& style, OptionSet<TypeFlag> baseTypeFlags, TypeSpecificFlags typeSpecificFlags)
84 : RenderElement(type, document, WTF::move(style), baseTypeFlags | TypeFlag::IsLayerModelObject, typeSpecificFlags)
85{
86 ASSERT(isRenderLayerModelObject())((void)0);
87}
88
89// Do not add any code in below destructor. Add it to willBeDestroyed() instead.
90RenderLayerModelObject::~RenderLayerModelObject() = default;
91
92void RenderLayerModelObject::willBeDestroyed()
93{
94 if (isPositioned()) {
95 if (style().hasViewportConstrainedPosition())
96 view().frameView().removeViewportConstrainedObject(*this);
97 }
98
99 destroyLayer();
100
101 RenderElement::willBeDestroyed();
102}
103
104void RenderLayerModelObject::destroyLayer()
105{
106 setHasLayer(false);
107 m_layer = nullptr;
108}
109
110void RenderLayerModelObject::createLayer()
111{
112 ASSERT(!m_layer)((void)0);
113 m_layer = RenderLayer::create(*this);
114 setHasLayer(true);
115 m_layer->insertOnlyThisLayer();
116}
117
118bool RenderLayerModelObject::hasSelfPaintingLayer() const
119{
120 return m_layer && m_layer->isSelfPaintingLayer();
121}
122
123void RenderLayerModelObject::styleWillChange(Style::Difference diff, const RenderStyle& newStyle)
124{
125 s_wasFloating = isFloating();
126 s_hadLayer = hasLayer();
127 s_wasTransformed = isTransformed();
128 if (s_hadLayer)
129 s_layerWasSelfPainting = layer()->isSelfPaintingLayer();
130
131 auto* oldStyle = hasInitializedStyle() ? &style() : nullptr;
132 if (diff == Style::DifferenceResult::RepaintLayer && parent() && oldStyle && oldStyle->clip() != newStyle.clip())
133 layer()->clearClipRectsIncludingDescendants();
134 RenderElement::styleWillChange(diff, newStyle);
135}
136
137void RenderLayerModelObject::styleDidChange(Style::Difference diff, const RenderStyle* oldStyle)
138{
139 updateFromStyle();
140 RenderElement::styleDidChange(diff, oldStyle);
141
142 // When an out-of-flow-positioned element changes its display between block and inline-block,
143 // then an incremental layout on the element's containing block lays out the element through
144 // LayoutPositionedObjects, which skips laying out the element's parent.
145 // The element's parent needs to relayout so that it calls
146 // RenderBlockFlow::setStaticInlinePositionForChild with the out-of-flow-positioned child, so
147 // that when it's laid out, its RenderBox::computeOutOfFlowPositionedLogicalWidth/Height takes into
148 // account its new inline/block position rather than its old block/inline position.
149 // Position changes and other types of display changes are handled elsewhere.
150 if ((oldStyle && isOutOfFlowPositioned() && parent() && (parent() != containingBlock()))
151 && (style().position() == oldStyle->position())
152 && (style().originalDisplay().isInlineType() != oldStyle->originalDisplay().isInlineType())
153 && (style().originalDisplay().isBlockType() || style().originalDisplay().isInlineType())
154 && (oldStyle->originalDisplay().isBlockType() || oldStyle->originalDisplay().isInlineType()))
155 parent()->setChildNeedsLayout();
156
157 bool gainedOrLostLayer = false;
158 if (requiresLayer()) {
159 if (!layer() && layerCreationAllowedForSubtree()) {
160 gainedOrLostLayer = true;
161 if (s_wasFloating && isFloating())
162 setChildNeedsLayout();
163 createLayer();
164 if (parent() && !needsLayout())
165 layer()->setRepaintStatus(RepaintStatus::NeedsFullRepaint);
166 }
167 } else if (layer() && layer()->parent()) {
168 gainedOrLostLayer = true;
169 if (oldStyle && oldStyle->blendMode() != BlendMode::Normal)
170 layer()->willRemoveChildWithBlendMode();
171 setHasTransformRelatedProperty(false); // All transform-related properties force layers, so we know we don't have one or the object doesn't support them.
172 setHasSVGTransform(false); // Same reason as for setHasTransformRelatedProperty().
173 setHasReflection(false);
174
175 // Repaint the about to be destroyed self-painting layer when style change also triggers repaint.
176 if (layer()->isSelfPaintingLayer() && layer()->repaintStatus() == RepaintStatus::NeedsFullRepaint && layer()->cachedClippedOverflowRect())
177 repaintUsingContainer(containerForRepaint().renderer.get(), *(layer()->cachedClippedOverflowRect()));
178
179 layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
180 if (s_wasFloating && isFloating())
181 setChildNeedsLayout();
182 if (s_wasTransformed)
183 setNeedsLayoutAndPreferredWidthsUpdate();
184 }
185
186 if (gainedOrLostLayer)
187 InspectorInstrumentation::didAddOrRemoveScrollbars(*this);
188
189 if (layer()) {
190 layer()->styleChanged(diff, oldStyle);
191 if (s_hadLayer && layer()->isSelfPaintingLayer() != s_layerWasSelfPainting)
192 setChildNeedsLayout();
193 }
194
195 bool newStyleIsViewportConstrained = style().hasViewportConstrainedPosition();
196 bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition();
197 if (newStyleIsViewportConstrained != oldStyleIsViewportConstrained) {
198 if (newStyleIsViewportConstrained && layer())
199 view().frameView().addViewportConstrainedObject(*this);
200 else
201 view().frameView().removeViewportConstrainedObject(*this);
202 }
203
204 if (oldStyle && !oldStyle->scrollPaddingEqual(style())) {
205 if (isDocumentElementRenderer()) {
206 LocalFrameView& frameView = view().frameView();
Local variable 'frameView' is uncounted and unsafe
207 frameView.updateScrollbarSteps();
208 } else if (CheckedPtr renderLayer = layer())
209 renderLayer->updateScrollbarSteps();
210 }
211
212 if (oldStyle && !oldStyle->scrollSnapDataEquivalent(style())) {
213 if (auto* scrollSnapBox = enclosingScrollableContainer())
214 scrollSnapBox->setNeedsLayout();
215 }
216}
217
218bool RenderLayerModelObject::applyCachedClipAndScrollPosition(RepaintRects&, const RenderLayerModelObject*, VisibleRectContext) const
219{
220 return false;
221}
222
223bool RenderLayerModelObject::shouldPlaceVerticalScrollbarOnLeft() const
224{
225// RTL Scrollbars require some system support, and this system support does not exist on certain versions of macOS. iOS uses a separate mechanism.
226#if PLATFORM(IOS_FAMILY)(defined WTF_PLATFORM_IOS_FAMILY && WTF_PLATFORM_IOS_FAMILY
)
227 return false;
228#else
229 switch (settings().userInterfaceDirectionPolicy()) {
230 case UserInterfaceDirectionPolicy::Content:
231 return style().shouldPlaceVerticalScrollbarOnLeft();
232 case UserInterfaceDirectionPolicy::System:
233 return settings().systemLayoutDirection() == TextDirection::RTL;
234 }
235 ASSERT_NOT_REACHED()((void)0);
236 return style().shouldPlaceVerticalScrollbarOnLeft();
237#endif
238}
239
240std::optional<LayoutRect> RenderLayerModelObject::cachedLayerClippedOverflowRect() const
241{
242 return hasLayer() ? layer()->cachedClippedOverflowRect() : std::nullopt;
243}
244
245bool RenderLayerModelObject::startAnimation(double timeOffset, const GraphicsLayerAnimation& animation, const BlendingKeyframes& keyframes)
246{
247 if (!layer() || !layer()->backing())
248 return false;
249 return layer()->backing()->startAnimation(timeOffset, animation, keyframes);
250}
251
252void RenderLayerModelObject::animationPaused(double timeOffset, const BlendingKeyframes& keyframes)
253{
254 if (!layer() || !layer()->backing())
255 return;
256 layer()->backing()->animationPaused(timeOffset, keyframes.acceleratedAnimationName());
257}
258
259void RenderLayerModelObject::animationFinished(const BlendingKeyframes& keyframes)
260{
261 if (!layer() || !layer()->backing())
262 return;
263 layer()->backing()->animationFinished(keyframes.acceleratedAnimationName());
264}
265
266void RenderLayerModelObject::transformRelatedPropertyDidChange()
267{
268 if (!layer() || !layer()->backing())
269 return;
270 layer()->backing()->transformRelatedPropertyDidChange();
271}
272
273void RenderLayerModelObject::suspendAnimations(MonotonicTime time)
274{
275 if (!layer() || !layer()->backing())
276 return;
277 layer()->backing()->suspendAnimations(time);
278}
279
280TransformationMatrix* RenderLayerModelObject::layerTransform() const
281{
282 if (hasLayer())
283 return layer()->transform();
284 return nullptr;
285}
286
287void RenderLayerModelObject::updateLayerTransform()
288{
289 if (auto* box = dynamicDowncast<RenderBox>(this); box && MotionPath::needsUpdateAfterContainingBlockLayout(style().offsetPath())) {
290 if (auto* containingBlock = this->containingBlock()) {
291 view().frameView().layoutContext().setBoxNeedsTransformUpdateAfterContainerLayout(*box, *containingBlock);
292 return;
293 }
294 }
295 // Transform-origin depends on box size, so we need to update the layer transform after layout.
296 if (hasLayer())
297 layer()->updateTransform();
298}
299
300bool RenderLayerModelObject::shouldPaintSVGRenderer(const PaintInfo& paintInfo, const OptionSet<PaintPhase> relevantPaintPhases) const
301{
302 if (paintInfo.context().paintingDisabled())
303 return false;
304
305 if (!relevantPaintPhases.isEmpty() && !relevantPaintPhases.contains(paintInfo.phase))
306 return false;
307
308 if (!paintInfo.shouldPaintWithinRoot(*this))
309 return false;
310
311 if (style().usedVisibility() == Visibility::Hidden || style().display() == Style::DisplayType::None)
312 return false;
313
314 return true;
315}
316
317auto RenderLayerModelObject::computeVisibleRectsInSVGContainer(const RepaintRects& rects, const RenderLayerModelObject* container, VisibleRectContext context) const -> std::optional<RepaintRects>
318{
319 ASSERT(is<RenderSVGModelObject>(this) || is<RenderSVGBlock>(this))((void)0);
320 ASSERT(!style().hasInFlowPosition())((void)0);
321 ASSERT(!view().frameView().layoutContext().isPaintOffsetCacheEnabled())((void)0);
322
323 if (container == this)
324 return rects;
325
326 bool containerIsSkipped;
327 auto* localContainer = this->container(container, containerIsSkipped);
328 if (!localContainer)
329 return rects;
330
331 ASSERT_UNUSED(containerIsSkipped, !containerIsSkipped)((void)containerIsSkipped);
332
333 auto adjustedRects = rects;
334
335 LayoutSize locationOffset;
336 if (CheckedPtr modelObject = dynamicDowncast<RenderSVGModelObject>(this))
337 locationOffset = modelObject->locationOffsetEquivalent();
338 else if (CheckedPtr svgBlock = dynamicDowncast<RenderSVGBlock>(this))
339 locationOffset = svgBlock->locationOffset();
340
341
342 // We are now in our parent container's coordinate space. Apply our transform to obtain a bounding box
343 // in the parent's coordinate space that encloses us.
344 if (hasLayer() && layer()->transform())
345 adjustedRects.transform(*layer()->transform());
346
347 adjustedRects.move(locationOffset);
348
349 if (localContainer->hasNonVisibleOverflow()) {
350 bool isEmpty = !downcast<RenderLayerModelObject>(*localContainer).applyCachedClipAndScrollPosition(adjustedRects, container, context);
351 if (isEmpty) {
352 if (context.options.contains(VisibleRectContext::Option::UseEdgeInclusiveIntersection))
353 return std::nullopt;
354 return adjustedRects;
355 }
356 }
357
358 return localContainer->computeVisibleRectsInContainer(adjustedRects, container, context);
359}
360
361void RenderLayerModelObject::mapLocalToSVGContainer(const RenderLayerModelObject* ancestorContainer, TransformState& transformState, OptionSet<MapCoordinatesMode> mode, bool* wasFixed) const
362{
363 ASSERT(is<RenderSVGModelObject>(this) || is<RenderSVGBlock>(this))((void)0);
364 ASSERT(style().position() == PositionType::Static)((void)0);
365
366 if (ancestorContainer == this)
367 return;
368
369 ASSERT(!view().frameView().layoutContext().isPaintOffsetCacheEnabled())((void)0);
370
371 bool ancestorSkipped;
372 auto* container = this->container(ancestorContainer, ancestorSkipped);
373 if (!container)
374 return;
375
376 ASSERT_UNUSED(ancestorSkipped, !ancestorSkipped)((void)ancestorSkipped);
377
378 // If this box has a transform, it acts as a fixed position container for fixed descendants,
379 // and may itself also be fixed position. So propagate 'fixed' up only if this box is fixed position.
380 if (isTransformed())
381 mode.remove(IsFixed);
382
383 if (wasFixed)
384 *wasFixed = mode.contains(IsFixed);
385
386 auto containerOffset = offsetFromContainer(*container, LayoutPoint(transformState.mappedPoint()));
387
388 pushOntoTransformState(transformState, mode, nullptr, container, containerOffset, false);
389
390 mode.remove(ApplyContainerFlip);
391
392 container->mapLocalToContainer(ancestorContainer, transformState, mode, wasFixed);
393}
394
395void RenderLayerModelObject::applySVGTransform(TransformationMatrix& transform, const SVGGraphicsElement& graphicsElement, const RenderStyle& style, const FloatRect& boundingBox, const std::optional<AffineTransform>& preApplySVGTransformMatrix, const std::optional<AffineTransform>& postApplySVGTransformMatrix, OptionSet<Style::TransformResolverOption> options) const
396{
397 auto svgTransform = graphicsElement.transform().concatenate();
398 auto* supplementalTransform = graphicsElement.supplementalTransform(); // SMIL <animateMotion>
399
400 // This check does not use style.hasTransformRelatedProperty() on purpose -- we only want to know if either the 'transform' property, an
401 // offset path, or the individual transform operations are set (perspective / transform-style: preserve-3d are not relevant here).
402 bool hasCSSTransform = !style.transform().isNone()
403 || !style.offsetPath().isNone()
404 || !style.rotate().isNone()
405 || !style.translate().isNone()
406 || !style.scale().isNone();
407 bool hasSVGTransform = !svgTransform.isIdentity() || preApplySVGTransformMatrix || postApplySVGTransformMatrix || supplementalTransform;
408
409 // Common case: 'viewBox' set on outermost <svg> element -> 'preApplySVGTransformMatrix'
410 // passed by RenderSVGViewportContainer::applyTransform(), the anonymous single child
411 // of RenderSVGRoot, that wraps all direct children from <svg> as present in DOM. All
412 // other transformations are unset (no need to compute transform-origin, etc. in that case).
413 if (!hasCSSTransform && !hasSVGTransform)
414 return;
415
416 Style::TransformResolver transformResolver { transform, style };
417
418 auto affectedByTransformOrigin = [&]() {
419 if (preApplySVGTransformMatrix && !preApplySVGTransformMatrix->isIdentityOrTranslation())
420 return true;
421 if (postApplySVGTransformMatrix && !postApplySVGTransformMatrix->isIdentityOrTranslation())
422 return true;
423 if (supplementalTransform && !supplementalTransform->isIdentityOrTranslation())
424 return true;
425 if (hasCSSTransform)
426 return transformResolver.affectedByTransformOrigin();
427 return !svgTransform.isIdentityOrTranslation();
428 };
429
430 FloatPoint3D originTranslate;
431 if (options.contains(Style::TransformResolverOption::TransformOrigin) && affectedByTransformOrigin())
432 originTranslate = transformResolver.computeTransformOrigin(boundingBox);
433
434 transformResolver.applyTransformOrigin(originTranslate);
435
436 if (supplementalTransform)
437 transform.multiplyAffineTransform(*supplementalTransform);
438
439 if (preApplySVGTransformMatrix)
440 transform.multiplyAffineTransform(preApplySVGTransformMatrix.value());
441
442 // CSS transforms take precedence over SVG transforms.
443 if (hasCSSTransform)
444 transformResolver.applyCSSTransform(TransformOperationData(boundingBox, this), options);
445 else if (!svgTransform.isIdentity())
446 transform.multiplyAffineTransform(svgTransform);
447
448 if (postApplySVGTransformMatrix)
449 transform.multiplyAffineTransform(postApplySVGTransformMatrix.value());
450
451 transformResolver.unapplyTransformOrigin(originTranslate);
452}
453
454void RenderLayerModelObject::updateHasSVGTransformFlags()
455{
456 ASSERT(document().settings().layerBasedSVGEngineEnabled())((void)0);
457
458 bool hasSVGTransform = needsHasSVGTransformFlags();
459 setHasTransformRelatedProperty(hasSVGTransform || style().hasTransformRelatedProperty());
460 setHasSVGTransform(hasSVGTransform);
461}
462
463RenderSVGResourceClipper* RenderLayerModelObject::svgClipperResourceFromStyle() const
464{
465 if (!document().settings().layerBasedSVGEngineEnabled())
466 return nullptr;
467
468 return WTF::switchOn(style().clipPath(),
469 [&](const Style::ReferencePath& clipPath) -> RenderSVGResourceClipper* {
470 if (RefPtr referencedClipPathElement = ReferencedSVGResources::referencedClipPathElement(treeScopeForSVGReferences(), clipPath)) {
471 if (auto* referencedClipperRenderer = dynamicDowncast<RenderSVGResourceClipper>(referencedClipPathElement->renderer()))
472 return referencedClipperRenderer;
473 }
474
475 if (RefPtr svgElement = dynamicDowncast<SVGElement>(this->element()))
476 document().addPendingSVGResource(clipPath.fragment(), *svgElement);
477
478 return nullptr;
479
480 },
481 [&](const auto&) -> RenderSVGResourceClipper* {
482 return nullptr;
483 }
484 );
485}
486
487RenderSVGResourceFilter* RenderLayerModelObject::svgFilterResourceFromStyle() const
488{
489 if (!document().settings().layerBasedSVGEngineEnabled())
490 return nullptr;
491
492 if (style().filter().size() != 1)
493 return nullptr;
494
495 return WTF::switchOn(style().filter().first(),
496 [&](const Style::FilterReference& filterReference) -> RenderSVGResourceFilter* {
497 if (RefPtr referencedFilterElement = ReferencedSVGResources::referencedFilterElement(treeScopeForSVGReferences(), filterReference)) {
498 if (auto* referencedFilterRenderer = dynamicDowncast<RenderSVGResourceFilter>(referencedFilterElement->renderer()))
499 return referencedFilterRenderer;
500 }
501
502 if (RefPtr svgElement = dynamicDowncast<SVGElement>(this->element()))
503 document().addPendingSVGResource(filterReference.cachedFragment, *svgElement);
504
505 return nullptr;
506 },
507 []<CSSValueID C, typename T>(const FunctionNotation<C, T>&) -> RenderSVGResourceFilter* {
508 return nullptr;
509 }
510 );
511}
512
513RenderSVGResourceMasker* RenderLayerModelObject::svgMaskerResourceFromStyle() const
514{
515 if (!document().settings().layerBasedSVGEngineEnabled())
516 return nullptr;
517
518 RefPtr maskImage = style().maskLayers().usedFirst().image().tryStyleImage();
519 if (!maskImage)
520 return nullptr;
521
522 auto resourceID = SVGURIReference::fragmentIdentifierFromIRIString(maskImage->url(), protect(document()));
523
524 if (RefPtr referencedMaskElement = ReferencedSVGResources::referencedMaskElement(treeScopeForSVGReferences(), *maskImage)) {
525 if (auto* referencedMaskerRenderer = dynamicDowncast<RenderSVGResourceMasker>(referencedMaskElement->renderer()))
526 return referencedMaskerRenderer;
527 }
528
529 if (RefPtr element = this->element())
530 document().addPendingSVGResource(resourceID, downcast<SVGElement>(*element));
531
532 return nullptr;
533}
534
535RenderSVGResourceMarker* RenderLayerModelObject::svgMarkerStartResourceFromStyle() const
536{
537 return svgMarkerResourceFromStyle(style().markerStart());
538}
539
540RenderSVGResourceMarker* RenderLayerModelObject::svgMarkerMidResourceFromStyle() const
541{
542 return svgMarkerResourceFromStyle(style().markerMid());
543}
544
545RenderSVGResourceMarker* RenderLayerModelObject::svgMarkerEndResourceFromStyle() const
546{
547 return svgMarkerResourceFromStyle(style().markerEnd());
548}
549
550RenderSVGResourceMarker* RenderLayerModelObject::svgMarkerResourceFromStyle(const Style::SVGMarkerResource& markerResource) const
551{
552 if (!document().settings().layerBasedSVGEngineEnabled())
553 return nullptr;
554
555 auto markerResourceURL = markerResource.tryURL();
556 if (!markerResourceURL)
557 return nullptr;
558
559 if (RefPtr referencedMarkerElement = ReferencedSVGResources::referencedMarkerElement(treeScopeForSVGReferences(), *markerResourceURL)) {
560 if (auto* referencedMarkerRenderer = dynamicDowncast<RenderSVGResourceMarker>(referencedMarkerElement->renderer()))
561 return referencedMarkerRenderer;
562 }
563
564 if (RefPtr element = dynamicDowncast<SVGElement>(this->element())) {
565 auto resourceID = SVGURIReference::fragmentIdentifierFromIRIString(markerResourceURL->resolved.string(), document());
566 document().addPendingSVGResource(resourceID, *element);
567 }
568
569 return nullptr;
570}
571
572RenderSVGResourcePaintServer* RenderLayerModelObject::svgFillPaintServerResourceFromStyle(const RenderStyle& style) const
573{
574 if (!document().settings().layerBasedSVGEngineEnabled())
575 return nullptr;
576
577 auto fillURL = style.fill().tryAnyURL();
578 if (!fillURL)
579 return nullptr;
580
581 if (RefPtr referencedElement = ReferencedSVGResources::referencedPaintServerElement(treeScopeForSVGReferences(), *fillURL)) {
582 if (auto* referencedPaintServerRenderer = dynamicDowncast<RenderSVGResourcePaintServer>(referencedElement->renderer()))
583 return referencedPaintServerRenderer;
584 }
585
586 if (RefPtr element = this->element())
587 document().addPendingSVGResource(AtomString(fillURL->resolved.string()), downcast<SVGElement>(*element));
588
589 return nullptr;
590}
591
592RenderSVGResourcePaintServer* RenderLayerModelObject::svgStrokePaintServerResourceFromStyle(const RenderStyle& style) const
593{
594 if (!document().settings().layerBasedSVGEngineEnabled())
595 return nullptr;
596
597 auto strokeURL = style.stroke().tryAnyURL();
598 if (!strokeURL)
599 return nullptr;
600
601 if (RefPtr referencedElement = ReferencedSVGResources::referencedPaintServerElement(treeScopeForSVGReferences(), *strokeURL)) {
602 if (auto* referencedPaintServerRenderer = dynamicDowncast<RenderSVGResourcePaintServer>(referencedElement->renderer()))
603 return referencedPaintServerRenderer;
604 }
605
606 if (RefPtr element = this->element())
607 document().addPendingSVGResource(AtomString(strokeURL->resolved.string()), downcast<SVGElement>(*element));
608
609 return nullptr;
610}
611
612LegacyRenderSVGResourceClipper* RenderLayerModelObject::legacySVGClipperResourceFromStyle() const
613{
614 return WTF::switchOn(style().clipPath(),
615 [&](const Style::ReferencePath& clipPath) -> LegacyRenderSVGResourceClipper* {
616 return ReferencedSVGResources::referencedClipperRenderer(treeScopeForSVGReferences(), clipPath);
617 },
618 [&](const auto&) -> LegacyRenderSVGResourceClipper* {
619 return nullptr;
620 }
621 );
622}
623
624bool RenderLayerModelObject::pointInSVGClippingArea(const FloatPoint& point) const
625{
626 auto clipPathReferenceBox = [&](CSSBoxType boxType) -> FloatRect {
627 FloatRect referenceBox;
628 switch (boxType) {
629 case CSSBoxType::BorderBox:
630 case CSSBoxType::MarginBox:
631 case CSSBoxType::StrokeBox:
632 case CSSBoxType::BoxMissing:
633 // FIXME: strokeBoundingBox() takes dasharray into account but shouldn't.
634 referenceBox = strokeBoundingBox();
635 break;
636 case CSSBoxType::ViewBox:
637 if (element()) {
638 // FIXME: [LBSE] This should not need to use SVGLengthContext, RenderSVGRoot holds that information.
639 auto viewportSize = SVGLengthContext(downcast<SVGElement>(element())).viewportSize();
640 if (viewportSize)
641 referenceBox.setSize(*viewportSize);
642 break;
643 }
644 [[fallthrough]];
645 case CSSBoxType::ContentBox:
646 case CSSBoxType::FillBox:
647 case CSSBoxType::PaddingBox:
648 referenceBox = objectBoundingBox();
649 break;
650 }
651 return referenceBox;
652 };
653
654 return WTF::switchOn(style().clipPath(),
655 [&](const Style::BasicShapePath& clipPath) {
656 auto referenceBox = clipPathReferenceBox(clipPath.referenceBox());
657 if (!referenceBox.contains(point))
658 return false;
659 return Style::path(clipPath.shape(), referenceBox, style().usedZoomForLength()).contains(point, Style::windRule(clipPath.shape()));
660 },
661 [&](const Style::BoxPath& clipPath) {
662 auto referenceBox = clipPathReferenceBox(clipPath.referenceBox());
663 if (!referenceBox.contains(point))
664 return false;
665 return FloatRoundedRect { referenceBox }.path().contains(point);
666 },
667 [&](const auto&) {
668 if (auto* referencedClipperRenderer = svgClipperResourceFromStyle())
669 return referencedClipperRenderer->hitTestClipContent(objectBoundingBox(), LayoutPoint(point));
670 return true;
671 }
672 );
673}
674
675void RenderLayerModelObject::repaintOrRelayoutAfterSVGTransformChange()
676{
677 ASSERT(document().settings().layerBasedSVGEngineEnabled())((void)0);
678
679 updateHasSVGTransformFlags();
680
681 // LBSE shares the text rendering code with the legacy SVG engine, largely unmodified.
682 // At present text layout depends on transformations ('screen font scaling factor' is used to
683 // determine which font to use for layout / painting). Therefore if the x/y scaling factors
684 // of the transformation matrix changes due to the transform update, we have to recompute the text metrics
685 // of all RenderSVGText descendants of the renderer in the ancestor chain, that will receive the transform
686 // update.
687 //
688 // There is no intrinsic reason for that, besides historical ones. If we decouple
689 // the 'font size screen scaling factor' from layout and only use it during painting
690 // we can optimize transformations for text, simply by avoid the need for layout.
691 auto previousTransform = layerTransform() ? layerTransform()->toAffineTransform() : identity;
692 updateLayerTransform();
693
694 auto currentTransform = layerTransform() ? layerTransform()->toAffineTransform() : identity;
695
696 // We have to force a stacking context if we did not have a transform before. Normally
697 // RenderLayer::styleChanged does this for us but repaintOrRelayoutAfterSVGTransformChange
698 // does not end up calling it.
699 if (previousTransform.isIdentity() && !currentTransform.isIdentity()) {
700 if (hasLayer())
701 layer()->forceStackingContextIfNeeded();
702 }
703
704 auto determineIfLayerTransformChangeModifiesScale = [&]() -> bool {
705 if (previousTransform == currentTransform)
706 return false;
707
708 // Only if the effective x/y scale changes, a re-layout is necessary, due to changed on-screen scaling factors.
709 // The next RenderSVGText layout will see a different 'screen font scaling factor', different text metrics etc.
710 if (!WTF::areEssentiallyEqual(previousTransform.xScale(), currentTransform.xScale()))
711 return true;
712
713 if (!WTF::areEssentiallyEqual(previousTransform.yScale(), currentTransform.yScale()))
714 return true;
715
716 return false;
717 }();
718
719 if (determineIfLayerTransformChangeModifiesScale) {
720 if (auto* textAffectedByTransformChange = dynamicDowncast<RenderSVGText>(this)) {
721 // Mark text metrics for update, and only trigger a relayout and not an explicit repaint.
722 textAffectedByTransformChange->setNeedsTextMetricsUpdate();
723 textAffectedByTransformChange->textElement().updateSVGRendererForElementChange();
724 return;
725 }
726
727 // Recursively mark text metrics for update in all descendant RenderSVGText objects.
728 bool markedAny = false;
729 for (auto& textDescendantAffectedByTransformChange : descendantsOfType<RenderSVGText>(*this)) {
730 textDescendantAffectedByTransformChange.setNeedsTextMetricsUpdate();
731 textDescendantAffectedByTransformChange.textElement().updateSVGRendererForElementChange();
732 if (!markedAny)
733 markedAny = true;
734 }
735
736 // If we marked a text descendant for relayout, we are expecting a relayout ourselves, so no reason for an explicit repaint().
737 if (markedAny)
738 return;
739 }
740
741 // Instead of performing a full-fledged layout (issuing repaints), just recompute the layer transform, and repaint.
742 // In LBSE transformations do not affect the layout (except for text, where it still does!) -- SVG follows closely the CSS/HTML route, to avoid costly layouts.
743 repaintRendererOrClientsOfReferencedSVGResources();
744}
745
746void RenderLayerModelObject::paintSVGClippingMask(PaintInfo& paintInfo, const FloatRect& objectBoundingBox) const
747{
748 ASSERT(paintInfo.phase == PaintPhase::ClippingMask)((void)0);
749 auto& context = paintInfo.context();
750 if (!paintInfo.shouldPaintWithinRoot(*this) || style().usedVisibility() != Visibility::Visible || context.paintingDisabled())
751 return;
752
753 ASSERT(document().settings().layerBasedSVGEngineEnabled())((void)0);
754 if (auto* referencedClipperRenderer = svgClipperResourceFromStyle())
755 referencedClipperRenderer->applyMaskClipping(paintInfo, *this, objectBoundingBox);
756}
757
758void RenderLayerModelObject::paintSVGMask(PaintInfo& paintInfo, const LayoutPoint& adjustedPaintOffset) const
759{
760 ASSERT(paintInfo.phase == PaintPhase::Mask)((void)0);
761 auto& context = paintInfo.context();
762 if (!paintInfo.shouldPaintWithinRoot(*this) || context.paintingDisabled())
763 return;
764
765 ASSERT(isSVGLayerAwareRenderer())((void)0);
766 if (auto* referencedMaskerRenderer = svgMaskerResourceFromStyle())
767 referencedMaskerRenderer->applyMask(paintInfo, *this, adjustedPaintOffset);
768}
769
770void RenderLayerModelObject::paintSVGEventRegion(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
771{
772 ASSERT(paintInfo.phase == PaintPhase::EventRegion)((void)0);
773 if (style().usedVisibility() == Visibility::Hidden || objectBoundingBox().isEmpty())
774 return;
775
776 auto adjustedPaintOffset = paintOffset + currentSVGLayoutLocation();
777 auto coordinateSystemOriginTranslation = adjustedPaintOffset - nominalSVGLayoutLocation();
778 auto eventRegionBounds = strokeBoundingBox();
779 eventRegionBounds.move(coordinateSystemOriginTranslation);
780 paintInfo.eventRegionContext()->unite(FloatRoundedRect(eventRegionBounds), *this, style(), false);
781}
782
783#if ASSERT_ENABLED0
784bool RenderLayerModelObject::layerAccessPreventedSlow() const
785{
786 return view().frameView().layerAccessPrevented();
787}
788#endif
789
790bool rendererNeedsPixelSnapping(const RenderLayerModelObject& renderer)
791{
792 if (renderer.document().settings().layerBasedSVGEngineEnabled() && renderer.isSVGLayerAwareRenderer() && !renderer.isRenderSVGRoot())
793 return false;
794 return true;
795}
796
797FloatRect snapRectToDevicePixelsIfNeeded(const LayoutRect& rect, const RenderLayerModelObject& renderer)
798{
799 if (!rendererNeedsPixelSnapping(renderer))
800 return rect;
801 return snapRectToDevicePixels(rect, renderer.document().deviceScaleFactor());
802}
803
804FloatRect snapRectToDevicePixelsIfNeeded(const FloatRect& rect, const RenderLayerModelObject& renderer)
805{
806 if (!rendererNeedsPixelSnapping(renderer))
807 return rect;
808 return snapRectToDevicePixels(LayoutRect { rect }, renderer.document().deviceScaleFactor());
809}
810
811} // namespace WebCore
812