From df4bd88d45e66ad056133e5970c7a22e5d49b423 Mon Sep 17 00:00:00 2001 From: penguindark <57967770+penguindark@users.noreply.github.com> Date: Fri, 8 Jul 2022 08:20:59 +0200 Subject: [PATCH] x.ttf: fix a bug in TTF fixed point data management (#14987) --- vlib/x/ttf/ttf.v | 73 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 4 deletions(-) diff --git a/vlib/x/ttf/ttf.v b/vlib/x/ttf/ttf.v index 91a065423f..398ea600fe 100644 --- a/vlib/x/ttf/ttf.v +++ b/vlib/x/ttf/ttf.v @@ -90,6 +90,8 @@ pub mut: kern []Kern0Table // cache glyph_cache map[int]Glyph + // font widths array scale for PDF export + width_scale f32 = 1.0 } pub fn (mut tf TTF_File) init() { @@ -103,6 +105,8 @@ pub fn (mut tf TTF_File) init() { tf.length = tf.glyph_count() dprintln('Number of symbols: $tf.length') dprintln('*****************************') + dprintln('Unit per em: $tf.units_per_em') + dprintln('advance_width_max: $tf.advance_width_max') } /****************************************************************************** @@ -159,7 +163,7 @@ pub fn (mut tf TTF_File) get_horizontal_metrics(glyph_index u16) (int, int) { tf.pos = offset advance_width = tf.get_u16() left_side_bearing = tf.get_i16() - // dprintln("Found h_metric aw: $advance_width lsb: $left_side_bearing") + // dprintln("${glyph_index} aw:${advance_width} lsb:${left_side_bearing}") } else { // read the last entry of the hMetrics array tf.pos = offset + (tf.num_of_long_hor_metrics - 1) * 4 @@ -200,7 +204,7 @@ fn (mut tf TTF_File) get_glyph_offset(index u32) u32 { return offset + tf.tables['glyf'].offset } -fn (mut tf TTF_File) glyph_count() u16 { +pub fn (mut tf TTF_File) glyph_count() u16 { assert 'maxp' in tf.tables old_pos := tf.pos tf.pos = tf.tables['maxp'].offset + 4 @@ -233,6 +237,58 @@ pub fn (mut tf TTF_File) read_glyph_dim(index u16) (int, int, int, int) { return x_min, x_max, y_min, y_max } +pub fn (mut tf TTF_File) get_ttf_widths() ([]int, int, int) { + mut space_cw, _ := tf.get_horizontal_metrics(u16(` `)) + // div_space_cw := int((f32(space_cw) * 0.3)) + + // count := int(tf.glyph_count()) + mut min_code := 0xFFFF + 1 + mut max_code := 0 + for i in 0 .. 300 { + glyph_index := tf.map_code(i) + if glyph_index == 0 { + continue + } + // dprintln("$i = glyph_index: $glyph_index ${i:c}") + if i > max_code { + max_code = i + } + if i < min_code { + min_code = i + } + } + // dprintln("min_code: $min_code max_code: $max_code") + mut widths := []int{len: max_code - min_code + 1, init: 0} + + for i in min_code .. max_code { + pos := i - min_code + glyph_index := tf.map_code(i) + + if glyph_index == 0 || i == 32 { + widths[pos] = space_cw + continue + } + + x_min, x_max, _, _ := tf.read_glyph_dim(glyph_index) + aw, lsb := tf.get_horizontal_metrics(u16(glyph_index)) + w := x_max - x_min + rsb := aw - (lsb + w) + + // pp1 := x_min - lsb + // pp2 := pp1 + aw + + w1 := w + lsb + rsb + + widths[pos] = int(w1 / tf.width_scale) + // if i >= int(`A`) && i <= int(`Z`) { + // dprintln("${i:c}|$glyph_index [$pos] => width:${x_max-x_min} aw:${aw}|w1:${w1} lsb:${lsb} rsb:${rsb} pp1:${pp1} pp2:${pp2}") + //} + } + + // dprintln("Widths: ${widths.len}") + return widths, min_code, max_code +} + pub fn (mut tf TTF_File) read_glyph(index u16) Glyph { index_int := int(index) // index.str() if index_int in tf.glyph_cache { @@ -511,7 +567,12 @@ fn (mut tf TTF_File) get_ufword() u16 { } fn (mut tf TTF_File) get_i16() i16 { - return i16(tf.get_u16()) + // return i16(tf.get_u16()) + mut res := u32(tf.get_u16()) + if (res & 0x8000) > 0 { + res -= (u32(1) << 16) + } + return i16(res) } fn (mut tf TTF_File) get_fword() i16 { @@ -526,7 +587,11 @@ fn (mut tf TTF_File) get_u32() u32 { } fn (mut tf TTF_File) get_i32() int { - return int(tf.get_u32()) + mut res := u64(tf.get_u32()) + if (res & 0x8000_0000) > 0 { + res -= (u64(1) << 32) + } + return int(res) } fn (mut tf TTF_File) get_2dot14() f32 {