-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
189 additions
and
163 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
mod read; | ||
mod write; | ||
|
||
use super::*; | ||
use crate::name::read::Version0Table; | ||
use crate::Error::{MalformedFont, SubsetError}; | ||
|
||
pub(crate) fn subset(ctx: &mut Context) -> Result<()> { | ||
let name = ctx.expect_table(Tag::NAME).ok_or(MalformedFont)?; | ||
let mut r = Reader::new(name); | ||
|
||
let version = r.read::<u16>().ok_or(MalformedFont)?; | ||
|
||
// From my personal experiments, version 0 is isn't used at all, so we | ||
// don't bother subsetting it. | ||
if version != 0 { | ||
ctx.push(Tag::NAME, name); | ||
return Ok(()); | ||
} | ||
|
||
let table = Version0Table::parse(name).ok_or(MalformedFont)?; | ||
let subsetted_table = write::subset(&table).ok_or(SubsetError)?; | ||
|
||
let mut w = Writer::new(); | ||
w.write(subsetted_table); | ||
|
||
ctx.push(Tag::NAME, w.finish()); | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
use crate::stream::{Readable, Reader}; | ||
use std::borrow::Cow; | ||
|
||
#[derive(Clone, Debug)] | ||
pub struct Version0Table<'a> { | ||
pub names: Vec<NameRecord>, | ||
pub storage: Cow<'a, [u8]>, | ||
} | ||
|
||
impl<'a> Version0Table<'a> { | ||
pub fn parse(data: &'a [u8]) -> Option<Self> { | ||
let mut r = Reader::new(data); | ||
|
||
let version = r.read::<u16>()?; | ||
|
||
if version != 0 { | ||
return None; | ||
} | ||
|
||
let count = r.read::<u16>()?; | ||
r.read::<u16>()?; // storage offset | ||
|
||
let mut names = Vec::with_capacity(count as usize); | ||
|
||
for _ in 0..count { | ||
names.push(r.read::<NameRecord>()?); | ||
} | ||
|
||
let storage = Cow::Borrowed(r.tail()?); | ||
|
||
Some(Self { names, storage }) | ||
} | ||
} | ||
|
||
impl Readable<'_> for NameRecord { | ||
const SIZE: usize = u16::SIZE * 6; | ||
|
||
fn read(r: &mut Reader<'_>) -> Option<Self> { | ||
let platform_id = r.read::<u16>()?; | ||
let encoding_id = r.read::<u16>()?; | ||
let language_id = r.read::<u16>()?; | ||
let name_id = r.read::<u16>()?; | ||
let length = r.read::<u16>()?; | ||
let string_offset = r.read::<u16>()?; | ||
|
||
Some(Self { | ||
platform_id, | ||
encoding_id, | ||
language_id, | ||
name_id, | ||
length, | ||
string_offset, | ||
}) | ||
} | ||
} | ||
|
||
#[derive(Clone, Copy, Debug)] | ||
pub struct NameRecord { | ||
pub platform_id: u16, | ||
pub encoding_id: u16, | ||
pub language_id: u16, | ||
pub name_id: u16, | ||
pub length: u16, | ||
pub string_offset: u16, | ||
} | ||
|
||
impl NameRecord { | ||
pub fn is_unicode(&self) -> bool { | ||
self.platform_id == 0 | ||
|| (self.platform_id == 3 && [0, 1, 10].contains(&self.encoding_id)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
use crate::name::read::NameRecord; | ||
use crate::name::read::Version0Table; | ||
use crate::stream::{Readable, Writeable, Writer}; | ||
use std::borrow::Cow; | ||
|
||
type SubsettedVersion0Table<'a> = Version0Table<'a>; | ||
|
||
pub fn subset<'a>(table: &Version0Table<'a>) -> Option<SubsettedVersion0Table<'a>> { | ||
let mut names = table | ||
.names | ||
.iter() | ||
.copied() | ||
.filter(|record| { | ||
record.is_unicode() && [0, 1, 2, 3, 4, 5, 6].contains(&record.name_id) | ||
}) | ||
.collect::<Vec<_>>(); | ||
|
||
let mut storage = Vec::new(); | ||
let mut cur_storage_offset = 0; | ||
|
||
for record in &mut names { | ||
storage.extend( | ||
&table.storage[(record.string_offset as usize) | ||
..((record.string_offset + record.length) as usize)], | ||
); | ||
record.string_offset = cur_storage_offset; | ||
cur_storage_offset += record.length; | ||
} | ||
|
||
Some(SubsettedVersion0Table { names, storage: Cow::Owned(storage) }) | ||
} | ||
|
||
impl Writeable for SubsettedVersion0Table<'_> { | ||
fn write(&self, w: &mut Writer) { | ||
let count = u16::try_from(self.names.len()).unwrap(); | ||
|
||
// version | ||
w.write::<u16>(0); | ||
// count | ||
w.write::<u16>(count); | ||
// storage offset | ||
w.write::<u16>(u16::SIZE as u16 * 3 + count * NameRecord::SIZE as u16); | ||
w.write_vector::<NameRecord>(&self.names); | ||
w.extend(&self.storage); | ||
} | ||
} | ||
|
||
impl Writeable for NameRecord { | ||
fn write(&self, w: &mut Writer) { | ||
w.write::<u16>(self.platform_id); | ||
w.write::<u16>(self.encoding_id); | ||
w.write::<u16>(self.language_id); | ||
w.write::<u16>(self.name_id); | ||
w.write::<u16>(self.length); | ||
w.write::<u16>(self.string_offset); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.