mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +01:00
Add unique canvas IDs to all canvas operations.
This commit is contained in:
parent
a69eceefc9
commit
8a1590efc6
13 changed files with 334 additions and 155 deletions
|
@ -64,6 +64,7 @@ pub struct CanvasPaintThread<'a> {
|
||||||
old_image_key: Option<webrender_api::ImageKey>,
|
old_image_key: Option<webrender_api::ImageKey>,
|
||||||
/// An old webrender image key that can be deleted when the current epoch ends.
|
/// An old webrender image key that can be deleted when the current epoch ends.
|
||||||
very_old_image_key: Option<webrender_api::ImageKey>,
|
very_old_image_key: Option<webrender_api::ImageKey>,
|
||||||
|
canvas_id: CanvasId,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -99,7 +100,8 @@ impl<'a> CanvasPaintState<'a> {
|
||||||
impl<'a> CanvasPaintThread<'a> {
|
impl<'a> CanvasPaintThread<'a> {
|
||||||
fn new(size: Size2D<i32>,
|
fn new(size: Size2D<i32>,
|
||||||
webrender_api_sender: webrender_api::RenderApiSender,
|
webrender_api_sender: webrender_api::RenderApiSender,
|
||||||
antialias: AntialiasMode) -> CanvasPaintThread<'a> {
|
antialias: AntialiasMode,
|
||||||
|
canvas_id: CanvasId) -> CanvasPaintThread<'a> {
|
||||||
let draw_target = CanvasPaintThread::create(size);
|
let draw_target = CanvasPaintThread::create(size);
|
||||||
let path_builder = draw_target.create_path_builder();
|
let path_builder = draw_target.create_path_builder();
|
||||||
let webrender_api = webrender_api_sender.create_api();
|
let webrender_api = webrender_api_sender.create_api();
|
||||||
|
@ -112,6 +114,7 @@ impl<'a> CanvasPaintThread<'a> {
|
||||||
image_key: None,
|
image_key: None,
|
||||||
old_image_key: None,
|
old_image_key: None,
|
||||||
very_old_image_key: None,
|
very_old_image_key: None,
|
||||||
|
canvas_id: canvas_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +122,8 @@ impl<'a> CanvasPaintThread<'a> {
|
||||||
/// communicate with it.
|
/// communicate with it.
|
||||||
pub fn start(size: Size2D<i32>,
|
pub fn start(size: Size2D<i32>,
|
||||||
webrender_api_sender: webrender_api::RenderApiSender,
|
webrender_api_sender: webrender_api::RenderApiSender,
|
||||||
antialias: bool)
|
antialias: bool,
|
||||||
|
canvas_id: CanvasId)
|
||||||
-> IpcSender<CanvasMsg> {
|
-> IpcSender<CanvasMsg> {
|
||||||
let (sender, receiver) = ipc::channel::<CanvasMsg>().unwrap();
|
let (sender, receiver) = ipc::channel::<CanvasMsg>().unwrap();
|
||||||
let antialias = if antialias {
|
let antialias = if antialias {
|
||||||
|
@ -128,11 +132,12 @@ impl<'a> CanvasPaintThread<'a> {
|
||||||
AntialiasMode::None
|
AntialiasMode::None
|
||||||
};
|
};
|
||||||
thread::Builder::new().name("CanvasThread".to_owned()).spawn(move || {
|
thread::Builder::new().name("CanvasThread".to_owned()).spawn(move || {
|
||||||
let mut painter = CanvasPaintThread::new(size, webrender_api_sender, antialias);
|
let mut painter = CanvasPaintThread::new(size, webrender_api_sender, antialias, canvas_id);
|
||||||
loop {
|
loop {
|
||||||
let msg = receiver.recv();
|
let msg = receiver.recv();
|
||||||
match msg.unwrap() {
|
match msg.unwrap() {
|
||||||
CanvasMsg::Canvas2d(message) => {
|
CanvasMsg::Canvas2d(message, canvas_id) => {
|
||||||
|
assert!(canvas_id == painter.canvas_id);
|
||||||
match message {
|
match message {
|
||||||
Canvas2dMsg::FillText(text, x, y, max_width) => painter.fill_text(text, x, y, max_width),
|
Canvas2dMsg::FillText(text, x, y, max_width) => painter.fill_text(text, x, y, max_width),
|
||||||
Canvas2dMsg::FillRect(ref rect) => painter.fill_rect(rect),
|
Canvas2dMsg::FillRect(ref rect) => painter.fill_rect(rect),
|
||||||
|
@ -165,10 +170,10 @@ impl<'a> CanvasPaintThread<'a> {
|
||||||
painter.draw_image_self(image_size, dest_rect, source_rect, smoothing_enabled)
|
painter.draw_image_self(image_size, dest_rect, source_rect, smoothing_enabled)
|
||||||
}
|
}
|
||||||
Canvas2dMsg::DrawImageInOther(
|
Canvas2dMsg::DrawImageInOther(
|
||||||
renderer, image_size, dest_rect, source_rect, smoothing, sender
|
renderer, other_canvas_id, image_size, dest_rect, source_rect, smoothing, sender
|
||||||
) => {
|
) => {
|
||||||
painter.draw_image_in_other(
|
painter.draw_image_in_other(
|
||||||
renderer, image_size, dest_rect, source_rect, smoothing, sender)
|
renderer, other_canvas_id, image_size, dest_rect, source_rect, smoothing, sender)
|
||||||
}
|
}
|
||||||
Canvas2dMsg::MoveTo(ref point) => painter.move_to(point),
|
Canvas2dMsg::MoveTo(ref point) => painter.move_to(point),
|
||||||
Canvas2dMsg::LineTo(ref point) => painter.line_to(point),
|
Canvas2dMsg::LineTo(ref point) => painter.line_to(point),
|
||||||
|
@ -220,22 +225,30 @@ impl<'a> CanvasPaintThread<'a> {
|
||||||
Canvas2dMsg::SetShadowColor(ref color) => painter.set_shadow_color(color.to_azure_style()),
|
Canvas2dMsg::SetShadowColor(ref color) => painter.set_shadow_color(color.to_azure_style()),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CanvasMsg::Close => break,
|
CanvasMsg::Close(canvas_id) =>{
|
||||||
CanvasMsg::Recreate(size) => painter.recreate(size),
|
assert!(canvas_id == painter.canvas_id);
|
||||||
CanvasMsg::FromScript(message) => {
|
break;
|
||||||
|
},
|
||||||
|
CanvasMsg::Recreate(size, canvas_id) =>{
|
||||||
|
assert!(canvas_id == painter.canvas_id);
|
||||||
|
painter.recreate(size);
|
||||||
|
},
|
||||||
|
CanvasMsg::FromScript(message, canvas_id) => {
|
||||||
|
assert!(canvas_id == painter.canvas_id);
|
||||||
match message {
|
match message {
|
||||||
FromScriptMsg::SendPixels(chan) => {
|
FromScriptMsg::SendPixels(chan) => {
|
||||||
painter.send_pixels(chan)
|
painter.send_pixels(chan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
CanvasMsg::FromLayout(message) => {
|
CanvasMsg::FromLayout(message, canvas_id) => {
|
||||||
|
assert!(canvas_id == painter.canvas_id);
|
||||||
match message {
|
match message {
|
||||||
FromLayoutMsg::SendData(chan) => {
|
FromLayoutMsg::SendData(chan) => {
|
||||||
painter.send_data(chan)
|
painter.send_data(chan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).expect("Thread spawning failed");
|
}).expect("Thread spawning failed");
|
||||||
|
@ -415,6 +428,7 @@ impl<'a> CanvasPaintThread<'a> {
|
||||||
|
|
||||||
fn draw_image_in_other(&self,
|
fn draw_image_in_other(&self,
|
||||||
renderer: IpcSender<CanvasMsg>,
|
renderer: IpcSender<CanvasMsg>,
|
||||||
|
other_canvas_id: CanvasId,
|
||||||
image_size: Size2D<f64>,
|
image_size: Size2D<f64>,
|
||||||
dest_rect: Rect<f64>,
|
dest_rect: Rect<f64>,
|
||||||
source_rect: Rect<f64>,
|
source_rect: Rect<f64>,
|
||||||
|
@ -430,7 +444,9 @@ impl<'a> CanvasPaintThread<'a> {
|
||||||
dest_rect,
|
dest_rect,
|
||||||
source_rect,
|
source_rect,
|
||||||
smoothing_enabled,
|
smoothing_enabled,
|
||||||
));
|
),
|
||||||
|
other_canvas_id,
|
||||||
|
);
|
||||||
renderer.send(msg).unwrap();
|
renderer.send(msg).unwrap();
|
||||||
// We acknowledge to the caller here that the data was sent to the
|
// We acknowledge to the caller here that the data was sent to the
|
||||||
// other canvas so that if JS immediately afterwards try to get the
|
// other canvas so that if JS immediately afterwards try to get the
|
||||||
|
|
|
@ -16,13 +16,16 @@ pub enum FillRule {
|
||||||
Evenodd,
|
Evenodd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
||||||
|
pub struct CanvasId(pub u64);
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Serialize)]
|
#[derive(Clone, Deserialize, Serialize)]
|
||||||
pub enum CanvasMsg {
|
pub enum CanvasMsg {
|
||||||
Canvas2d(Canvas2dMsg),
|
Canvas2d(Canvas2dMsg, CanvasId),
|
||||||
FromLayout(FromLayoutMsg),
|
FromLayout(FromLayoutMsg, CanvasId),
|
||||||
FromScript(FromScriptMsg),
|
FromScript(FromScriptMsg, CanvasId),
|
||||||
Recreate(Size2D<i32>),
|
Recreate(Size2D<i32>, CanvasId),
|
||||||
Close,
|
Close(CanvasId),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Serialize)]
|
#[derive(Clone, Deserialize, Serialize)]
|
||||||
|
@ -37,7 +40,7 @@ pub enum Canvas2dMsg {
|
||||||
DrawImage(ByteBuf, Size2D<f64>, Rect<f64>, Rect<f64>, bool),
|
DrawImage(ByteBuf, Size2D<f64>, Rect<f64>, Rect<f64>, bool),
|
||||||
DrawImageSelf(Size2D<f64>, Rect<f64>, Rect<f64>, bool),
|
DrawImageSelf(Size2D<f64>, Rect<f64>, Rect<f64>, bool),
|
||||||
DrawImageInOther(
|
DrawImageInOther(
|
||||||
IpcSender<CanvasMsg>, Size2D<f64>, Rect<f64>, Rect<f64>, bool, IpcSender<()>),
|
IpcSender<CanvasMsg>, CanvasId, Size2D<f64>, Rect<f64>, Rect<f64>, bool, IpcSender<()>),
|
||||||
BeginPath,
|
BeginPath,
|
||||||
BezierCurveTo(Point2D<f32>, Point2D<f32>, Point2D<f32>),
|
BezierCurveTo(Point2D<f32>, Point2D<f32>, Point2D<f32>),
|
||||||
ClearRect(Rect<f32>),
|
ClearRect(Rect<f32>),
|
||||||
|
|
|
@ -95,6 +95,7 @@ use browsingcontext::{BrowsingContext, SessionHistoryChange, SessionHistoryEntry
|
||||||
use browsingcontext::{FullyActiveBrowsingContextsIterator, AllBrowsingContextsIterator};
|
use browsingcontext::{FullyActiveBrowsingContextsIterator, AllBrowsingContextsIterator};
|
||||||
use canvas::canvas_paint_thread::CanvasPaintThread;
|
use canvas::canvas_paint_thread::CanvasPaintThread;
|
||||||
use canvas::webgl_thread::WebGLThreads;
|
use canvas::webgl_thread::WebGLThreads;
|
||||||
|
use canvas_traits::canvas::CanvasId;
|
||||||
use canvas_traits::canvas::CanvasMsg;
|
use canvas_traits::canvas::CanvasMsg;
|
||||||
use clipboard::{ClipboardContext, ClipboardProvider};
|
use clipboard::{ClipboardContext, ClipboardProvider};
|
||||||
use compositing::SendableFrameTree;
|
use compositing::SendableFrameTree;
|
||||||
|
@ -329,6 +330,9 @@ pub struct Constellation<Message, LTF, STF> {
|
||||||
|
|
||||||
/// A channel through which messages can be sent to the webvr thread.
|
/// A channel through which messages can be sent to the webvr thread.
|
||||||
webvr_chan: Option<IpcSender<WebVRMsg>>,
|
webvr_chan: Option<IpcSender<WebVRMsg>>,
|
||||||
|
|
||||||
|
/// An Id for the next canvas to use.
|
||||||
|
canvas_id: CanvasId,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// State needed to construct a constellation.
|
/// State needed to construct a constellation.
|
||||||
|
@ -626,6 +630,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}),
|
}),
|
||||||
webgl_threads: state.webgl_threads,
|
webgl_threads: state.webgl_threads,
|
||||||
webvr_chan: state.webvr_chan,
|
webvr_chan: state.webvr_chan,
|
||||||
|
canvas_id: CanvasId(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
constellation.run();
|
constellation.run();
|
||||||
|
@ -2203,11 +2208,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
fn handle_create_canvas_paint_thread_msg(
|
fn handle_create_canvas_paint_thread_msg(
|
||||||
&mut self,
|
&mut self,
|
||||||
size: &Size2D<i32>,
|
size: &Size2D<i32>,
|
||||||
response_sender: IpcSender<IpcSender<CanvasMsg>>) {
|
response_sender: IpcSender<(IpcSender<CanvasMsg>, CanvasId)>) {
|
||||||
|
self.canvas_id.0 += 1;
|
||||||
let webrender_api = self.webrender_api_sender.clone();
|
let webrender_api = self.webrender_api_sender.clone();
|
||||||
let sender = CanvasPaintThread::start(*size, webrender_api,
|
let sender = CanvasPaintThread::start(*size, webrender_api,
|
||||||
opts::get().enable_canvas_antialiasing);
|
opts::get().enable_canvas_antialiasing, self.canvas_id.clone());
|
||||||
if let Err(e) = response_sender.send(sender) {
|
if let Err(e) = response_sender.send((sender, self.canvas_id.clone())) {
|
||||||
warn!("Create canvas paint thread response failed ({})", e);
|
warn!("Create canvas paint thread response failed ({})", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1800,7 +1800,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
let ipc_renderer = ipc_renderer.lock().unwrap();
|
let ipc_renderer = ipc_renderer.lock().unwrap();
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
ipc_renderer
|
ipc_renderer
|
||||||
.send(CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender)))
|
.send(CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender),
|
||||||
|
canvas_fragment_info.canvas_id.clone()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
(receiver.recv().unwrap().image_key, PixelFormat::BGRA8)
|
(receiver.recv().unwrap().image_key, PixelFormat::BGRA8)
|
||||||
},
|
},
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
use ServoArc;
|
use ServoArc;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use canvas_traits::canvas::CanvasMsg;
|
use canvas_traits::canvas::{CanvasMsg, CanvasId};
|
||||||
use context::{LayoutContext, with_thread_local_font_context};
|
use context::{LayoutContext, with_thread_local_font_context};
|
||||||
use display_list::ToLayout;
|
use display_list::ToLayout;
|
||||||
use euclid::{Point2D, Vector2D, Rect, Size2D};
|
use euclid::{Point2D, Vector2D, Rect, Size2D};
|
||||||
|
@ -345,6 +345,7 @@ pub struct CanvasFragmentInfo {
|
||||||
pub source: CanvasFragmentSource,
|
pub source: CanvasFragmentSource,
|
||||||
pub dom_width: Au,
|
pub dom_width: Au,
|
||||||
pub dom_height: Au,
|
pub dom_height: Au,
|
||||||
|
pub canvas_id: CanvasId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CanvasFragmentInfo {
|
impl CanvasFragmentInfo {
|
||||||
|
@ -362,6 +363,7 @@ impl CanvasFragmentInfo {
|
||||||
source: source,
|
source: source,
|
||||||
dom_width: Au::from_px(data.width as i32),
|
dom_width: Au::from_px(data.width as i32),
|
||||||
dom_height: Au::from_px(data.height as i32),
|
dom_height: Au::from_px(data.height as i32),
|
||||||
|
canvas_id: data.canvas_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
//! `JSTraceable` to a datatype.
|
//! `JSTraceable` to a datatype.
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use canvas_traits::canvas::{CanvasGradientStop, LinearGradientStyle, RadialGradientStyle};
|
use canvas_traits::canvas::{CanvasGradientStop, CanvasId, LinearGradientStyle, RadialGradientStyle};
|
||||||
use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle};
|
use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle};
|
||||||
use canvas_traits::webgl::{WebGLBufferId, WebGLFramebufferId, WebGLProgramId, WebGLRenderbufferId};
|
use canvas_traits::webgl::{WebGLBufferId, WebGLFramebufferId, WebGLProgramId, WebGLRenderbufferId};
|
||||||
use canvas_traits::webgl::{WebGLChan, WebGLContextShareMode, WebGLError, WebGLPipeline, WebGLMsgSender};
|
use canvas_traits::webgl::{WebGLChan, WebGLContextShareMode, WebGLError, WebGLPipeline, WebGLMsgSender};
|
||||||
|
@ -423,6 +423,7 @@ unsafe_no_jsmanaged_fields!(WebVRGamepadHand);
|
||||||
unsafe_no_jsmanaged_fields!(ScriptToConstellationChan);
|
unsafe_no_jsmanaged_fields!(ScriptToConstellationChan);
|
||||||
unsafe_no_jsmanaged_fields!(InteractiveMetrics);
|
unsafe_no_jsmanaged_fields!(InteractiveMetrics);
|
||||||
unsafe_no_jsmanaged_fields!(InteractiveWindow);
|
unsafe_no_jsmanaged_fields!(InteractiveWindow);
|
||||||
|
unsafe_no_jsmanaged_fields!(CanvasId);
|
||||||
|
|
||||||
unsafe impl<'a> JSTraceable for &'a str {
|
unsafe impl<'a> JSTraceable for &'a str {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg};
|
use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg, CanvasId};
|
||||||
use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule};
|
use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule};
|
||||||
use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle};
|
use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle};
|
||||||
use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply};
|
use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply};
|
||||||
|
@ -78,6 +78,7 @@ pub struct CanvasRenderingContext2D {
|
||||||
state: DomRefCell<CanvasContextState>,
|
state: DomRefCell<CanvasContextState>,
|
||||||
saved_states: DomRefCell<Vec<CanvasContextState>>,
|
saved_states: DomRefCell<Vec<CanvasContextState>>,
|
||||||
origin_clean: Cell<bool>,
|
origin_clean: Cell<bool>,
|
||||||
|
canvas_id: CanvasId,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_root]
|
#[must_root]
|
||||||
|
@ -133,7 +134,7 @@ impl CanvasRenderingContext2D {
|
||||||
let script_to_constellation_chan = global.script_to_constellation_chan();
|
let script_to_constellation_chan = global.script_to_constellation_chan();
|
||||||
debug!("Asking constellation to create new canvas thread.");
|
debug!("Asking constellation to create new canvas thread.");
|
||||||
script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap();
|
script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap();
|
||||||
let ipc_renderer = receiver.recv().unwrap();
|
let (ipc_renderer, canvas_id) = receiver.recv().unwrap();
|
||||||
debug!("Done.");
|
debug!("Done.");
|
||||||
CanvasRenderingContext2D {
|
CanvasRenderingContext2D {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
|
@ -145,6 +146,7 @@ impl CanvasRenderingContext2D {
|
||||||
state: DomRefCell::new(CanvasContextState::new()),
|
state: DomRefCell::new(CanvasContextState::new()),
|
||||||
saved_states: DomRefCell::new(Vec::new()),
|
saved_states: DomRefCell::new(Vec::new()),
|
||||||
origin_clean: Cell::new(true),
|
origin_clean: Cell::new(true),
|
||||||
|
canvas_id: canvas_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +167,7 @@ impl CanvasRenderingContext2D {
|
||||||
pub fn set_bitmap_dimensions(&self, size: Size2D<i32>) {
|
pub fn set_bitmap_dimensions(&self, size: Size2D<i32>) {
|
||||||
self.reset_to_initial_state();
|
self.reset_to_initial_state();
|
||||||
self.ipc_renderer
|
self.ipc_renderer
|
||||||
.send(CanvasMsg::Recreate(size))
|
.send(CanvasMsg::Recreate(size, self.get_canvas_id()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,9 +184,7 @@ impl CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_transform(&self) {
|
fn update_transform(&self) {
|
||||||
self.ipc_renderer
|
self.send_canvas_2d_msg(Canvas2dMsg::SetTransform(self.state.borrow().transform))
|
||||||
.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetTransform(self.state.borrow().transform)))
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is used by DrawImage to calculate the size of the source and destination rectangles based
|
// It is used by DrawImage to calculate the size of the source and destination rectangles based
|
||||||
|
@ -363,9 +363,8 @@ impl CanvasRenderingContext2D {
|
||||||
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
|
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
|
||||||
|
|
||||||
if self.canvas.as_ref().map_or(false, |c| &**c == canvas) {
|
if self.canvas.as_ref().map_or(false, |c| &**c == canvas) {
|
||||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageSelf(
|
self.send_canvas_2d_msg(Canvas2dMsg::DrawImageSelf(
|
||||||
image_size, dest_rect, source_rect, smoothing_enabled));
|
image_size, dest_rect, source_rect, smoothing_enabled));
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
} else {
|
} else {
|
||||||
let context = match canvas.get_or_init_2d_context() {
|
let context = match canvas.get_or_init_2d_context() {
|
||||||
Some(context) => context,
|
Some(context) => context,
|
||||||
|
@ -375,11 +374,13 @@ impl CanvasRenderingContext2D {
|
||||||
let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
||||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageInOther(
|
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageInOther(
|
||||||
self.ipc_renderer.clone(),
|
self.ipc_renderer.clone(),
|
||||||
|
self.get_canvas_id(),
|
||||||
image_size,
|
image_size,
|
||||||
dest_rect,
|
dest_rect,
|
||||||
source_rect,
|
source_rect,
|
||||||
smoothing_enabled,
|
smoothing_enabled,
|
||||||
sender));
|
sender),
|
||||||
|
context.get_canvas_id());
|
||||||
|
|
||||||
let renderer = context.get_ipc_renderer();
|
let renderer = context.get_ipc_renderer();
|
||||||
renderer.send(msg).unwrap();
|
renderer.send(msg).unwrap();
|
||||||
|
@ -453,13 +454,13 @@ impl CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
|
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::DrawImage(
|
self.send_canvas_2d_msg(Canvas2dMsg::DrawImage(
|
||||||
image_data.into(),
|
image_data.into(),
|
||||||
image_size,
|
image_size,
|
||||||
dest_rect,
|
dest_rect,
|
||||||
source_rect,
|
source_rect,
|
||||||
smoothing_enabled,
|
smoothing_enabled,
|
||||||
))).unwrap();
|
));
|
||||||
self.mark_as_dirty();
|
self.mark_as_dirty();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -557,6 +558,14 @@ impl CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_canvas_id(&self) -> CanvasId {
|
||||||
|
self.canvas_id.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) {
|
||||||
|
self.ipc_renderer.send(CanvasMsg::Canvas2d(msg, self.get_canvas_id())).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> {
|
pub fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> {
|
||||||
self.ipc_renderer.clone()
|
self.ipc_renderer.clone()
|
||||||
}
|
}
|
||||||
|
@ -573,6 +582,8 @@ impl CanvasRenderingContext2D {
|
||||||
pub trait LayoutCanvasRenderingContext2DHelpers {
|
pub trait LayoutCanvasRenderingContext2DHelpers {
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg>;
|
unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg>;
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe fn get_canvas_id(&self) -> CanvasId;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<CanvasRenderingContext2D> {
|
impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<CanvasRenderingContext2D> {
|
||||||
|
@ -580,6 +591,11 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<CanvasRenderingContext2
|
||||||
unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> {
|
unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> {
|
||||||
(*self.unsafe_get()).ipc_renderer.clone()
|
(*self.unsafe_get()).ipc_renderer.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe fn get_canvas_id(&self) -> CanvasId {
|
||||||
|
(*self.unsafe_get()).canvas_id.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We add a guard to each of methods by the spec:
|
// We add a guard to each of methods by the spec:
|
||||||
|
@ -602,7 +618,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-save
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-save
|
||||||
fn Save(&self) {
|
fn Save(&self) {
|
||||||
self.saved_states.borrow_mut().push(self.state.borrow().clone());
|
self.saved_states.borrow_mut().push(self.state.borrow().clone());
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SaveContext)).unwrap();
|
self.send_canvas_2d_msg(Canvas2dMsg::SaveContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
|
@ -611,7 +627,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
let mut saved_states = self.saved_states.borrow_mut();
|
let mut saved_states = self.saved_states.borrow_mut();
|
||||||
if let Some(state) = saved_states.pop() {
|
if let Some(state) = saved_states.pop() {
|
||||||
self.state.borrow_mut().clone_from(&state);
|
self.state.borrow_mut().clone_from(&state);
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::RestoreContext)).unwrap();
|
self.send_canvas_2d_msg(Canvas2dMsg::RestoreContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,9 +712,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state.borrow_mut().global_alpha = alpha;
|
self.state.borrow_mut().global_alpha = alpha;
|
||||||
self.ipc_renderer
|
self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalAlpha(alpha as f32))
|
||||||
.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetGlobalAlpha(alpha as f32)))
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation
|
||||||
|
@ -714,16 +728,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
fn SetGlobalCompositeOperation(&self, op_str: DOMString) {
|
fn SetGlobalCompositeOperation(&self, op_str: DOMString) {
|
||||||
if let Ok(op) = CompositionOrBlending::from_str(&op_str) {
|
if let Ok(op) = CompositionOrBlending::from_str(&op_str) {
|
||||||
self.state.borrow_mut().global_composition = op;
|
self.state.borrow_mut().global_composition = op;
|
||||||
self.ipc_renderer
|
self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalComposition(op))
|
||||||
.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetGlobalComposition(op)))
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect
|
||||||
fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) {
|
fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) {
|
||||||
if let Some(rect) = self.create_drawable_rect(x, y, width, height) {
|
if let Some(rect) = self.create_drawable_rect(x, y, width, height) {
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::FillRect(rect))).unwrap();
|
self.send_canvas_2d_msg(Canvas2dMsg::FillRect(rect));
|
||||||
self.mark_as_dirty();
|
self.mark_as_dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -731,9 +743,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect
|
||||||
fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) {
|
fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) {
|
||||||
if let Some(rect) = self.create_drawable_rect(x, y, width, height) {
|
if let Some(rect) = self.create_drawable_rect(x, y, width, height) {
|
||||||
self.ipc_renderer
|
self.send_canvas_2d_msg(Canvas2dMsg::ClearRect(rect));
|
||||||
.send(CanvasMsg::Canvas2d(Canvas2dMsg::ClearRect(rect)))
|
|
||||||
.unwrap();
|
|
||||||
self.mark_as_dirty();
|
self.mark_as_dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -741,40 +751,38 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect
|
||||||
fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) {
|
fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) {
|
||||||
if let Some(rect) = self.create_drawable_rect(x, y, width, height) {
|
if let Some(rect) = self.create_drawable_rect(x, y, width, height) {
|
||||||
self.ipc_renderer
|
self.send_canvas_2d_msg(Canvas2dMsg::StrokeRect(rect));
|
||||||
.send(CanvasMsg::Canvas2d(Canvas2dMsg::StrokeRect(rect)))
|
|
||||||
.unwrap();
|
|
||||||
self.mark_as_dirty();
|
self.mark_as_dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath
|
||||||
fn BeginPath(&self) {
|
fn BeginPath(&self) {
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::BeginPath)).unwrap();
|
self.send_canvas_2d_msg(Canvas2dMsg::BeginPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath
|
||||||
fn ClosePath(&self) {
|
fn ClosePath(&self) {
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::ClosePath)).unwrap();
|
self.send_canvas_2d_msg(Canvas2dMsg::ClosePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-fill
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-fill
|
||||||
fn Fill(&self, _: CanvasFillRule) {
|
fn Fill(&self, _: CanvasFillRule) {
|
||||||
// TODO: Process fill rule
|
// TODO: Process fill rule
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Fill)).unwrap();
|
self.send_canvas_2d_msg(Canvas2dMsg::Fill);
|
||||||
self.mark_as_dirty();
|
self.mark_as_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke
|
||||||
fn Stroke(&self) {
|
fn Stroke(&self) {
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Stroke)).unwrap();
|
self.send_canvas_2d_msg(Canvas2dMsg::Stroke);
|
||||||
self.mark_as_dirty();
|
self.mark_as_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-clip
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-clip
|
||||||
fn Clip(&self, _: CanvasFillRule) {
|
fn Clip(&self, _: CanvasFillRule) {
|
||||||
// TODO: Process fill rule
|
// TODO: Process fill rule
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Clip)).unwrap();
|
self.send_canvas_2d_msg(Canvas2dMsg::Clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath
|
||||||
|
@ -784,16 +792,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
CanvasFillRule::Evenodd => FillRule::Evenodd,
|
CanvasFillRule::Evenodd => FillRule::Evenodd,
|
||||||
};
|
};
|
||||||
let (sender, receiver) = ipc::channel::<bool>(self.global().time_profiler_chan().clone()).unwrap();
|
let (sender, receiver) = ipc::channel::<bool>(self.global().time_profiler_chan().clone()).unwrap();
|
||||||
self.ipc_renderer
|
self.send_canvas_2d_msg(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender));
|
||||||
.send(CanvasMsg::Canvas2d(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender)))
|
|
||||||
.unwrap();
|
|
||||||
receiver.recv().unwrap()
|
receiver.recv().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext
|
||||||
fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) {
|
fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) {
|
||||||
let parsed_text: String = text.into();
|
let parsed_text: String = text.into();
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::FillText(parsed_text, x, y, max_width))).unwrap();
|
self.send_canvas_2d_msg(Canvas2dMsg::FillText(parsed_text, x, y, max_width));
|
||||||
self.mark_as_dirty();
|
self.mark_as_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -858,9 +864,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
if !(x.is_finite() && y.is_finite()) {
|
if !(x.is_finite() && y.is_finite()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
self.send_canvas_2d_msg(Canvas2dMsg::MoveTo(Point2D::new(x as f32, y as f32)));
|
||||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::MoveTo(Point2D::new(x as f32, y as f32)));
|
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto
|
||||||
|
@ -868,9 +872,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
if !(x.is_finite() && y.is_finite()) {
|
if !(x.is_finite() && y.is_finite()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
self.send_canvas_2d_msg(Canvas2dMsg::LineTo(Point2D::new(x as f32, y as f32)));
|
||||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::LineTo(Point2D::new(x as f32, y as f32)));
|
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-rect
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-rect
|
||||||
|
@ -878,8 +880,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
if [x, y, width, height].iter().all(|val| val.is_finite()) {
|
if [x, y, width, height].iter().all(|val| val.is_finite()) {
|
||||||
let rect = Rect::new(Point2D::new(x as f32, y as f32),
|
let rect = Rect::new(Point2D::new(x as f32, y as f32),
|
||||||
Size2D::new(width as f32, height as f32));
|
Size2D::new(width as f32, height as f32));
|
||||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::Rect(rect));
|
self.send_canvas_2d_msg(Canvas2dMsg::Rect(rect));
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,12 +889,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
if !(cpx.is_finite() && cpy.is_finite() && x.is_finite() && y.is_finite()) {
|
if !(cpx.is_finite() && cpy.is_finite() && x.is_finite() && y.is_finite()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
self.send_canvas_2d_msg(Canvas2dMsg::QuadraticCurveTo(Point2D::new(cpx as f32,
|
||||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::QuadraticCurveTo(Point2D::new(cpx as f32,
|
cpy as f32),
|
||||||
cpy as f32),
|
Point2D::new(x as f32,
|
||||||
Point2D::new(x as f32,
|
y as f32)));
|
||||||
y as f32)));
|
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto
|
||||||
|
@ -902,13 +901,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
x.is_finite() && y.is_finite()) {
|
x.is_finite() && y.is_finite()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
self.send_canvas_2d_msg(Canvas2dMsg::BezierCurveTo(Point2D::new(cp1x as f32,
|
||||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::BezierCurveTo(Point2D::new(cp1x as f32,
|
cp1y as f32),
|
||||||
cp1y as f32),
|
Point2D::new(cp2x as f32,
|
||||||
Point2D::new(cp2x as f32,
|
cp2y as f32),
|
||||||
cp2y as f32),
|
Point2D::new(x as f32, y as f32)));
|
||||||
Point2D::new(x as f32, y as f32)));
|
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-arc
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-arc
|
||||||
|
@ -921,13 +918,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
return Err(Error::IndexSize);
|
return Err(Error::IndexSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::Arc(Point2D::new(x as f32, y as f32),
|
self.send_canvas_2d_msg(Canvas2dMsg::Arc(Point2D::new(x as f32, y as f32),
|
||||||
r as f32,
|
r as f32,
|
||||||
start as f32,
|
start as f32,
|
||||||
end as f32,
|
end as f32,
|
||||||
ccw));
|
ccw));
|
||||||
|
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -940,10 +935,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
return Err(Error::IndexSize);
|
return Err(Error::IndexSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::ArcTo(Point2D::new(cp1x as f32, cp1y as f32),
|
self.send_canvas_2d_msg(Canvas2dMsg::ArcTo(Point2D::new(cp1x as f32, cp1y as f32),
|
||||||
Point2D::new(cp2x as f32, cp2y as f32),
|
Point2D::new(cp2x as f32, cp2y as f32),
|
||||||
r as f32));
|
r as f32));
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -956,14 +950,13 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
return Err(Error::IndexSize);
|
return Err(Error::IndexSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::Ellipse(Point2D::new(x as f32, y as f32),
|
self.send_canvas_2d_msg(Canvas2dMsg::Ellipse(Point2D::new(x as f32, y as f32),
|
||||||
rx as f32,
|
rx as f32,
|
||||||
ry as f32,
|
ry as f32,
|
||||||
rotation as f32,
|
rotation as f32,
|
||||||
start as f32,
|
start as f32,
|
||||||
end as f32,
|
end as f32,
|
||||||
ccw));
|
ccw));
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1001,25 +994,19 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
StringOrCanvasGradientOrCanvasPattern::String(string) => {
|
StringOrCanvasGradientOrCanvasPattern::String(string) => {
|
||||||
if let Ok(rgba) = self.parse_color(&string) {
|
if let Ok(rgba) = self.parse_color(&string) {
|
||||||
self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Color(rgba);
|
self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Color(rgba);
|
||||||
self.ipc_renderer
|
self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(
|
||||||
.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetStrokeStyle(
|
FillOrStrokeStyle::Color(rgba)));
|
||||||
FillOrStrokeStyle::Color(rgba))))
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => {
|
StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => {
|
||||||
self.state.borrow_mut().stroke_style =
|
self.state.borrow_mut().stroke_style =
|
||||||
CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient));
|
CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient));
|
||||||
let msg = CanvasMsg::Canvas2d(
|
self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(gradient.to_fill_or_stroke_style()));
|
||||||
Canvas2dMsg::SetStrokeStyle(gradient.to_fill_or_stroke_style()));
|
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
},
|
},
|
||||||
StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => {
|
StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => {
|
||||||
self.state.borrow_mut().stroke_style =
|
self.state.borrow_mut().stroke_style =
|
||||||
CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern));
|
CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern));
|
||||||
let msg = CanvasMsg::Canvas2d(
|
self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(pattern.to_fill_or_stroke_style()));
|
||||||
Canvas2dMsg::SetStrokeStyle(pattern.to_fill_or_stroke_style()));
|
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
if !pattern.origin_is_clean() {
|
if !pattern.origin_is_clean() {
|
||||||
self.set_origin_unclean();
|
self.set_origin_unclean();
|
||||||
}
|
}
|
||||||
|
@ -1050,25 +1037,19 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
StringOrCanvasGradientOrCanvasPattern::String(string) => {
|
StringOrCanvasGradientOrCanvasPattern::String(string) => {
|
||||||
if let Ok(rgba) = self.parse_color(&string) {
|
if let Ok(rgba) = self.parse_color(&string) {
|
||||||
self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Color(rgba);
|
self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Color(rgba);
|
||||||
self.ipc_renderer
|
self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(
|
||||||
.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetFillStyle(
|
FillOrStrokeStyle::Color(rgba)))
|
||||||
FillOrStrokeStyle::Color(rgba))))
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => {
|
StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => {
|
||||||
self.state.borrow_mut().fill_style =
|
self.state.borrow_mut().fill_style =
|
||||||
CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient));
|
CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient));
|
||||||
let msg = CanvasMsg::Canvas2d(
|
self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(gradient.to_fill_or_stroke_style()));
|
||||||
Canvas2dMsg::SetFillStyle(gradient.to_fill_or_stroke_style()));
|
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
}
|
}
|
||||||
StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => {
|
StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => {
|
||||||
self.state.borrow_mut().fill_style =
|
self.state.borrow_mut().fill_style =
|
||||||
CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern));
|
CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern));
|
||||||
let msg = CanvasMsg::Canvas2d(
|
self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(pattern.to_fill_or_stroke_style()));
|
||||||
Canvas2dMsg::SetFillStyle(pattern.to_fill_or_stroke_style()));
|
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
if !pattern.origin_is_clean() {
|
if !pattern.origin_is_clean() {
|
||||||
self.set_origin_unclean();
|
self.set_origin_unclean();
|
||||||
}
|
}
|
||||||
|
@ -1132,10 +1113,8 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
Size2D::new(sw as i32, sh as i32));
|
Size2D::new(sw as i32, sh as i32));
|
||||||
let canvas_size = self.canvas.as_ref().map(|c| c.get_size()).unwrap_or(Size2D::zero());
|
let canvas_size = self.canvas.as_ref().map(|c| c.get_size()).unwrap_or(Size2D::zero());
|
||||||
let canvas_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64);
|
let canvas_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64);
|
||||||
self.ipc_renderer
|
self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender));
|
||||||
.send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender)))
|
let mut data = receiver.recv().unwrap();
|
||||||
.unwrap();
|
|
||||||
let mut data = Vec::from(receiver.recv().unwrap());
|
|
||||||
|
|
||||||
// Un-premultiply alpha
|
// Un-premultiply alpha
|
||||||
for chunk in data.chunks_mut(4) {
|
for chunk in data.chunks_mut(4) {
|
||||||
|
@ -1145,7 +1124,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
chunk[2] = UNPREMULTIPLY_TABLE[256 * alpha + chunk[2] as usize];
|
chunk[2] = UNPREMULTIPLY_TABLE[256 * alpha + chunk[2] as usize];
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageData::new(&self.global(), sw, sh, Some(data))
|
ImageData::new(&self.global(), sw, sh, Some(data.to_vec()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
|
||||||
|
@ -1174,13 +1153,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
|
|
||||||
let dirty_rect = Rect::new(Point2D::new(*dirty_x, *dirty_y),
|
let dirty_rect = Rect::new(Point2D::new(*dirty_x, *dirty_y),
|
||||||
Size2D::new(*dirty_width, *dirty_height));
|
Size2D::new(*dirty_width, *dirty_height));
|
||||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::PutImageData(
|
self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(data.into(),
|
||||||
data.into(),
|
offset,
|
||||||
offset,
|
image_data_size,
|
||||||
image_data_size,
|
dirty_rect));
|
||||||
dirty_rect,
|
|
||||||
));
|
|
||||||
self.ipc_renderer.send(msg).unwrap();
|
|
||||||
self.mark_as_dirty();
|
self.mark_as_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1282,9 +1258,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state.borrow_mut().line_width = width;
|
self.state.borrow_mut().line_width = width;
|
||||||
self.ipc_renderer
|
self.send_canvas_2d_msg(Canvas2dMsg::SetLineWidth(width as f32))
|
||||||
.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineWidth(width as f32)))
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap
|
||||||
|
@ -1304,7 +1278,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
CanvasLineCap::Square => LineCapStyle::Square,
|
CanvasLineCap::Square => LineCapStyle::Square,
|
||||||
};
|
};
|
||||||
self.state.borrow_mut().line_cap = line_cap;
|
self.state.borrow_mut().line_cap = line_cap;
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineCap(line_cap))).unwrap();
|
self.send_canvas_2d_msg(Canvas2dMsg::SetLineCap(line_cap));
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin
|
||||||
|
@ -1324,7 +1298,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
CanvasLineJoin::Miter => LineJoinStyle::Miter,
|
CanvasLineJoin::Miter => LineJoinStyle::Miter,
|
||||||
};
|
};
|
||||||
self.state.borrow_mut().line_join = line_join;
|
self.state.borrow_mut().line_join = line_join;
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineJoin(line_join))).unwrap();
|
self.send_canvas_2d_msg(Canvas2dMsg::SetLineJoin(line_join));
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit
|
||||||
|
@ -1340,9 +1314,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state.borrow_mut().miter_limit = limit;
|
self.state.borrow_mut().miter_limit = limit;
|
||||||
self.ipc_renderer
|
self.send_canvas_2d_msg(Canvas2dMsg::SetMiterLimit(limit as f32))
|
||||||
.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetMiterLimit(limit as f32)))
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx
|
||||||
|
@ -1356,7 +1328,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.state.borrow_mut().shadow_offset_x = value;
|
self.state.borrow_mut().shadow_offset_x = value;
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetShadowOffsetX(value))).unwrap()
|
self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetX(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety
|
||||||
|
@ -1370,7 +1342,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.state.borrow_mut().shadow_offset_y = value;
|
self.state.borrow_mut().shadow_offset_y = value;
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetShadowOffsetY(value))).unwrap()
|
self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetY(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur
|
||||||
|
@ -1384,7 +1356,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.state.borrow_mut().shadow_blur = value;
|
self.state.borrow_mut().shadow_blur = value;
|
||||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetShadowBlur(value))).unwrap()
|
self.send_canvas_2d_msg(Canvas2dMsg::SetShadowBlur(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor
|
||||||
|
@ -1398,16 +1370,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
fn SetShadowColor(&self, value: DOMString) {
|
fn SetShadowColor(&self, value: DOMString) {
|
||||||
if let Ok(color) = parse_color(&value) {
|
if let Ok(color) = parse_color(&value) {
|
||||||
self.state.borrow_mut().shadow_color = color;
|
self.state.borrow_mut().shadow_color = color;
|
||||||
self.ipc_renderer
|
self.send_canvas_2d_msg(Canvas2dMsg::SetShadowColor(color))
|
||||||
.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetShadowColor(color)))
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for CanvasRenderingContext2D {
|
impl Drop for CanvasRenderingContext2D {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close) {
|
if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close(self.get_canvas_id())) {
|
||||||
warn!("Could not close canvas: {}", err)
|
warn!("Could not close canvas: {}", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use base64;
|
use base64;
|
||||||
use canvas_traits::canvas::{CanvasMsg, FromScriptMsg};
|
use canvas_traits::canvas::{CanvasMsg, CanvasId, FromScriptMsg};
|
||||||
use canvas_traits::webgl::WebGLVersion;
|
use canvas_traits::webgl::WebGLVersion;
|
||||||
use dom::attr::Attr;
|
use dom::attr::Attr;
|
||||||
use dom::bindings::cell::DomRefCell;
|
use dom::bindings::cell::DomRefCell;
|
||||||
|
@ -105,6 +105,7 @@ pub trait LayoutHTMLCanvasElementHelpers {
|
||||||
fn data(&self) -> HTMLCanvasData;
|
fn data(&self) -> HTMLCanvasData;
|
||||||
fn get_width(&self) -> LengthOrPercentageOrAuto;
|
fn get_width(&self) -> LengthOrPercentageOrAuto;
|
||||||
fn get_height(&self) -> LengthOrPercentageOrAuto;
|
fn get_height(&self) -> LengthOrPercentageOrAuto;
|
||||||
|
fn get_canvas_id_for_layout(&self) -> CanvasId;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutHTMLCanvasElementHelpers for LayoutDom<HTMLCanvasElement> {
|
impl LayoutHTMLCanvasElementHelpers for LayoutDom<HTMLCanvasElement> {
|
||||||
|
@ -133,6 +134,7 @@ impl LayoutHTMLCanvasElementHelpers for LayoutDom<HTMLCanvasElement> {
|
||||||
source: source,
|
source: source,
|
||||||
width: width_attr.map_or(DEFAULT_WIDTH, |val| val.as_uint()),
|
width: width_attr.map_or(DEFAULT_WIDTH, |val| val.as_uint()),
|
||||||
height: height_attr.map_or(DEFAULT_HEIGHT, |val| val.as_uint()),
|
height: height_attr.map_or(DEFAULT_HEIGHT, |val| val.as_uint()),
|
||||||
|
canvas_id: self.get_canvas_id_for_layout(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,6 +158,18 @@ impl LayoutHTMLCanvasElementHelpers for LayoutDom<HTMLCanvasElement> {
|
||||||
.unwrap_or(LengthOrPercentageOrAuto::Auto)
|
.unwrap_or(LengthOrPercentageOrAuto::Auto)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
fn get_canvas_id_for_layout(&self) -> CanvasId {
|
||||||
|
unsafe {
|
||||||
|
let canvas = &*self.unsafe_get();
|
||||||
|
if let &Some(CanvasContext::Context2d(ref context)) = canvas.context.borrow_for_layout() {
|
||||||
|
context.to_layout().get_canvas_id()
|
||||||
|
} else {
|
||||||
|
CanvasId(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -261,7 +275,7 @@ impl HTMLCanvasElement {
|
||||||
let data = match self.context.borrow().as_ref() {
|
let data = match self.context.borrow().as_ref() {
|
||||||
Some(&CanvasContext::Context2d(ref context)) => {
|
Some(&CanvasContext::Context2d(ref context)) => {
|
||||||
let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
|
||||||
let msg = CanvasMsg::FromScript(FromScriptMsg::SendPixels(sender));
|
let msg = CanvasMsg::FromScript(FromScriptMsg::SendPixels(sender), context.get_canvas_id());
|
||||||
context.get_ipc_renderer().send(msg).unwrap();
|
context.get_ipc_renderer().send(msg).unwrap();
|
||||||
|
|
||||||
receiver.recv().unwrap()?.into()
|
receiver.recv().unwrap()?.into()
|
||||||
|
|
|
@ -59,7 +59,7 @@ impl PaintRenderingContext2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_data(&self, sender: IpcSender<CanvasImageData>) {
|
pub fn send_data(&self, sender: IpcSender<CanvasImageData>) {
|
||||||
let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender));
|
let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender), self.context.get_canvas_id());
|
||||||
let _ = self.context.get_ipc_renderer().send(msg);
|
let _ = self.context.get_ipc_renderer().send(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ pub mod rpc;
|
||||||
pub mod wrapper_traits;
|
pub mod wrapper_traits;
|
||||||
|
|
||||||
use atomic_refcell::AtomicRefCell;
|
use atomic_refcell::AtomicRefCell;
|
||||||
use canvas_traits::canvas::CanvasMsg;
|
use canvas_traits::canvas::{CanvasMsg, CanvasId};
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
use net_traits::image_cache::PendingImageId;
|
use net_traits::image_cache::PendingImageId;
|
||||||
|
@ -133,6 +133,7 @@ pub struct HTMLCanvasData {
|
||||||
pub source: HTMLCanvasDataSource,
|
pub source: HTMLCanvasDataSource,
|
||||||
pub width: u32,
|
pub width: u32,
|
||||||
pub height: u32,
|
pub height: u32,
|
||||||
|
pub canvas_id: CanvasId,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SVGSVGData {
|
pub struct SVGSVGData {
|
||||||
|
|
|
@ -11,7 +11,7 @@ use LayoutControlMsg;
|
||||||
use LoadData;
|
use LoadData;
|
||||||
use WorkerGlobalScopeInit;
|
use WorkerGlobalScopeInit;
|
||||||
use WorkerScriptLoadOrigin;
|
use WorkerScriptLoadOrigin;
|
||||||
use canvas_traits::canvas::CanvasMsg;
|
use canvas_traits::canvas::{CanvasMsg, CanvasId};
|
||||||
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
||||||
use euclid::{Size2D, TypedSize2D};
|
use euclid::{Size2D, TypedSize2D};
|
||||||
use gfx_traits::Epoch;
|
use gfx_traits::Epoch;
|
||||||
|
@ -79,7 +79,7 @@ pub enum ScriptMsg {
|
||||||
ChangeRunningAnimationsState(AnimationState),
|
ChangeRunningAnimationsState(AnimationState),
|
||||||
/// Requests that a new 2D canvas thread be created. (This is done in the constellation because
|
/// Requests that a new 2D canvas thread be created. (This is done in the constellation because
|
||||||
/// 2D canvases may use the GPU and we don't want to give untrusted content access to the GPU.)
|
/// 2D canvases may use the GPU and we don't want to give untrusted content access to the GPU.)
|
||||||
CreateCanvasPaintThread(Size2D<i32>, IpcSender<IpcSender<CanvasMsg>>),
|
CreateCanvasPaintThread(Size2D<i32>, IpcSender<(IpcSender<CanvasMsg>, CanvasId)>),
|
||||||
/// Notifies the constellation that this frame has received focus.
|
/// Notifies the constellation that this frame has received focus.
|
||||||
Focus,
|
Focus,
|
||||||
/// Forward an event that was sent to the parent window.
|
/// Forward an event that was sent to the parent window.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
|
@ -130,7 +130,7 @@ destCanvas = {
|
||||||
height: 50
|
height: 50
|
||||||
};
|
};
|
||||||
|
|
||||||
drawImage(0, 0);
|
drawImage(0, 0);
|
||||||
|
|
||||||
function renderExample(title) {
|
function renderExample(title) {
|
||||||
var container = document.createElement('div');
|
var container = document.createElement('div');
|
||||||
|
|
165
tests/html/test_canvas_drawimage_canvas_timed.html
Normal file
165
tests/html/test_canvas_drawimage_canvas_timed.html
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
</head>
|
||||||
|
<style type=''>
|
||||||
|
html {
|
||||||
|
font-family: helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
padding: 15px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example {
|
||||||
|
display: inline-block;
|
||||||
|
width: 280px;
|
||||||
|
margin-top: 50px;
|
||||||
|
margin-right: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description div {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description .source {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description .target {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-title {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<h1 class="title">Timed DrawImage canvas to canvas</h1>
|
||||||
|
<h4 class="title", id="Test Result">This text is where the timing result will go...</h4>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var smoothingEnabled = false;
|
||||||
|
var examplesNum = 0;
|
||||||
|
|
||||||
|
var imageSource = {
|
||||||
|
width: 50,
|
||||||
|
height: 50
|
||||||
|
};
|
||||||
|
|
||||||
|
var destCanvas = {
|
||||||
|
width: 100,
|
||||||
|
height: 100
|
||||||
|
};
|
||||||
|
|
||||||
|
var t0 = performance.now(); //save starting time
|
||||||
|
drawImage(25, 25); // The source canvas will copied to the 25,25 position of the destination canvas
|
||||||
|
var t1 = performance.now(); //save ending time
|
||||||
|
document.getElementById('Test Result').innerHTML = "DrawImage took " + (t1 - t0) + " milliseconds."; //print to browser
|
||||||
|
console.log("DrawImage took " + (t1 - t0) + " milliseconds."); //print to console
|
||||||
|
|
||||||
|
function renderExample(title) {
|
||||||
|
var container = document.createElement('div');
|
||||||
|
container.id = 'example' + examplesNum++;
|
||||||
|
container.setAttribute('class', 'example');
|
||||||
|
|
||||||
|
var h2 = document.createElement('h2');
|
||||||
|
h2.textContent = title;
|
||||||
|
h2.setAttribute('class', 'example-title');
|
||||||
|
container.appendChild(h2);
|
||||||
|
|
||||||
|
var div1 = document.createElement('div');
|
||||||
|
var canvas1 = document.createElement('canvas');
|
||||||
|
var canvas2 = document.createElement('canvas');
|
||||||
|
div1.appendChild(canvas1);
|
||||||
|
div1.appendChild(canvas2);
|
||||||
|
container.appendChild(div1);
|
||||||
|
|
||||||
|
var div2 = document.createElement('div');
|
||||||
|
div2.setAttribute('class', 'description');
|
||||||
|
var source = document.createElement('div');
|
||||||
|
source.textContent = ' Source (' + imageSource.width + ',' + imageSource.height + ')';
|
||||||
|
source.setAttribute('class', 'source');
|
||||||
|
|
||||||
|
var arrow = document.createElement('div');
|
||||||
|
arrow.textContent = ' -> ';
|
||||||
|
arrow.setAttribute('class', 'arrow');
|
||||||
|
|
||||||
|
var target = document.createElement('div');
|
||||||
|
target.textContent = 'Target (' + destCanvas.width + ',' + destCanvas.height + ')';
|
||||||
|
target.setAttribute('class', 'target');
|
||||||
|
|
||||||
|
div2.appendChild(source);
|
||||||
|
div2.appendChild(arrow);
|
||||||
|
div2.appendChild(target);
|
||||||
|
container.appendChild(div2);
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawImage() {
|
||||||
|
var args = Array.prototype.slice.call(arguments);
|
||||||
|
|
||||||
|
var div = renderExample('drawImage(' + args.toString() + ')');
|
||||||
|
var canvasEls = div.querySelectorAll('canvas');
|
||||||
|
var canvas1 = canvasEls[0];
|
||||||
|
var canvas2 = canvasEls[1];
|
||||||
|
|
||||||
|
canvas1.width = imageSource.width;
|
||||||
|
canvas1.height = imageSource.height;
|
||||||
|
|
||||||
|
var ctx1 = canvas1.getContext('2d');
|
||||||
|
ctx1.fillStyle = "#00FFFF";
|
||||||
|
ctx1.fillRect(0, 0, imageSource.width, imageSource.height);
|
||||||
|
|
||||||
|
ctx1.fillStyle = "#000000";
|
||||||
|
ctx1.fillRect(5,5,40,40);
|
||||||
|
ctx1.clearRect(10,10,30,30);
|
||||||
|
ctx1.strokeRect(15,15,20,20);
|
||||||
|
|
||||||
|
canvas2.width = destCanvas.width;
|
||||||
|
canvas2.height = destCanvas.height;
|
||||||
|
|
||||||
|
var ctx2 = canvas2.getContext('2d');
|
||||||
|
ctx2.fillStyle = "#FF0000";
|
||||||
|
ctx2.fillRect(0, 0, destCanvas.width, destCanvas.height);
|
||||||
|
ctx2.imageSmoothingEnabled = smoothingEnabled;
|
||||||
|
|
||||||
|
args.unshift(canvas1);
|
||||||
|
try {
|
||||||
|
ctx2.drawImage.apply(ctx2, args);
|
||||||
|
}
|
||||||
|
catch(err) {
|
||||||
|
var title = div.querySelector('.example-title');
|
||||||
|
var error = document.createElement('h2');
|
||||||
|
error.setAttribute('class', 'example-title error');
|
||||||
|
div.insertBefore(error, title);
|
||||||
|
error.textContent += "Call Failed: " + err.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.appendChild(div);
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue