Merge branch 'master' into cff-subset

This commit is contained in:
Michiharu Ariza 2018-08-02 11:39:22 -07:00
commit e2fd49e477
223 changed files with 831 additions and 1024 deletions

8
NEWS
View File

@ -1,3 +1,11 @@
Overview of changes leading to 1.8.5
Wednesday, August 1, 2018
====================================
- Major Khmer shaper improvements to better match Microsoft.
- Indic bug fixes.
- Internal improvements to atomic operations.
Overview of changes leading to 1.8.4
Tuesday, July 17, 2018
====================================

View File

@ -44,6 +44,7 @@ build_script:
- 'if "%compiler%"=="msvc" msbuild harfbuzz.sln /p:Configuration=%configuration% /p:Platform=%platform%'
- 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" ctest --output-on-failure -C %configuration%'
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syyu mingw-w64-$MSYS2_ARCH-gcc"'
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S --needed mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config,python2}"'
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "curl https://raw.githubusercontent.com/mirror/mingw-w64/023eb04c396d4e8d8fcf604cfababc53dae13398/mingw-w64-headers/include/dwrite_1.h > %MINGW_PREFIX%/%MINGW_CHOST%/include/dwrite_1.h"'
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make; make check || .ci/fail.sh"'

View File

@ -1,6 +1,6 @@
AC_PREREQ([2.64])
AC_INIT([HarfBuzz],
[1.8.4],
[1.8.5],
[https://github.com/harfbuzz/harfbuzz/issues/new],
[harfbuzz],
[http://harfbuzz.org/])

View File

@ -327,6 +327,7 @@ HB_GOBJECT_TYPE_FACE
HB_GOBJECT_TYPE_FONT
HB_GOBJECT_TYPE_FONT_FUNCS
HB_GOBJECT_TYPE_GLYPH_FLAGS
HB_GOBJECT_TYPE_MAP
HB_GOBJECT_TYPE_MEMORY_MODE
HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS
HB_GOBJECT_TYPE_OT_MATH_CONSTANT
@ -358,6 +359,7 @@ hb_gobject_face_get_type
hb_gobject_font_funcs_get_type
hb_gobject_font_get_type
hb_gobject_glyph_flags_get_type
hb_gobject_map_get_type
hb_gobject_memory_mode_get_type
hb_gobject_ot_layout_glyph_class_get_type
hb_gobject_ot_math_constant_get_type
@ -447,10 +449,10 @@ HB_OT_TAG_GPOS
HB_OT_TAG_GSUB
HB_OT_TAG_JSTF
hb_ot_layout_collect_lookups
hb_ot_layout_collect_features
hb_ot_layout_feature_get_lookups
hb_ot_layout_feature_with_variations_get_lookups
hb_ot_layout_get_attach_points
hb_ot_layout_get_feature_name_ids
hb_ot_layout_get_glyph_class
hb_ot_layout_get_glyphs_in_class
hb_ot_layout_get_ligature_carets

View File

@ -233,10 +233,10 @@ int main (int argc, char **argv)
svg.dump (svg_callback);
svg.fini ();
hb_blob_t* colr_blob = OT::hb_sanitize_context_t().reference_table<OT::COLR> (face);
hb_blob_t* colr_blob = hb_sanitize_context_t ().reference_table<OT::COLR> (face);
const OT::COLR *colr = colr_blob->as<OT::COLR> ();
hb_blob_t* cpal_blob = OT::hb_sanitize_context_t().reference_table<OT::CPAL> (face);
hb_blob_t* cpal_blob = hb_sanitize_context_t ().reference_table<OT::CPAL> (face);
const OT::CPAL *cpal = cpal_blob->as<OT::CPAL> ();
cairo_font_face_t *cairo_face;

View File

@ -61,7 +61,7 @@ _get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
// static inline void
// _hb_aat_layout_create (hb_face_t *face)
// {
// hb_blob_t *morx_blob = OT::hb_sanitize_context_t().reference_table<AAT::morx> (face);
// hb_blob_t *morx_blob = hb_sanitize_context_t ().reference_table<AAT::morx> (face);
// morx_blob->as<AAT::morx> ();
// if (0)

View File

@ -46,21 +46,23 @@
/* Defined externally, i.e. in config.h; must have typedef'ed hb_atomic_int_impl_t as well. */
#elif !defined(HB_NO_MT) && defined(__ATOMIC_ACQUIRE)
#elif !defined(HB_NO_MT) && defined(__ATOMIC_CONSUME)
/* C++11-style GCC primitives. */
typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) __atomic_fetch_add (&(AI), (V), __ATOMIC_ACQ_REL)
#define hb_atomic_int_impl_add(AI, V) __atomic_fetch_add ((AI), (V), __ATOMIC_ACQ_REL)
#define hb_atomic_int_impl_set_relaxed(AI, V) __atomic_store_n ((AI), (V), __ATOMIC_RELAXED)
#define hb_atomic_int_impl_get_relaxed(AI) __atomic_load_n ((AI), __ATOMIC_RELAXED)
#define hb_atomic_ptr_impl_get(P) __atomic_load_n ((P), __ATOMIC_ACQUIRE)
#define hb_atomic_ptr_impl_get(P) __atomic_load_n ((P), __ATOMIC_CONSUME)
static inline bool
_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
{
const void *O = O_; // Need lvalue
return __atomic_compare_exchange_n ((void **) P, (void **) &O, (void *) N, true, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
}
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (_hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N)))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
#elif !defined(HB_NO_MT) && __cplusplus >= 201103L
@ -69,47 +71,49 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
#include <atomic>
typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast<std::atomic<int> *> (&AI)->fetch_add ((V), std::memory_order_acq_rel))
#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast<std::atomic<int> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast<std::atomic<int> *> (AI)->store ((V), std::memory_order_relaxed))
#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast<std::atomic<int> *> (AI)->load (std::memory_order_relaxed))
#define hb_atomic_ptr_impl_get(P) (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_acquire))
#define hb_atomic_ptr_impl_get(P) (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_consume))
static inline bool
_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
{
const void *O = O_; // Need lvalue
return reinterpret_cast<std::atomic<const void*> *> (P)->compare_exchange_weak (O, N, std::memory_order_acq_rel, std::memory_order_relaxed);
}
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (_hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N)))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
#include <windows.h>
/* MinGW has a convoluted history of supporting MemoryBarrier
* properly. As such, define a function to wrap the whole
* thing. */
static inline void _HBMemoryBarrier (void) {
static inline void _hb_memory_barrier (void)
{
#if !defined(MemoryBarrier)
/* MinGW has a convoluted history of supporting MemoryBarrier. */
long dummy = 0;
InterlockedExchange (&dummy, 1);
#else
MemoryBarrier ();
#endif
}
#define _hb_memory_barrier() _hb_memory_barrier ()
typedef LONG hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd (&(AI), (V))
#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd ((AI), (V))
#define hb_atomic_ptr_impl_get(P) (_HBMemoryBarrier (), (void *) *(P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add (&(AI), (V))
#define _hb_memory_barrier() __sync_synchronize ()
typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add ((AI), (V))
#define hb_atomic_ptr_impl_get(P) (void *) (__sync_synchronize (), *(P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N))
@ -118,11 +122,30 @@ typedef int hb_atomic_int_impl_t;
#include <atomic.h>
#include <mbarrier.h>
typedef unsigned int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V))
#define _hb_memory_r_barrier() __machine_r_barrier ()
#define _hb_memory_w_barrier() __machine_w_barrier ()
#define _hb_memory_barrier() __machine_rw_barrier ()
#define hb_atomic_ptr_impl_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false)
typedef unsigned int hb_atomic_int_impl_t;
static inline int _hb_fetch_and_add (hb_atomic_int_impl_t *AI, int V)
{
_hb_memory_w_barrier ();
int result = atomic_add_int_nv (AI, V);
_hb_memory_r_barrier ();
return result;
}
static inline bool _hb_compare_and_swap_ptr (const void **P, const void *O, const void *N)
{
_hb_memory_w_barrier ();
int result = atomic_cas_ptr ((void **) P, (void *) O, (void *) N) == (void *) O;
_hb_memory_r_barrier ();
return result;
}
#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swap_ptr ((const void **) (P), (O), (N))
#elif !defined(HB_NO_MT) && defined(__APPLE__)
@ -134,11 +157,11 @@ typedef unsigned int hb_atomic_int_impl_t;
#include <Availability.h>
#endif
#define _hb_memory_barrier() OSMemoryBarrier ()
typedef int32_t hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), (AI)) - (V))
#define hb_atomic_ptr_impl_get(P) (OSMemoryBarrier (), (void *) *(P))
#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
#else
@ -154,65 +177,88 @@ typedef int32_t hb_atomic_int_impl_t;
#include <builtins.h>
static inline int _hb_fetch_and_add(volatile int* AI, unsigned int V) {
__lwsync();
int result = __fetch_and_add(AI, V);
__isync();
return result;
}
static inline int _hb_compare_and_swaplp(volatile long* P, long O, long N) {
__sync();
int result = __compare_and_swaplp (P, &O, N);
__sync();
return result;
}
#define _hb_memory_barrier() __lwsync ()
typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add (&(AI), (V))
#define hb_atomic_ptr_impl_get(P) (__sync(), (void *) *(P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N))
static inline int _hb_fetch_and_add (hb_atomic_int_impl_t *AI, int V)
{
_hb_memory_barrier ();
int result = __fetch_and_add (AI, V);
_hb_memory_barrier ();
return result;
}
static inline bool _hb_compare_and_swaplp (long *P, long O, long N)
{
_hb_memory_barrier ();
bool result = __compare_and_swaplp (P, &O, N);
_hb_memory_barrier ();
return result;
}
#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long *) (P), (long) (O), (long) (N))
static_assert ((sizeof (long) == sizeof (void *)), "");
#elif !defined(HB_NO_MT)
#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
typedef volatile int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V))
#define _hb_memory_barrier()
typedef volatile int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
#define hb_atomic_ptr_impl_get(P) ((void *) *(P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false)
#else /* HB_NO_MT */
typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V))
#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
#define _hb_memory_barrier()
#define hb_atomic_ptr_impl_get(P) ((void *) *(P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
#endif
#ifndef _hb_memory_r_barrier
#define _hb_memory_r_barrier() _hb_memory_barrier ()
#endif
#ifndef _hb_memory_w_barrier
#define _hb_memory_w_barrier() _hb_memory_barrier ()
#endif
#ifndef HB_ATOMIC_INT_INIT
#define HB_ATOMIC_INT_INIT(V) {V}
#endif
#ifndef hb_atomic_int_impl_set_relaxed
#define hb_atomic_int_impl_set_relaxed(AI, V) (*(AI) = (V))
#endif
#ifndef hb_atomic_int_impl_get_relaxed
#define hb_atomic_int_impl_get_relaxed(AI) (*(AI))
#endif
#ifndef hb_atomic_ptr_impl_get
inline void *hb_atomic_ptr_impl_get (void **P) { void *v = *P; _hb_memory_r_barrier (); return v; }
#endif
struct hb_atomic_int_t
{
mutable hb_atomic_int_impl_t v;
inline void set_unsafe (int v_) { v = v_; }
inline int get_unsafe (void) const { return v; }
inline int inc (void) { return hb_atomic_int_impl_add (v, 1); }
inline int dec (void) { return hb_atomic_int_impl_add (v, -1); }
inline void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
inline int get_relaxed (void) const { return hb_atomic_int_impl_get_relaxed (&v); }
inline int inc (void) { return hb_atomic_int_impl_add (&v, 1); }
inline int dec (void) { return hb_atomic_int_impl_add (&v, -1); }
};
#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get(P)
#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get((void **) P)
#define hb_atomic_ptr_cmpexch(P,O,N) hb_atomic_ptr_impl_cmpexch((P),(O),(N))

View File

@ -57,11 +57,6 @@ struct hb_blob_t
HB_INTERNAL bool try_make_writable_inplace (void);
HB_INTERNAL bool try_make_writable_inplace_unix (void);
inline void lock (void)
{
hb_blob_make_immutable (this);
}
template <typename Type>
inline const Type* as (void) const
{

View File

@ -37,7 +37,7 @@
/* hb_options_t */
hb_options_union_t _hb_options;
hb_atomic_int_t _hb_options;
void
_hb_options_init (void)
@ -50,7 +50,7 @@ _hb_options_init (void)
u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible");
/* This is idempotent and threadsafe. */
_hb_options = u;
_hb_options.set_relaxed (u.i);
}

View File

