Coverage Report

Created: 2025-09-27 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fontations/klippa/src/base.rs
Line
Count
Source
1
//! impl subset() for hmtx
2
3
use crate::{
4
    offset::{SerializeCopy, SerializeSubset},
5
    offset_array::SubsetOffsetArray,
6
    serialize::{SerializeErrorFlags, Serializer},
7
    CollectVariationIndices, Plan, Subset, SubsetError, SubsetTable,
8
};
9
use write_fonts::{
10
    read::{
11
        collections::IntSet,
12
        tables::base::{
13
            Axis, Base, BaseCoord, BaseCoordFormat1, BaseCoordFormat2, BaseCoordFormat3,
14
            BaseLangSysRecord, BaseScript, BaseScriptList, BaseScriptRecord, BaseValues,
15
            FeatMinMaxRecord, MinMax,
16
        },
17
        FontData, FontRef, TopLevelTable,
18
    },
19
    types::{GlyphId, MajorMinor, Offset16, Offset32},
20
    FontBuilder,
21
};
22
23
// reference: subset() for BASE in harfbuzz
24
// <https://github.com/harfbuzz/harfbuzz/blob/fc42cdd68df0ce710b507981184ade7bf1b164e6/src/hb-ot-layout-base-table.hh#L763>
25
impl Subset for Base<'_> {
26
0
    fn subset(
27
0
        &self,
28
0
        plan: &Plan,
29
0
        _font: &FontRef,
30
0
        s: &mut Serializer,
31
0
        _builder: &mut FontBuilder,
32
0
    ) -> Result<(), SubsetError> {
33
0
        s.embed(self.version())
34
0
            .map_err(|_| SubsetError::SubsetTableError(Base::TAG))?;
35
36
        //hAxis offset
37
0
        let haxis_offset_pos = s
38
0
            .embed(0_u16)
39
0
            .map_err(|_| SubsetError::SubsetTableError(Base::TAG))?;
40
41
0
        if !self.horiz_axis_offset().is_null() {
42
0
            let Some(Ok(h_axis)) = self.horiz_axis() else {
43
0
                return Err(SubsetError::SubsetTableError(Base::TAG));
44
            };
45
46
0
            Offset16::serialize_subset(&h_axis, s, plan, (), haxis_offset_pos)
47
0
                .map_err(|_| SubsetError::SubsetTableError(Base::TAG))?;
48
0
        }
49
50
        //vertAxis offset
51
0
        let vaxis_offset_pos = s
52
0
            .embed(0_u16)
53
0
            .map_err(|_| SubsetError::SubsetTableError(Base::TAG))?;
54
55
0
        if !self.vert_axis_offset().is_null() {
56
0
            let Some(Ok(v_axis)) = self.vert_axis() else {
57
0
                return Err(SubsetError::SubsetTableError(Base::TAG));
58
            };
59
60
0
            Offset16::serialize_subset(&v_axis, s, plan, (), vaxis_offset_pos)
61
0
                .map_err(|_| SubsetError::SubsetTableError(Base::TAG))?;
62
0
        }
63
64
        //itemVarStore offset
65
0
        match self.item_var_store() {
66
0
            Some(Ok(var_store)) => {
67
0
                let varstore_offset_pos = s
68
0
                    .embed(0_u32)
69
0
                    .map_err(|_| SubsetError::SubsetTableError(Base::TAG))?;
70
71
0
                Offset32::serialize_subset(
72
0
                    &var_store,
73
0
                    s,
74
0
                    plan,
75
0
                    &plan.base_varstore_inner_maps,
76
0
                    varstore_offset_pos,
77
                )
78
0
                .map_err(|_| SubsetError::SubsetTableError(Base::TAG))?;
79
0
                Ok(())
80
            }
81
            None => {
82
0
                if self.version().minor > 0 {
83
0
                    s.copy_assign(0, MajorMinor::new(1, 0));
84
0
                }
85
0
                Ok(())
86
            }
87
0
            Some(Err(_)) => Err(SubsetError::SubsetTableError(Base::TAG)),
88
        }
89
0
    }
90
}
91
92
impl SubsetTable<'_> for Axis<'_> {
93
    type ArgsForSubset = ();
94
    type Output = ();
95
0
    fn subset(
96
0
        &self,
97
0
        plan: &Plan,
98
0
        s: &mut Serializer,
99
0
        _args: (),
100
0
    ) -> Result<(), SerializeErrorFlags> {
101
0
        let base_taglist_offset_pos = s.embed(0_u16)?;
102
0
        let base_scriptlist_offset_pos = s.embed(0_u16)?;
103
104
0
        if !self.base_tag_list_offset().is_null() {
105
0
            let Some(Ok(base_taglist)) = self.base_tag_list() else {
106
0
                return Err(SerializeErrorFlags::SERIALIZE_ERROR_READ_ERROR);
107
            };
108
0
            Offset16::serialize_copy(&base_taglist, s, base_taglist_offset_pos)?;
109
0
        }
110
111
0
        let Ok(base_scriptlist) = self.base_script_list() else {
112
0
            return Err(SerializeErrorFlags::SERIALIZE_ERROR_READ_ERROR);
113
        };
114
0
        Offset16::serialize_subset(&base_scriptlist, s, plan, (), base_scriptlist_offset_pos)
115
0
    }
116
}
117
118
impl SubsetTable<'_> for BaseScriptList<'_> {
119
    type ArgsForSubset = ();
120
    type Output = ();
121
122
0
    fn subset(
123
0
        &self,
124
0
        plan: &Plan,
125
0
        s: &mut Serializer,
126
0
        _args: (),
127
0
    ) -> Result<(), SerializeErrorFlags> {
128
0
        let script_count_pos = s.embed(0_u16)?;
129
0
        let mut count: usize = 0;
130
0
        for script_record in self.base_script_records().iter() {
131
0
            let script_tag = script_record.base_script_tag();
132
0
            if !plan.layout_scripts.contains(script_tag) {
133
0
                continue;
134
0
            }
135
136
0
            script_record.subset(plan, s, self.offset_data())?;
137
0
            count += 1;
138
        }
139
0
        s.check_assign::<u16>(
140
0
            script_count_pos,
141
0
            count,
142
            SerializeErrorFlags::SERIALIZE_ERROR_INT_OVERFLOW,
143
        )
144
0
    }
145
}
146
147
impl<'a> SubsetTable<'a> for BaseScriptRecord {
148
    type ArgsForSubset = FontData<'a>;
149
    type Output = ();
150
151
0
    fn subset(
152
0
        &self,
153
0
        plan: &Plan,
154
0
        s: &mut Serializer,
155
0
        data: FontData,
156
0
    ) -> Result<(), SerializeErrorFlags> {
157
0
        s.embed(self.base_script_tag())?;
158
0
        let base_script_offset_pos = s.embed(0_u16)?;
159
0
        let Ok(base_script) = self.base_script(data) else {
160
0
            return Err(SerializeErrorFlags::SERIALIZE_ERROR_READ_ERROR);
161
        };
162
0
        Offset16::serialize_subset(&base_script, s, plan, (), base_script_offset_pos)
163
0
    }
164
}
165
166
impl SubsetTable<'_> for BaseScript<'_> {
167
    type ArgsForSubset = ();
168
    type Output = ();
169
170
0
    fn subset(
171
0
        &self,
172
0
        plan: &Plan,
173
0
        s: &mut Serializer,
174
0
        _args: Self::ArgsForSubset,
175
0
    ) -> Result<(), SerializeErrorFlags> {
176
0
        let base_values_offset_pos = s.embed(0_u16)?;
177
0
        if !self.base_values_offset().is_null() {
178
0
            let Some(Ok(base_value)) = self.base_values() else {
179
0
                return Err(SerializeErrorFlags::SERIALIZE_ERROR_READ_ERROR);
180
            };
181
0
            Offset16::serialize_subset(&base_value, s, plan, (), base_values_offset_pos)?;
182
0
        }
183
184
0
        let default_min_max_offset_pos = s.embed(0_u16)?;
185
0
        if !self.default_min_max_offset().is_null() {
186
0
            let Some(Ok(default_min_max)) = self.default_min_max() else {
187
0
                return Err(SerializeErrorFlags::SERIALIZE_ERROR_READ_ERROR);
188
            };
189
0
            Offset16::serialize_subset(&default_min_max, s, plan, (), default_min_max_offset_pos)?;
190
0
        }
191
192
0
        s.embed(self.base_lang_sys_count())?;
193
194
0
        for record in self.base_lang_sys_records().iter() {
195
0
            record.subset(plan, s, self.offset_data())?;
196
        }
197
0
        Ok(())
198
0
    }
199
}
200
201
impl SubsetTable<'_> for BaseValues<'_> {
202
    type ArgsForSubset = ();
203
    type Output = ();
204
205
0
    fn subset(
206
0
        &self,
207
0
        plan: &Plan,
208
0
        s: &mut Serializer,
209
0
        _args: Self::ArgsForSubset,
210
0
    ) -> Result<(), SerializeErrorFlags> {
211
0
        s.embed(self.default_baseline_index())?;
212
        // base_coord count
213
0
        let mut base_coord_count: u16 = 0;
214
0
        let count_pos = s.embed(base_coord_count)?;
215
216
0
        let org_num_base_coords = self.base_coord_count() as usize;
217
0
        let base_coords = self.base_coords();
218
0
        for idx in 0..org_num_base_coords {
219
0
            base_coords.subset_offset(idx, s, plan, ())?;
220
0
            base_coord_count += 1;
221
        }
222
0
        s.copy_assign(count_pos, base_coord_count);
223
0
        Ok(())
224
0
    }
225
}
226
227
impl SubsetTable<'_> for MinMax<'_> {
228
    type ArgsForSubset = ();
229
    type Output = ();
230
231
0
    fn subset(
232
0
        &self,
233
0
        plan: &Plan,
234
0
        s: &mut Serializer,
235
0
        _args: Self::ArgsForSubset,
236
0
    ) -> Result<(), SerializeErrorFlags> {
237
0
        let min_coord_offset_pos = s.embed(0_u16)?;
238
0
        if !self.min_coord_offset().is_null() {
239
0
            let Some(Ok(min_coord)) = self.min_coord() else {
240
0
                return Err(SerializeErrorFlags::SERIALIZE_ERROR_READ_ERROR);
241
            };
242
0
            Offset16::serialize_subset(&min_coord, s, plan, (), min_coord_offset_pos)?;
243
0
        }
244
245
0
        let max_coord_offset_pos = s.embed(0_u16)?;
246
0
        if !self.max_coord_offset().is_null() {
247
0
            let Some(Ok(max_coord)) = self.max_coord() else {
248
0
                return Err(SerializeErrorFlags::SERIALIZE_ERROR_READ_ERROR);
249
            };
250
0
            Offset16::serialize_subset(&max_coord, s, plan, (), max_coord_offset_pos)?;
251
0
        }
252
253
0
        let feat_min_max_count_pos = s.embed(0_u16)?;
254
0
        let mut count: u16 = 0;
255
0
        for record in self.feat_min_max_records().iter() {
256
0
            let feature_tag = record.feature_table_tag();
257
0
            if !plan.layout_features.contains(feature_tag) {
258
0
                continue;
259
0
            }
260
0
            record.subset(plan, s, self.offset_data())?;
261
0
            count += 1;
262
        }
263
0
        s.copy_assign(feat_min_max_count_pos, count);
264
0
        Ok(())
265
0
    }
266
}
267
268
impl<'a> SubsetTable<'a> for FeatMinMaxRecord {
269
    type ArgsForSubset = FontData<'a>;
270
    type Output = ();
271
272
0
    fn subset(
273
0
        &self,
274
0
        plan: &Plan,
275
0
        s: &mut Serializer,
276
0
        data: FontData,
277
0
    ) -> Result<(), SerializeErrorFlags> {
278
0
        s.embed(self.feature_table_tag())?;
279
280
0
        let min_coord_offset_pos = s.embed(0_u16)?;
281
0
        if !self.min_coord_offset().is_null() {
282
0
            let Some(Ok(min_coord)) = self.min_coord(data) else {
283
0
                return Err(SerializeErrorFlags::SERIALIZE_ERROR_READ_ERROR);
284
            };
285
0
            Offset16::serialize_subset(&min_coord, s, plan, (), min_coord_offset_pos)?;
286
0
        }
287
288
0
        let max_coord_offset_pos = s.embed(0_u16)?;
289
0
        if !self.max_coord_offset().is_null() {
290
0
            let Some(Ok(max_coord)) = self.max_coord(data) else {
291
0
                return Err(SerializeErrorFlags::SERIALIZE_ERROR_READ_ERROR);
292
            };
293
0
            Offset16::serialize_subset(&max_coord, s, plan, (), max_coord_offset_pos)?;
294
0
        }
295
0
        Ok(())
296
0
    }
297
}
298
299
impl<'a> SubsetTable<'a> for BaseLangSysRecord {
300
    type ArgsForSubset = FontData<'a>;
301
    type Output = ();
302
303
0
    fn subset(
304
0
        &self,
305
0
        plan: &Plan,
306
0
        s: &mut Serializer,
307
0
        data: FontData,
308
0
    ) -> Result<(), SerializeErrorFlags> {
309
0
        s.embed(self.base_lang_sys_tag())?;
310
311
0
        let min_max_offset_pos = s.embed(0_u16)?;
312
0
        let Ok(min_max) = self.min_max(data) else {
313
0
            return Err(SerializeErrorFlags::SERIALIZE_ERROR_READ_ERROR);
314
        };
315
0
        Offset16::serialize_subset(&min_max, s, plan, (), min_max_offset_pos)
316
0
    }
317
}
318
319
impl SubsetTable<'_> for BaseCoord<'_> {
320
    type ArgsForSubset = ();
321
    type Output = ();
322
0
    fn subset(
323
0
        &self,
324
0
        plan: &Plan,
325
0
        s: &mut Serializer,
326
0
        _args: Self::ArgsForSubset,
327
0
    ) -> Result<(), SerializeErrorFlags> {
328
0
        match self {
329
0
            Self::Format1(item) => item.subset(plan, s, ()),
330
0
            Self::Format2(item) => item.subset(plan, s, ()),
331
0
            Self::Format3(item) => item.subset(plan, s, ()),
332
        }
333
0
    }
334
}
335
336
impl SubsetTable<'_> for BaseCoordFormat1<'_> {
337
    type ArgsForSubset = ();
338
    type Output = ();
339
0
    fn subset(
340
0
        &self,
341
0
        _plan: &Plan,
342
0
        s: &mut Serializer,
343
0
        _args: Self::ArgsForSubset,
344
0
    ) -> Result<(), SerializeErrorFlags> {
345
0
        s.embed_bytes(self.min_table_bytes()).map(|_| ())
346
0
    }
347
}
348
349
impl SubsetTable<'_> for BaseCoordFormat2<'_> {
350
    type ArgsForSubset = ();
351
    type Output = ();
352
0
    fn subset(
353
0
        &self,
354
0
        plan: &Plan,
355
0
        s: &mut Serializer,
356
0
        _args: Self::ArgsForSubset,
357
0
    ) -> Result<(), SerializeErrorFlags> {
358
0
        s.embed_bytes(self.min_table_bytes())?;
359
0
        let Some(new_gid) = plan.glyph_map.get(&GlyphId::from(self.reference_glyph())) else {
360
0
            return Err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER);
361
        };
362
0
        s.check_assign::<u16>(
363
            4,
364
0
            new_gid.to_u32() as usize,
365
            SerializeErrorFlags::SERIALIZE_ERROR_INT_OVERFLOW,
366
        )
367
0
    }
