mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Auto merge of #23936 - Eijebong:raqote, r=jdm
Implement the raqote backend Rebased version of #23601 with some more stuff implemented. This passes some (not many) wpt tests. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23936) <!-- Reviewable:end -->
This commit is contained in:
commit
d8a1c1e02e
4 changed files with 685 additions and 231 deletions
|
@ -18,6 +18,8 @@ use canvas_traits::canvas::*;
|
|||
use cssparser::RGBA;
|
||||
use euclid::default::{Point2D, Rect, Size2D, Transform2D, Vector2D};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct AzureBackend;
|
||||
|
||||
impl Backend for AzureBackend {
|
||||
|
@ -31,7 +33,7 @@ impl Backend for AzureBackend {
|
|||
|
||||
fn size_from_pattern(&self, rect: &Rect<f32>, pattern: &Pattern) -> Option<Size2D<f32>> {
|
||||
match pattern {
|
||||
Pattern::Azure(azure_hl::Pattern::Surface(ref surface)) => {
|
||||
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,
|
||||
|
@ -43,7 +45,7 @@ impl Backend for AzureBackend {
|
|||
};
|
||||
Some(size)
|
||||
},
|
||||
Pattern::Azure(_) => None,
|
||||
Pattern::Azure(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +60,7 @@ impl Backend for AzureBackend {
|
|||
drawtarget: &dyn GenericDrawTarget,
|
||||
) {
|
||||
if let Some(pattern) = style.to_azure_pattern(drawtarget) {
|
||||
state.fill_style = Pattern::Azure(pattern)
|
||||
state.fill_style = Pattern::Azure(pattern, PhantomData::default())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +71,7 @@ impl Backend for AzureBackend {
|
|||
drawtarget: &dyn GenericDrawTarget,
|
||||
) {
|
||||
if let Some(pattern) = style.to_azure_pattern(drawtarget) {
|
||||
state.stroke_style = Pattern::Azure(pattern)
|
||||
state.stroke_style = Pattern::Azure(pattern, PhantomData::default())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,12 +110,14 @@ impl<'a> CanvasPaintState<'a> {
|
|||
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(),
|
||||
))),
|
||||
fill_style: Pattern::Azure(
|
||||
azure_hl::Pattern::Color(ColorPattern::new(azure_hl::Color::black())),
|
||||
PhantomData::default(),
|
||||
),
|
||||
stroke_style: Pattern::Azure(
|
||||
azure_hl::Pattern::Color(ColorPattern::new(azure_hl::Color::black())),
|
||||
PhantomData::default(),
|
||||
),
|
||||
stroke_opts: StrokeOptions::Azure(azure_hl::StrokeOptions::new(
|
||||
1.0,
|
||||
JoinStyle::MiterOrBevel,
|
||||
|
@ -132,14 +136,15 @@ impl<'a> CanvasPaintState<'a> {
|
|||
|
||||
impl GenericPathBuilder for azure_hl::PathBuilder {
|
||||
fn arc(
|
||||
&self,
|
||||
&mut self,
|
||||
origin: Point2D<f32>,
|
||||
radius: f32,
|
||||
start_angle: f32,
|
||||
end_angle: f32,
|
||||
anticlockwise: bool,
|
||||
) {
|
||||
self.arc(
|
||||
azure_hl::PathBuilder::arc(
|
||||
self,
|
||||
origin as Point2D<AzFloat>,
|
||||
radius as AzFloat,
|
||||
start_angle as AzFloat,
|
||||
|
@ -148,22 +153,23 @@ impl GenericPathBuilder for azure_hl::PathBuilder {
|
|||
);
|
||||
}
|
||||
fn bezier_curve_to(
|
||||
&self,
|
||||
&mut self,
|
||||
control_point1: &Point2D<f32>,
|
||||
control_point2: &Point2D<f32>,
|
||||
control_point3: &Point2D<f32>,
|
||||
) {
|
||||
self.bezier_curve_to(
|
||||
azure_hl::PathBuilder::bezier_curve_to(
|
||||
self,
|
||||
control_point1 as &Point2D<AzFloat>,
|
||||
control_point2 as &Point2D<AzFloat>,
|
||||
control_point3 as &Point2D<AzFloat>,
|
||||
);
|
||||
}
|
||||
fn close(&self) {
|
||||
self.close();
|
||||
fn close(&mut self) {
|
||||
azure_hl::PathBuilder::close(self);
|
||||
}
|
||||
fn ellipse(
|
||||
&self,
|
||||
&mut self,
|
||||
origin: Point2D<f32>,
|
||||
radius_x: f32,
|
||||
radius_y: f32,
|
||||
|
@ -172,7 +178,8 @@ impl GenericPathBuilder for azure_hl::PathBuilder {
|
|||
end_angle: f32,
|
||||
anticlockwise: bool,
|
||||
) {
|
||||
self.ellipse(
|
||||
azure_hl::PathBuilder::ellipse(
|
||||
self,
|
||||
origin as Point2D<AzFloat>,
|
||||
radius_x as AzFloat,
|
||||
radius_y as AzFloat,
|
||||
|
@ -182,34 +189,40 @@ impl GenericPathBuilder for azure_hl::PathBuilder {
|
|||
anticlockwise,
|
||||
);
|
||||
}
|
||||
fn get_current_point(&self) -> Point2D<f32> {
|
||||
let AzPoint { x, y } = self.get_current_point();
|
||||
fn get_current_point(&mut self) -> Point2D<f32> {
|
||||
let AzPoint { x, y } = azure_hl::PathBuilder::get_current_point(self);
|
||||
Point2D::new(x as f32, y as f32)
|
||||
}
|
||||
fn line_to(&self, point: Point2D<f32>) {
|
||||
self.line_to(point as Point2D<AzFloat>);
|
||||
fn line_to(&mut self, point: Point2D<f32>) {
|
||||
azure_hl::PathBuilder::line_to(self, point as Point2D<AzFloat>);
|
||||
}
|
||||
fn move_to(&self, point: Point2D<f32>) {
|
||||
self.move_to(point as Point2D<AzFloat>);
|
||||
fn move_to(&mut self, point: Point2D<f32>) {
|
||||
azure_hl::PathBuilder::move_to(self, point as Point2D<AzFloat>);
|
||||
}
|
||||
fn quadratic_curve_to(&self, control_point: &Point2D<f32>, end_point: &Point2D<f32>) {
|
||||
self.quadratic_curve_to(
|
||||
fn quadratic_curve_to(&mut self, control_point: &Point2D<f32>, end_point: &Point2D<f32>) {
|
||||
azure_hl::PathBuilder::quadratic_curve_to(
|
||||
self,
|
||||
control_point as &Point2D<AzFloat>,
|
||||
end_point as &Point2D<AzFloat>,
|
||||
);
|
||||
}
|
||||
fn finish(&self) -> Path {
|
||||
Path::Azure(self.finish())
|
||||
fn finish(&mut self) -> Path {
|
||||
Path::Azure(azure_hl::PathBuilder::finish(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericDrawTarget for azure_hl::DrawTarget {
|
||||
fn clear_rect(&self, rect: &Rect<f32>) {
|
||||
self.clear_rect(rect as &Rect<AzFloat>);
|
||||
fn clear_rect(&mut self, rect: &Rect<f32>) {
|
||||
azure_hl::DrawTarget::clear_rect(self, 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 copy_surface(
|
||||
&mut self,
|
||||
surface: SourceSurface,
|
||||
source: Rect<i32>,
|
||||
destination: Point2D<i32>,
|
||||
) {
|
||||
azure_hl::DrawTarget::copy_surface(self, surface.into_azure(), source, destination);
|
||||
}
|
||||
|
||||
fn create_gradient_stops(
|
||||
|
@ -243,7 +256,7 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
|
|||
.map(|s| SourceSurface::Azure(s))
|
||||
}
|
||||
fn draw_surface(
|
||||
&self,
|
||||
&mut self,
|
||||
surface: SourceSurface,
|
||||
dest: Rect<f64>,
|
||||
source: Rect<f64>,
|
||||
|
@ -256,7 +269,8 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
|
|||
draw_options.as_azure().composition,
|
||||
azure_hl::AntialiasMode::None,
|
||||
);
|
||||
self.draw_surface(
|
||||
azure_hl::DrawTarget::draw_surface(
|
||||
self,
|
||||
surface.into_azure(),
|
||||
dest.to_azure_style(),
|
||||
source.to_azure_style(),
|
||||
|
@ -282,15 +296,22 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
|
|||
operator.into_azure(),
|
||||
);
|
||||
}
|
||||
fn fill(&self, path: &Path, pattern: Pattern, draw_options: &DrawOptions) {
|
||||
self.fill(
|
||||
fn fill(&mut self, path: &Path, pattern: Pattern, draw_options: &DrawOptions) {
|
||||
azure_hl::DrawTarget::fill(
|
||||
self,
|
||||
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(
|
||||
fn fill_rect(
|
||||
&mut self,
|
||||
rect: &Rect<f32>,
|
||||
pattern: Pattern,
|
||||
draw_options: Option<&DrawOptions>,
|
||||
) {
|
||||
azure_hl::DrawTarget::fill_rect(
|
||||
self,
|
||||
rect as &Rect<AzFloat>,
|
||||
pattern.as_azure().to_pattern_ref(),
|
||||
draw_options.map(|x| x.as_azure()),
|
||||
|
@ -306,26 +327,27 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
|
|||
fn get_transform(&self) -> Transform2D<f32> {
|
||||
self.get_transform() as Transform2D<f32>
|
||||
}
|
||||
fn pop_clip(&self) {
|
||||
self.pop_clip();
|
||||
fn pop_clip(&mut self) {
|
||||
azure_hl::DrawTarget::pop_clip(self);
|
||||
}
|
||||
fn push_clip(&self, path: &Path) {
|
||||
self.push_clip(path.as_azure());
|
||||
fn push_clip(&mut self, path: &Path) {
|
||||
azure_hl::DrawTarget::push_clip(self, path.as_azure());
|
||||
}
|
||||
fn set_transform(&self, matrix: &Transform2D<f32>) {
|
||||
self.set_transform(matrix as &Transform2D<AzFloat>);
|
||||
fn set_transform(&mut self, matrix: &Transform2D<f32>) {
|
||||
azure_hl::DrawTarget::set_transform(self, matrix as &Transform2D<AzFloat>);
|
||||
}
|
||||
fn snapshot(&self) -> SourceSurface {
|
||||
SourceSurface::Azure(self.snapshot())
|
||||
}
|
||||
fn stroke(
|
||||
&self,
|
||||
&mut self,
|
||||
path: &Path,
|
||||
pattern: Pattern,
|
||||
stroke_options: &StrokeOptions,
|
||||
draw_options: &DrawOptions,
|
||||
) {
|
||||
self.stroke(
|
||||
azure_hl::DrawTarget::stroke(
|
||||
self,
|
||||
path.as_azure(),
|
||||
pattern.as_azure().to_pattern_ref(),
|
||||
stroke_options.as_azure(),
|
||||
|
@ -333,7 +355,7 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
|
|||
);
|
||||
}
|
||||
fn stroke_line(
|
||||
&self,
|
||||
&mut self,
|
||||
start: Point2D<f32>,
|
||||
end: Point2D<f32>,
|
||||
pattern: Pattern,
|
||||
|
@ -354,7 +376,8 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
|
|||
stroke_options.mDashPattern,
|
||||
);
|
||||
|
||||
self.stroke_line(
|
||||
azure_hl::DrawTarget::stroke_line(
|
||||
self,
|
||||
start,
|
||||
end,
|
||||
pattern.as_azure().to_pattern_ref(),
|
||||
|
@ -363,13 +386,14 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
|
|||
);
|
||||
}
|
||||
fn stroke_rect(
|
||||
&self,
|
||||
&mut self,
|
||||
rect: &Rect<f32>,
|
||||
pattern: Pattern,
|
||||
stroke_options: &StrokeOptions,
|
||||
draw_options: &DrawOptions,
|
||||
) {
|
||||
self.stroke_rect(
|
||||
azure_hl::DrawTarget::stroke_rect(
|
||||
self,
|
||||
rect as &Rect<AzFloat>,
|
||||
pattern.as_azure().to_pattern_ref(),
|
||||
stroke_options.as_azure(),
|
||||
|
@ -469,10 +493,10 @@ impl Path {
|
|||
}
|
||||
}
|
||||
|
||||
impl Pattern {
|
||||
impl Pattern<'_> {
|
||||
fn as_azure(&self) -> &azure_hl::Pattern {
|
||||
match self {
|
||||
Pattern::Azure(p) => p,
|
||||
Pattern::Azure(p, _) => p,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -723,10 +747,10 @@ impl ToAzureStyle for RGBA {
|
|||
}
|
||||
}
|
||||
|
||||
impl Pattern {
|
||||
impl Pattern<'_> {
|
||||
pub fn is_zero_size_gradient(&self) -> bool {
|
||||
match *self {
|
||||
Pattern::Azure(azure_hl::Pattern::LinearGradient(ref gradient)) => {
|
||||
Pattern::Azure(azure_hl::Pattern::LinearGradient(ref gradient), _) => {
|
||||
gradient.is_zero_size()
|
||||
},
|
||||
_ => false,
|
||||
|
|
|
@ -84,7 +84,7 @@ pub trait Backend {
|
|||
/// azure's and raqote's PathBuilder.
|
||||
pub trait GenericPathBuilder {
|
||||
fn arc(
|
||||
&self,
|
||||
&mut self,
|
||||
origin: Point2D<f32>,
|
||||
radius: f32,
|
||||
start_angle: f32,
|
||||
|
@ -92,14 +92,14 @@ pub trait GenericPathBuilder {
|
|||
anticlockwise: bool,
|
||||
);
|
||||
fn bezier_curve_to(
|
||||
&self,
|
||||
&mut self,
|
||||
control_point1: &Point2D<f32>,
|
||||
control_point2: &Point2D<f32>,
|
||||
control_point3: &Point2D<f32>,
|
||||
);
|
||||
fn close(&self);
|
||||
fn close(&mut self);
|
||||
fn ellipse(
|
||||
&self,
|
||||
&mut self,
|
||||
origin: Point2D<f32>,
|
||||
radius_x: f32,
|
||||
radius_y: f32,
|
||||
|
@ -108,32 +108,32 @@ pub trait GenericPathBuilder {
|
|||
end_angle: f32,
|
||||
anticlockwise: bool,
|
||||
);
|
||||
fn get_current_point(&self) -> Point2D<f32>;
|
||||
fn line_to(&self, point: Point2D<f32>);
|
||||
fn move_to(&self, point: Point2D<f32>);
|
||||
fn quadratic_curve_to(&self, control_point: &Point2D<f32>, end_point: &Point2D<f32>);
|
||||
fn finish(&self) -> Path;
|
||||
fn get_current_point(&mut self) -> Point2D<f32>;
|
||||
fn line_to(&mut self, point: Point2D<f32>);
|
||||
fn move_to(&mut self, point: Point2D<f32>);
|
||||
fn quadratic_curve_to(&mut self, control_point: &Point2D<f32>, end_point: &Point2D<f32>);
|
||||
fn finish(&mut self) -> Path;
|
||||
}
|
||||
|
||||
/// A wrapper around a stored PathBuilder and an optional transformation that should be
|
||||
/// applied to any points to ensure they are in the matching device space.
|
||||
struct PathBuilderRef<'a> {
|
||||
builder: &'a Box<dyn GenericPathBuilder>,
|
||||
builder: &'a mut Box<dyn GenericPathBuilder>,
|
||||
transform: Transform2D<f32>,
|
||||
}
|
||||
|
||||
impl<'a> PathBuilderRef<'a> {
|
||||
fn line_to(&self, pt: &Point2D<f32>) {
|
||||
fn line_to(&mut self, pt: &Point2D<f32>) {
|
||||
let pt = self.transform.transform_point(*pt);
|
||||
self.builder.line_to(pt);
|
||||
}
|
||||
|
||||
fn move_to(&self, pt: &Point2D<f32>) {
|
||||
fn move_to(&mut self, pt: &Point2D<f32>) {
|
||||
let pt = self.transform.transform_point(*pt);
|
||||
self.builder.move_to(pt);
|
||||
}
|
||||
|
||||
fn rect(&self, rect: &Rect<f32>) {
|
||||
fn rect(&mut self, rect: &Rect<f32>) {
|
||||
let (first, second, third, fourth) = (
|
||||
Point2D::new(rect.origin.x, rect.origin.y),
|
||||
Point2D::new(rect.origin.x + rect.size.width, rect.origin.y),
|
||||
|
@ -150,14 +150,14 @@ impl<'a> PathBuilderRef<'a> {
|
|||
self.builder.close();
|
||||
}
|
||||
|
||||
fn quadratic_curve_to(&self, cp: &Point2D<f32>, endpoint: &Point2D<f32>) {
|
||||
fn quadratic_curve_to(&mut self, cp: &Point2D<f32>, endpoint: &Point2D<f32>) {
|
||||
self.builder.quadratic_curve_to(
|
||||
&self.transform.transform_point(*cp),
|
||||
&self.transform.transform_point(*endpoint),
|
||||
)
|
||||
}
|
||||
|
||||
fn bezier_curve_to(&self, cp1: &Point2D<f32>, cp2: &Point2D<f32>, endpoint: &Point2D<f32>) {
|
||||
fn bezier_curve_to(&mut self, cp1: &Point2D<f32>, cp2: &Point2D<f32>, endpoint: &Point2D<f32>) {
|
||||
self.builder.bezier_curve_to(
|
||||
&self.transform.transform_point(*cp1),
|
||||
&self.transform.transform_point(*cp2),
|
||||
|
@ -165,14 +165,21 @@ impl<'a> PathBuilderRef<'a> {
|
|||
)
|
||||
}
|
||||
|
||||
fn arc(&self, center: &Point2D<f32>, radius: f32, start_angle: f32, end_angle: f32, ccw: bool) {
|
||||
fn arc(
|
||||
&mut self,
|
||||
center: &Point2D<f32>,
|
||||
radius: f32,
|
||||
start_angle: f32,
|
||||
end_angle: f32,
|
||||
ccw: bool,
|
||||
) {
|
||||
let center = self.transform.transform_point(*center);
|
||||
self.builder
|
||||
.arc(center, radius, start_angle, end_angle, ccw);
|
||||
}
|
||||
|
||||
pub fn ellipse(
|
||||
&self,
|
||||
&mut self,
|
||||
center: &Point2D<f32>,
|
||||
radius_x: f32,
|
||||
radius_y: f32,
|
||||
|
@ -193,7 +200,7 @@ impl<'a> PathBuilderRef<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
fn current_point(&self) -> Option<Point2D<f32>> {
|
||||
fn current_point(&mut self) -> Option<Point2D<f32>> {
|
||||
let inverse = match self.transform.inverse() {
|
||||
Some(i) => i,
|
||||
None => return None,
|
||||
|
@ -207,8 +214,13 @@ impl<'a> PathBuilderRef<'a> {
|
|||
// This defines required methods for DrawTarget of azure and raqote
|
||||
// The prototypes are derived from azure's methods.
|
||||
pub trait GenericDrawTarget {
|
||||
fn clear_rect(&self, rect: &Rect<f32>);
|
||||
fn copy_surface(&self, surface: SourceSurface, source: Rect<i32>, destination: Point2D<i32>);
|
||||
fn clear_rect(&mut self, rect: &Rect<f32>);
|
||||
fn copy_surface(
|
||||
&mut self,
|
||||
surface: SourceSurface,
|
||||
source: Rect<i32>,
|
||||
destination: Point2D<i32>,
|
||||
);
|
||||
fn create_gradient_stops(
|
||||
&self,
|
||||
gradient_stops: Vec<GradientStop>,
|
||||
|
@ -227,7 +239,7 @@ pub trait GenericDrawTarget {
|
|||
stride: i32,
|
||||
) -> Option<SourceSurface>;
|
||||
fn draw_surface(
|
||||
&self,
|
||||
&mut self,
|
||||
surface: SourceSurface,
|
||||
dest: Rect<f64>,
|
||||
source: Rect<f64>,
|
||||
|
@ -243,24 +255,24 @@ pub trait GenericDrawTarget {
|
|||
sigma: f32,
|
||||
operator: CompositionOp,
|
||||
);
|
||||
fn fill(&self, path: &Path, pattern: Pattern, draw_options: &DrawOptions);
|
||||
fn fill_rect(&self, rect: &Rect<f32>, pattern: Pattern, draw_options: Option<&DrawOptions>);
|
||||
fn fill(&mut self, path: &Path, pattern: Pattern, draw_options: &DrawOptions);
|
||||
fn fill_rect(&mut self, rect: &Rect<f32>, pattern: Pattern, draw_options: Option<&DrawOptions>);
|
||||
fn get_format(&self) -> SurfaceFormat;
|
||||
fn get_size(&self) -> Size2D<i32>;
|
||||
fn get_transform(&self) -> Transform2D<f32>;
|
||||
fn pop_clip(&self);
|
||||
fn push_clip(&self, path: &Path);
|
||||
fn set_transform(&self, matrix: &Transform2D<f32>);
|
||||
fn pop_clip(&mut self);
|
||||
fn push_clip(&mut self, path: &Path);
|
||||
fn set_transform(&mut self, matrix: &Transform2D<f32>);
|
||||
fn snapshot(&self) -> SourceSurface;
|
||||
fn stroke(
|
||||
&self,
|
||||
&mut self,
|
||||
path: &Path,
|
||||
pattern: Pattern,
|
||||
stroke_options: &StrokeOptions,
|
||||
draw_options: &DrawOptions,
|
||||
);
|
||||
fn stroke_line(
|
||||
&self,
|
||||
&mut self,
|
||||
start: Point2D<f32>,
|
||||
end: Point2D<f32>,
|
||||
pattern: Pattern,
|
||||
|
@ -268,7 +280,7 @@ pub trait GenericDrawTarget {
|
|||
draw_options: &DrawOptions,
|
||||
);
|
||||
fn stroke_rect(
|
||||
&self,
|
||||
&mut self,
|
||||
rect: &Rect<f32>,
|
||||
pattern: Pattern,
|
||||
stroke_options: &StrokeOptions,
|
||||
|
@ -305,7 +317,7 @@ pub enum Color {
|
|||
#[cfg(feature = "canvas2d-azure")]
|
||||
Azure(azure::azure_hl::Color),
|
||||
#[cfg(feature = "canvas2d-raqote")]
|
||||
Raqote(()),
|
||||
Raqote(raqote::SolidSource),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -313,7 +325,7 @@ pub enum CompositionOp {
|
|||
#[cfg(feature = "canvas2d-azure")]
|
||||
Azure(azure::azure_hl::CompositionOp),
|
||||
#[cfg(feature = "canvas2d-raqote")]
|
||||
Raqote(()),
|
||||
Raqote(raqote::BlendMode),
|
||||
}
|
||||
|
||||
pub enum SurfaceFormat {
|
||||
|
@ -328,22 +340,23 @@ pub enum SourceSurface {
|
|||
#[cfg(feature = "canvas2d-azure")]
|
||||
Azure(azure::azure_hl::SourceSurface),
|
||||
#[cfg(feature = "canvas2d-raqote")]
|
||||
Raqote(()),
|
||||
Raqote(Vec<u8>), // TODO: See if we can avoid the alloc (probably?)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Path {
|
||||
#[cfg(feature = "canvas2d-azure")]
|
||||
Azure(azure::azure_hl::Path),
|
||||
#[cfg(feature = "canvas2d-raqote")]
|
||||
Raqote(()),
|
||||
Raqote(raqote::Path),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Pattern {
|
||||
pub enum Pattern<'a> {
|
||||
#[cfg(feature = "canvas2d-azure")]
|
||||
Azure(azure::azure_hl::Pattern),
|
||||
Azure(azure::azure_hl::Pattern, PhantomData<&'a ()>),
|
||||
#[cfg(feature = "canvas2d-raqote")]
|
||||
Raqote(()),
|
||||
Raqote(raqote::Source<'a>),
|
||||
}
|
||||
|
||||
pub enum DrawSurfaceOptions {
|
||||
|
@ -358,7 +371,7 @@ pub enum DrawOptions {
|
|||
#[cfg(feature = "canvas2d-azure")]
|
||||
Azure(azure::azure_hl::DrawOptions),
|
||||
#[cfg(feature = "canvas2d-raqote")]
|
||||
Raqote(()),
|
||||
Raqote(raqote::DrawOptions),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -366,7 +379,7 @@ pub enum StrokeOptions<'a> {
|
|||
#[cfg(feature = "canvas2d-azure")]
|
||||
Azure(azure::azure_hl::StrokeOptions<'a>),
|
||||
#[cfg(feature = "canvas2d-raqote")]
|
||||
Raqote(PhantomData<&'a ()>),
|
||||
Raqote(raqote::StrokeStyle, PhantomData<&'a ()>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
@ -425,7 +438,7 @@ impl<'a> CanvasData<'a> {
|
|||
}
|
||||
|
||||
pub fn draw_image(
|
||||
&self,
|
||||
&mut self,
|
||||
image_data: Vec<u8>,
|
||||
image_size: Size2D<f64>,
|
||||
dest_rect: Rect<f64>,
|
||||
|
@ -441,14 +454,15 @@ impl<'a> CanvasData<'a> {
|
|||
image_data.into()
|
||||
};
|
||||
|
||||
let writer = |draw_target: &dyn GenericDrawTarget| {
|
||||
let draw_options = self.state.draw_options.clone();
|
||||
let writer = |draw_target: &mut dyn GenericDrawTarget| {
|
||||
write_image(
|
||||
draw_target,
|
||||
image_data,
|
||||
source_rect.size,
|
||||
dest_rect,
|
||||
smoothing_enabled,
|
||||
&self.state.draw_options,
|
||||
&draw_options,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -461,7 +475,7 @@ impl<'a> CanvasData<'a> {
|
|||
// TODO(pylbrecht) pass another closure for raqote
|
||||
self.draw_with_shadow(&rect, writer);
|
||||
} else {
|
||||
writer(&*self.drawtarget);
|
||||
writer(&mut *self.drawtarget);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -484,7 +498,7 @@ impl<'a> CanvasData<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
pub fn fill_rect(&self, rect: &Rect<f32>) {
|
||||
pub fn fill_rect(&mut self, rect: &Rect<f32>) {
|
||||
if self.state.fill_style.is_zero_size_gradient() {
|
||||
return; // Paint nothing if gradient size is zero.
|
||||
}
|
||||
|
@ -497,7 +511,7 @@ impl<'a> CanvasData<'a> {
|
|||
);
|
||||
|
||||
if self.need_to_draw_shadow() {
|
||||
self.draw_with_shadow(&draw_rect, |new_draw_target: &dyn GenericDrawTarget| {
|
||||
self.draw_with_shadow(&draw_rect, |new_draw_target: &mut dyn GenericDrawTarget| {
|
||||
new_draw_target.fill_rect(
|
||||
&draw_rect,
|
||||
self.state.fill_style.clone(),
|
||||
|
@ -513,17 +527,17 @@ impl<'a> CanvasData<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn clear_rect(&self, rect: &Rect<f32>) {
|
||||
pub fn clear_rect(&mut self, rect: &Rect<f32>) {
|
||||
self.drawtarget.clear_rect(rect);
|
||||
}
|
||||
|
||||
pub fn stroke_rect(&self, rect: &Rect<f32>) {
|
||||
pub fn stroke_rect(&mut self, rect: &Rect<f32>) {
|
||||
if self.state.stroke_style.is_zero_size_gradient() {
|
||||
return; // Paint nothing if gradient size is zero.
|
||||
}
|
||||
|
||||
if self.need_to_draw_shadow() {
|
||||
self.draw_with_shadow(&rect, |new_draw_target: &dyn GenericDrawTarget| {
|
||||
self.draw_with_shadow(&rect, |new_draw_target: &mut dyn GenericDrawTarget| {
|
||||
new_draw_target.stroke_rect(
|
||||
rect,
|
||||
self.state.stroke_style.clone(),
|
||||
|
@ -532,11 +546,13 @@ impl<'a> CanvasData<'a> {
|
|||
);
|
||||
});
|
||||
} else if rect.size.width == 0. || rect.size.height == 0. {
|
||||
let mut stroke_opts = self.state.stroke_opts.clone();
|
||||
stroke_opts.set_line_cap(LineCapStyle::Butt);
|
||||
self.drawtarget.stroke_line(
|
||||
rect.origin,
|
||||
rect.bottom_right(),
|
||||
self.state.stroke_style.clone(),
|
||||
&self.state.stroke_opts,
|
||||
&stroke_opts,
|
||||
&self.state.draw_options,
|
||||
);
|
||||
} else {
|
||||
|
@ -569,7 +585,7 @@ impl<'a> CanvasData<'a> {
|
|||
|
||||
// If a user-space builder exists, create a finished path from it.
|
||||
let new_state = match *self.path_state.as_mut().unwrap() {
|
||||
PathState::UserSpacePathBuilder(ref builder, ref mut transform) => {
|
||||
PathState::UserSpacePathBuilder(ref mut builder, ref mut transform) => {
|
||||
Some((builder.finish(), transform.take()))
|
||||
},
|
||||
PathState::DeviceSpacePathBuilder(..) | PathState::UserSpacePath(..) => None,
|
||||
|
@ -594,8 +610,8 @@ impl<'a> CanvasData<'a> {
|
|||
|
||||
// If a device-space builder is present, create a user-space path from its
|
||||
// finished path by inverting the initial transformation.
|
||||
let new_state = match self.path_state.as_ref().unwrap() {
|
||||
PathState::DeviceSpacePathBuilder(ref builder) => {
|
||||
let new_state = match *self.path_state.as_mut().unwrap() {
|
||||
PathState::DeviceSpacePathBuilder(ref mut builder) => {
|
||||
let path = builder.finish();
|
||||
let inverse = match self.drawtarget.get_transform().inverse() {
|
||||
Some(m) => m,
|
||||
|
@ -604,7 +620,7 @@ impl<'a> CanvasData<'a> {
|
|||
return;
|
||||
},
|
||||
};
|
||||
let builder = path.transformed_copy_to_builder(&inverse);
|
||||
let mut builder = path.transformed_copy_to_builder(&inverse);
|
||||
Some(builder.finish())
|
||||
},
|
||||
PathState::UserSpacePathBuilder(..) | PathState::UserSpacePath(..) => None,
|
||||
|
@ -630,7 +646,7 @@ impl<'a> CanvasData<'a> {
|
|||
|
||||
self.ensure_path();
|
||||
self.drawtarget.fill(
|
||||
&self.path(),
|
||||
&self.path().clone(),
|
||||
self.state.fill_style.clone(),
|
||||
&self.state.draw_options,
|
||||
);
|
||||
|
@ -643,7 +659,7 @@ impl<'a> CanvasData<'a> {
|
|||
|
||||
self.ensure_path();
|
||||
self.drawtarget.stroke(
|
||||
&self.path(),
|
||||
&self.path().clone(),
|
||||
self.state.stroke_style.clone(),
|
||||
&self.state.stroke_opts,
|
||||
&self.state.draw_options,
|
||||
|
@ -652,7 +668,8 @@ impl<'a> CanvasData<'a> {
|
|||
|
||||
pub fn clip(&mut self) {
|
||||
self.ensure_path();
|
||||
self.drawtarget.push_clip(&self.path());
|
||||
let path = self.path().clone();
|
||||
self.drawtarget.push_clip(&path);
|
||||
}
|
||||
|
||||
pub fn is_point_in_path(
|
||||
|
@ -694,19 +711,20 @@ impl<'a> CanvasData<'a> {
|
|||
// and overwriting path_state in other ones. The following awkward use of duplicate
|
||||
// matches works around the resulting borrow errors.
|
||||
let new_state = {
|
||||
match self.path_state.as_ref().unwrap() {
|
||||
&PathState::UserSpacePathBuilder(_, None) |
|
||||
&PathState::DeviceSpacePathBuilder(_) => None,
|
||||
&PathState::UserSpacePathBuilder(ref builder, Some(ref transform)) => {
|
||||
match *self.path_state.as_mut().unwrap() {
|
||||
PathState::UserSpacePathBuilder(_, None) | PathState::DeviceSpacePathBuilder(_) => {
|
||||
None
|
||||
},
|
||||
PathState::UserSpacePathBuilder(ref mut builder, Some(ref transform)) => {
|
||||
let path = builder.finish();
|
||||
Some(PathState::DeviceSpacePathBuilder(
|
||||
path.transformed_copy_to_builder(transform),
|
||||
))
|
||||
},
|
||||
&PathState::UserSpacePath(ref path, Some(ref transform)) => Some(
|
||||
PathState::UserSpacePath(ref path, Some(ref transform)) => Some(
|
||||
PathState::DeviceSpacePathBuilder(path.transformed_copy_to_builder(transform)),
|
||||
),
|
||||
&PathState::UserSpacePath(ref path, None) => Some(PathState::UserSpacePathBuilder(
|
||||
PathState::UserSpacePath(ref path, None) => Some(PathState::UserSpacePathBuilder(
|
||||
path.copy_to_builder(),
|
||||
None,
|
||||
)),
|
||||
|
@ -716,14 +734,14 @@ impl<'a> CanvasData<'a> {
|
|||
// There's a new builder value that needs to be stored.
|
||||
Some(state) => self.path_state = Some(state),
|
||||
// There's an existing builder value that can be returned immediately.
|
||||
None => match self.path_state.as_ref().unwrap() {
|
||||
&PathState::UserSpacePathBuilder(ref builder, None) => {
|
||||
None => match *self.path_state.as_mut().unwrap() {
|
||||
PathState::UserSpacePathBuilder(ref mut builder, None) => {
|
||||
return PathBuilderRef {
|
||||
builder,
|
||||
transform: Transform2D::identity(),
|
||||
};
|
||||
},
|
||||
&PathState::DeviceSpacePathBuilder(ref builder) => {
|
||||
PathState::DeviceSpacePathBuilder(ref mut builder) => {
|
||||
return PathBuilderRef {
|
||||
builder,
|
||||
transform: self.drawtarget.get_transform(),
|
||||
|
@ -733,16 +751,16 @@ impl<'a> CanvasData<'a> {
|
|||
},
|
||||
}
|
||||
|
||||
match self.path_state.as_ref().unwrap() {
|
||||
&PathState::UserSpacePathBuilder(ref builder, None) => PathBuilderRef {
|
||||
match *self.path_state.as_mut().unwrap() {
|
||||
PathState::UserSpacePathBuilder(ref mut builder, None) => PathBuilderRef {
|
||||
builder,
|
||||
transform: Transform2D::identity(),
|
||||
},
|
||||
&PathState::DeviceSpacePathBuilder(ref builder) => PathBuilderRef {
|
||||
PathState::DeviceSpacePathBuilder(ref mut builder) => PathBuilderRef {
|
||||
builder,
|
||||
transform: self.drawtarget.get_transform(),
|
||||
},
|
||||
&PathState::UserSpacePathBuilder(..) | &PathState::UserSpacePath(..) => unreachable!(),
|
||||
PathState::UserSpacePathBuilder(..) | PathState::UserSpacePath(..) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1023,7 +1041,7 @@ impl<'a> CanvasData<'a> {
|
|||
}
|
||||
|
||||
fn create_draw_target_for_shadow(&self, source_rect: &Rect<f32>) -> Box<dyn GenericDrawTarget> {
|
||||
let draw_target = self.drawtarget.create_similar_draw_target(
|
||||
let mut draw_target = self.drawtarget.create_similar_draw_target(
|
||||
&Size2D::new(
|
||||
source_rect.size.width as i32,
|
||||
source_rect.size.height as i32,
|
||||
|
@ -1039,11 +1057,11 @@ impl<'a> CanvasData<'a> {
|
|||
|
||||
fn draw_with_shadow<F>(&self, rect: &Rect<f32>, draw_shadow_source: F)
|
||||
where
|
||||
F: FnOnce(&dyn GenericDrawTarget),
|
||||
F: FnOnce(&mut dyn GenericDrawTarget),
|
||||
{
|
||||
let shadow_src_rect = self.state.transform.transform_rect(rect);
|
||||
let new_draw_target = self.create_draw_target_for_shadow(&shadow_src_rect);
|
||||
draw_shadow_source(&*new_draw_target);
|
||||
let mut new_draw_target = self.create_draw_target_for_shadow(&shadow_src_rect);
|
||||
draw_shadow_source(&mut *new_draw_target);
|
||||
self.drawtarget.draw_surface_with_shadow(
|
||||
new_draw_target.snapshot(),
|
||||
&Point2D::new(
|
||||
|
@ -1097,8 +1115,8 @@ impl<'a> Drop for CanvasData<'a> {
|
|||
#[derive(Clone)]
|
||||
pub struct CanvasPaintState<'a> {
|
||||
pub draw_options: DrawOptions,
|
||||
pub fill_style: Pattern,
|
||||
pub stroke_style: Pattern,
|
||||
pub fill_style: Pattern<'a>,
|
||||
pub stroke_style: Pattern<'a>,
|
||||
pub stroke_opts: StrokeOptions<'a>,
|
||||
/// The current 2D transform matrix.
|
||||
pub transform: Transform2D<f32>,
|
||||
|
@ -1115,7 +1133,7 @@ pub struct CanvasPaintState<'a> {
|
|||
/// dest_rect: Area of the destination target where the pixels will be copied
|
||||
/// smoothing_enabled: It determines if smoothing is applied to the image result
|
||||
fn write_image(
|
||||
draw_target: &dyn GenericDrawTarget,
|
||||
draw_target: &mut dyn GenericDrawTarget,
|
||||
image_data: Vec<u8>,
|
||||
image_size: Size2D<f64>,
|
||||
dest_rect: Rect<f64>,
|
||||
|
|
|
@ -16,46 +16,56 @@ use std::marker::PhantomData;
|
|||
pub struct RaqoteBackend;
|
||||
|
||||
impl Backend for RaqoteBackend {
|
||||
fn get_composition_op(&self, _opts: &DrawOptions) -> CompositionOp {
|
||||
unimplemented!()
|
||||
fn get_composition_op(&self, opts: &DrawOptions) -> CompositionOp {
|
||||
CompositionOp::Raqote(opts.as_raqote().blend_mode)
|
||||
}
|
||||
|
||||
fn need_to_draw_shadow(&self, _color: &Color) -> bool {
|
||||
unimplemented!()
|
||||
fn need_to_draw_shadow(&self, color: &Color) -> bool {
|
||||
color.as_raqote().a != 0
|
||||
}
|
||||
|
||||
fn size_from_pattern(&self, _rect: &Rect<f32>, _pattern: &Pattern) -> Option<Size2D<f32>> {
|
||||
unimplemented!()
|
||||
fn size_from_pattern(&self, rect: &Rect<f32>, pattern: &Pattern) -> Option<Size2D<f32>> {
|
||||
match pattern {
|
||||
Pattern::Raqote(raqote::Source::Image(image, extend, ..)) => match extend {
|
||||
raqote::ExtendMode::Repeat => Some(rect.size),
|
||||
_ => Some(Size2D::new(image.width as f32, image.height as f32)),
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_shadow_color<'a>(&mut self, _color: RGBA, _state: &mut CanvasPaintState<'a>) {
|
||||
unimplemented!()
|
||||
fn set_shadow_color<'a>(&mut self, color: RGBA, state: &mut CanvasPaintState<'a>) {
|
||||
state.shadow_color = Color::Raqote(color.to_raqote_style());
|
||||
}
|
||||
|
||||
fn set_fill_style<'a>(
|
||||
&mut self,
|
||||
_style: FillOrStrokeStyle,
|
||||
_state: &mut CanvasPaintState<'a>,
|
||||
style: FillOrStrokeStyle,
|
||||
state: &mut CanvasPaintState<'a>,
|
||||
_drawtarget: &dyn GenericDrawTarget,
|
||||
) {
|
||||
unimplemented!()
|
||||
if let Some(source) = style.to_raqote_source() {
|
||||
state.fill_style = Pattern::Raqote(source);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_stroke_style<'a>(
|
||||
&mut self,
|
||||
_style: FillOrStrokeStyle,
|
||||
_state: &mut CanvasPaintState<'a>,
|
||||
style: FillOrStrokeStyle,
|
||||
state: &mut CanvasPaintState<'a>,
|
||||
_drawtarget: &dyn GenericDrawTarget,
|
||||
) {
|
||||
unimplemented!()
|
||||
if let Some(pattern) = style.to_raqote_source() {
|
||||
state.stroke_style = Pattern::Raqote(pattern)
|
||||
}
|
||||
}
|
||||
|
||||
fn set_global_composition<'a>(
|
||||
&mut self,
|
||||
_op: CompositionOrBlending,
|
||||
_state: &mut CanvasPaintState<'a>,
|
||||
op: CompositionOrBlending,
|
||||
state: &mut CanvasPaintState<'a>,
|
||||
) {
|
||||
unimplemented!()
|
||||
state.draw_options.as_raqote_mut().blend_mode = op.to_raqote_style();
|
||||
}
|
||||
|
||||
fn create_drawtarget(&self, size: Size2D<u64>) -> Box<dyn GenericDrawTarget> {
|
||||
|
@ -72,47 +82,95 @@ impl Backend for RaqoteBackend {
|
|||
|
||||
impl<'a> CanvasPaintState<'a> {
|
||||
pub fn new(_antialias: AntialiasMode) -> CanvasPaintState<'a> {
|
||||
let solid_src = raqote::SolidSource {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 255,
|
||||
};
|
||||
CanvasPaintState {
|
||||
draw_options: DrawOptions::Raqote(()),
|
||||
fill_style: Pattern::Raqote(()),
|
||||
stroke_style: Pattern::Raqote(()),
|
||||
stroke_opts: StrokeOptions::Raqote(PhantomData),
|
||||
draw_options: DrawOptions::Raqote(raqote::DrawOptions::new()),
|
||||
fill_style: Pattern::Raqote(raqote::Source::Solid(solid_src)),
|
||||
stroke_style: Pattern::Raqote(raqote::Source::Solid(solid_src)),
|
||||
stroke_opts: StrokeOptions::Raqote(Default::default(), PhantomData),
|
||||
transform: Transform2D::identity(),
|
||||
shadow_offset_x: 0.0,
|
||||
shadow_offset_y: 0.0,
|
||||
shadow_blur: 0.0,
|
||||
shadow_color: Color::Raqote(()),
|
||||
shadow_color: Color::Raqote(raqote::SolidSource {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pattern {
|
||||
impl Pattern<'_> {
|
||||
pub fn is_zero_size_gradient(&self) -> bool {
|
||||
match *self {
|
||||
Pattern::Raqote(()) => unimplemented!(),
|
||||
match self {
|
||||
Pattern::Raqote(p) => {
|
||||
use raqote::Source::*;
|
||||
|
||||
match p {
|
||||
LinearGradient(g, ..) |
|
||||
RadialGradient(g, ..) |
|
||||
TwoCircleRadialGradient(g, ..) => g.stops.is_empty(),
|
||||
_ => false,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
pub fn as_raqote(&self) -> &raqote::Source {
|
||||
match self {
|
||||
Pattern::Raqote(p) => p,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> StrokeOptions<'a> {
|
||||
pub fn set_line_width(&mut self, _val: f32) {
|
||||
unimplemented!()
|
||||
match self {
|
||||
StrokeOptions::Raqote(options, _) => options.width = _val,
|
||||
}
|
||||
}
|
||||
pub fn set_miter_limit(&mut self, _val: f32) {
|
||||
unimplemented!()
|
||||
match self {
|
||||
StrokeOptions::Raqote(options, _) => options.miter_limit = _val,
|
||||
}
|
||||
}
|
||||
pub fn set_line_join(&mut self, _val: LineJoinStyle) {
|
||||
unimplemented!()
|
||||
pub fn set_line_join(&mut self, val: LineJoinStyle) {
|
||||
match self {
|
||||
StrokeOptions::Raqote(options, _) => options.join = val.to_raqote_style(),
|
||||
}
|
||||
}
|
||||
pub fn set_line_cap(&mut self, _val: LineCapStyle) {
|
||||
unimplemented!()
|
||||
pub fn set_line_cap(&mut self, val: LineCapStyle) {
|
||||
match self {
|
||||
StrokeOptions::Raqote(options, _) => options.cap = val.to_raqote_style(),
|
||||
}
|
||||
}
|
||||
pub fn as_raqote(&self) -> &raqote::StrokeStyle {
|
||||
match self {
|
||||
StrokeOptions::Raqote(options, _) => options,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DrawOptions {
|
||||
pub fn set_alpha(&mut self, _val: f32) {
|
||||
pub fn set_alpha(&mut self, val: f32) {
|
||||
match self {
|
||||
DrawOptions::Raqote(()) => unimplemented!(),
|
||||
DrawOptions::Raqote(draw_options) => draw_options.alpha = val,
|
||||
}
|
||||
}
|
||||
pub fn as_raqote(&self) -> &raqote::DrawOptions {
|
||||
match self {
|
||||
DrawOptions::Raqote(options) => options,
|
||||
}
|
||||
}
|
||||
fn as_raqote_mut(&mut self) -> &mut raqote::DrawOptions {
|
||||
match self {
|
||||
DrawOptions::Raqote(options) => options,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,60 +188,108 @@ impl Path {
|
|||
}
|
||||
|
||||
pub fn copy_to_builder(&self) -> Box<dyn GenericPathBuilder> {
|
||||
unimplemented!()
|
||||
Box::new(PathBuilder(Some(raqote::PathBuilder::from(
|
||||
self.as_raqote().clone(),
|
||||
))))
|
||||
}
|
||||
|
||||
pub fn as_raqote(&self) -> &raqote::Path {
|
||||
match self {
|
||||
Path::Raqote(p) => p,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericDrawTarget for raqote::DrawTarget {
|
||||
fn clear_rect(&self, _rect: &Rect<f32>) {
|
||||
unimplemented!()
|
||||
fn clear_rect(&mut self, rect: &Rect<f32>) {
|
||||
let mut pb = raqote::PathBuilder::new();
|
||||
pb.rect(
|
||||
rect.origin.x,
|
||||
rect.origin.y,
|
||||
rect.size.width,
|
||||
rect.size.height,
|
||||
);
|
||||
let mut options = raqote::DrawOptions::new();
|
||||
options.blend_mode = raqote::BlendMode::Clear;
|
||||
raqote::DrawTarget::fill(
|
||||
self,
|
||||
&pb.finish(),
|
||||
&raqote::Source::Solid(raqote::SolidSource {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0,
|
||||
}),
|
||||
&options,
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn copy_surface(
|
||||
&self,
|
||||
_surface: SourceSurface,
|
||||
_source: Rect<i32>,
|
||||
_destination: Point2D<i32>,
|
||||
&mut self,
|
||||
surface: SourceSurface,
|
||||
source: Rect<i32>,
|
||||
destination: Point2D<i32>,
|
||||
) {
|
||||
unimplemented!()
|
||||
let mut dt = raqote::DrawTarget::new(source.size.width, source.size.height);
|
||||
let data = surface.as_raqote();
|
||||
let s = unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u32, data.len() / 4) };
|
||||
dt.get_data_mut().copy_from_slice(s);
|
||||
raqote::DrawTarget::copy_surface(self, &dt, source.to_box2d(), destination);
|
||||
}
|
||||
|
||||
fn create_gradient_stops(
|
||||
&self,
|
||||
_gradient_stops: Vec<GradientStop>,
|
||||
_extend_mode: ExtendMode,
|
||||
) -> GradientStops {
|
||||
unimplemented!()
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn create_path_builder(&self) -> Box<dyn GenericPathBuilder> {
|
||||
unimplemented!()
|
||||
Box::new(PathBuilder::new())
|
||||
}
|
||||
|
||||
fn create_similar_draw_target(
|
||||
&self,
|
||||
_size: &Size2D<i32>,
|
||||
size: &Size2D<i32>,
|
||||
_format: SurfaceFormat,
|
||||
) -> Box<dyn GenericDrawTarget> {
|
||||
unimplemented!()
|
||||
Box::new(raqote::DrawTarget::new(size.width, size.height))
|
||||
}
|
||||
fn create_source_surface_from_data(
|
||||
&self,
|
||||
_data: &[u8],
|
||||
data: &[u8],
|
||||
_size: Size2D<i32>,
|
||||
_stride: i32,
|
||||
) -> Option<SourceSurface> {
|
||||
unimplemented!()
|
||||
Some(SourceSurface::Raqote(data.to_vec()))
|
||||
}
|
||||
#[allow(unsafe_code)]
|
||||
fn draw_surface(
|
||||
&self,
|
||||
_surface: SourceSurface,
|
||||
_dest: Rect<f64>,
|
||||
_source: Rect<f64>,
|
||||
&mut self,
|
||||
surface: SourceSurface,
|
||||
dest: Rect<f64>,
|
||||
source: Rect<f64>,
|
||||
_filter: Filter,
|
||||
_draw_options: &DrawOptions,
|
||||
draw_options: &DrawOptions,
|
||||
) {
|
||||
unimplemented!()
|
||||
let v = surface.as_raqote();
|
||||
let image = raqote::Image {
|
||||
width: source.size.width as i32,
|
||||
height: source.size.height as i32,
|
||||
data: unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
v.as_ptr() as *const u32,
|
||||
v.len() * std::mem::size_of::<u8>(),
|
||||
)
|
||||
},
|
||||
};
|
||||
raqote::DrawTarget::draw_image_with_size_at(
|
||||
self,
|
||||
dest.size.width as f32,
|
||||
dest.size.height as f32,
|
||||
dest.origin.x as f32,
|
||||
dest.origin.y as f32,
|
||||
&image,
|
||||
draw_options.as_raqote(),
|
||||
);
|
||||
}
|
||||
fn draw_surface_with_shadow(
|
||||
&self,
|
||||
|
@ -194,69 +300,362 @@ impl GenericDrawTarget for raqote::DrawTarget {
|
|||
_sigma: f32,
|
||||
_operator: CompositionOp,
|
||||
) {
|
||||
unimplemented!()
|
||||
unimplemented!();
|
||||
}
|
||||
fn fill(&self, _path: &Path, _pattern: Pattern, _draw_options: &DrawOptions) {
|
||||
unimplemented!()
|
||||
fn fill(&mut self, path: &Path, pattern: Pattern, draw_options: &DrawOptions) {
|
||||
self.fill(
|
||||
path.as_raqote(),
|
||||
pattern.as_raqote(),
|
||||
draw_options.as_raqote(),
|
||||
);
|
||||
}
|
||||
fn fill_rect(&self, _rect: &Rect<f32>, _pattern: Pattern, _draw_options: Option<&DrawOptions>) {
|
||||
unimplemented!()
|
||||
fn fill_rect(
|
||||
&mut self,
|
||||
rect: &Rect<f32>,
|
||||
pattern: Pattern,
|
||||
draw_options: Option<&DrawOptions>,
|
||||
) {
|
||||
let mut pb = raqote::PathBuilder::new();
|
||||
pb.rect(
|
||||
rect.origin.x,
|
||||
rect.origin.y,
|
||||
rect.size.width,
|
||||
rect.size.height,
|
||||
);
|
||||
let draw_options = if let Some(options) = draw_options {
|
||||
*options.as_raqote()
|
||||
} else {
|
||||
raqote::DrawOptions::new()
|
||||
};
|
||||
|
||||
raqote::DrawTarget::fill(self, &pb.finish(), pattern.as_raqote(), &draw_options);
|
||||
}
|
||||
fn get_format(&self) -> SurfaceFormat {
|
||||
unimplemented!()
|
||||
SurfaceFormat::Raqote(())
|
||||
}
|
||||
fn get_size(&self) -> Size2D<i32> {
|
||||
unimplemented!()
|
||||
Size2D::new(self.width(), self.height())
|
||||
}
|
||||
fn get_transform(&self) -> Transform2D<f32> {
|
||||
unimplemented!()
|
||||
*self.get_transform()
|
||||
}
|
||||
fn pop_clip(&self) {
|
||||
unimplemented!()
|
||||
fn pop_clip(&mut self) {
|
||||
self.pop_clip();
|
||||
}
|
||||
fn push_clip(&self, _path: &Path) {
|
||||
unimplemented!()
|
||||
fn push_clip(&mut self, path: &Path) {
|
||||
self.push_clip(path.as_raqote());
|
||||
}
|
||||
fn set_transform(&self, _matrix: &Transform2D<f32>) {
|
||||
unimplemented!()
|
||||
fn set_transform(&mut self, matrix: &Transform2D<f32>) {
|
||||
self.set_transform(matrix);
|
||||
}
|
||||
fn snapshot(&self) -> SourceSurface {
|
||||
unimplemented!()
|
||||
unimplemented!();
|
||||
}
|
||||
fn stroke(
|
||||
&self,
|
||||
_path: &Path,
|
||||
_pattern: Pattern,
|
||||
_stroke_options: &StrokeOptions,
|
||||
_draw_options: &DrawOptions,
|
||||
&mut self,
|
||||
path: &Path,
|
||||
pattern: Pattern,
|
||||
stroke_options: &StrokeOptions,
|
||||
draw_options: &DrawOptions,
|
||||
) {
|
||||
unimplemented!()
|
||||
self.stroke(
|
||||
path.as_raqote(),
|
||||
pattern.as_raqote(),
|
||||
stroke_options.as_raqote(),
|
||||
draw_options.as_raqote(),
|
||||
);
|
||||
}
|
||||
fn stroke_line(
|
||||
&self,
|
||||
_start: Point2D<f32>,
|
||||
_end: Point2D<f32>,
|
||||
_pattern: Pattern,
|
||||
_stroke_options: &StrokeOptions,
|
||||
_draw_options: &DrawOptions,
|
||||
&mut self,
|
||||
start: Point2D<f32>,
|
||||
end: Point2D<f32>,
|
||||
pattern: Pattern,
|
||||
stroke_options: &StrokeOptions,
|
||||
draw_options: &DrawOptions,
|
||||
) {
|
||||
unimplemented!()
|
||||
let mut pb = raqote::PathBuilder::new();
|
||||
pb.move_to(start.x, start.y);
|
||||
pb.line_to(end.x, end.y);
|
||||
let mut stroke_options = stroke_options.as_raqote().clone();
|
||||
let cap = match stroke_options.join {
|
||||
raqote::LineJoin::Round => raqote::LineCap::Round,
|
||||
_ => raqote::LineCap::Butt,
|
||||
};
|
||||
stroke_options.cap = cap;
|
||||
|
||||
self.stroke(
|
||||
&pb.finish(),
|
||||
pattern.as_raqote(),
|
||||
&stroke_options,
|
||||
draw_options.as_raqote(),
|
||||
);
|
||||
}
|
||||
fn stroke_rect(
|
||||
&self,
|
||||
_rect: &Rect<f32>,
|
||||
_pattern: Pattern,
|
||||
_stroke_options: &StrokeOptions<'_>,
|
||||
_draw_options: &DrawOptions,
|
||||
&mut self,
|
||||
rect: &Rect<f32>,
|
||||
pattern: Pattern,
|
||||
stroke_options: &StrokeOptions,
|
||||
draw_options: &DrawOptions,
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
let mut pb = raqote::PathBuilder::new();
|
||||
pb.rect(
|
||||
rect.origin.x,
|
||||
rect.origin.y,
|
||||
rect.size.width,
|
||||
rect.size.height,
|
||||
);
|
||||
|
||||
fn snapshot_data(&self, _f: &dyn Fn(&[u8]) -> Vec<u8>) -> Vec<u8> {
|
||||
unimplemented!()
|
||||
self.stroke(
|
||||
&pb.finish(),
|
||||
pattern.as_raqote(),
|
||||
stroke_options.as_raqote(),
|
||||
draw_options.as_raqote(),
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn snapshot_data(&self, f: &dyn Fn(&[u8]) -> Vec<u8>) -> Vec<u8> {
|
||||
let v = self.get_data();
|
||||
f(unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
v.as_ptr() as *const u8,
|
||||
v.len() * std::mem::size_of::<u32>(),
|
||||
)
|
||||
})
|
||||
}
|
||||
#[allow(unsafe_code)]
|
||||
fn snapshot_data_owned(&self) -> Vec<u8> {
|
||||
unimplemented!()
|
||||
let v = self.get_data();
|
||||
unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
v.as_ptr() as *const u8,
|
||||
v.len() * std::mem::size_of::<u32>(),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct PathBuilder(Option<raqote::PathBuilder>);
|
||||
|
||||
impl PathBuilder {
|
||||
fn new() -> PathBuilder {
|
||||
PathBuilder(Some(raqote::PathBuilder::new()))
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericPathBuilder for PathBuilder {
|
||||
fn arc(
|
||||
&mut self,
|
||||
origin: Point2D<f32>,
|
||||
radius: f32,
|
||||
start_angle: f32,
|
||||
end_angle: f32,
|
||||
_anticlockwise: bool,
|
||||
) {
|
||||
self.0
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.arc(origin.x, origin.y, radius, start_angle, end_angle);
|
||||
}
|
||||
fn bezier_curve_to(
|
||||
&mut self,
|
||||
control_point1: &Point2D<f32>,
|
||||
control_point2: &Point2D<f32>,
|
||||
control_point3: &Point2D<f32>,
|
||||
) {
|
||||
self.0.as_mut().unwrap().cubic_to(
|
||||
control_point1.x,
|
||||
control_point1.y,
|
||||
control_point2.x,
|
||||
control_point2.y,
|
||||
control_point3.x,
|
||||
control_point3.y,
|
||||
);
|
||||
}
|
||||
fn close(&mut self) {
|
||||
self.0.as_mut().unwrap().close();
|
||||
}
|
||||
fn ellipse(
|
||||
&mut self,
|
||||
_origin: Point2D<f32>,
|
||||
_radius_x: f32,
|
||||
_radius_y: f32,
|
||||
_rotation_angle: f32,
|
||||
_start_angle: f32,
|
||||
_end_angle: f32,
|
||||
_anticlockwise: bool,
|
||||
) {
|
||||
unimplemented!();
|
||||
}
|
||||
fn get_current_point(&mut self) -> Point2D<f32> {
|
||||
unimplemented!();
|
||||
}
|
||||
fn line_to(&mut self, point: Point2D<f32>) {
|
||||
self.0.as_mut().unwrap().line_to(point.x, point.y);
|
||||
}
|
||||
fn move_to(&mut self, point: Point2D<f32>) {
|
||||
self.0.as_mut().unwrap().move_to(point.x, point.y);
|
||||
}
|
||||
fn quadratic_curve_to(&mut self, control_point: &Point2D<f32>, end_point: &Point2D<f32>) {
|
||||
self.0.as_mut().unwrap().quad_to(
|
||||
control_point.x,
|
||||
control_point.y,
|
||||
end_point.x,
|
||||
end_point.y,
|
||||
);
|
||||
}
|
||||
fn finish(&mut self) -> Path {
|
||||
Path::Raqote(self.0.take().unwrap().finish())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToRaqoteStyle {
|
||||
type Target;
|
||||
|
||||
fn to_raqote_style(self) -> Self::Target;
|
||||
}
|
||||
|
||||
impl ToRaqoteStyle for LineJoinStyle {
|
||||
type Target = raqote::LineJoin;
|
||||
|
||||
fn to_raqote_style(self) -> raqote::LineJoin {
|
||||
match self {
|
||||
LineJoinStyle::Round => raqote::LineJoin::Round,
|
||||
LineJoinStyle::Bevel => raqote::LineJoin::Bevel,
|
||||
LineJoinStyle::Miter => raqote::LineJoin::Miter,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToRaqoteStyle for LineCapStyle {
|
||||
type Target = raqote::LineCap;
|
||||
|
||||
fn to_raqote_style(self) -> raqote::LineCap {
|
||||
match self {
|
||||
LineCapStyle::Butt => raqote::LineCap::Butt,
|
||||
LineCapStyle::Round => raqote::LineCap::Round,
|
||||
LineCapStyle::Square => raqote::LineCap::Square,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToRaqoteSource<'a> {
|
||||
fn to_raqote_source(self) -> Option<raqote::Source<'a>>;
|
||||
}
|
||||
|
||||
impl<'a> ToRaqoteSource<'a> for FillOrStrokeStyle {
|
||||
#[allow(unsafe_code)]
|
||||
fn to_raqote_source(self) -> Option<raqote::Source<'a>> {
|
||||
use canvas_traits::canvas::FillOrStrokeStyle::*;
|
||||
|
||||
match self {
|
||||
Color(rgba) => Some(raqote::Source::Solid(raqote::SolidSource {
|
||||
r: rgba.red,
|
||||
g: rgba.green,
|
||||
b: rgba.blue,
|
||||
a: rgba.alpha,
|
||||
})),
|
||||
LinearGradient(_) => unimplemented!(),
|
||||
RadialGradient(_) => unimplemented!(),
|
||||
Surface(ref surface) => {
|
||||
let data = &surface.surface_data[..];
|
||||
Some(raqote::Source::Image(
|
||||
raqote::Image {
|
||||
data: unsafe {
|
||||
std::slice::from_raw_parts(data.as_ptr() as *const u32, data.len() / 4)
|
||||
},
|
||||
width: surface.surface_size.width as i32,
|
||||
height: surface.surface_size.height as i32,
|
||||
},
|
||||
raqote::ExtendMode::Repeat, // TODO: repeat-x, repeat-y ?
|
||||
raqote::FilterMode::Bilinear,
|
||||
raqote::Transform::identity(),
|
||||
))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Color {
|
||||
fn as_raqote(&self) -> &raqote::SolidSource {
|
||||
match self {
|
||||
Color::Raqote(s) => s,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToRaqoteStyle for RGBA {
|
||||
type Target = raqote::SolidSource;
|
||||
|
||||
fn to_raqote_style(self) -> Self::Target {
|
||||
raqote::SolidSource {
|
||||
r: self.red,
|
||||
g: self.green,
|
||||
b: self.blue,
|
||||
a: self.alpha,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToRaqoteStyle for CompositionOrBlending {
|
||||
type Target = raqote::BlendMode;
|
||||
|
||||
fn to_raqote_style(self) -> Self::Target {
|
||||
match self {
|
||||
CompositionOrBlending::Composition(op) => op.to_raqote_style(),
|
||||
CompositionOrBlending::Blending(op) => op.to_raqote_style(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToRaqoteStyle for BlendingStyle {
|
||||
type Target = raqote::BlendMode;
|
||||
|
||||
fn to_raqote_style(self) -> Self::Target {
|
||||
match self {
|
||||
BlendingStyle::Multiply => raqote::BlendMode::Multiply,
|
||||
BlendingStyle::Screen => raqote::BlendMode::Screen,
|
||||
BlendingStyle::Overlay => raqote::BlendMode::Overlay,
|
||||
BlendingStyle::Darken => raqote::BlendMode::Darken,
|
||||
BlendingStyle::Lighten => raqote::BlendMode::Lighten,
|
||||
BlendingStyle::ColorDodge => raqote::BlendMode::ColorDodge,
|
||||
BlendingStyle::HardLight => raqote::BlendMode::HardLight,
|
||||
BlendingStyle::SoftLight => raqote::BlendMode::SoftLight,
|
||||
BlendingStyle::Difference => raqote::BlendMode::Difference,
|
||||
BlendingStyle::Exclusion => raqote::BlendMode::Exclusion,
|
||||
BlendingStyle::Hue => raqote::BlendMode::Hue,
|
||||
BlendingStyle::Saturation => raqote::BlendMode::Saturation,
|
||||
BlendingStyle::Color => raqote::BlendMode::Color,
|
||||
BlendingStyle::Luminosity => raqote::BlendMode::Luminosity,
|
||||
BlendingStyle::ColorBurn => unimplemented!("raqote doesn't support colorburn"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToRaqoteStyle for CompositionStyle {
|
||||
type Target = raqote::BlendMode;
|
||||
|
||||
fn to_raqote_style(self) -> Self::Target {
|
||||
match self {
|
||||
CompositionStyle::SrcIn => raqote::BlendMode::SrcIn,
|
||||
CompositionStyle::SrcOut => raqote::BlendMode::SrcOut,
|
||||
CompositionStyle::SrcOver => raqote::BlendMode::SrcOver,
|
||||
CompositionStyle::SrcAtop => raqote::BlendMode::SrcAtop,
|
||||
CompositionStyle::DestIn => raqote::BlendMode::DstIn,
|
||||
CompositionStyle::DestOut => raqote::BlendMode::DstOut,
|
||||
CompositionStyle::DestOver => raqote::BlendMode::DstOver,
|
||||
CompositionStyle::DestAtop => raqote::BlendMode::DstAtop,
|
||||
CompositionStyle::Copy => raqote::BlendMode::Src,
|
||||
CompositionStyle::Lighter => raqote::BlendMode::Add,
|
||||
CompositionStyle::Xor => raqote::BlendMode::Xor,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SourceSurface {
|
||||
fn as_raqote(&self) -> &Vec<u8> {
|
||||
match self {
|
||||
SourceSurface::Raqote(s) => s,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue