aboutsummaryrefslogtreecommitdiffstats
path: root/components/canvas/azure_backend.rs
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2019-05-29 14:50:45 -0400
committerJosh Matthews <josh@joshmatthews.net>2019-06-03 00:12:01 -0400
commit3243f1753bca71c5b14d9f43c34aad51e59a01a4 (patch)
treeb78885795bbd59bdd30fefcfc48a71211d83472c /components/canvas/azure_backend.rs
parent42bf1984be6498517e98b7942633ec0f57adaab1 (diff)
downloadservo-3243f1753bca71c5b14d9f43c34aad51e59a01a4.tar.gz
servo-3243f1753bca71c5b14d9f43c34aad51e59a01a4.zip
Add cargo feature to control canvas backend.
Diffstat (limited to 'components/canvas/azure_backend.rs')
-rw-r--r--components/canvas/azure_backend.rs744
1 files changed, 744 insertions, 0 deletions
diff --git a/components/canvas/azure_backend.rs b/components/canvas/azure_backend.rs
new file mode 100644
index 00000000000..8727751d5a6
--- /dev/null
+++ b/components/canvas/azure_backend.rs
@@ -0,0 +1,744 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use cssparser::RGBA;
+use crate::canvas_data::{
+ Backend, CanvasPaintState, Color, CompositionOp, DrawOptions, GenericDrawTarget,
+ GenericPathBuilder, Path, Pattern, StrokeOptions,
+};
+use crate::canvas_paint_thread::AntialiasMode;
+use azure::azure::{AzFloat, AzGradientStop, AzIntSize, AzPoint};
+use azure::azure_hl;
+use azure::azure_hl::SurfacePattern;
+use azure::azure_hl::{AsAzurePoint, CapStyle, JoinStyle};
+use azure::azure_hl::{BackendType, ColorPattern, DrawTarget};
+use azure::azure_hl::{LinearGradientPattern, RadialGradientPattern};
+use euclid::{Point2D, Rect, Size2D, Transform2D, Vector2D};
+
+pub struct AzureBackend;
+
+impl Backend for AzureBackend {
+ fn get_composition_op(&self, opts: &DrawOptions) -> CompositionOp {
+ CompositionOp::Azure(opts.as_azure().composition)
+ }
+
+ fn need_to_draw_shadow(&self, color: &Color) -> bool {
+ self.state.shadow_color.as_azure().a != 0.0f32
+ }
+
+ fn size_from_pattern(&self, rect: &Rect<f32>, pattern: &Pattern) -> Option<Size2D<f32>> {
+ match pattern {
+ Pattern::Azure(azure_hl::Pattern::Surface(ref surface)) => {
+ let surface_size = surface.size();
+ let size = match (surface.repeat_x, surface.repeat_y) {
+ (true, true) => rect.size,
+ (true, false) => Size2D::new(rect.size.width, surface_size.height as f32),
+ (false, true) => Size2D::new(surface_size.width as f32, rect.size.height),
+ (false, false) => {
+ Size2D::new(surface_size.width as f32, surface_size.height as f32)
+ },
+ };
+ Some(size)
+ }
+ Pattern::Azure(_) => None
+ }
+ }
+
+ fn set_shadow_color<'a>(&mut self, color: RGBA, state: &mut CanvasPaintState<'a>) {
+ state.shadow_color = Color::Azure(color.to_azure_style());
+ }
+
+ fn set_fill_style<'a>(
+ &mut self,
+ style: FillOrStrokeStyle,
+ state: &mut CanvasPaintState<'a>,
+ drawtarget: &GenericDrawTarget,
+ ) {
+ if let Some(pattern) = style.to_azure_pattern(drawtarget) {
+ state.fill_style = Pattern::Azure(pattern)
+ }
+ }
+
+ fn set_stroke_style<'a>(
+ &mut self,
+ style: FillOrStrokeStyle,
+ state: &mut CanvasPaintState<'a>,
+ drawtarget: &GenericDrawTarget)
+ {
+ if let Some(pattern) = style.to_azure_pattern(drawtarget) {
+ state.stroke_style = Pattern::Azure(pattern)
+ }
+ }
+
+ fn set_global_composition<'a>(&mut self, op: CompositionOrBlending, state: &mut CanvasPaintState<'a>) {
+ state
+ .draw_options
+ .as_azure_mut()
+ .set_composition_op(op.to_azure_style());
+ }
+
+ fn create_drawtarget(&self, size: Size2D<u64>) -> Box<GenericDrawTarget> {
+ // FIXME(nox): Why is the size made of i32 values?
+ Box::new(DrawTarget::new(
+ BackendType::Skia,
+ size.to_i32(),
+ azure_hl::SurfaceFormat::B8G8R8A8,
+ ))
+ }
+
+ fn recreate_paint_state<'a>(&self, state: &CanvasPaintState<'a>) -> CanvasPaintState<'a> {
+ CanvasPaintState::new(AntialiasMode::from_azure(
+ self.state.draw_options.as_azure().antialias
+ ))
+ }
+}
+
+impl<'a> CanvasPaintState<'a> {
+ pub fn new(antialias: AntialiasMode) -> CanvasPaintState<'a> {
+ CanvasPaintState {
+ draw_options: DrawOptions::Azure(azure_hl::DrawOptions::new(1.0, azure_hl::CompositionOp::Over, antialias.into_azure())),
+ fill_style: Pattern::Azure(azure_hl::Pattern::Color(ColorPattern::new(azure_hl::Color::black()))),
+ stroke_style: Pattern::Azure(azure_hl::Pattern::Color(ColorPattern::new(azure_hl::Color::black()))),
+ stroke_opts: StrokeOptions::Azure(azure_hl::StrokeOptions::new(
+ 1.0,
+ JoinStyle::MiterOrBevel,
+ CapStyle::Butt,
+ 10.0,
+ &[],
+ )),
+ transform: Transform2D::identity(),
+ shadow_offset_x: 0.0,
+ shadow_offset_y: 0.0,
+ shadow_blur: 0.0,
+ shadow_color: Color::Azure(azure_hl::Color::transparent()),
+ }
+ }
+}
+
+impl GenericPathBuilder for azure_hl::PathBuilder {
+ fn arc(
+ &self,
+ origin: Point2D<f32>,
+ radius: f32,
+ start_angle: f32,
+ end_angle: f32,
+ anticlockwise: bool,
+ ) {
+ self.arc(
+ origin as Point2D<AzFloat>,
+ radius as AzFloat,
+ start_angle as AzFloat,
+ end_angle as AzFloat,
+ anticlockwise,
+ );
+ }
+ fn bezier_curve_to(
+ &self,
+ control_point1: &Point2D<f32>,
+ control_point2: &Point2D<f32>,
+ control_point3: &Point2D<f32>,
+ ) {
+ self.bezier_curve_to(
+ control_point1 as &Point2D<AzFloat>,
+ control_point2 as &Point2D<AzFloat>,
+ control_point3 as &Point2D<AzFloat>,
+ );
+ }
+ fn close(&self) {
+ self.close();
+ }
+ fn ellipse(
+ &self,
+ origin: Point2D<f32>,
+ radius_x: f32,
+ radius_y: f32,
+ rotation_angle: f32,
+ start_angle: f32,
+ end_angle: f32,
+ anticlockwise: bool,
+ ) {
+ self.ellipse(
+ origin as Point2D<AzFloat>,
+ radius_x as AzFloat,
+ radius_y as AzFloat,
+ rotation_angle as AzFloat,
+ start_angle as AzFloat,
+ end_angle as AzFloat,
+ anticlockwise,
+ );
+ }
+ fn get_current_point(&self) -> Point2D<f32> {
+ let AzPoint { x, y } = self.get_current_point();
+ Point2D::new(x as f32, y as f32)
+ }
+ fn line_to(&self, point: Point2D<f32>) {
+ self.line_to(point as Point2D<AzFloat>);
+ }
+ fn move_to(&self, point: Point2D<f32>) {
+ self.move_to(point as Point2D<AzFloat>);
+ }
+ fn quadratic_curve_to(&self, control_point: &Point2D<f32>, end_point: &Point2D<f32>) {
+ self.quadratic_curve_to(
+ control_point as &Point2D<AzFloat>,
+ end_point as &Point2D<AzFloat>,
+ );
+ }
+ fn finish(&self) -> Path {
+ Path::Azure(self.finish())
+ }
+}
+
+impl GenericDrawTarget for azure_hl::DrawTarget {
+ fn clear_rect(&self, rect: &Rect<f32>) {
+ self.clear_rect(rect as &Rect<AzFloat>);
+ }
+
+ fn copy_surface(&self, surface: SourceSurface, source: Rect<i32>, destination: Point2D<i32>) {
+ self.copy_surface(surface.into_azure(), source, destination);
+ }
+
+ fn create_gradient_stops(
+ &self,
+ gradient_stops: Vec<GradientStop>,
+ extend_mode: ExtendMode,
+ ) -> GradientStops {
+ let gradient_stops: Vec<AzGradientStop> =
+ gradient_stops.into_iter().map(|x| x.into_azure()).collect();
+ GradientStops::Azure(self.create_gradient_stops(&gradient_stops, extend_mode.into_azure()))
+ }
+
+ fn create_path_builder(&self) -> Box<GenericPathBuilder> {
+ Box::new(self.create_path_builder())
+ }
+
+ fn create_similar_draw_target(
+ &self,
+ size: &Size2D<i32>,
+ format: SurfaceFormat,
+ ) -> Box<GenericDrawTarget> {
+ Box::new(self.create_similar_draw_target(size, format.into_azure()))
+ }
+ fn create_source_surface_from_data(
+ &self,
+ data: &[u8],
+ size: Size2D<i32>,
+ stride: i32,
+ ) -> Option<SourceSurface> {
+ self.create_source_surface_from_data(data, size, stride, azure_hl::SurfaceFormat::B8G8R8A8)
+ .map(|s| SourceSurface::Azure(s))
+ }
+ fn draw_surface(
+ &self,
+ surface: SourceSurface,
+ dest: Rect<f64>,
+ source: Rect<f64>,
+ filter: Filter,
+ draw_options: &DrawOptions,
+ ) {
+ let surf_options = azure_hl::DrawSurfaceOptions::new(filter.as_azure(), true);
+ let draw_options = azure_hl::DrawOptions::new(
+ draw_options.as_azure().alpha,
+ draw_options.as_azure().composition.into_azure(),
+ azure_hl::AntialiasMode::None
+ );
+ self.draw_surface(
+ surface.into_azure(),
+ dest as Rect<AzFloat>,
+ source as Rect<AzFloat>,
+ surf_options.into_azure(),
+ options.into_azure(),
+ );
+ }
+ fn draw_surface_with_shadow(
+ &self,
+ surface: SourceSurface,
+ dest: &Point2D<f32>,
+ color: &Color,
+ offset: &Vector2D<f32>,
+ sigma: f32,
+ operator: CompositionOp,
+ ) {
+ self.draw_surface_with_shadow(
+ surface.into_azure(),
+ dest as &Point2D<AzFloat>,
+ color.as_azure(),
+ offset as &Vector2D<AzFloat>,
+ sigma as AzFloat,
+ operator.into_azure(),
+ );
+ }
+ fn fill(&self, path: &Path, pattern: Pattern, draw_options: &DrawOptions) {
+ self.fill(
+ path.as_azure(),
+ pattern.as_azure().to_pattern_ref(),
+ draw_options.as_azure(),
+ );
+ }
+ fn fill_rect(&self, rect: &Rect<f32>, pattern: Pattern, draw_options: Option<&DrawOptions>) {
+ self.fill_rect(
+ rect as &Rect<AzFloat>,
+ pattern.as_azure().to_pattern_ref(),
+ draw_options.map(|x| x.as_azure()),
+ );
+ }
+ fn get_format(&self) -> SurfaceFormat {
+ SurfaceFormat::Azure(self.get_format())
+ }
+ fn get_size(&self) -> Size2D<i32> {
+ let size = self.get_size();
+ Size2D::new(size.width, size.height)
+ }
+ fn get_transform(&self) -> Transform2D<f32> {
+ self.get_transform() as Transform2D<f32>
+ }
+ fn pop_clip(&self) {
+ self.pop_clip();
+ }
+ fn push_clip(&self, path: &Path) {
+ self.push_clip(path.as_azure());
+ }
+ fn set_transform(&self, matrix: &Transform2D<f32>) {
+ self.set_transform(matrix as &Transform2D<AzFloat>);
+ }
+ fn snapshot(&self) -> SourceSurface {
+ SourceSurface::Azure(self.snapshot())
+ }
+ fn stroke(
+ &self,
+ path: &Path,
+ pattern: Pattern,
+ stroke_options: &StrokeOptions,
+ draw_options: &DrawOptions,
+ ) {
+ self.stroke(
+ path.as_azure(),
+ pattern.as_azure().to_pattern_ref(),
+ stroke_options.as_azure(),
+ draw_options.as_azure(),
+ );
+ }
+ fn stroke_line(
+ &self,
+ start: Point2D<f32>,
+ end: Point2D<f32>,
+ pattern: Pattern,
+ stroke_options: &StrokeOptions,
+ draw_options: &DrawOptions,
+ ) {
+ let stroke_options = stroke_options.as_azure();
+ let cap = match stroke_options.line_join {
+ JoinStyle::Round => CapStyle::Round,
+ _ => CapStyle::Butt,
+ };
+
+ let stroke_opts = azure_hl::StrokeOptions::new(
+ stroke_options.line_width,
+ stroke_options.line_join,
+ cap,
+ stroke_options.miter_limit,
+ stroke_options.mDashPattern,
+ );
+
+ self.stroke_line(
+ start,
+ end,
+ pattern.as_azure().to_pattern_ref(),
+ stroke_options.as_azure(),
+ draw_options.as_azure(),
+ );
+ }
+ fn stroke_rect(
+ &self,
+ rect: &Rect<f32>,
+ pattern: Pattern,
+ stroke_options: &StrokeOptions,
+ draw_options: &DrawOptions,
+ ) {
+ self.stroke_rect(
+ rect as &Rect<AzFloat>,
+ pattern.as_azure().to_pattern_ref(),
+ stroke_options.as_azure(),
+ draw_options.as_azure(),
+ );
+ }
+
+ fn snapshot_data(&self) -> &[u8] {
+ unsafe {
+ self.snapshot().get_data_surface().data()
+ }
+ }
+}
+
+impl AntialiasMode {
+ fn into_azure(self) -> azure_hl::AntialiasMode {
+ match self {
+ AntialiasMode::Default => azure_hl::AntialiasMode::Default,
+ AntialiasMode::None => azure_hl::AntialiasMode::None,
+ }
+ }
+
+ fn from_azure(val: azure_hl::AntialiasMode) {
+ match val {
+ azure_hl::AntialiasMode::Default => AntialiasMode::Default,
+ azure_hl::AntialiasMode::None => AntialiasMode::None,
+ }
+ }
+}
+
+impl ExtendMode {
+ fn into_azure(self) -> azure_hl::ExtendMode {
+ match self {
+ ExtendMode::Azure(m) => m,
+ }
+ }
+}
+
+impl GradientStop {
+ fn into_azure(self) -> AzGradientStop {
+ match self {
+ GradientStop::Azure(s) => s,
+ }
+ }
+}
+
+impl GradientStops {
+ fn into_azure(self) -> azure_hl::GradientStops {
+ match self {
+ GradientStops::Azure(s) => s,
+ }
+ }
+}
+
+impl Color {
+ fn as_azure(&self) -> &azure_hl::Color {
+ match self {
+ Color::Azure(s) => s,
+ }
+ }
+}
+
+impl CompositionOp {
+ fn into_azure(self) -> azure_hl::CompositionOp {
+ match self {
+ CompositionOp::Azure(s) => s,
+ }
+ }
+}
+
+impl SurfaceFormat {
+ fn into_azure(self) -> azure_hl::SurfaceFormat {
+ match self {
+ SurfaceFormat::Azure(s) => s,
+ }
+ }
+}
+
+impl SourceSurface {
+ fn into_azure(self) -> azure_hl::SourceSurface {
+ match self {
+ SourceSurface::Azure(s) => s,
+ }
+ }
+}
+
+impl IntSize {
+ fn into_azure(self) -> AzIntSize {
+ match self {
+ IntSize::Azure(s) => s,
+ }
+ }
+}
+
+impl Path {
+ fn as_azure(&self) -> &azure_hl::Path {
+ match self {
+ Path::Azure(p) => p,
+ }
+ }
+}
+
+impl Pattern {
+ fn as_azure(&self) -> &azure_hl::Pattern {
+ match self {
+ Pattern::Azure(p) => p,
+ }
+ }
+}
+
+impl DrawSurfaceOptions {
+ fn into_azure(self) -> azure_hl::DrawSurfaceOptions {
+ match self {
+ DrawSurfaceOptions::Azure(options) => options,
+ }
+ }
+}
+
+impl DrawOptions {
+ fn as_azure(&self) -> &azure_hl::DrawOptions {
+ match self {
+ DrawOptions::Azure(options) => options,
+ }
+ }
+ fn as_azure_mut(&mut self) -> &mut azure_hl::DrawOptions {
+ match self {
+ DrawOptions::Azure(options) => options,
+ }
+ }
+ fn into_azure(self) -> azure_hl::DrawOptions {
+ match self {
+ DrawOptions::Azure(options) => options,
+ }
+ }
+ pub fn set_alpha(&mut self, val: f32) {
+ match self {
+ DrawOptions::Azure(options) => options.alpha = val as AzFloat,
+ }
+ }
+}
+
+impl<'a> StrokeOptions<'a> {
+ pub fn as_azure(&self) -> &azure_hl::StrokeOptions<'a> {
+ match self {
+ StrokeOptions::Azure(options) => options,
+ }
+ }
+ pub fn set_line_width(&mut self, val: f32) {
+ match self {
+ StrokeOptions::Azure(options) => options.line_width = val as AzFloat,
+ }
+ }
+ pub fn set_miter_limit(&mut self, val: f32) {
+ match self {
+ StrokeOptions::Azure(options) => options.miter_limit = val as AzFloat,
+ }
+ }
+ pub fn set_line_join(&mut self, val: LineJoinStyle) {
+ match self {
+ StrokeOptions::Azure(options) => options.line_join = val.to_azure_style(),
+ }
+ }
+ pub fn set_line_cap(&mut self, val: LineCapStyle) {
+ match self {
+ StrokeOptions::Azure(options) => options.line_cap = val.to_azure_style(),
+ }
+ }
+}
+
+pub trait ToAzureStyle {
+ type Target;
+ fn to_azure_style(self) -> Self::Target;
+}
+
+impl ToAzureStyle for Rect<f64> {
+ type Target = Rect<f32>;
+
+ fn to_azure_style(self) -> Rect<f32> {
+ Rect::new(
+ Point2D::new(self.origin.x as f32, self.origin.y as f32),
+ Size2D::new(self.size.width as f32, self.size.height as f32),
+ )
+ }
+}
+
+impl ToAzureStyle for LineCapStyle {
+ type Target = CapStyle;
+
+ fn to_azure_style(self) -> CapStyle {
+ match self {
+ LineCapStyle::Butt => CapStyle::Butt,
+ LineCapStyle::Round => CapStyle::Round,
+ LineCapStyle::Square => CapStyle::Square,
+ }
+ }
+}
+
+impl ToAzureStyle for LineJoinStyle {
+ type Target = JoinStyle;
+
+ fn to_azure_style(self) -> JoinStyle {
+ match self {
+ LineJoinStyle::Round => JoinStyle::Round,
+ LineJoinStyle::Bevel => JoinStyle::Bevel,
+ LineJoinStyle::Miter => JoinStyle::Miter,
+ }
+ }
+}
+
+impl ToAzureStyle for CompositionStyle {
+ type Target = azure_hl::CompositionOp;
+
+ fn to_azure_style(self) -> azure_hl::CompositionOp {
+ match self {
+ CompositionStyle::SrcIn => azure_hl::CompositionOp::In,
+ CompositionStyle::SrcOut => azure_hl::CompositionOp::Out,
+ CompositionStyle::SrcOver => azure_hl::CompositionOp::Over,
+ CompositionStyle::SrcAtop => azure_hl::CompositionOp::Atop,
+ CompositionStyle::DestIn => azure_hl::CompositionOp::DestIn,
+ CompositionStyle::DestOut => azure_hl::CompositionOp::DestOut,
+ CompositionStyle::DestOver => azure_hl::CompositionOp::DestOver,
+ CompositionStyle::DestAtop => azure_hl::CompositionOp::DestAtop,
+ CompositionStyle::Copy => azure_hl::CompositionOp::Source,
+ CompositionStyle::Lighter => azure_hl::CompositionOp::Add,
+ CompositionStyle::Xor => azure_hl::CompositionOp::Xor,
+ }
+ }
+}
+
+impl ToAzureStyle for BlendingStyle {
+ type Target = azure_hl::CompositionOp;
+
+ fn to_azure_style(self) -> azure_hl::CompositionOp {
+ match self {
+ BlendingStyle::Multiply => azure_hl::CompositionOp::Multiply,
+ BlendingStyle::Screen => azure_hl::CompositionOp::Screen,
+ BlendingStyle::Overlay => azure_hl::CompositionOp::Overlay,
+ BlendingStyle::Darken => azure_hl::CompositionOp::Darken,
+ BlendingStyle::Lighten => azure_hl::CompositionOp::Lighten,
+ BlendingStyle::ColorDodge => azure_hl::CompositionOp::ColorDodge,
+ BlendingStyle::ColorBurn => azure_hl::CompositionOp::ColorBurn,
+ BlendingStyle::HardLight => azure_hl::CompositionOp::HardLight,
+ BlendingStyle::SoftLight => azure_hl::CompositionOp::SoftLight,
+ BlendingStyle::Difference => azure_hl::CompositionOp::Difference,
+ BlendingStyle::Exclusion => azure_hl::CompositionOp::Exclusion,
+ BlendingStyle::Hue => azure_hl::CompositionOp::Hue,
+ BlendingStyle::Saturation => azure_hl::CompositionOp::Saturation,
+ BlendingStyle::Color => azure_hl::CompositionOp::Color,
+ BlendingStyle::Luminosity => azure_hl::CompositionOp::Luminosity,
+ }
+ }
+}
+
+impl ToAzureStyle for CompositionOrBlending {
+ type Target = azure_hl::CompositionOp;
+
+ fn to_azure_style(self) -> azure_hl::CompositionOp {
+ match self {
+ CompositionOrBlending::Composition(op) => op.to_azure_style(),
+ CompositionOrBlending::Blending(op) => op.to_azure_style(),
+ }
+ }
+}
+
+pub trait ToAzurePattern {
+ fn to_azure_pattern(&self, drawtarget: &GenericDrawTarget) -> Option<azure_hl::Pattern>;
+}
+
+impl ToAzurePattern for FillOrStrokeStyle {
+ fn to_azure_pattern(&self, drawtarget: &GenericDrawTarget) -> Option<azure_hl::Pattern> {
+ Some(match *self {
+ FillOrStrokeStyle::Color(ref color) => {
+ azure_hl::Pattern::Color(ColorPattern::new(color.to_azure_style()))
+ },
+ FillOrStrokeStyle::LinearGradient(ref linear_gradient_style) => {
+ let gradient_stops: Vec<GradientStop> = linear_gradient_style
+ .stops
+ .iter()
+ .map(|s| GradientStop::Azure(azure_hl::GradientStop {
+ offset: s.offset as f32,
+ color: s.color.to_azure_style(),
+ }))
+ .collect();
+
+ azure_hl::Pattern::LinearGradient(LinearGradientPattern::new(
+ &Point2D::new(
+ linear_gradient_style.x0 as f32,
+ linear_gradient_style.y0 as f32,
+ ),
+ &Point2D::new(
+ linear_gradient_style.x1 as f32,
+ linear_gradient_style.y1 as f32,
+ ),
+ drawtarget.create_gradient_stops(gradient_stops, ExtendMode::Azure(azure_hl::ExtendMode::Clamp)).into_azure(),
+ &Transform2D::identity(),
+ ))
+ },
+ FillOrStrokeStyle::RadialGradient(ref radial_gradient_style) => {
+ let gradient_stops: Vec<GradientStop> = radial_gradient_style
+ .stops
+ .iter()
+ .map(|s| GradientStop::Azure(azure_hl::GradientStop {
+ offset: s.offset as f32,
+ color: s.color.to_azure_style(),
+ }))
+ .collect();
+
+ azure_hl::Pattern::RadialGradient(RadialGradientPattern::new(
+ &Point2D::new(
+ radial_gradient_style.x0 as f32,
+ radial_gradient_style.y0 as f32,
+ ),
+ &Point2D::new(
+ radial_gradient_style.x1 as f32,
+ radial_gradient_style.y1 as f32,
+ ),
+ radial_gradient_style.r0 as f32,
+ radial_gradient_style.r1 as f32,
+ drawtarget.create_gradient_stops(gradient_stops, ExtendMode::Azure(azure_hl::ExtendMode::Clamp)).into_azure(),
+ &Transform2D::identity(),
+ ))
+ },
+ FillOrStrokeStyle::Surface(ref surface_style) => {
+ let source_surface = drawtarget.create_source_surface_from_data(
+ &surface_style.surface_data,
+ // FIXME(nox): Why are those i32 values?
+ surface_style.surface_size.to_i32(),
+ surface_style.surface_size.width as i32 * 4,
+ )?.into_azure();
+ azure_hl::Pattern::Surface(SurfacePattern::new(
+ source_surface.azure_source_surface,
+ surface_style.repeat_x,
+ surface_style.repeat_y,
+ &Transform2D::identity(),
+ ))
+ },
+ })
+ }
+}
+
+impl ToAzureStyle for RGBA {
+ type Target = azure_hl::Color;
+
+ fn to_azure_style(self) -> azure_hl::Color {
+ azure_hl::Color::rgba(
+ self.red_f32() as f32,
+ self.green_f32() as f32,
+ self.blue_f32() as f32,
+ self.alpha_f32() as f32,
+ )
+ }
+}
+
+impl Pattern {
+ pub fn is_zero_size_gradient(&self) -> bool {
+ match *self {
+ Pattern::Azure(azure_hl::Pattern::LinearGradient(ref az_pattern)) => {
+ gradient.is_zero_size()
+ }
+ _ => false,
+ }
+ }
+}
+
+impl Filter {
+ fn as_azure(&self) -> azure_hl::Filter {
+ match *self {
+ Filter::Linear => azure_hl::Filter::Linear,
+ Filter::Point => azure_hl::Filter::Point,
+ }
+ }
+}
+
+impl Path {
+ pub fn transformed_copy_to_builder(&self, transform: &Transform2D<f32>) -> Box<GenericPathBuilder> {
+ Box::new(self.as_azure().transformed_copy_to_builder(transform))
+ }
+
+ pub fn contains_point(&self, x: f64, y: f64, path_transform: &Transform2D<f32>) -> bool {
+ self.as_azure().contains_point(x, y, path_transform)
+ }
+
+ pub fn copy_to_builder(&self) -> Box<GenericPathBuilder> {
+ self.as_azure().copy_to_builder()
+ }
+}