ttf: improvement on not found glyphs (#8050)

pull/8056/head
penguindark 2021-01-12 00:49:58 +01:00 committed by GitHub
parent 5f95dd54bd
commit 55e3e50b9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 235 additions and 197 deletions

View File

@ -111,23 +111,23 @@ fn fabs(a f32) f32 {
// integer part of x // integer part of x
[inline] [inline]
fn ipart(x f32) f32 { fn ipart(x f32) f32 {
return f32(math.floor(x)) return f32(math.floor(x))
} }
[inline] [inline]
fn round(x f32) f32 { fn round(x f32) f32 {
return ipart(x + 0.5) return ipart(x + 0.5)
} }
// fractional part of x // fractional part of x
[inline] [inline]
fn fpart(x f32) f32 { fn fpart(x f32) f32 {
return x - f32(math.floor(x)) return x - f32(math.floor(x))
} }
[inline] [inline]
fn rfpart(x f32) f32 { fn rfpart(x f32) f32 {
return 1 - fpart(x) return 1 - fpart(x)
} }
/****************************************************************************** /******************************************************************************

View File

@ -515,6 +515,13 @@ fn (mut bmp BitMap) get_chars_bbox(in_string string) []int {
} }
c_index := bmp.tf.map_code(int(char)) c_index := bmp.tf.map_code(int(char))
// Glyph not found
if c_index == 0 {
w += int(space_cw * bmp.space_cw)
i += c_len
continue
}
ax , ay := bmp.tf.next_kern(c_index) ax , ay := bmp.tf.next_kern(c_index)
//dprintln("char_index: $c_index ax: $ax ay: $ay") //dprintln("char_index: $c_index ax: $ax ay: $ay")
@ -548,7 +555,7 @@ fn (mut bmp BitMap) get_chars_bbox(in_string string) []int {
i+= c_len i+= c_len
} }
return res return res
} }
pub pub
@ -581,6 +588,12 @@ fn (mut bmp BitMap) get_bbox(in_string string) (int, int){
} }
c_index := bmp.tf.map_code(int(char)) c_index := bmp.tf.map_code(int(char))
// Glyph not found
if c_index == 0 {
w += int(space_cw * bmp.space_cw)
i += c_len
continue
}
ax , ay := bmp.tf.next_kern(c_index) ax , ay := bmp.tf.next_kern(c_index)
//dprintln("char_index: $c_index ax: $ax ay: $ay") //dprintln("char_index: $c_index ax: $ax ay: $ay")
@ -623,6 +636,25 @@ fn (mut bmp BitMap) get_bbox(in_string string) (int, int){
* TTF draw glyph * TTF draw glyph
* *
******************************************************************************/ ******************************************************************************/
fn (mut bmp BitMap) draw_notdef_glyph(in_x int, in_w int) {
mut p := Point{in_x, 0, false}
x1 , y1 := bmp.trf_txt(p)
// init ch_matrix
bmp.ch_matrix[0] = bmp.tr_matrix[0] * bmp.scale * bmp.scale_x
bmp.ch_matrix[1] = bmp.tr_matrix[1] * bmp.scale * bmp.scale_x
bmp.ch_matrix[3] = bmp.tr_matrix[3] * -bmp.scale * bmp.scale_y
bmp.ch_matrix[4] = bmp.tr_matrix[4] * -bmp.scale * bmp.scale_y
bmp.ch_matrix[6] = int(x1)
bmp.ch_matrix[7] = int(y1)
x,y := bmp.trf_ch(p)
y_h := fabs(bmp.tf.y_max-bmp.tf.y_min)* bmp.scale * 0.5
bmp.box(int(x), int(y), int(x - in_w), int(y - y_h), bmp.color)
bmp.line(int(x), int(y), int(x - in_w ), int(y - y_h), bmp.color)
bmp.line(int(x - in_w ), int(y), int(x), int(y - y_h), bmp.color)
}
pub pub
fn (mut bmp BitMap) draw_text(in_string string) (int, int){ fn (mut bmp BitMap) draw_text(in_string string) (int, int){
mut w := 0 mut w := 0
@ -652,45 +684,52 @@ fn (mut bmp BitMap) draw_text(in_string string) (int, int){
char = u16(tmp_char) char = u16(tmp_char)
} }
c_index := bmp.tf.map_code(int(char)) c_index := bmp.tf.map_code(int(char))
ax , ay := bmp.tf.next_kern(c_index) // Glyph not found
//dprintln("char_index: $c_index ax: $ax ay: $ay") if c_index == 0 {
bmp.draw_notdef_glyph(w, int(space_cw * bmp.space_cw))
w += int(space_cw * bmp.space_cw)
i += c_len
continue
}
cw, _ := bmp.tf.get_horizontal_metrics(u16(char)) ax , ay := bmp.tf.next_kern(c_index)
//cw, lsb := bmp.tf.get_horizontal_metrics(u16(char)) //dprintln("char_index: $c_index ax: $ax ay: $ay")
//dprintln("metrics: [${u16(char):c}] cw:$cw lsb:$lsb")
//----- Draw_Glyph transformations ----- cw, _ := bmp.tf.get_horizontal_metrics(u16(char))
mut x0 := w + int(ax * bmp.scale) //cw, lsb := bmp.tf.get_horizontal_metrics(u16(char))
mut y0 := 0 + int(ay * bmp.scale) //dprintln("metrics: [${u16(char):c}] cw:$cw lsb:$lsb")
p := Point{x0,y0,false} //----- Draw_Glyph transformations -----
x1 , y1 := bmp.trf_txt(p) mut x0 := w + int(ax * bmp.scale)
// init ch_matrix mut y0 := 0 + int(ay * bmp.scale)
bmp.ch_matrix[0] = bmp.tr_matrix[0] * bmp.scale * bmp.scale_x
bmp.ch_matrix[1] = bmp.tr_matrix[1] * bmp.scale * bmp.scale_x
bmp.ch_matrix[3] = bmp.tr_matrix[3] * -bmp.scale * bmp.scale_y
bmp.ch_matrix[4] = bmp.tr_matrix[4] * -bmp.scale * bmp.scale_y
bmp.ch_matrix[6] = int(x1)
bmp.ch_matrix[7] = int(y1)
x_min, x_max := bmp.draw_glyph(c_index) p := Point{x0,y0,false}
// x_min := 1 x1 , y1 := bmp.trf_txt(p)
// x_max := 2 // init ch_matrix
//----------------- bmp.ch_matrix[0] = bmp.tr_matrix[0] * bmp.scale * bmp.scale_x
bmp.ch_matrix[1] = bmp.tr_matrix[1] * bmp.scale * bmp.scale_x
bmp.ch_matrix[3] = bmp.tr_matrix[3] * -bmp.scale * bmp.scale_y
bmp.ch_matrix[4] = bmp.tr_matrix[4] * -bmp.scale * bmp.scale_y
bmp.ch_matrix[6] = int(x1)
bmp.ch_matrix[7] = int(y1)
mut width := int( (abs(x_max + x_min) + ax) * bmp.scale) x_min, x_max := bmp.draw_glyph(c_index)
if bmp.use_font_metrics { // x_min := 1
width = int((cw+ax) * bmp.scale) // x_max := 2
} //-----------------
w += width + div_space_cw
i+= c_len mut width := int( (abs(x_max + x_min) + ax) * bmp.scale)
} if bmp.use_font_metrics {
width = int((cw+ax) * bmp.scale)
}
w += width + div_space_cw
i+= c_len
}
//dprintln("y_min: $bmp.tf.y_min y_max: $bmp.tf.y_max res: ${int((bmp.tf.y_max - bmp.tf.y_min)*buf.scale)} width: ${int( (cw) * buf.scale)}") //dprintln("y_min: $bmp.tf.y_min y_max: $bmp.tf.y_max res: ${int((bmp.tf.y_max - bmp.tf.y_min)*buf.scale)} width: ${int( (cw) * buf.scale)}")
//buf.box(0,y_base - int((bmp.tf.y_min)*buf.scale), int( (x_max) * buf.scale), y_base-int((bmp.tf.y_max)*buf.scale), u32(0xFF00_0000) ) //buf.box(0,y_base - int((bmp.tf.y_min)*buf.scale), int( (x_max) * buf.scale), y_base-int((bmp.tf.y_max)*buf.scale), u32(0xFF00_0000) )
return w , int(abs(int(bmp.tf.y_max - bmp.tf.y_min)) * bmp.scale) return w , int(abs(int(bmp.tf.y_max - bmp.tf.y_min)) * bmp.scale)
} }
pub pub
@ -759,13 +798,13 @@ fn (mut bmp BitMap) draw_glyph(index u16) (int, int){
} else { } else {
//dprintln("HERE2") //dprintln("HERE2")
// ctx.quadraticCurveTo(prev.x + x, prev.y + y, // ctx.quadraticCurveTo(prev.x + x, prev.y + y,
// (prev.x + point.x) / 2 + x, // (prev.x + point.x) / 2 + x,
// (prev.y + point.y) / 2 + y); // (prev.y + point.y) / 2 + y);
//bmp.line(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, color2) //bmp.line(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, color2)
//bmp.quadratic(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, prev.x, prev.y, color2) //bmp.quadratic(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, prev.x, prev.y, color2)
bmp.quadratic(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, prev.x, prev.y, color) bmp.quadratic(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, prev.x, prev.y, color)
x0 = (prev.x + point.x)/2 x0 = (prev.x + point.x)/2
y0 = (prev.y + point.y)/2 y0 = (prev.y + point.y)/2
} }
} }
@ -774,29 +813,29 @@ fn (mut bmp BitMap) draw_glyph(index u16) (int, int){
//dprintln("count == glyph.contour_ends[count]") //dprintln("count == glyph.contour_ends[count]")
if s == 2 { // final point was off-curve. connect to start if s == 2 { // final point was off-curve. connect to start
mut start_point := glyph.points[contour_start] mut start_point := glyph.points[contour_start]
start_point.x, start_point.y = bmp.trf_ch(start_point) start_point.x, start_point.y = bmp.trf_ch(start_point)
if point.on_curve { if point.on_curve {
//ctx.quadraticCurveTo(prev.x + x, prev.y + y, //ctx.quadraticCurveTo(prev.x + x, prev.y + y,
// point.x + x, point.y + y); //point.x + x, point.y + y);
//bmp.line(x0, y0, start_point.x + in_x, start_point.y + in_y, u32(0x00FF0000)) //bmp.line(x0, y0, start_point.x + in_x, start_point.y + in_y, u32(0x00FF0000))
bmp.quadratic(x0, y0, start_point.x, start_point.y , bmp.quadratic(x0, y0, start_point.x, start_point.y ,
// start_point.x + in_x, start_point.y + in_y, u32(0xFF00FF00)) // start_point.x + in_x, start_point.y + in_y, u32(0xFF00FF00))
start_point.x, start_point.y, color) start_point.x, start_point.y, color)
} else { } else {
//ctx.quadraticCurveTo(prev.x + x, prev.y + y, //ctx.quadraticCurveTo(prev.x + x, prev.y + y,
// (prev.x + point.x) / 2 + x, // (prev.x + point.x) / 2 + x,
// (prev.y + point.y) / 2 + y); // (prev.y + point.y) / 2 + y);
//bmp.line(x0, y0, start_point.x, start_point.y, u32(0x00FF0000) //bmp.line(x0, y0, start_point.x, start_point.y, u32(0x00FF0000)
bmp.quadratic(x0, y0, start_point.x, start_point.y, bmp.quadratic(x0, y0, start_point.x, start_point.y,
(point.x + start_point.x)/2, (point.x + start_point.x)/2,
(point.y + start_point.y)/2, (point.y + start_point.y)/2,
//u32(0xFF000000)) //u32(0xFF000000))
color) color)
} }
}else{ } else {
// last point not in a curve // last point not in a curve
//bmp.line(point.x, point.y, sp_x, sp_y, u32(0x00FF0000)) //bmp.line(point.x, point.y, sp_x, sp_y, u32(0x00FF0000))
bmp.line(point.x, point.y, sp_x, sp_y, color) bmp.line(point.x, point.y, sp_x, sp_y, color)

View File

@ -156,7 +156,7 @@ fn (mut tf_skl TTF_render_Sokol) create_texture(){
height: h height: h
num_mipmaps: 0 num_mipmaps: 0
min_filter: .linear min_filter: .linear
mag_filter: .linear mag_filter: .linear
//usage: .dynamic //usage: .dynamic
wrap_u: .clamp_to_edge wrap_u: .clamp_to_edge
wrap_v: .clamp_to_edge wrap_v: .clamp_to_edge

View File

@ -24,10 +24,10 @@ import strings
******************************************************************************/ ******************************************************************************/
struct Segment { struct Segment {
mut: mut:
id_range_offset u32 id_range_offset u32
start_code u16 start_code u16
end_code u16 end_code u16
id_delta u16 id_delta u16
} }
struct TrueTypeCmap { struct TrueTypeCmap {
@ -220,8 +220,8 @@ fn (mut tf TTF_File) glyph_count() u16{
old_pos := tf.pos old_pos := tf.pos
tf.pos = tf.tables["maxp"].offset + 4 tf.pos = tf.tables["maxp"].offset + 4
count := tf.get_u16() count := tf.get_u16()
tf.pos = old_pos tf.pos = old_pos
return count return count
} }
pub pub
@ -474,22 +474,21 @@ fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph){
simple_glyph := tf.read_glyph(component.glyph_index) simple_glyph := tf.read_glyph(component.glyph_index)
if simple_glyph.valid_glyph { if simple_glyph.valid_glyph {
point_offset := in_glyph.points.len point_offset := in_glyph.points.len
for i in 0..simple_glyph.contour_ends.len { for i in 0..simple_glyph.contour_ends.len {
in_glyph.contour_ends << u16(simple_glyph.contour_ends[i] + point_offset) in_glyph.contour_ends << u16(simple_glyph.contour_ends[i] + point_offset)
} }
for p in simple_glyph.points { for p in simple_glyph.points {
mut x := f32(p.x) mut x := f32(p.x)
mut y := f32(p.y) mut y := f32(p.y)
x = component.matrix[0] * x + component.matrix[1] * y + component.matrix[4] x = component.matrix[0] * x + component.matrix[1] * y + component.matrix[4]
y = component.matrix[2] * x + component.matrix[3] * y + component.matrix[5] y = component.matrix[2] * x + component.matrix[3] * y + component.matrix[5]
in_glyph.points << Point{ in_glyph.points << Point{
x: int(x) x: int(x)
y: int(y) y: int(y)
on_curve: p.on_curve on_curve: p.on_curve
} }
}
}
} }
tf.pos = old_pos tf.pos = old_pos
} }
@ -501,7 +500,7 @@ fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph){
} }
// ok we have a valid glyph // ok we have a valid glyph
in_glyph.valid_glyph = true in_glyph.valid_glyph = true
} }
/****************************************************************************** /******************************************************************************
@ -695,9 +694,9 @@ fn (mut tf TTF_File) read_head_table() {
tf.y_max = tf.get_i16() tf.y_max = tf.get_i16()
tf.mac_style = tf.get_u16() tf.mac_style = tf.get_u16()
tf.lowest_rec_ppem = tf.get_u16() tf.lowest_rec_ppem = tf.get_u16()
tf.font_direction_hint = tf.get_i16() tf.font_direction_hint = tf.get_i16()
tf.index_to_loc_format = tf.get_i16() tf.index_to_loc_format = tf.get_i16()
tf.glyph_data_format = tf.get_i16() tf.glyph_data_format = tf.get_i16()
} }
/****************************************************************************** /******************************************************************************
@ -721,36 +720,36 @@ fn (mut tf TTF_File) read_name_table() {
/*platform_specific_id :=*/ tf.get_u16() /*platform_specific_id :=*/ tf.get_u16()
/*language_id :=*/ tf.get_u16() /*language_id :=*/ tf.get_u16()
name_id := tf.get_u16() name_id := tf.get_u16()
length := tf.get_u16() length := tf.get_u16()
offset := tf.get_u16() offset := tf.get_u16()
old_pos := tf.pos old_pos := tf.pos
tf.pos = table_offset + string_offset + offset tf.pos = table_offset + string_offset + offset
mut name := "" mut name := ""
if platform_id == 0 || platform_id == 3 { if platform_id == 0 || platform_id == 3 {
name = tf.get_unicode_string(length) name = tf.get_unicode_string(length)
} else { } else {
name = tf.get_string(length) name = tf.get_string(length)
} }
//dprintln("Name [${platform_id} / ${platform_specific_id}] id:[$name_id] language:[$language_id] [$name]") //dprintln("Name [${platform_id} / ${platform_specific_id}] id:[$name_id] language:[$language_id] [$name]")
tf.pos = old_pos tf.pos = old_pos
match name_id { match name_id {
1 { 1 {
tf.font_family = name tf.font_family = name
}
2 {
tf.font_sub_family = name
}
4 {
tf.full_name = name
}
6 {
tf.postscript_name = name
}
else {}
} }
2 {
tf.font_sub_family = name
}
4 {
tf.full_name = name
}
6 {
tf.postscript_name = name
}
else {}
}
} }
} }
@ -767,24 +766,24 @@ fn (mut tf TTF_File) read_cmap_table() {
version := tf.get_u16() // must be 0 version := tf.get_u16() // must be 0
assert version == 0 assert version == 0
number_sub_tables := tf.get_u16() number_sub_tables := tf.get_u16()
// tables must be sorted by platform id and then platform specific // tables must be sorted by platform id and then platform specific
// encoding. // encoding.
for _ in 0..number_sub_tables { for _ in 0..number_sub_tables {
// platforms are: // platforms are:
// 0 - Unicode -- use specific id 6 for full coverage. 0/4 common. // 0 - Unicode -- use specific id 6 for full coverage. 0/4 common.
// 1 - Macintosh (Discouraged) // 1 - Macintosh (Discouraged)
// 2 - reserved // 2 - reserved
// 3 - Microsoft // 3 - Microsoft
platform_id := tf.get_u16() platform_id := tf.get_u16()
platform_specific_id := tf.get_u16() platform_specific_id := tf.get_u16()
offset := tf.get_u32() offset := tf.get_u32()
dprintln("CMap platform_id=${platform_id} specific_id=${platform_specific_id} offset=${offset}") dprintln("CMap platform_id=${platform_id} specific_id=${platform_specific_id} offset=${offset}")
if platform_id == 3 && platform_specific_id <= 1 { if platform_id == 3 && platform_specific_id <= 1 {
tf.read_cmap(table_offset + offset) tf.read_cmap(table_offset + offset)
} }
} }
} }
fn (mut tf TTF_File) read_cmap(offset u32) { fn (mut tf TTF_File) read_cmap(offset u32) {
@ -817,17 +816,17 @@ fn (mut tf TTF_File) read_cmap(offset u32) {
******************************************************************************/ ******************************************************************************/
fn (mut tf TTF_File) map_code(char_code int) u16{ fn (mut tf TTF_File) map_code(char_code int) u16{
mut index := 0 mut index := 0
for i in 0..tf.cmaps.len { for i in 0..tf.cmaps.len {
mut cmap := tf.cmaps[i] mut cmap := tf.cmaps[i]
if cmap.format == 0 { if cmap.format == 0 {
//dprintln("format 0") //dprintln("format 0")
index = cmap.map_0(char_code) index = cmap.map_0(char_code)
} else if cmap.format == 4 { } else if cmap.format == 4 {
//dprintln("format 4") //dprintln("format 4")
index = cmap.map_4(char_code, mut tf) index = cmap.map_4(char_code, mut tf)
}
} }
} return u16(index)
return u16(index)
} }
fn (mut tm TrueTypeCmap) init_0(mut tf TTF_File) { fn (mut tm TrueTypeCmap) init_0(mut tf TTF_File) {
@ -851,45 +850,45 @@ fn (mut tm TrueTypeCmap) init_4(mut tf TTF_File) {
tm.format = 4 tm.format = 4
// 2x segcount // 2x segcount
seg_count := tf.get_u16() >> 1 seg_count := tf.get_u16() >> 1
/*search_range :=*/ tf.get_u16() /*search_range :=*/ tf.get_u16()
/*entry_selector :=*/ tf.get_u16() /*entry_selector :=*/ tf.get_u16()
/*range_shift :=*/ tf.get_u16() /*range_shift :=*/ tf.get_u16()
// Ending character code for each segment, last is 0xffff // Ending character code for each segment, last is 0xffff
for _ in 0..seg_count { for _ in 0..seg_count {
tm.segments << Segment{0, 0, tf.get_u16(), 0} tm.segments << Segment{0, 0, tf.get_u16(), 0}
} }
// reservePAD // reservePAD
tf.get_u16() tf.get_u16()
// starting character code for each segment // starting character code for each segment
for i in 0..seg_count { for i in 0..seg_count {
tm.segments[i].start_code = tf.get_u16() tm.segments[i].start_code = tf.get_u16()
} }
// Delta for all character codes in segment // Delta for all character codes in segment
for i in 0..seg_count { for i in 0..seg_count {
tm.segments[i].id_delta = tf.get_u16() tm.segments[i].id_delta = tf.get_u16()
} }
// offset in bytes to glyph indexArray, or 0 // offset in bytes to glyph indexArray, or 0
for i in 0..seg_count { for i in 0..seg_count {
ro := u32(tf.get_u16()) ro := u32(tf.get_u16())
if ro != 0 { if ro != 0 {
tm.segments[i].id_range_offset = tf.pos - 2 + ro tm.segments[i].id_range_offset = tf.pos - 2 + ro
} else { } else {
tm.segments[i].id_range_offset = 0 tm.segments[i].id_range_offset = 0
} }
} }
/* /*
// DEBUG LOG // DEBUG LOG
for i in 0..seg_count { for i in 0..seg_count {
seg := tm.segments[i] seg := tm.segments[i]
dprintln(" segments[$i] = $seg.start_code $seg.end_code $seg.id_delta $seg.id_range_offset") dprintln(" segments[$i] = $seg.start_code $seg.end_code $seg.id_delta $seg.id_range_offset")
} }
*/ */
} }
@ -935,21 +934,21 @@ fn (mut tf TTF_File) read_hhea_table() {
/*version :=*/ tf.get_fixed() // 0x00010000 /*version :=*/ tf.get_fixed() // 0x00010000
tf.ascent = tf.get_fword() tf.ascent = tf.get_fword()
tf.descent = tf.get_fword() tf.descent = tf.get_fword()
tf.line_gap = tf.get_fword() tf.line_gap = tf.get_fword()
tf.advance_width_max = tf.get_ufword() tf.advance_width_max = tf.get_ufword()
tf.min_left_side_bearing = tf.get_fword() tf.min_left_side_bearing = tf.get_fword()
tf.min_right_side_bearing = tf.get_fword() tf.min_right_side_bearing = tf.get_fword()
tf.x_max_extent = tf.get_fword() tf.x_max_extent = tf.get_fword()
tf.caret_slope_rise = tf.get_i16() tf.caret_slope_rise = tf.get_i16()
tf.caret_slope_run = tf.get_i16() tf.caret_slope_run = tf.get_i16()
tf.caret_offset = tf.get_fword() tf.caret_offset = tf.get_fword()
tf.get_i16() // reserved tf.get_i16() // reserved
tf.get_i16() // reserved tf.get_i16() // reserved
tf.get_i16() // reserved tf.get_i16() // reserved
tf.get_i16() // reserved tf.get_i16() // reserved
tf.metric_data_format = tf.get_i16() tf.metric_data_format = tf.get_i16()
tf.num_of_long_hor_metrics = tf.get_u16() tf.num_of_long_hor_metrics = tf.get_u16()
} }
/****************************************************************************** /******************************************************************************
@ -959,11 +958,11 @@ fn (mut tf TTF_File) read_hhea_table() {
******************************************************************************/ ******************************************************************************/
struct Kern0Table { struct Kern0Table {
mut: mut:
swap bool swap bool
offset u32 offset u32
n_pairs int n_pairs int
kmap map[u32]i16 kmap map[u32]i16
old_index int = -1 old_index int = -1
} }
fn (mut kt Kern0Table) reset() { fn (mut kt Kern0Table) reset() {
@ -1027,23 +1026,23 @@ fn (mut tf TTF_File) read_kern_table() {
dprintln("Kern Table version: $version Kern nTables: $n_tables") dprintln("Kern Table version: $version Kern nTables: $n_tables")
for _ in 0..n_tables{ for _ in 0..n_tables{
st_version := tf.get_u16() // sub table version st_version := tf.get_u16() // sub table version
length := tf.get_u16() length := tf.get_u16()
coverage := tf.get_u16() coverage := tf.get_u16()
format := coverage >> 8 format := coverage >> 8
cross := coverage & 4 cross := coverage & 4
vertical := (coverage & 0x1) == 0 vertical := (coverage & 0x1) == 0
dprintln("Kerning subtable version [$st_version] format [$format] length [$length] coverage: [${coverage.hex()}]") dprintln("Kerning subtable version [$st_version] format [$format] length [$length] coverage: [${coverage.hex()}]")
if format == 0 { if format == 0 {
dprintln("kern format: 0") dprintln("kern format: 0")
kern := tf.create_kern_table0(vertical, cross != 0) kern := tf.create_kern_table0(vertical, cross != 0)
tf.kern << kern tf.kern << kern
} else { } else {
dprintln("Unknown format -- skip") dprintln("Unknown format -- skip")
tf.pos = tf.pos + length tf.pos = tf.pos + length
}
} }
}
} }
fn (mut tf TTF_File) reset_kern() { fn (mut tf TTF_File) reset_kern() {