Skip to content

Commit 25d3873

Browse files
committed
feat: change collect stage
1 parent 9db3d78 commit 25d3873

File tree

1 file changed

+133
-117
lines changed

1 file changed

+133
-117
lines changed

src/lib2.zig

Lines changed: 133 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -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

411427
test "ttf.zig" {

0 commit comments

Comments
 (0)