Update Harfbuzz to version 3.0.0
[ChangeLog][Text] Updated bundled Harfbuzz to version 3.0.0. Change-Id: I8d9fb465586bc1dbe58ce91b7f49c8483982c75a Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com> Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>bb10
parent
fab1debb74
commit
cb651f81de
|
|
@ -1,3 +1,70 @@
|
|||
Overview of changes leading to 3.0.0
|
||||
Friday, September 17, 2021
|
||||
====================================
|
||||
- Unicode 14.0 support (David Corbett).
|
||||
- The hb-subset API and the harfbuzz-subset library's ABI are now declared
|
||||
stable. The harfbuzz-subset library would not have been possible without the
|
||||
work of Garret Rieger and Qunxin Liu from Google Fonts, and the earlier work
|
||||
of Michiharu Ariza from Adobe.
|
||||
- The hb-style API is now stable and no longer experimental.
|
||||
|
||||
- New API:
|
||||
+hb_style_tag_t
|
||||
+hb_style_get_value()
|
||||
+hb_subset_input_t
|
||||
+hb_subset_flags_t
|
||||
+hb_subset_sets_t
|
||||
+hb_subset_input_create_or_fail()
|
||||
+hb_subset_input_reference()
|
||||
+hb_subset_input_destroy()
|
||||
+hb_subset_input_set_user_data()
|
||||
+hb_subset_input_get_user_data()
|
||||
+hb_subset_input_unicode_set()
|
||||
+hb_subset_input_glyph_set()
|
||||
+hb_subset_input_set()
|
||||
+hb_subset_input_get_flags()
|
||||
+hb_subset_input_set_flags()
|
||||
+hb_subset_or_fail()
|
||||
|
||||
- Removed old unstable harfbuzz-subset API:
|
||||
-hb_subset_input_nameid_set()
|
||||
-hb_subset_input_namelangid_set()
|
||||
-hb_subset_input_layout_features_set()
|
||||
-hb_subset_input_no_subset_tables_set()
|
||||
-hb_subset_input_drop_tables_set()
|
||||
-hb_subset_input_set_drop_hints()
|
||||
-hb_subset_input_get_drop_hints()
|
||||
-hb_subset_input_set_desubroutinize()
|
||||
-hb_subset_input_get_desubroutinize()
|
||||
-hb_subset_input_set_retain_gids()
|
||||
-hb_subset_input_get_retain_gids()
|
||||
-hb_subset_input_set_name_legacy()
|
||||
-hb_subset_input_get_name_legacy()
|
||||
-hb_subset_input_set_overlaps_flag()
|
||||
-hb_subset_input_get_overlaps_flag()
|
||||
-hb_subset_input_set_notdef_outline()
|
||||
-hb_subset_input_get_notdef_outline()
|
||||
-hb_subset_input_set_no_prune_unicode_ranges()
|
||||
-hb_subset_input_get_no_prune_unicode_ranges()
|
||||
-hb_subset()
|
||||
|
||||
|
||||
Overview of changes leading to 2.9.1
|
||||
Tuesday, September 7, 2021
|
||||
====================================
|
||||
- Final subset API is in place and if no issues are discovered, it will be the
|
||||
stable subset API of HarfBuzz 3.0.0. Old API is kept to ease transition, but
|
||||
will be removed in 3.0.0.
|
||||
- Various fuzzer-found bug fixes.
|
||||
- hb_buffer_append() now handles the pre- and post-context which previously
|
||||
were left unchanged in the destination buffer.
|
||||
- hb-view / hb-shape now accept following new arguments:
|
||||
o --unicodes-before/after: takes a list of hex numbers that represent Unicode
|
||||
codepoints.
|
||||
- Undeprecated API:
|
||||
hb_set_invert()
|
||||
|
||||
|
||||
Overview of changes leading to 2.9.0
|
||||
Wednesday, August 18, 2021
|
||||
History Repeats Itself (Afghanistan)
|
||||
|
|
@ -18,6 +85,7 @@ History Repeats Itself (Afghanistan)
|
|||
--glyphs-file, --unicodes-file, supporting ranges in --unicodes.
|
||||
- Various bug fixes.
|
||||
|
||||
|
||||
Overview of changes leading to 2.8.2
|
||||
Tuesday, July 8, 2021
|
||||
====================================
|
||||
|
|
@ -34,6 +102,7 @@ Tuesday, July 8, 2021
|
|||
+hb_blob_create_from_file_or_fail()
|
||||
+hb_set_copy()
|
||||
|
||||
|
||||
Overview of changes leading to 2.8.1
|
||||
Tuesday, May 4, 2021
|
||||
====================================
|
||||
|
|
@ -65,6 +134,7 @@ Sunday, December 27, 2020
|
|||
tarball.
|
||||
- Documentation updates.
|
||||
|
||||
|
||||
Overview of changes leading to 2.7.3
|
||||
Wednesday, December 23, 2020
|
||||
====================================
|
||||
|
|
|
|||
|
|
@ -6,20 +6,21 @@
|
|||
|
||||
"Description": "HarfBuzz is an OpenType text shaping engine.",
|
||||
"Homepage": "http://harfbuzz.org",
|
||||
"Version": "2.9.0",
|
||||
"Version": "3.0.0",
|
||||
|
||||
"License": "MIT License",
|
||||
"LicenseId": "MIT",
|
||||
"LicenseFile": "COPYING",
|
||||
"Copyright": "Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019 Google, Inc.
|
||||
Copyright © 2019 Facebook, Inc.
|
||||
"Copyright": "Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 Google, Inc.
|
||||
Copyright © 2018,2019,2020 Ebrahim Byagowi
|
||||
Copyright © 2019,2020 Facebook, Inc.
|
||||
Copyright © 2012 Mozilla Foundation
|
||||
Copyright © 2011 Codethink Limited
|
||||
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
|
||||
Copyright © 2009 Keith Stribley
|
||||
Copyright © 2009 Martin Hosken and SIL International
|
||||
Copyright © 2007 Chris Wilson
|
||||
Copyright © 2006 Behdad Esfahbod
|
||||
Copyright © 2005,2006,2020,2021 Behdad Esfahbod
|
||||
Copyright © 2005 David Turner
|
||||
Copyright © 2004,2007,2008,2009,2010 Red Hat, Inc.
|
||||
Copyright © 1998-2004 David Turner and Werner Lemberg
|
||||
|
|
|
|||
|
|
@ -1159,30 +1159,48 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
|
|||
|
||||
/* Operators. */
|
||||
|
||||
struct hb_bitwise_and
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_bitwise_and);
|
||||
struct hb_bitwise_or
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_bitwise_or);
|
||||
struct hb_bitwise_xor
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_bitwise_xor);
|
||||
struct hb_bitwise_sub
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a & b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_bitwise_lt);
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_bitwise_sub);
|
||||
HB_FUNCOBJ (hb_bitwise_gt); // aka sub
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a | b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_bitwise_le);
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | ~b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_bitwise_ge);
|
||||
struct
|
||||
{
|
||||
template <typename T> constexpr auto
|
||||
|
|
@ -1203,6 +1221,12 @@ struct
|
|||
}
|
||||
HB_FUNCOBJ (hb_sub);
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T, typename T2> constexpr auto
|
||||
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (b - a)
|
||||
}
|
||||
HB_FUNCOBJ (hb_rsub);
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T, typename T2> constexpr auto
|
||||
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright © 2012,2017 Google, Inc.
|
||||
* Copyright © 2021 Behdad Esfahbod
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_BIT_PAGE_HH
|
||||
#define HB_BIT_PAGE_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
struct hb_bit_page_t
|
||||
{
|
||||
void init0 () { v.clear (); }
|
||||
void init1 () { v.clear (0xFF); }
|
||||
|
||||
constexpr unsigned len () const
|
||||
{ return ARRAY_LENGTH_CONST (v); }
|
||||
|
||||
bool is_empty () const
|
||||
{
|
||||
for (unsigned int i = 0; i < len (); i++)
|
||||
if (v[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void add (hb_codepoint_t g) { elt (g) |= mask (g); }
|
||||
void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
|
||||
void set (hb_codepoint_t g, bool v) { if (v) add (g); else del (g); }
|
||||
bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
|
||||
|
||||
void add_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
elt_t *la = &elt (a);
|
||||
elt_t *lb = &elt (b);
|
||||
if (la == lb)
|
||||
*la |= (mask (b) << 1) - mask(a);
|
||||
else
|
||||
{
|
||||
*la |= ~(mask (a) - 1);
|
||||
la++;
|
||||
|
||||
memset (la, 0xff, (char *) lb - (char *) la);
|
||||
|
||||
*lb |= ((mask (b) << 1) - 1);
|
||||
}
|
||||
}
|
||||
void del_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
elt_t *la = &elt (a);
|
||||
elt_t *lb = &elt (b);
|
||||
if (la == lb)
|
||||
*la &= ~((mask (b) << 1) - mask(a));
|
||||
else
|
||||
{
|
||||
*la &= mask (a) - 1;
|
||||
la++;
|
||||
|
||||
memset (la, 0, (char *) lb - (char *) la);
|
||||
|
||||
*lb &= ~((mask (b) << 1) - 1);
|
||||
}
|
||||
}
|
||||
void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
|
||||
{ if (v) add_range (a, b); else del_range (a, b); }
|
||||
|
||||
bool is_equal (const hb_bit_page_t &other) const
|
||||
{
|
||||
return 0 == hb_memcmp (&v, &other.v, sizeof (v));
|
||||
}
|
||||
bool is_subset (const hb_bit_page_t &larger_page) const
|
||||
{
|
||||
for (unsigned i = 0; i < len (); i++)
|
||||
if (~larger_page.v[i] & v[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int get_population () const
|
||||
{
|
||||
unsigned int pop = 0;
|
||||
for (unsigned int i = 0; i < len (); i++)
|
||||
pop += hb_popcount (v[i]);
|
||||
return pop;
|
||||
}
|
||||
|
||||
bool next (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
unsigned int m = (*codepoint + 1) & MASK;
|
||||
if (!m)
|
||||
{
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
unsigned int i = m / ELT_BITS;
|
||||
unsigned int j = m & ELT_MASK;
|
||||
|
||||
const elt_t vv = v[i] & ~((elt_t (1) << j) - 1);
|
||||
for (const elt_t *p = &vv; i < len (); p = &v[++i])
|
||||
if (*p)
|
||||
{
|
||||
*codepoint = i * ELT_BITS + elt_get_min (*p);
|
||||
return true;
|
||||
}
|
||||
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
bool previous (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
unsigned int m = (*codepoint - 1) & MASK;
|
||||
if (m == MASK)
|
||||
{
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
unsigned int i = m / ELT_BITS;
|
||||
unsigned int j = m & ELT_MASK;
|
||||
|
||||
/* Fancy mask to avoid shifting by elt_t bitsize, which is undefined. */
|
||||
const elt_t mask = j < 8 * sizeof (elt_t) - 1 ?
|
||||
((elt_t (1) << (j + 1)) - 1) :
|
||||
(elt_t) -1;
|
||||
const elt_t vv = v[i] & mask;
|
||||
const elt_t *p = &vv;
|
||||
while (true)
|
||||
{
|
||||
if (*p)
|
||||
{
|
||||
*codepoint = i * ELT_BITS + elt_get_max (*p);
|
||||
return true;
|
||||
}
|
||||
if ((int) i <= 0) break;
|
||||
p = &v[--i];
|
||||
}
|
||||
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
hb_codepoint_t get_min () const
|
||||
{
|
||||
for (unsigned int i = 0; i < len (); i++)
|
||||
if (v[i])
|
||||
return i * ELT_BITS + elt_get_min (v[i]);
|
||||
return INVALID;
|
||||
}
|
||||
hb_codepoint_t get_max () const
|
||||
{
|
||||
for (int i = len () - 1; i >= 0; i--)
|
||||
if (v[i])
|
||||
return i * ELT_BITS + elt_get_max (v[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static constexpr hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
|
||||
|
||||
typedef unsigned long long elt_t;
|
||||
static constexpr unsigned PAGE_BITS = 512;
|
||||
static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
|
||||
|
||||
static unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); }
|
||||
static unsigned int elt_get_max (const elt_t &elt) { return hb_bit_storage (elt) - 1; }
|
||||
|
||||
typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
|
||||
|
||||
static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8;
|
||||
static constexpr unsigned ELT_MASK = ELT_BITS - 1;
|
||||
static constexpr unsigned BITS = sizeof (vector_t) * 8;
|
||||
static constexpr unsigned MASK = BITS - 1;
|
||||
static_assert ((unsigned) PAGE_BITS == (unsigned) BITS, "");
|
||||
|
||||
elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; }
|
||||
const elt_t& elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
|
||||
static constexpr elt_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); }
|
||||
|
||||
vector_t v;
|
||||
};
|
||||
static_assert (hb_bit_page_t::PAGE_BITS == sizeof (hb_bit_page_t) * 8, "");
|
||||
|
||||
|
||||
#endif /* HB_BIT_PAGE_HH */
|
||||
|
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* Copyright © 2012,2017 Google, Inc.
|
||||
* Copyright © 2021 Behdad Esfahbod
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_BIT_SET_INVERTIBLE_HH
|
||||
#define HB_BIT_SET_INVERTIBLE_HH
|
||||
|
||||
#include "hb.hh"
|
||||
#include "hb-bit-set.hh"
|
||||
|
||||
|
||||
struct hb_bit_set_invertible_t
|
||||
{
|
||||
hb_bit_set_t s;
|
||||
bool inverted;
|
||||
|
||||
hb_bit_set_invertible_t () { init (); }
|
||||
~hb_bit_set_invertible_t () { fini (); }
|
||||
|
||||
void init () { s.init (); inverted = false; }
|
||||
void fini () { s.fini (); }
|
||||
void err () { s.err (); }
|
||||
bool in_error () const { return s.in_error (); }
|
||||
explicit operator bool () const { return !is_empty (); }
|
||||
|
||||
void reset ()
|
||||
{
|
||||
s.reset ();
|
||||
inverted = false;
|
||||
}
|
||||
void clear ()
|
||||
{
|
||||
s.clear ();
|
||||
if (likely (s.successful))
|
||||
inverted = false;
|
||||
}
|
||||
void invert ()
|
||||
{
|
||||
if (likely (s.successful))
|
||||
inverted = !inverted;
|
||||
}
|
||||
|
||||
bool is_empty () const
|
||||
{
|
||||
hb_codepoint_t v = INVALID;
|
||||
next (&v);
|
||||
return v == INVALID;
|
||||
}
|
||||
hb_codepoint_t get_min () const
|
||||
{
|
||||
hb_codepoint_t v = INVALID;
|
||||
next (&v);
|
||||
return v;
|
||||
}
|
||||
hb_codepoint_t get_max () const
|
||||
{
|
||||
hb_codepoint_t v = INVALID;
|
||||
previous (&v);
|
||||
return v;
|
||||
}
|
||||
unsigned int get_population () const
|
||||
{ return inverted ? INVALID - s.get_population () : s.get_population (); }
|
||||
|
||||
|
||||
void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); }
|
||||
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{ return unlikely (inverted) ? (s.del_range (a, b), true) : s.add_range (a, b); }
|
||||
|
||||
template <typename T>
|
||||
void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{ inverted ? s.del_array (array, count, stride) : s.add_array (array, count, stride); }
|
||||
template <typename T>
|
||||
void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
|
||||
|
||||
/* Might return false if array looks unsorted.
|
||||
* Used for faster rejection of corrupt data. */
|
||||
template <typename T>
|
||||
bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{ return inverted ? s.del_sorted_array (array, count, stride) : s.add_sorted_array (array, count, stride); }
|
||||
template <typename T>
|
||||
bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
|
||||
|
||||
void del (hb_codepoint_t g) { unlikely (inverted) ? s.add (g) : s.del (g); }
|
||||
void del_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{ unlikely (inverted) ? (void) s.add_range (a, b) : s.del_range (a, b); }
|
||||
|
||||
bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; }
|
||||
|
||||
/* Has interface. */
|
||||
static constexpr bool SENTINEL = false;
|
||||
typedef bool value_t;
|
||||
value_t operator [] (hb_codepoint_t k) const { return get (k); }
|
||||
bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
|
||||
/* Predicate. */
|
||||
bool operator () (hb_codepoint_t k) const { return has (k); }
|
||||
|
||||
/* Sink interface. */
|
||||
hb_bit_set_invertible_t& operator << (hb_codepoint_t v)
|
||||
{ add (v); return *this; }
|
||||
hb_bit_set_invertible_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
|
||||
{ add_range (range.first, range.second); return *this; }
|
||||
|
||||
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
|
||||
{
|
||||
hb_codepoint_t c = first - 1;
|
||||
return next (&c) && c <= last;
|
||||
}
|
||||
|
||||
void set (const hb_bit_set_invertible_t &other)
|
||||
{
|
||||
s.set (other.s);
|
||||
if (likely (s.successful))
|
||||
inverted = other.inverted;
|
||||
}
|
||||
|
||||
bool is_equal (const hb_bit_set_invertible_t &other) const
|
||||
{
|
||||
if (likely (inverted == other.inverted))
|
||||
return s.is_equal (other.s);
|
||||
else
|
||||
{
|
||||
/* TODO Add iter_ranges() and use here. */
|
||||
auto it1 = iter ();
|
||||
auto it2 = other.iter ();
|
||||
return hb_all (+ hb_zip (it1, it2)
|
||||
| hb_map ([](hb_pair_t<hb_codepoint_t, hb_codepoint_t> _) { return _.first == _.second; }));
|
||||
}
|
||||
}
|
||||
|
||||
bool is_subset (const hb_bit_set_invertible_t &larger_set) const
|
||||
{
|
||||
if (unlikely (inverted != larger_set.inverted))
|
||||
return hb_all (hb_iter (s) | hb_map (larger_set.s));
|
||||
else
|
||||
return unlikely (inverted) ? larger_set.s.is_subset (s) : s.is_subset (larger_set.s);
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename Op>
|
||||
void process (const Op& op, const hb_bit_set_invertible_t &other)
|
||||
{ s.process (op, other.s); }
|
||||
public:
|
||||
void union_ (const hb_bit_set_invertible_t &other)
|
||||
{
|
||||
if (likely (inverted == other.inverted))
|
||||
{
|
||||
if (unlikely (inverted))
|
||||
process (hb_bitwise_and, other);
|
||||
else
|
||||
process (hb_bitwise_or, other); /* Main branch. */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlikely (inverted))
|
||||
process (hb_bitwise_gt, other);
|
||||
else
|
||||
process (hb_bitwise_lt, other);
|
||||
}
|
||||
if (likely (s.successful))
|
||||
inverted = inverted || other.inverted;
|
||||
}
|
||||
void intersect (const hb_bit_set_invertible_t &other)
|
||||
{
|
||||
if (likely (inverted == other.inverted))
|
||||
{
|
||||
if (unlikely (inverted))
|
||||
process (hb_bitwise_or, other);
|
||||
else
|
||||
process (hb_bitwise_and, other); /* Main branch. */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlikely (inverted))
|
||||
process (hb_bitwise_lt, other);
|
||||
else
|
||||
process (hb_bitwise_gt, other);
|
||||
}
|
||||
if (likely (s.successful))
|
||||
inverted = inverted && other.inverted;
|
||||
}
|
||||
void subtract (const hb_bit_set_invertible_t &other)
|
||||
{
|
||||
if (likely (inverted == other.inverted))
|
||||
{
|
||||
if (unlikely (inverted))
|
||||
process (hb_bitwise_lt, other);
|
||||
else
|
||||
process (hb_bitwise_gt, other); /* Main branch. */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlikely (inverted))
|
||||
process (hb_bitwise_or, other);
|
||||
else
|
||||
process (hb_bitwise_and, other);
|
||||
}
|
||||
if (likely (s.successful))
|
||||
inverted = inverted && !other.inverted;
|
||||
}
|
||||
void symmetric_difference (const hb_bit_set_invertible_t &other)
|
||||
{
|
||||
process (hb_bitwise_xor, other);
|
||||
if (likely (s.successful))
|
||||
inverted = inverted ^ other.inverted;
|
||||
}
|
||||
|
||||
bool next (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
if (likely (!inverted))
|
||||
return s.next (codepoint);
|
||||
|
||||
auto old = *codepoint;
|
||||
if (unlikely (old + 1 == INVALID))
|
||||
{
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto v = old;
|
||||
s.next (&v);
|
||||
if (old + 1 < v)
|
||||
{
|
||||
*codepoint = old + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
v = old;
|
||||
s.next_range (&old, &v);
|
||||
|
||||
*codepoint = v + 1;
|
||||
return *codepoint != INVALID;
|
||||
}
|
||||
bool previous (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
if (likely (!inverted))
|
||||
return s.previous (codepoint);
|
||||
|
||||
auto old = *codepoint;
|
||||
if (unlikely (old - 1 == INVALID))
|
||||
{
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto v = old;
|
||||
s.previous (&v);
|
||||
|
||||
if (old - 1 > v || v == INVALID)
|
||||
{
|
||||
*codepoint = old - 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
v = old;
|
||||
s.previous_range (&v, &old);
|
||||
|
||||
*codepoint = v - 1;
|
||||
return *codepoint != INVALID;
|
||||
}
|
||||
bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
|
||||
{
|
||||
if (likely (!inverted))
|
||||
return s.next_range (first, last);
|
||||
|
||||
if (!next (last))
|
||||
{
|
||||
*last = *first = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
*first = *last;
|
||||
s.next (last);
|
||||
--*last;
|
||||
return true;
|
||||
}
|
||||
bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
|
||||
{
|
||||
if (likely (!inverted))
|
||||
return s.previous_range (first, last);
|
||||
|
||||
if (!previous (first))
|
||||
{
|
||||
*last = *first = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
*last = *first;
|
||||
s.previous (first);
|
||||
++*first;
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID;
|
||||
|
||||
/*
|
||||
* Iterator implementation.
|
||||
*/
|
||||
struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
|
||||
{
|
||||
static constexpr bool is_sorted_iterator = true;
|
||||
iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t),
|
||||
bool init = true) : s (&s_), v (INVALID), l(0)
|
||||
{
|
||||
if (init)
|
||||
{
|
||||
l = s->get_population () + 1;
|
||||
__next__ ();
|
||||
}
|
||||
}
|
||||
|
||||
typedef hb_codepoint_t __item_t__;
|
||||
hb_codepoint_t __item__ () const { return v; }
|
||||
bool __more__ () const { return v != INVALID; }
|
||||
void __next__ () { s->next (&v); if (l) l--; }
|
||||
void __prev__ () { s->previous (&v); }
|
||||
unsigned __len__ () const { return l; }
|
||||
iter_t end () const { return iter_t (*s, false); }
|
||||
bool operator != (const iter_t& o) const
|
||||
{ return s != o.s || v != o.v; }
|
||||
|
||||
protected:
|
||||
const hb_bit_set_invertible_t *s;
|
||||
hb_codepoint_t v;
|
||||
unsigned l;
|
||||
};
|
||||
iter_t iter () const { return iter_t (*this); }
|
||||
operator iter_t () const { return iter (); }
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_BIT_SET_INVERTIBLE_HH */
|
||||
|
|
@ -0,0 +1,808 @@
|
|||
/*
|
||||
* Copyright © 2012,2017 Google, Inc.
|
||||
* Copyright © 2021 Behdad Esfahbod
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_BIT_SET_HH
|
||||
#define HB_BIT_SET_HH
|
||||
|
||||
#include "hb.hh"
|
||||
#include "hb-bit-page.hh"
|
||||
#include "hb-machinery.hh"
|
||||
|
||||
|
||||
struct hb_bit_set_t
|
||||
{
|
||||
hb_bit_set_t () { init (); }
|
||||
~hb_bit_set_t () { fini (); }
|
||||
|
||||
hb_bit_set_t (const hb_bit_set_t& other) : hb_bit_set_t () { set (other); }
|
||||
void operator= (const hb_bit_set_t& other) { set (other); }
|
||||
// TODO Add move construtor/assign
|
||||
// TODO Add constructor for Iterator; with specialization for (sorted) vector / array?
|
||||
|
||||
void init ()
|
||||
{
|
||||
successful = true;
|
||||
population = 0;
|
||||
last_page_lookup = 0;
|
||||
page_map.init ();
|
||||
pages.init ();
|
||||
}
|
||||
void fini ()
|
||||
{
|
||||
page_map.fini ();
|
||||
pages.fini ();
|
||||
}
|
||||
|
||||
using page_t = hb_bit_page_t;
|
||||
struct page_map_t
|
||||
{
|
||||
int cmp (const page_map_t &o) const { return cmp (o.major); }
|
||||
int cmp (uint32_t o_major) const { return (int) o_major - (int) major; }
|
||||
|
||||
uint32_t major;
|
||||
uint32_t index;
|
||||
};
|
||||
|
||||
bool successful; /* Allocations successful */
|
||||
mutable unsigned int population;
|
||||
mutable unsigned int last_page_lookup;
|
||||
hb_sorted_vector_t<page_map_t> page_map;
|
||||
hb_vector_t<page_t> pages;
|
||||
|
||||
void err () { if (successful) successful = false; } /* TODO Remove */
|
||||
bool in_error () const { return !successful; }
|
||||
|
||||
bool resize (unsigned int count)
|
||||
{
|
||||
if (unlikely (!successful)) return false;
|
||||
if (unlikely (!pages.resize (count) || !page_map.resize (count)))
|
||||
{
|
||||
pages.resize (page_map.length);
|
||||
successful = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void reset ()
|
||||
{
|
||||
successful = true;
|
||||
clear ();
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
resize (0);
|
||||
if (likely (successful))
|
||||
population = 0;
|
||||
}
|
||||
bool is_empty () const
|
||||
{
|
||||
unsigned int count = pages.length;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!pages[i].is_empty ())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
explicit operator bool () const { return !is_empty (); }
|
||||
|
||||
private:
|
||||
void dirty () { population = UINT_MAX; }
|
||||
public:
|
||||
|
||||
void add (hb_codepoint_t g)
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
if (unlikely (g == INVALID)) return;
|
||||
dirty ();
|
||||
page_t *page = page_for (g, true); if (unlikely (!page)) return;
|
||||
page->add (g);
|
||||
}
|
||||
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
|
||||
if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
|
||||
dirty ();
|
||||
unsigned int ma = get_major (a);
|
||||
unsigned int mb = get_major (b);
|
||||
if (ma == mb)
|
||||
{
|
||||
page_t *page = page_for (a, true); if (unlikely (!page)) return false;
|
||||
page->add_range (a, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
page_t *page = page_for (a, true); if (unlikely (!page)) return false;
|
||||
page->add_range (a, major_start (ma + 1) - 1);
|
||||
|
||||
for (unsigned int m = ma + 1; m < mb; m++)
|
||||
{
|
||||
page = page_for (major_start (m), true); if (unlikely (!page)) return false;
|
||||
page->init1 ();
|
||||
}
|
||||
|
||||
page = page_for (b, true); if (unlikely (!page)) return false;
|
||||
page->add_range (major_start (mb), b);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void set_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
if (!count) return;
|
||||
dirty ();
|
||||
hb_codepoint_t g = *array;
|
||||
while (count)
|
||||
{
|
||||
unsigned int m = get_major (g);
|
||||
page_t *page = page_for (g, v); if (unlikely (v && !page)) return;
|
||||
unsigned int start = major_start (m);
|
||||
unsigned int end = major_start (m + 1);
|
||||
do
|
||||
{
|
||||
if (v || page) /* The v check is to optimize out the page check if v is true. */
|
||||
page->set (g, v);
|
||||
|
||||
array = &StructAtOffsetUnaligned<T> (array, stride);
|
||||
count--;
|
||||
}
|
||||
while (count && (g = *array, start <= g && g < end));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{ set_array (true, array, count, stride); }
|
||||
template <typename T>
|
||||
void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
|
||||
|
||||
template <typename T>
|
||||
void del_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{ set_array (false, array, count, stride); }
|
||||
template <typename T>
|
||||
void del_array (const hb_array_t<const T>& arr) { del_array (&arr, arr.len ()); }
|
||||
|
||||
/* Might return false if array looks unsorted.
|
||||
* Used for faster rejection of corrupt data. */
|
||||
template <typename T>
|
||||
bool set_sorted_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{
|
||||
if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
|
||||
if (!count) return true;
|
||||
dirty ();
|
||||
hb_codepoint_t g = *array;
|
||||
hb_codepoint_t last_g = g;
|
||||
while (count)
|
||||
{
|
||||
unsigned int m = get_major (g);
|
||||
page_t *page = page_for (g, v); if (unlikely (v && !page)) return false;
|
||||
unsigned int end = major_start (m + 1);
|
||||
do
|
||||
{
|
||||
/* If we try harder we can change the following comparison to <=;
|
||||
* Not sure if it's worth it. */
|
||||
if (g < last_g) return false;
|
||||
last_g = g;
|
||||
|
||||
if (v || page) /* The v check is to optimize out the page check if v is true. */
|
||||
page->add (g);
|
||||
|
||||
array = (const T *) ((const char *) array + stride);
|
||||
count--;
|
||||
}
|
||||
while (count && (g = *array, g < end));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{ return set_sorted_array (true, array, count, stride); }
|
||||
template <typename T>
|
||||
bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
|
||||
|
||||
template <typename T>
|
||||
bool del_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{ return set_sorted_array (false, array, count, stride); }
|
||||
template <typename T>
|
||||
bool del_sorted_array (const hb_sorted_array_t<const T>& arr) { return del_sorted_array (&arr, arr.len ()); }
|
||||
|
||||
void del (hb_codepoint_t g)
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
page_t *page = page_for (g);
|
||||
if (!page)
|
||||
return;
|
||||
dirty ();
|
||||
page->del (g);
|
||||
}
|
||||
|
||||
private:
|
||||
void del_pages (int ds, int de)
|
||||
{
|
||||
if (ds <= de)
|
||||
{
|
||||
// Pre-allocate the workspace that compact() will need so we can bail on allocation failure
|
||||
// before attempting to rewrite the page map.
|
||||
hb_vector_t<unsigned> compact_workspace;
|
||||
if (unlikely (!allocate_compact_workspace (compact_workspace))) return;
|
||||
|
||||
unsigned int write_index = 0;
|
||||
for (unsigned int i = 0; i < page_map.length; i++)
|
||||
{
|
||||
int m = (int) page_map[i].major;
|
||||
if (m < ds || de < m)
|
||||
page_map[write_index++] = page_map[i];
|
||||
}
|
||||
compact (compact_workspace, write_index);
|
||||
resize (write_index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
void del_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
if (unlikely (a > b || a == INVALID)) return;
|
||||
dirty ();
|
||||
unsigned int ma = get_major (a);
|
||||
unsigned int mb = get_major (b);
|
||||
/* Delete pages from ds through de if ds <= de. */
|
||||
int ds = (a == major_start (ma))? (int) ma: (int) (ma + 1);
|
||||
int de = (b + 1 == major_start (mb + 1))? (int) mb: ((int) mb - 1);
|
||||
if (ds > de || (int) ma < ds)
|
||||
{
|
||||
page_t *page = page_for (a);
|
||||
if (page)
|
||||
{
|
||||
if (ma == mb)
|
||||
page->del_range (a, b);
|
||||
else
|
||||
page->del_range (a, major_start (ma + 1) - 1);
|
||||
}
|
||||
}
|
||||
if (de < (int) mb && ma != mb)
|
||||
{
|
||||
page_t *page = page_for (b);
|
||||
if (page)
|
||||
page->del_range (major_start (mb), b);
|
||||
}
|
||||
del_pages (ds, de);
|
||||
}
|
||||
|
||||
bool get (hb_codepoint_t g) const
|
||||
{
|
||||
const page_t *page = page_for (g);
|
||||
if (!page)
|
||||
return false;
|
||||
return page->get (g);
|
||||
}
|
||||
|
||||
/* Has interface. */
|
||||
static constexpr bool SENTINEL = false;
|
||||
typedef bool value_t;
|
||||
value_t operator [] (hb_codepoint_t k) const { return get (k); }
|
||||
bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
|
||||
/* Predicate. */
|
||||
bool operator () (hb_codepoint_t k) const { return has (k); }
|
||||
|
||||
/* Sink interface. */
|
||||
hb_bit_set_t& operator << (hb_codepoint_t v)
|
||||
{ add (v); return *this; }
|
||||
hb_bit_set_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
|
||||
{ add_range (range.first, range.second); return *this; }
|
||||
|
||||
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
|
||||
{
|
||||
hb_codepoint_t c = first - 1;
|
||||
return next (&c) && c <= last;
|
||||
}
|
||||
void set (const hb_bit_set_t &other)
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
unsigned int count = other.pages.length;
|
||||
if (unlikely (!resize (count)))
|
||||
return;
|
||||
population = other.population;
|
||||
|
||||
/* TODO switch to vector operator =. */
|
||||
hb_memcpy ((void *) pages, (const void *) other.pages, count * pages.item_size);
|
||||
hb_memcpy ((void *) page_map, (const void *) other.page_map, count * page_map.item_size);
|
||||
}
|
||||
|
||||
bool is_equal (const hb_bit_set_t &other) const
|
||||
{
|
||||
if (has_population () && other.has_population () &&
|
||||
get_population () != other.get_population ())
|
||||
return false;
|
||||
|
||||
unsigned int na = pages.length;
|
||||
unsigned int nb = other.pages.length;
|
||||
|
||||
unsigned int a = 0, b = 0;
|
||||
for (; a < na && b < nb; )
|
||||
{
|
||||
if (page_at (a).is_empty ()) { a++; continue; }
|
||||
if (other.page_at (b).is_empty ()) { b++; continue; }
|
||||
if (page_map[a].major != other.page_map[b].major ||
|
||||
!page_at (a).is_equal (other.page_at (b)))
|
||||
return false;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
for (; a < na; a++)
|
||||
if (!page_at (a).is_empty ()) { return false; }
|
||||
for (; b < nb; b++)
|
||||
if (!other.page_at (b).is_empty ()) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_subset (const hb_bit_set_t &larger_set) const
|
||||
{
|
||||
if (has_population () && larger_set.has_population () &&
|
||||
get_population () != larger_set.get_population ())
|
||||
return false;
|
||||
|
||||
uint32_t spi = 0;
|
||||
for (uint32_t lpi = 0; spi < page_map.length && lpi < larger_set.page_map.length; lpi++)
|
||||
{
|
||||
uint32_t spm = page_map[spi].major;
|
||||
uint32_t lpm = larger_set.page_map[lpi].major;
|
||||
auto sp = page_at (spi);
|
||||
auto lp = larger_set.page_at (lpi);
|
||||
|
||||
if (spm < lpm && !sp.is_empty ())
|
||||
return false;
|
||||
|
||||
if (lpm < spm)
|
||||
continue;
|
||||
|
||||
if (!sp.is_subset (lp))
|
||||
return false;
|
||||
|
||||
spi++;
|
||||
}
|
||||
|
||||
while (spi < page_map.length)
|
||||
if (!page_at (spi++).is_empty ())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool allocate_compact_workspace (hb_vector_t<unsigned>& workspace)
|
||||
{
|
||||
if (unlikely (!workspace.resize (pages.length)))
|
||||
{
|
||||
successful = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* workspace should be a pre-sized vector allocated to hold at exactly pages.length
|
||||
* elements.
|
||||
*/
|
||||
void compact (hb_vector_t<unsigned>& workspace,
|
||||
unsigned int length)
|
||||
{
|
||||
assert(workspace.length == pages.length);
|
||||
hb_vector_t<unsigned>& old_index_to_page_map_index = workspace;
|
||||
|
||||
hb_fill (old_index_to_page_map_index.writer(), 0xFFFFFFFF);
|
||||
for (unsigned i = 0; i < length; i++)
|
||||
old_index_to_page_map_index[page_map[i].index] = i;
|
||||
|
||||
compact_pages (old_index_to_page_map_index);
|
||||
}
|
||||
void compact_pages (const hb_vector_t<unsigned>& old_index_to_page_map_index)
|
||||
{
|
||||
unsigned int write_index = 0;
|
||||
for (unsigned int i = 0; i < pages.length; i++)
|
||||
{
|
||||
if (old_index_to_page_map_index[i] == 0xFFFFFFFF) continue;
|
||||
|
||||
if (write_index < i)
|
||||
pages[write_index] = pages[i];
|
||||
|
||||
page_map[old_index_to_page_map_index[i]].index = write_index;
|
||||
write_index++;
|
||||
}
|
||||
}
|
||||
public:
|
||||
|
||||
template <typename Op>
|
||||
void process (const Op& op, const hb_bit_set_t &other)
|
||||
{
|
||||
const bool passthru_left = op (1, 0);
|
||||
const bool passthru_right = op (0, 1);
|
||||
|
||||
if (unlikely (!successful)) return;
|
||||
|
||||
dirty ();
|
||||
|
||||
unsigned int na = pages.length;
|
||||
unsigned int nb = other.pages.length;
|
||||
unsigned int next_page = na;
|
||||
|
||||
unsigned int count = 0, newCount = 0;
|
||||
unsigned int a = 0, b = 0;
|
||||
unsigned int write_index = 0;
|
||||
|
||||
// Pre-allocate the workspace that compact() will need so we can bail on allocation failure
|
||||
// before attempting to rewrite the page map.
|
||||
hb_vector_t<unsigned> compact_workspace;
|
||||
if (!passthru_left && unlikely (!allocate_compact_workspace (compact_workspace))) return;
|
||||
|
||||
for (; a < na && b < nb; )
|
||||
{
|
||||
if (page_map[a].major == other.page_map[b].major)
|
||||
{
|
||||
if (!passthru_left)
|
||||
{
|
||||
// Move page_map entries that we're keeping from the left side set
|
||||
// to the front of the page_map vector. This isn't necessary if
|
||||
// passthru_left is set since no left side pages will be removed
|
||||
// in that case.
|
||||
if (write_index < a)
|
||||
page_map[write_index] = page_map[a];
|
||||
write_index++;
|
||||
}
|
||||
|
||||
count++;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
else if (page_map[a].major < other.page_map[b].major)
|
||||
{
|
||||
if (passthru_left)
|
||||
count++;
|
||||
a++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (passthru_right)
|
||||
count++;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
if (passthru_left)
|
||||
count += na - a;
|
||||
if (passthru_right)
|
||||
count += nb - b;
|
||||
|
||||
if (!passthru_left)
|
||||
{
|
||||
na = write_index;
|
||||
next_page = write_index;
|
||||
compact (compact_workspace, write_index);
|
||||
}
|
||||
|
||||
if (unlikely (!resize (count)))
|
||||
return;
|
||||
|
||||
newCount = count;
|
||||
|
||||
/* Process in-place backward. */
|
||||
a = na;
|
||||
b = nb;
|
||||
for (; a && b; )
|
||||
{
|
||||
if (page_map[a - 1].major == other.page_map[b - 1].major)
|
||||
{
|
||||
a--;
|
||||
b--;
|
||||
count--;
|
||||
page_map[count] = page_map[a];
|
||||
page_at (count).v = op (page_at (a).v, other.page_at (b).v);
|
||||
}
|
||||
else if (page_map[a - 1].major > other.page_map[b - 1].major)
|
||||
{
|
||||
a--;
|
||||
if (passthru_left)
|
||||
{
|
||||
count--;
|
||||
page_map[count] = page_map[a];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
b--;
|
||||
if (passthru_right)
|
||||
{
|
||||
count--;
|
||||
page_map[count].major = other.page_map[b].major;
|
||||
page_map[count].index = next_page++;
|
||||
page_at (count).v = other.page_at (b).v;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (passthru_left)
|
||||
while (a)
|
||||
{
|
||||
a--;
|
||||
count--;
|
||||
page_map[count] = page_map [a];
|
||||
}
|
||||
if (passthru_right)
|
||||
while (b)
|
||||
{
|
||||
b--;
|
||||
count--;
|
||||
page_map[count].major = other.page_map[b].major;
|
||||
page_map[count].index = next_page++;
|
||||
page_at (count).v = other.page_at (b).v;
|
||||
}
|
||||
assert (!count);
|
||||
resize (newCount);
|
||||
}
|
||||
|
||||
void union_ (const hb_bit_set_t &other) { process (hb_bitwise_or, other); }
|
||||
void intersect (const hb_bit_set_t &other) { process (hb_bitwise_and, other); }
|
||||
void subtract (const hb_bit_set_t &other) { process (hb_bitwise_gt, other); }
|
||||
void symmetric_difference (const hb_bit_set_t &other) { process (hb_bitwise_xor, other); }
|
||||
|
||||
bool next (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
// TODO: this should be merged with prev() as both implementations
|
||||
// are very similar.
|
||||
if (unlikely (*codepoint == INVALID)) {
|
||||
*codepoint = get_min ();
|
||||
return *codepoint != INVALID;
|
||||
}
|
||||
|
||||
const auto* page_map_array = page_map.arrayZ;
|
||||
unsigned int major = get_major (*codepoint);
|
||||
unsigned int i = last_page_lookup;
|
||||
|
||||
if (unlikely (i >= page_map.length || page_map_array[i].major != major))
|
||||
{
|
||||
page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST);
|
||||
if (i >= page_map.length) {
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const auto* pages_array = pages.arrayZ;
|
||||
const page_map_t ¤t = page_map_array[i];
|
||||
if (likely (current.major == major))
|
||||
{
|
||||
if (pages_array[current.index].next (codepoint))
|
||||
{
|
||||
*codepoint += current.major * page_t::PAGE_BITS;
|
||||
last_page_lookup = i;
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
for (; i < page_map.length; i++)
|
||||
{
|
||||
const page_map_t ¤t = page_map.arrayZ[i];
|
||||
hb_codepoint_t m = pages_array[current.index].get_min ();
|
||||
if (m != INVALID)
|
||||
{
|
||||
*codepoint = current.major * page_t::PAGE_BITS + m;
|
||||
last_page_lookup = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
last_page_lookup = 0;
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
bool previous (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
if (unlikely (*codepoint == INVALID)) {
|
||||
*codepoint = get_max ();
|
||||
return *codepoint != INVALID;
|
||||
}
|
||||
|
||||
page_map_t map = {get_major (*codepoint), 0};
|
||||
unsigned int i;
|
||||
page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST);
|
||||
if (i < page_map.length && page_map[i].major == map.major)
|
||||
{
|
||||
if (pages[page_map[i].index].previous (codepoint))
|
||||
{
|
||||
*codepoint += page_map[i].major * page_t::PAGE_BITS;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
i--;
|
||||
for (; (int) i >= 0; i--)
|
||||
{
|
||||
hb_codepoint_t m = pages[page_map[i].index].get_max ();
|
||||
if (m != INVALID)
|
||||
{
|
||||
*codepoint = page_map[i].major * page_t::PAGE_BITS + m;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
|
||||
{
|
||||
hb_codepoint_t i;
|
||||
|
||||
i = *last;
|
||||
if (!next (&i))
|
||||
{
|
||||
*last = *first = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* TODO Speed up. */
|
||||
*last = *first = i;
|
||||
while (next (&i) && i == *last + 1)
|
||||
(*last)++;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
|
||||
{
|
||||
hb_codepoint_t i;
|
||||
|
||||
i = *first;
|
||||
if (!previous (&i))
|
||||
{
|
||||
*last = *first = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* TODO Speed up. */
|
||||
*last = *first = i;
|
||||
while (previous (&i) && i == *first - 1)
|
||||
(*first)--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool has_population () const { return population != UINT_MAX; }
|
||||
unsigned int get_population () const
|
||||
{
|
||||
if (has_population ())
|
||||
return population;
|
||||
|
||||
unsigned int pop = 0;
|
||||
unsigned int count = pages.length;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
pop += pages[i].get_population ();
|
||||
|
||||
population = pop;
|
||||
return pop;
|
||||
}
|
||||
hb_codepoint_t get_min () const
|
||||
{
|
||||
unsigned count = pages.length;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
const auto& map = page_map[i];
|
||||
const auto& page = pages[map.index];
|
||||
|
||||
if (!page.is_empty ())
|
||||
return map.major * page_t::PAGE_BITS + page.get_min ();
|
||||
}
|
||||
return INVALID;
|
||||
}
|
||||
hb_codepoint_t get_max () const
|
||||
{
|
||||
unsigned count = pages.length;
|
||||
for (signed i = count - 1; i >= 0; i--)
|
||||
{
|
||||
const auto& map = page_map[(unsigned) i];
|
||||
const auto& page = pages[map.index];
|
||||
|
||||
if (!page.is_empty ())
|
||||
return map.major * page_t::PAGE_BITS + page.get_max ();
|
||||
}
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
static constexpr hb_codepoint_t INVALID = page_t::INVALID;
|
||||
|
||||
/*
|
||||
* Iterator implementation.
|
||||
*/
|
||||
struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
|
||||
{
|
||||
static constexpr bool is_sorted_iterator = true;
|
||||
iter_t (const hb_bit_set_t &s_ = Null (hb_bit_set_t),
|
||||
bool init = true) : s (&s_), v (INVALID), l(0)
|
||||
{
|
||||
if (init)
|
||||
{
|
||||
l = s->get_population () + 1;
|
||||
__next__ ();
|
||||
}
|
||||
}
|
||||
|
||||
typedef hb_codepoint_t __item_t__;
|
||||
hb_codepoint_t __item__ () const { return v; }
|
||||
bool __more__ () const { return v != INVALID; }
|
||||
void __next__ () { s->next (&v); if (l) l--; }
|
||||
void __prev__ () { s->previous (&v); }
|
||||
unsigned __len__ () const { return l; }
|
||||
iter_t end () const { return iter_t (*s, false); }
|
||||
bool operator != (const iter_t& o) const
|
||||
{ return s != o.s || v != o.v; }
|
||||
|
||||
protected:
|
||||
const hb_bit_set_t *s;
|
||||
hb_codepoint_t v;
|
||||
unsigned l;
|
||||
};
|
||||
iter_t iter () const { return iter_t (*this); }
|
||||
operator iter_t () const { return iter (); }
|
||||
|
||||
protected:
|
||||
|
||||
page_t *page_for (hb_codepoint_t g, bool insert = false)
|
||||
{
|
||||
page_map_t map = {get_major (g), pages.length};
|
||||
unsigned int i;
|
||||
if (!page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST))
|
||||
{
|
||||
if (!insert)
|
||||
return nullptr;
|
||||
|
||||
if (unlikely (!resize (pages.length + 1)))
|
||||
return nullptr;
|
||||
|
||||
pages[map.index].init0 ();
|
||||
memmove (page_map + i + 1,
|
||||
page_map + i,
|
||||
(page_map.length - 1 - i) * page_map.item_size);
|
||||
page_map[i] = map;
|
||||
}
|
||||
return &pages[page_map[i].index];
|
||||
}
|
||||
const page_t *page_for (hb_codepoint_t g) const
|
||||
{
|
||||
page_map_t key = {get_major (g)};
|
||||
const page_map_t *found = page_map.bsearch (key);
|
||||
if (found)
|
||||
return &pages[found->index];
|
||||
return nullptr;
|
||||
}
|
||||
page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
|
||||
const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
|
||||
unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
|
||||
hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_BIT_SET_HH */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1755,6 +1755,28 @@ hb_buffer_append (hb_buffer_t *buffer,
|
|||
memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
|
||||
if (buffer->have_positions)
|
||||
memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
|
||||
|
||||
if (source->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE)
|
||||
{
|
||||
/* See similar logic in add_utf. */
|
||||
|
||||
/* pre-context */
|
||||
if (!orig_len && start + source->context_len[0] > 0)
|
||||
{
|
||||
buffer->clear_context (0);
|
||||
while (start > 0 && buffer->context_len[0] < buffer->CONTEXT_LENGTH)
|
||||
buffer->context[0][buffer->context_len[0]++] = source->info[--start].codepoint;
|
||||
for (auto i = 0u; i < source->context_len[0] && buffer->context_len[0] < buffer->CONTEXT_LENGTH; i++)
|
||||
buffer->context[0][buffer->context_len[0]++] = source->context[0][i];
|
||||
}
|
||||
|
||||
/* post-context */
|
||||
buffer->clear_context (1);
|
||||
while (end < source->len && buffer->context_len[1] < buffer->CONTEXT_LENGTH)
|
||||
buffer->context[1][buffer->context_len[1]++] = source->info[end++].codepoint;
|
||||
for (auto i = 0u; i < source->context_len[1] && buffer->context_len[1] < buffer->CONTEXT_LENGTH; i++)
|
||||
buffer->context[1][buffer->context_len[1]++] = source->context[1][i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -280,8 +280,7 @@ struct hb_language_item_t {
|
|||
|
||||
static hb_atomic_ptr_t <hb_language_item_t> langs;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void
|
||||
static inline void
|
||||
free_langs ()
|
||||
{
|
||||
retry:
|
||||
|
|
@ -296,7 +295,6 @@ retry:
|
|||
first_lang = next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static hb_language_item_t *
|
||||
lang_find_or_insert (const char *key)
|
||||
|
|
@ -327,10 +325,8 @@ retry:
|
|||
goto retry;
|
||||
}
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
if (!first_lang)
|
||||
atexit (free_langs); /* First person registers atexit() callback. */
|
||||
#endif
|
||||
hb_atexit (free_langs); /* First person registers atexit() callback. */
|
||||
|
||||
return lang;
|
||||
}
|
||||
|
|
@ -599,6 +595,9 @@ hb_script_get_horizontal_direction (hb_script_t script)
|
|||
case HB_SCRIPT_CHORASMIAN:
|
||||
case HB_SCRIPT_YEZIDI:
|
||||
|
||||
/* Unicode-14.0 additions */
|
||||
case HB_SCRIPT_OLD_UYGHUR:
|
||||
|
||||
return HB_DIRECTION_RTL;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -476,6 +476,11 @@ hb_language_get_default (void);
|
|||
* @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7
|
||||
* @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7
|
||||
* @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7
|
||||
* @HB_SCRIPT_CYPRO_MINOAN: `Cpmn`, Since: 3.0.0
|
||||
* @HB_SCRIPT_OLD_UYGHUR: `Ougr`, Since: 3.0.0
|
||||
* @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0
|
||||
* @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0
|
||||
* @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0
|
||||
* @HB_SCRIPT_INVALID: No script set
|
||||
*
|
||||
* Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
|
||||
|
|
@ -683,6 +688,15 @@ typedef enum
|
|||
HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/
|
||||
HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/
|
||||
|
||||
/*
|
||||
* Since 3.0.0
|
||||
*/
|
||||
HB_SCRIPT_CYPRO_MINOAN = HB_TAG ('C','p','m','n'), /*14.0*/
|
||||
HB_SCRIPT_OLD_UYGHUR = HB_TAG ('O','u','g','r'), /*14.0*/
|
||||
HB_SCRIPT_TANGSA = HB_TAG ('T','n','s','a'), /*14.0*/
|
||||
HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/
|
||||
HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/
|
||||
|
||||
/* No script set. */
|
||||
HB_SCRIPT_INVALID = HB_TAG_NONE,
|
||||
|
||||
|
|
|
|||
|
|
@ -107,9 +107,6 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
|
|||
hb_font_get_glyph_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
HB_EXTERN HB_DEPRECATED void
|
||||
hb_set_invert (hb_set_t *set);
|
||||
|
||||
/**
|
||||
* hb_unicode_eastasian_width_func_t:
|
||||
* @ufuncs: A Unicode-functions structure
|
||||
|
|
|
|||
|
|
@ -561,9 +561,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
|
|||
return true;
|
||||
}
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_ft_funcs ();
|
||||
#endif
|
||||
static inline void free_static_ft_funcs ();
|
||||
|
||||
static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
|
||||
{
|
||||
|
|
@ -591,21 +589,17 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
|
|||
|
||||
hb_font_funcs_make_immutable (funcs);
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_ft_funcs);
|
||||
#endif
|
||||
hb_atexit (free_static_ft_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_ft_funcs;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_ft_funcs ()
|
||||
{
|
||||
static_ft_funcs.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
static hb_font_funcs_t *
|
||||
_hb_ft_get_font_funcs ()
|
||||
|
|
@ -905,9 +899,7 @@ hb_ft_font_create_referenced (FT_Face ft_face)
|
|||
return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
|
||||
}
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_ft_library ();
|
||||
#endif
|
||||
static inline void free_static_ft_library ();
|
||||
|
||||
static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<FT_Library>,
|
||||
hb_ft_library_lazy_loader_t>
|
||||
|
|
@ -918,9 +910,7 @@ static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<F
|
|||
if (FT_Init_FreeType (&l))
|
||||
return nullptr;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_ft_library);
|
||||
#endif
|
||||
hb_atexit (free_static_ft_library);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
|
@ -934,13 +924,11 @@ static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<F
|
|||
}
|
||||
} static_ft_library;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_ft_library ()
|
||||
{
|
||||
static_ft_library.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
static FT_Library
|
||||
get_ft_library ()
|
||||
|
|
|
|||
|
|
@ -218,9 +218,7 @@ hb_glib_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
|||
}
|
||||
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_glib_funcs ();
|
||||
#endif
|
||||
static inline void free_static_glib_funcs ();
|
||||
|
||||
static struct hb_glib_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_glib_unicode_funcs_lazy_loader_t>
|
||||
{
|
||||
|
|
@ -237,21 +235,17 @@ static struct hb_glib_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader
|
|||
|
||||
hb_unicode_funcs_make_immutable (funcs);
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_glib_funcs);
|
||||
#endif
|
||||
hb_atexit (free_static_glib_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_glib_funcs;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_glib_funcs ()
|
||||
{
|
||||
static_glib_funcs.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hb_glib_get_unicode_funcs:
|
||||
|
|
|
|||
|
|
@ -233,9 +233,7 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
|||
}
|
||||
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_icu_funcs ();
|
||||
#endif
|
||||
static inline void free_static_icu_funcs ();
|
||||
|
||||
static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_icu_unicode_funcs_lazy_loader_t>
|
||||
{
|
||||
|
|
@ -257,21 +255,17 @@ static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_
|
|||
|
||||
hb_unicode_funcs_make_immutable (funcs);
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_icu_funcs);
|
||||
#endif
|
||||
hb_atexit (free_static_icu_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_icu_funcs;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_icu_funcs ()
|
||||
{
|
||||
static_icu_funcs.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hb_icu_get_unicode_funcs:
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ hb_map_set (hb_map_t *map,
|
|||
hb_codepoint_t key,
|
||||
hb_codepoint_t value)
|
||||
{
|
||||
/* Immutable-safe. */
|
||||
map->set (key, value);
|
||||
}
|
||||
|
||||
|
|
@ -220,6 +221,7 @@ void
|
|||
hb_map_del (hb_map_t *map,
|
||||
hb_codepoint_t key)
|
||||
{
|
||||
/* Immutable-safe. */
|
||||
map->del (key);
|
||||
}
|
||||
|
||||
|
|
@ -253,9 +255,6 @@ hb_map_has (const hb_map_t *map,
|
|||
void
|
||||
hb_map_clear (hb_map_t *map)
|
||||
{
|
||||
if (unlikely (hb_object_is_immutable (map)))
|
||||
return;
|
||||
|
||||
return map->clear ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -169,6 +169,8 @@ struct hb_hashmap_t
|
|||
|
||||
void clear ()
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
|
||||
if (items)
|
||||
for (auto &_ : hb_iter (items, mask + 1))
|
||||
_.clear ();
|
||||
|
|
|
|||
|
|
@ -140,8 +140,6 @@ struct hb_lockable_set_t
|
|||
* Reference-count.
|
||||
*/
|
||||
|
||||
#define HB_REFERENCE_COUNT_INIT {0}
|
||||
|
||||
struct hb_reference_count_t
|
||||
{
|
||||
mutable hb_atomic_int_t ref_count;
|
||||
|
|
@ -197,6 +195,8 @@ struct hb_object_header_t
|
|||
hb_reference_count_t ref_count;
|
||||
mutable hb_atomic_int_t writable = 0;
|
||||
hb_atomic_ptr_t<hb_user_data_array_t> user_data;
|
||||
|
||||
bool is_inert () const { return !ref_count.get_relaxed (); }
|
||||
};
|
||||
#define HB_OBJECT_HEADER_STATIC {}
|
||||
|
||||
|
|
@ -234,11 +234,6 @@ static inline void hb_object_init (Type *obj)
|
|||
obj->header.user_data.init ();
|
||||
}
|
||||
template <typename Type>
|
||||
static inline bool hb_object_is_inert (const Type *obj)
|
||||
{
|
||||
return unlikely (obj->header.ref_count.is_inert ());
|
||||
}
|
||||
template <typename Type>
|
||||
static inline bool hb_object_is_valid (const Type *obj)
|
||||
{
|
||||
return likely (obj->header.ref_count.is_valid ());
|
||||
|
|
@ -257,7 +252,7 @@ template <typename Type>
|
|||
static inline Type *hb_object_reference (Type *obj)
|
||||
{
|
||||
hb_object_trace (obj, HB_FUNC);
|
||||
if (unlikely (!obj || hb_object_is_inert (obj)))
|
||||
if (unlikely (!obj || obj->header.is_inert ()))
|
||||
return obj;
|
||||
assert (hb_object_is_valid (obj));
|
||||
obj->header.ref_count.inc ();
|
||||
|
|
@ -267,7 +262,7 @@ template <typename Type>
|
|||
static inline bool hb_object_destroy (Type *obj)
|
||||
{
|
||||
hb_object_trace (obj, HB_FUNC);
|
||||
if (unlikely (!obj || hb_object_is_inert (obj)))
|
||||
if (unlikely (!obj || obj->header.is_inert ()))
|
||||
return false;
|
||||
assert (hb_object_is_valid (obj));
|
||||
if (obj->header.ref_count.dec () != 1)
|
||||
|
|
@ -295,7 +290,7 @@ static inline bool hb_object_set_user_data (Type *obj,
|
|||
hb_destroy_func_t destroy,
|
||||
hb_bool_t replace)
|
||||
{
|
||||
if (unlikely (!obj || hb_object_is_inert (obj)))
|
||||
if (unlikely (!obj || obj->header.is_inert ()))
|
||||
return false;
|
||||
assert (hb_object_is_valid (obj));
|
||||
|
||||
|
|
@ -322,7 +317,7 @@ template <typename Type>
|
|||
static inline void *hb_object_get_user_data (Type *obj,
|
||||
hb_user_data_key_t *key)
|
||||
{
|
||||
if (unlikely (!obj || hb_object_is_inert (obj)))
|
||||
if (unlikely (!obj || obj->header.is_inert ()))
|
||||
return nullptr;
|
||||
assert (hb_object_is_valid (obj));
|
||||
hb_user_data_array_t *user_data = obj->header.user_data.get ();
|
||||
|
|
|
|||
|
|
@ -218,29 +218,24 @@ struct CmapSubtableFormat4
|
|||
HBINT16 *idDelta,
|
||||
unsigned segcount)
|
||||
{
|
||||
hb_hashmap_t<hb_codepoint_t, hb_codepoint_t> cp_to_gid;
|
||||
+ it | hb_sink (cp_to_gid);
|
||||
|
||||
HBUINT16 *idRangeOffset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
|
||||
if (unlikely (!c->check_success (idRangeOffset))) return nullptr;
|
||||
if (unlikely ((char *)idRangeOffset - (char *)idDelta != (int) segcount * (int) HBINT16::static_size)) return nullptr;
|
||||
|
||||
+ hb_range (segcount)
|
||||
| hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; })
|
||||
| hb_apply ([&] (const unsigned i)
|
||||
{
|
||||
idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
|
||||
|
||||
+ it
|
||||
| hb_filter ([&] (const hb_item_type<Iterator> _) { return _.first >= startCode[i] && _.first <= endCode[i]; })
|
||||
| hb_apply ([&] (const hb_item_type<Iterator> _)
|
||||
{
|
||||
HBUINT16 glyID;
|
||||
glyID = _.second;
|
||||
c->copy<HBUINT16> (glyID);
|
||||
})
|
||||
;
|
||||
|
||||
|
||||
})
|
||||
;
|
||||
for (unsigned i : + hb_range (segcount)
|
||||
| hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; }))
|
||||
{
|
||||
idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
|
||||
for (hb_codepoint_t cp = startCode[i]; cp <= endCode[i]; cp++)
|
||||
{
|
||||
HBUINT16 gid;
|
||||
gid = cp_to_gid[cp];
|
||||
c->copy<HBUINT16> (gid);
|
||||
}
|
||||
}
|
||||
|
||||
return idRangeOffset;
|
||||
}
|
||||
|
|
@ -282,9 +277,17 @@ struct CmapSubtableFormat4
|
|||
HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount);
|
||||
if (unlikely (!c->check_success (idRangeOffset))) return;
|
||||
|
||||
if (unlikely (!c->check_assign(this->length,
|
||||
c->length () - table_initpos,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
|
||||
this->length = c->length () - table_initpos;
|
||||
if ((long long) this->length != (long long) c->length () - table_initpos)
|
||||
{
|
||||
// Length overflowed. Discard the current object before setting the error condition, otherwise
|
||||
// discard is a noop which prevents the higher level code from reverting the serializer to the
|
||||
// pre-error state in cmap4 overflow handling code.
|
||||
c->pop_discard ();
|
||||
c->err (HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||
return;
|
||||
}
|
||||
|
||||
this->segCountX2 = segcount * 2;
|
||||
this->entrySelector = hb_max (1u, hb_bit_storage (segcount)) - 1;
|
||||
this->searchRange = 2 * (1u << this->entrySelector);
|
||||
|
|
@ -1389,26 +1392,45 @@ struct cmap
|
|||
|
||||
template<typename Iterator, typename EncodingRecIter,
|
||||
hb_requires (hb_is_iterator (EncodingRecIter))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
EncodingRecIter encodingrec_iter,
|
||||
const void *base,
|
||||
const hb_subset_plan_t *plan)
|
||||
const hb_subset_plan_t *plan,
|
||||
bool drop_format_4 = false)
|
||||
{
|
||||
if (unlikely (!c->extend_min ((*this)))) return;
|
||||
if (unlikely (!c->extend_min ((*this)))) return false;
|
||||
this->version = 0;
|
||||
|
||||
unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0;
|
||||
auto snap = c->snapshot ();
|
||||
|
||||
for (const EncodingRecord& _ : encodingrec_iter)
|
||||
{
|
||||
if (c->in_error ())
|
||||
return false;
|
||||
|
||||
unsigned format = (base+_.subtable).u.format;
|
||||
if (format != 4 && format != 12 && format != 14) continue;
|
||||
|
||||
hb_set_t unicodes_set;
|
||||
(base+_.subtable).collect_unicodes (&unicodes_set);
|
||||
|
||||
if (format == 4) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
|
||||
if (!drop_format_4 && format == 4)
|
||||
{
|
||||
c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
|
||||
if (c->in_error () && c->only_overflow ())
|
||||
{
|
||||
// cmap4 overflowed, reset and retry serialization without format 4 subtables.
|
||||
c->revert (snap);
|
||||
return serialize (c, it,
|
||||
encodingrec_iter,
|
||||
base,
|
||||
plan,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
else if (format == 12)
|
||||
{
|
||||
if (_can_drop (_, unicodes_set, base, + it | hb_map (hb_first), encodingrec_iter)) continue;
|
||||
|
|
@ -1416,10 +1438,12 @@ struct cmap
|
|||
}
|
||||
else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
|
||||
}
|
||||
|
||||
c->check_assign(this->encodingRecord.len,
|
||||
(c->length () - cmap::min_size)/EncodingRecord::static_size,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||
|
||||
// Fail if format 4 was dropped and there is no cmap12.
|
||||
return !drop_format_4 || format12objidx;
|
||||
}
|
||||
|
||||
template<typename Iterator, typename EncodingRecordIterator,
|
||||
|
|
@ -1540,8 +1564,8 @@ struct cmap
|
|||
| hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
|
||||
{ return (_.second != HB_MAP_VALUE_INVALID); })
|
||||
;
|
||||
cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan);
|
||||
return_trace (true);
|
||||
|
||||
return_trace (cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan));
|
||||
}
|
||||
|
||||
const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
|
||||
|
|
|
|||
|
|
@ -83,8 +83,13 @@ struct CPALV1Tail
|
|||
auto *out = c->allocate_size<CPALV1Tail> (static_size);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
out->paletteFlagsZ.serialize_copy (c, paletteFlagsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
out->paletteLabelsZ.serialize_copy (c, paletteLabelsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
out->paletteFlagsZ = 0;
|
||||
if (paletteFlagsZ)
|
||||
out->paletteFlagsZ.serialize_copy (c, paletteFlagsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
|
||||
out->paletteLabelsZ = 0;
|
||||
if (paletteLabelsZ)
|
||||
out->paletteLabelsZ.serialize_copy (c, paletteLabelsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
|
||||
const hb_array_t<const NameID> colorLabels = (base+colorLabelsZ).as_array (color_count);
|
||||
if (colorLabelsZ)
|
||||
|
|
@ -119,6 +124,8 @@ struct CPALV1Tail
|
|||
}
|
||||
|
||||
protected:
|
||||
// TODO(garretrieger): these offsets can hold nulls so we should not be using non-null offsets
|
||||
// here. Currently they are needed since UnsizedArrayOf doesn't define null_size
|
||||
NNOffset32To<UnsizedArrayOf<HBUINT32>>
|
||||
paletteFlagsZ; /* Offset from the beginning of CPAL table to
|
||||
* the Palette Type Array. Set to 0 if no array
|
||||
|
|
@ -234,7 +241,7 @@ struct CPAL
|
|||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
|
||||
out->version = version;
|
||||
out->numColors = retained_color_indices.get_population ();
|
||||
out->numPalettes = numPalettes;
|
||||
|
|
|
|||
|
|
@ -253,9 +253,7 @@ hb_ot_get_font_v_extents (hb_font_t *font,
|
|||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap);
|
||||
}
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_ot_funcs ();
|
||||
#endif
|
||||
static inline void free_static_ot_funcs ();
|
||||
|
||||
static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
|
||||
{
|
||||
|
|
@ -281,21 +279,17 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
|
|||
|
||||
hb_font_funcs_make_immutable (funcs);
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_ot_funcs);
|
||||
#endif
|
||||
hb_atexit (free_static_ot_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_ot_funcs;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_ot_funcs ()
|
||||
{
|
||||
static_ot_funcs.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
static hb_font_funcs_t *
|
||||
_hb_ot_get_font_funcs ()
|
||||
|
|
|
|||
|
|
@ -1618,7 +1618,14 @@ struct Rule
|
|||
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
|
||||
(inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
|
||||
for (unsigned i = 0; i < (unsigned) lookupCount; i++)
|
||||
{
|
||||
if (!lookup_map->has (lookupRecord[i].lookupListIndex))
|
||||
{
|
||||
out->lookupCount--;
|
||||
continue;
|
||||
}
|
||||
c->copy (lookupRecord[i], lookup_map);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
@ -2234,7 +2241,14 @@ struct ContextFormat3
|
|||
const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
|
||||
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
|
||||
for (unsigned i = 0; i < (unsigned) lookupCount; i++)
|
||||
{
|
||||
if (!lookup_map->has (lookupRecord[i].lookupListIndex))
|
||||
{
|
||||
out->lookupCount--;
|
||||
continue;
|
||||
}
|
||||
c->serializer->copy (lookupRecord[i], lookup_map);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
@ -3303,13 +3317,21 @@ struct ChainContextFormat3
|
|||
return_trace (false);
|
||||
|
||||
const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
|
||||
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
|
||||
hb_set_t lookup_indices;
|
||||
for (unsigned i = 0; i < (unsigned) lookupRecord.len; i++)
|
||||
if (lookup_map->has (lookupRecord[i].lookupListIndex))
|
||||
lookup_indices.add (i);
|
||||
|
||||
HBUINT16 lookupCount;
|
||||
lookupCount = lookupRecord.len;
|
||||
lookupCount = lookup_indices.get_population ();
|
||||
if (!c->serializer->copy (lookupCount)) return_trace (false);
|
||||
|
||||
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
|
||||
for (unsigned i = 0; i < (unsigned) lookupCount; i++)
|
||||
if (!c->serializer->copy (lookupRecord[i], lookup_map)) return_trace (false);
|
||||
for (unsigned i : lookup_indices.iter ())
|
||||
{
|
||||
if (!c->serializer->copy (lookupRecord[i], lookup_map))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
@ -3719,8 +3741,9 @@ struct GSUBGPOS
|
|||
hb_set_t alternate_feature_indices;
|
||||
if (version.to_int () >= 0x00010001u)
|
||||
(this+featureVars).closure_features (lookup_indices, &alternate_feature_indices);
|
||||
if (unlikely (alternate_feature_indices.in_error())) {
|
||||
feature_indices->successful = false;
|
||||
if (unlikely (alternate_feature_indices.in_error()))
|
||||
{
|
||||
feature_indices->err ();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
|
|||
face = face_;
|
||||
props = *props_;
|
||||
|
||||
|
||||
/* Fetch script/language indices for GSUB/GPOS. We need these later to skip
|
||||
* features not available in either table and not waste precious bits for them. */
|
||||
|
||||
|
|
@ -63,12 +62,28 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
|
|||
hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
|
||||
hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
|
||||
|
||||
hb_ot_tags_from_script_and_language (props.script, props.language, &script_count, script_tags, &language_count, language_tags);
|
||||
hb_ot_tags_from_script_and_language (props.script,
|
||||
props.language,
|
||||
&script_count,
|
||||
script_tags,
|
||||
&language_count,
|
||||
language_tags);
|
||||
|
||||
for (unsigned int table_index = 0; table_index < 2; table_index++) {
|
||||
for (unsigned int table_index = 0; table_index < 2; table_index++)
|
||||
{
|
||||
hb_tag_t table_tag = table_tags[table_index];
|
||||
found_script[table_index] = (bool) hb_ot_layout_table_select_script (face, table_tag, script_count, script_tags, &script_index[table_index], &chosen_script[table_index]);
|
||||
hb_ot_layout_script_select_language (face, table_tag, script_index[table_index], language_count, language_tags, &language_index[table_index]);
|
||||
found_script[table_index] = (bool) hb_ot_layout_table_select_script (face,
|
||||
table_tag,
|
||||
script_count,
|
||||
script_tags,
|
||||
&script_index[table_index],
|
||||
&chosen_script[table_index]);
|
||||
hb_ot_layout_script_select_language (face,
|
||||
table_tag,
|
||||
script_index[table_index],
|
||||
language_count,
|
||||
language_tags,
|
||||
&language_index[table_index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -156,7 +156,8 @@ hb_ot_name_get_utf (hb_face_t *face,
|
|||
*
|
||||
* Fetches a font name from the OpenType 'name' table.
|
||||
* If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
|
||||
* Returns string in UTF-8 encoding.
|
||||
* Returns string in UTF-8 encoding. A NUL terminator is always written
|
||||
* for convenience, and isn't included in the output @text_size.
|
||||
*
|
||||
* Returns: full length of the requested string, or 0 if not found.
|
||||
* Since: 2.1.0
|
||||
|
|
@ -183,7 +184,8 @@ hb_ot_name_get_utf8 (hb_face_t *face,
|
|||
*
|
||||
* Fetches a font name from the OpenType 'name' table.
|
||||
* If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
|
||||
* Returns string in UTF-16 encoding.
|
||||
* Returns string in UTF-16 encoding. A NUL terminator is always written
|
||||
* for convenience, and isn't included in the output @text_size.
|
||||
*
|
||||
* Returns: full length of the requested string, or 0 if not found.
|
||||
* Since: 2.1.0
|
||||
|
|
@ -209,7 +211,8 @@ hb_ot_name_get_utf16 (hb_face_t *face,
|
|||
*
|
||||
* Fetches a font name from the OpenType 'name' table.
|
||||
* If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
|
||||
* Returns string in UTF-32 encoding.
|
||||
* Returns string in UTF-32 encoding. A NUL terminator is always written
|
||||
* for convenience, and isn't included in the output @text_size.
|
||||
*
|
||||
* Returns: full length of the requested string, or 0 if not found.
|
||||
* Since: 2.1.0
|
||||
|
|
|
|||
|
|
@ -76,6 +76,9 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
|
|||
hb_map_t old_new_index_map, old_gid_new_index_map;
|
||||
unsigned i = 0;
|
||||
|
||||
post::accelerator_t _post;
|
||||
_post.init (c->plan->source);
|
||||
|
||||
for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
|
||||
{
|
||||
hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
|
||||
|
|
@ -86,9 +89,24 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
|
|||
else if (old_new_index_map.has (old_index)) new_index = old_new_index_map.get (old_index);
|
||||
else
|
||||
{
|
||||
new_index = 258 + i;
|
||||
hb_bytes_t s = _post.find_glyph_name (old_gid);
|
||||
int standard_glyph_index = -1;
|
||||
for (unsigned i = 0; i < format1_names_length; i++)
|
||||
{
|
||||
if (s == format1_names (i))
|
||||
{
|
||||
standard_glyph_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (standard_glyph_index == -1)
|
||||
{
|
||||
new_index = 258 + i;
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{ new_index = standard_glyph_index; }
|
||||
old_new_index_map.set (old_index, new_index);
|
||||
i++;
|
||||
}
|
||||
old_gid_new_index_map.set (old_gid, new_index);
|
||||
}
|
||||
|
|
@ -103,8 +121,6 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
|
|||
})
|
||||
;
|
||||
|
||||
post::accelerator_t _post;
|
||||
_post.init (c->plan->source);
|
||||
bool ret = serialize (c->serializer, index_iter, &_post);
|
||||
_post.fini ();
|
||||
return_trace (ret);
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
*
|
||||
* on files with these headers:
|
||||
*
|
||||
* # ArabicShaping-13.0.0.txt
|
||||
* # Date: 2020-01-31, 23:55:00 GMT [KW, RP]
|
||||
* # Scripts-13.0.0.txt
|
||||
* # Date: 2020-01-22, 00:07:43 GMT
|
||||
* # ArabicShaping-14.0.0.txt
|
||||
* # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
|
||||
* # Scripts-14.0.0.txt
|
||||
* # Date: 2021-07-10, 00:35:31 GMT
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_JOINING_LIST_HH
|
||||
|
|
@ -29,6 +29,7 @@ has_arabic_joining (hb_script_t script)
|
|||
case HB_SCRIPT_MANICHAEAN:
|
||||
case HB_SCRIPT_MONGOLIAN:
|
||||
case HB_SCRIPT_NKO:
|
||||
case HB_SCRIPT_OLD_UYGHUR:
|
||||
case HB_SCRIPT_PHAGS_PA:
|
||||
case HB_SCRIPT_PSALTER_PAHLAVI:
|
||||
case HB_SCRIPT_SOGDIAN:
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
*
|
||||
* on files with these headers:
|
||||
*
|
||||
* # ArabicShaping-13.0.0.txt
|
||||
* # Date: 2020-01-31, 23:55:00 GMT [KW, RP]
|
||||
* # Blocks-13.0.0.txt
|
||||
* # Date: 2019-07-10, 19:06:00 GMT [KW]
|
||||
* # ArabicShaping-14.0.0.txt
|
||||
* # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
|
||||
* # Blocks-14.0.0.txt
|
||||
* # Date: 2021-01-22, 23:29:00 GMT [KW]
|
||||
* UnicodeData.txt does not have a header.
|
||||
*/
|
||||
|
||||
|
|
@ -75,13 +75,17 @@ static const uint8_t joining_table[] =
|
|||
|
||||
/* Syriac Supplement */
|
||||
|
||||
/* 0860 */ D,U,D,D,D,D,U,R,D,R,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
/* 0880 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
/* 0860 */ D,U,D,D,D,D,U,R,D,R,R,X,X,X,X,X,
|
||||
|
||||
/* Arabic Extended-B */
|
||||
|
||||
/* 0860 */ R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,
|
||||
/* 0880 */ R,R,R,C,C,C,D,U,U,D,D,D,D,D,R,X,U,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
|
||||
/* Arabic Extended-A */
|
||||
|
||||
/* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,X,D,D,D,R,D,D,D,D,D,D,
|
||||
/* 08C0 */ D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
/* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,D,D,D,D,R,D,D,D,D,D,D,
|
||||
/* 08C0 */ D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
/* 08E0 */ X,X,U,
|
||||
|
||||
#define joining_offset_0x1806u 739
|
||||
|
|
@ -137,23 +141,28 @@ static const uint8_t joining_table[] =
|
|||
/* Sogdian */
|
||||
|
||||
/* 10F20 */ D,D,D,R,D,D,D,D,D,D,D,D,D,D,D,D,
|
||||
/* 10F40 */ D,D,D,D,D,U,X,X,X,X,X,X,X,X,X,X,X,D,D,D,R,
|
||||
/* 10F40 */ D,D,D,D,D,U,X,X,X,X,X,X,X,X,X,X,X,D,D,D,R,X,X,X,X,X,X,X,X,X,X,X,
|
||||
/* 10F60 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
|
||||
#define joining_offset_0x10fb0u 1219
|
||||
/* Old Uyghur */
|
||||
|
||||
/* 10F60 */ D,D,D,D,R,R,D,D,D,D,D,D,D,D,D,D,
|
||||
/* 10F80 */ D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
/* 10FA0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
|
||||
/* Chorasmian */
|
||||
|
||||
/* 10FA0 */ D,U,D,D,R,R,R,U,D,R,R,D,D,R,D,D,
|
||||
/* 10FC0 */ U,D,R,R,D,U,U,U,U,R,D,L,
|
||||
|
||||
#define joining_offset_0x110bdu 1247
|
||||
#define joining_offset_0x110bdu 1338
|
||||
|
||||
/* Kaithi */
|
||||
|
||||
/* 110A0 */ U,X,X,
|
||||
/* 110C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,U,
|
||||
|
||||
#define joining_offset_0x1e900u 1264
|
||||
#define joining_offset_0x1e900u 1355
|
||||
|
||||
/* Adlam */
|
||||
|
||||
|
|
@ -161,7 +170,7 @@ static const uint8_t joining_table[] =
|
|||
/* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
|
||||
/* 1E940 */ D,D,D,D,X,X,X,X,X,X,X,T,
|
||||
|
||||
}; /* Table items: 1340; occupancy: 57% */
|
||||
}; /* Table items: 1431; occupancy: 57% */
|
||||
|
||||
|
||||
static unsigned int
|
||||
|
|
@ -189,8 +198,7 @@ joining_type (hb_codepoint_t u)
|
|||
if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D23u)) return joining_table[u - 0x10D00u + joining_offset_0x10d00u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10F54u)) return joining_table[u - 0x10F30u + joining_offset_0x10f30u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10FB0u, 0x10FCBu)) return joining_table[u - 0x10FB0u + joining_offset_0x10fb0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10FCBu)) return joining_table[u - 0x10F30u + joining_offset_0x10f30u];
|
||||
break;
|
||||
|
||||
case 0x11u:
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@
|
|||
*
|
||||
* on files with these headers:
|
||||
*
|
||||
* # IndicSyllabicCategory-13.0.0.txt
|
||||
* # Date: 2019-07-22, 19:55:00 GMT [KW, RP]
|
||||
* # IndicPositionalCategory-13.0.0.txt
|
||||
* # Date: 2019-07-23, 00:01:00 GMT [KW, RP]
|
||||
* # Blocks-13.0.0.txt
|
||||
* # Date: 2019-07-10, 19:06:00 GMT [KW]
|
||||
* # IndicSyllabicCategory-14.0.0.txt
|
||||
* # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
|
||||
* # IndicPositionalCategory-14.0.0.txt
|
||||
* # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
|
||||
* # Blocks-14.0.0.txt
|
||||
* # Date: 2021-01-22, 23:29:00 GMT [KW]
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
|
@ -27,9 +27,9 @@
|
|||
#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 91 chars; Bindu */
|
||||
#define ISC_BJN INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER /* 20 chars; Brahmi_Joining_Number */
|
||||
#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 59 chars; Cantillation_Mark */
|
||||
#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 2195 chars; Consonant */
|
||||
#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 12 chars; Consonant_Dead */
|
||||
#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 67 chars; Consonant_Final */
|
||||
#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 2206 chars; Consonant */
|
||||
#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 14 chars; Consonant_Dead */
|
||||
#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 70 chars; Consonant_Final */
|
||||
#define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 5 chars; Consonant_Head_Letter */
|
||||
#define ISC_CIP INDIC_SYLLABIC_CATEGORY_CONSONANT_INITIAL_POSTFIXED /* 1 chars; Consonant_Initial_Postfixed */
|
||||
#define ISC_CK INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER /* 2 chars; Consonant_Killer */
|
||||
|
|
@ -38,18 +38,18 @@
|
|||
#define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 3 chars; Consonant_Preceding_Repha */
|
||||
#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 10 chars; Consonant_Prefixed */
|
||||
#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 94 chars; Consonant_Subjoined */
|
||||
#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 4 chars; Consonant_Succeeding_Repha */
|
||||
#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 1 chars; Consonant_Succeeding_Repha */
|
||||
#define ISC_CWS INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER /* 8 chars; Consonant_With_Stacker */
|
||||
#define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 3 chars; Gemination_Mark */
|
||||
#define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 12 chars; Invisible_Stacker */
|
||||
#define ISC_ZWJ INDIC_SYLLABIC_CATEGORY_JOINER /* 1 chars; Joiner */
|
||||
#define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */
|
||||
#define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER /* 1 chars; Non_Joiner */
|
||||
#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 31 chars; Nukta */
|
||||
#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 32 chars; Nukta */
|
||||
#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 491 chars; Number */
|
||||
#define ISC_NJ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER /* 1 chars; Number_Joiner */
|
||||
#define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */
|
||||
#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 23 chars; Pure_Killer */
|
||||
#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 25 chars; Pure_Killer */
|
||||
#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 2 chars; Register_Shifter */
|
||||
#define ISC_SM INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER /* 25 chars; Syllable_Modifier */
|
||||
#define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */
|
||||
|
|
@ -57,18 +57,18 @@
|
|||
#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 27 chars; Virama */
|
||||
#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 35 chars; Visarga */
|
||||
#define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 30 chars; Vowel */
|
||||
#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 683 chars; Vowel_Dependent */
|
||||
#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 484 chars; Vowel_Independent */
|
||||
#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 686 chars; Vowel_Dependent */
|
||||
#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 486 chars; Vowel_Independent */
|
||||
|
||||
#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 351 chars; Bottom */
|
||||
#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 352 chars; Bottom */
|
||||
#define IMC_BL INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT /* 1 chars; Bottom_And_Left */
|
||||
#define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 4 chars; Bottom_And_Right */
|
||||
#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 64 chars; Left */
|
||||
#define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 22 chars; Left_And_Right */
|
||||
#define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */
|
||||
#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 10 chars; Overstruck */
|
||||
#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 288 chars; Right */
|
||||
#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 415 chars; Top */
|
||||
#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 290 chars; Right */
|
||||
#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 418 chars; Top */
|
||||
#define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 10 chars; Top_And_Bottom */
|
||||
#define IMC_TBL INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_LEFT /* 2 chars; Top_And_Bottom_And_Left */
|
||||
#define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */
|
||||
|
|
@ -231,11 +231,11 @@ static const uint16_t indic_table[] = {
|
|||
/* 0C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
|
||||
/* 0C28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
|
||||
/* 0C30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
|
||||
/* 0C38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(A,x), _(M,T), _(M,T),
|
||||
/* 0C38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,T), _(M,T),
|
||||
/* 0C40 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,T),
|
||||
/* 0C48 */ _(M,TB), _(x,x), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x), _(x,x),
|
||||
/* 0C50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,B), _(x,x),
|
||||
/* 0C58 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
|
||||
/* 0C58 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(CD,x), _(x,x), _(x,x),
|
||||
/* 0C60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
|
||||
/* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
|
||||
/* 0C70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
|
||||
|
|
@ -254,7 +254,7 @@ static const uint16_t indic_table[] = {
|
|||
/* 0CC0 */ _(M,TR), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,TR),
|
||||
/* 0CC8 */ _(M,TR), _(x,x), _(M,TR), _(M,TR), _(M,T), _(V,T), _(x,x), _(x,x),
|
||||
/* 0CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), _(x,x),
|
||||
/* 0CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(x,x),
|
||||
/* 0CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CD,x), _(C,x), _(x,x),
|
||||
/* 0CE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
|
||||
/* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
|
||||
/* 0CF0 */ _(x,x),_(CWS,x),_(CWS,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
|
||||
|
|
@ -402,7 +402,7 @@ static const uint16_t indic_table[] = {
|
|||
/* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(CP,x), _(CP,x), _(CP,x), _(x,x),
|
||||
/* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,R), _(TM,T), _(TM,R), _(C,x), _(C,x),
|
||||
|
||||
}; /* Table items: 1792; occupancy: 70% */
|
||||
}; /* Table items: 1792; occupancy: 71% */
|
||||
|
||||
uint16_t
|
||||
hb_indic_get_categories (hb_codepoint_t u)
|
||||
|
|
|
|||
|
|
@ -1,29 +1,30 @@
|
|||
|
||||
#line 1 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
/*
|
||||
* Copyright © 2011,2012 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): Behdad Esfahbod
|
||||
*/
|
||||
* Copyright © 2011,2012 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): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
|
||||
#define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
|
||||
|
|
@ -31,13 +32,13 @@
|
|||
#include "hb.hh"
|
||||
|
||||
enum khmer_syllable_type_t {
|
||||
khmer_consonant_syllable,
|
||||
khmer_broken_cluster,
|
||||
khmer_non_khmer_cluster,
|
||||
khmer_consonant_syllable,
|
||||
khmer_broken_cluster,
|
||||
khmer_non_khmer_cluster,
|
||||
};
|
||||
|
||||
|
||||
#line 41 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
#line 42 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
#define khmer_syllable_machine_ex_C 1u
|
||||
#define khmer_syllable_machine_ex_Coeng 14u
|
||||
#define khmer_syllable_machine_ex_DOTTEDCIRCLE 12u
|
||||
|
|
@ -55,125 +56,180 @@ enum khmer_syllable_type_t {
|
|||
#define khmer_syllable_machine_ex_ZWNJ 5u
|
||||
|
||||
|
||||
#line 59 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
#line 60 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
static const unsigned char _khmer_syllable_machine_trans_keys[] = {
|
||||
2u, 8u, 2u, 6u, 2u, 8u, 2u, 6u,
|
||||
0u, 0u, 2u, 6u, 2u, 8u, 2u, 6u,
|
||||
2u, 8u, 2u, 6u, 2u, 6u, 2u, 8u,
|
||||
2u, 6u, 0u, 0u, 2u, 6u, 2u, 8u,
|
||||
2u, 6u, 2u, 8u, 2u, 6u, 2u, 8u,
|
||||
0u, 11u, 2u, 11u, 2u, 11u, 2u, 11u,
|
||||
7u, 7u, 2u, 7u, 2u, 11u, 2u, 11u,
|
||||
2u, 11u, 0u, 0u, 2u, 8u, 2u, 11u,
|
||||
2u, 11u, 7u, 7u, 2u, 7u, 2u, 11u,
|
||||
2u, 11u, 0u, 0u, 2u, 11u, 2u, 11u,
|
||||
0u
|
||||
5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u,
|
||||
5u, 26u, 5u, 21u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u,
|
||||
5u, 21u, 5u, 26u, 5u, 21u, 5u, 26u, 1u, 29u, 5u, 29u, 5u, 29u, 5u, 29u,
|
||||
22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 26u, 5u, 29u,
|
||||
5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 29u, 5u, 29u,
|
||||
0
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_char_class[] = {
|
||||
0, 0, 1, 1, 2, 2, 1, 1,
|
||||
1, 1, 3, 3, 1, 4, 1, 0,
|
||||
1, 1, 1, 5, 6, 7, 1, 1,
|
||||
1, 8, 9, 10, 11, 0
|
||||
static const char _khmer_syllable_machine_key_spans[] = {
|
||||
22, 17, 22, 17, 16, 17, 22, 17,
|
||||
22, 17, 17, 22, 17, 16, 17, 22,
|
||||
17, 22, 17, 22, 29, 25, 25, 25,
|
||||
1, 18, 25, 25, 25, 16, 22, 25,
|
||||
25, 1, 18, 25, 25, 16, 25, 25
|
||||
};
|
||||
|
||||
static const short _khmer_syllable_machine_index_offsets[] = {
|
||||
0, 7, 12, 19, 24, 25, 30, 37,
|
||||
42, 49, 54, 59, 66, 71, 72, 77,
|
||||
84, 89, 96, 101, 108, 120, 130, 140,
|
||||
150, 151, 157, 167, 177, 187, 188, 195,
|
||||
205, 215, 216, 222, 232, 242, 243, 253,
|
||||
0
|
||||
0, 23, 41, 64, 82, 99, 117, 140,
|
||||
158, 181, 199, 217, 240, 258, 275, 293,
|
||||
316, 334, 357, 375, 398, 428, 454, 480,
|
||||
506, 508, 527, 553, 579, 605, 622, 645,
|
||||
671, 697, 699, 718, 744, 770, 787, 813
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_indicies[] = {
|
||||
1, 0, 0, 2, 3, 0, 4, 1,
|
||||
0, 0, 0, 3, 1, 0, 0, 0,
|
||||
3, 0, 4, 5, 0, 0, 0, 4,
|
||||
6, 7, 0, 0, 0, 8, 9, 0,
|
||||
0, 0, 10, 0, 4, 9, 0, 0,
|
||||
0, 10, 11, 0, 0, 0, 12, 0,
|
||||
4, 11, 0, 0, 0, 12, 14, 13,
|
||||
13, 13, 15, 14, 16, 16, 16, 15,
|
||||
16, 17, 18, 16, 16, 16, 17, 19,
|
||||
20, 16, 16, 16, 21, 22, 16, 16,
|
||||
16, 23, 16, 17, 22, 16, 16, 16,
|
||||
23, 24, 16, 16, 16, 25, 16, 17,
|
||||
24, 16, 16, 16, 25, 14, 16, 16,
|
||||
26, 15, 16, 17, 29, 28, 30, 2,
|
||||
31, 28, 15, 19, 17, 23, 25, 21,
|
||||
33, 32, 34, 2, 3, 6, 4, 10,
|
||||
12, 8, 35, 32, 36, 32, 3, 6,
|
||||
4, 10, 12, 8, 5, 32, 36, 32,
|
||||
4, 6, 32, 32, 32, 8, 6, 7,
|
||||
32, 36, 32, 8, 6, 37, 32, 36,
|
||||
32, 10, 6, 4, 32, 32, 8, 38,
|
||||
32, 36, 32, 12, 6, 4, 10, 32,
|
||||
8, 35, 32, 34, 32, 3, 6, 4,
|
||||
10, 12, 8, 29, 14, 39, 39, 39,
|
||||
15, 39, 17, 41, 40, 42, 40, 15,
|
||||
19, 17, 23, 25, 21, 18, 40, 42,
|
||||
40, 17, 19, 40, 40, 40, 21, 19,
|
||||
20, 40, 42, 40, 21, 19, 43, 40,
|
||||
42, 40, 23, 19, 17, 40, 40, 21,
|
||||
44, 40, 42, 40, 25, 19, 17, 23,
|
||||
40, 21, 45, 46, 40, 31, 26, 15,
|
||||
19, 17, 23, 25, 21, 41, 40, 31,
|
||||
40, 15, 19, 17, 23, 25, 21, 0
|
||||
static const char _khmer_syllable_machine_indicies[] = {
|
||||
1, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 2,
|
||||
3, 0, 0, 0, 0, 4, 0, 1,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 3,
|
||||
0, 1, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 3, 0, 0, 0, 0, 4, 0,
|
||||
5, 5, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 0, 6, 6, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 6, 0, 7, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 8, 0, 9, 9, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 10, 0, 0,
|
||||
0, 0, 4, 0, 9, 9, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 10, 0, 11, 11,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 12, 0,
|
||||
0, 0, 0, 4, 0, 11, 11, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 12, 0, 14,
|
||||
14, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 15,
|
||||
13, 14, 14, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 15, 16, 16, 16, 16, 17, 16,
|
||||
18, 18, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
17, 16, 19, 19, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 19, 16, 20, 20, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 21, 16, 22, 22, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 23, 16, 16,
|
||||
16, 16, 17, 16, 22, 22, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 23, 16, 24, 24,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 25, 16,
|
||||
16, 16, 16, 17, 16, 24, 24, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 25, 16, 14,
|
||||
14, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 26, 15,
|
||||
16, 16, 16, 16, 17, 16, 28, 28,
|
||||
27, 27, 29, 29, 27, 27, 27, 27,
|
||||
2, 2, 27, 30, 27, 28, 27, 27,
|
||||
27, 27, 15, 19, 27, 27, 27, 17,
|
||||
23, 25, 21, 27, 32, 32, 31, 31,
|
||||
31, 31, 31, 31, 31, 33, 31, 31,
|
||||
31, 31, 31, 2, 3, 6, 31, 31,
|
||||
31, 4, 10, 12, 8, 31, 34, 34,
|
||||
31, 31, 31, 31, 31, 31, 31, 35,
|
||||
31, 31, 31, 31, 31, 31, 3, 6,
|
||||
31, 31, 31, 4, 10, 12, 8, 31,
|
||||
5, 5, 31, 31, 31, 31, 31, 31,
|
||||
31, 35, 31, 31, 31, 31, 31, 31,
|
||||
4, 6, 31, 31, 31, 31, 31, 31,
|
||||
8, 31, 6, 31, 7, 7, 31, 31,
|
||||
31, 31, 31, 31, 31, 35, 31, 31,
|
||||
31, 31, 31, 31, 8, 6, 31, 36,
|
||||
36, 31, 31, 31, 31, 31, 31, 31,
|
||||
35, 31, 31, 31, 31, 31, 31, 10,
|
||||
6, 31, 31, 31, 4, 31, 31, 8,
|
||||
31, 37, 37, 31, 31, 31, 31, 31,
|
||||
31, 31, 35, 31, 31, 31, 31, 31,
|
||||
31, 12, 6, 31, 31, 31, 4, 10,
|
||||
31, 8, 31, 34, 34, 31, 31, 31,
|
||||
31, 31, 31, 31, 33, 31, 31, 31,
|
||||
31, 31, 31, 3, 6, 31, 31, 31,
|
||||
4, 10, 12, 8, 31, 28, 28, 31,
|
||||
31, 31, 31, 31, 31, 31, 31, 31,
|
||||
31, 31, 31, 31, 28, 31, 14, 14,
|
||||
38, 38, 38, 38, 38, 38, 38, 38,
|
||||
38, 38, 38, 38, 38, 38, 15, 38,
|
||||
38, 38, 38, 17, 38, 40, 40, 39,
|
||||
39, 39, 39, 39, 39, 39, 41, 39,
|
||||
39, 39, 39, 39, 39, 15, 19, 39,
|
||||
39, 39, 17, 23, 25, 21, 39, 18,
|
||||
18, 39, 39, 39, 39, 39, 39, 39,
|
||||
41, 39, 39, 39, 39, 39, 39, 17,
|
||||
19, 39, 39, 39, 39, 39, 39, 21,
|
||||
39, 19, 39, 20, 20, 39, 39, 39,
|
||||
39, 39, 39, 39, 41, 39, 39, 39,
|
||||
39, 39, 39, 21, 19, 39, 42, 42,
|
||||
39, 39, 39, 39, 39, 39, 39, 41,
|
||||
39, 39, 39, 39, 39, 39, 23, 19,
|
||||
39, 39, 39, 17, 39, 39, 21, 39,
|
||||
43, 43, 39, 39, 39, 39, 39, 39,
|
||||
39, 41, 39, 39, 39, 39, 39, 39,
|
||||
25, 19, 39, 39, 39, 17, 23, 39,
|
||||
21, 39, 44, 44, 39, 39, 39, 39,
|
||||
39, 39, 39, 39, 39, 39, 39, 39,
|
||||
39, 44, 39, 45, 45, 39, 39, 39,
|
||||
39, 39, 39, 39, 30, 39, 39, 39,
|
||||
39, 39, 26, 15, 19, 39, 39, 39,
|
||||
17, 23, 25, 21, 39, 40, 40, 39,
|
||||
39, 39, 39, 39, 39, 39, 30, 39,
|
||||
39, 39, 39, 39, 39, 15, 19, 39,
|
||||
39, 39, 17, 23, 25, 21, 39, 0
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_index_defaults[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 13, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 28, 32, 32, 32,
|
||||
32, 32, 32, 32, 32, 32, 39, 40,
|
||||
40, 40, 40, 40, 40, 40, 40, 40,
|
||||
0
|
||||
static const char _khmer_syllable_machine_trans_targs[] = {
|
||||
20, 1, 28, 22, 23, 3, 24, 5,
|
||||
25, 7, 26, 9, 27, 20, 10, 31,
|
||||
20, 32, 12, 33, 14, 34, 16, 35,
|
||||
18, 36, 39, 20, 21, 30, 37, 20,
|
||||
0, 29, 2, 4, 6, 8, 20, 20,
|
||||
11, 13, 15, 17, 38, 19
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_cond_targs[] = {
|
||||
20, 1, 28, 22, 23, 3, 24, 5,
|
||||
25, 7, 26, 9, 27, 20, 10, 31,
|
||||
20, 32, 12, 33, 14, 34, 16, 35,
|
||||
18, 36, 39, 20, 20, 21, 30, 37,
|
||||
20, 0, 29, 2, 4, 6, 8, 20,
|
||||
20, 11, 13, 15, 17, 38, 19, 0
|
||||
static const char _khmer_syllable_machine_trans_actions[] = {
|
||||
1, 0, 2, 2, 2, 0, 0, 0,
|
||||
2, 0, 2, 0, 2, 3, 0, 4,
|
||||
5, 2, 0, 0, 0, 2, 0, 2,
|
||||
0, 2, 4, 8, 2, 9, 0, 10,
|
||||
0, 0, 0, 0, 0, 0, 11, 12,
|
||||
0, 0, 0, 0, 4, 0
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_cond_actions[] = {
|
||||
1, 0, 2, 2, 2, 0, 0, 0,
|
||||
2, 0, 2, 0, 2, 3, 0, 4,
|
||||
5, 2, 0, 0, 0, 2, 0, 2,
|
||||
0, 2, 4, 0, 8, 2, 9, 0,
|
||||
10, 0, 0, 0, 0, 0, 0, 11,
|
||||
12, 0, 0, 0, 0, 4, 0, 0
|
||||
static const char _khmer_syllable_machine_to_state_actions[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 6, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_to_state_actions[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 6, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0
|
||||
static const char _khmer_syllable_machine_from_state_actions[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_from_state_actions[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_eof_trans[] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 14, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 28, 33, 33, 33,
|
||||
33, 33, 33, 33, 33, 33, 40, 41,
|
||||
41, 41, 41, 41, 41, 41, 41, 41,
|
||||
0
|
||||
static const unsigned char _khmer_syllable_machine_eof_trans[] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 14, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 0, 32, 32, 32,
|
||||
32, 32, 32, 32, 32, 32, 39, 40,
|
||||
40, 40, 40, 40, 40, 40, 40, 40
|
||||
};
|
||||
|
||||
static const int khmer_syllable_machine_start = 20;
|
||||
|
|
@ -191,263 +247,148 @@ static const int khmer_syllable_machine_en_main = 20;
|
|||
|
||||
|
||||
#define found_syllable(syllable_type) \
|
||||
HB_STMT_START { \
|
||||
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
|
||||
for (unsigned int i = ts; i < te; i++) \
|
||||
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
|
||||
syllable_serial++; \
|
||||
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
|
||||
} HB_STMT_END
|
||||
HB_STMT_START { \
|
||||
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
|
||||
for (unsigned int i = ts; i < te; i++) \
|
||||
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
|
||||
syllable_serial++; \
|
||||
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
|
||||
} HB_STMT_END
|
||||
|
||||
static void
|
||||
find_syllables_khmer (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int p, pe, eof, ts, te, act HB_UNUSED;
|
||||
int cs;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
||||
#line 210 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
unsigned int p, pe, eof, ts, te, act HB_UNUSED;
|
||||
int cs;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
||||
#line 266 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
{
|
||||
cs = (int)khmer_syllable_machine_start;
|
||||
ts = 0;
|
||||
te = 0;
|
||||
act = 0;
|
||||
cs = khmer_syllable_machine_start;
|
||||
ts = 0;
|
||||
te = 0;
|
||||
act = 0;
|
||||
}
|
||||
|
||||
|
||||
#line 106 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
|
||||
|
||||
p = 0;
|
||||
pe = eof = buffer->len;
|
||||
|
||||
unsigned int syllable_serial = 1;
|
||||
|
||||
#line 226 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
p = 0;
|
||||
pe = eof = buffer->len;
|
||||
|
||||
unsigned int syllable_serial = 1;
|
||||
|
||||
#line 282 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
{
|
||||
unsigned int _trans = 0;
|
||||
const unsigned char * _keys;
|
||||
const signed char * _inds;
|
||||
int _ic;
|
||||
_resume: {}
|
||||
if ( p == pe && p != eof )
|
||||
goto _out;
|
||||
switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
|
||||
case 7: {
|
||||
{
|
||||
int _slen;
|
||||
int _trans;
|
||||
const unsigned char *_keys;
|
||||
const char *_inds;
|
||||
if ( p == pe )
|
||||
goto _test_eof;
|
||||
_resume:
|
||||
switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
|
||||
case 7:
|
||||
#line 1 "NONE"
|
||||
{ts = p;}}
|
||||
|
||||
#line 241 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( p == eof ) {
|
||||
if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
|
||||
_trans = (unsigned int)_khmer_syllable_machine_eof_trans[cs] - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_keys = ( _khmer_syllable_machine_trans_keys + ((cs<<1)));
|
||||
_inds = ( _khmer_syllable_machine_indicies + (_khmer_syllable_machine_index_offsets[cs]));
|
||||
|
||||
if ( (info[p].khmer_category()) <= 29 && (info[p].khmer_category()) >= 1 ) {
|
||||
_ic = (int)_khmer_syllable_machine_char_class[(int)(info[p].khmer_category()) - 1];
|
||||
if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) )
|
||||
_trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) ));
|
||||
else
|
||||
_trans = (unsigned int)_khmer_syllable_machine_index_defaults[cs];
|
||||
}
|
||||
else {
|
||||
_trans = (unsigned int)_khmer_syllable_machine_index_defaults[cs];
|
||||
}
|
||||
|
||||
}
|
||||
cs = (int)_khmer_syllable_machine_cond_targs[_trans];
|
||||
|
||||
if ( _khmer_syllable_machine_cond_actions[_trans] != 0 ) {
|
||||
|
||||
switch ( _khmer_syllable_machine_cond_actions[_trans] ) {
|
||||
case 2: {
|
||||
{
|
||||
#line 1 "NONE"
|
||||
{te = p+1;}}
|
||||
|
||||
#line 279 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
{
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p+1;{
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_non_khmer_cluster); }
|
||||
}}
|
||||
|
||||
#line 292 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 10: {
|
||||
{
|
||||
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p;p = p - 1;{
|
||||
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_consonant_syllable); }
|
||||
}}
|
||||
|
||||
#line 305 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 12: {
|
||||
{
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p;p = p - 1;{
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_broken_cluster); }
|
||||
}}
|
||||
|
||||
#line 318 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 11: {
|
||||
{
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p;p = p - 1;{
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_non_khmer_cluster); }
|
||||
}}
|
||||
|
||||
#line 331 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
{
|
||||
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{p = ((te))-1;
|
||||
{
|
||||
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_consonant_syllable); }
|
||||
}}
|
||||
|
||||
#line 345 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
{
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{p = ((te))-1;
|
||||
{
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_broken_cluster); }
|
||||
}}
|
||||
|
||||
#line 359 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
{
|
||||
#line 1 "NONE"
|
||||
{switch( act ) {
|
||||
case 2: {
|
||||
p = ((te))-1;
|
||||
{
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_broken_cluster); }
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
p = ((te))-1;
|
||||
{
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_non_khmer_cluster); }
|
||||
break;
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
#line 385 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
{
|
||||
#line 1 "NONE"
|
||||
{te = p+1;}}
|
||||
|
||||
#line 395 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
{
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{act = 2;}}
|
||||
|
||||
#line 401 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 9: {
|
||||
{
|
||||
#line 1 "NONE"
|
||||
{te = p+1;}}
|
||||
|
||||
#line 411 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
{
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{act = 3;}}
|
||||
|
||||
#line 417 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( p == eof ) {
|
||||
if ( cs >= 20 )
|
||||
goto _out;
|
||||
}
|
||||
else {
|
||||
switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
|
||||
case 6: {
|
||||
{
|
||||
#line 1 "NONE"
|
||||
{ts = 0;}}
|
||||
|
||||
#line 437 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p += 1;
|
||||
goto _resume;
|
||||
}
|
||||
_out: {}
|
||||
{ts = p;}
|
||||
break;
|
||||
#line 296 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
}
|
||||
|
||||
|
||||
_keys = _khmer_syllable_machine_trans_keys + (cs<<1);
|
||||
_inds = _khmer_syllable_machine_indicies + _khmer_syllable_machine_index_offsets[cs];
|
||||
|
||||
_slen = _khmer_syllable_machine_key_spans[cs];
|
||||
_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].khmer_category()) &&
|
||||
( info[p].khmer_category()) <= _keys[1] ?
|
||||
( info[p].khmer_category()) - _keys[0] : _slen ];
|
||||
|
||||
_eof_trans:
|
||||
cs = _khmer_syllable_machine_trans_targs[_trans];
|
||||
|
||||
if ( _khmer_syllable_machine_trans_actions[_trans] == 0 )
|
||||
goto _again;
|
||||
|
||||
switch ( _khmer_syllable_machine_trans_actions[_trans] ) {
|
||||
case 2:
|
||||
#line 1 "NONE"
|
||||
{te = p+1;}
|
||||
break;
|
||||
case 8:
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p+1;{ found_syllable (khmer_non_khmer_cluster); }}
|
||||
break;
|
||||
case 10:
|
||||
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p;p--;{ found_syllable (khmer_consonant_syllable); }}
|
||||
break;
|
||||
case 12:
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p;p--;{ found_syllable (khmer_broken_cluster); }}
|
||||
break;
|
||||
case 11:
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p;p--;{ found_syllable (khmer_non_khmer_cluster); }}
|
||||
break;
|
||||
case 1:
|
||||
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{{p = ((te))-1;}{ found_syllable (khmer_consonant_syllable); }}
|
||||
break;
|
||||
case 5:
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{{p = ((te))-1;}{ found_syllable (khmer_broken_cluster); }}
|
||||
break;
|
||||
case 3:
|
||||
#line 1 "NONE"
|
||||
{ switch( act ) {
|
||||
case 2:
|
||||
{{p = ((te))-1;} found_syllable (khmer_broken_cluster); }
|
||||
break;
|
||||
case 3:
|
||||
{{p = ((te))-1;} found_syllable (khmer_non_khmer_cluster); }
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
#line 1 "NONE"
|
||||
{te = p+1;}
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{act = 2;}
|
||||
break;
|
||||
case 9:
|
||||
#line 1 "NONE"
|
||||
{te = p+1;}
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{act = 3;}
|
||||
break;
|
||||
#line 366 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
}
|
||||
|
||||
_again:
|
||||
switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
|
||||
case 6:
|
||||
#line 1 "NONE"
|
||||
{ts = 0;}
|
||||
break;
|
||||
#line 375 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
}
|
||||
|
||||
if ( ++p != pe )
|
||||
goto _resume;
|
||||
_test_eof: {}
|
||||
if ( p == eof )
|
||||
{
|
||||
if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
|
||||
_trans = _khmer_syllable_machine_eof_trans[cs] - 1;
|
||||
goto _eof_trans;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#line 114 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
|
||||
|
||||
}
|
||||
|
||||
#undef found_syllable
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -6,14 +6,14 @@
|
|||
*
|
||||
* on files with these headers:
|
||||
*
|
||||
* # IndicSyllabicCategory-13.0.0.txt
|
||||
* # Date: 2019-07-22, 19:55:00 GMT [KW, RP]
|
||||
* # IndicPositionalCategory-13.0.0.txt
|
||||
* # Date: 2019-07-23, 00:01:00 GMT [KW, RP]
|
||||
* # ArabicShaping-13.0.0.txt
|
||||
* # Date: 2020-01-31, 23:55:00 GMT [KW, RP]
|
||||
* # Blocks-13.0.0.txt
|
||||
* # Date: 2019-07-10, 19:06:00 GMT [KW]
|
||||
* # IndicSyllabicCategory-14.0.0.txt
|
||||
* # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
|
||||
* # IndicPositionalCategory-14.0.0.txt
|
||||
* # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
|
||||
* # ArabicShaping-14.0.0.txt
|
||||
* # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
|
||||
* # Blocks-14.0.0.txt
|
||||
* # Date: 2021-01-22, 23:29:00 GMT [KW]
|
||||
* # Override values For Indic_Syllabic_Category
|
||||
* # Not derivable
|
||||
* # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
|
||||
|
|
@ -199,7 +199,7 @@ static const uint8_t use_table[] = {
|
|||
/* 0C00 */ VMAbv, VMPst, VMPst, VMPst, VMAbv, B, B, B, B, B, B, B, B, O, B, B,
|
||||
/* 0C10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
|
||||
/* 0C20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
|
||||
/* 0C30 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, VAbv, VAbv,
|
||||
/* 0C30 */ B, B, B, B, B, B, B, B, B, B, O, O, CMBlw, B, VAbv, VAbv,
|
||||
/* 0C40 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O,
|
||||
/* 0C50 */ O, O, O, O, O, VAbv, VBlw, O, B, B, B, O, O, O, O, O,
|
||||
/* 0C60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
|
||||
|
|
@ -278,13 +278,13 @@ static const uint8_t use_table[] = {
|
|||
|
||||
/* Tagalog */
|
||||
|
||||
/* 1700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, B, B,
|
||||
/* 1710 */ B, B, VAbv, VBlw, VBlw, O, O, O, O, O, O, O, O, O, O, O,
|
||||
/* 1700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
|
||||
/* 1710 */ B, B, VAbv, VBlw, VBlw, VPst, O, O, O, O, O, O, O, O, O, B,
|
||||
|
||||
/* Hanunoo */
|
||||
|
||||
/* 1720 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
|
||||
/* 1730 */ B, B, VAbv, VBlw, VBlw, O, O, O, O, O, O, O, O, O, O, O,
|
||||
/* 1730 */ B, B, VAbv, VBlw, VPst, O, O, O, O, O, O, O, O, O, O, O,
|
||||
|
||||
/* Buhid */
|
||||
|
||||
|
|
@ -374,7 +374,7 @@ static const uint8_t use_table[] = {
|
|||
/* 1B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
|
||||
/* 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 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, O, O, O, O,
|
||||
/* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, B, O, O, O,
|
||||
/* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, GB, GB, O, O, GB,
|
||||
/* 1B60 */ O, S, GB, S, S, S, S, S, GB, S, S, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
|
||||
/* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, O,
|
||||
|
|
@ -630,7 +630,7 @@ static const uint8_t use_table[] = {
|
|||
/* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, HVM, O, O, O, O, O, O, O, O, O,
|
||||
/* 11050 */ O, O, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
|
||||
/* 11060 */ N, N, N, N, N, N, B, B, B, B, B, B, B, B, B, B,
|
||||
/* 11070 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, HN,
|
||||
/* 11070 */ VAbv, B, B, VAbv, VAbv, B, O, O, O, O, O, O, O, O, O, HN,
|
||||
|
||||
/* Kaithi */
|
||||
|
||||
|
|
@ -638,8 +638,9 @@ static const uint8_t use_table[] = {
|
|||
/* 11090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
|
||||
/* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
|
||||
/* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O,
|
||||
/* 110C0 */ O, O, VBlw, O, O, O, O, O,
|
||||
|
||||
#define use_offset_0x11100u 4608
|
||||
#define use_offset_0x11100u 4616
|
||||
|
||||
|
||||
/* Chakma */
|
||||
|
|
@ -677,7 +678,7 @@ static const uint8_t use_table[] = {
|
|||
/* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw,
|
||||
/* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, O,
|
||||
|
||||
#define use_offset_0x11280u 4928
|
||||
#define use_offset_0x11280u 4936
|
||||
|
||||
|
||||
/* Multani */
|
||||
|
|
@ -705,7 +706,7 @@ static const uint8_t use_table[] = {
|
|||
/* 11360 */ B, B, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O,
|
||||
/* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O,
|
||||
|
||||
#define use_offset_0x11400u 5176
|
||||
#define use_offset_0x11400u 5184
|
||||
|
||||
|
||||
/* Newa */
|
||||
|
|
@ -728,7 +729,7 @@ static const uint8_t use_table[] = {
|
|||
/* 114C0 */ VMAbv, VMAbv, H, CMBlw, B, O, O, O, O, O, O, O, O, O, O, O,
|
||||
/* 114D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
|
||||
|
||||
#define use_offset_0x11580u 5400
|
||||
#define use_offset_0x11580u 5408
|
||||
|
||||
|
||||
/* Siddham */
|
||||
|
|
@ -770,8 +771,9 @@ static const uint8_t use_table[] = {
|
|||
/* 11710 */ B, B, B, B, B, B, B, B, B, B, B, O, O, MBlw, MPre, MAbv,
|
||||
/* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O,
|
||||
/* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O,
|
||||
/* 11740 */ B, B, B, B, B, B, B, O,
|
||||
|
||||
#define use_offset_0x11800u 5848
|
||||
#define use_offset_0x11800u 5864
|
||||
|
||||
|
||||
/* Dogra */
|
||||
|
|
@ -781,7 +783,7 @@ static const uint8_t use_table[] = {
|
|||
/* 11820 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPre, VPst, VBlw,
|
||||
/* 11830 */ VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VMAbv, VMPst, H, CMBlw, O, O, O, O, O,
|
||||
|
||||
#define use_offset_0x11900u 5912
|
||||
#define use_offset_0x11900u 5928
|
||||
|
||||
|
||||
/* Dives Akuru */
|
||||
|
|
@ -793,7 +795,7 @@ static const uint8_t use_table[] = {
|
|||
/* 11940 */ MPst, R, MPst, CMBlw, O, O, O, O, O, O, O, O, O, O, O, O,
|
||||
/* 11950 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
|
||||
|
||||
#define use_offset_0x119a0u 6008
|
||||
#define use_offset_0x119a0u 6024
|
||||
|
||||
|
||||
/* Nandinagari */
|
||||
|
|
@ -821,7 +823,7 @@ static const uint8_t use_table[] = {
|
|||
/* 11A80 */ B, B, B, B, R, R, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw,
|
||||
/* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, H, O, O, O, B, O, O,
|
||||
|
||||
#define use_offset_0x11c00u 6264
|
||||
#define use_offset_0x11c00u 6280
|
||||
|
||||
|
||||
/* Bhaiksuki */
|
||||
|
|
@ -842,7 +844,7 @@ static const uint8_t use_table[] = {
|
|||
/* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
|
||||
/* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, O,
|
||||
|
||||
#define use_offset_0x11d00u 6448
|
||||
#define use_offset_0x11d00u 6464
|
||||
|
||||
|
||||
/* Masaram Gondi */
|
||||
|
|
@ -862,7 +864,7 @@ static const uint8_t use_table[] = {
|
|||
/* 11D90 */ VAbv, VAbv, O, VPst, VPst, VMAbv, VMPst, H, O, O, O, O, O, O, O, O,
|
||||
/* 11DA0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
|
||||
|
||||
#define use_offset_0x11ee0u 6624
|
||||
#define use_offset_0x11ee0u 6640
|
||||
|
||||
|
||||
/* Makasar */
|
||||
|
|
@ -870,7 +872,7 @@ static const uint8_t use_table[] = {
|
|||
/* 11EE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
|
||||
/* 11EF0 */ B, B, GB, VAbv, VBlw, VPre, VPst, O,
|
||||
|
||||
#define use_offset_0x13000u 6648
|
||||
#define use_offset_0x13000u 6664
|
||||
|
||||
|
||||
/* Egyptian Hieroglyphs */
|
||||
|
|
@ -947,7 +949,7 @@ static const uint8_t use_table[] = {
|
|||
|
||||
/* 13430 */ J, J, J, J, J, J, J, SB, SE, O, O, O, O, O, O, O,
|
||||
|
||||
#define use_offset_0x16b00u 7736
|
||||
#define use_offset_0x16b00u 7752
|
||||
|
||||
|
||||
/* Pahawh Hmong */
|
||||
|
|
@ -957,7 +959,7 @@ static const uint8_t use_table[] = {
|
|||
/* 16B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
|
||||
/* 16B30 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O,
|
||||
|
||||
#define use_offset_0x16f00u 7792
|
||||
#define use_offset_0x16f00u 7808
|
||||
|
||||
|
||||
/* Miao */
|
||||
|
|
@ -973,14 +975,14 @@ static const uint8_t use_table[] = {
|
|||
/* 16F80 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, O, O, O, O, O, O, O, VMBlw,
|
||||
/* 16F90 */ VMBlw, VMBlw, VMBlw, O, O, O, O, O,
|
||||
|
||||
#define use_offset_0x16fe0u 7944
|
||||
#define use_offset_0x16fe0u 7960
|
||||
|
||||
|
||||
/* Ideographic Symbols and Punctuation */
|
||||
|
||||
/* 16FE0 */ O, O, O, O, B, O, O, O,
|
||||
|
||||
#define use_offset_0x18b00u 7952
|
||||
#define use_offset_0x18b00u 7968
|
||||
|
||||
|
||||
/* Khitan Small Script */
|
||||
|
|
@ -1016,7 +1018,7 @@ static const uint8_t use_table[] = {
|
|||
/* 18CC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
|
||||
/* 18CD0 */ B, B, B, B, B, B, O, O,
|
||||
|
||||
#define use_offset_0x1bc00u 8424
|
||||
#define use_offset_0x1bc00u 8440
|
||||
|
||||
|
||||
/* Duployan */
|
||||
|
|
@ -1032,7 +1034,7 @@ static const uint8_t use_table[] = {
|
|||
/* 1BC80 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O,
|
||||
/* 1BC90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, CMBlw, CMBlw, O,
|
||||
|
||||
#define use_offset_0x1e100u 8584
|
||||
#define use_offset_0x1e100u 8600
|
||||
|
||||
|
||||
/* Nyiakeng Puachue Hmong */
|
||||
|
|
@ -1043,7 +1045,7 @@ static const uint8_t use_table[] = {
|
|||
/* 1E130 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, O, O,
|
||||
/* 1E140 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, B, B,
|
||||
|
||||
#define use_offset_0x1e2c0u 8664
|
||||
#define use_offset_0x1e2c0u 8680
|
||||
|
||||
|
||||
/* Wancho */
|
||||
|
|
@ -1053,7 +1055,7 @@ static const uint8_t use_table[] = {
|
|||
/* 1E2E0 */ B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv,
|
||||
/* 1E2F0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
|
||||
|
||||
#define use_offset_0x1e900u 8728
|
||||
#define use_offset_0x1e900u 8744
|
||||
|
||||
|
||||
/* Adlam */
|
||||
|
|
@ -1065,7 +1067,7 @@ static const uint8_t use_table[] = {
|
|||
/* 1E940 */ B, B, B, B, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, B, O, O, O, O,
|
||||
/* 1E950 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
|
||||
|
||||
}; /* Table items: 8824; occupancy: 79% */
|
||||
}; /* Table items: 8840; occupancy: 79% */
|
||||
|
||||
static inline uint8_t
|
||||
hb_use_get_category (hb_codepoint_t u)
|
||||
|
|
@ -1111,15 +1113,15 @@ hb_use_get_category (hb_codepoint_t u)
|
|||
if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D3Fu)) return use_table[u - 0x10D00u + use_offset_0x10d00u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10E80u, 0x10EB7u)) return use_table[u - 0x10E80u + use_offset_0x10e80u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10F57u)) return use_table[u - 0x10F30u + use_offset_0x10f30u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10FB0u, 0x110BFu)) return use_table[u - 0x10FB0u + use_offset_0x10fb0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10FB0u, 0x110C7u)) return use_table[u - 0x10FB0u + use_offset_0x10fb0u];
|
||||
break;
|
||||
|
||||
case 0x11u:
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10FB0u, 0x110BFu)) return use_table[u - 0x10FB0u + use_offset_0x10fb0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10FB0u, 0x110C7u)) return use_table[u - 0x10FB0u + use_offset_0x10fb0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x11580u, 0x1173Fu)) return use_table[u - 0x11580u + use_offset_0x11580u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x11580u, 0x11747u)) return use_table[u - 0x11580u + use_offset_0x11580u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x11800u, 0x1183Fu)) return use_table[u - 0x11800u + use_offset_0x11800u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x11900u, 0x1195Fu)) return use_table[u - 0x11900u + use_offset_0x11900u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x119A0u, 0x11A9Fu)) return use_table[u - 0x119A0u + use_offset_0x119a0u];
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
* # Date: 2015-03-12, 21:17:00 GMT [AG]
|
||||
* # Date: 2019-11-08, 23:22:00 GMT [AG]
|
||||
*
|
||||
* # Scripts-13.0.0.txt
|
||||
* # Date: 2020-01-22, 00:07:43 GMT
|
||||
* # Scripts-14.0.0.txt
|
||||
* # Date: 2021-07-10, 00:35:31 GMT
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
|
|
|||
|
|
@ -373,6 +373,15 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
|
|||
/* Unicode-13.0 additions */
|
||||
case HB_SCRIPT_CHORASMIAN:
|
||||
case HB_SCRIPT_DIVES_AKURU:
|
||||
case HB_SCRIPT_KHITAN_SMALL_SCRIPT:
|
||||
case HB_SCRIPT_YEZIDI:
|
||||
|
||||
/* Unicode-14.0 additions */
|
||||
case HB_SCRIPT_CYPRO_MINOAN:
|
||||
case HB_SCRIPT_OLD_UYGHUR:
|
||||
case HB_SCRIPT_TANGSA:
|
||||
case HB_SCRIPT_TOTO:
|
||||
case HB_SCRIPT_VITHKUQI:
|
||||
|
||||
/* If the designer designed the font for the 'DFLT' script,
|
||||
* (or we ended up arbitrarily pick 'latn'), use the default shaper.
|
||||
|
|
|
|||
|
|
@ -149,7 +149,9 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
|||
* Decide who does positioning. GPOS, kerx, kern, or fallback.
|
||||
*/
|
||||
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
bool has_gsub = hb_ot_layout_has_substitution (face);
|
||||
#endif
|
||||
bool has_gpos = !disable_gpos && hb_ot_layout_has_positioning (face);
|
||||
if (false)
|
||||
;
|
||||
|
|
@ -317,16 +319,17 @@ horizontal_features[] =
|
|||
};
|
||||
|
||||
static void
|
||||
hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
|
||||
const hb_feature_t *user_features,
|
||||
unsigned int num_user_features)
|
||||
hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
|
||||
const hb_feature_t *user_features,
|
||||
unsigned int num_user_features)
|
||||
{
|
||||
hb_ot_map_builder_t *map = &planner->map;
|
||||
|
||||
map->enable_feature (HB_TAG('r','v','r','n'));
|
||||
map->add_gsub_pause (nullptr);
|
||||
|
||||
switch (planner->props.direction) {
|
||||
switch (planner->props.direction)
|
||||
{
|
||||
case HB_DIRECTION_LTR:
|
||||
map->enable_feature (HB_TAG ('l','t','r','a'));
|
||||
map->enable_feature (HB_TAG ('l','t','r','m'));
|
||||
|
|
@ -359,12 +362,14 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
|
|||
map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK);
|
||||
#endif
|
||||
|
||||
map->enable_feature (HB_TAG ('H','A','R','F'));
|
||||
map->enable_feature (HB_TAG ('H','a','r','f')); /* Considered required. */
|
||||
map->enable_feature (HB_TAG ('H','A','R','F')); /* Considered discretionary. */
|
||||
|
||||
if (planner->shaper->collect_features)
|
||||
planner->shaper->collect_features (planner);
|
||||
|
||||
map->enable_feature (HB_TAG ('B','U','Z','Z'));
|
||||
map->enable_feature (HB_TAG ('B','u','z','z')); /* Considered required. */
|
||||
map->enable_feature (HB_TAG ('B','U','Z','Z')); /* Considered discretionary. */
|
||||
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++)
|
||||
map->add_feature (common_features[i]);
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
*
|
||||
* on files with these headers:
|
||||
*
|
||||
* <meta name="updated_at" content="2021-02-12 04:08 PM" />
|
||||
* File-Date: 2021-03-05
|
||||
* <meta name="updated_at" content="2021-09-02 09:40 PM" />
|
||||
* File-Date: 2021-08-06
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_TAG_TABLE_HH
|
||||
|
|
@ -93,6 +93,7 @@ static const LangTag ot_languages[] = {
|
|||
{"auz", HB_TAG('A','R','A',' ')}, /* Uzbeki Arabic -> Arabic */
|
||||
{"av", HB_TAG('A','V','R',' ')}, /* Avaric -> Avar */
|
||||
{"avl", HB_TAG('A','R','A',' ')}, /* Eastern Egyptian Bedawi Arabic -> Arabic */
|
||||
/*{"avn", HB_TAG('A','V','N',' ')},*/ /* Avatime */
|
||||
/*{"awa", HB_TAG('A','W','A',' ')},*/ /* Awadhi */
|
||||
{"ay", HB_TAG('A','Y','M',' ')}, /* Aymara [macrolanguage] */
|
||||
{"ayc", HB_TAG('A','Y','M',' ')}, /* Southern Aymara -> Aymara */
|
||||
|
|
@ -345,6 +346,7 @@ static const LangTag ot_languages[] = {
|
|||
{"cth", HB_TAG('Q','I','N',' ')}, /* Thaiphum Chin -> Chin */
|
||||
{"ctl", HB_TAG('C','C','H','N')}, /* Tlacoatzintepec Chinantec -> Chinantec */
|
||||
{"cts", HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol -> Bikol */
|
||||
/*{"ctt", HB_TAG('C','T','T',' ')},*/ /* Wayanad Chetti */
|
||||
{"ctu", HB_TAG('M','Y','N',' ')}, /* Chol -> Mayan */
|
||||
{"cu", HB_TAG('C','S','L',' ')}, /* Church Slavonic */
|
||||
{"cuc", HB_TAG('C','C','H','N')}, /* Usila Chinantec -> Chinantec */
|
||||
|
|
@ -537,23 +539,27 @@ static const LangTag ot_languages[] = {
|
|||
{"ha", HB_TAG('H','A','U',' ')}, /* Hausa */
|
||||
{"haa", HB_TAG('A','T','H',' ')}, /* Han -> Athapaskan */
|
||||
{"hae", HB_TAG('O','R','O',' ')}, /* Eastern Oromo -> Oromo */
|
||||
{"hai", HB_TAG_NONE }, /* Haida [macrolanguage] != Haitian (Haitian Creole) */
|
||||
{"hai", HB_TAG('H','A','I','0')}, /* Haida [macrolanguage] */
|
||||
{"hak", HB_TAG('Z','H','S',' ')}, /* Hakka Chinese -> Chinese, Simplified */
|
||||
{"hal", HB_TAG_NONE }, /* Halang != Halam (Falam Chin) */
|
||||
{"har", HB_TAG('H','R','I',' ')}, /* Harari */
|
||||
/*{"haw", HB_TAG('H','A','W',' ')},*/ /* Hawaiian */
|
||||
{"hax", HB_TAG('H','A','I','0')}, /* Southern Haida -> Haida */
|
||||
/*{"hay", HB_TAG('H','A','Y',' ')},*/ /* Haya */
|
||||
/*{"haz", HB_TAG('H','A','Z',' ')},*/ /* Hazaragi */
|
||||
{"hbn", HB_TAG_NONE }, /* Heiban != Hammer-Banna */
|
||||
{"hca", HB_TAG('C','P','P',' ')}, /* Andaman Creole Hindi -> Creoles */
|
||||
{"hdn", HB_TAG('H','A','I','0')}, /* Northern Haida -> Haida */
|
||||
{"he", HB_TAG('I','W','R',' ')}, /* Hebrew */
|
||||
{"hea", HB_TAG('H','M','N',' ')}, /* Northern Qiandong Miao -> Hmong */
|
||||
/*{"hei", HB_TAG('H','E','I',' ')},*/ /* Heiltsuk */
|
||||
{"hi", HB_TAG('H','I','N',' ')}, /* Hindi */
|
||||
/*{"hil", HB_TAG('H','I','L',' ')},*/ /* Hiligaynon */
|
||||
{"hji", HB_TAG('M','L','Y',' ')}, /* Haji -> Malay */
|
||||
{"hlt", HB_TAG('Q','I','N',' ')}, /* Matu Chin -> Chin */
|
||||
{"hma", HB_TAG('H','M','N',' ')}, /* Southern Mashan Hmong -> Hmong */
|
||||
{"hmc", HB_TAG('H','M','N',' ')}, /* Central Huishui Hmong -> Hmong */
|
||||
{"hmd", HB_TAG('H','M','D',' ')}, /* Large Flowery Miao -> A-Hmao */
|
||||
{"hmd", HB_TAG('H','M','N',' ')}, /* Large Flowery Miao -> Hmong */
|
||||
{"hme", HB_TAG('H','M','N',' ')}, /* Eastern Huishui Hmong -> Hmong */
|
||||
{"hmg", HB_TAG('H','M','N',' ')}, /* Southwestern Guiyang Hmong -> Hmong */
|
||||
|
|
@ -569,6 +575,7 @@ static const LangTag ot_languages[] = {
|
|||
{"hms", HB_TAG('H','M','N',' ')}, /* Southern Qiandong Miao -> Hmong */
|
||||
{"hmw", HB_TAG('H','M','N',' ')}, /* Western Mashan Hmong -> Hmong */
|
||||
{"hmy", HB_TAG('H','M','N',' ')}, /* Southern Guiyang Hmong -> Hmong */
|
||||
{"hmz", HB_TAG('H','M','Z',' ')}, /* Hmong Shua -> Hmong Shuat */
|
||||
{"hmz", HB_TAG('H','M','N',' ')}, /* Hmong Shua -> Hmong */
|
||||
/*{"hnd", HB_TAG('H','N','D',' ')},*/ /* Southern Hindko -> Hindko */
|
||||
{"hne", HB_TAG('C','H','H',' ')}, /* Chhattisgarhi -> Chattisgarhi */
|
||||
|
|
@ -625,6 +632,7 @@ static const LangTag ot_languages[] = {
|
|||
{"inh", HB_TAG('I','N','G',' ')}, /* Ingush */
|
||||
{"io", HB_TAG('I','D','O',' ')}, /* Ido */
|
||||
{"iri", HB_TAG_NONE }, /* Rigwe != Irish */
|
||||
/*{"iru", HB_TAG('I','R','U',' ')},*/ /* Irula */
|
||||
{"is", HB_TAG('I','S','L',' ')}, /* Icelandic */
|
||||
{"ism", HB_TAG_NONE }, /* Masimasi != Inari Sami */
|
||||
{"it", HB_TAG('I','T','A',' ')}, /* Italian */
|
||||
|
|
@ -660,6 +668,7 @@ static const LangTag ot_languages[] = {
|
|||
{"kac", HB_TAG_NONE }, /* Kachin != Kachchi */
|
||||
{"kam", HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */
|
||||
{"kar", HB_TAG('K','R','N',' ')}, /* Karen [family] */
|
||||
/*{"kaw", HB_TAG('K','A','W',' ')},*/ /* Kawi (Old Javanese) */
|
||||
{"kbd", HB_TAG('K','A','B',' ')}, /* Kabardian */
|
||||
{"kby", HB_TAG('K','N','R',' ')}, /* Manga Kanuri -> Kanuri */
|
||||
{"kca", HB_TAG('K','H','K',' ')}, /* Khanty -> Khanty-Kazim */
|
||||
|
|
@ -779,6 +788,7 @@ static const LangTag ot_languages[] = {
|
|||
{"kvu", HB_TAG('K','R','N',' ')}, /* Yinbaw Karen -> Karen */
|
||||
{"kvy", HB_TAG('K','R','N',' ')}, /* Yintale Karen -> Karen */
|
||||
{"kw", HB_TAG('C','O','R',' ')}, /* Cornish */
|
||||
/*{"kwk", HB_TAG('K','W','K',' ')},*/ /* Kwakiutl -> Kwakʼwala */
|
||||
{"kww", HB_TAG('C','P','P',' ')}, /* Kwinti -> Creoles */
|
||||
{"kwy", HB_TAG('K','O','N','0')}, /* San Salvador Kongo -> Kongo */
|
||||
{"kxc", HB_TAG('K','M','S',' ')}, /* Konso -> Komso */
|
||||
|
|
@ -806,6 +816,7 @@ static const LangTag ot_languages[] = {
|
|||
{"lcf", HB_TAG('M','L','Y',' ')}, /* Lubu -> Malay */
|
||||
{"ldi", HB_TAG('K','O','N','0')}, /* Laari -> Kongo */
|
||||
{"ldk", HB_TAG_NONE }, /* Leelau != Ladakhi */
|
||||
/*{"lef", HB_TAG('L','E','F',' ')},*/ /* Lelemi */
|
||||
/*{"lez", HB_TAG('L','E','Z',' ')},*/ /* Lezghian -> Lezgi */
|
||||
{"lg", HB_TAG('L','U','G',' ')}, /* Ganda */
|
||||
{"li", HB_TAG('L','I','M',' ')}, /* Limburgish */
|
||||
|
|
@ -832,6 +843,7 @@ static const LangTag ot_languages[] = {
|
|||
{"lo", HB_TAG('L','A','O',' ')}, /* Lao */
|
||||
/*{"lom", HB_TAG('L','O','M',' ')},*/ /* Loma (Liberia) */
|
||||
{"lou", HB_TAG('C','P','P',' ')}, /* Louisiana Creole -> Creoles */
|
||||
/*{"lpo", HB_TAG('L','P','O',' ')},*/ /* Lipo */
|
||||
/*{"lrc", HB_TAG('L','R','C',' ')},*/ /* Northern Luri -> Luri */
|
||||
{"lri", HB_TAG('L','U','H',' ')}, /* Marachi -> Luyia */
|
||||
{"lrm", HB_TAG('L','U','H',' ')}, /* Marama -> Luyia */
|
||||
|
|
@ -1231,6 +1243,7 @@ static const LangTag ot_languages[] = {
|
|||
{"rbl", HB_TAG('B','I','K',' ')}, /* Miraya Bikol -> Bikol */
|
||||
{"rcf", HB_TAG('C','P','P',' ')}, /* Réunion Creole French -> Creoles */
|
||||
/*{"rej", HB_TAG('R','E','J',' ')},*/ /* Rejang */
|
||||
/*{"rhg", HB_TAG('R','H','G',' ')},*/ /* Rohingya */
|
||||
/*{"ria", HB_TAG('R','I','A',' ')},*/ /* Riang (India) */
|
||||
{"rif", HB_TAG('R','I','F',' ')}, /* Tarifit */
|
||||
{"rif", HB_TAG('B','B','R',' ')}, /* Tarifit -> Berber */
|
||||
|
|
@ -1286,6 +1299,7 @@ static const LangTag ot_languages[] = {
|
|||
{"sek", HB_TAG('A','T','H',' ')}, /* Sekani -> Athapaskan */
|
||||
/*{"sel", HB_TAG('S','E','L',' ')},*/ /* Selkup */
|
||||
{"sez", HB_TAG('Q','I','N',' ')}, /* Senthang Chin -> Chin */
|
||||
{"sfm", HB_TAG('S','F','M',' ')}, /* Small Flowery Miao */
|
||||
{"sfm", HB_TAG('H','M','N',' ')}, /* Small Flowery Miao -> Hmong */
|
||||
{"sg", HB_TAG('S','G','O',' ')}, /* Sango */
|
||||
/*{"sga", HB_TAG('S','G','A',' ')},*/ /* Old Irish (to 900) */
|
||||
|
|
@ -1413,6 +1427,7 @@ static const LangTag ot_languages[] = {
|
|||
{"tkg", HB_TAG('M','L','G',' ')}, /* Tesaka Malagasy -> Malagasy */
|
||||
{"tkm", HB_TAG_NONE }, /* Takelma != Turkmen */
|
||||
{"tl", HB_TAG('T','G','L',' ')}, /* Tagalog */
|
||||
/*{"tli", HB_TAG('T','L','I',' ')},*/ /* Tlingit */
|
||||
{"tmg", HB_TAG('C','P','P',' ')}, /* Ternateño -> Creoles */
|
||||
{"tmh", HB_TAG('T','M','H',' ')}, /* Tamashek [macrolanguage] */
|
||||
{"tmh", HB_TAG('B','B','R',' ')}, /* Tamashek [macrolanguage] -> Berber */
|
||||
|
|
@ -1499,6 +1514,7 @@ static const LangTag ot_languages[] = {
|
|||
{"wbm", HB_TAG('W','A',' ',' ')}, /* Wa */
|
||||
{"wbr", HB_TAG('W','A','G',' ')}, /* Wagdi */
|
||||
{"wbr", HB_TAG('R','A','J',' ')}, /* Wagdi -> Rajasthani */
|
||||
/*{"wci", HB_TAG('W','C','I',' ')},*/ /* Waci Gbe */
|
||||
{"wea", HB_TAG('K','R','N',' ')}, /* Wewaw -> Karen */
|
||||
{"wes", HB_TAG('C','P','P',' ')}, /* Cameroon Pidgin -> Creoles */
|
||||
{"weu", HB_TAG('Q','I','N',' ')}, /* Rawngtu Chin -> Chin */
|
||||
|
|
@ -1533,6 +1549,8 @@ static const LangTag ot_languages[] = {
|
|||
{"xsl", HB_TAG('S','L','A',' ')}, /* South Slavey -> Slavey */
|
||||
{"xsl", HB_TAG('A','T','H',' ')}, /* South Slavey -> Athapaskan */
|
||||
{"xst", HB_TAG('S','I','G',' ')}, /* Silt'e (retired code) -> Silte Gurage */
|
||||
/*{"xub", HB_TAG('X','U','B',' ')},*/ /* Betta Kurumba -> Bette Kuruma */
|
||||
/*{"xuj", HB_TAG('X','U','J',' ')},*/ /* Jennu Kurumba -> Jennu Kuruma */
|
||||
{"xup", HB_TAG('A','T','H',' ')}, /* Upper Umpqua -> Athapaskan */
|
||||
{"xwo", HB_TAG('T','O','D',' ')}, /* Written Oirat -> Todo */
|
||||
{"yaj", HB_TAG('B','A','D','0')}, /* Banda-Yangere -> Banda */
|
||||
|
|
@ -1543,13 +1561,16 @@ static const LangTag ot_languages[] = {
|
|||
{"ybb", HB_TAG('B','M','L',' ')}, /* Yemba -> Bamileke */
|
||||
{"ybd", HB_TAG('A','R','K',' ')}, /* Yangbye (retired code) -> Rakhine */
|
||||
{"ydd", HB_TAG('J','I','I',' ')}, /* Eastern Yiddish -> Yiddish */
|
||||
/*{"ygp", HB_TAG('Y','G','P',' ')},*/ /* Gepo */
|
||||
{"yi", HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */
|
||||
{"yih", HB_TAG('J','I','I',' ')}, /* Western Yiddish -> Yiddish */
|
||||
{"yim", HB_TAG_NONE }, /* Yimchungru Naga != Yi Modern */
|
||||
/*{"yna", HB_TAG('Y','N','A',' ')},*/ /* Aluo */
|
||||
{"yo", HB_TAG('Y','B','A',' ')}, /* Yoruba */
|
||||
{"yos", HB_TAG('Q','I','N',' ')}, /* Yos (retired code) -> Chin */
|
||||
{"yua", HB_TAG('M','Y','N',' ')}, /* Yucateco -> Mayan */
|
||||
{"yue", HB_TAG('Z','H','H',' ')}, /* Yue Chinese -> Chinese, Traditional, Hong Kong SAR */
|
||||
/*{"ywq", HB_TAG('Y','W','Q',' ')},*/ /* Wuding-Luquan Yi */
|
||||
{"za", HB_TAG('Z','H','A',' ')}, /* Zhuang [macrolanguage] */
|
||||
{"zch", HB_TAG('Z','H','A',' ')}, /* Central Hongshuihe Zhuang -> Zhuang */
|
||||
{"zdj", HB_TAG('C','M','R',' ')}, /* Ngazidja Comorian -> Comorian */
|
||||
|
|
|
|||
|
|
@ -102,10 +102,11 @@ struct hb_serialize_context_t
|
|||
char *tail;
|
||||
object_t *current; // Just for sanity check
|
||||
unsigned num_links;
|
||||
hb_serialize_error_t errors;
|
||||
};
|
||||
|
||||
snapshot_t snapshot ()
|
||||
{ return snapshot_t { head, tail, current, current->links.length }; }
|
||||
{ return snapshot_t { head, tail, current, current->links.length, errors }; }
|
||||
|
||||
hb_serialize_context_t (void *start_, unsigned int size) :
|
||||
start ((char *) start_),
|
||||
|
|
@ -136,6 +137,12 @@ struct hb_serialize_context_t
|
|||
HB_NODISCARD bool ran_out_of_room () const { return errors & HB_SERIALIZE_ERROR_OUT_OF_ROOM; }
|
||||
HB_NODISCARD bool offset_overflow () const { return errors & HB_SERIALIZE_ERROR_OFFSET_OVERFLOW; }
|
||||
HB_NODISCARD bool only_offset_overflow () const { return errors == HB_SERIALIZE_ERROR_OFFSET_OVERFLOW; }
|
||||
HB_NODISCARD bool only_overflow () const
|
||||
{
|
||||
return errors == HB_SERIALIZE_ERROR_OFFSET_OVERFLOW
|
||||
|| errors == HB_SERIALIZE_ERROR_INT_OVERFLOW
|
||||
|| errors == HB_SERIALIZE_ERROR_ARRAY_OVERFLOW;
|
||||
}
|
||||
|
||||
void reset (void *start_, unsigned int size)
|
||||
{
|
||||
|
|
@ -317,9 +324,11 @@ struct hb_serialize_context_t
|
|||
|
||||
void revert (snapshot_t snap)
|
||||
{
|
||||
if (unlikely (in_error ())) return;
|
||||
// Overflows that happened after the snapshot will be erased by the revert.
|
||||
if (unlikely (in_error () && !only_overflow ())) return;
|
||||
assert (snap.current == current);
|
||||
current->links.shrink (snap.num_links);
|
||||
errors = snap.errors;
|
||||
revert (snap.head, snap.tail);
|
||||
}
|
||||
|
||||
|
|
@ -363,6 +372,8 @@ struct hb_serialize_context_t
|
|||
assert (current->head <= (const char *) &ofs);
|
||||
|
||||
auto& link = *current->links.push ();
|
||||
if (current->links.in_error ())
|
||||
err (HB_SERIALIZE_ERROR_OTHER);
|
||||
|
||||
link.width = sizeof (T);
|
||||
link.is_signed = hb_is_signed (hb_unwrap_type (T));
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ hb_set_get_user_data (hb_set_t *set,
|
|||
hb_bool_t
|
||||
hb_set_allocation_successful (const hb_set_t *set)
|
||||
{
|
||||
return set->successful;
|
||||
return !set->in_error ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -201,9 +201,7 @@ hb_set_copy (const hb_set_t *set)
|
|||
void
|
||||
hb_set_clear (hb_set_t *set)
|
||||
{
|
||||
if (unlikely (hb_object_is_immutable (set)))
|
||||
return;
|
||||
|
||||
/* Immutible-safe. */
|
||||
set->clear ();
|
||||
}
|
||||
|
||||
|
|
@ -254,6 +252,7 @@ void
|
|||
hb_set_add (hb_set_t *set,
|
||||
hb_codepoint_t codepoint)
|
||||
{
|
||||
/* Immutible-safe. */
|
||||
set->add (codepoint);
|
||||
}
|
||||
|
||||
|
|
@ -273,6 +272,7 @@ hb_set_add_range (hb_set_t *set,
|
|||
hb_codepoint_t first,
|
||||
hb_codepoint_t last)
|
||||
{
|
||||
/* Immutible-safe. */
|
||||
set->add_range (first, last);
|
||||
}
|
||||
|
||||
|
|
@ -289,6 +289,7 @@ void
|
|||
hb_set_del (hb_set_t *set,
|
||||
hb_codepoint_t codepoint)
|
||||
{
|
||||
/* Immutible-safe. */
|
||||
set->del (codepoint);
|
||||
}
|
||||
|
||||
|
|
@ -311,6 +312,7 @@ hb_set_del_range (hb_set_t *set,
|
|||
hb_codepoint_t first,
|
||||
hb_codepoint_t last)
|
||||
{
|
||||
/* Immutible-safe. */
|
||||
set->del_range (first, last);
|
||||
}
|
||||
|
||||
|
|
@ -364,6 +366,7 @@ void
|
|||
hb_set_set (hb_set_t *set,
|
||||
const hb_set_t *other)
|
||||
{
|
||||
/* Immutible-safe. */
|
||||
set->set (*other);
|
||||
}
|
||||
|
||||
|
|
@ -380,6 +383,7 @@ void
|
|||
hb_set_union (hb_set_t *set,
|
||||
const hb_set_t *other)
|
||||
{
|
||||
/* Immutible-safe. */
|
||||
set->union_ (*other);
|
||||
}
|
||||
|
||||
|
|
@ -396,6 +400,7 @@ void
|
|||
hb_set_intersect (hb_set_t *set,
|
||||
const hb_set_t *other)
|
||||
{
|
||||
/* Immutible-safe. */
|
||||
set->intersect (*other);
|
||||
}
|
||||
|
||||
|
|
@ -412,6 +417,7 @@ void
|
|||
hb_set_subtract (hb_set_t *set,
|
||||
const hb_set_t *other)
|
||||
{
|
||||
/* Immutible-safe. */
|
||||
set->subtract (*other);
|
||||
}
|
||||
|
||||
|
|
@ -429,25 +435,24 @@ void
|
|||
hb_set_symmetric_difference (hb_set_t *set,
|
||||
const hb_set_t *other)
|
||||
{
|
||||
/* Immutible-safe. */
|
||||
set->symmetric_difference (*other);
|
||||
}
|
||||
|
||||
#ifndef HB_DISABLE_DEPRECATED
|
||||
/**
|
||||
* hb_set_invert:
|
||||
* @set: A set
|
||||
*
|
||||
* Inverts the contents of @set.
|
||||
*
|
||||
* Since: 0.9.10
|
||||
*
|
||||
* Deprecated: 1.6.1
|
||||
* Since: 3.0.0
|
||||
**/
|
||||
void
|
||||
hb_set_invert (hb_set_t *set HB_UNUSED)
|
||||
hb_set_invert (hb_set_t *set)
|
||||
{
|
||||
/* Immutible-safe. */
|
||||
set->invert ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hb_set_get_population:
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@ hb_set_clear (hb_set_t *set);
|
|||
HB_EXTERN hb_bool_t
|
||||
hb_set_is_empty (const hb_set_t *set);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_set_invert (hb_set_t *set);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_set_has (const hb_set_t *set,
|
||||
hb_codepoint_t codepoint);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright © 2012,2017 Google, Inc.
|
||||
* Copyright © 2021 Behdad Esfahbod
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
|
@ -28,330 +29,52 @@
|
|||
#define HB_SET_HH
|
||||
|
||||
#include "hb.hh"
|
||||
#include "hb-machinery.hh"
|
||||
#include "hb-bit-set-invertible.hh"
|
||||
|
||||
|
||||
/*
|
||||
* hb_set_t
|
||||
*/
|
||||
|
||||
/* TODO Keep a freelist so we can release pages that are completely zeroed. At that
|
||||
* point maybe also use a sentinel value for "all-1" pages? */
|
||||
|
||||
struct hb_set_t
|
||||
template <typename impl_t>
|
||||
struct hb_sparseset_t
|
||||
{
|
||||
hb_set_t () { init (); }
|
||||
~hb_set_t () { fini (); }
|
||||
|
||||
hb_set_t (const hb_set_t& other) : hb_set_t () { set (other); }
|
||||
void operator= (const hb_set_t& other) { set (other); }
|
||||
// TODO Add move construtor/assign
|
||||
// TODO Add constructor for Iterator; with specialization for (sorted) vector / array?
|
||||
|
||||
struct page_map_t
|
||||
{
|
||||
int cmp (const page_map_t &o) const { return (int) o.major - (int) major; }
|
||||
int cmp (uint32_t o_major) const { return (int) o_major - (int) major; }
|
||||
|
||||
uint32_t major;
|
||||
uint32_t index;
|
||||
};
|
||||
|
||||
struct page_t
|
||||
{
|
||||
void init0 () { v.clear (); }
|
||||
void init1 () { v.clear (0xFF); }
|
||||
|
||||
constexpr unsigned len () const
|
||||
{ return ARRAY_LENGTH_CONST (v); }
|
||||
|
||||
bool is_empty () const
|
||||
{
|
||||
for (unsigned int i = 0; i < len (); i++)
|
||||
if (v[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void add (hb_codepoint_t g) { elt (g) |= mask (g); }
|
||||
void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
|
||||
bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
|
||||
|
||||
void add_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
elt_t *la = &elt (a);
|
||||
elt_t *lb = &elt (b);
|
||||
if (la == lb)
|
||||
*la |= (mask (b) << 1) - mask(a);
|
||||
else
|
||||
{
|
||||
*la |= ~(mask (a) - 1);
|
||||
la++;
|
||||
|
||||
memset (la, 0xff, (char *) lb - (char *) la);
|
||||
|
||||
*lb |= ((mask (b) << 1) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void del_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
elt_t *la = &elt (a);
|
||||
elt_t *lb = &elt (b);
|
||||
if (la == lb)
|
||||
*la &= ~((mask (b) << 1) - mask(a));
|
||||
else
|
||||
{
|
||||
*la &= mask (a) - 1;
|
||||
la++;
|
||||
|
||||
memset (la, 0, (char *) lb - (char *) la);
|
||||
|
||||
*lb &= ~((mask (b) << 1) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_equal (const page_t &other) const
|
||||
{
|
||||
return 0 == hb_memcmp (&v, &other.v, sizeof (v));
|
||||
}
|
||||
bool is_subset (const page_t &larger_page) const
|
||||
{
|
||||
for (unsigned i = 0; i < len (); i++)
|
||||
if (~larger_page.v[i] & v[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int get_population () const
|
||||
{
|
||||
unsigned int pop = 0;
|
||||
for (unsigned int i = 0; i < len (); i++)
|
||||
pop += hb_popcount (v[i]);
|
||||
return pop;
|
||||
}
|
||||
|
||||
bool next (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
unsigned int m = (*codepoint + 1) & MASK;
|
||||
if (!m)
|
||||
{
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
unsigned int i = m / ELT_BITS;
|
||||
unsigned int j = m & ELT_MASK;
|
||||
|
||||
const elt_t vv = v[i] & ~((elt_t (1) << j) - 1);
|
||||
for (const elt_t *p = &vv; i < len (); p = &v[++i])
|
||||
if (*p)
|
||||
{
|
||||
*codepoint = i * ELT_BITS + elt_get_min (*p);
|
||||
return true;
|
||||
}
|
||||
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
bool previous (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
unsigned int m = (*codepoint - 1) & MASK;
|
||||
if (m == MASK)
|
||||
{
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
unsigned int i = m / ELT_BITS;
|
||||
unsigned int j = m & ELT_MASK;
|
||||
|
||||
/* Fancy mask to avoid shifting by elt_t bitsize, which is undefined. */
|
||||
const elt_t mask = j < 8 * sizeof (elt_t) - 1 ?
|
||||
((elt_t (1) << (j + 1)) - 1) :
|
||||
(elt_t) -1;
|
||||
const elt_t vv = v[i] & mask;
|
||||
const elt_t *p = &vv;
|
||||
while (true)
|
||||
{
|
||||
if (*p)
|
||||
{
|
||||
*codepoint = i * ELT_BITS + elt_get_max (*p);
|
||||
return true;
|
||||
}
|
||||
if ((int) i <= 0) break;
|
||||
p = &v[--i];
|
||||
}
|
||||
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
hb_codepoint_t get_min () const
|
||||
{
|
||||
for (unsigned int i = 0; i < len (); i++)
|
||||
if (v[i])
|
||||
return i * ELT_BITS + elt_get_min (v[i]);
|
||||
return INVALID;
|
||||
}
|
||||
hb_codepoint_t get_max () const
|
||||
{
|
||||
for (int i = len () - 1; i >= 0; i--)
|
||||
if (v[i])
|
||||
return i * ELT_BITS + elt_get_max (v[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef unsigned long long elt_t;
|
||||
static constexpr unsigned PAGE_BITS = 512;
|
||||
static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
|
||||
|
||||
static unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); }
|
||||
static unsigned int elt_get_max (const elt_t &elt) { return hb_bit_storage (elt) - 1; }
|
||||
|
||||
typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
|
||||
|
||||
static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8;
|
||||
static constexpr unsigned ELT_MASK = ELT_BITS - 1;
|
||||
static constexpr unsigned BITS = sizeof (vector_t) * 8;
|
||||
static constexpr unsigned MASK = BITS - 1;
|
||||
static_assert ((unsigned) PAGE_BITS == (unsigned) BITS, "");
|
||||
|
||||
elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; }
|
||||
const elt_t& elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
|
||||
static constexpr elt_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); }
|
||||
|
||||
vector_t v;
|
||||
};
|
||||
static_assert (page_t::PAGE_BITS == sizeof (page_t) * 8, "");
|
||||
|
||||
hb_object_header_t header;
|
||||
bool successful; /* Allocations successful */
|
||||
mutable unsigned int population;
|
||||
mutable unsigned int last_page_lookup;
|
||||
hb_sorted_vector_t<page_map_t> page_map;
|
||||
hb_vector_t<page_t> pages;
|
||||
impl_t s;
|
||||
|
||||
void init_shallow ()
|
||||
{
|
||||
successful = true;
|
||||
population = 0;
|
||||
last_page_lookup = 0;
|
||||
page_map.init ();
|
||||
pages.init ();
|
||||
}
|
||||
hb_sparseset_t () { init (); }
|
||||
~hb_sparseset_t () { fini (); }
|
||||
|
||||
hb_sparseset_t (const hb_sparseset_t& other) : hb_sparseset_t () { set (other); }
|
||||
void operator= (const hb_sparseset_t& other) { set (other); }
|
||||
// TODO Add move construtor/assign
|
||||
// TODO Add constructor for Iterator
|
||||
|
||||
void init_shallow () { s.init (); }
|
||||
void init ()
|
||||
{
|
||||
hb_object_init (this);
|
||||
init_shallow ();
|
||||
}
|
||||
void fini_shallow ()
|
||||
{
|
||||
population = 0;
|
||||
last_page_lookup = 0;
|
||||
page_map.fini ();
|
||||
pages.fini ();
|
||||
}
|
||||
void fini_shallow () { s.fini (); }
|
||||
void fini ()
|
||||
{
|
||||
hb_object_fini (this);
|
||||
fini_shallow ();
|
||||
}
|
||||
|
||||
bool in_error () const { return !successful; }
|
||||
|
||||
bool resize (unsigned int count)
|
||||
{
|
||||
if (unlikely (count > pages.length && !successful)) return false;
|
||||
if (!pages.resize (count) || !page_map.resize (count))
|
||||
{
|
||||
pages.resize (page_map.length);
|
||||
successful = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void reset ()
|
||||
{
|
||||
successful = true;
|
||||
clear ();
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
if (resize (0))
|
||||
population = 0;
|
||||
}
|
||||
bool is_empty () const
|
||||
{
|
||||
unsigned int count = pages.length;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!pages[i].is_empty ())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
explicit operator bool () const { return !is_empty (); }
|
||||
|
||||
void dirty () { population = UINT_MAX; }
|
||||
void err () { s.err (); }
|
||||
bool in_error () const { return s.in_error (); }
|
||||
|
||||
void add (hb_codepoint_t g)
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
if (unlikely (g == INVALID)) return;
|
||||
dirty ();
|
||||
page_t *page = page_for_insert (g); if (unlikely (!page)) return;
|
||||
page->add (g);
|
||||
}
|
||||
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
|
||||
if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
|
||||
dirty ();
|
||||
unsigned int ma = get_major (a);
|
||||
unsigned int mb = get_major (b);
|
||||
if (ma == mb)
|
||||
{
|
||||
page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
|
||||
page->add_range (a, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
|
||||
page->add_range (a, major_start (ma + 1) - 1);
|
||||
void reset () { s.reset (); }
|
||||
void clear () { s.clear (); }
|
||||
void invert () { s.invert (); }
|
||||
bool is_empty () const { return s.is_empty (); }
|
||||
|
||||
for (unsigned int m = ma + 1; m < mb; m++)
|
||||
{
|
||||
page = page_for_insert (major_start (m)); if (unlikely (!page)) return false;
|
||||
page->init1 ();
|
||||
}
|
||||
|
||||
page = page_for_insert (b); if (unlikely (!page)) return false;
|
||||
page->add_range (major_start (mb), b);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void add (hb_codepoint_t g) { s.add (g); }
|
||||
bool add_range (hb_codepoint_t a, hb_codepoint_t b) { return s.add_range (a, b); }
|
||||
|
||||
template <typename T>
|
||||
void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
if (!count) return;
|
||||
dirty ();
|
||||
hb_codepoint_t g = *array;
|
||||
while (count)
|
||||
{
|
||||
unsigned int m = get_major (g);
|
||||
page_t *page = page_for_insert (g); if (unlikely (!page)) return;
|
||||
unsigned int start = major_start (m);
|
||||
unsigned int end = major_start (m + 1);
|
||||
do
|
||||
{
|
||||
page->add (g);
|
||||
|
||||
array = &StructAtOffsetUnaligned<T> (array, stride);
|
||||
count--;
|
||||
}
|
||||
while (count && (g = *array, start <= g && g < end));
|
||||
}
|
||||
}
|
||||
{ s.add_array (array, count, stride); }
|
||||
template <typename T>
|
||||
void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
|
||||
|
||||
|
|
@ -359,108 +82,14 @@ struct hb_set_t
|
|||
* Used for faster rejection of corrupt data. */
|
||||
template <typename T>
|
||||
bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{
|
||||
if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
|
||||
if (!count) return true;
|
||||
dirty ();
|
||||
hb_codepoint_t g = *array;
|
||||
hb_codepoint_t last_g = g;
|
||||
while (count)
|
||||
{
|
||||
unsigned int m = get_major (g);
|
||||
page_t *page = page_for_insert (g); if (unlikely (!page)) return false;
|
||||
unsigned int end = major_start (m + 1);
|
||||
do
|
||||
{
|
||||
/* If we try harder we can change the following comparison to <=;
|
||||
* Not sure if it's worth it. */
|
||||
if (g < last_g) return false;
|
||||
last_g = g;
|
||||
page->add (g);
|
||||
|
||||
array = (const T *) ((const char *) array + stride);
|
||||
count--;
|
||||
}
|
||||
while (count && (g = *array, g < end));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
{ return s.add_sorted_array (array, count, stride); }
|
||||
template <typename T>
|
||||
bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
|
||||
|
||||
void del (hb_codepoint_t g)
|
||||
{
|
||||
/* TODO perform op even if !successful. */
|
||||
if (unlikely (!successful)) return;
|
||||
page_t *page = page_for (g);
|
||||
if (!page)
|
||||
return;
|
||||
dirty ();
|
||||
page->del (g);
|
||||
}
|
||||
void del (hb_codepoint_t g) { s.del (g); }
|
||||
void del_range (hb_codepoint_t a, hb_codepoint_t b) { s.del_range (a, b); }
|
||||
|
||||
private:
|
||||
void del_pages (int ds, int de)
|
||||
{
|
||||
if (ds <= de)
|
||||
{
|
||||
// Pre-allocate the workspace that compact() will need so we can bail on allocation failure
|
||||
// before attempting to rewrite the page map.
|
||||
hb_vector_t<unsigned> compact_workspace;
|
||||
if (unlikely (!allocate_compact_workspace (compact_workspace))) return;
|
||||
|
||||
unsigned int write_index = 0;
|
||||
for (unsigned int i = 0; i < page_map.length; i++)
|
||||
{
|
||||
int m = (int) page_map[i].major;
|
||||
if (m < ds || de < m)
|
||||
page_map[write_index++] = page_map[i];
|
||||
}
|
||||
compact (compact_workspace, write_index);
|
||||
resize (write_index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
void del_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
/* TODO perform op even if !successful. */
|
||||
if (unlikely (!successful)) return;
|
||||
if (unlikely (a > b || a == INVALID)) return;
|
||||
dirty ();
|
||||
unsigned int ma = get_major (a);
|
||||
unsigned int mb = get_major (b);
|
||||
/* Delete pages from ds through de if ds <= de. */
|
||||
int ds = (a == major_start (ma))? (int) ma: (int) (ma + 1);
|
||||
int de = (b + 1 == major_start (mb + 1))? (int) mb: ((int) mb - 1);
|
||||
if (ds > de || (int) ma < ds)
|
||||
{
|
||||
page_t *page = page_for (a);
|
||||
if (page)
|
||||
{
|
||||
if (ma == mb)
|
||||
page->del_range (a, b);
|
||||
else
|
||||
page->del_range (a, major_start (ma + 1) - 1);
|
||||
}
|
||||
}
|
||||
if (de < (int) mb && ma != mb)
|
||||
{
|
||||
page_t *page = page_for (b);
|
||||
if (page)
|
||||
page->del_range (major_start (mb), b);
|
||||
}
|
||||
del_pages (ds, de);
|
||||
}
|
||||
|
||||
bool get (hb_codepoint_t g) const
|
||||
{
|
||||
const page_t *page = page_for (g);
|
||||
if (!page)
|
||||
return false;
|
||||
return page->get (g);
|
||||
}
|
||||
bool get (hb_codepoint_t g) const { return s.get (g); }
|
||||
|
||||
/* Has interface. */
|
||||
static constexpr bool SENTINEL = false;
|
||||
|
|
@ -471,503 +100,49 @@ struct hb_set_t
|
|||
bool operator () (hb_codepoint_t k) const { return has (k); }
|
||||
|
||||
/* Sink interface. */
|
||||
hb_set_t& operator << (hb_codepoint_t v)
|
||||
hb_sparseset_t& operator << (hb_codepoint_t v)
|
||||
{ add (v); return *this; }
|
||||
hb_set_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
|
||||
hb_sparseset_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
|
||||
{ add_range (range.first, range.second); return *this; }
|
||||
|
||||
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
|
||||
{
|
||||
hb_codepoint_t c = first - 1;
|
||||
return next (&c) && c <= last;
|
||||
}
|
||||
void set (const hb_set_t &other)
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
unsigned int count = other.pages.length;
|
||||
if (!resize (count))
|
||||
return;
|
||||
population = other.population;
|
||||
{ return s.intersects (first, last); }
|
||||
|
||||
hb_memcpy ((void *) pages, (const void *) other.pages, count * pages.item_size);
|
||||
hb_memcpy ((void *) page_map, (const void *) other.page_map, count * page_map.item_size);
|
||||
}
|
||||
void set (const hb_sparseset_t &other) { s.set (other.s); }
|
||||
|
||||
bool is_equal (const hb_set_t &other) const
|
||||
{
|
||||
if (get_population () != other.get_population ())
|
||||
return false;
|
||||
bool is_equal (const hb_sparseset_t &other) const { return s.is_equal (other.s); }
|
||||
|
||||
unsigned int na = pages.length;
|
||||
unsigned int nb = other.pages.length;
|
||||
bool is_subset (const hb_sparseset_t &larger_set) const { return s.is_subset (larger_set.s); }
|
||||
|
||||
unsigned int a = 0, b = 0;
|
||||
for (; a < na && b < nb; )
|
||||
{
|
||||
if (page_at (a).is_empty ()) { a++; continue; }
|
||||
if (other.page_at (b).is_empty ()) { b++; continue; }
|
||||
if (page_map[a].major != other.page_map[b].major ||
|
||||
!page_at (a).is_equal (other.page_at (b)))
|
||||
return false;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
for (; a < na; a++)
|
||||
if (!page_at (a).is_empty ()) { return false; }
|
||||
for (; b < nb; b++)
|
||||
if (!other.page_at (b).is_empty ()) { return false; }
|
||||
void union_ (const hb_sparseset_t &other) { s.union_ (other.s); }
|
||||
void intersect (const hb_sparseset_t &other) { s.intersect (other.s); }
|
||||
void subtract (const hb_sparseset_t &other) { s.subtract (other.s); }
|
||||
void symmetric_difference (const hb_sparseset_t &other) { s.symmetric_difference (other.s); }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_subset (const hb_set_t &larger_set) const
|
||||
{
|
||||
/* TODO: Merge this and is_equal() into something like process(). */
|
||||
if (unlikely(larger_set.is_empty ()))
|
||||
return is_empty ();
|
||||
|
||||
uint32_t spi = 0;
|
||||
for (uint32_t lpi = 0; spi < page_map.length && lpi < larger_set.page_map.length; lpi++)
|
||||
{
|
||||
uint32_t spm = page_map[spi].major;
|
||||
uint32_t lpm = larger_set.page_map[lpi].major;
|
||||
auto sp = page_at (spi);
|
||||
auto lp = larger_set.page_at (lpi);
|
||||
|
||||
if (spm < lpm && !sp.is_empty ())
|
||||
return false;
|
||||
|
||||
if (lpm < spm)
|
||||
continue;
|
||||
|
||||
if (!sp.is_subset (lp))
|
||||
return false;
|
||||
|
||||
spi++;
|
||||
}
|
||||
|
||||
while (spi < page_map.length)
|
||||
if (!page_at (spi++).is_empty ())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool allocate_compact_workspace(hb_vector_t<unsigned>& workspace)
|
||||
{
|
||||
if (unlikely(!workspace.resize (pages.length)))
|
||||
{
|
||||
successful = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* workspace should be a pre-sized vector allocated to hold at exactly pages.length
|
||||
* elements.
|
||||
*/
|
||||
void compact (hb_vector_t<unsigned>& workspace,
|
||||
unsigned int length)
|
||||
{
|
||||
assert(workspace.length == pages.length);
|
||||
hb_vector_t<unsigned>& old_index_to_page_map_index = workspace;
|
||||
|
||||
hb_fill (old_index_to_page_map_index.writer(), 0xFFFFFFFF);
|
||||
/* TODO(iter) Rewrite as dagger? */
|
||||
for (unsigned i = 0; i < length; i++)
|
||||
old_index_to_page_map_index[page_map[i].index] = i;
|
||||
|
||||
compact_pages (old_index_to_page_map_index);
|
||||
}
|
||||
|
||||
void compact_pages (const hb_vector_t<unsigned>& old_index_to_page_map_index)
|
||||
{
|
||||
unsigned int write_index = 0;
|
||||
for (unsigned int i = 0; i < pages.length; i++)
|
||||
{
|
||||
if (old_index_to_page_map_index[i] == 0xFFFFFFFF) continue;
|
||||
|
||||
if (write_index < i)
|
||||
pages[write_index] = pages[i];
|
||||
|
||||
page_map[old_index_to_page_map_index[i]].index = write_index;
|
||||
write_index++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Op>
|
||||
void process (const Op& op, const hb_set_t &other)
|
||||
{
|
||||
const bool passthru_left = op (1, 0);
|
||||
const bool passthru_right = op (0, 1);
|
||||
|
||||
if (unlikely (!successful)) return;
|
||||
|
||||
dirty ();
|
||||
|
||||
unsigned int na = pages.length;
|
||||
unsigned int nb = other.pages.length;
|
||||
unsigned int next_page = na;
|
||||
|
||||
unsigned int count = 0, newCount = 0;
|
||||
unsigned int a = 0, b = 0;
|
||||
unsigned int write_index = 0;
|
||||
|
||||
// Pre-allocate the workspace that compact() will need so we can bail on allocation failure
|
||||
// before attempting to rewrite the page map.
|
||||
hb_vector_t<unsigned> compact_workspace;
|
||||
if (!passthru_left && unlikely (!allocate_compact_workspace (compact_workspace))) return;
|
||||
|
||||
for (; a < na && b < nb; )
|
||||
{
|
||||
if (page_map[a].major == other.page_map[b].major)
|
||||
{
|
||||
if (!passthru_left)
|
||||
{
|
||||
// Move page_map entries that we're keeping from the left side set
|
||||
// to the front of the page_map vector. This isn't necessary if
|
||||
// passthru_left is set since no left side pages will be removed
|
||||
// in that case.
|
||||
if (write_index < a)
|
||||
page_map[write_index] = page_map[a];
|
||||
write_index++;
|
||||
}
|
||||
|
||||
count++;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
else if (page_map[a].major < other.page_map[b].major)
|
||||
{
|
||||
if (passthru_left)
|
||||
count++;
|
||||
a++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (passthru_right)
|
||||
count++;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
if (passthru_left)
|
||||
count += na - a;
|
||||
if (passthru_right)
|
||||
count += nb - b;
|
||||
|
||||
if (!passthru_left)
|
||||
{
|
||||
na = write_index;
|
||||
next_page = write_index;
|
||||
compact (compact_workspace, write_index);
|
||||
}
|
||||
|
||||
if (!resize (count))
|
||||
return;
|
||||
|
||||
newCount = count;
|
||||
|
||||
/* Process in-place backward. */
|
||||
a = na;
|
||||
b = nb;
|
||||
for (; a && b; )
|
||||
{
|
||||
if (page_map[a - 1].major == other.page_map[b - 1].major)
|
||||
{
|
||||
a--;
|
||||
b--;
|
||||
count--;
|
||||
page_map[count] = page_map[a];
|
||||
page_at (count).v = op (page_at (a).v, other.page_at (b).v);
|
||||
}
|
||||
else if (page_map[a - 1].major > other.page_map[b - 1].major)
|
||||
{
|
||||
a--;
|
||||
if (passthru_left)
|
||||
{
|
||||
count--;
|
||||
page_map[count] = page_map[a];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
b--;
|
||||
if (passthru_right)
|
||||
{
|
||||
count--;
|
||||
page_map[count].major = other.page_map[b].major;
|
||||
page_map[count].index = next_page++;
|
||||
page_at (count).v = other.page_at (b).v;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (passthru_left)
|
||||
while (a)
|
||||
{
|
||||
a--;
|
||||
count--;
|
||||
page_map[count] = page_map [a];
|
||||
}
|
||||
if (passthru_right)
|
||||
while (b)
|
||||
{
|
||||
b--;
|
||||
count--;
|
||||
page_map[count].major = other.page_map[b].major;
|
||||
page_map[count].index = next_page++;
|
||||
page_at (count).v = other.page_at (b).v;
|
||||
}
|
||||
assert (!count);
|
||||
if (pages.length > newCount)
|
||||
// This resize() doesn't need to be checked because we can't get here
|
||||
// if the set is currently in_error() and this only resizes downwards
|
||||
// which will always succeed if the set is not in_error().
|
||||
resize (newCount);
|
||||
}
|
||||
|
||||
void union_ (const hb_set_t &other)
|
||||
{
|
||||
process (hb_bitwise_or, other);
|
||||
}
|
||||
void intersect (const hb_set_t &other)
|
||||
{
|
||||
process (hb_bitwise_and, other);
|
||||
}
|
||||
void subtract (const hb_set_t &other)
|
||||
{
|
||||
process (hb_bitwise_sub, other);
|
||||
}
|
||||
void symmetric_difference (const hb_set_t &other)
|
||||
{
|
||||
process (hb_bitwise_xor, other);
|
||||
}
|
||||
bool next (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
// TODO: this should be merged with prev() as both implementations
|
||||
// are very similar.
|
||||
if (unlikely (*codepoint == INVALID)) {
|
||||
*codepoint = get_min ();
|
||||
return *codepoint != INVALID;
|
||||
}
|
||||
|
||||
const auto* page_map_array = page_map.arrayZ;
|
||||
unsigned int major = get_major (*codepoint);
|
||||
unsigned int i = last_page_lookup;
|
||||
|
||||
if (unlikely (i >= page_map.length || page_map_array[i].major != major))
|
||||
{
|
||||
page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST);
|
||||
if (i >= page_map.length) {
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const auto* pages_array = pages.arrayZ;
|
||||
const page_map_t ¤t = page_map_array[i];
|
||||
if (likely (current.major == major))
|
||||
{
|
||||
if (pages_array[current.index].next (codepoint))
|
||||
{
|
||||
*codepoint += current.major * page_t::PAGE_BITS;
|
||||
last_page_lookup = i;
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
for (; i < page_map.length; i++)
|
||||
{
|
||||
const page_map_t ¤t = page_map.arrayZ[i];
|
||||
hb_codepoint_t m = pages_array[current.index].get_min ();
|
||||
if (m != INVALID)
|
||||
{
|
||||
*codepoint = current.major * page_t::PAGE_BITS + m;
|
||||
last_page_lookup = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
last_page_lookup = 0;
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
bool previous (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
if (unlikely (*codepoint == INVALID)) {
|
||||
*codepoint = get_max ();
|
||||
return *codepoint != INVALID;
|
||||
}
|
||||
|
||||
page_map_t map = {get_major (*codepoint), 0};
|
||||
unsigned int i;
|
||||
page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST);
|
||||
if (i < page_map.length && page_map[i].major == map.major)
|
||||
{
|
||||
if (pages[page_map[i].index].previous (codepoint))
|
||||
{
|
||||
*codepoint += page_map[i].major * page_t::PAGE_BITS;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
i--;
|
||||
for (; (int) i >= 0; i--)
|
||||
{
|
||||
hb_codepoint_t m = pages[page_map[i].index].get_max ();
|
||||
if (m != INVALID)
|
||||
{
|
||||
*codepoint = page_map[i].major * page_t::PAGE_BITS + m;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
bool next (hb_codepoint_t *codepoint) const { return s.next (codepoint); }
|
||||
bool previous (hb_codepoint_t *codepoint) const { return s.previous (codepoint); }
|
||||
bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
|
||||
{
|
||||
hb_codepoint_t i;
|
||||
|
||||
i = *last;
|
||||
if (!next (&i))
|
||||
{
|
||||
*last = *first = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* TODO Speed up. */
|
||||
*last = *first = i;
|
||||
while (next (&i) && i == *last + 1)
|
||||
(*last)++;
|
||||
|
||||
return true;
|
||||
}
|
||||
{ return s.next_range (first, last); }
|
||||
bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
|
||||
{
|
||||
hb_codepoint_t i;
|
||||
{ return s.previous_range (first, last); }
|
||||
|
||||
i = *first;
|
||||
if (!previous (&i))
|
||||
{
|
||||
*last = *first = INVALID;
|
||||
return false;
|
||||
}
|
||||
unsigned int get_population () const { return s.get_population (); }
|
||||
hb_codepoint_t get_min () const { return s.get_min (); }
|
||||
hb_codepoint_t get_max () const { return s.get_max (); }
|
||||
|
||||
/* TODO Speed up. */
|
||||
*last = *first = i;
|
||||
while (previous (&i) && i == *first - 1)
|
||||
(*first)--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int get_population () const
|
||||
{
|
||||
if (population != UINT_MAX)
|
||||
return population;
|
||||
|
||||
unsigned int pop = 0;
|
||||
unsigned int count = pages.length;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
pop += pages[i].get_population ();
|
||||
|
||||
population = pop;
|
||||
return pop;
|
||||
}
|
||||
hb_codepoint_t get_min () const
|
||||
{
|
||||
unsigned int count = pages.length;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!page_at (i).is_empty ())
|
||||
return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_min ();
|
||||
return INVALID;
|
||||
}
|
||||
hb_codepoint_t get_max () const
|
||||
{
|
||||
unsigned int count = pages.length;
|
||||
for (int i = count - 1; i >= 0; i--)
|
||||
if (!page_at (i).is_empty ())
|
||||
return page_map[(unsigned) i].major * page_t::PAGE_BITS + page_at (i).get_max ();
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
static constexpr hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
|
||||
static constexpr hb_codepoint_t INVALID = impl_t::INVALID;
|
||||
|
||||
/*
|
||||
* Iterator implementation.
|
||||
*/
|
||||
struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
|
||||
{
|
||||
static constexpr bool is_sorted_iterator = true;
|
||||
iter_t (const hb_set_t &s_ = Null (hb_set_t),
|
||||
bool init = true) : s (&s_), v (INVALID), l(0)
|
||||
{
|
||||
if (init)
|
||||
{
|
||||
l = s->get_population () + 1;
|
||||
__next__ ();
|
||||
}
|
||||
}
|
||||
|
||||
typedef hb_codepoint_t __item_t__;
|
||||
hb_codepoint_t __item__ () const { return v; }
|
||||
bool __more__ () const { return v != INVALID; }
|
||||
void __next__ () { s->next (&v); if (l) l--; }
|
||||
void __prev__ () { s->previous (&v); }
|
||||
unsigned __len__ () const { return l; }
|
||||
iter_t end () const { return iter_t (*s, false); }
|
||||
bool operator != (const iter_t& o) const
|
||||
{ return s != o.s || v != o.v; }
|
||||
|
||||
protected:
|
||||
const hb_set_t *s;
|
||||
hb_codepoint_t v;
|
||||
unsigned l;
|
||||
};
|
||||
iter_t iter () const { return iter_t (*this); }
|
||||
using iter_t = typename impl_t::iter_t;
|
||||
iter_t iter () const { return iter_t (this->s); }
|
||||
operator iter_t () const { return iter (); }
|
||||
|
||||
protected:
|
||||
|
||||
page_t *page_for_insert (hb_codepoint_t g)
|
||||
{
|
||||
page_map_t map = {get_major (g), pages.length};
|
||||
unsigned int i;
|
||||
if (!page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST))
|
||||
{
|
||||
if (!resize (pages.length + 1))
|
||||
return nullptr;
|
||||
|
||||
pages[map.index].init0 ();
|
||||
memmove (page_map + i + 1,
|
||||
page_map + i,
|
||||
(page_map.length - 1 - i) * page_map.item_size);
|
||||
page_map[i] = map;
|
||||
}
|
||||
return &pages[page_map[i].index];
|
||||
}
|
||||
page_t *page_for (hb_codepoint_t g)
|
||||
{
|
||||
page_map_t key = {get_major (g)};
|
||||
const page_map_t *found = page_map.bsearch (key);
|
||||
if (found)
|
||||
return &pages[found->index];
|
||||
return nullptr;
|
||||
}
|
||||
const page_t *page_for (hb_codepoint_t g) const
|
||||
{
|
||||
page_map_t key = {get_major (g)};
|
||||
const page_map_t *found = page_map.bsearch (key);
|
||||
if (found)
|
||||
return &pages[found->index];
|
||||
return nullptr;
|
||||
}
|
||||
page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
|
||||
const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
|
||||
unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
|
||||
hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
|
||||
};
|
||||
|
||||
struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t> {};
|
||||
|
||||
static_assert (hb_set_t::INVALID == HB_SET_VALUE_INVALID, "");
|
||||
|
||||
|
||||
#endif /* HB_SET_HH */
|
||||
|
|
|
|||
|
|
@ -404,7 +404,7 @@ _hb_shape_plan_execute_internal (hb_shape_plan_t *shape_plan,
|
|||
|
||||
buffer->assert_unicode ();
|
||||
|
||||
if (unlikely (hb_object_is_inert (shape_plan)))
|
||||
if (unlikely (!hb_object_is_valid (shape_plan)))
|
||||
return false;
|
||||
|
||||
assert (shape_plan->face_unsafe == font->face);
|
||||
|
|
@ -529,7 +529,7 @@ hb_shape_plan_create_cached2 (hb_face_t *face,
|
|||
retry:
|
||||
hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans;
|
||||
|
||||
bool dont_cache = hb_object_is_inert (face);
|
||||
bool dont_cache = !hb_object_is_valid (face);
|
||||
|
||||
if (likely (!dont_cache))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -48,9 +48,7 @@
|
|||
**/
|
||||
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_shaper_list ();
|
||||
#endif
|
||||
static inline void free_static_shaper_list ();
|
||||
|
||||
static const char *nil_shaper_list[] = {nullptr};
|
||||
|
||||
|
|
@ -69,9 +67,7 @@ static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
|
|||
shaper_list[i] = shapers[i].name;
|
||||
shaper_list[i] = nullptr;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_shaper_list);
|
||||
#endif
|
||||
hb_atexit (free_static_shaper_list);
|
||||
|
||||
return shaper_list;
|
||||
}
|
||||
|
|
@ -81,13 +77,11 @@ static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
|
|||
{ return nil_shaper_list; }
|
||||
} static_shaper_list;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_shaper_list ()
|
||||
{
|
||||
static_shaper_list.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -38,9 +38,7 @@ static const hb_shaper_entry_t all_shapers[] = {
|
|||
static_assert (0 != ARRAY_LENGTH_CONST (all_shapers), "No shaper enabled.");
|
||||
#endif
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_shapers ();
|
||||
#endif
|
||||
static inline void free_static_shapers ();
|
||||
|
||||
static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_t,
|
||||
hb_shapers_lazy_loader_t>
|
||||
|
|
@ -83,9 +81,7 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_
|
|||
p = end + 1;
|
||||
}
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_shapers);
|
||||
#endif
|
||||
hb_atexit (free_static_shapers);
|
||||
|
||||
return shapers;
|
||||
}
|
||||
|
|
@ -93,13 +89,11 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_
|
|||
static const hb_shaper_entry_t *get_null () { return all_shapers; }
|
||||
} static_shapers;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_shapers ()
|
||||
{
|
||||
static_shapers.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
const hb_shaper_entry_t *
|
||||
_hb_shapers_get ()
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_STYLE
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
|
||||
#include "hb-ot-var-avar-table.hh"
|
||||
#include "hb-ot-var-fvar-table.hh"
|
||||
|
|
@ -36,56 +35,46 @@
|
|||
#include "hb-ot-face.hh"
|
||||
|
||||
/**
|
||||
* hb_style_tag_t:
|
||||
* @HB_STYLE_TAG_ITALIC: Used to vary between non-italic and italic.
|
||||
* A value of 0 can be interpreted as "Roman" (non-italic); a value of 1 can
|
||||
* be interpreted as (fully) italic.
|
||||
* @HB_STYLE_TAG_OPTICAL_SIZE: Used to vary design to suit different text sizes.
|
||||
* Non-zero. Values can be interpreted as text size, in points.
|
||||
* @HB_STYLE_TAG_SLANT: Used to vary between upright and slanted text. Values
|
||||
* must be greater than -90 and less than +90. Values can be interpreted as
|
||||
* the angle, in counter-clockwise degrees, of oblique slant from whatever the
|
||||
* designer considers to be upright for that font design.
|
||||
* @HB_STYLE_TAG_WIDTH: Used to vary width of text from narrower to wider.
|
||||
* Non-zero. Values can be interpreted as a percentage of whatever the font
|
||||
* designer considers “normal width” for that font design.
|
||||
* @HB_STYLE_TAG_WEIGHT: Used to vary stroke thicknesses or other design details
|
||||
* to give variation from lighter to blacker. Values can be interpreted in direct
|
||||
* comparison to values for usWeightClass in the OS/2 table,
|
||||
* or the CSS font-weight property.
|
||||
* SECTION:hb-style
|
||||
* @title: hb-style
|
||||
* @short_description: Font Styles
|
||||
* @include: hb.h
|
||||
*
|
||||
* Defined by https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
* Functions for fetching style information from fonts.
|
||||
**/
|
||||
typedef enum {
|
||||
HB_STYLE_TAG_ITALIC = HB_TAG ('i','t','a','l'),
|
||||
HB_STYLE_TAG_OPTICAL_SIZE = HB_TAG ('o','p','s','z'),
|
||||
HB_STYLE_TAG_SLANT = HB_TAG ('s','l','n','t'),
|
||||
HB_STYLE_TAG_WIDTH = HB_TAG ('w','d','t','h'),
|
||||
HB_STYLE_TAG_WEIGHT = HB_TAG ('w','g','h','t'),
|
||||
|
||||
/*< private >*/
|
||||
_HB_STYLE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
|
||||
} hb_style_tag_t;
|
||||
static inline float
|
||||
_hb_angle_to_ratio (float a)
|
||||
{
|
||||
return tanf (a * float (M_PI / 180.));
|
||||
}
|
||||
#if 0
|
||||
static inline float
|
||||
_hb_ratio_to_angle (float r)
|
||||
{
|
||||
return atanf (r) * float (180. / M_PI);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hb_style_get_value:
|
||||
* @font: a #hb_font_t object.
|
||||
* @style_tag: a style tag.
|
||||
*
|
||||
* Searches variation axes of a hb_font_t object for a specific axis first,
|
||||
* Searches variation axes of a #hb_font_t object for a specific axis first,
|
||||
* if not set, then tries to get default style values from different
|
||||
* tables of the font.
|
||||
*
|
||||
* Returns: Corresponding axis or default value to a style tag.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
* Since: 3.0.0
|
||||
**/
|
||||
float
|
||||
hb_style_get_value (hb_font_t *font, hb_tag_t tag)
|
||||
hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag)
|
||||
{
|
||||
hb_style_tag_t style_tag = (hb_style_tag_t) tag;
|
||||
if (unlikely (style_tag == HB_STYLE_TAG_SLANT_RATIO))
|
||||
return _hb_angle_to_ratio (hb_style_get_value (font, HB_STYLE_TAG_SLANT_ANGLE));
|
||||
|
||||
hb_face_t *face = font->face;
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
|
|
@ -112,12 +101,14 @@ hb_style_get_value (hb_font_t *font, hb_tag_t tag)
|
|||
return face->table.OS2->is_italic () || face->table.head->is_italic () ? 1 : 0;
|
||||
case HB_STYLE_TAG_OPTICAL_SIZE:
|
||||
{
|
||||
unsigned int lower, upper;
|
||||
unsigned int lower, design, upper;
|
||||
return face->table.OS2->v5 ().get_optical_size (&lower, &upper)
|
||||
? (float) (lower + upper) / 2.f
|
||||
: hb_ot_layout_get_size_params (face, &design, nullptr, nullptr, nullptr, nullptr)
|
||||
? design / 10.f
|
||||
: 12.f;
|
||||
}
|
||||
case HB_STYLE_TAG_SLANT:
|
||||
case HB_STYLE_TAG_SLANT_ANGLE:
|
||||
return face->table.post->table->italicAngle.to_float ();
|
||||
case HB_STYLE_TAG_WIDTH:
|
||||
return face->table.OS2->has_data ()
|
||||
|
|
@ -133,4 +124,3 @@ hb_style_get_value (hb_font_t *font, hb_tag_t tag)
|
|||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,10 +33,46 @@
|
|||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
/**
|
||||
* hb_style_tag_t:
|
||||
* @HB_STYLE_TAG_ITALIC: Used to vary between non-italic and italic.
|
||||
* A value of 0 can be interpreted as "Roman" (non-italic); a value of 1 can
|
||||
* be interpreted as (fully) italic.
|
||||
* @HB_STYLE_TAG_OPTICAL_SIZE: Used to vary design to suit different text sizes.
|
||||
* Non-zero. Values can be interpreted as text size, in points.
|
||||
* @HB_STYLE_TAG_SLANT_ANGLE: Used to vary between upright and slanted text. Values
|
||||
* must be greater than -90 and less than +90. Values can be interpreted as
|
||||
* the angle, in counter-clockwise degrees, of oblique slant from whatever the
|
||||
* designer considers to be upright for that font design.
|
||||
* @HB_STYLE_TAG_SLANT_RATIO: same as @HB_STYLE_TAG_SLANT_ANGLE expression as ratio.
|
||||
* @HB_STYLE_TAG_WIDTH: Used to vary width of text from narrower to wider.
|
||||
* Non-zero. Values can be interpreted as a percentage of whatever the font
|
||||
* designer considers “normal width” for that font design.
|
||||
* @HB_STYLE_TAG_WEIGHT: Used to vary stroke thicknesses or other design details
|
||||
* to give variation from lighter to blacker. Values can be interpreted in direct
|
||||
* comparison to values for usWeightClass in the OS/2 table,
|
||||
* or the CSS font-weight property.
|
||||
*
|
||||
* Defined by [OpenType Design-Variation Axis Tag Registry](https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg).
|
||||
*
|
||||
* Since: 3.0.0
|
||||
**/
|
||||
typedef enum
|
||||
{
|
||||
HB_STYLE_TAG_ITALIC = HB_TAG ('i','t','a','l'),
|
||||
HB_STYLE_TAG_OPTICAL_SIZE = HB_TAG ('o','p','s','z'),
|
||||
HB_STYLE_TAG_SLANT_ANGLE = HB_TAG ('s','l','n','t'),
|
||||
HB_STYLE_TAG_SLANT_RATIO = HB_TAG ('S','l','n','t'),
|
||||
HB_STYLE_TAG_WIDTH = HB_TAG ('w','d','t','h'),
|
||||
HB_STYLE_TAG_WEIGHT = HB_TAG ('w','g','h','t'),
|
||||
|
||||
/*< private >*/
|
||||
_HB_STYLE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
|
||||
} hb_style_tag_t;
|
||||
|
||||
|
||||
HB_EXTERN float
|
||||
hb_style_get_value (hb_font_t *font, hb_tag_t style_tag);
|
||||
#endif
|
||||
hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -45,18 +45,20 @@ hb_subset_input_create_or_fail (void)
|
|||
if (unlikely (!input))
|
||||
return nullptr;
|
||||
|
||||
input->unicodes = hb_set_create ();
|
||||
input->glyphs = hb_set_create ();
|
||||
input->name_ids = hb_set_create ();
|
||||
hb_set_add_range (input->name_ids, 0, 6);
|
||||
input->name_languages = hb_set_create ();
|
||||
hb_set_add (input->name_languages, 0x0409);
|
||||
input->layout_features = hb_set_create ();
|
||||
input->drop_tables = hb_set_create ();
|
||||
input->no_subset_tables = hb_set_create ();
|
||||
for (auto& set : input->sets_iter ())
|
||||
set = hb_set_create ();
|
||||
|
||||
if (input->in_error ())
|
||||
{
|
||||
hb_subset_input_destroy (input);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
input->flags = HB_SUBSET_FLAGS_DEFAULT;
|
||||
|
||||
hb_set_add_range (input->sets.name_ids, 0, 6);
|
||||
hb_set_add (input->sets.name_languages, 0x0409);
|
||||
|
||||
hb_tag_t default_drop_tables[] = {
|
||||
// Layout disabled by default
|
||||
HB_TAG ('m', 'o', 'r', 'x'),
|
||||
|
|
@ -81,7 +83,7 @@ hb_subset_input_create_or_fail (void)
|
|||
HB_TAG ('S', 'i', 'l', 'f'),
|
||||
HB_TAG ('S', 'i', 'l', 'l'),
|
||||
};
|
||||
input->drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables));
|
||||
input->sets.drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables));
|
||||
|
||||
hb_tag_t default_no_subset_tables[] = {
|
||||
HB_TAG ('a', 'v', 'a', 'r'),
|
||||
|
|
@ -96,8 +98,8 @@ hb_subset_input_create_or_fail (void)
|
|||
HB_TAG ('c', 'v', 'a', 'r'),
|
||||
HB_TAG ('S', 'T', 'A', 'T'),
|
||||
};
|
||||
input->no_subset_tables->add_array (default_no_subset_tables,
|
||||
ARRAY_LENGTH (default_no_subset_tables));
|
||||
input->sets.no_subset_tables->add_array (default_no_subset_tables,
|
||||
ARRAY_LENGTH (default_no_subset_tables));
|
||||
|
||||
//copied from _layout_features_groups in fonttools
|
||||
hb_tag_t default_layout_features[] = {
|
||||
|
|
@ -186,7 +188,13 @@ hb_subset_input_create_or_fail (void)
|
|||
HB_TAG ('b', 'l', 'w', 'm'),
|
||||
};
|
||||
|
||||
input->layout_features->add_array (default_layout_features, ARRAY_LENGTH (default_layout_features));
|
||||
input->sets.layout_features->add_array (default_layout_features, ARRAY_LENGTH (default_layout_features));
|
||||
|
||||
if (input->in_error ())
|
||||
{
|
||||
hb_subset_input_destroy (input);
|
||||
return nullptr;
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
|
|
@ -220,13 +228,8 @@ hb_subset_input_destroy (hb_subset_input_t *input)
|
|||
{
|
||||
if (!hb_object_destroy (input)) return;
|
||||
|
||||
hb_set_destroy (input->unicodes);
|
||||
hb_set_destroy (input->glyphs);
|
||||
hb_set_destroy (input->name_ids);
|
||||
hb_set_destroy (input->name_languages);
|
||||
hb_set_destroy (input->drop_tables);
|
||||
hb_set_destroy (input->layout_features);
|
||||
hb_set_destroy (input->no_subset_tables);
|
||||
for (hb_set_t* set : input->sets_iter ())
|
||||
hb_set_destroy (set);
|
||||
|
||||
hb_free (input);
|
||||
}
|
||||
|
|
@ -246,7 +249,7 @@ hb_subset_input_destroy (hb_subset_input_t *input)
|
|||
HB_EXTERN hb_set_t *
|
||||
hb_subset_input_unicode_set (hb_subset_input_t *input)
|
||||
{
|
||||
return input->unicodes;
|
||||
return input->sets.unicodes;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -263,100 +266,32 @@ hb_subset_input_unicode_set (hb_subset_input_t *input)
|
|||
HB_EXTERN hb_set_t *
|
||||
hb_subset_input_glyph_set (hb_subset_input_t *input)
|
||||
{
|
||||
return input->glyphs;
|
||||
return input->sets.glyphs;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_subset_input_nameid_set:
|
||||
* hb_subset_input_set:
|
||||
* @input: a #hb_subset_input_t object.
|
||||
* @set_type: a #hb_subset_sets_t set type.
|
||||
*
|
||||
* Gets the set of name table name IDs to retain, the caller should modify the
|
||||
* set as needed.
|
||||
* Gets the set of the specified type.
|
||||
*
|
||||
* Return value: (transfer none): pointer to the #hb_set_t of name IDs.
|
||||
* Return value: (transfer none): pointer to the #hb_set_t of the specified type.
|
||||
*
|
||||
* Since: 2.9.0
|
||||
* Since: 2.9.1
|
||||
**/
|
||||
HB_EXTERN hb_set_t *
|
||||
hb_subset_input_nameid_set (hb_subset_input_t *input)
|
||||
hb_subset_input_set (hb_subset_input_t *input, hb_subset_sets_t set_type)
|
||||
{
|
||||
return input->name_ids;
|
||||
return input->sets_iter () [set_type];
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_subset_input_namelangid_set:
|
||||
* @input: a #hb_subset_input_t object.
|
||||
*
|
||||
* Gets the set of name table language IDs to retain, the caller should modify
|
||||
* the set as needed.
|
||||
*
|
||||
* Return value: (transfer none): pointer to the #hb_set_t of language IDs.
|
||||
*
|
||||
* Since: 2.9.0
|
||||
**/
|
||||
HB_EXTERN hb_set_t *
|
||||
hb_subset_input_namelangid_set (hb_subset_input_t *input)
|
||||
{
|
||||
return input->name_languages;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hb_subset_input_layout_features_set:
|
||||
* @input: a #hb_subset_input_t object.
|
||||
*
|
||||
* Gets the set of layout feature tags to retain, the caller should modify the
|
||||
* set as needed.
|
||||
*
|
||||
* Return value: (transfer none): pointer to the #hb_set_t of feature tags.
|
||||
*
|
||||
* Since: 2.9.0
|
||||
**/
|
||||
HB_EXTERN hb_set_t *
|
||||
hb_subset_input_layout_features_set (hb_subset_input_t *input)
|
||||
{
|
||||
return input->layout_features;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_subset_input_drop_tables_set:
|
||||
* @input: a #hb_subset_input_t object.
|
||||
*
|
||||
* Gets the set of table tags to drop, the caller should modify the set as
|
||||
* needed.
|
||||
*
|
||||
* Return value: (transfer none): pointer to the #hb_set_t of table tags.
|
||||
*
|
||||
* Since: 2.9.0
|
||||
**/
|
||||
HB_EXTERN hb_set_t *
|
||||
hb_subset_input_drop_tables_set (hb_subset_input_t *input)
|
||||
{
|
||||
return input->drop_tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_subset_input_no_subset_tables_set:
|
||||
* @input: a #hb_subset_input_t object.
|
||||
*
|
||||
* Gets the set of table tags which specifies tables that should not be
|
||||
* subsetted, the caller should modify the set as needed.
|
||||
*
|
||||
* Return value: (transfer none): pointer to the #hb_set_t of table tags.
|
||||
*
|
||||
* Since: 2.9.0
|
||||
**/
|
||||
HB_EXTERN hb_set_t *
|
||||
hb_subset_input_no_subset_tables_set (hb_subset_input_t *input)
|
||||
{
|
||||
return input->no_subset_tables;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hb_subset_input_get_flags:
|
||||
* @input: a #hb_subset_input_t object.
|
||||
*
|
||||
* Gets all of the subsetting flags in the input object.
|
||||
*
|
||||
* Return value: the subsetting flags bit field.
|
||||
*
|
||||
* Since: 2.9.0
|
||||
|
|
@ -372,8 +307,8 @@ hb_subset_input_get_flags (hb_subset_input_t *input)
|
|||
* @input: a #hb_subset_input_t object.
|
||||
* @value: bit field of flags
|
||||
*
|
||||
* Set all of the flags in the input object to the values
|
||||
* specified by the bit field.
|
||||
* Sets all of the flags in the input object to the values specified by the bit
|
||||
* field.
|
||||
*
|
||||
* Since: 2.9.0
|
||||
**/
|
||||
|
|
@ -426,133 +361,3 @@ hb_subset_input_get_user_data (const hb_subset_input_t *input,
|
|||
{
|
||||
return hb_object_get_user_data (input, key);
|
||||
}
|
||||
|
||||
|
||||
static void set_flag_value (hb_subset_input_t *input, hb_subset_flags_t flag, hb_bool_t value)
|
||||
{
|
||||
hb_subset_input_set_flags (input,
|
||||
value
|
||||
? hb_subset_input_get_flags (input) | flag
|
||||
: hb_subset_input_get_flags (input) & ~flag);
|
||||
}
|
||||
|
||||
void
|
||||
hb_subset_input_set_retain_all_features (hb_subset_input_t *subset_input,
|
||||
hb_bool_t value)
|
||||
{
|
||||
return set_flag_value (subset_input,
|
||||
HB_SUBSET_FLAGS_RETAIN_ALL_FEATURES,
|
||||
value);
|
||||
}
|
||||
|
||||
hb_bool_t
|
||||
hb_subset_input_get_retain_all_features (hb_subset_input_t *subset_input)
|
||||
{
|
||||
return (bool) (hb_subset_input_get_flags (subset_input) & HB_SUBSET_FLAGS_RETAIN_ALL_FEATURES);
|
||||
}
|
||||
|
||||
void
|
||||
hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
|
||||
hb_bool_t drop_hints)
|
||||
{
|
||||
return set_flag_value (subset_input,
|
||||
HB_SUBSET_FLAGS_NO_HINTING,
|
||||
drop_hints);
|
||||
}
|
||||
|
||||
hb_bool_t
|
||||
hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input)
|
||||
{
|
||||
return (bool) (hb_subset_input_get_flags (subset_input) & HB_SUBSET_FLAGS_NO_HINTING);
|
||||
}
|
||||
|
||||
void
|
||||
hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
|
||||
hb_bool_t desubroutinize)
|
||||
{
|
||||
return set_flag_value (subset_input,
|
||||
HB_SUBSET_FLAGS_DESUBROUTINIZE,
|
||||
desubroutinize);
|
||||
}
|
||||
|
||||
hb_bool_t
|
||||
hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input)
|
||||
{
|
||||
return (bool) (hb_subset_input_get_flags (subset_input) & HB_SUBSET_FLAGS_DESUBROUTINIZE);
|
||||
}
|
||||
|
||||
void
|
||||
hb_subset_input_set_retain_gids (hb_subset_input_t *subset_input,
|
||||
hb_bool_t retain_gids)
|
||||
{
|
||||
return set_flag_value (subset_input,
|
||||
HB_SUBSET_FLAGS_RETAIN_GIDS,
|
||||
retain_gids);
|
||||
}
|
||||
|
||||
hb_bool_t
|
||||
hb_subset_input_get_retain_gids (hb_subset_input_t *subset_input)
|
||||
{
|
||||
return (bool) (hb_subset_input_get_flags (subset_input) & HB_SUBSET_FLAGS_RETAIN_GIDS);
|
||||
}
|
||||
|
||||
void
|
||||
hb_subset_input_set_name_legacy (hb_subset_input_t *subset_input,
|
||||
hb_bool_t name_legacy)
|
||||
{
|
||||
return set_flag_value (subset_input,
|
||||
HB_SUBSET_FLAGS_NAME_LEGACY,
|
||||
name_legacy);
|
||||
}
|
||||
|
||||
hb_bool_t
|
||||
hb_subset_input_get_name_legacy (hb_subset_input_t *subset_input)
|
||||
{
|
||||
return (bool) (hb_subset_input_get_flags (subset_input) & HB_SUBSET_FLAGS_NAME_LEGACY);
|
||||
}
|
||||
|
||||
void
|
||||
hb_subset_input_set_overlaps_flag (hb_subset_input_t *subset_input,
|
||||
hb_bool_t overlaps_flag)
|
||||
{
|
||||
return set_flag_value (subset_input,
|
||||
HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG,
|
||||
overlaps_flag);
|
||||
}
|
||||
|
||||
hb_bool_t
|
||||
hb_subset_input_get_overlaps_flag (hb_subset_input_t *subset_input)
|
||||
{
|
||||
return (bool) (hb_subset_input_get_flags (subset_input) & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG);
|
||||
}
|
||||
|
||||
void
|
||||
hb_subset_input_set_notdef_outline (hb_subset_input_t *subset_input,
|
||||
hb_bool_t notdef_outline)
|
||||
{
|
||||
return set_flag_value (subset_input,
|
||||
HB_SUBSET_FLAGS_NOTDEF_OUTLINE,
|
||||
notdef_outline);
|
||||
}
|
||||
|
||||
hb_bool_t
|
||||
hb_subset_input_get_notdef_outline (hb_subset_input_t *subset_input)
|
||||
{
|
||||
return (bool) (hb_subset_input_get_flags (subset_input) & HB_SUBSET_FLAGS_NOTDEF_OUTLINE);
|
||||
}
|
||||
|
||||
void
|
||||
hb_subset_input_set_no_prune_unicode_ranges (hb_subset_input_t *subset_input,
|
||||
hb_bool_t no_prune_unicode_ranges)
|
||||
{
|
||||
return set_flag_value (subset_input,
|
||||
HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES,
|
||||
no_prune_unicode_ranges);
|
||||
}
|
||||
|
||||
|
||||
hb_bool_t
|
||||
hb_subset_input_get_no_prune_unicode_ranges (hb_subset_input_t *subset_input)
|
||||
{
|
||||
return (bool) (hb_subset_input_get_flags (subset_input) & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
#include "hb.hh"
|
||||
|
||||
#include "hb-subset.h"
|
||||
#include "hb-map.hh"
|
||||
#include "hb-set.hh"
|
||||
|
||||
#include "hb-font.hh"
|
||||
|
||||
|
|
@ -40,23 +42,40 @@ struct hb_subset_input_t
|
|||
{
|
||||
hb_object_header_t header;
|
||||
|
||||
hb_set_t *unicodes;
|
||||
hb_set_t *glyphs;
|
||||
hb_set_t *name_ids;
|
||||
hb_set_t *name_languages;
|
||||
hb_set_t *no_subset_tables;
|
||||
hb_set_t *drop_tables;
|
||||
hb_set_t *layout_features;
|
||||
union {
|
||||
struct {
|
||||
hb_set_t *glyphs;
|
||||
hb_set_t *unicodes;
|
||||
hb_set_t *no_subset_tables;
|
||||
hb_set_t *drop_tables;
|
||||
hb_set_t *name_ids;
|
||||
hb_set_t *name_languages;
|
||||
hb_set_t *layout_features;
|
||||
} sets;
|
||||
hb_set_t* set_ptrs[sizeof (sets) / sizeof (hb_set_t*)];
|
||||
};
|
||||
|
||||
unsigned flags;
|
||||
|
||||
/* TODO
|
||||
*
|
||||
* features
|
||||
* lookups
|
||||
* name_ids
|
||||
* ...
|
||||
*/
|
||||
inline unsigned num_sets () const
|
||||
{
|
||||
return sizeof (set_ptrs) / sizeof (hb_set_t*);
|
||||
}
|
||||
|
||||
inline hb_array_t<hb_set_t*> sets_iter ()
|
||||
{
|
||||
return hb_array_t<hb_set_t*> (set_ptrs, num_sets ());
|
||||
}
|
||||
|
||||
bool in_error () const
|
||||
{
|
||||
for (unsigned i = 0; i < num_sets (); i++)
|
||||
{
|
||||
if (unlikely (set_ptrs[i]->in_error ()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -87,43 +87,49 @@ _remap_indexes (const hb_set_t *indexes,
|
|||
#ifndef HB_NO_SUBSET_LAYOUT
|
||||
typedef void (*layout_collect_func_t) (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *scripts, const hb_tag_t *languages, const hb_tag_t *features, hb_set_t *lookup_indexes /* OUT */);
|
||||
|
||||
static void _collect_subset_layout (hb_face_t *face,
|
||||
hb_tag_t table_tag,
|
||||
const hb_set_t *layout_features_to_retain,
|
||||
bool retain_all_features,
|
||||
layout_collect_func_t layout_collect_func,
|
||||
hb_set_t *lookup_indices /* OUT */)
|
||||
|
||||
template <typename T>
|
||||
static void _collect_layout_indices (hb_face_t *face,
|
||||
const T& table,
|
||||
const hb_set_t *layout_features_to_retain,
|
||||
layout_collect_func_t layout_collect_func,
|
||||
hb_set_t *indices /* OUT */)
|
||||
{
|
||||
if (retain_all_features)
|
||||
hb_vector_t<hb_tag_t> features;
|
||||
if (!features.alloc (table.get_feature_count () + 1))
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < table.get_feature_count (); i++)
|
||||
{
|
||||
hb_tag_t tag = table.get_feature_tag (i);
|
||||
if (tag && layout_features_to_retain->has (tag))
|
||||
features.push (tag);
|
||||
}
|
||||
|
||||
if (!features)
|
||||
return;
|
||||
|
||||
// The collect function needs a null element to signal end of the array.
|
||||
features.push (0);
|
||||
|
||||
if (features.get_size () == table.get_feature_count () + 1)
|
||||
{
|
||||
// Looking for all features, trigger the faster collection method.
|
||||
layout_collect_func (face,
|
||||
table_tag,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
lookup_indices);
|
||||
T::tableTag,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
indices);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hb_set_is_empty (layout_features_to_retain)) return;
|
||||
unsigned num = layout_features_to_retain->get_population () + 1;
|
||||
hb_tag_t *features = (hb_tag_t *) hb_malloc (num * sizeof (hb_tag_t));
|
||||
if (!features) return;
|
||||
|
||||
unsigned i = 0;
|
||||
for (hb_tag_t f : layout_features_to_retain->iter ())
|
||||
features[i++] = f;
|
||||
|
||||
features[i] = 0;
|
||||
|
||||
layout_collect_func (face,
|
||||
table_tag,
|
||||
T::tableTag,
|
||||
nullptr,
|
||||
nullptr,
|
||||
features,
|
||||
lookup_indices);
|
||||
|
||||
hb_free (features);
|
||||
features.arrayZ,
|
||||
indices);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
@ -131,7 +137,6 @@ static inline void
|
|||
_closure_glyphs_lookups_features (hb_face_t *face,
|
||||
hb_set_t *gids_to_retain,
|
||||
const hb_set_t *layout_features_to_retain,
|
||||
bool retain_all_features,
|
||||
hb_map_t *lookups,
|
||||
hb_map_t *features,
|
||||
script_langsys_map *langsys_map)
|
||||
|
|
@ -139,12 +144,11 @@ _closure_glyphs_lookups_features (hb_face_t *face,
|
|||
hb_blob_ptr_t<T> table = hb_sanitize_context_t ().reference_table<T> (face);
|
||||
hb_tag_t table_tag = table->tableTag;
|
||||
hb_set_t lookup_indices;
|
||||
_collect_subset_layout (face,
|
||||
table_tag,
|
||||
layout_features_to_retain,
|
||||
retain_all_features,
|
||||
hb_ot_layout_collect_lookups,
|
||||
&lookup_indices);
|
||||
_collect_layout_indices<T> (face,
|
||||
*table,
|
||||
layout_features_to_retain,
|
||||
hb_ot_layout_collect_lookups,
|
||||
&lookup_indices);
|
||||
|
||||
if (table_tag == HB_OT_TAG_GSUB)
|
||||
hb_ot_layout_lookups_substitute_closure (face,
|
||||
|
|
@ -157,12 +161,11 @@ _closure_glyphs_lookups_features (hb_face_t *face,
|
|||
|
||||
// Collect and prune features
|
||||
hb_set_t feature_indices;
|
||||
_collect_subset_layout (face,
|
||||
table_tag,
|
||||
layout_features_to_retain,
|
||||
retain_all_features,
|
||||
hb_ot_layout_collect_features,
|
||||
&feature_indices);
|
||||
_collect_layout_indices<T> (face,
|
||||
*table,
|
||||
layout_features_to_retain,
|
||||
hb_ot_layout_collect_features,
|
||||
&feature_indices);
|
||||
|
||||
table->prune_features (lookups, &feature_indices);
|
||||
hb_map_t duplicate_feature_map;
|
||||
|
|
@ -238,41 +241,58 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
|
|||
OT::cmap::accelerator_t cmap;
|
||||
cmap.init (plan->source);
|
||||
|
||||
for (hb_codepoint_t cp : *unicodes)
|
||||
constexpr static const int size_threshold = 4096;
|
||||
|
||||
if (glyphs->is_empty () && unicodes->get_population () < size_threshold)
|
||||
{
|
||||
hb_codepoint_t gid;
|
||||
if (!cmap.get_nominal_glyph (cp, &gid))
|
||||
/* This is the fast path if it's anticipated that size of unicodes
|
||||
* is << than the number of codepoints in the font. */
|
||||
for (hb_codepoint_t cp : *unicodes)
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
|
||||
continue;
|
||||
hb_codepoint_t gid;
|
||||
if (!cmap.get_nominal_glyph (cp, &gid))
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
|
||||
continue;
|
||||
}
|
||||
|
||||
plan->codepoint_to_glyph->set (cp, gid);
|
||||
}
|
||||
plan->unicodes->add (cp);
|
||||
plan->codepoint_to_glyph->set (cp, gid);
|
||||
plan->_glyphset_gsub->add (gid);
|
||||
}
|
||||
|
||||
if (glyphs->is_empty ())
|
||||
else
|
||||
{
|
||||
cmap.fini ();
|
||||
return;
|
||||
hb_map_t unicode_glyphid_map;
|
||||
cmap.collect_mapping (hb_set_get_empty (), &unicode_glyphid_map);
|
||||
|
||||
for (hb_pair_t<hb_codepoint_t, hb_codepoint_t> cp_gid :
|
||||
+ unicode_glyphid_map.iter ())
|
||||
{
|
||||
if (!unicodes->has (cp_gid.first) && !glyphs->has (cp_gid.second))
|
||||
continue;
|
||||
|
||||
plan->codepoint_to_glyph->set (cp_gid.first, cp_gid.second);
|
||||
}
|
||||
|
||||
/* Add gids which where requested, but not mapped in cmap */
|
||||
// TODO(garretrieger):
|
||||
// Once https://github.com/harfbuzz/harfbuzz/issues/3169
|
||||
// is implemented, this can be done with union and del_range
|
||||
for (hb_codepoint_t gid : glyphs->iter ())
|
||||
{
|
||||
if (gid >= plan->source->get_num_glyphs ())
|
||||
break;
|
||||
plan->_glyphset_gsub->add (gid);
|
||||
}
|
||||
}
|
||||
|
||||
hb_map_t unicode_glyphid_map;
|
||||
cmap.collect_mapping (hb_set_get_empty (), &unicode_glyphid_map);
|
||||
+ plan->codepoint_to_glyph->keys () | hb_sink (plan->unicodes);
|
||||
+ plan->codepoint_to_glyph->values () | hb_sink (plan->_glyphset_gsub);
|
||||
|
||||
cmap.fini ();
|
||||
|
||||
for (hb_pair_t<hb_codepoint_t, hb_codepoint_t> cp_gid :
|
||||
+ unicode_glyphid_map.iter () | hb_filter (glyphs, hb_second))
|
||||
{
|
||||
plan->unicodes->add (cp_gid.first);
|
||||
plan->codepoint_to_glyph->set (cp_gid.first, cp_gid.second);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||
const hb_set_t *unicodes,
|
||||
const hb_set_t *input_glyphs_to_retain,
|
||||
bool close_over_gsub,
|
||||
bool close_over_gpos,
|
||||
bool close_over_gdef)
|
||||
|
|
@ -289,7 +309,6 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
|||
colr.init (plan->source);
|
||||
|
||||
plan->_glyphset_gsub->add (0); // Not-def
|
||||
hb_set_union (plan->_glyphset_gsub, input_glyphs_to_retain);
|
||||
|
||||
_cmap_closure (plan->source, plan->unicodes, plan->_glyphset_gsub);
|
||||
|
||||
|
|
@ -300,7 +319,6 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
|||
plan->source,
|
||||
plan->_glyphset_gsub,
|
||||
plan->layout_features,
|
||||
plan->flags & HB_SUBSET_FLAGS_RETAIN_ALL_FEATURES,
|
||||
plan->gsub_lookups,
|
||||
plan->gsub_features,
|
||||
plan->gsub_langsys);
|
||||
|
|
@ -310,7 +328,6 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
|||
plan->source,
|
||||
plan->_glyphset_gsub,
|
||||
plan->layout_features,
|
||||
plan->flags & HB_SUBSET_FLAGS_RETAIN_ALL_FEATURES,
|
||||
plan->gpos_lookups,
|
||||
plan->gpos_features,
|
||||
plan->gpos_langsys);
|
||||
|
|
@ -439,13 +456,13 @@ hb_subset_plan_create (hb_face_t *face,
|
|||
plan->successful = true;
|
||||
plan->flags = input->flags;
|
||||
plan->unicodes = hb_set_create ();
|
||||
plan->name_ids = hb_set_copy (input->name_ids);
|
||||
plan->name_ids = hb_set_copy (input->sets.name_ids);
|
||||
_nameid_closure (face, plan->name_ids);
|
||||
plan->name_languages = hb_set_copy (input->name_languages);
|
||||
plan->layout_features = hb_set_copy (input->layout_features);
|
||||
plan->glyphs_requested = hb_set_copy (input->glyphs);
|
||||
plan->drop_tables = hb_set_copy (input->drop_tables);
|
||||
plan->no_subset_tables = hb_set_copy (input->no_subset_tables);
|
||||
plan->name_languages = hb_set_copy (input->sets.name_languages);
|
||||
plan->layout_features = hb_set_copy (input->sets.layout_features);
|
||||
plan->glyphs_requested = hb_set_copy (input->sets.glyphs);
|
||||
plan->drop_tables = hb_set_copy (input->sets.drop_tables);
|
||||
plan->no_subset_tables = hb_set_copy (input->sets.no_subset_tables);
|
||||
plan->source = hb_face_reference (face);
|
||||
plan->dest = hb_face_builder_create ();
|
||||
|
||||
|
|
@ -473,14 +490,12 @@ hb_subset_plan_create (hb_face_t *face,
|
|||
return plan;
|
||||
}
|
||||
|
||||
_populate_unicodes_to_retain (input->unicodes, input->glyphs, plan);
|
||||
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan);
|
||||
|
||||
_populate_gids_to_retain (plan,
|
||||
input->unicodes,
|
||||
input->glyphs,
|
||||
!input->drop_tables->has (HB_OT_TAG_GSUB),
|
||||
!input->drop_tables->has (HB_OT_TAG_GPOS),
|
||||
!input->drop_tables->has (HB_OT_TAG_GDEF));
|
||||
!input->sets.drop_tables->has (HB_OT_TAG_GSUB),
|
||||
!input->sets.drop_tables->has (HB_OT_TAG_GPOS),
|
||||
!input->sets.drop_tables->has (HB_OT_TAG_GDEF));
|
||||
|
||||
_create_old_gid_to_new_gid_map (face,
|
||||
input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS,
|
||||
|
|
|
|||
|
|
@ -330,14 +330,6 @@ _subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
|
|||
}
|
||||
}
|
||||
|
||||
hb_face_t *
|
||||
hb_subset (hb_face_t *source, hb_subset_input_t *input)
|
||||
{
|
||||
hb_face_t* face = hb_subset_or_fail (source, input);
|
||||
if (face) return face;
|
||||
return hb_face_get_empty ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_subset_or_fail:
|
||||
* @source: font face data to be subset.
|
||||
|
|
|
|||
|
|
@ -61,10 +61,6 @@ typedef struct hb_subset_input_t hb_subset_input_t;
|
|||
* in the final subset.
|
||||
* @HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in
|
||||
* OS/2 will not be recalculated.
|
||||
* @HB_SUBSET_FLAGS_RETAIN_ALL_FEATURES: If set all layout features will be
|
||||
* retained. If unset then the set accessed by
|
||||
* hb_subset_input_layout_features_set() will be used to determine the features
|
||||
* to be retained.
|
||||
*
|
||||
* List of boolean properties that can be configured on the subset input.
|
||||
*
|
||||
|
|
@ -81,9 +77,35 @@ typedef enum { /*< flags >*/
|
|||
HB_SUBSET_FLAGS_NOTDEF_OUTLINE = 0x00000040u,
|
||||
HB_SUBSET_FLAGS_GLYPH_NAMES = 0x00000080u,
|
||||
HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES = 0x00000100u,
|
||||
HB_SUBSET_FLAGS_RETAIN_ALL_FEATURES = 0x00000200u,
|
||||
} hb_subset_flags_t;
|
||||
|
||||
/**
|
||||
* hb_subset_sets_t:
|
||||
* @HB_SUBSET_SETS_GLYPH_INDEX: the set of glyph indexes to retain in the subset.
|
||||
* @HB_SUBSET_SETS_UNICODE: the set of unicode codepoints to retain in the subset.
|
||||
* @HB_SUBSET_SETS_NO_SUBSET_TABLE_TAG: the set of table tags which specifies tables that should not be
|
||||
* subsetted.
|
||||
* @HB_SUBSET_SETS_DROP_TABLE_TAG: the set of table tags which specifies tables which will be dropped
|
||||
* in the subset.
|
||||
* @HB_SUBSET_SETS_NAME_ID: the set of name ids that will be retained.
|
||||
* @HB_SUBSET_SETS_NAME_LANG_ID: the set of name lang ids that will be retained.
|
||||
* @HB_SUBSET_SETS_LAYOUT_FEATURE_TAG: the set of layout feature tags that will be retained
|
||||
* in the subset.
|
||||
*
|
||||
* List of sets that can be configured on the subset input.
|
||||
*
|
||||
* Since: 2.9.1
|
||||
**/
|
||||
typedef enum {
|
||||
HB_SUBSET_SETS_GLYPH_INDEX = 0,
|
||||
HB_SUBSET_SETS_UNICODE,
|
||||
HB_SUBSET_SETS_NO_SUBSET_TABLE_TAG,
|
||||
HB_SUBSET_SETS_DROP_TABLE_TAG,
|
||||
HB_SUBSET_SETS_NAME_ID,
|
||||
HB_SUBSET_SETS_NAME_LANG_ID,
|
||||
HB_SUBSET_SETS_LAYOUT_FEATURE_TAG,
|
||||
} hb_subset_sets_t;
|
||||
|
||||
HB_EXTERN hb_subset_input_t *
|
||||
hb_subset_input_create_or_fail (void);
|
||||
|
||||
|
|
@ -111,19 +133,7 @@ HB_EXTERN hb_set_t *
|
|||
hb_subset_input_glyph_set (hb_subset_input_t *input);
|
||||
|
||||
HB_EXTERN hb_set_t *
|
||||
hb_subset_input_nameid_set (hb_subset_input_t *input);
|
||||
|
||||
HB_EXTERN hb_set_t *
|
||||
hb_subset_input_namelangid_set (hb_subset_input_t *input);
|
||||
|
||||
HB_EXTERN hb_set_t *
|
||||
hb_subset_input_layout_features_set (hb_subset_input_t *input);
|
||||
|
||||
HB_EXTERN hb_set_t *
|
||||
hb_subset_input_no_subset_tables_set (hb_subset_input_t *input);
|
||||
|
||||
HB_EXTERN hb_set_t *
|
||||
hb_subset_input_drop_tables_set (hb_subset_input_t *input);
|
||||
hb_subset_input_set (hb_subset_input_t *input, hb_subset_sets_t set_type);
|
||||
|
||||
HB_EXTERN hb_subset_flags_t
|
||||
hb_subset_input_get_flags (hb_subset_input_t *input);
|
||||
|
|
@ -135,67 +145,6 @@ hb_subset_input_set_flags (hb_subset_input_t *input,
|
|||
HB_EXTERN hb_face_t *
|
||||
hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input);
|
||||
|
||||
|
||||
/*
|
||||
* ### Legacy API ###
|
||||
* The methods below are part of the legacy harfbuzz subsetting API and will be
|
||||
* Removed as of version 3.0.0
|
||||
*/
|
||||
|
||||
HB_EXTERN void
|
||||
hb_subset_input_set_retain_all_features (hb_subset_input_t *subset_input,
|
||||
hb_bool_t value);
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_get_retain_all_features (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);
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
|
||||
hb_bool_t desubroutinize);
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_subset_input_set_retain_gids (hb_subset_input_t *subset_input,
|
||||
hb_bool_t retain_gids);
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_get_retain_gids (hb_subset_input_t *subset_input);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_subset_input_set_name_legacy (hb_subset_input_t *subset_input,
|
||||
hb_bool_t name_legacy);
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_get_name_legacy (hb_subset_input_t *subset_input);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_subset_input_set_overlaps_flag (hb_subset_input_t *subset_input,
|
||||
hb_bool_t overlaps_flag);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_get_overlaps_flag (hb_subset_input_t *subset_input);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_subset_input_set_notdef_outline (hb_subset_input_t *subset_input,
|
||||
hb_bool_t notdef_outline);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_get_notdef_outline (hb_subset_input_t *subset_input);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_subset_input_set_no_prune_unicode_ranges (hb_subset_input_t *subset_input,
|
||||
hb_bool_t no_prune_unicode_ranges);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_get_no_prune_unicode_ranges (hb_subset_input_t *subset_input);
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_subset (hb_face_t *source, hb_subset_input_t *input);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_SUBSET_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -203,9 +203,7 @@ hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
|||
}
|
||||
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_ucd_funcs ();
|
||||
#endif
|
||||
|
||||
static struct hb_ucd_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_ucd_unicode_funcs_lazy_loader_t>
|
||||
{
|
||||
|
|
@ -222,21 +220,17 @@ static struct hb_ucd_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_
|
|||
|
||||
hb_unicode_funcs_make_immutable (funcs);
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_ucd_funcs);
|
||||
#endif
|
||||
hb_atexit (free_static_ucd_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_ucd_funcs;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_ucd_funcs ()
|
||||
{
|
||||
static_ucd_funcs.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
hb_unicode_funcs_t *
|
||||
hb_ucd_get_unicode_funcs ()
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@
|
|||
*
|
||||
* on file with this header:
|
||||
*
|
||||
* # emoji-data.txt
|
||||
* # Date: 2020-01-28, 20:52:38 GMT
|
||||
* # © 2020 Unicode®, Inc.
|
||||
* # emoji-data-14.0.0.txt
|
||||
* # Date: 2021-08-26, 17:22:22 GMT
|
||||
* # © 2021 Unicode®, Inc.
|
||||
* # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
|
||||
* # For terms of use, see http://www.unicode.org/terms_of_use.html
|
||||
* #
|
||||
* # Emoji Data for UTS #51
|
||||
* # Version: 13.0
|
||||
* # Used with Emoji Version 14.0 and subsequent minor revisions (if any)
|
||||
* #
|
||||
* # For documentation and usage, see http://www.unicode.org/reports/tr51
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -239,9 +239,7 @@ struct hb_uniscribe_shaper_funcs_t
|
|||
}
|
||||
};
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_uniscribe_shaper_funcs ();
|
||||
#endif
|
||||
static inline void free_static_uniscribe_shaper_funcs ();
|
||||
|
||||
static struct hb_uniscribe_shaper_funcs_lazy_loader_t : hb_lazy_loader_t<hb_uniscribe_shaper_funcs_t,
|
||||
hb_uniscribe_shaper_funcs_lazy_loader_t>
|
||||
|
|
@ -254,9 +252,7 @@ static struct hb_uniscribe_shaper_funcs_lazy_loader_t : hb_lazy_loader_t<hb_unis
|
|||
|
||||
funcs->init ();
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_uniscribe_shaper_funcs);
|
||||
#endif
|
||||
hb_atexit (free_static_uniscribe_shaper_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
|
|
@ -270,13 +266,11 @@ static struct hb_uniscribe_shaper_funcs_lazy_loader_t : hb_lazy_loader_t<hb_unis
|
|||
}
|
||||
} static_uniscribe_shaper_funcs;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_uniscribe_shaper_funcs ()
|
||||
{
|
||||
static_uniscribe_shaper_funcs.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
static hb_uniscribe_shaper_funcs_t *
|
||||
hb_uniscribe_shaper_get_funcs ()
|
||||
|
|
|
|||
|
|
@ -41,13 +41,13 @@ HB_BEGIN_DECLS
|
|||
*
|
||||
* The major component of the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_MAJOR 2
|
||||
#define HB_VERSION_MAJOR 3
|
||||
/**
|
||||
* HB_VERSION_MINOR:
|
||||
*
|
||||
* The minor component of the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_MINOR 9
|
||||
#define HB_VERSION_MINOR 0
|
||||
/**
|
||||
* HB_VERSION_MICRO:
|
||||
*
|
||||
|
|
@ -60,7 +60,7 @@ HB_BEGIN_DECLS
|
|||
*
|
||||
* A string literal containing the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_STRING "2.9.0"
|
||||
#define HB_VERSION_STRING "3.0.0"
|
||||
|
||||
/**
|
||||
* HB_VERSION_ATLEAST:
|
||||
|
|
|
|||
|
|
@ -182,6 +182,9 @@
|
|||
#include <cassert>
|
||||
#include <cfloat>
|
||||
#include <climits>
|
||||
#ifdef _MSC_VER
|
||||
# define _USE_MATH_DEFINES
|
||||
#endif
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
|
|
@ -405,6 +408,9 @@ static int HB_UNUSED _hb_errno = 0;
|
|||
# define errno _hb_errno
|
||||
#endif
|
||||
|
||||
#define HB_STMT_START do
|
||||
#define HB_STMT_END while (0)
|
||||
|
||||
#if defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT)
|
||||
/* atexit() is only safe to be called from shared libraries on certain
|
||||
* platforms. Whitelist.
|
||||
|
|
@ -433,16 +439,23 @@ static int HB_UNUSED _hb_errno = 0;
|
|||
*/
|
||||
# define HB_USE_ATEXIT 1
|
||||
# endif
|
||||
#endif
|
||||
#endif /* defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT) */
|
||||
#ifdef HB_NO_ATEXIT
|
||||
# undef HB_USE_ATEXIT
|
||||
#endif
|
||||
#ifndef HB_USE_ATEXIT
|
||||
# define HB_USE_ATEXIT 0
|
||||
#endif
|
||||
|
||||
#define HB_STMT_START do
|
||||
#define HB_STMT_END while (0)
|
||||
#if !HB_USE_ATEXIT
|
||||
# define hb_atexit(_) HB_STMT_START { if (0) (_) (); } HB_STMT_END
|
||||
#else /* HB_USE_ATEXIT */
|
||||
# ifdef HAVE_ATEXIT
|
||||
# define hb_atexit atexit
|
||||
# else
|
||||
template <void (*function) (void)> struct hb_atexit_t { ~hb_atexit_t () { function (); } };
|
||||
# define hb_atexit(f) static hb_atexit_t<f> _hb_atexit_##__LINE__;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Lets assert int types. Saves trouble down the road. */
|
||||
static_assert ((sizeof (hb_codepoint_t) == 4), "");
|
||||
|
|
|
|||
Loading…
Reference in New Issue