Don't create 2D canvas contexts arbitrarily

Sometimes, the canvas still has no rendering context, in this case it represents
a transparent black rectangle.
This commit is contained in:
Anthony Ramine 2018-09-15 12:28:53 +02:00
parent ed673f8070
commit f1e8eb640c
4 changed files with 107 additions and 90 deletions

View file

@ -27,7 +27,7 @@ use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeSty
use dom::canvaspattern::CanvasPattern;
use dom::element::Element;
use dom::globalscope::GlobalScope;
use dom::htmlcanvaselement::HTMLCanvasElement;
use dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement};
use dom::imagedata::ImageData;
use dom::node::{Node, NodeDamage, window_from_node};
use dom_struct::dom_struct;
@ -315,17 +315,18 @@ impl CanvasRenderingContext2D {
result
}
fn draw_html_canvas_element(&self,
canvas: &HTMLCanvasElement,
sx: f64,
sy: f64,
sw: Option<f64>,
sh: Option<f64>,
dx: f64,
dy: f64,
dw: Option<f64>,
dh: Option<f64>)
-> ErrorResult {
fn draw_html_canvas_element(
&self,
canvas: &HTMLCanvasElement,
sx: f64,
sy: f64,
sw: Option<f64>,
sh: Option<f64>,
dx: f64,
dy: f64,
dw: Option<f64>,
dh: Option<f64>,
) -> ErrorResult {
// 1. Check the usability of the image argument
if !canvas.is_valid() {
return Err(Error::InvalidState);
@ -339,15 +340,17 @@ impl CanvasRenderingContext2D {
let image_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64);
// 2. Establish the source and destination rectangles
let (source_rect, dest_rect) = self.adjust_source_dest_rects(image_size,
sx,
sy,
sw,
sh,
dx,
dy,
dw,
dh);
let (source_rect, dest_rect) = self.adjust_source_dest_rects(
image_size,
sx,
sy,
sw,
sh,
dx,
dy,
dw,
dh,
);
if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) {
return Ok(());
@ -355,29 +358,40 @@ impl CanvasRenderingContext2D {
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
if self.canvas.as_ref().map_or(false, |c| &**c == canvas) {
self.send_canvas_2d_msg(Canvas2dMsg::DrawImageSelf(
image_size, dest_rect, source_rect, smoothing_enabled));
if let Some(context) = canvas.context() {
match *context {
CanvasContext::Context2d(ref context) => {
if self.canvas.as_ref().map_or(false, |c| &**c == canvas) {
self.send_canvas_2d_msg(Canvas2dMsg::DrawImageSelf(
image_size,
dest_rect,
source_rect,
smoothing_enabled,
));
} else {
context.get_ipc_renderer().send(CanvasMsg::Canvas2d(
Canvas2dMsg::DrawImageInOther(
self.get_canvas_id(),
image_size,
dest_rect,
source_rect,
smoothing_enabled,
),
context.get_canvas_id(),
)).unwrap();
}
},
_ => return Err(Error::InvalidState),
}
} else {
let context = match canvas.get_or_init_2d_context() {
Some(context) => context,
None => return Err(Error::InvalidState),
};
let msg = CanvasMsg::Canvas2d(
Canvas2dMsg::DrawImageInOther(
self.get_canvas_id(),
image_size,
dest_rect,
source_rect,
smoothing_enabled
),
context.get_canvas_id()
);
let renderer = context.get_ipc_renderer();
renderer.send(msg).unwrap();
};
self.send_canvas_2d_msg(Canvas2dMsg::DrawImage(
None,
image_size,
dest_rect,
source_rect,
smoothing_enabled,
));
}
self.mark_as_dirty();
Ok(())
@ -447,7 +461,7 @@ impl CanvasRenderingContext2D {
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
self.send_canvas_2d_msg(Canvas2dMsg::DrawImage(
image_data.into(),
Some(image_data.into()),
image_size,
dest_rect,
source_rect,
@ -1205,8 +1219,6 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
.ok_or(Error::InvalidState)?
},
CanvasImageSource::HTMLCanvasElement(ref canvas) => {
let _ = canvas.get_or_init_2d_context();
canvas.fetch_all_data().ok_or(Error::InvalidState)?
},
CanvasImageSource::CSSStyleValue(ref value) => {