1use canvas_traits::canvas::*;
6use peniko::ImageAlphaType;
7use pixels::{Alpha, SnapshotPixelFormat};
8use style::color::AbsoluteColor;
9
10use crate::backend::Convert;
11use crate::canvas_data::Filter;
12
13impl Convert<peniko::FontData> for fonts::FontDataAndIndex {
14 fn convert(self) -> peniko::FontData {
15 use std::sync::Arc;
16 peniko::FontData::new(peniko::Blob::new(Arc::new(self.data)), self.index)
17 }
18}
19
20impl Convert<kurbo::Join> for LineJoinStyle {
21 fn convert(self) -> kurbo::Join {
22 match self {
23 LineJoinStyle::Round => kurbo::Join::Round,
24 LineJoinStyle::Bevel => kurbo::Join::Bevel,
25 LineJoinStyle::Miter => kurbo::Join::Miter,
26 }
27 }
28}
29
30impl Convert<kurbo::Cap> for LineCapStyle {
31 fn convert(self) -> kurbo::Cap {
32 match self {
33 LineCapStyle::Butt => kurbo::Cap::Butt,
34 LineCapStyle::Round => kurbo::Cap::Round,
35 LineCapStyle::Square => kurbo::Cap::Square,
36 }
37 }
38}
39
40impl Convert<peniko::Color> for AbsoluteColor {
41 fn convert(self) -> peniko::Color {
42 let srgb = self.into_srgb_legacy();
43 peniko::Color::new([
44 srgb.components.0,
45 srgb.components.1,
46 srgb.components.2,
47 srgb.alpha,
48 ])
49 }
50}
51
52impl Convert<peniko::BlendMode> for CompositionOrBlending {
53 fn convert(self) -> peniko::BlendMode {
54 match self {
55 CompositionOrBlending::Composition(composition_style) => {
56 composition_style.convert().into()
57 },
58 CompositionOrBlending::Blending(blending_style) => blending_style.convert().into(),
59 }
60 }
61}
62
63impl Convert<peniko::Compose> for CompositionStyle {
64 fn convert(self) -> peniko::Compose {
65 match self {
66 CompositionStyle::SourceIn => peniko::Compose::SrcIn,
67 CompositionStyle::SourceOut => peniko::Compose::SrcOut,
68 CompositionStyle::SourceOver => peniko::Compose::SrcOver,
69 CompositionStyle::SourceAtop => peniko::Compose::SrcAtop,
70 CompositionStyle::DestinationIn => peniko::Compose::DestIn,
71 CompositionStyle::DestinationOut => peniko::Compose::DestOut,
72 CompositionStyle::DestinationOver => peniko::Compose::DestOver,
73 CompositionStyle::DestinationAtop => peniko::Compose::DestAtop,
74 CompositionStyle::Copy => peniko::Compose::Copy,
75 CompositionStyle::Lighter => peniko::Compose::Plus,
76 CompositionStyle::Xor => peniko::Compose::Xor,
77 CompositionStyle::Clear => peniko::Compose::Clear,
78 }
79 }
80}
81
82impl Convert<peniko::Mix> for BlendingStyle {
83 fn convert(self) -> peniko::Mix {
84 match self {
85 BlendingStyle::Multiply => peniko::Mix::Multiply,
86 BlendingStyle::Screen => peniko::Mix::Screen,
87 BlendingStyle::Overlay => peniko::Mix::Overlay,
88 BlendingStyle::Darken => peniko::Mix::Darken,
89 BlendingStyle::Lighten => peniko::Mix::Lighten,
90 BlendingStyle::ColorDodge => peniko::Mix::ColorDodge,
91 BlendingStyle::ColorBurn => peniko::Mix::ColorBurn,
92 BlendingStyle::HardLight => peniko::Mix::HardLight,
93 BlendingStyle::SoftLight => peniko::Mix::SoftLight,
94 BlendingStyle::Difference => peniko::Mix::Difference,
95 BlendingStyle::Exclusion => peniko::Mix::Exclusion,
96 BlendingStyle::Hue => peniko::Mix::Hue,
97 BlendingStyle::Saturation => peniko::Mix::Saturation,
98 BlendingStyle::Color => peniko::Mix::Color,
99 BlendingStyle::Luminosity => peniko::Mix::Luminosity,
100 }
101 }
102}
103
104impl Convert<kurbo::Stroke> for LineOptions {
105 fn convert(self) -> kurbo::Stroke {
106 let LineOptions {
107 width,
108 cap_style,
109 join_style,
110 miter_limit,
111 dash,
112 dash_offset,
113 } = self;
114 kurbo::Stroke {
115 width,
116 join: join_style.convert(),
117 miter_limit,
118 start_cap: cap_style.convert(),
119 end_cap: cap_style.convert(),
120 dash_pattern: dash.iter().map(|x| *x as f64).collect(),
121 dash_offset,
122 }
123 }
124}
125
126impl Convert<peniko::ImageFormat> for SnapshotPixelFormat {
127 fn convert(self) -> peniko::ImageFormat {
128 match self {
129 SnapshotPixelFormat::RGBA => peniko::ImageFormat::Rgba8,
130 SnapshotPixelFormat::BGRA => peniko::ImageFormat::Bgra8,
131 }
132 }
133}
134
135impl Convert<ImageAlphaType> for Alpha {
136 fn convert(self) -> ImageAlphaType {
137 match self {
138 Alpha::Premultiplied => ImageAlphaType::AlphaPremultiplied,
139 Alpha::NotPremultiplied => ImageAlphaType::Alpha,
140 Alpha::DontCare => ImageAlphaType::Alpha,
141 }
142 }
143}
144
145impl Convert<peniko::Brush> for FillOrStrokeStyle {
146 fn convert(self) -> peniko::Brush {
147 use canvas_traits::canvas::FillOrStrokeStyle::*;
148 match self {
149 Color(absolute_color) => peniko::Brush::Solid(absolute_color.convert()),
150 LinearGradient(style) => {
151 let start = kurbo::Point::new(style.x0, style.y0);
152 let end = kurbo::Point::new(style.x1, style.y1);
153 let mut gradient = peniko::Gradient::new_linear(start, end);
154 gradient.stops = style.stops.convert();
155 peniko::Brush::Gradient(gradient)
156 },
157 RadialGradient(style) => {
158 let center1 = kurbo::Point::new(style.x0, style.y0);
159 let center2 = kurbo::Point::new(style.x1, style.y1);
160 let mut gradient = peniko::Gradient::new_two_point_radial(
161 center1,
162 style.r0 as f32,
163 center2,
164 style.r1 as f32,
165 );
166 gradient.stops = style.stops.convert();
167 peniko::Brush::Gradient(gradient)
168 },
169 Surface(surface_style) => {
170 let snapshot = &surface_style.surface_data;
171 peniko::Brush::Image(peniko::ImageBrush {
172 image: peniko::ImageData {
173 data: peniko::Blob::from(Vec::from(snapshot.data())),
174 format: snapshot.format().convert(),
175 width: surface_style.surface_size.width,
176 height: surface_style.surface_size.height,
177 alpha_type: snapshot.alpha_mode().alpha().convert(),
178 },
179 sampler: peniko::ImageSampler {
180 x_extend: if surface_style.repeat_x {
181 peniko::Extend::Repeat
182 } else {
183 peniko::Extend::Pad
184 },
185 y_extend: if surface_style.repeat_y {
186 peniko::Extend::Repeat
187 } else {
188 peniko::Extend::Pad
189 },
190 quality: peniko::ImageQuality::Low,
191 alpha: 1.0,
192 },
193 })
194 },
195 }
196 }
197}
198
199impl Convert<peniko::color::DynamicColor> for AbsoluteColor {
200 fn convert(self) -> peniko::color::DynamicColor {
201 peniko::color::DynamicColor::from_alpha_color(self.convert())
202 }
203}
204
205impl Convert<peniko::ColorStop> for CanvasGradientStop {
206 fn convert(self) -> peniko::ColorStop {
207 peniko::ColorStop {
208 offset: self.offset as f32,
209 color: self.color.convert(),
210 }
211 }
212}
213
214impl Convert<peniko::ColorStops> for Vec<CanvasGradientStop> {
215 fn convert(self) -> peniko::ColorStops {
216 let mut stops = peniko::ColorStops(self.into_iter().map(|item| item.convert()).collect());
217 stops
219 .0
220 .sort_by(|a, b| a.offset.partial_cmp(&b.offset).unwrap());
221 stops
222 }
223}
224
225impl Convert<peniko::ImageQuality> for Filter {
226 fn convert(self) -> peniko::ImageQuality {
227 match self {
228 Filter::Bilinear => peniko::ImageQuality::Medium,
229 Filter::Nearest => peniko::ImageQuality::Low,
230 }
231 }
232}
233
234impl Convert<peniko::Fill> for FillRule {
235 fn convert(self) -> peniko::Fill {
236 match self {
237 FillRule::Nonzero => peniko::Fill::NonZero,
238 FillRule::Evenodd => peniko::Fill::EvenOdd,
239 }
240 }
241}