368
}
369
370
impl SubsetTable<'_> for BaseCoordFormat3<'_> {
371
    type ArgsForSubset = ();
372
    type Output = ();
373
374
0
    fn subset(
375
0
        &self,
376
0
        plan: &Plan,
377
0
        s: &mut Serializer,
378
0
        _args: Self::ArgsForSubset,
379
0
    ) -> Result<(), SerializeErrorFlags> {
380
0
        s.embed(self.base_coord_format())?;
381
0
        s.embed(self.coordinate())?;
382
383
0
        let device_offset_pos = s.embed(0_u16)?;
384
0
        if !self.device_offset().is_null() {
385
0
            let Some(Ok(device)) = self.device() else {
386
0
                return Err(SerializeErrorFlags::SERIALIZE_ERROR_READ_ERROR);
387
            };
388
389
0
            Offset16::serialize_subset(
390
0
                &device,
391
0
                s,
392
0
                plan,
393
0
                &plan.base_varidx_delta_map,
394
0
                device_offset_pos,
395
0
            )?;
396
0
        }
397
0
        Ok(())
398
0
    }
399
}
400
401
impl CollectVariationIndices for Base<'_> {
402
0
    fn collect_variation_indices(&self, plan: &Plan, varidx_set: &mut IntSet<u32>) {
403
0
        if let Some(Ok(h_axis)) = self.horiz_axis() {
404
0
            h_axis.collect_variation_indices(plan, varidx_set);
405
0
        }
406
407
0
        if let Some(Ok(v_axis)) = self.vert_axis() {
408
0
            v_axis.collect_variation_indices(plan, varidx_set);
409
0
        }
410
0
    }
