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:
bors-servo 2019-08-22 01:45:40 -04:00 committed by GitHub
commit d8a1c1e02e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 685 additions and 231 deletions

25
Cargo.lock generated
View file

@ -138,7 +138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "azure" name = "azure"
version = "0.36.1" version = "0.36.1"
source = "git+https://github.com/servo/rust-azure#37a57b3d862bcf345d1413c7ebb534ff69daab3b" source = "git+https://github.com/servo/rust-azure#5996612af3139cc3c5eafb019d8218f8ca1634de"
dependencies = [ dependencies = [
"cmake 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2500,12 +2500,13 @@ dependencies = [
[[package]] [[package]]
name = "libflate" name = "libflate"
version = "0.1.19" version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -3004,7 +3005,7 @@ dependencies = [
"immeta 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "immeta 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "libflate 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"malloc_size_of 0.0.1", "malloc_size_of 0.0.1",
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3711,7 +3712,7 @@ dependencies = [
[[package]] [[package]]
name = "raqote" name = "raqote"
version = "0.6.2-alpha.0" version = "0.6.2-alpha.0"
source = "git+https://github.com/jrmuizel/raqote#2d9a0fbb419d10e066fb49e121a45fce1e1f2abe" source = "git+https://github.com/jrmuizel/raqote#b3675e6cc1ac1d854605918f6613b64636d5e47b"
dependencies = [ dependencies = [
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
"font-kit 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "font-kit 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3802,6 +3803,11 @@ dependencies = [
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "rle-decode-fast"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "ron" name = "ron"
version = "0.1.7" version = "0.1.7"
@ -4871,6 +4877,11 @@ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "take_mut"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "task_info" name = "task_info"
version = "0.0.1" version = "0.0.1"
@ -6042,7 +6053,7 @@ dependencies = [
"checksum leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40a8225d44241fd324a8af2806ba635fc7c8a7e9a7de4d5cf3ef54e71f5926fc" "checksum leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40a8225d44241fd324a8af2806ba635fc7c8a7e9a7de4d5cf3ef54e71f5926fc"
"checksum libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)" = "ec350a9417dfd244dc9a6c4a71e13895a4db6b92f0b106f07ebbc3f3bc580cee" "checksum libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)" = "ec350a9417dfd244dc9a6c4a71e13895a4db6b92f0b106f07ebbc3f3bc580cee"
"checksum libdbus-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "99c78106156a964aadc1c59f7798276967be6705243b60f3ab7e131e3841db88" "checksum libdbus-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "99c78106156a964aadc1c59f7798276967be6705243b60f3ab7e131e3841db88"
"checksum libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "bff3ac7d6f23730d3b533c35ed75eef638167634476a499feef16c428d74b57b" "checksum libflate 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "45c97cf62125b79dcac52d506acdc4799f21a198597806947fd5f40dc7b93412"
"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2"
"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
"checksum line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9" "checksum line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9"
@ -6154,6 +6165,7 @@ dependencies = [
"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" "checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58"
"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" "checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
"checksum rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
"checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399" "checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399"
"checksum rust-webvr 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab628b77aaacca496483788a5e0184d42af6dc0e938551aa5be20676c84dd196" "checksum rust-webvr 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab628b77aaacca496483788a5e0184d42af6dc0e938551aa5be20676c84dd196"
"checksum rust-webvr-api 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63d01034b181187e7d048ef4c5caaf95d28d0f7973834907fe7dd74b2bfb66e8" "checksum rust-webvr-api 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63d01034b181187e7d048ef4c5caaf95d28d0f7973834907fe7dd74b2bfb66e8"
@ -6213,6 +6225,7 @@ dependencies = [
"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c" "checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c"
"checksum syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "158521e6f544e7e3dcfc370ac180794aa38cb34a1b1e07609376d4adcf429b93" "checksum syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "158521e6f544e7e3dcfc370ac180794aa38cb34a1b1e07609376d4adcf429b93"
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
"checksum tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dc4738f2e68ed2855de5ac9cdbe05c9216773ecde4739b2f095002ab03a13ef" "checksum tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dc4738f2e68ed2855de5ac9cdbe05c9216773ecde4739b2f095002ab03a13ef"
"checksum tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b" "checksum tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b"
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"

View file

@ -18,6 +18,8 @@ use canvas_traits::canvas::*;
use cssparser::RGBA; use cssparser::RGBA;
use euclid::default::{Point2D, Rect, Size2D, Transform2D, Vector2D}; use euclid::default::{Point2D, Rect, Size2D, Transform2D, Vector2D};
use std::marker::PhantomData;
pub struct AzureBackend; pub struct AzureBackend;
impl Backend for 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>> { fn size_from_pattern(&self, rect: &Rect<f32>, pattern: &Pattern) -> Option<Size2D<f32>> {
match pattern { match pattern {
Pattern::Azure(azure_hl::Pattern::Surface(ref surface)) => { Pattern::Azure(azure_hl::Pattern::Surface(ref surface), _) => {
let surface_size = surface.size(); let surface_size = surface.size();
let size = match (surface.repeat_x, surface.repeat_y) { let size = match (surface.repeat_x, surface.repeat_y) {
(true, true) => rect.size, (true, true) => rect.size,
@ -43,7 +45,7 @@ impl Backend for AzureBackend {
}; };
Some(size) Some(size)
}, },
Pattern::Azure(_) => None, Pattern::Azure(..) => None,
} }
} }
@ -58,7 +60,7 @@ impl Backend for AzureBackend {
drawtarget: &dyn GenericDrawTarget, drawtarget: &dyn GenericDrawTarget,
) { ) {
if let Some(pattern) = style.to_azure_pattern(drawtarget) { 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, drawtarget: &dyn GenericDrawTarget,
) { ) {
if let Some(pattern) = style.to_azure_pattern(drawtarget) { 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, azure_hl::CompositionOp::Over,
antialias.into_azure(), antialias.into_azure(),
)), )),
fill_style: Pattern::Azure(azure_hl::Pattern::Color(ColorPattern::new( fill_style: Pattern::Azure(
azure_hl::Color::black(), 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(), stroke_style: Pattern::Azure(
))), azure_hl::Pattern::Color(ColorPattern::new(azure_hl::Color::black())),
PhantomData::default(),
),
stroke_opts: StrokeOptions::Azure(azure_hl::StrokeOptions::new( stroke_opts: StrokeOptions::Azure(azure_hl::StrokeOptions::new(
1.0, 1.0,
JoinStyle::MiterOrBevel, JoinStyle::MiterOrBevel,
@ -132,14 +136,15 @@ impl<'a> CanvasPaintState<'a> {
impl GenericPathBuilder for azure_hl::PathBuilder { impl GenericPathBuilder for azure_hl::PathBuilder {
fn arc( fn arc(
&self, &mut self,
origin: Point2D<f32>, origin: Point2D<f32>,
radius: f32, radius: f32,
start_angle: f32, start_angle: f32,
end_angle: f32, end_angle: f32,
anticlockwise: bool, anticlockwise: bool,
) { ) {
self.arc( azure_hl::PathBuilder::arc(
self,
origin as Point2D<AzFloat>, origin as Point2D<AzFloat>,
radius as AzFloat, radius as AzFloat,
start_angle as AzFloat, start_angle as AzFloat,
@ -148,22 +153,23 @@ impl GenericPathBuilder for azure_hl::PathBuilder {
); );
} }
fn bezier_curve_to( fn bezier_curve_to(
&self, &mut self,
control_point1: &Point2D<f32>, control_point1: &Point2D<f32>,
control_point2: &Point2D<f32>, control_point2: &Point2D<f32>,
control_point3: &Point2D<f32>, control_point3: &Point2D<f32>,
) { ) {
self.bezier_curve_to( azure_hl::PathBuilder::bezier_curve_to(
self,
control_point1 as &Point2D<AzFloat>, control_point1 as &Point2D<AzFloat>,
control_point2 as &Point2D<AzFloat>, control_point2 as &Point2D<AzFloat>,
control_point3 as &Point2D<AzFloat>, control_point3 as &Point2D<AzFloat>,
); );
} }
fn close(&self) { fn close(&mut self) {
self.close(); azure_hl::PathBuilder::close(self);
} }
fn ellipse( fn ellipse(
&self, &mut self,
origin: Point2D<f32>, origin: Point2D<f32>,
radius_x: f32, radius_x: f32,
radius_y: f32, radius_y: f32,
@ -172,7 +178,8 @@ impl GenericPathBuilder for azure_hl::PathBuilder {
end_angle: f32, end_angle: f32,
anticlockwise: bool, anticlockwise: bool,
) { ) {
self.ellipse( azure_hl::PathBuilder::ellipse(
self,
origin as Point2D<AzFloat>, origin as Point2D<AzFloat>,
radius_x as AzFloat, radius_x as AzFloat,
radius_y as AzFloat, radius_y as AzFloat,
@ -182,34 +189,40 @@ impl GenericPathBuilder for azure_hl::PathBuilder {
anticlockwise, anticlockwise,
); );
} }
fn get_current_point(&self) -> Point2D<f32> { fn get_current_point(&mut self) -> Point2D<f32> {
let AzPoint { x, y } = self.get_current_point(); let AzPoint { x, y } = azure_hl::PathBuilder::get_current_point(self);
Point2D::new(x as f32, y as f32) Point2D::new(x as f32, y as f32)
} }
fn line_to(&self, point: Point2D<f32>) { fn line_to(&mut self, point: Point2D<f32>) {
self.line_to(point as Point2D<AzFloat>); azure_hl::PathBuilder::line_to(self, point as Point2D<AzFloat>);
} }
fn move_to(&self, point: Point2D<f32>) { fn move_to(&mut self, point: Point2D<f32>) {
self.move_to(point as Point2D<AzFloat>); azure_hl::PathBuilder::move_to(self, point as Point2D<AzFloat>);
} }
fn quadratic_curve_to(&self, control_point: &Point2D<f32>, end_point: &Point2D<f32>) { fn quadratic_curve_to(&mut self, control_point: &Point2D<f32>, end_point: &Point2D<f32>) {
self.quadratic_curve_to( azure_hl::PathBuilder::quadratic_curve_to(
self,
control_point as &Point2D<AzFloat>, control_point as &Point2D<AzFloat>,
end_point as &Point2D<AzFloat>, end_point as &Point2D<AzFloat>,
); );
} }
fn finish(&self) -> Path { fn finish(&mut self) -> Path {
Path::Azure(self.finish()) Path::Azure(azure_hl::PathBuilder::finish(self))
} }
} }
impl GenericDrawTarget for azure_hl::DrawTarget { impl GenericDrawTarget for azure_hl::DrawTarget {
fn clear_rect(&self, rect: &Rect<f32>) { fn clear_rect(&mut self, rect: &Rect<f32>) {
self.clear_rect(rect as &Rect<AzFloat>); azure_hl::DrawTarget::clear_rect(self, rect as &Rect<AzFloat>);
} }
fn copy_surface(&self, surface: SourceSurface, source: Rect<i32>, destination: Point2D<i32>) { fn copy_surface(
self.copy_surface(surface.into_azure(), source, destination); &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( fn create_gradient_stops(
@ -243,7 +256,7 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
.map(|s| SourceSurface::Azure(s)) .map(|s| SourceSurface::Azure(s))
} }
fn draw_surface( fn draw_surface(
&self, &mut self,
surface: SourceSurface, surface: SourceSurface,
dest: Rect<f64>, dest: Rect<f64>,
source: Rect<f64>, source: Rect<f64>,
@ -256,7 +269,8 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
draw_options.as_azure().composition, draw_options.as_azure().composition,
azure_hl::AntialiasMode::None, azure_hl::AntialiasMode::None,
); );
self.draw_surface( azure_hl::DrawTarget::draw_surface(
self,
surface.into_azure(), surface.into_azure(),
dest.to_azure_style(), dest.to_azure_style(),
source.to_azure_style(), source.to_azure_style(),
@ -282,15 +296,22 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
operator.into_azure(), operator.into_azure(),
); );
} }
fn fill(&self, path: &Path, pattern: Pattern, draw_options: &DrawOptions) { fn fill(&mut self, path: &Path, pattern: Pattern, draw_options: &DrawOptions) {
self.fill( azure_hl::DrawTarget::fill(
self,
path.as_azure(), path.as_azure(),
pattern.as_azure().to_pattern_ref(), pattern.as_azure().to_pattern_ref(),
draw_options.as_azure(), draw_options.as_azure(),
); );
} }
fn fill_rect(&self, rect: &Rect<f32>, pattern: Pattern, draw_options: Option<&DrawOptions>) { fn fill_rect(
self.fill_rect( &mut self,
rect: &Rect<f32>,
pattern: Pattern,
draw_options: Option<&DrawOptions>,
) {
azure_hl::DrawTarget::fill_rect(
self,
rect as &Rect<AzFloat>, rect as &Rect<AzFloat>,
pattern.as_azure().to_pattern_ref(), pattern.as_azure().to_pattern_ref(),
draw_options.map(|x| x.as_azure()), draw_options.map(|x| x.as_azure()),
@ -306,26 +327,27 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
fn get_transform(&self) -> Transform2D<f32> { fn get_transform(&self) -> Transform2D<f32> {
self.get_transform() as Transform2D<f32> self.get_transform() as Transform2D<f32>
} }
fn pop_clip(&self) { fn pop_clip(&mut self) {
self.pop_clip(); azure_hl::DrawTarget::pop_clip(self);
} }
fn push_clip(&self, path: &Path) { fn push_clip(&mut self, path: &Path) {
self.push_clip(path.as_azure()); azure_hl::DrawTarget::push_clip(self, path.as_azure());
} }
fn set_transform(&self, matrix: &Transform2D<f32>) { fn set_transform(&mut self, matrix: &Transform2D<f32>) {
self.set_transform(matrix as &Transform2D<AzFloat>); azure_hl::DrawTarget::set_transform(self, matrix as &Transform2D<AzFloat>);
} }
fn snapshot(&self) -> SourceSurface { fn snapshot(&self) -> SourceSurface {
SourceSurface::Azure(self.snapshot()) SourceSurface::Azure(self.snapshot())
} }
fn stroke( fn stroke(
&self, &mut self,
path: &Path, path: &Path,
pattern: Pattern, pattern: Pattern,
stroke_options: &StrokeOptions, stroke_options: &StrokeOptions,
draw_options: &DrawOptions, draw_options: &DrawOptions,
) { ) {
self.stroke( azure_hl::DrawTarget::stroke(
self,
path.as_azure(), path.as_azure(),
pattern.as_azure().to_pattern_ref(), pattern.as_azure().to_pattern_ref(),
stroke_options.as_azure(), stroke_options.as_azure(),
@ -333,7 +355,7 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
); );
} }
fn stroke_line( fn stroke_line(
&self, &mut self,
start: Point2D<f32>, start: Point2D<f32>,
end: Point2D<f32>, end: Point2D<f32>,
pattern: Pattern, pattern: Pattern,
@ -354,7 +376,8 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
stroke_options.mDashPattern, stroke_options.mDashPattern,
); );
self.stroke_line( azure_hl::DrawTarget::stroke_line(
self,
start, start,
end, end,
pattern.as_azure().to_pattern_ref(), pattern.as_azure().to_pattern_ref(),
@ -363,13 +386,14 @@ impl GenericDrawTarget for azure_hl::DrawTarget {
); );
} }
fn stroke_rect( fn stroke_rect(
&self, &mut self,
rect: &Rect<f32>, rect: &Rect<f32>,
pattern: Pattern, pattern: Pattern,
stroke_options: &StrokeOptions, stroke_options: &StrokeOptions,
draw_options: &DrawOptions, draw_options: &DrawOptions,
) { ) {
self.stroke_rect( azure_hl::DrawTarget::stroke_rect(
self,
rect as &Rect<AzFloat>, rect as &Rect<AzFloat>,
pattern.as_azure().to_pattern_ref(), pattern.as_azure().to_pattern_ref(),
stroke_options.as_azure(), stroke_options.as_azure(),
@ -469,10 +493,10 @@ impl Path {
} }
} }
impl Pattern { impl Pattern<'_> {
fn as_azure(&self) -> &azure_hl::Pattern { fn as_azure(&self) -> &azure_hl::Pattern {
match self { 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 { pub fn is_zero_size_gradient(&self) -> bool {
match *self { match *self {
Pattern::Azure(azure_hl::Pattern::LinearGradient(ref gradient)) => { Pattern::Azure(azure_hl::Pattern::LinearGradient(ref gradient), _) => {
gradient.is_zero_size() gradient.is_zero_size()
}, },
_ => false, _ => false,

View file

@ -84,7 +84,7 @@ pub trait Backend {
/// azure's and raqote's PathBuilder. /// azure's and raqote's PathBuilder.
pub trait GenericPathBuilder { pub trait GenericPathBuilder {
fn arc( fn arc(
&self, &mut self,
origin: Point2D<f32>, origin: Point2D<f32>,
radius: f32, radius: f32,
start_angle: f32, start_angle: f32,
@ -92,14 +92,14 @@ pub trait GenericPathBuilder {
anticlockwise: bool, anticlockwise: bool,
); );
fn bezier_curve_to( fn bezier_curve_to(
&self, &mut self,
control_point1: &Point2D<f32>, control_point1: &Point2D<f32>,
control_point2: &Point2D<f32>, control_point2: &Point2D<f32>,
control_point3: &Point2D<f32>, control_point3: &Point2D<f32>,
); );
fn close(&self); fn close(&mut self);
fn ellipse( fn ellipse(
&self, &mut self,
origin: Point2D<f32>, origin: Point2D<f32>,
radius_x: f32, radius_x: f32,
radius_y: f32, radius_y: f32,
@ -108,32 +108,32 @@ pub trait GenericPathBuilder {
end_angle: f32, end_angle: f32,
anticlockwise: bool, anticlockwise: bool,
); );
fn get_current_point(&self) -> Point2D<f32>; fn get_current_point(&mut self) -> Point2D<f32>;
fn line_to(&self, point: Point2D<f32>); fn line_to(&mut self, point: Point2D<f32>);
fn move_to(&self, point: Point2D<f32>); fn move_to(&mut self, point: Point2D<f32>);
fn quadratic_curve_to(&self, control_point: &Point2D<f32>, end_point: &Point2D<f32>); fn quadratic_curve_to(&mut self, control_point: &Point2D<f32>, end_point: &Point2D<f32>);
fn finish(&self) -> Path; fn finish(&mut self) -> Path;
} }
/// A wrapper around a stored PathBuilder and an optional transformation that should be /// 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. /// applied to any points to ensure they are in the matching device space.
struct PathBuilderRef<'a> { struct PathBuilderRef<'a> {
builder: &'a Box<dyn GenericPathBuilder>, builder: &'a mut Box<dyn GenericPathBuilder>,
transform: Transform2D<f32>, transform: Transform2D<f32>,
} }
impl<'a> PathBuilderRef<'a> { 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); let pt = self.transform.transform_point(*pt);
self.builder.line_to(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); let pt = self.transform.transform_point(*pt);
self.builder.move_to(pt); self.builder.move_to(pt);
} }
fn rect(&self, rect: &Rect<f32>) { fn rect(&mut self, rect: &Rect<f32>) {
let (first, second, third, fourth) = ( let (first, second, third, fourth) = (
Point2D::new(rect.origin.x, rect.origin.y), Point2D::new(rect.origin.x, rect.origin.y),
Point2D::new(rect.origin.x + rect.size.width, 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(); 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.builder.quadratic_curve_to(
&self.transform.transform_point(*cp), &self.transform.transform_point(*cp),
&self.transform.transform_point(*endpoint), &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.builder.bezier_curve_to(
&self.transform.transform_point(*cp1), &self.transform.transform_point(*cp1),
&self.transform.transform_point(*cp2), &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); let center = self.transform.transform_point(*center);
self.builder self.builder
.arc(center, radius, start_angle, end_angle, ccw); .arc(center, radius, start_angle, end_angle, ccw);
} }
pub fn ellipse( pub fn ellipse(
&self, &mut self,
center: &Point2D<f32>, center: &Point2D<f32>,
radius_x: f32, radius_x: f32,
radius_y: 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() { let inverse = match self.transform.inverse() {
Some(i) => i, Some(i) => i,
None => return None, None => return None,
@ -207,8 +214,13 @@ impl<'a> PathBuilderRef<'a> {
// This defines required methods for DrawTarget of azure and raqote // This defines required methods for DrawTarget of azure and raqote
// The prototypes are derived from azure's methods. // The prototypes are derived from azure's methods.
pub trait GenericDrawTarget { pub trait GenericDrawTarget {
fn clear_rect(&self, rect: &Rect<f32>); fn clear_rect(&mut self, rect: &Rect<f32>);
fn copy_surface(&self, surface: SourceSurface, source: Rect<i32>, destination: Point2D<i32>); fn copy_surface(
&mut self,
surface: SourceSurface,
source: Rect<i32>,
destination: Point2D<i32>,
);
fn create_gradient_stops( fn create_gradient_stops(
&self, &self,
gradient_stops: Vec<GradientStop>, gradient_stops: Vec<GradientStop>,
@ -227,7 +239,7 @@ pub trait GenericDrawTarget {
stride: i32, stride: i32,
) -> Option<SourceSurface>; ) -> Option<SourceSurface>;
fn draw_surface( fn draw_surface(
&self, &mut self,
surface: SourceSurface, surface: SourceSurface,
dest: Rect<f64>, dest: Rect<f64>,
source: Rect<f64>, source: Rect<f64>,
@ -243,24 +255,24 @@ pub trait GenericDrawTarget {
sigma: f32, sigma: f32,
operator: CompositionOp, operator: CompositionOp,
); );
fn fill(&self, path: &Path, pattern: Pattern, draw_options: &DrawOptions); fn fill(&mut self, path: &Path, pattern: Pattern, draw_options: &DrawOptions);
fn fill_rect(&self, rect: &Rect<f32>, pattern: Pattern, draw_options: Option<&DrawOptions>); fn fill_rect(&mut self, rect: &Rect<f32>, pattern: Pattern, draw_options: Option<&DrawOptions>);
fn get_format(&self) -> SurfaceFormat; fn get_format(&self) -> SurfaceFormat;
fn get_size(&self) -> Size2D<i32>; fn get_size(&self) -> Size2D<i32>;
fn get_transform(&self) -> Transform2D<f32>; fn get_transform(&self) -> Transform2D<f32>;
fn pop_clip(&self); fn pop_clip(&mut self);
fn push_clip(&self, path: &Path); fn push_clip(&mut self, path: &Path);
fn set_transform(&self, matrix: &Transform2D<f32>); fn set_transform(&mut self, matrix: &Transform2D<f32>);
fn snapshot(&self) -> SourceSurface; fn snapshot(&self) -> SourceSurface;
fn stroke( fn stroke(
&self, &mut self,
path: &Path, path: &Path,
pattern: Pattern, pattern: Pattern,
stroke_options: &StrokeOptions, stroke_options: &StrokeOptions,
draw_options: &DrawOptions, draw_options: &DrawOptions,
); );
fn stroke_line( fn stroke_line(
&self, &mut self,
start: Point2D<f32>, start: Point2D<f32>,
end: Point2D<f32>, end: Point2D<f32>,
pattern: Pattern, pattern: Pattern,
@ -268,7 +280,7 @@ pub trait GenericDrawTarget {
draw_options: &DrawOptions, draw_options: &DrawOptions,
); );
fn stroke_rect( fn stroke_rect(
&self, &mut self,
rect: &Rect<f32>, rect: &Rect<f32>,
pattern: Pattern, pattern: Pattern,
stroke_options: &StrokeOptions, stroke_options: &StrokeOptions,
@ -305,7 +317,7 @@ pub enum Color {
#[cfg(feature = "canvas2d-azure")] #[cfg(feature = "canvas2d-azure")]
Azure(azure::azure_hl::Color), Azure(azure::azure_hl::Color),
#[cfg(feature = "canvas2d-raqote")] #[cfg(feature = "canvas2d-raqote")]
Raqote(()), Raqote(raqote::SolidSource),
} }
#[derive(Clone)] #[derive(Clone)]
@ -313,7 +325,7 @@ pub enum CompositionOp {
#[cfg(feature = "canvas2d-azure")] #[cfg(feature = "canvas2d-azure")]
Azure(azure::azure_hl::CompositionOp), Azure(azure::azure_hl::CompositionOp),
#[cfg(feature = "canvas2d-raqote")] #[cfg(feature = "canvas2d-raqote")]
Raqote(()), Raqote(raqote::BlendMode),
} }
pub enum SurfaceFormat { pub enum SurfaceFormat {
@ -328,22 +340,23 @@ pub enum SourceSurface {
#[cfg(feature = "canvas2d-azure")] #[cfg(feature = "canvas2d-azure")]
Azure(azure::azure_hl::SourceSurface), Azure(azure::azure_hl::SourceSurface),
#[cfg(feature = "canvas2d-raqote")] #[cfg(feature = "canvas2d-raqote")]
Raqote(()), Raqote(Vec<u8>), // TODO: See if we can avoid the alloc (probably?)
} }
#[derive(Clone)]
pub enum Path { pub enum Path {
#[cfg(feature = "canvas2d-azure")] #[cfg(feature = "canvas2d-azure")]
Azure(azure::azure_hl::Path), Azure(azure::azure_hl::Path),
#[cfg(feature = "canvas2d-raqote")] #[cfg(feature = "canvas2d-raqote")]
Raqote(()), Raqote(raqote::Path),
} }
#[derive(Clone)] #[derive(Clone)]
pub enum Pattern { pub enum Pattern<'a> {
#[cfg(feature = "canvas2d-azure")] #[cfg(feature = "canvas2d-azure")]
Azure(azure::azure_hl::Pattern), Azure(azure::azure_hl::Pattern, PhantomData<&'a ()>),
#[cfg(feature = "canvas2d-raqote")] #[cfg(feature = "canvas2d-raqote")]
Raqote(()), Raqote(raqote::Source<'a>),
} }
pub enum DrawSurfaceOptions { pub enum DrawSurfaceOptions {
@ -358,7 +371,7 @@ pub enum DrawOptions {
#[cfg(feature = "canvas2d-azure")] #[cfg(feature = "canvas2d-azure")]
Azure(azure::azure_hl::DrawOptions), Azure(azure::azure_hl::DrawOptions),
#[cfg(feature = "canvas2d-raqote")] #[cfg(feature = "canvas2d-raqote")]
Raqote(()), Raqote(raqote::DrawOptions),
} }
#[derive(Clone)] #[derive(Clone)]
@ -366,7 +379,7 @@ pub enum StrokeOptions<'a> {
#[cfg(feature = "canvas2d-azure")] #[cfg(feature = "canvas2d-azure")]
Azure(azure::azure_hl::StrokeOptions<'a>), Azure(azure::azure_hl::StrokeOptions<'a>),
#[cfg(feature = "canvas2d-raqote")] #[cfg(feature = "canvas2d-raqote")]
Raqote(PhantomData<&'a ()>), Raqote(raqote::StrokeStyle, PhantomData<&'a ()>),
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -425,7 +438,7 @@ impl<'a> CanvasData<'a> {
} }
pub fn draw_image( pub fn draw_image(
&self, &mut self,
image_data: Vec<u8>, image_data: Vec<u8>,
image_size: Size2D<f64>, image_size: Size2D<f64>,
dest_rect: Rect<f64>, dest_rect: Rect<f64>,
@ -441,14 +454,15 @@ impl<'a> CanvasData<'a> {
image_data.into() 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( write_image(
draw_target, draw_target,
image_data, image_data,
source_rect.size, source_rect.size,
dest_rect, dest_rect,
smoothing_enabled, smoothing_enabled,
&self.state.draw_options, &draw_options,
); );
}; };
@ -461,7 +475,7 @@ impl<'a> CanvasData<'a> {
// TODO(pylbrecht) pass another closure for raqote // TODO(pylbrecht) pass another closure for raqote
self.draw_with_shadow(&rect, writer); self.draw_with_shadow(&rect, writer);
} else { } 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() { if self.state.fill_style.is_zero_size_gradient() {
return; // Paint nothing if gradient size is zero. return; // Paint nothing if gradient size is zero.
} }
@ -497,7 +511,7 @@ impl<'a> CanvasData<'a> {
); );
if self.need_to_draw_shadow() { 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( new_draw_target.fill_rect(
&draw_rect, &draw_rect,
self.state.fill_style.clone(), 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); 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() { if self.state.stroke_style.is_zero_size_gradient() {
return; // Paint nothing if gradient size is zero. return; // Paint nothing if gradient size is zero.
} }
if self.need_to_draw_shadow() { 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( new_draw_target.stroke_rect(
rect, rect,
self.state.stroke_style.clone(), self.state.stroke_style.clone(),
@ -532,11 +546,13 @@ impl<'a> CanvasData<'a> {
); );
}); });
} else if rect.size.width == 0. || rect.size.height == 0. { } 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( self.drawtarget.stroke_line(
rect.origin, rect.origin,
rect.bottom_right(), rect.bottom_right(),
self.state.stroke_style.clone(), self.state.stroke_style.clone(),
&self.state.stroke_opts, &stroke_opts,
&self.state.draw_options, &self.state.draw_options,
); );
} else { } else {
@ -569,7 +585,7 @@ impl<'a> CanvasData<'a> {
// If a user-space builder exists, create a finished path from it. // If a user-space builder exists, create a finished path from it.
let new_state = match *self.path_state.as_mut().unwrap() { 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())) Some((builder.finish(), transform.take()))
}, },
PathState::DeviceSpacePathBuilder(..) | PathState::UserSpacePath(..) => None, 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 // If a device-space builder is present, create a user-space path from its
// finished path by inverting the initial transformation. // finished path by inverting the initial transformation.
let new_state = match self.path_state.as_ref().unwrap() { let new_state = match *self.path_state.as_mut().unwrap() {
PathState::DeviceSpacePathBuilder(ref builder) => { PathState::DeviceSpacePathBuilder(ref mut builder) => {
let path = builder.finish(); let path = builder.finish();
let inverse = match self.drawtarget.get_transform().inverse() { let inverse = match self.drawtarget.get_transform().inverse() {
Some(m) => m, Some(m) => m,
@ -604,7 +620,7 @@ impl<'a> CanvasData<'a> {
return; return;
}, },
}; };
let builder = path.transformed_copy_to_builder(&inverse); let mut builder = path.transformed_copy_to_builder(&inverse);
Some(builder.finish()) Some(builder.finish())
}, },
PathState::UserSpacePathBuilder(..) | PathState::UserSpacePath(..) => None, PathState::UserSpacePathBuilder(..) | PathState::UserSpacePath(..) => None,
@ -630,7 +646,7 @@ impl<'a> CanvasData<'a> {
self.ensure_path(); self.ensure_path();
self.drawtarget.fill( self.drawtarget.fill(
&self.path(), &self.path().clone(),
self.state.fill_style.clone(), self.state.fill_style.clone(),
&self.state.draw_options, &self.state.draw_options,
); );
@ -643,7 +659,7 @@ impl<'a> CanvasData<'a> {
self.ensure_path(); self.ensure_path();
self.drawtarget.stroke( self.drawtarget.stroke(
&self.path(), &self.path().clone(),
self.state.stroke_style.clone(), self.state.stroke_style.clone(),
&self.state.stroke_opts, &self.state.stroke_opts,
&self.state.draw_options, &self.state.draw_options,
@ -652,7 +668,8 @@ impl<'a> CanvasData<'a> {
pub fn clip(&mut self) { pub fn clip(&mut self) {
self.ensure_path(); 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( 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 // and overwriting path_state in other ones. The following awkward use of duplicate
// matches works around the resulting borrow errors. // matches works around the resulting borrow errors.
let new_state = { let new_state = {
match self.path_state.as_ref().unwrap() { match *self.path_state.as_mut().unwrap() {
&PathState::UserSpacePathBuilder(_, None) | PathState::UserSpacePathBuilder(_, None) | PathState::DeviceSpacePathBuilder(_) => {
&PathState::DeviceSpacePathBuilder(_) => None, None
&PathState::UserSpacePathBuilder(ref builder, Some(ref transform)) => { },
PathState::UserSpacePathBuilder(ref mut builder, Some(ref transform)) => {
let path = builder.finish(); let path = builder.finish();
Some(PathState::DeviceSpacePathBuilder( Some(PathState::DeviceSpacePathBuilder(
path.transformed_copy_to_builder(transform), 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::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(), path.copy_to_builder(),
None, None,
)), )),
@ -716,14 +734,14 @@ impl<'a> CanvasData<'a> {
// There's a new builder value that needs to be stored. // There's a new builder value that needs to be stored.
Some(state) => self.path_state = Some(state), Some(state) => self.path_state = Some(state),
// There's an existing builder value that can be returned immediately. // There's an existing builder value that can be returned immediately.
None => match self.path_state.as_ref().unwrap() { None => match *self.path_state.as_mut().unwrap() {
&PathState::UserSpacePathBuilder(ref builder, None) => { PathState::UserSpacePathBuilder(ref mut builder, None) => {
return PathBuilderRef { return PathBuilderRef {
builder, builder,
transform: Transform2D::identity(), transform: Transform2D::identity(),
}; };
}, },
&PathState::DeviceSpacePathBuilder(ref builder) => { PathState::DeviceSpacePathBuilder(ref mut builder) => {
return PathBuilderRef { return PathBuilderRef {
builder, builder,
transform: self.drawtarget.get_transform(), transform: self.drawtarget.get_transform(),
@ -733,16 +751,16 @@ impl<'a> CanvasData<'a> {
}, },
} }
match self.path_state.as_ref().unwrap() { match *self.path_state.as_mut().unwrap() {
&PathState::UserSpacePathBuilder(ref builder, None) => PathBuilderRef { PathState::UserSpacePathBuilder(ref mut builder, None) => PathBuilderRef {
builder, builder,
transform: Transform2D::identity(), transform: Transform2D::identity(),
}, },
&PathState::DeviceSpacePathBuilder(ref builder) => PathBuilderRef { PathState::DeviceSpacePathBuilder(ref mut builder) => PathBuilderRef {
builder, builder,
transform: self.drawtarget.get_transform(), 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> { 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( &Size2D::new(
source_rect.size.width as i32, source_rect.size.width as i32,
source_rect.size.height 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) fn draw_with_shadow<F>(&self, rect: &Rect<f32>, draw_shadow_source: F)
where where
F: FnOnce(&dyn GenericDrawTarget), F: FnOnce(&mut dyn GenericDrawTarget),
{ {
let shadow_src_rect = self.state.transform.transform_rect(rect); let shadow_src_rect = self.state.transform.transform_rect(rect);
let new_draw_target = self.create_draw_target_for_shadow(&shadow_src_rect); let mut new_draw_target = self.create_draw_target_for_shadow(&shadow_src_rect);
draw_shadow_source(&*new_draw_target); draw_shadow_source(&mut *new_draw_target);
self.drawtarget.draw_surface_with_shadow( self.drawtarget.draw_surface_with_shadow(
new_draw_target.snapshot(), new_draw_target.snapshot(),
&Point2D::new( &Point2D::new(
@ -1097,8 +1115,8 @@ impl<'a> Drop for CanvasData<'a> {
#[derive(Clone)] #[derive(Clone)]
pub struct CanvasPaintState<'a> { pub struct CanvasPaintState<'a> {
pub draw_options: DrawOptions, pub draw_options: DrawOptions,
pub fill_style: Pattern, pub fill_style: Pattern<'a>,
pub stroke_style: Pattern, pub stroke_style: Pattern<'a>,
pub stroke_opts: StrokeOptions<'a>, pub stroke_opts: StrokeOptions<'a>,
/// The current 2D transform matrix. /// The current 2D transform matrix.
pub transform: Transform2D<f32>, 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 /// 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 /// smoothing_enabled: It determines if smoothing is applied to the image result
fn write_image( fn write_image(
draw_target: &dyn GenericDrawTarget, draw_target: &mut dyn GenericDrawTarget,
image_data: Vec<u8>, image_data: Vec<u8>,
image_size: Size2D<f64>, image_size: Size2D<f64>,
dest_rect: Rect<f64>, dest_rect: Rect<f64>,

View file

@ -16,46 +16,56 @@ use std::marker::PhantomData;
pub struct RaqoteBackend; pub struct RaqoteBackend;
impl Backend for RaqoteBackend { impl Backend for RaqoteBackend {
fn get_composition_op(&self, _opts: &DrawOptions) -> CompositionOp { fn get_composition_op(&self, opts: &DrawOptions) -> CompositionOp {
unimplemented!() CompositionOp::Raqote(opts.as_raqote().blend_mode)
} }
fn need_to_draw_shadow(&self, _color: &Color) -> bool { fn need_to_draw_shadow(&self, color: &Color) -> bool {
unimplemented!() color.as_raqote().a != 0
} }
fn size_from_pattern(&self, _rect: &Rect<f32>, _pattern: &Pattern) -> Option<Size2D<f32>> { fn size_from_pattern(&self, rect: &Rect<f32>, pattern: &Pattern) -> Option<Size2D<f32>> {
unimplemented!() 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>) { fn set_shadow_color<'a>(&mut self, color: RGBA, state: &mut CanvasPaintState<'a>) {
unimplemented!() state.shadow_color = Color::Raqote(color.to_raqote_style());
} }
fn set_fill_style<'a>( fn set_fill_style<'a>(
&mut self, &mut self,
_style: FillOrStrokeStyle, style: FillOrStrokeStyle,
_state: &mut CanvasPaintState<'a>, state: &mut CanvasPaintState<'a>,
_drawtarget: &dyn GenericDrawTarget, _drawtarget: &dyn GenericDrawTarget,
) { ) {
unimplemented!() if let Some(source) = style.to_raqote_source() {
state.fill_style = Pattern::Raqote(source);
}
} }
fn set_stroke_style<'a>( fn set_stroke_style<'a>(
&mut self, &mut self,
_style: FillOrStrokeStyle, style: FillOrStrokeStyle,
_state: &mut CanvasPaintState<'a>, state: &mut CanvasPaintState<'a>,
_drawtarget: &dyn GenericDrawTarget, _drawtarget: &dyn GenericDrawTarget,
) { ) {
unimplemented!() if let Some(pattern) = style.to_raqote_source() {
state.stroke_style = Pattern::Raqote(pattern)
}
} }
fn set_global_composition<'a>( fn set_global_composition<'a>(
&mut self, &mut self,
_op: CompositionOrBlending, op: CompositionOrBlending,
_state: &mut CanvasPaintState<'a>, 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> { fn create_drawtarget(&self, size: Size2D<u64>) -> Box<dyn GenericDrawTarget> {
@ -72,47 +82,95 @@ impl Backend for RaqoteBackend {
impl<'a> CanvasPaintState<'a> { impl<'a> CanvasPaintState<'a> {
pub fn new(_antialias: AntialiasMode) -> CanvasPaintState<'a> { pub fn new(_antialias: AntialiasMode) -> CanvasPaintState<'a> {
let solid_src = raqote::SolidSource {
r: 0,
g: 0,
b: 0,
a: 255,
};
CanvasPaintState { CanvasPaintState {
draw_options: DrawOptions::Raqote(()), draw_options: DrawOptions::Raqote(raqote::DrawOptions::new()),
fill_style: Pattern::Raqote(()), fill_style: Pattern::Raqote(raqote::Source::Solid(solid_src)),
stroke_style: Pattern::Raqote(()), stroke_style: Pattern::Raqote(raqote::Source::Solid(solid_src)),
stroke_opts: StrokeOptions::Raqote(PhantomData), stroke_opts: StrokeOptions::Raqote(Default::default(), PhantomData),
transform: Transform2D::identity(), transform: Transform2D::identity(),
shadow_offset_x: 0.0, shadow_offset_x: 0.0,
shadow_offset_y: 0.0, shadow_offset_y: 0.0,
shadow_blur: 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 { pub fn is_zero_size_gradient(&self) -> bool {
match *self { match self {
Pattern::Raqote(()) => unimplemented!(), 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> { impl<'a> StrokeOptions<'a> {
pub fn set_line_width(&mut self, _val: f32) { 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) { 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) { pub fn set_line_join(&mut self, val: LineJoinStyle) {
unimplemented!() match self {
StrokeOptions::Raqote(options, _) => options.join = val.to_raqote_style(),
}
} }
pub fn set_line_cap(&mut self, _val: LineCapStyle) { pub fn set_line_cap(&mut self, val: LineCapStyle) {
unimplemented!() 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 { impl DrawOptions {
pub fn set_alpha(&mut self, _val: f32) { pub fn set_alpha(&mut self, val: f32) {
match self { 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> { 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 { impl GenericDrawTarget for raqote::DrawTarget {
fn clear_rect(&self, _rect: &Rect<f32>) { fn clear_rect(&mut self, rect: &Rect<f32>) {
unimplemented!() 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( fn copy_surface(
&self, &mut self,
_surface: SourceSurface, surface: SourceSurface,
_source: Rect<i32>, source: Rect<i32>,
_destination: Point2D<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( fn create_gradient_stops(
&self, &self,
_gradient_stops: Vec<GradientStop>, _gradient_stops: Vec<GradientStop>,
_extend_mode: ExtendMode, _extend_mode: ExtendMode,
) -> GradientStops { ) -> GradientStops {
unimplemented!() unimplemented!();
} }
fn create_path_builder(&self) -> Box<dyn GenericPathBuilder> { fn create_path_builder(&self) -> Box<dyn GenericPathBuilder> {
unimplemented!() Box::new(PathBuilder::new())
} }
fn create_similar_draw_target( fn create_similar_draw_target(
&self, &self,
_size: &Size2D<i32>, size: &Size2D<i32>,
_format: SurfaceFormat, _format: SurfaceFormat,
) -> Box<dyn GenericDrawTarget> { ) -> Box<dyn GenericDrawTarget> {
unimplemented!() Box::new(raqote::DrawTarget::new(size.width, size.height))
} }
fn create_source_surface_from_data( fn create_source_surface_from_data(
&self, &self,
_data: &[u8], data: &[u8],
_size: Size2D<i32>, _size: Size2D<i32>,
_stride: i32, _stride: i32,
) -> Option<SourceSurface> { ) -> Option<SourceSurface> {
unimplemented!() Some(SourceSurface::Raqote(data.to_vec()))
} }
#[allow(unsafe_code)]
fn draw_surface( fn draw_surface(
&self, &mut self,
_surface: SourceSurface, surface: SourceSurface,
_dest: Rect<f64>, dest: Rect<f64>,
_source: Rect<f64>, source: Rect<f64>,
_filter: Filter, _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( fn draw_surface_with_shadow(
&self, &self,
@ -194,69 +300,362 @@ impl GenericDrawTarget for raqote::DrawTarget {
_sigma: f32, _sigma: f32,
_operator: CompositionOp, _operator: CompositionOp,
) { ) {
unimplemented!() unimplemented!();
} }
fn fill(&self, _path: &Path, _pattern: Pattern, _draw_options: &DrawOptions) { fn fill(&mut self, path: &Path, pattern: Pattern, draw_options: &DrawOptions) {
unimplemented!() 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>) { fn fill_rect(
unimplemented!() &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 { fn get_format(&self) -> SurfaceFormat {
unimplemented!() SurfaceFormat::Raqote(())
} }
fn get_size(&self) -> Size2D<i32> { fn get_size(&self) -> Size2D<i32> {
unimplemented!() Size2D::new(self.width(), self.height())
} }
fn get_transform(&self) -> Transform2D<f32> { fn get_transform(&self) -> Transform2D<f32> {
unimplemented!() *self.get_transform()
} }
fn pop_clip(&self) { fn pop_clip(&mut self) {
unimplemented!() self.pop_clip();
} }
fn push_clip(&self, _path: &Path) { fn push_clip(&mut self, path: &Path) {
unimplemented!() self.push_clip(path.as_raqote());
} }
fn set_transform(&self, _matrix: &Transform2D<f32>) { fn set_transform(&mut self, matrix: &Transform2D<f32>) {
unimplemented!() self.set_transform(matrix);
} }
fn snapshot(&self) -> SourceSurface { fn snapshot(&self) -> SourceSurface {
unimplemented!() unimplemented!();
} }
fn stroke( fn stroke(
&self, &mut self,
_path: &Path, path: &Path,
_pattern: Pattern, pattern: Pattern,
_stroke_options: &StrokeOptions, stroke_options: &StrokeOptions,
_draw_options: &DrawOptions, draw_options: &DrawOptions,
) { ) {
unimplemented!() self.stroke(
path.as_raqote(),
pattern.as_raqote(),
stroke_options.as_raqote(),
draw_options.as_raqote(),
);
} }
fn stroke_line( fn stroke_line(
&self, &mut self,
_start: Point2D<f32>, start: Point2D<f32>,
_end: Point2D<f32>, end: Point2D<f32>,
_pattern: Pattern, pattern: Pattern,
_stroke_options: &StrokeOptions, stroke_options: &StrokeOptions,
_draw_options: &DrawOptions, 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( fn stroke_rect(
&self, &mut self,
_rect: &Rect<f32>, rect: &Rect<f32>,
_pattern: Pattern, pattern: Pattern,
_stroke_options: &StrokeOptions<'_>, stroke_options: &StrokeOptions,
_draw_options: &DrawOptions, 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> { self.stroke(
unimplemented!() &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> { 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,
}
} }
} }