diff options
author | Minijackson <minijackson@riseup.net> | 2023-01-20 16:03:25 +0100 |
---|---|---|
committer | Minijackson <minijackson@riseup.net> | 2023-01-20 16:03:25 +0100 |
commit | 7b0e215008c94c4a7ddb5f47b12c341d807ea062 (patch) | |
tree | 52aef22ad227e0ad1b39e76574f8f55f70e31875 | |
parent | e8f8e5aa2f4a2372452e77ffe1cf8a035ce8cf8a (diff) | |
download | diaphragm-7b0e215008c94c4a7ddb5f47b12c341d807ea062.tar.gz diaphragm-7b0e215008c94c4a7ddb5f47b12c341d807ea062.zip |
tree-wide: properly set figure size
-rw-r--r-- | cairo-renderer/src/lib.rs | 16 | ||||
-rw-r--r-- | core/src/rendering.rs | 2 | ||||
-rw-r--r-- | core/src/runtime.rs | 13 | ||||
-rw-r--r-- | lua-bindings/src/lib.rs | 42 |
4 files changed, 65 insertions, 8 deletions
diff --git a/cairo-renderer/src/lib.rs b/cairo-renderer/src/lib.rs index 830e6bc..2a88379 100644 --- a/cairo-renderer/src/lib.rs +++ b/cairo-renderer/src/lib.rs | |||
@@ -10,15 +10,27 @@ pub struct CairoRenderer { | |||
10 | 10 | ||
11 | impl CairoRenderer { | 11 | impl CairoRenderer { |
12 | pub fn new() -> Self { | 12 | pub fn new() -> Self { |
13 | // TODO: properly | 13 | // HACK: a bit ugly, but text_extents requires a context, so we have to create a "dummy" |
14 | let surface = cairo::SvgSurface::for_stream(1920., 1080., std::io::stdout()).unwrap(); | 14 | // surface |
15 | let surface = cairo::SvgSurface::for_stream(1920., 1080., std::io::sink()).unwrap(); | ||
15 | let ctx = cairo::Context::new(&surface).unwrap(); | 16 | let ctx = cairo::Context::new(&surface).unwrap(); |
16 | 17 | ||
17 | Self { ctx } | 18 | Self { ctx } |
18 | } | 19 | } |
19 | } | 20 | } |
20 | 21 | ||
22 | impl Default for CairoRenderer { | ||
23 | fn default() -> Self { | ||
24 | Self::new() | ||
25 | } | ||
26 | } | ||
27 | |||
21 | impl Renderer for CairoRenderer { | 28 | impl Renderer for CairoRenderer { |
29 | fn set_size(&mut self, width: f64, height: f64) { | ||
30 | let surface = cairo::SvgSurface::for_stream(width, height, std::io::stdout()).unwrap(); | ||
31 | self.ctx = cairo::Context::new(&surface).unwrap(); | ||
32 | } | ||
33 | |||
22 | fn move_to(&mut self, x: f64, y: f64) { | 34 | fn move_to(&mut self, x: f64, y: f64) { |
23 | self.ctx.move_to(x, y) | 35 | self.ctx.move_to(x, y) |
24 | } | 36 | } |
diff --git a/core/src/rendering.rs b/core/src/rendering.rs index 3f2303b..73daa2a 100644 --- a/core/src/rendering.rs +++ b/core/src/rendering.rs | |||
@@ -4,6 +4,8 @@ use super::text::{DefinedFontDescription, FontDescription}; | |||
4 | use super::types::DefinedCoreShapeContext; | 4 | use super::types::DefinedCoreShapeContext; |
5 | 5 | ||
6 | pub trait Renderer { | 6 | pub trait Renderer { |
7 | // Must be called once before any drawing happens | ||
8 | fn set_size(&mut self, width: f64, height: f64); | ||
7 | fn move_to(&mut self, x: f64, y: f64); | 9 | fn move_to(&mut self, x: f64, y: f64); |
8 | fn stroke(&mut self); | 10 | fn stroke(&mut self); |
9 | fn fill(&mut self); | 11 | fn fill(&mut self); |
diff --git a/core/src/runtime.rs b/core/src/runtime.rs index d70e4d0..6b1b5d1 100644 --- a/core/src/runtime.rs +++ b/core/src/runtime.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | use crate::core_shapes::CoreDrawable; | 1 | use crate::core_shapes::CoreDrawable; |
2 | use crate::rendering::Render; | 2 | use crate::rendering::Render; |
3 | use crate::types::Bounds; | ||
3 | 4 | ||
4 | // use super::complex_shapes::{ComplexShape, Drawable}; | 5 | // use super::complex_shapes::{ComplexShape, Drawable}; |
5 | use super::rendering::Renderer; | 6 | use super::rendering::Renderer; |
@@ -40,14 +41,22 @@ impl<'a> Runtime<'a> { | |||
40 | &mut *self.renderer | 41 | &mut *self.renderer |
41 | } | 42 | } |
42 | 43 | ||
43 | pub fn render(mut self) { | 44 | pub fn render(mut self, bounds: Bounds) { |
44 | let model = self.solver_ctx.solve(); | 45 | let model = self.solver_ctx.solve(); |
45 | 46 | ||
47 | let bounds = bounds | ||
48 | .fixate(&*model) | ||
49 | .expect("Could not fixate figure bounds"); | ||
50 | |||
51 | self.renderer.set_size(bounds.width, bounds.height); | ||
52 | |||
46 | for drawable in &self.drawables { | 53 | for drawable in &self.drawables { |
47 | let defined_drawable = drawable | 54 | let defined_drawable = drawable |
48 | .fixate(&*model) | 55 | .fixate(&*model) |
49 | .expect("Could not fixate core shape"); | 56 | .expect("Could not fixate core shape"); |
50 | defined_drawable.shape.render(defined_drawable.context, &mut *self.renderer); | 57 | defined_drawable |
58 | .shape | ||
59 | .render(defined_drawable.context, &mut *self.renderer); | ||
51 | } | 60 | } |
52 | } | 61 | } |
53 | 62 | ||
diff --git a/lua-bindings/src/lib.rs b/lua-bindings/src/lib.rs index 35cdaf8..53622de 100644 --- a/lua-bindings/src/lib.rs +++ b/lua-bindings/src/lib.rs | |||
@@ -16,7 +16,9 @@ use diaphragm_core::{ | |||
16 | solving::VariableHandle, | 16 | solving::VariableHandle, |
17 | styles::Pattern, | 17 | styles::Pattern, |
18 | text::{FontDescription as CoreFontDescription, FontStyle, FontWeight, Text as CoreText}, | 18 | text::{FontDescription as CoreFontDescription, FontStyle, FontWeight, Text as CoreText}, |
19 | types::{Bool as CoreBool, CoreShapeContext, Float as CoreFloat, Point2D as CorePoint2D}, | 19 | types::{ |
20 | Bool as CoreBool, Bounds, CoreShapeContext, Float as CoreFloat, Point2D as CorePoint2D, | ||
21 | }, | ||
20 | Runtime, | 22 | Runtime, |
21 | }; | 23 | }; |
22 | use diaphragm_z3_solver::{z3, Z3Context}; | 24 | use diaphragm_z3_solver::{z3, Z3Context}; |
@@ -656,6 +658,7 @@ thread_local! { | |||
656 | 658 | ||
657 | enum Message { | 659 | enum Message { |
658 | Do(Box<dyn FnOnce(&mut Runtime) + Send>), | 660 | Do(Box<dyn FnOnce(&mut Runtime) + Send>), |
661 | SetBounds(Bounds), | ||
659 | } | 662 | } |
660 | 663 | ||
661 | fn runtime_thread_do<T: Any + Send>(fun: Box<dyn FnOnce(&mut Runtime) -> T + Send>) -> T { | 664 | fn runtime_thread_do<T: Any + Send>(fun: Box<dyn FnOnce(&mut Runtime) -> T + Send>) -> T { |
@@ -698,7 +701,7 @@ fn constrain(_: &Lua, bool: Bool) -> LuaResult<()> { | |||
698 | Ok(()) | 701 | Ok(()) |
699 | } | 702 | } |
700 | 703 | ||
701 | fn draw(_: &Lua, params: LuaTable) -> LuaResult<()> { | 704 | fn draw(lua: &Lua, params: LuaTable) -> LuaResult<()> { |
702 | // So.... The Z3 stuff isn't Send and contains lifetimes, so we can't store them in global | 705 | // So.... The Z3 stuff isn't Send and contains lifetimes, so we can't store them in global |
703 | // variables or convert them to Lua. Solution: handle everything in a specific thread, and | 706 | // variables or convert them to Lua. Solution: handle everything in a specific thread, and |
704 | // communicate through a channel. | 707 | // communicate through a channel. |
@@ -728,23 +731,54 @@ fn draw(_: &Lua, params: LuaTable) -> LuaResult<()> { | |||
728 | // TODO: we shouldn't need the renderer until the end | 731 | // TODO: we shouldn't need the renderer until the end |
729 | let mut runtime = Runtime::new(Box::new(ctx), Box::new(cairo_renderer)); | 732 | let mut runtime = Runtime::new(Box::new(ctx), Box::new(cairo_renderer)); |
730 | 733 | ||
734 | let mut bounds = None; | ||
731 | for message in message_receiver { | 735 | for message in message_receiver { |
732 | match message { | 736 | match message { |
733 | Message::Do(fun) => { | 737 | Message::Do(fun) => { |
734 | fun(&mut runtime); | 738 | fun(&mut runtime); |
735 | } | 739 | } |
740 | Message::SetBounds(new_bounds) => bounds = Some(new_bounds), | ||
736 | } | 741 | } |
737 | } | 742 | } |
738 | 743 | ||
739 | runtime.render(); | 744 | let bounds = bounds.unwrap(); |
745 | |||
746 | // TODO: it would be nicer to do in Lua | ||
747 | let bounds_top = bounds.top(runtime.solver_ctx()); | ||
748 | let top_constraint = runtime | ||
749 | .solver_ctx() | ||
750 | .float_eq(bounds_top, CoreFloat::Fixed(0.0)); | ||
751 | runtime.solver_ctx().constrain(top_constraint); | ||
752 | |||
753 | let bounds_left = bounds.left(runtime.solver_ctx()); | ||
754 | let left_constraint = runtime | ||
755 | .solver_ctx() | ||
756 | .float_eq(bounds_left, CoreFloat::Fixed(0.0)); | ||
757 | runtime.solver_ctx().constrain(left_constraint); | ||
758 | |||
759 | runtime.render(bounds); | ||
740 | }); | 760 | }); |
741 | 761 | ||
742 | let content: LuaValue = params.get("content")?; | 762 | let content: LuaValue = params.get("content")?; |
743 | let _output: LuaTable = params.get("output")?; | 763 | let _output: LuaTable = params.get("output")?; |
744 | 764 | ||
765 | let figure = complex_shape(lua, ())?; | ||
766 | let figure_bounds = figure.0.bounds().clone(); | ||
767 | |||
768 | // TODO: sending bounds before callin `draw` prevents doing things like | ||
769 | // figure = dia.rectangle.new(...) | ||
770 | SENDER.with(|sender| { | ||
771 | sender | ||
772 | .borrow_mut() | ||
773 | .as_mut() | ||
774 | .expect("Not currently drawing") | ||
775 | .send(Message::SetBounds(figure_bounds)) | ||
776 | .unwrap() | ||
777 | }); | ||
778 | |||
745 | match content { | 779 | match content { |
746 | // TODO: this doesn't stop the runtime thread? | 780 | // TODO: this doesn't stop the runtime thread? |
747 | LuaValue::Table(table) => table.call_method("draw", ()).unwrap(), | 781 | LuaValue::Table(table) => table.call_method("draw", figure).unwrap(), |
748 | 782 | ||
749 | // TODO: switch to enum | 783 | // TODO: switch to enum |
750 | // LuaValue::UserData(user_data) => { | 784 | // LuaValue::UserData(user_data) => { |