@ -269,7 +269,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
return ct_font;
}
hb_coretext_shaper_face_data_t *
hb_coretext_face_data_t *
_hb_coretext_shaper_face_data_create (hb_face_t *face)
{
CGFontRef cg_font = create_cg_font (face);
@ -280,11 +280,11 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face)
return nullptr;
}
return (hb_coretext_shaper_face_data_t *) cg_font;
return (hb_coretext_face_data_t *) cg_font;
}
void
_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
_hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data)
{
CFRelease ((CGFontRef) data);
}
@ -306,7 +306,7 @@ hb_coretext_face_get_cg_font (hb_face_t *face)
}
hb_coretext_shaper_font_data_t *
hb_coretext_font_data_t *
_hb_coretext_shaper_font_data_create (hb_font_t *font)
{
hb_face_t *face = font->face;
@ -321,11 +321,11 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
return nullptr;
}
return (hb_coretext_shaper_font_data_t *) ct_font;
return (hb_coretext_font_data_t *) ct_font;
}
void
_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
_hb_coretext_shaper_font_data_destroy (hb_coretext_font_data_t *data)
{
CFRelease ((CTFontRef) data);
}
@ -348,7 +348,7 @@ hb_coretext_font_create (CTFontRef ct_font)
hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font)));
/* Let there be dragons here... */
HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font);
HB_SHAPER_DATA_GET (font) = (hb_coretext_font_data_t *) CFRetain (ct_font);
return font;
}
@ -366,20 +366,20 @@ hb_coretext_font_get_ct_font (hb_font_t *font)
* shaper shape_plan data
*/
struct hb_coretext_shaper_shape_plan_data_t {};
struct hb_coretext_shape_plan_data_t {};
hb_coretext_shaper_shape_plan_data_t *
hb_coretext_shape_plan_data_t *
_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_coretext_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED)
_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shape_plan_data_t *data HB_UNUSED)
{
}
@ -1329,9 +1329,9 @@ HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font)
* shaper face data
*/
struct hb_coretext_aat_shaper_face_data_t {};
struct hb_coretext_aat_face_data_t {};
hb_coretext_aat_shaper_face_data_t *
hb_coretext_aat_face_data_t *
_hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
{
static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX};
@ -1342,7 +1342,7 @@ _hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
if (hb_blob_get_length (blob))
{
hb_blob_destroy (blob);
return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
}
hb_blob_destroy (blob);
}
@ -1351,7 +1351,7 @@ _hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
}
void
_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED)
_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_face_data_t *data HB_UNUSED)
{
}
@ -1360,16 +1360,16 @@ _hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *d
* shaper font data
*/
struct hb_coretext_aat_shaper_font_data_t {};
struct hb_coretext_aat_font_data_t {};
hb_coretext_aat_shaper_font_data_t *
hb_coretext_aat_font_data_t *
_hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
{
return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
}
void
_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *data HB_UNUSED)
_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_font_data_t *data HB_UNUSED)
{
}
@ -1378,20 +1378,20 @@ _hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *d
* shaper shape_plan data
*/
struct hb_coretext_aat_shaper_shape_plan_data_t {};
struct hb_coretext_aat_shape_plan_data_t {};
hb_coretext_aat_shaper_shape_plan_data_t *
hb_coretext_aat_shape_plan_data_t *
_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_coretext_aat_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shaper_shape_plan_data_t *data HB_UNUSED)
_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shape_plan_data_t *data HB_UNUSED)
{
}

View File

@ -28,6 +28,7 @@
#define HB_DEBUG_HH
#include "hb-private.hh"
#include "hb-atomic-private.hh"
#include "hb-dsalgs.hh"
@ -35,6 +36,47 @@
#define HB_DEBUG 0
#endif
/*
* Global runtime options.
*/
struct hb_options_t
{
unsigned int unused : 1; /* In-case sign bit is here. */
unsigned int initialized : 1;
unsigned int uniscribe_bug_compatible : 1;
};
union hb_options_union_t {
int i;
hb_options_t opts;
};
static_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), "");
HB_INTERNAL void
_hb_options_init (void);
extern HB_INTERNAL hb_atomic_int_t _hb_options;
static inline hb_options_t
hb_options (void)
{
/* Make a local copy, so we can access bitfield threadsafely. */
hb_options_union_t u;
u.i = _hb_options.get_relaxed ();
if (unlikely (!u.i))
_hb_options_init ();
return u.opts;
}
/*
* Debug output (needs enabling at compile time.)
*/
static inline bool
_hb_debug (unsigned int level,
unsigned int max_level)

View File

