1use std::collections::{BTreeMap, HashMap};
4
5use read_fonts::collections::IntSet;
6use types::GlyphId16;
7
8use crate::tables::{
9 layout::{
10 builders::{Builder, ClassDefBuilder, DeviceOrDeltas, Metric},
11 CoverageTable,
12 },
13 variations::ivs_builder::VariationStoreBuilder,
14};
15
16use super::{
17 AnchorTable, BaseArray, BaseRecord, Class1Record, Class2Record, ComponentRecord,
18 CursivePosFormat1, EntryExitRecord, LigatureArray, LigatureAttach, Mark2Array, Mark2Record,
19 MarkArray, MarkBasePosFormat1, MarkLigPosFormat1, MarkMarkPosFormat1, MarkRecord, PairPos,
20 PairSet, PairValueRecord, SinglePos, ValueFormat, ValueRecord,
21};
22
23type GlyphSet = IntSet<GlyphId16>;
24
25#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28pub struct ValueRecordBuilder {
29 pub x_advance: Option<Metric>,
31 pub y_advance: Option<Metric>,
33 pub x_placement: Option<Metric>,
35 pub y_placement: Option<Metric>,
37}
38
39#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
41#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
42pub struct AnchorBuilder {
43 pub x: Metric,
45 pub y: Metric,
47 pub contourpoint: Option<u16>,
51}
52
53impl ValueRecordBuilder {
54 pub fn new() -> Self {
56 Default::default()
57 }
58
59 pub fn make_rtl_compatible(&mut self) {
64 if self.x_placement.is_none() {
65 self.x_placement.clone_from(&self.x_advance);
66 }
67 }
68
69 pub fn with_x_placement(mut self, val: i16) -> Self {
72 self.x_placement
73 .get_or_insert_with(Default::default)
74 .default = val;
75 self
76 }
77
78 pub fn with_y_placement(mut self, val: i16) -> Self {
80 self.y_placement
81 .get_or_insert_with(Default::default)
82 .default = val;
83 self
84 }
85
86 pub fn with_x_advance(mut self, val: i16) -> Self {
88 self.x_advance.get_or_insert_with(Default::default).default = val;
89 self
90 }
91
92 pub fn with_y_advance(mut self, val: i16) -> Self {
94 self.y_advance.get_or_insert_with(Default::default).default = val;
95 self
96 }
97
98 pub fn with_x_placement_device(mut self, val: impl Into<DeviceOrDeltas>) -> Self {
102 self.x_placement
103 .get_or_insert_with(Default::default)
104 .device_or_deltas = val.into();
105 self
106 }
107
108 pub fn with_y_placement_device(mut self, val: impl Into<DeviceOrDeltas>) -> Self {
112 self.y_placement
113 .get_or_insert_with(Default::default)
114 .device_or_deltas = val.into();
115 self
116 }
117
118 pub fn with_x_advance_device(mut self, val: impl Into<DeviceOrDeltas>) -> Self {
122 self.x_advance
123 .get_or_insert_with(Default::default)
124 .device_or_deltas = val.into();
125 self
126 }
127
128 pub fn with_y_advance_device(mut self, val: impl Into<DeviceOrDeltas>) -> Self {
132 self.y_advance
133 .get_or_insert_with(Default::default)
134 .device_or_deltas = val.into();
135 self
136 }
137
138 pub fn clear_zeros(mut self) -> Self {
140 self.x_advance = self.x_advance.filter(|m| !m.is_zero());
141 self.y_advance = self.y_advance.filter(|m| !m.is_zero());
142 self.x_placement = self.x_placement.filter(|m| !m.is_zero());
143 self.y_placement = self.y_placement.filter(|m| !m.is_zero());
144 self
145 }
146
147 pub fn format(&self) -> ValueFormat {
149 const EMPTY: ValueFormat = ValueFormat::empty();
150 use ValueFormat as VF;
151
152 let get_flags = |field: &Option<Metric>, def_flag, dev_flag| {
153 let field = field.as_ref();
154 let def_flag = if field.is_some() { def_flag } else { EMPTY };
155 let dev_flag = field
156 .and_then(|fld| (!fld.device_or_deltas.is_none()).then_some(dev_flag))
157 .unwrap_or(EMPTY);
158 (def_flag, dev_flag)
159 };
160
161 let (x_adv, x_adv_dev) = get_flags(&self.x_advance, VF::X_ADVANCE, VF::X_ADVANCE_DEVICE);
162 let (y_adv, y_adv_dev) = get_flags(&self.y_advance, VF::Y_ADVANCE, VF::Y_ADVANCE_DEVICE);
163 let (x_place, x_place_dev) =
164 get_flags(&self.x_placement, VF::X_PLACEMENT, VF::X_PLACEMENT_DEVICE);
165 let (y_place, y_place_dev) =
166 get_flags(&self.y_placement, VF::Y_PLACEMENT, VF::Y_PLACEMENT_DEVICE);
167 x_adv | y_adv | x_place | y_place | x_adv_dev | y_adv_dev | x_place_dev | y_place_dev
168 }
169
170 pub fn is_all_zeros(&self) -> bool {
172 let device_mask = ValueFormat::X_PLACEMENT_DEVICE
173 | ValueFormat::Y_PLACEMENT_DEVICE
174 | ValueFormat::X_ADVANCE_DEVICE
175 | ValueFormat::Y_ADVANCE_DEVICE;
176
177 let format = self.format();
178 if format.is_empty() || format.intersects(device_mask) {
179 return false;
180 }
181 let all_values = [
182 &self.x_placement,
183 &self.y_placement,
184 &self.x_advance,
185 &self.y_advance,
186 ];
187 all_values
188 .iter()
189 .all(|v| v.as_ref().map(|v| v.is_zero()).unwrap_or(true))
190 }
191
192 pub fn build(self, var_store: &mut VariationStoreBuilder) -> ValueRecord {
194 let mut result = ValueRecord::new();
195 result.x_advance = self.x_advance.as_ref().map(|val| val.default);
196 result.y_advance = self.y_advance.as_ref().map(|val| val.default);
197 result.x_placement = self.x_placement.as_ref().map(|val| val.default);
198 result.y_placement = self.y_placement.as_ref().map(|val| val.default);
199 result.x_advance_device = self
200 .x_advance
201 .and_then(|val| val.device_or_deltas.build(var_store))
202 .into();
203 result.y_advance_device = self
204 .y_advance
205 .and_then(|val| val.device_or_deltas.build(var_store))
206 .into();
207 result.x_placement_device = self
208 .x_placement
209 .and_then(|val| val.device_or_deltas.build(var_store))
210 .into();
211 result.y_placement_device = self
212 .y_placement
213 .and_then(|val| val.device_or_deltas.build(var_store))
214 .into();
215
216 result
217 }
218}
219
220impl AnchorBuilder {
221 pub fn new(x: i16, y: i16) -> Self {
223 AnchorBuilder {
224 x: x.into(),
225 y: y.into(),
226 contourpoint: None,
227 }
228 }
229
230 pub fn with_x_device(mut self, val: impl Into<DeviceOrDeltas>) -> Self {
234 self.x.device_or_deltas = val.into();
235 self
236 }
237
238 pub fn with_y_device(mut self, val: impl Into<DeviceOrDeltas>) -> Self {
242 self.y.device_or_deltas = val.into();
243 self
244 }
245
246 pub fn with_contourpoint(mut self, idx: u16) -> Self {
251 self.contourpoint = Some(idx);
252 self
253 }
254
255 pub fn build(self, var_store: &mut VariationStoreBuilder) -> AnchorTable {
257 let x = self.x.default;
258 let y = self.y.default;
259 let x_dev = self.x.device_or_deltas.build(var_store);
260 let y_dev = self.y.device_or_deltas.build(var_store);
261 if x_dev.is_some() || y_dev.is_some() {
262 AnchorTable::format_3(x, y, x_dev, y_dev)
263 } else if let Some(point) = self.contourpoint {
264 AnchorTable::format_2(x, y, point)
265 } else {
266 AnchorTable::format_1(x, y)
267 }
268 }
269}
270
271#[derive(Clone, Debug, Default, PartialEq, Eq)]
273#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
274pub struct SinglePosBuilder {
275 items: BTreeMap<GlyphId16, ValueRecordBuilder>,
276}
277
278impl SinglePosBuilder {
279 pub fn len(&self) -> usize {
281 self.items.len()
282 }
283
284 pub fn is_empty(&self) -> bool {
286 self.items.is_empty()
287 }
288
289 pub fn insert(&mut self, glyph: GlyphId16, record: ValueRecordBuilder) {
291 self.items.insert(glyph, record);
292 }
293
294 pub fn can_add(&self, glyph: GlyphId16, value: &ValueRecordBuilder) -> bool {
296 self.items
297 .get(&glyph)
298 .map(|existing| existing == value)
299 .unwrap_or(true)
300 }
301
302 pub fn iter(&self) -> impl Iterator<Item = (GlyphId16, &ValueRecordBuilder)> + '_ {
304 self.items.iter().map(|(glyph, value)| (*glyph, value))
305 }
306}
307
308impl Builder for SinglePosBuilder {
309 type Output = Vec<SinglePos>;
310
311 fn build(self, var_store: &mut VariationStoreBuilder) -> Self::Output {
312 fn build_subtable(items: BTreeMap<GlyphId16, &ValueRecord>) -> SinglePos {
313 let first = *items.values().next().unwrap();
314 let use_format_1 = first.format().is_empty() || items.values().all(|val| val == &first);
315 let coverage: CoverageTable = items.keys().copied().collect();
316 if use_format_1 {
317 SinglePos::format_1(coverage.clone(), first.clone())
318 } else {
319 SinglePos::format_2(coverage, items.into_values().cloned().collect())
320 }
321 }
322 const NEW_SUBTABLE_COST: usize = 10;
323 let items = self
324 .items
325 .into_iter()
326 .map(|(glyph, anchor)| (glyph, anchor.build(var_store)))
327 .collect::<BTreeMap<_, _>>();
328
329 let mut subtables = Vec::new();
331 let mut group_by_record: HashMap<&ValueRecord, BTreeMap<GlyphId16, &ValueRecord>> =
332 Default::default();
333
334 for (gid, value) in &items {
337 group_by_record
338 .entry(value)
339 .or_default()
340 .insert(*gid, value);
341 }
342 let mut group_by_format: HashMap<ValueFormat, BTreeMap<GlyphId16, &ValueRecord>> =
343 Default::default();
344 for (value, glyphs) in group_by_record {
345 if glyphs.len() * value.encoded_size() > NEW_SUBTABLE_COST {
347 subtables.push(glyphs);
348 } else {
351 group_by_format
352 .entry(value.format())
353 .or_default()
354 .extend(glyphs.into_iter());
355 }
356 }
357 subtables.extend(group_by_format.into_values());
358
359 let mut output = subtables
360 .into_iter()
361 .map(build_subtable)
362 .collect::<Vec<_>>();
363
364 output.sort_unstable_by_key(|table| match table {
367 SinglePos::Format1(table) => cmp_coverage_key(&table.coverage),
368 SinglePos::Format2(table) => cmp_coverage_key(&table.coverage),
369 });
370 output
371 }
372}
373
374fn cmp_coverage_key(coverage: &CoverageTable) -> impl Ord {
375 (std::cmp::Reverse(coverage.len()), coverage.iter().next())
376}
377
378#[derive(Clone, Debug, Default, PartialEq)]
382#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
383pub struct PairPosBuilder {
384 pairs: GlyphPairPosBuilder,
385 classes: ClassPairPosBuilder,
386}
387
388#[derive(Clone, Debug, Default, PartialEq)]
389#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
390struct GlyphPairPosBuilder(
391 BTreeMap<GlyphId16, BTreeMap<GlyphId16, (ValueRecordBuilder, ValueRecordBuilder)>>,
392);
393
394#[derive(Clone, Debug, PartialEq)]
395#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
396struct ClassPairPosSubtable {
397 items:
398 BTreeMap<IntSet<GlyphId16>, BTreeMap<GlyphSet, (ValueRecordBuilder, ValueRecordBuilder)>>,
399 classdef_1: ClassDefBuilder,
400 classdef_2: ClassDefBuilder,
401}
402
403impl Default for ClassPairPosSubtable {
404 fn default() -> Self {
405 Self {
406 items: Default::default(),
407 classdef_1: ClassDefBuilder::new_using_class_0(),
408 classdef_2: Default::default(),
409 }
410 }
411}
412
413#[derive(Clone, Debug, Default, PartialEq)]
414#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
415struct ClassPairPosBuilder(Vec<ClassPairPosSubtable>);
416
417impl ClassPairPosBuilder {
418 fn insert(
419 &mut self,
420 class1: GlyphSet,
421 record1: ValueRecordBuilder,
422 class2: GlyphSet,
423 record2: ValueRecordBuilder,
424 ) {
425 if self.0.last().map(|last| last.can_add(&class1, &class2)) != Some(true) {
426 self.0.push(Default::default())
427 }
428 self.0
429 .last_mut()
430 .unwrap()
431 .add(class1, class2, record1, record2);
432 }
433}
434
435impl ClassPairPosSubtable {
436 fn can_add(&self, class1: &GlyphSet, class2: &GlyphSet) -> bool {
437 self.classdef_1.can_add(class1) && self.classdef_2.can_add(class2)
438 }
439
440 fn add(
441 &mut self,
442 class1: GlyphSet,
443 class2: GlyphSet,
444 record1: ValueRecordBuilder,
445 record2: ValueRecordBuilder,
446 ) {
447 self.classdef_1.checked_add(class1.clone());
448 self.classdef_2.checked_add(class2.clone());
449 self.items
450 .entry(class1)
451 .or_default()
452 .insert(class2, (record1, record2));
453 }
454
455 fn compute_value_formats(&self) -> (ValueFormat, ValueFormat) {
462 self.items.values().flat_map(|v| v.values()).fold(
463 (ValueFormat::empty(), ValueFormat::empty()),
464 |(acc1, acc2), (f1, f2)| (acc1 | f1.format(), acc2 | f2.format()),
465 )
466 }
467}
468
469impl PairPosBuilder {
470 pub fn is_empty(&self) -> bool {
472 self.pairs.0.is_empty() && self.classes.0.is_empty()
473 }
474
475 pub fn len(&self) -> usize {
477 self.pairs.0.values().map(|vals| vals.len()).sum::<usize>()
478 + self
479 .classes
480 .0
481 .iter()
482 .map(|sub| sub.items.values().len())
483 .sum::<usize>()
484 }
485
486 pub fn insert_pair(
488 &mut self,
489 glyph1: GlyphId16,
490 record1: ValueRecordBuilder,
491 glyph2: GlyphId16,
492 record2: ValueRecordBuilder,
493 ) {
494 self.pairs
506 .0
507 .entry(glyph1)
508 .or_default()
509 .entry(glyph2)
510 .or_insert((record1, record2));
511 }
512
513 pub fn insert_classes(
515 &mut self,
516 class1: GlyphSet,
517 record1: ValueRecordBuilder,
518 class2: GlyphSet,
519 record2: ValueRecordBuilder,
520 ) {
521 self.classes.insert(class1, record1, class2, record2)
522 }
523
524 pub fn iter_pairs(
528 &self,
529 ) -> impl Iterator<
530 Item = (
531 GlyphId16,
532 GlyphId16,
533 &ValueRecordBuilder,
534 &ValueRecordBuilder,
535 ),
536 > + '_ {
537 self.pairs.0.iter().flat_map(|(glyph1, seconds)| {
538 seconds
539 .iter()
540 .map(move |(glyph2, (record1, record2))| (*glyph1, *glyph2, record1, record2))
541 })
542 }
543
544 pub fn iter_class_pairs(
552 &self,
553 ) -> impl Iterator<
554 Item = (
555 &IntSet<GlyphId16>,
556 &IntSet<GlyphId16>,
557 &ValueRecordBuilder,
558 &ValueRecordBuilder,
559 ),
560 > + '_ {
561 self.iter_class_subtables().flatten()
562 }
563
564 pub fn iter_class_subtables(
571 &self,
572 ) -> impl Iterator<
573 Item = impl Iterator<
574 Item = (
575 &IntSet<GlyphId16>,
576 &IntSet<GlyphId16>,
577 &ValueRecordBuilder,
578 &ValueRecordBuilder,
579 ),
580 >,
581 > + '_ {
582 self.classes.0.iter().map(|subtable| {
583 subtable.items.iter().flat_map(|(class1, seconds)| {
584 seconds
585 .iter()
586 .map(move |(class2, (record1, record2))| (class1, class2, record1, record2))
587 })
588 })
589 }
590}
591
592impl Builder for PairPosBuilder {
593 type Output = Vec<PairPos>;
594
595 fn build(self, var_store: &mut VariationStoreBuilder) -> Self::Output {
596 let mut out = self.pairs.build(var_store);
597 out.extend(self.classes.build(var_store));
598 out
599 }
600}
601
602impl Builder for GlyphPairPosBuilder {
603 type Output = Vec<PairPos>;
604
605 fn build(self, var_store: &mut VariationStoreBuilder) -> Self::Output {
606 let mut split_by_format = BTreeMap::<_, BTreeMap<_, Vec<_>>>::default();
607 for (g1, map) in self.0 {
608 for (g2, (v1, v2)) in map {
609 split_by_format
610 .entry((v1.format(), v2.format()))
611 .or_default()
612 .entry(g1)
613 .or_default()
614 .push(PairValueRecord::new(
615 g2,
616 v1.build(var_store),
617 v2.build(var_store),
618 ));
619 }
620 }
621
622 split_by_format
623 .into_values()
624 .map(|map| {
625 let coverage = map.keys().copied().collect();
626 let pair_sets = map.into_values().map(PairSet::new).collect();
627 PairPos::format_1(coverage, pair_sets)
628 })
629 .collect()
630 }
631}
632
633impl Builder for ClassPairPosBuilder {
634 type Output = Vec<PairPos>;
635
636 fn build(self, var_store: &mut VariationStoreBuilder) -> Self::Output {
637 self.0.into_iter().map(|sub| sub.build(var_store)).collect()
638 }
639}
640
641impl Builder for ClassPairPosSubtable {
642 type Output = PairPos;
643
644 fn build(self, var_store: &mut VariationStoreBuilder) -> Self::Output {
645 assert!(!self.items.is_empty(), "filter before here");
646 let (format1, format2) = self.compute_value_formats();
647 let empty_record = Class2Record::new(
651 ValueRecord::new().with_explicit_value_format(format1),
652 ValueRecord::new().with_explicit_value_format(format2),
653 );
654
655 let (class1def, class1map) = self.classdef_1.build_with_mapping();
656 let (class2def, class2map) = self.classdef_2.build_with_mapping();
657
658 let coverage = self.items.keys().flat_map(GlyphSet::iter).collect();
659
660 let mut out = vec![Class1Record::default(); self.items.len()];
661 for (cls1, stuff) in self.items {
662 let idx = class1map.get(&cls1).unwrap();
663 let mut records = vec![empty_record.clone(); class2map.len() + 1];
664 for (class, (v1, v2)) in stuff {
665 let idx = class2map.get(&class).unwrap();
666 records[*idx as usize] = Class2Record::new(
667 v1.build(var_store).with_explicit_value_format(format1),
668 v2.build(var_store).with_explicit_value_format(format2),
669 );
670 }
671 out[*idx as usize] = Class1Record::new(records);
672 }
673 PairPos::format_2(coverage, class1def, class2def, out)
674 }
675}
676
677#[derive(Clone, Debug, Default, PartialEq, Eq)]
679#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
680pub struct CursivePosBuilder {
681 items: BTreeMap<GlyphId16, (Option<AnchorBuilder>, Option<AnchorBuilder>)>,
683}
684
685impl CursivePosBuilder {
686 pub fn len(&self) -> usize {
688 self.items.len()
689 }
690
691 pub fn is_empty(&self) -> bool {
693 self.items.is_empty()
694 }
695
696 pub fn insert(
698 &mut self,
699 glyph: GlyphId16,
700 entry: Option<AnchorBuilder>,
701 exit: Option<AnchorBuilder>,
702 ) {
703 self.items.insert(glyph, (entry, exit));
704 }
705
706 pub fn iter(
710 &self,
711 ) -> impl Iterator<Item = (GlyphId16, Option<&AnchorBuilder>, Option<&AnchorBuilder>)> + '_
712 {
713 self.items
714 .iter()
715 .map(|(glyph, (entry, exit))| (*glyph, entry.as_ref(), exit.as_ref()))
716 }
717}
718
719impl Builder for CursivePosBuilder {
720 type Output = Vec<CursivePosFormat1>;
721
722 fn build(self, var_store: &mut VariationStoreBuilder) -> Self::Output {
723 let coverage = self.items.keys().copied().collect();
724 let records = self
725 .items
726 .into_values()
727 .map(|(entry, exit)| {
728 EntryExitRecord::new(
729 entry.map(|x| x.build(var_store)),
730 exit.map(|x| x.build(var_store)),
731 )
732 })
733 .collect();
734 vec![CursivePosFormat1::new(coverage, records)]
735 }
736}
737
738#[derive(Clone, Debug, Default, PartialEq, Eq)]
740#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
741struct MarkList {
742 glyphs: BTreeMap<GlyphId16, (u16, AnchorBuilder)>,
744 classes: HashMap<String, u16>,
746}
747
748impl MarkList {
749 fn insert(
753 &mut self,
754 glyph: GlyphId16,
755 class: &str,
756 anchor: AnchorBuilder,
757 ) -> Result<u16, PreviouslyAssignedClass> {
758 let next_id = self.classes.len().try_into().unwrap();
759 let id = self.classes.get(class).copied().unwrap_or_else(|| {
760 self.classes.insert(class.to_owned(), next_id);
761 next_id
762 });
763 if let Some(prev) = self
764 .glyphs
765 .insert(glyph, (id, anchor))
766 .filter(|prev| prev.0 != id)
767 {
768 let class = self
769 .classes
770 .iter()
771 .find_map(|(name, idx)| (*idx == prev.0).then(|| name.clone()))
772 .unwrap();
773
774 return Err(PreviouslyAssignedClass {
775 glyph_id: glyph,
776 class,
777 });
778 }
779 Ok(id)
780 }
781
782 fn glyphs(&self) -> impl Iterator<Item = GlyphId16> + Clone + '_ {
783 self.glyphs.keys().copied()
784 }
785
786 fn class_names(&self) -> Vec<&str> {
791 let mut names = vec![""; self.classes.len()];
792 for (name, id) in &self.classes {
793 names[*id as usize] = name.as_str();
794 }
795 names
796 }
797
798 fn iter(&self) -> impl Iterator<Item = (GlyphId16, &str, &AnchorBuilder)> + '_ {
799 let names = self.class_names();
800 self.glyphs
801 .iter()
802 .map(move |(glyph, (class, anchor))| (*glyph, names[*class as usize], anchor))
803 }
804
805 fn get_class(&self, class_name: &str) -> u16 {
806 *self
807 .classes
808 .get(class_name)
809 .expect("marks added before bases")
811 }
812}
813
814impl Builder for MarkList {
815 type Output = (CoverageTable, MarkArray);
816
817 fn build(self, var_store: &mut VariationStoreBuilder) -> Self::Output {
818 let coverage = self.glyphs().collect();
819 let array = MarkArray::new(
820 self.glyphs
821 .into_values()
822 .map(|(class, anchor)| MarkRecord::new(class, anchor.build(var_store)))
823 .collect(),
824 );
825 (coverage, array)
826 }
827}
828
829#[derive(Clone, Debug, Default, PartialEq, Eq)]
831#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
832pub struct MarkToBaseBuilder {
833 marks: MarkList,
834 bases: BTreeMap<GlyphId16, Vec<(u16, AnchorBuilder)>>,
835}
836
837#[derive(Clone, Debug, Default)]
839pub struct PreviouslyAssignedClass {
840 pub glyph_id: GlyphId16,
842 pub class: String,
844}
845
846impl std::error::Error for PreviouslyAssignedClass {}
847
848impl std::fmt::Display for PreviouslyAssignedClass {
849 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
850 write!(
851 f,
852 "Glyph '{}' was previously assigned to class '{}'",
853 self.glyph_id.to_u16(),
854 self.class
855 )
856 }
857}
858
859impl MarkToBaseBuilder {
860 pub fn len(&self) -> usize {
862 self.bases.len()
863 }
864
865 pub fn is_empty(&self) -> bool {
867 self.bases.is_empty()
868 }
869
870 pub fn insert_mark(
875 &mut self,
876 glyph: GlyphId16,
877 class: &str,
878 anchor: AnchorBuilder,
879 ) -> Result<u16, PreviouslyAssignedClass> {
880 self.marks.insert(glyph, class, anchor)
881 }
882
883 pub fn insert_base(&mut self, glyph: GlyphId16, class: &str, anchor: AnchorBuilder) {
885 let class = self.marks.get_class(class);
886 self.bases.entry(glyph).or_default().push((class, anchor))
887 }
888
889 pub fn base_glyphs(&self) -> impl Iterator<Item = GlyphId16> + Clone + '_ {
891 self.bases.keys().copied()
892 }
893
894 pub fn mark_glyphs(&self) -> impl Iterator<Item = GlyphId16> + Clone + '_ {
896 self.marks.glyphs()
897 }
898
899 pub fn iter_marks(&self) -> impl Iterator<Item = (GlyphId16, &str, &AnchorBuilder)> + '_ {
905 self.marks.iter()
906 }
907
908 pub fn iter_bases(&self) -> impl Iterator<Item = (GlyphId16, &str, &AnchorBuilder)> + '_ {
913 let names = self.marks.class_names();
914 self.bases
915 .iter()
916 .flat_map(|(glyph, anchors)| {
917 anchors
918 .iter()
919 .map(move |(class, anchor)| (*glyph, *class, anchor))
920 })
921 .map(move |(glyph, class, anchor)| (glyph, names[class as usize], anchor))
922 }
923}
924
925impl Builder for MarkToBaseBuilder {
926 type Output = Vec<MarkBasePosFormat1>;
927
928 fn build(self, var_store: &mut VariationStoreBuilder) -> Self::Output {
929 let MarkToBaseBuilder { marks, bases } = self;
930 let n_classes = marks.classes.len();
931
932 let (mark_coverage, mark_array) = marks.build(var_store);
933 let base_coverage = bases.keys().copied().collect();
934 let base_records = bases
935 .into_values()
936 .map(|anchors| {
937 let mut anchor_offsets = vec![None; n_classes];
938 for (class, anchor) in anchors {
939 anchor_offsets[class as usize] = Some(anchor.build(var_store));
940 }
941 BaseRecord::new(anchor_offsets)
942 })
943 .collect();
944 let base_array = BaseArray::new(base_records);
945 vec![MarkBasePosFormat1::new(
946 mark_coverage,
947 base_coverage,
948 mark_array,
949 base_array,
950 )]
951 }
952}
953
954#[derive(Clone, Debug, Default, PartialEq, Eq)]
956#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
957pub struct MarkToLigBuilder {
958 marks: MarkList,
959 ligatures: BTreeMap<GlyphId16, Vec<BTreeMap<String, AnchorBuilder>>>,
960}
961
962impl MarkToLigBuilder {
963 pub fn len(&self) -> usize {
965 self.ligatures.len()
966 }
967
968 pub fn is_empty(&self) -> bool {
970 self.ligatures.is_empty()
971 }
972
973 pub fn insert_mark(
978 &mut self,
979 glyph: GlyphId16,
980 class: &str,
981 anchor: AnchorBuilder,
982 ) -> Result<u16, PreviouslyAssignedClass> {
983 self.marks.insert(glyph, class, anchor)
984 }
985
986 pub fn add_ligature_components_directly(
999 &mut self,
1000 glyph: GlyphId16,
1001 components: Vec<BTreeMap<String, AnchorBuilder>>,
1002 ) {
1003 self.ligatures.insert(glyph, components);
1004 }
1005
1006 pub fn insert_ligature(
1015 &mut self,
1016 glyph: GlyphId16,
1017 class: &str,
1018 components: Vec<Option<AnchorBuilder>>,
1019 ) {
1020 let component_list = self.ligatures.entry(glyph).or_default();
1021 if component_list.is_empty() {
1022 component_list.resize(components.len(), Default::default());
1023 } else if component_list.len() != components.len() {
1024 log::warn!("mismatched component lengths for anchors in glyph {glyph}");
1025 }
1026 for (i, anchor) in components.into_iter().enumerate() {
1027 if let Some(anchor) = anchor {
1028 component_list[i].insert(class.to_owned(), anchor);
1029 }
1030 }
1031 }
1032
1033 pub fn mark_glyphs(&self) -> impl Iterator<Item = GlyphId16> + Clone + '_ {
1035 self.marks.glyphs()
1036 }
1037
1038 pub fn lig_glyphs(&self) -> impl Iterator<Item = GlyphId16> + Clone + '_ {
1040 self.ligatures.keys().copied()
1041 }
1042
1043 pub fn iter_marks(&self) -> impl Iterator<Item = (GlyphId16, &str, &AnchorBuilder)> + '_ {
1049 self.marks.iter()
1050 }
1051
1052 pub fn iter_ligatures(
1058 &self,
1059 ) -> impl Iterator<Item = (GlyphId16, &[BTreeMap<String, AnchorBuilder>])> + '_ {
1060 self.ligatures
1061 .iter()
1062 .map(|(glyph, components)| (*glyph, components.as_slice()))
1063 }
1064}
1065
1066impl Builder for MarkToLigBuilder {
1067 type Output = Vec<MarkLigPosFormat1>;
1068
1069 fn build(self, var_store: &mut VariationStoreBuilder) -> Self::Output {
1070 let MarkToLigBuilder { marks, ligatures } = self;
1071 let n_classes = marks.classes.len();
1072
1073 let ligature_coverage = ligatures.keys().copied().collect();
1078 let ligature_array = ligatures
1079 .into_values()
1080 .map(|components| {
1081 let comp_records = components
1082 .into_iter()
1083 .map(|anchors| {
1084 let mut anchor_offsets = vec![None; n_classes];
1085 for (class, anchor) in anchors {
1086 let class_idx = marks.get_class(&class);
1087 anchor_offsets[class_idx as usize] = Some(anchor.build(var_store));
1088 }
1089 ComponentRecord::new(anchor_offsets)
1090 })
1091 .collect();
1092 LigatureAttach::new(comp_records)
1093 })
1094 .collect();
1095 let ligature_array = LigatureArray::new(ligature_array);
1096 let (mark_coverage, mark_array) = marks.build(var_store);
1097 vec![MarkLigPosFormat1::new(
1098 mark_coverage,
1099 ligature_coverage,
1100 mark_array,
1101 ligature_array,
1102 )]
1103 }
1104}
1105
1106#[derive(Clone, Debug, Default, PartialEq, Eq)]
1108#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1109pub struct MarkToMarkBuilder {
1110 attaching_marks: MarkList,
1111 base_marks: BTreeMap<GlyphId16, Vec<(u16, AnchorBuilder)>>,
1112}
1113
1114impl MarkToMarkBuilder {
1115 pub fn len(&self) -> usize {
1117 self.base_marks.len()
1118 }
1119
1120 pub fn is_empty(&self) -> bool {
1122 self.base_marks.is_empty()
1123 }
1124
1125 pub fn insert_mark1(
1130 &mut self,
1131 glyph: GlyphId16,
1132 class: &str,
1133 anchor: AnchorBuilder,
1134 ) -> Result<u16, PreviouslyAssignedClass> {
1135 self.attaching_marks.insert(glyph, class, anchor)
1136 }
1137
1138 pub fn insert_mark2(&mut self, glyph: GlyphId16, class: &str, anchor: AnchorBuilder) {
1140 let id = self.attaching_marks.get_class(class);
1141 self.base_marks.entry(glyph).or_default().push((id, anchor))
1142 }
1143
1144 pub fn mark1_glyphs(&self) -> impl Iterator<Item = GlyphId16> + Clone + '_ {
1146 self.attaching_marks.glyphs()
1147 }
1148
1149 pub fn mark2_glyphs(&self) -> impl Iterator<Item = GlyphId16> + Clone + '_ {
1151 self.base_marks.keys().copied()
1152 }
1153
1154 pub fn iter_mark1s(&self) -> impl Iterator<Item = (GlyphId16, &str, &AnchorBuilder)> + '_ {
1160 self.attaching_marks.iter()
1161 }
1162
1163 pub fn iter_mark2s(&self) -> impl Iterator<Item = (GlyphId16, &str, &AnchorBuilder)> + '_ {
1168 let names = self.attaching_marks.class_names();
1169 self.base_marks
1170 .iter()
1171 .flat_map(|(glyph, anchors)| {
1172 anchors
1173 .iter()
1174 .map(move |(class, anchor)| (*glyph, *class, anchor))
1175 })
1176 .map(move |(glyph, class, anchor)| (glyph, names[class as usize], anchor))
1177 }
1178}
1179
1180impl Builder for MarkToMarkBuilder {
1181 type Output = Vec<MarkMarkPosFormat1>;
1182
1183 fn build(self, var_store: &mut VariationStoreBuilder) -> Self::Output {
1184 let MarkToMarkBuilder {
1185 attaching_marks,
1186 base_marks,
1187 } = self;
1188 let n_classes = attaching_marks.classes.len();
1189
1190 let (mark_coverage, mark_array) = attaching_marks.build(var_store);
1191 let mark2_coverage = base_marks.keys().copied().collect();
1192 let mark2_records = base_marks
1193 .into_values()
1194 .map(|anchors| {
1195 let mut anchor_offsets = vec![None; n_classes];
1196 for (class, anchor) in anchors {
1197 anchor_offsets[class as usize] = Some(anchor.build(var_store));
1198 }
1199 Mark2Record::new(anchor_offsets)
1200 })
1201 .collect();
1202 let mark2array = Mark2Array::new(mark2_records);
1203 vec![MarkMarkPosFormat1::new(
1204 mark_coverage,
1205 mark2_coverage,
1206 mark_array,
1207 mark2array,
1208 )]
1209 }
1210}
1211
1212#[cfg(test)]
1213mod tests {
1214 use super::*;
1215
1216 fn gid(raw: u16) -> GlyphId16 {
1217 GlyphId16::new(raw)
1218 }
1219
1220 fn advance(val: i16) -> ValueRecordBuilder {
1221 ValueRecordBuilder::new().with_x_advance(val)
1222 }
1223
1224 #[test]
1225 fn single_pos_round_trip() {
1226 let mut builder = SinglePosBuilder::default();
1227 builder.insert(gid(5), advance(-10));
1228 builder.insert(gid(1), advance(20));
1229
1230 let items = builder.iter().collect::<Vec<_>>();
1232 assert_eq!(items, vec![(gid(1), &advance(20)), (gid(5), &advance(-10))]);
1233 }
1234
1235 #[test]
1236 fn pair_pos_round_trip() {
1237 let mut builder = PairPosBuilder::default();
1238 builder.insert_pair(gid(1), advance(7), gid(2), ValueRecordBuilder::new());
1239 builder.insert_classes(
1240 [gid(3), gid(4)].into_iter().collect(),
1241 advance(9),
1242 [gid(5)].into_iter().collect(),
1243 ValueRecordBuilder::new(),
1244 );
1245
1246 let pairs = builder
1247 .iter_pairs()
1248 .map(|(g1, g2, v1, _)| (g1, g2, v1.clone()))
1249 .collect::<Vec<_>>();
1250 assert_eq!(pairs, vec![(gid(1), gid(2), advance(7))]);
1251
1252 let classes = builder
1253 .iter_class_pairs()
1254 .map(|(c1, c2, v1, _)| (c1.iter().collect::<Vec<_>>(), c2.len(), v1.clone()))
1255 .collect::<Vec<_>>();
1256 assert_eq!(classes, vec![(vec![gid(3), gid(4)], 1, advance(9))]);
1257 }
1258
1259 #[test]
1260 fn class_pair_subtable_boundaries() {
1261 let class = |ids: &[u16]| ids.iter().map(|id| gid(*id)).collect::<IntSet<_>>();
1262 let mut builder = PairPosBuilder::default();
1263 builder.insert_classes(class(&[1, 2]), advance(1), class(&[9]), advance(0));
1264 builder.insert_classes(class(&[1, 2, 3]), advance(2), class(&[9]), advance(0));
1266 builder.insert_classes(class(&[4]), advance(3), class(&[9]), advance(0));
1268
1269 let subtables = builder
1270 .iter_class_subtables()
1271 .map(|rules| rules.map(|(_, _, v1, _)| v1.clone()).collect::<Vec<_>>())
1272 .collect::<Vec<_>>();
1273 assert_eq!(
1274 subtables,
1275 vec![vec![advance(1)], vec![advance(2), advance(3)]]
1276 );
1277 assert_eq!(builder.iter_class_pairs().count(), 3);
1278 }
1279
1280 #[test]
1281 fn cursive_round_trip() {
1282 let mut builder = CursivePosBuilder::default();
1283 builder.insert(gid(1), Some(AnchorBuilder::new(10, 20)), None);
1284
1285 let items = builder
1286 .iter()
1287 .map(|(g, entry, exit)| (g, entry.cloned(), exit.cloned()))
1288 .collect::<Vec<_>>();
1289 assert_eq!(
1290 items,
1291 vec![(gid(1), Some(AnchorBuilder::new(10, 20)), None)]
1292 );
1293 }
1294
1295 #[test]
1296 fn mark_to_base_round_trip() {
1297 let mut builder = MarkToBaseBuilder::default();
1298 builder
1299 .insert_mark(gid(10), "top", AnchorBuilder::new(1, 2))
1300 .unwrap();
1301 builder
1302 .insert_mark(gid(11), "bottom", AnchorBuilder::new(3, 4))
1303 .unwrap();
1304 builder.insert_base(gid(1), "top", AnchorBuilder::new(5, 6));
1305 builder.insert_base(gid(1), "bottom", AnchorBuilder::new(7, 8));
1306
1307 let marks = builder
1308 .iter_marks()
1309 .map(|(g, class, anchor)| (g, class, anchor.clone()))
1310 .collect::<Vec<_>>();
1311 assert_eq!(
1312 marks,
1313 vec![
1314 (gid(10), "top", AnchorBuilder::new(1, 2)),
1315 (gid(11), "bottom", AnchorBuilder::new(3, 4)),
1316 ]
1317 );
1318
1319 let bases = builder
1321 .iter_bases()
1322 .map(|(g, class, anchor)| (g, class, anchor.clone()))
1323 .collect::<Vec<_>>();
1324 assert_eq!(
1325 bases,
1326 vec![
1327 (gid(1), "top", AnchorBuilder::new(5, 6)),
1328 (gid(1), "bottom", AnchorBuilder::new(7, 8)),
1329 ]
1330 );
1331 }
1332
1333 #[test]
1336 fn mark_class_names_are_id_order_independent() {
1337 let mut first = MarkToBaseBuilder::default();
1338 first
1339 .insert_mark(gid(10), "top", AnchorBuilder::new(1, 2))
1340 .unwrap();
1341 first
1342 .insert_mark(gid(11), "bottom", AnchorBuilder::new(3, 4))
1343 .unwrap();
1344 first.insert_base(gid(1), "bottom", AnchorBuilder::new(7, 8));
1345
1346 let mut second = MarkToBaseBuilder::default();
1347 second
1348 .insert_mark(gid(11), "bottom", AnchorBuilder::new(3, 4))
1349 .unwrap();
1350 second
1351 .insert_mark(gid(10), "top", AnchorBuilder::new(1, 2))
1352 .unwrap();
1353 second.insert_base(gid(1), "bottom", AnchorBuilder::new(7, 8));
1354
1355 assert_eq!(
1356 first.iter_bases().map(|(_, c, _)| c).collect::<Vec<_>>(),
1357 second.iter_bases().map(|(_, c, _)| c).collect::<Vec<_>>(),
1358 );
1359 assert_ne!(first.marks.classes, second.marks.classes);
1361 }
1362
1363 #[test]
1364 fn mark_to_mark_round_trip() {
1365 let mut builder = MarkToMarkBuilder::default();
1366 builder
1367 .insert_mark1(gid(10), "top", AnchorBuilder::new(1, 2))
1368 .unwrap();
1369 builder.insert_mark2(gid(20), "top", AnchorBuilder::new(3, 4));
1370
1371 assert_eq!(
1372 builder
1373 .iter_mark1s()
1374 .map(|(g, c, _)| (g, c))
1375 .collect::<Vec<_>>(),
1376 vec![(gid(10), "top")]
1377 );
1378 assert_eq!(
1379 builder
1380 .iter_mark2s()
1381 .map(|(g, c, _)| (g, c))
1382 .collect::<Vec<_>>(),
1383 vec![(gid(20), "top")]
1384 );
1385 }
1386
1387 #[test]
1388 fn mark_to_lig_round_trip() {
1389 let mut builder = MarkToLigBuilder::default();
1390 builder
1391 .insert_mark(gid(10), "top", AnchorBuilder::new(1, 2))
1392 .unwrap();
1393 builder.insert_ligature(gid(1), "top", vec![Some(AnchorBuilder::new(5, 6)), None]);
1394
1395 let ligs = builder.iter_ligatures().collect::<Vec<_>>();
1396 assert_eq!(ligs.len(), 1);
1397 let (glyph, components) = ligs[0];
1398 assert_eq!(glyph, gid(1));
1399 assert_eq!(components.len(), 2);
1400 assert_eq!(components[0].get("top"), Some(&AnchorBuilder::new(5, 6)));
1401 assert!(components[1].is_empty());
1403 }
1404}