diff options
author | bors-servo <metajack+bors@gmail.com> | 2015-03-20 03:12:47 -0600 |
---|---|---|
committer | bors-servo <metajack+bors@gmail.com> | 2015-03-20 03:12:47 -0600 |
commit | dea36f981650f027902b4f71f0cdabd2da69fe21 (patch) | |
tree | 3b22140821d0018583a02b55940b0a982f0bda06 /components/script/dom | |
parent | 459c35441612d3247450e253b1dcd0bc003985ae (diff) | |
parent | d3199aef74b548b9afe8281db3a6fe67b7a03874 (diff) | |
download | servo-dea36f981650f027902b4f71f0cdabd2da69fe21.tar.gz servo-dea36f981650f027902b4f71f0cdabd2da69fe21.zip |
auto merge of #4891 : mmatyas/servo/canvas_gradient, r=jdm
Based on [ebalint](https://github.com/ebalint)'s original patch, this commit implements the linear and radial gradients for the canvas. The PR also includes test cases.
Depends on #4623 and servo/rust-azure#136.
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/trace.rs | 2 | ||||
-rw-r--r-- | components/script/dom/canvasgradient.rs | 72 | ||||
-rw-r--r-- | components/script/dom/canvasrenderingcontext2d.rs | 24 | ||||
-rw-r--r-- | components/script/dom/webidls/CanvasGradient.webidl | 2 | ||||
-rw-r--r-- | components/script/dom/webidls/CanvasRenderingContext2D.webidl | 6 |
5 files changed, 101 insertions, 5 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 505307dd7bf..9e7b7012190 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -34,6 +34,7 @@ use dom::bindings::refcounted::Trusted; use dom::bindings::utils::{Reflectable, Reflector, WindowProxyHandler}; use script_task::ScriptChan; +use canvas::canvas_paint_task::{CanvasGradientStop, LinearGradientStyle, RadialGradientStyle}; use cssparser::RGBA; use encoding::types::EncodingRef; use geom::matrix2d::Matrix2D; @@ -233,6 +234,7 @@ no_jsmanaged_fields!(LengthOrPercentageOrAuto); no_jsmanaged_fields!(RGBA); no_jsmanaged_fields!(Matrix2D<T>); no_jsmanaged_fields!(StorageType); +no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle); impl JSTraceable for Box<ScriptChan+Send> { #[inline] diff --git a/components/script/dom/canvasgradient.rs b/components/script/dom/canvasgradient.rs index def78ca7f33..c1e61a12c26 100644 --- a/components/script/dom/canvasgradient.rs +++ b/components/script/dom/canvasgradient.rs @@ -2,10 +2,80 @@ * 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/. */ -use dom::bindings::utils::Reflector; +use cssparser::RGBA; +use canvas::canvas_paint_task::{CanvasGradientStop, FillOrStrokeStyle, LinearGradientStyle, RadialGradientStyle}; +use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::CanvasGradientBinding; +use dom::bindings::codegen::Bindings::CanvasGradientBinding::CanvasGradientMethods; +use dom::bindings::global::GlobalRef; +use dom::bindings::js::{JSRef, Temporary}; +use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::canvasrenderingcontext2d::parse_color; #[dom_struct] pub struct CanvasGradient { reflector_: Reflector, + style: CanvasGradientStyle, + stops: DOMRefCell<Vec<CanvasGradientStop>>, } +#[jstraceable] +pub enum CanvasGradientStyle { + Linear(LinearGradientStyle), + Radial(RadialGradientStyle), +} + +impl CanvasGradient { + fn new_inherited(style: CanvasGradientStyle) -> CanvasGradient { + CanvasGradient { + reflector_: Reflector::new(), + style: style, + stops: DOMRefCell::new(Vec::new()), + } + } + + pub fn new(global: GlobalRef, style: CanvasGradientStyle) -> Temporary<CanvasGradient> { + reflect_dom_object(box CanvasGradient::new_inherited(style), + global, CanvasGradientBinding::Wrap) + } +} + +impl<'a> CanvasGradientMethods for JSRef<'a, CanvasGradient> { + fn AddColorStop(self, offset: f32, color: String) { + let default_black = RGBA { + red: 0.0, + green: 0.0, + blue: 0.0, + alpha: 1.0, + }; + + self.stops.borrow_mut().push(CanvasGradientStop { + offset: offset as f64, + color: parse_color(color.as_slice()).unwrap_or(default_black), + }); + } +} + +pub trait ToFillOrStrokeStyle { + fn to_fill_or_stroke_style(&self) -> FillOrStrokeStyle; +} + +impl<'a> ToFillOrStrokeStyle for JSRef<'a, CanvasGradient> { + fn to_fill_or_stroke_style(&self) -> FillOrStrokeStyle { + let gradient_stops = self.stops.borrow().clone(); + match self.style { + CanvasGradientStyle::Linear(ref gradient) => { + FillOrStrokeStyle::LinearGradient( + LinearGradientStyle::new(gradient.x0, gradient.y0, + gradient.x1, gradient.y1, + gradient_stops)) + }, + CanvasGradientStyle::Radial(ref gradient) => { + FillOrStrokeStyle::RadialGradient( + RadialGradientStyle::new(gradient.x0, gradient.y0, gradient.r0, + gradient.x1, gradient.y1, gradient.r1, + gradient_stops)) + } + } + } +} diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index d481aca911f..a029b3d3c54 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -7,11 +7,12 @@ use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRen use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasWindingRule; use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods; use dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern; -use dom::bindings::error::Error::IndexSize; +use dom::bindings::error::Error::{IndexSize, TypeError}; use dom::bindings::error::Fallible; use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::js::{JS, JSRef, LayoutJS, Temporary}; use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; use dom::htmlcanvaselement::{HTMLCanvasElement, HTMLCanvasElementHelpers}; use dom::imagedata::{ImageData, ImageDataHelpers}; @@ -23,7 +24,9 @@ use geom::rect::Rect; use geom::size::Size2D; use canvas::canvas_paint_task::{CanvasMsg, CanvasPaintTask, FillOrStrokeStyle}; +use canvas::canvas_paint_task::{LinearGradientStyle, RadialGradientStyle}; +use std::borrow::ToOwned; use std::cell::Cell; use std::num::{Float, ToPrimitive}; use std::sync::mpsc::{channel, Sender}; @@ -215,6 +218,9 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> _ => {} } } + StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient) => { + self.renderer.send(CanvasMsg::SetFillStyle(gradient.root().r().to_fill_or_stroke_style())).unwrap(); + } _ => {} } } @@ -264,6 +270,22 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> let canvas_size = self.canvas.root().r().get_size(); self.renderer.send(CanvasMsg::PutImageData(data, image_data_rect, dirty_rect, canvas_size)).unwrap() } + + fn CreateLinearGradient(self, x0: f64, y0: f64, x1: f64, y1: f64) -> Fallible<Temporary<CanvasGradient>> { + if [x0, y0, x1, y1].iter().any(|x| x.is_nan() || x.is_infinite()) { + return Err(TypeError("One of the arguments of createLinearGradient() is not a finite floating-point value.".to_owned())); + } + Ok(CanvasGradient::new(self.global.root().r(), + CanvasGradientStyle::Linear(LinearGradientStyle::new(x0, y0, x1, y1, Vec::new())))) + } + + fn CreateRadialGradient(self, x0: f64, y0: f64, r0: f64, x1: f64, y1: f64, r1: f64) -> Fallible<Temporary<CanvasGradient>> { + if [x0, y0, r0, x1, y1, r1].iter().any(|x| x.is_nan() || x.is_infinite()) { + return Err(TypeError("One of the arguments of createRadialGradient() is not a finite floating-point value.".to_owned())); + } + Ok(CanvasGradient::new(self.global.root().r(), + CanvasGradientStyle::Radial(RadialGradientStyle::new(x0, y0, r0, x1, y1, r1, Vec::new())))) + } } #[unsafe_destructor] diff --git a/components/script/dom/webidls/CanvasGradient.webidl b/components/script/dom/webidls/CanvasGradient.webidl index 1dc1ac4c1f0..fbeab843987 100644 --- a/components/script/dom/webidls/CanvasGradient.webidl +++ b/components/script/dom/webidls/CanvasGradient.webidl @@ -6,7 +6,7 @@ interface CanvasGradient { // opaque object // addColorStop should take a double - //void addColorStop(float offset, DOMString color); + void addColorStop(float offset, DOMString color); }; diff --git a/components/script/dom/webidls/CanvasRenderingContext2D.webidl b/components/script/dom/webidls/CanvasRenderingContext2D.webidl index f9a4c7b68f8..e0861f02cbd 100644 --- a/components/script/dom/webidls/CanvasRenderingContext2D.webidl +++ b/components/script/dom/webidls/CanvasRenderingContext2D.webidl @@ -52,8 +52,10 @@ interface CanvasRenderingContext2D { // colours and styles (see also the CanvasDrawingStyles interface) attribute (DOMString or CanvasGradient or CanvasPattern) strokeStyle; // (default black) attribute (DOMString or CanvasGradient or CanvasPattern) fillStyle; // (default black) - //CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1); - //CanvasGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1); + [Throws] + CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1); + [Throws] + CanvasGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1); //CanvasPattern createPattern(CanvasImageSource image, [TreatNullAs=EmptyString] DOMString repetition); // shadows |