ttf_parser/tables/
sbix.rs
1use core::convert::TryFrom;
4use core::num::NonZeroU16;
5
6use crate::{GlyphId, RasterGlyphImage, RasterImageFormat, Tag};
7use crate::parser::{Stream, FromData, Offset, Offset32};
8
9pub fn parse(
10 data: &[u8],
11 number_of_glyphs: NonZeroU16,
12 glyph_id: GlyphId,
13 pixels_per_em: u16,
14 depth: u8,
15) -> Option<RasterGlyphImage> {
16 if depth == 10 {
17 return None;
18 }
19
20 let total_glyphs = u32::from(number_of_glyphs.get().checked_add(1)?);
21
22 let mut s = Stream::new(data);
23 let version: u16 = s.read()?;
24 if version != 1 {
25 return None;
26 }
27
28 s.skip::<u16>(); let count: u32 = s.read()?;
30 if count == 0 {
31 return None;
32 }
33
34 let strikes = s.read_array32::<Offset32>(count)?;
35
36 let mut idx = 0;
38 let mut max_ppem = 0;
39 {
40 for (i, offset) in strikes.into_iter().enumerate() {
41 let mut s = Stream::new_at(data, offset.to_usize())?;
42 let ppem: u16 = s.read()?;
43 s.skip::<u16>(); if (pixels_per_em <= ppem && ppem < max_ppem) ||
46 (pixels_per_em > max_ppem && ppem > max_ppem)
47 {
48 idx = i as u32;
49 max_ppem = ppem;
50 }
51 }
52 }
53
54 let offset = strikes.get(idx)?;
55 let mut s = Stream::new_at(data, offset.to_usize())?;
56 s.skip::<u16>(); s.skip::<u16>(); let glyph_offsets = s.read_array32::<Offset32>(total_glyphs)?;
60 let start = glyph_offsets.get(u32::from(glyph_id.0))?.to_usize();
61 let end = glyph_offsets.get(u32::from(glyph_id.0.checked_add(1)?))?.to_usize();
62
63 if start == end {
64 return None;
66 }
67
68 let data_len = end.checked_sub(start)?.checked_sub(8)?; let mut s = Stream::new_at(data, offset.to_usize() + start)?;
71 let x: i16 = s.read()?;
72 let y: i16 = s.read()?;
73 let image_type: Tag = s.read()?;
74 let image_data = s.read_bytes(data_len)?;
75
76 let format = match &image_type.to_bytes() {
80 b"png " => RasterImageFormat::PNG,
81 b"dupe" => {
82 let glyph_id = GlyphId::parse(image_data)?;
86 return parse(data, number_of_glyphs, glyph_id, pixels_per_em, depth + 1);
87 }
88 _ => {
89 return None;
91 }
92 };
93
94 let (width, height) = png_size(image_data)?;
95
96 Some(RasterGlyphImage {
97 x,
98 y,
99 width,
100 height,
101 pixels_per_em: max_ppem,
102 format,
103 data: image_data,
104 })
105}
106
107fn png_size(data: &[u8]) -> Option<(u16, u16)> {
111 let mut s = Stream::new_at(data, 16)?;
113 let width: u32 = s.read()?;
114 let height: u32 = s.read()?;
115
116 Some((
118 u16::try_from(width).ok()?,
119 u16::try_from(height).ok()?,
120 ))
121}