diff --git a/.circleci/config.yml b/.circleci/config.yml
index 1c901ebf1..9eeb1549e 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -235,15 +235,6 @@ jobs:
- run: CFLAGS="-Wno-attributes" CXXFLAGS="-Wno-attributes" ./autogen.sh --prefix=/usr/local/djgpp --host=i586-pc-msdosdjgpp
- run: make -j32
- crosscompile-notest-freebsd9:
- docker:
- - image: donbowman/freebsd-cross-build
- steps:
- - checkout
- - run: apt update && apt install -y pkg-config ragel
- - run: ./autogen.sh --prefix=/freebsd --host=x86_64-pc-freebsd9
- - run: make -j32
-
crosscompile-notest-psvita:
docker:
- image: dockcross/base
@@ -327,7 +318,6 @@ workflows:
# they can't be test thus are without tests
## autotools
- crosscompile-notest-djgpp
- - crosscompile-notest-freebsd9
- crosscompile-notest-psvita
## cmake
diff --git a/.editorconfig b/.editorconfig
index 499147351..4850f2bf6 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -9,7 +9,7 @@ insert_final_newline = true
[*.{c,cc,h,hh}]
tab_width = 8
indent_size = 2
-indent_style = space
+indent_style = tab # should be space
[*.{py,sh}]
indent_style = tab
diff --git a/AUTHORS b/AUTHORS
index 0763761bb..83c0c66f9 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,11 +1,14 @@
Behdad Esfahbod
+David Corbett
David Turner
Ebrahim Byagowi
+Garret Rieger
Jonathan Kew
Khaled Hosny
Lars Knoll
Martin Hosken
Owen Taylor
+Roderick Sheeter
Roozbeh Pournader
Simon Hausmann
Werner Lemberg
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f64f96d1c..a8d12c163 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -844,7 +844,7 @@ endif ()
if (HB_BUILD_TESTS)
## src/ executables
- foreach (prog main test test-would-substitute test-size-params test-buffer-serialize hb-ot-tag test-unicode-ranges)
+ foreach (prog main test test-gsub-would-substitute test-gpos-size-params test-buffer-serialize hb-ot-tag test-unicode-ranges)
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
diff --git a/COPYING b/COPYING
index 9d1056f40..0278e60a5 100644
--- a/COPYING
+++ b/COPYING
@@ -2,7 +2,8 @@ HarfBuzz is licensed under the so-called "Old MIT" license. Details follow.
For parts of HarfBuzz that are licensed under different licenses see individual
files names COPYING in subdirectories where applicable.
-Copyright © 2010,2011,2012 Google, Inc.
+Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019 Google, Inc.
+Copyright © 2019 Facebook, Inc.
Copyright © 2012 Mozilla Foundation
Copyright © 2011 Codethink Limited
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
diff --git a/THANKS b/THANKS
index 940cfde5c..88cb7e9ea 100644
--- a/THANKS
+++ b/THANKS
@@ -1,6 +1,6 @@
Bradley Grainger
-Khaled Hosny
Kenichi Ishibashi
+Ivan Kuckir
Ryan Lortie
Jeff Muizelaar
suzuki toshiya
diff --git a/docs/harfbuzz-docs.xml b/docs/harfbuzz-docs.xml
index f4ad134ea..e48d17593 100644
--- a/docs/harfbuzz-docs.xml
+++ b/docs/harfbuzz-docs.xml
@@ -20,11 +20,7 @@
The canonical source-code tree is available at
- github.com/harfbuzz/harfbuzz
- and is also available at
- cgit.freedesktop.org/harfbuzz.
+ github.com/harfbuzz/harfbuzz.
See for
release tarballs.
diff --git a/src/Makefile.am b/src/Makefile.am
index 66a3b3177..9b5512f20 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -310,9 +310,9 @@ noinst_PROGRAMS = \
main \
test \
test-buffer-serialize \
- test-name-table \
- test-size-params \
- test-would-substitute \
+ test-ot-name \
+ test-gpos-size-params \
+ test-gsub-would-substitute \
$(NULL)
bin_PROGRAMS =
@@ -328,17 +328,17 @@ test_buffer_serialize_SOURCES = test-buffer-serialize.cc
test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
-test_name_table_SOURCES = test-name-table.cc
-test_name_table_CPPFLAGS = $(HBCFLAGS)
-test_name_table_LDADD = libharfbuzz.la $(HBLIBS)
+test_ot_name_SOURCES = test-ot-name.cc
+test_ot_name_CPPFLAGS = $(HBCFLAGS)
+test_ot_name_LDADD = libharfbuzz.la $(HBLIBS)
-test_size_params_SOURCES = test-size-params.cc
-test_size_params_CPPFLAGS = $(HBCFLAGS)
-test_size_params_LDADD = libharfbuzz.la $(HBLIBS)
+test_gpos_size_params_SOURCES = test-gpos-size-params.cc
+test_gpos_size_params_CPPFLAGS = $(HBCFLAGS)
+test_gpos_size_params_LDADD = libharfbuzz.la $(HBLIBS)
-test_would_substitute_SOURCES = test-would-substitute.cc
-test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
-test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
+test_gsub_would_substitute_SOURCES = test-gsub-would-substitute.cc
+test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
+test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
if HAVE_FREETYPE
if HAVE_CAIRO_FT
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 5c2e02bca..289e12601 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -86,7 +86,7 @@ HB_BASE_sources = \
hb-ot-math-table.hh \
hb-ot-math.cc \
hb-ot-maxp-table.hh \
- hb-ot-name-language.cc \
+ hb-ot-name-language-static.hh \
hb-ot-name-language.hh \
hb-ot-name-table.hh \
hb-ot-name.cc \
diff --git a/src/gen-use-table.py b/src/gen-use-table.py
index 029e66e53..1a33b8af5 100755
--- a/src/gen-use-table.py
+++ b/src/gen-use-table.py
@@ -48,6 +48,12 @@ defaults = ('Other', 'Not_Applicable', 'Cn', 'No_Block')
# TODO Characters that are not in Unicode Indic files, but used in USE
data[0][0x034F] = defaults[0]
data[0][0x2060] = defaults[0]
+# TODO https://github.com/harfbuzz/harfbuzz/pull/1685
+data[0][0x1B5B] = 'Consonant_Placeholder'
+data[0][0x1B5C] = 'Consonant_Placeholder'
+data[0][0x1B5F] = 'Consonant_Placeholder'
+data[0][0x1B62] = 'Consonant_Placeholder'
+data[0][0x1B68] = 'Consonant_Placeholder'
# TODO https://github.com/roozbehp/unicode-data/issues/9
data[0][0x11C44] = 'Consonant_Placeholder'
data[0][0x11C45] = 'Consonant_Placeholder'
@@ -171,7 +177,7 @@ def is_BASE(U, UISC, UGC):
def is_BASE_IND(U, UISC, UGC):
#SPEC-DRAFT return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po)
return (UISC in [Consonant_Dead, Modifying_Letter] or
- (UGC == Po and not U in [0x104B, 0x104E, 0x2022, 0x111C8, 0x11A3F, 0x11A45, 0x11C44, 0x11C45]) or
+ (UGC == Po and not U in [0x104B, 0x104E, 0x1B5B, 0x1B5C, 0x1B5F, 0x2022, 0x111C8, 0x11A3F, 0x11A45, 0x11C44, 0x11C45]) or
False # SPEC-DRAFT-OUTDATED! U == 0x002D
)
def is_BASE_NUM(U, UISC, UGC):
@@ -228,7 +234,7 @@ def is_REPHA(U, UISC, UGC):
def is_SYM(U, UISC, UGC):
if U == 0x25CC: return False #SPEC-DRAFT
#SPEC-DRAFT return UGC in [So, Sc] or UISC == Symbol_Letter
- return UGC in [So, Sc]
+ return UGC in [So, Sc] and U not in [0x1B62, 0x1B68]
def is_SYM_MOD(U, UISC, UGC):
return U in [0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73]
def is_VARIATION_SELECTOR(U, UISC, UGC):
diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh
index 2508276c2..7c74d7938 100644
--- a/src/hb-aat-layout-common.hh
+++ b/src/hb-aat-layout-common.hh
@@ -153,13 +153,13 @@ struct LookupSegmentArray
first <= last &&
valuesZ.sanitize (c, base, last - first + 1));
}
- template
- bool sanitize (hb_sanitize_context_t *c, const void *base, T2 user_data) const
+ template
+ bool sanitize (hb_sanitize_context_t *c, const void *base, Ts &&...ds) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
first <= last &&
- valuesZ.sanitize (c, base, last - first + 1, user_data));
+ valuesZ.sanitize (c, base, last - first + 1, hb_forward (ds)...));
}
GlyphID last; /* Last GlyphID in this segment */
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
index 5168a9c85..1966ded32 100644
--- a/src/hb-aat-layout.cc
+++ b/src/hb-aat-layout.cc
@@ -311,14 +311,6 @@ hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
trak.apply (&c);
}
-
-hb_language_t
-_hb_aat_language_get (hb_face_t *face,
- unsigned int i)
-{
- return face->table.ltag->get_language (i);
-}
-
/**
* hb_aat_layout_get_feature_types:
* @face: a face object
diff --git a/src/hb-aat-layout.hh b/src/hb-aat-layout.hh
index 6340924bf..9a0e4468f 100644
--- a/src/hb-aat-layout.hh
+++ b/src/hb-aat-layout.hh
@@ -30,7 +30,7 @@
#include "hb.hh"
#include "hb-ot-shape.hh"
-
+#include "hb-aat-ltag-table.hh"
struct hb_aat_feature_mapping_t
{
@@ -77,9 +77,13 @@ hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-HB_INTERNAL hb_language_t
+
+inline hb_language_t
_hb_aat_language_get (hb_face_t *face,
- unsigned int i);
+ unsigned int i)
+{
+ return face->table.ltag->get_language (i);
+}
#endif /* HB_AAT_LAYOUT_HH */
diff --git a/src/hb-algs.hh b/src/hb-algs.hh
index 93677435b..c3467800b 100644
--- a/src/hb-algs.hh
+++ b/src/hb-algs.hh
@@ -71,28 +71,31 @@ struct
private:
/* Pointer-to-member-function. */
- template auto
- impl (Appl&& a, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
- (hb_forward (hb_deref_pointer (v)).*a ())
+ template auto
+ impl (Appl&& a, hb_priority<2>, Val1 &&v1, Vals &&...vs) const HB_AUTO_RETURN
+ ((hb_deref_pointer (hb_forward (v1)).*hb_forward (a)) (hb_forward (vs)...))
/* Pointer-to-member. */
template auto
- impl (Appl&& a, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
- (hb_forward (hb_deref_pointer (v)).*a)
+ impl (Appl&& a, hb_priority<1>, Val &&v) const HB_AUTO_RETURN
+ ((hb_deref_pointer (hb_forward (v))).*hb_forward (a))
/* Operator(). */
- template auto
- impl (Appl&& a, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
- (hb_deref_pointer (a) (hb_forward (v)))
+ template auto
+ impl (Appl&& a, hb_priority<0>, Vals &&...vs) const HB_AUTO_RETURN
+ (hb_deref_pointer (hb_forward (a)) (hb_forward (vs)...))
public:
+ template auto
+ impl2 (Appl&& a, hb_priority<2>, Val1 &&v1, Vals &&...vs) const HB_AUTO_RETURN
+ (hb_deref_pointer (hb_forward (v1)).*hb_forward (a) (hb_forward (vs)...))
- template auto
- operator () (Appl&& a, Val &&v) const HB_AUTO_RETURN
+ template auto
+ operator () (Appl&& a, Vals &&...vs) const HB_AUTO_RETURN
(
impl (hb_forward (a),
- hb_forward (v),
- hb_prioritize)
+ hb_prioritize,
+ hb_forward (vs)...)
)
} HB_FUNCOBJ (hb_invoke);
@@ -102,7 +105,7 @@ struct
template auto
impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
- (hb_deref_pointer (p).has (v))
+ (hb_deref_pointer (hb_forward (p)).has (v))
template auto
impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
@@ -127,7 +130,7 @@ struct
template auto
impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
- (hb_deref_pointer (f).get (hb_forward (v)))
+ (hb_deref_pointer (hb_forward (f)).get (hb_forward (v)))
template auto
impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
diff --git a/src/hb-array.hh b/src/hb-array.hh
index 74b6757b2..b4619ee9a 100644
--- a/src/hb-array.hh
+++ b/src/hb-array.hh
@@ -43,20 +43,19 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&>
* Constructors.
*/
hb_array_t () : arrayZ (nullptr), length (0) {}
- hb_array_t (const hb_array_t &o) :
- hb_iter_with_fallback_t, Type&> (),
- arrayZ (o.arrayZ), length (o.length) {}
- template
- hb_array_t (const hb_array_t > &o) : arrayZ (o.arrayZ), length (o.length) {}
-
hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
template hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_) {}
- template
- hb_array_t& operator = (const hb_array_t > &o)
- { arrayZ = o.arrayZ; length = o.length; return *this; }
- hb_array_t& operator = (const hb_array_t &o)
+ template
+ hb_array_t (const hb_array_t &o) :
+ hb_iter_with_fallback_t, Type&> (),
+ arrayZ (o.arrayZ), length (o.length) {}
+ template
+ hb_array_t& operator = (const hb_array_t &o)
{ arrayZ = o.arrayZ; length = o.length; return *this; }
+
/*
* Iterator implementation.
*/
@@ -212,12 +211,19 @@ struct hb_sorted_array_t :
static constexpr bool is_sorted_iterator = true;
hb_sorted_array_t () : hb_array_t () {}
- hb_sorted_array_t (const hb_array_t &o) : hb_array_t (o) {}
- template
- hb_sorted_array_t (const hb_sorted_array_t > &o) : hb_array_t (o) {}
hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t (array_, length_) {}
template hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t (array_) {}
+ template
+ hb_sorted_array_t (const hb_array_t &o) :
+ hb_iter_t, Type&> (),
+ hb_array_t (o) {}
+ template
+ hb_sorted_array_t& operator = (const hb_array_t &o)
+ { hb_array_t (*this) = o; return *this; }
+
hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
{ return hb_sorted_array_t (((const hb_array_t *) (this))->sub_array (start_offset, seg_count)); }
hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
diff --git a/src/hb-cff-interp-common.hh b/src/hb-cff-interp-common.hh
index 78ef997b1..c5157c783 100644
--- a/src/hb-cff-interp-common.hh
+++ b/src/hb-cff-interp-common.hh
@@ -691,7 +691,7 @@ struct opset_t
case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
- env.argStack.push_int ((int16_t)(-(op - OpCode_TwoByteNegInt0) * 256 - env.str_ref[0] - 108));
+ env.argStack.push_int ((-(int16_t)(op - OpCode_TwoByteNegInt0) * 256 - env.str_ref[0] - 108));
env.str_ref.inc ();
break;
diff --git a/src/hb-common.cc b/src/hb-common.cc
index 60d16c8a4..c453443e7 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -1160,6 +1160,59 @@ hb_variation_to_string (hb_variation_t *variation,
buf[len] = '\0';
}
+/**
+ * hb_color_get_alpha:
+ *
+ *
+ *
+ * Since: REPLACEME
+ */
+uint8_t
+(hb_color_get_alpha) (hb_color_t color)
+{
+ return hb_color_get_alpha (color);
+}
+
+/**
+ * hb_color_get_red:
+ *
+ *
+ *
+ * Since: REPLACEME
+ */
+uint8_t
+(hb_color_get_red) (hb_color_t color)
+{
+ return hb_color_get_red (color);
+}
+
+/**
+ * hb_color_get_green:
+ *
+ *
+ *
+ * Since: REPLACEME
+ */
+uint8_t
+(hb_color_get_green) (hb_color_t color)
+{
+ return hb_color_get_green (color);
+}
+
+/**
+ * hb_color_get_blue:
+ *
+ *
+ *
+ * Since: REPLACEME
+ */
+uint8_t
+(hb_color_get_blue) (hb_color_t color)
+{
+ return hb_color_get_blue (color);
+}
+
+
/* If there is no visibility control, then hb-static.cc will NOT
* define anything. Instead, we get it to define one set in here
* only, so only libharfbuzz.so defines them, not other libs. */
diff --git a/src/hb-common.h b/src/hb-common.h
index 371b2bfc9..edd9ffb86 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -467,39 +467,21 @@ typedef uint32_t hb_color_t;
#define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a)))
-/**
- * hb_color_get_alpha:
- *
- *
- *
- * Since: 2.1.0
- */
+HB_EXTERN uint8_t
+hb_color_get_alpha (hb_color_t color);
#define hb_color_get_alpha(color) ((color) & 0xFF)
-/**
- * hb_color_get_red:
- *
- *
- *
- * Since: 2.1.0
- */
-#define hb_color_get_red(color) (((color) >> 8) & 0xFF)
-/**
- * hb_color_get_green:
- *
- *
- *
- * Since: 2.1.0
- */
-#define hb_color_get_green(color) (((color) >> 16) & 0xFF)
-/**
- * hb_color_get_blue:
- *
- *
- *
- * Since: 2.1.0
- */
-#define hb_color_get_blue(color) (((color) >> 24) & 0xFF)
+HB_EXTERN uint8_t
+hb_color_get_red (hb_color_t color);
+#define hb_color_get_red(color) (((color) >> 8) & 0xFF)
+
+HB_EXTERN uint8_t
+hb_color_get_green (hb_color_t color);
+#define hb_color_get_green(color) (((color) >> 16) & 0xFF)
+
+HB_EXTERN uint8_t
+hb_color_get_blue (hb_color_t color);
+#define hb_color_get_blue(color) (((color) >> 24) & 0xFF)
HB_END_DECLS
diff --git a/src/hb-iter.hh b/src/hb-iter.hh
index a4ffbd6f0..f0947282d 100644
--- a/src/hb-iter.hh
+++ b/src/hb-iter.hh
@@ -129,8 +129,6 @@ struct hb_iter_t
#define hb_iter_t(Iterable) decltype (hb_declval (Iterable).iter ())
-/* TODO Change to function-object. */
-
template struct hb_array_t;
struct
@@ -209,35 +207,35 @@ template
struct hb_is_iterable
{
private:
+
template
- static auto test (int) -> decltype (hb_declval (U).iter (), hb_true_t ());
+ static auto impl (hb_priority<1>) -> decltype (hb_declval (U).iter (), hb_true_t ());
+
template
- static hb_false_t test (...);
+ static hb_false_t impl (hb_priority<0>);
public:
- enum { value = decltype (test (0))::value };
+
+ enum { value = decltype (impl (hb_prioritize))::value };
};
#define hb_is_iterable(Iterable) hb_is_iterable::value
/* TODO Add hb_is_iterable_of().
* TODO Add random_access / sorted variants. */
-
/* hb_is_iterator() / hb_is_random_access_iterator() / hb_is_sorted_iterator() */
-template
-struct _hb_is_iterator_of
-{
- char operator () (...) { return 0; }
- template int operator () (hb_iter_t *) { return 0; }
- template int operator () (hb_iter_t *) { return 0; }
- template int operator () (hb_iter_t *) { return 0; }
- template int operator () (hb_iter_t *) { return 0; }
- static_assert (sizeof (char) != sizeof (int), "");
-};
+template
+static inline char _hb_is_iterator_of (hb_priority<0>, const void *) { return 0; }
+template
+static inline int _hb_is_iterator_of (hb_priority<2>, hb_iter_t *) { return 0; }
+
template
struct hb_is_iterator_of { enum {
- value = sizeof (int) == sizeof (hb_declval (_hb_is_iterator_of) (hb_declval (Iter*))) }; };
+ value = sizeof (int) == sizeof (_hb_is_iterator_of (hb_prioritize, hb_declval (Iter*))) }; };
#define hb_is_iterator_of(Iter, Item) hb_is_iterator_of::value
#define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t)
diff --git a/src/hb-map.hh b/src/hb-map.hh
index b99fb8f4b..bbb1bef5d 100644
--- a/src/hb-map.hh
+++ b/src/hb-map.hh
@@ -34,11 +34,9 @@
* hb_hashmap_t
*/
-/* TODO if K/V is signed integer, -1 is not a good default.
- * Don't know how to get to -MAX using bit work. */
template
+ K kINVALID = hb_is_pointer (K) ? 0 : hb_is_signed (K) ? hb_int_min (K) : (K) -1,
+ V vINVALID = hb_is_pointer (V) ? 0 : hb_is_signed (V) ? hb_int_min (V) : (V) -1>
struct hb_hashmap_t
{
HB_DELETE_COPY_ASSIGN (hb_hashmap_t);
@@ -122,7 +120,7 @@ struct hb_hashmap_t
return false;
}
+ hb_iter (new_items, new_size)
- | hb_apply ([] (item_t &_) { _.clear (); }) /* TODO make pointer-to-methods invokable. */
+ | hb_apply (&item_t::clear)
;
unsigned int old_size = mask + 1;
@@ -193,7 +191,7 @@ struct hb_hashmap_t
return;
if (items)
+ hb_iter (items, mask + 1)
- | hb_apply ([] (item_t &_) { _.clear (); }) /* TODO make pointer-to-methods invokable. */
+ | hb_apply (&item_t::clear)
;
population = occupancy = 0;
diff --git a/src/hb-meta.hh b/src/hb-meta.hh
index 0dcf79320..b80358c2a 100644
--- a/src/hb-meta.hh
+++ b/src/hb-meta.hh
@@ -65,6 +65,9 @@ template <> struct hb_priority<0> {};
#define HB_FUNCOBJ(x) static_const x HB_UNUSED
+template struct hb_match_identity { typedef T type; };
+template using hb_type_identity = typename hb_match_identity::type;
+
struct
{
template
@@ -96,6 +99,14 @@ template struct hb_match_pointer { typedef T type; enum { valu
template using hb_remove_pointer = typename hb_match_pointer::type;
#define hb_is_pointer(T) hb_match_pointer::value
+/* TODO Add feature-parity to std::decay. */
+template using hb_decay = hb_remove_const>;
+
+#define hb_is_cr_convertible_to(A, B) ( \
+ hb_is_same (hb_decay, hb_decay) && \
+ hb_is_const (A) <= hb_is_const (B) && \
+ hb_is_reference (A) >= hb_is_reference (B))
+
/* std::move and std::forward */
@@ -127,17 +138,25 @@ template struct hb_is_same : hb_true_t {};
#define hb_is_same(T, T2) hb_is_same::value
template struct hb_is_signed;
-/* https://github.com/harfbuzz/harfbuzz/issues/1535 */
-template <> struct hb_is_signed { enum { value = true }; };
-template <> struct hb_is_signed { enum { value = true }; };
-template <> struct hb_is_signed { enum { value = true }; };
-template <> struct hb_is_signed { enum { value = true }; };
-template <> struct hb_is_signed { enum { value = false }; };
-template <> struct hb_is_signed { enum { value = false }; };
-template <> struct hb_is_signed { enum { value = false }; };
-template <> struct hb_is_signed { enum { value = false }; };
+template <> struct hb_is_signed { enum { value = CHAR_MIN < 0 }; };
+template <> struct hb_is_signed { enum { value = true }; };
+template <> struct hb_is_signed { enum { value = false }; };
+template <> struct hb_is_signed { enum { value = true }; };
+template <> struct hb_is_signed { enum { value = false }; };
+template <> struct hb_is_signed { enum { value = true }; };
+template <> struct hb_is_signed { enum { value = false }; };
+template <> struct hb_is_signed { enum { value = true }; };
+template <> struct hb_is_signed { enum { value = false }; };
+template <> struct hb_is_signed { enum { value = true }; };
+template <> struct hb_is_signed { enum { value = false }; };
#define hb_is_signed(T) hb_is_signed::value
+template struct hb_int_min { static constexpr T value = 0; };
+template <> struct hb_int_min { static constexpr char value = CHAR_MIN; };
+template <> struct hb_int_min { static constexpr int value = INT_MIN; };
+template <> struct hb_int_min { static constexpr long value = LONG_MIN; };
+#define hb_int_min(T) hb_int_min::value
+
template struct hb_signedness_int;
template <> struct hb_signedness_int { typedef unsigned int value; };
template <> struct hb_signedness_int { typedef signed int value; };
diff --git a/src/hb-mutex.hh b/src/hb-mutex.hh
index 35f1fded1..a760e7317 100644
--- a/src/hb-mutex.hh
+++ b/src/hb-mutex.hh
@@ -127,8 +127,6 @@ typedef int hb_mutex_impl_t;
struct hb_mutex_t
{
- /* TODO Add tracing. */
-
hb_mutex_impl_t m;
void init () { hb_mutex_impl_init (&m); }
diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
index 23f7511b1..041b9843f 100644
--- a/src/hb-open-type.hh
+++ b/src/hb-open-type.hh
@@ -182,7 +182,7 @@ struct Offset : Type
void *serialize (hb_serialize_context_t *c, const void *base)
{
void *t = c->start_embed ();
- *this = (char *) t - (char *) base; /* TODO(serialize) Overflow? */
+ c->check_assign (*this, (unsigned) ((char *) t - (char *) base));
return t;
}
@@ -284,8 +284,8 @@ struct OffsetTo : Offset
return * (Type *) Offset::serialize (c, base);
}
- template
- bool serialize_subset (hb_subset_context_t *c, const T &src, const void *base)
+ template
+ bool serialize_subset (hb_subset_context_t *c, const T &src, const void *base, Ts &&...ds)
{
*this = 0;
if (has_null && &src == &Null (T))
@@ -295,7 +295,7 @@ struct OffsetTo : Offset
s->push ();
- bool ret = src.subset (c);
+ bool ret = src.subset (c, hb_forward (ds)...);
if (ret || !has_null)
s->add_link (*this, s->pop_pack (), base);
@@ -314,39 +314,13 @@ struct OffsetTo : Offset
return_trace (true);
}
- bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ template
+ bool sanitize (hb_sanitize_context_t *c, const void *base, Ts &&...ds) const
{
TRACE_SANITIZE (this);
return_trace (sanitize_shallow (c, base) &&
(this->is_null () ||
- StructAtOffset (base, *this).sanitize (c) ||
- neuter (c)));
- }
- template
- bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1) const
- {
- TRACE_SANITIZE (this);
- return_trace (sanitize_shallow (c, base) &&
- (this->is_null () ||
- StructAtOffset (base, *this).sanitize (c, d1) ||
- neuter (c)));
- }
- template
- bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2) const
- {
- TRACE_SANITIZE (this);
- return_trace (sanitize_shallow (c, base) &&
- (this->is_null () ||
- StructAtOffset (base, *this).sanitize (c, d1, d2) ||
- neuter (c)));
- }
- template
- bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2, T3 d3) const
- {
- TRACE_SANITIZE (this);
- return_trace (sanitize_shallow (c, base) &&
- (this->is_null () ||
- StructAtOffset (base, *this).sanitize (c, d1, d2, d3) ||
+ StructAtOffset (base, *this).sanitize (c, hb_forward (ds)...) ||
neuter (c)));
}
@@ -430,29 +404,26 @@ struct UnsizedArrayOf
* we do not need to call their sanitize() as we already did
* a bound check on the aggregate array size. We just include
* a small unreachable expression to make sure the structs
- * pointed to do have a simple sanitize(), ie. they do not
+ * pointed to do have a simple sanitize() as well as an
+ * assignment opreator. This ensures that they do not
* reference other structs via offsets.
*/
- (void) (false && arrayZ[0].sanitize (c));
+ if (false)
+ {
+ arrayZ[0].sanitize (c);
+ Type v;
+ v = arrayZ[0];
+ }
return_trace (true);
}
- bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const
+ template
+ bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts &&...ds) const
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
for (unsigned int i = 0; i < count; i++)
- if (unlikely (!arrayZ[i].sanitize (c, base)))
- return_trace (false);
- return_trace (true);
- }
- template
- bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const
- {
- TRACE_SANITIZE (this);
- if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
+ if (unlikely (!arrayZ[i].sanitize (c, hb_forward (ds)...)))
return_trace (false);
return_trace (true);
}
@@ -492,17 +463,12 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf
return this+*p;
}
-
- bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+ template
+ bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts &&...ds) const
{
TRACE_SANITIZE (this);
- return_trace ((UnsizedOffsetArrayOf::sanitize (c, count, this)));
- }
- template
- bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
- {
- TRACE_SANITIZE (this);
- return_trace ((UnsizedOffsetArrayOf::sanitize (c, count, this, user_data)));
+ return_trace ((UnsizedOffsetArrayOf
+ ::sanitize (c, count, this, hb_forward (ds)...)));
}
};
@@ -582,7 +548,7 @@ struct ArrayOf
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return_trace (false);
- len = items_len; /* TODO(serialize) Overflow? */
+ c->check_assign (len, items_len);
if (unlikely (!c->extend (*this))) return_trace (false);
return_trace (true);
}
@@ -622,24 +588,14 @@ struct ArrayOf
return_trace (true);
}
- bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ template
+ bool sanitize (hb_sanitize_context_t *c, Ts &&...ds) const
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
- if (unlikely (!arrayZ[i].sanitize (c, base)))
- return_trace (false);
- return_trace (true);
- }
- template
- bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
- {
- TRACE_SANITIZE (this);
- if (unlikely (!sanitize_shallow (c))) return_trace (false);
- unsigned int count = len;
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
+ if (unlikely (!arrayZ[i].sanitize (c, hb_forward (ds)...)))
return_trace (false);
return_trace (true);
}
@@ -706,16 +662,11 @@ struct OffsetListOf : OffsetArrayOf
return_trace (true);
}
- bool sanitize (hb_sanitize_context_t *c) const
+ template
+ bool sanitize (hb_sanitize_context_t *c, Ts &&...ds) const
{
TRACE_SANITIZE (this);
- return_trace (OffsetArrayOf::sanitize (c, this));
- }
- template
- bool sanitize (hb_sanitize_context_t *c, T user_data) const
- {
- TRACE_SANITIZE (this);
- return_trace (OffsetArrayOf::sanitize (c, this, user_data));
+ return_trace (OffsetArrayOf::sanitize (c, this, hb_forward (ds)...));
}
};
@@ -747,7 +698,7 @@ struct HeadlessArrayOf
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return_trace (false);
- lenP1 = items.length + 1; /* TODO(serialize) Overflow? */
+ c->check_assign (lenP1, items.length + 1);
if (unlikely (!c->extend (*this))) return_trace (false);
for (unsigned int i = 0; i < items.length; i++)
arrayZ[i] = items[i];
@@ -763,10 +714,16 @@ struct HeadlessArrayOf
* we do not need to call their sanitize() as we already did
* a bound check on the aggregate array size. We just include
* a small unreachable expression to make sure the structs
- * pointed to do have a simple sanitize(), ie. they do not
+ * pointed to do have a simple sanitize() as well as an
+ * assignment opreator. This ensures that they do not
* reference other structs via offsets.
*/
- (void) (false && arrayZ[0].sanitize (c));
+ if (false)
+ {
+ arrayZ[0].sanitize (c);
+ Type v;
+ v = arrayZ[0];
+ }
return_trace (true);
}
@@ -807,14 +764,14 @@ struct ArrayOfM1
unsigned int get_size () const
{ return lenM1.static_size + (lenM1 + 1) * Type::static_size; }
- template
- bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+ template
+ bool sanitize (hb_sanitize_context_t *c, Ts &&...ds) const
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
unsigned int count = lenM1 + 1;
for (unsigned int i = 0; i < count; i++)
- if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
+ if (unlikely (!arrayZ[i].sanitize (c, hb_forward (ds)...)))
return_trace (false);
return_trace (true);
}
@@ -999,31 +956,27 @@ struct VarSizedBinSearchArrayOf
* we do not need to call their sanitize() as we already did
* a bound check on the aggregate array size. We just include
* a small unreachable expression to make sure the structs
- * pointed to do have a simple sanitize(), ie. they do not
+ * pointed to do have a simple sanitize() as well as an
+ * assignment opreator. This ensures that they do not
* reference other structs via offsets.
*/
- (void) (false && StructAtOffset (&bytesZ, 0).sanitize (c));
+ if (false)
+ {
+ (*this)[0].sanitize (c);
+ Type v;
+ v = (*this)[0];
+ }
return_trace (true);
}
- bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ template
+ bool sanitize (hb_sanitize_context_t *c, Ts &&...ds) const
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
unsigned int count = get_length ();
for (unsigned int i = 0; i < count; i++)
- if (unlikely (!(*this)[i].sanitize (c, base)))
- return_trace (false);
- return_trace (true);
- }
- template
- bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
- {
- TRACE_SANITIZE (this);
- if (unlikely (!sanitize_shallow (c))) return_trace (false);
- unsigned int count = get_length ();
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (!(*this)[i].sanitize (c, base, user_data)))
+ if (unlikely (!(*this)[i].sanitize (c, hb_forward (ds)...)))
return_trace (false);
return_trace (true);
}
diff --git a/src/hb-ot-cff1-table.cc b/src/hb-ot-cff1-table.cc
index 8773c05a2..1d97e5444 100644
--- a/src/hb-ot-cff1-table.cc
+++ b/src/hb-ot-cff1-table.cc
@@ -165,8 +165,8 @@ struct bounds_t
{
void init ()
{
- min.set_int (0x7FFFFFFF, 0x7FFFFFFF);
- max.set_int (-0x80000000, -0x80000000);
+ min.set_int (INT_MAX, INT_MAX);
+ max.set_int (INT_MIN, INT_MIN);
}
void update (const point_t &pt)
diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh
index 18cbafa3f..3957d5daf 100644
--- a/src/hb-ot-cff1-table.hh
+++ b/src/hb-ot-cff1-table.hh
@@ -110,7 +110,8 @@ struct Encoding1 {
{
if (glyph <= ranges[i].nLeft)
{
- return (hb_codepoint_t)ranges[i].first + glyph;
+ hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph;
+ return (likely (code < 0x100) ? code: CFF_UNDEF_CODE);
}
glyph -= (ranges[i].nLeft + 1);
}
diff --git a/src/hb-ot-cff2-table.cc b/src/hb-ot-cff2-table.cc
index 7daa53656..d2463d785 100644
--- a/src/hb-ot-cff2-table.cc
+++ b/src/hb-ot-cff2-table.cc
@@ -34,10 +34,10 @@ struct extents_param_t
void init ()
{
path_open = false;
- min_x.set_int (0x7FFFFFFF);
- min_y.set_int (0x7FFFFFFF);
- max_x.set_int (-0x80000000);
- max_y.set_int (-0x80000000);
+ min_x.set_int (INT_MAX);
+ min_y.set_int (INT_MAX);
+ max_x.set_int (INT_MIN);
+ max_y.set_int (INT_MIN);
}
void start_path () { path_open = true; }
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index e664e06f4..10c35e32c 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -85,12 +85,12 @@ struct SingleSubstFormat1
bool serialize (hb_serialize_context_t *c,
hb_sorted_array_t glyphs,
- int delta)
+ unsigned delta)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return_trace (false);
if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
- deltaGlyphID = delta; /* TODO(serialize) overflow? */
+ c->check_assign (deltaGlyphID, delta);
return_trace (true);
}
@@ -127,8 +127,8 @@ struct SingleSubstFormat1
OffsetTo
coverage; /* Offset to Coverage table--from
* beginning of Substitution table */
- HBINT16 deltaGlyphID; /* Add to original GlyphID to get
- * substitute GlyphID */
+ HBUINT16 deltaGlyphID; /* Add to original GlyphID to get
+ * substitute GlyphID, modulo 0x10000 */
public:
DEFINE_SIZE_STATIC (6);
};
@@ -231,15 +231,14 @@ struct SingleSubst
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (u.format))) return_trace (false);
- unsigned int format = 2;
- int delta = 0;
+ unsigned format = 2;
+ unsigned delta = 0;
if (glyphs.length)
{
format = 1;
- /* TODO(serialize) check for wrap-around */
- delta = substitutes[0] - glyphs[0];
+ delta = (unsigned) (substitutes[0] - glyphs[0]) & 0xFFFF;
for (unsigned int i = 1; i < glyphs.length; i++)
- if (delta != (int) (substitutes[i] - glyphs[i])) {
+ if (delta != ((unsigned) (substitutes[i] - glyphs[i]) & 0xFFFF)) {
format = 2;
break;
}
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
index 2e9165be2..840c142ab 100644
--- a/src/hb-ot-layout-gsubgpos.hh
+++ b/src/hb-ot-layout-gsubgpos.hh
@@ -286,7 +286,7 @@ struct hb_ot_apply_context_t :
};
may_match_t may_match (const hb_glyph_info_t &info,
- const HBUINT16 *glyph_data) const
+ const HBUINT16 *glyph_data) const
{
if (!(info.mask & mask) ||
(syllable && syllable != info.syllable ()))
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index ef0bcc716..846414c9b 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -219,28 +219,28 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
continue; /* Feature disabled, or not enough bits. */
- hb_bool_t found = false;
+ bool found = false;
unsigned int feature_index[2];
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
if (required_feature_tag[table_index] == info->tag)
required_feature_stage[table_index] = info->stage[table_index];
- found |= hb_ot_layout_language_find_feature (face,
- table_tags[table_index],
- script_index[table_index],
- language_index[table_index],
- info->tag,
- &feature_index[table_index]);
+ found |= (bool) hb_ot_layout_language_find_feature (face,
+ table_tags[table_index],
+ script_index[table_index],
+ language_index[table_index],
+ info->tag,
+ &feature_index[table_index]);
}
if (!found && (info->flags & F_GLOBAL_SEARCH))
{
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
- found |= hb_ot_layout_table_find_feature (face,
- table_tags[table_index],
- info->tag,
- &feature_index[table_index]);
+ found |= (bool) hb_ot_layout_table_find_feature (face,
+ table_tags[table_index],
+ info->tag,
+ &feature_index[table_index]);
}
}
if (!found && !(info->flags & F_HAS_FALLBACK))
diff --git a/src/hb-ot-name-language.cc b/src/hb-ot-name-language-static.hh
similarity index 99%
rename from src/hb-ot-name-language.cc
rename to src/hb-ot-name-language-static.hh
index 0e37e0acb..fac317856 100644
--- a/src/hb-ot-name-language.cc
+++ b/src/hb-ot-name-language-static.hh
@@ -24,6 +24,9 @@
* Google Author(s): Behdad Esfahbod
*/
+#ifndef HB_OT_NAME_LANGUAGE_STATIC_HH
+#define HB_OT_NAME_LANGUAGE_STATIC_HH
+
#include "hb-ot-name-language.hh"
/* Following two tables were generated by joining FreeType, FontConfig,
@@ -455,3 +458,5 @@ _hb_ot_name_language_for_mac_code (unsigned int code)
hb_mac_language_map,
ARRAY_LENGTH (hb_mac_language_map));
}
+
+#endif /* HB_OT_NAME_LANGUAGE_STATIC_HH */
diff --git a/src/hb-ot-name-table.hh b/src/hb-ot-name-table.hh
index fca509149..72deb10b4 100644
--- a/src/hb-ot-name-table.hh
+++ b/src/hb-ot-name-table.hh
@@ -158,6 +158,150 @@ struct name
unsigned int get_size () const
{ return min_size + count * nameRecordZ.item_size; }
+ void get_subsetted_ids (const name *source_name,
+ const hb_subset_plan_t *plan,
+ hb_vector_t& name_record_idx_to_retain) const
+ {
+ for(unsigned int i = 0; i < count; i++)
+ {
+ if (format == 0 && (unsigned int) source_name->nameRecordZ[i].nameID > 25)
+ continue;
+ if (!hb_set_is_empty (plan->name_ids) &&
+ !hb_set_has (plan->name_ids, source_name->nameRecordZ[i].nameID))
+ continue;
+ name_record_idx_to_retain.push (i);
+ }
+ }
+
+ bool serialize_name_record (hb_serialize_context_t *c,
+ const name *source_name,
+ const hb_vector_t& name_record_idx_to_retain)
+ {
+ for (unsigned int i = 0; i < name_record_idx_to_retain.length; i++)
+ {
+ unsigned int idx = name_record_idx_to_retain[i];
+ if (unlikely (idx >= source_name->count))
+ {
+ DEBUG_MSG (SUBSET, nullptr, "Invalid index: %d.", idx);
+ return false;
+ }
+
+ c->push ();
+
+ NameRecord *p = c->embed (source_name->nameRecordZ[idx]);
+ if (!p)
+ return false;
+ p->offset = 0;
+ }
+
+ return true;
+ }
+
+ bool serialize_strings (hb_serialize_context_t *c,
+ const name *source_name,
+ const hb_subset_plan_t *plan,
+ const hb_vector_t& name_record_idx_to_retain)
+ {
+ hb_face_t *face = plan->source;
+ accelerator_t acc;
+ acc.init (face);
+
+ for (unsigned int i = 0; i < name_record_idx_to_retain.length; i++)
+ {
+ unsigned int idx = name_record_idx_to_retain[i];
+ unsigned int size = acc.get_name (idx).get_size ();
+
+ c->push ();
+ char *new_pos = c->allocate_size (size);
+
+ if (unlikely (new_pos == nullptr))
+ {
+ acc.fini ();
+ DEBUG_MSG (SUBSET, nullptr, "Couldn't allocate enough space for Name string: %u.",
+ size);
+ return false;
+ }
+
+ const HBUINT8* source_string_pool = (source_name + source_name->stringOffset).arrayZ;
+ unsigned int name_record_offset = source_name->nameRecordZ[idx].offset;
+
+ memcpy (new_pos, source_string_pool + name_record_offset, size);
+ }
+
+ acc.fini ();
+ return true;
+ }
+
+ bool pack_record_and_strings (name *dest_name_unpacked,
+ hb_serialize_context_t *c,
+ unsigned length)
+ {
+ hb_hashmap_t id_str_idx_map;
+ for (int i = length-1; i >= 0; i--)
+ {
+ unsigned objidx = c->pop_pack ();
+ id_str_idx_map.set ((unsigned)i, objidx);
+ }
+
+ const void *base = & (dest_name_unpacked->nameRecordZ[length]);
+ for (int i = length-1; i >= 0; i--)
+ {
+ unsigned str_idx = id_str_idx_map.get ((unsigned)i);
+ NameRecord& namerecord = dest_name_unpacked->nameRecordZ[i];
+ c->add_link (namerecord.offset, str_idx, base);
+ c->pop_pack ();
+ }
+
+ if (c->in_error ())
+ return false;
+
+ return true;
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ const name *source_name,
+ const hb_subset_plan_t *plan,
+ const hb_vector_t& name_record_idx_to_retain)
+ {
+ TRACE_SERIALIZE (this);
+
+ if (unlikely (!c->extend_min ((*this)))) return_trace (false);
+
+ this->format = source_name->format;
+ this->count = name_record_idx_to_retain.length;
+ this->stringOffset = min_size + name_record_idx_to_retain.length * NameRecord::static_size;
+
+
+ if (!serialize_name_record (c, source_name, name_record_idx_to_retain))
+ return_trace (false);
+
+ if (!serialize_strings (c, source_name, plan, name_record_idx_to_retain))
+ return_trace (false);
+
+ if (!pack_record_and_strings (this, c, name_record_idx_to_retain.length))
+ return_trace (false);
+
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ hb_subset_plan_t *plan = c->plan;
+ hb_vector_t name_record_idx_to_retain;
+
+ get_subsetted_ids (this, plan, name_record_idx_to_retain);
+
+ hb_serialize_context_t *serializer = c->serializer;
+ name *name_prime = serializer->start_embed ();
+ if (!name_prime || !name_prime->serialize (serializer, this, plan, name_record_idx_to_retain))
+ {
+ DEBUG_MSG (SUBSET, nullptr, "Failed to serialize write new name.");
+ return false;
+ }
+
+ return true;
+ }
+
bool sanitize_records (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 1fd8fc670..6d46fe33c 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -1008,7 +1008,6 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
ginfo.cluster = buffer->cur().cluster;
ginfo.mask = buffer->cur().mask;
ginfo.syllable() = buffer->cur().syllable();
- /* TODO Set glyph_props? */
/* Insert dottedcircle after possible Repha. */
while (buffer->idx < buffer->len && buffer->successful &&
diff --git a/src/hb-ot-shape-complex-khmer.cc b/src/hb-ot-shape-complex-khmer.cc
index 5746651d6..4c8847762 100644
--- a/src/hb-ot-shape-complex-khmer.cc
+++ b/src/hb-ot-shape-complex-khmer.cc
@@ -368,7 +368,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
- /* Note: This loop is extra overhead, but should not be measurable. */
+ /* Note: This loop is extra overhead, but should not be measurable.
+ * TODO Use a buffer scratch flag to remove the loop. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
@@ -407,7 +408,6 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
ginfo.cluster = buffer->cur().cluster;
ginfo.mask = buffer->cur().mask;
ginfo.syllable() = buffer->cur().syllable();
- /* TODO Set glyph_props? */
/* Insert dottedcircle after possible Repha. */
while (buffer->idx < buffer->len && buffer->successful &&
diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc
index 70ab972c6..b1f6b65ef 100644
--- a/src/hb-ot-shape-complex-myanmar.cc
+++ b/src/hb-ot-shape-complex-myanmar.cc
@@ -301,7 +301,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
- /* Note: This loop is extra overhead, but should not be measurable. */
+ /* Note: This loop is extra overhead, but should not be measurable.
+ * TODO Use a buffer scratch flag to remove the loop. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
diff --git a/src/hb-ot-shape-complex-use-table.cc b/src/hb-ot-shape-complex-use-table.cc
index cb5c358cd..ddf7053db 100644
--- a/src/hb-ot-shape-complex-use-table.cc
+++ b/src/hb-ot-shape-complex-use-table.cc
@@ -318,8 +318,8 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 1B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre,
/* 1B40 */ VPst, VPst, VAbv, VAbv, H, B, B, B, B, B, B, B, O, O, O, O,
- /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
- /* 1B60 */ O, O, O, O, O, O, O, O, O, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
+ /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, GB, GB, O, O, GB,
+ /* 1B60 */ O, O, GB, O, O, O, O, O, GB, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
/* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, O,
/* Sundanese */
diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc
index eecde6e85..ec4d4aa7e 100644
--- a/src/hb-ot-shape-complex-use.cc
+++ b/src/hb-ot-shape-complex-use.cc
@@ -526,7 +526,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
- /* Note: This loop is extra overhead, but should not be measurable. */
+ /* Note: This loop is extra overhead, but should not be measurable.
+ * TODO Use a buffer scratch flag to remove the loop. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
@@ -560,7 +561,6 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
ginfo.cluster = buffer->cur().cluster;
ginfo.mask = buffer->cur().mask;
ginfo.syllable() = buffer->cur().syllable();
- /* TODO Set glyph_props? */
/* Insert dottedcircle after possible Repha. */
while (buffer->idx < buffer->len && buffer->successful &&
diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh
index 0d908bd13..7566881a8 100644
--- a/src/hb-serialize.hh
+++ b/src/hb-serialize.hh
@@ -120,17 +120,23 @@ struct hb_serialize_context_t
this->packed.push (nullptr);
}
- bool propagate_error (bool e)
- { return this->successful = this->successful && e; }
- template bool propagate_error (const T &obj)
- { return this->successful = this->successful && !obj.in_error (); }
- template bool propagate_error (const T *obj)
- { return this->successful = this->successful && !obj->in_error (); }
- template bool propagate_error (T1 &&o1, T2 &&o2)
- { return propagate_error (o1) && propagate_error (o2); }
- template
- bool propagate_error (T1 &&o1, T2 &&o2, T3 &&o3)
- { return propagate_error (o1) && propagate_error (o2, o3); }
+ bool check_success (bool success)
+ { return this->successful && (success || (err_other_error (), false)); }
+
+ template
+ bool check_equal (T1 &&v1, T2 &&v2)
+ { return check_success (v1 == v2); }
+
+ template
+ bool check_assign (T1 &v1, T2 &&v2)
+ { return check_equal (v1 = v2, v2); }
+
+ template bool propagate_error (T &&obj)
+ { return check_success (!hb_deref_pointer (obj).in_error ()); }
+
+ template bool propagate_error (T1 &&o1, Ts &&...os)
+ { return propagate_error (hb_forward (o1)) &&
+ propagate_error (hb_forward (os)...); }
/* To be called around main operation. */
template
@@ -172,7 +178,7 @@ struct hb_serialize_context_t
{
object_t *obj = object_pool.alloc ();
if (unlikely (!obj))
- propagate_error (false);
+ check_success (false);
else
{
obj->head = head;
@@ -272,7 +278,7 @@ struct hb_serialize_context_t
auto& link = *current->links.push ();
link.is_wide = sizeof (T) == 4;
- link.position = (const char *) &ofs - (const char *) base;
+ link.position = (const char *) &ofs - current->head;
link.bias = (const char *) base - current->head;
link.objidx = objidx;
}
@@ -294,14 +300,14 @@ struct hb_serialize_context_t
if (link.is_wide)
{
auto &off = * ((BEInt *) (parent.head + link.position));
- off = offset;
- propagate_error (off == offset);
+ assert (0 == off);
+ check_assign (off, offset);
}
else
{
auto &off = * ((BEInt *) (parent.head + link.position));
- off = offset;
- propagate_error (off == offset);
+ assert (0 == off);
+ check_assign (off, offset);
}
}
}
@@ -323,8 +329,9 @@ struct hb_serialize_context_t
return ret;
}
- void
- err_ran_out_of_room () { this->ran_out_of_room = true; }
+ /* Following two functions exist to allow setting breakpoint on. */
+ void err_ran_out_of_room () { this->ran_out_of_room = true; }
+ void err_other_error () { this->successful = false; }
template
Type *allocate_size (unsigned int size)
@@ -358,6 +365,24 @@ struct hb_serialize_context_t
memcpy (ret, &obj, size);
return ret;
}
+
+ template auto
+ _copy (const Type &obj, hb_priority<1>) const HB_RETURN (Type *, obj.copy (this))
+
+ template auto
+ _copy (const Type &obj, hb_priority<0>) const -> decltype (&(obj = obj))
+ {
+ Type *ret = this->allocate_size (sizeof (Type));
+ if (unlikely (!ret)) return nullptr;
+ *ret = obj;
+ return ret;
+ }
+
+ /* Like embed, but active: calls obj.operator=() or obj.copy() to transfer data
+ * instead of memcpy(). */
+ template
+ Type *copy (const Type &obj) { return _copy (obj, hb_prioritize); }
+
template
hb_serialize_context_t &operator << (const Type &obj) { embed (obj); return *this; }
diff --git a/src/hb-static.cc b/src/hb-static.cc
index 4c5158860..6b89183ca 100644
--- a/src/hb-static.cc
+++ b/src/hb-static.cc
@@ -37,6 +37,7 @@
#include "hb-ot-maxp-table.hh"
#ifndef HB_NO_VISIBILITY
+#include "hb-ot-name-language-static.hh"
hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc
index 4d203b545..b3b27d427 100644
--- a/src/hb-subset-input.cc
+++ b/src/hb-subset-input.cc
@@ -44,6 +44,7 @@ hb_subset_input_create_or_fail ()
input->unicodes = hb_set_create ();
input->glyphs = hb_set_create ();
+ input->name_ids = hb_set_create ();
input->drop_hints = false;
input->drop_layout = true;
input->desubroutinize = false;
@@ -81,6 +82,7 @@ hb_subset_input_destroy (hb_subset_input_t *subset_input)
hb_set_destroy (subset_input->unicodes);
hb_set_destroy (subset_input->glyphs);
+ hb_set_destroy (subset_input->name_ids);
free (subset_input);
}
@@ -109,6 +111,12 @@ hb_subset_input_glyph_set (hb_subset_input_t *subset_input)
return subset_input->glyphs;
}
+HB_EXTERN hb_set_t *
+hb_subset_input_nameid_set (hb_subset_input_t *subset_input)
+{
+ return subset_input->name_ids;
+}
+
HB_EXTERN void
hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
hb_bool_t drop_hints)
diff --git a/src/hb-subset-input.hh b/src/hb-subset-input.hh
index 04d6e121b..d01fecee0 100644
--- a/src/hb-subset-input.hh
+++ b/src/hb-subset-input.hh
@@ -40,6 +40,7 @@ struct hb_subset_input_t
hb_set_t *unicodes;
hb_set_t *glyphs;
+ hb_set_t *name_ids;
bool drop_hints : 1;
bool drop_layout : 1;
@@ -49,7 +50,7 @@ struct hb_subset_input_t
*
* features
* lookups
- * nameIDs
+ * name_ids
* ...
*/
};
diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index 8b7231494..fe636b190 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -204,12 +204,14 @@ hb_subset_plan_create (hb_face_t *face,
plan->drop_hints = input->drop_hints;
plan->drop_layout = input->drop_layout;
plan->desubroutinize = input->desubroutinize;
- plan->unicodes = hb_set_create();
+ plan->retain_gids = input->retain_gids;
+ plan->unicodes = hb_set_create ();
+ plan->name_ids = hb_set_reference (input->name_ids);
plan->source = hb_face_reference (face);
plan->dest = hb_face_builder_create ();
- plan->codepoint_to_glyph = hb_map_create();
- plan->glyph_map = hb_map_create();
- plan->reverse_glyph_map = hb_map_create();
+ plan->codepoint_to_glyph = hb_map_create ();
+ plan->glyph_map = hb_map_create ();
+ plan->reverse_glyph_map = hb_map_create ();
plan->_glyphset = _populate_gids_to_retain (face,
input->unicodes,
input->glyphs,
@@ -238,6 +240,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
if (!hb_object_destroy (plan)) return;
hb_set_destroy (plan->unicodes);
+ hb_set_destroy (plan->name_ids);
hb_face_destroy (plan->source);
hb_face_destroy (plan->dest);
hb_map_destroy (plan->codepoint_to_glyph);
diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh
index 56726d4d0..abbab5e22 100644
--- a/src/hb-subset-plan.hh
+++ b/src/hb-subset-plan.hh
@@ -42,10 +42,14 @@ struct hb_subset_plan_t
bool drop_hints : 1;
bool drop_layout : 1;
bool desubroutinize : 1;
+ bool retain_gids : 1;
// For each cp that we'd like to retain maps to the corresponding gid.
hb_set_t *unicodes;
+ //name_ids we would like to retain
+ hb_set_t *name_ids;
+
// The glyph subset
hb_map_t *codepoint_to_glyph;
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index a7066cd62..80d1628ef 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -43,6 +43,7 @@
#include "hb-ot-cff1-table.hh"
#include "hb-ot-cff2-table.hh"
#include "hb-ot-vorg-table.hh"
+#include "hb-ot-name-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
#include "hb-ot-var-gvar-table.hh"
@@ -69,11 +70,11 @@ template
static bool
_subset2 (hb_subset_plan_t *plan)
{
+ bool result = true;
hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table (plan->source);
const TableType *table = source_blob->as ();
hb_tag_t tag = TableType::tableTag;
- hb_bool_t result = false;
if (source_blob->data)
{
hb_vector_t buf;
@@ -88,8 +89,7 @@ _subset2 (hb_subset_plan_t *plan)
hb_serialize_context_t serializer ((void *) buf, buf_size);
serializer.start_serialize ();
hb_subset_context_t c (plan, &serializer);
- result = table->subset (&c);
- serializer.end_serialize ();
+ bool needed = table->subset (&c);
if (serializer.ran_out_of_room)
{
buf_size += (buf_size >> 1) + 32;
@@ -101,22 +101,23 @@ _subset2 (hb_subset_plan_t *plan)
}
goto retry;
}
- if (serializer.in_error ())
- {
- abort ();
- }
+ serializer.end_serialize ();
+
+ result = !serializer.in_error ();
if (result)
{
- hb_blob_t *dest_blob = serializer.copy_blob ();
- DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
- result = c.plan->add_table (tag, dest_blob);
- hb_blob_destroy (dest_blob);
- }
- else
- {
- DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
- result = true;
+ if (needed)
+ {
+ hb_blob_t *dest_blob = serializer.copy_blob ();
+ DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
+ result = c.plan->add_table (tag, dest_blob);
+ hb_blob_destroy (dest_blob);
+ }
+ else
+ {
+ DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
+ }
}
}
else
@@ -160,6 +161,9 @@ _subset_table (hb_subset_plan_t *plan,
case HB_OT_TAG_hdmx:
result = _subset (plan);
break;
+ case HB_OT_TAG_name:
+ result = _subset2 (plan);
+ break;
case HB_OT_TAG_head:
// TODO that won't work well if there is no glyf
DEBUG_MSG(SUBSET, nullptr, "skip head, handled by glyf");
diff --git a/src/hb-subset.h b/src/hb-subset.h
index 657709ec8..50345061c 100644
--- a/src/hb-subset.h
+++ b/src/hb-subset.h
@@ -54,6 +54,9 @@ hb_subset_input_unicode_set (hb_subset_input_t *subset_input);
HB_EXTERN hb_set_t *
hb_subset_input_glyph_set (hb_subset_input_t *subset_input);
+HB_EXTERN hb_set_t *
+hb_subset_input_nameid_set (hb_subset_input_t *subset_input);
+
HB_EXTERN void
hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
hb_bool_t drop_hints);
diff --git a/src/hb.hh b/src/hb.hh
index ee35c4dd9..0336ed568 100644
--- a/src/hb.hh
+++ b/src/hb.hh
@@ -167,8 +167,7 @@
#include "hb-aat.h"
#define HB_AAT_H_IN
-#include "hb-aat.h"
-
+#include
#include
#include
#include
diff --git a/src/test-algs.cc b/src/test-algs.cc
index 42a9538dc..163a79ad3 100644
--- a/src/test-algs.cc
+++ b/src/test-algs.cc
@@ -28,6 +28,17 @@
#include "hb-algs.hh"
+static char *
+test_func (int a, char **b)
+{
+ return b ? b[a] : nullptr;
+}
+
+struct A
+{
+ void a () {}
+};
+
int
main (int argc, char **argv)
{
@@ -46,5 +57,10 @@ main (int argc, char **argv)
q.second = 4;
assert (i == 4);
+ hb_invoke (test_func, 0, nullptr);
+
+ A a;
+ hb_invoke (&A::a, a);
+
return 0;
}
diff --git a/src/test-size-params.cc b/src/test-gpos-size-params.cc
similarity index 100%
rename from src/test-size-params.cc
rename to src/test-gpos-size-params.cc
diff --git a/src/test-would-substitute.cc b/src/test-gsub-would-substitute.cc
similarity index 100%
rename from src/test-would-substitute.cc
rename to src/test-gsub-would-substitute.cc
diff --git a/src/test-iter.cc b/src/test-iter.cc
index 675bbe397..3de340145 100644
--- a/src/test-iter.cc
+++ b/src/test-iter.cc
@@ -91,7 +91,7 @@ test_iterator (Iter it)
}
template
+ hb_enable_if (hb_is_iterable (Iterable))>
static void
test_iterable (const Iterable &lst = Null(Iterable))
{
@@ -127,6 +127,11 @@ main (int argc, char **argv)
hb_set_t st;
test_iterable (st);
hb_sorted_array_t sa;
+ (void) static_cast, hb_sorted_array_t::item_t>&> (sa);
+ (void) static_cast, hb_sorted_array_t::__item_t__>&> (sa);
+ (void) static_cast, int&>&>(sa);
+ (void) static_cast>&>(sa);
+ (void) static_cast, int&>&> (sa);
test_iterable (sa);
test_iterable > ();
@@ -181,7 +186,7 @@ main (int argc, char **argv)
;
/* The result should be something like 0->10, 1->11, ..., 9->19 */
assert (hb_map_get (result, 9) == 19);
-
+
unsigned int temp3 = 0;
+ hb_iter(src)
| hb_map([&] (int i) -> int { return ++temp3; })
diff --git a/src/test-name-table.cc b/src/test-ot-name.cc
similarity index 100%
rename from src/test-name-table.cc
rename to src/test-ot-name.cc
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index eb033811c..70a9fda85 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -55,6 +55,7 @@ TEST_PROGS = \
test-subset-vvar \
test-unicode \
test-version \
+ test-subset-nameids \
$(NULL)
test_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
@@ -70,6 +71,7 @@ test_subset_cff2_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
test_subset_gvar_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
test_subset_hvar_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
test_subset_vvar_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+test_subset_nameids_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
test_unicode_CPPFLAGS = \
$(AM_CPPFLAGS) \
diff --git a/test/api/fonts/nameID.dup.expected.ttf b/test/api/fonts/nameID.dup.expected.ttf
new file mode 100644
index 000000000..e9e7ff5b4
Binary files /dev/null and b/test/api/fonts/nameID.dup.expected.ttf differ
diff --git a/test/api/fonts/nameID.dup.origin.ttf b/test/api/fonts/nameID.dup.origin.ttf
new file mode 100644
index 000000000..aad75d421
Binary files /dev/null and b/test/api/fonts/nameID.dup.origin.ttf differ
diff --git a/test/api/fonts/nameID.expected.ttf b/test/api/fonts/nameID.expected.ttf
new file mode 100644
index 000000000..ccd4b8bcd
Binary files /dev/null and b/test/api/fonts/nameID.expected.ttf differ
diff --git a/test/api/fonts/nameID.origin.ttf b/test/api/fonts/nameID.origin.ttf
new file mode 100644
index 000000000..aec973a58
Binary files /dev/null and b/test/api/fonts/nameID.origin.ttf differ
diff --git a/test/api/hb-subset-test.h b/test/api/hb-subset-test.h
index 3e759a8a9..8f32aee67 100644
--- a/test/api/hb-subset-test.h
+++ b/test/api/hb-subset-test.h
@@ -65,6 +65,15 @@ hb_subset_test_create_input_from_glyphs (const hb_set_t *glyphs)
return input;
}
+static inline hb_subset_input_t *
+hb_subset_test_create_input_from_nameids (const hb_set_t *name_ids)
+{
+ hb_subset_input_t *input = hb_subset_input_create_or_fail ();
+ hb_set_t * input_name_ids = hb_subset_input_nameid_set (input);
+ hb_set_union (input_name_ids, name_ids);
+ return input;
+}
+
static inline hb_face_t *
hb_subset_test_create_subset (hb_face_t *source,
hb_subset_input_t *input)
diff --git a/test/api/test-ot-face.c b/test/api/test-ot-face.c
index 9ebcb4e2b..12ac666a4 100644
--- a/test/api/test-ot-face.c
+++ b/test/api/test-ot-face.c
@@ -111,7 +111,7 @@ test_ot_face_empty (void)
}
static void
-test_ot_var_axis_on_zero_named_instance ()
+test_ot_var_axis_on_zero_named_instance (void)
{
hb_face_t *face = hb_test_open_font_file ("fonts/Zycon.ttf");
g_assert (hb_ot_var_get_axis_count (face));
diff --git a/test/api/test-subset-nameids.c b/test/api/test-subset-nameids.c
new file mode 100644
index 000000000..b58a86c91
--- /dev/null
+++ b/test/api/test-subset-nameids.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright © 2018 Google, Inc.
+ *
+ * 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): Garret Rieger
+ */
+
+#include "hb-test.h"
+#include "hb-subset-test.h"
+
+static void
+test_subset_nameids (void)
+{
+ hb_face_t *face_origin = hb_test_open_font_file ("fonts/nameID.origin.ttf");
+ hb_face_t *face_expected = hb_test_open_font_file ("fonts/nameID.expected.ttf");
+
+ hb_set_t *name_ids = hb_set_create();
+ hb_face_t *face_subset;
+ hb_set_add (name_ids, 0);
+ hb_set_add (name_ids, 9);
+ face_subset = hb_subset_test_create_subset (face_origin, hb_subset_test_create_input_from_nameids (name_ids));
+ hb_set_destroy (name_ids);
+
+ hb_subset_test_check (face_expected, face_subset, HB_TAG ('n','a','m','e'));
+
+ hb_face_destroy (face_subset);
+ hb_face_destroy (face_origin);
+ hb_face_destroy (face_expected);
+}
+
+static void
+test_subset_nameids_with_dup_strs (void)
+{
+ hb_face_t *face_origin = hb_test_open_font_file ("fonts/nameID.dup.origin.ttf");
+ hb_face_t *face_expected = hb_test_open_font_file ("fonts/nameID.dup.expected.ttf");
+
+ hb_set_t *name_ids = hb_set_create();
+ hb_face_t *face_subset;
+ hb_set_add (name_ids, 1);
+ hb_set_add (name_ids, 3);
+ face_subset = hb_subset_test_create_subset (face_origin, hb_subset_test_create_input_from_nameids (name_ids));
+ hb_set_destroy (name_ids);
+
+ hb_subset_test_check (face_expected, face_subset, HB_TAG ('n','a','m','e'));
+
+ hb_face_destroy (face_subset);
+ hb_face_destroy (face_origin);
+ hb_face_destroy (face_expected);
+}
+
+int
+main (int argc, char **argv)
+{
+ hb_test_init (&argc, &argv);
+
+ hb_test_add (test_subset_nameids);
+ hb_test_add (test_subset_nameids_with_dup_strs);
+
+ return hb_test_run();
+}
diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am
index a77df7061..5bd2d7e6d 100644
--- a/test/fuzzing/Makefile.am
+++ b/test/fuzzing/Makefile.am
@@ -55,8 +55,8 @@ hb_subset_fuzzer_CPPFLAGS = $(AM_CPPFLAGS)
hb_subset_fuzzer_DEPENDENCIES = $(top_builddir)/src/libharfbuzz-subset.la
check:
- EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-shape-fuzzer-tests.py
- EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-subset-fuzzer-tests.py
+ EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" LIBTOOL="$(LIBTOOL)" $(srcdir)/run-shape-fuzzer-tests.py
+ EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" LIBTOOL="$(LIBTOOL)" $(srcdir)/run-subset-fuzzer-tests.py
check-valgrind:
$(AM_V_at)RUN_VALGRIND=1 $(MAKE) $(AM_MAKEFLGS) check
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5716947896893440 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5716947896893440
new file mode 100644
index 000000000..639132038
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5716947896893440 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5923632099885056 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5923632099885056
new file mode 100644
index 000000000..0a3c6df0e
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5923632099885056 differ
diff --git a/test/fuzzing/run-shape-fuzzer-tests.py b/test/fuzzing/run-shape-fuzzer-tests.py
index 90ed509c7..ba480dd52 100755
--- a/test/fuzzing/run-shape-fuzzer-tests.py
+++ b/test/fuzzing/run-shape-fuzzer-tests.py
@@ -67,36 +67,36 @@ please provide it as the first argument to the tool""")
print ('hb_shape_fuzzer:', hb_shape_fuzzer)
fails = 0
+libtool = os.environ.get('LIBTOOL')
valgrind = None
if os.environ.get('RUN_VALGRIND', ''):
valgrind = which ('valgrind')
if valgrind is None:
print ("""Valgrind requested but not found.""")
sys.exit (1)
+ if libtool is None:
+ print ("""Valgrind support is currently autotools only and needs libtool but not found.""")
+
parent_path = os.path.join (srcdir, "fonts")
for file in os.listdir (parent_path):
path = os.path.join(parent_path, file)
- text, returncode = cmd ([hb_shape_fuzzer, path])
- if text.strip ():
+ if valgrind:
+ text, returncode = cmd (libtool.split(' ') + ['--mode=execute', valgrind + ' --leak-check=full --error-exitcode=1', '--', hb_shape_fuzzer, path])
+ else:
+ text, returncode = cmd ([hb_shape_fuzzer, path])
+ if 'error' in text:
+ returncode = 1
+
+ if not valgrind and text.strip ():
print (text)
- failed = False
- if returncode != 0 or 'error' in text:
+ if returncode != 0:
print ('failure on %s' % file)
- failed = True
-
- if valgrind:
- text, returncode = cmd ([valgrind, '--error-exitcode=1', '--leak-check=full', hb_shape_fuzzer, path])
- if returncode:
- print (text)
- print ('failure on %s' % file)
- failed = True
-
- if failed:
fails = fails + 1
+
if fails:
print ("%i shape fuzzer related tests failed." % fails)
sys.exit (1)
diff --git a/test/fuzzing/run-subset-fuzzer-tests.py b/test/fuzzing/run-subset-fuzzer-tests.py
index 7392a92ec..3ac22889e 100755
--- a/test/fuzzing/run-subset-fuzzer-tests.py
+++ b/test/fuzzing/run-subset-fuzzer-tests.py
@@ -2,7 +2,54 @@
from __future__ import print_function, division, absolute_import
-import sys, os, subprocess
+import sys, os, subprocess, tempfile, threading
+
+
+def which(program):
+ # https://stackoverflow.com/a/377028
+ def is_exe(fpath):
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+
+ fpath, _ = os.path.split(program)
+ if fpath:
+ if is_exe(program):
+ return program
+ else:
+ for path in os.environ["PATH"].split(os.pathsep):
+ exe_file = os.path.join(path, program)
+ if is_exe(exe_file):
+ return exe_file
+
+ return None
+
+
+def cmd(command):
+ # https://stackoverflow.com/a/4408409
+ # https://stackoverflow.com/a/10012262
+ with tempfile.TemporaryFile() as tempf:
+ p = subprocess.Popen (command, stderr=tempf)
+ is_killed = {'value': False}
+
+ def timeout(p, is_killed):
+ is_killed['value'] = True
+ p.kill()
+ timer = threading.Timer (2, timeout, [p, is_killed])
+
+ try:
+ timer.start()
+ p.wait ()
+ tempf.seek (0)
+ text = tempf.read().decode ("utf-8").strip ()
+ returncode = p.returncode
+ finally:
+ timer.cancel()
+
+ if is_killed['value']:
+ text = 'error: timeout, ' + text
+ returncode = 1
+
+ return text, returncode
+
srcdir = os.environ.get ("srcdir", ".")
EXEEXT = os.environ.get ("EXEEXT", "")
@@ -20,21 +67,37 @@ please provide it as the first argument to the tool""")
print ('hb_subset_fuzzer:', hb_subset_fuzzer)
fails = 0
+libtool = os.environ.get('LIBTOOL')
+valgrind = None
+if os.environ.get('RUN_VALGRIND', ''):
+ valgrind = which ('valgrind')
+ if valgrind is None:
+ print ("""Valgrind requested but not found.""")
+ sys.exit (1)
+ if libtool is None:
+ print ("""Valgrind support is currently autotools only and needs libtool but not found.""")
+
+
def run_dir (parent_path):
global fails
for file in os.listdir (parent_path):
path = os.path.join(parent_path, file)
print ("running subset fuzzer against %s" % path)
- p = subprocess.Popen ([hb_subset_fuzzer, path])
+ if valgrind:
+ text, returncode = cmd (libtool.split(' ') + ['--mode=execute', valgrind + ' --leak-check=full --show-leak-kinds=all --error-exitcode=1', '--', hb_subset_fuzzer, path])
+ else:
+ text, returncode = cmd ([hb_subset_fuzzer, path])
+ if 'error' in text:
+ returncode = 1
- if p.wait () != 0:
+ if not valgrind and text.strip ():
+ print (text)
+
+ if returncode != 0:
print ("failed for %s" % path)
fails = fails + 1
- if p.wait () != 0:
- print ("failed for %s" % path)
- fails = fails + 1
run_dir (os.path.join (srcdir, "..", "subset", "data", "fonts"))
# TODO running these tests very slow tests. Fix and re-enable
diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.61,62,63.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.61,62,63.ttf
new file mode 100644
index 000000000..12d92081b
Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.61,62,63.ttf differ
diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.61,63.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.61,63.ttf
new file mode 100644
index 000000000..1af233f48
Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.61,63.ttf differ
diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.61.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.61.ttf
new file mode 100644
index 000000000..a699eea0b
Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.61.ttf differ
diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.62.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.62.ttf
new file mode 100644
index 000000000..52706dc90
Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.62.ttf differ
diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.63.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.63.ttf
new file mode 100644
index 000000000..3de7c7734
Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.63.ttf differ
diff --git a/test/subset/data/profiles/name-ids.txt b/test/subset/data/profiles/name-ids.txt
new file mode 100644
index 000000000..db42c09a4
--- /dev/null
+++ b/test/subset/data/profiles/name-ids.txt
@@ -0,0 +1 @@
+--name-IDs=0,1,2
diff --git a/test/subset/data/tests/basics.tests b/test/subset/data/tests/basics.tests
index 4fc3f4eba..794510d87 100644
--- a/test/subset/data/tests/basics.tests
+++ b/test/subset/data/tests/basics.tests
@@ -6,6 +6,7 @@ default.txt
drop-hints.txt
drop-hints-retain-gids.txt
retain-gids.txt
+name-ids.txt
SUBSETS:
abc
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index 33e584b75..682ca4c34 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -93,6 +93,7 @@ struct subset_consumer_t
hb_subset_input_set_drop_hints (input, subset_options.drop_hints);
hb_subset_input_set_retain_gids (input, subset_options.retain_gids);
hb_subset_input_set_desubroutinize (input, subset_options.desubroutinize);
+ hb_set_set (hb_subset_input_nameid_set (input), subset_options.name_ids);
hb_face_t *face = hb_font_get_face (font);
diff --git a/util/options.cc b/util/options.cc
index c5a4f0f0b..a9b3fc77e 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -971,6 +971,49 @@ format_options_t::serialize_buffer_of_glyphs (hb_buffer_t *buffer,
g_string_append_c (gs, '\n');
}
+static gboolean
+parse_nameids (const char *name G_GNUC_UNUSED,
+ const char *arg,
+ gpointer data,
+ GError **error G_GNUC_UNUSED)
+{
+ subset_options_t *subset_opts = (subset_options_t *) data;
+
+ hb_set_t *name_ids = hb_set_create ();
+ char *s = (char *) arg;
+ char *p;
+
+ while (s && *s)
+ {
+ while (*s && strchr ("<+>{},;\\xXuUnNiI\n\t\v\f\r ", *s))
+ s++;
+ if (!*s)
+ break;
+
+ errno = 0;
+ hb_codepoint_t u = strtoul (s, &p, 10);
+ if (errno || s == p)
+ {
+ hb_set_destroy (name_ids);
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "Failed parsing nameID values at: '%s'", s);
+ return false;
+ }
+
+ hb_set_add (name_ids, u);
+
+ s = p;
+ }
+
+ hb_set_t *prev = subset_opts->name_ids;
+ subset_opts->name_ids = hb_set_reference (name_ids);
+ hb_set_destroy (prev);
+ hb_set_destroy (name_ids);
+
+ return true;
+}
+
+
void
subset_options_t::add_options (option_parser_t *parser)
{
@@ -980,6 +1023,7 @@ subset_options_t::add_options (option_parser_t *parser)
{"no-hinting", 0, 0, G_OPTION_ARG_NONE, &this->drop_hints, "Whether to drop hints", nullptr},
{"retain-gids", 0, 0, G_OPTION_ARG_NONE, &this->retain_gids, "If set don't renumber glyph ids in the subset.", nullptr},
{"desubroutinize", 0, 0, G_OPTION_ARG_NONE, &this->desubroutinize, "Remove CFF/CFF2 use of subroutines", nullptr},
+ {"name-IDs", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_nameids, "Subset specified nameids", "list of int numbers"},
{nullptr}
};
@@ -989,3 +1033,4 @@ subset_options_t::add_options (option_parser_t *parser)
"Options subsetting",
this);
}
+
diff --git a/util/options.hh b/util/options.hh
index 84139f55c..2691e2269 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -677,16 +677,24 @@ struct subset_options_t : option_group_t
drop_hints = false;
retain_gids = false;
desubroutinize = false;
+ name_ids = hb_set_create ();
add_options (parser);
}
+ virtual ~subset_options_t ()
+ {
+ hb_set_destroy (name_ids);
+ }
+
+
void add_options (option_parser_t *parser);
hb_bool_t keep_layout;
hb_bool_t drop_hints;
hb_bool_t retain_gids;
hb_bool_t desubroutinize;
+ hb_set_t *name_ids;
};
/* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */