servo: Merge #8200 - Implement HTMLCanvasElement#toDataURL (from dzbarsky:canvas_todata); r=glennw

Confirmed that dumping the output of toDataUrl on toDataURL.png.primarycolours.html gives the same results as Firefox (including padding)

Source-Repo: https://github.com/servo/servo
Source-Revision: 4a4dda38969d5f7efdfc1e28e04721302552195a
This commit is contained in:
David Zbarsky 2015-10-26 23:29:04 -05:00
parent 62da234ead
commit d747cdd1bc
5 changed files with 49 additions and 1 deletions

View File

@ -92,3 +92,4 @@ tendril = "0.1.1"
rand = "0.3"
serde = "0.6"
caseless = "0.1.0"
image = "0.4.0"

View File

@ -5,13 +5,16 @@
use canvas_traits::{CanvasMsg, FromLayoutMsg};
use dom::attr::Attr;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods;
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding;
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes;
use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext;
use dom::bindings::conversions::Castable;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root};
use dom::bindings::num::Finite;
use dom::bindings::utils::{Reflectable};
use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers};
use dom::document::Document;
@ -21,9 +24,12 @@ use dom::node::{Node, window_from_node};
use dom::virtualmethods::VirtualMethods;
use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext};
use euclid::size::Size2D;
use image::ColorType;
use image::png::PNGEncoder;
use ipc_channel::ipc::{self, IpcSender};
use js::jsapi::{HandleValue, JSContext};
use offscreen_gl_context::GLContextAttributes;
use rustc_serialize::base64::{STANDARD, ToBase64};
use std::cell::Cell;
use std::iter::repeat;
use util::str::{DOMString, parse_unsigned_integer};
@ -246,6 +252,44 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
_ => None
}
}
// https://html.spec.whatwg.org/multipage/#dom-canvas-todataurl
fn ToDataURL(&self,
_context: *mut JSContext,
_mime_type: Option<DOMString>,
_arguments: Vec<HandleValue>) -> Fallible<DOMString> {
// Step 1: Check the origin-clean flag (should be set in fillText/strokeText
// and currently unimplemented)
// Step 2.
if self.Width() == 0 || self.Height() == 0 {
return Ok("data:,".to_owned());
}
// Step 3.
if let Some(CanvasContext::Context2d(ref context)) = *self.context.borrow() {
let window = window_from_node(self);
let image_data = try!(context.GetImageData(Finite::wrap(0f64), Finite::wrap(0f64),
Finite::wrap(self.Width() as f64),
Finite::wrap(self.Height() as f64)));
let raw_data = image_data.get_data_array(&GlobalRef::Window(window.r()));
// Only handle image/png for now.
let mime_type = "image/png";
let mut encoded = Vec::new();
{
let encoder: PNGEncoder<&mut Vec<u8>> = PNGEncoder::new(&mut encoded);
encoder.encode(&raw_data, self.Width(), self.Height(), ColorType::RGBA(8)).unwrap();
}
let encoded = encoded.to_base64(STANDARD);
Ok(format!("data:{};base64,{}", mime_type, encoded))
} else {
Err(Error::NotSupported)
}
}
}
impl VirtualMethods for HTMLCanvasElement {

View File

@ -18,6 +18,7 @@ interface HTMLCanvasElement : HTMLElement {
//void setContext(RenderingContext context);
//CanvasProxy transferControlToProxy();
//DOMString toDataURL(optional DOMString type, any... arguments);
[Throws]
DOMString toDataURL(optional DOMString type, any... arguments);
//void toBlob(FileCallback? _callback, optional DOMString type, any... arguments);
};

View File

@ -58,6 +58,7 @@ extern crate euclid;
extern crate fnv;
extern crate html5ever;
extern crate hyper;
extern crate image;
extern crate ipc_channel;
extern crate js;
extern crate libc;

View File

@ -1516,6 +1516,7 @@ dependencies = [
"fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"html5ever 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
"js 0.1.0 (git+https://github.com/servo/rust-mozjs)",
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",