@ -133,7 +133,7 @@ public:
* shaper face data
*/
struct hb_directwrite_shaper_face_data_t
struct hb_directwrite_face_data_t
{
IDWriteFactory *dwriteFactory;
IDWriteFontFile *fontFile;
@ -143,10 +143,10 @@ struct hb_directwrite_shaper_face_data_t
hb_blob_t *faceBlob;
};
hb_directwrite_shaper_face_data_t *
hb_directwrite_face_data_t *
_hb_directwrite_shaper_face_data_create (hb_face_t *face)
{
hb_directwrite_shaper_face_data_t *data = new hb_directwrite_shaper_face_data_t;
hb_directwrite_face_data_t *data = new hb_directwrite_face_data_t;
if (unlikely (!data))
return nullptr;
@ -206,7 +206,7 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
}
void
_hb_directwrite_shaper_face_data_destroy (hb_directwrite_shaper_face_data_t *data)
_hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
{
if (data->fontFace)
data->fontFace->Release ();
@ -233,16 +233,16 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_shaper_face_data_t *dat
* shaper font data
*/
struct hb_directwrite_shaper_font_data_t
struct hb_directwrite_font_data_t
{
};
hb_directwrite_shaper_font_data_t *
hb_directwrite_font_data_t *
_hb_directwrite_shaper_font_data_create (hb_font_t *font)
{
if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return nullptr;
hb_directwrite_shaper_font_data_t *data = new hb_directwrite_shaper_font_data_t;
hb_directwrite_font_data_t *data = new hb_directwrite_font_data_t;
if (unlikely (!data))
return nullptr;
@ -250,7 +250,7 @@ _hb_directwrite_shaper_font_data_create (hb_font_t *font)
}
void
_hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *data)
_hb_directwrite_shaper_font_data_destroy (hb_directwrite_font_data_t *data)
{
delete data;
}
@ -260,20 +260,20 @@ _hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *dat
* shaper shape_plan data
*/
struct hb_directwrite_shaper_shape_plan_data_t {};
struct hb_directwrite_shape_plan_data_t {};
hb_directwrite_shaper_shape_plan_data_t *
hb_directwrite_shape_plan_data_t *
_hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_directwrite_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shaper_shape_plan_data_t *data HB_UNUSED)
_hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shape_plan_data_t *data HB_UNUSED)
{
}
@ -555,8 +555,8 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan,
float lineWidth)
{
hb_face_t *face = font->face;
hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
hb_directwrite_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
hb_directwrite_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
IDWriteFactory *dwriteFactory = face_data->dwriteFactory;
IDWriteFontFace *fontFace = face_data->fontFace;

View File

@ -33,7 +33,6 @@
#include "hb-open-file-private.hh"
/**
* hb_face_count: Get number of faces on the blob
* @blob:
@ -51,7 +50,8 @@ hb_face_count (hb_blob_t *blob)
return 0;
/* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */
hb_blob_t *sanitized = OT::hb_sanitize_context_t().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
/* Make API signature const after. */
hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
unsigned int ret = ot.get_face_count ();
hb_blob_destroy (sanitized);
@ -189,7 +189,7 @@ hb_face_create (hb_blob_t *blob,
if (unlikely (!blob))
blob = hb_blob_get_empty ();
hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::hb_sanitize_context_t().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)), index);
hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)), index);
if (unlikely (!closure))
return hb_face_get_empty ();
@ -302,7 +302,7 @@ hb_face_set_user_data (hb_face_t *face,
* Since: 0.9.2
**/
void *
hb_face_get_user_data (hb_face_t *face,
hb_face_get_user_data (const hb_face_t *face,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (face, key);
@ -336,7 +336,7 @@ hb_face_make_immutable (hb_face_t *face)
* Since: 0.9.2
**/
hb_bool_t
hb_face_is_immutable (hb_face_t *face)
hb_face_is_immutable (const hb_face_t *face)
{
return face->immutable;
}
@ -354,8 +354,8 @@ hb_face_is_immutable (hb_face_t *face)
* Since: 0.9.2
**/
hb_blob_t *
hb_face_reference_table (hb_face_t *face,
hb_tag_t tag)
hb_face_reference_table (const hb_face_t *face,
hb_tag_t tag)
{
return face->reference_table (tag);
}
@ -406,7 +406,7 @@ hb_face_set_index (hb_face_t *face,
* Since: 0.9.2
**/
unsigned int
hb_face_get_index (hb_face_t *face)
hb_face_get_index (const hb_face_t *face)
{
return face->index;
}
@ -441,7 +441,7 @@ hb_face_set_upem (hb_face_t *face,
* Since: 0.9.2
**/
unsigned int
hb_face_get_upem (hb_face_t *face)
hb_face_get_upem (const hb_face_t *face)
{
return face->get_upem ();
}
@ -476,7 +476,7 @@ hb_face_set_glyph_count (hb_face_t *face,
* Since: 0.9.7
**/
unsigned int
hb_face_get_glyph_count (hb_face_t *face)
hb_face_get_glyph_count (const hb_face_t *face)
{
return face->get_num_glyphs ();
}
@ -492,7 +492,7 @@ hb_face_get_glyph_count (hb_face_t *face)
* Since: 1.6.0
**/
unsigned int
hb_face_get_table_tags (hb_face_t *face,
hb_face_get_table_tags (const hb_face_t *face,
unsigned int start_offset,
unsigned int *table_count, /* IN/OUT */
hb_tag_t *table_tags /* OUT */)

View File

@ -76,19 +76,19 @@ hb_face_set_user_data (hb_face_t *face,
hb_bool_t replace);
HB_EXTERN void *
hb_face_get_user_data (hb_face_t *face,
hb_face_get_user_data (const hb_face_t *face,
hb_user_data_key_t *key);
HB_EXTERN void
hb_face_make_immutable (hb_face_t *face);
HB_EXTERN hb_bool_t
hb_face_is_immutable (hb_face_t *face);
hb_face_is_immutable (const hb_face_t *face);
HB_EXTERN hb_blob_t *
hb_face_reference_table (hb_face_t *face,
hb_tag_t tag);
hb_face_reference_table (const hb_face_t *face,
hb_tag_t tag);
HB_EXTERN hb_blob_t *
hb_face_reference_blob (hb_face_t *face);
@ -98,24 +98,24 @@ hb_face_set_index (hb_face_t *face,
unsigned int index);
HB_EXTERN unsigned int
hb_face_get_index (hb_face_t *face);
hb_face_get_index (const hb_face_t *face);
HB_EXTERN void
hb_face_set_upem (hb_face_t *face,
unsigned int upem);
HB_EXTERN unsigned int
hb_face_get_upem (hb_face_t *face);
hb_face_get_upem (const hb_face_t *face);
HB_EXTERN void
hb_face_set_glyph_count (hb_face_t *face,
unsigned int glyph_count);
HB_EXTERN unsigned int
hb_face_get_glyph_count (hb_face_t *face);
hb_face_get_glyph_count (const hb_face_t *face);
HB_EXTERN unsigned int
hb_face_get_table_tags (hb_face_t *face,
hb_face_get_table_tags (const hb_face_t *face,
unsigned int start_offset,
unsigned int *table_count, /* IN/OUT */
hb_tag_t *table_tags /* OUT */);

View File

@ -36,16 +36,16 @@ HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font)
* shaper face data
*/
struct hb_fallback_shaper_face_data_t {};
struct hb_fallback_face_data_t {};
hb_fallback_shaper_face_data_t *
hb_fallback_face_data_t *
_hb_fallback_shaper_face_data_create (hb_face_t *face HB_UNUSED)
{
return (hb_fallback_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_fallback_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_fallback_shaper_face_data_destroy (hb_fallback_shaper_face_data_t *data HB_UNUSED)
_hb_fallback_shaper_face_data_destroy (hb_fallback_face_data_t *data HB_UNUSED)
{
}
@ -54,16 +54,16 @@ _hb_fallback_shaper_face_data_destroy (hb_fallback_shaper_face_data_t *data HB_U
* shaper font data
*/
struct hb_fallback_shaper_font_data_t {};
struct hb_fallback_font_data_t {};
hb_fallback_shaper_font_data_t *
hb_fallback_font_data_t *
_hb_fallback_shaper_font_data_create (hb_font_t *font HB_UNUSED)
{
return (hb_fallback_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_fallback_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_fallback_shaper_font_data_destroy (hb_fallback_shaper_font_data_t *data HB_UNUSED)
_hb_fallback_shaper_font_data_destroy (hb_fallback_font_data_t *data HB_UNUSED)
{
}
@ -72,20 +72,20 @@ _hb_fallback_shaper_font_data_destroy (hb_fallback_shaper_font_data_t *data HB_U
* shaper shape_plan data
*/
struct hb_fallback_shaper_shape_plan_data_t {};
struct hb_fallback_shape_plan_data_t {};
hb_fallback_shaper_shape_plan_data_t *
hb_fallback_shape_plan_data_t *
_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_fallback_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_fallback_shaper_shape_plan_data_destroy (hb_fallback_shaper_shape_plan_data_t *data HB_UNUSED)
_hb_fallback_shaper_shape_plan_data_destroy (hb_fallback_shape_plan_data_t *data HB_UNUSED)
{
}

View File

@ -71,6 +71,7 @@ HB_DEFINE_OBJECT_TYPE (face)
HB_DEFINE_OBJECT_TYPE (font)
HB_DEFINE_OBJECT_TYPE (font_funcs)
HB_DEFINE_OBJECT_TYPE (set)
HB_DEFINE_OBJECT_TYPE (map)
HB_DEFINE_OBJECT_TYPE (shape_plan)
HB_DEFINE_OBJECT_TYPE (unicode_funcs)
HB_DEFINE_VALUE_TYPE (feature)

View File

@ -89,6 +89,10 @@ HB_EXTERN GType
hb_gobject_set_get_type (void);
#define HB_GOBJECT_TYPE_SET (hb_gobject_set_get_type ())
HB_EXTERN GType
hb_gobject_map_get_type (void);
#define HB_GOBJECT_TYPE_MAP (hb_gobject_map_get_type ())
HB_EXTERN GType
hb_gobject_shape_plan_get_type (void);
#define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ())

View File

@ -48,7 +48,7 @@ typedef struct hb_graphite2_tablelist_t {
unsigned int tag;
} hb_graphite2_tablelist_t;
struct hb_graphite2_shaper_face_data_t {
struct hb_graphite2_face_data_t {
hb_face_t *face;
gr_face *grface;
hb_graphite2_tablelist_t *tlist;
@ -56,7 +56,7 @@ struct hb_graphite2_shaper_face_data_t {
static const void *hb_graphite2_get_table (const void *data, unsigned int tag, size_t *len)
{
hb_graphite2_shaper_face_data_t *face_data = (hb_graphite2_shaper_face_data_t *) data;
hb_graphite2_face_data_t *face_data = (hb_graphite2_face_data_t *) data;
hb_graphite2_tablelist_t *tlist = face_data->tlist;
hb_blob_t *blob = nullptr;
@ -93,7 +93,7 @@ retry:
return d;
}
hb_graphite2_shaper_face_data_t *
hb_graphite2_face_data_t *
_hb_graphite2_shaper_face_data_create (hb_face_t *face)
{
hb_blob_t *silf_blob = face->reference_table (HB_GRAPHITE2_TAG_SILF);
@ -106,7 +106,7 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face)
}
hb_blob_destroy (silf_blob);
hb_graphite2_shaper_face_data_t *data = (hb_graphite2_shaper_face_data_t *) calloc (1, sizeof (hb_graphite2_shaper_face_data_t));
hb_graphite2_face_data_t *data = (hb_graphite2_face_data_t *) calloc (1, sizeof (hb_graphite2_face_data_t));
if (unlikely (!data))
return nullptr;
@ -122,7 +122,7 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face)
}
void
_hb_graphite2_shaper_face_data_destroy (hb_graphite2_shaper_face_data_t *data)
_hb_graphite2_shaper_face_data_destroy (hb_graphite2_face_data_t *data)
{
hb_graphite2_tablelist_t *tlist = data->tlist;
@ -154,16 +154,16 @@ hb_graphite2_face_get_gr_face (hb_face_t *face)
* shaper font data
*/
struct hb_graphite2_shaper_font_data_t {};
struct hb_graphite2_font_data_t {};
hb_graphite2_shaper_font_data_t *
hb_graphite2_font_data_t *
_hb_graphite2_shaper_font_data_create (hb_font_t *font HB_UNUSED)
{
return (hb_graphite2_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_graphite2_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data HB_UNUSED)
_hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED)
{
}
@ -181,20 +181,20 @@ hb_graphite2_font_get_gr_font (hb_font_t *font)
* shaper shape_plan data
*/
struct hb_graphite2_shaper_shape_plan_data_t {};
struct hb_graphite2_shape_plan_data_t {};
hb_graphite2_shaper_shape_plan_data_t *
hb_graphite2_shape_plan_data_t *
_hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_graphite2_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_graphite2_shaper_shape_plan_data_destroy (hb_graphite2_shaper_shape_plan_data_t *data HB_UNUSED)
_hb_graphite2_shaper_shape_plan_data_destroy (hb_graphite2_shape_plan_data_t *data HB_UNUSED)
{
}

View File

@ -30,12 +30,11 @@
#define HB_MACHINERY_PRIVATE_HH
#include "hb-private.hh"
#include "hb-blob-private.hh"
#include "hb-iter-private.hh"
namespace OT {
/*
* Casts
*/
@ -188,7 +187,7 @@ struct hb_sanitize_context_t :
inline void start_processing (void)
{
this->start = hb_blob_get_data (this->blob, nullptr);
this->start = this->blob->data;
this->end = this->start + this->blob->length;
assert (this->start <= this->end); /* Must not overflow. */
this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
@ -336,7 +335,7 @@ struct hb_sanitize_context_t :
DEBUG_MSG_FUNC (SANITIZE, start, sane ? "PASSED" : "FAILED");
if (sane)
{
blob->lock ();
hb_blob_make_immutable (blob);
return blob;
}
else
@ -350,8 +349,8 @@ struct hb_sanitize_context_t :
inline hb_blob_t *reference_table (const hb_face_t *face, hb_tag_t tableTag = Type::tableTag)
{
if (!num_glyphs_set)
set_num_glyphs (face->get_num_glyphs ());
return sanitize_blob<Type> (face->reference_table (tableTag));
set_num_glyphs (hb_face_get_glyph_count (face));
return sanitize_blob<Type> (hb_face_reference_table (face, tableTag));
}
mutable unsigned int debug_depth;
@ -467,12 +466,6 @@ struct hb_serialize_context_t
return reinterpret_cast<Type *> (&obj);
}
inline void truncate (void *new_head)
{
assert (this->start < new_head && new_head <= this->head);
this->head = (char *) new_head;
}
unsigned int debug_depth;
char *start, *end, *head;
bool ran_out_of_room;
@ -594,109 +587,117 @@ struct BEInt<Type, 4>
/*
* Lazy struct and blob loaders.
* Lazy loaders.
*/
/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
template <typename T>
struct hb_lazy_loader_t
template <unsigned int WheresFace,
typename Subclass,
typename Returned,
typename Stored = Returned>
struct hb_base_lazy_loader_t
{
inline void init (hb_face_t *face_)
static_assert (WheresFace > 0, "");
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
inline const Subclass* thiz (void) const { return static_cast<const Subclass *> (this); }
inline Subclass* thiz (void) { return static_cast<Subclass *> (this); }
inline void init (void)
{
face = face_;
instance = nullptr;
}
inline void fini (void)
{
if (instance && instance != &Null(T))
{
instance->fini();
free (instance);
}
if (instance)
thiz ()->destroy (instance);
}
inline const T* get (void) const
inline const Returned * operator-> (void) const
{
return thiz ()->get ();
}
inline Stored * get_stored (void) const
{
retry:
T *p = (T *) hb_atomic_ptr_get (&instance);
Stored *p = (Stored *) hb_atomic_ptr_get (&this->instance);
if (unlikely (!p))
{
p = (T *) calloc (1, sizeof (T));
if (unlikely (!p))
p = const_cast<T *> (&Null(T));
else
p->init (face);
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p)))
hb_face_t *face = *(((hb_face_t **) this) - WheresFace);
p = thiz ()->create (face);
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<Stored **>(&this->instance), nullptr, p)))
{
if (p != &Null(T))
p->fini ();
thiz ()->destroy (p);
goto retry;
}
}
return p;
}
inline const T* operator-> (void) const
inline const Returned * get (void) const
{
return get ();
return thiz ()->convert (get_stored ());
}
static inline const Returned* convert (const Stored *p)
{
return p;
}
private:
hb_face_t *face;
mutable T *instance;
/* Must only have one pointer. */
mutable Stored *instance;
};
/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
template <typename T>
struct hb_table_lazy_loader_t
{
inline void init (hb_face_t *face_)
{
face = face_;
blob = nullptr;
}
/* Specializations. */
inline void fini (void)
template <unsigned int WheresFace, typename T>
struct hb_lazy_loader_t : hb_base_lazy_loader_t<WheresFace, hb_lazy_loader_t<WheresFace, T>, T>
{
static inline T *create (hb_face_t *face)
{
hb_blob_destroy (blob);
if (unlikely (!face))
return const_cast<T *> (&Null(T));
T *p = (T *) calloc (1, sizeof (T));
if (unlikely (!p))
p = const_cast<T *> (&Null(T));
else
p->init (face);
return p;
}
static inline void destroy (T *p)
{
if (p != &Null(T))
{
p->fini();
free (p);
}
}
};
template <unsigned int WheresFace, typename T>
struct hb_table_lazy_loader_t : hb_base_lazy_loader_t<WheresFace, hb_table_lazy_loader_t<WheresFace, T>, T, hb_blob_t>
{
static inline hb_blob_t *create (hb_face_t *face)
{
if (unlikely (!face))
return hb_blob_get_empty ();
return hb_sanitize_context_t ().reference_table<T> (face);
}
static inline void destroy (hb_blob_t *p)
{
hb_blob_destroy (p);
}
static inline const T* convert (const hb_blob_t *blob)
{
return blob->as<T> ();
}
inline hb_blob_t* get_blob (void) const
{
retry:
hb_blob_t *b = (hb_blob_t *) hb_atomic_ptr_get (&blob);
if (unlikely (!b))
{
b = OT::hb_sanitize_context_t().reference_table<T> (face);
if (!hb_atomic_ptr_cmpexch (&blob, nullptr, b))
{
hb_blob_destroy (b);
goto retry;
}
blob = b;
}
return b;
return this->get_stored ();
}
inline const T* get (void) const
{
hb_blob_t *b = get_blob ();
return b->as<T> ();
}
inline const T* operator-> (void) const
{
return get();
}
private:
hb_face_t *face;
mutable hb_blob_t *blob;
};
} /* namespace OT */
#endif /* HB_MACHINERY_PRIVATE_HH */

View File

@ -157,8 +157,6 @@ hb_map_allocation_successful (const hb_map_t *map)
*
*
*
* Return value:
*
* Since: 1.7.7
**/
void
@ -188,7 +186,7 @@ hb_map_get (const hb_map_t *map,
/**
* hb_map_del:
* @map: a map.
* @codepoint:
* @key:
*
*
*
@ -204,7 +202,7 @@ hb_map_del (hb_map_t *map,
/**
* hb_map_has:
* @map: a map.
* @codepoint:
* @key:
*
*
*

View File

@ -47,14 +47,14 @@ struct hb_reference_count_t
{
hb_atomic_int_t ref_count;
inline void init (int v) { ref_count.set_unsafe (v); }
inline int get_unsafe (void) const { return ref_count.get_unsafe (); }
inline void init (int v) { ref_count.set_relaxed (v); }
inline int get_relaxed (void) const { return ref_count.get_relaxed (); }
inline int inc (void) { return ref_count.inc (); }
inline int dec (void) { return ref_count.dec (); }
inline void fini (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); }
inline void fini (void) { ref_count.set_relaxed (HB_REFERENCE_COUNT_POISON_VALUE); }
inline bool is_inert (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; }
inline bool is_valid (void) const { return ref_count.get_unsafe () > 0; }
inline bool is_inert (void) const { return ref_count.get_relaxed () == HB_REFERENCE_COUNT_INERT_VALUE; }
inline bool is_valid (void) const { return ref_count.get_relaxed () > 0; }
};
@ -111,7 +111,7 @@ static inline void hb_object_trace (const Type *obj, const char *function)
DEBUG_MSG (OBJECT, (void *) obj,
"%s refcount=%d",
function,
obj ? obj->header.ref_count.get_unsafe () : 0);
obj ? obj->header.ref_count.get_relaxed () : 0);
}
template <typename Type>

View File

@ -421,7 +421,7 @@ struct cff2
}
}
globalSubrs = &OT::StructAtOffset<Subrs> (cff2, cff2->topDict + cff2->topDictSize);
globalSubrs = &StructAtOffset<Subrs> (cff2, cff2->topDict + cff2->topDictSize);
varStore = &top.vstoreOffset (cff2);
charStrings = &top.charStringsOffset (cff2);
fdArray = &top.FDArrayOffset (cff2);

View File

@ -37,6 +37,9 @@
*/
#define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
#ifndef HB_MAX_UNICODE_CODEPOINT_VALUE
#define HB_MAX_UNICODE_CODEPOINT_VALUE 0x10FFFF
#endif
namespace OT {
@ -437,8 +440,10 @@ struct CmapSubtableLongSegmented
{
for (unsigned int i = 0; i < this->groups.len; i++) {
hb_set_add_range (out,
this->groups[i].startCharCode,
this->groups[i].endCharCode);
MIN ((unsigned int) this->groups[i].startCharCode,
(unsigned int) HB_MAX_UNICODE_CODEPOINT_VALUE),
MIN ((unsigned int) this->groups[i].endCharCode,
(unsigned int) HB_MAX_UNICODE_CODEPOINT_VALUE));
}
}

View File

@ -45,11 +45,13 @@ struct hb_ot_font_t
OT::cmap::accelerator_t cmap;
OT::hmtx::accelerator_t h_metrics;
OT::vmtx::accelerator_t v_metrics;
OT::hb_lazy_loader_t<OT::glyf::accelerator_t> glyf;
OT::hb_lazy_loader_t<OT::cff2::accelerator_t> cff2;
OT::hb_lazy_loader_t<OT::CBDT::accelerator_t> cbdt;
OT::hb_lazy_loader_t<OT::post::accelerator_t> post;
OT::hb_lazy_loader_t<OT::kern::accelerator_t> kern;
hb_face_t *face; /* MUST be before the lazy loaders. */
hb_lazy_loader_t<1, OT::glyf::accelerator_t> glyf;
hb_lazy_loader_t<2, OT::CBDT::accelerator_t> cbdt;
hb_lazy_loader_t<3, OT::post::accelerator_t> post;
hb_lazy_loader_t<4, OT::kern::accelerator_t> kern;
hb_lazy_loader_t<5, OT::kern::accelerator_t> cff2;
};
@ -64,10 +66,11 @@ _hb_ot_font_create (hb_face_t *face)
ot_font->cmap.init (face);
ot_font->h_metrics.init (face);
ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
ot_font->glyf.init (face);
ot_font->cbdt.init (face);
ot_font->post.init (face);
ot_font->kern.init (face);
ot_font->face = face;
ot_font->glyf.init ();
ot_font->cbdt.init ();
ot_font->post.init ();
ot_font->kern.init ();
return ot_font;
}

View File

@ -45,8 +45,10 @@
/*
* The maximum number of times a lookup can be applied during shaping.
* Used to limit the number of iterations of the closure algorithm.
* This must be larger than the number of times add_pause() is
* called in a collect_features call of any shaper.
*/
#define HB_CLOSURE_MAX_STAGES 8
#define HB_CLOSURE_MAX_STAGES 32
#endif
@ -188,6 +190,11 @@ struct IndexArray : ArrayOf<Index>
}
return this->len;
}
inline void add_indexes_to (hb_set_t* output /* OUT */) const
{
output->add_array (arrayZ, len);
}
};
@ -206,6 +213,8 @@ struct LangSys
unsigned int *feature_count /* IN/OUT */,
unsigned int *feature_indexes /* OUT */) const
{ return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
inline void add_feature_indexes_to (hb_set_t *feature_indexes) const
{ featureIndex.add_indexes_to (feature_indexes); }
inline bool has_required_feature (void) const { return reqFeatureIndex != 0xFFFFu; }
inline unsigned int get_required_feature_index (void) const
@ -485,20 +494,6 @@ struct FeatureParams
return Null(FeatureParamsSize);
}
inline const FeatureParamsStylisticSet& get_stylistic_set_params (hb_tag_t tag) const
{
if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
return u.stylisticSet;
return Null(FeatureParamsStylisticSet);
}
inline const FeatureParamsCharacterVariants& get_character_variants_params (hb_tag_t tag) const
{
if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
return u.characterVariants;
return Null(FeatureParamsCharacterVariants);
}
private:
union {
FeatureParamsSize size;

View File

@ -171,18 +171,18 @@ struct hb_ot_layout_t
const struct OT::GSUB *gsub;
const struct OT::GPOS *gpos;
/* TODO Move the following out of this struct. */
OT::hb_table_lazy_loader_t<struct OT::BASE> base;
OT::hb_table_lazy_loader_t<struct OT::MATH> math;
OT::hb_table_lazy_loader_t<struct OT::fvar> fvar;
OT::hb_table_lazy_loader_t<struct OT::avar> avar;
OT::hb_table_lazy_loader_t<struct AAT::morx> morx;
unsigned int gsub_lookup_count;
unsigned int gpos_lookup_count;
hb_ot_layout_lookup_accelerator_t *gsub_accels;
hb_ot_layout_lookup_accelerator_t *gpos_accels;
/* TODO Move the following out of this struct. */
hb_face_t *face; /* MUST be before the lazy loaders. */
hb_table_lazy_loader_t<1, struct OT::MATH> math;
hb_table_lazy_loader_t<2, struct OT::fvar> fvar;
hb_table_lazy_loader_t<3, struct OT::avar> avar;
hb_table_lazy_loader_t<4, struct AAT::morx> morx;
};

View File

@ -54,19 +54,20 @@ _hb_ot_layout_create (hb_face_t *face)
if (unlikely (!layout))
return nullptr;
layout->gdef_blob = OT::hb_sanitize_context_t().reference_table<OT::GDEF> (face);
layout->gdef_blob = hb_sanitize_context_t ().reference_table<OT::GDEF> (face);
layout->gdef = layout->gdef_blob->as<OT::GDEF> ();
layout->gsub_blob = OT::hb_sanitize_context_t().reference_table<OT::GSUB> (face);
layout->gsub_blob = hb_sanitize_context_t ().reference_table<OT::GSUB> (face);
layout->gsub = layout->gsub_blob->as<OT::GSUB> ();
layout->gpos_blob = OT::hb_sanitize_context_t().reference_table<OT::GPOS> (face);
layout->gpos_blob = hb_sanitize_context_t ().reference_table<OT::GPOS> (face);
layout->gpos = layout->gpos_blob->as<OT::GPOS> ();
layout->math.init (face);
layout->fvar.init (face);
layout->avar.init (face);
layout->morx.init (face);
layout->face = face;
layout->math.init ();
layout->fvar.init ();
layout->avar.init ();
layout->morx.init ();
{
/*
@ -520,6 +521,19 @@ hb_ot_layout_language_get_required_feature (hb_face_t *face,
return l.has_required_feature ();
}
static void
_hb_ot_layout_language_add_feature_indexes_to (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
unsigned int language_index,
hb_set_t *feature_indexes /* OUT */)
{
const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
l.add_feature_indexes_to (feature_indexes);
}
unsigned int
hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
hb_tag_t table_tag,
@ -658,13 +672,12 @@ _hb_ot_layout_collect_lookups_lookups (hb_face_t *face,
}
static void
_hb_ot_layout_collect_lookups_features (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
unsigned int language_index,
const hb_tag_t *features,
hb_set_t *visited_features,
hb_set_t *lookup_indexes /* OUT */)
_hb_ot_layout_collect_features_features (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
unsigned int language_index,
const hb_tag_t *features,
hb_set_t *feature_indexes /* OUT */)
{
if (!features)
{
@ -674,42 +687,15 @@ _hb_ot_layout_collect_lookups_features (hb_face_t *face,
script_index,
language_index,
&required_feature_index,
nullptr)
&& !visited_features->has (required_feature_index))
{
_hb_ot_layout_collect_lookups_lookups (face,
table_tag,
required_feature_index,
lookup_indexes);
visited_features->add (required_feature_index);
}
nullptr))
feature_indexes->add (required_feature_index);
/* All features */
unsigned int feature_indices[32];
unsigned int offset, len;
offset = 0;
do {
len = ARRAY_LENGTH (feature_indices);
hb_ot_layout_language_get_feature_indexes (face,
table_tag,
script_index,
language_index,
offset, &len,
feature_indices);
for (unsigned int i = 0; i < len; i++)
{
if (visited_features->has (feature_indices[i])) continue;
_hb_ot_layout_collect_lookups_lookups (face,
table_tag,
feature_indices[i],
lookup_indexes);
visited_features->add (feature_indices[i]);
}
offset += len;
} while (len == ARRAY_LENGTH (feature_indices));
_hb_ot_layout_language_add_feature_indexes_to (face,
table_tag,
script_index,
language_index,
feature_indexes);
}
else
{
@ -722,30 +708,25 @@ _hb_ot_layout_collect_lookups_features (hb_face_t *face,
language_index,
*features,
&feature_index))
_hb_ot_layout_collect_lookups_lookups (face,
table_tag,
feature_index,
lookup_indexes);
feature_indexes->add (feature_index);
}
}
}
static void
_hb_ot_layout_collect_lookups_languages (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
const hb_tag_t *languages,
const hb_tag_t *features,
hb_set_t *visited_features,
hb_set_t *lookup_indexes /* OUT */)
_hb_ot_layout_collect_features_languages (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
const hb_tag_t *languages,
const hb_tag_t *features,
hb_set_t *feature_indexes /* OUT */)
{
_hb_ot_layout_collect_lookups_features (face,
table_tag,
script_index,
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
features,
visited_features,
lookup_indexes);
_hb_ot_layout_collect_features_features (face,
table_tag,
script_index,
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
features,
feature_indexes);
if (!languages)
{
@ -755,13 +736,12 @@ _hb_ot_layout_collect_lookups_languages (hb_face_t *face,
script_index,
0, nullptr, nullptr);
for (unsigned int language_index = 0; language_index < count; language_index++)
_hb_ot_layout_collect_lookups_features (face,
table_tag,
script_index,
language_index,
features,
visited_features,
lookup_indexes);
_hb_ot_layout_collect_features_features (face,
table_tag,
script_index,
language_index,
features,
feature_indexes);
}
else
{
@ -773,13 +753,58 @@ _hb_ot_layout_collect_lookups_languages (hb_face_t *face,
script_index,
*languages,
&language_index))
_hb_ot_layout_collect_lookups_features (face,
table_tag,
script_index,
language_index,
features,
visited_features,
lookup_indexes);
_hb_ot_layout_collect_features_features (face,
table_tag,
script_index,
language_index,
features,
feature_indexes);
}
}
}
/**
* hb_ot_layout_collect_features:
*
* Since: 1.8.5
**/
void
hb_ot_layout_collect_features (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 *feature_indexes /* OUT */)
{
if (!scripts)
{
/* All scripts */
unsigned int count = hb_ot_layout_table_get_script_tags (face,
table_tag,
0, nullptr, nullptr);
for (unsigned int script_index = 0; script_index < count; script_index++)
_hb_ot_layout_collect_features_languages (face,
table_tag,
script_index,
languages,
features,
feature_indexes);
}
else
{
for (; *scripts; scripts++)
{
unsigned int script_index;
if (hb_ot_layout_table_find_script (face,
table_tag,
*scripts,
&script_index))
_hb_ot_layout_collect_features_languages (face,
table_tag,
script_index,
languages,
features,
feature_indexes);
}
}
}
@ -797,40 +822,10 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
const hb_tag_t *features,
hb_set_t *lookup_indexes /* OUT */)
{
hb_auto_t<hb_set_t> visited_features;
if (!scripts)
{
/* All scripts */
unsigned int count = hb_ot_layout_table_get_script_tags (face,
table_tag,
0, nullptr, nullptr);
for (unsigned int script_index = 0; script_index < count; script_index++)
_hb_ot_layout_collect_lookups_languages (face,
table_tag,
script_index,
languages,
features,
&visited_features,
lookup_indexes);
}
else
{
for (; *scripts; scripts++)
{
unsigned int script_index;
if (hb_ot_layout_table_find_script (face,
table_tag,
*scripts,
&script_index))
_hb_ot_layout_collect_lookups_languages (face,
table_tag,
script_index,
languages,
features,
&visited_features,
lookup_indexes);
}
}
hb_auto_t<hb_set_t> feature_indexes;
hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes);
for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID; hb_set_next (&feature_indexes, &feature_index);)
_hb_ot_layout_collect_lookups_lookups (face, table_tag, feature_index, lookup_indexes);
}
/**
@ -1035,24 +1030,6 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
OT::GPOS::position_finish_offsets (font, buffer);
}
static const OT::FeatureParams&
_get_gsubgpos_matched_feature_params (hb_face_t *face, hb_tag_t feature)
{
const OT::GSUB &gsub = _get_gsub (face);
unsigned int gsub_num_features = gsub.get_feature_count ();
for (unsigned int i = 0; i < gsub_num_features; i++)
if (feature == gsub.get_feature_tag (i))
return gsub.get_feature (i).get_feature_params ();
const OT::GPOS &gpos = _get_gpos (face);
unsigned int gpos_num_features = gpos.get_feature_count ();
for (unsigned int i = 0; i < gpos_num_features; i++)
if (feature == gpos.get_feature_tag (i))
return gpos.get_feature (i).get_feature_params ();
return Null (OT::FeatureParams);
}
/**
* hb_ot_layout_get_size_params:
*
@ -1103,74 +1080,6 @@ hb_ot_layout_get_size_params (hb_face_t *face,
return false;
}
/**
* hb_ot_layout_get_feature_name_ids:
* @face: #hb_face_t to work upon
* @feature: ssXX and cvXX tag
* @label_id: (out) (allow-none): The name table name ID that specifies a string
* for a user-interface label for this feature. (May be NULL.)
* @tooltip_id: (out) (allow-none): The name table name ID that specifies a string
* that an application can use for tooltip text for this
* feature. (May be NULL.)
* @sample_id: (out) (allow-none): The name table name ID that specifies sample text
* that illustrates the effect of this feature. (May be NULL.)
* @num_named_parameters: (out) (allow-none): Number of named parameters. (May be zero.)
* @first_param_id: (out) (allow-none): The first name table name ID used to specify
* strings for user-interface labels for the feature
* parameters. (Must be zero if numParameters is zero.)
*
* Return value: true if could find any feature with the tag, false otherwise
*
* Since: REPLACEME
**/
hb_bool_t
hb_ot_layout_get_feature_name_ids (hb_face_t *face,
hb_tag_t feature,
unsigned int *label_id, /* OUT. May be nullptr */
unsigned int *tooltip_id, /* OUT. May be nullptr */
unsigned int *sample_id, /* OUT. May be nullptr */
unsigned int *num_named_parameters, /* OUT. May be nullptr */
unsigned int *first_param_id /* OUT. May be nullptr */)
{
const OT::FeatureParams &feature_params =
_get_gsubgpos_matched_feature_params (face, feature);
if (&feature_params != &Null (OT::FeatureParams))
{
const OT::FeatureParamsStylisticSet& ss_params =
feature_params.get_stylistic_set_params (feature);
if (&ss_params != &Null (OT::FeatureParamsStylisticSet)) /* ssXX */
{
#define PARAM(a, A) if (a) *a = A
PARAM(label_id, ss_params.uiNameID);
// ssXX features don't have the rest
PARAM(tooltip_id, 0);
PARAM(sample_id, 0);
PARAM(num_named_parameters, 0);
PARAM(first_param_id, 0);
return true;
}
const OT::FeatureParamsCharacterVariants& cv_params =
feature_params.get_character_variants_params (feature);
if (&cv_params != &Null (OT::FeatureParamsCharacterVariants)) /* cvXX */
{
PARAM(label_id, cv_params.featUILableNameID);
PARAM(tooltip_id, cv_params.featUITooltipTextNameID);
PARAM(sample_id, cv_params.sampleTextNameID);
PARAM(num_named_parameters, cv_params.numNamedParameters);
PARAM(first_param_id, cv_params.firstParamUILabelNameID);
return true;
}
}
PARAM(label_id, 0);
PARAM(tooltip_id, 0);
PARAM(sample_id, 0);
PARAM(num_named_parameters, 0);
PARAM(first_param_id, 0);
#undef PARAM
return false;
}
/*
* Parts of different types are implemented here such that they have direct
@ -1208,7 +1117,7 @@ struct GPOSProxy
struct hb_get_subtables_context_t :
OT::hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
{
template <typename Type>
static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)

View File

@ -194,6 +194,13 @@ HB_EXTERN unsigned int
hb_ot_layout_table_get_lookup_count (hb_face_t *face,
hb_tag_t table_tag);
HB_EXTERN void
hb_ot_layout_collect_features (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 *feature_indexes /* OUT */);
HB_EXTERN void
hb_ot_layout_collect_lookups (hb_face_t *face,
@ -322,14 +329,6 @@ hb_ot_layout_get_size_params (hb_face_t *face,
unsigned int *range_start, /* OUT. May be NULL */
unsigned int *range_end /* OUT. May be NULL */);
HB_EXTERN hb_bool_t
hb_ot_layout_get_feature_name_ids (hb_face_t *face,
hb_tag_t feature,
unsigned int *label_id /* OUT. May be NULL */,
unsigned int *tooltip_id /* OUT. May be NULL */,
unsigned int *sample_id /* OUT. May be NULL */,
unsigned int *num_named_parameters /* OUT. May be NULL */,
unsigned int *first_param_id /* OUT. May be NULL */);
/*
* BASE

View File

@ -79,12 +79,12 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
* May not be good-enough for presidential candidate interviews, but good-enough for us... */
hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]);
OT::Supplier<OT::GlyphID> glyphs_supplier (glyphs, num_glyphs);
OT::Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
Supplier<OT::GlyphID> glyphs_supplier (glyphs, num_glyphs);
Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
/* Each glyph takes four bytes max, and there's some overhead. */
char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128];
OT::hb_serialize_context_t c (buf, sizeof (buf));
hb_serialize_context_t c (buf, sizeof (buf));
OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
bool ret = lookup->serialize_single (&c,
OT::LookupFlag::IgnoreMarks,
@ -155,15 +155,15 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN
if (!num_ligatures)
return nullptr;
OT::Supplier<OT::GlyphID> first_glyphs_supplier (first_glyphs, num_first_glyphs);
OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs);
OT::Supplier<OT::GlyphID> ligatures_supplier (ligature_list, num_ligatures);
OT::Supplier<unsigned int > component_count_supplier (component_count_list, num_ligatures);
OT::Supplier<OT::GlyphID> component_supplier (component_list, num_ligatures);
Supplier<OT::GlyphID> first_glyphs_supplier (first_glyphs, num_first_glyphs);
Supplier<unsigned int > ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs);
Supplier<OT::GlyphID> ligatures_supplier (ligature_list, num_ligatures);
Supplier<unsigned int > component_count_supplier (component_count_list, num_ligatures);
Supplier<OT::GlyphID> component_supplier (component_list, num_ligatures);
/* 16 bytes per ligature ought to be enough... */
char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128];
OT::hb_serialize_context_t c (buf, sizeof (buf));
hb_serialize_context_t c (buf, sizeof (buf));
OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
bool ret = lookup->serialize_ligature (&c,
OT::LookupFlag::IgnoreMarks,

View File

@ -300,7 +300,9 @@ static const hb_codepoint_t ra_chars[] = {
0x0CB0u, /* Kannada */
0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */
0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
0x179Au, /* Khmer */
};
static inline bool

View File

@ -251,10 +251,10 @@ struct indic_shape_plan_t
{
ASSERT_POD ();
inline bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
inline bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
{
hb_codepoint_t glyph = virama_glyph;
if (unlikely (virama_glyph == (hb_codepoint_t) -1))
hb_codepoint_t glyph = virama_glyph.get_relaxed ();
if (unlikely (glyph == (hb_codepoint_t) -1))
{
if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph))
glyph = 0;
@ -262,8 +262,8 @@ struct indic_shape_plan_t
* Maybe one day... */
/* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
* during shape planning... Instead, overwrite it here. It's safe. Don't worry! */
virama_glyph = glyph;
* during shape planning... Instead, overwrite it here. */
virama_glyph.set_relaxed ((int) glyph);
}
*pglyph = glyph;
@ -273,7 +273,7 @@ struct indic_shape_plan_t
const indic_config_t *config;
bool is_old_spec;
mutable hb_codepoint_t virama_glyph;
mutable hb_atomic_int_t virama_glyph;
would_substitute_feature_t rphf;
would_substitute_feature_t pref;
@ -298,7 +298,7 @@ data_create_indic (const hb_ot_shape_plan_t *plan)
}
indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
indic_plan->virama_glyph = (hb_codepoint_t) -1;
indic_plan->virama_glyph.set_relaxed (-1);
/* Use zero-context would_substitute() matching for new-spec of the main
* Indic scripts, and scripts with one spec only, but not for old-specs.
@ -419,7 +419,7 @@ update_consonant_positions (const hb_ot_shape_plan_t *plan,
return;
hb_codepoint_t virama;
if (indic_plan->get_virama_glyph (font, &virama))
if (indic_plan->load_virama_glyph (font, &virama))
{
hb_face_t *face = font->face;
unsigned int count = buffer->len;
@ -667,10 +667,10 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
* last consonant.
*
* Reports suggest that in some scripts Uniscribe does this only if there
* is *not* a Halant after last consonant already (eg. Kannada), while it
* does it unconditionally in other scripts (eg. Malayalam, Bengali). We
* don't currently know about other scripts, so we whitelist Malayalam and
* Bengali for now.
* is *not* a Halant after last consonant already. We know that is the
* case for Kannada, while it reorders unconditionally in other scripts,
* eg. Malayalam, Bengali, and Devanagari. We don't currently know about
* other scripts, so we blacklist Kannada.
*
* Kannada test case:
* U+0C9A,U+0CCD,U+0C9A,U+0CCD
@ -681,15 +681,19 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
* U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D
* With lohit-ttf-20121122/Lohit-Malayalam.ttf
*
* Bengali test case
* Bengali test case:
* U+0998,U+09CD,U+09AF,U+09CD
* With Windows XP vrinda.ttf
* https://github.com/harfbuzz/harfbuzz/issues/1073
*
* Devanagari test case:
* U+091F,U+094D,U+0930,U+094D
* With chandas.ttf
* https://github.com/harfbuzz/harfbuzz/issues/1071
*/
if (indic_plan->is_old_spec)
{
bool disallow_double_halants = buffer->props.script != HB_SCRIPT_MALAYALAM &&
buffer->props.script != HB_SCRIPT_BENGALI;
bool disallow_double_halants = buffer->props.script == HB_SCRIPT_KANNADA;
for (unsigned int i = base + 1; i < end; i++)
if (info[i].indic_category() == OT_H)
{
@ -1036,9 +1040,11 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
* phase, and that might have messed up our properties. Recover
* from a particular case of that where we're fairly sure that a
* class of OT_H is desired but has been lost. */
if (indic_plan->virama_glyph)
/* We don't call load_virama_glyph(), since we know it's already
* loaded. */
hb_codepoint_t virama_glyph = indic_plan->virama_glyph.get_relaxed ();
if (virama_glyph)
{
unsigned int virama_glyph = indic_plan->virama_glyph;
for (unsigned int i = start; i < end; i++)
if (info[i].codepoint == virama_glyph &&
_hb_glyph_info_ligated (&info[i]) &&

View File

@ -42,7 +42,7 @@ khmer_features[] =
{
/*
* Basic features.
* These features are applied in order, one at a time, after initial_reordering.
* These features are applied in order, one at a time, after reordering.
*/
{HB_TAG('p','r','e','f'), F_NONE},
{HB_TAG('b','l','w','f'), F_NONE},
@ -51,9 +51,7 @@ khmer_features[] =
{HB_TAG('c','f','a','r'), F_NONE},
/*
* Other features.
* These features are applied all at once, after final_reordering.
* Default Bengali font in Windows for example has intermixed
* lookups for init,pres,abvs,blws features.
* These features are applied all at once.
*/
{HB_TAG('p','r','e','s'), F_GLOBAL},
{HB_TAG('a','b','v','s'), F_GLOBAL},
@ -92,13 +90,9 @@ setup_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
initial_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
final_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
reorder (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
clear_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
@ -111,20 +105,28 @@ collect_features_khmer (hb_ot_shape_planner_t *plan)
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables);
map->add_gsub_pause (reorder);
/* Testing suggests that Uniscribe does NOT pause between basic
* features. Test with KhmerUI.ttf and the following three
* sequences:
*
* U+1789,U+17BC
* U+1789,U+17D2,U+1789
* U+1789,U+17D2,U+1789,U+17BC
*
* https://github.com/harfbuzz/harfbuzz/issues/974
*/
map->add_global_bool_feature (HB_TAG('l','o','c','l'));
/* The Indic specs do not require ccmp, but we apply it here since if
* there is a use of it, it's typically at the beginning. */
map->add_global_bool_feature (HB_TAG('c','c','m','p'));
unsigned int i = 0;
map->add_gsub_pause (initial_reordering);
for (; i < KHMER_BASIC_FEATURES; i++) {
map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
map->add_gsub_pause (nullptr);
}
map->add_gsub_pause (final_reordering);
map->add_gsub_pause (clear_syllables);
for (; i < KHMER_NUM_FEATURES; i++) {
map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
}
@ -132,7 +134,6 @@ collect_features_khmer (hb_ot_shape_planner_t *plan)
map->add_global_bool_feature (HB_TAG('c','a','l','t'));
map->add_global_bool_feature (HB_TAG('c','l','i','g'));
map->add_gsub_pause (clear_syllables);
}
static void
@ -264,162 +265,58 @@ setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
buffer->unsafe_to_break (start, end);
}
static int
compare_khmer_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
{
int a = pa->khmer_position();
int b = pb->khmer_position();
return a < b ? -1 : a == b ? 0 : +1;
}
/* Rules from:
* https://docs.microsoft.com/en-us/typography/script-development/devanagari */
static void
initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
hb_glyph_info_t *info = buffer->info;
/* 1. Khmer shaping assumes that a syllable will begin with a Cons, IndV, or Number. */
/* The first consonant is always the base. */
unsigned int base = start;
info[base].khmer_position() = POS_BASE_C;
/* Mark all subsequent consonants as below. */
for (unsigned int i = base + 1; i < end; i++)
if (is_consonant_or_vowel (info[i]))
info[i].khmer_position() = POS_BELOW_C;
/* Mark final consonants. A final consonant is one appearing after a matra,
* like in Khmer. */
for (unsigned int i = base + 1; i < end; i++)
if (info[i].khmer_category() == OT_M) {
for (unsigned int j = i + 1; j < end; j++)
if (is_consonant_or_vowel (info[j])) {
info[j].khmer_position() = POS_FINAL_C;
break;
}
break;
}
/* Attach misc marks to previous char to move with them. */
/* Setup masks. */
{
khmer_position_t last_pos = POS_START;
for (unsigned int i = start; i < end; i++)
{
if ((FLAG_UNSAFE (info[i].khmer_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_Coeng))))
{
info[i].khmer_position() = last_pos;
if (unlikely (info[i].khmer_category() == OT_Coeng &&
info[i].khmer_position() == POS_PRE_M))
{
/*
* Uniscribe doesn't move the Halant with Left Matra.
* TEST: U+092B,U+093F,U+094DE
* We follow. This is important for the Sinhala
* U+0DDA split matra since it decomposes to U+0DD9,U+0DCA
* where U+0DD9 is a left matra and U+0DCA is the virama.
* We don't want to move the virama with the left matra.
* TEST: U+0D9A,U+0DDA
*/
for (unsigned int j = i; j > start; j--)
if (info[j - 1].khmer_position() != POS_PRE_M) {
info[i].khmer_position() = info[j - 1].khmer_position();
break;
}
}
} else if (info[i].khmer_position() != POS_SMVD) {
last_pos = (khmer_position_t) info[i].khmer_position();
}
}
}
/* For post-base consonants let them own anything before them
* since the last consonant or matra. */
{
unsigned int last = base;
for (unsigned int i = base + 1; i < end; i++)
if (is_consonant_or_vowel (info[i]))
{
for (unsigned int j = last + 1; j < i; j++)
if (info[j].khmer_position() < POS_SMVD)
info[j].khmer_position() = info[i].khmer_position();
last = i;
} else if (info[i].khmer_category() == OT_M)
last = i;
}
{
/* Use syllable() for sort accounting temporarily. */
unsigned int syllable = info[start].syllable();
for (unsigned int i = start; i < end; i++)
info[i].syllable() = i - start;
/* Sit tight, rock 'n roll! */
hb_stable_sort (info + start, end - start, compare_khmer_order);
/* Find base again */
base = end;
for (unsigned int i = start; i < end; i++)
if (info[i].khmer_position() == POS_BASE_C)
{
base = i;
break;
}
if (unlikely (end - start >= 127))
buffer->merge_clusters (start, end);
else
/* Note! syllable() is a one-byte field. */
for (unsigned int i = base; i < end; i++)
if (info[i].syllable() != 255)
{
unsigned int max = i;
unsigned int j = start + info[i].syllable();
while (j != i)
{
max = MAX (max, j);
unsigned int next = start + info[j].syllable();
info[j].syllable() = 255; /* So we don't process j later again. */
j = next;
}
if (i != max)
buffer->merge_clusters (i, max + 1);
}
/* Put syllable back in. */
for (unsigned int i = start; i < end; i++)
info[i].syllable() = syllable;
}
/* Setup masks now */
{
hb_mask_t mask;
/* Post-base */
mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF];
for (unsigned int i = base + 1; i < end; i++)
hb_mask_t mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF];
for (unsigned int i = start + 1; i < end; i++)
info[i].mask |= mask;
}
unsigned int pref_len = 2;
if (khmer_plan->mask_array[PREF] && base + pref_len < end)
unsigned int num_coengs = 0;
for (unsigned int i = start + 1; i < end; i++)
{
/* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */
for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
hb_codepoint_t glyphs[2];
for (unsigned int j = 0; j < pref_len; j++)
glyphs[j] = info[i + j].codepoint;
if (khmer_plan->pref.would_substitute (glyphs, pref_len, face))
/* """
* When a COENG + (Cons | IndV) combination are found (and subscript count
* is less than two) the character combination is handled according to the
* subscript type of the character following the COENG.
*
* ...
*
* Subscript Type 2 - The COENG + RO characters are reordered to immediately
* before the base glyph. Then the COENG + RO characters are assigned to have
* the 'pref' OpenType feature applied to them.
* """
*/
if (info[i].khmer_category() == OT_Coeng && num_coengs <= 2 && i + 1 < end)
{
num_coengs++;
if (info[i + 1].khmer_category() == OT_Ra)
{
for (unsigned int j = 0; j < pref_len; j++)
info[i++].mask |= khmer_plan->mask_array[PREF];
for (unsigned int j = 0; j < 2; j++)
info[i + j].mask |= khmer_plan->mask_array[PREF];
/* Move the Coeng,Ro sequence to the start. */
buffer->merge_clusters (start, i + 2);
hb_glyph_info_t t0 = info[i];
hb_glyph_info_t t1 = info[i + 1];
memmove (&info[start + 2], &info[start], (i - start) * sizeof (info[0]));
info[start] = t0;
info[start + 1] = t1;
/* Mark the subsequent stuff with 'cfar'. Used in Khmer.
* Read the feature spec.
@ -428,12 +325,22 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
* U+1784,U+17D2,U+1782,U+17D2,U+179A
*/
if (khmer_plan->mask_array[CFAR])
for (; i < end; i++)
info[i].mask |= khmer_plan->mask_array[CFAR];
for (unsigned int j = i + 2; j < end; j++)
info[j].mask |= khmer_plan->mask_array[CFAR];
break;
num_coengs = 2; /* Done. */
}
}
/* Reorder left matra piece. */
else if (info[i].khmer_position() == POS_PRE_M)
{
/* Move to the start. */
buffer->merge_clusters (start, i + 1);
hb_glyph_info_t t = info[i];
memmove (&info[start + 1], &info[start], (i - start) * sizeof (info[0]));
info[start] = t;
}
}
}
@ -448,7 +355,7 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
{
case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
case consonant_syllable:
initial_reordering_consonant_syllable (plan, face, buffer, start, end);
reorder_consonant_syllable (plan, face, buffer, start, end);
break;
case non_khmer_cluster:
@ -518,263 +425,26 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
static void
initial_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
reorder (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
insert_dotted_circles (plan, font, buffer);
foreach_syllable (buffer, start, end)
initial_reordering_syllable (plan, font->face, buffer, start, end);
}
static void
final_reordering_syllable (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
hb_glyph_info_t *info = buffer->info;
/* This function relies heavily on halant glyphs. Lots of ligation
* and possibly multiple substitutions happened prior to this
* phase, and that might have messed up our properties. Recover
* from a particular case of that where we're fairly sure that a
* class of OT_Coeng is desired but has been lost. */
if (khmer_plan->virama_glyph)
{
unsigned int virama_glyph = khmer_plan->virama_glyph;
for (unsigned int i = start; i < end; i++)
if (info[i].codepoint == virama_glyph &&
_hb_glyph_info_ligated (&info[i]) &&
_hb_glyph_info_multiplied (&info[i]))
{
/* This will make sure that this glyph passes is_coeng() test. */
info[i].khmer_category() = OT_Coeng;
_hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
}
}
/* 4. Final reordering:
*
* After the localized forms and basic shaping forms GSUB features have been
* applied (see below), the shaping engine performs some final glyph
* reordering before applying all the remaining font features to the entire
* syllable.
*/
bool try_pref = !!khmer_plan->mask_array[PREF];
/* Find base again */
unsigned int base;
for (base = start; base < end; base++)
if (info[base].khmer_position() >= POS_BASE_C)
{
if (try_pref && base + 1 < end)
{
for (unsigned int i = base + 1; i < end; i++)
if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0)
{
if (!(_hb_glyph_info_substituted (&info[i]) &&
_hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
{
/* Ok, this was a 'pref' candidate but didn't form any.
* Base is around here... */
base = i;
while (base < end && is_coeng (info[base]))
base++;
info[base].khmer_position() = POS_BASE_C;
try_pref = false;
}
break;
}
}
if (start < base && info[base].khmer_position() > POS_BASE_C)
base--;
break;
}
if (base == end && start < base &&
is_one_of (info[base - 1], FLAG (OT_ZWJ)))
base--;
if (base < end)
while (start < base &&
is_one_of (info[base], (FLAG (OT_N) | FLAG (OT_Coeng))))
base--;
/* o Reorder matras:
*
* If a pre-base matra character had been reordered before applying basic
* features, the glyph can be moved closer to the main consonant based on
* whether half-forms had been formed. Actual position for the matra is
* defined as after last standalone halant glyph, after initial matra
* position and before the main consonant. If ZWJ or ZWNJ follow this
* halant, position is moved after it.
*/
if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */
{
/* If we lost track of base, alas, position before last thingy. */
unsigned int new_pos = base == end ? base - 2 : base - 1;
while (new_pos > start &&
!(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_Coeng)))))
new_pos--;
/* If we found no Halant we are done.
* Otherwise only proceed if the Halant does
* not belong to the Matra itself! */
if (is_coeng (info[new_pos]) &&
info[new_pos].khmer_position() != POS_PRE_M)
{
/* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
if (new_pos + 1 < end && is_joiner (info[new_pos + 1]))
new_pos++;
}
else
new_pos = start; /* No move. */
if (start < new_pos && info[new_pos].khmer_position () != POS_PRE_M)
{
/* Now go see if there's actually any matras... */
for (unsigned int i = new_pos; i > start; i--)
if (info[i - 1].khmer_position () == POS_PRE_M)
{
unsigned int old_pos = i - 1;
if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */
base--;
hb_glyph_info_t tmp = info[old_pos];
memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0]));
info[new_pos] = tmp;
/* Note: this merge_clusters() is intentionally *after* the reordering.
* Indic matra reordering is special and tricky... */
buffer->merge_clusters (new_pos, MIN (end, base + 1));
new_pos--;
}
} else {
for (unsigned int i = start; i < base; i++)
if (info[i].khmer_position () == POS_PRE_M) {
buffer->merge_clusters (i, MIN (end, base + 1));
break;
}
}
}
/* o Reorder pre-base-reordering consonants:
*
* If a pre-base-reordering consonant is found, reorder it according to
* the following rules:
*/
if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */
{
for (unsigned int i = base + 1; i < end; i++)
if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0)
{
/* 1. Only reorder a glyph produced by substitution during application
* of the <pref> feature. (Note that a font may shape a Ra consonant with
* the feature generally but block it in certain contexts.)
*/
/* Note: We just check that something got substituted. We don't check that
* the <pref> feature actually did it...
*
* Reorder pref only if it ligated. */
if (_hb_glyph_info_ligated_and_didnt_multiply (&info[i]))
{
/*
* 2. Try to find a target position the same way as for pre-base matra.
* If it is found, reorder pre-base consonant glyph.
*
* 3. If position is not found, reorder immediately before main
* consonant.
*/
unsigned int new_pos = base;
while (new_pos > start &&
!(is_one_of (info[new_pos - 1], FLAG(OT_M) | FLAG (OT_Coeng))))
new_pos--;
/* In Khmer coeng model, a H,Ra can go *after* matras. If it goes after a
* split matra, it should be reordered to *before* the left part of such matra. */
if (new_pos > start && info[new_pos - 1].khmer_category() == OT_M)
{
unsigned int old_pos = i;
for (unsigned int j = base + 1; j < old_pos; j++)
if (info[j].khmer_category() == OT_M)
{
new_pos--;
break;
}
}
if (new_pos > start && is_coeng (info[new_pos - 1]))
{
/* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
if (new_pos < end && is_joiner (info[new_pos]))
new_pos++;
}
{
unsigned int old_pos = i;
buffer->merge_clusters (new_pos, old_pos + 1);
hb_glyph_info_t tmp = info[old_pos];
memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
info[new_pos] = tmp;
if (new_pos <= base && base < old_pos)
base++;
}
}
break;
}
}
/*
* Finish off the clusters and go home!
*/
if (hb_options ().uniscribe_bug_compatible)
{
/* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala.
* This means, half forms are submerged into the main consonant's cluster.
* This is unnecessary, and makes cursor positioning harder, but that's what
* Uniscribe does. */
buffer->merge_clusters (start, end);
}
}
static void
final_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
if (unlikely (!count)) return;
foreach_syllable (buffer, start, end)
final_reordering_syllable (plan, buffer, start, end);
HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_position);
}
static void
clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
/* TODO: In USE, we clear syllables right after reorder. Figure out
* what Uniscribe does. */
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)

