From: Brendan Hansen Date: Sun, 18 Apr 2021 18:21:53 +0000 (-0500) Subject: added kerning to TTF X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=15e87542fe964070026a71387f4bc5826976968e;p=onyx-imgui.git added kerning to TTF --- diff --git a/data/Inconsolata-Regular.ttf b/data/Inconsolata-Regular.ttf new file mode 100644 index 0000000..e329bbc Binary files /dev/null and b/data/Inconsolata-Regular.ttf differ diff --git a/lib/ttf/types.onyx b/lib/ttf/types.onyx index caa8252..340973b 100644 --- a/lib/ttf/types.onyx +++ b/lib/ttf/types.onyx @@ -226,10 +226,10 @@ ttf_glyph_destroy :: (glyph: ^TTGlyph) { #private_file TTGlyphFlags :: enum #flags { - On_Curve :: 0x01; - X_Is_Byte :: 0x2; - Y_Is_Byte :: 0x4; - Repeat :: 0x8; + On_Curve :: 0x01; + X_Is_Byte :: 0x02; + Y_Is_Byte :: 0x04; + Repeat :: 0x08; X_Delta :: 0x10; Y_Delta :: 0x20; } @@ -513,8 +513,84 @@ TTKern0Table :: struct { n_pairs : i32; kmap : map.Map(u32, i16); old_index : i32 = -1; + + reset :: (use kern: ^TTKern0Table) { + old_index = -1; + } + + get :: (use kern: ^TTKern0Table, glyph_index: i32) -> (i32, i32) { + x := 0 + + if old_index >= 0 { + ch := ((cast(u32) old_index & 0xFFFF) << 16) | (cast(u32) glyph_index & 0xFFFF); + if map.has(^kmap, ch) { + x = cast(i32) map.get(^kmap, ch); + } + } + + old_index = glyph_index; + if swap do return 0, x; + else do return x, 0; + } } +ttf_read_kern_table :: (use ttf: ^TrueTypeFont) { + use package core.io.binary + if !map.has(^table_map, "kern") do return; + + kern_table_info := map.get(^table_map, "kern"); + seek(^reader, kern_table_info.offset); + + version := read_u16(^reader); + assert(version == 0, "Expected kern table version to be 0."); + n_tables := cast(u32) read_u16(^reader); + + for _: n_tables { + sub_table_version := cast(u32) read_u16(^reader); + length := cast(u32) read_u16(^reader); + coverage := cast(u32) read_u16(^reader); + format := coverage >> 8; + cross := coverage & 4; + vertical := (coverage & 1) == 0; + + if format == 0 { + kern_table := ttf_read_kern0(ttf, vertical, cross != 0); + array.push(^kern, kern_table); + + } else { + // Unknown format + seek(^reader, tell(^reader) + length); + } + } +} + +ttf_read_kern0 :: (use ttf: ^TrueTypeFont, vertical: bool, cross: bool) -> TTKern0Table { + use package core.io.binary + use package core.intrinsics.onyx { __zero_value } + + offset := tell(^reader); + n_pairs := cast(i32) read_u16(^reader); + search_range := cast(i32) read_u16(^reader); + entry_selector := cast(i32) read_u16(^reader); + range_shift := cast(i32) read_u16(^reader); + + kt := TTKern0Table.{ + swap = (vertical && !cross) || (!vertical && cross), + offset = offset, + n_pairs = n_pairs, + kmap = __zero_value(#type map.Map(u32, i16)) + }; + + for _: n_pairs { + left := cast(i32) read_u16(^reader); + right := cast(i32) read_u16(^reader); + value := read_fword(^reader); + tmp_index := (left << 16) | right; + map.put(^kt.kmap, tmp_index, value); + } + + return kt; +} TTHorizontalMetrics :: struct { advance_width : u16; diff --git a/lib/ttf_font.onyx b/lib/ttf_font.onyx deleted file mode 100644 index 5c736fa..0000000 --- a/lib/ttf_font.onyx +++ /dev/null @@ -1,95 +0,0 @@ -package imgui.font - -use package core -#private_file gl :: package gl - - -TrueTypeFont :: struct { - reader: io.Reader; - - // NOTE: I don't know how useful these are, but they're at - // the beginning of the ttf file. - scalar_type : u32; - search_range : u16; - entry_selector : u16; - range_shift : u16; - - table_map : map.Map(i32, TTTableInfo); - char_maps : [..] TTCmap; - - version : u32; - font_revision : u32; - checksum_adjustment : u32; - magic_number : u32; - flags : u16; - units_per_em : u16; - // created : u64; - // modified : u64; - x_min : i16; - x_max : i16; - y_min : i16; - y_max : i16; - mac_style : u16; - lowest_rec_ppem : u16; - font_direction_hint : i16; - index_to_loc_format : TTIndexToLocFormat; - glyph_data_format : i16; - - hhea : struct { - version : u32; - ascent : i16; - descent : i16; - line_gap : i16; - advance_width_max : u16; - min_left_side_bearing : i16; - min_right_side_bearing : i16; - x_max_extent : i16; - caret_slope_rise : i16; - caret_slope_run : i16; - caret_offset : i16; - metric_data_format : i16; - num_of_long_hor_metrics : u16; - }; -} - -TTTableInfo :: struct { - checksum : u32 = 0; - offset : u32 = 0; - length : u32 = 0; -} - -TTIndexToLocFormat :: enum (i16) { - Short :: 0x00; - Long :: 0x01; -} - -TTGlyph :: struct { - contour_count : i16; - x_min : i16; - x_max : i16; - y_min : i16; - y_max : i16; - - points : [..] TTGlyphPoint; - contour_ends : [..] u16; -} - -TTGlyphPoint :: struct { - on_curve : bool; - x : i16 = ~~0; - y : i16 = ~~0; -} - -ttf_create :: (ttf_data: [] u8) -> TrueTypeFont { - ttf : TrueTypeFont; - ttf.reader = binary_reader_create(ttf_data); - map.init(^ttf.table_map, .{}); - array.init(^ttf.char_maps); - ttf_read_offset_table(^ttf); - ttf_read_head_table(^ttf); - ttf_read_cmap_table(^ttf); - ttf_read_hhea_table(^ttf); - - return ttf; -} - diff --git a/test/basic.onyx b/test/basic.onyx index b1e51bd..6b87b5d 100644 --- a/test/basic.onyx +++ b/test/basic.onyx @@ -99,7 +99,8 @@ loop :: () -> void #export { main :: (args: [] cstr) { - println("Hey! We got here!"); + font_data := #file_contents "data/Inconsolata-Regular.ttf"; + font := imgui.ttf.ttf_create(font_data); init();