Merge branch 'master' into var-subset

This commit is contained in:
Michiharu Ariza 2019-04-29 16:43:48 -07:00
commit 1223a352b7
73 changed files with 772 additions and 343 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

2
THANKS
View File

@ -1,6 +1,6 @@
Bradley Grainger
Khaled Hosny
Kenichi Ishibashi
Ivan Kuckir <https://photopea.com/>
Ryan Lortie
Jeff Muizelaar
suzuki toshiya

View File

@ -20,11 +20,7 @@
<para>
The canonical source-code tree is available at
<ulink
url="https://github.com/harfbuzz/harfbuzz">github.com/harfbuzz/harfbuzz</ulink>
and is also available at
<ulink
url="http://cgit.freedesktop.org/harfbuzz/">cgit.freedesktop.org/harfbuzz</ulink>.
<ulink url="https://github.com/harfbuzz/harfbuzz">github.com/harfbuzz/harfbuzz</ulink>.
See <xref linkend="download" endterm="download.title"/> for
release tarballs.
</para>

View File

@ -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

View File

@ -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 \

View File

@ -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):

View File

@ -153,13 +153,13 @@ struct LookupSegmentArray
first <= last &&
valuesZ.sanitize (c, base, last - first + 1));
}
template <typename T2>
bool sanitize (hb_sanitize_context_t *c, const void *base, T2 user_data) const
template <typename ...Ts>
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<Ts> (ds)...));
}
GlyphID last; /* Last GlyphID in this segment */

View File

@ -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

View File

@ -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 */

View File

