canvas: Add HTMLVideoElement to CanvasImageSource union type (#37135)

Follow to the specification and add HTMLVideoElement to
CanvasImageSource union type
to allow use it as image source for createPattern/drawImage operations.
https://html.spec.whatwg.org/multipage/#canvasimagesource

https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern
https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage

The HTMLVideoElement media resource has an associated origin:
- media provider object (MediaStream/MediaSource/Blob): CORS-same-origin
 - URL record: CORS-cross-origin/CORS-same-origin

https://html.spec.whatwg.org/multipage/media.html#media-resource

Testing:
 - html/canvas/element/*
 - html/semantics/embedded-content/the-canvas-element/*

Signed-off-by: Andrei Volykhin <andrei.volykhin@gmail.com>
This commit is contained in:
Andrei Volykhin 2025-05-28 15:04:01 +03:00 committed by GitHub
parent 4f4c99a39e
commit 644138c1da
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 184 additions and 88 deletions

View file

@ -9,7 +9,6 @@ use content_security_policy as csp;
use dom_struct::dom_struct;
use euclid::default::Size2D;
use html5ever::{LocalName, Prefix, local_name, ns};
use ipc_channel::ipc;
use js::rust::HandleObject;
use net_traits::image_cache::{
ImageCache, ImageCacheResult, ImageLoadListener, ImageOrMetadataAvailable, ImageResponse,
@ -23,6 +22,7 @@ use net_traits::{
use script_layout_interface::{HTMLMediaData, MediaMetadata};
use servo_media::player::video::VideoFrame;
use servo_url::ServoUrl;
use snapshot::Snapshot;
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
use crate::document_loader::{LoadBlocker, LoadType};
@ -133,9 +133,7 @@ impl HTMLVideoElement {
sent_resize
}
pub(crate) fn get_current_frame_data(
&self,
) -> Option<(Option<ipc::IpcSharedMemory>, Size2D<u32>)> {
pub(crate) fn get_current_frame_data(&self) -> Option<Snapshot> {
let frame = self.htmlmediaelement.get_current_frame();
if frame.is_some() {
*self.last_frame.borrow_mut() = frame;
@ -145,11 +143,19 @@ impl HTMLVideoElement {
Some(frame) => {
let size = Size2D::new(frame.get_width() as u32, frame.get_height() as u32);
if !frame.is_gl_texture() {
let data = Some(ipc::IpcSharedMemory::from_bytes(&frame.get_data()));
Some((data, size))
let alpha_mode = snapshot::AlphaMode::Transparent {
premultiplied: false,
};
Some(Snapshot::from_vec(
size.cast(),
snapshot::PixelFormat::BGRA,
alpha_mode,
frame.get_data().to_vec(),
))
} else {
// XXX(victor): here we only have the GL texture ID.
Some((None, size))
Some(Snapshot::cleared(size.cast()))
}
},
None => None,
@ -276,6 +282,18 @@ impl HTMLVideoElement {
},
}
}
/// <https://html.spec.whatwg.org/multipage/#check-the-usability-of-the-image-argument>
pub(crate) fn is_usable(&self) -> bool {
!matches!(
self.htmlmediaelement.get_ready_state(),
ReadyState::HaveNothing | ReadyState::HaveMetadata
)
}
pub(crate) fn origin_is_clean(&self) -> bool {
self.htmlmediaelement.origin_is_clean()
}
}
impl HTMLVideoElementMethods<crate::DomTypeHolder> for HTMLVideoElement {