Compare commits

..
Author SHA1 Message Date
iris 983e15cd9a Keep widget storage idea in TODO 2026-09-13 03:36:48 -04:00
iris 338f10f070 Restore unresolved TODO items 2026-09-13 03:34:28 -04:00
iris 234abb8052 Prune resolved TODO items 2026-09-13 03:31:17 -04:00
iris 80b28fff1a Warn when glyphs cannot fit the atlas 2026-09-13 03:28:10 -04:00
iris 2026e5d088 Record typed texture handle follow-up 2026-09-13 03:15:27 -04:00
iris 15a156595b Borrow cached rendered text instead of cloning it 2026-09-13 03:11:51 -04:00
8 changed files with 44 additions and 64 deletions

No files matched your search

Generated
+1
View File
@@ -1189,6 +1189,7 @@ dependencies = [
"bytemuck", "bytemuck",
"fxhash", "fxhash",
"image", "image",
"log",
"parley", "parley",
"swash", "swash",
"wgpu", "wgpu",
+1
View File
@@ -35,6 +35,7 @@ image = "0.25.6"
parley = "0.11.1" parley = "0.11.1"
swash = "0.2.10" swash = "0.2.10"
fxhash = "0.2.1" fxhash = "0.2.1"
log = "0.4.29"
arboard = "3.6.1" arboard = "3.6.1"
iris-core = { path = "core" } iris-core = { path = "core" }
iris-macro = { path = "macro" } iris-macro = { path = "macro" }
+1 -25
View File
@@ -1,19 +1,6 @@
images images
settings (sampler) settings (sampler)
consider typed TextureHandle<T> variants for distinct texture uses
text
figure out ways to speed up / what costs the most
resizing (per frame) is really slow (assuming painter isn't griefing)
j is weird / fix x offset
masks r just made to bare minimum work
scaling
could be just a simple scaling factor that multiplies abs
and need to ensure text uses raw abs and not scaled abs
naming? (pt, px)
want to keep (drawn) regions using px? or should I add another field to UiScalar/Vec
field could be best solution so redrawing stuff isn't needed & you can specify both as user
WidgetRef<W> or smth instead of Id WidgetRef<W> or smth instead of Id
enum that's either an Id or an actual concrete instance of W enum that's either an Id or an actual concrete instance of W
@@ -24,17 +11,6 @@ WidgetRef<W> or smth instead of Id
maybe introduce InnerWidget trait to allow for editors to expose & modify inner type maybe introduce InnerWidget trait to allow for editors to expose & modify inner type
maybe could also store a parent widget and keep using InnerWidget trait? unsure if possible maybe could also store a parent widget and keep using InnerWidget trait? unsure if possible
really weird limitation:
I don't think you can currently remove an element from a parent and put it in a child of the same parent
because it removes the unused children after the entire parent redraw
but the child gets drawn during that, so it will think the child is still active !!!
or something like that idk, maybe I need a special enum for parent that includes a undecided state where it may or may not get redrawn by the parent
or just do ref counting and ensure all drawn things == 1 afterwards (seems like best way)
ok so I'm removing the limit for now
don't forget I'm streaming
tags
vecs for each widget type? vecs for each widget type?
POTENTIAL BUG: closures that store IDs will not decrement the id!!! need to not increment id if moved into closure somehow??? wait no, need to decrement ID every time an event fn is added...... only if the id is used in it..?? POTENTIAL BUG: closures that store IDs will not decrement the id!!! need to not increment id if moved into closure somehow??? wait no, need to decrement ID every time an event fn is added...... only if the id is used in it..??
+1
View File
@@ -10,3 +10,4 @@ image = { workspace = true }
parley = { workspace = true } parley = { workspace = true }
swash = { workspace = true } swash = { workspace = true }
fxhash = { workspace = true } fxhash = { workspace = true }
log = { workspace = true }
+6 -6
View File
@@ -185,7 +185,7 @@ impl TextData {
subpixel, subpixel,
coords: coords_hash, coords: coords_hash,
}; };
let entry = self.glyph_entry( let Some(entry) = self.glyph_entry(
GlyphRaster { GlyphRaster {
key, key,
font: font_ref, font: font_ref,
@@ -195,8 +195,9 @@ impl TextData {
glyph_id: glyph.id, glyph_id: glyph.id,
}, },
textures, textures,
); ) else {
let Some(entry) = entry else { continue }; continue;
};
placed.push(PlacedGlyph { placed.push(PlacedGlyph {
entry, entry,
offset: Vec2::new( offset: Vec2::new(
@@ -265,9 +266,8 @@ fn glyph_size_key(font_size: f32) -> u32 {
(font_size * GLYPH_SIZE_STEPS_PER_PIXEL).round() as u32 (font_size * GLYPH_SIZE_STEPS_PER_PIXEL).round() as u32
} }
#[derive(Clone)]
pub struct RenderedText { pub struct RenderedText {
pub glyphs: std::sync::Arc<Vec<PlacedGlyph>>, pub glyphs: Vec<PlacedGlyph>,
pub size: Vec2, pub size: Vec2,
pub color: UiColor, pub color: UiColor,
} }
@@ -283,7 +283,7 @@ impl TextData {
buffer.shape(self, attrs, width); buffer.shape(self, attrs, width);
let glyphs = self.place(buffer, textures); let glyphs = self.place(buffer, textures);
RenderedText { RenderedText {
glyphs: std::sync::Arc::new(glyphs), glyphs,
size: buffer.size(), size: buffer.size(),
color: attrs.color, color: attrs.color,
} }
+15 -7
View File
@@ -1,5 +1,5 @@
use crate::{ use crate::{
GlyphPrimitive, PatchRect, TextureHandle, Textures, PatchRect, TextureHandle, Textures,
util::{HashMap, Vec2}, util::{HashMap, Vec2},
}; };
use image::RgbaImage; use image::RgbaImage;
@@ -40,12 +40,10 @@ pub struct GlyphEntry {
} }
impl GlyphEntry { impl GlyphEntry {
const IS_COLORED: u32 = 1;
pub(crate) fn flags(&self) -> u32 { pub(crate) fn flags(&self) -> u32 {
if self.is_colored { if self.is_colored { Self::IS_COLORED } else { 0 }
GlyphPrimitive::IS_COLORED
} else {
0
}
} }
} }
@@ -78,10 +76,20 @@ impl GlyphAtlas {
let w = image.placement.width; let w = image.placement.width;
let h = image.placement.height; let h = image.placement.height;
if w == 0 || h == 0 { if w == 0 || h == 0 {
log::warn!(
"glyph {} in font {} rasterized at {w}x{h}; skipping it",
key.glyph,
key.font,
);
self.entries.insert(key, None); self.entries.insert(key, None);
return None; return None;
} }
if w + PAD * 2 > PAGE || h + PAD * 2 > PAGE { if w > PAGE - PAD * 2 || h > PAGE - PAD * 2 {
log::warn!(
"glyph {} in font {} rasterized at {w}x{h}, too large for the {PAGE}x{PAGE} atlas; skipping it",
key.glyph,
key.font,
);
self.entries.insert(key, None); self.entries.insert(key, None);
return None; return None;
} }
-4
View File
@@ -243,10 +243,6 @@ pub struct GlyphPrimitive {
pub flags: u32, pub flags: u32,
} }
impl GlyphPrimitive {
pub const IS_COLORED: u32 = 1;
}
pub struct PrimitiveVec<T> { pub struct PrimitiveVec<T> {
vec: Vec<T>, vec: Vec<T>,
free: Vec<usize>, free: Vec<usize>,
+19 -22
View File
@@ -52,25 +52,19 @@ impl TextView {
.align(self.align) .align(self.align)
} }
fn render(&mut self, ctx: &mut SizeCtx) -> RenderedText { fn render(&mut self, ctx: &mut SizeCtx) -> &RenderedText {
let width = if self.attrs.wrap { let width = if self.attrs.wrap {
Some(ctx.px_size().x) Some(ctx.px_size().x)
} else { } else {
None None
}; };
if width == self.width if width != self.width || self.tex.is_none() || self.attrs.changed || self.buf.changed {
&& let Some(tex) = &self.tex self.width = width;
&& !self.attrs.changed self.tex = Some(ctx.draw_text(&mut self.buf, &self.attrs, width));
&& !self.buf.changed self.attrs.changed = false;
{ self.buf.changed = false;
return tex.clone();
} }
self.width = width; self.tex.as_ref().unwrap()
let tex = ctx.draw_text(&mut self.buf, &self.attrs, width);
self.tex = Some(tex.clone());
self.attrs.changed = false;
self.buf.changed = false;
tex
} }
pub fn tex(&self) -> Option<&RenderedText> { pub fn tex(&self) -> Option<&RenderedText> {
self.tex.as_ref() self.tex.as_ref()
@@ -94,16 +88,19 @@ impl TextView {
} }
} }
pub fn draw(&mut self, painter: &mut Painter) -> UiRegion { pub fn draw(&mut self, painter: &mut Painter) -> UiRegion {
let tex = self.render(&mut painter.size_ctx()); let align = self.align;
let region = tex.size.align(self.align); if self.is_empty() && self.hint.is_some() {
if self.is_empty() let region = self.render(&mut painter.size_ctx()).size.align(align);
&& let Some(hint) = &self.hint if let Some(hint) = &self.hint {
{ painter.widget(hint);
painter.widget(hint); }
} else { return region;
let within = region.within(&painter.region());
painter.glyphs(&tex, within);
} }
let tex = self.render(&mut painter.size_ctx());
let region = tex.size.align(align);
let within = region.within(&painter.region());
painter.glyphs(tex, within);
region region
} }