1use alloc::{vec::Vec, string::String};
3use crate::{Text, registry::Face};
4
5#[derive(Default)]
6pub(crate) struct Cache {
7 pub enabled: bool, serial: u64, font: u32, size: i32,
8 engine: Option<text_shape::Engine>, text: String, glyphs: Vec<Placed>, carets: Vec<(usize,i32)>, width: i32,
9 fallbacks: Vec<(u32, text_shape::Engine)>,
10 segments: Vec<(usize, usize, i32, i32)>,
11}
12#[derive(Clone, Copy)]
13pub(crate) struct Placed { pub font: u32, pub id: u32, pub x: i32, pub y: i32 }
14impl Text {
15 pub fn set_shaping(&mut self, enabled: bool) -> bool { core::mem::replace(&mut self.shaping.enabled,enabled) }
18 pub fn set_fallback_fonts(&mut self, fonts: &[u32]) {
19 if self.fb.app != fonts { self.fallback_app(fonts); }
20 let ids:Vec<_>=self.shaping.fallbacks.iter().map(|v|v.0).collect();
21 if ids==fonts { return; }
22 self.shaping.fallbacks=fonts.iter().take(16).filter_map(|&id| self.shape_engine(id).map(|e|(id,e))).collect();
23 self.shaping.size=0;
24 }
25 fn shape_face(&self, mut font: u32) -> Option<&crate::ttf::TtFont> {
26 for _ in 0..16 { match self.face(font)? { Face::Tt(tt) => return Some(tt), Face::Syn(s) => font=s.base, Face::Var(v) => font=v.base, _ => return None } }
27 None
28 }
29 pub(crate) fn shape_line(&mut self, bytes: &[u8], limit: Option<usize>) -> bool {
30 if !self.shaping.enabled { return false; }
31 let n=limit.unwrap_or(bytes.len()).min(bytes.len());
32 let n=bytes[..n].iter().position(|b| *b==0 || *b==b'\n').unwrap_or(n);
33 let Ok(text)=core::str::from_utf8(&bytes[..n]) else { return false; };
34 let render_font=if self.shape_face(self.font).is_some() { self.font } else { match self.shaping.fallbacks.first() { Some(v)=>v.0,None=>return false } };
35 if self.shape_face(render_font).is_none() { return false; }
36 let serial=self.shape_serial(render_font); if self.shaping.serial!=serial || self.shaping.engine.is_none() {
38 let engine=self.shape_engine(render_font);
39 self.shaping.engine=engine; self.shaping.serial=serial; self.shaping.text.clear(); self.shaping.size=0;
40 }
41 if self.shaping.engine.is_none() { return false; }
42 if self.shaping.font==self.font && self.shaping.size==self.size && self.shaping.text==text { return true; }
43 if self.system_fallback() { self.shape_system_fallbacks(text, render_font); }
44 let fallback_engines:Vec<_>=self.shaping.fallbacks.iter().map(|v|&v.1).collect();
45 let Some(glyphs)=self.shaping.engine.as_ref().and_then(|e| e.shape_with_fallback(text,&fallback_engines)) else { return false; };
46 let classic=self.classic_metrics(self.font);
47 let scale=|v:i32,font:u32| { let n=(v as i64*self.size as i64/self.upem(font).max(1) as i64).clamp(i32::MIN as i64,i32::MAX as i64) as i32; if classic { n.saturating_add(128)&!255 } else { n } };
48 let mut pen=0i32; let mut placed=Vec::new(); let mut carets=Vec::new(); let mut segments=Vec::new();
49 let mut i=0;
50 while i<glyphs.len() {
51 let first=glyphs[i]; let left=pen;
52 while i<glyphs.len() && glyphs[i].cluster==first.cluster {
53 let g=glyphs[i];
54 let font=if g.font==0 { render_font } else { self.shaping.fallbacks[g.font-1].0 };
55 placed.push(Placed { font, id:g.id, x:pen.saturating_add(scale(g.x,font)), y:scale(g.y,font) });
56 pen=pen.saturating_add(scale(g.advance,font)); i+=1;
57 }
58 let right=pen; let (begin,end)=if first.rtl { (right,left) } else { (left,right) };
59 carets.push((first.cluster,begin));
60 let chars:Vec<_>=text[first.cluster..first.end].char_indices().map(|(o,_)| first.cluster+o).collect();
62 for (k,&index) in chars.iter().enumerate() {
63 let a=begin+((end-begin) as i64*k as i64/chars.len() as i64) as i32;
64 let b=begin+((end-begin) as i64*(k+1) as i64/chars.len() as i64) as i32;
65 segments.push((index,chars.get(k+1).copied().unwrap_or(first.end),a.min(b),a.max(b)));
66 }
67 for (k,&index) in chars.iter().enumerate().skip(1) {
68 carets.push((index,begin+((end-begin) as i64*k as i64/chars.len() as i64) as i32));
69 }
70 carets.push((first.end,end));
71 }
72 if carets.is_empty() { carets.push((0,0)); }
73 carets.sort_by_key(|c| c.0); carets.dedup_by_key(|c| c.0);
74 self.shaping.text=String::from(text); self.shaping.font=self.font; self.shaping.size=self.size;
75 self.shaping.glyphs=placed; self.shaping.carets=carets; self.shaping.width=pen; self.shaping.segments=segments;
76 true
77 }
78 fn shape_system_fallbacks(&mut self, text: &str, render_font: u32) {
80 let mut need: Vec<u32> = Vec::new();
81 for ch in text.chars() {
82 let cp = ch as u32;
83 if self.has(render_font, cp) || self.shaping.fallbacks.iter().any(|f| self.has(f.0, cp)) { continue; }
84 if let Some(id) = self.fallback_for(cp) {
85 if !need.contains(&id) && !self.shaping.fallbacks.iter().any(|f| f.0 == id) { need.push(id); }
86 }
87 }
88 for id in need {
89 if self.shaping.fallbacks.len() >= 16 { break; }
90 let engine = self.shape_engine(id);
91 if let Some(e) = engine { self.shaping.fallbacks.push((id, e)); self.shaping.size = 0; }
92 }
93 }
94 pub(crate) fn shaped_draw(&mut self, pen0: i32, mut target: Option<(&mut gfx::Dc,&mut gfx::Surface)>) -> i32 {
95 let baseline=self.run_y;
96 for i in 0..self.shaping.glyphs.len() {
97 let g=self.shaping.glyphs[i];
98 if let Some((dc,sf))=&mut target {
99 self.run_y=baseline-((g.y+128)>>8);
100 if !self.color_glyph(dc,sf,g.font,g.id,pen0.saturating_add(g.x)) { self.glyph_draw(dc,sf,g.font,g.id,pen0.saturating_add(g.x),true); }
101 }
102 }
103 self.run_y=baseline; self.shaping.width
104 }
105 pub(crate) fn shaped_caret(&self, index: usize) -> i32 {
106 self.shaping.carets.iter().min_by_key(|c| c.0.abs_diff(index)).map_or(0,|c| (c.1+128)>>8)
107 }
108 pub(crate) fn shaped_hit(&self, x: i32) -> usize {
109 self.shaping.carets.iter().min_by_key(|c| ((c.1 as i64)-(x as i64*256)).abs()).map_or(0,|c| c.0)
110 }
111 pub fn selection_spans(&mut self, text: &[u8], start: usize, end: usize) -> Vec<(i32,i32)> {
114 if start>=end { return Vec::new(); }
115 if !self.shape_line(text,None) {
116 let a=self.caret_x(text,start); let b=self.caret_x(text,end);
117 return alloc::vec![(a.min(b),a.max(b))];
118 }
119 let mut spans:Vec<_>=self.shaping.segments.iter().filter(|s|s.0<end && s.1>start)
120 .map(|s|((s.2+128)>>8,(s.3+128)>>8)).collect();
121 spans.sort_unstable();
122 let mut merged:Vec<(i32,i32)>=Vec::new();
123 for (a,b) in spans {
124 if let Some(last)=merged.last_mut() { if a<=last.1 { last.1=last.1.max(b); continue; } }
125 merged.push((a,b));
126 }
127 merged
128 }
129}