View File

@ -279,20 +279,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
return &_hb_ot_complex_shaper_indic;
case HB_SCRIPT_KHMER:
/* A number of Khmer fonts in the wild don't have a 'pref' feature,
* and as such won't shape properly via the Indic shaper;
* however, they typically have 'liga' / 'clig' features that implement
* the necessary "reordering" by means of ligature substitutions.
* So we send such pref-less fonts through the generic shaper instead. */
if (planner->map.found_script[0] &&
hb_ot_layout_language_find_feature (planner->face, HB_OT_TAG_GSUB,
planner->map.script_index[0],
planner->map.language_index[0],
HB_TAG ('p','r','e','f'),
nullptr))
return &_hb_ot_complex_shaper_khmer;
else
return &_hb_ot_complex_shaper_default;
case HB_SCRIPT_MYANMAR:
if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','2'))

View File

@ -27,8 +27,8 @@
*/
#define HB_SHAPER ot
#define hb_ot_shaper_face_data_t hb_ot_layout_t
#define hb_ot_shaper_shape_plan_data_t hb_ot_shape_plan_t
#define hb_ot_face_data_t hb_ot_layout_t
#define hb_ot_shape_plan_data_t hb_ot_shape_plan_t
#include "hb-shaper-impl-private.hh"
#include "hb-ot-shape-private.hh"
@ -132,14 +132,14 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
HB_SHAPER_DATA_ENSURE_DEFINE(ot, face)
hb_ot_shaper_face_data_t *
hb_ot_face_data_t *
_hb_ot_shaper_face_data_create (hb_face_t *face)
{
return _hb_ot_layout_create (face);
}
void
_hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
_hb_ot_shaper_face_data_destroy (hb_ot_face_data_t *data)
{
_hb_ot_layout_destroy (data);
}
@ -151,16 +151,16 @@ _hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
HB_SHAPER_DATA_ENSURE_DEFINE(ot, font)
struct hb_ot_shaper_font_data_t {};
struct hb_ot_font_data_t {};
hb_ot_shaper_font_data_t *
hb_ot_font_data_t *
_hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED)
{
return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data)
_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data)
{
}
@ -169,7 +169,7 @@ _hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data)
* shaper shape_plan data
*/
hb_ot_shaper_shape_plan_data_t *
hb_ot_shape_plan_data_t *
_hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
const hb_feature_t *user_features,
unsigned int num_user_features,
@ -204,7 +204,7 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
}
void
_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan)
_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shape_plan_data_t *plan)
{
if (plan->shaper->data_destroy)
plan->shaper->data_destroy (const_cast<void *> (plan->data));

View File

@ -525,34 +525,6 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
/* Global runtime options. */
struct hb_options_t
{
unsigned int initialized : 1;
unsigned int uniscribe_bug_compatible : 1;
};
union hb_options_union_t {
unsigned int i;
hb_options_t opts;
};
static_assert ((sizeof (int) == sizeof (hb_options_union_t)), "");
HB_INTERNAL void
_hb_options_init (void);
extern HB_INTERNAL hb_options_union_t _hb_options;
static inline hb_options_t
hb_options (void)
{
if (unlikely (!_hb_options.i))
_hb_options_init ();
return _hb_options.opts;
}
/* Size signifying variable-sized array */
#define VAR 1

View File

@ -49,23 +49,12 @@ HB_INTERNAL const hb_shaper_pair_t *
_hb_shapers_get (void);
/* For embedding in face / font / ... */
struct hb_shaper_data_t {
#define HB_SHAPER_IMPLEMENT(shaper) void *shaper;
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
};
#define HB_SHAPERS_COUNT (sizeof (hb_shaper_data_t) / sizeof (void *))
/* Means: succeeded, but don't need to keep any data. */
#define HB_SHAPER_DATA_SUCCEEDED ((void *) +1)
/* Means: tried but failed to create. */
#define HB_SHAPER_DATA_INVALID ((void *) -1)
#define HB_SHAPER_DATA_IS_INVALID(data) ((void *) (data) == HB_SHAPER_DATA_INVALID)
#define HB_SHAPER_DATA_TYPE_NAME(shaper, object) hb_##shaper##_shaper_##object##_data_t
#define HB_SHAPER_DATA_TYPE_NAME(shaper, object) hb_##shaper##_##object##_data_t
#define HB_SHAPER_DATA_TYPE(shaper, object) struct HB_SHAPER_DATA_TYPE_NAME(shaper, object)
#define HB_SHAPER_DATA_INSTANCE(shaper, object, instance) (* (HB_SHAPER_DATA_TYPE(shaper, object) **) &(instance)->shaper_data.shaper)
#define HB_SHAPER_DATA(shaper, object) HB_SHAPER_DATA_INSTANCE(shaper, object, object)
@ -100,7 +89,13 @@ HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \
/* Note that evaluating condition above can be dangerous if another thread \
* got here first and destructed data. That's, as always, bad use pattern. \
* If you modify the font (change font size), other threads must not be \
* using it at the same time. */ \
* using it at the same time. However, since this check is delayed to \
* when one actually tries to shape something, this is a XXX race condition \
* (and the only know we have that I know of) right now. Ie. you modify the \
* font size in one thread, then (supposedly safely) try to use it from two \
* or more threads and BOOM! I'm not sure how to fix this. We want RCU. \
* Maybe when it doesn't matter when we finally implement AAT shaping, as
* this (condition) is currently only used by hb-coretext. */ \
/* Drop and recreate. */ \
/* If someone dropped it in the mean time, throw it away and don't touch it. \
* Otherwise, destruct it. */ \
@ -121,8 +116,17 @@ HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \
goto retry; \
} \
} \
return data != nullptr && !HB_SHAPER_DATA_IS_INVALID (data); \
return data != nullptr && (void *) data != HB_SHAPER_DATA_INVALID; \
}
/* For embedding in face / font / ... */
struct hb_shaper_data_t {
#define HB_SHAPER_IMPLEMENT(shaper) void *shaper;
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
};
#define HB_SHAPERS_COUNT (sizeof (hb_shaper_data_t) / sizeof (void *))
#endif /* HB_SHAPER_PRIVATE_HH */

