1use std::collections::{BTreeMap, HashMap, HashSet};
4
5use read_fonts::collections::IntSet;
6use types::GlyphId16;
7
8use super::{
9 ClassDef, ClassDefFormat1, ClassDefFormat2, ClassRangeRecord, CoverageFormat1, CoverageFormat2,
10 CoverageTable, Device, DeviceOrVariationIndex, Lookup, LookupFlag, PendingVariationIndex,
11 RangeRecord,
12};
13use crate::tables::{
14 gdef::CaretValue,
15 variations::{ivs_builder::VariationStoreBuilder, VariationRegion},
16};
17
18pub trait Builder {
22 type Output;
27 fn build(self, var_store: &mut VariationStoreBuilder) -> Self::Output;
40}
41
42pub(crate) type FilterSetId = u16;
43
44#[derive(Clone, Debug, Default)]
45pub struct LookupBuilder<T> {
46 pub flags: LookupFlag,
47 pub mark_set: Option<FilterSetId>,
48 pub subtables: Vec<T>,
49}
50
51#[derive(Clone, Debug, Default, PartialEq, Eq)]
71#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
72pub struct ClassDefBuilder {
73 classes: HashSet<IntSet<GlyphId16>>,
74 all_glyphs: IntSet<GlyphId16>,
75 use_class_0: bool,
76}
77
78#[derive(Debug, Default, PartialEq, Eq)]
82pub struct CoverageTableBuilder {
83 glyphs: Vec<GlyphId16>,
85}
86
87#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
95#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
96pub struct Metric {
97 pub default: i16,
99 pub device_or_deltas: DeviceOrDeltas,
101}
102
103#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
111#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
112#[allow(missing_docs)]
113pub enum DeviceOrDeltas {
114 Device(Device),
115 Deltas(Vec<(VariationRegion, i16)>),
116 #[default]
117 None,
118}
119
120#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
122#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
123pub enum CaretValueBuilder {
124 Coordinate {
126 default: i16,
128 deltas: DeviceOrDeltas,
130 },
131 PointIndex(u16),
135}
136
137impl ClassDefBuilder {
138 pub fn new() -> Self {
140 Self::default()
141 }
142
143 pub fn new_using_class_0() -> Self {
151 Self {
152 use_class_0: true,
153 ..Default::default()
154 }
155 }
156
157 pub(crate) fn can_add(&self, cls: &IntSet<GlyphId16>) -> bool {
158 self.classes.contains(cls) || cls.iter().all(|gid| !self.all_glyphs.contains(gid))
159 }
160
161 pub fn checked_add(&mut self, cls: IntSet<GlyphId16>) -> bool {
165 if self.can_add(&cls) {
166 self.all_glyphs.extend(cls.iter());
167 self.classes.insert(cls);
168 true
169 } else {
170 false
171 }
172 }
173
174 pub fn build_with_mapping(self) -> (ClassDef, HashMap<IntSet<GlyphId16>, u16>) {
182 let mut classes = self.classes.into_iter().collect::<Vec<_>>();
183 classes.sort_unstable_by_key(|cls| {
186 (
187 std::cmp::Reverse(cls.len()),
188 cls.iter().next().unwrap_or_default().to_u16(),
189 )
190 });
191 classes.dedup();
192 let add_one = u16::from(!self.use_class_0);
193 let mapping = classes
194 .into_iter()
195 .enumerate()
196 .map(|(i, cls)| (cls, i as u16 + add_one))
197 .collect::<HashMap<_, _>>();
198 let class_def = mapping
199 .iter()
200 .flat_map(|(cls, id)| cls.iter().map(move |gid| (gid, *id)))
201 .collect();
202
203 (class_def, mapping)
204 }
205
206 pub fn build(self) -> ClassDef {
208 self.build_with_mapping().0
209 }
210}
211
212#[derive(Debug, PartialEq, Eq)]
219pub(super) struct ClassDefBuilderImpl {
220 items: BTreeMap<GlyphId16, u16>,
221}
222
223impl ClassDefBuilderImpl {
224 fn prefer_format_1(&self) -> bool {
225 const U16_LEN: usize = std::mem::size_of::<u16>();
226 const FORMAT1_HEADER_LEN: usize = U16_LEN * 3;
227 const FORMAT2_HEADER_LEN: usize = U16_LEN * 2;
228 const CLASS_RANGE_RECORD_LEN: usize = U16_LEN * 3;
229 if self.items.is_empty() {
231 return false;
232 }
233 let first = self.items.keys().next().map(|g| g.to_u16()).unwrap();
235 let last = self.items.keys().next_back().map(|g| g.to_u16()).unwrap();
236 let format1_array_len = (last - first) as usize + 1;
237 let len_format1 = FORMAT1_HEADER_LEN + format1_array_len * U16_LEN;
238 let len_format2 =
239 FORMAT2_HEADER_LEN + iter_class_ranges(&self.items).count() * CLASS_RANGE_RECORD_LEN;
240
241 len_format1 < len_format2
242 }
243
244 pub fn build(&self) -> ClassDef {
245 if self.prefer_format_1() {
246 let first = self.items.keys().next().map(|g| g.to_u16()).unwrap_or(0);
247 let last = self.items.keys().next_back().map(|g| g.to_u16());
248 let class_value_array = (first..=last.unwrap_or_default())
249 .map(|g| self.items.get(&GlyphId16::new(g)).copied().unwrap_or(0))
250 .collect();
251 ClassDef::Format1(ClassDefFormat1 {
252 start_glyph_id: self
253 .items
254 .keys()
255 .next()
256 .copied()
257 .unwrap_or(GlyphId16::NOTDEF),
258 class_value_array,
259 })
260 } else {
261 ClassDef::Format2(ClassDefFormat2 {
262 class_range_records: iter_class_ranges(&self.items).collect(),
263 })
264 }
265 }
266}
267
268impl CoverageTableBuilder {
269 pub fn from_glyphs(mut glyphs: Vec<GlyphId16>) -> Self {
271 glyphs.sort_unstable();
272 glyphs.dedup();
273 CoverageTableBuilder { glyphs }
274 }
275
276 pub fn add(&mut self, glyph: GlyphId16) -> u16 {
282 match self.glyphs.binary_search(&glyph) {
283 Ok(ix) => ix as u16,
284 Err(ix) => {
285 self.glyphs.insert(ix, glyph);
286 ix.try_into().unwrap()
288 }
289 }
290 }
291
292 pub fn build(self) -> CoverageTable {
296 if should_choose_coverage_format_2(&self.glyphs) {
297 CoverageTable::Format2(CoverageFormat2 {
298 range_records: RangeRecord::iter_for_glyphs(&self.glyphs).collect(),
299 })
300 } else {
301 CoverageTable::Format1(CoverageFormat1 {
302 glyph_array: self.glyphs,
303 })
304 }
305 }
306}
307
308impl<T: Default> LookupBuilder<T> {
309 pub fn new(flags: LookupFlag, mark_set: Option<FilterSetId>) -> Self {
310 LookupBuilder {
311 flags,
312 mark_set,
313 subtables: vec![Default::default()],
314 }
315 }
316
317 pub fn new_with_lookups(
318 flags: LookupFlag,
319 mark_set: Option<FilterSetId>,
320 subtables: Vec<T>,
321 ) -> Self {
322 Self {
323 flags,
324 mark_set,
325 subtables,
326 }
327 }
328
329 pub fn last_mut(&mut self) -> Option<&mut T> {
331 self.subtables.last_mut()
332 }
333
334 pub fn force_subtable_break(&mut self) {
335 self.subtables.push(Default::default())
336 }
337
338 pub fn iter_subtables(&self) -> impl Iterator<Item = &T> + '_ {
339 self.subtables.iter()
340 }
341}
342
343impl<U> LookupBuilder<U> {
344 pub fn convert<T: From<U>>(self) -> LookupBuilder<T> {
346 let LookupBuilder {
347 flags,
348 mark_set,
349 subtables,
350 } = self;
351 LookupBuilder {
352 flags,
353 mark_set,
354 subtables: subtables.into_iter().map(Into::into).collect(),
355 }
356 }
357}
358
359impl<U, T> Builder for LookupBuilder<T>
360where
361 T: Builder<Output = Vec<U>>,
362 U: Default,
363{
364 type Output = Lookup<U>;
365
366 fn build(self, var_store: &mut VariationStoreBuilder) -> Self::Output {
367 let subtables = self
368 .subtables
369 .into_iter()
370 .flat_map(|b| b.build(var_store).into_iter())
371 .collect();
372 let mut out = Lookup::new(self.flags, subtables);
373 out.mark_filtering_set = self.mark_set;
374 out
375 }
376}
377
378impl Metric {
379 pub fn is_zero(&self) -> bool {
381 self.default == 0 && !self.has_device_or_deltas()
382 }
383
384 pub fn has_device_or_deltas(&self) -> bool {
386 !self.device_or_deltas.is_none()
387 }
388}
389
390impl DeviceOrDeltas {
391 pub fn is_none(&self) -> bool {
393 *self == DeviceOrDeltas::None
394 }
395
396 pub fn build(self, var_store: &mut VariationStoreBuilder) -> Option<DeviceOrVariationIndex> {
406 match self {
407 DeviceOrDeltas::Device(dev) => Some(DeviceOrVariationIndex::Device(dev)),
408 DeviceOrDeltas::Deltas(deltas) => {
409 let temp_id = var_store.add_deltas(deltas);
410 Some(DeviceOrVariationIndex::PendingVariationIndex(
411 PendingVariationIndex::new(temp_id),
412 ))
413 }
414 DeviceOrDeltas::None => None,
415 }
416 }
417}
418
419impl CaretValueBuilder {
420 pub fn build(self, var_store: &mut VariationStoreBuilder) -> CaretValue {
422 match self {
423 Self::Coordinate { default, deltas } => match deltas.build(var_store) {
424 Some(deltas) => CaretValue::format_3(default, deltas),
425 None => CaretValue::format_1(default),
426 },
427 Self::PointIndex(index) => CaretValue::format_2(index),
428 }
429 }
430}
431
432impl From<i16> for Metric {
433 fn from(src: i16) -> Metric {
434 Metric {
435 default: src,
436 device_or_deltas: DeviceOrDeltas::None,
437 }
438 }
439}
440
441impl From<Option<Device>> for DeviceOrDeltas {
442 fn from(src: Option<Device>) -> DeviceOrDeltas {
443 src.map(DeviceOrDeltas::Device).unwrap_or_default()
444 }
445}
446
447impl From<Device> for DeviceOrDeltas {
448 fn from(value: Device) -> Self {
449 DeviceOrDeltas::Device(value)
450 }
451}
452
453impl From<Vec<(VariationRegion, i16)>> for DeviceOrDeltas {
454 fn from(src: Vec<(VariationRegion, i16)>) -> DeviceOrDeltas {
455 if src.is_empty() {
456 DeviceOrDeltas::None
457 } else {
458 DeviceOrDeltas::Deltas(src)
459 }
460 }
461}
462impl FromIterator<(GlyphId16, u16)> for ClassDefBuilderImpl {
463 fn from_iter<T: IntoIterator<Item = (GlyphId16, u16)>>(iter: T) -> Self {
464 Self {
465 items: iter.into_iter().filter(|(_, cls)| *cls != 0).collect(),
466 }
467 }
468}
469
470impl FromIterator<GlyphId16> for CoverageTableBuilder {
471 fn from_iter<T: IntoIterator<Item = GlyphId16>>(iter: T) -> Self {
472 let glyphs = iter.into_iter().collect::<Vec<_>>();
473 CoverageTableBuilder::from_glyphs(glyphs)
474 }
475}
476
477fn iter_class_ranges(
478 values: &BTreeMap<GlyphId16, u16>,
479) -> impl Iterator<Item = ClassRangeRecord> + '_ {
480 let mut iter = values.iter();
481 let mut prev = None;
482
483 #[allow(clippy::while_let_on_iterator)]
484 std::iter::from_fn(move || {
485 while let Some((gid, class)) = iter.next() {
486 match prev.take() {
487 None => prev = Some((*gid, *gid, *class)),
488 Some((start, end, pclass))
489 if super::are_sequential(end, *gid) && pclass == *class =>
490 {
491 prev = Some((start, *gid, pclass))
492 }
493 Some((start_glyph_id, end_glyph_id, pclass)) => {
494 prev = Some((*gid, *gid, *class));
495 return Some(ClassRangeRecord {
496 start_glyph_id,
497 end_glyph_id,
498 class: pclass,
499 });
500 }
501 }
502 }
503 prev.take()
504 .map(|(start_glyph_id, end_glyph_id, class)| ClassRangeRecord {
505 start_glyph_id,
506 end_glyph_id,
507 class,
508 })
509 })
510}
511
512fn should_choose_coverage_format_2(glyphs: &[GlyphId16]) -> bool {
513 let format2_len = 4 + RangeRecord::iter_for_glyphs(glyphs).count() * 6;
514 let format1_len = 4 + glyphs.len() * 2;
515 format2_len < format1_len
516}
517
518#[cfg(test)]
519mod tests {
520 use std::ops::RangeInclusive;
521
522 use read_fonts::collections::IntSet;
523
524 use crate::tables::layout::DeltaFormat;
525
526 use super::*;
527
528 #[test]
529 fn classdef_format() {
530 let builder: ClassDefBuilderImpl = [(3u16, 4u16), (4, 6), (5, 1), (9, 5), (10, 2), (11, 3)]
531 .map(|(gid, cls)| (GlyphId16::new(gid), cls))
532 .into_iter()
533 .collect();
534
535 assert!(builder.prefer_format_1());
536
537 let builder: ClassDefBuilderImpl = [(1u16, 1u16), (3, 4), (9, 5), (10, 2), (11, 3)]
538 .map(|(gid, cls)| (GlyphId16::new(gid), cls))
539 .into_iter()
540 .collect();
541
542 assert!(builder.prefer_format_1());
543 }
544
545 #[test]
546 fn classdef_prefer_format2() {
547 fn iter_class_items(
548 start: u16,
549 end: u16,
550 cls: u16,
551 ) -> impl Iterator<Item = (GlyphId16, u16)> {
552 (start..=end).map(move |gid| (GlyphId16::new(gid), cls))
553 }
554
555 let builder: ClassDefBuilderImpl = iter_class_items(5, 8, 3)
558 .chain(iter_class_items(9, 12, 4))
559 .chain(iter_class_items(13, 16, 5))
560 .collect();
561
562 assert!(!builder.prefer_format_1());
563 }
564
565 #[test]
566 fn delta_format_dflt() {
567 let some: DeltaFormat = Default::default();
568 assert_eq!(some, DeltaFormat::Local2BitDeltas);
569 }
570
571 fn make_glyph_vec<const N: usize>(gids: [u16; N]) -> Vec<GlyphId16> {
572 gids.into_iter().map(GlyphId16::new).collect()
573 }
574
575 #[test]
576 fn coverage_builder() {
577 let coverage = make_glyph_vec([1u16, 2, 9, 3, 6, 9])
578 .into_iter()
579 .collect::<CoverageTableBuilder>();
580 assert_eq!(coverage.glyphs, make_glyph_vec([1, 2, 3, 6, 9]));
581 }
582
583 fn make_class<const N: usize>(gid_class_pairs: [(u16, u16); N]) -> ClassDef {
584 gid_class_pairs
585 .iter()
586 .map(|(gid, cls)| (GlyphId16::new(*gid), *cls))
587 .collect::<ClassDefBuilderImpl>()
588 .build()
589 }
590
591 #[test]
592 fn class_def_builder_zero() {
593 let class = make_class([(4, 0), (5, 1)]);
595 assert!(class.get_raw(GlyphId16::new(4)).is_none());
596 assert_eq!(class.get_raw(GlyphId16::new(5)), Some(1));
597 assert!(class.get_raw(GlyphId16::new(100)).is_none());
598 }
599
600 #[test]
603 fn class_def_builder_empty() {
604 let builder = ClassDefBuilderImpl::from_iter([]);
605 let built = builder.build();
606
607 assert_eq!(
608 built,
609 ClassDef::Format2(ClassDefFormat2 {
610 class_range_records: vec![]
611 })
612 )
613 }
614
615 #[test]
616 fn class_def_small() {
617 let class = make_class([(1, 1), (2, 1), (3, 1)]);
618
619 assert_eq!(
620 class,
621 ClassDef::Format2(ClassDefFormat2 {
622 class_range_records: vec![ClassRangeRecord {
623 start_glyph_id: GlyphId16::new(1),
624 end_glyph_id: GlyphId16::new(3),
625 class: 1
626 }]
627 })
628 )
629 }
630
631 #[test]
632 fn classdef_f2_get() {
633 fn make_f2_class<const N: usize>(range: [RangeInclusive<u16>; N]) -> ClassDef {
634 ClassDefFormat2::new(
635 range
636 .into_iter()
637 .enumerate()
638 .map(|(i, range)| {
639 ClassRangeRecord::new(
640 GlyphId16::new(*range.start()),
641 GlyphId16::new(*range.end()),
642 (1 + i) as _,
643 )
644 })
645 .collect(),
646 )
647 .into()
648 }
649
650 let cls = make_f2_class([1..=1, 2..=9]);
651 assert_eq!(cls.get(GlyphId16::new(2)), 2);
652 assert_eq!(cls.get(GlyphId16::new(20)), 0);
653 }
654
655 fn make_glyph_class<const N: usize>(glyphs: [u16; N]) -> IntSet<GlyphId16> {
656 glyphs.into_iter().map(GlyphId16::new).collect()
657 }
658
659 #[test]
660 fn smoke_test_class_builder() {
661 let mut builder = ClassDefBuilder::new();
662 builder.checked_add(make_glyph_class([6, 10]));
663 let cls = builder.build();
664 assert_eq!(cls.get(GlyphId16::new(6)), 1);
665
666 let mut builder = ClassDefBuilder::new_using_class_0();
667 builder.checked_add(make_glyph_class([6, 10]));
668 let cls = builder.build();
669 assert_eq!(cls.get(GlyphId16::new(6)), 0);
670 assert_eq!(cls.get(GlyphId16::new(10)), 0);
671 }
672
673 #[test]
674 fn classdef_assign_order() {
675 let mut builder = ClassDefBuilder::default();
679 builder.checked_add(make_glyph_class([7, 8, 9]));
680 builder.checked_add(make_glyph_class([1, 12]));
681 builder.checked_add(make_glyph_class([3, 4]));
682 let cls = builder.build();
683 assert_eq!(cls.get(GlyphId16::new(9)), 1);
684 assert_eq!(cls.get(GlyphId16::new(1)), 2);
685 assert_eq!(cls.get(GlyphId16::new(4)), 3);
686 assert_eq!(cls.get(GlyphId16::new(5)), 0);
688 }
689
690 #[test]
691 fn we_handle_dupes() {
692 let mut builder = ClassDefBuilder::default();
693 let c1 = make_glyph_class([1, 2, 3, 4]);
694 let c2 = make_glyph_class([4, 3, 2, 1, 1]);
695 let c3 = make_glyph_class([1, 5, 6, 7]);
696 assert!(builder.checked_add(c1.clone()));
697 assert!(builder.checked_add(c2.clone()));
698 assert!(!builder.checked_add(c3.clone()));
699
700 let (_, map) = builder.build_with_mapping();
701 assert_eq!(map.get(&c1), map.get(&c2));
702 assert!(!map.contains_key(&c3));
703 }
704}