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