src/hb-aat-layout-common.hh | 4 src/hb-aat-layout-trak-table.hh | 135 ++++++++++++++---------- src/hb-aat-layout.cc | 25 ++++ src/hb-aat-layout.hh | 8 + src/hb-ot-shape.cc | 2 test/shaping/data/in-house/Makefile.sources | 1 test/shaping/data/in-house/fonts/TestTRAK.ttf |binary test/shaping/data/in-house/tests/aat-trak.tests | 8 + 8 files changed, 126 insertions(+), 57 deletions(-)
New commits: commit 100e95f48e3d137c654d206e858d6419ea62a12c Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 11 11:30:45 2018 -0400 [trak] Add tests diff --git a/test/shaping/data/in-house/Makefile.sources b/test/shaping/data/in-house/Makefile.sources index 1f7eff20..f2402740 100644 --- a/test/shaping/data/in-house/Makefile.sources +++ b/test/shaping/data/in-house/Makefile.sources @@ -1,4 +1,5 @@ TESTS = \ + tests/aat-trak.tests \ tests/arabic-fallback-shaping.tests \ tests/arabic-feature-order.tests \ tests/arabic-like-joining.tests \ diff --git a/test/shaping/data/in-house/fonts/TestTRAK.ttf b/test/shaping/data/in-house/fonts/TestTRAK.ttf new file mode 100644 index 00000000..07ae3afd Binary files /dev/null and b/test/shaping/data/in-house/fonts/TestTRAK.ttf differ diff --git a/test/shaping/data/in-house/tests/aat-trak.tests b/test/shaping/data/in-house/tests/aat-trak.tests new file mode 100644 index 00000000..9e650558 --- /dev/null +++ b/test/shaping/data/in-house/tests/aat-trak.tests @@ -0,0 +1,8 @@ +../fonts/TestTRAK.ttf::U+0041,U+0042,U+0043:[A.alt=0+1000|B=1+1000|C.alt=2+1000] +../fonts/TestTRAK.ttf:--font-ptem=.5:U+0041,U+0042,U+0043:[A.alt=0@100,0+1200|B=1@100,0+1200|C.alt=2@100,0+1200] +../fonts/TestTRAK.ttf:--font-ptem=1:U+0041,U+0042,U+0043:[A.alt=0@100,0+1200|B=1@100,0+1200|C.alt=2@100,0+1200] +../fonts/TestTRAK.ttf:--font-ptem=2:U+0041,U+0042,U+0043:[A.alt=0@93,0+1187|B=1@93,0+1187|C.alt=2@93,0+1187] +../fonts/TestTRAK.ttf:--font-ptem=9:U+0041,U+0042,U+0043:[A.alt=0+1000|B=1+1000|C.alt=2+1000] +../fonts/TestTRAK.ttf:--font-ptem=24:U+0041,U+0042,U+0043:[A.alt=0@-12,0+976|B=1@-12,0+976|C.alt=2@-12,0+976] +../fonts/TestTRAK.ttf:--font-ptem=72:U+0041,U+0042,U+0043:[A.alt=0@-50,0+900|B=1@-50,0+900|C.alt=2@-50,0+900] +../fonts/TestTRAK.ttf:--font-ptem=144:U+0041,U+0042,U+0043:[A.alt=0@-100,0+800|B=1@-100,0+800|C.alt=2@-100,0+800] commit 04f72e8990ea61ffc6b62105c75e0a3e1b1ebab4 Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 11 11:25:07 2018 -0400 [trak] Implement extrapolation This concludes trak, as well as AAT shaping support! diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index b2d69413..e0272175 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -82,6 +82,22 @@ struct TrackTableEntry struct TrackData { + inline float interpolate_at (unsigned int idx, + float target_size, + const TrackTableEntry &trackTableEntry, + const void *base) const + { + unsigned int sizes = nSizes; + hb_array_t<Fixed> 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 (float) t * trackTableEntry.get_value (base, idx + 1, sizes) + + ((float) 1.0 - t) * trackTableEntry.get_value (base, idx, sizes); + return 0; + } + inline float get_tracking (const void *base, float ptem) const { /* CoreText points are CSS pixels (96 per inch), @@ -90,13 +106,10 @@ struct TrackData * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html */ float csspx = ptem * 96.f / 72.f; - Fixed fixed_size; - fixed_size.set_float (csspx); /* * Choose track. */ - const TrackTableEntry *trackTableEntry = nullptr; unsigned int count = nTracks; for (unsigned int i = 0; i < count; i++) @@ -117,31 +130,19 @@ struct TrackData /* * Choose size. */ - unsigned int sizes = nSizes; - if (!sizes) return 0.; if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes); /* TODO bfind() */ - unsigned int size_index; hb_array_t<Fixed> size_table ((base+sizeTable).arrayZ, sizes); + unsigned int size_index; for (size_index = 0; size_index < sizes; size_index++) - if ((int) size_table[size_index] >= (int) fixed_size) + if (size_table[size_index].to_float () >= csspx) break; - // TODO(ebraminio): We don't attempt to extrapolate to larger or - // smaller values for now but we should do, per spec - if (size_index == sizes) - return trackTableEntry->get_value (base, sizes - 1, sizes); - if (size_index == 0 || size_table[size_index] == fixed_size) - return trackTableEntry->get_value (base, size_index, sizes); - - float s0 = size_table[size_index - 1].to_float (); - float s1 = size_table[size_index].to_float (); - float t = (csspx - s0) / (s1 - s0); - return (float) t * trackTableEntry->get_value (base, size_index, sizes) + - ((float) 1.0 - t) * trackTableEntry->get_value (base, size_index - 1, sizes); + return interpolate_at (size_index ? size_index - 1 : 0, csspx, + *trackTableEntry, base); } inline bool sanitize (hb_sanitize_context_t *c, const void *base) const commit d6a12dba6da6262fd9e5d8397b46ac8516136cae Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 11 11:10:06 2018 -0400 [trak] Fix, and hook up Works beautifully! Test coming. diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index 78de04fa..78a27a74 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -540,7 +540,7 @@ struct hb_aat_apply_context_t : inline hb_aat_apply_context_t (hb_ot_shape_plan_t *plan_, hb_font_t *font_, hb_buffer_t *buffer_, - hb_blob_t *table, + hb_blob_t *blob = const_cast<hb_blob_t *> (&Null(hb_blob_t)), const ankr &ankr_table_ = Null(ankr), const char *ankr_end_ = nullptr) : plan (plan_), font (font_), face (font->face), buffer (buffer_), @@ -548,7 +548,7 @@ struct hb_aat_apply_context_t : ankr_table (ankr_table_), ankr_end (ankr_end_), lookup_index (0), debug_depth (0) { - sanitizer.init (table); + sanitizer.init (blob); sanitizer.set_num_glyphs (face->get_num_glyphs ()); sanitizer.start_processing (); sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX); diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index 368c55c1..b2d69413 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -125,9 +125,9 @@ struct TrackData /* TODO bfind() */ unsigned int size_index; - UnsizedArrayOf<Fixed> size_table = base+sizeTable; + hb_array_t<Fixed> size_table ((base+sizeTable).arrayZ, sizes); for (size_index = 0; size_index < sizes; size_index++) - if (size_table[size_index] >= fixed_size) + if ((int) size_table[size_index] >= (int) fixed_size) break; // TODO(ebraminio): We don't attempt to extrapolate to larger or @@ -169,6 +169,8 @@ struct trak { static const hb_tag_t tableTag = HB_AAT_TAG_trak; + inline bool has_data (void) const { return version.to_int () != 0; } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index 73ab06d3..2b86ba8c 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -37,7 +37,7 @@ #include "hb-aat-ltag-table.hh" // Just so we compile it; unused otherwise. /* - * morx/kerx/trak/ankr + * morx/kerx/trak */ static inline const AAT::morx& @@ -82,6 +82,12 @@ _get_ankr (hb_face_t *face, hb_blob_t **blob = nullptr) *blob = hb_ot_face_data (face)->ankr.get_blob (); return ankr; } +static inline const AAT::trak& +_get_trak (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(AAT::trak); + return *(hb_ot_face_data (face)->trak.get ()); +} hb_bool_t @@ -124,3 +130,20 @@ hb_aat_layout_position (hb_ot_shape_plan_t *plan, ankr, ankr_blob->data + ankr_blob->length); kerx.apply (&c); } + +hb_bool_t +hb_aat_layout_has_tracking (hb_face_t *face) +{ + return _get_trak (face).has_data (); +} + +void +hb_aat_layout_track (hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) +{ + const AAT::trak& trak = _get_trak (font->face); + + AAT::hb_aat_apply_context_t c (plan, font, buffer); + trak.apply (&c); +} diff --git a/src/hb-aat-layout.hh b/src/hb-aat-layout.hh index aafc3278..897c26aa 100644 --- a/src/hb-aat-layout.hh +++ b/src/hb-aat-layout.hh @@ -47,4 +47,12 @@ hb_aat_layout_position (hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); +HB_INTERNAL hb_bool_t +hb_aat_layout_has_tracking (hb_face_t *face); + +HB_INTERNAL void +hb_aat_layout_track (hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); + #endif /* HB_AAT_LAYOUT_HH */ diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 75f72eda..3ca54ac8 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -838,6 +838,8 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c) else if (c->plan->apply_kerx) hb_aat_layout_position (c->plan, c->font, c->buffer); + hb_aat_layout_track (c->plan, c->font, c->buffer); + if (!c->plan->apply_kerx) switch (c->plan->shaper->zero_width_marks) { commit 3d7dea6dfdc9e75dcca100a79525aa3736dbe29c Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 11 10:32:08 2018 -0400 [trak] Handle nSizes=0 and 1 diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index 63dd890c..368c55c1 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -93,7 +93,9 @@ struct TrackData Fixed fixed_size; fixed_size.set_float (csspx); - /* XXX Clean this up. Make it work with nSizes==1 and 0. */ + /* + * Choose track. + */ const TrackTableEntry *trackTableEntry = nullptr; unsigned int count = nTracks; @@ -112,8 +114,15 @@ struct TrackData } if (!trackTableEntry) return 0.; + /* + * Choose size. + */ + unsigned int sizes = nSizes; + if (!sizes) return 0.; + if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes); + /* TODO bfind() */ unsigned int size_index; UnsizedArrayOf<Fixed> size_table = base+sizeTable; commit 451f3de521ff1b7f4d3b8ebb2cc0b95d88c9314a Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 11 10:30:32 2018 -0400 [trak] Fix counting diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index 9054922b..63dd890c 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -95,10 +95,9 @@ struct TrackData /* XXX Clean this up. Make it work with nSizes==1 and 0. */ - unsigned int sizes = nSizes; - const TrackTableEntry *trackTableEntry = nullptr; - for (unsigned int i = 0; i < sizes; i++) + unsigned int count = nTracks; + for (unsigned int i = 0; i < count; i++) { /* Note: Seems like the track entries are sorted by values. But the * spec doesn't explicitly say that. It just mentions it in the example. */ @@ -111,9 +110,10 @@ struct TrackData break; } } - if (!trackTableEntry) return 0.; + unsigned int sizes = nSizes; + /* TODO bfind() */ unsigned int size_index; UnsizedArrayOf<Fixed> size_table = base+sizeTable; commit a5be380cae9b49ed85c8620f1921209ef61a72ad Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 11 10:29:02 2018 -0400 [trak] More diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index dbad449b..9054922b 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -98,33 +98,41 @@ struct TrackData unsigned int sizes = nSizes; const TrackTableEntry *trackTableEntry = nullptr; - for (unsigned int i = 0; i < sizes; ++i) - // For now we only seek for track entries with zero tracking value + for (unsigned int i = 0; i < sizes; i++) + { + /* Note: Seems like the track entries are sorted by values. But the + * spec doesn't explicitly say that. It just mentions it in the example. */ + + /* For now we only seek for track entries with zero tracking value */ + if (trackTable[i].get_track_value () == 0.f) - trackTableEntry = &trackTable[0]; + { + trackTableEntry = &trackTable[0]; + break; + } + } - // We couldn't match any, exit if (!trackTableEntry) return 0.; /* TODO bfind() */ unsigned int size_index; UnsizedArrayOf<Fixed> size_table = base+sizeTable; - for (size_index = 0; size_index < sizes; ++size_index) + for (size_index = 0; size_index < sizes; size_index++) if (size_table[size_index] >= fixed_size) break; // TODO(ebraminio): We don't attempt to extrapolate to larger or // smaller values for now but we should do, per spec if (size_index == sizes) - return trackTableEntry->get_value (base, sizes - 1, nSizes); + return trackTableEntry->get_value (base, sizes - 1, sizes); if (size_index == 0 || size_table[size_index] == fixed_size) - return trackTableEntry->get_value (base, size_index, nSizes); + return trackTableEntry->get_value (base, size_index, sizes); float s0 = size_table[size_index - 1].to_float (); float s1 = size_table[size_index].to_float (); float t = (csspx - s0) / (s1 - s0); - return (float) t * trackTableEntry->get_value (base, size_index, nSizes) + - ((float) 1.0 - t) * trackTableEntry->get_value (base, size_index - 1, nSizes); + return (float) t * trackTableEntry->get_value (base, size_index, sizes) + + ((float) 1.0 - t) * trackTableEntry->get_value (base, size_index - 1, sizes); } inline bool sanitize (hb_sanitize_context_t *c, const void *base) const commit d06c4a867f0d383d8c27f2957e646d9e3fe6853b Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 11 10:22:01 2018 -0400 [trak] Only adjust around first glyph Assumes graphemes only have one base glyph. diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index 71f169c5..dbad449b 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -174,24 +174,24 @@ struct trak { const TrackData &trackData = this+horizData; float tracking = trackData.get_tracking (this, ptem); - hb_position_t advance_to_add = c->font->em_scalef_x (tracking / 2); + 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) { - buffer->pos[start].x_offset += advance_to_add; buffer->pos[start].x_advance += advance_to_add; - buffer->pos[end].x_advance += advance_to_add; + buffer->pos[start].x_offset += offset_to_add; } } else { const TrackData &trackData = this+vertData; float tracking = trackData.get_tracking (this, ptem); - hb_position_t advance_to_add = c->font->em_scalef_y (tracking / 2); + 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) { - buffer->pos[start].y_offset += advance_to_add; buffer->pos[start].y_advance += advance_to_add; - buffer->pos[end].y_advance += advance_to_add; + buffer->pos[start].y_offset += offset_to_add; } } commit 071a2cbcddcbafae9458e674c21db5001b39518d Author: Behdad Esfahbod <[email protected]> Date: Thu Oct 11 10:18:46 2018 -0400 [trak] Clean up diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index 3b7d4388..71f169c5 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -46,28 +46,32 @@ struct TrackTableEntry { friend struct TrackData; - inline bool sanitize (hb_sanitize_context_t *c, const void *base, - unsigned int size) const + inline float get_track_value () const { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - (valuesZ.sanitize (c, base, size)))); + return track.to_float (); } - private: - inline float get_track_value () const + inline int get_value (const void *base, + unsigned int index, + unsigned int nSizes) const { - return track.to_float (); + return hb_array_t<FWORD> ((base+valuesZ).arrayZ, nSizes)[index]; } - inline int get_value (const void *base, unsigned int index) const + public: + inline bool sanitize (hb_sanitize_context_t *c, const void *base, + unsigned int nSizes) const { - return (base+valuesZ)[index]; + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + (valuesZ.sanitize (c, base, nSizes)))); } protected: Fixed track; /* Track value for this record. */ - NameID trackNameID; /* The 'name' table index for this track */ + NameID trackNameID; /* The 'name' table index for this track. + * (a short word or phrase like "loose" + * or "very tight") */ OffsetTo<UnsizedArrayOf<FWORD>, HBUINT16, false> valuesZ; /* Offset from start of tracking table to * per-size tracking values for this track. */ @@ -78,14 +82,6 @@ struct TrackTableEntry struct TrackData { - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - sizeTable.sanitize (c, base, nSizes) && - trackTable.sanitize (c, nTracks, base, nSizes)); - } - inline float get_tracking (const void *base, float ptem) const { /* CoreText points are CSS pixels (96 per inch), @@ -120,22 +116,31 @@ struct TrackData // TODO(ebraminio): We don't attempt to extrapolate to larger or // smaller values for now but we should do, per spec if (size_index == sizes) - return trackTableEntry->get_value (base, sizes - 1); + return trackTableEntry->get_value (base, sizes - 1, nSizes); if (size_index == 0 || size_table[size_index] == fixed_size) - return trackTableEntry->get_value (base, size_index); + return trackTableEntry->get_value (base, size_index, nSizes); float s0 = size_table[size_index - 1].to_float (); float s1 = size_table[size_index].to_float (); float t = (csspx - s0) / (s1 - s0); - return (float) t * trackTableEntry->get_value (base, size_index) + - ((float) 1.0 - t) * trackTableEntry->get_value (base, size_index - 1); + return (float) t * trackTableEntry->get_value (base, size_index, nSizes) + + ((float) 1.0 - t) * trackTableEntry->get_value (base, size_index - 1, nSizes); + } + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + sizeTable.sanitize (c, base, nSizes) && + trackTable.sanitize (c, nTracks, base, nSizes)); } protected: HBUINT16 nTracks; /* Number of separate tracks included in this table. */ HBUINT16 nSizes; /* Number of point sizes included in this table. */ LOffsetTo<UnsizedArrayOf<Fixed>, false> - sizeTable; /* Offset to array[nSizes] of size values. */ + sizeTable; /* Offset from start of the tracking table to + * Array[nSizes] of size values.. */ UnsizedArrayOf<TrackTableEntry> trackTable; /* Array[nTracks] of TrackTableEntry records. */ @@ -194,15 +199,17 @@ struct trak } protected: - FixedVersion<> version; /* Version of the tracking table--currently - * 0x00010000u for version 1.0. */ - HBUINT16 format; /* Format of the tracking table */ - OffsetTo<TrackData> horizData; /* TrackData for horizontal text */ - OffsetTo<TrackData> vertData; /* TrackData for vertical text */ + FixedVersion<> version; /* Version of the tracking table + * (0x00010000u for version 1.0). */ + HBUINT16 format; /* Format of the tracking table (set to 0). */ + OffsetTo<TrackData> horizData; /* Offset from start of tracking table to TrackData + * for horizontal text (or 0 if none). */ + OffsetTo<TrackData> vertData; /* Offset from start of tracking table to TrackData + * for vertical text (or 0 if none). */ HBUINT16 reserved; /* Reserved. Set to 0. */ public: - DEFINE_SIZE_MIN (12); + DEFINE_SIZE_STATIC (12); }; } /* namespace AAT */ _______________________________________________ HarfBuzz mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/harfbuzz
