@@ -13,6 +13,7 @@ use siphasher::sip128::{Hasher128, SipHasher13};
1313use std:: collections:: { BTreeMap , HashMap } ;
1414use std:: hash:: Hash ;
1515use std:: sync:: Arc ;
16+ use subsetter:: GlyphRemapper ;
1617use ttf_parser:: { name_id, Face , GlyphId , PlatformId , Tag } ;
1718use unicode_properties:: { GeneralCategory , UnicodeGeneralCategory } ;
1819use usvg:: { Fill , Group , ImageKind , Node , PaintOrder , Stroke , Transform } ;
@@ -45,6 +46,7 @@ pub fn write_font(
4546 let data_ref = alloc. alloc_ref ( ) ;
4647
4748 let glyph_set = & mut font. glyph_set ;
49+ let glyph_remapper = & font. glyph_remapper ;
4850
4951 // Do we have a TrueType or CFF font?
5052 //
@@ -83,14 +85,10 @@ pub fn write_font(
8385 }
8486
8587 let mut widths = vec ! [ ] ;
86- for gid in std :: iter :: once ( 0 ) . chain ( glyph_set . keys ( ) . copied ( ) ) {
87- let width = ttf. glyph_hor_advance ( GlyphId ( gid ) ) . unwrap_or ( 0 ) ;
88+ for old_gid in glyph_remapper . remapped_gids ( ) {
89+ let width = ttf. glyph_hor_advance ( GlyphId ( old_gid ) ) . unwrap_or ( 0 ) ;
8890 let units = ( width as f64 / units_per_em as f64 ) * 1000.0 ;
89- let cid = glyph_cid ( & ttf, gid) ;
90- if usize:: from ( cid) >= widths. len ( ) {
91- widths. resize ( usize:: from ( cid) + 1 , 0.0 ) ;
92- widths[ usize:: from ( cid) ] = units as f32 ;
93- }
91+ widths. push ( units as f32 ) ;
9492 }
9593
9694 // Write all non-zero glyph widths.
@@ -156,12 +154,12 @@ pub fn write_font(
156154
157155 font_descriptor. finish ( ) ;
158156
159- let cmap = create_cmap ( & ttf, glyph_set) ;
157+ let cmap =
158+ create_cmap ( & ttf, glyph_set, glyph_remapper) . ok_or ( SubsetError ( font. id ) ) ?;
160159 chunk. cmap ( cmap_ref, & cmap. finish ( ) ) ;
161160
162161 // Subset and write the font's bytes.
163- let glyphs: Vec < _ > = glyph_set. keys ( ) . copied ( ) . collect ( ) ;
164- let data = subset_font ( & font. face_data , font. face_index , & glyphs, font. id ) ?;
162+ let data = subset_font ( & font. face_data , font. face_index , glyph_remapper, font. id ) ?;
165163
166164 let mut stream = chunk. stream ( data_ref, & data) ;
167165 stream. filter ( Filter :: FlateDecode ) ;
@@ -174,7 +172,11 @@ pub fn write_font(
174172}
175173
176174/// Create a /ToUnicode CMap.
177- fn create_cmap ( ttf : & Face , glyph_set : & mut BTreeMap < u16 , String > ) -> UnicodeCmap {
175+ fn create_cmap (
176+ ttf : & Face ,
177+ glyph_set : & mut BTreeMap < u16 , String > ,
178+ glyph_remapper : & GlyphRemapper ,
179+ ) -> Option < UnicodeCmap > {
178180 // For glyphs that have codepoints mapping to them in the font's cmap table,
179181 // we prefer them over pre-existing text mappings from the document. Only
180182 // things that don't have a corresponding codepoint (or only a private-use
@@ -201,24 +203,25 @@ fn create_cmap(ttf: &Face, glyph_set: &mut BTreeMap<u16, String>) -> UnicodeCmap
201203 // Produce a reverse mapping from glyphs' CIDs to unicode strings.
202204 let mut cmap = UnicodeCmap :: new ( CMAP_NAME , SYSTEM_INFO ) ;
203205 for ( & g, text) in glyph_set. iter ( ) {
206+ let new_gid = glyph_remapper. get ( g) ?;
204207 if !text. is_empty ( ) {
205- cmap. pair_with_multiple ( glyph_cid ( ttf , g ) , text. chars ( ) ) ;
208+ cmap. pair_with_multiple ( new_gid , text. chars ( ) ) ;
206209 }
207210 }
208211
209- cmap
212+ Some ( cmap)
210213}
211214
212215fn subset_font (
213216 font_data : & [ u8 ] ,
214217 index : u32 ,
215- glyphs : & [ u16 ] ,
218+ glyph_remapper : & GlyphRemapper ,
216219 id : fontdb:: ID ,
217220) -> Result < Vec < u8 > > {
218221 let data = font_data;
219- let profile = subsetter :: Profile :: pdf ( glyphs ) ;
220- let subsetted = subsetter:: subset ( data, index, profile ) ;
221- let mut data = subsetted. as_deref ( ) . unwrap_or ( data ) ;
222+ let subsetted =
223+ subsetter:: subset ( data, index, glyph_remapper ) . map_err ( |_| SubsetError ( id ) ) ? ;
224+ let mut data = subsetted. as_ref ( ) ;
222225
223226 // Extract the standalone CFF font program if applicable.
224227 let face = ttf_parser:: RawFace :: parse ( data, 0 ) . map_err ( |_| SubsetError ( id) ) ?;
@@ -265,7 +268,8 @@ pub fn render(
265268
266269 let name = font_names. get ( & font. reference ) . unwrap ( ) ;
267270
268- let gid = glyph. id . 0 ;
271+ // TODO: Remove unwraps and switch to error-based handling.
272+ let cid = font. glyph_remapper . get ( glyph. id . 0 ) . unwrap ( ) ;
269273 let ts = glyph
270274 . outline_transform ( )
271275 . pre_scale ( font. units_per_em as f32 , font. units_per_em as f32 )
@@ -277,7 +281,7 @@ pub fn render(
277281 content. begin_text ( ) ;
278282 content. set_text_matrix ( ts. to_pdf_transform ( ) ) ;
279283 content. set_font ( Name ( name. as_bytes ( ) ) , span. font_size . get ( ) ) ;
280- content. show ( Str ( & [ ( gid >> 8 ) as u8 , ( gid & 0xff ) as u8 ] ) ) ;
284+ content. show ( Str ( & [ ( cid >> 8 ) as u8 , ( cid & 0xff ) as u8 ] ) ) ;
281285 content. end_text ( ) ;
282286 content. restore_state ( ) ;
283287 }
@@ -451,13 +455,6 @@ fn decode_mac_roman(coded: &[u8]) -> String {
451455 coded. iter ( ) . copied ( ) . map ( char_from_mac_roman) . collect ( )
452456}
453457
454- fn glyph_cid ( ttf : & Face , glyph_id : u16 ) -> u16 {
455- ttf. tables ( )
456- . cff
457- . and_then ( |cff| cff. glyph_cid ( GlyphId ( glyph_id) ) )
458- . unwrap_or ( glyph_id)
459- }
460-
461458/// Extra methods for [`[T]`](slice).
462459pub trait SliceExt < T > {
463460 /// Split a slice into consecutive runs with the same key and yield for
@@ -501,6 +498,7 @@ where
501498pub struct Font {
502499 pub id : fontdb:: ID ,
503500 pub glyph_set : BTreeMap < u16 , String > ,
501+ pub glyph_remapper : GlyphRemapper ,
504502 pub reference : Ref ,
505503 pub face_data : Arc < Vec < u8 > > ,
506504 pub units_per_em : u16 ,
@@ -525,12 +523,14 @@ pub fn fill_fonts(group: &Group, ctx: &mut Context, fontdb: &fontdb::Database) {
525523 {
526524 let reference = allocator. alloc_ref ( ) ;
527525 let glyph_set = BTreeMap :: new ( ) ;
526+ let glyph_remapper = GlyphRemapper :: new ( ) ;
528527 return Some ( Font {
529528 id : g. font ,
530529 reference,
531530 face_data : Arc :: new ( Vec :: from ( data) ) ,
532531 units_per_em : ttf. units_per_em ( ) ,
533532 glyph_set,
533+ glyph_remapper,
534534 face_index,
535535 } ) ;
536536 }
@@ -542,6 +542,7 @@ pub fn fill_fonts(group: &Group, ctx: &mut Context, fontdb: &fontdb::Database) {
542542
543543 if let Some ( ref mut font) = font {
544544 font. glyph_set . insert ( g. id . 0 , g. text . clone ( ) ) ;
545+ font. glyph_remapper . remap ( g. id . 0 ) ;
545546 }
546547 }
547548 }
0 commit comments