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 text;
use super::*;
pub use div::*;

View file

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

View file

@ -1,6 +1,5 @@
use crate::{
AnyElement, Element, IntoAnyElement, Layout, LayoutId, Line, LineLayout, Pixels, Result, Size,
ViewContext,
AnyElement, Element, IntoAnyElement, Layout, LayoutId, Line, Pixels, Result, Size, ViewContext,
};
use parking_lot::Mutex;
use std::{marker::PhantomData, sync::Arc};
@ -42,16 +41,18 @@ impl<S: 'static> Element for Text<S> {
) -> Result<(LayoutId, Self::FrameState)> {
let text_system = cx.text_system().clone();
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 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();
move |_, _| {
let line_layout = text_system.layout_str(
text.as_ref(),
text_style.font_size,
font_size,
&[(text.len(), text_style.to_run())],
);
@ -78,7 +79,7 @@ impl<S: 'static> Element for Text<S> {
_: &mut Self::State,
paint_state: &mut Self::FrameState,
cx: &mut ViewContext<S>,
) {
) -> Result<()> {
let bounds = layout.bounds;
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.");
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 }
}
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>> {
fn from(val: Size<Option<Pixels>>) -> Self {
Size {

View file

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

View file

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

View file

@ -4,9 +4,24 @@ use super::{
};
use std::fmt::Debug;
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);
#[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 {
pub fn new() -> Self {
TaffyLayoutEngine(Taffy::new())
@ -30,12 +45,17 @@ impl TaffyLayoutEngine {
&mut self,
style: Style,
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> {
let style = style.to_taffy(rem_size);
self.0
.new_leaf_with_measure(style, Box::new(Measureable(measure)))
let measurable = Box::new(Measureable(measure)) as Box<dyn Measurable>;
Ok(self
.0
.new_leaf_with_measure(style, MeasureFunc::Boxed(measurable))?)
}
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>
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(
&self,
known_dimensions: taffy::prelude::Size<Option<f32>>,
available_space: taffy::prelude::Size<AvailableSpace>,
) -> taffy::prelude::Size<f32> {
(self.0)(known_dimensions.into(), available_space.into()).into()
known_dimensions: TaffySize<Option<f32>>,
available_space: TaffySize<TaffyAvailableSpace>,
) -> TaffySize<f32> {
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>
where
S: Into<T>,
{
fn from(value: taffy::geometry::Size<S>) -> Self {
Self {
width: value.width.into(),
height: value.height.into(),
impl<T: Into<U>, U: Clone + Debug> From<TaffySize<T>> for Size<U> {
fn from(taffy_size: taffy::geometry::Size<T>) -> Self {
Size {
width: taffy_size.width.into(),
height: taffy_size.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::{
px, taffy::LayoutId, AppContext, Bounds, Context, EntityId, Handle, Pixels, Reference,
@ -11,7 +11,6 @@ use std::{
any::{Any, TypeId},
marker::PhantomData,
};
use taffy::style::AvailableSpace;
pub struct AnyWindow {}
@ -75,7 +74,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
}
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,
style: Style,
@ -107,11 +106,12 @@ impl<'a, 'w> WindowContext<'a, 'w> {
self.window.text_style_stack.pop();
}
pub fn text_style(&self) -> &Vec<TextStyle> {
let style = TextStyleRefinement::default();
pub fn text_style(&self) -> TextStyle {
let mut style = TextStyle::default();
for refinement in &self.window.text_style_stack {
style.refine(refinement);
}
style
}
pub fn mouse_position(&self) -> Point<Pixels> {