1use canvas_traits::canvas::Canvas2dMsg;
6use dom_struct::dom_struct;
7use euclid::default::Size2D;
8use js::context::JSContext;
9use pixels::Snapshot;
10
11use crate::canvas_context::{CanvasContext, HTMLCanvasElementOrOffscreenCanvas};
12use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{
13 CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin,
14 CanvasRenderingContext2DMethods, CanvasTextAlign, CanvasTextBaseline,
15};
16use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit;
17use crate::dom::bindings::codegen::Bindings::OffscreenCanvasRenderingContext2DBinding::OffscreenCanvasRenderingContext2DMethods;
18use crate::dom::bindings::codegen::UnionTypes::{
19 HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas,
20 StringOrCanvasGradientOrCanvasPattern,
21};
22use crate::dom::bindings::error::{ErrorResult, Fallible};
23use crate::dom::bindings::num::Finite;
24use crate::dom::bindings::reflector::reflect_dom_object;
25use crate::dom::bindings::root::{Dom, DomRoot};
26use crate::dom::bindings::str::DOMString;
27use crate::dom::canvasgradient::CanvasGradient;
28use crate::dom::canvaspattern::CanvasPattern;
29use crate::dom::canvasrenderingcontext2d::CanvasRenderingContext2D;
30use crate::dom::dommatrix::DOMMatrix;
31use crate::dom::globalscope::GlobalScope;
32use crate::dom::imagedata::ImageData;
33use crate::dom::offscreencanvas::OffscreenCanvas;
34use crate::dom::path2d::Path2D;
35use crate::dom::textmetrics::TextMetrics;
36use crate::script_runtime::CanGc;
37
38#[dom_struct(associated_memory)]
39pub(crate) struct OffscreenCanvasRenderingContext2D {
40 context: CanvasRenderingContext2D,
41}
42
43impl OffscreenCanvasRenderingContext2D {
44 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
45 fn new_inherited(
46 global: &GlobalScope,
47 canvas: HTMLCanvasElementOrOffscreenCanvas,
48 size: Size2D<u32>,
49 ) -> Option<OffscreenCanvasRenderingContext2D> {
50 Some(OffscreenCanvasRenderingContext2D {
51 context: CanvasRenderingContext2D::new_inherited(global, canvas, size)?,
52 })
53 }
54
55 pub(crate) fn new(
56 global: &GlobalScope,
57 canvas: &OffscreenCanvas,
58 size: Size2D<u32>,
59 can_gc: CanGc,
60 ) -> Option<DomRoot<OffscreenCanvasRenderingContext2D>> {
61 OffscreenCanvasRenderingContext2D::new_inherited(
62 global,
63 HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(Dom::from_ref(canvas)),
64 size,
65 )
66 .map(|context| reflect_dom_object(Box::new(context), global, can_gc))
67 }
68
69 pub(crate) fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) {
70 self.context.send_canvas_2d_msg(msg)
71 }
72}
73
74impl CanvasContext for OffscreenCanvasRenderingContext2D {
75 type ID = <CanvasRenderingContext2D as CanvasContext>::ID;
76
77 fn context_id(&self) -> Self::ID {
78 self.context.context_id()
79 }
80
81 fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
82 self.context.canvas()
83 }
84
85 fn resize(&self) {
86 self.context.resize()
87 }
88
89 fn reset_bitmap(&self) {
90 self.context.reset_bitmap()
91 }
92
93 fn get_image_data(&self) -> Option<Snapshot> {
94 self.context.get_image_data()
95 }
96
97 fn origin_is_clean(&self) -> bool {
98 self.context.origin_is_clean()
99 }
100
101 fn mark_as_dirty(&self) {}
102}
103
104impl OffscreenCanvasRenderingContext2DMethods<crate::DomTypeHolder>
105 for OffscreenCanvasRenderingContext2D
106{
107 fn Canvas(&self) -> DomRoot<OffscreenCanvas> {
109 match self.context.canvas() {
110 Some(RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas)) => canvas,
111 _ => panic!("Should not be called from onscreen canvas"),
112 }
113 }
114
115 fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) {
117 self.context.FillRect(x, y, width, height);
118 }
119
120 fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) {
122 self.context.ClearRect(x, y, width, height);
123 }
124
125 fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) {
127 self.context.StrokeRect(x, y, width, height);
128 }
129
130 fn ShadowOffsetX(&self) -> f64 {
132 self.context.ShadowOffsetX()
133 }
134
135 fn SetShadowOffsetX(&self, value: f64) {
137 self.context.SetShadowOffsetX(value)
138 }
139
140 fn ShadowOffsetY(&self) -> f64 {
142 self.context.ShadowOffsetY()
143 }
144
145 fn SetShadowOffsetY(&self, value: f64) {
147 self.context.SetShadowOffsetY(value)
148 }
149
150 fn ShadowBlur(&self) -> f64 {
152 self.context.ShadowBlur()
153 }
154
155 fn SetShadowBlur(&self, value: f64) {
157 self.context.SetShadowBlur(value)
158 }
159
160 fn ShadowColor(&self) -> DOMString {
162 self.context.ShadowColor()
163 }
164
165 fn SetShadowColor(&self, value: DOMString) {
167 self.context.SetShadowColor(value)
168 }
169
170 fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
172 self.context.StrokeStyle()
173 }
174
175 fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
177 self.context.SetStrokeStyle(value)
178 }
179
180 fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
182 self.context.FillStyle()
183 }
184
185 fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
187 self.context.SetFillStyle(value)
188 }
189
190 fn CreateLinearGradient(
192 &self,
193 cx: &mut JSContext,
194 x0: Finite<f64>,
195 y0: Finite<f64>,
196 x1: Finite<f64>,
197 y1: Finite<f64>,
198 ) -> DomRoot<CanvasGradient> {
199 self.context.CreateLinearGradient(cx, x0, y0, x1, y1)
200 }
201
202 fn CreateRadialGradient(
204 &self,
205 cx: &mut JSContext,
206 x0: Finite<f64>,
207 y0: Finite<f64>,
208 r0: Finite<f64>,
209 x1: Finite<f64>,
210 y1: Finite<f64>,
211 r1: Finite<f64>,
212 ) -> Fallible<DomRoot<CanvasGradient>> {
213 self.context
214 .CreateRadialGradient(cx, x0, y0, r0, x1, y1, r1)
215 }
216
217 fn CreatePattern(
219 &self,
220 cx: &mut JSContext,
221 image: CanvasImageSource,
222 repetition: DOMString,
223 ) -> Fallible<Option<DomRoot<CanvasPattern>>> {
224 self.context.CreatePattern(cx, image, repetition)
225 }
226
227 fn Save(&self) {
229 self.context.Save()
230 }
231
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, cx: &mut JSContext, text: DOMString) -> DomRoot<TextMetrics> {
284 self.context.MeasureText(cx, text)
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(
389 &self,
390 cx: &mut JSContext,
391 sw: i32,
392 sh: i32,
393 ) -> Fallible<DomRoot<ImageData>> {
394 self.context.CreateImageData(sw, sh, CanGc::from_cx(cx))
395 }
396
397 fn CreateImageData_(
399 &self,
400 cx: &mut JSContext,
401 imagedata: &ImageData,
402 ) -> Fallible<DomRoot<ImageData>> {
403 self.context.CreateImageData_(imagedata, CanGc::from_cx(cx))
404 }
405
406 fn GetImageData(
408 &self,
409 cx: &mut JSContext,
410 sx: i32,
411 sy: i32,
412 sw: i32,
413 sh: i32,
414 ) -> Fallible<DomRoot<ImageData>> {
415 self.context
416 .GetImageData(sx, sy, sw, sh, CanGc::from_cx(cx))
417 }
418
419 fn PutImageData(&self, imagedata: &ImageData, dx: i32, dy: i32) {
421 self.context.PutImageData(imagedata, dx, dy)
422 }
423
424 fn PutImageData_(
426 &self,
427 imagedata: &ImageData,
428 dx: i32,
429 dy: i32,
430 dirty_x: i32,
431 dirty_y: i32,
432 dirty_width: i32,
433 dirty_height: i32,
434 ) {
435 self.context.PutImageData_(
436 imagedata,
437 dx,
438 dy,
439 dirty_x,
440 dirty_y,
441 dirty_width,
442 dirty_height,
443 )
444 }
445
446 fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult {
448 self.context.DrawImage(image, dx, dy)
449 }
450
451 fn DrawImage_(
453 &self,
454 image: CanvasImageSource,
455 dx: f64,
456 dy: f64,
457 dw: f64,
458 dh: f64,
459 ) -> ErrorResult {
460 self.context.DrawImage_(image, dx, dy, dw, dh)
461 }
462
463 fn DrawImage__(
465 &self,
466 image: CanvasImageSource,
467 sx: f64,
468 sy: f64,
469 sw: f64,
470 sh: f64,
471 dx: f64,
472 dy: f64,
473 dw: f64,
474 dh: f64,
475 ) -> ErrorResult {
476 self.context
477 .DrawImage__(image, sx, sy, sw, sh, dx, dy, dw, dh)
478 }
479
480 fn BeginPath(&self) {
482 self.context.BeginPath()
483 }
484
485 fn Fill(&self, fill_rule: CanvasFillRule) {
487 self.context.Fill(fill_rule)
488 }
489
490 fn Fill_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
492 self.context.Fill_(path, fill_rule)
493 }
494
495 fn Stroke(&self) {
497 self.context.Stroke()
498 }
499
500 fn Stroke_(&self, path: &Path2D) {
502 self.context.Stroke_(path)
503 }
504
505 fn Clip(&self, fill_rule: CanvasFillRule) {
507 self.context.Clip(fill_rule)
508 }
509
510 fn Clip_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
512 self.context.Clip_(path, fill_rule)
513 }
514
515 fn IsPointInPath(&self, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
517 self.context.IsPointInPath(x, y, fill_rule)
518 }
519
520 fn IsPointInPath_(&self, path: &Path2D, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
522 self.context.IsPointInPath_(path, x, y, fill_rule)
523 }
524
525 fn Scale(&self, x: f64, y: f64) {
527 self.context.Scale(x, y)
528 }
529
530 fn Rotate(&self, angle: f64) {
532 self.context.Rotate(angle)
533 }
534
535 fn Translate(&self, x: f64, y: f64) {
537 self.context.Translate(x, y)
538 }
539
540 fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
542 self.context.Transform(a, b, c, d, e, f)
543 }
544
545 fn GetTransform(&self, cx: &mut JSContext) -> DomRoot<DOMMatrix> {
547 self.context.GetTransform(cx)
548 }
549
550 fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) -> ErrorResult {
552 self.context.SetTransform(a, b, c, d, e, f)
553 }
554
555 fn SetTransform_(&self, transform: &DOMMatrix2DInit) -> ErrorResult {
557 self.context.SetTransform_(transform)
558 }
559
560 fn ResetTransform(&self) {
562 self.context.ResetTransform()
563 }
564
565 fn ClosePath(&self) {
567 self.context.ClosePath()
568 }
569
570 fn MoveTo(&self, x: f64, y: f64) {
572 self.context.MoveTo(x, y)
573 }
574
575 fn LineTo(&self, x: f64, y: f64) {
577 self.context.LineTo(x, y)
578 }
579
580 fn Rect(&self, x: f64, y: f64, width: f64, height: f64) {
582 self.context.Rect(x, y, width, height)
583 }
584
585 fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) {
587 self.context.QuadraticCurveTo(cpx, cpy, x, y)
588 }
589
590 fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) {
592 self.context.BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
593 }
594
595 fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> ErrorResult {
597 self.context.Arc(x, y, r, start, end, ccw)
598 }
599
600 fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult {
602 self.context.ArcTo(cp1x, cp1y, cp2x, cp2y, r)
603 }
604
605 fn Ellipse(
607 &self,
608 x: f64,
609 y: f64,
610 rx: f64,
611 ry: f64,
612 rotation: f64,
613 start: f64,
614 end: f64,
615 ccw: bool,
616 ) -> ErrorResult {
617 self.context
618 .Ellipse(x, y, rx, ry, rotation, start, end, ccw)
619 }
620}