@ -71,28 +71,31 @@ struct
private:
/* Pointer-to-member-function. */
template <typename Appl, typename Val> auto
impl (Appl&& a, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
(hb_forward<Val> (hb_deref_pointer (v)).*a ())
template <typename Appl, typename Val1, typename ...Vals> auto
impl (Appl&& a, hb_priority<2>, Val1 &&v1, Vals &&...vs) const HB_AUTO_RETURN
((hb_deref_pointer (hb_forward<Val1> (v1)).*hb_forward<Appl> (a)) (hb_forward<Vals> (vs)...))
/* Pointer-to-member. */
template <typename Appl, typename Val> auto
impl (Appl&& a, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
(hb_forward<Val> (hb_deref_pointer (v)).*a)
impl (Appl&& a, hb_priority<1>, Val &&v) const HB_AUTO_RETURN
((hb_deref_pointer (hb_forward<Val> (v))).*hb_forward<Appl> (a))
/* Operator(). */
template <typename Appl, typename Val> auto
impl (Appl&& a, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
(hb_deref_pointer (a) (hb_forward<Val> (v)))
template <typename Appl, typename ...Vals> auto
impl (Appl&& a, hb_priority<0>, Vals &&...vs) const HB_AUTO_RETURN
(hb_deref_pointer (hb_forward<Appl> (a)) (hb_forward<Vals> (vs)...))
public:
template <typename Appl, typename Val1, typename ...Vals> auto
impl2 (Appl&& a, hb_priority<2>, Val1 &&v1, Vals &&...vs) const HB_AUTO_RETURN
(hb_deref_pointer (hb_forward<Val1> (v1)).*hb_forward<Appl> (a) (hb_forward<Vals> (vs)...))
template <typename Appl, typename Val> auto
operator () (Appl&& a, Val &&v) const HB_AUTO_RETURN
template <typename Appl, typename ...Vals> auto
operator () (Appl&& a, Vals &&...vs) const HB_AUTO_RETURN
(
impl (hb_forward<Appl> (a),
hb_forward<Val> (v),
hb_prioritize)
hb_prioritize,
hb_forward<Vals> (vs)...)
)
} HB_FUNCOBJ (hb_invoke);
@ -102,7 +105,7 @@ struct
template <typename Pred, typename Val> auto
impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
(hb_deref_pointer (p).has (v))
(hb_deref_pointer (hb_forward<Pred> (p)).has (v))
template <typename Pred, typename Val> auto
impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
@ -127,7 +130,7 @@ struct
template <typename Proj, typename Val> auto
impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
(hb_deref_pointer (f).get (hb_forward<Val> (v)))
(hb_deref_pointer (hb_forward<Proj> (f)).get (hb_forward<Val> (v)))
template <typename Proj, typename Val> auto
impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN

View File

@ -43,20 +43,19 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
* Constructors.
*/
hb_array_t () : arrayZ (nullptr), length (0) {}
hb_array_t (const hb_array_t<Type> &o) :
hb_iter_with_fallback_t<hb_array_t<Type>, Type&> (),
arrayZ (o.arrayZ), length (o.length) {}
template <typename U = Type, hb_enable_if (hb_is_const (U))>
hb_array_t (const hb_array_t<hb_remove_const<Type> > &o) : arrayZ (o.arrayZ), length (o.length) {}
hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
template <unsigned int length_> hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_) {}
template <typename U = Type, hb_enable_if (hb_is_const (U))>
hb_array_t& operator = (const hb_array_t<hb_remove_const<Type> > &o)
{ arrayZ = o.arrayZ; length = o.length; return *this; }
hb_array_t& operator = (const hb_array_t &o)
template <typename U,
hb_enable_if (hb_is_cr_convertible_to(U, Type))>
hb_array_t (const hb_array_t<U> &o) :
hb_iter_with_fallback_t<hb_array_t<Type>, Type&> (),
arrayZ (o.arrayZ), length (o.length) {}
template <typename U,
hb_enable_if (hb_is_cr_convertible_to(U, Type))>
hb_array_t& operator = (const hb_array_t<U> &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<Type> () {}
hb_sorted_array_t (const hb_array_t<Type> &o) : hb_array_t<Type> (o) {}
template <typename U = Type, hb_enable_if (hb_is_const (U))>
hb_sorted_array_t (const hb_sorted_array_t<hb_remove_const<Type> > &o) : hb_array_t<Type> (o) {}
hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
template <unsigned int length_> hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
template <typename U,
hb_enable_if (hb_is_cr_convertible_to(U, Type))>
hb_sorted_array_t (const hb_array_t<U> &o) :
hb_iter_t<hb_sorted_array_t<Type>, Type&> (),
hb_array_t<Type> (o) {}
template <typename U,
hb_enable_if (hb_is_cr_convertible_to(U, Type))>
hb_sorted_array_t& operator = (const hb_array_t<U> &o)
{ hb_array_t<Type> (*this) = o; return *this; }
hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
{ return hb_sorted_array_t<Type> (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const

View File

@ -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;

View File

@ -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. */

View File

@ -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

View File

@ -129,8 +129,6 @@ struct hb_iter_t
#define hb_iter_t(Iterable) decltype (hb_declval (Iterable).iter ())
/* TODO Change to function-object. */
template <typename> struct hb_array_t;
struct
@ -209,35 +207,35 @@ template <typename T>
struct hb_is_iterable
{
private:
template <typename U>
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 <typename>
static hb_false_t test (...);
static hb_false_t impl (hb_priority<0>);
public:
enum { value = decltype (test<T> (0))::value };
enum { value = decltype (impl<T> (hb_prioritize))::value };
};
#define hb_is_iterable(Iterable) hb_is_iterable<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 <typename Iter>
struct _hb_is_iterator_of
{
char operator () (...) { return 0; }
template<typename Item> int operator () (hb_iter_t<Iter, Item> *) { return 0; }
template<typename Item> int operator () (hb_iter_t<Iter, const Item> *) { return 0; }
template<typename Item> int operator () (hb_iter_t<Iter, Item&> *) { return 0; }
template<typename Item> int operator () (hb_iter_t<Iter, const Item&> *) { return 0; }
static_assert (sizeof (char) != sizeof (int), "");
};
template <typename Iter, typename Item>
static inline char _hb_is_iterator_of (hb_priority<0>, const void *) { return 0; }
template <typename Iter,
typename Item,
typename Item2 = typename Iter::item_t,
hb_enable_if (hb_is_cr_convertible_to (Item2, Item))>
static inline int _hb_is_iterator_of (hb_priority<2>, hb_iter_t<Iter, Item2> *) { return 0; }
template<typename Iter, typename Item>
struct hb_is_iterator_of { enum {
value = sizeof (int) == sizeof (hb_declval (_hb_is_iterator_of<Iter>) (hb_declval (Iter*))) }; };
value = sizeof (int) == sizeof (_hb_is_iterator_of<Iter, Item> (hb_prioritize, hb_declval (Iter*))) }; };
#define hb_is_iterator_of(Iter, Item) hb_is_iterator_of<Iter, Item>::value
#define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t)

View File

@ -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 <typename K, typename V,
K kINVALID = hb_is_pointer (K) ? 0 : (K) -1,
V vINVALID = hb_is_pointer (V) ? 0 : (V) -1>
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;

View File

@ -65,6 +65,9 @@ template <> struct hb_priority<0> {};
#define HB_FUNCOBJ(x) static_const x HB_UNUSED
template <typename T> struct hb_match_identity { typedef T type; };
template <typename T> using hb_type_identity = typename hb_match_identity<T>::type;
struct
{
template <typename T>
@ -96,6 +99,14 @@ template <typename T> struct hb_match_pointer<T *> { typedef T type; enum { valu
template <typename T> using hb_remove_pointer = typename hb_match_pointer<T>::type;
#define hb_is_pointer(T) hb_match_pointer<T>::value
/* TODO Add feature-parity to std::decay. */
template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>;
#define hb_is_cr_convertible_to(A, B) ( \
hb_is_same (hb_decay<A>, hb_decay<B>) && \
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 <typename T> struct hb_is_same<T, T> : hb_true_t {};
#define hb_is_same(T, T2) hb_is_same<T, T2>::value
template <typename T> struct hb_is_signed;
/* https://github.com/harfbuzz/harfbuzz/issues/1535 */
template <> struct hb_is_signed<int8_t> { enum { value = true }; };
template <> struct hb_is_signed<int16_t> { enum { value = true }; };
template <> struct hb_is_signed<int32_t> { enum { value = true }; };
template <> struct hb_is_signed<int64_t> { enum { value = true }; };
template <> struct hb_is_signed<uint8_t> { enum { value = false }; };
template <> struct hb_is_signed<uint16_t> { enum { value = false }; };
template <> struct hb_is_signed<uint32_t> { enum { value = false }; };
template <> struct hb_is_signed<uint64_t> { enum { value = false }; };
template <> struct hb_is_signed<char> { enum { value = CHAR_MIN < 0 }; };
template <> struct hb_is_signed<signed char> { enum { value = true }; };
template <> struct hb_is_signed<unsigned char> { enum { value = false }; };
template <> struct hb_is_signed<signed short> { enum { value = true }; };
template <> struct hb_is_signed<unsigned short> { enum { value = false }; };
template <> struct hb_is_signed<signed int> { enum { value = true }; };
template <> struct hb_is_signed<unsigned int> { enum { value = false }; };
template <> struct hb_is_signed<signed long> { enum { value = true }; };
template <> struct hb_is_signed<unsigned long> { enum { value = false }; };
template <> struct hb_is_signed<signed long long> { enum { value = true }; };
template <> struct hb_is_signed<unsigned long long> { enum { value = false }; };
#define hb_is_signed(T) hb_is_signed<T>::value
template <typename T> struct hb_int_min { static constexpr T value = 0; };
template <> struct hb_int_min<char> { static constexpr char value = CHAR_MIN; };
template <> struct hb_int_min<int> { static constexpr int value = INT_MIN; };
template <> struct hb_int_min<long> { static constexpr long value = LONG_MIN; };
#define hb_int_min(T) hb_int_min<T>::value
template <bool is_signed> struct hb_signedness_int;
template <> struct hb_signedness_int<false> { typedef unsigned int value; };
template <> struct hb_signedness_int<true> { typedef signed int value; };

View File

@ -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); }

View File

@ -182,7 +182,7 @@ struct Offset : Type
void *serialize (hb_serialize_context_t *c, const void *base)
{
void *t = c->start_embed<void> ();
*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<OffsetType, has_null>
return * (Type *) Offset<OffsetType>::serialize (c, base);
}
template <typename T>
bool serialize_subset (hb_subset_context_t *c, const T &src, const void *base)
template <typename T, typename ...Ts>
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<OffsetType, has_null>
s->push ();
bool ret = src.subset (c);
bool ret = src.subset (c, hb_forward<Ts> (ds)...);
if (ret || !has_null)
s->add_link (*this, s->pop_pack (), base);
@ -314,39 +314,13 @@ struct OffsetTo : Offset<OffsetType, has_null>
return_trace (true);
}
bool sanitize (hb_sanitize_context_t *c, const void *base) const
template <typename ...Ts>
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<Type> (base, *this).sanitize (c) ||
neuter (c)));
}
template <typename T1>
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<Type> (base, *this).sanitize (c, d1) ||
neuter (c)));
}
template <typename T1, typename T2>
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<Type> (base, *this).sanitize (c, d1, d2) ||
neuter (c)));
}
template <typename T1, typename T2, typename T3>
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<Type> (base, *this).sanitize (c, d1, d2, d3) ||
StructAtOffset<Type> (base, *this).sanitize (c, hb_forward<Ts> (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 <typename ...Ts>
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 <typename T>
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<Ts> (ds)...)))
return_trace (false);
return_trace (true);
}
@ -492,17 +463,12 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
return this+*p;
}
bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
template <typename ...Ts>
bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts &&...ds) const
{
TRACE_SANITIZE (this);
return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this)));
}
template <typename T>
bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
{
TRACE_SANITIZE (this);
return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this, user_data)));
return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>
::sanitize (c, count, this, hb_forward<Ts> (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 <typename ...Ts>
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 <typename T>
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<Ts> (ds)...)))
return_trace (false);
return_trace (true);
}
@ -706,16 +662,11 @@ struct OffsetListOf : OffsetArrayOf<Type>
return_trace (true);
}
bool sanitize (hb_sanitize_context_t *c) const
template <typename ...Ts>
bool sanitize (hb_sanitize_context_t *c, Ts &&...ds) const
{
TRACE_SANITIZE (this);
return_trace (OffsetArrayOf<Type>::sanitize (c, this));
}
template <typename T>
bool sanitize (hb_sanitize_context_t *c, T user_data) const
{
TRACE_SANITIZE (this);
return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
return_trace (OffsetArrayOf<Type>::sanitize (c, this, hb_forward<Ts> (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 <typename T>
bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
template <typename ...Ts>
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<Ts> (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<Type> (&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 <typename ...Ts>
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 <typename T>
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<Ts> (ds)...)))
return_trace (false);
return_trace (true);
}

View File

@ -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)

View File

@ -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);
}

