Skip to content

Commit

Permalink
[klippa] subset name table
Browse files Browse the repository at this point in the history
  • Loading branch information
qxliu76 committed Sep 4, 2024
1 parent 731fbd0 commit f116b9b
Show file tree
Hide file tree
Showing 196 changed files with 287 additions and 53 deletions.
4 changes: 4 additions & 0 deletions klippa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod head;
mod hmtx;
mod layout;
mod maxp;
mod name;
mod os2;
mod parsing_util;
mod post;
Expand All @@ -17,6 +18,7 @@ use glyf_loca::subset_glyf_loca;
use head::subset_head;
use hmtx::subset_hmtx_hhea;
use maxp::subset_maxp;
use name::subset_name;
use os2::subset_os2;
pub use parsing_util::{
parse_drop_tables, parse_name_ids, parse_name_languages, parse_unicodes, populate_gids,
Expand Down Expand Up @@ -541,6 +543,8 @@ fn subset_table<'a>(

Maxp::TAG => subset_maxp(font, plan, builder),

Name::TAG => subset_name(font, plan, builder),

Os2::TAG => subset_os2(font, plan, builder),

Post::TAG => subset_post(font, plan, builder),
Expand Down
123 changes: 123 additions & 0 deletions klippa/src/name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
//! impl subset() for name table

use std::cmp::Ordering;

use crate::{
Plan,
SubsetError::{self, SubsetTableError},
SubsetFlags,
};

use write_fonts::{
read::{tables::name::Name, FontRef, TableProvider, TopLevelTable},
FontBuilder,
};

// reference: subset() for name table in harfbuzz
// https://github.com/harfbuzz/harfbuzz/blob/main/src/OT/name/name.hh#L387
pub(crate) fn subset_name(
font: &FontRef,
plan: &Plan,
builder: &mut FontBuilder,
) -> Result<(), SubsetError> {
let name = font.name().or(Err(SubsetTableError(Name::TAG)))?;
let name_records = name.name_record();
//TODO: support name_table_override
//TODO: support name table version 1
let mut retained_name_record_idxes = name_records
.iter()
.enumerate()
.filter(|(_, record)| {
if !plan.name_ids.contains(record.name_id())
|| !plan.name_languages.contains(record.language_id())
{
return false;
}
plan.subset_flags
.contains(SubsetFlags::SUBSET_FLAGS_NAME_LEGACY)
|| record.is_unicode()
})
.map(|x| x.0)
.collect::<Vec<_>>();

retained_name_record_idxes.sort_unstable_by(|a, b| {
let id_a = name_records[*a].platform_id();
let id_b = name_records[*b].platform_id();
if id_a != id_b {
return id_a.cmp(&id_b);
}

let id_a = name_records[*a].encoding_id();
let id_b = name_records[*b].encoding_id();
if id_a != id_b {
return id_a.cmp(&id_b);
}

let id_a = name_records[*a].language_id();
let id_b = name_records[*b].language_id();
if id_a != id_b {
return id_a.cmp(&id_b);
}

let id_a = name_records[*a].name_id().to_u16();
let id_b = name_records[*b].name_id().to_u16();
if id_a != id_b {
return id_a.cmp(&id_b);
}

let len_a = name_records[*a].length();
let len_b = name_records[*b].length();
if len_a != len_b {
return len_a.cmp(&len_b);
}

Ordering::Equal
});

let name_data = name.offset_data().as_bytes();
let mut out = Vec::with_capacity(name_data.len());
// version
// TODO: support version 1
out.extend_from_slice(&[0, 0]);
//count
let count = retained_name_record_idxes.len() as u16;
out.extend_from_slice(&count.to_be_bytes());
//storage_offset
let storage_offset = count * 12 + 6;
out.extend_from_slice(&storage_offset.to_be_bytes());

//pre-allocate space for name records array
out.resize(storage_offset as usize, 0);

let mut string_offset = 0_u16;
let storage_start = name.storage_offset() as usize;
for (new_idx, old_idx) in retained_name_record_idxes.iter().enumerate() {
let old_record_start = 6 + 12 * old_idx;
let new_record_start = 6 + 12 * new_idx;
//copy name_record except for string offset
out.get_mut(new_record_start..new_record_start + 10)
.unwrap()
.copy_from_slice(
name_data
.get(old_record_start..old_record_start + 10)
.unwrap(),
);
//copy string offset
out.get_mut(new_record_start + 10..new_record_start + 12)
.unwrap()
.copy_from_slice(&string_offset.to_be_bytes());

//copy string data
let str_start = storage_start + name_records[*old_idx].string_offset().to_u32() as usize;
let str_len = name_records[*old_idx].length();
let str_data = name_data
.get(str_start..str_start + str_len as usize)
.ok_or(SubsetTableError(Name::TAG))?;
out.extend_from_slice(str_data);

string_offset += str_len;
}

builder.add_raw(Name::TAG, out);
Ok(())
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified klippa/test-data/expected/basics/Roboto-Regular.abc.default.61.ttf
Binary file not shown.
Binary file modified klippa/test-data/expected/basics/Roboto-Regular.abc.default.62.ttf
Binary file not shown.
Binary file modified klippa/test-data/expected/basics/Roboto-Regular.abc.default.63.ttf
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions klippa/test-data/profiles/gids.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--gids=1,2,3
1 change: 1 addition & 0 deletions klippa/test-data/profiles/name-ids.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--name-IDs=0,1,2
1 change: 1 addition & 0 deletions klippa/test-data/profiles/name-languages.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--name-languages=*
1 change: 1 addition & 0 deletions klippa/test-data/profiles/name-legacy.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--name-legacy
4 changes: 4 additions & 0 deletions klippa/test-data/tests/basics.tests
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ drop-hints.txt
drop-hints-retain-gids.txt
retain-gids.txt
notdef-outline.txt
name-ids.txt
name-languages.txt
name-legacy.txt
gids.txt
no-prune-unicode-ranges.txt
glyph-names.txt
retain-gids-glyph-names.txt
Expand Down
Loading

0 comments on commit f116b9b

Please sign in to comment.