CMakeLists.txt | 24 src/Makefile.sources | 1 src/dev-run.sh | 22 src/hb-aat-layout-kerx-table.hh | 377 ++++++++++ src/hb-aat-layout.cc | 1 src/hb-ot-layout-gpos-table.hh | 5 src/hb-ot-layout-private.hh | 2 test/api/CMakeLists.txt | 2 test/shaping/data/in-house/fonts/573d3a3177c9a8646e94c8a0d7b224334340946a.ttf |binary test/shaping/data/in-house/tests/use.tests | 1 10 files changed, 422 insertions(+), 13 deletions(-)
New commits: commit 1c50a88623a881a9e2b2b0f1f6a783962626f03a Author: Behdad Esfahbod <[email protected]> Date: Sun Feb 18 15:57:09 2018 -0800 Readjust mark attachment heuristic a bit more Previously adjusted logic could fail if nothing around was ligated, and something moved. This should take care of that. CC https://github.com/harfbuzz/harfbuzz/issues/740 diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 5b1bc6ab..4e1a10d7 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -1079,7 +1079,10 @@ struct MarkBasePosFormat1 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) || (skippy_iter.idx == 0 || _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) != - _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]))) + _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) || + _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) != + _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1 + )) break; skippy_iter.reject (); } while (1); commit 246e280d88b6b26757297a349f01e52c15eaec53 Author: Behdad Esfahbod <[email protected]> Date: Sun Feb 18 15:42:25 2018 -0800 [test] Add test for https://github.com/harfbuzz/harfbuzz/issues/740 diff --git a/test/shaping/data/in-house/fonts/573d3a3177c9a8646e94c8a0d7b224334340946a.ttf b/test/shaping/data/in-house/fonts/573d3a3177c9a8646e94c8a0d7b224334340946a.ttf new file mode 100644 index 00000000..2fc9e9cf Binary files /dev/null and b/test/shaping/data/in-house/fonts/573d3a3177c9a8646e94c8a0d7b224334340946a.ttf differ diff --git a/test/shaping/data/in-house/tests/use.tests b/test/shaping/data/in-house/tests/use.tests index f83f6f9a..172946c4 100644 --- a/test/shaping/data/in-house/tests/use.tests +++ b/test/shaping/data/in-house/tests/use.tests @@ -2,3 +2,4 @@ ../fonts/4cce528e99f600ed9c25a2b69e32eb94a03b4ae8.ttf::U+1A48,U+1A58,U+1A25,U+1A48,U+1A58,U+1A25,U+1A6E,U+1A63:[uni1A48=0+1212|uni1A25=0+1912|uni1A58=0+0|uni1A48=3+1212|uni1A6E=3+0|uni1A25=3+1912|uni1A58=3+0|uni1A63=3+1212] ../fonts/f518eb6f6b5eec2946c9fbbbde44e45d46f5e2ac.ttf::U+1A48,U+1A58,U+1A25,U+1A48,U+1A58,U+1A25,U+1A6E,U+1A63:[uni1A48=0+1212|uni1A25=0+1912|uni1A58=0+0|uni1A48=3+1212|uni1A6E=3+1211|uni1A25=3+1912|uni1A58=3+0|uni1A63=3+1212] ../fonts/6ff0fbead4462d9f229167b4e6839eceb8465058.ttf:--font-funcs=ot:U+11103,U+11128:[u11103=0+837|u11128=0+0] +../fonts/573d3a3177c9a8646e94c8a0d7b224334340946a.ttf:--font-funcs=ft:U+11410,U+11442,U+11411,U+11440,U+11443,U+11410,U+11442,U+11411,U+11441,U+11443:[E_dv.alt=0+275|Ga.icd=0+367|Gha.diag=0@100,0+386|AA_dv.alt=0+208|Candrabindu=0@17,-8+0|E_dv.alt=5+275|Ga.icd=5+367|Gha.diag=5@100,0+386|AU_dv_part.alt=5+213|Candrabindu.sm=5@-52,179+0] commit 79756c9039a628b0df441228ca1ea20b8a91e3e8 Author: Ebrahim Byagowi <[email protected]> Date: Mon Feb 19 03:17:44 2018 +0330 [aat] First dig on 'kerx' (#704) diff --git a/src/Makefile.sources b/src/Makefile.sources index ec60ec0a..3a73bc00 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -82,6 +82,7 @@ HB_FALLBACK_sources = \ HB_OT_sources = \ hb-aat-layout.cc \ hb-aat-layout-common-private.hh \ + hb-aat-layout-kerx-table.hh \ hb-aat-layout-morx-table.hh \ hb-aat-layout-private.hh \ hb-ot-font.cc \ diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh new file mode 100644 index 00000000..4a40d1c2 --- /dev/null +++ b/src/hb-aat-layout-kerx-table.hh @@ -0,0 +1,377 @@ +/* + * Copyright © 2018 Google, Inc. + * Copyright © 2018 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_AAT_LAYOUT_KERX_TABLE_HH +#define HB_AAT_LAYOUT_KERX_TABLE_HH + +#include "hb-aat-layout-common-private.hh" + +namespace AAT { + + +/* + * kerx -- Kerning + */ + +#define HB_AAT_TAG_kerx HB_TAG('k','e','r','x') + +struct hb_glyph_pair_t +{ + hb_codepoint_t left; + hb_codepoint_t right; +}; + +struct KerxPair +{ + inline int get_kerning (void) const + { return value; } + + inline int cmp (const hb_glyph_pair_t &o) const + { + int ret = left.cmp (o.left); + if (ret) return ret; + return right.cmp (o.right); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + GlyphID left; + GlyphID right; + FWORD value; + HBUINT16 pad; + public: + DEFINE_SIZE_STATIC (8); +}; + +struct KerxSubTableFormat0 +{ + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const + { + hb_glyph_pair_t pair = {left, right}; + //int i = pairs.bsearch (pair); + //if (i == -1) + return 0; + //return pairs[i].get_kerning (); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (pairs.sanitize (c)); + } + + protected: + BinSearchArrayOf<KerxPair> pairs; /* Array of kerning pairs. */ + //FIXME: BinSearchArrayOf and its BinSearchHeader should be + //modified in a way to accept uint32s + public: + //DEFINE_SIZE_ARRAY (16, pairs); +}; + +struct KerxAction +{ + HBUINT16 index; +}; + +struct KerxSubTableFormat1 +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + //TRACE_SANITIZE (this); + //return_trace (stateHeader.sanitize (c)); + return false; + } + + protected: + StateTable<KerxAction> stateHeader; + OffsetTo<ArrayOf<HBUINT16>, HBUINT32> valueTable; + + public: + //DEFINE_SIZE_MIN (4); +}; + +//FIXME: Maybe this can be replaced with Lookup<HBUINT16>? +struct KerxClassTable +{ + inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (firstGlyph.sanitize (c) && classes.sanitize (c)); + } + + protected: + HBUINT16 firstGlyph; /* First glyph in class range. */ + ArrayOf<HBUINT16> classes; /* Glyph classes. */ + public: + DEFINE_SIZE_ARRAY (4, classes); +}; + +struct KerxSubTableFormat2 +{ + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const + { + unsigned int l = (this+leftClassTable).get_class (left); + unsigned int r = (this+leftClassTable).get_class (left); + unsigned int offset = l * rowWidth + r * sizeof (FWORD); + const FWORD *arr = &(this+array); + if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end)) + return 0; + const FWORD *v = &StructAtOffset<FWORD> (arr, offset); + if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end)) + return 0; + return *v; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (rowWidth.sanitize (c) && + leftClassTable.sanitize (c, this) && + rightClassTable.sanitize (c, this) && + array.sanitize (c, this)); + } + + protected: + HBUINT32 rowWidth; /* The width, in bytes, of a row in the table. */ + LOffsetTo<KerxClassTable> + leftClassTable; /* Offset from beginning of this subtable to + * left-hand class table. */ + LOffsetTo<KerxClassTable> + rightClassTable;/* Offset from beginning of this subtable to + * right-hand class table. */ + LOffsetTo<FWORD> + array; /* Offset from beginning of this subtable to + * the start of the kerning array. */ + public: + DEFINE_SIZE_MIN (16); +}; + +struct KerxSubTableFormat4 +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (rowWidth.sanitize (c) && + leftClassTable.sanitize (c, this) && + rightClassTable.sanitize (c, this) && + array.sanitize (c, this)); + } + + protected: + HBUINT32 rowWidth; /* The width, in bytes, of a row in the table. */ + LOffsetTo<KerxClassTable> + leftClassTable; /* Offset from beginning of this subtable to + * left-hand class table. */ + LOffsetTo<KerxClassTable> + rightClassTable;/* Offset from beginning of this subtable to + * right-hand class table. */ + LOffsetTo<FWORD> + array; /* Offset from beginning of this subtable to + * the start of the kerning array. */ + public: + DEFINE_SIZE_MIN (16); +}; + +struct KerxSubTableFormat6 +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + //TRACE_SANITIZE (this); + //return_trace ; + return false; + } + + protected: + HBUINT32 flags; + HBUINT16 rowCount; + HBUINT16 columnCount; + HBUINT32 rowIndexTableOffset; + HBUINT32 columnIndexTableOffset; + HBUINT32 kerningArrayOffset; + HBUINT32 kerningVectorOffset; + + public: + DEFINE_SIZE_MIN (24); +}; + +struct KerxSubTable +{ + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const + { + switch (format) { + case 0: return u.format0.get_kerning (left, right); + case 2: return u.format2.get_kerning (left, right, end); + default:return 0; + } + } + + inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const + { + TRACE_SANITIZE (this); + switch (format) { + case 0: return_trace (u.format0.sanitize (c)); + case 2: return_trace (u.format2.sanitize (c)); + default:return_trace (true); + } + } + + protected: + union { + KerxSubTableFormat0 format0; + KerxSubTableFormat2 format2; + KerxSubTableFormat4 format4; + KerxSubTableFormat6 format6; + } u; + public: + DEFINE_SIZE_MIN (0); +}; + + + +struct kerx +{ + static const hb_tag_t tableTag = HB_AAT_TAG_kerx; + + struct SubTableWrapper + { + enum coverage_flags_t { + COVERAGE_VERTICAL_FLAG = 0x8000u, + COVERAGE_CROSSSTREAM_FLAG = 0x4000u, + COVERAGE_VARIATION_FLAG = 0x2000u, + + COVERAGE_OVERRIDE_FLAG = 0x0000u, /* Not supported. */ + + COVERAGE_CHECK_FLAGS = 0x0700u, //FIXME: Where these two come from? + COVERAGE_CHECK_HORIZONTAL = 0x0100u + }; + + protected: + HBUINT32 length; /* Length of the subtable (including this header). */ + HBUINT16 coverage; /* Coverage bits. */ + HBUINT16 format; /* Subtable format. */ + HBUINT32 tupleIndex; /* The tuple index (used for variations fonts). + * This value specifies which tuple this subtable covers. */ + KerxSubTable subtable; /* Subtable data. */ + public: + inline bool is_horizontal (void) const + { return (coverage & COVERAGE_CHECK_FLAGS) == COVERAGE_CHECK_HORIZONTAL; } + + inline bool is_override (void) const + { return bool (coverage & COVERAGE_OVERRIDE_FLAG); } + + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const + { return subtable.get_kerning (left, right, end, format); } + + inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const + { return is_horizontal () ? get_kerning (left, right, end) : 0; } + + inline unsigned int get_size (void) const { return length; } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + length >= min_size && + c->check_array (this, 1, length) && + subtable.sanitize (c, format)); + } + DEFINE_SIZE_MIN (12); + }; + + inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const + { + int v = 0; + const SubTableWrapper *st = (SubTableWrapper *) data; + unsigned int count = nTables; + for (unsigned int i = 0; i < count; i++) + { + if (st->is_override ()) + v = 0; + v += st->get_h_kerning (left, right, table_length + (const char *) this); + st = (SubTableWrapper *) st; + } + return v; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + const SubTableWrapper *st = (SubTableWrapper *) data; + unsigned int count = nTables; + for (unsigned int i = 0; i < count; i++) + { + if (unlikely (!st->sanitize (c))) + return_trace (false); + st = (SubTableWrapper *) st; + } + + return_trace (true); + } + + struct accelerator_t + { + inline void init (hb_face_t *face) + { + blob = Sanitizer<kerx>().sanitize (face->reference_table (HB_AAT_TAG_kerx)); + table = Sanitizer<kerx>::lock_instance (blob); + table_length = hb_blob_get_length (blob); + } + inline void fini (void) + { + hb_blob_destroy (blob); + } + + inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const + { return table->get_h_kerning (left, right, table_length); } + + private: + hb_blob_t *blob; + const kerx *table; + unsigned int table_length; + }; + + protected: + HBUINT16 version; + HBUINT16 padding; + HBUINT32 nTables; /* Number of subtables in the kerning table. */ + HBUINT8 data[VAR]; + //ArrayOf<GlyphCoverageArray> subtableGlyphCoverageArray; + public: + DEFINE_SIZE_ARRAY (8, data); +}; + +} /* namespace AAT */ + + +#endif /* HB_AAT_LAYOUT_KERX_TABLE_HH */ diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index d882fa16..b1b1c741 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -30,6 +30,7 @@ #include "hb-ot-layout-gsubgpos-private.hh" #include "hb-aat-layout-private.hh" +#include "hb-aat-layout-kerx-table.hh" #include "hb-aat-layout-morx-table.hh" /* diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index 60119629..cf691d37 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -131,6 +131,7 @@ namespace OT { } namespace AAT { + struct kerx; struct morx; } @@ -169,6 +170,7 @@ struct hb_ot_layout_t OT::hb_lazy_table_loader_t<struct OT::MATH> math; OT::hb_lazy_table_loader_t<struct OT::fvar> fvar; OT::hb_lazy_table_loader_t<struct OT::avar> avar; + OT::hb_lazy_table_loader_t<struct AAT::kerx> kerx; OT::hb_lazy_table_loader_t<struct AAT::morx> morx; unsigned int gsub_lookup_count; commit 279c70a5b36446f444e5d2f4ac1db7614c8a3db8 Merge: e9164478 89b82814 Author: Behdad Esfahbod <[email protected]> Date: Sun Feb 18 14:04:33 2018 -0800 Merge pull request #796 from ebraminio/dev-run Add a continuous builder using fswatch commit 89b82814b605d2bfcc481a47607e642a928dff15 Author: Ebrahim Byagowi <[email protected]> Date: Fri Feb 16 12:53:33 2018 +0330 Add a continuous builder using fswatch diff --git a/CMakeLists.txt b/CMakeLists.txt index d23fc2df..0c19a4b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,7 @@ if (HB_HAVE_INTROSPECTION) set (HB_HAVE_GLIB ON) endif () +option(HB_DISABLE_TEST_PROGS OFF "Do not build some of the test programs, useful for continuous builds") option(HB_CHECK OFF "Do a configuration suitable for testing (shared library and enable all options)") if (HB_CHECK) set (BUILD_SHARED_LIBS ON) @@ -807,17 +808,18 @@ endif () ## src/ executables -foreach (prog main test test-would-substitute test-size-params test-buffer-serialize hb-ot-tag) - set (prog_name ${prog}) - if (${prog_name} STREQUAL "test") - # test can not be used as a valid executable name on cmake, lets special case it - set (prog_name test-test) - endif () - add_executable(${prog_name} ${PROJECT_SOURCE_DIR}/src/${prog}.cc) - target_link_libraries(${prog_name} harfbuzz ${THIRD_PARTY_LIBS}) -endforeach () -set_target_properties(hb-ot-tag PROPERTIES COMPILE_FLAGS "-DMAIN") - +if (NOT HB_DISABLE_TEST_PROGS) + foreach (prog main test test-would-substitute test-size-params test-buffer-serialize hb-ot-tag) + set (prog_name ${prog}) + if (${prog_name} STREQUAL "test") + # test can not be used as a valid executable name on cmake, lets special case it + set (prog_name test-test) + endif () + add_executable(${prog_name} ${PROJECT_SOURCE_DIR}/src/${prog}.cc) + target_link_libraries(${prog_name} harfbuzz ${THIRD_PARTY_LIBS}) + endforeach () + set_target_properties(hb-ot-tag PROPERTIES COMPILE_FLAGS "-DMAIN") +endif () ## Tests if (UNIX OR MINGW) diff --git a/src/dev-run.sh b/src/dev-run.sh new file mode 100755 index 00000000..f713ce82 --- /dev/null +++ b/src/dev-run.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +for cmd in cmake ninja fswatch; do + command -v $cmd >/dev/null 2>&1 || { echo >&2 "This script needs $cmd be installed"; exit 1; } +done + +[ $# = 0 ] && echo Usage: "src/dev-run.sh [FONT-FILE] [TEXT]" && exit + +cmake -DHB_CHECK=ON -DHB_DISABLE_TEST_PROGS=ON -Bbuild -H. -GNinja +ninja -Cbuild + +# or "fswatch -0 . -e build/ -e .git" +find src/ | entr printf '\0' | while read -d "" event; do + clear + ninja -Cbuild + build/hb-shape $@ + build/hb-view $@ +done + +cmake -DHB_CHECK=ON -DHB_DISABLE_TEST_PROGS=OFF -Bbuild -H. -GNinja +ninja -Cbuild +CTEST_OUTPUT_ON_FAILURE=1 CTEST_PARALLEL_LEVEL=8 ninja -Cbuild test diff --git a/test/api/CMakeLists.txt b/test/api/CMakeLists.txt index f1a2300f..6a62b656 100644 --- a/test/api/CMakeLists.txt +++ b/test/api/CMakeLists.txt @@ -1,4 +1,4 @@ -if (HB_HAVE_GLIB) +if (HB_HAVE_GLIB AND NOT HB_DISABLE_TEST_PROGS) file (READ "${CMAKE_CURRENT_SOURCE_DIR}/Makefile.am" MAKEFILEAM) extract_make_variable (TEST_PROGS ${MAKEFILEAM}) _______________________________________________ HarfBuzz mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/harfbuzz
