script/dom/canvas/2d/
canvasrenderingcontext2d.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use base::Epoch;
6use canvas_traits::canvas::{Canvas2dMsg, CanvasId};
7use dom_struct::dom_struct;
8use euclid::default::Size2D;
9use ipc_channel::ipc;
10use pixels::Snapshot;
11use script_bindings::inheritance::Castable;
12use servo_url::ServoUrl;
13use webrender_api::ImageKey;
14
15use super::canvas_state::CanvasState;
16use crate::canvas_context::{
17    CanvasContext, CanvasHelpers, HTMLCanvasElementOrOffscreenCanvas,
18    LayoutCanvasRenderingContextHelpers,
19};
20use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{
21    CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin,
22    CanvasRenderingContext2DMethods, CanvasTextAlign, CanvasTextBaseline,
23};
24use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit;
25use crate::dom::bindings::codegen::UnionTypes::{
26    HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas,
27    StringOrCanvasGradientOrCanvasPattern,
28};
29use crate::dom::bindings::error::{ErrorResult, Fallible};
30use crate::dom::bindings::num::Finite;
31use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
32use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom};
33use crate::dom::bindings::str::DOMString;
34use crate::dom::canvasgradient::CanvasGradient;
35use crate::dom::canvaspattern::CanvasPattern;
36use crate::dom::dommatrix::DOMMatrix;
37use crate::dom::globalscope::GlobalScope;
38use crate::dom::html::htmlcanvaselement::HTMLCanvasElement;
39use crate::dom::imagedata::ImageData;
40use crate::dom::node::{Node, NodeDamage, NodeTraits};
41use crate::dom::path2d::Path2D;
42use crate::dom::textmetrics::TextMetrics;
43use crate::script_runtime::CanGc;
44
45// https://html.spec.whatwg.org/multipage/#canvasrenderingcontext2d
46#[dom_struct]
47pub(crate) struct CanvasRenderingContext2D {
48    reflector_: Reflector,
49    canvas: HTMLCanvasElementOrOffscreenCanvas,
50    canvas_state: CanvasState,
51}
52
53impl CanvasRenderingContext2D {
54    #[cfg_attr(crown, allow(crown::unrooted_must_root))]
55    pub(crate) fn new_inherited(
56        global: &GlobalScope,
57        canvas: HTMLCanvasElementOrOffscreenCanvas,
58        size: Size2D<u32>,
59    ) -> Option<CanvasRenderingContext2D> {
60        let canvas_state =
61            CanvasState::new(global, Size2D::new(size.width as u64, size.height as u64))?;
62        Some(CanvasRenderingContext2D {
63            reflector_: Reflector::new(),
64            canvas,
65            canvas_state,
66        })
67    }
68
69    pub(crate) fn new(
70        global: &GlobalScope,
71        canvas: &HTMLCanvasElement,
72        size: Size2D<u32>,
73        can_gc: CanGc,
74    ) -> Option<DomRoot<CanvasRenderingContext2D>> {
75        CanvasRenderingContext2D::new_inherited(
76            global,
77            HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(Dom::from_ref(canvas)),
78            size,
79        )
80        .map(|context| reflect_dom_object(Box::new(context), global, can_gc))
81    }
82
83    // https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state
84    fn reset_to_initial_state(&self) {
85        self.canvas_state.reset_to_initial_state();
86    }
87
88    /// <https://html.spec.whatwg.org/multipage/#concept-canvas-set-bitmap-dimensions>
89    pub(crate) fn set_canvas_bitmap_dimensions(&self, size: Size2D<u64>) {
90        self.canvas_state.set_bitmap_dimensions(size);
91    }
92
93    pub(crate) fn take_missing_image_urls(&self) -> Vec<ServoUrl> {
94        std::mem::take(&mut self.canvas_state.get_missing_image_urls().borrow_mut())
95    }
96
97    pub(crate) fn get_canvas_id(&self) -> CanvasId {
98        self.canvas_state.get_canvas_id()
99    }
100
101    pub(crate) fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) {
102        self.canvas_state.send_canvas_2d_msg(msg)
103    }
104}
105
106impl LayoutCanvasRenderingContextHelpers for LayoutDom<'_, CanvasRenderingContext2D> {
107    fn canvas_data_source(self) -> Option<ImageKey> {
108        let canvas_state = &self.unsafe_get().canvas_state;
109
110        if canvas_state.is_paintable() {
111            Some(canvas_state.image_key())
112        } else {
113            None
114        }
115    }
116}
117
118impl CanvasContext for CanvasRenderingContext2D {
119    type ID = CanvasId;
120
121    fn context_id(&self) -> Self::ID {
122        self.canvas_state.get_canvas_id()
123    }
124
125    fn canvas(&self) -> Option<RootedHTMLCanvasElementOrOffscreenCanvas> {
126        Some(RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas))
127    }
128
129    fn update_rendering(&self, canvas_epoch: Epoch) -> bool {
130        if !self.onscreen() {
131            return false;
132        }
133        self.canvas_state.update_rendering(Some(canvas_epoch))
134    }
135
136    fn resize(&self) {
137        self.set_canvas_bitmap_dimensions(self.size().cast())
138    }
139
140    fn reset_bitmap(&self) {
141        self.canvas_state.reset_bitmap()
142    }
143
144    fn get_image_data(&self) -> Option<Snapshot> {
145        if !self.canvas_state.is_paintable() {
146            return None;
147        }
148
149        let (sender, receiver) = ipc::channel().unwrap();
150        self.canvas_state
151            .send_canvas_2d_msg(Canvas2dMsg::GetImageData(None, sender));
152        Some(receiver.recv().unwrap().to_owned())
153    }
154
155    fn origin_is_clean(&self) -> bool {
156        self.canvas_state.origin_is_clean()
157    }
158
159    fn mark_as_dirty(&self) {
160        if let Some(canvas) = self.canvas.canvas() {
161            canvas.upcast::<Node>().dirty(NodeDamage::Other);
162            canvas.owner_document().add_dirty_2d_canvas(self);
163        }
164    }
165
166    fn image_key(&self) -> Option<ImageKey> {
167        Some(self.canvas_state.image_key())
168    }
169}
170
171// We add a guard to each of methods by the spec:
172// http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/
173//
174// > Except where otherwise specified, for the 2D context interface,
175// > any method call with a numeric argument whose value is infinite or a NaN value must be ignored.
176//
177//  Restricted values are guarded in glue code. Therefore we need not add a guard.
178//
179// FIXME: this behavior should might be generated by some annotattions to idl.
180impl CanvasRenderingContext2DMethods<crate::DomTypeHolder> for CanvasRenderingContext2D {
181    // https://html.spec.whatwg.org/multipage/#dom-context-2d-canvas
182    fn Canvas(&self) -> DomRoot<HTMLCanvasElement> {
183        match &self.canvas {
184            HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => canvas.as_rooted(),
185            _ => panic!("Should not be called from offscreen canvas"),
186        }
187    }
188
189    // https://html.spec.whatwg.org/multipage/#dom-context-2d-save
190    fn Save(&self) {
191        self.canvas_state.save()
192    }
193
194    #[cfg_attr(crown, allow(crown::unrooted_must_root))]
195    // https://html.spec.whatwg.org/multipage/#dom-context-2d-restore
196    fn Restore(&self) {
197        self.canvas_state.restore()
198    }
199
200    /// <https://html.spec.whatwg.org/multipage/#dom-context-2d-reset>
201    fn Reset(&self) {
202        self.canvas_state.reset()
203    }
204
205    // https://html.spec.whatwg.org/multipage/#dom-context-2d-scale
206    fn Scale(&self, x: f64, y: f64) {
207        self.canvas_state.scale(x, y)
208    }
209
210    // https://html.spec.whatwg.org/multipage/#dom-context-2d-rotate
211    fn Rotate(&self, angle: f64) {
212        self.canvas_state.rotate(angle)
213    }
214
215    // https://html.spec.whatwg.org/multipage/#dom-context-2d-translate
216    fn Translate(&self, x: f64, y: f64) {
217        self.canvas_state.translate(x, y)
218    }
219
220    // https://html.spec.whatwg.org/multipage/#dom-context-2d-transform
221    fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
222        self.canvas_state.transform(a, b, c, d, e, f)
223    }
224
225    // https://html.spec.whatwg.org/multipage/#dom-context-2d-gettransform
226    fn GetTransform(&self, can_gc: CanGc) -> DomRoot<DOMMatrix> {
227        self.canvas_state.get_transform(&self.global(), can_gc)
228    }
229
230    /// <https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform>
231    fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) -> ErrorResult {
232        self.canvas_state.set_transform(a, b, c, d, e, f);
233        Ok(())
234    }
235
236    /// <https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform-matrix>
237    fn SetTransform_(&self, transform: &DOMMatrix2DInit) -> ErrorResult {
238        self.canvas_state.set_transform_(transform)
239    }
240
241    // https://html.spec.whatwg.org/multipage/#dom-context-2d-resettransform
242    fn ResetTransform(&self) {
243        self.canvas_state.reset_transform()
244    }
245
246    // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha
247    fn GlobalAlpha(&self) -> f64 {
248        self.canvas_state.global_alpha()
249    }
250
251    // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha
252    fn SetGlobalAlpha(&self, alpha: f64) {
253        self.canvas_state.set_global_alpha(alpha)
254    }
255
256    // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation
257    fn GlobalCompositeOperation(&self) -> DOMString {
258        self.canvas_state.global_composite_operation()
259    }
260
261    // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation
262    fn SetGlobalCompositeOperation(&self, op_str: DOMString) {
263        self.canvas_state.set_global_composite_operation(op_str)
264    }
265
266    // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect
267    fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) {
268        self.canvas_state.fill_rect(x, y, width, height);
269        self.mark_as_dirty();
270    }
271
272    // https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect
273    fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) {
274        self.canvas_state.clear_rect(x, y, width, height);
275        self.mark_as_dirty();
276    }
277
278    // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect
279    fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) {
280        self.canvas_state.stroke_rect(x, y, width, height);
281        self.mark_as_dirty();
282    }
283
284    // https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath
285    fn BeginPath(&self) {
286        self.canvas_state.begin_path()
287    }
288
289    // https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath
290    fn ClosePath(&self) {
291        self.canvas_state.close_path()
292    }
293
294    // https://html.spec.whatwg.org/multipage/#dom-context-2d-fill
295    fn Fill(&self, fill_rule: CanvasFillRule) {
296        self.canvas_state.fill(fill_rule);
297        self.mark_as_dirty();
298    }
299
300    // https://html.spec.whatwg.org/multipage/#dom-context-2d-fill
301    fn Fill_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
302        self.canvas_state.fill_(path.segments(), fill_rule);
303        self.mark_as_dirty();
304    }
305
306    // https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke
307    fn Stroke(&self) {
308        self.canvas_state.stroke();
309        self.mark_as_dirty();
310    }
311
312    // https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke
313    fn Stroke_(&self, path: &Path2D) {
314        self.canvas_state.stroke_(path.segments());
315        self.mark_as_dirty();
316    }
317
318    // https://html.spec.whatwg.org/multipage/#dom-context-2d-clip
319    fn Clip(&self, fill_rule: CanvasFillRule) {
320        self.canvas_state.clip(fill_rule)
321    }
322
323    // https://html.spec.whatwg.org/multipage/#dom-context-2d-clip
324    fn Clip_(&self, path: &Path2D, fill_rule: CanvasFillRule) {
325        self.canvas_state.clip_(path.segments(), fill_rule)
326    }
327
328    // https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath
329    fn IsPointInPath(&self, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
330        self.canvas_state
331            .is_point_in_path(&self.global(), x, y, fill_rule)
332    }
333
334    // https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath
335    fn IsPointInPath_(&self, path: &Path2D, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool {
336        self.canvas_state
337            .is_point_in_path_(&self.global(), path.segments(), x, y, fill_rule)
338    }
339
340    // https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext
341    fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) {
342        self.canvas_state.fill_text(
343            &self.global(),
344            self.canvas.canvas().as_deref(),
345            text,
346            x,
347            y,
348            max_width,
349        );
350        self.mark_as_dirty();
351    }
352
353    // https://html.spec.whatwg.org/multipage/#textmetrics
354    fn MeasureText(&self, text: DOMString, can_gc: CanGc) -> DomRoot<TextMetrics> {
355        self.canvas_state.measure_text(
356            &self.global(),
357            self.canvas.canvas().as_deref(),
358            text,
359            can_gc,
360        )
361    }
362
363    // https://html.spec.whatwg.org/multipage/#dom-context-2d-font
364    fn Font(&self) -> DOMString {
365        self.canvas_state.font()
366    }
367
368    // https://html.spec.whatwg.org/multipage/#dom-context-2d-font
369    fn SetFont(&self, value: DOMString) {
370        self.canvas_state
371            .set_font(self.canvas.canvas().as_deref(), value)
372    }
373
374    // https://html.spec.whatwg.org/multipage/#dom-context-2d-textalign
375    fn TextAlign(&self) -> CanvasTextAlign {
376        self.canvas_state.text_align()
377    }
378
379    // https://html.spec.whatwg.org/multipage/#dom-context-2d-textalign
380    fn SetTextAlign(&self, value: CanvasTextAlign) {
381        self.canvas_state.set_text_align(value)
382    }
383
384    // https://html.spec.whatwg.org/multipage/#dom-context-2d-textbaseline
385    fn TextBaseline(&self) -> CanvasTextBaseline {
386        self.canvas_state.text_baseline()
387    }
388
389    // https://html.spec.whatwg.org/multipage/#dom-context-2d-textbaseline
390    fn SetTextBaseline(&self, value: CanvasTextBaseline) {
391        self.canvas_state.set_text_baseline(value)
392    }
393
394    // https://html.spec.whatwg.org/multipage/#dom-context-2d-direction
395    fn Direction(&self) -> CanvasDirection {
396        self.canvas_state.direction()
397    }
398
399    // https://html.spec.whatwg.org/multipage/#dom-context-2d-direction
400    fn SetDirection(&self, value: CanvasDirection) {
401        self.canvas_state.set_direction(value)
402    }
403
404    // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
405    fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult {
406        self.canvas_state
407            .draw_image(self.canvas.canvas().as_deref(), image, dx, dy)
408    }
409
410    // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
411    fn DrawImage_(
412        &self,
413        image: CanvasImageSource,
414        dx: f64,
415        dy: f64,
416        dw: f64,
417        dh: f64,
418    ) -> ErrorResult {
419        self.canvas_state
420            .draw_image_(self.canvas.canvas().as_deref(), image, dx, dy, dw, dh)
421    }
422
423    // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
424    fn DrawImage__(
425        &self,
426        image: CanvasImageSource,
427        sx: f64,
428        sy: f64,
429        sw: f64,
430        sh: f64,
431        dx: f64,
432        dy: f64,
433        dw: f64,
434        dh: f64,
435    ) -> ErrorResult {
436        self.canvas_state.draw_image__(
437            self.canvas.canvas().as_deref(),
438            image,
439            sx,
440            sy,
441            sw,
442            sh,
443            dx,
444            dy,
445            dw,
446            dh,
447        )
448    }
449
450    // https://html.spec.whatwg.org/multipage/#dom-context-2d-moveto
451    fn MoveTo(&self, x: f64, y: f64) {
452        self.canvas_state.move_to(x, y)
453    }
454
455    // https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto
456    fn LineTo(&self, x: f64, y: f64) {
457        self.canvas_state.line_to(x, y)
458    }
459
460    // https://html.spec.whatwg.org/multipage/#dom-context-2d-rect
461    fn Rect(&self, x: f64, y: f64, width: f64, height: f64) {
462        self.canvas_state.rect(x, y, width, height)
463    }
464
465    // https://html.spec.whatwg.org/multipage/#dom-context-2d-quadraticcurveto
466    fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) {
467        self.canvas_state.quadratic_curve_to(cpx, cpy, x, y)
468    }
469
470    // https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto
471    fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) {
472        self.canvas_state
473            .bezier_curve_to(cp1x, cp1y, cp2x, cp2y, x, y)
474    }
475
476    // https://html.spec.whatwg.org/multipage/#dom-context-2d-arc
477    fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> ErrorResult {
478        self.canvas_state.arc(x, y, r, start, end, ccw)
479    }
480
481    // https://html.spec.whatwg.org/multipage/#dom-context-2d-arcto
482    fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult {
483        self.canvas_state.arc_to(cp1x, cp1y, cp2x, cp2y, r)
484    }
485
486    // https://html.spec.whatwg.org/multipage/#dom-context-2d-ellipse
487    fn Ellipse(
488        &self,
489        x: f64,
490        y: f64,
491        rx: f64,
492        ry: f64,
493        rotation: f64,
494        start: f64,
495        end: f64,
496        ccw: bool,
497    ) -> ErrorResult {
498        self.canvas_state
499            .ellipse(x, y, rx, ry, rotation, start, end, ccw)
500    }
501
502    // https://html.spec.whatwg.org/multipage/#dom-context-2d-imagesmoothingenabled
503    fn ImageSmoothingEnabled(&self) -> bool {
504        self.canvas_state.image_smoothing_enabled()
505    }
506
507    // https://html.spec.whatwg.org/multipage/#dom-context-2d-imagesmoothingenabled
508    fn SetImageSmoothingEnabled(&self, value: bool) {
509        self.canvas_state.set_image_smoothing_enabled(value)
510    }
511
512    // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle
513    fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
514        self.canvas_state.stroke_style()
515    }
516
517    // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle
518    fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
519        self.canvas_state
520            .set_stroke_style(self.canvas.canvas().as_deref(), value)
521    }
522
523    // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle
524    fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
525        self.canvas_state.fill_style()
526    }
527
528    // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle
529    fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
530        self.canvas_state
531            .set_fill_style(self.canvas.canvas().as_deref(), value)
532    }
533
534    // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata
535    fn CreateImageData(&self, sw: i32, sh: i32, can_gc: CanGc) -> Fallible<DomRoot<ImageData>> {
536        self.canvas_state
537            .create_image_data(&self.global(), sw, sh, can_gc)
538    }
539
540    // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata
541    fn CreateImageData_(
542        &self,
543        imagedata: &ImageData,
544        can_gc: CanGc,
545    ) -> Fallible<DomRoot<ImageData>> {
546        self.canvas_state
547            .create_image_data_(&self.global(), imagedata, can_gc)
548    }
549
550    // https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata
551    fn GetImageData(
552        &self,
553        sx: i32,
554        sy: i32,
555        sw: i32,
556        sh: i32,
557        can_gc: CanGc,
558    ) -> Fallible<DomRoot<ImageData>> {
559        self.canvas_state
560            .get_image_data(self.canvas.size(), &self.global(), sx, sy, sw, sh, can_gc)
561    }
562
563    // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
564    fn PutImageData(&self, imagedata: &ImageData, dx: i32, dy: i32) {
565        self.canvas_state
566            .put_image_data(self.canvas.size(), imagedata, dx, dy)
567    }
568
569    // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
570    #[allow(unsafe_code)]
571    fn PutImageData_(
572        &self,
573        imagedata: &ImageData,
574        dx: i32,
575        dy: i32,
576        dirty_x: i32,
577        dirty_y: i32,
578        dirty_width: i32,
579        dirty_height: i32,
580    ) {
581        self.canvas_state.put_image_data_(
582            self.canvas.size(),
583            imagedata,
584            dx,
585            dy,
586            dirty_x,
587            dirty_y,
588            dirty_width,
589            dirty_height,
590        );
591        self.mark_as_dirty();
592    }
593
594    // https://html.spec.whatwg.org/multipage/#dom-context-2d-createlineargradient
595    fn CreateLinearGradient(
596        &self,
597        x0: Finite<f64>,
598        y0: Finite<f64>,
599        x1: Finite<f64>,
600        y1: Finite<f64>,
601        can_gc: CanGc,
602    ) -> DomRoot<CanvasGradient> {
603        self.canvas_state
604            .create_linear_gradient(&self.global(), x0, y0, x1, y1, can_gc)
605    }
606
607    // https://html.spec.whatwg.org/multipage/#dom-context-2d-createradialgradient
608    fn CreateRadialGradient(
609        &self,
610        x0: Finite<f64>,
611        y0: Finite<f64>,
612        r0: Finite<f64>,
613        x1: Finite<f64>,
614        y1: Finite<f64>,
615        r1: Finite<f64>,
616        can_gc: CanGc,
617    ) -> Fallible<DomRoot<CanvasGradient>> {
618        self.canvas_state
619            .create_radial_gradient(&self.global(), x0, y0, r0, x1, y1, r1, can_gc)
620    }
621
622    // https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern
623    fn CreatePattern(
624        &self,
625        image: CanvasImageSource,
626        repetition: DOMString,
627        can_gc: CanGc,
628    ) -> Fallible<Option<DomRoot<CanvasPattern>>> {
629        self.canvas_state
630            .create_pattern(&self.global(), image, repetition, can_gc)
631    }
632
633    // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth
634    fn LineWidth(&self) -> f64 {
635        self.canvas_state.line_width()
636    }
637
638    // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth
639    fn SetLineWidth(&self, width: f64) {
640        self.canvas_state.set_line_width(width)
641    }
642
643    // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap
644    fn LineCap(&self) -> CanvasLineCap {
645        self.canvas_state.line_cap()
646    }
647
648    // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap
649    fn SetLineCap(&self, cap: CanvasLineCap) {
650        self.canvas_state.set_line_cap(cap)
651    }
652
653    // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin
654    fn LineJoin(&self) -> CanvasLineJoin {
655        self.canvas_state.line_join()
656    }
657
658    // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin
659    fn SetLineJoin(&self, join: CanvasLineJoin) {
660        self.canvas_state.set_line_join(join)
661    }
662
663    // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit
664    fn MiterLimit(&self) -> f64 {
665        self.canvas_state.miter_limit()
666    }
667
668    // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit
669    fn SetMiterLimit(&self, limit: f64) {
670        self.canvas_state.set_miter_limit(limit)
671    }
672
673    /// <https://html.spec.whatwg.org/multipage/#dom-context-2d-setlinedash>
674    fn SetLineDash(&self, segments: Vec<f64>) {
675        self.canvas_state.set_line_dash(segments);
676    }
677
678    /// <https://html.spec.whatwg.org/multipage/#dom-context-2d-getlinedash>
679    fn GetLineDash(&self) -> Vec<f64> {
680        self.canvas_state.line_dash()
681    }
682
683    /// <https://html.spec.whatwg.org/multipage/#dom-context-2d-linedashoffset>
684    fn LineDashOffset(&self) -> f64 {
685        self.canvas_state.line_dash_offset()
686    }
687
688    /// <https://html.spec.whatwg.org/multipage/#dom-context-2d-linedashoffset>
689    fn SetLineDashOffset(&self, offset: f64) {
690        self.canvas_state.set_line_dash_offset(offset);
691    }
692
693    // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx
694    fn ShadowOffsetX(&self) -> f64 {
695        self.canvas_state.shadow_offset_x()
696    }
697
698    // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx
699    fn SetShadowOffsetX(&self, value: f64) {
700        self.canvas_state.set_shadow_offset_x(value)
701    }
702
703    // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety
704    fn ShadowOffsetY(&self) -> f64 {
705        self.canvas_state.shadow_offset_y()
706    }
707
708    // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety
709    fn SetShadowOffsetY(&self, value: f64) {
710        self.canvas_state.set_shadow_offset_y(value)
711    }
712
713    // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur
714    fn ShadowBlur(&self) -> f64 {
715        self.canvas_state.shadow_blur()
716    }
717
718    // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur
719    fn SetShadowBlur(&self, value: f64) {
720        self.canvas_state.set_shadow_blur(value)
721    }
722
723    // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor
724    fn ShadowColor(&self) -> DOMString {
725        self.canvas_state.shadow_color()
726    }
727
728    // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor
729    fn SetShadowColor(&self, value: DOMString) {
730        self.canvas_state
731            .set_shadow_color(self.canvas.canvas().as_deref(), value)
732    }
733}