1use dom_struct::dom_struct;
6use euclid::default::Size2D;
7use js::context::JSContext;
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, CanvasTextAlign, CanvasTextBaseline,
16};
17use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit;
18use crate::dom::bindings::codegen::Bindings::OffscreenCanvasRenderingContext2DBinding::OffscreenCanvasRenderingContext2DMethods;
19use crate::dom::bindings::codegen::UnionTypes::{
20 HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas,
21 StringOrCanvasGradientOrCanvasPattern,
22};
23use crate::dom::bindings::error::{ErrorResult, Fallible};
24use crate::dom::bindings::num::Finite;
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;
36
37#[dom_struct(associated_memory)]
38pub(crate) struct OffscreenCanvasRenderingContext2D {
39 context: CanvasRenderingContext2D,
40}
41
42impl OffscreenCanvasRenderingContext2D {
43 #[cfg_attr(crown, expect(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 cx: &mut JSContext,
56 global: &GlobalScope,
57 canvas: &OffscreenCanvas,
58 size: Size2D<u32>,
59 ) -> Option<DomRoot<OffscreenCanvasRenderingContext2D>> {
60 OffscreenCanvasRenderingContext2D::new_inherited(
61 global,
62 HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(Dom::from_ref(canvas)),
63 size,
64 )
65 .map(|context| {
66 let context = reflect_dom_object_with_cx(Box::new(context), global, cx);
67 context.context.update_associated_memory_size();
68 context
69 })
70 }
71
72 pub(crate) fn send_canvas_command_immediate(&self, msg: CanvasCommand) {
73 self.context.send_canvas_command_immediate(msg)
74 }
75}
76
77impl CanvasContext for OffscreenCanvasRenderingContext2D {
78 type ID = <CanvasRenderingContext2D as CanvasContext>::ID;
79
80 fn context_id(&self) -> Self::ID {
81 self.context.context_id()
82 }
83
84 fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
85 self.context.canvas()
86 }
87
88 fn resize(&self) {
89 self.context.resize()
90 }
91
92 fn reset_bitmap(&self) {
93 self.context.reset_bitmap()
94 }
95
96 fn get_image_data(&self) -> Option<Snapshot> {
97 self.context.get_image_data()
98 }
99
100 fn origin_is_clean(&self) -> bool {
101 self.context.origin_is_clean()
102 }
103
104 fn mark_as_dirty(&self) {}
105}
106
107impl OffscreenCanvasRenderingContext2DMethods<crate::DomTypeHolder>
108 for OffscreenCanvasRenderingContext2D
109{
110 fn Canvas(&self) -> DomRoot<OffscreenCanvas> {
112 match self.context.canvas() {
113 Some(RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas)) => canvas,
114 _ => panic!("Should not be called from onscreen canvas"),
115 }
116 }
117
118 fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) {
120 self.context.FillRect(x, y, width, height);
121 }
122
123 fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) {
125 self.context.ClearRect(x, y, width, height);
126 }
127
128 fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) {
130 self.context.StrokeRect(x, y, width, height);
131 }
132
133 fn ShadowOffsetX(&self) -> f64 {
135 self.context.ShadowOffsetX()
136 }
137
138 fn SetShadowOffsetX(&self, value: f64) {
140 self.context.SetShadowOffsetX(value)
141 }
142
143 fn ShadowOffsetY(&self) -> f64 {
145 self.context.ShadowOffsetY()
146 }
147
148 fn SetShadowOffsetY(&self, value: f64) {
150 self.context.SetShadowOffsetY(value)
151 }
152
153 fn ShadowBlur(&self) -> f64 {
155 self.context.ShadowBlur()
156 }
157
158 fn SetShadowBlur(&self, value: f64) {
160 self.context.SetShadowBlur(value)
161 }
162
163 fn ShadowColor(&self) -> DOMString {
165 self.context.ShadowColor()
166 }
167
168 fn SetShadowColor(&self, value: DOMString) {
170 self.context.SetShadowColor(value)
171 }
172
173 fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
175 self.context.StrokeStyle()
176 }
177
178 fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
180 self.context.SetStrokeStyle(value)
181 }
182
183 fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
185 self.context.FillStyle()
186 }
187
188 fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
190 self.context.SetFillStyle(value)
191 }
192
193 fn CreateLinearGradient(
195 &self,
196 cx: &mut JSContext,
197 x0: Finite<f64>,
198 y0: Finite<f64>,
199 x1: Finite<f64>,
200 y1: Finite<f64>,
201 ) -> DomRoot<CanvasGradient> {
202 self.context.CreateLinearGradient(cx, x0, y0, x1, y1)
203 }
204
205 fn CreateRadialGradient(
207 &self,
208 cx: &mut JSContext,
209 x0: Finite<f64>,
210 y0: Finite<f64>,
211 r0: Finite<f64>,
212 x1: Finite<f64>,
213 y1: Finite<f64>,
214 r1: Finite<f64>,
215 ) -> Fallible<DomRoot<CanvasGradient>> {
216 self.context
217 .CreateRadialGradient(cx, x0, y0, r0, x1, y1, r1)
218 }
219
220 fn CreatePattern(
222 &self,
223 cx: &mut JSContext,
224 image: CanvasImageSource,
225 repetition: DOMString,
226 ) -> Fallible<Option<DomRoot<CanvasPattern>>> {
227 self.context.CreatePattern(cx, image, repetition)
228 }
229
230 fn Save(&self) {
232 self.context.Save()
233 }
234
235 fn Restore(&self) {
237 self.context.Restore()
238 }
239
240 fn Reset(&self) {
242 self.context.Reset()
243 }
244
245 fn GlobalAlpha(&self) -> f64 {
247 self.context.GlobalAlpha()
248 }
249
250 fn SetGlobalAlpha(&self, alpha: f64) {
252 self.context.SetGlobalAlpha(alpha)
253 }
254
255 fn GlobalCompositeOperation(&self) -> DOMString {
257 self.context.GlobalCompositeOperation()
258 }
259
260 fn SetGlobalCompositeOperation(&self, op_str: DOMString) {
262 self.context.SetGlobalCompositeOperation(op_str)
263 }
264
265 fn ImageSmoothingEnabled(&self) -> bool {
267 self.context.ImageSmoothingEnabled()
268 }
269
270 fn SetImageSmoothingEnabled(&self, value: bool) {
272 self.context.SetImageSmoothingEnabled(value)
273 }
274
275 fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) {
277 self.context.FillText(text, x, y, max_width)
278 }
279
280 fn StrokeText(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) {
282 self.context.StrokeText(text, x, y, max_width)
283 }
284
285 fn MeasureText(&self, cx: &mut JSContext, text: DOMString) -> DomRoot<TextMetrics> {
287 self.context.MeasureText(cx, text)
288 }
289
290 fn Font(&self) -> DOMString {
292 self.context.Font()
293 }
294
295 fn SetFont(&self, value: DOMString) {
297 self.context.SetFont(value)
298 }
299
300 fn TextAlign(&self) -> CanvasTextAlign {
302 self.context.TextAlign()
303 }
304
305 fn SetTextAlign(&self, value: CanvasTextAlign) {
307 self.context.SetTextAlign(value)
308 }
309
310 fn TextBaseline(&self) -> CanvasTextBaseline {
312 self.context.TextBaseline()
313 }
314
315 fn SetTextBaseline(&self, value: CanvasTextBaseline) {
317 self.context.SetTextBaseline(value)
318 }
319
320 fn Direction(&self) -> CanvasDirection {
322 self.context.Direction()
323 }
324
325 fn SetDirection(&self, value: CanvasDirection) {
327 self.context.SetDirection(value)
328 }
329
330 fn LineWidth(&self) -> f64 {
332 self.context.LineWidth()
333 }
334
335 fn SetLineWidth(&self, width: f64) {
337 self.context.SetLineWidth(width)
338 }
339
340 fn LineCap(&self) -> CanvasLineCap {
342 self.context.LineCap()
343 }
344
345 fn SetLineCap(&self, cap: CanvasLineCap) {
347 self.context.SetLineCap(cap)
348 }
349
350 fn LineJoin(&self) -> CanvasLineJoin {
352 self.context.LineJoin()
353 }
354
355 fn SetLineJoin(&self, join: CanvasLineJoin) {
357 self.context.SetLineJoin(join)
358 }
359
360 fn MiterLimit(&self) -> f64 {
362 self.context.MiterLimit()
363 }
364
365 fn SetMiterLimit(&self, limit: f64) {
367 self.context.SetMiterLimit(limit)
368 }
369
370 fn SetLineDash(&self, segments: Vec<f64>) {
372 self.context.SetLineDash(segments)
373 }
374
375 fn GetLineDash(&self) -> Vec<f64> {
377 self.context.GetLineDash()
378 }
379
380 fn LineDashOffset(&self) -> f64 {
382 self.context.LineDashOffset()
383 }
384
385 fn SetLineDashOffset(&self, offset: f64) {
387 self.context.SetLineDashOffset(offset)
388 }
389
390 fn CreateImageData(
392 &self,
393 cx: &mut JSContext,
394 sw: i32,
395 sh: i32,
396 ) -> Fallible<DomRoot<ImageData>> {
397 self.context.CreateImageData(cx, sw, sh)
398 }
399
400 fn CreateImageData_(
402 &self,
403 cx: &mut JSContext,
404 imagedata: &ImageData,
405 ) -> Fallible<DomRoot<ImageData>> {
406 self.context.CreateImageData_(cx, imagedata)
407 }
408
409 fn GetImageData(
411 &self,
412 cx: &mut JSContext,
413 sx: i32,
414 sy: i32,
415 sw: i32,
416 sh: i32,
417 ) -> Fallible<DomRoot<ImageData>> {
418 self.context.GetImageData(cx, sx, sy, sw, sh)
419 }
420
421 fn PutImageData(&self, imagedata: &ImageData, dx: i32, dy: i32) {
423 self.context.PutImageData(imagedata, dx, dy)
424 }
425
426 fn PutImageData_(
428 &self,
429 imagedata: &ImageData,
430 dx: i32,
431 dy: i32,
432 dirty_x: i32,
433 dirty_y: i32,
434 dirty_width: i32,
435 dirty_height: i32,
436 ) {
437 self.context.PutImageData_(
438 imagedata,
439 dx,
440 dy,
441 dirty_x,
442 dirty_y,
443 dirty_width,
444 dirty_height,
445 )
446 }
447
448 fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult {
450 self.context.DrawImage(image, dx, dy)
451 }
452
453 fn DrawImage_(
455 &self,
456 image: CanvasImageSource,
457 dx: f64,
458 dy: f64,
459 dw: f64,
460 dh: f64,
461 ) -> ErrorResult {
462 self.context.DrawImage_(image, dx, dy, dw, dh)
463 }
464
465 fn DrawImage__(
467 &self,
468 image: CanvasImageSource,
469 sx: f64,
470 sy: f64,
471 sw: f64,
472 sh: f64,
473 dx: f64,
474 dy: f64,
475 dw: f64,
476 dh: f64,
477 ) -> ErrorResult {
478 self.context
479 .DrawImage__(image, sx, sy, sw, sh, dx, dy, dw, dh)
480 }
481
482 fn BeginPath(&self) {
484 self.context.BeginPath()
485 }
486
487 fn Fill(&self, fill_rule: CanvasFillRule) {
489 self.context.Fill(fill_rule)
490 }
491
492 fn Fill_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
494 self.context.Fill_(path, fill_rule)
495 }
496
497 fn Stroke(&self) {
499 self.context.Stroke()
500 }
501
502 fn Stroke_(&self, path: &Path2D) {
504 self.context.Stroke_(path)
505 }
506
507 fn Clip(&self, fill_rule: CanvasFillRule) {
509 self.context.Clip(fill_rule)
510 }
511
512 fn Clip_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
514 self.context.Clip_(path, fill_rule)
515 }
516
517 fn IsPointInPath(&self, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
519 self.context.IsPointInPath(x, y, fill_rule)
520 }
521
522 fn IsPointInPath_(&self, path: &Path2D, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
524 self.context.IsPointInPath_(path, x, y, fill_rule)
525 }
526
527 fn Scale(&self, x: f64, y: f64) {
529 self.context.Scale(x, y)
530 }
531
532 fn Rotate(&self, angle: f64) {
534 self.context.Rotate(angle)
535 }
536
537 fn Translate(&self, x: f64, y: f64) {
539 self.context.Translate(x, y)
540 }
541
542 fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
544 self.context.Transform(a, b, c, d, e, f)
545 }
546
547 fn GetTransform(&self, cx: &mut JSContext) -> DomRoot<DOMMatrix> {
549 self.context.GetTransform(cx)
550 }
551
552 fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) -> ErrorResult {
554 self.context.SetTransform(a, b, c, d, e, f)
555 }
556
557 fn SetTransform_(&self, transform: &DOMMatrix2DInit) -> ErrorResult {
559 self.context.SetTransform_(transform)
560 }
561
562 fn ResetTransform(&self) {
564 self.context.ResetTransform()
565 }
566
567 fn ClosePath(&self) {
569 self.context.ClosePath()
570 }
571
572 fn MoveTo(&self, x: f64, y: f64) {
574 self.context.MoveTo(x, y)
575 }
576
577 fn LineTo(&self, x: f64, y: f64) {
579 self.context.LineTo(x, y)
580 }
581
582 fn Rect(&self, x: f64, y: f64, width: f64, height: f64) {
584 self.context.Rect(x, y, width, height)
585 }
586
587 fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) {
589 self.context.QuadraticCurveTo(cpx, cpy, x, y)
590 }
591
592 fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) {
594 self.context.BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
595 }
596
597 fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> ErrorResult {
599 self.context.Arc(x, y, r, start, end, ccw)
600 }
601
602 fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult {
604 self.context.ArcTo(cp1x, cp1y, cp2x, cp2y, r)
605 }
606
607 fn Ellipse(
609 &self,
610 x: f64,
611 y: f64,
612 rx: f64,
613 ry: f64,
614 rotation: f64,
615 start: f64,
616 end: f64,
617 ccw: bool,
618 ) -> ErrorResult {
619 self.context
620 .Ellipse(x, y, rx, ry, rotation, start, end, ccw)
621 }
622}