View File

@ -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; }

View File

@ -85,12 +85,12 @@ struct SingleSubstFormat1
bool serialize (hb_serialize_context_t *c,
hb_sorted_array_t<const GlyphID> 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>
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;
}

View File

@ -219,14 +219,14 @@ 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,
found |= (bool) hb_ot_layout_language_find_feature (face,
table_tags[table_index],
script_index[table_index],
language_index[table_index],
@ -237,7 +237,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
{
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
found |= hb_ot_layout_table_find_feature (face,
found |= (bool) hb_ot_layout_table_find_feature (face,
table_tags[table_index],
info->tag,
&feature_index[table_index]);

View File

@ -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 */

View File

@ -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<unsigned int>& 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<unsigned int>& 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> ();
NameRecord *p = c->embed<NameRecord> (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<unsigned int>& 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> ();
char *new_pos = c->allocate_size<char> (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<unsigned, unsigned> 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<HBUINT16> (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<unsigned int>& 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<unsigned int> 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<name> ();
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);

View File

@ -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 &&

View File

@ -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 &&

View File

@ -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;

View File

@ -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 */

View File

@ -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 &&

View File

@ -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 <typename T> bool propagate_error (const T &obj)
{ return this->successful = this->successful && !obj.in_error (); }
template <typename T> bool propagate_error (const T *obj)
{ return this->successful = this->successful && !obj->in_error (); }
template <typename T1, typename T2> bool propagate_error (T1 &&o1, T2 &&o2)
{ return propagate_error (o1) && propagate_error (o2); }
template <typename T1, typename T2, typename T3>
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 <typename T1, typename T2>
bool check_equal (T1 &&v1, T2 &&v2)
{ return check_success (v1 == v2); }
template <typename T1, typename T2>
bool check_assign (T1 &v1, T2 &&v2)
{ return check_equal (v1 = v2, v2); }
template <typename T> bool propagate_error (T &&obj)
{ return check_success (!hb_deref_pointer (obj).in_error ()); }
template <typename T1, typename... Ts> bool propagate_error (T1 &&o1, Ts &&...os)
{ return propagate_error (hb_forward<T1> (o1)) &&
propagate_error (hb_forward<Ts> (os)...); }
/* To be called around main operation. */
template <typename Type>
@ -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<uint32_t, 4> *) (parent.head + link.position));
off = offset;
propagate_error (off == offset);
assert (0 == off);
check_assign (off, offset);
}
else
{
auto &off = * ((BEInt<uint16_t, 2> *) (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 <typename Type>
Type *allocate_size (unsigned int size)
@ -358,6 +365,24 @@ struct hb_serialize_context_t
memcpy (ret, &obj, size);
return ret;
}
template <typename Type> auto
_copy (const Type &obj, hb_priority<1>) const HB_RETURN (Type *, obj.copy (this))
template <typename Type> auto
_copy (const Type &obj, hb_priority<0>) const -> decltype (&(obj = obj))
{
Type *ret = this->allocate_size<Type> (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 <typename Type>
Type *copy (const Type &obj) { return _copy (obj, hb_prioritize); }
template <typename Type>
hb_serialize_context_t &operator << (const Type &obj) { embed (obj); return *this; }

View File

@ -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)] = {};

View File

@ -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)

View File

@ -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
* ...
*/
};

View File

@ -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);

View File

@ -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;

View File

@ -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<typename TableType>
static bool
_subset2 (hb_subset_plan_t *plan)
{
bool result = true;
hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
const TableType *table = source_blob->as<TableType> ();
hb_tag_t tag = TableType::tableTag;
hb_bool_t result = false;
if (source_blob->data)
{
hb_vector_t<char> buf;
@ -88,8 +89,7 @@ _subset2 (hb_subset_plan_t *plan)
hb_serialize_context_t serializer ((void *) buf, buf_size);
serializer.start_serialize<TableType> ();
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,12 +101,13 @@ _subset2 (hb_subset_plan_t *plan)
}
goto retry;
}
if (serializer.in_error ())
{
abort ();
}
serializer.end_serialize ();
result = !serializer.in_error ();
if (result)
{
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);
@ -116,7 +117,7 @@ _subset2 (hb_subset_plan_t *plan)
else
{
DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
result = true;
}
}
}
else
@ -160,6 +161,9 @@ _subset_table (hb_subset_plan_t *plan,
case HB_OT_TAG_hdmx:
result = _subset<const OT::hdmx> (plan);
break;
case HB_OT_TAG_name:
result = _subset2<const OT::name> (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");

View File

@ -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);

View File

@ -167,8 +167,7 @@
#include "hb-aat.h"
#define HB_AAT_H_IN
#include "hb-aat.h"
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <stddef.h>

View File

@ -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;
}

