1#![no_std]
41#![forbid(unsafe_code)]
42
43extern crate alloc;
44
45pub mod cff;
46pub mod colr;
47mod fallback;
48pub mod font;
49pub mod fontconf;
50pub mod fontdb;
51pub mod glyphcache;
52pub mod lcd;
53pub mod outline;
54mod record;
55pub mod rendering;
56pub mod registry;
57pub mod segment;
58mod segment_data;
59pub mod ttf;
60mod shaping;
61pub mod var;
62
63use alloc::vec::Vec;
64
65use gfx::path::Path;
66use gfx::raster::Raster;
67use gfx::{blend, Dc, Surface, FMT_A8};
68use rt::fx::{cvt, div255};
69
70pub use font::*;
71pub use glyphcache::{GcEntry, GcRef};
72pub use lcd::{SUBPIXEL_BGR, SUBPIXEL_NONE, SUBPIXEL_RGB, SUBPIXEL_VBGR, SUBPIXEL_VRGB};
73pub use record::{GlyphRec, GlyphView};
74pub use registry::{FONT_EMBEDDED, FONT_MAX_IDS};
75pub use rendering::FontRaster;
76pub use var::{VarAxis, VarInstance};
77
78use colr::LAYER_FG;
79use outline::Outline;
80use registry::Slot;
81
82pub const FONT_REG: u32 = 0;
83pub const FONT_SEMI: u32 = 1;
84pub const FONT_BOLD: u32 = 2;
85pub const FONT_ICON: u32 = 3;
86const LAYER_CAP: usize = 256; pub struct Text {
89 shaping: shaping::Cache,
90 pub(crate) fb: fallback::Fallback,
91 pub(crate) slots: Vec<Slot>,
92 pub(crate) serial: u64,
93 pub(crate) names: [[&'static str; 5]; 4],
94 pub ol: Outline,
96 pub gp: Gp,
98 pub path: Path,
99 pub ras: Raster,
100 pub(crate) gc: glyphcache::Gc,
101 pub(crate) cb_metrics: [u8; 5],
102 pub png_decode: Option<colr::PngDecode>,
104 pub img_scale: Option<colr::ImgScale>,
105 font: u32,
106 size: i32,
107 sx: f32,
108 run_y: i32,
109 layers: Vec<(u32, u32)>,
110 lcd: u8,
112 lcd_lut: Option<alloc::boxed::Box<lcd::Lut>>,
113 rec: Option<record::GlyphRec>,
115}
116
117pub(crate) fn utf8_put(out: &mut Vec<u8>, cp: u32) {
118 if cp < 0x80 {
119 out.push(cp as u8);
120 } else if cp < 0x800 {
121 out.push(0xC0 | (cp >> 6) as u8);
122 out.push(0x80 | (cp & 0x3F) as u8);
123 } else if cp < 0x10000 {
124 out.push(0xE0 | (cp >> 12) as u8);
125 out.push(0x80 | ((cp >> 6) & 0x3F) as u8);
126 out.push(0x80 | (cp & 0x3F) as u8);
127 } else {
128 out.push(0xF0 | (cp >> 18) as u8);
129 out.push(0x80 | ((cp >> 12) & 0x3F) as u8);
130 out.push(0x80 | ((cp >> 6) & 0x3F) as u8);
131 out.push(0x80 | (cp & 0x3F) as u8);
132 }
133}
134
135impl Text {
136 pub fn new(fonts: [&'static [u8]; 4], names: [[&'static str; 5]; 4]) -> Text {
140 let mut t = Text {
141 shaping: Default::default(),
142 fb: Default::default(),
143 slots: Vec::new(),
144 serial: 0,
145 names,
146 ol: Outline::default(),
147 gp: Gp::default(),
148 path: Path::default(),
149 ras: Raster::default(),
150 gc: glyphcache::Gc::default(),
151 cb_metrics: [0; 5],
152 png_decode: Some(png_decode),
153 img_scale: Some(img_scale),
154 font: 0,
155 size: 0,
156 sx: 0.0,
157 run_y: 0,
158 layers: Vec::new(),
159 lcd: SUBPIXEL_NONE,
160 lcd_lut: None,
161 rec: None,
162 };
163 t.ol.reset();
164 for f in fonts {
165 if f.starts_with(b"SGF1") { t.register(f); } else { t.load_mem(f, 0); }
166 }
167 t.set_font(FONT_REG, 14 << 8);
168 t
169 }
170
171 pub fn set_font(&mut self, font: u32, size_fx: i32) {
173 self.font = font;
174 self.size = size_fx;
175 self.sx = self.gc_scale(font, size_fx).0;
176 }
177
178 pub fn get_font(&self) -> (u32, i32) {
180 (self.font, self.size)
181 }
182
183 fn units_fx(&self, u: i32) -> i32 {
185 cvt(u as f32 * self.sx * 256.0)
186 }
187
188 fn units_fx_of(&self, font: u32, u: i32) -> i32 {
190 if font == self.font { self.units_fx(u) } else { cvt(u as f32 * self.gc_scale(font, self.size).0 * 256.0) }
191 }
192
193 pub fn ascent(&self) -> i32 {
195 (self.units_fx(self.hdr(self.font).asc) + 255) >> 8
196 }
197
198 pub fn descent(&self) -> i32 {
200 (self.units_fx(self.hdr(self.font).desc.wrapping_neg()) + 255) >> 8
201 }
202
203 pub fn line_h(&self) -> i32 {
205 let h = self.hdr(self.font);
206 (self.units_fx(h.asc - h.desc + h.gap) + 128) >> 8
207 }
208
209 pub fn measure(&mut self, s: &str) -> i32 {
211 self.run(s.as_bytes(), 0, None, None)
212 }
213
214 pub fn measure_n(&mut self, s: &[u8], len: usize) -> i32 {
216 self.run(s, 0, Some(len), None)
217 }
218
219 pub fn width(&mut self, s: &str) -> i32 {
221 (self.measure(s) + 255) >> 8
222 }
223
224 pub fn width_n(&mut self, s: &[u8], len: usize) -> i32 {
225 (self.measure_n(s, len) + 255) >> 8
226 }
227
228 pub fn draw(&mut self, dc: &mut Dc, sf: &mut Surface, x: i32, y: i32, s: &[u8]) -> i32 {
230 self.draw_impl(dc, sf, x, y, s, None)
231 }
232
233 pub fn draw_n(&mut self, dc: &mut Dc, sf: &mut Surface, x: i32, y: i32, s: &[u8], len: usize) -> i32 {
235 self.draw_impl(dc, sf, x, y, s, Some(len))
236 }
237
238 fn draw_impl(&mut self, dc: &mut Dc, sf: &mut Surface, x: i32, y: i32, s: &[u8], len: Option<usize>) -> i32 {
239 let pen = x.wrapping_add(dc.ox) << 8;
240 self.run_y = y.wrapping_add(dc.oy);
241 let w = self.run(s, pen, len, Some((dc, sf)));
242 (w + 255) >> 8
243 }
244
245 fn run(&mut self, s: &[u8], pen0: i32, len: Option<usize>, mut target: Option<(&mut Dc, &mut Surface)>) -> i32 {
248 if self.shape_line(s,len) { return self.shaped_draw(pen0,target); }
249 let font = self.font;
250 let classic = self.classic_metrics(font);
251 let spacing = |v: i32| if classic { v.saturating_add(128) & !255 } else { v };
252 let fallback = self.fallback_active();
253 let mut pen = pen0;
254 let mut prev: i32 = -1;
255 let mut prev_font = font;
256 let mut left = len.unwrap_or(usize::MAX);
257 let mut i = 0;
258 while left > 0 && i < s.len() {
259 let b = s[i];
260 if b == 0 || b == b'\n' {
261 break;
262 }
263 if len.is_some() {
264 let n = if b < 0xC0 {
266 1
267 } else if b < 0xE0 {
268 2
269 } else if b < 0xF0 {
270 3
271 } else {
272 4
273 };
274 if left < n {
275 break;
276 }
277 }
278 let (cp, next) = base::utf8_decode(s, i);
279 if len.is_some() {
280 left = left.saturating_sub(next - i);
281 }
282 i = next;
283 if cp == 0xAD {
284 continue; }
286 let cp = if matches!(cp, 0xA0 | 0x2000..=0x200A | 0x202F | 0x205F) && !self.has(font, cp) { 0x20 } else { cp };
288 let mut f = font;
290 if fallback && !self.has(font, cp) {
291 if let Some(alt) = self.fallback_for(cp) {
292 f = alt;
293 }
294 }
295 let g = self.glyph(f, cp);
296 if prev >= 0 && f == prev_font {
297 let k = self.kern(f, prev as u32, g);
298 if k != 0 {
299 pen = pen.wrapping_add(spacing(self.units_fx_of(f, k)));
300 }
301 }
302 if let Some((dc, sf)) = target.as_mut() {
303 let flags = if self.slots.is_empty() { 0 } else { self.hdr(f).flags };
304 let mut drawn = false;
305 if flags & (SGH_COLR | SGH_CBDT) != 0 {
306 drawn = self.color_glyph(dc, sf, f, g, pen);
307 }
308 if !drawn {
309 self.glyph_draw(dc, sf, f, g, pen, true);
310 }
311 }
312 let adv = self.adv(f, g);
313 pen = pen.wrapping_add(spacing(self.units_fx_of(f, adv)));
314 prev = g as i32;
315 prev_font = f;
316 }
317 pen.wrapping_sub(pen0)
318 }
319
320 pub(crate) fn glyph_draw(&mut self, dc: &Dc, sf: &mut Surface, font: u32, g: u32, pen: i32, lcd: bool) {
325 let size = self.size;
326 let pen = self.font_raster(font).position(pen);
327 let phase = (pen >> 6) & 3;
328 let base = self.run_y;
329 let rec = self.rec.is_some();
330 if lcd && self.lcd_for(sf, font) {
331 self.lcd_prepare(dc.color);
332 let order = self.lcd;
333 let vertical = order >= SUBPIXEL_VRGB;
334 let bgr = order == SUBPIXEL_BGR || order == SUBPIXEL_VBGR;
335 match self.gc_get_lcd(font, g, size, phase, vertical) {
336 GcRef::None => return,
337 GcRef::Entry(_) => {
338 let key = glyphcache::lcd_key(font, g, size, phase, vertical);
339 if let (Some(e), Some(lut)) = (self.gc.map.get(&key), self.lcd_lut.as_deref()) {
340 match self.rec.as_mut() {
341 Some(r) => r.lcd(key, e, pen >> 8, base, dc.color, bgr, lut.adj()),
342 None => lcd::blit(dc, sf, pen >> 8, base, e, bgr, lut, lut.adj()),
343 }
344 }
345 return;
346 }
347 GcRef::Direct => {} }
349 }
350 match self.gc_get(font, g, size, phase) {
351 GcRef::None => {}
352 GcRef::Entry(e) if !rec => mask_blit(dc, sf, pen >> 8, base, e),
353 GcRef::Entry(_) => {
354 let key = glyphcache::gc_key(font, g, size, phase);
355 if let (Some(e), Some(r)) = (self.gc.map.get(&key), self.rec.as_mut()) {
356 r.mask(key, e, pen >> 8, base, dc.color);
357 }
358 }
359 GcRef::Direct if rec => {
360 if let Some(r) = self.rec.as_mut() {
361 r.fail(); }
363 }
364 GcRef::Direct => {
365 let (sx, sy) = self.gc_scale(font, size);
367 self.gp = Gp { x: (pen >> 6) as f32 * 0.25, y: base as f32, sx, sy, dx: 0, dy: 0 };
368 self.path.begin(dc);
369 self.glyph_path(font, g);
370 self.path.fill(&mut self.ras, dc, sf, 0);
371 }
372 }
373 }
374
375 fn color_glyph(&mut self, dc: &mut Dc, sf: &mut Surface, font: u32, g: u32, pen: i32) -> bool {
377 if self.hdr(font).flags & SGH_CBDT != 0 {
378 let size = self.size;
379 let base = self.run_y;
380 let rec = self.rec.is_some();
381 match self.gc_get_bitmap(font, g, size) {
382 Some(e) if !rec => {
383 bitmap_blit(dc, sf, pen >> 8, base, e);
384 return true;
385 }
386 Some(_) => {
387 let key = glyphcache::bitmap_key(font, g, size);
389 match (self.gc.map.get(&key), self.rec.as_mut()) {
390 (Some(e), Some(r)) => r.bitmap(key, e, pen >> 8, base, dc.color),
391 (None, Some(r)) => r.fail(),
392 _ => {}
393 }
394 return true;
395 }
396 None => {}
397 }
398 }
399 let mut layers = core::mem::take(&mut self.layers);
400 self.layers(font, g, LAYER_CAP, &mut layers);
401 if layers.is_empty() {
402 self.layers = layers;
403 return false;
404 }
405 let saved = dc.get_color();
406 for &(lg, argb) in &layers {
407 let c = if lg & LAYER_FG != 0 {
408 saved
409 } else {
410 let a = div255((argb >> 24) * (saved >> 24));
412 (a << 24) | (argb & 0xFF_FFFF)
413 };
414 dc.set_color(c);
415 self.glyph_draw(dc, sf, font, lg & 0xFFFF, pen, false);
416 }
417 dc.set_color(saved);
418 self.layers = layers;
419 true
420 }
421
422 pub fn caret_x(&mut self, s: &[u8], index: usize) -> i32 {
424 if self.shape_line(s,None) { return self.shaped_caret(index); }
425 (self.measure_n(s, index) + 128) >> 8
426 }
427
428 pub fn hit(&mut self, s: &[u8], len: Option<usize>, x: i32) -> usize {
431 if self.shape_line(s,len) { return self.shaped_hit(x); }
432 let xf = x << 8;
433 let mut i = 0usize;
434 let mut pen = 0i32;
435 loop {
436 if let Some(l) = len
437 && i >= l
438 {
439 break;
440 }
441 if i >= s.len() || s[i] == 0 || s[i] == b'\n' {
442 break;
443 }
444 let next = utf8_next(s, i);
445 let p = self.measure_n(s, next);
446 if xf < (pen.wrapping_add(p)) >> 1 {
448 break;
449 }
450 pen = p;
451 i = next;
452 }
453 i
454 }
455
456 pub fn decor(&self, dc: &Dc, sf: &mut Surface, x: i32, y: i32, w: i32, flags: u32) {
459 let m = self.metrics(self.font).unwrap_or_default();
460 if flags & TD_UNDERLINE != 0 {
461 self.td_rect(dc, sf, x, y, w, m.ul_pos, m.ul_thick);
462 }
463 if flags & TD_STRIKEOUT != 0 {
464 self.td_rect(dc, sf, x, y, w, m.st_pos, m.st_thick);
465 }
466 }
467
468 fn td_rect(&self, dc: &Dc, sf: &mut Surface, x: i32, y: i32, w: i32, pos: i32, thick: i32) {
470 let top = y.wrapping_sub(cvt(pos as f32 * self.sx));
471 let th = cvt(thick as f32 * self.sx).max(1);
472 dc.fill(sf, x, top, w, th);
473 }
474
475 pub fn icon_draw(&mut self, dc: &mut Dc, sf: &mut Surface, cp: u32, x: i32, y: i32, size_fx: i32) {
477 let saved = self.get_font();
478 self.set_font(FONT_ICON, size_fx);
479 let mut buf = Vec::new();
480 utf8_put(&mut buf, cp);
481 let asc = self.ascent(); self.draw(dc, sf, x, y + asc, &buf);
483 self.set_font(saved.0, saved.1);
484 }
485}
486
487fn png_decode(d: &[u8]) -> Option<Surface> {
489 let mut sf = Surface::new(0, 0, gfx::FMT_PARGB);
490 if img_png::dec::decode(d, &mut sf) == 0 { Some(sf) } else { None }
491}
492
493fn img_scale(src: &Surface, w: i32, h: i32) -> Option<Surface> {
494 img_core::ops::scale(src, w, h, true).ok()
495}
496
497fn utf8_next(s: &[u8], i: usize) -> usize {
499 base::utf8_decode(s, i).1
500}
501
502pub(crate) fn mask_blit(dc: &Dc, sf: &mut Surface, pen_x: i32, base: i32, gl: &GcEntry) {
505 let mut x0 = pen_x.wrapping_add(gl.left);
506 let mut y0 = base.wrapping_add(gl.top);
507 let mut sx = 0i32;
508 let mut sy = 0i32;
509 let x1 = x0.wrapping_add(gl.w).min(dc.clip[2]);
510 let y1 = y0.wrapping_add(gl.h).min(dc.clip[3]);
511 if dc.clip[0] > x0 {
512 sx = dc.clip[0] - x0;
513 x0 = dc.clip[0];
514 }
515 if dc.clip[1] > y0 {
516 sy = dc.clip[1] - y0;
517 y0 = dc.clip[1];
518 }
519 let w = x1 - x0;
520 let h = y1 - y0;
521 if w <= 0 || h <= 0 {
522 return;
523 }
524 let stride = sf.stride as usize;
525 for r in 0..h as usize {
526 let mo = (sy as usize + r) * gl.w as usize + sx as usize;
527 let mask = &gl.px[mo..mo + w as usize];
528 let o = ((y0 - dc.row0) as usize + r) * stride;
529 if sf.fmt == FMT_A8 {
530 blend::a8_over(&mut sf.px[o + x0 as usize..o + x1 as usize], mask, dc.pcol32 >> 24);
531 } else {
532 blend::mask_over(&mut sf.px[o + x0 as usize * 4..o + x1 as usize * 4], mask, &dc.pcol);
533 }
534 }
535}
536
537pub(crate) fn bitmap_blit(dc: &Dc, sf: &mut Surface, pen_x: i32, base: i32, e: &GcEntry) {
540 if sf.fmt == FMT_A8 {
541 return;
542 }
543 let mut x0 = pen_x.wrapping_add(e.left);
544 let mut y0 = base.wrapping_add(e.top);
545 let mut sx = 0i32;
546 let mut sy = 0i32;
547 let x1 = x0.wrapping_add(e.w).min(dc.clip[2]);
548 let y1 = y0.wrapping_add(e.h).min(dc.clip[3]);
549 if dc.clip[0] > x0 {
550 sx = dc.clip[0] - x0;
551 x0 = dc.clip[0];
552 }
553 if dc.clip[1] > y0 {
554 sy = dc.clip[1] - y0;
555 y0 = dc.clip[1];
556 }
557 let w = x1 - x0;
558 let h = y1 - y0;
559 if w <= 0 || h <= 0 {
560 return;
561 }
562 let op = div255((dc.color >> 24) * dc.opac);
563 let stride = sf.stride as usize;
564 let sstride = e.w as usize * 4;
565 for r in 0..h as usize {
566 let so = (sy as usize + r) * sstride + sx as usize * 4;
567 let o = ((y0 - dc.row0) as usize + r) * stride + x0 as usize * 4;
568 blend::blit_over(&mut sf.px[o..o + w as usize * 4], &e.px[so..so + w as usize * 4], op);
569 }
570}