script/dom/canvas/2d/
canvaspattern.rs1#![cfg_attr(crown, allow(crown::jscontext_first_arg))]
6
7use dom_struct::dom_struct;
8use euclid::default::{Size2D, Transform2D};
9use js::context::JSContext;
10use pixels::{SharedSnapshot, Snapshot};
11use script_bindings::cell::DomRefCell;
12use script_bindings::reflector::{Reflector, reflect_dom_object};
13use servo_canvas_traits::canvas::{FillOrStrokeStyle, RepetitionStyle, SurfaceStyle};
14
15use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasPatternMethods;
16use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit;
17use crate::dom::bindings::error::ErrorResult;
18use crate::dom::bindings::root::DomRoot;
19use crate::dom::canvasgradient::ToFillOrStrokeStyle;
20use crate::dom::dommatrixreadonly::dommatrix2dinit_to_matrix;
21use crate::dom::globalscope::GlobalScope;
22
23#[dom_struct]
25pub(crate) struct CanvasPattern {
26 reflector_: Reflector,
27 #[no_trace]
28 surface_data: SharedSnapshot,
29 #[no_trace]
30 surface_size: Size2D<u32>,
31 repeat_x: bool,
32 repeat_y: bool,
33 #[no_trace]
34 transform: DomRefCell<Transform2D<f32>>,
35 origin_clean: bool,
36}
37
38impl CanvasPattern {
39 fn new_inherited(
40 surface_data: Snapshot,
41 surface_size: Size2D<u32>,
42 repeat: RepetitionStyle,
43 origin_clean: bool,
44 ) -> CanvasPattern {
45 let (x, y) = match repeat {
46 RepetitionStyle::Repeat => (true, true),
47 RepetitionStyle::RepeatX => (true, false),
48 RepetitionStyle::RepeatY => (false, true),
49 RepetitionStyle::NoRepeat => (false, false),
50 };
51
52 CanvasPattern {
53 reflector_: Reflector::new(),
54 surface_data: surface_data.to_shared(),
55 surface_size,
56 repeat_x: x,
57 repeat_y: y,
58 transform: DomRefCell::new(Transform2D::identity()),
59 origin_clean,
60 }
61 }
62 pub(crate) fn new(
63 global: &GlobalScope,
64 cx: &mut JSContext,
65 surface_data: Snapshot,
66 surface_size: Size2D<u32>,
67 repeat: RepetitionStyle,
68 origin_clean: bool,
69 ) -> DomRoot<CanvasPattern> {
70 reflect_dom_object(
71 cx,
72 Box::new(CanvasPattern::new_inherited(
73 surface_data,
74 surface_size,
75 repeat,
76 origin_clean,
77 )),
78 global,
79 )
80 }
81 pub(crate) fn origin_is_clean(&self) -> bool {
82 self.origin_clean
83 }
84}
85
86impl CanvasPatternMethods<crate::DomTypeHolder> for CanvasPattern {
87 fn SetTransform(&self, transform: &DOMMatrix2DInit) -> ErrorResult {
89 let matrix = dommatrix2dinit_to_matrix(transform)?;
92
93 if !matrix.m11.is_finite() ||
97 !matrix.m12.is_finite() ||
98 !matrix.m21.is_finite() ||
99 !matrix.m22.is_finite() ||
100 !matrix.m31.is_finite() ||
101 !matrix.m32.is_finite()
102 {
103 return Ok(());
104 }
105
106 *self.transform.borrow_mut() = matrix.cast();
108
109 Ok(())
110 }
111}
112
113impl ToFillOrStrokeStyle for &CanvasPattern {
114 fn to_fill_or_stroke_style(self) -> FillOrStrokeStyle {
115 FillOrStrokeStyle::Surface(SurfaceStyle::new(
116 self.surface_data.clone(),
117 self.surface_size,
118 self.repeat_x,
119 self.repeat_y,
120 *self.transform.borrow(),
121 ))
122 }
123}