1use dom_struct::dom_struct;
6use euclid::default::Size2D;
7use js::context::{JSContext, NoGC};
8use pixels::Snapshot;
9use script_bindings::reflector::reflect_dom_object;
10use servo_canvas_traits::canvas::CanvasCommand;
11
12use crate::canvas_context::{CanvasContext, HTMLCanvasElementOrOffscreenCanvas};
13use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{
14 CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin,
15 CanvasRenderingContext2DMethods, CanvasRenderingContext2DSettings, CanvasTextAlign,
16 CanvasTextBaseline,
17};
18use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit;
19use crate::dom::bindings::codegen::Bindings::OffscreenCanvasRenderingContext2DBinding::OffscreenCanvasRenderingContext2DMethods;
20use crate::dom::bindings::codegen::UnionTypes::{
21 HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas,
22 StringOrCanvasGradientOrCanvasPattern,
23 UnrestrictedDoubleOrDOMPointInitOrUnrestrictedDoubleOrDOMPointInitSequence,
24};
25use crate::dom::bindings::error::{ErrorResult, Fallible};
26use crate::dom::bindings::num::Finite;
27use crate::dom::bindings::root::{Dom, DomRoot};
28use crate::dom::bindings::str::DOMString;
29use crate::dom::canvasgradient::CanvasGradient;
30use crate::dom::canvaspattern::CanvasPattern;
31use crate::dom::canvasrenderingcontext2d::CanvasRenderingContext2D;
32use crate::dom::dommatrix::DOMMatrix;
33use crate::dom::globalscope::GlobalScope;
34use crate::dom::imagedata::ImageData;
35use crate::dom::offscreencanvas::OffscreenCanvas;
36use crate::dom::path2d::Path2D;
37use crate::dom::textmetrics::TextMetrics;
38
39#[dom_struct]
40pub(crate) struct OffscreenCanvasRenderingContext2D {
41 context: CanvasRenderingContext2D,
42}
43
44impl OffscreenCanvasRenderingContext2D {
45 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
46 fn new_inherited(
47 global: &GlobalScope,
48 canvas: HTMLCanvasElementOrOffscreenCanvas,
49 size: Size2D<u32>,
50 settings: &CanvasRenderingContext2DSettings,
51 ) -> Option<OffscreenCanvasRenderingContext2D> {
52 Some(OffscreenCanvasRenderingContext2D {
53 context: CanvasRenderingContext2D::new_inherited(global, canvas, size, settings)?,
54 })
55 }
56
57 pub(crate) fn new(
58 cx: &mut JSContext,
59 global: &GlobalScope,
60 canvas: &OffscreenCanvas,
61 size: Size2D<u32>,
62 settings: &CanvasRenderingContext2DSettings,
63 ) -> Option<DomRoot<OffscreenCanvasRenderingContext2D>> {
64 OffscreenCanvasRenderingContext2D::new_inherited(
65 global,
66 HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(Dom::from_ref(canvas)),
67 size,
68 settings,
69 )
70 .map(|context| {
71 let context = reflect_dom_object(cx, Box::new(context), global);
72 context.context.update_associated_memory_size();
73 context
74 })
75 }
76
77 pub(crate) fn send_canvas_command_immediate(&self, msg: CanvasCommand) {
78 self.context.send_canvas_command_immediate(msg)
79 }
80}
81
82impl CanvasContext for OffscreenCanvasRenderingContext2D {
83 type ID = <CanvasRenderingContext2D as CanvasContext>::ID;
84
85 fn context_id(&self) -> Self::ID {
86 self.context.context_id()
87 }
88
89 fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
90 self.context.canvas()
91 }
92
93 fn resize(&self) {
94 self.context.resize()
95 }
96
97 fn reset_bitmap(&self) {
98 self.context.reset_bitmap()
99 }
100
101 fn get_image_data(&self) -> Option<Snapshot> {
102 self.context.get_image_data()
103 }
104
105 fn origin_is_clean(&self) -> bool {
106 self.context.origin_is_clean()
107 }
108
109 fn mark_as_dirty(&self) {}
110}
111
112impl OffscreenCanvasRenderingContext2DMethods<crate::DomTypeHolder>
113 for OffscreenCanvasRenderingContext2D
114{
115 fn GetContextAttributes(&self) -> CanvasRenderingContext2DSettings {
117 self.context.GetContextAttributes()
121 }
122
123 fn Canvas(&self) -> DomRoot<OffscreenCanvas> {
125 match self.context.canvas() {
126 Some(RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas)) => canvas,
127 _ => panic!("Should not be called from onscreen canvas"),
128 }
129 }
130
131 fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) {
133 self.context.FillRect(x, y, width, height);
134 }
135
136 fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) {
138 self.context.ClearRect(x, y, width, height);
139 }
140
141 fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) {
143 self.context.StrokeRect(x, y, width, height);
144 }
145
146 fn ShadowOffsetX(&self) -> f64 {
148 self.context.ShadowOffsetX()
149 }
150
151 fn SetShadowOffsetX(&self, value: f64) {
153 self.context.SetShadowOffsetX(value)
154 }
155
156 fn ShadowOffsetY(&self) -> f64 {
158 self.context.ShadowOffsetY()
159 }
160
161 fn SetShadowOffsetY(&self, value: f64) {
163 self.context.SetShadowOffsetY(value)
164 }
165
166 fn ShadowBlur(&self) -> f64 {
168 self.context.ShadowBlur()
169 }
170
171 fn SetShadowBlur(&self, value: f64) {
173 self.context.SetShadowBlur(value)
174 }
175
176 fn ShadowColor(&self) -> DOMString {
178 self.context.ShadowColor()
179 }
180
181 fn SetShadowColor(&self, value: DOMString) {
183 self.context.SetShadowColor(value)
184 }
185
186 fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
188 self.context.StrokeStyle()
189 }
190
191 fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
193 self.context.SetStrokeStyle(value)
194 }
195
196 fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
198 self.context.FillStyle()
199 }
200
201 fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
203 self.context.SetFillStyle(value)
204 }
205
206 fn CreateLinearGradient(
208 &self,
209 cx: &mut JSContext,
210 x0: Finite<f64>,
211 y0: Finite<f64>,
212 x1: Finite<f64>,
213 y1: Finite<f64>,
214 ) -> DomRoot<CanvasGradient> {
215 self.context.CreateLinearGradient(cx, x0, y0, x1, y1)
216 }
217
218 fn CreateRadialGradient(
220 &self,
221 cx: &mut JSContext,
222 x0: Finite<f64>,
223 y0: Finite<f64>,
224 r0: Finite<f64>,
225 x1: Finite<f64>,
226 y1: Finite<f64>,
227 r1: Finite<f64>,
228 ) -> Fallible<DomRoot<CanvasGradient>> {
229 self.context
230 .CreateRadialGradient(cx, x0, y0, r0, x1, y1, r1)
231 }
232
233 fn CreatePattern(
235 &self,
236 cx: &mut JSContext,
237 image: CanvasImageSource,
238 repetition: DOMString,
239 ) -> Fallible<Option<DomRoot<CanvasPattern>>> {
240 self.context.CreatePattern(cx, image, repetition)
241 }
242
243 fn Save(&self) {
245 self.context.Save()
246 }
247
248 fn Restore(&self) {
250 self.context.Restore()
251 }
252
253 fn Reset(&self) {
255 self.context.Reset()
256 }
257
258 fn GlobalAlpha(&self) -> f64 {
260 self.context.GlobalAlpha()
261 }
262
263 fn SetGlobalAlpha(&self, alpha: f64) {
265 self.context.SetGlobalAlpha(alpha)
266 }
267
268 fn GlobalCompositeOperation(&self) -> DOMString {
270 self.context.GlobalCompositeOperation()
271 }
272
273 fn SetGlobalCompositeOperation(&self, op_str: DOMString) {
275 self.context.SetGlobalCompositeOperation(op_str)
276 }
277
278 fn ImageSmoothingEnabled(&self) -> bool {
280 self.context.ImageSmoothingEnabled()
281 }
282
283 fn SetImageSmoothingEnabled(&self, value: bool) {
285 self.context.SetImageSmoothingEnabled(value)
286 }
287
288 fn FillText(
290 &self,
291 cx: &mut JSContext,
292 text: DOMString,
293 x: f64,
294 y: f64,
295 max_width: Option<f64>,
296 ) {
297 self.context.FillText(cx, text, x, y, max_width)
298 }
299
300 fn StrokeText(
302 &self,
303 cx: &mut JSContext,
304 text: DOMString,
305 x: f64,
306 y: f64,
307 max_width: Option<f64>,
308 ) {
309 self.context.StrokeText(cx, text, x, y, max_width)
310 }
311
312 fn MeasureText(&self, cx: &mut JSContext, text: DOMString) -> DomRoot<TextMetrics> {
314 self.context.MeasureText(cx, text)
315 }
316
317 fn Font(&self) -> DOMString {
319 self.context.Font()
320 }
321
322 fn SetFont(&self, cx: &mut JSContext, value: DOMString) {
324 self.context.SetFont(cx, value)
325 }
326
327 fn TextAlign(&self) -> CanvasTextAlign {
329 self.context.TextAlign()
330 }
331
332 fn SetTextAlign(&self, value: CanvasTextAlign) {
334 self.context.SetTextAlign(value)
335 }
336
337 fn TextBaseline(&self) -> CanvasTextBaseline {
339 self.context.TextBaseline()
340 }
341
342 fn SetTextBaseline(&self, value: CanvasTextBaseline) {
344 self.context.SetTextBaseline(value)
345 }
346
347 fn Direction(&self) -> CanvasDirection {
349 self.context.Direction()
350 }
351
352 fn SetDirection(&self, value: CanvasDirection) {
354 self.context.SetDirection(value)
355 }
356
357 fn LineWidth(&self) -> f64 {
359 self.context.LineWidth()
360 }
361
362 fn SetLineWidth(&self, width: f64) {
364 self.context.SetLineWidth(width)
365 }
366
367 fn LineCap(&self) -> CanvasLineCap {
369 self.context.LineCap()
370 }
371
372 fn SetLineCap(&self, cap: CanvasLineCap) {
374 self.context.SetLineCap(cap)
375 }
376
377 fn LineJoin(&self) -> CanvasLineJoin {
379 self.context.LineJoin()
380 }
381
382 fn SetLineJoin(&self, join: CanvasLineJoin) {
384 self.context.SetLineJoin(join)
385 }
386
387 fn MiterLimit(&self) -> f64 {
389 self.context.MiterLimit()
390 }
391
392 fn SetMiterLimit(&self, limit: f64) {
394 self.context.SetMiterLimit(limit)
395 }
396
397 fn SetLineDash(&self, segments: Vec<f64>) {
399 self.context.SetLineDash(segments)
400 }
401
402 fn GetLineDash(&self) -> Vec<f64> {
404 self.context.GetLineDash()
405 }
406
407 fn LineDashOffset(&self) -> f64 {
409 self.context.LineDashOffset()
410 }
411
412 fn SetLineDashOffset(&self, offset: f64) {
414 self.context.SetLineDashOffset(offset)
415 }
416
417 fn CreateImageData(
419 &self,
420 cx: &mut JSContext,
421 sw: i32,
422 sh: i32,
423 ) -> Fallible<DomRoot<ImageData>> {
424 self.context.CreateImageData(cx, sw, sh)
425 }
426
427 fn CreateImageData_(
429 &self,
430 cx: &mut JSContext,
431 imagedata: &ImageData,
432 ) -> Fallible<DomRoot<ImageData>> {
433 self.context.CreateImageData_(cx, imagedata)
434 }
435
436 fn GetImageData(
438 &self,
439 cx: &mut JSContext,
440 sx: i32,
441 sy: i32,
442 sw: i32,
443 sh: i32,
444 ) -> Fallible<DomRoot<ImageData>> {
445 self.context.GetImageData(cx, sx, sy, sw, sh)
446 }
447
448 fn PutImageData(&self, no_gc: &NoGC, imagedata: &ImageData, dx: i32, dy: i32) {
450 self.context.PutImageData(no_gc, imagedata, dx, dy)
451 }
452
453 fn PutImageData_(
455 &self,
456 no_gc: &NoGC,
457 imagedata: &ImageData,
458 dx: i32,
459 dy: i32,
460 dirty_x: i32,
461 dirty_y: i32,
462 dirty_width: i32,
463 dirty_height: i32,
464 ) {
465 self.context.PutImageData_(
466 no_gc,
467 imagedata,
468 dx,
469 dy,
470 dirty_x,
471 dirty_y,
472 dirty_width,
473 dirty_height,
474 )
475 }
476
477 fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult {
479 self.context.DrawImage(image, dx, dy)
480 }
481
482 fn DrawImage_(
484 &self,
485 image: CanvasImageSource,
486 dx: f64,
487 dy: f64,
488 dw: f64,
489 dh: f64,
490 ) -> ErrorResult {
491 self.context.DrawImage_(image, dx, dy, dw, dh)
492 }
493
494 fn DrawImage__(
496 &self,
497 image: CanvasImageSource,
498 sx: f64,
499 sy: f64,
500 sw: f64,
501 sh: f64,
502 dx: f64,
503 dy: f64,
504 dw: f64,
505 dh: f64,
506 ) -> ErrorResult {
507 self.context
508 .DrawImage__(image, sx, sy, sw, sh, dx, dy, dw, dh)
509 }
510
511 fn BeginPath(&self) {
513 self.context.BeginPath()
514 }
515
516 fn Fill(&self, fill_rule: CanvasFillRule) {
518 self.context.Fill(fill_rule)
519 }
520
521 fn Fill_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
523 self.context.Fill_(path, fill_rule)
524 }
525
526 fn Stroke(&self) {
528 self.context.Stroke()
529 }
530
531 fn Stroke_(&self, path: &Path2D) {
533 self.context.Stroke_(path)
534 }
535
536 fn Clip(&self, fill_rule: CanvasFillRule) {
538 self.context.Clip(fill_rule)
539 }
540
541 fn Clip_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
543 self.context.Clip_(path, fill_rule)
544 }
545
546 fn IsPointInPath(&self, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
548 self.context.IsPointInPath(x, y, fill_rule)
549 }
550
551 fn IsPointInPath_(&self, path: &Path2D, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
553 self.context.IsPointInPath_(path, x, y, fill_rule)
554 }
555
556 fn Scale(&self, x: f64, y: f64) {
558 self.context.Scale(x, y)
559 }
560
561 fn Rotate(&self, angle: f64) {
563 self.context.Rotate(angle)
564 }
565
566 fn Translate(&self, x: f64, y: f64) {
568 self.context.Translate(x, y)
569 }
570
571 fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
573 self.context.Transform(a, b, c, d, e, f)
574 }
575
576 fn GetTransform(&self, cx: &mut JSContext) -> DomRoot<DOMMatrix> {
578 self.context.GetTransform(cx)
579 }
580
581 fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) -> ErrorResult {
583 self.context.SetTransform(a, b, c, d, e, f)
584 }
585
586 fn SetTransform_(&self, transform: &DOMMatrix2DInit) -> ErrorResult {
588 self.context.SetTransform_(transform)
589 }
590
591 fn ResetTransform(&self) {
593 self.context.ResetTransform()
594 }
595
596 fn ClosePath(&self) {
598 self.context.ClosePath()
599 }
600
601 fn MoveTo(&self, x: f64, y: f64) {
603 self.context.MoveTo(x, y)
604 }
605
606 fn LineTo(&self, x: f64, y: f64) {
608 self.context.LineTo(x, y)
609 }
610
611 fn Rect(&self, x: f64, y: f64, width: f64, height: f64) {
613 self.context.Rect(x, y, width, height)
614 }
615
616 fn RoundRect(
618 &self,
619 x: f64,
620 y: f64,
621 width: f64,
622 height: f64,
623 radii: UnrestrictedDoubleOrDOMPointInitOrUnrestrictedDoubleOrDOMPointInitSequence,
624 ) -> ErrorResult {
625 self.context.RoundRect(x, y, width, height, radii)
626 }
627
628 fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) {
630 self.context.QuadraticCurveTo(cpx, cpy, x, y)
631 }
632
633 fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) {
635 self.context.BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
636 }
637
638 fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> ErrorResult {
640 self.context.Arc(x, y, r, start, end, ccw)
641 }
642
643 fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult {
645 self.context.ArcTo(cp1x, cp1y, cp2x, cp2y, r)
646 }
647
648 fn Ellipse(
650 &self,
651 x: f64,
652 y: f64,
653 rx: f64,
654 ry: f64,
655 rotation: f64,
656 start: f64,
657 end: f64,
658 ccw: bool,
659 ) -> ErrorResult {
660 self.context
661 .Ellipse(x, y, rx, ry, rotation, start, end, ccw)
662 }
663}