diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index da29ab9f0..93ad558c5 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -48,17 +48,69 @@ struct TrackTableEntry float get_track_value () const { return track.to_float (); } - int get_value (const void *base, unsigned int index, - unsigned int table_size) const - { return (base+valuesZ).as_array (table_size)[index]; } + float interpolate_at (unsigned int idx, + float ptem, + const void *base, + hb_array_t size_table) const + { + const FWORD *values = (base+valuesZ).arrayZ; + + float s0 = size_table[idx].to_float (); + float s1 = size_table[idx + 1].to_float (); + int v0 = values[idx]; + int v1 = values[idx + 1]; + + // Deal with font bugs. + if (unlikely (s1 < s0)) + { hb_swap (s0, s1); hb_swap (v0, v1); } + if (unlikely (ptem < s0)) return v0; + if (unlikely (ptem > s1)) return v1; + if (unlikely (s0 == s1)) return (v0 + v1) * 0.5f; + + float t = (ptem - s0) / (s1 - s0); + return v0 + t * (v1 - v0); + } + + float get_value (float ptem, + const void *base, + hb_array_t size_table) const + { + const FWORD *values = (base+valuesZ).arrayZ; + + unsigned int n_sizes = size_table.length; + + /* + * Choose size. + */ + if (!n_sizes) return 0.f; + if (n_sizes == 1) return values[0]; + + // At least two entries. + + unsigned i; + for (i = 0; i < n_sizes; i++) + if (size_table[i].to_float () >= ptem) + break; + + // Boundary conditions. + if (i == 0) return values[0]; + if (i == n_sizes) return values[n_sizes - 1]; + + // Exact match. + if (size_table[i].to_float () == ptem) return values[i]; + + // Interpolate. + return interpolate_at (i - 1, ptem, base, size_table); + } public: - bool sanitize (hb_sanitize_context_t *c, const void *base, - unsigned int table_size) const + bool sanitize (hb_sanitize_context_t *c, + const void *base, + unsigned int n_sizes) const { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && - (valuesZ.sanitize (c, base, table_size)))); + (valuesZ.sanitize (c, base, n_sizes)))); } protected: @@ -76,22 +128,7 @@ struct TrackTableEntry struct TrackData { - float interpolate_at (unsigned int idx, - float target_size, - const TrackTableEntry &trackTableEntry, - const void *base) const - { - unsigned int sizes = nSizes; - hb_array_t size_table ((base+sizeTable).arrayZ, sizes); - - float s0 = size_table[idx].to_float (); - float s1 = size_table[idx + 1].to_float (); - float t = unlikely (s0 == s1) ? 0.f : (target_size - s0) / (s1 - s0); - return t * trackTableEntry.get_value (base, idx + 1, sizes) + - (1.f - t) * trackTableEntry.get_value (base, idx, sizes); - } - - int get_tracking (const void *base, float ptem) const + float get_tracking (const void *base, float ptem) const { /* * Choose track. @@ -116,30 +153,9 @@ struct TrackData } if (!trackTableEntry) return 0; - /* - * Choose size. - */ - count = nSizes; - if (!count) return 0; - if (count == 1) return trackTableEntry->get_value (base, 0, count); - - // At least two entries. - - hb_array_t size_table ((base+sizeTable).arrayZ, count); - unsigned int size_index; - for (size_index = 0; size_index < count; size_index++) - if (size_table[size_index].to_float () >= ptem) - break; - - if (size_index == 0) - return trackTableEntry->get_value (base, 0, count); - if (size_index == count) - return trackTableEntry->get_value (base, count - 1, count); - - // Interpolate. - - return roundf (interpolate_at (size_index - 1, ptem, - *trackTableEntry, base)); + return trackTableEntry->get_value (ptem, + base, + (base+sizeTable).as_array (nSizes)); } bool sanitize (hb_sanitize_context_t *c, const void *base) const @@ -187,7 +203,7 @@ struct trak if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) { const TrackData &trackData = this+horizData; - int tracking = trackData.get_tracking (this, ptem); + float tracking = trackData.get_tracking (this, ptem); hb_position_t offset_to_add = c->font->em_scalef_x (tracking / 2); hb_position_t advance_to_add = c->font->em_scalef_x (tracking); foreach_grapheme (buffer, start, end) @@ -200,7 +216,7 @@ struct trak else { const TrackData &trackData = this+vertData; - int tracking = trackData.get_tracking (this, ptem); + float tracking = trackData.get_tracking (this, ptem); hb_position_t offset_to_add = c->font->em_scalef_y (tracking / 2); hb_position_t advance_to_add = c->font->em_scalef_y (tracking); foreach_grapheme (buffer, start, end) diff --git a/test/shape/data/in-house/tests/aat-trak.tests b/test/shape/data/in-house/tests/aat-trak.tests index 63ca941a4..b293fbc2e 100644 --- a/test/shape/data/in-house/tests/aat-trak.tests +++ b/test/shape/data/in-house/tests/aat-trak.tests @@ -4,7 +4,7 @@ ../fonts/TRAK.ttf;--font-ptem=2;U+0041,U+0042,U+0043;[A.alt=0@100,0+1200|B=1@100,0+1200|C.alt=2@100,0+1200] ../fonts/TRAK.ttf;--font-ptem=9;U+0041,U+0042,U+0043;[A.alt=0@30,0+1060|B=1@30,0+1060|C.alt=2@30,0+1060] ../fonts/TRAK.ttf;--font-ptem=24;U+0041,U+0042,U+0043;[A.alt=0@-7,0+986|B=1@-7,0+986|C.alt=2@-7,0+986] -../fonts/TRAK.ttf;--font-ptem=72;U+0041,U+0042,U+0043;[A.alt=0@-35,0+929|B=1@-35,0+929|C.alt=2@-35,0+929] +../fonts/TRAK.ttf;--font-ptem=72;U+0041,U+0042,U+0043;[A.alt=0@-36,0+929|B=1@-36,0+929|C.alt=2@-36,0+929] ../fonts/TRAK.ttf;--font-ptem=144;U+0041,U+0042,U+0043;[A.alt=0@-50,0+900|B=1@-50,0+900|C.alt=2@-50,0+900] ../fonts/TRAK.ttf;--font-ptem=144 --features=-trak;U+0041,U+0042,U+0043;[A.alt=0+1000|B=1+1000|C.alt=2+1000] ../fonts/TRAK.ttf;--font-ptem=144 --features=-trak[1:3];U+0041,U+0042,U+0043,U+0041,U+0042,U+0043;[A.alt=0@-50,0+900|B=1+1000|C.alt=2+1000|A.alt=3@-50,0+900|B=4@-50,0+900|C.alt=5@-50,0+900]