Skip to content

Commit

Permalink
Only write once
Browse files Browse the repository at this point in the history
  • Loading branch information
LaurenzV committed May 22, 2024
1 parent 8ee5ad3 commit 93acb42
Show file tree
Hide file tree
Showing 9 changed files with 260 additions and 145 deletions.
19 changes: 12 additions & 7 deletions src/cff/dict/font_dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::cff::dict::private_dict::parse_subr_offset;
use crate::cff::dict::DictionaryParser;
use crate::cff::index::{create_index, parse_index, Index};
use crate::cff::number::{Number, StringId};
use crate::cff::operator::Operator;
use crate::cff::remapper::{FontDictRemapper, SidRemapper};
use crate::cff::{dict, FontWriteContext};
use crate::read::Reader;
Expand Down Expand Up @@ -67,17 +66,23 @@ pub(crate) fn write_font_dict_index(
w.write(dict::operators::FONT_NAME);
}

// Private dicts have already been written, so the offsets are already correct.
// TODO: Offsets can be u32?
let private_dict_offset = font_write_context
.private_dicts_offsets
font_write_context
.private_dicts_lens
.get(new_df as usize)
.ok_or(SubsetError)?;
.ok_or(SubsetError)?
.value.write_as_5_bytes(&mut w);

font_write_context
.private_dicts_offsets
.get_mut(new_df as usize)
.ok_or(SubsetError)?
.value.write_as_5_bytes(&mut w);

private_dict_offset.0.write_as_5_bytes(&mut w);
private_dict_offset.1.write_as_5_bytes(&mut w);
w.write(dict::operators::PRIVATE);
dicts.push(w.finish());
}

create_index(dicts)
create_index(dicts).map(|i| i.data)
}
28 changes: 19 additions & 9 deletions src/cff/dict/private_dict.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::cff::cid_font::CIDMetadata;
use crate::cff::dict::operators::*;
use crate::cff::dict::DictionaryParser;
use crate::cff::number::{IntegerNumber, Number};
use crate::cff::number::Number;
use crate::cff::remapper::FontDictRemapper;
use crate::cff::sid_font::SIDMetadata;
use crate::cff::FontWriteContext;
Expand Down Expand Up @@ -66,12 +66,17 @@ pub fn write_private_dicts(

let private_dict_len = private_dict_data.len();

let offsets = font_write_context
font_write_context
.private_dicts_lens
.get_mut(new_df)
.ok_or(SubsetError)?
.update_value(private_dict_len)?;

font_write_context
.private_dicts_offsets
.get_mut(new_df)
.ok_or(SubsetError)?;
offsets.0 = IntegerNumber(private_dict_len as i32);
offsets.1 = IntegerNumber(private_dict_offset as i32);
.ok_or(SubsetError)?
.update_value(private_dict_offset)?;

w.extend(&private_dict_data);
}
Expand Down Expand Up @@ -113,12 +118,17 @@ pub fn write_sid_private_dicts(

let private_dict_len = private_dict_data.len();

let offsets = font_write_context
font_write_context
.private_dicts_lens
.get_mut(0)
.ok_or(SubsetError)?
.update_value(private_dict_len)?;

font_write_context
.private_dicts_offsets
.get_mut(0)
.ok_or(SubsetError)?;
offsets.0 = IntegerNumber(private_dict_len as i32);
offsets.1 = IntegerNumber(private_dict_offset as i32);
.ok_or(SubsetError)?
.update_value(private_dict_offset)?;

w.extend(&private_dict_data);

Expand Down
88 changes: 54 additions & 34 deletions src/cff/dict/top_dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ use crate::cff::dict::DictionaryParser;
use crate::cff::index::{create_index, parse_index};
use crate::cff::number::{Number, StringId};
use crate::cff::remapper::SidRemapper;
use crate::cff::FontWriteContext;
use crate::cff::{FontWriteContext, DUMMY_VALUE};
use crate::read::Reader;
use crate::write::Writer;
use crate::Error::SubsetError;
use std::array;
use std::collections::BTreeSet;
use std::ops::Range;
Expand Down Expand Up @@ -70,10 +69,11 @@ pub(crate) fn write_top_dict_index(
raw_top_dict: &[u8],
font_write_context: &mut FontWriteContext,
sid_remapper: &SidRemapper,
) -> crate::Result<Vec<u8>> {
w: &mut Writer
) -> crate::Result<()> {
use super::operators::*;

let mut w = Writer::new();
let mut sub_w = Writer::new();
let mut r = Reader::new(raw_top_dict);

let index = parse_index::<u16>(&mut r).unwrap();
Expand All @@ -87,36 +87,35 @@ pub(crate) fn write_top_dict_index(
while let Some(operator) = dict_parser.parse_next() {
match operator {
CHARSET => {
font_write_context.charset_offset.write_as_5_bytes(&mut w);
w.write(operator)
font_write_context.charset_offset.update_location(sub_w.len() + w.len());
DUMMY_VALUE.write_as_5_bytes(&mut sub_w);
sub_w.write(operator)
}
ENCODING => {
font_write_context.encoding_offset.write_as_5_bytes(&mut w);
w.write(operator);
font_write_context.encoding_offset.update_location(sub_w.len() + w.len());
DUMMY_VALUE.write_as_5_bytes(&mut sub_w);
sub_w.write(operator);
}
CHAR_STRINGS => {
font_write_context.char_strings_offset.write_as_5_bytes(&mut w);
w.write(operator);
font_write_context.char_strings_offset.update_location(sub_w.len() + w.len());
DUMMY_VALUE.write_as_5_bytes(&mut sub_w);
sub_w.write(operator);
}
FD_ARRAY => {
let Some(cid_context) = &font_write_context.cid_context else {
return Err(SubsetError);
};
cid_context.fd_array_offset.write_as_5_bytes(&mut w);
w.write(operator);
font_write_context.fd_array_offset.update_location(sub_w.len() + w.len());
DUMMY_VALUE.write_as_5_bytes(&mut sub_w);
sub_w.write(operator);
}
FD_SELECT => {
let Some(cid_context) = &font_write_context.cid_context else {
return Err(SubsetError);
};
cid_context.fd_select_offset.write_as_5_bytes(&mut w);
w.write(&operator);
font_write_context.fd_select_offset.update_location(sub_w.len() + w.len());
DUMMY_VALUE.write_as_5_bytes(&mut sub_w);
sub_w.write(&operator);
}
VERSION | NOTICE | COPYRIGHT | FULL_NAME | FAMILY_NAME | WEIGHT
| POSTSCRIPT | BASE_FONT_NAME | BASE_FONT_BLEND | FONT_NAME => {
let sid = sid_remapper.get(dict_parser.parse_sid().unwrap()).unwrap();
w.write(Number::from_i32(sid.0 as i32));
w.write(operator);
sub_w.write(Number::from_i32(sid.0 as i32));
sub_w.write(operator);
}
ROS => {
dict_parser.parse_operands().unwrap();
Expand All @@ -129,31 +128,52 @@ pub(crate) fn write_top_dict_index(
.get(StringId(u16::try_from(operands[1].as_u32().unwrap()).unwrap()))
.unwrap();

w.write(Number::from_i32(arg1.0 as i32));
w.write(Number::from_i32(arg2.0 as i32));
w.write(&operands[2]);
w.write(operator);
sub_w.write(Number::from_i32(arg1.0 as i32));
sub_w.write(Number::from_i32(arg2.0 as i32));
sub_w.write(&operands[2]);
sub_w.write(operator);
}
PRIVATE => {
if let Some(offsets) = font_write_context.private_dicts_offsets.first() {
offsets.0.write_as_5_bytes(&mut w);
offsets.1.write_as_5_bytes(&mut w);
w.write(PRIVATE);
if let (Some(lens), Some(offsets)) = (
font_write_context.private_dicts_lens.first_mut(),
font_write_context.private_dicts_offsets.first_mut(),
) {
lens.update_location(sub_w.len() + w.len());
DUMMY_VALUE.write_as_5_bytes(&mut sub_w);
offsets.update_location(sub_w.len() + w.len());
DUMMY_VALUE.write_as_5_bytes(&mut sub_w);
sub_w.write(PRIVATE);
}
}
_ => {
dict_parser.parse_operands().unwrap();
let operands = dict_parser.operands();

w.write(operands);
w.write(operator);
sub_w.write(operands);
sub_w.write(operator);
}
}
}

let finished = w.finish();
let finished = sub_w.finish();

let index = create_index(vec![finished])?;

Ok(index)
font_write_context.charset_offset.adjust_location(index.header_size);
font_write_context.char_strings_offset.adjust_location(index.header_size);
font_write_context.encoding_offset.adjust_location(index.header_size);
font_write_context.fd_array_offset.adjust_location(index.header_size);
font_write_context.fd_select_offset.adjust_location(index.header_size);

if let (Some(lens), Some(offsets)) = (
font_write_context.private_dicts_lens.first_mut(),
font_write_context.private_dicts_offsets.first_mut(),
) {
lens.adjust_location(index.header_size);
offsets.adjust_location(index.header_size);
}

w.write(index);

Ok(())
}
33 changes: 29 additions & 4 deletions src/cff/index.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::cff::number::U24;
use crate::read::{Readable, Reader};
use crate::write::Writer;
use crate::write::{Writeable, Writer};
use crate::Error::MalformedFont;

pub trait IndexSize: for<'a> Readable<'a> {
Expand Down Expand Up @@ -214,14 +214,34 @@ impl Readable<'_> for OffsetSize {
}
}

pub(crate) fn create_index(data: Vec<Vec<u8>>) -> crate::Result<Vec<u8>> {
pub struct OwnedIndex {
pub data: Vec<u8>,
pub header_size: usize
}

impl Writeable for OwnedIndex {
fn write(&self, w: &mut Writer) {
w.extend(&self.data);
}
}

impl Default for OwnedIndex {
fn default() -> Self {
Self {
data: vec![0, 0],
header_size: 2
}
}
}

pub(crate) fn create_index(data: Vec<Vec<u8>>) -> crate::Result<OwnedIndex> {
let count = u16::try_from(data.len()).map_err(|_| MalformedFont)?;
// + 1 Since we start counting from the preceding byte.
let offsize = data.iter().map(|v| v.len() as u32).sum::<u32>() + 1;

// Empty Index only contains the count field
if count == 0 {
return Ok(vec![0, 0]);
return Ok(OwnedIndex::default());
}

let offset_size = if offsize <= u8::MAX as u32 {
Expand Down Expand Up @@ -267,9 +287,14 @@ pub(crate) fn create_index(data: Vec<Vec<u8>>) -> crate::Result<Vec<u8>> {
write_offset(el.len() as u32)?;
}

let header_size = w.len();

for el in &data {
w.extend(el);
}

Ok(w.finish())
Ok(OwnedIndex {
header_size,
data: w.finish()
})
}
Loading

0 comments on commit 93acb42

Please sign in to comment.