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 image_key(&self) -> Option<webrender_api::ImageKey> {
101 None
102 }
103}
104
105impl OffscreenCanvasRenderingContext2DMethods<crate::DomTypeHolder>
106 for OffscreenCanvasRenderingContext2D
107{
108 fn Canvas(&self) -> DomRoot<OffscreenCanvas> {
110 match self.context.canvas() {
111 Some(RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas)) => canvas,
112 _ => panic!("Should not be called from onscreen canvas"),
113 }
114 }
115
116 fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) {
118 self.context.FillRect(x, y, width, height);
119 }
120
121 fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) {
123 self.context.ClearRect(x, y, width, height);
124 }
125
126 fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) {
128 self.context.StrokeRect(x, y, width, height);
129 }
130
131 fn ShadowOffsetX(&self) -> f64 {
133 self.context.ShadowOffsetX()
134 }
135
136 fn SetShadowOffsetX(&self, value: f64) {
138 self.context.SetShadowOffsetX(value)
139 }
140
141 fn ShadowOffsetY(&self) -> f64 {
143 self.context.ShadowOffsetY()
144 }
145
146 fn SetShadowOffsetY(&self, value: f64) {
148 self.context.SetShadowOffsetY(value)
149 }
150
151 fn ShadowBlur(&self) -> f64 {
153 self.context.ShadowBlur()
154 }
155
156 fn SetShadowBlur(&self, value: f64) {
158 self.context.SetShadowBlur(value)
159 }
160
161 fn ShadowColor(&self) -> DOMString {
163 self.context.ShadowColor()
164 }
165
166 fn SetShadowColor(&self, value: DOMString) {
168 self.context.SetShadowColor(value)
169 }
170
171 fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
173 self.context.StrokeStyle()
174 }
175
176 fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
178 self.context.SetStrokeStyle(value)
179 }
180
181 fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
183 self.context.FillStyle()
184 }
185
186 fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
188 self.context.SetFillStyle(value)
189 }
190
191 fn CreateLinearGradient(
193 &self,
194 x0: Finite<f64>,
195 y0: Finite<f64>,
196 x1: Finite<f64>,
197 y1: Finite<f64>,
198 can_gc: CanGc,
199 ) -> DomRoot<CanvasGradient> {
200 self.context.CreateLinearGradient(x0, y0, x1, y1, can_gc)
201 }
202
203 fn CreateRadialGradient(
205 &self,
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 can_gc: CanGc,
213 ) -> Fallible<DomRoot<CanvasGradient>> {
214 self.context
215 .CreateRadialGradient(x0, y0, r0, x1, y1, r1, can_gc)
216 }
217
218 fn CreatePattern(
220 &self,
221 image: CanvasImageSource,
222 repetition: DOMString,
223 can_gc: CanGc,
224 ) -> Fallible<Option<DomRoot<CanvasPattern>>> {
225 self.context.CreatePattern(image, repetition, can_gc)
226 }
227
228 fn Save(&self) {
230 self.context.Save()
231 }
232
233 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
234 fn Restore(&self) {
236 self.context.Restore()
237 }
238
239 fn Reset(&self) {
241 self.context.Reset()
242 }
243
244 fn GlobalAlpha(&self) -> f64 {
246 self.context.GlobalAlpha()
247 }
248
249 fn SetGlobalAlpha(&self, alpha: f64) {
251 self.context.SetGlobalAlpha(alpha)
252 }
253
254 fn GlobalCompositeOperation(&self) -> DOMString {
256 self.context.GlobalCompositeOperation()
257 }
258
259 fn SetGlobalCompositeOperation(&self, op_str: DOMString) {
261 self.context.SetGlobalCompositeOperation(op_str)
262 }
263
264 fn ImageSmoothingEnabled(&self) -> bool {
266 self.context.ImageSmoothingEnabled()
267 }
268
269 fn SetImageSmoothingEnabled(&self, value: bool) {
271 self.context.SetImageSmoothingEnabled(value)
272 }
273
274 fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) {
276 self.context.FillText(text, x, y, max_width)
277 }
278
279 fn MeasureText(&self, text: DOMString, can_gc: CanGc) -> DomRoot<TextMetrics> {
281 self.context.MeasureText(text, can_gc)
282 }
283
284 fn Font(&self) -> DOMString {
286 self.context.Font()
287 }
288
289 fn SetFont(&self, value: DOMString) {
291 self.context.SetFont(value)
292 }
293
294 fn TextAlign(&self) -> CanvasTextAlign {
296 self.context.TextAlign()
297 }
298
299 fn SetTextAlign(&self, value: CanvasTextAlign) {
301 self.context.SetTextAlign(value)
302 }
303
304 fn TextBaseline(&self) -> CanvasTextBaseline {
306 self.context.TextBaseline()
307 }
308
309 fn SetTextBaseline(&self, value: CanvasTextBaseline) {
311 self.context.SetTextBaseline(value)
312 }
313
314 fn Direction(&self) -> CanvasDirection {
316 self.context.Direction()
317 }
318
319 fn SetDirection(&self, value: CanvasDirection) {
321 self.context.SetDirection(value)
322 }
323
324 fn LineWidth(&self) -> f64 {
326 self.context.LineWidth()
327 }
328
329 fn SetLineWidth(&self, width: f64) {
331 self.context.SetLineWidth(width)
332 }
333
334 fn LineCap(&self) -> CanvasLineCap {
336 self.context.LineCap()
337 }
338
339 fn SetLineCap(&self, cap: CanvasLineCap) {
341 self.context.SetLineCap(cap)
342 }
343
344 fn LineJoin(&self) -> CanvasLineJoin {
346 self.context.LineJoin()
347 }
348
349 fn SetLineJoin(&self, join: CanvasLineJoin) {
351 self.context.SetLineJoin(join)
352 }
353
354 fn MiterLimit(&self) -> f64 {
356 self.context.MiterLimit()
357 }
358
359 fn SetMiterLimit(&self, limit: f64) {
361 self.context.SetMiterLimit(limit)
362 }
363
364 fn SetLineDash(&self, segments: Vec<f64>) {
366 self.context.SetLineDash(segments)
367 }
368
369 fn GetLineDash(&self) -> Vec<f64> {
371 self.context.GetLineDash()
372 }
373
374 fn LineDashOffset(&self) -> f64 {
376 self.context.LineDashOffset()
377 }
378
379 fn SetLineDashOffset(&self, offset: f64) {
381 self.context.SetLineDashOffset(offset)
382 }
383
384 fn CreateImageData(&self, sw: i32, sh: i32, can_gc: CanGc) -> Fallible<DomRoot<ImageData>> {
386 self.context.CreateImageData(sw, sh, can_gc)
387 }
388
389 fn CreateImageData_(
391 &self,
392 imagedata: &ImageData,
393 can_gc: CanGc,
394 ) -> Fallible<DomRoot<ImageData>> {
395 self.context.CreateImageData_(imagedata, can_gc)
396 }
397
398 fn GetImageData(
400 &self,
401 sx: i32,
402 sy: i32,
403 sw: i32,
404 sh: i32,
405 can_gc: CanGc,
406 ) -> Fallible<DomRoot<ImageData>> {
407 self.context.GetImageData(sx, sy, sw, sh, can_gc)
408 }
409
410 fn PutImageData(&self, imagedata: &ImageData, dx: i32, dy: i32) {
412 self.context.PutImageData(imagedata, dx, dy)
413 }
414
415 #[allow(unsafe_code)]
417 fn PutImageData_(
418 &self,
419 imagedata: &ImageData,
420 dx: i32,
421 dy: i32,
422 dirty_x: i32,
423 dirty_y: i32,
424 dirty_width: i32,
425 dirty_height: i32,
426 ) {
427 self.context.PutImageData_(
428 imagedata,
429 dx,
430 dy,
431 dirty_x,
432 dirty_y,
433 dirty_width,
434 dirty_height,
435 )
436 }
437
438 fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult {
440 self.context.DrawImage(image, dx, dy)
441 }
442
443 fn DrawImage_(
445 &self,
446 image: CanvasImageSource,
447 dx: f64,
448 dy: f64,
449 dw: f64,
450 dh: f64,
451 ) -> ErrorResult {
452 self.context.DrawImage_(image, dx, dy, dw, dh)
453 }
454
455 fn DrawImage__(
457 &self,
458 image: CanvasImageSource,
459 sx: f64,
460 sy: f64,
461 sw: f64,
462 sh: f64,
463 dx: f64,
464 dy: f64,
465 dw: f64,
466 dh: f64,
467 ) -> ErrorResult {
468 self.context
469 .DrawImage__(image, sx, sy, sw, sh, dx, dy, dw, dh)
470 }
471
472 fn BeginPath(&self) {
474 self.context.BeginPath()
475 }
476
477 fn Fill(&self, fill_rule: CanvasFillRule) {
479 self.context.Fill(fill_rule)
480 }
481
482 fn Fill_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
484 self.context.Fill_(path, fill_rule)
485 }
486
487 fn Stroke(&self) {
489 self.context.Stroke()
490 }
491
492 fn Stroke_(&self, path: &Path2D) {
494 self.context.Stroke_(path)
495 }
496
497 fn Clip(&self, fill_rule: CanvasFillRule) {
499 self.context.Clip(fill_rule)
500 }
501
502 fn Clip_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
504 self.context.Clip_(path, fill_rule)
505 }
506
507 fn IsPointInPath(&self, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
509 self.context.IsPointInPath(x, y, fill_rule)
510 }
511
512 fn IsPointInPath_(&self, path: &Path2D, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
514 self.context.IsPointInPath_(path, x, y, fill_rule)
515 }
516
517 fn Scale(&self, x: f64, y: f64) {
519 self.context.Scale(x, y)
520 }
521
522 fn Rotate(&self, angle: f64) {
524 self.context.Rotate(angle)
525 }
526
527 fn Translate(&self, x: f64, y: f64) {
529 self.context.Translate(x, y)
530 }
531
532 fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
534 self.context.Transform(a, b, c, d, e, f)
535 }
536
537 fn GetTransform(&self, can_gc: CanGc) -> DomRoot<DOMMatrix> {
539 self.context.GetTransform(can_gc)
540 }
541
542 fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) -> ErrorResult {
544 self.context.SetTransform(a, b, c, d, e, f)
545 }
546
547 fn SetTransform_(&self, transform: &DOMMatrix2DInit) -> ErrorResult {
549 self.context.SetTransform_(transform)
550 }
551
552 fn ResetTransform(&self) {
554 self.context.ResetTransform()
555 }
556
557 fn ClosePath(&self) {
559 self.context.ClosePath()
560 }
561
562 fn MoveTo(&self, x: f64, y: f64) {
564 self.context.MoveTo(x, y)
565 }
566
567 fn LineTo(&self, x: f64, y: f64) {
569 self.context.LineTo(x, y)
570 }
571
572 fn Rect(&self, x: f64, y: f64, width: f64, height: f64) {
574 self.context.Rect(x, y, width, height)
575 }
576
577 fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) {
579 self.context.QuadraticCurveTo(cpx, cpy, x, y)
580 }
581
582 fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) {
584 self.context.BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
585 }
586
587 fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> ErrorResult {
589 self.context.Arc(x, y, r, start, end, ccw)
590 }
591
592 fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult {
594 self.context.ArcTo(cp1x, cp1y, cp2x, cp2y, r)
595 }
596
597 fn Ellipse(
599 &self,
600 x: f64,
601 y: f64,
602 rx: f64,
603 ry: f64,
604 rotation: f64,
605 start: f64,
606 end: f64,
607 ccw: bool,
608 ) -> ErrorResult {
609 self.context
610 .Ellipse(x, y, rx, ry, rotation, start, end, ccw)
611 }
612}