This commit is contained in:
Nathan Sobo 2023-09-20 20:28:32 -06:00
parent 44608517c1
commit a8bb3dd9a3
8 changed files with 107 additions and 34 deletions

View file

@ -3,6 +3,4 @@ mod img;
mod svg; mod svg;
mod text; mod text;
use super::*;
pub use div::*; pub use div::*;

View file

@ -1,7 +1,7 @@
use crate::{Element, Layout, LayoutId, Result, Style, Styled}; use crate::{Element, Layout, LayoutId, Result, Style, Styled};
use refineable::RefinementCascade; use refineable::RefinementCascade;
use std::marker::PhantomData; use std::marker::PhantomData;
use util::{arc_cow::ArcCow, ResultExt}; use util::arc_cow::ArcCow;
pub struct Img<S> { pub struct Img<S> {
style: RefinementCascade<Style>, style: RefinementCascade<Style>,

View file

@ -1,6 +1,5 @@
use crate::{ use crate::{
AnyElement, Element, IntoAnyElement, Layout, LayoutId, Line, LineLayout, Pixels, Result, Size, AnyElement, Element, IntoAnyElement, Layout, LayoutId, Line, Pixels, Result, Size, ViewContext,
ViewContext,
}; };
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{marker::PhantomData, sync::Arc}; use std::{marker::PhantomData, sync::Arc};
@ -42,16 +41,18 @@ impl<S: 'static> Element for Text<S> {
) -> Result<(LayoutId, Self::FrameState)> { ) -> Result<(LayoutId, Self::FrameState)> {
let text_system = cx.text_system().clone(); let text_system = cx.text_system().clone();
let text_style = cx.text_style(); let text_style = cx.text_style();
let line_height = cx.text_system().line_height(text_style.font_size); let font_size = text_style.font_size * cx.rem_size();
let line_height = cx.text_system().line_height(font_size);
let text = self.text.clone(); let text = self.text.clone();
let paint_state = Arc::new(Mutex::new(None)); let paint_state = Arc::new(Mutex::new(None));
let layout_id = cx.request_measured_layout(Default::default(), cx.rem_size(), { let rem_size = cx.rem_size();
let layout_id = cx.request_measured_layout(Default::default(), rem_size, {
let frame_state = paint_state.clone(); let frame_state = paint_state.clone();
move |_, _| { move |_, _| {
let line_layout = text_system.layout_str( let line_layout = text_system.layout_str(
text.as_ref(), text.as_ref(),
text_style.font_size, font_size,
&[(text.len(), text_style.to_run())], &[(text.len(), text_style.to_run())],
); );
@ -78,7 +79,7 @@ impl<S: 'static> Element for Text<S> {
_: &mut Self::State, _: &mut Self::State,
paint_state: &mut Self::FrameState, paint_state: &mut Self::FrameState,
cx: &mut ViewContext<S>, cx: &mut ViewContext<S>,
) { ) -> Result<()> {
let bounds = layout.bounds; let bounds = layout.bounds;
let line; let line;
@ -96,7 +97,9 @@ impl<S: 'static> Element for Text<S> {
// todo!("We haven't added visible bounds to the new element system yet, so this is a placeholder."); // todo!("We haven't added visible bounds to the new element system yet, so this is a placeholder.");
let visible_bounds = bounds; let visible_bounds = bounds;
line.paint(bounds.origin, visible_bounds, line_height, cx.legacy_cx); line.paint(bounds.origin, visible_bounds, line_height, cx);
Ok(())
} }
} }

View file

@ -79,6 +79,15 @@ pub fn size<T: Clone + Debug>(width: T, height: T) -> Size<T> {
Size { width, height } Size { width, height }
} }
impl<T: Clone + Debug> Size<T> {
pub fn map<U: Clone + Debug, F: Fn(T) -> U>(&self, f: F) -> Size<U> {
Size {
width: f(self.width.clone()),
height: f(self.height.clone()),
}
}
}
impl From<Size<Option<Pixels>>> for Size<Option<f32>> { impl From<Size<Option<Pixels>>> for Size<Option<f32>> {
fn from(val: Size<Option<Pixels>>) -> Self { fn from(val: Size<Option<Pixels>>) -> Self {
Size { Size {

View file

@ -31,8 +31,8 @@ pub use smol::Timer;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
pub use style::*; pub use style::*;
pub use styled::*; pub use styled::*;
pub use taffy::LayoutId;
use taffy::TaffyLayoutEngine; use taffy::TaffyLayoutEngine;
pub use taffy::{AvailableSpace, LayoutId};
pub use text_system::*; pub use text_system::*;
pub use util::arc_cow::ArcCow; pub use util::arc_cow::ArcCow;
pub use window::*; pub use window::*;
@ -55,6 +55,12 @@ pub trait Context {
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq)]
pub struct SharedString(ArcCow<'static, str>); pub struct SharedString(ArcCow<'static, str>);
impl Default for SharedString {
fn default() -> Self {
Self(ArcCow::Owned("".into()))
}
}
impl AsRef<str> for SharedString { impl AsRef<str> for SharedString {
fn as_ref(&self) -> &str { fn as_ref(&self) -> &str {
&self.0 &self.0

View file

@ -3,7 +3,6 @@ use super::{
Hsla, Length, Pixels, Point, PointRefinement, Rems, Result, RunStyle, SharedString, Size, Hsla, Length, Pixels, Point, PointRefinement, Rems, Result, RunStyle, SharedString, Size,
SizeRefinement, ViewContext, WindowContext, SizeRefinement, ViewContext, WindowContext,
}; };
use crate::{FontCache, TextSystem};
use refineable::Refineable; use refineable::Refineable;
pub use taffy::style::{ pub use taffy::style::{
AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent, AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent,

View file

@ -4,9 +4,24 @@ use super::{
}; };
use std::fmt::Debug; use std::fmt::Debug;
pub use taffy::tree::NodeId as LayoutId; pub use taffy::tree::NodeId as LayoutId;
use taffy::{style::AvailableSpace, tree::MeasureFunc, *}; use taffy::{
geometry::Size as TaffySize,
style::AvailableSpace as TaffyAvailableSpace,
tree::{Measurable, MeasureFunc},
Taffy,
};
pub struct TaffyLayoutEngine(Taffy); pub struct TaffyLayoutEngine(Taffy);
#[derive(Copy, Clone, Debug)]
pub enum AvailableSpace {
/// The amount of space available is the specified number of pixels
Definite(Pixels),
/// The amount of space available is indefinite and the node should be laid out under a min-content constraint
MinContent,
/// The amount of space available is indefinite and the node should be laid out under a max-content constraint
MaxContent,
}
impl TaffyLayoutEngine { impl TaffyLayoutEngine {
pub fn new() -> Self { pub fn new() -> Self {
TaffyLayoutEngine(Taffy::new()) TaffyLayoutEngine(Taffy::new())
@ -30,12 +45,17 @@ impl TaffyLayoutEngine {
&mut self, &mut self,
style: Style, style: Style,
rem_size: Pixels, rem_size: Pixels,
measure: impl FnOnce(Size<Option<Pixels>>, Size<AvailableSpace>) + 'static, measure: impl Fn(Size<Option<Pixels>>, Size<AvailableSpace>) -> Size<Pixels>
+ Send
+ Sync
+ 'static,
) -> Result<LayoutId> { ) -> Result<LayoutId> {
let style = style.to_taffy(rem_size); let style = style.to_taffy(rem_size);
self.0 let measurable = Box::new(Measureable(measure)) as Box<dyn Measurable>;
.new_leaf_with_measure(style, Box::new(Measureable(measure))) Ok(self
.0
.new_leaf_with_measure(style, MeasureFunc::Boxed(measurable))?)
} }
pub fn layout(&mut self, id: LayoutId) -> Result<Layout> { pub fn layout(&mut self, id: LayoutId) -> Result<Layout> {
@ -47,14 +67,18 @@ struct Measureable<F>(F);
impl<F> taffy::tree::Measurable for Measureable<F> impl<F> taffy::tree::Measurable for Measureable<F>
where where
F: Send + Sync + FnOnce(Size<Option<Pixels>>, Size<AvailableSpace>) -> Size<Pixels>, F: Send + Sync + Fn(Size<Option<Pixels>>, Size<AvailableSpace>) -> Size<Pixels>,
{ {
fn measure( fn measure(
&self, &self,
known_dimensions: taffy::prelude::Size<Option<f32>>, known_dimensions: TaffySize<Option<f32>>,
available_space: taffy::prelude::Size<AvailableSpace>, available_space: TaffySize<TaffyAvailableSpace>,
) -> taffy::prelude::Size<f32> { ) -> TaffySize<f32> {
(self.0)(known_dimensions.into(), available_space.into()).into() let known_dimensions: Size<Option<f32>> = known_dimensions.into();
let known_dimensions: Size<Option<Pixels>> = known_dimensions.map(|d| d.map(Into::into));
let available_space = available_space.into();
let size = (self.0)(known_dimensions, available_space);
size.into()
} }
} }
@ -232,14 +256,48 @@ where
} }
} }
impl<S, T: Clone + Default + Debug> From<taffy::geometry::Size<S>> for Size<T> impl<T: Into<U>, U: Clone + Debug> From<TaffySize<T>> for Size<U> {
where fn from(taffy_size: taffy::geometry::Size<T>) -> Self {
S: Into<T>, Size {
{ width: taffy_size.width.into(),
fn from(value: taffy::geometry::Size<S>) -> Self { height: taffy_size.height.into(),
Self { }
width: value.width.into(), }
height: value.height.into(), }
impl<T: Into<U> + Clone + Debug, U> From<Size<T>> for taffy::geometry::Size<U> {
fn from(size: Size<T>) -> Self {
taffy::geometry::Size {
width: size.width.into(),
height: size.height.into(),
}
}
}
// impl From<TaffySize<Option<f32>>> for Size<Option<Pixels>> {
// fn from(value: TaffySize<Option<f32>>) -> Self {
// Self {
// width: value.width.map(Into::into),
// height: value.height.map(Into::into),
// }
// }
// }
// impl From<TaffySize<TaffyAvailableSpace>> for Size<AvailableSpace> {
// fn from(taffy_size: TaffySize<TaffyAvailableSpace>) -> Self {
// Size {
// width: From::from(taffy_size.width),
// height: From::from(taffy_size.height),
// }
// }
// }
impl From<TaffyAvailableSpace> for AvailableSpace {
fn from(space: TaffyAvailableSpace) -> Self {
match space {
TaffyAvailableSpace::Definite(value) => AvailableSpace::Definite(Pixels(value)),
TaffyAvailableSpace::MinContent => AvailableSpace::MinContent,
TaffyAvailableSpace::MaxContent => AvailableSpace::MaxContent,
} }
} }
} }

View file

@ -1,4 +1,4 @@
use crate::{PlatformWindow, Point, Size, Style, TextStyle, TextStyleRefinement}; use crate::{AvailableSpace, PlatformWindow, Point, Size, Style, TextStyle, TextStyleRefinement};
use super::{ use super::{
px, taffy::LayoutId, AppContext, Bounds, Context, EntityId, Handle, Pixels, Reference, px, taffy::LayoutId, AppContext, Bounds, Context, EntityId, Handle, Pixels, Reference,
@ -11,7 +11,6 @@ use std::{
any::{Any, TypeId}, any::{Any, TypeId},
marker::PhantomData, marker::PhantomData,
}; };
use taffy::style::AvailableSpace;
pub struct AnyWindow {} pub struct AnyWindow {}
@ -75,7 +74,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
} }
pub fn request_measured_layout< pub fn request_measured_layout<
F: FnOnce(Size<Option<Pixels>>, Size<AvailableSpace>) + 'static, F: Fn(Size<Option<Pixels>>, Size<AvailableSpace>) -> Size<Pixels> + Send + Sync + 'static,
>( >(
&mut self, &mut self,
style: Style, style: Style,
@ -107,11 +106,12 @@ impl<'a, 'w> WindowContext<'a, 'w> {
self.window.text_style_stack.pop(); self.window.text_style_stack.pop();
} }
pub fn text_style(&self) -> &Vec<TextStyle> { pub fn text_style(&self) -> TextStyle {
let style = TextStyleRefinement::default(); let mut style = TextStyle::default();
for refinement in &self.window.text_style_stack { for refinement in &self.window.text_style_stack {
style.refine(refinement); style.refine(refinement);
} }
style
} }
pub fn mouse_position(&self) -> Point<Pixels> { pub fn mouse_position(&self) -> Point<Pixels> {