Detailed changes
@@ -3,7 +3,7 @@ use crate::{
};
use parking_lot::Mutex;
use std::{marker::PhantomData, sync::Arc};
-use util::{arc_cow::ArcCow, ResultExt};
+use util::arc_cow::ArcCow;
impl<S: 'static> IntoAnyElement<S> for ArcCow<'static, str> {
fn into_any(self) -> AnyElement<S> {
@@ -92,8 +92,6 @@ impl<S: 'static> Element for Text<S> {
paint_state: &mut Self::FrameState,
cx: &mut ViewContext<S>,
) -> Result<()> {
- let bounds = layout.bounds;
-
let line;
let line_height;
{
@@ -108,8 +106,8 @@ impl<S: 'static> Element for Text<S> {
let _text_style = cx.text_style();
// 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)?;
+ let visible_bounds = layout.bounds;
+ line.paint(&layout, visible_bounds, line_height, cx)?;
Ok(())
}
@@ -425,7 +425,9 @@ unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Corners<T> {}
unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Corners<T> {}
-#[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd)]
+#[derive(
+ Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd, Zeroable, Pod,
+)]
#[repr(transparent)]
pub struct Pixels(pub(crate) f32);
@@ -445,6 +447,12 @@ impl Mul<Pixels> for f32 {
}
}
+impl MulAssign<f32> for Pixels {
+ fn mul_assign(&mut self, other: f32) {
+ self.0 *= other;
+ }
+}
+
impl Pixels {
pub fn round(&self) -> Self {
Self(self.0.round())
@@ -489,9 +497,6 @@ impl From<f32> for Pixels {
}
}
-unsafe impl bytemuck::Pod for Pixels {}
-unsafe impl bytemuck::Zeroable for Pixels {}
-
impl Debug for Pixels {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} px", self.0)
@@ -7,174 +7,194 @@ float4 hsla_to_rgba(Hsla hsla);
float4 to_device_position(float2 pixel_position, float2 viewport_size);
struct QuadVertexOutput {
- float4 position [[position]];
- float4 background_color;
- float4 border_color;
- uint quad_id;
+ float4 position [[position]];
+ float4 background_color;
+ float4 border_color;
+ uint quad_id;
};
vertex QuadVertexOutput quad_vertex(
- uint unit_vertex_id [[vertex_id]],
- uint quad_id [[instance_id]],
+ uint unit_vertex_id [[vertex_id]], uint quad_id [[instance_id]],
constant float2 *unit_vertices [[buffer(QuadInputIndex_Vertices)]],
constant Quad *quads [[buffer(QuadInputIndex_Quads)]],
- constant QuadUniforms *uniforms [[buffer(QuadInputIndex_Uniforms)]]
-) {
- float2 unit_vertex = unit_vertices[unit_vertex_id];
- Quad quad = quads[quad_id];
- float2 position_2d = unit_vertex * float2(quad.bounds.size.width, quad.bounds.size.height) + float2(quad.bounds.origin.x, quad.bounds.origin.y);
- position_2d.x = max(quad.clip_bounds.origin.x, position_2d.x);
- position_2d.x = min(quad.clip_bounds.origin.x + quad.clip_bounds.size.width, position_2d.x);
- position_2d.y = max(quad.clip_bounds.origin.y, position_2d.y);
- position_2d.y = min(quad.clip_bounds.origin.y + quad.clip_bounds.size.height, position_2d.y);
-
- float2 viewport_size = float2((float)uniforms->viewport_size.width, (float)uniforms->viewport_size.height);
- float4 device_position = to_device_position(position_2d, viewport_size);
- float4 background_color = hsla_to_rgba(quad.background);
- float4 border_color = hsla_to_rgba(quad.border_color);
- return QuadVertexOutput {
- device_position,
- background_color,
- border_color,
- quad_id
- };
+ constant QuadUniforms *uniforms [[buffer(QuadInputIndex_Uniforms)]]) {
+ float2 unit_vertex = unit_vertices[unit_vertex_id];
+ Quad quad = quads[quad_id];
+ float2 position_2d =
+ unit_vertex * float2(quad.bounds.size.width, quad.bounds.size.height) +
+ float2(quad.bounds.origin.x, quad.bounds.origin.y);
+ position_2d.x = max(quad.clip_bounds.origin.x, position_2d.x);
+ position_2d.x = min(quad.clip_bounds.origin.x + quad.clip_bounds.size.width,
+ position_2d.x);
+ position_2d.y = max(quad.clip_bounds.origin.y, position_2d.y);
+ position_2d.y = min(quad.clip_bounds.origin.y + quad.clip_bounds.size.height,
+ position_2d.y);
+
+ float2 viewport_size = float2((float)uniforms->viewport_size.width,
+ (float)uniforms->viewport_size.height);
+ float4 device_position = to_device_position(position_2d, viewport_size);
+ float4 background_color = hsla_to_rgba(quad.background);
+ float4 border_color = hsla_to_rgba(quad.border_color);
+ return QuadVertexOutput{device_position, background_color, border_color,
+ quad_id};
}
-float quad_sdf(float2 point, Bounds_Pixels bounds, Corners_Pixels 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;
- float corner_radius;
- if (center_to_point.x < 0.) {
- if (center_to_point.y < 0.) {
- corner_radius = corner_radii.top_left;
- } else {
- corner_radius = corner_radii.bottom_left;
- }
+float quad_sdf(float2 point, Bounds_Pixels bounds,
+ Corners_Pixels 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;
+ float corner_radius;
+ if (center_to_point.x < 0.) {
+ if (center_to_point.y < 0.) {
+ corner_radius = corner_radii.top_left;
} else {
- if (center_to_point.y < 0.) {
- corner_radius = corner_radii.top_right;
- } else {
- corner_radius = corner_radii.bottom_right;
- }
+ corner_radius = corner_radii.bottom_left;
}
+ } else {
+ if (center_to_point.y < 0.) {
+ corner_radius = corner_radii.top_right;
+ } else {
+ corner_radius = corner_radii.bottom_right;
+ }
+ }
- float2 rounded_edge_to_point = abs(center_to_point) - half_size + corner_radius;
- float distance = length(max(0., rounded_edge_to_point))
- + min(0., max(rounded_edge_to_point.x, rounded_edge_to_point.y))
- - corner_radius;
+ float2 rounded_edge_to_point =
+ abs(center_to_point) - half_size + corner_radius;
+ float distance =
+ length(max(0., rounded_edge_to_point)) +
+ min(0., max(rounded_edge_to_point.x, rounded_edge_to_point.y)) -
+ corner_radius;
- return distance;
+ return distance;
}
-fragment float4 quad_fragment(
- QuadVertexOutput input [[stage_in]],
- constant Quad *quads [[buffer(QuadInputIndex_Quads)]]
-) {
- Quad quad = quads[input.quad_id];
- float2 half_size = float2(quad.bounds.size.width, quad.bounds.size.height) / 2.;
- float2 center = float2(quad.bounds.origin.x, quad.bounds.origin.y) + half_size;
- float2 center_to_point = input.position.xy - center;
- float corner_radius;
- if (center_to_point.x < 0.) {
- if (center_to_point.y < 0.) {
- corner_radius = quad.corner_radii.top_left;
- } else {
- corner_radius = quad.corner_radii.bottom_left;
- }
- } else {
- if (center_to_point.y < 0.) {
- corner_radius = quad.corner_radii.top_right;
- } else {
- corner_radius = quad.corner_radii.bottom_right;
- }
- }
-
- float2 rounded_edge_to_point = fabs(center_to_point) - half_size + corner_radius;
- float distance = length(max(0., rounded_edge_to_point)) + min(0., max(rounded_edge_to_point.x, rounded_edge_to_point.y)) - corner_radius;
-
- float vertical_border = center_to_point.x <= 0. ? quad.border_widths.left : quad.border_widths.right;
- float horizontal_border = center_to_point.y <= 0. ? quad.border_widths.top : quad.border_widths.bottom;
- float2 inset_size = half_size - corner_radius - float2(vertical_border, horizontal_border);
- float2 point_to_inset_corner = fabs(center_to_point) - inset_size;
- float border_width;
- if (point_to_inset_corner.x < 0. && point_to_inset_corner.y < 0.) {
- border_width = 0.;
- } else if (point_to_inset_corner.y > point_to_inset_corner.x) {
- border_width = horizontal_border;
+fragment float4 quad_fragment(QuadVertexOutput input [[stage_in]],
+ constant Quad *quads
+ [[buffer(QuadInputIndex_Quads)]]) {
+ Quad quad = quads[input.quad_id];
+ float2 half_size =
+ float2(quad.bounds.size.width, quad.bounds.size.height) / 2.;
+ float2 center =
+ float2(quad.bounds.origin.x, quad.bounds.origin.y) + half_size;
+ float2 center_to_point = input.position.xy - center;
+ float corner_radius;
+ if (center_to_point.x < 0.) {
+ if (center_to_point.y < 0.) {
+ corner_radius = quad.corner_radii.top_left;
} else {
- border_width = vertical_border;
+ corner_radius = quad.corner_radii.bottom_left;
}
-
- float4 color;
- if (border_width == 0.) {
- color = input.background_color;
+ } else {
+ if (center_to_point.y < 0.) {
+ corner_radius = quad.corner_radii.top_right;
} else {
- float inset_distance = distance + border_width;
-
- // Decrease border's opacity as we move inside the background.
- input.border_color.a *= 1. - saturate(0.5 - inset_distance);
-
- // Alpha-blend the border and the background.
- float output_alpha = quad.border_color.a + quad.background.a * (1. - quad.border_color.a);
- float3 premultiplied_border_rgb = input.border_color.rgb * quad.border_color.a;
- float3 premultiplied_background_rgb = input.background_color.rgb * input.background_color.a;
- float3 premultiplied_output_rgb = premultiplied_border_rgb + premultiplied_background_rgb * (1. - input.border_color.a);
- color = float4(premultiplied_output_rgb, output_alpha);
+ corner_radius = quad.corner_radii.bottom_right;
}
-
- float clip_distance = quad_sdf(input.position.xy, quad.clip_bounds, quad.clip_corner_radii);
- return color * float4(1., 1., 1., saturate(0.5 - distance) * saturate(0.5 - clip_distance));
+ }
+
+ float2 rounded_edge_to_point =
+ fabs(center_to_point) - half_size + corner_radius;
+ float distance =
+ length(max(0., rounded_edge_to_point)) +
+ min(0., max(rounded_edge_to_point.x, rounded_edge_to_point.y)) -
+ corner_radius;
+
+ float vertical_border = center_to_point.x <= 0. ? quad.border_widths.left
+ : quad.border_widths.right;
+ float horizontal_border = center_to_point.y <= 0. ? quad.border_widths.top
+ : quad.border_widths.bottom;
+ float2 inset_size =
+ half_size - corner_radius - float2(vertical_border, horizontal_border);
+ float2 point_to_inset_corner = fabs(center_to_point) - inset_size;
+ float border_width;
+ if (point_to_inset_corner.x < 0. && point_to_inset_corner.y < 0.) {
+ border_width = 0.;
+ } else if (point_to_inset_corner.y > point_to_inset_corner.x) {
+ border_width = horizontal_border;
+ } else {
+ border_width = vertical_border;
+ }
+
+ float4 color;
+ if (border_width == 0.) {
+ color = input.background_color;
+ } else {
+ float inset_distance = distance + border_width;
+
+ // Decrease border's opacity as we move inside the background.
+ input.border_color.a *= 1. - saturate(0.5 - inset_distance);
+
+ // Alpha-blend the border and the background.
+ float output_alpha =
+ quad.border_color.a + quad.background.a * (1. - quad.border_color.a);
+ float3 premultiplied_border_rgb =
+ input.border_color.rgb * quad.border_color.a;
+ float3 premultiplied_background_rgb =
+ input.background_color.rgb * input.background_color.a;
+ float3 premultiplied_output_rgb =
+ premultiplied_border_rgb +
+ premultiplied_background_rgb * (1. - input.border_color.a);
+ color = float4(premultiplied_output_rgb, output_alpha);
+ }
+
+ float clip_distance =
+ quad_sdf(input.position.xy, quad.clip_bounds, quad.clip_corner_radii);
+ return color *
+ float4(1., 1., 1.,
+ saturate(0.5 - distance) * saturate(0.5 - clip_distance));
}
float4 hsla_to_rgba(Hsla hsla) {
- float h = hsla.h * 6.0; // Now, it's an angle but scaled in [0, 6) range
- float s = hsla.s;
- float l = hsla.l;
- float a = hsla.a;
-
- float c = (1.0 - fabs(2.0*l - 1.0)) * s;
- float x = c * (1.0 - fabs(fmod(h, 2.0) - 1.0));
- float m = l - c/2.0;
-
- float r = 0.0;
- float g = 0.0;
- float b = 0.0;
-
- if (h >= 0.0 && h < 1.0) {
- r = c;
- g = x;
- b = 0.0;
- } else if (h >= 1.0 && h < 2.0) {
- r = x;
- g = c;
- b = 0.0;
- } else if (h >= 2.0 && h < 3.0) {
- r = 0.0;
- g = c;
- b = x;
- } else if (h >= 3.0 && h < 4.0) {
- r = 0.0;
- g = x;
- b = c;
- } else if (h >= 4.0 && h < 5.0) {
- r = x;
- g = 0.0;
- b = c;
- } else {
- r = c;
- g = 0.0;
- b = x;
- }
-
- float4 rgba;
- rgba.x = (r + m);
- rgba.y = (g + m);
- rgba.z = (b + m);
- rgba.w = a;
- return rgba;
+ float h = hsla.h * 6.0; // Now, it's an angle but scaled in [0, 6) range
+ float s = hsla.s;
+ float l = hsla.l;
+ float a = hsla.a;
+
+ float c = (1.0 - fabs(2.0 * l - 1.0)) * s;
+ float x = c * (1.0 - fabs(fmod(h, 2.0) - 1.0));
+ float m = l - c / 2.0;
+
+ float r = 0.0;
+ float g = 0.0;
+ float b = 0.0;
+
+ if (h >= 0.0 && h < 1.0) {
+ r = c;
+ g = x;
+ b = 0.0;
+ } else if (h >= 1.0 && h < 2.0) {
+ r = x;
+ g = c;
+ b = 0.0;
+ } else if (h >= 2.0 && h < 3.0) {
+ r = 0.0;
+ g = c;
+ b = x;
+ } else if (h >= 3.0 && h < 4.0) {
+ r = 0.0;
+ g = x;
+ b = c;
+ } else if (h >= 4.0 && h < 5.0) {
+ r = x;
+ g = 0.0;
+ b = c;
+ } else {
+ r = c;
+ g = 0.0;
+ b = x;
+ }
+
+ float4 rgba;
+ rgba.x = (r + m);
+ rgba.y = (g + m);
+ rgba.z = (b + m);
+ rgba.w = a;
+ return rgba;
}
float4 to_device_position(float2 pixel_position, float2 viewport_size) {
- return float4(pixel_position / viewport_size * float2(2., -2.) + float2(-1., 1.), 0., 1.);
+ return float4(pixel_position / viewport_size * float2(2., -2.) +
+ float2(-1., 1.),
+ 0., 1.);
}
@@ -1,7 +1,7 @@
use std::mem;
use super::{Bounds, Hsla, Pixels, Point};
-use crate::{Corners, Edges};
+use crate::{Corners, Edges, FontId, GlyphId};
use bytemuck::{Pod, Zeroable};
use collections::BTreeMap;
@@ -17,6 +17,7 @@ pub struct Scene {
#[derive(Default, Debug)]
pub struct SceneLayer {
pub quads: Vec<Quad>,
+ pub symbol: Vec<Symbol>,
}
impl Scene {
@@ -40,6 +41,7 @@ impl Scene {
let layer = self.layers.entry(primitive.order()).or_default();
match primitive {
Primitive::Quad(quad) => layer.quads.push(quad),
+ Primitive::MonochromeGlyph(glyph) => layer.symbol.push(glyph),
}
}
@@ -51,20 +53,14 @@ impl Scene {
#[derive(Clone, Debug)]
pub enum Primitive {
Quad(Quad),
+ MonochromeGlyph(Symbol),
}
impl Primitive {
pub fn order(&self) -> u32 {
match self {
Primitive::Quad(quad) => quad.order,
- }
- }
-
- pub fn is_transparent(&self) -> bool {
- match self {
- Primitive::Quad(quad) => {
- quad.background.is_transparent() && quad.border_color.is_transparent()
- }
+ Primitive::MonochromeGlyph(glyph) => glyph.order,
}
}
@@ -73,6 +69,9 @@ impl Primitive {
Primitive::Quad(quad) => {
quad.scale(factor);
}
+ Primitive::MonochromeGlyph(glyph) => {
+ glyph.scale(factor);
+ }
}
}
}
@@ -119,3 +118,27 @@ impl From<Quad> for Primitive {
Primitive::Quad(quad)
}
}
+
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct Symbol {
+ pub order: u32,
+ pub origin: Point<Pixels>,
+ pub font_id: FontId,
+ pub font_size: Pixels,
+ pub id: GlyphId,
+ pub color: Hsla,
+}
+
+impl Symbol {
+ pub fn scale(&mut self, factor: f32) {
+ self.font_size *= factor;
+ self.origin *= factor;
+ }
+}
+
+impl From<Symbol> for Primitive {
+ fn from(glyph: Symbol) -> Self {
+ Primitive::MonochromeGlyph(glyph)
+ }
+}
@@ -1,9 +1,12 @@
mod font_features;
+mod line;
mod line_wrapper;
mod text_layout_cache;
use anyhow::anyhow;
+use bytemuck::{Pod, Zeroable};
pub use font_features::*;
+pub use line::*;
use line_wrapper::*;
pub use text_layout_cache::*;
@@ -20,7 +23,8 @@ use std::{
sync::Arc,
};
-#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)]
+#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug, Zeroable, Pod)]
+#[repr(C)]
pub struct FontId(pub usize);
#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)]
@@ -51,7 +55,6 @@ impl TextSystem {
pub fn font_id(&self, font: &Font) -> Result<FontId> {
let font_id = self.font_ids_by_font.read().get(font).copied();
-
if let Some(font_id) = font_id {
Ok(font_id)
} else {
@@ -160,29 +163,18 @@ impl TextSystem {
) -> Result<Line> {
let mut font_runs = self.font_runs_pool.lock().pop().unwrap_or_default();
- dbg!("got font runs from pool");
let mut last_font: Option<&Font> = None;
for (len, style) in runs {
- dbg!(len);
if let Some(last_font) = last_font.as_ref() {
- dbg!("a");
if **last_font == style.font {
- dbg!("b");
font_runs.last_mut().unwrap().0 += len;
- dbg!("c");
continue;
}
- dbg!("d");
}
- dbg!("e");
last_font = Some(&style.font);
- dbg!("f");
font_runs.push((*len, self.font_id(&style.font)?));
- dbg!("g");
}
- dbg!("built font runs");
-
let layout = self
.text_layout_cache
.layout_line(text, font_size, &font_runs);
@@ -332,7 +324,8 @@ pub struct RunStyle {
pub underline: Option<UnderlineStyle>,
}
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Zeroable, Pod)]
+#[repr(C)]
pub struct GlyphId(u32);
impl From<GlyphId> for u32 {
@@ -1,8 +1,4 @@
-use crate::{
- black, point, px, Bounds, FontId, Glyph, Hsla, LineLayout, Pixels, PlatformTextSystem, Point,
- Run, RunStyle, UnderlineStyle, WindowContext,
-};
-use anyhow::Result;
+use crate::{FontId, Glyph, LineLayout, Pixels, PlatformTextSystem, Run};
use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard};
use smallvec::SmallVec;
use std::{
@@ -40,7 +36,6 @@ impl TextLayoutCache {
font_size: Pixels,
runs: &[(usize, FontId)],
) -> Arc<LineLayout> {
- dbg!("layout line");
let key = &CacheKeyRef {
text,
font_size,
@@ -145,332 +140,12 @@ impl<'a> Hash for CacheKeyRef<'a> {
}
}
-#[derive(Default, Debug, Clone)]
-pub struct Line {
- layout: Arc<LineLayout>,
- style_runs: SmallVec<[StyleRun; 32]>,
-}
-
-#[derive(Debug, Clone)]
-struct StyleRun {
- len: u32,
- color: Hsla,
- underline: UnderlineStyle,
-}
-
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct ShapedBoundary {
pub run_ix: usize,
pub glyph_ix: usize,
}
-impl Line {
- pub fn new(layout: Arc<LineLayout>, runs: &[(usize, RunStyle)]) -> Self {
- let mut style_runs = SmallVec::new();
- for (len, style) in runs {
- style_runs.push(StyleRun {
- len: *len as u32,
- color: style.color,
- underline: style.underline.clone().unwrap_or_default(),
- });
- }
- Self { layout, style_runs }
- }
-
- pub fn runs(&self) -> &[Run] {
- &self.layout.runs
- }
-
- pub fn width(&self) -> Pixels {
- self.layout.width
- }
-
- pub fn font_size(&self) -> Pixels {
- self.layout.font_size
- }
-
- pub fn x_for_index(&self, index: usize) -> Pixels {
- for run in &self.layout.runs {
- for glyph in &run.glyphs {
- if glyph.index >= index {
- return glyph.position.x;
- }
- }
- }
- self.layout.width
- }
-
- pub fn font_for_index(&self, index: usize) -> Option<FontId> {
- for run in &self.layout.runs {
- for glyph in &run.glyphs {
- if glyph.index >= index {
- return Some(run.font_id);
- }
- }
- }
-
- None
- }
-
- pub fn len(&self) -> usize {
- self.layout.len
- }
-
- pub fn is_empty(&self) -> bool {
- self.layout.len == 0
- }
-
- pub fn index_for_x(&self, x: Pixels) -> Option<usize> {
- if x >= self.layout.width {
- None
- } else {
- for run in self.layout.runs.iter().rev() {
- for glyph in run.glyphs.iter().rev() {
- if glyph.position.x <= x {
- return Some(glyph.index);
- }
- }
- }
- Some(0)
- }
- }
-
- // todo!
- pub fn paint(
- &self,
- origin: Point<Pixels>,
- visible_bounds: Bounds<Pixels>,
- line_height: Pixels,
- cx: &mut WindowContext,
- ) -> Result<()> {
- let padding_top = (line_height - self.layout.ascent - self.layout.descent) / 2.;
- let baseline_offset = point(px(0.), padding_top + self.layout.ascent);
-
- let mut style_runs = self.style_runs.iter();
- let mut run_end = 0;
- let mut color = black();
- let mut underline = None;
-
- for run in &self.layout.runs {
- cx.text_system().with_font(run.font_id, |system, font| {
- let max_glyph_width = system.bounding_box(font, self.layout.font_size)?.size.width;
-
- for glyph in &run.glyphs {
- let glyph_origin = origin + baseline_offset + glyph.position;
- if glyph_origin.x > visible_bounds.upper_right().x {
- break;
- }
-
- let mut finished_underline: Option<(Point<Pixels>, UnderlineStyle)> = None;
- if glyph.index >= run_end {
- if let Some(style_run) = style_runs.next() {
- if let Some((_, underline_style)) = &mut underline {
- if style_run.underline != *underline_style {
- finished_underline = underline.take();
- }
- }
- if style_run.underline.thickness > px(0.) {
- underline.get_or_insert((
- point(
- glyph_origin.x,
- origin.y
- + baseline_offset.y
- + (self.layout.descent * 0.618),
- ),
- UnderlineStyle {
- color: style_run.underline.color,
- thickness: style_run.underline.thickness,
- squiggly: style_run.underline.squiggly,
- },
- ));
- }
-
- run_end += style_run.len as usize;
- color = style_run.color;
- } else {
- run_end = self.layout.len;
- finished_underline = underline.take();
- }
- }
-
- if glyph_origin.x + max_glyph_width < visible_bounds.origin.x {
- continue;
- }
-
- if let Some((_underline_origin, _underline_style)) = finished_underline {
- // cx.scene().insert(Underline {
- // origin: underline_origin,
- // width: glyph_origin.x - underline_origin.x,
- // thickness: underline_style.thickness.into(),
- // color: underline_style.color.unwrap(),
- // squiggly: underline_style.squiggly,
- // });
- }
-
- // if glyph.is_emoji {
- // cx.scene().push_image_glyph(scene::ImageGlyph {
- // font_id: run.font_id,
- // font_size: self.layout.font_size,
- // id: glyph.id,
- // origin: glyph_origin,
- // });
- // } else {
- // cx.scene().push_glyph(scene::Glyph {
- // font_id: run.font_id,
- // font_size: self.layout.font_size,
- // id: glyph.id,
- // origin: glyph_origin,
- // color,
- // });
- // }
- }
-
- anyhow::Ok(())
- })??;
- }
-
- if let Some((_underline_start, _underline_style)) = underline.take() {
- let _line_end_x = origin.x + self.layout.width;
- // cx.scene().push_underline(Underline {
- // origin: underline_start,
- // width: line_end_x - underline_start.x,
- // color: underline_style.color,
- // thickness: underline_style.thickness.into(),
- // squiggly: underline_style.squiggly,
- // });
- }
-
- Ok(())
- }
-
- pub fn paint_wrapped(
- &self,
- origin: Point<Pixels>,
- _visible_bounds: Bounds<Pixels>,
- line_height: Pixels,
- boundaries: &[ShapedBoundary],
- cx: &mut WindowContext,
- ) -> Result<()> {
- let padding_top = (line_height - self.layout.ascent - self.layout.descent) / 2.;
- let baseline_offset = point(px(0.), padding_top + self.layout.ascent);
-
- let mut boundaries = boundaries.into_iter().peekable();
- let mut color_runs = self.style_runs.iter();
- let mut style_run_end = 0;
- let mut _color = black(); // todo!
- let mut underline: Option<(Point<Pixels>, UnderlineStyle)> = None;
-
- let mut glyph_origin = origin;
- let mut prev_position = px(0.);
- for (run_ix, run) in self.layout.runs.iter().enumerate() {
- for (glyph_ix, glyph) in run.glyphs.iter().enumerate() {
- glyph_origin.x += glyph.position.x - prev_position;
-
- if boundaries
- .peek()
- .map_or(false, |b| b.run_ix == run_ix && b.glyph_ix == glyph_ix)
- {
- boundaries.next();
- if let Some((_underline_origin, _underline_style)) = underline.take() {
- // cx.scene().push_underline(Underline {
- // origin: underline_origin,
- // width: glyph_origin.x - underline_origin.x,
- // thickness: underline_style.thickness.into(),
- // color: underline_style.color.unwrap(),
- // squiggly: underline_style.squiggly,
- // });
- }
-
- glyph_origin = point(origin.x, glyph_origin.y + line_height);
- }
- prev_position = glyph.position.x;
-
- let mut finished_underline = None;
- if glyph.index >= style_run_end {
- if let Some(style_run) = color_runs.next() {
- style_run_end += style_run.len as usize;
- _color = style_run.color;
- if let Some((_, underline_style)) = &mut underline {
- if style_run.underline != *underline_style {
- finished_underline = underline.take();
- }
- }
- if style_run.underline.thickness > px(0.) {
- underline.get_or_insert((
- glyph_origin
- + point(
- px(0.),
- baseline_offset.y + (self.layout.descent * 0.618),
- ),
- UnderlineStyle {
- color: Some(
- style_run.underline.color.unwrap_or(style_run.color),
- ),
- thickness: style_run.underline.thickness,
- squiggly: style_run.underline.squiggly,
- },
- ));
- }
- } else {
- style_run_end = self.layout.len;
- _color = black();
- finished_underline = underline.take();
- }
- }
-
- if let Some((_underline_origin, _underline_style)) = finished_underline {
- // cx.scene().push_underline(Underline {
- // origin: underline_origin,
- // width: glyph_origin.x - underline_origin.x,
- // thickness: underline_style.thickness.into(),
- // color: underline_style.color.unwrap(),
- // squiggly: underline_style.squiggly,
- // });
- }
-
- cx.text_system().with_font(run.font_id, |system, font| {
- let _glyph_bounds = Bounds {
- origin: glyph_origin,
- size: system.bounding_box(font, self.layout.font_size)?.size,
- };
- // if glyph_bounds.intersects(visible_bounds) {
- // if glyph.is_emoji {
- // cx.scene().push_image_glyph(scene::ImageGlyph {
- // font_id: run.font_id,
- // font_size: self.layout.font_size,
- // id: glyph.id,
- // origin: glyph_bounds.origin() + baseline_offset,
- // });
- // } else {
- // cx.scene().push_glyph(scene::Glyph {
- // font_id: run.font_id,
- // font_size: self.layout.font_size,
- // id: glyph.id,
- // origin: glyph_bounds.origin() + baseline_offset,
- // color,
- // });
- // }
- // }
- anyhow::Ok(())
- })??;
- }
- }
-
- if let Some((_underline_origin, _underline_style)) = underline.take() {
- // let line_end_x = glyph_origin.x + self.layout.width - prev_position;
- // cx.scene().push_underline(Underline {
- // origin: underline_origin,
- // width: line_end_x - underline_origin.x,
- // thickness: underline_style.thickness.into(),
- // color: underline_style.color,
- // squiggly: underline_style.squiggly,
- // });
- }
-
- Ok(())
- }
-}
-
impl Run {
pub fn glyphs(&self) -> &[Glyph] {
&self.glyphs
@@ -5,6 +5,7 @@ use crate::{
};
use anyhow::Result;
use futures::Future;
+use smallvec::SmallVec;
use std::{any::TypeId, marker::PhantomData, mem, sync::Arc};
use util::ResultExt;
@@ -18,6 +19,7 @@ pub struct Window {
layout_engine: TaffyLayoutEngine,
pub(crate) root_view: Option<AnyView<()>>,
mouse_position: Point<Pixels>,
+ z_index_stack: SmallVec<[u32; 8]>,
pub(crate) scene: Scene,
pub(crate) dirty: bool,
}
@@ -56,6 +58,7 @@ impl Window {
layout_engine: TaffyLayoutEngine::new(),
root_view: None,
mouse_position,
+ z_index_stack: SmallVec::new(),
scene: Scene::new(scale_factor),
dirty: true,
}
@@ -126,6 +129,13 @@ impl<'a, 'w> WindowContext<'a, 'w> {
&mut self.window.scene
}
+ pub fn with_z_index<R>(&mut self, z_index: u32, f: impl FnOnce(&mut Self) -> R) -> R {
+ self.window.z_index_stack.push(z_index);
+ let result = f(self);
+ self.window.z_index_stack.pop();
+ result
+ }
+
pub fn run_on_main<R>(
&self,
f: impl FnOnce(&mut MainThread<WindowContext>) -> R + Send + 'static,