Another project
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 2.1 kB View raw
1use bone_text::{ 2 FontFace, FontWeight, ShapeRequest, ShapedText, Shaper, TessellatedOutline, append_outline, 3 tessellate_path, 4}; 5use lyon_tessellation::{FillTessellator, path::Path as LyonPath}; 6use swash::{ 7 FontRef, 8 scale::{ScaleContext, outline::Outline}, 9 zeno::Point as ZenoPoint, 10}; 11 12pub(crate) fn shape_line( 13 text: &str, 14 size_px: f32, 15 face: FontFace, 16 shaper: &mut Shaper, 17) -> ShapedText { 18 shaper.shape( 19 text, 20 ShapeRequest { 21 face, 22 size_px, 23 weight: FontWeight::Regular, 24 line_height_px: 0.0, 25 letter_spacing_px: 0.0, 26 max_width: None, 27 }, 28 ) 29} 30 31pub(crate) fn tessellate_at( 32 layout: &ShapedText, 33 font: &FontRef<'_>, 34 scale_ctx: &mut ScaleContext, 35 fill: &mut FillTessellator, 36 origin: ZenoPoint, 37) -> TessellatedOutline { 38 let path = build_path_at(layout, scale_ctx, font, origin); 39 tessellate_path(&path, fill).unwrap_or_else(|e| { 40 tracing::warn!(error = %e, "text tessellation failed"); 41 TessellatedOutline::default() 42 }) 43} 44 45fn build_path_at( 46 layout: &ShapedText, 47 scale_ctx: &mut ScaleContext, 48 font: &FontRef<'_>, 49 origin: ZenoPoint, 50) -> LyonPath { 51 let mut scaler = scale_ctx.builder(*font).size(layout.font_size_px).build(); 52 layout 53 .lines 54 .iter() 55 .flat_map(|line| line.runs.iter()) 56 .flat_map(|run| { 57 let run_origin = run.origin_x_px; 58 run.glyphs.iter().map(move |g| (run_origin + g.x_px, g.id)) 59 }) 60 .fold(LyonPath::svg_builder(), |mut builder, (x, id)| { 61 let Ok(glyph_id_u16) = u16::try_from(id.raw()) else { 62 return builder; 63 }; 64 let mut outline = Outline::new(); 65 if scaler.scale_outline_into(glyph_id_u16, &mut outline) { 66 append_outline( 67 &mut builder, 68 &outline, 69 ZenoPoint::new(origin.x + x, origin.y), 70 ); 71 } 72 builder 73 }) 74 .build() 75}