1 use crate::rasterizer::Rasterizer;
2 
3 use crate::blitter::*;
4 use sw_composite::*;
5 
6 use crate::dash::*;
7 use crate::geom::*;
8 use crate::path_builder::*;
9 
10 pub use crate::path_builder::Winding;
11 use lyon_geom::cubic_to_quadratic::cubic_to_quadratics;
12 use lyon_geom::CubicBezierSegment;
13 
14 #[cfg(feature = "text")]
15 mod fk {
16     pub use font_kit::canvas::{Canvas, Format, RasterizationOptions};
17     pub use font_kit::font::Font;
18     pub use font_kit::hinting::HintingOptions;
19     pub use font_kit::loader::FontTransform;
20 }
21 
22 use std::fs::*;
23 use std::io::BufWriter;
24 
25 use crate::stroke::*;
26 use crate::{IntRect, IntPoint, Point, Transform, Vector};
27 
28 use euclid::vec2;
29 
30 #[derive(Clone)]
31 pub struct Mask {
32     pub width: i32,
33     pub height: i32,
34     pub data: Vec<u8>,
35 }
36 
37 /// A premultiplied color. i.e. r,b,g <= a
38 #[derive(Clone, Copy, PartialEq, Debug)]
39 pub struct SolidSource {
40     pub r: u8,
41     pub g: u8,
42     pub b: u8,
43     pub a: u8,
44 }
45 
46 impl SolidSource {
to_u32(&self) -> u3247     pub fn to_u32(&self) -> u32 {
48         let color = ((self.a as u32) << 24)
49             | ((self.r as u32) << 16)
50             | ((self.g as u32) << 8)
51             | ((self.b as u32) << 0);
52         color
53     }
54 
from_unpremultiplied_argb(a: u8, r: u8, g: u8, b: u8) -> Self55     pub fn from_unpremultiplied_argb(a: u8, r: u8, g: u8, b: u8) -> Self {
56         SolidSource {
57             a: a,
58             r: muldiv255(a as u32, r as u32) as u8,
59             g: muldiv255(a as u32, g as u32) as u8,
60             b: muldiv255(a as u32, b as u32) as u8
61         }
62     }
63 }
64 
65 #[derive(PartialEq, Clone, Copy, Debug)]
66 pub enum BlendMode {
67     Dst,
68     Src,
69     Clear,
70     SrcOver,
71     DstOver,
72     SrcIn,
73     DstIn,
74     SrcOut,
75     DstOut,
76     SrcAtop,
77     DstAtop,
78     Xor,
79     Add,
80 
81     Screen,
82     Overlay,
83     Darken,
84     Lighten,
85     ColorDodge,
86     ColorBurn,
87     HardLight,
88     SoftLight,
89     Difference,
90     Exclusion,
91     Multiply,
92     Hue,
93     Saturation,
94     Color,
95     Luminosity
96 }
97 
98 trait Blender {
99     type Output;
build<T: blend::Blend>() -> Self::Output100     fn build<T: blend::Blend>() -> Self::Output;
101 }
102 
103 struct BlendRow;
104 
blend_row<T: blend::Blend>(src: &[u32], dst: &mut [u32])105 fn blend_row<T: blend::Blend>(src: &[u32], dst: &mut [u32]) {
106     for (dst, src) in dst.iter_mut().zip(src) {
107         *dst = T::blend(*src, *dst);
108     }
109 }
110 
111 impl Blender for BlendRow {
112     type Output = fn(&[u32], &mut [u32]);
build<T: blend::Blend>() -> Self::Output113     fn build<T: blend::Blend>() -> Self::Output {
114         blend_row::<T>
115     }
116 }
117 
118 struct BlendRowMask;
119 
blend_row_mask<T: blend::Blend>(src: &[u32], mask: &[u8], dst: &mut [u32])120 fn blend_row_mask<T: blend::Blend>(src: &[u32], mask: &[u8], dst: &mut [u32]) {
121     for ((dst, src), mask) in dst.iter_mut().zip(src).zip(mask) {
122         *dst = lerp(
123             *dst,
124             T::blend(*src, *dst),
125             alpha_to_alpha256(*mask as u32),
126         );
127     }
128 }
129 
130 impl Blender for BlendRowMask {
131     type Output = fn(&[u32], &[u8], &mut [u32]);
build<T: blend::Blend>() -> Self::Output132     fn build<T: blend::Blend>() -> Self::Output {
133         blend_row_mask::<T>
134     }
135 }
136 
137 struct BlendRowMaskClip;
138 
blend_row_mask_clip<T: blend::Blend>(src: &[u32], mask: &[u8], clip: &[u8], dst: &mut [u32])139 fn blend_row_mask_clip<T: blend::Blend>(src: &[u32], mask: &[u8], clip: &[u8], dst: &mut [u32]) {
140     for (((dst, src), mask), clip) in dst.iter_mut().zip(src).zip(mask).zip(clip) {
141         *dst = alpha_lerp(
142             *dst,
143             T::blend(*src, *dst),
144             *mask as u32,
145             *clip as u32
146         );
147     }
148 }
149 
150 impl Blender for BlendRowMaskClip {
151     type Output = fn(&[u32], &[u8], &[u8], &mut [u32]);
build<T: blend::Blend>() -> Self::Output152     fn build<T: blend::Blend>() -> Self::Output {
153         blend_row_mask_clip::<T>
154     }
155 }
156 
build_blend_proc<T: Blender>(mode: BlendMode) -> T::Output157 fn build_blend_proc<T: Blender>(mode: BlendMode) -> T::Output {
158     use sw_composite::blend::*;
159     match mode {
160         BlendMode::Dst => T::build::<Dst>(),
161         BlendMode::Src => T::build::<Src>(),
162         BlendMode::Clear => T::build::<Clear>(),
163         BlendMode::SrcOver => T::build::<SrcOver>(),
164         BlendMode::DstOver => T::build::<DstOver>(),
165         BlendMode::SrcIn => T::build::<SrcIn>(),
166         BlendMode::DstIn => T::build::<DstIn>(),
167         BlendMode::SrcOut => T::build::<SrcOut>(),
168         BlendMode::DstOut => T::build::<DstOut>(),
169         BlendMode::SrcAtop => T::build::<SrcAtop>(),
170         BlendMode::DstAtop => T::build::<DstAtop>(),
171         BlendMode::Xor => T::build::<Xor>(),
172         BlendMode::Add => T::build::<Add>(),
173         BlendMode::Screen => T::build::<Screen>(),
174         BlendMode::Overlay => T::build::<Overlay>(),
175         BlendMode::Darken => T::build::<Darken>(),
176         BlendMode::Lighten => T::build::<Lighten>(),
177         BlendMode::ColorDodge => T::build::<ColorDodge>(),
178         BlendMode::ColorBurn => T::build::<ColorBurn>(),
179         BlendMode::HardLight => T::build::<HardLight>(),
180         BlendMode::SoftLight => T::build::<SoftLight>(),
181         BlendMode::Difference => T::build::<Difference>(),
182         BlendMode::Exclusion => T::build::<Exclusion>(),
183         BlendMode::Multiply => T::build::<Multiply>(),
184         BlendMode::Hue => T::build::<Hue>(),
185         BlendMode::Saturation => T::build::<Saturation>(),
186         BlendMode::Color => T::build::<Color>(),
187         BlendMode::Luminosity => T::build::<Luminosity>(),
188     }
189 }
190 
191 #[derive(Copy, Clone)]
192 pub enum ExtendMode {
193     Pad,
194     Repeat
195 }
196 
197 #[derive(Copy, Clone, PartialEq)]
198 pub enum FilterMode {
199     Bilinear,
200     Nearest
201 }
202 
203 /// LinearGradients have an implicit start point at 0,0 and an end point at 256,0. The transform
204 /// parameter can be used to adjust them to the desired location.
205 /// RadialGradients have an implict center at 0,0 and a radius of 128.
206 /// The helper functions: `new_linear_gradient`, `new_radial_gradient` and `new_two_circle_radial_gradient`
207 /// allow the gradients to be constructed with easier to understand inputs.
208 /// The `transform` parameter maps user space to source space. This means that setting the same transform
209 /// on the draw target as the source will have the effect of canceling out.
210 ///
211 /// These locations are an artifact of the blitter implementation and will probably change in the
212 /// future to become more ergonomic.
213 #[derive(Clone)]
214 pub enum Source<'a> {
215     Solid(SolidSource),
216     Image(Image<'a>, ExtendMode, FilterMode, Transform),
217     RadialGradient(Gradient, Spread, Transform),
218     TwoCircleRadialGradient(Gradient, Spread, Point, f32, Point, f32, Transform),
219     LinearGradient(Gradient, Spread, Transform),
220 }
221 
222 impl<'a> Source<'a> {
223     /// Creates a new linear gradient source where the start point corresponds to the gradient
224     /// stop at position = 0 and the end point corresponds to the gradient stop at position = 1.
new_linear_gradient(gradient: Gradient, start: Point, end: Point, spread: Spread) -> Source<'a>225     pub fn new_linear_gradient(gradient: Gradient, start: Point, end: Point, spread: Spread) -> Source<'a> {
226         let gradient_vector = Vector::new(end.x - start.x, end.y - start.y);
227         // Get length of desired gradient vector
228         let length = gradient_vector.length();
229         if length != 0. {
230             let gradient_vector = gradient_vector.normalize();
231 
232             let sin = gradient_vector.y;
233             let cos = gradient_vector.x;
234             // Build up a rotation matrix from our vector
235             let mat = Transform::row_major(cos, -sin, sin, cos, 0., 0.);
236 
237             // Adjust for the start point
238             let mat = mat.pre_translate(vec2(-start.x, -start.y));
239 
240             // Scale gradient to desired length
241             let mat = mat.post_scale(1. / length, 1. / length);
242             Source::LinearGradient(gradient, spread, mat)
243         } else {
244             // use some degenerate matrix
245             Source::LinearGradient(gradient, spread, Transform::create_scale(0., 0.))
246         }
247     }
248 
249     /// Creates a new radial gradient that is centered at the given point and has the given radius.
new_radial_gradient(gradient: Gradient, center: Point, radius: f32, spread: Spread) -> Source<'a>250     pub fn new_radial_gradient(gradient: Gradient, center: Point, radius: f32, spread: Spread) -> Source<'a> {
251         // Scale gradient to desired radius
252         let scale = Transform::create_scale(radius, radius);
253         // Transform gradient to center of gradient
254         let translate = Transform::create_translation(center.x, center.y);
255         // Compute final transform
256         let transform = translate.pre_transform(&scale).inverse().unwrap();
257 
258         Source::RadialGradient(gradient, spread, transform)
259     }
260 
261     /// Creates a new radial gradient that is centered at the given point and has the given radius.
new_two_circle_radial_gradient(gradient: Gradient, center1: Point, radius1: f32, center2: Point, radius2: f32, spread: Spread) -> Source<'a>262     pub fn new_two_circle_radial_gradient(gradient: Gradient, center1: Point, radius1: f32,  center2: Point, radius2: f32, spread: Spread) -> Source<'a> {
263         let transform = Transform::identity();
264         Source::TwoCircleRadialGradient(gradient, spread, center1, radius1, center2, radius2, transform)
265     }
266 }
267 
268 #[derive(PartialEq, Clone, Copy, Debug)]
269 pub enum AntialiasMode {
270     None,
271     Gray,
272 }
273 
274 #[derive(PartialEq, Clone, Copy, Debug)]
275 pub struct DrawOptions {
276     pub blend_mode: BlendMode,
277     pub alpha: f32,
278     pub antialias: AntialiasMode,
279 }
280 
281 impl DrawOptions {
new() -> Self282     pub fn new() -> Self {
283         Default::default()
284     }
285 }
286 
287 impl Default for DrawOptions {
default() -> Self288     fn default() -> Self {
289         DrawOptions {
290             blend_mode: BlendMode::SrcOver,
291             alpha: 1.,
292             antialias: AntialiasMode::Gray,
293         }
294     }
295 }
296 
297 #[derive(Clone)]
298 struct Clip {
299     rect: IntRect,
300     mask: Option<Vec<u8>>,
301 }
302 
303 #[derive(Clone)]
304 struct Layer {
305     buf: Vec<u32>,
306     opacity: f32,
307     rect: IntRect,
308     blend: BlendMode,
309 }
310 
scaled_tolerance(x: f32, trans: &Transform) -> f32311 fn scaled_tolerance(x: f32, trans: &Transform) -> f32 {
312     // The absolute value of the determinant is the area parallelogram
313     // Take the sqrt of the area to losily convert to one dimension
314     x / trans.determinant().abs().sqrt()
315 }
316 
317 
318 
319 /// The main type used for drawing
320 pub struct DrawTarget {
321     width: i32,
322     height: i32,
323     rasterizer: Rasterizer,
324     current_point: Option<Point>,
325     first_point: Option<Point>,
326     buf: Vec<u32>,
327     clip_stack: Vec<Clip>,
328     layer_stack: Vec<Layer>,
329     transform: Transform,
330 }
331 
332 impl DrawTarget {
new(width: i32, height: i32) -> DrawTarget333     pub fn new(width: i32, height: i32) -> DrawTarget {
334         DrawTarget {
335             width,
336             height,
337             current_point: None,
338             first_point: None,
339             rasterizer: Rasterizer::new(width, height),
340             buf: vec![0; (width * height) as usize],
341             clip_stack: Vec::new(),
342             layer_stack: Vec::new(),
343             transform: Transform::identity(),
344         }
345     }
346 
width(&self) -> i32347     pub fn width(&self) -> i32 {
348         self.width
349     }
350 
height(&self) -> i32351     pub fn height(&self) -> i32 {
352         self.height
353     }
354 
355     /// Use a previously used vector for the bitmap and extend it to the given size(if needed)
from_vec(width: i32, height: i32, mut vec: Vec<u32>) -> DrawTarget356     pub fn from_vec(width: i32, height: i32, mut vec: Vec<u32>) -> DrawTarget{
357         vec.resize((width*height) as usize, 0);
358         DrawTarget {
359             width,
360             height,
361             current_point: None,
362             first_point: None,
363             rasterizer: Rasterizer::new(width, height),
364             buf: vec,
365             clip_stack: Vec::new(),
366             layer_stack: Vec::new(),
367             transform: Transform::identity()
368     }
369 }
370 
371     /// sets a transform that will be applied to all drawing operations
set_transform(&mut self, transform: &Transform)372     pub fn set_transform(&mut self, transform: &Transform) {
373         self.transform = *transform;
374     }
375 
376     /// gets the current transform
get_transform(&self) -> &Transform377     pub fn get_transform(&self) -> &Transform {
378         &self.transform
379     }
380 
move_to(&mut self, pt: Point)381     fn move_to(&mut self, pt: Point) {
382         self.current_point = Some(pt);
383         self.first_point = Some(pt);
384     }
385 
line_to(&mut self, pt: Point)386     fn line_to(&mut self, pt: Point) {
387         if self.current_point.is_none() {
388             self.current_point = Some(pt);
389             self.first_point = Some(pt);
390         }
391         if let Some(current_point) = self.current_point {
392             self.rasterizer
393                 .add_edge(current_point, pt, false, Point::new(0., 0.));
394             self.current_point = Some(pt);
395         }
396     }
397 
quad_to(&mut self, cpt: Point, pt: Point)398     fn quad_to(&mut self, cpt: Point, pt: Point) {
399         if self.current_point.is_none() {
400             self.current_point = Some(cpt);
401             self.first_point = Some(cpt);
402         }
403         if let Some(current_point) = self.current_point {
404             let curve = [current_point, cpt, pt];
405             self.current_point = Some(curve[2]);
406             self.add_quad(curve);
407         }
408     }
409 
add_quad(&mut self, mut curve: [Point; 3])410     fn add_quad(&mut self, mut curve: [Point; 3]) {
411         let a = curve[0].y;
412         let b = curve[1].y;
413         let c = curve[2].y;
414         if is_not_monotonic(a, b, c) {
415             let mut t_value = 0.;
416             if valid_unit_divide(a - b, a - b - b + c, &mut t_value) {
417                 let mut dst = [Point::new(0., 0.); 5];
418                 chop_quad_at(&curve, &mut dst, t_value);
419                 flatten_double_quad_extrema(&mut dst);
420                 self.rasterizer.add_edge(dst[0], dst[2], true, dst[1]);
421                 self.rasterizer.add_edge(dst[2], dst[4], true, dst[3]);
422                 return;
423             }
424             // if we get here, we need to force dst to be monotonic, even though
425             // we couldn't compute a unit_divide value (probably underflow).
426             let b = if abs(a - b) < abs(b - c) { a } else { c };
427             curve[1].y = b;
428         }
429         self.rasterizer.add_edge(curve[0], curve[2], true, curve[1]);
430     }
431 
cubic_to(&mut self, cpt1: Point, cpt2: Point, pt: Point)432     fn cubic_to(&mut self, cpt1: Point, cpt2: Point, pt: Point) {
433         if self.current_point.is_none() {
434             self.current_point = Some(cpt1);
435             self.first_point = Some(cpt1);
436         }
437         if let Some(current_point) = self.current_point {
438             let c = CubicBezierSegment {
439                 from: current_point,
440                 ctrl1: cpt1,
441                 ctrl2: cpt2,
442                 to: pt,
443             };
444             cubic_to_quadratics(&c, 0.01, &mut |q| {
445                 let curve = [q.from, q.ctrl, q.to];
446                 self.add_quad(curve);
447             });
448             self.current_point = Some(pt);
449         }
450     }
451 
close(&mut self)452     fn close(&mut self) {
453         if let (Some(first_point), Some(current_point)) = (self.first_point, self.current_point) {
454             self.rasterizer.add_edge(
455                 current_point,
456                 first_point,
457                 false,
458                 Point::new(0., 0.),
459             );
460         }
461         self.current_point = self.first_point;
462     }
463 
apply_path(&mut self, path: &Path)464     fn apply_path(&mut self, path: &Path) {
465         for op in &path.ops {
466             match *op {
467                 PathOp::MoveTo(pt) => {
468                     self.close();
469                     self.move_to(self.transform.transform_point(pt));
470                 },
471                 PathOp::LineTo(pt) => self.line_to(self.transform.transform_point(pt)),
472                 PathOp::QuadTo(cpt, pt) => self.quad_to(
473                     self.transform.transform_point(cpt),
474                     self.transform.transform_point(pt),
475                 ),
476                 PathOp::CubicTo(cpt1, cpt2, pt) => self.cubic_to(
477                     self.transform.transform_point(cpt1),
478                     self.transform.transform_point(cpt2),
479                     self.transform.transform_point(pt),
480                 ),
481                 PathOp::Close => self.close(),
482             }
483         }
484         // make sure the path is closed
485         self.close();
486         // XXX: we'd like for this function to return the bounds of the path
487     }
488 
push_clip_rect(&mut self, rect: IntRect)489     pub fn push_clip_rect(&mut self, rect: IntRect) {
490         // intersect with current clip
491         let clip = match self.clip_stack.last() {
492             Some(Clip {
493                      rect: current_clip,
494                      mask: _,
495                  }) => Clip {
496                 rect: current_clip.intersection(&rect),
497                 mask: None,
498             },
499             _ => Clip {
500                 rect: rect,
501                 mask: None,
502             },
503         };
504         self.clip_stack.push(clip);
505     }
506 
pop_clip(&mut self)507     pub fn pop_clip(&mut self) {
508         self.clip_stack.pop();
509     }
510 
push_clip(&mut self, path: &Path)511     pub fn push_clip(&mut self, path: &Path) {
512         self.apply_path(path);
513 
514         // XXX: restrict to clipped area
515         let mut blitter = MaskSuperBlitter::new(0, 0, self.width, self.height);
516         self.rasterizer.rasterize(&mut blitter, path.winding);
517 
518         if let Some(last) = self.clip_stack.last() {
519             // combine with previous mask
520             if let Some(last_mask) = &last.mask {
521                 for i in 0..((self.width * self.height) as usize) {
522                     blitter.buf[i] = muldiv255(blitter.buf[i] as u32, last_mask[i] as u32) as u8
523                 }
524             }
525         }
526 
527         let current_bounds = self.clip_bounds();
528         //XXX: handle interleaving of clip rect/masks better
529         self.clip_stack.push(Clip {
530             rect: current_bounds,
531             mask: Some(blitter.buf),
532         });
533         self.rasterizer.reset();
534     }
535 
clip_bounds(&self) -> IntRect536     fn clip_bounds(&self) -> IntRect {
537         self.clip_stack.last().map(|c| c.rect).unwrap_or(IntRect::new(
538             euclid::Point2D::new(0, 0),
539             euclid::Point2D::new(self.width, self.height),
540         ))
541     }
542 
543     /// Pushes a new layer as the drawing target. This is used for implementing
544     /// group opacity effects.
push_layer(&mut self, opacity: f32)545     pub fn push_layer(&mut self, opacity: f32) {
546         self.push_layer_with_blend(opacity, BlendMode::SrcOver)
547     }
548 
549     /// Pushes a new layer as the drawing target. This is used for implementing
550     /// group opacity or blend effects.
push_layer_with_blend(&mut self, opacity: f32, blend: BlendMode)551     pub fn push_layer_with_blend(&mut self, opacity: f32, blend: BlendMode) {
552         let rect = self.clip_bounds();
553         self.layer_stack.push(Layer {
554             rect,
555             buf: vec![0; (rect.size().width * rect.size().height) as usize],
556             opacity,
557             blend
558         });
559     }
560 
561     /// Draws the most recently pushed layer to the drawing target with
562     /// the pushed opacity applied.
pop_layer(&mut self)563     pub fn pop_layer(&mut self) {
564         let layer = self.layer_stack.pop().unwrap();
565         let opacity = (layer.opacity * 255. + 0.5) as u8;
566         // Allocating an entire mask just for the opacity is needlessly bad.
567         // We should be able to fix it once the blitters work better.
568         let mask = vec![opacity; (self.width * self.height) as usize];
569         let size = layer.rect.size();
570         let ctm = self.transform;
571         self.transform = Transform::identity();
572         let image = Source::Image(Image {
573             width: size.width,
574             height: size.height,
575             data: &layer.buf
576         },
577                                   ExtendMode::Pad,
578                                   FilterMode::Nearest,
579                                   Transform::create_translation(-layer.rect.min.x as f32,
580                                                                 -layer.rect.min.y as f32));
581         self.composite(&image, Some(&mask), intrect(0, 0, self.width, self.height), layer.rect, layer.blend, 1.);
582         self.transform = ctm;
583     }
584 
585     /// Draws an image at (x, y) with the size (width, height). This will rescale the image to the
586     /// destination size.
draw_image_with_size_at(&mut self, width: f32, height: f32, x: f32, y: f32, image: &Image, options: &DrawOptions)587     pub fn draw_image_with_size_at(&mut self, width: f32, height: f32, x: f32, y: f32, image: &Image, options: &DrawOptions) {
588         let source = Source::Image(*image,
589                                    ExtendMode::Pad,
590                                    FilterMode::Bilinear,
591                                    Transform::create_translation(-x, -y).post_scale(image.width as f32 / width, image.height as f32 / height));
592 
593         self.fill_rect(x, y, width, height, &source, options);
594     }
595 
596     /// Draws an image at x, y
draw_image_at(&mut self, x: f32, y: f32, image: &Image, options: &DrawOptions)597     pub fn draw_image_at(&mut self, x: f32, y: f32, image: &Image, options: &DrawOptions) {
598         self.draw_image_with_size_at(image.width as f32, image.height as f32, x, y, image, options);
599     }
600 
601     /// Draws `src` through an untransformed `mask` positioned at `x`, `y` in device space
mask(&mut self, src: &Source, x: i32, y: i32, mask: &Mask)602     pub fn mask(&mut self, src: &Source, x: i32, y: i32, mask: &Mask) {
603         self.composite(src, Some(&mask.data), intrect(x, y, mask.width, mask.height), intrect(x, y, mask.width, mask.height), BlendMode::SrcOver, 1.);
604     }
605 
606     /// Strokes `path` with `style` and fills the result with `src`
stroke(&mut self, path: &Path, src: &Source, style: &StrokeStyle, options: &DrawOptions)607     pub fn stroke(&mut self, path: &Path, src: &Source, style: &StrokeStyle, options: &DrawOptions) {
608         let tolerance = 0.1;
609 
610         // Since we're flattening in userspace, we need to compensate for the transform otherwise
611         // we'll flatten too much or not enough depending on the scale. We approximate doing this
612         // correctly by scaling the tolerance value using the same mechanism as Fitz. This
613         // approximation will fail if the scale between axes is drastically different. An
614         // alternative would be to use transform specific flattening but I haven't seen that done
615         // anywhere.
616         let tolerance = scaled_tolerance(tolerance, &self.transform);
617         let mut path = path.flatten(tolerance);
618 
619         if !style.dash_array.is_empty() {
620             path = dash_path(&path, &style.dash_array, style.dash_offset);
621         }
622         let stroked = stroke_to_path(&path, style);
623         self.fill(&stroked, src, options);
624     }
625 
626     /// Fills the rect `x`, `y,`, `width`, `height` with `src`. If the result is an
627     /// integer aligned rectangle performance will be faster than filling a rectangular path.
fill_rect(&mut self, x: f32, y: f32, width: f32, height: f32, src: &Source, options: &DrawOptions)628     pub fn fill_rect(&mut self, x: f32, y: f32, width: f32, height: f32, src: &Source, options: &DrawOptions) {
629         let ix = x as i32;
630         let iy = y as i32;
631         let iwidth = width as i32;
632         let iheight = height as i32;
633         let integer_rect = ix as f32 == x        && iy as f32 == y &&
634                                 iwidth as f32 == width && iheight as f32 == height;
635 
636         if self.transform == Transform::identity() && integer_rect && self.clip_stack.is_empty() {
637             let bounds = intrect(0, 0, self.width, self.height);
638             let mut irect = intrect(ix, iy, ix + iwidth, iy + iheight);
639             irect = irect.intersection(&bounds);
640             if irect.is_negative() {
641                 return;
642             }
643             self.composite(src, None, irect, irect, options.blend_mode, options.alpha);
644         } else {
645             let mut pb = PathBuilder::new();
646             pb.rect(x, y, width, height);
647             self.fill(&pb.finish(), src, options);
648         }
649     }
650 
651     /// Fills `path` with `src`
fill(&mut self, path: &Path, src: &Source, options: &DrawOptions)652     pub fn fill(&mut self, path: &Path, src: &Source, options: &DrawOptions) {
653         self.apply_path(path);
654         let bounds = self.rasterizer.get_bounds();
655         match options.antialias {
656             AntialiasMode::None => {
657                 let mut blitter = MaskBlitter::new(bounds.min.x, bounds.min.y, bounds.size().width, bounds.size().height);
658                 self.rasterizer.rasterize(&mut blitter, path.winding);
659                 self.composite(
660                     src,
661                     Some(&blitter.buf),
662                     bounds,
663                     bounds,
664                     options.blend_mode,
665                     options.alpha,
666                 );
667             }
668             AntialiasMode::Gray => {
669                 let mut blitter = MaskSuperBlitter::new(bounds.min.x, bounds.min.y, bounds.size().width, bounds.size().height);
670                 self.rasterizer.rasterize(&mut blitter, path.winding);
671                 self.composite(
672                     src,
673                     Some(&blitter.buf),
674                     bounds,
675                     bounds,
676                     options.blend_mode,
677                     options.alpha,
678                 );
679             }
680         }
681         self.rasterizer.reset();
682     }
683 
684     /// Fills the current clip with the solid color `solid`
clear(&mut self, solid: SolidSource)685     pub fn clear(&mut self, solid: SolidSource) {
686         let mut pb = PathBuilder::new();
687         if self.clip_stack.is_empty() {
688             let color = solid.to_u32();
689             for pixel in &mut self.buf[..] {
690                 *pixel = color;
691             }
692         } else {
693             let ctm = self.transform;
694             self.transform = Transform::identity();
695             pb.rect(0., 0., self.width as f32, self.height as f32);
696             self.fill(
697                 &pb.finish(),
698                 &Source::Solid(solid),
699                 &DrawOptions {
700                     blend_mode: BlendMode::Src,
701                     alpha: 1.,
702                     antialias: AntialiasMode::Gray,
703                 },
704             );
705             self.transform = ctm;
706         }
707     }
708 
709     #[cfg(feature = "text")]
draw_text( &mut self, font: &fk::Font, point_size: f32, text: &str, mut start: Point, src: &Source, options: &DrawOptions, )710     pub fn draw_text(
711         &mut self,
712         font: &fk::Font,
713         point_size: f32,
714         text: &str,
715         mut start: Point,
716         src: &Source,
717         options: &DrawOptions,
718     ) {
719         let mut ids = Vec::new();
720         let mut positions = Vec::new();
721         for c in text.chars() {
722             let id = font.glyph_for_char(c).unwrap();
723             ids.push(id);
724             positions.push(start);
725             start += font.advance(id).unwrap() * point_size / 24. / 96.;
726         }
727         self.draw_glyphs(font, point_size, &ids, &positions, src, options);
728     }
729 
730     #[cfg(feature = "text")]
draw_glyphs( &mut self, font: &fk::Font, point_size: f32, ids: &[u32], positions: &[Point], src: &Source, options: &DrawOptions, )731     pub fn draw_glyphs(
732         &mut self,
733         font: &fk::Font,
734         point_size: f32,
735         ids: &[u32],
736         positions: &[Point],
737         src: &Source,
738         options: &DrawOptions,
739     ) {
740         let mut combined_bounds = euclid::Rect::zero();
741         for (id, position) in ids.iter().zip(positions.iter()) {
742             let bounds = font.raster_bounds(
743                 *id,
744                 point_size,
745                 &fk::FontTransform::new(self.transform.m11, self.transform.m21, self.transform.m12, self.transform.m22),
746                 &(self.transform.transform_point(*position)),
747                 fk::HintingOptions::None,
748                 fk::RasterizationOptions::GrayscaleAa,
749             );
750             combined_bounds = match bounds {
751                 Ok(bounds) => {
752                     combined_bounds.union(&bounds)
753                 }
754                 _ => panic!(),
755             }
756         }
757 
758         /*let mut canvas = Canvas::new(&euclid::Size2D::new(combined_bounds.size.width as u32,
759         combined_bounds.size.height as u32), Format::A8);*/
760         let mut canvas = fk::Canvas::new(
761             &euclid::Size2D::new(combined_bounds.size.width as u32, combined_bounds.size.height as u32),
762             fk::Format::A8,
763         );
764         for (id, position) in ids.iter().zip(positions.iter()) {
765             let mut position = self.transform.transform_point(*position);
766             position.x -= combined_bounds.origin.x as f32;
767             position.y -= combined_bounds.origin.y as f32;
768             font.rasterize_glyph(
769                 &mut canvas,
770                 *id,
771                 point_size,
772                 &fk::FontTransform::new(self.transform.m11, self.transform.m21, self.transform.m12, self.transform.m22),
773                 &position,
774                 fk::HintingOptions::None,
775                 fk::RasterizationOptions::GrayscaleAa,
776             ).unwrap();
777         }
778 
779         self.composite(
780             src,
781             Some(&canvas.pixels),
782             combined_bounds.to_box2d(),
783             combined_bounds.to_box2d(),
784             options.blend_mode,
785             1.,
786         );
787     }
788 
789 
790 
791 
choose_blitter<'a, 'b, 'c>(mask: Option<&[u8]>, clip_stack: &'a Vec<Clip>, blitter_storage: &'b mut ShaderBlitterStorage<'a>, shader: &'a dyn Shader, blend: BlendMode, dest: &'a mut [u32], dest_bounds: IntRect, width: i32) -> &'b mut dyn Blitter792     fn choose_blitter<'a, 'b, 'c>(mask: Option<&[u8]>, clip_stack: &'a Vec<Clip>, blitter_storage: &'b mut ShaderBlitterStorage<'a>, shader: &'a dyn Shader, blend: BlendMode, dest: &'a mut [u32], dest_bounds: IntRect, width: i32) -> &'b mut dyn Blitter {
793         let blitter: &mut dyn Blitter;
794 
795         match (mask, clip_stack.last()) {
796             (Some(_mask), Some(Clip {
797                         rect: _,
798                         mask: Some(clip),
799                     })) => {
800                 if blend == BlendMode::SrcOver {
801                     let scb = ShaderClipMaskBlitter {
802                         x: dest_bounds.min.x,
803                         y: dest_bounds.min.y,
804                         shader: shader,
805                         tmp: vec![0; width as usize],
806                         dest,
807                         dest_stride: dest_bounds.size().width,
808                         clip,
809                         clip_stride: width,
810                     };
811                     *blitter_storage = ShaderBlitterStorage::ShaderClipMaskBlitter(scb);
812                     blitter = match blitter_storage { ShaderBlitterStorage::ShaderClipMaskBlitter(s) => s, _ => panic!() };
813                 } else {
814                     let blend_fn = build_blend_proc::<BlendRowMaskClip>(blend);
815                     let scb_blend = ShaderClipBlendMaskBlitter {
816                         x: dest_bounds.min.x,
817                         y: dest_bounds.min.y,
818                         shader: shader,
819                         tmp: vec![0; width as usize],
820                         dest,
821                         dest_stride: dest_bounds.size().width,
822                         clip,
823                         clip_stride: width,
824                         blend_fn
825                     };
826 
827                     *blitter_storage = ShaderBlitterStorage::ShaderClipBlendMaskBlitter(scb_blend);
828                     blitter = match blitter_storage {
829                         ShaderBlitterStorage::ShaderClipBlendMaskBlitter(s) => s,
830                         _ => panic!()
831                     };
832                 }
833             }
834             (Some(_mask), _) => {
835                 if blend == BlendMode::SrcOver {
836                     let sb = ShaderMaskBlitter {
837                         x: dest_bounds.min.x,
838                         y: dest_bounds.min.y,
839                         shader: &*shader,
840                         tmp: vec![0; width as usize],
841                         dest,
842                         dest_stride: dest_bounds.size().width,
843                     };
844                     *blitter_storage = ShaderBlitterStorage::ShaderMaskBlitter(sb);
845                     blitter = match blitter_storage { ShaderBlitterStorage::ShaderMaskBlitter(s) => s, _ => panic!() };
846                 } else {
847                     let blend_fn = build_blend_proc::<BlendRowMask>(blend);
848                     let sb_blend = ShaderBlendMaskBlitter {
849                         x: dest_bounds.min.x,
850                         y: dest_bounds.min.y,
851                         shader: &*shader,
852                         tmp: vec![0; width as usize],
853                         dest,
854                         dest_stride: dest_bounds.size().width,
855                         blend_fn,
856                     };
857                     *blitter_storage = ShaderBlitterStorage::ShaderBlendMaskBlitter(sb_blend);
858                     blitter = match blitter_storage {
859                         ShaderBlitterStorage::ShaderBlendMaskBlitter(s) => s,
860                         _ => panic!()
861                     };
862                 }
863             }
864             (None, _) => {
865                 let blend_fn = build_blend_proc::<BlendRow>(blend);
866                 let sb_blend = ShaderBlendBlitter {
867                     x: dest_bounds.min.x,
868                     y: dest_bounds.min.y,
869                     shader: &*shader,
870                     tmp: vec![0; width as usize],
871                     dest,
872                     dest_stride: dest_bounds.size().width,
873                     blend_fn,
874                 };
875                 *blitter_storage = ShaderBlitterStorage::ShaderBlendBlitter(sb_blend);
876                 blitter = match blitter_storage {
877                     ShaderBlitterStorage::ShaderBlendBlitter(s) => s,
878                     _ => panic!()
879                 };
880             }
881         }
882         blitter
883     }
884 
885     /// `mask_rect` is in DrawTarget space. i.e size is the size of the mask and origin is the position.
886     /// you can not render a part of the mask
composite(&mut self, src: &Source, mask: Option<&[u8]>, mask_rect: IntRect, mut rect: IntRect, blend: BlendMode, alpha: f32)887     fn composite(&mut self, src: &Source, mask: Option<&[u8]>, mask_rect: IntRect, mut rect: IntRect, blend: BlendMode, alpha: f32) {
888         let ti = self.transform.inverse();
889         let ti = if let Some(ti) = ti {
890             ti
891         } else {
892             // the transform is not invertible so we have nothing to draw
893             return;
894         };
895 
896         let clip_bounds = self.clip_bounds();
897 
898         let (dest, dest_bounds) = match self.layer_stack.last_mut() {
899             Some(layer) => (&mut layer.buf[..], layer.rect),
900             None => (&mut self.buf[..], intrect(0, 0, self.width, self.height))
901         };
902 
903         rect = rect
904             .intersection(&clip_bounds)
905             .intersection(&dest_bounds)
906             .intersection(&mask_rect);
907         if rect.is_negative() {
908             return;
909         }
910 
911         let mut shader_storage: ShaderStorage = ShaderStorage::None;
912         let shader = choose_shader(&ti, src, alpha, &mut shader_storage);
913 
914         let mut blitter_storage: ShaderBlitterStorage = ShaderBlitterStorage::None;
915         let blitter = DrawTarget::choose_blitter(mask, &self.clip_stack, &mut blitter_storage, shader, blend, dest, dest_bounds, self.width);
916 
917         match mask {
918             Some(mask) => {
919                 for y in rect.min.y..rect.max.y {
920                     let mask_row = (y - mask_rect.min.y) * mask_rect.size().width;
921                     let mask_start = (mask_row + rect.min.x - mask_rect.min.x) as usize;
922                     let mask_end = (mask_row + rect.max.x - mask_rect.min.x) as usize;
923                     blitter.blit_span(y, rect.min.x, rect.max.x, &mask[mask_start..mask_end]);
924                 }
925             }
926             None => {
927                 for y in rect.min.y..rect.max.y {
928                     let empty_mask = [];
929                     blitter.blit_span(y, rect.min.x, rect.max.x, &empty_mask[..]);
930                 }
931             }
932         };
933     }
934 
935     /// Draws `src_rect` of `src` at `dst`. The current transform and clip are ignored
composite_surface<F: Fn(&[u32], &mut [u32])>(&mut self, src: &DrawTarget, src_rect: IntRect, dst: IntPoint, f: F)936     pub fn composite_surface<F: Fn(&[u32], &mut [u32])>(&mut self, src: &DrawTarget, src_rect: IntRect, dst: IntPoint, f: F) {
937         let dst_rect = intrect(0, 0, self.width, self.height);
938 
939         // intersect the src_rect with the source size so that we don't go out of bounds
940         let src_rect = src_rect.intersection(&intrect(0, 0, src.width, src.height));
941 
942         let src_rect = dst_rect
943             .intersection(&src_rect.translate(dst.to_vector())).translate(-dst.to_vector());
944 
945         // clamp requires Float so open code it
946         let dst = IntPoint::new(dst.x.max(dst_rect.min.x).min(dst_rect.max.x),
947                                 dst.y.max(dst_rect.min.y).min(dst_rect.max.y));
948 
949         if src_rect.is_negative() {
950             return;
951         }
952 
953         for y in src_rect.min.y..src_rect.max.y {
954             let dst_row_start = (dst.x + (dst.y + y - src_rect.min.y) * self.width) as usize;
955             let dst_row_end = dst_row_start + src_rect.size().width as usize;
956             let src_row_start = (src_rect.min.x + y * src.width) as usize;
957             let src_row_end = src_row_start + src_rect.size().width as usize;
958             f(&src.buf[src_row_start..src_row_end], &mut self.buf[dst_row_start..dst_row_end]);
959         }
960     }
961 
962     /// Draws `src_rect` of `src` at `dst`. The current transform and clip are ignored.
963     /// `src_rect` is clamped to (0, 0, src.width, src.height).
copy_surface(&mut self, src: &DrawTarget, src_rect: IntRect, dst: IntPoint)964     pub fn copy_surface(&mut self, src: &DrawTarget, src_rect: IntRect, dst: IntPoint) {
965         self.composite_surface(src, src_rect, dst, |src, dst| {
966             dst.copy_from_slice(src)
967         })
968     }
969 
970     /// Blends `src_rect` of `src` at `dst`using `blend` mode.
971     /// The current transform and clip are ignored.
972     /// `src_rect` is clamped to (0, 0, `src.width`, `src.height`).
blend_surface(&mut self, src: &DrawTarget, src_rect: IntRect, dst: IntPoint, blend: BlendMode)973     pub fn blend_surface(&mut self, src: &DrawTarget, src_rect: IntRect, dst: IntPoint, blend: BlendMode) {
974         let blend_fn = build_blend_proc::<BlendRow>(blend);
975         self.composite_surface(src, src_rect, dst, |src, dst| {
976             blend_fn(src, dst);
977         });
978     }
979 
980     /// Blends `src_rect` of `src` at `dst` using `alpha`. The current transform and clip are ignored.
981     /// `src_rect` is clamped to (0, 0, `src.width`, `src.height`).
blend_surface_with_alpha(&mut self, src: &DrawTarget, src_rect: IntRect, dst: IntPoint, alpha: f32)982     pub fn blend_surface_with_alpha(&mut self, src: &DrawTarget, src_rect: IntRect, dst: IntPoint, alpha: f32) {
983         let alpha = (alpha * 255. + 0.5) as u8;
984 
985         self.composite_surface(src, src_rect, dst, |src, dst| {
986             over_in_row(src, dst, alpha as u32);
987         });
988     }
989 
990     /// Returns a reference to the underlying pixel data
get_data(&self) -> &[u32]991     pub fn get_data(&self) -> &[u32] {
992         &self.buf
993     }
994 
995     /// Returns a mut reference to the underlying pixel data as ARGB with a representation
996     /// like: (A << 24) | (R << 16) | (G << 8) | B
get_data_mut(&mut self) -> &mut [u32]997     pub fn get_data_mut(&mut self) -> &mut [u32] {
998         &mut self.buf
999     }
1000 
1001     /// Returns a reference to the underlying pixel data as individual bytes with the order BGRA
1002     /// on little endian.
get_data_u8(&self) -> &[u8]1003     pub fn get_data_u8(&self) -> &[u8] {
1004         let p = self.buf[..].as_ptr();
1005         let len = self.buf[..].len();
1006         // we want to return an [u8] slice instead of a [u32] slice. This is a safe thing to
1007         // do because requirements of a [u32] slice are stricter.
1008         unsafe { std::slice::from_raw_parts(p as *const u8, len * std::mem::size_of::<u32>()) }
1009     }
1010 
1011     /// Returns a mut reference to the underlying pixel data as individual bytes with the order BGRA
1012     /// on little endian.
get_data_u8_mut(&mut self) -> &mut [u8]1013     pub fn get_data_u8_mut(&mut self) -> &mut [u8] {
1014         let p = self.buf[..].as_mut_ptr();
1015         let len = self.buf[..].len();
1016         // we want to return an [u8] slice instead of a [u32] slice. This is a safe thing to
1017         // do because requirements of a [u32] slice are stricter.
1018         unsafe { std::slice::from_raw_parts_mut(p as *mut u8, len * std::mem::size_of::<u32>()) }
1019     }
1020 
1021     /// Take ownership of the buffer backing the DrawTarget
into_vec(self) -> Vec<u32>1022     pub fn into_vec(self) -> Vec<u32> {
1023         self.buf
1024     }
1025 
1026 
1027     /// Saves the current pixel to a png file at `path`
write_png<P: AsRef<std::path::Path>>(&self, path: P) -> Result<(), png::EncodingError>1028     pub fn write_png<P: AsRef<std::path::Path>>(&self, path: P) -> Result<(), png::EncodingError> {
1029         let file = File::create(path)?;
1030 
1031         let ref mut w = BufWriter::new(file);
1032 
1033         let mut encoder = png::Encoder::new(w, self.width as u32, self.height as u32);
1034         encoder.set_color(png::ColorType::RGBA);
1035         encoder.set_depth(png::BitDepth::Eight);
1036         let mut writer = encoder.write_header()?;
1037         let mut output = Vec::with_capacity(self.buf.len() * 4);
1038 
1039         for pixel in &self.buf {
1040             let a = (pixel >> 24) & 0xffu32;
1041             let mut r = (pixel >> 16) & 0xffu32;
1042             let mut g = (pixel >> 8) & 0xffu32;
1043             let mut b = (pixel >> 0) & 0xffu32;
1044 
1045             if a > 0u32 {
1046                 r = r * 255u32 / a;
1047                 g = g * 255u32 / a;
1048                 b = b * 255u32 / a;
1049             }
1050 
1051             output.push(r as u8);
1052             output.push(g as u8);
1053             output.push(b as u8);
1054             output.push(a as u8);
1055         }
1056 
1057         writer.write_image_data(&output)
1058     }
1059 }
1060