View File

@ -38,7 +38,7 @@ hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_
void
hb_face_t::load_num_glyphs (void) const
{
OT::hb_sanitize_context_t c = OT::hb_sanitize_context_t();
hb_sanitize_context_t c = hb_sanitize_context_t ();
c.set_num_glyphs (0); /* So we don't recurse ad infinitum. */
hb_blob_t *maxp_blob = c.reference_table<OT::maxp> (this);
const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
@ -49,7 +49,7 @@ hb_face_t::load_num_glyphs (void) const
void
hb_face_t::load_upem (void) const
{
hb_blob_t *head_blob = OT::hb_sanitize_context_t().reference_table<OT::head> (this);
hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<OT::head> (this);
const OT::head *head_table = head_blob->as<OT::head> ();
upem = head_table->get_upem ();
hb_blob_destroy (head_blob);

View File

@ -398,7 +398,7 @@ bool
hb_subset_cff2 (hb_subset_plan_t *plan,
hb_blob_t **prime /* OUT */)
{
hb_blob_t *cff2_blob = OT::hb_sanitize_context_t().reference_table<CFF::cff2> (plan->source);
hb_blob_t *cff2_blob = hb_sanitize_context_t().reference_table<CFF::cff2> (plan->source);
const char *data = hb_blob_get_data(cff2_blob, nullptr);
OT::cff2::accelerator_t acc;

View File

@ -292,7 +292,7 @@ hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
hb_blob_t **glyf_prime, /* OUT */
hb_blob_t **loca_prime /* OUT */)
{
hb_blob_t *glyf_blob = OT::hb_sanitize_context_t().reference_table<OT::glyf> (plan->source);
hb_blob_t *glyf_blob = hb_sanitize_context_t ().reference_table<OT::glyf> (plan->source);
const char *glyf_data = hb_blob_get_data(glyf_blob, nullptr);
OT::glyf::accelerator_t glyf;

View File

@ -79,7 +79,7 @@ template<typename TableType>
static bool
_subset (hb_subset_plan_t *plan)
{
hb_blob_t *source_blob = OT::hb_sanitize_context_t().reference_table<TableType> (plan->source);
hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
const TableType *table = source_blob->as<TableType> ();
hb_tag_t tag = TableType::tableTag;
@ -158,14 +158,14 @@ _hb_subset_face_data_reference_blob (hb_subset_face_data_t *data)
if (unlikely (!buf))
return nullptr;
OT::hb_serialize_context_t c (buf, face_length);
hb_serialize_context_t c (buf, face_length);
OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
OT::Supplier<hb_tag_t> tags_supplier (&data->tables[0].tag, table_count, sizeof (data->tables[0]));
OT::Supplier<hb_blob_t *> blobs_supplier (&data->tables[0].blob, table_count, sizeof (data->tables[0]));
Supplier<hb_tag_t> tags_supplier (&data->tables[0].tag, table_count, sizeof (data->tables[0]));
Supplier<hb_blob_t *> blobs_supplier (&data->tables[0].blob, table_count, sizeof (data->tables[0]));
bool ret = f->serialize_single (&c,
sfnt_tag,
tags_supplier,

View File

@ -309,7 +309,7 @@ HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, font)
* shaper face data
*/
struct hb_uniscribe_shaper_face_data_t {
struct hb_uniscribe_face_data_t {
HANDLE fh;
hb_uniscribe_shaper_funcs_t *funcs;
wchar_t face_name[LF_FACESIZE];
@ -358,7 +358,7 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
* full, PS. All of them point to the same name data with our unique name.
*/
blob = OT::hb_sanitize_context_t().sanitize_blob<OT::OpenTypeFontFile> (blob);
blob = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (blob);
unsigned int length, new_length, name_str_len;
const char *orig_sfnt_data = hb_blob_get_data (blob, &length);
@ -383,7 +383,7 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
memcpy(new_sfnt_data, orig_sfnt_data, length);
OT::name &name = OT::StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
OT::name &name = StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
name.format.set (0);
name.count.set (ARRAY_LENGTH (name_IDs));
name.stringOffset.set (name.get_size ());
@ -399,7 +399,7 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
}
/* Copy string data from new_name, converting wchar_t to UTF16BE. */
unsigned char *p = &OT::StructAfter<unsigned char> (name);
unsigned char *p = &StructAfter<unsigned char> (name);
for (unsigned int i = 0; i < name_str_len; i++)
{
*p++ = new_name[i] >> 8;
@ -439,10 +439,10 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
HB_MEMORY_MODE_WRITABLE, nullptr, free);
}
hb_uniscribe_shaper_face_data_t *
hb_uniscribe_face_data_t *
_hb_uniscribe_shaper_face_data_create (hb_face_t *face)
{
hb_uniscribe_shaper_face_data_t *data = (hb_uniscribe_shaper_face_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_face_data_t));
hb_uniscribe_face_data_t *data = (hb_uniscribe_face_data_t *) calloc (1, sizeof (hb_uniscribe_face_data_t));
if (unlikely (!data))
return nullptr;
@ -479,7 +479,7 @@ _hb_uniscribe_shaper_face_data_create (hb_face_t *face)
}
void
_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data)
_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_face_data_t *data)
{
RemoveFontMemResourceEx (data->fh);
free (data);
@ -490,7 +490,7 @@ _hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data)
* shaper font data
*/
struct hb_uniscribe_shaper_font_data_t {
struct hb_uniscribe_font_data_t {
HDC hdc;
LOGFONTW log_font;
HFONT hfont;
@ -508,19 +508,19 @@ populate_log_font (LOGFONTW *lf,
lf->lfCharSet = DEFAULT_CHARSET;
hb_face_t *face = font->face;
hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
hb_uniscribe_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName));
return true;
}
hb_uniscribe_shaper_font_data_t *
hb_uniscribe_font_data_t *
_hb_uniscribe_shaper_font_data_create (hb_font_t *font)
{
if (unlikely (!hb_uniscribe_shaper_face_data_ensure (font->face))) return nullptr;
hb_uniscribe_shaper_font_data_t *data = (hb_uniscribe_shaper_font_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_font_data_t));
hb_uniscribe_font_data_t *data = (hb_uniscribe_font_data_t *) calloc (1, sizeof (hb_uniscribe_font_data_t));
if (unlikely (!data))
return nullptr;
@ -559,7 +559,7 @@ _hb_uniscribe_shaper_font_data_create (hb_font_t *font)
}
void
_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data)
_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_font_data_t *data)
{
if (data->hdc)
ReleaseDC (nullptr, data->hdc);
@ -574,7 +574,7 @@ LOGFONTW *
hb_uniscribe_font_get_logfontw (hb_font_t *font)
{
if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return nullptr;
hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
hb_uniscribe_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
return &font_data->log_font;
}
@ -582,7 +582,7 @@ HFONT
hb_uniscribe_font_get_hfont (hb_font_t *font)
{
if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return nullptr;
hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
hb_uniscribe_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
return font_data->hfont;
}
@ -591,20 +591,20 @@ hb_uniscribe_font_get_hfont (hb_font_t *font)
* shaper shape_plan data
*/
struct hb_uniscribe_shaper_shape_plan_data_t {};
struct hb_uniscribe_shape_plan_data_t {};
hb_uniscribe_shaper_shape_plan_data_t *
hb_uniscribe_shape_plan_data_t *
_hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
return (hb_uniscribe_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_data_t *data HB_UNUSED)
_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shape_plan_data_t *data HB_UNUSED)
{
}
@ -622,8 +622,8 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan,
unsigned int num_features)
{
hb_face_t *face = font->face;
hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
hb_uniscribe_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
hb_uniscribe_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
hb_uniscribe_shaper_funcs_t *funcs = face_data->funcs;
/*

View File

@ -38,9 +38,9 @@ HB_BEGIN_DECLS
#define HB_VERSION_MAJOR 1
#define HB_VERSION_MINOR 8
#define HB_VERSION_MICRO 4
#define HB_VERSION_MICRO 5
#define HB_VERSION_STRING "1.8.4"
#define HB_VERSION_STRING "1.8.5"
#define HB_VERSION_ATLEAST(major,minor,micro) \
((major)*10000+(minor)*100+(micro) <= \

View File

@ -1,2 +1,4 @@
../fonts/57a9d9f83020155cbb1d2be1f43d82388cbecc88.ttf::U+0C9A,U+0CCD,U+0C9A,U+0CCD:[U0C9A_U0CCD.haln=0+1066|U0C9A_0CCD.blwf=0+0]
../fonts/270b89df543a7e48e206a2d830c0e10e5265c630.ttf::U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D:[glyph201=0+1183|U0D4D=0+0]
../fonts/b722a7d09e60421f3efbc706ad348ab47b88567b.ttf::U+091F,U+094D,U+0930,U+094D,U+0020:[Tra=0+550|virAma=0@-73,-110+0|space=4+500]
../fonts/b722a7d09e60421f3efbc706ad348ab47b88567b.ttf::U+091F,U+094D,U+0930,U+0942:[Tra=0+550|UT=0@42,-150+0]

View File

@ -0,0 +1,89 @@
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1781,U+17D2,U+1798,U+17C2:[uni17C2=0+288|uni1781=0+635|uni17D21798=0@22,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1787,U+17B6:[uni178717B6=0+923]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1790,U+17D2,U+1784,U+17C3:[uni17C3=0+288|uni1790=0+635|uni17D21784=0@-1,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17B6:[uni179817B6=0+923]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+1796,U+17BB:[uni1798=0+635|uni17D21796=0@-1,-26+0|uni17BB=0@-22,-296+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A:[uni179A=0+288]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A,U+17B8:[uni179A=0+288|uni17B8.r=0@76,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A,U+17CD:[uni179A=0+288|uni17CD.r=0@18,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17C5:[uni17C1=0+288|uni179F17C5=0+1216]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A,U+17D2,U+17A5:[uni179A=0+288|uni17D2=0+0|uni17A5=2+635]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1784,U+17B9,U+17D2,U+1788:[uni1784=0+635|uni17B9=0@-46,30+0|uni17D21788=0+234]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1784,U+17D2,U+1788,U+17B9:[uni1784=0+635|uni17D21788=0+234|uni17B9=0@8,30+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1784,U+17D2,U+1782,U+17D2,U+179A:[uni17D2179A.low=0+287|uni1784=0+635|uni17D21782=0@0,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1784,U+17D2,U+179A,U+17D2,U+1782:[uni17D2179A.low=0+287|uni1784=0+635|uni17D21782=0@0,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17C9,U+17D2,U+179B,U+17C1,U+17C7:[uni17C1=0+288|uni1798=0+635|uni17C9=0@-46,-29+0|uni17D2179B=0@-1,-26+0|uni17C7=0+386]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+200C,U+17C9,U+17D2,U+179B,U+17C1,U+17C7:[uni17C1=0+288|uni1798=0+635|space=0+0|uni17C9=0@-46,-29+0|uni17D2179B=0@-1,-26+0|uni17C7=0+386]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1794,U+17CA,U+17D0:[uni1794=0+635|uni17CA=0@-46,-29+0|uni17D0=0@-46,113+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1793,U+17C2,U+17CE:[uni17C2=0+288|uni1793=0+635|uni17CE=0@-36,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17C1,U+17D2,U+179A:[uni17D2179A=0+287|uni17C1=0+288|uni1780=0+636]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17C0,U+17D2,U+179A:[uni17D2179A=0+287|uni17C1=0+288|uni1780=0+636|uni17C0.right1=0+288]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17C4,U+17D2,U+179A:[uni17D2179A=0+287|uni17C1=0+288|uni178017B6=0+924]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17C5,U+17D2,U+179A:[uni17D2179A=0+287|uni17C1=0+288|uni178017C5=0+924]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1796,U+17D1,U+17B6:[uni179617B6=0+923|uni17D1=0@-311,-19+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+1793,U+17D2,U+178F,U+17D2,U+179A,U+17B6,U+1780,U+17CB:[uni1780=0+636|uni17D2179A.low=1+287|uni179317B6=1+924|uni17D2178F=1@-290,-26+0|uni1780=7+636|uni17CB=7@-23,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+1793,U+17D2,U+179A,U+17D2,U+179F,U+17B7,U+1780,U+17CB:[uni1780=0+636|uni17D2179A=1+287|uni1793=1+635|uni17D2179F=1+302|uni17B7=1@-4,30+0|uni1780=7+636|uni17CB=7@-23,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+1793,U+17D2,U+179A,U+17D2,U+179F,U+17B8,U+1780,U+17CB:[uni1780=0+636|uni17D2179A=1+287|uni1793=1+635|uni17D2179F=1+302|uni17B8=1@-4,30+0|uni1780=7+636|uni17CB=7@-23,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17B6,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F17B6=0+584|uni1793=4+635|uni17D2178F=4@-1,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17B7,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17B7=0@-4,30+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17B8,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17B8=0@-4,30+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17B9,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17B9=0@-4,30+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BA,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17BA=0@-4,30+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BB,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17BB=0@1,-260+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BC,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17BC=0@1,-260+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BD,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17BD=0@1,-260+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BF,U+1793,U+17D2,U+178F:[uni17C1=0+288|uni1780=0+636|uni17D2179F=0+302|uni17BF.right2=0+288|uni1793=4+635|uni17D2178F=4@-1,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17B6,U+17C6:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F17B6.low=0+584|uni17C6=0@39,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17B7,U+17C7:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17B7=0@-4,30+0|uni17C7=0+386]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17BB,U+17C6:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17BB=0+0|uni17C6=0@-4,30+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17BB,U+17C7:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17BB=0+0|uni17C7=0+386]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17C1,U+17C7:[uni17C1=0+288|uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17C7=0+386]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17C4,U+17C7:[uni17C1=0+288|uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F17B6.low=0+584|uni17C7=0+386]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17C6:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17C6=0@-4,30+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17C7:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17C7=0+386]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17BC:[uni1789=0+952|uni17BC=0@-173,-260+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17D2,U+1789:[uni1789.a=0+952|uni17D21789.a=0@19,-22+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17D2,U+1789,U+17BB:[uni1789.a=0+952|uni17D21789.a=0@19,-22+0|uni17BB=0@-160,-296+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17D2,U+1789,U+17BC:[uni1789.a=0+952|uni17D21789.a=0@19,-22+0|uni17BC=0@-160,-296+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17D2,U+1789,U+17BD:[uni1789.a=0+952|uni17D21789.a=0@19,-22+0|uni17BD=0@-160,-296+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C0:[uni17C1=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F=0+302|uni17C0.right2=0+288]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C1:[uni17C1=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F=0+302]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C2:[uni17C2=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F=0+302]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C3:[uni17C3=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F=0+302]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C4:[uni17C1=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F17B6=0+584]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C5:[uni17C1=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F17C5=0+584]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1792,U+17D2,U+179B,U+17BB,U+17C6,U+1780,U+17CB:[uni1792=0+635|uni17D2179B=0@-2,-26+0|uni17BB=0@-19,-296+0|uni17C6=0@-46,-29+0|uni1780=5+636|uni17CB=5@-23,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1792,U+17D2,U+179B,U+17C4,U+1780,U+17CB:[uni17C1=0+288|uni179217B6=0+923|uni17D2179B=0@-290,-26+0|uni1780=4+636|uni17CB=4@-23,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1792,U+17D2,U+179B,U+17C5,U+1780,U+17CB:[uni17C1=0+288|uni179217C5=0+923|uni17D2179B=0@-290,-26+0|uni1780=4+636|uni17CB=4@-23,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1792,U+17D2,U+179B,U+17C6,U+1780,U+17CB:[uni1792=0+635|uni17D2179B=0@-2,-26+0|uni17C6=0@-46,-29+0|uni1780=4+636|uni17CB=4@-23,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+178F,U+17D2,U+179B,U+17C9,U+17B6:[uni179817B6=0+923|uni17D2178F=0@-289,-26+0|uni17D2179B=0@-289,-296+0|uni17C9=0@-334,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+178F,U+17D2,U+179B,U+17C9,U+17BB:[uni1798=0+635|uni17D2178F=0@-1,-26+0|uni17D2179B=0@-1,-296+0|uni17C9=0@-46,-29+0|uni17BB=0@-18,-566+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+178F,U+17D2,U+179B,U+17C9,U+17BF:[uni17C1=0+288|uni1798=0+635|uni17D2178F=0@-1,-26+0|uni17D2179B=0@-1,-296+0|uni17C9=0@-46,-29+0|uni17BF.right1=0+288]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+178F,U+17D2,U+179B,U+17C9,U+17C0:[uni17C1=0+288|uni1798=0+635|uni17D2178F=0@-1,-26+0|uni17D2179B=0@-1,-296+0|uni17C9=0@-46,-29+0|uni17C0.right1=0+288]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1799,U+17D2,U+1799,U+17BE,U+17A0,U+17D2,U+179C,U+17D2,U+179B,U+17C3:[uni17C1=0+288|uni1799=0+953|uni17D21799=0+298|uni17B8=0@1,30+0|uni17C3=4+288|uni17A0=4+928|uni17D2179C=4@20,-26+0|uni17D2179B=4@19,-296+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A,U+17D2,U+179A:[uni17D2179A=0+287|uni179A=0+288]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17B6,U+179F,U+17D2,U+178F,U+17D2,U+179A,U+1783,U+17D2,U+1788,U+1784,U+17B6:[uni179F17B6=0+1216|uni17D2179A=2+287|uni179F=2+928|uni17D2178F=2@14,-26+0|uni1783=7+928|uni17D21788=7+234|uni178417B6=10+923]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17B6,U+179F,U+17D2,U+178F,U+17D2,U+179A,U+1783,U+17D2,U+1788,U+1784,U+17B7:[uni179F17B6=0+1216|uni17D2179A=2+287|uni179F=2+928|uni17D2178F=2@14,-26+0|uni1783=7+928|uni17D21788=7+234|uni1784=10+635|uni17B7=10@-46,30+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17B6,U+179F,U+17D2,U+178F,U+17D2,U+179A,U+1783,U+17D2,U+1788,U+1784,U+17B8:[uni179F17B6=0+1216|uni17D2179A=2+287|uni179F=2+928|uni17D2178F=2@14,-26+0|uni1783=7+928|uni17D21788=7+234|uni1784=10+635|uni17B8=10@-46,30+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+178F,U+17D2,U+179A,U+17B8,U+179C,U+17D0,U+1781,U+17D2,U+1789,U+17D2,U+179F,U+17B6:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B8=0@-32,-29+0|uni179C=6+326|uni17D0=6@139,40+0|uni1781=8+635|uni17D21789=8@-4,-26+0|uni17D2179F17B6.low=8+584]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17B6:[uni17D2179A=0+287|uni179F17B6=0+1216|uni17D2178F=0@-274,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17B7:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B7=0@-32,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17B8:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B8=0@-32,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17B9:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B9=0@-32,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BA:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BA=0@-32,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BB:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BB=0@-6,-296+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BC:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BC=0@-6,-296+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BD:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BD=0@-6,-296+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BE:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B8=0@-32,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BF:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BF.right2=0+288]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17BF:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0|uni17BF.right1=0+288]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C0:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0|uni17C0.right1.high=0+288]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C1:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C2:[uni17C2=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C3:[uni17C3=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C6:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0|uni17C6=0@-32,113+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+1782,U+17D2,U+179F,U+17CA,U+17BE:[uni17C1=0+288|uni17A0=0+928|uni17D21782=0@20,-26+0|uni17D2179F.low=0+302|uni17BB=0+0|uni17B8=0@-4,30+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+1782,U+17D2,U+179F,U+17CA,U+17BF:[uni17C1=0+288|uni17A0=0+928|uni17D21782=0@20,-26+0|uni17D2179F.low=0+302|uni17CA=0@-4,30+0|uni17BF.right1=0+288]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+1782,U+17D2,U+179F,U+17CA,U+17C0:[uni17C1=0+288|uni17A0=0+928|uni17D21782=0@20,-26+0|uni17D2179F.low=0+302|uni17CA=0@-4,30+0|uni17C0.right1.high=0+288]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+179A,U+17D2,U+179C,U+1784,U+17D2,U+1780:[uni17D2179A=0+287|uni17A0=0+928|uni17D2179C=0@20,-26+0|uni1784=5+635|uni17D21780=5@0,-26+0]
../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+179A,U+17D2,U+179C,U+17B6,U+17C6,U+1784:[uni17D2179A=0+287|uni17A017B6=0+1216|uni17D2179C=0@-268,-26+0|uni17C6=0@47,-29+0|uni1784=7+635]

Some files were not shown because too many files have changed in this diff Show More