Bug Summary

File:Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/Source/WebCore/rendering/RenderVideo.cpp
Warning:line 264, column 68
Call argument is uncounted and unsafe

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple arm64-apple-ios26.2.0-simulator -O3 -Wundef-prefix=TARGET_OS_ -Werror=undef-prefix -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -Werror=implicit-function-declaration -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name UnifiedSource419.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=26.2 -fdepfile-entry=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/SDKSettings.json -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/Apple-iOS-26-Safer-CPP-Checks-EWS/build/Source/WebCore -target-linker-version 1230.1 -fcoverage-compilation-dir=/Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/Source/WebCore -resource-dir /Users/buildbot/Library/Developer/Toolchains/swift-webkit.xctoolchain/usr/lib/clang/21 -dependency-file /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/scan-build-output/StaticAnalyzer/WebCore/WebCore/normal/arm64/UnifiedSource419.d -skip-unused-modulemap-deps -MT dependencies -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk -iquote /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/WebCore-generated-files.hmap -iquote /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/WebCore-project-headers.hmap -isystem /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/Source/WebCore/PAL/ThirdParty/dav1d/include -isystem /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/SDKAdditions/usr/include -iframework /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/SDKAdditions/System/Library/Frameworks -iframework /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitLibraries/SDKs/iphonesimulator26.0-additions.sdk/System/Library/PrivateFrameworks -iframework /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/System/Library/Frameworks -include-pch /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/PrecompiledHeaders/SharedPrecompiledHeaders/11721353671419897710/WebCorePrefix.h.gch -D _LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE -D NDEBUG -D BUILDING_WEBKIT -D GL_SILENCE_DEPRECATION=1 -D GLES_SILENCE_DEPRECATION=1 -D __clang_analyzer__ -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/WebCore-own-target-headers.hmap -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/WebCore-all-target-headers.hmap -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/include -I PAL -I ForwardingHeaders -I /usr/include/libxslt -I /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/include/libxml2 -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/DerivedSources/WebCore -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/usr/local/include -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/usr/local/include/WebKitAdditions -I /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/local/include/WebKitAdditions -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/usr/local/include -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitLibraries/SDKs/iphonesimulator26.0-additions.sdk/usr/local/include -I /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/local/include -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/usr/local/include/webrtc -I /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/local/include/webrtc -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/usr/local/include/webm -I /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/local/include/webm -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/PAL.build/PAL.build/DerivedSources -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/PAL.build/Release-iphonesimulator/PAL.build/DerivedSources -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/Source/WebCore -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/DerivedSources-normal/arm64 -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/DerivedSources/arm64 -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/DerivedSources -F/Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator -F/Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator -I/usr/local/include -stdlib=libc++ -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/include/c++/v1 -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/local/include -internal-isystem /Users/buildbot/Library/Developer/Toolchains/swift-webkit.xctoolchain/usr/lib/clang/21/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/include -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/System/Library/Frameworks -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/System/Library/SubFrameworks -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.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/Apple-iOS-26-Safer-CPP-Checks-EWS/build/scan-build-output/StaticAnalyzer/WebCore/WebCore/normal/arm64/UnifiedSource419.plist -x c++ /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/DerivedSources/WebCore/unified-sources/UnifiedSource419.cpp
1/*
2 * Copyright (C) 2007-2025 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27
28#if ENABLE(VIDEO)(defined 1 && 1)
29#include "RenderVideo.h"
30
31#include "Document.h"
32#include "DocumentFullscreen.h"
33#include "GraphicsContext.h"
34#include "HTMLNames.h"
35#include "HTMLVideoElement.h"
36#include "LayoutIntegrationLineLayout.h"
37#include "LocalFrame.h"
38#include "LocalFrameView.h"
39#include "MediaPlayer.h"
40#include "MediaPlayerEnums.h"
41#include "Page.h"
42#include "PaintInfo.h"
43#include "RenderBoxInlines.h"
44#include "RenderElementStyleInlines.h"
45#include "RenderElementInlines.h"
46#include "RenderMediaInlines.h"
47#include "RenderObjectInlines.h"
48#include "RenderVideoInlines.h"
49#include "RenderView.h"
50#include <wtf/StackStats.h>
51#include <wtf/TZoneMallocInlines.h>
52
53namespace WebCore {
54
55using namespace HTMLNames;
56
57WTF_MAKE_TZONE_ALLOCATED_IMPL(RenderVideo)::bmalloc::api::HeapRef RenderVideo::s_heapRef; const TZoneSpecification
RenderVideo::s_heapSpec = { &RenderVideo::s_heapRef, TZoneSpecification
::encodeSize<RenderVideo>(), TZoneSpecification::encodeAlignment
<RenderVideo>(), TZoneSpecification::encodeCategory<
RenderVideo>(), ::bmalloc::api::compactAllocationMode<RenderVideo
>(), TZoneSpecification::encodeDescriptor<RenderVideo>
(), }; void* RenderVideo::operatorNewSlow(size_t size) { if constexpr
(::bmalloc::api::compactAllocationMode<RenderVideo>() ==
CompactAllocationMode::Compact) return ::bmalloc::api::tzoneAllocateCompactSlow
(size, s_heapSpec); return ::bmalloc::api::tzoneAllocateNonCompactSlow
(size, s_heapSpec); } using __makeBtzoneMallocedInlineMacroSemicolonifier
__attribute__((unused)) = int
;
58
59RenderVideo::RenderVideo(HTMLVideoElement& element, RenderStyle&& style)
60 : RenderMedia(Type::Video, element, WTF::move(style))
61{
62 setIntrinsicSize(calculateIntrinsicSize());
63 ASSERT(isRenderVideo())((void)0);
64}
65
66// Do not add any code in below destructor. Add it to willBeDestroyed() instead.
67RenderVideo::~RenderVideo() = default;
68
69void RenderVideo::willBeDestroyed()
70{
71 visibleInViewportStateChanged();
72
73 if (RefPtr player = protect(videoElement())->player())
74 player->renderVideoWillBeDestroyed();
75
76 RenderMedia::willBeDestroyed();
77}
78
79void RenderVideo::visibleInViewportStateChanged()
80{
81 protect(videoElement())->isVisibleInViewportChanged();
82}
83
84IntSize RenderVideo::defaultSize()
85{
86 // These values are specified in the spec.
87 static const int cDefaultWidth = 300;
88 static const int cDefaultHeight = 150;
89
90 return IntSize(cDefaultWidth, cDefaultHeight);
91}
92
93void RenderVideo::intrinsicSizeChanged()
94{
95 if (protect(videoElement())->shouldDisplayPosterImage())
96 RenderMedia::intrinsicSizeChanged();
97 if (updateIntrinsicSize())
98 invalidateLineLayout();
99}
100
101bool RenderVideo::updateIntrinsicSize()
102{
103 LayoutSize size = calculateIntrinsicSize();
104 // Never set the element size to zero when in a media document.
105 if (size.isEmpty() && document().isMediaDocument())
106 return false;
107
108 // Treat the media player's natural size as visually non-empty.
109 if (protect(videoElement())->readyState() >= HTMLMediaElementEnums::HAVE_METADATA)
110 incrementVisuallyNonEmptyPixelCountIfNeeded(roundedIntSize(size));
111
112 if (size == intrinsicSize())
113 return false;
114
115 setIntrinsicSize(size);
116 setNeedsPreferredWidthsUpdate();
117 setNeedsLayout();
118 return true;
119}
120
121LayoutSize RenderVideo::calculateIntrinsicSizeInternal()
122{
123 // This implements the intrinsic width/height calculation from:
124 // https://html.spec.whatwg.org/#the-video-element:dimension-attributes:~:text=The%20intrinsic%20width%20of%20a%20video%20element's%20playback%20area
125 // If the video playback area is currently represented by the poster image,
126 // the intrinsic width and height are that of the poster image.
127 Ref videoElement = this->videoElement();
128 RefPtr player = videoElement->player();
129
130 // Assume the intrinsic width is that of the video.
131 if (player && videoElement->readyState() >= HTMLVideoElement::HAVE_METADATA) {
132 LayoutSize size(player->naturalSize());
133 if (!size.isEmpty())
134 return size;
135 }
136
137 // <video> in standalone media documents should not use the default 300x150
138 // size since they also have audio-only files. By setting the intrinsic
139 // size to 300x1 the video will resize itself in these cases, and audio will
140 // have the correct height (it needs to be > 0 for controls to render properly).
141 if (videoElement->document().isMediaDocument())
142 return LayoutSize(defaultSize().width(), 1);
143
144 return defaultSize();
145}
146
147LayoutSize RenderVideo::calculateIntrinsicSize()
148{
149 if (shouldApplySizeContainment())
150 return intrinsicSize();
151
152 // Return cached poster size directly if we're using it, since it's already scaled.
153 // Determine what we should display: poster or video.
154 // If the show-poster-flag is set (or there is no video frame to display) AND
155 // there is a poster image, display the poster.
156 Ref videoElement = this->videoElement();
157 RefPtr player = videoElement->player();
158 bool shouldUsePoster = (videoElement->shouldDisplayPosterImage() || !player || !player->hasAvailableVideoFrame()) && hasPosterFrameSize();
159
160 if (shouldUsePoster) {
161 auto cachedSize = m_cachedImageSize;
162 if (shouldApplyInlineSizeContainment()) {
163 if (isHorizontalWritingMode())
164 cachedSize.setWidth(intrinsicSize().width());
165 else
166 cachedSize.setHeight(intrinsicSize().height());
167 }
168 return cachedSize;
169 }
170
171 auto calculatedIntrinsicSize = calculateIntrinsicSizeInternal();
172 calculatedIntrinsicSize.scale(style().usedZoom());
173
174 if (shouldApplyInlineSizeContainment()) {
175 if (isHorizontalWritingMode())
176 calculatedIntrinsicSize.setWidth(intrinsicSize().width());
177 else
178 calculatedIntrinsicSize.setHeight(intrinsicSize().height());
179 }
180 return calculatedIntrinsicSize;
181}
182
183void RenderVideo::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
184{
185 RenderMedia::imageChanged(newImage, rect);
186
187 // Cache the image intrinsic size so we can continue to use it to draw the image correctly
188 // even if we know the video intrinsic size but aren't able to draw video frames yet
189 // (we don't want to scale the poster to the video size without keeping aspect ratio).
190 if (protect(videoElement())->shouldDisplayPosterImage())
191 m_cachedImageSize = intrinsicSize();
192
193 // The intrinsic size is now that of the image, but in case we already had the
194 // intrinsic size of the video we call this here to restore the video size.
195 if (updateIntrinsicSize() || selfNeedsLayout())
196 invalidateLineLayout();
197}
198
199IntRect RenderVideo::videoBox() const
200{
201 Ref videoElement = this->videoElement();
202 RefPtr mediaPlayer = videoElement->player();
203 if (mediaPlayer && mediaPlayer->shouldIgnoreIntrinsicSize())
204 return snappedIntRect(contentBoxRect());
205
206 LayoutSize intrinsicSize = this->intrinsicSize();
207
208 if (videoElement->shouldDisplayPosterImage())
209 intrinsicSize = m_cachedImageSize;
210
211 return snappedIntRect(replacedContentRect(intrinsicSize));
212}
213
214IntRect RenderVideo::videoBoxInRootView() const
215{
216 RefPtr view = document().view();
217 if (!view)
218 return { };
219
220 auto videoBox = this->videoBox();
221 videoBox.moveBy(absoluteBoundingBoxRect().location());
222 return view->contentsToRootView(videoBox);
223}
224
225bool RenderVideo::shouldDisplayVideo() const
226{
227 return !protect(videoElement())->shouldDisplayPosterImage();
228}
229
230bool RenderVideo::failedToLoadPosterImage() const
231{
232 return protect(imageResource())->errorOccurred();
233}
234
235void RenderVideo::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
236{
237 ASSERT(!isSkippedContentRoot(*this))((void)0);
238
239 Ref videoElement = this->videoElement();
240 Ref page = this->page();
241 RefPtr mediaPlayer = videoElement->player();
242 bool displayingPoster = videoElement->shouldDisplayPosterImage();
243
244 if (!displayingPoster && !mediaPlayer) {
245 if (paintInfo.phase == PaintPhase::Foreground)
246 page->addRelevantUnpaintedObject(*this, visualOverflowRect());
247 return;
248 }
249
250 LayoutRect videoBoxRect = videoBox();
251 if (videoBoxRect.isEmpty()) {
252 if (paintInfo.phase == PaintPhase::Foreground)
253 page->addRelevantUnpaintedObject(*this, visualOverflowRect());
254 return;
255 }
256
257 auto rect = videoBoxRect;
258 rect.moveBy(paintOffset);
259 GraphicsContext& context = paintInfo.context();
260
261 if (paintInfo.phase == PaintPhase::Foreground) {
262 page->addRelevantRepaintedObject(*this, rect);
263 if (displayingPoster && !context.paintingDisabled())
264 protect(document())->didPaintImage(videoElement.get(), cachedImage(), videoBoxRect);
Call argument is uncounted and unsafe
265 }
266
267 LayoutRect contentRect = contentBoxRect();
268 contentRect.moveBy(paintOffset);
269
270 if (context.detectingContentfulPaint()) {
271 context.setContentfulPaintDetected();
272 return;
273 }
274
275 bool clip = !contentRect.contains(rect);
276 GraphicsContextStateSaver stateSaver(context, clip);
277 if (clip)
278 context.clip(contentRect);
279
280 if (displayingPoster) {
281 paintIntoRect(paintInfo, rect);
282 return;
283 }
284
285 if (!mediaPlayer)
286 return;
287
288 // Painting contents during fullscreen playback causes stutters on iOS when the device is rotated.
289 // https://bugs.webkit.org/show_bug.cgi?id=142097
290 if (videoElement->supportsAcceleratedRendering() && videoElement->isFullscreen())
291 return;
292
293 // Avoid unnecessary paints by skipping software painting if
294 // the renderer is accelerated, and the paint operation does
295 // not flatten compositing layers and is not snapshotting.
296 if (hasAcceleratedCompositing()
297 && videoElement->supportsAcceleratedRendering()
298 && !paintInfo.paintBehavior.contains(PaintBehavior::FlattenCompositingLayers)
299 && !paintInfo.paintBehavior.contains(PaintBehavior::Snapshotting))
300 return;
301
302 videoElement->paint(context, rect);
303}
304
305void RenderVideo::layout()
306{
307 StackStats::LayoutCheckPoint layoutCheckPoint;
308 updateIntrinsicSize();
309 RenderMedia::layout();
310 updatePlayer();
311}
312
313void RenderVideo::styleDidChange(Style::Difference difference, const RenderStyle* oldStyle)
314{
315 RenderMedia::styleDidChange(difference, oldStyle);
316 if (!oldStyle || style().objectFit() != oldStyle->objectFit())
317 setNeedsLayout();
318}
319
320HTMLVideoElement& NODELETE[[clang::annotate_type("webkit.nodelete")]] RenderVideo::videoElement() const
321{
322 return downcast<HTMLVideoElement>(RenderMedia::mediaElement());
323}
324
325void RenderVideo::updateFromElement()
326{
327 RenderMedia::updateFromElement();
328 if (updatePlayer())
329 invalidateLineLayout();
330}
331
332bool RenderVideo::updatePlayer()
333{
334 if (renderTreeBeingDestroyed())
335 return false;
336
337 auto intrinsicSizeChanged = updateIntrinsicSize();
338 ASSERT(!intrinsicSizeChanged || !view().frameView().layoutContext().isInRenderTreeLayout())((void)0);
339
340 Ref videoElement = this->videoElement();
341 RefPtr mediaPlayer = videoElement->player();
342 if (!mediaPlayer)
343 return intrinsicSizeChanged;
344
345 if (videoElement->inActiveDocument())
346 contentChanged(ContentChangeType::Video);
347
348 videoElement->updateMediaPlayer(videoBox().size(), style().objectFit() != ObjectFit::Fill);
349 return intrinsicSizeChanged;
350}
351
352LayoutUnit RenderVideo::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const
353{
354 return computeReplacedLogicalWidthRespectingMinMaxWidth(RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred), shouldComputePreferred);
355}
356
357LayoutUnit RenderVideo::minimumReplacedHeight() const
358{
359 return RenderReplaced::minimumReplacedHeight();
360}
361
362bool RenderVideo::supportsAcceleratedRendering() const
363{
364 return protect(videoElement())->supportsAcceleratedRendering();
365}
366
367void RenderVideo::acceleratedRenderingStateChanged()
368{
369 protect(videoElement())->acceleratedRenderingStateChanged();
370}
371
372bool RenderVideo::requiresImmediateCompositing() const
373{
374 RefPtr player = protect(videoElement())->player();
375 return player && player->requiresImmediateCompositing();
376}
377
378bool RenderVideo::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const
379{
380 Ref videoElement = this->videoElement();
381 if (videoElement->shouldDisplayPosterImage())
382 return RenderImage::foregroundIsKnownToBeOpaqueInRect(localRect, maxDepthToTest);
383
384 if (!videoBox().contains(enclosingIntRect(localRect)))
385 return false;
386
387 if (RefPtr player = videoElement->player())
388 return player->hasAvailableVideoFrame();
389
390 return false;
391}
392
393bool RenderVideo::hasVideoMetadata() const
394{
395 if (RefPtr player = protect(videoElement())->player())
396 return player->readyState() >= MediaPlayerEnums::ReadyState::HaveMetadata;
397 return false;
398}
399
400bool RenderVideo::hasPosterFrameSize() const
401{
402 bool isEmpty = m_cachedImageSize.isEmpty();
403 // For contain: inline-size, if the block-size is not empty, it shouldn't be treated as empty here,
404 // so that contain: inline-size could affect the intrinsic size, which should be 0 x block-size.
405 if (shouldApplyInlineSizeContainment())
406 isEmpty = isHorizontalWritingMode() ? !m_cachedImageSize.height() : !m_cachedImageSize.width();
407 return protect(videoElement())->shouldDisplayPosterImage() && !isEmpty && !protect(imageResource())->errorOccurred();
408}
409
410bool RenderVideo::hasDefaultObjectSize() const
411{
412 return !hasVideoMetadata() && !hasPosterFrameSize() && !shouldApplySizeContainment();
413}
414
415void RenderVideo::invalidateLineLayout()
416{
417 if (CheckedPtr inlineLayout = LayoutIntegration::LineLayout::containing(*this))
418 inlineLayout->boxContentWillChange(*this);
419}
420
421} // namespace WebCore
422
423#endif