411
}
412
413
impl CollectVariationIndices for Axis<'_> {
414
0
    fn collect_variation_indices(&self, plan: &Plan, varidx_set: &mut IntSet<u32>) {
415
0
        let Ok(base_scriptlist) = self.base_script_list() else {
416
0
            return;
417
        };
418
0
        base_scriptlist.collect_variation_indices(plan, varidx_set);
419
0
    }
420
}
421
422
impl CollectVariationIndices for BaseScriptList<'_> {
423
0
    fn collect_variation_indices(&self, plan: &Plan, varidx_set: &mut IntSet<u32>) {
424
0
        for script_record in self.base_script_records().iter() {
425
0
            let script_tag = script_record.base_script_tag();
426
0
            if !plan.layout_scripts.contains(script_tag) {
427
0
                continue;
428
0
            }
429
430
0
            let Ok(base_script) = script_record.base_script(self.offset_data()) else {
431
0
                return;
432
            };
433
0
            base_script.collect_variation_indices(plan, varidx_set);
434
        }
435
0
    }
436
}
437
438
impl CollectVariationIndices for BaseScript<'_> {
439
0
    fn collect_variation_indices(&self, plan: &Plan, varidx_set: &mut IntSet<u32>) {
440
0
        if let Some(Ok(base_values)) = self.base_values() {
441
0
            base_values.collect_variation_indices(plan, varidx_set);
442
0
        }
443
444
0
        if let Some(Ok(default_min_max)) = self.default_min_max() {
445
0
            default_min_max.collect_variation_indices(plan, varidx_set);
446
0
        }
447
448
0
        for record in self.base_lang_sys_records().iter() {
449
0
            if let Ok(min_max) = record.min_max(self.offset_data()) {
450
0
                min_max.collect_variation_indices(plan, varidx_set);
451
0
            }
452
        }
453
0
    }