View File

@ -127,6 +127,11 @@ main (int argc, char **argv)
hb_set_t st;
test_iterable (st);
hb_sorted_array_t<int> sa;
(void) static_cast<hb_iter_t<hb_sorted_array_t<int>, hb_sorted_array_t<int>::item_t>&> (sa);
(void) static_cast<hb_iter_t<hb_sorted_array_t<int>, hb_sorted_array_t<int>::__item_t__>&> (sa);
(void) static_cast<hb_iter_t<hb_sorted_array_t<int>, int&>&>(sa);
(void) static_cast<hb_iter_t<hb_sorted_array_t<int>>&>(sa);
(void) static_cast<hb_iter_t<hb_array_t<int>, int&>&> (sa);
test_iterable (sa);
test_iterable<hb_array_t<int> > ();

View File

@ -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) \

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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)

View File

@ -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));

View File

@ -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();
}

View File

@ -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

View File

@ -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 ():
print (text)
failed = False
if returncode != 0 or 'error' in text:
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
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 failed:
if not valgrind and text.strip ():
print (text)
if returncode != 0:
print ('failure on %s' % file)
fails = fails + 1
if fails:
print ("%i shape fuzzer related tests failed." % fails)
sys.exit (1)

View File

@ -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

View File

@ -0,0 +1 @@
--name-IDs=0,1,2

View File

@ -6,6 +6,7 @@ default.txt
drop-hints.txt
drop-hints-retain-gids.txt
retain-gids.txt
name-ids.txt
SUBSETS:
abc

View File

@ -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);

View File

@ -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);
}

View File

@ -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 */