summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMinijackson <minijackson@riseup.net>2023-01-20 16:03:25 +0100
committerMinijackson <minijackson@riseup.net>2023-01-20 16:03:25 +0100
commit7b0e215008c94c4a7ddb5f47b12c341d807ea062 (patch)
tree52aef22ad227e0ad1b39e76574f8f55f70e31875
parente8f8e5aa2f4a2372452e77ffe1cf8a035ce8cf8a (diff)
downloaddiaphragm-7b0e215008c94c4a7ddb5f47b12c341d807ea062.tar.gz
diaphragm-7b0e215008c94c4a7ddb5f47b12c341d807ea062.zip
tree-wide: properly set figure size
-rw-r--r--cairo-renderer/src/lib.rs16
-rw-r--r--core/src/rendering.rs2
-rw-r--r--core/src/runtime.rs13
-rw-r--r--lua-bindings/src/lib.rs42
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
11impl CairoRenderer { 11impl 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
22impl Default for CairoRenderer {
23 fn default() -> Self {
24 Self::new()
25 }
26}
27
21impl Renderer for CairoRenderer { 28impl 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};
4use super::types::DefinedCoreShapeContext; 4use super::types::DefinedCoreShapeContext;
5 5
6pub trait Renderer { 6pub 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 @@
1use crate::core_shapes::CoreDrawable; 1use crate::core_shapes::CoreDrawable;
2use crate::rendering::Render; 2use crate::rendering::Render;
3use crate::types::Bounds;
3 4
4// use super::complex_shapes::{ComplexShape, Drawable}; 5// use super::complex_shapes::{ComplexShape, Drawable};
5use super::rendering::Renderer; 6use 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};
22use diaphragm_z3_solver::{z3, Z3Context}; 24use diaphragm_z3_solver::{z3, Z3Context};
@@ -656,6 +658,7 @@ thread_local! {
656 658
657enum Message { 659enum Message {
658 Do(Box<dyn FnOnce(&mut Runtime) + Send>), 660 Do(Box<dyn FnOnce(&mut Runtime) + Send>),
661 SetBounds(Bounds),
659} 662}
660 663
661fn runtime_thread_do<T: Any + Send>(fun: Box<dyn FnOnce(&mut Runtime) -> T + Send>) -> T { 664fn 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
701fn draw(_: &Lua, params: LuaTable) -> LuaResult<()> { 704fn 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) => {