1use canvas_traits::canvas::Canvas2dMsg;
6use dom_struct::dom_struct;
7use euclid::default::Size2D;
8use pixels::Snapshot;
9
10use crate::canvas_context::{CanvasContext, HTMLCanvasElementOrOffscreenCanvas};
11use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{
12 CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin,
13 CanvasRenderingContext2DMethods, CanvasTextAlign, CanvasTextBaseline,
14};
15use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit;
16use crate::dom::bindings::codegen::Bindings::OffscreenCanvasRenderingContext2DBinding::OffscreenCanvasRenderingContext2DMethods;
17use crate::dom::bindings::codegen::UnionTypes::{
18 HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas,
19 StringOrCanvasGradientOrCanvasPattern,
20};
21use crate::dom::bindings::error::{ErrorResult, Fallible};
22use crate::dom::bindings::num::Finite;
23use crate::dom::bindings::reflector::reflect_dom_object;
24use crate::dom::bindings::root::{Dom, DomRoot};
25use crate::dom::bindings::str::DOMString;
26use crate::dom::canvasgradient::CanvasGradient;
27use crate::dom::canvaspattern::CanvasPattern;
28use crate::dom::canvasrenderingcontext2d::CanvasRenderingContext2D;
29use crate::dom::dommatrix::DOMMatrix;
30use crate::dom::globalscope::GlobalScope;
31use crate::dom::imagedata::ImageData;
32use crate::dom::offscreencanvas::OffscreenCanvas;
33use crate::dom::path2d::Path2D;
34use crate::dom::textmetrics::TextMetrics;
35use crate::script_runtime::CanGc;
36
37#[dom_struct]
38pub(crate) struct OffscreenCanvasRenderingContext2D {
39 context: CanvasRenderingContext2D,
40}
41
42impl OffscreenCanvasRenderingContext2D {
43 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
44 fn new_inherited(
45 global: &GlobalScope,
46 canvas: HTMLCanvasElementOrOffscreenCanvas,
47 size: Size2D<u32>,
48 ) -> Option<OffscreenCanvasRenderingContext2D> {
49 Some(OffscreenCanvasRenderingContext2D {
50 context: CanvasRenderingContext2D::new_inherited(global, canvas, size)?,
51 })
52 }
53
54 pub(crate) fn new(
55 global: &GlobalScope,
56 canvas: &OffscreenCanvas,
57 size: Size2D<u32>,
58 can_gc: CanGc,
59 ) -> Option<DomRoot<OffscreenCanvasRenderingContext2D>> {
60 OffscreenCanvasRenderingContext2D::new_inherited(
61 global,
62 HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(Dom::from_ref(canvas)),
63 size,
64 )
65 .map(|context| reflect_dom_object(Box::new(context), global, can_gc))
66 }
67
68 pub(crate) fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) {
69 self.context.send_canvas_2d_msg(msg)
70 }
71}
72
73impl CanvasContext for OffscreenCanvasRenderingContext2D {
74 type ID = <CanvasRenderingContext2D as CanvasContext>::ID;
75
76 fn context_id(&self) -> Self::ID {
77 self.context.context_id()
78 }
79
80 fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
81 self.context.canvas()
82 }
83
84 fn resize(&self) {
85 self.context.resize()
86 }
87
88 fn reset_bitmap(&self) {
89 self.context.reset_bitmap()
90 }
91
92 fn get_image_data(&self) -> Option<Snapshot> {
93 self.context.get_image_data()
94 }
95
96 fn origin_is_clean(&self) -> bool {
97 self.context.origin_is_clean()
98 }
99
100 fn mark_as_dirty(&self) {}
101}
102
103impl OffscreenCanvasRenderingContext2DMethods<crate::DomTypeHolder>
104 for OffscreenCanvasRenderingContext2D
105{
106 fn Canvas(&self) -> DomRoot<OffscreenCanvas> {
108 match self.context.canvas() {
109 Some(RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas)) => canvas,
110 _ => panic!("Should not be called from onscreen canvas"),
111 }
112 }
113
114 fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) {
116 self.context.FillRect(x, y, width, height);
117 }
118
119 fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) {
121 self.context.ClearRect(x, y, width, height);
122 }
123
124 fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) {
126 self.context.StrokeRect(x, y, width, height);
127 }
128
129 fn ShadowOffsetX(&self) -> f64 {
131 self.context.ShadowOffsetX()
132 }
133
134 fn SetShadowOffsetX(&self, value: f64) {
136 self.context.SetShadowOffsetX(value)
137 }
138
139 fn ShadowOffsetY(&self) -> f64 {
141 self.context.ShadowOffsetY()
142 }
143
144 fn SetShadowOffsetY(&self, value: f64) {
146 self.context.SetShadowOffsetY(value)
147 }
148
149 fn ShadowBlur(&self) -> f64 {
151 self.context.ShadowBlur()
152 }
153
154 fn SetShadowBlur(&self, value: f64) {
156 self.context.SetShadowBlur(value)
157 }
158
159 fn ShadowColor(&self) -> DOMString {
161 self.context.ShadowColor()
162 }
163
164 fn SetShadowColor(&self, value: DOMString) {
166 self.context.SetShadowColor(value)
167 }
168
169 fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
171 self.context.StrokeStyle()
172 }
173
174 fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
176 self.context.SetStrokeStyle(value)
177 }
178
179 fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
181 self.context.FillStyle()
182 }
183
184 fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
186 self.context.SetFillStyle(value)
187 }
188
189 fn CreateLinearGradient(
191 &self,
192 x0: Finite<f64>,
193 y0: Finite<f64>,
194 x1: Finite<f64>,
195 y1: Finite<f64>,
196 can_gc: CanGc,
197 ) -> DomRoot<CanvasGradient> {
198 self.context.CreateLinearGradient(x0, y0, x1, y1, can_gc)
199 }
200
201 fn CreateRadialGradient(
203 &self,
204 x0: Finite<f64>,
205 y0: Finite<f64>,
206 r0: Finite<f64>,
207 x1: Finite<f64>,
208 y1: Finite<f64>,
209 r1: Finite<f64>,
210 can_gc: CanGc,
211 ) -> Fallible<DomRoot<CanvasGradient>> {
212 self.context
213 .CreateRadialGradient(x0, y0, r0, x1, y1, r1, can_gc)
214 }
215
216 fn CreatePattern(
218 &self,
219 image: CanvasImageSource,
220 repetition: DOMString,
221 can_gc: CanGc,
222 ) -> Fallible<Option<DomRoot<CanvasPattern>>> {
223 self.context.CreatePattern(image, repetition, can_gc)
224 }
225
226 fn Save(&self) {
228 self.context.Save()
229 }
230
231 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
232 fn Restore(&self) {
234 self.context.Restore()
235 }
236
237 fn Reset(&self) {
239 self.context.Reset()
240 }
241
242 fn GlobalAlpha(&self) -> f64 {
244 self.context.GlobalAlpha()
245 }
246
247 fn SetGlobalAlpha(&self, alpha: f64) {
249 self.context.SetGlobalAlpha(alpha)
250 }
251
252 fn GlobalCompositeOperation(&self) -> DOMString {
254 self.context.GlobalCompositeOperation()
255 }
256
257 fn SetGlobalCompositeOperation(&self, op_str: DOMString) {
259 self.context.SetGlobalCompositeOperation(op_str)
260 }
261
262 fn ImageSmoothingEnabled(&self) -> bool {
264 self.context.ImageSmoothingEnabled()
265 }
266
267 fn SetImageSmoothingEnabled(&self, value: bool) {
269 self.context.SetImageSmoothingEnabled(value)
270 }
271
272 fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) {
274 self.context.FillText(text, x, y, max_width)
275 }
276
277 fn StrokeText(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) {
279 self.context.StrokeText(text, x, y, max_width)
280 }
281
282 fn MeasureText(&self, text: DOMString, can_gc: CanGc) -> DomRoot<TextMetrics> {
284 self.context.MeasureText(text, can_gc)
285 }
286
287 fn Font(&self) -> DOMString {
289 self.context.Font()
290 }
291
292 fn SetFont(&self, value: DOMString) {
294 self.context.SetFont(value)
295 }
296
297 fn TextAlign(&self) -> CanvasTextAlign {
299 self.context.TextAlign()
300 }
301
302 fn SetTextAlign(&self, value: CanvasTextAlign) {
304 self.context.SetTextAlign(value)
305 }
306
307 fn TextBaseline(&self) -> CanvasTextBaseline {
309 self.context.TextBaseline()
310 }
311
312 fn SetTextBaseline(&self, value: CanvasTextBaseline) {
314 self.context.SetTextBaseline(value)
315 }
316
317 fn Direction(&self) -> CanvasDirection {
319 self.context.Direction()
320 }
321
322 fn SetDirection(&self, value: CanvasDirection) {
324 self.context.SetDirection(value)
325 }
326
327 fn LineWidth(&self) -> f64 {
329 self.context.LineWidth()
330 }
331
332 fn SetLineWidth(&self, width: f64) {
334 self.context.SetLineWidth(width)
335 }
336
337 fn LineCap(&self) -> CanvasLineCap {
339 self.context.LineCap()
340 }
341
342 fn SetLineCap(&self, cap: CanvasLineCap) {
344 self.context.SetLineCap(cap)
345 }
346
347 fn LineJoin(&self) -> CanvasLineJoin {
349 self.context.LineJoin()
350 }
351
352 fn SetLineJoin(&self, join: CanvasLineJoin) {
354 self.context.SetLineJoin(join)
355 }
356
357 fn MiterLimit(&self) -> f64 {
359 self.context.MiterLimit()
360 }
361
362 fn SetMiterLimit(&self, limit: f64) {
364 self.context.SetMiterLimit(limit)
365 }
366
367 fn SetLineDash(&self, segments: Vec<f64>) {
369 self.context.SetLineDash(segments)
370 }
371
372 fn GetLineDash(&self) -> Vec<f64> {
374 self.context.GetLineDash()
375 }
376
377 fn LineDashOffset(&self) -> f64 {
379 self.context.LineDashOffset()
380 }
381
382 fn SetLineDashOffset(&self, offset: f64) {
384 self.context.SetLineDashOffset(offset)
385 }
386
387 fn CreateImageData(&self, sw: i32, sh: i32, can_gc: CanGc) -> Fallible<DomRoot<ImageData>> {
389 self.context.CreateImageData(sw, sh, can_gc)
390 }
391
392 fn CreateImageData_(
394 &self,
395 imagedata: &ImageData,
396 can_gc: CanGc,
397 ) -> Fallible<DomRoot<ImageData>> {
398 self.context.CreateImageData_(imagedata, can_gc)
399 }
400
401 fn GetImageData(
403 &self,
404 sx: i32,
405 sy: i32,
406 sw: i32,
407 sh: i32,
408 can_gc: CanGc,
409 ) -> Fallible<DomRoot<ImageData>> {
410 self.context.GetImageData(sx, sy, sw, sh, can_gc)
411 }
412
413 fn PutImageData(&self, imagedata: &ImageData, dx: i32, dy: i32) {
415 self.context.PutImageData(imagedata, dx, dy)
416 }
417
418 fn PutImageData_(
420 &self,
421 imagedata: &ImageData,
422 dx: i32,
423 dy: i32,
424 dirty_x: i32,
425 dirty_y: i32,
426 dirty_width: i32,
427 dirty_height: i32,
428 ) {
429 self.context.PutImageData_(
430 imagedata,
431 dx,
432 dy,
433 dirty_x,
434 dirty_y,
435 dirty_width,
436 dirty_height,
437 )
438 }
439
440 fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult {
442 self.context.DrawImage(image, dx, dy)
443 }
444
445 fn DrawImage_(
447 &self,
448 image: CanvasImageSource,
449 dx: f64,
450 dy: f64,
451 dw: f64,
452 dh: f64,
453 ) -> ErrorResult {
454 self.context.DrawImage_(image, dx, dy, dw, dh)
455 }
456
457 fn DrawImage__(
459 &self,
460 image: CanvasImageSource,
461 sx: f64,
462 sy: f64,
463 sw: f64,
464 sh: f64,
465 dx: f64,
466 dy: f64,
467 dw: f64,
468 dh: f64,
469 ) -> ErrorResult {
470 self.context
471 .DrawImage__(image, sx, sy, sw, sh, dx, dy, dw, dh)
472 }
473
474 fn BeginPath(&self) {
476 self.context.BeginPath()
477 }
478
479 fn Fill(&self, fill_rule: CanvasFillRule) {
481 self.context.Fill(fill_rule)
482 }
483
484 fn Fill_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
486 self.context.Fill_(path, fill_rule)
487 }
488
489 fn Stroke(&self) {
491 self.context.Stroke()
492 }
493
494 fn Stroke_(&self, path: &Path2D) {
496 self.context.Stroke_(path)
497 }
498
499 fn Clip(&self, fill_rule: CanvasFillRule) {
501 self.context.Clip(fill_rule)
502 }
503
504 fn Clip_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
506 self.context.Clip_(path, fill_rule)
507 }
508
509 fn IsPointInPath(&self, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
511 self.context.IsPointInPath(x, y, fill_rule)
512 }
513
514 fn IsPointInPath_(&self, path: &Path2D, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
516 self.context.IsPointInPath_(path, x, y, fill_rule)
517 }
518
519 fn Scale(&self, x: f64, y: f64) {
521 self.context.Scale(x, y)
522 }
523
524 fn Rotate(&self, angle: f64) {
526 self.context.Rotate(angle)
527 }
528
529 fn Translate(&self, x: f64, y: f64) {
531 self.context.Translate(x, y)
532 }
533
534 fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
536 self.context.Transform(a, b, c, d, e, f)
537 }
538
539 fn GetTransform(&self, can_gc: CanGc) -> DomRoot<DOMMatrix> {
541 self.context.GetTransform(can_gc)
542 }
543
544 fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) -> ErrorResult {
546 self.context.SetTransform(a, b, c, d, e, f)
547 }
548
549 fn SetTransform_(&self, transform: &DOMMatrix2DInit) -> ErrorResult {
551 self.context.SetTransform_(transform)
552 }
553
554 fn ResetTransform(&self) {
556 self.context.ResetTransform()
557 }
558
559 fn ClosePath(&self) {
561 self.context.ClosePath()
562 }
563
564 fn MoveTo(&self, x: f64, y: f64) {
566 self.context.MoveTo(x, y)
567 }
568
569 fn LineTo(&self, x: f64, y: f64) {
571 self.context.LineTo(x, y)
572 }
573
574 fn Rect(&self, x: f64, y: f64, width: f64, height: f64) {
576 self.context.Rect(x, y, width, height)
577 }
578
579 fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) {
581 self.context.QuadraticCurveTo(cpx, cpy, x, y)
582 }
583
584 fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) {
586 self.context.BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
587 }
588
589 fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> ErrorResult {
591 self.context.Arc(x, y, r, start, end, ccw)
592 }
593
594 fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult {
596 self.context.ArcTo(cp1x, cp1y, cp2x, cp2y, r)
597 }
598
599 fn Ellipse(
601 &self,
602 x: f64,
603 y: f64,
604 rx: f64,
605 ry: f64,
606 rotation: f64,
607 start: f64,
608 end: f64,
609 ccw: bool,
610 ) -> ErrorResult {
611 self.context
612 .Ellipse(x, y, rx, ry, rotation, start, end, ccw)
613 }
614}