ferroui_base/rendering/composition/server/
server_composition_view_box.rs1use super::{
5 impl_server_render_resource, surface_brush_content_rect, IAnimatedServerObject, IServerObject,
6 IServerRenderResource, ServerCompositor, ServerRenderResource,
7};
8use crate::rendering::composition::generated::{ServerCompositionViewBoxHooks, ServerCompositionViewBoxProps};
9use crate::rendering::composition::transport::BatchStreamReader;
10use crate::rendering::composition::CompositionStretch;
11use crate::{Matrix, Rect, Size, Vector};
12use std::any::{Any, TypeId};
13use std::rc::{Rc, Weak};
14use std::time::Duration;
15
16#[derive(Clone, Copy, Debug, PartialEq)]
18pub struct ViewBoxMapping {
19 pub transform: Matrix,
22 pub clip: Rect,
25}
26
27pub fn view_box_mapping(
32 offset: Vector,
33 size: Vector,
34 area: Rect,
35 stretch: CompositionStretch,
36 horizontal_ratio: f64,
37 vertical_ratio: f64,
38) -> Option<ViewBoxMapping> {
39 let content = surface_brush_content_rect(Size::new(size.x, size.y), area, stretch, horizontal_ratio, vertical_ratio)?;
40 let transform = Matrix::create_translation(-offset.x, -offset.y)
41 * Matrix::create_scale(content.width / size.x, content.height / size.y)
42 * Matrix::create_translation(content.x, content.y);
43 Some(ViewBoxMapping { transform, clip: content.intersect(area) })
44}
45
46pub struct ServerCompositionViewBox {
49 base: ServerRenderResource,
50 props: ServerCompositionViewBoxProps,
51}
52
53impl ServerCompositionViewBox {
54 pub fn new(compositor: &Rc<ServerCompositor>) -> Rc<ServerCompositionViewBox> {
57 let view_box = Rc::new_cyclic(|this: &Weak<ServerCompositionViewBox>| ServerCompositionViewBox {
58 base: ServerRenderResource::new(
59 compositor,
60 this.clone() as Weak<dyn IAnimatedServerObject>,
61 this.clone() as Weak<dyn IServerRenderResource>,
62 ),
63 props: ServerCompositionViewBoxProps::new(),
64 });
65 view_box.base.object().activate();
66 view_box
67 }
68
69 pub fn props(&self) -> &ServerCompositionViewBoxProps {
71 &self.props
72 }
73
74 pub fn is_disposed(&self) -> bool {
75 self.base.is_disposed()
76 }
77
78 pub fn mapping(&self, size: Vector) -> Option<ViewBoxMapping> {
82 view_box_mapping(
83 self.props.offset(),
84 self.props.size(),
85 Rect::new(0.0, 0.0, size.x, size.y),
86 self.props.stretch(),
87 self.props.horizontal_alignment_ratio() as f64,
88 self.props.vertical_alignment_ratio() as f64,
89 )
90 }
91
92 pub fn mapping_of(object: &Rc<dyn IServerObject>, size: Vector) -> Option<ViewBoxMapping> {
95 object.as_any().downcast_ref::<ServerCompositionViewBox>()?.mapping(size)
96 }
97}
98
99impl_server_render_resource!(
100 ServerCompositionViewBox,
101 base,
102 composition_property: ServerCompositionViewBoxProps::get_composition_property
103);
104
105impl ServerCompositionViewBoxHooks for ServerCompositionViewBox {}
106
107impl IServerObject for ServerCompositionViewBox {
108 fn deserialize_changes_core(&self, reader: &mut BatchStreamReader<'_>, committed_at: Duration) {
109 self.props.deserialize_changes_core(self, reader, committed_at);
110 }
111
112 fn values_invalidated(&self) {
113 self.base.core().invalidated(self);
114 }
115
116 fn dispose(&self) {
117 self.base.core().dispose();
118 }
119
120 fn as_render_resource(self: Rc<Self>) -> Option<Rc<dyn IServerRenderResource>> {
121 Some(self)
122 }
123
124 fn as_animated(self: Rc<Self>) -> Option<Rc<dyn IAnimatedServerObject>> {
125 Some(self)
126 }
127
128 fn get_props(&self, type_id: TypeId) -> Option<&dyn Any> {
129 self.props.find_props(type_id)
130 }
131
132 fn as_any(&self) -> &dyn Any {
133 self
134 }
135
136 fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any> {
137 self
138 }
139}