1use crate::CacheKey;
2use crate::font::cid::Type0Font;
3use crate::font::true_type::TrueTypeFont;
4use crate::font::type1::Type1Font;
5use kurbo::BezPath;
6use pdf_font::OutlineBuilder;
7use pdf_font::cmap::BfString;
8use skrifa::GlyphId;
9use skrifa::outline::OutlinePen;
10use std::rc::Rc;
11
12#[derive(Clone)]
14pub struct OutlineFontData {
15 pub data: crate::font::FontData,
17 pub cache_key: u128,
19 pub postscript_name: Option<String>,
21 pub weight: Option<u32>,
23 pub is_italic: bool,
25 pub is_serif: bool,
27 pub is_monospace: bool,
29}
30
31pub(crate) struct OutlinePath(BezPath);
32
33impl OutlinePath {
34 pub(crate) fn new() -> Self {
35 Self(BezPath::new())
36 }
37
38 pub(crate) fn take(self) -> BezPath {
39 self.0
40 }
41}
42
43impl OutlinePen for OutlinePath {
44 #[inline]
45 fn move_to(&mut self, x: f32, y: f32) {
46 self.0.move_to((x, y));
47 }
48
49 #[inline]
50 fn line_to(&mut self, x: f32, y: f32) {
51 if !self.0.elements().is_empty() {
52 self.0.line_to((x, y));
53 }
54 }
55
56 #[inline]
57 fn quad_to(&mut self, cx: f32, cy: f32, x: f32, y: f32) {
58 if !self.0.elements().is_empty() {
59 self.0.quad_to((cx, cy), (x, y));
60 }
61 }
62
63 #[inline]
64 fn curve_to(&mut self, cx0: f32, cy0: f32, cx1: f32, cy1: f32, x: f32, y: f32) {
65 if !self.0.elements().is_empty() {
66 self.0.curve_to((cx0, cy0), (cx1, cy1), (x, y));
67 }
68 }
69
70 #[inline]
71 fn close(&mut self) {
72 if !self.0.elements().is_empty() {
73 self.0.close_path();
74 }
75 }
76}
77
78impl OutlineBuilder for OutlinePath {
79 fn move_to(&mut self, x: f32, y: f32) {
80 self.0.move_to((x, y));
81 }
82
83 fn line_to(&mut self, x: f32, y: f32) {
84 if !self.0.elements().is_empty() {
85 self.0.line_to((x, y));
86 }
87 }
88
89 fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) {
90 if !self.0.elements().is_empty() {
91 self.0.quad_to((x1, y1), (x, y));
92 }
93 }
94
95 fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) {
96 if !self.0.elements().is_empty() {
97 self.0.curve_to((x1, y1), (x2, y2), (x, y));
98 }
99 }
100
101 fn close(&mut self) {
102 if !self.0.elements().is_empty() {
103 self.0.close_path();
104 }
105 }
106}
107
108#[derive(Debug, Clone)]
109pub(crate) enum OutlineFont {
110 Type1(Rc<Type1Font>),
111 TrueType(Rc<TrueTypeFont>),
112 Type0(Rc<Type0Font>),
113}
114
115impl CacheKey for OutlineFont {
116 fn cache_key(&self) -> u128 {
117 match self {
118 Self::Type1(f) => f.cache_key(),
119 Self::TrueType(t) => t.cache_key(),
120 Self::Type0(t0) => t0.cache_key(),
121 }
122 }
123}
124
125impl OutlineFont {
126 pub(crate) fn outline_glyph(&self, glyph: GlyphId, code: u32) -> BezPath {
127 match self {
128 Self::Type1(t) => t.outline_glyph(glyph),
129 Self::TrueType(t) => t.outline_glyph(glyph),
130 Self::Type0(t) => t.outline_glyph(glyph, code),
131 }
132 }
133
134 pub(crate) fn char_code_to_unicode(&self, char_code: u32) -> Option<BfString> {
135 match self {
136 Self::Type1(t) => t.char_code_to_unicode(char_code),
137 Self::TrueType(t) => t.char_code_to_unicode(char_code),
138 Self::Type0(t) => t.char_code_to_unicode(char_code),
139 }
140 }
141
142 pub(crate) fn glyph_advance_width(&self, char_code: u32) -> Option<f32> {
144 match self {
145 Self::Type1(t) => t.glyph_width(char_code as u8),
146 Self::TrueType(t) => Some(t.glyph_width(char_code as u8)),
147 Self::Type0(t) => Some(t.code_advance(char_code).x as f32),
148 }
149 }
150
151 pub(crate) fn font_data(&self) -> Option<OutlineFontData> {
155 match self {
156 Self::Type1(_) => None,
157 Self::TrueType(t) => Some(OutlineFontData {
158 data: t.font_data()?,
159 cache_key: t.cache_key(),
160 postscript_name: t.postscript_name().map(|s| s.to_string()),
161 weight: t.weight(),
162 is_italic: t.is_italic(),
163 is_serif: t.is_serif(),
164 is_monospace: t.is_monospace(),
165 }),
166 Self::Type0(t) => Some(OutlineFontData {
167 data: t.font_data()?,
168 cache_key: t.cache_key(),
169 postscript_name: t.postscript_name().map(|s| s.to_string()),
170 weight: t.weight(),
171 is_italic: t.is_italic(),
172 is_serif: t.is_serif(),
173 is_monospace: t.is_monospace(),
174 }),
175 }
176 }
177}