diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2020-01-25 22:06:47 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-25 22:06:47 -0500 |
commit | 0bd266149263cbdcd0ddd677ab3a7eaa0322b660 (patch) | |
tree | b68daa966a4e2ac3c75d4f8e63ea751ffb0df40e | |
parent | 694bb408cc4d59394ca2698967606f28ba053e43 (diff) | |
parent | 5a773bf55a3dfd1b486887c3c36bafe0cbe58f2e (diff) | |
download | servo-0bd266149263cbdcd0ddd677ab3a7eaa0322b660.tar.gz servo-0bd266149263cbdcd0ddd677ab3a7eaa0322b660.zip |
Auto merge of #25603 - pylbrecht:raqote, r=jdm
Update CanvasRenderingContext2D fillStyle and strokeStyle only when required
So far fill and stroke style updates have been sent to the canvas paint
thread by `SetFillStyle()` and `SetStrokeStyle()`. This resulted in
fill/stroke style updates not being considered by the canvas paint
thread between the latest call of `SetFillStyle()`/`SetStrokeStyle()` and
the drawing operation (e.g. fill or stroke).
This issue is solved by making `SetFillStyle()` and `SetStrokeStyle()`
update the local canvas state and propagating the state to the canvas
paint thread along with the drawing operations that require it.
<!-- Please describe your changes on the following line: -->
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix part of #25331
<!-- Either: -->
- [x] There are tests for these changes
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
7 files changed, 44 insertions, 55 deletions
diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs index a1932a0e56f..80017dc194a 100644 --- a/components/canvas/canvas_paint_thread.rs +++ b/components/canvas/canvas_paint_thread.rs @@ -121,16 +121,29 @@ impl<'a> CanvasPaintThread<'a> { fn process_canvas_2d_message(&mut self, message: Canvas2dMsg, canvas_id: CanvasId) { match message { - Canvas2dMsg::FillText(text, x, y, max_width) => { - self.canvas(canvas_id).fill_text(text, x, y, max_width) + Canvas2dMsg::FillText(text, x, y, max_width, style) => { + self.canvas(canvas_id).set_fill_style(style); + self.canvas(canvas_id).fill_text(text, x, y, max_width); + }, + Canvas2dMsg::FillRect(rect, style) => { + self.canvas(canvas_id).set_fill_style(style); + self.canvas(canvas_id).fill_rect(&rect); + }, + Canvas2dMsg::StrokeRect(rect, style) => { + self.canvas(canvas_id).set_stroke_style(style); + self.canvas(canvas_id).stroke_rect(&rect); }, - Canvas2dMsg::FillRect(ref rect) => self.canvas(canvas_id).fill_rect(rect), - Canvas2dMsg::StrokeRect(ref rect) => self.canvas(canvas_id).stroke_rect(rect), Canvas2dMsg::ClearRect(ref rect) => self.canvas(canvas_id).clear_rect(rect), Canvas2dMsg::BeginPath => self.canvas(canvas_id).begin_path(), Canvas2dMsg::ClosePath => self.canvas(canvas_id).close_path(), - Canvas2dMsg::Fill => self.canvas(canvas_id).fill(), - Canvas2dMsg::Stroke => self.canvas(canvas_id).stroke(), + Canvas2dMsg::Fill(style) => { + self.canvas(canvas_id).set_fill_style(style); + self.canvas(canvas_id).fill(); + }, + Canvas2dMsg::Stroke(style) => { + self.canvas(canvas_id).set_stroke_style(style); + self.canvas(canvas_id).stroke(); + }, Canvas2dMsg::Clip => self.canvas(canvas_id).clip(), Canvas2dMsg::IsPointInPath(x, y, fill_rule, chan) => self .canvas(canvas_id) @@ -192,8 +205,6 @@ impl<'a> CanvasPaintThread<'a> { .ellipse(center, radius_x, radius_y, rotation, start, end, ccw), Canvas2dMsg::RestoreContext => self.canvas(canvas_id).restore_context_state(), Canvas2dMsg::SaveContext => self.canvas(canvas_id).save_context_state(), - Canvas2dMsg::SetFillStyle(style) => self.canvas(canvas_id).set_fill_style(style), - Canvas2dMsg::SetStrokeStyle(style) => self.canvas(canvas_id).set_stroke_style(style), Canvas2dMsg::SetLineWidth(width) => self.canvas(canvas_id).set_line_width(width), Canvas2dMsg::SetLineCap(cap) => self.canvas(canvas_id).set_line_cap(cap), Canvas2dMsg::SetLineJoin(join) => self.canvas(canvas_id).set_line_join(join), diff --git a/components/canvas_traits/canvas.rs b/components/canvas_traits/canvas.rs index ee659e16f3a..b203399a200 100644 --- a/components/canvas_traits/canvas.rs +++ b/components/canvas_traits/canvas.rs @@ -44,9 +44,9 @@ pub enum Canvas2dMsg { Clip, ClosePath, Ellipse(Point2D<f32>, f32, f32, f32, f32, f32, bool), - Fill, - FillText(String, f64, f64, Option<f64>), - FillRect(Rect<f32>), + Fill(FillOrStrokeStyle), + FillText(String, f64, f64, Option<f64>, FillOrStrokeStyle), + FillRect(Rect<f32>, FillOrStrokeStyle), GetImageData(Rect<u64>, Size2D<u64>, IpcBytesSender), IsPointInPath(f64, f64, FillRule, IpcSender<bool>), LineTo(Point2D<f32>), @@ -56,10 +56,8 @@ pub enum Canvas2dMsg { Rect(Rect<f32>), RestoreContext, SaveContext, - StrokeRect(Rect<f32>), - Stroke, - SetFillStyle(FillOrStrokeStyle), - SetStrokeStyle(FillOrStrokeStyle), + StrokeRect(Rect<f32>, FillOrStrokeStyle), + Stroke(FillOrStrokeStyle), SetLineWidth(f32), SetLineCap(LineCapStyle), SetLineJoin(LineJoinStyle), diff --git a/components/script/canvas_state.rs b/components/script/canvas_state.rs index 0416c96aff0..c9492ed5da5 100644 --- a/components/script/canvas_state.rs +++ b/components/script/canvas_state.rs @@ -64,6 +64,16 @@ pub(crate) enum CanvasFillOrStrokeStyle { Pattern(Dom<CanvasPattern>), } +impl CanvasFillOrStrokeStyle { + fn to_fill_or_stroke_style(&self) -> FillOrStrokeStyle { + match self { + CanvasFillOrStrokeStyle::Color(rgba) => FillOrStrokeStyle::Color(*rgba), + CanvasFillOrStrokeStyle::Gradient(gradient) => gradient.to_fill_or_stroke_style(), + CanvasFillOrStrokeStyle::Pattern(pattern) => pattern.to_fill_or_stroke_style(), + } + } +} + #[unrooted_must_root_lint::must_root] #[derive(Clone, JSTraceable, MallocSizeOf)] pub(crate) struct CanvasContextState { @@ -654,7 +664,8 @@ impl CanvasState { // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect pub fn fill_rect(&self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.send_canvas_2d_msg(Canvas2dMsg::FillRect(rect)); + let style = self.state.borrow().fill_style.to_fill_or_stroke_style(); + self.send_canvas_2d_msg(Canvas2dMsg::FillRect(rect, style)); } } @@ -668,7 +679,8 @@ impl CanvasState { // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect pub fn stroke_rect(&self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.send_canvas_2d_msg(Canvas2dMsg::StrokeRect(rect)); + let style = self.state.borrow().stroke_style.to_fill_or_stroke_style(); + self.send_canvas_2d_msg(Canvas2dMsg::StrokeRect(rect, style)); } } @@ -756,24 +768,15 @@ impl CanvasState { StringOrCanvasGradientOrCanvasPattern::String(string) => { if let Ok(rgba) = self.parse_color(canvas, &string) { self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Color(rgba); - self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(FillOrStrokeStyle::Color( - rgba, - ))); } }, StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); - self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle( - gradient.to_fill_or_stroke_style(), - )); }, StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); - self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle( - pattern.to_fill_or_stroke_style(), - )); if !pattern.origin_is_clean() { self.set_origin_unclean(); } @@ -808,24 +811,15 @@ impl CanvasState { StringOrCanvasGradientOrCanvasPattern::String(string) => { if let Ok(rgba) = self.parse_color(canvas, &string) { self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Color(rgba); - self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(FillOrStrokeStyle::Color( - rgba, - ))) } }, StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); - self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle( - gradient.to_fill_or_stroke_style(), - )); }, StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); - self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle( - pattern.to_fill_or_stroke_style(), - )); if !pattern.origin_is_clean() { self.set_origin_unclean(); } @@ -995,7 +989,8 @@ impl CanvasState { // https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext pub fn fill_text(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) { let parsed_text: String = text.into(); - self.send_canvas_2d_msg(Canvas2dMsg::FillText(parsed_text, x, y, max_width)); + let style = self.state.borrow().fill_style.to_fill_or_stroke_style(); + self.send_canvas_2d_msg(Canvas2dMsg::FillText(parsed_text, x, y, max_width, style)); } // https://html.spec.whatwg.org/multipage/#textmetrics @@ -1302,12 +1297,14 @@ impl CanvasState { // https://html.spec.whatwg.org/multipage/#dom-context-2d-fill pub fn fill(&self, _fill_rule: CanvasFillRule) { // TODO: Process fill rule - self.send_canvas_2d_msg(Canvas2dMsg::Fill); + let style = self.state.borrow().fill_style.to_fill_or_stroke_style(); + self.send_canvas_2d_msg(Canvas2dMsg::Fill(style)); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke pub fn stroke(&self) { - self.send_canvas_2d_msg(Canvas2dMsg::Stroke); + let style = self.state.borrow().stroke_style.to_fill_or_stroke_style(); + self.send_canvas_2d_msg(Canvas2dMsg::Stroke(style)); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-clip diff --git a/tests/wpt/metadata/2dcontext/fill-and-stroke-styles/2d.gradient.object.update.html.ini b/tests/wpt/metadata/2dcontext/fill-and-stroke-styles/2d.gradient.object.update.html.ini deleted file mode 100644 index 5ab8ded6255..00000000000 --- a/tests/wpt/metadata/2dcontext/fill-and-stroke-styles/2d.gradient.object.update.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.gradient.object.update.html] - type: testharness - [Canvas test: 2d.gradient.object.update] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/fill-and-stroke-styles/2d.pattern.animated.gif.html.ini b/tests/wpt/metadata/2dcontext/fill-and-stroke-styles/2d.pattern.animated.gif.html.ini deleted file mode 100644 index 8dc7eba742c..00000000000 --- a/tests/wpt/metadata/2dcontext/fill-and-stroke-styles/2d.pattern.animated.gif.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[2d.pattern.animated.gif.html] - [createPattern() of an animated GIF draws the first frame] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.object.update.html.ini b/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.object.update.html.ini deleted file mode 100644 index fbbb458645d..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.object.update.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[2d.gradient.object.update.html] - [OffscreenCanvas test: 2d.gradient.object.update] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.object.update.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.object.update.worker.js.ini deleted file mode 100644 index 1676060bf3c..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.object.update.worker.js.ini +++ /dev/null @@ -1,4 +0,0 @@ -[2d.gradient.object.update.worker.html] - [2d] - expected: FAIL - |