Checkpoint
This commit is contained in:
parent
7f9e3bc787
commit
da211bef96
10 changed files with 215 additions and 81 deletions
|
@ -45,6 +45,7 @@ fn generate_shader_bindings() -> PathBuf {
|
|||
"Pixels".into(),
|
||||
"PointF".into(),
|
||||
"Hsla".into(),
|
||||
"ScaledContentMask".into(),
|
||||
"Uniforms".into(),
|
||||
"AtlasTile".into(),
|
||||
"Quad".into(),
|
||||
|
@ -58,12 +59,14 @@ fn generate_shader_bindings() -> PathBuf {
|
|||
.with_src(crate_dir.join("src/scene.rs"))
|
||||
.with_src(crate_dir.join("src/geometry.rs"))
|
||||
.with_src(crate_dir.join("src/color.rs"))
|
||||
.with_src(crate_dir.join("src/window.rs"))
|
||||
.with_src(crate_dir.join("src/platform.rs"))
|
||||
.with_src(crate_dir.join("src/platform/mac/metal_renderer.rs"))
|
||||
.with_config(config)
|
||||
.generate()
|
||||
.expect("Unable to generate bindings")
|
||||
.write_to_file(&output_path);
|
||||
|
||||
output_path
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
AnyElement, Bounds, Element, Layout, LayoutId, Overflow, ParentElement, Pixels, Point,
|
||||
Refineable, RefinementCascade, Result, StackContext, Style, StyleHelpers, Styled, ViewContext,
|
||||
Refineable, RefinementCascade, Result, Style, StyleHelpers, Styled, ViewContext,
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use smallvec::SmallVec;
|
||||
|
@ -33,16 +33,9 @@ impl<S: 'static + Send + Sync> Element for Div<S> {
|
|||
cx: &mut ViewContext<S>,
|
||||
) -> Result<(LayoutId, Self::FrameState)> {
|
||||
let style = self.computed_style();
|
||||
let child_layout_ids = if let Some(text_style) = style.text_style(cx) {
|
||||
cx.with_text_style(text_style.clone(), |cx| self.layout_children(view, cx))?
|
||||
} else {
|
||||
self.layout_children(view, cx)?
|
||||
};
|
||||
|
||||
Ok((
|
||||
cx.request_layout(style.into(), child_layout_ids.clone())?,
|
||||
child_layout_ids,
|
||||
))
|
||||
let child_layout_ids = style.apply_text_style(cx, |cx| self.layout_children(view, cx))?;
|
||||
let layout_id = cx.request_layout(style.into(), child_layout_ids.clone())?;
|
||||
Ok((layout_id, child_layout_ids))
|
||||
}
|
||||
|
||||
fn paint(
|
||||
|
@ -56,20 +49,18 @@ impl<S: 'static + Send + Sync> Element for Div<S> {
|
|||
|
||||
let style = self.computed_style();
|
||||
style.paint(order, bounds, cx);
|
||||
let overflow = &style.overflow;
|
||||
// // todo!("support only one dimension being hidden")
|
||||
// if style.overflow.y != Overflow::Visible || style.overflow.x != Overflow::Visible {
|
||||
// cx.scene().push_layer(Some(bounds));
|
||||
// pop_layer = true;
|
||||
// }
|
||||
if let Some(text_style) = style.text_style(cx) {
|
||||
cx.with_text_style(text_style.clone(), |cx| {
|
||||
self.paint_children(overflow, state, cx)
|
||||
})?;
|
||||
} else {
|
||||
self.paint_children(overflow, state, cx)?;
|
||||
}
|
||||
|
||||
// // todo!("support only one dimension being hidden")
|
||||
let overflow = &style.overflow;
|
||||
// if style.overflow.y != Overflow::Visible || style.overflow.x != Overflow::Visible {
|
||||
// cx.clip(layout.bounds, style.corner_radii, || )
|
||||
// }
|
||||
|
||||
style.apply_text_style(cx, |cx| {
|
||||
style.apply_overflow(layout.bounds, cx, |cx| {
|
||||
self.paint_children(overflow, state, cx)
|
||||
})
|
||||
})?;
|
||||
self.handle_scroll(order, bounds, style.overflow.clone(), child_layouts, cx);
|
||||
|
||||
// todo!("enable inspector")
|
||||
|
|
|
@ -225,6 +225,20 @@ pub struct Bounds<T: Clone + Debug> {
|
|||
pub size: Size<T>,
|
||||
}
|
||||
|
||||
impl<T: Clone + Debug + Sub<Output = T>> Bounds<T> {
|
||||
pub fn from_corners(upper_left: Point<T>, lower_right: Point<T>) -> Self {
|
||||
let origin = Point {
|
||||
x: upper_left.x.clone(),
|
||||
y: upper_left.y.clone(),
|
||||
};
|
||||
let size = Size {
|
||||
width: lower_right.x - upper_left.x,
|
||||
height: lower_right.y - upper_left.y,
|
||||
};
|
||||
Bounds { origin, size }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Rhs> Mul<Rhs> for Bounds<T>
|
||||
where
|
||||
T: Mul<Rhs, Output = Rhs> + Clone + Debug,
|
||||
|
@ -418,6 +432,28 @@ pub struct Corners<T: Clone + Debug> {
|
|||
pub bottom_left: T,
|
||||
}
|
||||
|
||||
impl Corners<AbsoluteLength> {
|
||||
pub fn to_pixels(&self, rem_size: Pixels) -> Corners<Pixels> {
|
||||
Corners {
|
||||
top_left: self.top_left.to_pixels(rem_size),
|
||||
top_right: self.top_right.to_pixels(rem_size),
|
||||
bottom_right: self.bottom_right.to_pixels(rem_size),
|
||||
bottom_left: self.bottom_left.to_pixels(rem_size),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Corners<Pixels> {
|
||||
pub fn scale(&self, factor: f32) -> Corners<ScaledPixels> {
|
||||
Corners {
|
||||
top_left: self.top_left.scale(factor),
|
||||
top_right: self.top_right.scale(factor),
|
||||
bottom_right: self.bottom_right.scale(factor),
|
||||
bottom_left: self.bottom_left.scale(factor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + Debug> Corners<T> {
|
||||
pub fn map<U: Clone + Debug, F: Fn(&T) -> U>(&self, f: F) -> Corners<U> {
|
||||
Corners {
|
||||
|
|
|
@ -84,16 +84,16 @@ impl<T> DerefMut for MainThread<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait StackContext {
|
||||
fn app(&mut self) -> &mut AppContext;
|
||||
pub trait BorrowAppContext {
|
||||
fn app_mut(&mut self) -> &mut AppContext;
|
||||
|
||||
fn with_text_style<F, R>(&mut self, style: TextStyleRefinement, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut Self) -> R,
|
||||
{
|
||||
self.app().push_text_style(style);
|
||||
self.app_mut().push_text_style(style);
|
||||
let result = f(self);
|
||||
self.app().pop_text_style();
|
||||
self.app_mut().pop_text_style();
|
||||
result
|
||||
}
|
||||
|
||||
|
@ -101,9 +101,9 @@ pub trait StackContext {
|
|||
where
|
||||
F: FnOnce(&mut Self) -> R,
|
||||
{
|
||||
self.app().push_state(state);
|
||||
self.app_mut().push_state(state);
|
||||
let result = f(self);
|
||||
self.app().pop_state::<T>();
|
||||
self.app_mut().pop_state::<T>();
|
||||
result
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
using namespace metal;
|
||||
|
||||
float4 hsla_to_rgba(Hsla hsla);
|
||||
float4 to_device_position(float2 unit_vertex, Bounds_Pixels bounds,
|
||||
Bounds_Pixels clip_bounds,
|
||||
float4 to_device_position(float2 unit_vertex, Bounds_ScaledPixels bounds,
|
||||
Bounds_ScaledPixels clip_bounds,
|
||||
constant Size_DevicePixels *viewport_size);
|
||||
float quad_sdf(float2 point, Bounds_Pixels bounds, Corners_Pixels corner_radii);
|
||||
float quad_sdf(float2 point, Bounds_ScaledPixels bounds, Corners_ScaledPixels corner_radii);
|
||||
|
||||
struct QuadVertexOutput {
|
||||
float4 position [[position]];
|
||||
|
@ -131,7 +131,7 @@ vertex MonochromeSpriteVertexOutput monochrome_sprite_vertex(
|
|||
float2 unit_vertex = unit_vertices[unit_vertex_id];
|
||||
MonochromeSprite sprite = sprites[sprite_id];
|
||||
float4 device_position = to_device_position(
|
||||
unit_vertex, sprite.bounds, sprite.clip_bounds, viewport_size);
|
||||
unit_vertex, sprite.bounds, sprite.content_mask.bounds, viewport_size);
|
||||
|
||||
float2 tile_origin =
|
||||
float2(sprite.tile.bounds.origin.x, sprite.tile.bounds.origin.y);
|
||||
|
@ -157,7 +157,7 @@ fragment float4 monochrome_sprite_fragment(
|
|||
float4 sample =
|
||||
atlas_texture.sample(atlas_texture_sampler, input.tile_position);
|
||||
float clip_distance =
|
||||
quad_sdf(input.position.xy, sprite.clip_bounds, sprite.clip_corner_radii);
|
||||
quad_sdf(input.position.xy, sprite.content_mask.bounds, sprite.content_mask.corner_radii);
|
||||
float4 color = input.color;
|
||||
color.a *= sample.a * saturate(0.5 - clip_distance);
|
||||
return color;
|
||||
|
@ -211,8 +211,8 @@ float4 hsla_to_rgba(Hsla hsla) {
|
|||
return rgba;
|
||||
}
|
||||
|
||||
float4 to_device_position(float2 unit_vertex, Bounds_Pixels bounds,
|
||||
Bounds_Pixels clip_bounds,
|
||||
float4 to_device_position(float2 unit_vertex, Bounds_ScaledPixels bounds,
|
||||
Bounds_ScaledPixels clip_bounds,
|
||||
constant Size_DevicePixels *input_viewport_size) {
|
||||
float2 position =
|
||||
unit_vertex * float2(bounds.size.width, bounds.size.height) +
|
||||
|
@ -229,8 +229,8 @@ float4 to_device_position(float2 unit_vertex, Bounds_Pixels bounds,
|
|||
return float4(device_position, 0., 1.);
|
||||
}
|
||||
|
||||
float quad_sdf(float2 point, Bounds_Pixels bounds,
|
||||
Corners_Pixels corner_radii) {
|
||||
float quad_sdf(float2 point, Bounds_ScaledPixels bounds,
|
||||
Corners_ScaledPixels corner_radii) {
|
||||
float2 half_size = float2(bounds.size.width, bounds.size.height) / 2.;
|
||||
float2 center = float2(bounds.origin.x, bounds.origin.y) + half_size;
|
||||
float2 center_to_point = point - center;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::{iter::Peekable, mem};
|
||||
|
||||
use super::{Bounds, Hsla, Point};
|
||||
use crate::{AtlasTextureId, AtlasTile, Corners, Edges, ScaledPixels};
|
||||
use crate::{AtlasTextureId, AtlasTile, Corners, Edges, ScaledContentMask, ScaledPixels};
|
||||
use collections::BTreeMap;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
@ -234,8 +234,7 @@ impl From<Quad> for Primitive {
|
|||
pub struct MonochromeSprite {
|
||||
pub order: u32,
|
||||
pub bounds: Bounds<ScaledPixels>,
|
||||
pub clip_bounds: Bounds<ScaledPixels>,
|
||||
pub clip_corner_radii: Corners<ScaledPixels>,
|
||||
pub content_mask: ScaledContentMask,
|
||||
pub color: Hsla,
|
||||
pub tile: AtlasTile,
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::{
|
||||
phi, rems, AbsoluteLength, Bounds, Corners, CornersRefinement, DefiniteLength, Edges,
|
||||
EdgesRefinement, Font, FontFeatures, FontStyle, FontWeight, Hsla, Length, Pixels, Point,
|
||||
PointRefinement, Quad, Rems, Result, RunStyle, SharedString, Size, SizeRefinement, ViewContext,
|
||||
WindowContext,
|
||||
phi, point, rems, AbsoluteLength, BorrowAppContext, BorrowWindow, Bounds, ContentMask, Corners,
|
||||
CornersRefinement, DefiniteLength, Edges, EdgesRefinement, Font, FontFeatures, FontStyle,
|
||||
FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Quad, Rems, Result, RunStyle,
|
||||
SharedString, Size, SizeRefinement, ViewContext, WindowContext,
|
||||
};
|
||||
use refineable::Refineable;
|
||||
pub use taffy::style::{
|
||||
|
@ -179,6 +179,57 @@ impl Style {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn apply_text_style<C, F, R>(&self, cx: &mut C, f: F) -> R
|
||||
where
|
||||
C: BorrowAppContext,
|
||||
F: FnOnce(&mut C) -> R,
|
||||
{
|
||||
if self.text.is_some() {
|
||||
cx.with_text_style(self.text.clone(), f)
|
||||
} else {
|
||||
f(cx)
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply overflow to content mask
|
||||
pub fn apply_overflow<C, F, R>(&self, bounds: Bounds<Pixels>, cx: &mut C, f: F) -> R
|
||||
where
|
||||
C: BorrowWindow,
|
||||
F: FnOnce(&mut C) -> R,
|
||||
{
|
||||
let current_mask = cx.content_mask();
|
||||
|
||||
let min = current_mask.bounds.origin;
|
||||
let max = current_mask.bounds.lower_right();
|
||||
|
||||
let mask_corner_radii = Corners::default();
|
||||
let mask_bounds = match (
|
||||
self.overflow.x == Overflow::Visible,
|
||||
self.overflow.y == Overflow::Visible,
|
||||
) {
|
||||
// x and y both visible
|
||||
(true, true) => return f(cx),
|
||||
// x visible, y hidden
|
||||
(true, false) => Bounds::from_corners(
|
||||
point(min.x, bounds.origin.y),
|
||||
point(max.x, bounds.lower_right().y),
|
||||
),
|
||||
// x hidden, y visible
|
||||
(false, true) => Bounds::from_corners(
|
||||
point(bounds.origin.x, min.y),
|
||||
point(bounds.lower_right().x, max.y),
|
||||
),
|
||||
// both hidden
|
||||
(false, false) => bounds,
|
||||
};
|
||||
let mask = ContentMask {
|
||||
bounds: mask_bounds,
|
||||
corner_radii: mask_corner_radii,
|
||||
};
|
||||
|
||||
cx.with_content_mask(mask, f)
|
||||
}
|
||||
|
||||
/// Paints the background of an element styled with this style.
|
||||
pub fn paint<V: 'static>(&self, order: u32, bounds: Bounds<Pixels>, cx: &mut ViewContext<V>) {
|
||||
let rem_size = cx.rem_size();
|
||||
|
|
|
@ -2,12 +2,6 @@ use smol::future::FutureExt;
|
|||
use std::{future::Future, time::Duration};
|
||||
pub use util::*;
|
||||
|
||||
pub fn post_inc(value: &mut usize) -> usize {
|
||||
let prev = *value;
|
||||
*value += 1;
|
||||
prev
|
||||
}
|
||||
|
||||
pub async fn timeout<F, T>(timeout: Duration, f: F) -> Result<T, ()>
|
||||
where
|
||||
F: Future<Output = T>,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::{
|
||||
px, AnyView, AppContext, AvailableSpace, Bounds, Context, Corners, Effect, Element, EntityId,
|
||||
FontId, GlyphId, GlyphRasterParams, Handle, Hsla, IsZero, LayerId, LayoutId, MainThread,
|
||||
MainThreadOnly, MonochromeSprite, Pixels, PlatformAtlas, PlatformWindow, Point, Reference,
|
||||
Scene, Size, StackContext, Style, TaffyLayoutEngine, WeakHandle, WindowOptions,
|
||||
px, AnyView, AppContext, AvailableSpace, BorrowAppContext, Bounds, Context, Corners, Effect,
|
||||
Element, EntityId, FontId, GlyphId, GlyphRasterParams, Handle, Hsla, IsZero, LayerId, LayoutId,
|
||||
MainThread, MainThreadOnly, MonochromeSprite, Pixels, PlatformAtlas, PlatformWindow, Point,
|
||||
Reference, ScaledPixels, Scene, Size, Style, TaffyLayoutEngine, WeakHandle, WindowOptions,
|
||||
SUBPIXEL_VARIANTS,
|
||||
};
|
||||
use anyhow::Result;
|
||||
|
@ -74,8 +74,24 @@ impl Window {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ContentMask {
|
||||
bounds: Bounds<Pixels>,
|
||||
corner_radii: Corners<Pixels>,
|
||||
pub bounds: Bounds<Pixels>,
|
||||
pub corner_radii: Corners<Pixels>,
|
||||
}
|
||||
|
||||
impl ContentMask {
|
||||
pub fn scale(&self, factor: f32) -> ScaledContentMask {
|
||||
ScaledContentMask {
|
||||
bounds: self.bounds.scale(factor),
|
||||
corner_radii: self.corner_radii.scale(factor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(C)]
|
||||
pub struct ScaledContentMask {
|
||||
bounds: Bounds<ScaledPixels>,
|
||||
corner_radii: Corners<ScaledPixels>,
|
||||
}
|
||||
|
||||
pub struct WindowContext<'a, 'w> {
|
||||
|
@ -174,20 +190,6 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
|||
self.window.current_layer_id.clone()
|
||||
}
|
||||
|
||||
pub fn current_clipping_mask(&self) -> ContentMask {
|
||||
self.window
|
||||
.content_mask_stack
|
||||
.last()
|
||||
.cloned()
|
||||
.unwrap_or_else(|| ContentMask {
|
||||
bounds: Bounds {
|
||||
origin: Point::default(),
|
||||
size: self.window.content_size,
|
||||
},
|
||||
corner_radii: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn run_on_main<R>(
|
||||
&self,
|
||||
f: impl FnOnce(&mut MainThread<WindowContext>) -> R + Send + 'static,
|
||||
|
@ -239,14 +241,14 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
|||
origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
|
||||
size: tile.bounds.size.map(Into::into),
|
||||
};
|
||||
let content_mask = self.content_mask().scale(scale_factor);
|
||||
|
||||
self.window.scene.insert(
|
||||
layer_id,
|
||||
MonochromeSprite {
|
||||
order,
|
||||
bounds,
|
||||
clip_bounds: bounds,
|
||||
clip_corner_radii: Default::default(),
|
||||
content_mask,
|
||||
color,
|
||||
tile,
|
||||
},
|
||||
|
@ -330,8 +332,60 @@ impl<'a, 'w> std::ops::DerefMut for WindowContext<'a, 'w> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> StackContext for ViewContext<'_, '_, S> {
|
||||
fn app(&mut self) -> &mut AppContext {
|
||||
impl BorrowAppContext for WindowContext<'_, '_> {
|
||||
fn app_mut(&mut self) -> &mut AppContext {
|
||||
&mut *self.app
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BorrowWindow: BorrowAppContext {
|
||||
fn window(&self) -> &Window;
|
||||
fn window_mut(&mut self) -> &mut Window;
|
||||
|
||||
fn with_content_mask<R>(&mut self, mask: ContentMask, f: impl FnOnce(&mut Self) -> R) -> R {
|
||||
self.window_mut().content_mask_stack.push(mask);
|
||||
let result = f(self);
|
||||
self.window_mut().content_mask_stack.pop();
|
||||
result
|
||||
}
|
||||
|
||||
fn content_mask(&self) -> ContentMask {
|
||||
self.window()
|
||||
.content_mask_stack
|
||||
.last()
|
||||
.cloned()
|
||||
.unwrap_or_else(|| ContentMask {
|
||||
bounds: Bounds {
|
||||
origin: Point::default(),
|
||||
size: self.window().content_size,
|
||||
},
|
||||
corner_radii: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
fn rem_size(&self) -> Pixels {
|
||||
self.window().rem_size
|
||||
}
|
||||
}
|
||||
|
||||
impl BorrowWindow for WindowContext<'_, '_> {
|
||||
fn window(&self) -> &Window {
|
||||
&*self.window
|
||||
}
|
||||
|
||||
fn window_mut(&mut self) -> &mut Window {
|
||||
&mut *self.window
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ViewContext<'a, 'w, S> {
|
||||
window_cx: WindowContext<'a, 'w>,
|
||||
entity_type: PhantomData<S>,
|
||||
entity_id: EntityId,
|
||||
}
|
||||
|
||||
impl<S> BorrowAppContext for ViewContext<'_, '_, S> {
|
||||
fn app_mut(&mut self) -> &mut AppContext {
|
||||
&mut *self.window_cx.app
|
||||
}
|
||||
|
||||
|
@ -356,10 +410,14 @@ impl<S> StackContext for ViewContext<'_, '_, S> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct ViewContext<'a, 'w, S> {
|
||||
window_cx: WindowContext<'a, 'w>,
|
||||
entity_type: PhantomData<S>,
|
||||
entity_id: EntityId,
|
||||
impl<S> BorrowWindow for ViewContext<'_, '_, S> {
|
||||
fn window(&self) -> &Window {
|
||||
&self.window_cx.window
|
||||
}
|
||||
|
||||
fn window_mut(&mut self) -> &mut Window {
|
||||
&mut *self.window_cx.window
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'w, S: Send + Sync + 'static> ViewContext<'a, 'w, S> {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use gpui3::{Element, Hsla, Layout, LayoutId, Result, StackContext, ViewContext, WindowContext};
|
||||
use gpui3::{
|
||||
BorrowAppContext, Element, Hsla, Layout, LayoutId, Result, ViewContext, WindowContext,
|
||||
};
|
||||
use serde::{de::Visitor, Deserialize, Deserializer};
|
||||
use std::{collections::HashMap, fmt};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue