зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #6410 - Create pattern from HTMLCanvasElement or CanvasRenderingContext2D (from hyowon:create_pattern); r=pcwalton
r? @nox @pcwalton cc @yichoi Source-Repo: https://github.com/servo/servo Source-Revision: 95d643c995a271fac11ab3d9aac97f2d0aac8934
This commit is contained in:
Родитель
9bacf73484
Коммит
423cdb8c21
|
@ -275,7 +275,7 @@ impl CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_image_data(&self,
|
fn fetch_image_data(&self,
|
||||||
image_element: &&HTMLImageElement)
|
image_element: &HTMLImageElement)
|
||||||
-> Option<(Vec<u8>, Size2D<f64>)> {
|
-> Option<(Vec<u8>, Size2D<f64>)> {
|
||||||
let url = match image_element.get_url() {
|
let url = match image_element.get_url() {
|
||||||
Some(url) => url,
|
Some(url) => url,
|
||||||
|
@ -288,18 +288,36 @@ impl CanvasRenderingContext2D {
|
||||||
};
|
};
|
||||||
|
|
||||||
let image_size = Size2D::new(img.width as f64, img.height as f64);
|
let image_size = Size2D::new(img.width as f64, img.height as f64);
|
||||||
let mut image_data = match img.pixels {
|
let image_data = match img.pixels {
|
||||||
PixelsByColorType::RGBA8(ref pixels) => pixels.to_vec(),
|
PixelsByColorType::RGBA8(ref pixels) => pixels.to_vec(),
|
||||||
PixelsByColorType::K8(_) => panic!("K8 color type not supported"),
|
PixelsByColorType::K8(_) => panic!("K8 color type not supported"),
|
||||||
PixelsByColorType::RGB8(_) => panic!("RGB8 color type not supported"),
|
PixelsByColorType::RGB8(_) => panic!("RGB8 color type not supported"),
|
||||||
PixelsByColorType::KA8(_) => panic!("KA8 color type not supported"),
|
PixelsByColorType::KA8(_) => panic!("KA8 color type not supported"),
|
||||||
};
|
};
|
||||||
// Pixels come from cache in BGRA order and drawImage expects RGBA so we
|
|
||||||
// have to swap the color values
|
|
||||||
byte_swap(&mut image_data);
|
|
||||||
return Some((image_data, image_size));
|
return Some((image_data, image_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fetch_canvas_data(&self,
|
||||||
|
canvas_element: &HTMLCanvasElement,
|
||||||
|
source_rect: Rect<f64>)
|
||||||
|
-> Option<(Vec<u8>, Size2D<f64>)> {
|
||||||
|
let context = match canvas_element.get_or_init_2d_context() {
|
||||||
|
Some(context) => context,
|
||||||
|
None => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let canvas_size = canvas_element.get_size();
|
||||||
|
let image_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64);
|
||||||
|
|
||||||
|
let renderer = context.r().get_renderer();
|
||||||
|
let (sender, receiver) = channel::<Vec<u8>>();
|
||||||
|
// Reads pixels from source canvas
|
||||||
|
renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(source_rect, image_size, sender))).unwrap();
|
||||||
|
|
||||||
|
return Some((receiver.recv().unwrap(), image_size));
|
||||||
|
}
|
||||||
|
|
||||||
fn request_image_from_cache(&self, url: Url) -> ImageResponse {
|
fn request_image_from_cache(&self, url: Url) -> ImageResponse {
|
||||||
let canvas = self.canvas.root();
|
let canvas = self.canvas.root();
|
||||||
let window = window_from_node(canvas.r());
|
let window = window_from_node(canvas.r());
|
||||||
|
@ -580,7 +598,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
||||||
// If the image argument is an HTMLImageElement object that is in the broken state,
|
// If the image argument is an HTMLImageElement object that is in the broken state,
|
||||||
// then throw an InvalidStateError exception
|
// then throw an InvalidStateError exception
|
||||||
let (image_data, image_size) = match self.fetch_image_data(&image_element) {
|
let (image_data, image_size) = match self.fetch_image_data(&image_element) {
|
||||||
Some((data, size)) => (data, size),
|
Some((mut data, size)) => {
|
||||||
|
// Pixels come from cache in BGRA order and drawImage expects RGBA so we
|
||||||
|
// have to swap the color values
|
||||||
|
byte_swap(&mut data);
|
||||||
|
(data, size)
|
||||||
|
},
|
||||||
None => return Err(InvalidState),
|
None => return Err(InvalidState),
|
||||||
};
|
};
|
||||||
let dw: f64 = image_size.width as f64;
|
let dw: f64 = image_size.width as f64;
|
||||||
|
@ -636,7 +659,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
||||||
// If the image argument is an HTMLImageElement object that is in the broken state,
|
// If the image argument is an HTMLImageElement object that is in the broken state,
|
||||||
// then throw an InvalidStateError exception
|
// then throw an InvalidStateError exception
|
||||||
let (image_data, image_size) = match self.fetch_image_data(&image_element) {
|
let (image_data, image_size) = match self.fetch_image_data(&image_element) {
|
||||||
Some((data, size)) => (data, size),
|
Some((mut data, size)) => {
|
||||||
|
// Pixels come from cache in BGRA order and drawImage expects RGBA so we
|
||||||
|
// have to swap the color values
|
||||||
|
byte_swap(&mut data);
|
||||||
|
(data, size)
|
||||||
|
},
|
||||||
None => return Err(InvalidState),
|
None => return Err(InvalidState),
|
||||||
};
|
};
|
||||||
let sw: f64 = image_size.width as f64;
|
let sw: f64 = image_size.width as f64;
|
||||||
|
@ -677,7 +705,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
||||||
// If the image argument is an HTMLImageElement object that is in the broken state,
|
// If the image argument is an HTMLImageElement object that is in the broken state,
|
||||||
// then throw an InvalidStateError exception
|
// then throw an InvalidStateError exception
|
||||||
let (image_data, image_size) = match self.fetch_image_data(&image_element) {
|
let (image_data, image_size) = match self.fetch_image_data(&image_element) {
|
||||||
Some((data, size)) => (data, size),
|
Some((mut data, size)) => {
|
||||||
|
// Pixels come from cache in BGRA order and drawImage expects RGBA so we
|
||||||
|
// have to swap the color values
|
||||||
|
byte_swap(&mut data);
|
||||||
|
(data, size)
|
||||||
|
},
|
||||||
None => return Err(InvalidState),
|
None => return Err(InvalidState),
|
||||||
};
|
};
|
||||||
return self.draw_image_data(image_data,
|
return self.draw_image_data(image_data,
|
||||||
|
@ -1015,26 +1048,42 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern
|
||||||
fn CreatePattern(self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
fn CreatePattern(self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||||
repetition: DOMString) -> Fallible<Root<CanvasPattern>> {
|
repetition: DOMString) -> Fallible<Root<CanvasPattern>> {
|
||||||
match image {
|
let (image_data, image_size) = match image {
|
||||||
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
|
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
|
||||||
let image_element = image.r();
|
let image_element = image.r();
|
||||||
|
// https://html.spec.whatwg.org/multipage/#img-error
|
||||||
let url = match image_element.get_url() {
|
// If the image argument is an HTMLImageElement object that is in the broken state,
|
||||||
Some(url) => url,
|
// then throw an InvalidStateError exception
|
||||||
|
match self.fetch_image_data(&image_element) {
|
||||||
|
Some((data, size)) => (data, size),
|
||||||
None => return Err(InvalidState),
|
None => return Err(InvalidState),
|
||||||
};
|
}
|
||||||
|
},
|
||||||
|
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(canvas) => {
|
||||||
|
let canvas_element = canvas.r();
|
||||||
|
|
||||||
let img = match self.request_image_from_cache(url) {
|
let canvas_size = canvas_element.get_size();
|
||||||
ImageResponse::Loaded(img) => img,
|
let source_rect = Rect::new(Point2D::zero(),
|
||||||
ImageResponse::PlaceholderLoaded(_) | ImageResponse::None => return Err(InvalidState),
|
Size2D::new(canvas_size.width as f64, canvas_size.height as f64));
|
||||||
};
|
|
||||||
|
|
||||||
let image_size = Size2D::new(img.width as f64, img.height as f64);
|
match self.fetch_canvas_data(&canvas_element, source_rect) {
|
||||||
let image_data = match img.pixels {
|
Some((data, size)) => (data, size),
|
||||||
PixelsByColorType::RGBA8(ref pixels) => pixels.to_vec(),
|
None => return Err(InvalidState),
|
||||||
PixelsByColorType::K8(_) => panic!("K8 color type not supported"),
|
}
|
||||||
PixelsByColorType::RGB8(_) => panic!("RGB8 color type not supported"),
|
},
|
||||||
PixelsByColorType::KA8(_) => panic!("KA8 color type not supported"),
|
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(context) => {
|
||||||
|
let canvas = context.r().Canvas();
|
||||||
|
let canvas_element = canvas.r();
|
||||||
|
|
||||||
|
let canvas_size = canvas_element.get_size();
|
||||||
|
let source_rect = Rect::new(Point2D::zero(),
|
||||||
|
Size2D::new(canvas_size.width as f64, canvas_size.height as f64));
|
||||||
|
|
||||||
|
match self.fetch_canvas_data(&canvas_element, source_rect) {
|
||||||
|
Some((data, size)) => (data, size),
|
||||||
|
None => return Err(InvalidState),
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(rep) = RepetitionStyle::from_str(&repetition) {
|
if let Some(rep) = RepetitionStyle::from_str(&repetition) {
|
||||||
|
@ -1044,9 +1093,6 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
||||||
rep));
|
rep));
|
||||||
}
|
}
|
||||||
return Err(Syntax);
|
return Err(Syntax);
|
||||||
},
|
|
||||||
_ => return Err(Type("Not implemented".to_owned())),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth
|
||||||
|
|
Загрузка…
Ссылка в новой задаче