mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-30 13:26:54 -06:00
A new L4 crate that writes layers as an Android Vector Drawable (XML): shapes, booleans and text as baked path data, solid and gradient fills (linear, radial and sweep, exact for any handle frame via a group and a 2x2 SVD), native strokes where Android draws them the same and filled stroke outlines otherwise, clip frames and masks as <clip-path> groups. What a drawable can't hold is governed by Compat (bestEffort / exact / ignore): layer opacity over overlapping shapes, even-odd fills and clips (rewritten to non-zero via pathops), diamond gradients, alpha masks; effects, image and pattern fills and blend modes are left out with a warning. Output is pretty-printed, numbers are finite and short, names (android:name) are optional, escaped and unique.
31 lines
1.2 KiB
Rust
31 lines
1.2 KiB
Rust
//! Text layers as glyph outlines, one path per styled run.
|
|
|
|
use figcraft_color::Paint;
|
|
use figcraft_doc::{Node, NodeKind};
|
|
use figcraft_geom::{Affine, BezPath};
|
|
|
|
/// Text layer `n`'s glyph and decoration outlines grouped by style, in layer space, each with the
|
|
/// fills it paints in (its own, else the layer's). `None` for other layers and text that doesn't
|
|
/// lay out.
|
|
pub(crate) fn runs(n: &Node) -> Option<Vec<(BezPath, Vec<Paint>)>> {
|
|
let NodeKind::Text(_) = &n.kind else { return None };
|
|
let (layout, dy) = figcraft_text::layout_node(n)?;
|
|
let mut by_style: std::collections::BTreeMap<usize, BezPath> = std::collections::BTreeMap::new();
|
|
for g in &layout.glyphs {
|
|
by_style.entry(g.style).or_default().extend(g.path().elements().iter().copied());
|
|
}
|
|
for d in &layout.decorations {
|
|
by_style.entry(d.style).or_default().extend(d.path().elements().iter().copied());
|
|
}
|
|
Some(
|
|
by_style
|
|
.into_iter()
|
|
.map(|(k, mut path)| {
|
|
path.apply_affine(Affine::translate((0.0, dy)));
|
|
let fills = layout.styles.get(k).and_then(|s| s.fills.clone()).unwrap_or_else(|| n.fills.clone());
|
|
(path, fills)
|
|
})
|
|
.collect(),
|
|
)
|
|
}
|