@@ -137,17 +137,24 @@ const Reader = struct {
137137
138138 t : * ttf ,
139139 allocator : Allocator ,
140- glyph_cache : AutoHashMap (u32 , Glyph ),
140+ code_point_cache : AutoHashMap (u32 , []u16 ),
141+ glyph_cache : AutoHashMap (u16 , Glyph ),
141142
142143 pub fn init (t : * ttf ) Reader {
143144 return Self {
144145 .t = t ,
145146 .allocator = t .allocator ,
146- .glyph_cache = AutoHashMap (u32 , Glyph ).init (t .allocator ),
147+ .code_point_cache = AutoHashMap (u32 , []u16 ).init (t .allocator ),
148+ .glyph_cache = AutoHashMap (u16 , Glyph ).init (t .allocator ),
147149 };
148150 }
149151
150152 pub fn deinit (self : * Self ) void {
153+ var code_point_iter = self .code_point_cache .iterator ();
154+ while (code_point_iter .next ()) | entry | {
155+ self .allocator .free (entry .value_ptr .* );
156+ }
157+ self .code_point_cache .deinit ();
151158 self .glyph_cache .deinit ();
152159 }
153160
@@ -187,32 +194,35 @@ const Reader = struct {
187194 };
188195 }
189196
190- pub fn get_glyph_id (self : * Self , code_point : u32 ) ! u16 {
191- if (self .glyph_cache .get (code_point )) | glyph | {
192- return glyph . id ;
197+ pub fn get_glyph_ids_by_code_point (self : * Self , code_point : u32 ) ! [] u16 {
198+ if (self .code_point_cache .get (code_point )) | glyph_ids | {
199+ return glyph_ids ;
193200 }
201+
194202 const cmap_table = self .t .parser .parsed_tables .cmap .? ;
195203 const cmap = cmap_table .cast (table .Cmap );
196204 const gid = cmap .get_glyph_index (code_point ).? ;
197- try self .glyph_cache .put (code_point , Glyph {
198- .id = gid ,
199- });
200- return gid ;
201- }
202205
203- pub fn get_glyph_info_by_glyph_id (self : * Self , gid : u16 ) ! Glyph {
204- _ = self ; // autofix
205- _ = gid ; // autofix
206- }
206+ const main_glyph = try self .get_glyph_info (gid );
207207
208- pub fn get_glyph_info (self : * Self , code_point : u32 ) ! Glyph {
209- if (self .glyph_cache .get (code_point )) | glyph | {
210- if (! glyph .is_empty ()) {
211- return glyph ;
212- }
208+ var glyph_ids = std .ArrayList (u16 ).init (self .allocator );
209+ errdefer glyph_ids .deinit ();
210+
211+ try glyph_ids .append (gid );
212+
213+ if (main_glyph .is_composite ) {
214+ try self .collect_composite_glyph_ids (gid , & glyph_ids );
213215 }
214216
215- const gid = try self .get_glyph_id (code_point );
217+ const result = try glyph_ids .toOwnedSlice ();
218+ try self .code_point_cache .put (code_point , result );
219+ return result ;
220+ }
221+
222+ pub fn get_glyph_info (self : * Self , gid : u16 ) ! Glyph {
223+ if (self .glyph_cache .get (gid )) | glyph | {
224+ return glyph ;
225+ }
216226
217227 const hmtx_table = self .t .parser .parsed_tables .hmtx .? ;
218228 const hmtx = hmtx_table .cast (table .Hmtx );
@@ -244,19 +254,56 @@ const Reader = struct {
244254 .bbox = BoundingBox .empty (),
245255 .is_composite = false ,
246256 };
247-
248- var glyh = Glyph {
257+ var glyph = Glyph {
249258 .id = gid ,
250259 .advance_width = metrics .advance_width ,
251260 .left_side_bearing = metrics .left_side_bearing ,
252261 .has_outline = has_outline ,
253262 .bbox = glyph_info .bbox ,
254263 .is_composite = glyph_info .is_composite ,
255264 };
256- glyh .mark_as_done ();
257- try self .glyph_cache .put (code_point , glyh );
265+ glyph .mark_as_done ();
266+
267+ try self .glyph_cache .put (gid , glyph );
258268
259- return glyh ;
269+ return glyph ;
270+ }
271+
272+ fn collect_composite_glyph_ids (self : * Self , gid : u16 , glyph_ids : * std .ArrayList (u16 )) ! void {
273+ const glyf_table = self .t .parser .parsed_tables .glyf .? ;
274+ const glyf = glyf_table .cast (table .Glyf );
275+ const loca_table = self .t .parser .parsed_tables .loca .? ;
276+ const loca = loca_table .cast (table .Loca );
277+
278+ const glyph_offset = loca .get_glyph_offset (gid ).? ;
279+ var parsed_glyph = try glyf .parse_glyph (glyph_offset );
280+ defer parsed_glyph .deinit ();
281+
282+ switch (parsed_glyph ) {
283+ .simple = > {},
284+ .composite = > | composite_glyph | {
285+ for (composite_glyph .components ) | component | {
286+ const component_gid = component .glyph_index ;
287+
288+ var already_exists = false ;
289+ for (glyph_ids .items ) | existing_gid | {
290+ if (existing_gid == component_gid ) {
291+ already_exists = true ;
292+ break ;
293+ }
294+ }
295+
296+ if (! already_exists ) {
297+ try glyph_ids .append (component_gid );
298+
299+ const component_glyph = try self .get_glyph_info (component_gid );
300+ if (component_glyph .is_composite ) {
301+ try self .collect_composite_glyph_ids (component_gid , glyph_ids );
302+ }
303+ }
304+ }
305+ },
306+ }
260307 }
261308};
262309
@@ -284,67 +331,36 @@ const Subsetter = struct {
284331 var required_glyphs = AutoHashMap (u16 , Glyph ).init (self .allocator );
285332 defer required_glyphs .deinit ();
286333
334+ const notdef_glyph = try self .r .get_glyph_info (0 );
335+ try required_glyphs .put (0 , notdef_glyph );
336+
287337 var utf8_view = try UTF8 .init (options .input_text );
288338 var iterator = utf8_view .iterator ();
289339
290340 while (iterator .nextCodepoint ()) | codepoint | {
291- const glyph = try self .r .get_glyph_info (codepoint );
292- if (glyph .id != 0 ) {
293- try required_glyphs .put (glyph .id , glyph );
341+ const glyph_ids = try self .r .get_glyph_ids_by_code_point (codepoint );
342+
343+ for (glyph_ids ) | gid | {
344+ if (! required_glyphs .contains (gid )) {
345+ const glyph = try self .r .get_glyph_info (gid );
346+ try required_glyphs .put (gid , glyph );
347+ }
294348 }
295349 }
296- try required_glyphs .put (0 , Glyph {});
297350
298- try self .collect_glyph_ids_recursive (& required_glyphs );
299351 var glyph_ids = try self .allocator .alloc (u16 , required_glyphs .count ());
300352 defer self .allocator .free (glyph_ids );
353+
301354 var iter = required_glyphs .iterator ();
302355 var i : usize = 0 ;
303356 while (iter .next ()) | entry | {
304357 glyph_ids [i ] = entry .key_ptr .* ;
305358 i += 1 ;
306359 }
307360 std .sort .heap (u16 , glyph_ids , {}, std .sort .asc (u16 ));
308- const b = try self .build_post_table (glyph_ids );
309- defer self .allocator .free (b );
310- }
311-
312- fn collect_glyph_ids_recursive (self : * Self , required_glyphs : * AutoHashMap (u16 , Glyph )) ! void {
313- var new_glyphs = AutoHashMap (u16 , Glyph ).init (self .allocator );
314- defer new_glyphs .deinit ();
315-
316- var iter = required_glyphs .iterator ();
317- while (iter .next ()) | entry | {
318- const glyph_id = entry .key_ptr .* ;
319- const glyph = entry .value_ptr .* ;
320-
321- if (glyph .is_composite ) {
322- const glyf_table = self .t .parser .parsed_tables .glyf .? ;
323- const glyf = glyf_table .cast (table .Glyf );
324- const loca_table = self .t .parser .parsed_tables .loca .? ;
325- const loca = loca_table .cast (table .Loca );
326- const glyph_offset = loca .get_glyph_offset (glyph_id ).? ;
327- var parsed_glyph = try glyf .parse_glyph (glyph_offset );
328- defer parsed_glyph .deinit ();
329- const composite_glyph = parsed_glyph .composite ;
330-
331- for (composite_glyph .components ) | component | {
332- const component_glyph_id = component .glyph_index ;
333- if (! required_glyphs .contains (component_glyph_id )) {
334- const component_glyph = try self .r .get_glyph_info (component_glyph_id );
335- try new_glyphs .put (component_glyph_id , component_glyph );
336- }
337- }
338- }
339- }
340361
341- if (new_glyphs .count () > 0 ) {
342- var new_iter = new_glyphs .iterator ();
343- while (new_iter .next ()) | entry | {
344- try required_glyphs .put (entry .key_ptr .* , entry .value_ptr .* );
345- }
346- try self .collect_glyph_ids_recursive (required_glyphs );
347- }
362+ // const b = try self.build_post_table(glyph_ids);
363+ // defer self.allocator.free(b);
348364 }
349365
350366 fn get_default_binary_data (self : * Self , tag : parser.TableTag , end_position : ? usize ) []const u8 {
@@ -358,54 +374,54 @@ const Subsetter = struct {
358374 return self .get_default_binary_data (.name , null );
359375 }
360376
361- fn build_post_table (self : * Self , glyph_ids : []u16 ) ! []u8 {
362- var post_table = self .t .parser .parsed_tables .post .? ;
363- const post = post_table .cast (table .Post );
364-
365- var buffer = Writer (u8 ).init (self .allocator );
366-
367- errdefer buffer .deinit ();
368-
369- // const table_data = self.get_default_binary_data(.post, 32);
370-
371- // try buffer.write_bytes(table_data);
372-
373- if (post .v2_data ) | _ | {
374- try buffer .write (u16 , @intCast (glyph_ids .len ), .big );
375-
376- // var has_custom_names = false;
377- // for (glyph_ids) |glyph_id| {
378- // if (post.get_glyph_index(glyph_id)) |glyph_index| {
379- // try buffer.write(u16, glyph_index, .big);
380- // if (glyph_index >= 258) {
381- // has_custom_names = true;
382- // }
383- // }
384- // }
385- // if (has_custom_names) {
386- // for (glyph_ids) |glyph_id| {
387- // if (post.get_glyph_index(glyph_id)) |glyph_index| {
388- // if (glyph_index >= 258) {
389- // if (post.get_glyph_name(glyph_id)) |glyph_name| {
390- // try buffer.write_u8(@intCast(glyph_name.len));
391- // try buffer.write_bytes(glyph_name);
392- // }
393- // }
394- // }
395- // }
396- // }
397- // var has_custom_names = false;
398- // _ = has_custom_names; // autofix
399-
400- // for (glyph_ids) |glyph_id| {
401- // _ = glyph_id; // autofix
402- // //
403- // }
404- // std.debug.print("{any}\n", .{post.v2_data.?});
405- }
406-
407- return buffer .to_owned_slice ();
408- }
377+ // fn build_post_table(self: *Self, glyph_ids: []u16) ![]u8 {
378+ // var post_table = self.t.parser.parsed_tables.post.?;
379+ // const post = post_table.cast(table.Post);
380+
381+ // var buffer = Writer(u8).init(self.allocator);
382+
383+ // errdefer buffer.deinit();
384+
385+ // // const table_data = self.get_default_binary_data(.post, 32);
386+
387+ // // try buffer.write_bytes(table_data);
388+
389+ // if (post.v2_data) |_| {
390+ // try buffer.write(u16, @intCast(glyph_ids.len), .big);
391+
392+ // // var has_custom_names = false;
393+ // // for (glyph_ids) |glyph_id| {
394+ // // if (post.get_glyph_index(glyph_id)) |glyph_index| {
395+ // // try buffer.write(u16, glyph_index, .big);
396+ // // if (glyph_index >= 258) {
397+ // // has_custom_names = true;
398+ // // }
399+ // // }
400+ // // }
401+ // // if (has_custom_names) {
402+ // // for (glyph_ids) |glyph_id| {
403+ // // if (post.get_glyph_index(glyph_id)) |glyph_index| {
404+ // // if (glyph_index >= 258) {
405+ // // if (post.get_glyph_name(glyph_id)) |glyph_name| {
406+ // // try buffer.write_u8(@intCast(glyph_name.len));
407+ // // try buffer.write_bytes(glyph_name);
408+ // // }
409+ // // }
410+ // // }
411+ // // }
412+ // // }
413+ // // var has_custom_names = false;
414+ // // _ = has_custom_names; // autofix
415+
416+ // // for (glyph_ids) |glyph_id| {
417+ // // _ = glyph_id; // autofix
418+ // // //
419+ // // }
420+ // // std.debug.print("{any}\n", .{post.v2_data.?});
421+ // }
422+
423+ // return buffer.to_owned_slice();
424+ // }
409425};
410426
411427test "ttf.zig" {
0 commit comments