Skip to content

Conversation

@waywardmonkeys
Copy link
Contributor

  • Keep attributed_text generic; add read APIs for iterating attributes/ranges
  • Introduce text_style: inline/paragraph declarations, specified→computed resolution, root-relative units (rem), and extensible ResolveContext (parent/initial/root)
  • Add OpenType settings (tag/setting model) with CSS-like source parsing at resolution time
  • Add styled_text: StyledText blocks, StyledDocument block list w/ root style propagation, and resolved inline runs (Iterator<Item=Result<…>>)

@waywardmonkeys
Copy link
Contributor Author

There's at least one big problem with this ... text-style is already a taken name, so text_style can't be the name we use.

This is a great bike shedding opportunity for people (the name).

@waywardmonkeys
Copy link
Contributor Author

This also doesn't yet lower to Parley and have an example ... coming soon. Other things too.

@waywardmonkeys
Copy link
Contributor Author

I will also peel off the attributed_text change to a separate PR and land it separately ...

@waywardmonkeys waywardmonkeys force-pushed the stylamizing_yer_text branch 2 times, most recently from 5eac6a3 to ea54de2 Compare December 29, 2025 16:05
@dfrg
Copy link
Collaborator

dfrg commented Dec 29, 2025

I'm still reading through this but my general feeling is that we'll want a simpler vocabulary crate that only provides the fundamental resolved property types. Things like Tag, FontWeight, Language*, FontVariation, FontFeature, GenericFamily, WordBreak, etc. And maybe some parsing for these. I'm thinking of the color crate as an example.

* A zero alloc language type the only captures language, script and region subtags would be nice. We don't really care about the rest.

@nicoburns
Copy link
Collaborator

I'm still reading through this but my general feeling is that we'll want a simpler vocabulary crate that only provides the fundamental resolved property types. Things like Tag, FontWeight, Language*, FontVariation, FontFeature, GenericFamily, WordBreak, etc. And maybe some parsing for these. I'm thinking of the color crate as an example.

  • A zero alloc language type the only captures language, script and region subtags would be nice. We don't really care about the rest.

I agree with this. And would say that I think it would be useful to have the "computed" styles (and likely a few other complementary low-level types like Tag) in a low-level type-only vocabulary crate that can be shared by everything which consumes parley (and parley/fontique themselves). Whereas I would expect the "specified" styles to be coupled with the "style systems" (of whatever variety) that sit on top.

@waywardmonkeys
Copy link
Contributor Author

I'll be pushing a proposal to address some of this shortly... and then I'll be passing out. :)

@waywardmonkeys
Copy link
Contributor Author

@dfrg I think the last set of changes adding text_primitives (yay for more bike shedding opportunities!) may help ...

If so, I could separate that out from this PR and submit a new PR that contains just that and the changes to have Parley / Fontique use it. (After I sleep...)

@waywardmonkeys
Copy link
Contributor Author

(It would still need some of the code that we have for some of these types in the existing stuff ... like parse functions, display impls, and bytemuck stuff. But that's easy to bring over.)

@dfrg
Copy link
Collaborator

dfrg commented Dec 30, 2025

If so, I could separate that out from this PR

Yes, this looks much better to me and I think it makes sense to split it out into a separate PR so we can bikeshed a bit on name and get it merged.

Thanks!

@waywardmonkeys
Copy link
Contributor Author

Splitting a very small font_stack from parley would be useful to me as well.

…nt blocks)

- Keep `attributed_text` generic; add read APIs for iterating attributes/ranges
- Introduce `text_style`: inline/paragraph declarations, specified→computed resolution,
  root-relative units (rem), and extensible `ResolveContext` (parent/initial/root)
- Add OpenType settings (tag/setting model) with CSS-like source parsing at resolution time
- Add `styled_text`: `StyledText` blocks, `StyledDocument` block list w/ root style propagation,
  and resolved inline runs (`Iterator<Item=Result<…>>`)
Replace the O(segments×spans) “scan all spans per run” resolver with a sweep-line that maintains an active span set across boundaries and computes each segment’s computed style from only active spans.

This significantly reduces work for texts with many spans/runs, while preserving “last writer wins” semantics and dependent-property resolution (e.g. `em` spacing against final computed `font-size`). Includes a differential test against a reference (slow) resolver, and a forward-compat fallback for future `text_style::InlineDeclaration` variants.
Create new `text_style_resolve` crate providing computed style types, resolve contexts, specified→computed resolution, and OpenType settings parsing/errors.

Slim `text_style` down to vocabulary-only (declarations/values/settings) and update `styled_text` + docs to
use the new resolver layer.`
Replace the active-span `BTreeSet` with a sorted `Vec` (binary-search insert/remove) to eliminate per-span tree node allocations while preserving last-writer-wins ordering.
Change `ComputedInlineStyle` font variations/features to `Arc<[Setting<T>]>` and update resolution to inherit via `Arc` clone instead of allocating/copying `Vec`s. Keeps the public API returning `&[Setting<T>]` while reducing per-run allocations.
Replace per-boundary `Vec<Vec<usize>>` start/end event lists with CSR (Compressed Sparse Row) buffers (flat events + offsets) to avoid many small allocations while preserving run resolution semantics.
Add a new `no_std` + `alloc` `styled_text_parley` crate that lowers `styled_text::StyledText` resolved runs into Parley ranged builder calls, producing a `parley::Layout`.
@dfrg
Copy link
Collaborator

dfrg commented Jan 5, 2026

Splitting a very small font_stack from parley would be useful to me as well.

Adding this to text_primitives (with the name FontFamily to match CSS) makes sense to me. We just need to figure out how to handle names in a way that makes allocation optional.

@nicoburns
Copy link
Collaborator

Splitting a very small font_stack from parley would be useful to me as well.

+1 for this. I think basically everything that's a computed style in Parley makes sense here (I'm assuming that where this is headed is that Parley will end up with less style resolution than it currently has (basically only things that can't be computed ahead of time becuase they depend on the font metrics or font fallback).

Adding this to text_primitives (with the name FontFamily to match CSS) makes sense to me. We just need to figure out how to handle names in a way that makes allocation optional.

Some kind Arc-based solution might also make sense. I think a lot of consumers will be converting into this type from some other similar type, and being able to cache that conversion would make a lot of sense. Especially because even without a single layout having a lot of spans with identical font-family specification is a common case.

In my case my source will be https://docs.rs/stylo/latest/style/values/computed/font/struct.FontFamilyList.html which is itself an Arc so I could probably have an Arc-> Arc lookup which I'd imagine would be quite cheap. Blitz currently is allocating a new Vec of Strings every time a font-family style is specified which isn't ideal. I haven't benchmarked how much of an impact that has.

@waywardmonkeys
Copy link
Contributor Author

Another part of this has been pulled out and turned into #501.

@waywardmonkeys
Copy link
Contributor Author

And the extraction of FontFamily (with improvements to parsing along the same lines as #501) is now in #502.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants