summaryrefslogtreecommitdiff
path: root/src/layout/mod.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-07-21 20:35:02 +0200
committerLaurenz <laurmaedje@gmail.com>2021-07-25 01:03:38 +0200
commitadb71ee040752f9348b0c9a511b2ab7e3710cb80 (patch)
tree13578f67cf7361a03924b2a7f18d3d17103dea09 /src/layout/mod.rs
parent927f1154fa983a13eda050d716d04dead96bf8fb (diff)
Move and refactor
Diffstat (limited to 'src/layout/mod.rs')
-rw-r--r--src/layout/mod.rs162
1 files changed, 2 insertions, 160 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 7f8ee4ff..22e6e8c8 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -10,6 +10,7 @@ mod pad;
mod par;
mod shaping;
mod stack;
+mod tree;
pub use self::image::*;
pub use background::*;
@@ -21,21 +22,16 @@ pub use pad::*;
pub use par::*;
pub use shaping::*;
pub use stack::*;
+pub use tree::*;
-use std::any::Any;
-use std::fmt::{self, Debug, Formatter};
use std::hash::Hash;
#[cfg(feature = "layout-cache")]
use std::hash::Hasher;
use std::rc::Rc;
-#[cfg(feature = "layout-cache")]
-use fxhash::FxHasher64;
-
use crate::font::FontCache;
use crate::geom::*;
use crate::image::ImageCache;
-use crate::loading::Loader;
use crate::Context;
/// Layout a tree into a collection of frames.
@@ -44,157 +40,6 @@ pub fn layout(ctx: &mut Context, tree: &LayoutTree) -> Vec<Rc<Frame>> {
tree.layout(&mut ctx)
}
-/// A tree of layout nodes.
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct LayoutTree {
- /// Runs of pages with the same properties.
- pub runs: Vec<PageRun>,
-}
-
-impl LayoutTree {
- /// Layout the tree into a collection of frames.
- pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<Rc<Frame>> {
- self.runs.iter().flat_map(|run| run.layout(ctx)).collect()
- }
-}
-
-/// A run of pages that all have the same properties.
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct PageRun {
- /// The size of each page.
- pub size: Size,
- /// The layout node that produces the actual pages (typically a
- /// [`StackNode`]).
- pub child: LayoutNode,
-}
-
-impl PageRun {
- /// Layout the page run.
- pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<Rc<Frame>> {
- // When one of the lengths is infinite the page fits its content along
- // that axis.
- let Size { width, height } = self.size;
- let expand = Spec::new(width.is_finite(), height.is_finite());
- let regions = Regions::repeat(self.size, expand);
- self.child.layout(ctx, &regions).into_iter().map(|c| c.item).collect()
- }
-}
-
-/// A dynamic layouting node.
-pub struct LayoutNode {
- node: Box<dyn Bounds>,
- #[cfg(feature = "layout-cache")]
- hash: u64,
-}
-
-impl LayoutNode {
- /// Create a new instance from any node that satisifies the required bounds.
- #[cfg(feature = "layout-cache")]
- pub fn new<T>(node: T) -> Self
- where
- T: Layout + Debug + Clone + Eq + PartialEq + Hash + 'static,
- {
- let hash = {
- let mut state = FxHasher64::default();
- node.type_id().hash(&mut state);
- node.hash(&mut state);
- state.finish()
- };
-
- Self { node: Box::new(node), hash }
- }
-
- /// Create a new instance from any node that satisifies the required bounds.
- #[cfg(not(feature = "layout-cache"))]
- pub fn new<T>(node: T) -> Self
- where
- T: Layout + Debug + Clone + Eq + PartialEq + 'static,
- {
- Self { node: Box::new(node) }
- }
-}
-
-impl Layout for LayoutNode {
- fn layout(
- &self,
- ctx: &mut LayoutContext,
- regions: &Regions,
- ) -> Vec<Constrained<Rc<Frame>>> {
- #[cfg(feature = "layout-cache")]
- {
- ctx.level += 1;
- let frames = ctx.layouts.get(self.hash, regions.clone()).unwrap_or_else(|| {
- let frames = self.node.layout(ctx, regions);
- ctx.layouts.insert(self.hash, frames.clone(), ctx.level - 1);
- frames
- });
- ctx.level -= 1;
- frames
- }
-
- #[cfg(not(feature = "layout-cache"))]
- self.node.layout(ctx, regions)
- }
-}
-
-impl Debug for LayoutNode {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- self.node.fmt(f)
- }
-}
-
-impl Clone for LayoutNode {
- fn clone(&self) -> Self {
- Self {
- node: self.node.dyn_clone(),
- #[cfg(feature = "layout-cache")]
- hash: self.hash,
- }
- }
-}
-
-impl Eq for LayoutNode {}
-
-impl PartialEq for LayoutNode {
- fn eq(&self, other: &Self) -> bool {
- self.node.dyn_eq(other.node.as_ref())
- }
-}
-
-#[cfg(feature = "layout-cache")]
-impl Hash for LayoutNode {
- fn hash<H: Hasher>(&self, state: &mut H) {
- state.write_u64(self.hash);
- }
-}
-
-trait Bounds: Layout + Debug + 'static {
- fn as_any(&self) -> &dyn Any;
- fn dyn_eq(&self, other: &dyn Bounds) -> bool;
- fn dyn_clone(&self) -> Box<dyn Bounds>;
-}
-
-impl<T> Bounds for T
-where
- T: Layout + Debug + Eq + PartialEq + Clone + 'static,
-{
- fn as_any(&self) -> &dyn Any {
- self
- }
-
- fn dyn_eq(&self, other: &dyn Bounds) -> bool {
- if let Some(other) = other.as_any().downcast_ref::<Self>() {
- self == other
- } else {
- false
- }
- }
-
- fn dyn_clone(&self) -> Box<dyn Bounds> {
- Box::new(self.clone())
- }
-}
-
/// Layout a node.
pub trait Layout {
/// Layout the node into the given regions.
@@ -207,8 +52,6 @@ pub trait Layout {
/// The context for layouting.
pub struct LayoutContext<'a> {
- /// The loader from which fonts are loaded.
- pub loader: &'a dyn Loader,
/// The cache for parsed font faces.
pub fonts: &'a mut FontCache,
/// The cache for decoded imges.
@@ -225,7 +68,6 @@ impl<'a> LayoutContext<'a> {
/// Create a new layout context.
pub fn new(ctx: &'a mut Context) -> Self {
Self {
- loader: ctx.loader.as_ref(),
fonts: &mut ctx.fonts,
images: &mut ctx.images,
#[cfg(feature = "layout-cache")]