Merge branch 'master' into var-subset
This commit is contained in:
commit
1223a352b7
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
3
AUTHORS
3
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
|
||||
|
|
|
@ -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
|
||||
|
|
3
COPYING
3
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)
|
||||
|
|
2
THANKS
2
THANKS
|
@ -1,6 +1,6 @@
|
|||
Bradley Grainger
|
||||
Khaled Hosny
|
||||
Kenichi Ishibashi
|
||||
Ivan Kuckir <https://photopea.com/>
|
||||
Ryan Lortie
|
||||
Jeff Muizelaar
|
||||
suzuki toshiya
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; };
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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 */
|
|
@ -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);
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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)] = {};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
* ...
|
||||
*/
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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> > ();
|
||||
|
|
|
@ -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.
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
--name-IDs=0,1,2
|
|
@ -6,6 +6,7 @@ default.txt
|
|||
drop-hints.txt
|
||||
drop-hints-retain-gids.txt
|
||||
retain-gids.txt
|
||||
name-ids.txt
|
||||
|
||||
SUBSETS:
|
||||
abc
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue