rive_rs/shapes/paint/
shape_paint.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::cell::RefCell;
6use std::rc::Rc;
7
8use crate::container_component::ContainerComponent;
9use crate::core::{Core, CoreContext, Object, ObjectRef, OnAdded, Property};
10use crate::math::Mat;
11use crate::option_cell::OptionCell;
12use crate::shapes::paint::shape_paint_mutator::ShapePaintMutator;
13use crate::shapes::paint::{BlendMode, Fill, Stroke};
14use crate::shapes::{CommandPath, PathSpace, ShapePaintContainer};
15use crate::status_code::StatusCode;
16use crate::{Component, RenderPaint, Renderer};
17
18#[derive(Debug)]
19pub struct ShapePaint {
20    container_component: ContainerComponent,
21    is_visible: Property<bool>,
22    render_paint: OptionCell<Rc<RefCell<RenderPaint>>>,
23    shape_paint_mutator: OptionCell<Object<ShapePaintMutator>>,
24}
25
26impl ObjectRef<'_, ShapePaint> {
27    pub fn is_visible(&self) -> bool {
28        self.is_visible.get()
29    }
30
31    pub fn set_is_visible(&self, is_visible: bool) {
32        self.is_visible.set(is_visible);
33    }
34}
35
36impl ObjectRef<'_, ShapePaint> {
37    pub fn init_render_paint(
38        &self,
39        mutator: Object<ShapePaintMutator>,
40    ) -> Option<Rc<RefCell<RenderPaint>>> {
41        self.shape_paint_mutator.set(Some(mutator));
42        self.render_paint.set(Some(Rc::new(RefCell::new(RenderPaint::default()))));
43
44        self.render_paint.get()
45    }
46
47    pub fn path_space(&self) -> PathSpace {
48        if let Some(fill) = self.try_cast::<Fill>() {
49            return fill.path_space();
50        }
51
52        if let Some(stroke) = self.try_cast::<Stroke>() {
53            return stroke.path_space();
54        }
55
56        unreachable!()
57    }
58
59    pub fn render_paint(&self) -> Rc<RefCell<RenderPaint>> {
60        self.render_paint.get().expect("init_render_paint has not been called yet")
61    }
62
63    pub fn set_blend_mode(&self, blend_mode: BlendMode) {
64        self.render_paint().borrow_mut().blend_mode = blend_mode;
65    }
66
67    pub fn set_render_opacity(&self, render_opacity: f32) {
68        self.shape_paint_mutator
69            .get()
70            .expect("init_paint_mutator has not been called yet")
71            .as_ref()
72            .set_render_opacity(render_opacity);
73    }
74
75    pub fn set_is_clipped(&self, is_clipped: bool) {
76        self.render_paint().borrow_mut().is_clipped = is_clipped;
77    }
78
79    pub fn draw(&self, renderer: &mut impl Renderer, path: &CommandPath, transform: Mat) {
80        if let Some(fill) = self.try_cast::<Fill>() {
81            return fill.draw(renderer, path, transform);
82        }
83
84        if let Some(stroke) = self.try_cast::<Stroke>() {
85            return stroke.draw(renderer, path, transform);
86        }
87
88        unreachable!()
89    }
90}
91
92impl Core for ShapePaint {
93    parent_types![(container_component, ContainerComponent)];
94
95    properties![(41, is_visible, set_is_visible), container_component];
96}
97
98impl OnAdded for ObjectRef<'_, ShapePaint> {
99    on_added!([on_added_dirty, import], ContainerComponent);
100
101    fn on_added_clean(&self, _context: &dyn CoreContext) -> StatusCode {
102        let container = self.cast::<Component>().parent().and_then(|parent| {
103            let object: Object = parent.into();
104            object.try_into().ok()
105        });
106
107        if let Some(container) = container {
108            let container: Object<ShapePaintContainer> = container;
109            container.as_ref().push_paint(self.as_object());
110
111            StatusCode::Ok
112        } else {
113            StatusCode::MissingObject
114        }
115    }
116}
117
118impl Default for ShapePaint {
119    fn default() -> Self {
120        Self {
121            container_component: ContainerComponent::default(),
122            is_visible: Property::new(true),
123            render_paint: OptionCell::new(),
124            shape_paint_mutator: OptionCell::new(),
125        }
126    }
127}