454
}
455
456
impl CollectVariationIndices for BaseValues<'_> {
457
0
    fn collect_variation_indices(&self, plan: &Plan, varidx_set: &mut IntSet<u32>) {
458
0
        for base_coord in self.base_coords().iter().flatten() {
459
0
            base_coord.collect_variation_indices(plan, varidx_set);
460
0
        }
461
0
    }
462
}
463
464
impl CollectVariationIndices for MinMax<'_> {
465
0
    fn collect_variation_indices(&self, plan: &Plan, varidx_set: &mut IntSet<u32>) {
466
0
        if let Some(Ok(min_coord)) = self.min_coord() {
467
0
            min_coord.collect_variation_indices(plan, varidx_set);
468
0
        }
469
470
0
        if let Some(Ok(max_coord)) = self.max_coord() {
471
0
            max_coord.collect_variation_indices(plan, varidx_set);
472
0
        }
473
474
0
        for record in self.feat_min_max_records().iter() {
475
0
            let feature_tag = record.feature_table_tag();
476
0
            if !plan.layout_features.contains(feature_tag) {
477
0
                continue;
478
0
            }
479
480
0
            if let Some(Ok(min_coord)) = record.min_coord(self.offset_data()) {
481
0
                min_coord.collect_variation_indices(plan, varidx_set);
482
0
            }
483
484
0
            if let Some(Ok(max_coord)) = record.max_coord(self.offset_data()) {
485
0
                max_coord.collect_variation_indices(plan, varidx_set);
486
0
            }
487
        }
488
0
    }
489
}
490
491
impl CollectVariationIndices for BaseCoord<'_> {
492
0
    fn collect_variation_indices(&self, plan: &Plan, varidx_set: &mut IntSet<u32>) {
493
0
        if let Self::Format3(item) = self {
494
0
            item.collect_variation_indices(plan, varidx_set);
495
0
        }
496
0
    }
497
}
498
499
impl CollectVariationIndices for BaseCoordFormat3<'_> {
500
0
    fn collect_variation_indices(&self, plan: &Plan, varidx_set: &mut IntSet<u32>) {
501
0
        let Some(Ok(device)) = self.device() else {
502
0
            return;
503
        };
504
0
        device.collect_variation_indices(plan, varidx_set);
505
0
    }
506
}