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