1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8pub use read_fonts::tables::gpos::ValueFormat;
9
10#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14pub struct Gpos {
15 pub script_list: NullableOffsetMarker<ScriptList>,
17 pub feature_list: NullableOffsetMarker<FeatureList>,
19 pub lookup_list: NullableOffsetMarker<OriginalPositionLookupList>,
21 pub feature_variations: NullableOffsetMarker<FeatureVariations, WIDTH_32>,
22 pub script_list2: NullableOffsetMarker<ScriptList, WIDTH_32>,
24 pub feature_list2: NullableOffsetMarker<FeatureList, WIDTH_32>,
26 pub lookup_list2: NullableOffsetMarker<PositionLookupList2, WIDTH_32>,
28}
29
30impl Default for Gpos {
31 fn default() -> Self {
32 Self {
33 script_list: Some(Default::default()).into(),
34 feature_list: Some(Default::default()).into(),
35 lookup_list: Some(Default::default()).into(),
36 feature_variations: Default::default(),
37 script_list2: Default::default(),
38 feature_list2: Default::default(),
39 lookup_list2: Default::default(),
40 }
41 }
42}
43
44impl FontWrite for Gpos {
45 #[allow(clippy::unnecessary_cast)]
46 fn write_into(&self, writer: &mut TableWriter) {
47 let version = self.compute_version() as MajorMinor;
48 version.write_into(writer);
49 self.script_list.write_into(writer);
50 self.feature_list.write_into(writer);
51 self.lookup_list.write_into(writer);
52 version
53 .compatible((1u16, 1u16))
54 .then(|| self.feature_variations.write_into(writer));
55 version
56 .compatible((1u16, 2u16))
57 .then(|| self.script_list2.write_into(writer));
58 version
59 .compatible((1u16, 2u16))
60 .then(|| self.feature_list2.write_into(writer));
61 version
62 .compatible((1u16, 2u16))
63 .then(|| self.lookup_list2.write_into(writer));
64 }
65 fn table_type(&self) -> TableType {
66 TableType::TopLevel(Gpos::TAG)
67 }
68}
69
70impl Validate for Gpos {
71 fn validate_impl(&self, ctx: &mut ValidationCtx) {
72 ctx.in_table("Gpos", |ctx| {
73 ctx.in_field("script_list", |ctx| {
74 self.script_list.validate_impl(ctx);
75 });
76 ctx.in_field("feature_list", |ctx| {
77 self.feature_list.validate_impl(ctx);
78 });
79 ctx.in_field("lookup_list", |ctx| {
80 self.lookup_list.validate_impl(ctx);
81 });
82 ctx.in_field("feature_variations", |ctx| {
83 self.feature_variations.validate_impl(ctx);
84 });
85 ctx.in_field("script_list2", |ctx| {
86 self.script_list2.validate_impl(ctx);
87 });
88 ctx.in_field("feature_list2", |ctx| {
89 self.feature_list2.validate_impl(ctx);
90 });
91 ctx.in_field("lookup_list2", |ctx| {
92 self.lookup_list2.validate_impl(ctx);
93 });
94 })
95 }
96}
97
98impl TopLevelTable for Gpos {
99 const TAG: Tag = Tag::new(b"GPOS");
100}
101
102impl<'a> FromObjRef<read_fonts::tables::gpos::Gpos<'a>> for Gpos {
103 fn from_obj_ref(obj: &read_fonts::tables::gpos::Gpos<'a>, _: FontData) -> Self {
104 Gpos {
105 script_list: obj.original_script_list().to_owned_table(),
106 feature_list: obj.original_feature_list().to_owned_table(),
107 lookup_list: obj.original_lookup_list().to_owned_table(),
108 feature_variations: obj.feature_variations().to_owned_table(),
109 script_list2: obj.script_list2().to_owned_table(),
110 feature_list2: obj.feature_list2().to_owned_table(),
111 lookup_list2: obj.lookup_list2().to_owned_table(),
112 }
113 }
114}
115
116#[allow(clippy::needless_lifetimes)]
117impl<'a> FromTableRef<read_fonts::tables::gpos::Gpos<'a>> for Gpos {}
118
119impl ReadArgs for Gpos {
120 type Args = ();
121}
122
123impl<'a> FontRead<'a> for Gpos {
124 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
125 <read_fonts::tables::gpos::Gpos as FontRead>::read(data).map(|x| x.to_owned_table())
126 }
127}
128
129#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
131#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
132pub enum PositionLookup {
133 Single(Lookup<SinglePos>),
134 Pair(Lookup<PairPos>),
135 Cursive(Lookup<CursivePos>),
136 MarkToBase(Lookup<MarkBasePos>),
137 MarkToLig(Lookup<MarkLigPos>),
138 MarkToMark(Lookup<MarkMarkPos>),
139 Contextual(Lookup<PositionSequenceContext>),
140 ChainContextual(Lookup<PositionChainContext>),
141 Extension(Lookup<ExtensionSubtable>),
142}
143
144impl Default for PositionLookup {
145 fn default() -> Self {
146 Self::Single(Default::default())
147 }
148}
149
150impl FontWrite for PositionLookup {
151 fn write_into(&self, writer: &mut TableWriter) {
152 match self {
153 Self::Single(table) => table.write_into(writer),
154 Self::Pair(table) => table.write_into(writer),
155 Self::Cursive(table) => table.write_into(writer),
156 Self::MarkToBase(table) => table.write_into(writer),
157 Self::MarkToLig(table) => table.write_into(writer),
158 Self::MarkToMark(table) => table.write_into(writer),
159 Self::Contextual(table) => table.write_into(writer),
160 Self::ChainContextual(table) => table.write_into(writer),
161 Self::Extension(table) => table.write_into(writer),
162 }
163 }
164 fn table_type(&self) -> TableType {
165 match self {
166 Self::Single(table) => table.table_type(),
167 Self::Pair(table) => table.table_type(),
168 Self::Cursive(table) => table.table_type(),
169 Self::MarkToBase(table) => table.table_type(),
170 Self::MarkToLig(table) => table.table_type(),
171 Self::MarkToMark(table) => table.table_type(),
172 Self::Contextual(table) => table.table_type(),
173 Self::ChainContextual(table) => table.table_type(),
174 Self::Extension(table) => table.table_type(),
175 }
176 }
177}
178
179impl Validate for PositionLookup {
180 fn validate_impl(&self, ctx: &mut ValidationCtx) {
181 match self {
182 Self::Single(table) => table.validate_impl(ctx),
183 Self::Pair(table) => table.validate_impl(ctx),
184 Self::Cursive(table) => table.validate_impl(ctx),
185 Self::MarkToBase(table) => table.validate_impl(ctx),
186 Self::MarkToLig(table) => table.validate_impl(ctx),
187 Self::MarkToMark(table) => table.validate_impl(ctx),
188 Self::Contextual(table) => table.validate_impl(ctx),
189 Self::ChainContextual(table) => table.validate_impl(ctx),
190 Self::Extension(table) => table.validate_impl(ctx),
191 }
192 }
193}
194
195impl FromObjRef<read_fonts::tables::gpos::PositionLookup<'_>> for PositionLookup {
196 fn from_obj_ref(from: &read_fonts::tables::gpos::PositionLookup<'_>, data: FontData) -> Self {
197 match from {
198 read_fonts::tables::gpos::PositionLookup::Single(table) => {
199 Self::Single(table.to_owned_obj(data))
200 }
201 read_fonts::tables::gpos::PositionLookup::Pair(table) => {
202 Self::Pair(table.to_owned_obj(data))
203 }
204 read_fonts::tables::gpos::PositionLookup::Cursive(table) => {
205 Self::Cursive(table.to_owned_obj(data))
206 }
207 read_fonts::tables::gpos::PositionLookup::MarkToBase(table) => {
208 Self::MarkToBase(table.to_owned_obj(data))
209 }
210 read_fonts::tables::gpos::PositionLookup::MarkToLig(table) => {
211 Self::MarkToLig(table.to_owned_obj(data))
212 }
213 read_fonts::tables::gpos::PositionLookup::MarkToMark(table) => {
214 Self::MarkToMark(table.to_owned_obj(data))
215 }
216 read_fonts::tables::gpos::PositionLookup::Contextual(table) => {
217 Self::Contextual(table.to_owned_obj(data))
218 }
219 read_fonts::tables::gpos::PositionLookup::ChainContextual(table) => {
220 Self::ChainContextual(table.to_owned_obj(data))
221 }
222 read_fonts::tables::gpos::PositionLookup::Extension(table) => {
223 Self::Extension(table.to_owned_obj(data))
224 }
225 }
226 }
227}
228
229impl FromTableRef<read_fonts::tables::gpos::PositionLookup<'_>> for PositionLookup {}
230
231impl From<Lookup<SinglePos>> for PositionLookup {
232 fn from(src: Lookup<SinglePos>) -> PositionLookup {
233 PositionLookup::Single(src)
234 }
235}
236
237impl From<Lookup<PairPos>> for PositionLookup {
238 fn from(src: Lookup<PairPos>) -> PositionLookup {
239 PositionLookup::Pair(src)
240 }
241}
242
243impl From<Lookup<CursivePos>> for PositionLookup {
244 fn from(src: Lookup<CursivePos>) -> PositionLookup {
245 PositionLookup::Cursive(src)
246 }
247}
248
249impl From<Lookup<MarkBasePos>> for PositionLookup {
250 fn from(src: Lookup<MarkBasePos>) -> PositionLookup {
251 PositionLookup::MarkToBase(src)
252 }
253}
254
255impl From<Lookup<MarkLigPos>> for PositionLookup {
256 fn from(src: Lookup<MarkLigPos>) -> PositionLookup {
257 PositionLookup::MarkToLig(src)
258 }
259}
260
261impl From<Lookup<MarkMarkPos>> for PositionLookup {
262 fn from(src: Lookup<MarkMarkPos>) -> PositionLookup {
263 PositionLookup::MarkToMark(src)
264 }
265}
266
267impl From<Lookup<PositionSequenceContext>> for PositionLookup {
268 fn from(src: Lookup<PositionSequenceContext>) -> PositionLookup {
269 PositionLookup::Contextual(src)
270 }
271}
272
273impl From<Lookup<PositionChainContext>> for PositionLookup {
274 fn from(src: Lookup<PositionChainContext>) -> PositionLookup {
275 PositionLookup::ChainContextual(src)
276 }
277}
278
279impl From<Lookup<ExtensionSubtable>> for PositionLookup {
280 fn from(src: Lookup<ExtensionSubtable>) -> PositionLookup {
281 PositionLookup::Extension(src)
282 }
283}
284
285impl FontWrite for ValueFormat {
286 fn write_into(&self, writer: &mut TableWriter) {
287 writer.write_slice(&self.bits().to_be_bytes())
288 }
289}
290
291#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
294#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
295pub enum AnchorTable {
296 Format1(AnchorFormat1),
297 Format2(AnchorFormat2),
298 Format3(AnchorFormat3),
299}
300
301impl AnchorTable {
302 pub fn format_1(x_coordinate: i16, y_coordinate: i16) -> Self {
304 Self::Format1(AnchorFormat1::new(x_coordinate, y_coordinate))
305 }
306
307 pub fn format_2(x_coordinate: i16, y_coordinate: i16, anchor_point: u16) -> Self {
309 Self::Format2(AnchorFormat2::new(x_coordinate, y_coordinate, anchor_point))
310 }
311
312 pub fn format_3(
314 x_coordinate: i16,
315 y_coordinate: i16,
316 x_device: Option<DeviceOrVariationIndex>,
317 y_device: Option<DeviceOrVariationIndex>,
318 ) -> Self {
319 Self::Format3(AnchorFormat3::new(
320 x_coordinate,
321 y_coordinate,
322 x_device,
323 y_device,
324 ))
325 }
326}
327
328impl Default for AnchorTable {
329 fn default() -> Self {
330 Self::Format1(Default::default())
331 }
332}
333
334impl FontWrite for AnchorTable {
335 fn write_into(&self, writer: &mut TableWriter) {
336 match self {
337 Self::Format1(item) => item.write_into(writer),
338 Self::Format2(item) => item.write_into(writer),
339 Self::Format3(item) => item.write_into(writer),
340 }
341 }
342 fn table_type(&self) -> TableType {
343 match self {
344 Self::Format1(item) => item.table_type(),
345 Self::Format2(item) => item.table_type(),
346 Self::Format3(item) => item.table_type(),
347 }
348 }
349}
350
351impl Validate for AnchorTable {
352 fn validate_impl(&self, ctx: &mut ValidationCtx) {
353 match self {
354 Self::Format1(item) => item.validate_impl(ctx),
355 Self::Format2(item) => item.validate_impl(ctx),
356 Self::Format3(item) => item.validate_impl(ctx),
357 }
358 }
359}
360
361impl FromObjRef<read_fonts::tables::gpos::AnchorTable<'_>> for AnchorTable {
362 fn from_obj_ref(obj: &read_fonts::tables::gpos::AnchorTable, _: FontData) -> Self {
363 use read_fonts::tables::gpos::AnchorTable as ObjRefType;
364 match obj {
365 ObjRefType::Format1(item) => AnchorTable::Format1(item.to_owned_table()),
366 ObjRefType::Format2(item) => AnchorTable::Format2(item.to_owned_table()),
367 ObjRefType::Format3(item) => AnchorTable::Format3(item.to_owned_table()),
368 }
369 }
370}
371
372impl FromTableRef<read_fonts::tables::gpos::AnchorTable<'_>> for AnchorTable {}
373
374impl ReadArgs for AnchorTable {
375 type Args = ();
376}
377
378impl<'a> FontRead<'a> for AnchorTable {
379 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
380 <read_fonts::tables::gpos::AnchorTable as FontRead>::read(data).map(|x| x.to_owned_table())
381 }
382}
383
384impl From<AnchorFormat1> for AnchorTable {
385 fn from(src: AnchorFormat1) -> AnchorTable {
386 AnchorTable::Format1(src)
387 }
388}
389
390impl From<AnchorFormat2> for AnchorTable {
391 fn from(src: AnchorFormat2) -> AnchorTable {
392 AnchorTable::Format2(src)
393 }
394}
395
396impl From<AnchorFormat3> for AnchorTable {
397 fn from(src: AnchorFormat3) -> AnchorTable {
398 AnchorTable::Format3(src)
399 }
400}
401
402#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
404#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
405pub struct AnchorFormat1 {
406 pub x_coordinate: i16,
408 pub y_coordinate: i16,
410}
411
412impl AnchorFormat1 {
413 pub fn new(x_coordinate: i16, y_coordinate: i16) -> Self {
415 Self {
416 x_coordinate,
417 y_coordinate,
418 }
419 }
420}
421
422impl FontWrite for AnchorFormat1 {
423 #[allow(clippy::unnecessary_cast)]
424 fn write_into(&self, writer: &mut TableWriter) {
425 (1 as u16).write_into(writer);
426 self.x_coordinate.write_into(writer);
427 self.y_coordinate.write_into(writer);
428 }
429 fn table_type(&self) -> TableType {
430 TableType::Named("AnchorFormat1")
431 }
432}
433
434impl Validate for AnchorFormat1 {
435 fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
436}
437
438impl<'a> FromObjRef<read_fonts::tables::gpos::AnchorFormat1<'a>> for AnchorFormat1 {
439 fn from_obj_ref(obj: &read_fonts::tables::gpos::AnchorFormat1<'a>, _: FontData) -> Self {
440 AnchorFormat1 {
441 x_coordinate: obj.x_coordinate(),
442 y_coordinate: obj.y_coordinate(),
443 }
444 }
445}
446
447#[allow(clippy::needless_lifetimes)]
448impl<'a> FromTableRef<read_fonts::tables::gpos::AnchorFormat1<'a>> for AnchorFormat1 {}
449
450impl ReadArgs for AnchorFormat1 {
451 type Args = ();
452}
453
454impl<'a> FontRead<'a> for AnchorFormat1 {
455 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
456 <read_fonts::tables::gpos::AnchorFormat1 as FontRead>::read(data)
457 .map(|x| x.to_owned_table())
458 }
459}
460
461#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
463#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
464pub struct AnchorFormat2 {
465 pub x_coordinate: i16,
467 pub y_coordinate: i16,
469 pub anchor_point: u16,
471}
472
473impl AnchorFormat2 {
474 pub fn new(x_coordinate: i16, y_coordinate: i16, anchor_point: u16) -> Self {
476 Self {
477 x_coordinate,
478 y_coordinate,
479 anchor_point,
480 }
481 }
482}
483
484impl FontWrite for AnchorFormat2 {
485 #[allow(clippy::unnecessary_cast)]
486 fn write_into(&self, writer: &mut TableWriter) {
487 (2 as u16).write_into(writer);
488 self.x_coordinate.write_into(writer);
489 self.y_coordinate.write_into(writer);
490 self.anchor_point.write_into(writer);
491 }
492 fn table_type(&self) -> TableType {
493 TableType::Named("AnchorFormat2")
494 }
495}
496
497impl Validate for AnchorFormat2 {
498 fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
499}
500
501impl<'a> FromObjRef<read_fonts::tables::gpos::AnchorFormat2<'a>> for AnchorFormat2 {
502 fn from_obj_ref(obj: &read_fonts::tables::gpos::AnchorFormat2<'a>, _: FontData) -> Self {
503 AnchorFormat2 {
504 x_coordinate: obj.x_coordinate(),
505 y_coordinate: obj.y_coordinate(),
506 anchor_point: obj.anchor_point(),
507 }
508 }
509}
510
511#[allow(clippy::needless_lifetimes)]
512impl<'a> FromTableRef<read_fonts::tables::gpos::AnchorFormat2<'a>> for AnchorFormat2 {}
513
514impl ReadArgs for AnchorFormat2 {
515 type Args = ();
516}
517
518impl<'a> FontRead<'a> for AnchorFormat2 {
519 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
520 <read_fonts::tables::gpos::AnchorFormat2 as FontRead>::read(data)
521 .map(|x| x.to_owned_table())
522 }
523}
524
525#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
527#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
528pub struct AnchorFormat3 {
529 pub x_coordinate: i16,
531 pub y_coordinate: i16,
533 pub x_device: NullableOffsetMarker<DeviceOrVariationIndex>,
537 pub y_device: NullableOffsetMarker<DeviceOrVariationIndex>,
541}
542
543impl AnchorFormat3 {
544 pub fn new(
546 x_coordinate: i16,
547 y_coordinate: i16,
548 x_device: Option<DeviceOrVariationIndex>,
549 y_device: Option<DeviceOrVariationIndex>,
550 ) -> Self {
551 Self {
552 x_coordinate,
553 y_coordinate,
554 x_device: x_device.into(),
555 y_device: y_device.into(),
556 }
557 }
558}
559
560impl FontWrite for AnchorFormat3 {
561 #[allow(clippy::unnecessary_cast)]
562 fn write_into(&self, writer: &mut TableWriter) {
563 (3 as u16).write_into(writer);
564 self.x_coordinate.write_into(writer);
565 self.y_coordinate.write_into(writer);
566 self.x_device.write_into(writer);
567 self.y_device.write_into(writer);
568 }
569 fn table_type(&self) -> TableType {
570 TableType::Named("AnchorFormat3")
571 }
572}
573
574impl Validate for AnchorFormat3 {
575 fn validate_impl(&self, ctx: &mut ValidationCtx) {
576 ctx.in_table("AnchorFormat3", |ctx| {
577 ctx.in_field("x_device", |ctx| {
578 self.x_device.validate_impl(ctx);
579 });
580 ctx.in_field("y_device", |ctx| {
581 self.y_device.validate_impl(ctx);
582 });
583 })
584 }
585}
586
587impl<'a> FromObjRef<read_fonts::tables::gpos::AnchorFormat3<'a>> for AnchorFormat3 {
588 fn from_obj_ref(obj: &read_fonts::tables::gpos::AnchorFormat3<'a>, _: FontData) -> Self {
589 AnchorFormat3 {
590 x_coordinate: obj.x_coordinate(),
591 y_coordinate: obj.y_coordinate(),
592 x_device: obj.x_device().to_owned_table(),
593 y_device: obj.y_device().to_owned_table(),
594 }
595 }
596}
597
598#[allow(clippy::needless_lifetimes)]
599impl<'a> FromTableRef<read_fonts::tables::gpos::AnchorFormat3<'a>> for AnchorFormat3 {}
600
601impl ReadArgs for AnchorFormat3 {
602 type Args = ();
603}
604
605impl<'a> FontRead<'a> for AnchorFormat3 {
606 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
607 <read_fonts::tables::gpos::AnchorFormat3 as FontRead>::read(data)
608 .map(|x| x.to_owned_table())
609 }
610}
611
612#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
614#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
615pub struct MarkArray {
616 pub mark_records: Vec<MarkRecord>,
619}
620
621impl MarkArray {
622 pub fn new(mark_records: Vec<MarkRecord>) -> Self {
624 Self { mark_records }
625 }
626}
627
628impl FontWrite for MarkArray {
629 #[allow(clippy::unnecessary_cast)]
630 fn write_into(&self, writer: &mut TableWriter) {
631 (u16::try_from(array_len(&self.mark_records)).unwrap()).write_into(writer);
632 self.mark_records.write_into(writer);
633 }
634 fn table_type(&self) -> TableType {
635 TableType::Named("MarkArray")
636 }
637}
638
639impl Validate for MarkArray {
640 fn validate_impl(&self, ctx: &mut ValidationCtx) {
641 ctx.in_table("MarkArray", |ctx| {
642 ctx.in_field("mark_records", |ctx| {
643 if self.mark_records.len() > to_usize(u16::MAX) {
644 ctx.report("array exceeds max length");
645 }
646 self.mark_records.validate_impl(ctx);
647 });
648 })
649 }
650}
651
652impl<'a> FromObjRef<read_fonts::tables::gpos::MarkArray<'a>> for MarkArray {
653 fn from_obj_ref(obj: &read_fonts::tables::gpos::MarkArray<'a>, _: FontData) -> Self {
654 let offset_data = obj.offset_data();
655 MarkArray {
656 mark_records: obj.mark_records().to_owned_obj(offset_data),
657 }
658 }
659}
660
661#[allow(clippy::needless_lifetimes)]
662impl<'a> FromTableRef<read_fonts::tables::gpos::MarkArray<'a>> for MarkArray {}
663
664impl ReadArgs for MarkArray {
665 type Args = ();
666}
667
668impl<'a> FontRead<'a> for MarkArray {
669 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
670 <read_fonts::tables::gpos::MarkArray as FontRead>::read(data).map(|x| x.to_owned_table())
671 }
672}
673
674#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
676#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
677pub struct MarkRecord {
678 pub mark_class: u16,
680 pub mark_anchor: OffsetMarker<AnchorTable>,
682}
683
684impl MarkRecord {
685 pub fn new(mark_class: u16, mark_anchor: AnchorTable) -> Self {
687 Self {
688 mark_class,
689 mark_anchor: mark_anchor.into(),
690 }
691 }
692}
693
694impl FontWrite for MarkRecord {
695 fn write_into(&self, writer: &mut TableWriter) {
696 self.mark_class.write_into(writer);
697 self.mark_anchor.write_into(writer);
698 }
699 fn table_type(&self) -> TableType {
700 TableType::Named("MarkRecord")
701 }
702}
703
704impl Validate for MarkRecord {
705 fn validate_impl(&self, ctx: &mut ValidationCtx) {
706 ctx.in_table("MarkRecord", |ctx| {
707 ctx.in_field("mark_anchor", |ctx| {
708 self.mark_anchor.validate_impl(ctx);
709 });
710 })
711 }
712}
713
714impl FromObjRef<read_fonts::tables::gpos::MarkRecord> for MarkRecord {
715 fn from_obj_ref(obj: &read_fonts::tables::gpos::MarkRecord, offset_data: FontData) -> Self {
716 MarkRecord {
717 mark_class: obj.mark_class(),
718 mark_anchor: obj.mark_anchor(offset_data).to_owned_table(),
719 }
720 }
721}
722
723#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
725#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
726pub enum SinglePos {
727 Format1(SinglePosFormat1),
728 Format2(SinglePosFormat2),
729 Format3(SinglePosFormat3),
730 Format4(SinglePosFormat4),
731}
732
733impl SinglePos {
734 pub fn format_1(coverage: CoverageTable, value_record: ValueRecord) -> Self {
736 Self::Format1(SinglePosFormat1::new(coverage, value_record))
737 }
738
739 pub fn format_2(coverage: CoverageTable, value_records: Vec<ValueRecord>) -> Self {
741 Self::Format2(SinglePosFormat2::new(coverage, value_records))
742 }
743
744 pub fn format_3(coverage: CoverageTable, value_record: ValueRecord) -> Self {
746 Self::Format3(SinglePosFormat3::new(coverage, value_record))
747 }
748
749 pub fn format_4(coverage: CoverageTable, value_records: Vec<ValueRecord>) -> Self {
751 Self::Format4(SinglePosFormat4::new(coverage, value_records))
752 }
753}
754
755impl Default for SinglePos {
756 fn default() -> Self {
757 Self::Format1(Default::default())
758 }
759}
760
761impl FontWrite for SinglePos {
762 fn write_into(&self, writer: &mut TableWriter) {
763 match self {
764 Self::Format1(item) => item.write_into(writer),
765 Self::Format2(item) => item.write_into(writer),
766 Self::Format3(item) => item.write_into(writer),
767 Self::Format4(item) => item.write_into(writer),
768 }
769 }
770 fn table_type(&self) -> TableType {
771 match self {
772 Self::Format1(item) => item.table_type(),
773 Self::Format2(item) => item.table_type(),
774 Self::Format3(item) => item.table_type(),
775 Self::Format4(item) => item.table_type(),
776 }
777 }
778}
779
780impl Validate for SinglePos {
781 fn validate_impl(&self, ctx: &mut ValidationCtx) {
782 match self {
783 Self::Format1(item) => item.validate_impl(ctx),
784 Self::Format2(item) => item.validate_impl(ctx),
785 Self::Format3(item) => item.validate_impl(ctx),
786 Self::Format4(item) => item.validate_impl(ctx),
787 }
788 }
789}
790
791impl FromObjRef<read_fonts::tables::gpos::SinglePos<'_>> for SinglePos {
792 fn from_obj_ref(obj: &read_fonts::tables::gpos::SinglePos, _: FontData) -> Self {
793 use read_fonts::tables::gpos::SinglePos as ObjRefType;
794 match obj {
795 ObjRefType::Format1(item) => SinglePos::Format1(item.to_owned_table()),
796 ObjRefType::Format2(item) => SinglePos::Format2(item.to_owned_table()),
797 ObjRefType::Format3(item) => SinglePos::Format3(item.to_owned_table()),
798 ObjRefType::Format4(item) => SinglePos::Format4(item.to_owned_table()),
799 }
800 }
801}
802
803impl FromTableRef<read_fonts::tables::gpos::SinglePos<'_>> for SinglePos {}
804
805impl ReadArgs for SinglePos {
806 type Args = ();
807}
808
809impl<'a> FontRead<'a> for SinglePos {
810 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
811 <read_fonts::tables::gpos::SinglePos as FontRead>::read(data).map(|x| x.to_owned_table())
812 }
813}
814
815impl From<SinglePosFormat1> for SinglePos {
816 fn from(src: SinglePosFormat1) -> SinglePos {
817 SinglePos::Format1(src)
818 }
819}
820
821impl From<SinglePosFormat2> for SinglePos {
822 fn from(src: SinglePosFormat2) -> SinglePos {
823 SinglePos::Format2(src)
824 }
825}
826
827impl From<SinglePosFormat3> for SinglePos {
828 fn from(src: SinglePosFormat3) -> SinglePos {
829 SinglePos::Format3(src)
830 }
831}
832
833impl From<SinglePosFormat4> for SinglePos {
834 fn from(src: SinglePosFormat4) -> SinglePos {
835 SinglePos::Format4(src)
836 }
837}
838
839#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
841#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
842pub struct SinglePosFormat1 {
843 pub coverage: OffsetMarker<CoverageTable>,
845 pub value_record: ValueRecord,
848}
849
850impl SinglePosFormat1 {
851 pub fn new(coverage: CoverageTable, value_record: ValueRecord) -> Self {
853 Self {
854 coverage: coverage.into(),
855 value_record,
856 }
857 }
858}
859
860impl FontWrite for SinglePosFormat1 {
861 #[allow(clippy::unnecessary_cast)]
862 fn write_into(&self, writer: &mut TableWriter) {
863 (1 as u16).write_into(writer);
864 self.coverage.write_into(writer);
865 (self.compute_value_format() as ValueFormat).write_into(writer);
866 self.value_record.write_into(writer);
867 }
868 fn table_type(&self) -> TableType {
869 TableType::Named("SinglePosFormat1")
870 }
871}
872
873impl Validate for SinglePosFormat1 {
874 fn validate_impl(&self, ctx: &mut ValidationCtx) {
875 ctx.in_table("SinglePosFormat1", |ctx| {
876 ctx.in_field("coverage", |ctx| {
877 self.coverage.validate_impl(ctx);
878 });
879 })
880 }
881}
882
883impl<'a> FromObjRef<read_fonts::tables::gpos::SinglePosFormat1<'a>> for SinglePosFormat1 {
884 fn from_obj_ref(obj: &read_fonts::tables::gpos::SinglePosFormat1<'a>, _: FontData) -> Self {
885 let offset_data = obj.offset_data();
886 SinglePosFormat1 {
887 coverage: obj.coverage().to_owned_table(),
888 value_record: obj.value_record().to_owned_obj(offset_data),
889 }
890 }
891}
892
893#[allow(clippy::needless_lifetimes)]
894impl<'a> FromTableRef<read_fonts::tables::gpos::SinglePosFormat1<'a>> for SinglePosFormat1 {}
895
896impl ReadArgs for SinglePosFormat1 {
897 type Args = ();
898}
899
900impl<'a> FontRead<'a> for SinglePosFormat1 {
901 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
902 <read_fonts::tables::gpos::SinglePosFormat1 as FontRead>::read(data)
903 .map(|x| x.to_owned_table())
904 }
905}
906
907#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
909#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
910pub struct SinglePosFormat2 {
911 pub coverage: OffsetMarker<CoverageTable>,
913 pub value_records: Vec<ValueRecord>,
915}
916
917impl SinglePosFormat2 {
918 pub fn new(coverage: CoverageTable, value_records: Vec<ValueRecord>) -> Self {
920 Self {
921 coverage: coverage.into(),
922 value_records,
923 }
924 }
925}
926
927impl FontWrite for SinglePosFormat2 {
928 #[allow(clippy::unnecessary_cast)]
929 fn write_into(&self, writer: &mut TableWriter) {
930 (2 as u16).write_into(writer);
931 self.coverage.write_into(writer);
932 (self.compute_value_format() as ValueFormat).write_into(writer);
933 (u16::try_from(array_len(&self.value_records)).unwrap()).write_into(writer);
934 self.value_records.write_into(writer);
935 }
936 fn table_type(&self) -> TableType {
937 TableType::Named("SinglePosFormat2")
938 }
939}
940
941impl Validate for SinglePosFormat2 {
942 fn validate_impl(&self, ctx: &mut ValidationCtx) {
943 ctx.in_table("SinglePosFormat2", |ctx| {
944 ctx.in_field("coverage", |ctx| {
945 self.coverage.validate_impl(ctx);
946 });
947 ctx.in_field("value_records", |ctx| {
948 if self.value_records.len() > to_usize(u16::MAX) {
949 ctx.report("array exceeds max length");
950 }
951 self.value_records.validate_impl(ctx);
952 });
953 })
954 }
955}
956
957impl<'a> FromObjRef<read_fonts::tables::gpos::SinglePosFormat2<'a>> for SinglePosFormat2 {
958 fn from_obj_ref(obj: &read_fonts::tables::gpos::SinglePosFormat2<'a>, _: FontData) -> Self {
959 let offset_data = obj.offset_data();
960 SinglePosFormat2 {
961 coverage: obj.coverage().to_owned_table(),
962 value_records: obj
963 .value_records()
964 .iter()
965 .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
966 .collect(),
967 }
968 }
969}
970
971#[allow(clippy::needless_lifetimes)]
972impl<'a> FromTableRef<read_fonts::tables::gpos::SinglePosFormat2<'a>> for SinglePosFormat2 {}
973
974impl ReadArgs for SinglePosFormat2 {
975 type Args = ();
976}
977
978impl<'a> FontRead<'a> for SinglePosFormat2 {
979 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
980 <read_fonts::tables::gpos::SinglePosFormat2 as FontRead>::read(data)
981 .map(|x| x.to_owned_table())
982 }
983}
984
985#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
987#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
988pub enum PairPos {
989 Format1(PairPosFormat1),
990 Format2(PairPosFormat2),
991 Format3(PairPosFormat3),
992 Format4(PairPosFormat4),
993}
994
995impl PairPos {
996 pub fn format_1(coverage: CoverageTable, pair_sets: Vec<PairSet>) -> Self {
998 Self::Format1(PairPosFormat1::new(coverage, pair_sets))
999 }
1000
1001 pub fn format_2(
1003 coverage: CoverageTable,
1004 class_def1: ClassDef,
1005 class_def2: ClassDef,
1006 class1_records: Vec<Class1Record>,
1007 ) -> Self {
1008 Self::Format2(PairPosFormat2::new(
1009 coverage,
1010 class_def1,
1011 class_def2,
1012 class1_records,
1013 ))
1014 }
1015
1016 pub fn format_3(coverage: CoverageTable, pair_sets: Vec<PairSet2>) -> Self {
1018 Self::Format3(PairPosFormat3::new(coverage, pair_sets))
1019 }
1020
1021 pub fn format_4(
1023 coverage: CoverageTable,
1024 class_def1: ClassDef,
1025 class_def2: ClassDef,
1026 class1_records: Vec<Class1Record>,
1027 ) -> Self {
1028 Self::Format4(PairPosFormat4::new(
1029 coverage,
1030 class_def1,
1031 class_def2,
1032 class1_records,
1033 ))
1034 }
1035}
1036
1037impl Default for PairPos {
1038 fn default() -> Self {
1039 Self::Format1(Default::default())
1040 }
1041}
1042
1043impl FontWrite for PairPos {
1044 fn write_into(&self, writer: &mut TableWriter) {
1045 match self {
1046 Self::Format1(item) => item.write_into(writer),
1047 Self::Format2(item) => item.write_into(writer),
1048 Self::Format3(item) => item.write_into(writer),
1049 Self::Format4(item) => item.write_into(writer),
1050 }
1051 }
1052 fn table_type(&self) -> TableType {
1053 match self {
1054 Self::Format1(item) => item.table_type(),
1055 Self::Format2(item) => item.table_type(),
1056 Self::Format3(item) => item.table_type(),
1057 Self::Format4(item) => item.table_type(),
1058 }
1059 }
1060}
1061
1062impl Validate for PairPos {
1063 fn validate_impl(&self, ctx: &mut ValidationCtx) {
1064 match self {
1065 Self::Format1(item) => item.validate_impl(ctx),
1066 Self::Format2(item) => item.validate_impl(ctx),
1067 Self::Format3(item) => item.validate_impl(ctx),
1068 Self::Format4(item) => item.validate_impl(ctx),
1069 }
1070 }
1071}
1072
1073impl FromObjRef<read_fonts::tables::gpos::PairPos<'_>> for PairPos {
1074 fn from_obj_ref(obj: &read_fonts::tables::gpos::PairPos, _: FontData) -> Self {
1075 use read_fonts::tables::gpos::PairPos as ObjRefType;
1076 match obj {
1077 ObjRefType::Format1(item) => PairPos::Format1(item.to_owned_table()),
1078 ObjRefType::Format2(item) => PairPos::Format2(item.to_owned_table()),
1079 ObjRefType::Format3(item) => PairPos::Format3(item.to_owned_table()),
1080 ObjRefType::Format4(item) => PairPos::Format4(item.to_owned_table()),
1081 }
1082 }
1083}
1084
1085impl FromTableRef<read_fonts::tables::gpos::PairPos<'_>> for PairPos {}
1086
1087impl ReadArgs for PairPos {
1088 type Args = ();
1089}
1090
1091impl<'a> FontRead<'a> for PairPos {
1092 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1093 <read_fonts::tables::gpos::PairPos as FontRead>::read(data).map(|x| x.to_owned_table())
1094 }
1095}
1096
1097impl From<PairPosFormat1> for PairPos {
1098 fn from(src: PairPosFormat1) -> PairPos {
1099 PairPos::Format1(src)
1100 }
1101}
1102
1103impl From<PairPosFormat2> for PairPos {
1104 fn from(src: PairPosFormat2) -> PairPos {
1105 PairPos::Format2(src)
1106 }
1107}
1108
1109impl From<PairPosFormat3> for PairPos {
1110 fn from(src: PairPosFormat3) -> PairPos {
1111 PairPos::Format3(src)
1112 }
1113}
1114
1115impl From<PairPosFormat4> for PairPos {
1116 fn from(src: PairPosFormat4) -> PairPos {
1117 PairPos::Format4(src)
1118 }
1119}
1120
1121#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1123#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1124pub struct PairPosFormat1 {
1125 pub coverage: OffsetMarker<CoverageTable>,
1127 pub pair_sets: Vec<OffsetMarker<PairSet>>,
1130}
1131
1132impl PairPosFormat1 {
1133 pub fn new(coverage: CoverageTable, pair_sets: Vec<PairSet>) -> Self {
1135 Self {
1136 coverage: coverage.into(),
1137 pair_sets: pair_sets.into_iter().map(Into::into).collect(),
1138 }
1139 }
1140}
1141
1142impl FontWrite for PairPosFormat1 {
1143 #[allow(clippy::unnecessary_cast)]
1144 fn write_into(&self, writer: &mut TableWriter) {
1145 (1 as u16).write_into(writer);
1146 self.coverage.write_into(writer);
1147 (self.compute_value_format1() as ValueFormat).write_into(writer);
1148 (self.compute_value_format2() as ValueFormat).write_into(writer);
1149 (u16::try_from(array_len(&self.pair_sets)).unwrap()).write_into(writer);
1150 self.pair_sets.write_into(writer);
1151 }
1152 fn table_type(&self) -> TableType {
1153 TableType::Named("PairPosFormat1")
1154 }
1155}
1156
1157impl Validate for PairPosFormat1 {
1158 fn validate_impl(&self, ctx: &mut ValidationCtx) {
1159 ctx.in_table("PairPosFormat1", |ctx| {
1160 ctx.in_field("coverage", |ctx| {
1161 self.coverage.validate_impl(ctx);
1162 });
1163 ctx.in_field("pair_sets", |ctx| {
1164 if self.pair_sets.len() > to_usize(u16::MAX) {
1165 ctx.report("array exceeds max length");
1166 }
1167 self.check_format_consistency(ctx);
1168 });
1169 })
1170 }
1171}
1172
1173impl<'a> FromObjRef<read_fonts::tables::gpos::PairPosFormat1<'a>> for PairPosFormat1 {
1174 fn from_obj_ref(obj: &read_fonts::tables::gpos::PairPosFormat1<'a>, _: FontData) -> Self {
1175 PairPosFormat1 {
1176 coverage: obj.coverage().to_owned_table(),
1177 pair_sets: obj.pair_sets().to_owned_table(),
1178 }
1179 }
1180}
1181
1182#[allow(clippy::needless_lifetimes)]
1183impl<'a> FromTableRef<read_fonts::tables::gpos::PairPosFormat1<'a>> for PairPosFormat1 {}
1184
1185impl ReadArgs for PairPosFormat1 {
1186 type Args = ();
1187}
1188
1189impl<'a> FontRead<'a> for PairPosFormat1 {
1190 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1191 <read_fonts::tables::gpos::PairPosFormat1 as FontRead>::read(data)
1192 .map(|x| x.to_owned_table())
1193 }
1194}
1195
1196#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1198#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1199pub struct PairSet {
1200 pub pair_value_records: Vec<PairValueRecord>,
1203}
1204
1205impl PairSet {
1206 pub fn new(pair_value_records: Vec<PairValueRecord>) -> Self {
1208 Self { pair_value_records }
1209 }
1210}
1211
1212impl FontWrite for PairSet {
1213 #[allow(clippy::unnecessary_cast)]
1214 fn write_into(&self, writer: &mut TableWriter) {
1215 (u16::try_from(array_len(&self.pair_value_records)).unwrap()).write_into(writer);
1216 self.pair_value_records.write_into(writer);
1217 }
1218 fn table_type(&self) -> TableType {
1219 TableType::Named("PairSet")
1220 }
1221}
1222
1223impl Validate for PairSet {
1224 fn validate_impl(&self, ctx: &mut ValidationCtx) {
1225 ctx.in_table("PairSet", |ctx| {
1226 ctx.in_field("pair_value_records", |ctx| {
1227 if self.pair_value_records.len() > to_usize(u16::MAX) {
1228 ctx.report("array exceeds max length");
1229 }
1230 self.pair_value_records.validate_impl(ctx);
1231 });
1232 })
1233 }
1234}
1235
1236impl<'a> FromObjRef<read_fonts::tables::gpos::PairSet<'a>> for PairSet {
1237 fn from_obj_ref(obj: &read_fonts::tables::gpos::PairSet<'a>, _: FontData) -> Self {
1238 let offset_data = obj.offset_data();
1239 PairSet {
1240 pair_value_records: obj
1241 .pair_value_records()
1242 .iter()
1243 .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
1244 .collect(),
1245 }
1246 }
1247}
1248
1249#[allow(clippy::needless_lifetimes)]
1250impl<'a> FromTableRef<read_fonts::tables::gpos::PairSet<'a>> for PairSet {}
1251
1252#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1254#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1255pub struct PairValueRecord {
1256 pub second_glyph: GlyphId16,
1259 pub value_record1: ValueRecord,
1261 pub value_record2: ValueRecord,
1263}
1264
1265impl PairValueRecord {
1266 pub fn new(
1268 second_glyph: GlyphId16,
1269 value_record1: ValueRecord,
1270 value_record2: ValueRecord,
1271 ) -> Self {
1272 Self {
1273 second_glyph,
1274 value_record1,
1275 value_record2,
1276 }
1277 }
1278}
1279
1280impl FontWrite for PairValueRecord {
1281 fn write_into(&self, writer: &mut TableWriter) {
1282 self.second_glyph.write_into(writer);
1283 self.value_record1.write_into(writer);
1284 self.value_record2.write_into(writer);
1285 }
1286 fn table_type(&self) -> TableType {
1287 TableType::Named("PairValueRecord")
1288 }
1289}
1290
1291impl Validate for PairValueRecord {
1292 fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1293}
1294
1295impl FromObjRef<read_fonts::tables::gpos::PairValueRecord<'_>> for PairValueRecord {
1296 fn from_obj_ref(
1297 obj: &read_fonts::tables::gpos::PairValueRecord,
1298 offset_data: FontData,
1299 ) -> Self {
1300 PairValueRecord {
1301 second_glyph: obj.second_glyph(),
1302 value_record1: obj.value_record1().to_owned_obj(offset_data),
1303 value_record2: obj.value_record2().to_owned_obj(offset_data),
1304 }
1305 }
1306}
1307
1308#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1310#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1311pub struct PairPosFormat2 {
1312 pub coverage: OffsetMarker<CoverageTable>,
1314 pub class_def1: OffsetMarker<ClassDef>,
1317 pub class_def2: OffsetMarker<ClassDef>,
1320 pub class1_records: Vec<Class1Record>,
1322}
1323
1324impl PairPosFormat2 {
1325 pub fn new(
1327 coverage: CoverageTable,
1328 class_def1: ClassDef,
1329 class_def2: ClassDef,
1330 class1_records: Vec<Class1Record>,
1331 ) -> Self {
1332 Self {
1333 coverage: coverage.into(),
1334 class_def1: class_def1.into(),
1335 class_def2: class_def2.into(),
1336 class1_records,
1337 }
1338 }
1339}
1340
1341impl FontWrite for PairPosFormat2 {
1342 #[allow(clippy::unnecessary_cast)]
1343 fn write_into(&self, writer: &mut TableWriter) {
1344 (2 as u16).write_into(writer);
1345 self.coverage.write_into(writer);
1346 (self.compute_value_format1() as ValueFormat).write_into(writer);
1347 (self.compute_value_format2() as ValueFormat).write_into(writer);
1348 self.class_def1.write_into(writer);
1349 self.class_def2.write_into(writer);
1350 (self.compute_class1_count() as u16).write_into(writer);
1351 (self.compute_class2_count() as u16).write_into(writer);
1352 self.class1_records.write_into(writer);
1353 }
1354 fn table_type(&self) -> TableType {
1355 TableType::Named("PairPosFormat2")
1356 }
1357}
1358
1359impl Validate for PairPosFormat2 {
1360 fn validate_impl(&self, ctx: &mut ValidationCtx) {
1361 ctx.in_table("PairPosFormat2", |ctx| {
1362 ctx.in_field("coverage", |ctx| {
1363 self.coverage.validate_impl(ctx);
1364 });
1365 ctx.in_field("class_def1", |ctx| {
1366 self.class_def1.validate_impl(ctx);
1367 });
1368 ctx.in_field("class_def2", |ctx| {
1369 self.class_def2.validate_impl(ctx);
1370 });
1371 ctx.in_field("class1_records", |ctx| {
1372 if self.class1_records.len() > to_usize(u16::MAX) {
1373 ctx.report("array exceeds max length");
1374 }
1375 self.class1_records.validate_impl(ctx);
1376 });
1377 self.check_length_and_format_conformance(ctx);
1378 })
1379 }
1380}
1381
1382impl<'a> FromObjRef<read_fonts::tables::gpos::PairPosFormat2<'a>> for PairPosFormat2 {
1383 fn from_obj_ref(obj: &read_fonts::tables::gpos::PairPosFormat2<'a>, _: FontData) -> Self {
1384 let offset_data = obj.offset_data();
1385 PairPosFormat2 {
1386 coverage: obj.coverage().to_owned_table(),
1387 class_def1: obj.class_def1().to_owned_table(),
1388 class_def2: obj.class_def2().to_owned_table(),
1389 class1_records: obj
1390 .class1_records()
1391 .iter()
1392 .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
1393 .collect(),
1394 }
1395 }
1396}
1397
1398#[allow(clippy::needless_lifetimes)]
1399impl<'a> FromTableRef<read_fonts::tables::gpos::PairPosFormat2<'a>> for PairPosFormat2 {}
1400
1401impl ReadArgs for PairPosFormat2 {
1402 type Args = ();
1403}
1404
1405impl<'a> FontRead<'a> for PairPosFormat2 {
1406 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1407 <read_fonts::tables::gpos::PairPosFormat2 as FontRead>::read(data)
1408 .map(|x| x.to_owned_table())
1409 }
1410}
1411
1412#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1414#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1415pub struct Class1Record {
1416 pub class2_records: Vec<Class2Record>,
1418}
1419
1420impl Class1Record {
1421 pub fn new(class2_records: Vec<Class2Record>) -> Self {
1423 Self { class2_records }
1424 }
1425}
1426
1427impl FontWrite for Class1Record {
1428 fn write_into(&self, writer: &mut TableWriter) {
1429 self.class2_records.write_into(writer);
1430 }
1431 fn table_type(&self) -> TableType {
1432 TableType::Named("Class1Record")
1433 }
1434}
1435
1436impl Validate for Class1Record {
1437 fn validate_impl(&self, ctx: &mut ValidationCtx) {
1438 ctx.in_table("Class1Record", |ctx| {
1439 ctx.in_field("class2_records", |ctx| {
1440 if self.class2_records.len() > to_usize(u16::MAX) {
1441 ctx.report("array exceeds max length");
1442 }
1443 self.class2_records.validate_impl(ctx);
1444 });
1445 })
1446 }
1447}
1448
1449impl FromObjRef<read_fonts::tables::gpos::Class1Record<'_>> for Class1Record {
1450 fn from_obj_ref(obj: &read_fonts::tables::gpos::Class1Record, offset_data: FontData) -> Self {
1451 Class1Record {
1452 class2_records: obj
1453 .class2_records()
1454 .iter()
1455 .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
1456 .collect(),
1457 }
1458 }
1459}
1460
1461#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1463#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1464pub struct Class2Record {
1465 pub value_record1: ValueRecord,
1467 pub value_record2: ValueRecord,
1469}
1470
1471impl Class2Record {
1472 pub fn new(value_record1: ValueRecord, value_record2: ValueRecord) -> Self {
1474 Self {
1475 value_record1,
1476 value_record2,
1477 }
1478 }
1479}
1480
1481impl FontWrite for Class2Record {
1482 fn write_into(&self, writer: &mut TableWriter) {
1483 self.value_record1.write_into(writer);
1484 self.value_record2.write_into(writer);
1485 }
1486 fn table_type(&self) -> TableType {
1487 TableType::Named("Class2Record")
1488 }
1489}
1490
1491impl Validate for Class2Record {
1492 fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1493}
1494
1495impl FromObjRef<read_fonts::tables::gpos::Class2Record<'_>> for Class2Record {
1496 fn from_obj_ref(obj: &read_fonts::tables::gpos::Class2Record, offset_data: FontData) -> Self {
1497 Class2Record {
1498 value_record1: obj.value_record1().to_owned_obj(offset_data),
1499 value_record2: obj.value_record2().to_owned_obj(offset_data),
1500 }
1501 }
1502}
1503
1504#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1506#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1507pub struct CursivePosFormat1 {
1508 pub coverage: OffsetMarker<CoverageTable>,
1510 pub entry_exit_record: Vec<EntryExitRecord>,
1512}
1513
1514impl CursivePosFormat1 {
1515 pub fn new(coverage: CoverageTable, entry_exit_record: Vec<EntryExitRecord>) -> Self {
1517 Self {
1518 coverage: coverage.into(),
1519 entry_exit_record,
1520 }
1521 }
1522}
1523
1524impl FontWrite for CursivePosFormat1 {
1525 #[allow(clippy::unnecessary_cast)]
1526 fn write_into(&self, writer: &mut TableWriter) {
1527 (1 as u16).write_into(writer);
1528 self.coverage.write_into(writer);
1529 (u16::try_from(array_len(&self.entry_exit_record)).unwrap()).write_into(writer);
1530 self.entry_exit_record.write_into(writer);
1531 }
1532 fn table_type(&self) -> TableType {
1533 TableType::Named("CursivePosFormat1")
1534 }
1535}
1536
1537impl Validate for CursivePosFormat1 {
1538 fn validate_impl(&self, ctx: &mut ValidationCtx) {
1539 ctx.in_table("CursivePosFormat1", |ctx| {
1540 ctx.in_field("coverage", |ctx| {
1541 self.coverage.validate_impl(ctx);
1542 });
1543 ctx.in_field("entry_exit_record", |ctx| {
1544 if self.entry_exit_record.len() > to_usize(u16::MAX) {
1545 ctx.report("array exceeds max length");
1546 }
1547 self.entry_exit_record.validate_impl(ctx);
1548 });
1549 })
1550 }
1551}
1552
1553impl<'a> FromObjRef<read_fonts::tables::gpos::CursivePosFormat1<'a>> for CursivePosFormat1 {
1554 fn from_obj_ref(obj: &read_fonts::tables::gpos::CursivePosFormat1<'a>, _: FontData) -> Self {
1555 let offset_data = obj.offset_data();
1556 CursivePosFormat1 {
1557 coverage: obj.coverage().to_owned_table(),
1558 entry_exit_record: obj.entry_exit_record().to_owned_obj(offset_data),
1559 }
1560 }
1561}
1562
1563#[allow(clippy::needless_lifetimes)]
1564impl<'a> FromTableRef<read_fonts::tables::gpos::CursivePosFormat1<'a>> for CursivePosFormat1 {}
1565
1566impl ReadArgs for CursivePosFormat1 {
1567 type Args = ();
1568}
1569
1570impl<'a> FontRead<'a> for CursivePosFormat1 {
1571 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1572 <read_fonts::tables::gpos::CursivePosFormat1 as FontRead>::read(data)
1573 .map(|x| x.to_owned_table())
1574 }
1575}
1576
1577#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1579#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1580pub struct EntryExitRecord {
1581 pub entry_anchor: NullableOffsetMarker<AnchorTable>,
1584 pub exit_anchor: NullableOffsetMarker<AnchorTable>,
1587}
1588
1589impl EntryExitRecord {
1590 pub fn new(entry_anchor: Option<AnchorTable>, exit_anchor: Option<AnchorTable>) -> Self {
1592 Self {
1593 entry_anchor: entry_anchor.into(),
1594 exit_anchor: exit_anchor.into(),
1595 }
1596 }
1597}
1598
1599impl FontWrite for EntryExitRecord {
1600 fn write_into(&self, writer: &mut TableWriter) {
1601 self.entry_anchor.write_into(writer);
1602 self.exit_anchor.write_into(writer);
1603 }
1604 fn table_type(&self) -> TableType {
1605 TableType::Named("EntryExitRecord")
1606 }
1607}
1608
1609impl Validate for EntryExitRecord {
1610 fn validate_impl(&self, ctx: &mut ValidationCtx) {
1611 ctx.in_table("EntryExitRecord", |ctx| {
1612 ctx.in_field("entry_anchor", |ctx| {
1613 self.entry_anchor.validate_impl(ctx);
1614 });
1615 ctx.in_field("exit_anchor", |ctx| {
1616 self.exit_anchor.validate_impl(ctx);
1617 });
1618 })
1619 }
1620}
1621
1622impl FromObjRef<read_fonts::tables::gpos::EntryExitRecord> for EntryExitRecord {
1623 fn from_obj_ref(
1624 obj: &read_fonts::tables::gpos::EntryExitRecord,
1625 offset_data: FontData,
1626 ) -> Self {
1627 EntryExitRecord {
1628 entry_anchor: obj.entry_anchor(offset_data).to_owned_table(),
1629 exit_anchor: obj.exit_anchor(offset_data).to_owned_table(),
1630 }
1631 }
1632}
1633
1634#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1636#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1637pub struct MarkBasePosFormat1 {
1638 pub mark_coverage: OffsetMarker<CoverageTable>,
1641 pub base_coverage: OffsetMarker<CoverageTable>,
1644 pub mark_array: OffsetMarker<MarkArray>,
1647 pub base_array: OffsetMarker<BaseArray>,
1650}
1651
1652impl MarkBasePosFormat1 {
1653 pub fn new(
1655 mark_coverage: CoverageTable,
1656 base_coverage: CoverageTable,
1657 mark_array: MarkArray,
1658 base_array: BaseArray,
1659 ) -> Self {
1660 Self {
1661 mark_coverage: mark_coverage.into(),
1662 base_coverage: base_coverage.into(),
1663 mark_array: mark_array.into(),
1664 base_array: base_array.into(),
1665 }
1666 }
1667}
1668
1669impl FontWrite for MarkBasePosFormat1 {
1670 #[allow(clippy::unnecessary_cast)]
1671 fn write_into(&self, writer: &mut TableWriter) {
1672 (1 as u16).write_into(writer);
1673 self.mark_coverage.write_into(writer);
1674 self.base_coverage.write_into(writer);
1675 (self.compute_mark_class_count() as u16).write_into(writer);
1676 self.mark_array.write_into(writer);
1677 self.base_array.write_into(writer);
1678 }
1679 fn table_type(&self) -> TableType {
1680 TableType::Named("MarkBasePosFormat1")
1681 }
1682}
1683
1684impl Validate for MarkBasePosFormat1 {
1685 fn validate_impl(&self, ctx: &mut ValidationCtx) {
1686 ctx.in_table("MarkBasePosFormat1", |ctx| {
1687 ctx.in_field("mark_coverage", |ctx| {
1688 self.mark_coverage.validate_impl(ctx);
1689 });
1690 ctx.in_field("base_coverage", |ctx| {
1691 self.base_coverage.validate_impl(ctx);
1692 });
1693 ctx.in_field("mark_array", |ctx| {
1694 self.mark_array.validate_impl(ctx);
1695 });
1696 ctx.in_field("base_array", |ctx| {
1697 self.base_array.validate_impl(ctx);
1698 });
1699 })
1700 }
1701}
1702
1703impl<'a> FromObjRef<read_fonts::tables::gpos::MarkBasePosFormat1<'a>> for MarkBasePosFormat1 {
1704 fn from_obj_ref(obj: &read_fonts::tables::gpos::MarkBasePosFormat1<'a>, _: FontData) -> Self {
1705 MarkBasePosFormat1 {
1706 mark_coverage: obj.mark_coverage().to_owned_table(),
1707 base_coverage: obj.base_coverage().to_owned_table(),
1708 mark_array: obj.mark_array().to_owned_table(),
1709 base_array: obj.base_array().to_owned_table(),
1710 }
1711 }
1712}
1713
1714#[allow(clippy::needless_lifetimes)]
1715impl<'a> FromTableRef<read_fonts::tables::gpos::MarkBasePosFormat1<'a>> for MarkBasePosFormat1 {}
1716
1717impl ReadArgs for MarkBasePosFormat1 {
1718 type Args = ();
1719}
1720
1721impl<'a> FontRead<'a> for MarkBasePosFormat1 {
1722 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1723 <read_fonts::tables::gpos::MarkBasePosFormat1 as FontRead>::read(data)
1724 .map(|x| x.to_owned_table())
1725 }
1726}
1727
1728#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1730#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1731pub struct BaseArray {
1732 pub base_records: Vec<BaseRecord>,
1734}
1735
1736impl BaseArray {
1737 pub fn new(base_records: Vec<BaseRecord>) -> Self {
1739 Self { base_records }
1740 }
1741}
1742
1743impl FontWrite for BaseArray {
1744 #[allow(clippy::unnecessary_cast)]
1745 fn write_into(&self, writer: &mut TableWriter) {
1746 (u16::try_from(array_len(&self.base_records)).unwrap()).write_into(writer);
1747 self.base_records.write_into(writer);
1748 }
1749 fn table_type(&self) -> TableType {
1750 TableType::Named("BaseArray")
1751 }
1752}
1753
1754impl Validate for BaseArray {
1755 fn validate_impl(&self, ctx: &mut ValidationCtx) {
1756 ctx.in_table("BaseArray", |ctx| {
1757 ctx.in_field("base_records", |ctx| {
1758 if self.base_records.len() > to_usize(u16::MAX) {
1759 ctx.report("array exceeds max length");
1760 }
1761 self.base_records.validate_impl(ctx);
1762 });
1763 })
1764 }
1765}
1766
1767impl<'a> FromObjRef<read_fonts::tables::gpos::BaseArray<'a>> for BaseArray {
1768 fn from_obj_ref(obj: &read_fonts::tables::gpos::BaseArray<'a>, _: FontData) -> Self {
1769 let offset_data = obj.offset_data();
1770 BaseArray {
1771 base_records: obj
1772 .base_records()
1773 .iter()
1774 .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
1775 .collect(),
1776 }
1777 }
1778}
1779
1780#[allow(clippy::needless_lifetimes)]
1781impl<'a> FromTableRef<read_fonts::tables::gpos::BaseArray<'a>> for BaseArray {}
1782
1783#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1785#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1786pub struct BaseRecord {
1787 pub base_anchors: Vec<NullableOffsetMarker<AnchorTable>>,
1791}
1792
1793impl BaseRecord {
1794 pub fn new(base_anchors: Vec<Option<AnchorTable>>) -> Self {
1796 Self {
1797 base_anchors: base_anchors.into_iter().map(Into::into).collect(),
1798 }
1799 }
1800}
1801
1802impl FontWrite for BaseRecord {
1803 fn write_into(&self, writer: &mut TableWriter) {
1804 self.base_anchors.write_into(writer);
1805 }
1806 fn table_type(&self) -> TableType {
1807 TableType::Named("BaseRecord")
1808 }
1809}
1810
1811impl Validate for BaseRecord {
1812 fn validate_impl(&self, ctx: &mut ValidationCtx) {
1813 ctx.in_table("BaseRecord", |ctx| {
1814 ctx.in_field("base_anchors", |ctx| {
1815 if self.base_anchors.len() > to_usize(u16::MAX) {
1816 ctx.report("array exceeds max length");
1817 }
1818 self.base_anchors.validate_impl(ctx);
1819 });
1820 })
1821 }
1822}
1823
1824impl FromObjRef<read_fonts::tables::gpos::BaseRecord<'_>> for BaseRecord {
1825 fn from_obj_ref(obj: &read_fonts::tables::gpos::BaseRecord, offset_data: FontData) -> Self {
1826 BaseRecord {
1827 base_anchors: obj.base_anchors(offset_data).to_owned_table(),
1828 }
1829 }
1830}
1831
1832#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1834#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1835pub struct MarkLigPosFormat1 {
1836 pub mark_coverage: OffsetMarker<CoverageTable>,
1839 pub ligature_coverage: OffsetMarker<CoverageTable>,
1842 pub mark_array: OffsetMarker<MarkArray>,
1845 pub ligature_array: OffsetMarker<LigatureArray>,
1848}
1849
1850impl MarkLigPosFormat1 {
1851 pub fn new(
1853 mark_coverage: CoverageTable,
1854 ligature_coverage: CoverageTable,
1855 mark_array: MarkArray,
1856 ligature_array: LigatureArray,
1857 ) -> Self {
1858 Self {
1859 mark_coverage: mark_coverage.into(),
1860 ligature_coverage: ligature_coverage.into(),
1861 mark_array: mark_array.into(),
1862 ligature_array: ligature_array.into(),
1863 }
1864 }
1865}
1866
1867impl FontWrite for MarkLigPosFormat1 {
1868 #[allow(clippy::unnecessary_cast)]
1869 fn write_into(&self, writer: &mut TableWriter) {
1870 (1 as u16).write_into(writer);
1871 self.mark_coverage.write_into(writer);
1872 self.ligature_coverage.write_into(writer);
1873 (self.compute_mark_class_count() as u16).write_into(writer);
1874 self.mark_array.write_into(writer);
1875 self.ligature_array.write_into(writer);
1876 }
1877 fn table_type(&self) -> TableType {
1878 TableType::Named("MarkLigPosFormat1")
1879 }
1880}
1881
1882impl Validate for MarkLigPosFormat1 {
1883 fn validate_impl(&self, ctx: &mut ValidationCtx) {
1884 ctx.in_table("MarkLigPosFormat1", |ctx| {
1885 ctx.in_field("mark_coverage", |ctx| {
1886 self.mark_coverage.validate_impl(ctx);
1887 });
1888 ctx.in_field("ligature_coverage", |ctx| {
1889 self.ligature_coverage.validate_impl(ctx);
1890 });
1891 ctx.in_field("mark_array", |ctx| {
1892 self.mark_array.validate_impl(ctx);
1893 });
1894 ctx.in_field("ligature_array", |ctx| {
1895 self.ligature_array.validate_impl(ctx);
1896 });
1897 })
1898 }
1899}
1900
1901impl<'a> FromObjRef<read_fonts::tables::gpos::MarkLigPosFormat1<'a>> for MarkLigPosFormat1 {
1902 fn from_obj_ref(obj: &read_fonts::tables::gpos::MarkLigPosFormat1<'a>, _: FontData) -> Self {
1903 MarkLigPosFormat1 {
1904 mark_coverage: obj.mark_coverage().to_owned_table(),
1905 ligature_coverage: obj.ligature_coverage().to_owned_table(),
1906 mark_array: obj.mark_array().to_owned_table(),
1907 ligature_array: obj.ligature_array().to_owned_table(),
1908 }
1909 }
1910}
1911
1912#[allow(clippy::needless_lifetimes)]
1913impl<'a> FromTableRef<read_fonts::tables::gpos::MarkLigPosFormat1<'a>> for MarkLigPosFormat1 {}
1914
1915impl ReadArgs for MarkLigPosFormat1 {
1916 type Args = ();
1917}
1918
1919impl<'a> FontRead<'a> for MarkLigPosFormat1 {
1920 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1921 <read_fonts::tables::gpos::MarkLigPosFormat1 as FontRead>::read(data)
1922 .map(|x| x.to_owned_table())
1923 }
1924}
1925
1926#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1928#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1929pub struct LigatureArray {
1930 pub ligature_attaches: Vec<OffsetMarker<LigatureAttach>>,
1934}
1935
1936impl LigatureArray {
1937 pub fn new(ligature_attaches: Vec<LigatureAttach>) -> Self {
1939 Self {
1940 ligature_attaches: ligature_attaches.into_iter().map(Into::into).collect(),
1941 }
1942 }
1943}
1944
1945impl FontWrite for LigatureArray {
1946 #[allow(clippy::unnecessary_cast)]
1947 fn write_into(&self, writer: &mut TableWriter) {
1948 (u16::try_from(array_len(&self.ligature_attaches)).unwrap()).write_into(writer);
1949 self.ligature_attaches.write_into(writer);
1950 }
1951 fn table_type(&self) -> TableType {
1952 TableType::Named("LigatureArray")
1953 }
1954}
1955
1956impl Validate for LigatureArray {
1957 fn validate_impl(&self, ctx: &mut ValidationCtx) {
1958 ctx.in_table("LigatureArray", |ctx| {
1959 ctx.in_field("ligature_attaches", |ctx| {
1960 if self.ligature_attaches.len() > to_usize(u16::MAX) {
1961 ctx.report("array exceeds max length");
1962 }
1963 self.ligature_attaches.validate_impl(ctx);
1964 });
1965 })
1966 }
1967}
1968
1969impl<'a> FromObjRef<read_fonts::tables::gpos::LigatureArray<'a>> for LigatureArray {
1970 fn from_obj_ref(obj: &read_fonts::tables::gpos::LigatureArray<'a>, _: FontData) -> Self {
1971 LigatureArray {
1972 ligature_attaches: obj.ligature_attaches().to_owned_table(),
1973 }
1974 }
1975}
1976
1977#[allow(clippy::needless_lifetimes)]
1978impl<'a> FromTableRef<read_fonts::tables::gpos::LigatureArray<'a>> for LigatureArray {}
1979
1980#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1982#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1983pub struct LigatureAttach {
1984 pub component_records: Vec<ComponentRecord>,
1986}
1987
1988impl LigatureAttach {
1989 pub fn new(component_records: Vec<ComponentRecord>) -> Self {
1991 Self { component_records }
1992 }
1993}
1994
1995impl FontWrite for LigatureAttach {
1996 #[allow(clippy::unnecessary_cast)]
1997 fn write_into(&self, writer: &mut TableWriter) {
1998 (u16::try_from(array_len(&self.component_records)).unwrap()).write_into(writer);
1999 self.component_records.write_into(writer);
2000 }
2001 fn table_type(&self) -> TableType {
2002 TableType::Named("LigatureAttach")
2003 }
2004}
2005
2006impl Validate for LigatureAttach {
2007 fn validate_impl(&self, ctx: &mut ValidationCtx) {
2008 ctx.in_table("LigatureAttach", |ctx| {
2009 ctx.in_field("component_records", |ctx| {
2010 if self.component_records.len() > to_usize(u16::MAX) {
2011 ctx.report("array exceeds max length");
2012 }
2013 self.component_records.validate_impl(ctx);
2014 });
2015 })
2016 }
2017}
2018
2019impl<'a> FromObjRef<read_fonts::tables::gpos::LigatureAttach<'a>> for LigatureAttach {
2020 fn from_obj_ref(obj: &read_fonts::tables::gpos::LigatureAttach<'a>, _: FontData) -> Self {
2021 let offset_data = obj.offset_data();
2022 LigatureAttach {
2023 component_records: obj
2024 .component_records()
2025 .iter()
2026 .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
2027 .collect(),
2028 }
2029 }
2030}
2031
2032#[allow(clippy::needless_lifetimes)]
2033impl<'a> FromTableRef<read_fonts::tables::gpos::LigatureAttach<'a>> for LigatureAttach {}
2034
2035#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2037#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2038pub struct ComponentRecord {
2039 pub ligature_anchors: Vec<NullableOffsetMarker<AnchorTable>>,
2043}
2044
2045impl ComponentRecord {
2046 pub fn new(ligature_anchors: Vec<Option<AnchorTable>>) -> Self {
2048 Self {
2049 ligature_anchors: ligature_anchors.into_iter().map(Into::into).collect(),
2050 }
2051 }
2052}
2053
2054impl FontWrite for ComponentRecord {
2055 fn write_into(&self, writer: &mut TableWriter) {
2056 self.ligature_anchors.write_into(writer);
2057 }
2058 fn table_type(&self) -> TableType {
2059 TableType::Named("ComponentRecord")
2060 }
2061}
2062
2063impl Validate for ComponentRecord {
2064 fn validate_impl(&self, ctx: &mut ValidationCtx) {
2065 ctx.in_table("ComponentRecord", |ctx| {
2066 ctx.in_field("ligature_anchors", |ctx| {
2067 if self.ligature_anchors.len() > to_usize(u16::MAX) {
2068 ctx.report("array exceeds max length");
2069 }
2070 self.ligature_anchors.validate_impl(ctx);
2071 });
2072 })
2073 }
2074}
2075
2076impl FromObjRef<read_fonts::tables::gpos::ComponentRecord<'_>> for ComponentRecord {
2077 fn from_obj_ref(
2078 obj: &read_fonts::tables::gpos::ComponentRecord,
2079 offset_data: FontData,
2080 ) -> Self {
2081 ComponentRecord {
2082 ligature_anchors: obj.ligature_anchors(offset_data).to_owned_table(),
2083 }
2084 }
2085}
2086
2087#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2089#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2090pub struct MarkMarkPosFormat1 {
2091 pub mark1_coverage: OffsetMarker<CoverageTable>,
2094 pub mark2_coverage: OffsetMarker<CoverageTable>,
2097 pub mark1_array: OffsetMarker<MarkArray>,
2100 pub mark2_array: OffsetMarker<Mark2Array>,
2103}
2104
2105impl MarkMarkPosFormat1 {
2106 pub fn new(
2108 mark1_coverage: CoverageTable,
2109 mark2_coverage: CoverageTable,
2110 mark1_array: MarkArray,
2111 mark2_array: Mark2Array,
2112 ) -> Self {
2113 Self {
2114 mark1_coverage: mark1_coverage.into(),
2115 mark2_coverage: mark2_coverage.into(),
2116 mark1_array: mark1_array.into(),
2117 mark2_array: mark2_array.into(),
2118 }
2119 }
2120}
2121
2122impl FontWrite for MarkMarkPosFormat1 {
2123 #[allow(clippy::unnecessary_cast)]
2124 fn write_into(&self, writer: &mut TableWriter) {
2125 (1 as u16).write_into(writer);
2126 self.mark1_coverage.write_into(writer);
2127 self.mark2_coverage.write_into(writer);
2128 (self.compute_mark_class_count() as u16).write_into(writer);
2129 self.mark1_array.write_into(writer);
2130 self.mark2_array.write_into(writer);
2131 }
2132 fn table_type(&self) -> TableType {
2133 TableType::Named("MarkMarkPosFormat1")
2134 }
2135}
2136
2137impl Validate for MarkMarkPosFormat1 {
2138 fn validate_impl(&self, ctx: &mut ValidationCtx) {
2139 ctx.in_table("MarkMarkPosFormat1", |ctx| {
2140 ctx.in_field("mark1_coverage", |ctx| {
2141 self.mark1_coverage.validate_impl(ctx);
2142 });
2143 ctx.in_field("mark2_coverage", |ctx| {
2144 self.mark2_coverage.validate_impl(ctx);
2145 });
2146 ctx.in_field("mark1_array", |ctx| {
2147 self.mark1_array.validate_impl(ctx);
2148 });
2149 ctx.in_field("mark2_array", |ctx| {
2150 self.mark2_array.validate_impl(ctx);
2151 });
2152 })
2153 }
2154}
2155
2156impl<'a> FromObjRef<read_fonts::tables::gpos::MarkMarkPosFormat1<'a>> for MarkMarkPosFormat1 {
2157 fn from_obj_ref(obj: &read_fonts::tables::gpos::MarkMarkPosFormat1<'a>, _: FontData) -> Self {
2158 MarkMarkPosFormat1 {
2159 mark1_coverage: obj.mark1_coverage().to_owned_table(),
2160 mark2_coverage: obj.mark2_coverage().to_owned_table(),
2161 mark1_array: obj.mark1_array().to_owned_table(),
2162 mark2_array: obj.mark2_array().to_owned_table(),
2163 }
2164 }
2165}
2166
2167#[allow(clippy::needless_lifetimes)]
2168impl<'a> FromTableRef<read_fonts::tables::gpos::MarkMarkPosFormat1<'a>> for MarkMarkPosFormat1 {}
2169
2170impl ReadArgs for MarkMarkPosFormat1 {
2171 type Args = ();
2172}
2173
2174impl<'a> FontRead<'a> for MarkMarkPosFormat1 {
2175 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2176 <read_fonts::tables::gpos::MarkMarkPosFormat1 as FontRead>::read(data)
2177 .map(|x| x.to_owned_table())
2178 }
2179}
2180
2181#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2183#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2184pub struct Mark2Array {
2185 pub mark2_records: Vec<Mark2Record>,
2187}
2188
2189impl Mark2Array {
2190 pub fn new(mark2_records: Vec<Mark2Record>) -> Self {
2192 Self { mark2_records }
2193 }
2194}
2195
2196impl FontWrite for Mark2Array {
2197 #[allow(clippy::unnecessary_cast)]
2198 fn write_into(&self, writer: &mut TableWriter) {
2199 (u16::try_from(array_len(&self.mark2_records)).unwrap()).write_into(writer);
2200 self.mark2_records.write_into(writer);
2201 }
2202 fn table_type(&self) -> TableType {
2203 TableType::Named("Mark2Array")
2204 }
2205}
2206
2207impl Validate for Mark2Array {
2208 fn validate_impl(&self, ctx: &mut ValidationCtx) {
2209 ctx.in_table("Mark2Array", |ctx| {
2210 ctx.in_field("mark2_records", |ctx| {
2211 if self.mark2_records.len() > to_usize(u16::MAX) {
2212 ctx.report("array exceeds max length");
2213 }
2214 self.mark2_records.validate_impl(ctx);
2215 });
2216 })
2217 }
2218}
2219
2220impl<'a> FromObjRef<read_fonts::tables::gpos::Mark2Array<'a>> for Mark2Array {
2221 fn from_obj_ref(obj: &read_fonts::tables::gpos::Mark2Array<'a>, _: FontData) -> Self {
2222 let offset_data = obj.offset_data();
2223 Mark2Array {
2224 mark2_records: obj
2225 .mark2_records()
2226 .iter()
2227 .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
2228 .collect(),
2229 }
2230 }
2231}
2232
2233#[allow(clippy::needless_lifetimes)]
2234impl<'a> FromTableRef<read_fonts::tables::gpos::Mark2Array<'a>> for Mark2Array {}
2235
2236#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2238#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2239pub struct Mark2Record {
2240 pub mark2_anchors: Vec<NullableOffsetMarker<AnchorTable>>,
2244}
2245
2246impl Mark2Record {
2247 pub fn new(mark2_anchors: Vec<Option<AnchorTable>>) -> Self {
2249 Self {
2250 mark2_anchors: mark2_anchors.into_iter().map(Into::into).collect(),
2251 }
2252 }
2253}
2254
2255impl FontWrite for Mark2Record {
2256 fn write_into(&self, writer: &mut TableWriter) {
2257 self.mark2_anchors.write_into(writer);
2258 }
2259 fn table_type(&self) -> TableType {
2260 TableType::Named("Mark2Record")
2261 }
2262}
2263
2264impl Validate for Mark2Record {
2265 fn validate_impl(&self, ctx: &mut ValidationCtx) {
2266 ctx.in_table("Mark2Record", |ctx| {
2267 ctx.in_field("mark2_anchors", |ctx| {
2268 if self.mark2_anchors.len() > to_usize(u16::MAX) {
2269 ctx.report("array exceeds max length");
2270 }
2271 self.mark2_anchors.validate_impl(ctx);
2272 });
2273 })
2274 }
2275}
2276
2277impl FromObjRef<read_fonts::tables::gpos::Mark2Record<'_>> for Mark2Record {
2278 fn from_obj_ref(obj: &read_fonts::tables::gpos::Mark2Record, offset_data: FontData) -> Self {
2279 Mark2Record {
2280 mark2_anchors: obj.mark2_anchors(offset_data).to_owned_table(),
2281 }
2282 }
2283}
2284
2285#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2287#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2288pub struct ExtensionPosFormat1<T> {
2289 pub extension_lookup_type: u16,
2292 pub extension: OffsetMarker<T, WIDTH_32>,
2296}
2297
2298impl<T: Default> ExtensionPosFormat1<T> {
2299 pub fn new(extension_lookup_type: u16, extension: T) -> Self {
2301 Self {
2302 extension_lookup_type,
2303 extension: extension.into(),
2304 }
2305 }
2306}
2307
2308impl<T: Validate> Validate for ExtensionPosFormat1<T> {
2309 fn validate_impl(&self, ctx: &mut ValidationCtx) {
2310 ctx.in_table("ExtensionPosFormat1", |ctx| {
2311 ctx.in_field("extension", |ctx| {
2312 self.extension.validate_impl(ctx);
2313 });
2314 })
2315 }
2316}
2317
2318impl<'a, T, U> FromObjRef<read_fonts::tables::gpos::ExtensionPosFormat1<'a, U>>
2319 for ExtensionPosFormat1<T>
2320where
2321 U: FontRead<'a, Args = ()>,
2322 T: FromTableRef<U> + Default + 'static,
2323{
2324 fn from_obj_ref(
2325 obj: &read_fonts::tables::gpos::ExtensionPosFormat1<'a, U>,
2326 _: FontData,
2327 ) -> Self {
2328 ExtensionPosFormat1 {
2329 extension_lookup_type: obj.extension_lookup_type(),
2330 extension: obj.extension().to_owned_table(),
2331 }
2332 }
2333}
2334
2335#[allow(clippy::needless_lifetimes)]
2336impl<'a, T, U> FromTableRef<read_fonts::tables::gpos::ExtensionPosFormat1<'a, U>>
2337 for ExtensionPosFormat1<T>
2338where
2339 U: FontRead<'a, Args = ()>,
2340 T: FromTableRef<U> + Default + 'static,
2341{
2342}
2343
2344#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2346#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2347pub enum ExtensionSubtable {
2348 Single(ExtensionPosFormat1<SinglePos>),
2349 Pair(ExtensionPosFormat1<PairPos>),
2350 Cursive(ExtensionPosFormat1<CursivePos>),
2351 MarkToBase(ExtensionPosFormat1<MarkBasePos>),
2352 MarkToLig(ExtensionPosFormat1<MarkLigPos>),
2353 MarkToMark(ExtensionPosFormat1<MarkMarkPos>),
2354 Contextual(ExtensionPosFormat1<PositionSequenceContext>),
2355 ChainContextual(ExtensionPosFormat1<PositionChainContext>),
2356}
2357
2358impl Default for ExtensionSubtable {
2359 fn default() -> Self {
2360 Self::Single(Default::default())
2361 }
2362}
2363
2364impl FontWrite for ExtensionSubtable {
2365 fn write_into(&self, writer: &mut TableWriter) {
2366 match self {
2367 Self::Single(table) => table.write_into(writer),
2368 Self::Pair(table) => table.write_into(writer),
2369 Self::Cursive(table) => table.write_into(writer),
2370 Self::MarkToBase(table) => table.write_into(writer),
2371 Self::MarkToLig(table) => table.write_into(writer),
2372 Self::MarkToMark(table) => table.write_into(writer),
2373 Self::Contextual(table) => table.write_into(writer),
2374 Self::ChainContextual(table) => table.write_into(writer),
2375 }
2376 }
2377 fn table_type(&self) -> TableType {
2378 match self {
2379 Self::Single(table) => table.table_type(),
2380 Self::Pair(table) => table.table_type(),
2381 Self::Cursive(table) => table.table_type(),
2382 Self::MarkToBase(table) => table.table_type(),
2383 Self::MarkToLig(table) => table.table_type(),
2384 Self::MarkToMark(table) => table.table_type(),
2385 Self::Contextual(table) => table.table_type(),
2386 Self::ChainContextual(table) => table.table_type(),
2387 }
2388 }
2389}
2390
2391impl Validate for ExtensionSubtable {
2392 fn validate_impl(&self, ctx: &mut ValidationCtx) {
2393 match self {
2394 Self::Single(table) => table.validate_impl(ctx),
2395 Self::Pair(table) => table.validate_impl(ctx),
2396 Self::Cursive(table) => table.validate_impl(ctx),
2397 Self::MarkToBase(table) => table.validate_impl(ctx),
2398 Self::MarkToLig(table) => table.validate_impl(ctx),
2399 Self::MarkToMark(table) => table.validate_impl(ctx),
2400 Self::Contextual(table) => table.validate_impl(ctx),
2401 Self::ChainContextual(table) => table.validate_impl(ctx),
2402 }
2403 }
2404}
2405
2406impl FromObjRef<read_fonts::tables::gpos::ExtensionSubtable<'_>> for ExtensionSubtable {
2407 fn from_obj_ref(
2408 from: &read_fonts::tables::gpos::ExtensionSubtable<'_>,
2409 data: FontData,
2410 ) -> Self {
2411 match from {
2412 read_fonts::tables::gpos::ExtensionSubtable::Single(table) => {
2413 Self::Single(table.to_owned_obj(data))
2414 }
2415 read_fonts::tables::gpos::ExtensionSubtable::Pair(table) => {
2416 Self::Pair(table.to_owned_obj(data))
2417 }
2418 read_fonts::tables::gpos::ExtensionSubtable::Cursive(table) => {
2419 Self::Cursive(table.to_owned_obj(data))
2420 }
2421 read_fonts::tables::gpos::ExtensionSubtable::MarkToBase(table) => {
2422 Self::MarkToBase(table.to_owned_obj(data))
2423 }
2424 read_fonts::tables::gpos::ExtensionSubtable::MarkToLig(table) => {
2425 Self::MarkToLig(table.to_owned_obj(data))
2426 }
2427 read_fonts::tables::gpos::ExtensionSubtable::MarkToMark(table) => {
2428 Self::MarkToMark(table.to_owned_obj(data))
2429 }
2430 read_fonts::tables::gpos::ExtensionSubtable::Contextual(table) => {
2431 Self::Contextual(table.to_owned_obj(data))
2432 }
2433 read_fonts::tables::gpos::ExtensionSubtable::ChainContextual(table) => {
2434 Self::ChainContextual(table.to_owned_obj(data))
2435 }
2436 }
2437 }
2438}
2439
2440impl FromTableRef<read_fonts::tables::gpos::ExtensionSubtable<'_>> for ExtensionSubtable {}
2441
2442impl From<ExtensionPosFormat1<SinglePos>> for ExtensionSubtable {
2443 fn from(src: ExtensionPosFormat1<SinglePos>) -> ExtensionSubtable {
2444 ExtensionSubtable::Single(src)
2445 }
2446}
2447
2448impl From<ExtensionPosFormat1<PairPos>> for ExtensionSubtable {
2449 fn from(src: ExtensionPosFormat1<PairPos>) -> ExtensionSubtable {
2450 ExtensionSubtable::Pair(src)
2451 }
2452}
2453
2454impl From<ExtensionPosFormat1<CursivePos>> for ExtensionSubtable {
2455 fn from(src: ExtensionPosFormat1<CursivePos>) -> ExtensionSubtable {
2456 ExtensionSubtable::Cursive(src)
2457 }
2458}
2459
2460impl From<ExtensionPosFormat1<MarkBasePos>> for ExtensionSubtable {
2461 fn from(src: ExtensionPosFormat1<MarkBasePos>) -> ExtensionSubtable {
2462 ExtensionSubtable::MarkToBase(src)
2463 }
2464}
2465
2466impl From<ExtensionPosFormat1<MarkLigPos>> for ExtensionSubtable {
2467 fn from(src: ExtensionPosFormat1<MarkLigPos>) -> ExtensionSubtable {
2468 ExtensionSubtable::MarkToLig(src)
2469 }
2470}
2471
2472impl From<ExtensionPosFormat1<MarkMarkPos>> for ExtensionSubtable {
2473 fn from(src: ExtensionPosFormat1<MarkMarkPos>) -> ExtensionSubtable {
2474 ExtensionSubtable::MarkToMark(src)
2475 }
2476}
2477
2478impl From<ExtensionPosFormat1<PositionSequenceContext>> for ExtensionSubtable {
2479 fn from(src: ExtensionPosFormat1<PositionSequenceContext>) -> ExtensionSubtable {
2480 ExtensionSubtable::Contextual(src)
2481 }
2482}
2483
2484impl From<ExtensionPosFormat1<PositionChainContext>> for ExtensionSubtable {
2485 fn from(src: ExtensionPosFormat1<PositionChainContext>) -> ExtensionSubtable {
2486 ExtensionSubtable::ChainContextual(src)
2487 }
2488}
2489
2490#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2492#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2493pub struct SinglePosFormat3 {
2494 pub coverage: OffsetMarker<CoverageTable, WIDTH_32>,
2496 pub value_record: ValueRecord,
2499}
2500
2501impl SinglePosFormat3 {
2502 pub fn new(coverage: CoverageTable, value_record: ValueRecord) -> Self {
2504 Self {
2505 coverage: coverage.into(),
2506 value_record,
2507 }
2508 }
2509}
2510
2511impl FontWrite for SinglePosFormat3 {
2512 #[allow(clippy::unnecessary_cast)]
2513 fn write_into(&self, writer: &mut TableWriter) {
2514 (3 as u16).write_into(writer);
2515 self.coverage.write_into(writer);
2516 (self.compute_value_format() as ValueFormat).write_into(writer);
2517 self.value_record.write_into(writer);
2518 }
2519 fn table_type(&self) -> TableType {
2520 TableType::Named("SinglePosFormat3")
2521 }
2522}
2523
2524impl Validate for SinglePosFormat3 {
2525 fn validate_impl(&self, ctx: &mut ValidationCtx) {
2526 ctx.in_table("SinglePosFormat3", |ctx| {
2527 ctx.in_field("coverage", |ctx| {
2528 self.coverage.validate_impl(ctx);
2529 });
2530 })
2531 }
2532}
2533
2534impl<'a> FromObjRef<read_fonts::tables::gpos::SinglePosFormat3<'a>> for SinglePosFormat3 {
2535 fn from_obj_ref(obj: &read_fonts::tables::gpos::SinglePosFormat3<'a>, _: FontData) -> Self {
2536 let offset_data = obj.offset_data();
2537 SinglePosFormat3 {
2538 coverage: obj.coverage().to_owned_table(),
2539 value_record: obj.value_record().to_owned_obj(offset_data),
2540 }
2541 }
2542}
2543
2544#[allow(clippy::needless_lifetimes)]
2545impl<'a> FromTableRef<read_fonts::tables::gpos::SinglePosFormat3<'a>> for SinglePosFormat3 {}
2546
2547impl ReadArgs for SinglePosFormat3 {
2548 type Args = ();
2549}
2550
2551impl<'a> FontRead<'a> for SinglePosFormat3 {
2552 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2553 <read_fonts::tables::gpos::SinglePosFormat3 as FontRead>::read(data)
2554 .map(|x| x.to_owned_table())
2555 }
2556}
2557
2558#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2560#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2561pub struct SinglePosFormat4 {
2562 pub coverage: OffsetMarker<CoverageTable, WIDTH_32>,
2564 pub value_records: Vec<ValueRecord>,
2566}
2567
2568impl SinglePosFormat4 {
2569 pub fn new(coverage: CoverageTable, value_records: Vec<ValueRecord>) -> Self {
2571 Self {
2572 coverage: coverage.into(),
2573 value_records,
2574 }
2575 }
2576}
2577
2578impl FontWrite for SinglePosFormat4 {
2579 #[allow(clippy::unnecessary_cast)]
2580 fn write_into(&self, writer: &mut TableWriter) {
2581 (4 as u16).write_into(writer);
2582 self.coverage.write_into(writer);
2583 (self.compute_value_format() as ValueFormat).write_into(writer);
2584 (Uint24::try_from(array_len(&self.value_records)).unwrap()).write_into(writer);
2585 self.value_records.write_into(writer);
2586 }
2587 fn table_type(&self) -> TableType {
2588 TableType::Named("SinglePosFormat4")
2589 }
2590}
2591
2592impl Validate for SinglePosFormat4 {
2593 fn validate_impl(&self, ctx: &mut ValidationCtx) {
2594 ctx.in_table("SinglePosFormat4", |ctx| {
2595 ctx.in_field("coverage", |ctx| {
2596 self.coverage.validate_impl(ctx);
2597 });
2598 ctx.in_field("value_records", |ctx| {
2599 if self.value_records.len() > to_usize(Uint24::MAX) {
2600 ctx.report("array exceeds max length");
2601 }
2602 self.check_format_consistency(ctx);
2603 });
2604 })
2605 }
2606}
2607
2608impl<'a> FromObjRef<read_fonts::tables::gpos::SinglePosFormat4<'a>> for SinglePosFormat4 {
2609 fn from_obj_ref(obj: &read_fonts::tables::gpos::SinglePosFormat4<'a>, _: FontData) -> Self {
2610 let offset_data = obj.offset_data();
2611 SinglePosFormat4 {
2612 coverage: obj.coverage().to_owned_table(),
2613 value_records: obj
2614 .value_records()
2615 .iter()
2616 .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
2617 .collect(),
2618 }
2619 }
2620}
2621
2622#[allow(clippy::needless_lifetimes)]
2623impl<'a> FromTableRef<read_fonts::tables::gpos::SinglePosFormat4<'a>> for SinglePosFormat4 {}
2624
2625impl ReadArgs for SinglePosFormat4 {
2626 type Args = ();
2627}
2628
2629impl<'a> FontRead<'a> for SinglePosFormat4 {
2630 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2631 <read_fonts::tables::gpos::SinglePosFormat4 as FontRead>::read(data)
2632 .map(|x| x.to_owned_table())
2633 }
2634}
2635
2636#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2638#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2639pub struct PairPosFormat3 {
2640 pub coverage: OffsetMarker<CoverageTable, WIDTH_32>,
2642 pub pair_sets: Vec<OffsetMarker<PairSet2, WIDTH_24>>,
2645}
2646
2647impl PairPosFormat3 {
2648 pub fn new(coverage: CoverageTable, pair_sets: Vec<PairSet2>) -> Self {
2650 Self {
2651 coverage: coverage.into(),
2652 pair_sets: pair_sets.into_iter().map(Into::into).collect(),
2653 }
2654 }
2655}
2656
2657impl FontWrite for PairPosFormat3 {
2658 #[allow(clippy::unnecessary_cast)]
2659 fn write_into(&self, writer: &mut TableWriter) {
2660 (3 as u16).write_into(writer);
2661 self.coverage.write_into(writer);
2662 (self.compute_value_format1() as ValueFormat).write_into(writer);
2663 (self.compute_value_format2() as ValueFormat).write_into(writer);
2664 (Uint24::try_from(array_len(&self.pair_sets)).unwrap()).write_into(writer);
2665 self.pair_sets.write_into(writer);
2666 }
2667 fn table_type(&self) -> TableType {
2668 TableType::Named("PairPosFormat3")
2669 }
2670}
2671
2672impl Validate for PairPosFormat3 {
2673 fn validate_impl(&self, ctx: &mut ValidationCtx) {
2674 ctx.in_table("PairPosFormat3", |ctx| {
2675 ctx.in_field("coverage", |ctx| {
2676 self.coverage.validate_impl(ctx);
2677 });
2678 ctx.in_field("pair_sets", |ctx| {
2679 if self.pair_sets.len() > to_usize(Uint24::MAX) {
2680 ctx.report("array exceeds max length");
2681 }
2682 self.check_format_consistency(ctx);
2683 });
2684 })
2685 }
2686}
2687
2688impl<'a> FromObjRef<read_fonts::tables::gpos::PairPosFormat3<'a>> for PairPosFormat3 {
2689 fn from_obj_ref(obj: &read_fonts::tables::gpos::PairPosFormat3<'a>, _: FontData) -> Self {
2690 PairPosFormat3 {
2691 coverage: obj.coverage().to_owned_table(),
2692 pair_sets: obj.pair_sets().to_owned_table(),
2693 }
2694 }
2695}
2696
2697#[allow(clippy::needless_lifetimes)]
2698impl<'a> FromTableRef<read_fonts::tables::gpos::PairPosFormat3<'a>> for PairPosFormat3 {}
2699
2700impl ReadArgs for PairPosFormat3 {
2701 type Args = ();
2702}
2703
2704impl<'a> FontRead<'a> for PairPosFormat3 {
2705 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2706 <read_fonts::tables::gpos::PairPosFormat3 as FontRead>::read(data)
2707 .map(|x| x.to_owned_table())
2708 }
2709}
2710
2711#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2713#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2714pub struct PairSet2 {
2715 pub pair_value_records: Vec<PairValueRecord2>,
2718}
2719
2720impl PairSet2 {
2721 pub fn new(pair_value_records: Vec<PairValueRecord2>) -> Self {
2723 Self { pair_value_records }
2724 }
2725}
2726
2727impl FontWrite for PairSet2 {
2728 #[allow(clippy::unnecessary_cast)]
2729 fn write_into(&self, writer: &mut TableWriter) {
2730 (Uint24::try_from(array_len(&self.pair_value_records)).unwrap()).write_into(writer);
2731 self.pair_value_records.write_into(writer);
2732 }
2733 fn table_type(&self) -> TableType {
2734 TableType::Named("PairSet2")
2735 }
2736}
2737
2738impl Validate for PairSet2 {
2739 fn validate_impl(&self, ctx: &mut ValidationCtx) {
2740 ctx.in_table("PairSet2", |ctx| {
2741 ctx.in_field("pair_value_records", |ctx| {
2742 if self.pair_value_records.len() > to_usize(Uint24::MAX) {
2743 ctx.report("array exceeds max length");
2744 }
2745 self.pair_value_records.validate_impl(ctx);
2746 });
2747 })
2748 }
2749}
2750
2751impl<'a> FromObjRef<read_fonts::tables::gpos::PairSet2<'a>> for PairSet2 {
2752 fn from_obj_ref(obj: &read_fonts::tables::gpos::PairSet2<'a>, _: FontData) -> Self {
2753 let offset_data = obj.offset_data();
2754 PairSet2 {
2755 pair_value_records: obj
2756 .pair_value_records()
2757 .iter()
2758 .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
2759 .collect(),
2760 }
2761 }
2762}
2763
2764#[allow(clippy::needless_lifetimes)]
2765impl<'a> FromTableRef<read_fonts::tables::gpos::PairSet2<'a>> for PairSet2 {}
2766
2767#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2769#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2770pub struct PairValueRecord2 {
2771 pub second_glyph: GlyphId24,
2774 pub value_record1: ValueRecord,
2776 pub value_record2: ValueRecord,
2778}
2779
2780impl PairValueRecord2 {
2781 pub fn new(
2783 second_glyph: GlyphId24,
2784 value_record1: ValueRecord,
2785 value_record2: ValueRecord,
2786 ) -> Self {
2787 Self {
2788 second_glyph,
2789 value_record1,
2790 value_record2,
2791 }
2792 }
2793}
2794
2795impl FontWrite for PairValueRecord2 {
2796 fn write_into(&self, writer: &mut TableWriter) {
2797 self.second_glyph.write_into(writer);
2798 self.value_record1.write_into(writer);
2799 self.value_record2.write_into(writer);
2800 }
2801 fn table_type(&self) -> TableType {
2802 TableType::Named("PairValueRecord2")
2803 }
2804}
2805
2806impl Validate for PairValueRecord2 {
2807 fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
2808}
2809
2810impl FromObjRef<read_fonts::tables::gpos::PairValueRecord2<'_>> for PairValueRecord2 {
2811 fn from_obj_ref(
2812 obj: &read_fonts::tables::gpos::PairValueRecord2,
2813 offset_data: FontData,
2814 ) -> Self {
2815 PairValueRecord2 {
2816 second_glyph: obj.second_glyph(),
2817 value_record1: obj.value_record1().to_owned_obj(offset_data),
2818 value_record2: obj.value_record2().to_owned_obj(offset_data),
2819 }
2820 }
2821}
2822
2823#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2825#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2826pub struct PairPosFormat4 {
2827 pub coverage: OffsetMarker<CoverageTable, WIDTH_32>,
2829 pub class_def1: OffsetMarker<ClassDef, WIDTH_32>,
2832 pub class_def2: OffsetMarker<ClassDef, WIDTH_32>,
2835 pub class1_records: Vec<Class1Record>,
2837}
2838
2839impl PairPosFormat4 {
2840 pub fn new(
2842 coverage: CoverageTable,
2843 class_def1: ClassDef,
2844 class_def2: ClassDef,
2845 class1_records: Vec<Class1Record>,
2846 ) -> Self {
2847 Self {
2848 coverage: coverage.into(),
2849 class_def1: class_def1.into(),
2850 class_def2: class_def2.into(),
2851 class1_records,
2852 }
2853 }
2854}
2855
2856impl FontWrite for PairPosFormat4 {
2857 #[allow(clippy::unnecessary_cast)]
2858 fn write_into(&self, writer: &mut TableWriter) {
2859 (4 as u16).write_into(writer);
2860 self.coverage.write_into(writer);
2861 (self.compute_value_format1() as ValueFormat).write_into(writer);
2862 (self.compute_value_format2() as ValueFormat).write_into(writer);
2863 self.class_def1.write_into(writer);
2864 self.class_def2.write_into(writer);
2865 (self.compute_class1_count() as u16).write_into(writer);
2866 (self.compute_class2_count() as u16).write_into(writer);
2867 self.class1_records.write_into(writer);
2868 }
2869 fn table_type(&self) -> TableType {
2870 TableType::Named("PairPosFormat4")
2871 }
2872}
2873
2874impl Validate for PairPosFormat4 {
2875 fn validate_impl(&self, ctx: &mut ValidationCtx) {
2876 ctx.in_table("PairPosFormat4", |ctx| {
2877 ctx.in_field("coverage", |ctx| {
2878 self.coverage.validate_impl(ctx);
2879 });
2880 ctx.in_field("class_def1", |ctx| {
2881 self.class_def1.validate_impl(ctx);
2882 });
2883 ctx.in_field("class_def2", |ctx| {
2884 self.class_def2.validate_impl(ctx);
2885 });
2886 ctx.in_field("class1_records", |ctx| {
2887 if self.class1_records.len() > to_usize(u16::MAX) {
2888 ctx.report("array exceeds max length");
2889 }
2890 self.class1_records.validate_impl(ctx);
2891 });
2892 self.check_length_and_format_conformance(ctx);
2893 })
2894 }
2895}
2896
2897impl<'a> FromObjRef<read_fonts::tables::gpos::PairPosFormat4<'a>> for PairPosFormat4 {
2898 fn from_obj_ref(obj: &read_fonts::tables::gpos::PairPosFormat4<'a>, _: FontData) -> Self {
2899 let offset_data = obj.offset_data();
2900 PairPosFormat4 {
2901 coverage: obj.coverage().to_owned_table(),
2902 class_def1: obj.class_def1().to_owned_table(),
2903 class_def2: obj.class_def2().to_owned_table(),
2904 class1_records: obj
2905 .class1_records()
2906 .iter()
2907 .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
2908 .collect(),
2909 }
2910 }
2911}
2912
2913#[allow(clippy::needless_lifetimes)]
2914impl<'a> FromTableRef<read_fonts::tables::gpos::PairPosFormat4<'a>> for PairPosFormat4 {}
2915
2916impl ReadArgs for PairPosFormat4 {
2917 type Args = ();
2918}
2919
2920impl<'a> FontRead<'a> for PairPosFormat4 {
2921 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2922 <read_fonts::tables::gpos::PairPosFormat4 as FontRead>::read(data)
2923 .map(|x| x.to_owned_table())
2924 }
2925}
2926
2927#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2929#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2930pub struct CursivePosFormat2 {
2931 pub coverage: OffsetMarker<CoverageTable, WIDTH_32>,
2933 pub entry_exit_record: Vec<EntryExitRecord2>,
2935}
2936
2937impl CursivePosFormat2 {
2938 pub fn new(coverage: CoverageTable, entry_exit_record: Vec<EntryExitRecord2>) -> Self {
2940 Self {
2941 coverage: coverage.into(),
2942 entry_exit_record,
2943 }
2944 }
2945}
2946
2947impl FontWrite for CursivePosFormat2 {
2948 #[allow(clippy::unnecessary_cast)]
2949 fn write_into(&self, writer: &mut TableWriter) {
2950 (2 as u16).write_into(writer);
2951 self.coverage.write_into(writer);
2952 (Uint24::try_from(array_len(&self.entry_exit_record)).unwrap()).write_into(writer);
2953 self.entry_exit_record.write_into(writer);
2954 }
2955 fn table_type(&self) -> TableType {
2956 TableType::Named("CursivePosFormat2")
2957 }
2958}
2959
2960impl Validate for CursivePosFormat2 {
2961 fn validate_impl(&self, ctx: &mut ValidationCtx) {
2962 ctx.in_table("CursivePosFormat2", |ctx| {
2963 ctx.in_field("coverage", |ctx| {
2964 self.coverage.validate_impl(ctx);
2965 });
2966 ctx.in_field("entry_exit_record", |ctx| {
2967 if self.entry_exit_record.len() > to_usize(Uint24::MAX) {
2968 ctx.report("array exceeds max length");
2969 }
2970 self.entry_exit_record.validate_impl(ctx);
2971 });
2972 })
2973 }
2974}
2975
2976impl<'a> FromObjRef<read_fonts::tables::gpos::CursivePosFormat2<'a>> for CursivePosFormat2 {
2977 fn from_obj_ref(obj: &read_fonts::tables::gpos::CursivePosFormat2<'a>, _: FontData) -> Self {
2978 let offset_data = obj.offset_data();
2979 CursivePosFormat2 {
2980 coverage: obj.coverage().to_owned_table(),
2981 entry_exit_record: obj.entry_exit_record().to_owned_obj(offset_data),
2982 }
2983 }
2984}
2985
2986#[allow(clippy::needless_lifetimes)]
2987impl<'a> FromTableRef<read_fonts::tables::gpos::CursivePosFormat2<'a>> for CursivePosFormat2 {}
2988
2989impl ReadArgs for CursivePosFormat2 {
2990 type Args = ();
2991}
2992
2993impl<'a> FontRead<'a> for CursivePosFormat2 {
2994 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2995 <read_fonts::tables::gpos::CursivePosFormat2 as FontRead>::read(data)
2996 .map(|x| x.to_owned_table())
2997 }
2998}
2999
3000#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
3002#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3003pub struct EntryExitRecord2 {
3004 pub entry_anchor: NullableOffsetMarker<AnchorTable, WIDTH_24>,
3007 pub exit_anchor: NullableOffsetMarker<AnchorTable, WIDTH_24>,
3010}
3011
3012impl EntryExitRecord2 {
3013 pub fn new(entry_anchor: Option<AnchorTable>, exit_anchor: Option<AnchorTable>) -> Self {
3015 Self {
3016 entry_anchor: entry_anchor.into(),
3017 exit_anchor: exit_anchor.into(),
3018 }
3019 }
3020}
3021
3022impl FontWrite for EntryExitRecord2 {
3023 fn write_into(&self, writer: &mut TableWriter) {
3024 self.entry_anchor.write_into(writer);
3025 self.exit_anchor.write_into(writer);
3026 }
3027 fn table_type(&self) -> TableType {
3028 TableType::Named("EntryExitRecord2")
3029 }
3030}
3031
3032impl Validate for EntryExitRecord2 {
3033 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3034 ctx.in_table("EntryExitRecord2", |ctx| {
3035 ctx.in_field("entry_anchor", |ctx| {
3036 self.entry_anchor.validate_impl(ctx);
3037 });
3038 ctx.in_field("exit_anchor", |ctx| {
3039 self.exit_anchor.validate_impl(ctx);
3040 });
3041 })
3042 }
3043}
3044
3045impl FromObjRef<read_fonts::tables::gpos::EntryExitRecord2> for EntryExitRecord2 {
3046 fn from_obj_ref(
3047 obj: &read_fonts::tables::gpos::EntryExitRecord2,
3048 offset_data: FontData,
3049 ) -> Self {
3050 EntryExitRecord2 {
3051 entry_anchor: obj.entry_anchor(offset_data).to_owned_table(),
3052 exit_anchor: obj.exit_anchor(offset_data).to_owned_table(),
3053 }
3054 }
3055}
3056
3057#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
3059#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3060pub struct MarkBasePosFormat2 {
3061 pub mark_coverage: OffsetMarker<CoverageTable, WIDTH_32>,
3064 pub base_coverage: OffsetMarker<CoverageTable, WIDTH_32>,
3067 pub mark_array: OffsetMarker<MarkArray2, WIDTH_32>,
3070 pub base_array: OffsetMarker<BaseArray2, WIDTH_32>,
3073}
3074
3075impl MarkBasePosFormat2 {
3076 pub fn new(
3078 mark_coverage: CoverageTable,
3079 base_coverage: CoverageTable,
3080 mark_array: MarkArray2,
3081 base_array: BaseArray2,
3082 ) -> Self {
3083 Self {
3084 mark_coverage: mark_coverage.into(),
3085 base_coverage: base_coverage.into(),
3086 mark_array: mark_array.into(),
3087 base_array: base_array.into(),
3088 }
3089 }
3090}
3091
3092impl FontWrite for MarkBasePosFormat2 {
3093 #[allow(clippy::unnecessary_cast)]
3094 fn write_into(&self, writer: &mut TableWriter) {
3095 (2 as u16).write_into(writer);
3096 self.mark_coverage.write_into(writer);
3097 self.base_coverage.write_into(writer);
3098 (self.compute_mark_class_count() as u16).write_into(writer);
3099 self.mark_array.write_into(writer);
3100 self.base_array.write_into(writer);
3101 }
3102 fn table_type(&self) -> TableType {
3103 TableType::Named("MarkBasePosFormat2")
3104 }
3105}
3106
3107impl Validate for MarkBasePosFormat2 {
3108 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3109 ctx.in_table("MarkBasePosFormat2", |ctx| {
3110 ctx.in_field("mark_coverage", |ctx| {
3111 self.mark_coverage.validate_impl(ctx);
3112 });
3113 ctx.in_field("base_coverage", |ctx| {
3114 self.base_coverage.validate_impl(ctx);
3115 });
3116 ctx.in_field("mark_array", |ctx| {
3117 self.mark_array.validate_impl(ctx);
3118 });
3119 ctx.in_field("base_array", |ctx| {
3120 self.base_array.validate_impl(ctx);
3121 });
3122 self.check_class_dimensions(ctx);
3123 })
3124 }
3125}
3126
3127impl<'a> FromObjRef<read_fonts::tables::gpos::MarkBasePosFormat2<'a>> for MarkBasePosFormat2 {
3128 fn from_obj_ref(obj: &read_fonts::tables::gpos::MarkBasePosFormat2<'a>, _: FontData) -> Self {
3129 MarkBasePosFormat2 {
3130 mark_coverage: obj.mark_coverage().to_owned_table(),
3131 base_coverage: obj.base_coverage().to_owned_table(),
3132 mark_array: obj.mark_array().to_owned_table(),
3133 base_array: obj.base_array().to_owned_table(),
3134 }
3135 }
3136}
3137
3138#[allow(clippy::needless_lifetimes)]
3139impl<'a> FromTableRef<read_fonts::tables::gpos::MarkBasePosFormat2<'a>> for MarkBasePosFormat2 {}
3140
3141impl ReadArgs for MarkBasePosFormat2 {
3142 type Args = ();
3143}
3144
3145impl<'a> FontRead<'a> for MarkBasePosFormat2 {
3146 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3147 <read_fonts::tables::gpos::MarkBasePosFormat2 as FontRead>::read(data)
3148 .map(|x| x.to_owned_table())
3149 }
3150}
3151
3152#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
3154#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3155pub struct BaseArray2 {
3156 pub base_records: Vec<BaseRecord2>,
3158}
3159
3160impl BaseArray2 {
3161 pub fn new(base_records: Vec<BaseRecord2>) -> Self {
3163 Self { base_records }
3164 }
3165}
3166
3167impl FontWrite for BaseArray2 {
3168 #[allow(clippy::unnecessary_cast)]
3169 fn write_into(&self, writer: &mut TableWriter) {
3170 (Uint24::try_from(array_len(&self.base_records)).unwrap()).write_into(writer);
3171 self.base_records.write_into(writer);
3172 }
3173 fn table_type(&self) -> TableType {
3174 TableType::Named("BaseArray2")
3175 }
3176}
3177
3178impl Validate for BaseArray2 {
3179 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3180 ctx.in_table("BaseArray2", |ctx| {
3181 ctx.in_field("base_records", |ctx| {
3182 if self.base_records.len() > to_usize(Uint24::MAX) {
3183 ctx.report("array exceeds max length");
3184 }
3185 self.base_records.validate_impl(ctx);
3186 });
3187 })
3188 }
3189}
3190
3191impl<'a> FromObjRef<read_fonts::tables::gpos::BaseArray2<'a>> for BaseArray2 {
3192 fn from_obj_ref(obj: &read_fonts::tables::gpos::BaseArray2<'a>, _: FontData) -> Self {
3193 let offset_data = obj.offset_data();
3194 BaseArray2 {
3195 base_records: obj
3196 .base_records()
3197 .iter()
3198 .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
3199 .collect(),
3200 }
3201 }
3202}
3203
3204#[allow(clippy::needless_lifetimes)]
3205impl<'a> FromTableRef<read_fonts::tables::gpos::BaseArray2<'a>> for BaseArray2 {}
3206
3207#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
3209#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3210pub struct BaseRecord2 {
3211 pub base_anchors: Vec<NullableOffsetMarker<AnchorTable, WIDTH_24>>,
3215}
3216
3217impl BaseRecord2 {
3218 pub fn new(base_anchors: Vec<Option<AnchorTable>>) -> Self {
3220 Self {
3221 base_anchors: base_anchors.into_iter().map(Into::into).collect(),
3222 }
3223 }
3224}
3225
3226impl FontWrite for BaseRecord2 {
3227 fn write_into(&self, writer: &mut TableWriter) {
3228 self.base_anchors.write_into(writer);
3229 }
3230 fn table_type(&self) -> TableType {
3231 TableType::Named("BaseRecord2")
3232 }
3233}
3234
3235impl Validate for BaseRecord2 {
3236 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3237 ctx.in_table("BaseRecord2", |ctx| {
3238 ctx.in_field("base_anchors", |ctx| {
3239 if self.base_anchors.len() > to_usize(u16::MAX) {
3240 ctx.report("array exceeds max length");
3241 }
3242 self.base_anchors.validate_impl(ctx);
3243 });
3244 })
3245 }
3246}
3247
3248impl FromObjRef<read_fonts::tables::gpos::BaseRecord2<'_>> for BaseRecord2 {
3249 fn from_obj_ref(obj: &read_fonts::tables::gpos::BaseRecord2, offset_data: FontData) -> Self {
3250 BaseRecord2 {
3251 base_anchors: obj.base_anchors(offset_data).to_owned_table(),
3252 }
3253 }
3254}
3255
3256#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
3258#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3259pub struct MarkLigPosFormat2 {
3260 pub mark_coverage: OffsetMarker<CoverageTable, WIDTH_32>,
3263 pub ligature_coverage: OffsetMarker<CoverageTable, WIDTH_32>,
3266 pub mark_array: OffsetMarker<MarkArray2, WIDTH_32>,
3269 pub ligature_array: OffsetMarker<LigatureArray2, WIDTH_32>,
3272}
3273
3274impl MarkLigPosFormat2 {
3275 pub fn new(
3277 mark_coverage: CoverageTable,
3278 ligature_coverage: CoverageTable,
3279 mark_array: MarkArray2,
3280 ligature_array: LigatureArray2,
3281 ) -> Self {
3282 Self {
3283 mark_coverage: mark_coverage.into(),
3284 ligature_coverage: ligature_coverage.into(),
3285 mark_array: mark_array.into(),
3286 ligature_array: ligature_array.into(),
3287 }
3288 }
3289}
3290
3291impl FontWrite for MarkLigPosFormat2 {
3292 #[allow(clippy::unnecessary_cast)]
3293 fn write_into(&self, writer: &mut TableWriter) {
3294 (2 as u16).write_into(writer);
3295 self.mark_coverage.write_into(writer);
3296 self.ligature_coverage.write_into(writer);
3297 (self.compute_mark_class_count() as u16).write_into(writer);
3298 self.mark_array.write_into(writer);
3299 self.ligature_array.write_into(writer);
3300 }
3301 fn table_type(&self) -> TableType {
3302 TableType::Named("MarkLigPosFormat2")
3303 }
3304}
3305
3306impl Validate for MarkLigPosFormat2 {
3307 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3308 ctx.in_table("MarkLigPosFormat2", |ctx| {
3309 ctx.in_field("mark_coverage", |ctx| {
3310 self.mark_coverage.validate_impl(ctx);
3311 });
3312 ctx.in_field("ligature_coverage", |ctx| {
3313 self.ligature_coverage.validate_impl(ctx);
3314 });
3315 ctx.in_field("mark_array", |ctx| {
3316 self.mark_array.validate_impl(ctx);
3317 });
3318 ctx.in_field("ligature_array", |ctx| {
3319 self.ligature_array.validate_impl(ctx);
3320 });
3321 self.check_class_dimensions(ctx);
3322 })
3323 }
3324}
3325
3326impl<'a> FromObjRef<read_fonts::tables::gpos::MarkLigPosFormat2<'a>> for MarkLigPosFormat2 {
3327 fn from_obj_ref(obj: &read_fonts::tables::gpos::MarkLigPosFormat2<'a>, _: FontData) -> Self {
3328 MarkLigPosFormat2 {
3329 mark_coverage: obj.mark_coverage().to_owned_table(),
3330 ligature_coverage: obj.ligature_coverage().to_owned_table(),
3331 mark_array: obj.mark_array().to_owned_table(),
3332 ligature_array: obj.ligature_array().to_owned_table(),
3333 }
3334 }
3335}
3336
3337#[allow(clippy::needless_lifetimes)]
3338impl<'a> FromTableRef<read_fonts::tables::gpos::MarkLigPosFormat2<'a>> for MarkLigPosFormat2 {}
3339
3340impl ReadArgs for MarkLigPosFormat2 {
3341 type Args = ();
3342}
3343
3344impl<'a> FontRead<'a> for MarkLigPosFormat2 {
3345 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3346 <read_fonts::tables::gpos::MarkLigPosFormat2 as FontRead>::read(data)
3347 .map(|x| x.to_owned_table())
3348 }
3349}
3350
3351#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
3353#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3354pub struct LigatureArray2 {
3355 pub ligature_attaches: Vec<OffsetMarker<LigatureAttach2, WIDTH_24>>,
3359}
3360
3361impl LigatureArray2 {
3362 pub fn new(ligature_attaches: Vec<LigatureAttach2>) -> Self {
3364 Self {
3365 ligature_attaches: ligature_attaches.into_iter().map(Into::into).collect(),
3366 }
3367 }
3368}
3369
3370impl FontWrite for LigatureArray2 {
3371 #[allow(clippy::unnecessary_cast)]
3372 fn write_into(&self, writer: &mut TableWriter) {
3373 (Uint24::try_from(array_len(&self.ligature_attaches)).unwrap()).write_into(writer);
3374 self.ligature_attaches.write_into(writer);
3375 }
3376 fn table_type(&self) -> TableType {
3377 TableType::Named("LigatureArray2")
3378 }
3379}
3380
3381impl Validate for LigatureArray2 {
3382 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3383 ctx.in_table("LigatureArray2", |ctx| {
3384 ctx.in_field("ligature_attaches", |ctx| {
3385 if self.ligature_attaches.len() > to_usize(Uint24::MAX) {
3386 ctx.report("array exceeds max length");
3387 }
3388 self.ligature_attaches.validate_impl(ctx);
3389 });
3390 })
3391 }
3392}
3393
3394impl<'a> FromObjRef<read_fonts::tables::gpos::LigatureArray2<'a>> for LigatureArray2 {
3395 fn from_obj_ref(obj: &read_fonts::tables::gpos::LigatureArray2<'a>, _: FontData) -> Self {
3396 LigatureArray2 {
3397 ligature_attaches: obj.ligature_attaches().to_owned_table(),
3398 }
3399 }
3400}
3401
3402#[allow(clippy::needless_lifetimes)]
3403impl<'a> FromTableRef<read_fonts::tables::gpos::LigatureArray2<'a>> for LigatureArray2 {}
3404
3405#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
3407#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3408pub struct LigatureAttach2 {
3409 pub component_records: Vec<ComponentRecord2>,
3411}
3412
3413impl LigatureAttach2 {
3414 pub fn new(component_records: Vec<ComponentRecord2>) -> Self {
3416 Self { component_records }
3417 }
3418}
3419
3420impl FontWrite for LigatureAttach2 {
3421 #[allow(clippy::unnecessary_cast)]
3422 fn write_into(&self, writer: &mut TableWriter) {
3423 (u16::try_from(array_len(&self.component_records)).unwrap()).write_into(writer);
3424 self.component_records.write_into(writer);
3425 }
3426 fn table_type(&self) -> TableType {
3427 TableType::Named("LigatureAttach2")
3428 }
3429}
3430
3431impl Validate for LigatureAttach2 {
3432 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3433 ctx.in_table("LigatureAttach2", |ctx| {
3434 ctx.in_field("component_records", |ctx| {
3435 if self.component_records.len() > to_usize(u16::MAX) {
3436 ctx.report("array exceeds max length");
3437 }
3438 self.component_records.validate_impl(ctx);
3439 });
3440 })
3441 }
3442}
3443
3444impl<'a> FromObjRef<read_fonts::tables::gpos::LigatureAttach2<'a>> for LigatureAttach2 {
3445 fn from_obj_ref(obj: &read_fonts::tables::gpos::LigatureAttach2<'a>, _: FontData) -> Self {
3446 let offset_data = obj.offset_data();
3447 LigatureAttach2 {
3448 component_records: obj
3449 .component_records()
3450 .iter()
3451 .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
3452 .collect(),
3453 }
3454 }
3455}
3456
3457#[allow(clippy::needless_lifetimes)]
3458impl<'a> FromTableRef<read_fonts::tables::gpos::LigatureAttach2<'a>> for LigatureAttach2 {}
3459
3460#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
3462#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3463pub struct ComponentRecord2 {
3464 pub ligature_anchors: Vec<NullableOffsetMarker<AnchorTable, WIDTH_24>>,
3468}
3469
3470impl ComponentRecord2 {
3471 pub fn new(ligature_anchors: Vec<Option<AnchorTable>>) -> Self {
3473 Self {
3474 ligature_anchors: ligature_anchors.into_iter().map(Into::into).collect(),
3475 }
3476 }
3477}
3478
3479impl FontWrite for ComponentRecord2 {
3480 fn write_into(&self, writer: &mut TableWriter) {
3481 self.ligature_anchors.write_into(writer);
3482 }
3483 fn table_type(&self) -> TableType {
3484 TableType::Named("ComponentRecord2")
3485 }
3486}
3487
3488impl Validate for ComponentRecord2 {
3489 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3490 ctx.in_table("ComponentRecord2", |ctx| {
3491 ctx.in_field("ligature_anchors", |ctx| {
3492 if self.ligature_anchors.len() > to_usize(u16::MAX) {
3493 ctx.report("array exceeds max length");
3494 }
3495 self.ligature_anchors.validate_impl(ctx);
3496 });
3497 })
3498 }
3499}
3500
3501impl FromObjRef<read_fonts::tables::gpos::ComponentRecord2<'_>> for ComponentRecord2 {
3502 fn from_obj_ref(
3503 obj: &read_fonts::tables::gpos::ComponentRecord2,
3504 offset_data: FontData,
3505 ) -> Self {
3506 ComponentRecord2 {
3507 ligature_anchors: obj.ligature_anchors(offset_data).to_owned_table(),
3508 }
3509 }
3510}
3511
3512#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
3514#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3515pub struct MarkMarkPosFormat2 {
3516 pub mark1_coverage: OffsetMarker<CoverageTable, WIDTH_32>,
3519 pub mark2_coverage: OffsetMarker<CoverageTable, WIDTH_32>,
3522 pub mark1_array: OffsetMarker<MarkArray2, WIDTH_32>,
3525 pub mark2_array: OffsetMarker<Mark2Array2, WIDTH_32>,
3528}
3529
3530impl MarkMarkPosFormat2 {
3531 pub fn new(
3533 mark1_coverage: CoverageTable,
3534 mark2_coverage: CoverageTable,
3535 mark1_array: MarkArray2,
3536 mark2_array: Mark2Array2,
3537 ) -> Self {
3538 Self {
3539 mark1_coverage: mark1_coverage.into(),
3540 mark2_coverage: mark2_coverage.into(),
3541 mark1_array: mark1_array.into(),
3542 mark2_array: mark2_array.into(),
3543 }
3544 }
3545}
3546
3547impl FontWrite for MarkMarkPosFormat2 {
3548 #[allow(clippy::unnecessary_cast)]
3549 fn write_into(&self, writer: &mut TableWriter) {
3550 (2 as u16).write_into(writer);
3551 self.mark1_coverage.write_into(writer);
3552 self.mark2_coverage.write_into(writer);
3553 (self.compute_mark_class_count() as u16).write_into(writer);
3554 self.mark1_array.write_into(writer);
3555 self.mark2_array.write_into(writer);
3556 }
3557 fn table_type(&self) -> TableType {
3558 TableType::Named("MarkMarkPosFormat2")
3559 }
3560}
3561
3562impl Validate for MarkMarkPosFormat2 {
3563 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3564 ctx.in_table("MarkMarkPosFormat2", |ctx| {
3565 ctx.in_field("mark1_coverage", |ctx| {
3566 self.mark1_coverage.validate_impl(ctx);
3567 });
3568 ctx.in_field("mark2_coverage", |ctx| {
3569 self.mark2_coverage.validate_impl(ctx);
3570 });
3571 ctx.in_field("mark1_array", |ctx| {
3572 self.mark1_array.validate_impl(ctx);
3573 });
3574 ctx.in_field("mark2_array", |ctx| {
3575 self.mark2_array.validate_impl(ctx);
3576 });
3577 self.check_class_dimensions(ctx);
3578 })
3579 }
3580}
3581
3582impl<'a> FromObjRef<read_fonts::tables::gpos::MarkMarkPosFormat2<'a>> for MarkMarkPosFormat2 {
3583 fn from_obj_ref(obj: &read_fonts::tables::gpos::MarkMarkPosFormat2<'a>, _: FontData) -> Self {
3584 MarkMarkPosFormat2 {
3585 mark1_coverage: obj.mark1_coverage().to_owned_table(),
3586 mark2_coverage: obj.mark2_coverage().to_owned_table(),
3587 mark1_array: obj.mark1_array().to_owned_table(),
3588 mark2_array: obj.mark2_array().to_owned_table(),
3589 }
3590 }
3591}
3592
3593#[allow(clippy::needless_lifetimes)]
3594impl<'a> FromTableRef<read_fonts::tables::gpos::MarkMarkPosFormat2<'a>> for MarkMarkPosFormat2 {}
3595
3596impl ReadArgs for MarkMarkPosFormat2 {
3597 type Args = ();
3598}
3599
3600impl<'a> FontRead<'a> for MarkMarkPosFormat2 {
3601 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3602 <read_fonts::tables::gpos::MarkMarkPosFormat2 as FontRead>::read(data)
3603 .map(|x| x.to_owned_table())
3604 }
3605}
3606
3607#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
3609#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3610pub struct Mark2Array2 {
3611 pub mark2_records: Vec<Mark2Record2>,
3613}
3614
3615impl Mark2Array2 {
3616 pub fn new(mark2_records: Vec<Mark2Record2>) -> Self {
3618 Self { mark2_records }
3619 }
3620}
3621
3622impl FontWrite for Mark2Array2 {
3623 #[allow(clippy::unnecessary_cast)]
3624 fn write_into(&self, writer: &mut TableWriter) {
3625 (u16::try_from(array_len(&self.mark2_records)).unwrap()).write_into(writer);
3626 self.mark2_records.write_into(writer);
3627 }
3628 fn table_type(&self) -> TableType {
3629 TableType::Named("Mark2Array2")
3630 }
3631}
3632
3633impl Validate for Mark2Array2 {
3634 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3635 ctx.in_table("Mark2Array2", |ctx| {
3636 ctx.in_field("mark2_records", |ctx| {
3637 if self.mark2_records.len() > to_usize(u16::MAX) {
3638 ctx.report("array exceeds max length");
3639 }
3640 self.mark2_records.validate_impl(ctx);
3641 });
3642 })
3643 }
3644}
3645
3646impl<'a> FromObjRef<read_fonts::tables::gpos::Mark2Array2<'a>> for Mark2Array2 {
3647 fn from_obj_ref(obj: &read_fonts::tables::gpos::Mark2Array2<'a>, _: FontData) -> Self {
3648 let offset_data = obj.offset_data();
3649 Mark2Array2 {
3650 mark2_records: obj
3651 .mark2_records()
3652 .iter()
3653 .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
3654 .collect(),
3655 }
3656 }
3657}
3658
3659#[allow(clippy::needless_lifetimes)]
3660impl<'a> FromTableRef<read_fonts::tables::gpos::Mark2Array2<'a>> for Mark2Array2 {}
3661
3662#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
3664#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3665pub struct Mark2Record2 {
3666 pub mark2_anchors: Vec<NullableOffsetMarker<AnchorTable, WIDTH_24>>,
3670}
3671
3672impl Mark2Record2 {
3673 pub fn new(mark2_anchors: Vec<Option<AnchorTable>>) -> Self {
3675 Self {
3676 mark2_anchors: mark2_anchors.into_iter().map(Into::into).collect(),
3677 }
3678 }
3679}
3680
3681impl FontWrite for Mark2Record2 {
3682 fn write_into(&self, writer: &mut TableWriter) {
3683 self.mark2_anchors.write_into(writer);
3684 }
3685 fn table_type(&self) -> TableType {
3686 TableType::Named("Mark2Record2")
3687 }
3688}
3689
3690impl Validate for Mark2Record2 {
3691 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3692 ctx.in_table("Mark2Record2", |ctx| {
3693 ctx.in_field("mark2_anchors", |ctx| {
3694 if self.mark2_anchors.len() > to_usize(u16::MAX) {
3695 ctx.report("array exceeds max length");
3696 }
3697 self.mark2_anchors.validate_impl(ctx);
3698 });
3699 })
3700 }
3701}
3702
3703impl FromObjRef<read_fonts::tables::gpos::Mark2Record2<'_>> for Mark2Record2 {
3704 fn from_obj_ref(obj: &read_fonts::tables::gpos::Mark2Record2, offset_data: FontData) -> Self {
3705 Mark2Record2 {
3706 mark2_anchors: obj.mark2_anchors(offset_data).to_owned_table(),
3707 }
3708 }
3709}
3710
3711#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
3713#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3714pub struct MarkArray2 {
3715 pub mark_records: Vec<MarkRecord2>,
3718}
3719
3720impl MarkArray2 {
3721 pub fn new(mark_records: Vec<MarkRecord2>) -> Self {
3723 Self { mark_records }
3724 }
3725}
3726
3727impl FontWrite for MarkArray2 {
3728 #[allow(clippy::unnecessary_cast)]
3729 fn write_into(&self, writer: &mut TableWriter) {
3730 (Uint24::try_from(array_len(&self.mark_records)).unwrap()).write_into(writer);
3731 self.mark_records.write_into(writer);
3732 }
3733 fn table_type(&self) -> TableType {
3734 TableType::Named("MarkArray2")
3735 }
3736}
3737
3738impl Validate for MarkArray2 {
3739 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3740 ctx.in_table("MarkArray2", |ctx| {
3741 ctx.in_field("mark_records", |ctx| {
3742 if self.mark_records.len() > to_usize(Uint24::MAX) {
3743 ctx.report("array exceeds max length");
3744 }
3745 self.mark_records.validate_impl(ctx);
3746 });
3747 self.check_class_count(ctx);
3748 })
3749 }
3750}
3751
3752impl<'a> FromObjRef<read_fonts::tables::gpos::MarkArray2<'a>> for MarkArray2 {
3753 fn from_obj_ref(obj: &read_fonts::tables::gpos::MarkArray2<'a>, _: FontData) -> Self {
3754 let offset_data = obj.offset_data();
3755 MarkArray2 {
3756 mark_records: obj.mark_records().to_owned_obj(offset_data),
3757 }
3758 }
3759}
3760
3761#[allow(clippy::needless_lifetimes)]
3762impl<'a> FromTableRef<read_fonts::tables::gpos::MarkArray2<'a>> for MarkArray2 {}
3763
3764impl ReadArgs for MarkArray2 {
3765 type Args = ();
3766}
3767
3768impl<'a> FontRead<'a> for MarkArray2 {
3769 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3770 <read_fonts::tables::gpos::MarkArray2 as FontRead>::read(data).map(|x| x.to_owned_table())
3771 }
3772}
3773
3774#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
3776#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3777pub struct MarkRecord2 {
3778 pub mark_class: u16,
3780 pub mark_anchor: OffsetMarker<AnchorTable, WIDTH_24>,
3782}
3783
3784impl MarkRecord2 {
3785 pub fn new(mark_class: u16, mark_anchor: AnchorTable) -> Self {
3787 Self {
3788 mark_class,
3789 mark_anchor: mark_anchor.into(),
3790 }
3791 }
3792}
3793
3794impl FontWrite for MarkRecord2 {
3795 fn write_into(&self, writer: &mut TableWriter) {
3796 self.mark_class.write_into(writer);
3797 self.mark_anchor.write_into(writer);
3798 }
3799 fn table_type(&self) -> TableType {
3800 TableType::Named("MarkRecord2")
3801 }
3802}
3803
3804impl Validate for MarkRecord2 {
3805 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3806 ctx.in_table("MarkRecord2", |ctx| {
3807 ctx.in_field("mark_anchor", |ctx| {
3808 self.mark_anchor.validate_impl(ctx);
3809 });
3810 })
3811 }
3812}
3813
3814impl FromObjRef<read_fonts::tables::gpos::MarkRecord2> for MarkRecord2 {
3815 fn from_obj_ref(obj: &read_fonts::tables::gpos::MarkRecord2, offset_data: FontData) -> Self {
3816 MarkRecord2 {
3817 mark_class: obj.mark_class(),
3818 mark_anchor: obj.mark_anchor(offset_data).to_owned_table(),
3819 }
3820 }
3821}
3822
3823#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
3825#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3826pub enum CursivePos {
3827 Format1(CursivePosFormat1),
3828 Format2(CursivePosFormat2),
3829}
3830
3831impl CursivePos {
3832 pub fn format_1(coverage: CoverageTable, entry_exit_record: Vec<EntryExitRecord>) -> Self {
3834 Self::Format1(CursivePosFormat1::new(coverage, entry_exit_record))
3835 }
3836
3837 pub fn format_2(coverage: CoverageTable, entry_exit_record: Vec<EntryExitRecord2>) -> Self {
3839 Self::Format2(CursivePosFormat2::new(coverage, entry_exit_record))
3840 }
3841}
3842
3843impl Default for CursivePos {
3844 fn default() -> Self {
3845 Self::Format1(Default::default())
3846 }
3847}
3848
3849impl FontWrite for CursivePos {
3850 fn write_into(&self, writer: &mut TableWriter) {
3851 match self {
3852 Self::Format1(item) => item.write_into(writer),
3853 Self::Format2(item) => item.write_into(writer),
3854 }
3855 }
3856 fn table_type(&self) -> TableType {
3857 match self {
3858 Self::Format1(item) => item.table_type(),
3859 Self::Format2(item) => item.table_type(),
3860 }
3861 }
3862}
3863
3864impl Validate for CursivePos {
3865 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3866 match self {
3867 Self::Format1(item) => item.validate_impl(ctx),
3868 Self::Format2(item) => item.validate_impl(ctx),
3869 }
3870 }
3871}
3872
3873impl FromObjRef<read_fonts::tables::gpos::CursivePos<'_>> for CursivePos {
3874 fn from_obj_ref(obj: &read_fonts::tables::gpos::CursivePos, _: FontData) -> Self {
3875 use read_fonts::tables::gpos::CursivePos as ObjRefType;
3876 match obj {
3877 ObjRefType::Format1(item) => CursivePos::Format1(item.to_owned_table()),
3878 ObjRefType::Format2(item) => CursivePos::Format2(item.to_owned_table()),
3879 }
3880 }
3881}
3882
3883impl FromTableRef<read_fonts::tables::gpos::CursivePos<'_>> for CursivePos {}
3884
3885impl ReadArgs for CursivePos {
3886 type Args = ();
3887}
3888
3889impl<'a> FontRead<'a> for CursivePos {
3890 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3891 <read_fonts::tables::gpos::CursivePos as FontRead>::read(data).map(|x| x.to_owned_table())
3892 }
3893}
3894
3895impl From<CursivePosFormat1> for CursivePos {
3896 fn from(src: CursivePosFormat1) -> CursivePos {
3897 CursivePos::Format1(src)
3898 }
3899}
3900
3901impl From<CursivePosFormat2> for CursivePos {
3902 fn from(src: CursivePosFormat2) -> CursivePos {
3903 CursivePos::Format2(src)
3904 }
3905}
3906
3907#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
3909#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3910pub enum MarkBasePos {
3911 Format1(MarkBasePosFormat1),
3912 Format2(MarkBasePosFormat2),
3913}
3914
3915impl MarkBasePos {
3916 pub fn format_1(
3918 mark_coverage: CoverageTable,
3919 base_coverage: CoverageTable,
3920 mark_array: MarkArray,
3921 base_array: BaseArray,
3922 ) -> Self {
3923 Self::Format1(MarkBasePosFormat1::new(
3924 mark_coverage,
3925 base_coverage,
3926 mark_array,
3927 base_array,
3928 ))
3929 }
3930
3931 pub fn format_2(
3933 mark_coverage: CoverageTable,
3934 base_coverage: CoverageTable,
3935 mark_array: MarkArray2,
3936 base_array: BaseArray2,
3937 ) -> Self {
3938 Self::Format2(MarkBasePosFormat2::new(
3939 mark_coverage,
3940 base_coverage,
3941 mark_array,
3942 base_array,
3943 ))
3944 }
3945}
3946
3947impl Default for MarkBasePos {
3948 fn default() -> Self {
3949 Self::Format1(Default::default())
3950 }
3951}
3952
3953impl FontWrite for MarkBasePos {
3954 fn write_into(&self, writer: &mut TableWriter) {
3955 match self {
3956 Self::Format1(item) => item.write_into(writer),
3957 Self::Format2(item) => item.write_into(writer),
3958 }
3959 }
3960 fn table_type(&self) -> TableType {
3961 match self {
3962 Self::Format1(item) => item.table_type(),
3963 Self::Format2(item) => item.table_type(),
3964 }
3965 }
3966}
3967
3968impl Validate for MarkBasePos {
3969 fn validate_impl(&self, ctx: &mut ValidationCtx) {
3970 match self {
3971 Self::Format1(item) => item.validate_impl(ctx),
3972 Self::Format2(item) => item.validate_impl(ctx),
3973 }
3974 }
3975}
3976
3977impl FromObjRef<read_fonts::tables::gpos::MarkBasePos<'_>> for MarkBasePos {
3978 fn from_obj_ref(obj: &read_fonts::tables::gpos::MarkBasePos, _: FontData) -> Self {
3979 use read_fonts::tables::gpos::MarkBasePos as ObjRefType;
3980 match obj {
3981 ObjRefType::Format1(item) => MarkBasePos::Format1(item.to_owned_table()),
3982 ObjRefType::Format2(item) => MarkBasePos::Format2(item.to_owned_table()),
3983 }
3984 }
3985}
3986
3987impl FromTableRef<read_fonts::tables::gpos::MarkBasePos<'_>> for MarkBasePos {}
3988
3989impl ReadArgs for MarkBasePos {
3990 type Args = ();
3991}
3992
3993impl<'a> FontRead<'a> for MarkBasePos {
3994 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3995 <read_fonts::tables::gpos::MarkBasePos as FontRead>::read(data).map(|x| x.to_owned_table())
3996 }
3997}
3998
3999impl From<MarkBasePosFormat1> for MarkBasePos {
4000 fn from(src: MarkBasePosFormat1) -> MarkBasePos {
4001 MarkBasePos::Format1(src)
4002 }
4003}
4004
4005impl From<MarkBasePosFormat2> for MarkBasePos {
4006 fn from(src: MarkBasePosFormat2) -> MarkBasePos {
4007 MarkBasePos::Format2(src)
4008 }
4009}
4010
4011#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
4013#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4014pub enum MarkLigPos {
4015 Format1(MarkLigPosFormat1),
4016 Format2(MarkLigPosFormat2),
4017}
4018
4019impl MarkLigPos {
4020 pub fn format_1(
4022 mark_coverage: CoverageTable,
4023 ligature_coverage: CoverageTable,
4024 mark_array: MarkArray,
4025 ligature_array: LigatureArray,
4026 ) -> Self {
4027 Self::Format1(MarkLigPosFormat1::new(
4028 mark_coverage,
4029 ligature_coverage,
4030 mark_array,
4031 ligature_array,
4032 ))
4033 }
4034
4035 pub fn format_2(
4037 mark_coverage: CoverageTable,
4038 ligature_coverage: CoverageTable,
4039 mark_array: MarkArray2,
4040 ligature_array: LigatureArray2,
4041 ) -> Self {
4042 Self::Format2(MarkLigPosFormat2::new(
4043 mark_coverage,
4044 ligature_coverage,
4045 mark_array,
4046 ligature_array,
4047 ))
4048 }
4049}
4050
4051impl Default for MarkLigPos {
4052 fn default() -> Self {
4053 Self::Format1(Default::default())
4054 }
4055}
4056
4057impl FontWrite for MarkLigPos {
4058 fn write_into(&self, writer: &mut TableWriter) {
4059 match self {
4060 Self::Format1(item) => item.write_into(writer),
4061 Self::Format2(item) => item.write_into(writer),
4062 }
4063 }
4064 fn table_type(&self) -> TableType {
4065 match self {
4066 Self::Format1(item) => item.table_type(),
4067 Self::Format2(item) => item.table_type(),
4068 }
4069 }
4070}
4071
4072impl Validate for MarkLigPos {
4073 fn validate_impl(&self, ctx: &mut ValidationCtx) {
4074 match self {
4075 Self::Format1(item) => item.validate_impl(ctx),
4076 Self::Format2(item) => item.validate_impl(ctx),
4077 }
4078 }
4079}
4080
4081impl FromObjRef<read_fonts::tables::gpos::MarkLigPos<'_>> for MarkLigPos {
4082 fn from_obj_ref(obj: &read_fonts::tables::gpos::MarkLigPos, _: FontData) -> Self {
4083 use read_fonts::tables::gpos::MarkLigPos as ObjRefType;
4084 match obj {
4085 ObjRefType::Format1(item) => MarkLigPos::Format1(item.to_owned_table()),
4086 ObjRefType::Format2(item) => MarkLigPos::Format2(item.to_owned_table()),
4087 }
4088 }
4089}
4090
4091impl FromTableRef<read_fonts::tables::gpos::MarkLigPos<'_>> for MarkLigPos {}
4092
4093impl ReadArgs for MarkLigPos {
4094 type Args = ();
4095}
4096
4097impl<'a> FontRead<'a> for MarkLigPos {
4098 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4099 <read_fonts::tables::gpos::MarkLigPos as FontRead>::read(data).map(|x| x.to_owned_table())
4100 }
4101}
4102
4103impl From<MarkLigPosFormat1> for MarkLigPos {
4104 fn from(src: MarkLigPosFormat1) -> MarkLigPos {
4105 MarkLigPos::Format1(src)
4106 }
4107}
4108
4109impl From<MarkLigPosFormat2> for MarkLigPos {
4110 fn from(src: MarkLigPosFormat2) -> MarkLigPos {
4111 MarkLigPos::Format2(src)
4112 }
4113}
4114
4115#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
4117#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4118pub enum MarkMarkPos {
4119 Format1(MarkMarkPosFormat1),
4120 Format2(MarkMarkPosFormat2),
4121}
4122
4123impl MarkMarkPos {
4124 pub fn format_1(
4126 mark1_coverage: CoverageTable,
4127 mark2_coverage: CoverageTable,
4128 mark1_array: MarkArray,
4129 mark2_array: Mark2Array,
4130 ) -> Self {
4131 Self::Format1(MarkMarkPosFormat1::new(
4132 mark1_coverage,
4133 mark2_coverage,
4134 mark1_array,
4135 mark2_array,
4136 ))
4137 }
4138
4139 pub fn format_2(
4141 mark1_coverage: CoverageTable,
4142 mark2_coverage: CoverageTable,
4143 mark1_array: MarkArray2,
4144 mark2_array: Mark2Array2,
4145 ) -> Self {
4146 Self::Format2(MarkMarkPosFormat2::new(
4147 mark1_coverage,
4148 mark2_coverage,
4149 mark1_array,
4150 mark2_array,
4151 ))
4152 }
4153}
4154
4155impl Default for MarkMarkPos {
4156 fn default() -> Self {
4157 Self::Format1(Default::default())
4158 }
4159}
4160
4161impl FontWrite for MarkMarkPos {
4162 fn write_into(&self, writer: &mut TableWriter) {
4163 match self {
4164 Self::Format1(item) => item.write_into(writer),
4165 Self::Format2(item) => item.write_into(writer),
4166 }
4167 }
4168 fn table_type(&self) -> TableType {
4169 match self {
4170 Self::Format1(item) => item.table_type(),
4171 Self::Format2(item) => item.table_type(),
4172 }
4173 }
4174}
4175
4176impl Validate for MarkMarkPos {
4177 fn validate_impl(&self, ctx: &mut ValidationCtx) {
4178 match self {
4179 Self::Format1(item) => item.validate_impl(ctx),
4180 Self::Format2(item) => item.validate_impl(ctx),
4181 }
4182 }
4183}
4184
4185impl FromObjRef<read_fonts::tables::gpos::MarkMarkPos<'_>> for MarkMarkPos {
4186 fn from_obj_ref(obj: &read_fonts::tables::gpos::MarkMarkPos, _: FontData) -> Self {
4187 use read_fonts::tables::gpos::MarkMarkPos as ObjRefType;
4188 match obj {
4189 ObjRefType::Format1(item) => MarkMarkPos::Format1(item.to_owned_table()),
4190 ObjRefType::Format2(item) => MarkMarkPos::Format2(item.to_owned_table()),
4191 }
4192 }
4193}
4194
4195impl FromTableRef<read_fonts::tables::gpos::MarkMarkPos<'_>> for MarkMarkPos {}
4196
4197impl ReadArgs for MarkMarkPos {
4198 type Args = ();
4199}
4200
4201impl<'a> FontRead<'a> for MarkMarkPos {
4202 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4203 <read_fonts::tables::gpos::MarkMarkPos as FontRead>::read(data).map(|x| x.to_owned_table())
4204 }
4205}
4206
4207impl From<MarkMarkPosFormat1> for MarkMarkPos {
4208 fn from(src: MarkMarkPosFormat1) -> MarkMarkPos {
4209 MarkMarkPos::Format1(src)
4210 }
4211}
4212
4213impl From<MarkMarkPosFormat2> for MarkMarkPos {
4214 fn from(src: MarkMarkPosFormat2) -> MarkMarkPos {
4215 MarkMarkPos::Format2(src)
4216 }
4217}