diff options
Diffstat (limited to 'core/src/core_shapes.rs')
-rw-r--r-- | core/src/core_shapes.rs | 174 |
1 files changed, 105 insertions, 69 deletions
diff --git a/core/src/core_shapes.rs b/core/src/core_shapes.rs index e6d79c9..c380870 100644 --- a/core/src/core_shapes.rs +++ b/core/src/core_shapes.rs | |||
@@ -1,7 +1,12 @@ | |||
1 | use crate::types::{CoreShapeContext, DefinedCoreShapeContext, DefinedPoint2D, Point2D}; | 1 | use std::path::PathBuf; |
2 | 2 | ||
3 | pub use super::text::{DefinedText, Text}; | 3 | use crate::{ |
4 | text::{DefinedText, Text}, | ||
5 | types::{CoreShapeContext, DefinedCoreShapeContext, DefinedPoint2D, Float, Point2D}, | ||
6 | Renderer, SolverContext, | ||
7 | }; | ||
4 | 8 | ||
9 | #[derive(Debug, Clone)] | ||
5 | pub struct CoreDrawable { | 10 | pub struct CoreDrawable { |
6 | pub(crate) shape: CoreShape, | 11 | pub(crate) shape: CoreShape, |
7 | pub(crate) context: CoreShapeContext, | 12 | pub(crate) context: CoreShapeContext, |
@@ -11,12 +16,91 @@ impl CoreDrawable { | |||
11 | pub fn new(shape: CoreShape, context: CoreShapeContext) -> Self { | 16 | pub fn new(shape: CoreShape, context: CoreShapeContext) -> Self { |
12 | Self { shape, context } | 17 | Self { shape, context } |
13 | } | 18 | } |
19 | |||
20 | // TODO: I don't like this design | ||
21 | // TODO: plus, having an enum for CoreShape could be bad since types have | ||
22 | // various sizes | ||
23 | pub(crate) fn inherent_constraints( | ||
24 | &self, | ||
25 | solver: &mut dyn SolverContext, | ||
26 | renderer: &mut dyn Renderer, | ||
27 | ) { | ||
28 | match &self.shape { | ||
29 | CoreShape::Text(text) => { | ||
30 | let (text_width, text_height) = renderer.text_extents(&text.content, &text.font); | ||
31 | |||
32 | let calculated_width = | ||
33 | solver.float_mul(&[Float::Fixed(text_width), text.font.size]); | ||
34 | let bounds_width = self.context.bounds().width(solver); | ||
35 | let width_constraint = solver.float_eq(bounds_width, calculated_width); | ||
36 | solver.constrain(width_constraint); | ||
37 | |||
38 | let calculated_height = | ||
39 | solver.float_mul(&[Float::Fixed(text_height), text.font.size]); | ||
40 | let bounds_height = self.context.bounds().height(solver); | ||
41 | let height_constraint = solver.float_eq(bounds_height, calculated_height); | ||
42 | solver.constrain(height_constraint); | ||
43 | } | ||
44 | CoreShape::StraightPath(path) => { | ||
45 | let (all_x, all_y): (Vec<_>, Vec<_>) = | ||
46 | path.points.iter().map(|p| (p.x, p.y)).unzip(); | ||
47 | |||
48 | let min_x = solver.float_min(&all_x); | ||
49 | let max_x = solver.float_max(&all_x); | ||
50 | let min_y = solver.float_min(&all_y); | ||
51 | let max_y = solver.float_max(&all_y); | ||
52 | |||
53 | let bounds_top = self.context.bounds().top(solver); | ||
54 | let bounds_bottom = self.context.bounds().bottom(solver); | ||
55 | let bounds_left = self.context.bounds().left(solver); | ||
56 | let bounds_right = self.context.bounds().right(solver); | ||
57 | |||
58 | let top_constraint = solver.float_eq(bounds_top, min_x); | ||
59 | solver.constrain(top_constraint); | ||
60 | |||
61 | let bottom_constraint = solver.float_eq(bounds_bottom, max_x); | ||
62 | solver.constrain(bottom_constraint); | ||
63 | |||
64 | let left_constraint = solver.float_eq(bounds_left, min_y); | ||
65 | solver.constrain(left_constraint); | ||
66 | |||
67 | let right_constraint = solver.float_eq(bounds_right, max_y); | ||
68 | solver.constrain(right_constraint); | ||
69 | } | ||
70 | CoreShape::Image(image) => { | ||
71 | if !image.keep_aspect_ratio { | ||
72 | return; | ||
73 | } | ||
74 | |||
75 | let scale_x = solver.new_free_float(); | ||
76 | let scale_y = solver.new_free_float(); | ||
77 | |||
78 | let constraint = solver.float_eq(scale_x, scale_y); | ||
79 | solver.constrain(constraint); | ||
80 | |||
81 | let (orig_width, orig_height) = renderer.geometry_for_image(&image.path); | ||
82 | |||
83 | let orig_width_scaled = solver.float_mul(&[scale_x, Float::Fixed(orig_width)]); | ||
84 | let width_constraint = | ||
85 | solver.float_eq(self.context.bounds().width, orig_width_scaled); | ||
86 | solver.constrain(width_constraint); | ||
87 | |||
88 | let orig_height_scaled = solver.float_mul(&[scale_y, Float::Fixed(orig_height)]); | ||
89 | let height_constraint = | ||
90 | solver.float_eq(self.context.bounds().height, orig_height_scaled); | ||
91 | solver.constrain(height_constraint); | ||
92 | } | ||
93 | _ => (), | ||
94 | } | ||
95 | } | ||
14 | } | 96 | } |
15 | 97 | ||
98 | #[derive(Debug, Clone)] | ||
16 | pub enum CoreShape { | 99 | pub enum CoreShape { |
17 | Rectangle(Rectangle), | 100 | Rectangle(Rectangle), |
18 | Text(Text), | 101 | Text(Text), |
19 | StraightPath(StraightPath), | 102 | StraightPath(StraightPath), |
103 | Image(Image), | ||
20 | } | 104 | } |
21 | 105 | ||
22 | impl From<Rectangle> for CoreShape { | 106 | impl From<Rectangle> for CoreShape { |
@@ -37,6 +121,12 @@ impl From<StraightPath> for CoreShape { | |||
37 | } | 121 | } |
38 | } | 122 | } |
39 | 123 | ||
124 | impl From<Image> for CoreShape { | ||
125 | fn from(image: Image) -> Self { | ||
126 | CoreShape::Image(image) | ||
127 | } | ||
128 | } | ||
129 | |||
40 | pub struct DefinedCoreDrawable { | 130 | pub struct DefinedCoreDrawable { |
41 | pub(crate) shape: DefinedCoreShape, | 131 | pub(crate) shape: DefinedCoreShape, |
42 | pub(crate) context: DefinedCoreShapeContext, | 132 | pub(crate) context: DefinedCoreShapeContext, |
@@ -46,72 +136,12 @@ pub enum DefinedCoreShape { | |||
46 | Rectangle(Rectangle), | 136 | Rectangle(Rectangle), |
47 | Text(DefinedText), | 137 | Text(DefinedText), |
48 | StraightPath(DefinedStraightPath), | 138 | StraightPath(DefinedStraightPath), |
139 | Image(Image), | ||
49 | } | 140 | } |
50 | 141 | ||
51 | /* | ||
52 | pub trait CoreShape { | ||
53 | fn constrain( | ||
54 | &self, | ||
55 | _context: &ShapeContext, | ||
56 | _solver: &mut dyn SolverContext, | ||
57 | _renderer: &dyn Renderer, | ||
58 | ) { | ||
59 | } | ||
60 | fn to_render(&self, model: &dyn SolverModel) -> Option<Box<dyn Render>>; | ||
61 | } | ||
62 | |||
63 | impl<T: CoreShape + Clone + 'static> ComplexShape for T { | ||
64 | fn as_core_shape(&self) -> Option<&dyn CoreShape> { | ||
65 | Some(self) | ||
66 | } | ||
67 | |||
68 | fn draw(&self, _context: &ShapeContext, _solver: &mut dyn SolverContext) -> DrawResult { | ||
69 | panic!("Tried to decompose core shape") | ||
70 | } | ||
71 | } | ||
72 | */ | ||
73 | |||
74 | #[derive(Copy, Clone, Debug, Default)] | 142 | #[derive(Copy, Clone, Debug, Default)] |
75 | pub struct Rectangle {} | 143 | pub struct Rectangle {} |
76 | 144 | ||
77 | /* | ||
78 | impl CoreShape for Rectangle { | ||
79 | fn to_render(&self, _model: &dyn SolverModel) -> Option<Box<dyn Render>> { | ||
80 | Some(Box::new(*self)) | ||
81 | } | ||
82 | } | ||
83 | */ | ||
84 | |||
85 | // TODO: re-enable this in some way | ||
86 | /* | ||
87 | impl CoreShape for Text { | ||
88 | fn constrain( | ||
89 | &self, | ||
90 | context: &ShapeContext, | ||
91 | solver: &mut dyn SolverContext, | ||
92 | renderer: &dyn Renderer, | ||
93 | ) { | ||
94 | let height_constraint = solver.float_eq(context.bounds.height, self.font.size); | ||
95 | solver.constrain(height_constraint); | ||
96 | |||
97 | // TODO: handle multiline | ||
98 | let (width, height) = renderer.text_extents(&self.content, &self.font); | ||
99 | dbg!(height); | ||
100 | |||
101 | let scale = solver.float_div(self.font.size, Float::Fixed(height)); | ||
102 | |||
103 | let calculated_width = solver.float_mul(&[Float::Fixed(width), scale]); | ||
104 | let width_constraint = solver.float_eq(context.bounds.width, calculated_width); | ||
105 | solver.constrain(width_constraint); | ||
106 | } | ||
107 | |||
108 | fn to_render(&self, model: &dyn SolverModel) -> Option<Box<dyn Render>> { | ||
109 | self.fixate(model) | ||
110 | .map(|path| -> Box<dyn Render> { Box::new(path) }) | ||
111 | } | ||
112 | } | ||
113 | */ | ||
114 | |||
115 | #[derive(Clone, Debug, Default)] | 145 | #[derive(Clone, Debug, Default)] |
116 | pub struct StraightPath { | 146 | pub struct StraightPath { |
117 | pub(crate) points: Vec<Point2D>, | 147 | pub(crate) points: Vec<Point2D>, |
@@ -127,11 +157,17 @@ pub struct DefinedStraightPath { | |||
127 | pub(crate) points: Vec<DefinedPoint2D>, | 157 | pub(crate) points: Vec<DefinedPoint2D>, |
128 | } | 158 | } |
129 | 159 | ||
130 | /* | 160 | #[derive(Clone, Debug, Default)] |
131 | impl CoreShape for StraightPath { | 161 | pub struct Image { |
132 | fn to_render(&self, model: &dyn SolverModel) -> Option<Box<dyn Render>> { | 162 | pub(crate) path: PathBuf, |
133 | self.fixate(model) | 163 | pub(crate) keep_aspect_ratio: bool, |
134 | .map(|path| -> Box<dyn Render> { Box::new(path) }) | 164 | } |
165 | |||
166 | impl Image { | ||
167 | pub fn new(path: PathBuf, keep_aspect_ratio: bool) -> Self { | ||
168 | Self { | ||
169 | path, | ||
170 | keep_aspect_ratio, | ||
171 | } | ||
135 | } | 172 | } |
136 | } | 173 | } |
137 | */ | ||