diff options
3 files changed, 77 insertions, 9 deletions
diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 3db1022507c..e61358325ae 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -7,7 +7,9 @@ use canvas_traits::webgl::{GLContextAttributes, WebGLVersion}; use dom_struct::dom_struct; use euclid::default::{Rect, Size2D}; use html5ever::{local_name, namespace_url, ns, LocalName, Prefix}; +use image::codecs::jpeg::JpegEncoder; use image::codecs::png::PngEncoder; +use image::codecs::webp::WebPEncoder; use image::{ColorType, ImageEncoder}; use ipc_channel::ipc::IpcSharedMemory; #[cfg(feature = "webgpu")] @@ -397,8 +399,8 @@ impl HTMLCanvasElementMethods<crate::DomTypeHolder> for HTMLCanvasElement { fn ToDataURL( &self, _context: JSContext, - _mime_type: Option<DOMString>, - _quality: HandleValue, + mime_type: Option<DOMString>, + quality: HandleValue, ) -> Fallible<USVString> { // Step 1. if !self.origin_is_clean() { @@ -436,17 +438,75 @@ impl HTMLCanvasElementMethods<crate::DomTypeHolder> for HTMLCanvasElement { }, }; - // FIXME: Only handle image/png for now. - let mut url = "data:image/png;base64,".to_owned(); + enum ImageType { + Png, + Jpeg, + Webp, + } + + // From: https://html.spec.whatwg.org/multipage/#serialising-bitmaps-to-a-file + // User agents must support PNG ("image/png"). User agents may support other types. + // If the user agent does not support the requested type, then it must create the file using the PNG format. + // Anything different than image/jpeg is thus treated as PNG. + let (image_type, url) = match mime_type { + Some(mime) => { + let mime = mime.to_string().to_lowercase(); + if mime == "image/jpeg" { + (ImageType::Jpeg, "data:image/jpeg;base64,") + } else if mime == "image/webp" { + (ImageType::Webp, "data:image/webp;base64,") + } else { + (ImageType::Png, "data:image/png;base64,") + } + }, + _ => (ImageType::Png, "data:image/png;base64,"), + }; + + let mut url = url.to_owned(); + let mut encoder = base64::write::EncoderStringWriter::from_consumer( &mut url, &base64::engine::general_purpose::STANDARD, ); - // FIXME(nox): https://github.com/image-rs/image-png/issues/86 - // FIXME(nox): https://github.com/image-rs/image-png/issues/87 - PngEncoder::new(&mut encoder) - .write_image(&file, self.Width(), self.Height(), ColorType::Rgba8) - .unwrap(); + + match image_type { + ImageType::Png => { + // FIXME(nox): https://github.com/image-rs/image-png/issues/86 + // FIXME(nox): https://github.com/image-rs/image-png/issues/87 + PngEncoder::new(&mut encoder) + .write_image(&file, self.Width(), self.Height(), ColorType::Rgba8) + .unwrap(); + }, + ImageType::Jpeg => { + let jpeg_encoder = if quality.is_number() { + let quality = quality.to_number(); + // The specification allows quality to be in [0.0..1.0] but the JPEG encoder + // expects it to be in [1..100] + if (0.0..=1.0).contains(&quality) { + JpegEncoder::new_with_quality( + &mut encoder, + (quality * 100.0).round().clamp(1.0, 100.0) as u8, + ) + } else { + JpegEncoder::new(&mut encoder) + } + } else { + JpegEncoder::new(&mut encoder) + }; + + jpeg_encoder + .write_image(&file, self.Width(), self.Height(), ColorType::Rgba8) + .unwrap(); + }, + + ImageType::Webp => { + // No quality support because of https://github.com/image-rs/image/issues/1984 + WebPEncoder::new_lossless(&mut encoder) + .write_image(&file, self.Width(), self.Height(), ColorType::Rgba8) + .unwrap(); + }, + } + encoder.into_inner(); Ok(USVString(url)) } diff --git a/tests/wpt/meta/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.alpha.html.ini b/tests/wpt/meta/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.alpha.html.ini new file mode 100644 index 00000000000..16ecb34bf33 --- /dev/null +++ b/tests/wpt/meta/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.alpha.html.ini @@ -0,0 +1,3 @@ +[toDataURL.jpeg.alpha.html] + [toDataURL with JPEG composites onto black] + expected: FAIL diff --git a/tests/wpt/webgl/meta/conformance/context/premultiplyalpha-test.html.ini b/tests/wpt/webgl/meta/conformance/context/premultiplyalpha-test.html.ini index 361c95a0427..5d1831e1025 100644 --- a/tests/wpt/webgl/meta/conformance/context/premultiplyalpha-test.html.ini +++ b/tests/wpt/webgl/meta/conformance/context/premultiplyalpha-test.html.ini @@ -90,3 +90,8 @@ [WebGL test #55: should draw with 255,192,128,1\nat (0, 0) expected: 255,192,128,1 was 0,0,0,255] expected: FAIL + [WebGL test #62: should draw with 128,128,128,255\nat (0, 0) expected: 128,128,128,255 was 255,255,255,255] + expected: FAIL + + [WebGL test #69: should draw with 128,128,128,255\nat (0, 0) expected: 128,128,128,255 was 255,255,255,255] + expected: FAIL |