1use crate::color::Color;
6use crate::render::generic::forma::*;
7use crate::render::generic::{
8 self, Composition as _, Context as _, PathBuilder as _, Raster as _, RasterBuilder as _,
9};
10pub use crate::render::generic::{BlendMode, Fill, FillRule, Gradient, GradientType, Order, Style};
11use crate::{Point, ViewAssistantContext};
12use anyhow::Error;
13use display_utils::PixelFormat;
14use euclid::default::{Point2D, Rect, Size2D, Transform2D, Vector2D};
15use euclid::{point2, size2};
16use std::io::Read;
17use std::ops::Add;
18use std::{mem, u32};
19#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
21pub struct Image {
22 inner: ImageInner,
23}
24#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
25enum ImageInner {
26 Forma(FormaImage),
27}
28#[derive(Clone, Copy, Debug, PartialEq)]
30pub struct CopyRegion {
31 pub src_offset: Point2D<u32>,
33 pub dst_offset: Point2D<u32>,
35 pub extent: Size2D<u32>,
37}
38#[derive(Clone, Debug, Default, PartialEq)]
40pub struct RenderExt {
41 pub pre_clear: Option<PreClear>,
43 pub pre_copy: Option<PreCopy>,
45 pub post_copy: Option<PostCopy>,
47}
48#[derive(Clone, Debug, PartialEq)]
50pub struct PreClear {
51 pub color: Color,
53}
54#[derive(Clone, Debug, PartialEq)]
56pub struct PreCopy {
57 pub image: Image,
59 pub copy_region: CopyRegion,
61}
62#[derive(Clone, Debug, PartialEq)]
64pub struct PostCopy {
65 pub image: Image,
67 pub copy_region: CopyRegion,
69}
70#[derive(Debug)]
72pub struct Context {
73 pub inner: ContextInner,
74}
75#[derive(Debug)]
76pub enum ContextInner {
77 Forma(FormaContext),
78}
79impl Context {
80 pub fn pixel_format(&self) -> PixelFormat {
82 match &self.inner {
83 ContextInner::Forma(context) => context.pixel_format(),
84 }
85 }
86 pub fn path_builder(&self) -> Option<PathBuilder> {
88 match &self.inner {
89 ContextInner::Forma(context) => context
90 .path_builder()
91 .map(|path_builder| PathBuilder { inner: PathBuilderInner::Forma(path_builder) }),
92 }
93 }
94 pub fn raster_builder(&self) -> Option<RasterBuilder> {
96 match &self.inner {
97 ContextInner::Forma(context) => context.raster_builder().map(|raster_builder| {
98 RasterBuilder { inner: RasterBuilderInner::Forma(raster_builder) }
99 }),
100 }
101 }
102 pub fn new_image(&mut self, size: Size2D<u32>) -> Image {
104 match &mut self.inner {
105 ContextInner::Forma(context) => {
106 Image { inner: ImageInner::Forma(context.new_image(size)) }
107 }
108 }
109 }
110 pub fn new_image_from_png<R: Read>(
112 &mut self,
113 reader: &mut png::Reader<R>,
114 ) -> Result<Image, Error> {
115 Ok(Image {
116 inner: match &mut self.inner {
117 ContextInner::Forma(context) => {
118 ImageInner::Forma(context.new_image_from_png(reader)?)
119 }
120 },
121 })
122 }
123 pub fn get_image(&mut self, image_index: u32) -> Image {
125 match &mut self.inner {
126 ContextInner::Forma(render_context) => {
127 Image { inner: ImageInner::Forma(render_context.get_image(image_index)) }
128 }
129 }
130 }
131 pub fn get_current_image(&mut self, context: &ViewAssistantContext) -> Image {
133 match &mut self.inner {
134 ContextInner::Forma(render_context) => {
135 Image { inner: ImageInner::Forma(render_context.get_current_image(context)) }
136 }
137 }
138 }
139
140 pub fn render(
142 &mut self,
143 composition: &mut Composition,
144 clip: Option<Rect<u32>>,
145 image: Image,
146 ext: &RenderExt,
147 ) {
148 self.render_with_clip(
149 composition,
150 clip.unwrap_or_else(|| {
151 Rect::new(point2(u32::MIN, u32::MIN), size2(u32::MAX, u32::MAX))
152 }),
153 image,
154 ext,
155 );
156 }
157 pub fn render_with_clip(
159 &mut self,
160 composition: &mut Composition,
161 clip: Rect<u32>,
162 image: Image,
163 ext: &RenderExt,
164 ) {
165 let background_color = composition.background_color;
166
167 match &mut self.inner {
168 ContextInner::Forma(context) => {
169 let ImageInner::Forma(image) = image.inner;
170 let ext = generic::RenderExt {
171 pre_clear: ext
172 .pre_clear
173 .clone()
174 .map(|pre_clear| generic::PreClear { color: pre_clear.color }),
175 pre_copy: ext.pre_copy.clone().map(|pre_copy| {
176 let ImageInner::Forma(src_image) = pre_copy.image.inner;
177 generic::PreCopy {
178 image: src_image,
179 copy_region: generic::CopyRegion {
180 src_offset: pre_copy.copy_region.src_offset,
181 dst_offset: pre_copy.copy_region.dst_offset,
182 extent: pre_copy.copy_region.extent,
183 },
184 }
185 }),
186 post_copy: ext.post_copy.clone().map(|post_copy| {
187 let ImageInner::Forma(dst_image) = post_copy.image.inner;
188 generic::PostCopy {
189 image: dst_image,
190 copy_region: generic::CopyRegion {
191 src_offset: post_copy.copy_region.src_offset,
192 dst_offset: post_copy.copy_region.dst_offset,
193 extent: post_copy.copy_region.extent,
194 },
195 }
196 }),
197 };
198 composition.with_inner_composition(|inner| {
199 let mut composition = match inner {
200 CompositionInner::Forma(composition) => composition,
201 CompositionInner::Empty => FormaComposition::new(background_color),
202 };
203 context.render_with_clip(&mut composition, clip, image, &ext);
204 CompositionInner::Forma(composition)
205 });
206 }
207 }
208 }
209}
210#[derive(Clone, Debug, Eq, PartialEq)]
212pub struct Path {
213 inner: PathInner,
214}
215#[derive(Clone, Debug, Eq, PartialEq)]
216enum PathInner {
217 Forma(FormaPath),
218}
219#[derive(Debug)]
221pub struct PathBuilder {
222 inner: PathBuilderInner,
223}
224#[derive(Debug)]
225enum PathBuilderInner {
226 Forma(FormaPathBuilder),
227}
228impl PathBuilder {
229 pub fn move_to(&mut self, point: Point) -> &mut Self {
231 match &mut self.inner {
232 PathBuilderInner::Forma(path_builder) => {
233 path_builder.move_to(point);
234 }
235 }
236 self
237 }
238 pub fn line_to(&mut self, point: Point) -> &mut Self {
240 match &mut self.inner {
241 PathBuilderInner::Forma(path_builder) => {
242 path_builder.line_to(point);
243 }
244 }
245 self
246 }
247 pub fn quad_to(&mut self, p1: Point, p2: Point) -> &mut Self {
249 match &mut self.inner {
250 PathBuilderInner::Forma(path_builder) => {
251 path_builder.quad_to(p1, p2);
252 }
253 }
254 self
255 }
256 pub fn cubic_to(&mut self, p1: Point, p2: Point, p3: Point) -> &mut Self {
258 match &mut self.inner {
259 PathBuilderInner::Forma(path_builder) => {
260 path_builder.cubic_to(p1, p2, p3);
261 }
262 }
263 self
264 }
265 pub fn rat_quad_to(&mut self, p1: Point, p2: Point, w: f32) -> &mut Self {
268 match &mut self.inner {
269 PathBuilderInner::Forma(path_builder) => {
270 path_builder.rat_quad_to(p1, p2, w);
271 }
272 }
273 self
274 }
275 pub fn rat_cubic_to(&mut self, p1: Point, p2: Point, p3: Point, w1: f32, w2: f32) -> &mut Self {
278 match &mut self.inner {
279 PathBuilderInner::Forma(path_builder) => {
280 path_builder.rat_cubic_to(p1, p2, p3, w1, w2);
281 }
282 }
283 self
284 }
285 pub fn build(self) -> Path {
289 match self.inner {
290 PathBuilderInner::Forma(path_builder) => {
291 Path { inner: PathInner::Forma(path_builder.build()) }
292 }
293 }
294 }
295}
296#[derive(Clone, Debug, Eq, PartialEq)]
298pub struct Raster {
299 inner: RasterInner,
300}
301#[derive(Clone, Debug, Eq, PartialEq)]
302enum RasterInner {
303 Forma(FormaRaster),
304}
305impl Raster {
306 pub fn translate(self, translation: Vector2D<i32>) -> Self {
308 match self.inner {
309 RasterInner::Forma(raster) => {
310 Raster { inner: RasterInner::Forma(raster.translate(translation)) }
311 }
312 }
313 }
314}
315impl Add for Raster {
316 type Output = Self;
317 fn add(self, other: Self) -> Self::Output {
318 let RasterInner::Forma(other_raster) = other.inner;
319 match self.inner {
320 RasterInner::Forma(raster) => {
321 Raster { inner: RasterInner::Forma(raster + other_raster) }
322 }
323 }
324 }
325}
326#[derive(Debug)]
328pub struct RasterBuilder {
329 inner: RasterBuilderInner,
330}
331#[derive(Debug)]
332enum RasterBuilderInner {
333 Forma(FormaRasterBuilder),
334}
335impl RasterBuilder {
336 pub fn add(&mut self, path: &Path, transform: Option<&Transform2D<f32>>) -> &mut Self {
338 let identity = Transform2D::identity();
339 self.add_with_transform(path, transform.unwrap_or(&identity))
340 }
341 pub fn add_with_transform(&mut self, path: &Path, transform: &Transform2D<f32>) -> &mut Self {
343 match &mut self.inner {
344 RasterBuilderInner::Forma(raster_builder) => {
345 let PathInner::Forma(path) = &path.inner;
346 raster_builder.add_with_transform(path, transform);
347 }
348 }
349 self
350 }
351 pub fn build(self) -> Raster {
355 match self.inner {
356 RasterBuilderInner::Forma(raster_builder) => {
357 Raster { inner: RasterInner::Forma(raster_builder.build()) }
358 }
359 }
360 }
361}
362
363#[derive(Clone, Debug)]
364pub struct Layer {
365 pub raster: Raster,
367 pub clip: Option<Raster>,
369 pub style: Style, }
372#[derive(Debug)]
373pub struct Composition {
375 inner: CompositionInner,
376 background_color: Color,
377}
378#[derive(Debug)]
379enum CompositionInner {
380 Forma(FormaComposition),
381 Empty,
382}
383impl Composition {
384 pub fn new(background_color: Color) -> Self {
386 Self { inner: CompositionInner::Empty, background_color }
387 }
388 fn with_inner_composition(&mut self, mut f: impl FnMut(CompositionInner) -> CompositionInner) {
389 let inner = f(mem::replace(&mut self.inner, CompositionInner::Empty));
390 self.inner = inner;
391 }
392 pub fn clear(&mut self) {
394 match &mut self.inner {
395 CompositionInner::Forma(composition) => composition.clear(),
396 CompositionInner::Empty => (),
397 }
398 }
399 pub fn insert(&mut self, order: Order, layer: Layer) {
401 if let CompositionInner::Empty = self.inner {
402 match layer {
403 Layer { raster: Raster { inner: RasterInner::Forma(_) }, .. } => {
404 self.inner =
405 CompositionInner::Forma(FormaComposition::new(self.background_color));
406 }
407 }
408 }
409 match &mut self.inner {
410 CompositionInner::Forma(composition) => composition.insert(
411 order,
412 generic::Layer {
413 raster: {
414 let RasterInner::Forma(raster) = layer.raster.inner;
415 raster
416 },
417 clip: layer.clip.map(|clip| {
418 let RasterInner::Forma(clip) = clip.inner;
419 clip
420 }),
421 style: layer.style,
422 },
423 ),
424 _ => unreachable!(),
425 }
426 }
427 pub fn remove(&mut self, order: Order) {
429 match &mut self.inner {
430 CompositionInner::Forma(composition) => composition.remove(order),
431 _ => (),
432 }
433 }
434}