1use dom_struct::dom_struct;
6use euclid::default::Size2D;
7use js::context::JSContext;
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, 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;
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| {
67 let context = reflect_dom_object(Box::new(context), global, can_gc);
68 context.context.update_associated_memory_size();
69 context
70 })
71 }
72
73 pub(crate) fn send_canvas_command(&self, msg: CanvasCommand) {
74 self.context.send_canvas_command(msg)
75 }
76}
77
78impl CanvasContext for OffscreenCanvasRenderingContext2D {
79 type ID = <CanvasRenderingContext2D as CanvasContext>::ID;
80
81 fn context_id(&self) -> Self::ID {
82 self.context.context_id()
83 }
84
85 fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
86 self.context.canvas()
87 }
88
89 fn resize(&self) {
90 self.context.resize()
91 }
92
93 fn reset_bitmap(&self) {
94 self.context.reset_bitmap()
95 }
96
97 fn get_image_data(&self) -> Option<Snapshot> {
98 self.context.get_image_data()
99 }
100
101 fn origin_is_clean(&self) -> bool {
102 self.context.origin_is_clean()
103 }
104
105 fn mark_as_dirty(&self) {}
106}
107
108impl OffscreenCanvasRenderingContext2DMethods<crate::DomTypeHolder>
109 for OffscreenCanvasRenderingContext2D
110{
111 fn Canvas(&self) -> DomRoot<OffscreenCanvas> {
113 match self.context.canvas() {
114 Some(RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas)) => canvas,
115 _ => panic!("Should not be called from onscreen canvas"),
116 }
117 }
118
119 fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) {
121 self.context.FillRect(x, y, width, height);
122 }
123
124 fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) {
126 self.context.ClearRect(x, y, width, height);
127 }
128
129 fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) {
131 self.context.StrokeRect(x, y, width, height);
132 }
133
134 fn ShadowOffsetX(&self) -> f64 {
136 self.context.ShadowOffsetX()
137 }
138
139 fn SetShadowOffsetX(&self, value: f64) {
141 self.context.SetShadowOffsetX(value)
142 }
143
144 fn ShadowOffsetY(&self) -> f64 {
146 self.context.ShadowOffsetY()
147 }
148
149 fn SetShadowOffsetY(&self, value: f64) {
151 self.context.SetShadowOffsetY(value)
152 }
153
154 fn ShadowBlur(&self) -> f64 {
156 self.context.ShadowBlur()
157 }
158
159 fn SetShadowBlur(&self, value: f64) {
161 self.context.SetShadowBlur(value)
162 }
163
164 fn ShadowColor(&self) -> DOMString {
166 self.context.ShadowColor()
167 }
168
169 fn SetShadowColor(&self, value: DOMString) {
171 self.context.SetShadowColor(value)
172 }
173
174 fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
176 self.context.StrokeStyle()
177 }
178
179 fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
181 self.context.SetStrokeStyle(value)
182 }
183
184 fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
186 self.context.FillStyle()
187 }
188
189 fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
191 self.context.SetFillStyle(value)
192 }
193
194 fn CreateLinearGradient(
196 &self,
197 cx: &mut JSContext,
198 x0: Finite<f64>,
199 y0: Finite<f64>,
200 x1: Finite<f64>,
201 y1: Finite<f64>,
202 ) -> DomRoot<CanvasGradient> {
203 self.context.CreateLinearGradient(cx, x0, y0, x1, y1)
204 }
205
206 fn CreateRadialGradient(
208 &self,
209 cx: &mut JSContext,
210 x0: Finite<f64>,
211 y0: Finite<f64>,
212 r0: Finite<f64>,
213 x1: Finite<f64>,
214 y1: Finite<f64>,
215 r1: Finite<f64>,
216 ) -> Fallible<DomRoot<CanvasGradient>> {
217 self.context
218 .CreateRadialGradient(cx, x0, y0, r0, x1, y1, r1)
219 }
220
221 fn CreatePattern(
223 &self,
224 cx: &mut JSContext,
225 image: CanvasImageSource,
226 repetition: DOMString,
227 ) -> Fallible<Option<DomRoot<CanvasPattern>>> {
228 self.context.CreatePattern(cx, image, repetition)
229 }
230
231 fn Save(&self) {
233 self.context.Save()
234 }
235
236 fn Restore(&self) {
238 self.context.Restore()
239 }
240
241 fn Reset(&self) {
243 self.context.Reset()
244 }
245
246 fn GlobalAlpha(&self) -> f64 {
248 self.context.GlobalAlpha()
249 }
250
251 fn SetGlobalAlpha(&self, alpha: f64) {
253 self.context.SetGlobalAlpha(alpha)
254 }
255
256 fn GlobalCompositeOperation(&self) -> DOMString {
258 self.context.GlobalCompositeOperation()
259 }
260
261 fn SetGlobalCompositeOperation(&self, op_str: DOMString) {
263 self.context.SetGlobalCompositeOperation(op_str)
264 }
265
266 fn ImageSmoothingEnabled(&self) -> bool {
268 self.context.ImageSmoothingEnabled()
269 }
270
271 fn SetImageSmoothingEnabled(&self, value: bool) {
273 self.context.SetImageSmoothingEnabled(value)
274 }
275
276 fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) {
278 self.context.FillText(text, x, y, max_width)
279 }
280
281 fn StrokeText(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) {
283 self.context.StrokeText(text, x, y, max_width)
284 }
285
286 fn MeasureText(&self, cx: &mut JSContext, text: DOMString) -> DomRoot<TextMetrics> {
288 self.context.MeasureText(cx, text)
289 }
290
291 fn Font(&self) -> DOMString {
293 self.context.Font()
294 }
295
296 fn SetFont(&self, value: DOMString) {
298 self.context.SetFont(value)
299 }
300
301 fn TextAlign(&self) -> CanvasTextAlign {
303 self.context.TextAlign()
304 }
305
306 fn SetTextAlign(&self, value: CanvasTextAlign) {
308 self.context.SetTextAlign(value)
309 }
310
311 fn TextBaseline(&self) -> CanvasTextBaseline {
313 self.context.TextBaseline()
314 }
315
316 fn SetTextBaseline(&self, value: CanvasTextBaseline) {
318 self.context.SetTextBaseline(value)
319 }
320
321 fn Direction(&self) -> CanvasDirection {
323 self.context.Direction()
324 }
325
326 fn SetDirection(&self, value: CanvasDirection) {
328 self.context.SetDirection(value)
329 }
330
331 fn LineWidth(&self) -> f64 {
333 self.context.LineWidth()
334 }
335
336 fn SetLineWidth(&self, width: f64) {
338 self.context.SetLineWidth(width)
339 }
340
341 fn LineCap(&self) -> CanvasLineCap {
343 self.context.LineCap()
344 }
345
346 fn SetLineCap(&self, cap: CanvasLineCap) {
348 self.context.SetLineCap(cap)
349 }
350
351 fn LineJoin(&self) -> CanvasLineJoin {
353 self.context.LineJoin()
354 }
355
356 fn SetLineJoin(&self, join: CanvasLineJoin) {
358 self.context.SetLineJoin(join)
359 }
360
361 fn MiterLimit(&self) -> f64 {
363 self.context.MiterLimit()
364 }
365
366 fn SetMiterLimit(&self, limit: f64) {
368 self.context.SetMiterLimit(limit)
369 }
370
371 fn SetLineDash(&self, segments: Vec<f64>) {
373 self.context.SetLineDash(segments)
374 }
375
376 fn GetLineDash(&self) -> Vec<f64> {
378 self.context.GetLineDash()
379 }
380
381 fn LineDashOffset(&self) -> f64 {
383 self.context.LineDashOffset()
384 }
385
386 fn SetLineDashOffset(&self, offset: f64) {
388 self.context.SetLineDashOffset(offset)
389 }
390
391 fn CreateImageData(
393 &self,
394 cx: &mut JSContext,
395 sw: i32,
396 sh: i32,
397 ) -> Fallible<DomRoot<ImageData>> {
398 self.context.CreateImageData(sw, sh, CanGc::from_cx(cx))
399 }
400
401 fn CreateImageData_(
403 &self,
404 cx: &mut JSContext,
405 imagedata: &ImageData,
406 ) -> Fallible<DomRoot<ImageData>> {
407 self.context.CreateImageData_(imagedata, CanGc::from_cx(cx))
408 }
409
410 fn GetImageData(
412 &self,
413 cx: &mut JSContext,
414 sx: i32,
415 sy: i32,
416 sw: i32,
417 sh: i32,
418 ) -> Fallible<DomRoot<ImageData>> {
419 self.context
420 .GetImageData(sx, sy, sw, sh, CanGc::from_cx(cx))
421 }
422
423 fn PutImageData(&self, imagedata: &ImageData, dx: i32, dy: i32) {
425 self.context.PutImageData(imagedata, dx, dy)
426 }
427
428 fn PutImageData_(
430 &self,
431 imagedata: &ImageData,
432 dx: i32,
433 dy: i32,
434 dirty_x: i32,
435 dirty_y: i32,
436 dirty_width: i32,
437 dirty_height: i32,
438 ) {
439 self.context.PutImageData_(
440 imagedata,
441 dx,
442 dy,
443 dirty_x,
444 dirty_y,
445 dirty_width,
446 dirty_height,
447 )
448 }
449
450 fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult {
452 self.context.DrawImage(image, dx, dy)
453 }
454
455 fn DrawImage_(
457 &self,
458 image: CanvasImageSource,
459 dx: f64,
460 dy: f64,
461 dw: f64,
462 dh: f64,
463 ) -> ErrorResult {
464 self.context.DrawImage_(image, dx, dy, dw, dh)
465 }
466
467 fn DrawImage__(
469 &self,
470 image: CanvasImageSource,
471 sx: f64,
472 sy: f64,
473 sw: f64,
474 sh: f64,
475 dx: f64,
476 dy: f64,
477 dw: f64,
478 dh: f64,
479 ) -> ErrorResult {
480 self.context
481 .DrawImage__(image, sx, sy, sw, sh, dx, dy, dw, dh)
482 }
483
484 fn BeginPath(&self) {
486 self.context.BeginPath()
487 }
488
489 fn Fill(&self, fill_rule: CanvasFillRule) {
491 self.context.Fill(fill_rule)
492 }
493
494 fn Fill_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
496 self.context.Fill_(path, fill_rule)
497 }
498
499 fn Stroke(&self) {
501 self.context.Stroke()
502 }
503
504 fn Stroke_(&self, path: &Path2D) {
506 self.context.Stroke_(path)
507 }
508
509 fn Clip(&self, fill_rule: CanvasFillRule) {
511 self.context.Clip(fill_rule)
512 }
513
514 fn Clip_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
516 self.context.Clip_(path, fill_rule)
517 }
518
519 fn IsPointInPath(&self, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
521 self.context.IsPointInPath(x, y, fill_rule)
522 }
523
524 fn IsPointInPath_(&self, path: &Path2D, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
526 self.context.IsPointInPath_(path, x, y, fill_rule)
527 }
528
529 fn Scale(&self, x: f64, y: f64) {
531 self.context.Scale(x, y)
532 }
533
534 fn Rotate(&self, angle: f64) {
536 self.context.Rotate(angle)
537 }
538
539 fn Translate(&self, x: f64, y: f64) {
541 self.context.Translate(x, y)
542 }
543
544 fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
546 self.context.Transform(a, b, c, d, e, f)
547 }
548
549 fn GetTransform(&self, cx: &mut JSContext) -> DomRoot<DOMMatrix> {
551 self.context.GetTransform(cx)
552 }
553
554 fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) -> ErrorResult {
556 self.context.SetTransform(a, b, c, d, e, f)
557 }
558
559 fn SetTransform_(&self, transform: &DOMMatrix2DInit) -> ErrorResult {
561 self.context.SetTransform_(transform)
562 }
563
564 fn ResetTransform(&self) {
566 self.context.ResetTransform()
567 }
568
569 fn ClosePath(&self) {
571 self.context.ClosePath()
572 }
573
574 fn MoveTo(&self, x: f64, y: f64) {
576 self.context.MoveTo(x, y)
577 }
578
579 fn LineTo(&self, x: f64, y: f64) {
581 self.context.LineTo(x, y)
582 }
583
584 fn Rect(&self, x: f64, y: f64, width: f64, height: f64) {
586 self.context.Rect(x, y, width, height)
587 }
588
589 fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) {
591 self.context.QuadraticCurveTo(cpx, cpy, x, y)
592 }
593
594 fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) {
596 self.context.BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
597 }
598
599 fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> ErrorResult {
601 self.context.Arc(x, y, r, start, end, ccw)
602 }
603
604 fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult {
606 self.context.ArcTo(cp1x, cp1y, cp2x, cp2y, r)
607 }
608
609 fn Ellipse(
611 &self,
612 x: f64,
613 y: f64,
614 rx: f64,
615 ry: f64,
616 rotation: f64,
617 start: f64,
618 end: f64,
619 ccw: bool,
620 ) -> ErrorResult {
621 self.context
622 .Ellipse(x, y, rx, ry, rotation, start, end, ccw)
623 }
624}