Bug 1157758 - Update harfbuzz to pick up fix for vertical-upright Arabic script (non-)shaping behavior; now at upstream commit f724cc351640ee075a9867ef42df32cf5e0ef3b7. r=jdaggett

This commit is contained in:
Jonathan Kew 2015-05-11 06:58:21 +01:00
parent 0323a0a1b5
commit 218a52280a
61 changed files with 2791 additions and 2334 deletions

View File

@ -1,16 +1,14 @@
gfx/harfbuzz status as of 2012-08-16: gfx/harfbuzz status as of 2015-04-25:
This directory contains the "harfbuzz-ng" source from the 'master' branch of This directory contains the harfbuzz source from the 'master' branch of
git://anongit.freedesktop.org/git/harfbuzz. https://github.com/behdad/harfbuzz.
UPDATING: UPDATING:
Note that hb-ot-shape-complex-indic-machine.hh and gfx/harfbuzz/src/hb-version.h Note that gfx/harfbuzz/src/hb-version.h is not present in the upstream Git
are not present in the upstream Git repository. These are created at build time repository. It is created at build time by the harfbuzz build system;
by the harfbuzz build system; but as we don't use that build system in mozilla, but as we don't use that build system in mozilla, it is necessary to refresh
it is necessary to refresh these files when updating harfbuzz, and check them in this files when updating harfbuzz, and check them into the mozilla tree.
to the mozilla tree. (This avoids adding the ragel processor to mozilla's build
prerequisites.)
The normal approach to updating harfbuzz, therefore, is to pull the latest HB The normal approach to updating harfbuzz, therefore, is to pull the latest HB
source into a scratch directory and do a local build; then copy the original source into a scratch directory and do a local build; then copy the original
@ -19,5 +17,4 @@ the mozilla tree.
In addition, the src/Makefile.in file here is NOT from upstream, nor is it In addition, the src/Makefile.in file here is NOT from upstream, nor is it
generated from src/Makefile.am (the original harfbuzz version); it is a mozilla- generated from src/Makefile.am (the original harfbuzz version); it is a mozilla-
specific makefile that is maintained by hand. It should only need updating when specific makefile that is maintained by hand.
new source files or exported headers are added in harfbuzz.

View File

@ -13,6 +13,9 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
# The following warning options are useful for debugging: -Wpadded # The following warning options are useful for debugging: -Wpadded
#AM_CXXFLAGS = #AM_CXXFLAGS =
# Convenience targets:
lib: libharfbuzz.la
lib_LTLIBRARIES = libharfbuzz.la lib_LTLIBRARIES = libharfbuzz.la
HBCFLAGS = HBCFLAGS =

44
gfx/harfbuzz/src/check-defs.sh Executable file
View File

@ -0,0 +1,44 @@
#!/bin/sh
LC_ALL=C
export LC_ALL
test -z "$srcdir" && srcdir=.
test -z "$MAKE" && MAKE=make
stat=0
if which nm 2>/dev/null >/dev/null; then
:
else
echo "check-defs.sh: 'nm' not found; skipping test"
exit 77
fi
defs="harfbuzz.def"
$MAKE $defs > /dev/null
tested=false
for def in $defs; do
lib=`echo "$def" | sed 's/[.]def$//;s@.*/@@'`
so=.libs/lib${lib}.so
EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| llvm_' | cut -d' ' -f3`"
if test -f "$so"; then
echo "Checking that $so has the same symbol list as $def"
{
echo EXPORTS
echo "$EXPORTED_SYMBOLS"
# cheat: copy the last line from the def file!
tail -n1 "$def"
} | diff "$def" - >&2 || stat=1
tested=true
fi
done
if ! $tested; then
echo "check-defs.sh: libharfbuzz shared library not found; skipping test"
exit 77
fi
exit $stat

View File

@ -19,9 +19,9 @@ for suffix in so dylib; do
so=.libs/libharfbuzz.$suffix so=.libs/libharfbuzz.$suffix
if ! test -f "$so"; then continue; fi if ! test -f "$so"; then continue; fi
echo "Checking that we are not linking to libstdc++" echo "Checking that we are not linking to libstdc++ or libc++"
if ldd $so | grep 'libstdc[+][+]'; then if ldd $so | grep 'libstdc[+][+]\|libc[+][+]'; then
echo "Ouch, linked to libstdc++" echo "Ouch, linked to libstdc++ or libc++"
stat=1 stat=1
fi fi
tested=true tested=true

View File

@ -209,7 +209,7 @@ for p in sorted(pages):
for (start,end) in zip (starts, ends): for (start,end) in zip (starts, ends):
if p not in [start>>page_bits, end>>page_bits]: continue if p not in [start>>page_bits, end>>page_bits]: continue
offset = "indic_offset_0x%04xu" % start offset = "indic_offset_0x%04xu" % start
print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end, start, offset) print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset)
for u,d in singles.items (): for u,d in singles.items ():
if p != u>>page_bits: continue if p != u>>page_bits: continue
print " if (unlikely (u == 0x%04Xu)) return _(%s,%s);" % (u, short[0][d[0]], short[1][d[1]]) print " if (unlikely (u == 0x%04Xu)) return _(%s,%s);" % (u, short[0][d[0]], short[1][d[1]])

View File

@ -39,7 +39,11 @@
/* We need external help for these */ /* We need external help for these */
#if 0 #if defined(hb_atomic_int_impl_add) \
&& defined(hb_atomic_ptr_impl_get) \
&& defined(hb_atomic_ptr_impl_cmpexch)
/* Defined externally, i.e. in config.h; must have typedef'ed hb_atomic_int_impl_t as well. */
#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) #elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
@ -58,11 +62,12 @@ static inline void _HBMemoryBarrier (void) {
#endif #endif
} }
typedef LONG hb_atomic_int_t; typedef LONG hb_atomic_int_impl_t;
#define hb_atomic_int_add(AI, V) InterlockedExchangeAdd (&(AI), (V)) #define HB_ATOMIC_INT_IMPL_INIT(V) (V)
#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd (&(AI), (V))
#define hb_atomic_ptr_get(P) (_HBMemoryBarrier (), (void *) *(P)) #define hb_atomic_ptr_impl_get(P) (_HBMemoryBarrier (), (void *) *(P))
#define hb_atomic_ptr_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O)) #define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
#elif !defined(HB_NO_MT) && defined(__APPLE__) #elif !defined(HB_NO_MT) && defined(__APPLE__)
@ -74,28 +79,31 @@ typedef LONG hb_atomic_int_t;
#include <Availability.h> #include <Availability.h>
#endif #endif
typedef int32_t hb_atomic_int_t;
#define hb_atomic_int_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
#define hb_atomic_ptr_get(P) (OSMemoryBarrier (), (void *) *(P)) typedef int32_t hb_atomic_int_impl_t;
#define HB_ATOMIC_INT_IMPL_INIT(V) (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) #if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P)) #define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
#else #else
#if __ppc64__ || __x86_64__ || __aarch64__ #if __ppc64__ || __x86_64__ || __aarch64__
#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P)) #define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P))
#else #else
#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P)) #define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P))
#endif #endif
#endif #endif
#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES) #elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
typedef int hb_atomic_int_t; typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_add(AI, V) __sync_fetch_and_add (&(AI), (V)) #define HB_ATOMIC_INT_IMPL_INIT(V) (V)
#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add (&(AI), (V))
#define hb_atomic_ptr_get(P) (void *) (__sync_synchronize (), *(P)) #define hb_atomic_ptr_impl_get(P) (void *) (__sync_synchronize (), *(P))
#define hb_atomic_ptr_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N)) #define hb_atomic_ptr_impl_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N))
#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS) #elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
@ -103,33 +111,54 @@ typedef int hb_atomic_int_t;
#include <atomic.h> #include <atomic.h>
#include <mbarrier.h> #include <mbarrier.h>
typedef unsigned int hb_atomic_int_t; typedef unsigned int hb_atomic_int_impl_t;
#define hb_atomic_int_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V)) #define HB_ATOMIC_INT_IMPL_INIT(V) (V)
#define hb_atomic_int_impl_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V))
#define hb_atomic_ptr_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P)) #define hb_atomic_ptr_impl_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P))
#define hb_atomic_ptr_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false) #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)
#elif !defined(HB_NO_MT) #elif !defined(HB_NO_MT)
#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */ #define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
typedef volatile int hb_atomic_int_t;
#define hb_atomic_int_add(AI, V) (((AI) += (V)) - (V))
#define hb_atomic_ptr_get(P) ((void *) *(P)) typedef volatile int hb_atomic_int_impl_t;
#define hb_atomic_ptr_cmpexch(P,O,N) (* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false) #define HB_ATOMIC_INT_IMPL_INIT(V) (V)
#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 */ #else /* HB_NO_MT */
typedef int hb_atomic_int_t; typedef int hb_atomic_int_impl_t;
#define hb_atomic_int_add(AI, V) (((AI) += (V)) - (V)) #define HB_ATOMIC_INT_IMPL_INIT(V) (V)
#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 **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
#define hb_atomic_ptr_get(P) ((void *) *(P))
#define hb_atomic_ptr_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
#endif #endif
/* TODO Add tracing. */
#define HB_ATOMIC_INT_INIT(V) {HB_ATOMIC_INT_IMPL_INIT(V)}
struct hb_atomic_int_t
{
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 (const_cast<hb_atomic_int_impl_t &> (v), 1); }
inline int dec (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v), -1); }
};
#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get(P)
#define hb_atomic_ptr_cmpexch(P,O,N) hb_atomic_ptr_impl_cmpexch((P),(O),(N))
#endif /* HB_ATOMIC_PRIVATE_HH */ #endif /* HB_ATOMIC_PRIVATE_HH */

View File

@ -78,8 +78,8 @@ _hb_blob_destroy_user_data (hb_blob_t *blob)
} }
/** /**
* hb_blob_create: (Xconstructor) * hb_blob_create: (skip)
* @data: (array length=length) (closure user_data) (destroy destroy) (scope notified) (transfer none): Pointer to blob data. * @data: Pointer to blob data.
* @length: Length of @data in bytes. * @length: Length of @data in bytes.
* @mode: Memory mode for @data. * @mode: Memory mode for @data.
* @user_data: Data parameter to pass to @destroy. * @user_data: Data parameter to pass to @destroy.

View File

@ -1,5 +1,5 @@
#line 1 "../../src/hb-buffer-deserialize-json.rl" #line 1 "hb-buffer-deserialize-json.rl"
/* /*
* Copyright © 2013 Google, Inc. * Copyright © 2013 Google, Inc.
* *
@ -32,7 +32,7 @@
#include "hb-private.hh" #include "hb-private.hh"
#line 36 "hb-buffer-deserialize-json.hh.tmp" #line 36 "hb-buffer-deserialize-json.hh"
static const unsigned char _deserialize_json_trans_keys[] = { static const unsigned char _deserialize_json_trans_keys[] = {
0u, 0u, 9u, 123u, 9u, 34u, 97u, 103u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 0u, 0u, 9u, 123u, 9u, 34u, 97u, 103u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u,
48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u,
@ -435,7 +435,7 @@ static const int deserialize_json_error = 0;
static const int deserialize_json_en_main = 1; static const int deserialize_json_en_main = 1;
#line 97 "../../src/hb-buffer-deserialize-json.rl" #line 97 "hb-buffer-deserialize-json.rl"
static hb_bool_t static hb_bool_t
@ -459,15 +459,15 @@ _hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer,
const char *tok = NULL; const char *tok = NULL;
int cs; int cs;
hb_glyph_info_t info; hb_glyph_info_t info = {0};
hb_glyph_position_t pos; hb_glyph_position_t pos = {0};
#line 466 "hb-buffer-deserialize-json.hh.tmp" #line 466 "hb-buffer-deserialize-json.hh"
{ {
cs = deserialize_json_start; cs = deserialize_json_start;
} }
#line 471 "hb-buffer-deserialize-json.hh.tmp" #line 471 "hb-buffer-deserialize-json.hh"
{ {
int _slen; int _slen;
int _trans; int _trans;
@ -493,14 +493,14 @@ _resume:
switch ( _deserialize_json_trans_actions[_trans] ) { switch ( _deserialize_json_trans_actions[_trans] ) {
case 1: case 1:
#line 38 "../../src/hb-buffer-deserialize-json.rl" #line 38 "hb-buffer-deserialize-json.rl"
{ {
memset (&info, 0, sizeof (info)); memset (&info, 0, sizeof (info));
memset (&pos , 0, sizeof (pos )); memset (&pos , 0, sizeof (pos ));
} }
break; break;
case 5: case 5:
#line 43 "../../src/hb-buffer-deserialize-json.rl" #line 43 "hb-buffer-deserialize-json.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -510,13 +510,13 @@ _resume:
} }
break; break;
case 2: case 2:
#line 51 "../../src/hb-buffer-deserialize-json.rl" #line 51 "hb-buffer-deserialize-json.rl"
{ {
tok = p; tok = p;
} }
break; break;
case 14: case 14:
#line 55 "../../src/hb-buffer-deserialize-json.rl" #line 55 "hb-buffer-deserialize-json.rl"
{ {
if (!hb_font_glyph_from_string (font, if (!hb_font_glyph_from_string (font,
tok, p - tok, tok, p - tok,
@ -525,33 +525,33 @@ _resume:
} }
break; break;
case 15: case 15:
#line 62 "../../src/hb-buffer-deserialize-json.rl" #line 62 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.codepoint)) return false; } { if (!parse_uint (tok, p, &info.codepoint)) return false; }
break; break;
case 8: case 8:
#line 63 "../../src/hb-buffer-deserialize-json.rl" #line 63 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.cluster )) return false; } { if (!parse_uint (tok, p, &info.cluster )) return false; }
break; break;
case 10: case 10:
#line 64 "../../src/hb-buffer-deserialize-json.rl" #line 64 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.x_offset )) return false; } { if (!parse_int (tok, p, &pos.x_offset )) return false; }
break; break;
case 12: case 12:
#line 65 "../../src/hb-buffer-deserialize-json.rl" #line 65 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; } { if (!parse_int (tok, p, &pos.y_offset )) return false; }
break; break;
case 3: case 3:
#line 66 "../../src/hb-buffer-deserialize-json.rl" #line 66 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; } { if (!parse_int (tok, p, &pos.x_advance)) return false; }
break; break;
case 6: case 6:
#line 67 "../../src/hb-buffer-deserialize-json.rl" #line 67 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; } { if (!parse_int (tok, p, &pos.y_advance)) return false; }
break; break;
case 16: case 16:
#line 62 "../../src/hb-buffer-deserialize-json.rl" #line 62 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.codepoint)) return false; } { if (!parse_uint (tok, p, &info.codepoint)) return false; }
#line 43 "../../src/hb-buffer-deserialize-json.rl" #line 43 "hb-buffer-deserialize-json.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -561,9 +561,9 @@ _resume:
} }
break; break;
case 9: case 9:
#line 63 "../../src/hb-buffer-deserialize-json.rl" #line 63 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.cluster )) return false; } { if (!parse_uint (tok, p, &info.cluster )) return false; }
#line 43 "../../src/hb-buffer-deserialize-json.rl" #line 43 "hb-buffer-deserialize-json.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -573,9 +573,9 @@ _resume:
} }
break; break;
case 11: case 11:
#line 64 "../../src/hb-buffer-deserialize-json.rl" #line 64 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.x_offset )) return false; } { if (!parse_int (tok, p, &pos.x_offset )) return false; }
#line 43 "../../src/hb-buffer-deserialize-json.rl" #line 43 "hb-buffer-deserialize-json.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -585,9 +585,9 @@ _resume:
} }
break; break;
case 13: case 13:
#line 65 "../../src/hb-buffer-deserialize-json.rl" #line 65 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; } { if (!parse_int (tok, p, &pos.y_offset )) return false; }
#line 43 "../../src/hb-buffer-deserialize-json.rl" #line 43 "hb-buffer-deserialize-json.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -597,9 +597,9 @@ _resume:
} }
break; break;
case 4: case 4:
#line 66 "../../src/hb-buffer-deserialize-json.rl" #line 66 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; } { if (!parse_int (tok, p, &pos.x_advance)) return false; }
#line 43 "../../src/hb-buffer-deserialize-json.rl" #line 43 "hb-buffer-deserialize-json.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -609,9 +609,9 @@ _resume:
} }
break; break;
case 7: case 7:
#line 67 "../../src/hb-buffer-deserialize-json.rl" #line 67 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; } { if (!parse_int (tok, p, &pos.y_advance)) return false; }
#line 43 "../../src/hb-buffer-deserialize-json.rl" #line 43 "hb-buffer-deserialize-json.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -620,7 +620,7 @@ _resume:
*end_ptr = p; *end_ptr = p;
} }
break; break;
#line 624 "hb-buffer-deserialize-json.hh.tmp" #line 624 "hb-buffer-deserialize-json.hh"
} }
_again: _again:
@ -632,7 +632,7 @@ _again:
_out: {} _out: {}
} }
#line 125 "../../src/hb-buffer-deserialize-json.rl" #line 125 "hb-buffer-deserialize-json.rl"
*end_ptr = p; *end_ptr = p;

View File

@ -1,5 +1,5 @@
#line 1 "../../src/hb-buffer-deserialize-text.rl" #line 1 "hb-buffer-deserialize-text.rl"
/* /*
* Copyright © 2013 Google, Inc. * Copyright © 2013 Google, Inc.
* *
@ -32,7 +32,7 @@
#include "hb-private.hh" #include "hb-private.hh"
#line 36 "hb-buffer-deserialize-text.hh.tmp" #line 36 "hb-buffer-deserialize-text.hh"
static const unsigned char _deserialize_text_trans_keys[] = { static const unsigned char _deserialize_text_trans_keys[] = {
0u, 0u, 9u, 122u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, 0u, 0u, 9u, 122u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u,
48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 9u, 124u, 9u, 124u, 0u, 0u,
@ -312,7 +312,7 @@ static const int deserialize_text_error = 0;
static const int deserialize_text_en_main = 1; static const int deserialize_text_en_main = 1;
#line 91 "../../src/hb-buffer-deserialize-text.rl" #line 91 "hb-buffer-deserialize-text.rl"
static hb_bool_t static hb_bool_t
@ -336,15 +336,15 @@ _hb_buffer_deserialize_glyphs_text (hb_buffer_t *buffer,
const char *eof = pe, *tok = NULL; const char *eof = pe, *tok = NULL;
int cs; int cs;
hb_glyph_info_t info; hb_glyph_info_t info = {0};
hb_glyph_position_t pos; hb_glyph_position_t pos = {0};
#line 343 "hb-buffer-deserialize-text.hh.tmp" #line 343 "hb-buffer-deserialize-text.hh"
{ {
cs = deserialize_text_start; cs = deserialize_text_start;
} }
#line 348 "hb-buffer-deserialize-text.hh.tmp" #line 348 "hb-buffer-deserialize-text.hh"
{ {
int _slen; int _slen;
int _trans; int _trans;
@ -370,13 +370,13 @@ _resume:
switch ( _deserialize_text_trans_actions[_trans] ) { switch ( _deserialize_text_trans_actions[_trans] ) {
case 2: case 2:
#line 51 "../../src/hb-buffer-deserialize-text.rl" #line 51 "hb-buffer-deserialize-text.rl"
{ {
tok = p; tok = p;
} }
break; break;
case 5: case 5:
#line 55 "../../src/hb-buffer-deserialize-text.rl" #line 55 "hb-buffer-deserialize-text.rl"
{ {
if (!hb_font_glyph_from_string (font, if (!hb_font_glyph_from_string (font,
tok, p - tok, tok, p - tok,
@ -385,41 +385,41 @@ _resume:
} }
break; break;
case 10: case 10:
#line 62 "../../src/hb-buffer-deserialize-text.rl" #line 62 "hb-buffer-deserialize-text.rl"
{ if (!parse_uint (tok, p, &info.cluster )) return false; } { if (!parse_uint (tok, p, &info.cluster )) return false; }
break; break;
case 3: case 3:
#line 63 "../../src/hb-buffer-deserialize-text.rl" #line 63 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_offset )) return false; } { if (!parse_int (tok, p, &pos.x_offset )) return false; }
break; break;
case 12: case 12:
#line 64 "../../src/hb-buffer-deserialize-text.rl" #line 64 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; } { if (!parse_int (tok, p, &pos.y_offset )) return false; }
break; break;
case 7: case 7:
#line 65 "../../src/hb-buffer-deserialize-text.rl" #line 65 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; } { if (!parse_int (tok, p, &pos.x_advance)) return false; }
break; break;
case 1: case 1:
#line 38 "../../src/hb-buffer-deserialize-text.rl" #line 38 "hb-buffer-deserialize-text.rl"
{ {
memset (&info, 0, sizeof (info)); memset (&info, 0, sizeof (info));
memset (&pos , 0, sizeof (pos )); memset (&pos , 0, sizeof (pos ));
} }
#line 51 "../../src/hb-buffer-deserialize-text.rl" #line 51 "hb-buffer-deserialize-text.rl"
{ {
tok = p; tok = p;
} }
break; break;
case 4: case 4:
#line 55 "../../src/hb-buffer-deserialize-text.rl" #line 55 "hb-buffer-deserialize-text.rl"
{ {
if (!hb_font_glyph_from_string (font, if (!hb_font_glyph_from_string (font,
tok, p - tok, tok, p - tok,
&info.codepoint)) &info.codepoint))
return false; return false;
} }
#line 43 "../../src/hb-buffer-deserialize-text.rl" #line 43 "hb-buffer-deserialize-text.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -429,9 +429,9 @@ _resume:
} }
break; break;
case 9: case 9:
#line 62 "../../src/hb-buffer-deserialize-text.rl" #line 62 "hb-buffer-deserialize-text.rl"
{ if (!parse_uint (tok, p, &info.cluster )) return false; } { if (!parse_uint (tok, p, &info.cluster )) return false; }
#line 43 "../../src/hb-buffer-deserialize-text.rl" #line 43 "hb-buffer-deserialize-text.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -441,9 +441,9 @@ _resume:
} }
break; break;
case 11: case 11:
#line 64 "../../src/hb-buffer-deserialize-text.rl" #line 64 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; } { if (!parse_int (tok, p, &pos.y_offset )) return false; }
#line 43 "../../src/hb-buffer-deserialize-text.rl" #line 43 "hb-buffer-deserialize-text.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -453,9 +453,9 @@ _resume:
} }
break; break;
case 6: case 6:
#line 65 "../../src/hb-buffer-deserialize-text.rl" #line 65 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; } { if (!parse_int (tok, p, &pos.x_advance)) return false; }
#line 43 "../../src/hb-buffer-deserialize-text.rl" #line 43 "hb-buffer-deserialize-text.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -465,9 +465,9 @@ _resume:
} }
break; break;
case 8: case 8:
#line 66 "../../src/hb-buffer-deserialize-text.rl" #line 66 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; } { if (!parse_int (tok, p, &pos.y_advance)) return false; }
#line 43 "../../src/hb-buffer-deserialize-text.rl" #line 43 "hb-buffer-deserialize-text.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -476,7 +476,7 @@ _resume:
*end_ptr = p; *end_ptr = p;
} }
break; break;
#line 480 "hb-buffer-deserialize-text.hh.tmp" #line 480 "hb-buffer-deserialize-text.hh"
} }
_again: _again:
@ -489,14 +489,14 @@ _again:
{ {
switch ( _deserialize_text_eof_actions[cs] ) { switch ( _deserialize_text_eof_actions[cs] ) {
case 4: case 4:
#line 55 "../../src/hb-buffer-deserialize-text.rl" #line 55 "hb-buffer-deserialize-text.rl"
{ {
if (!hb_font_glyph_from_string (font, if (!hb_font_glyph_from_string (font,
tok, p - tok, tok, p - tok,
&info.codepoint)) &info.codepoint))
return false; return false;
} }
#line 43 "../../src/hb-buffer-deserialize-text.rl" #line 43 "hb-buffer-deserialize-text.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -506,9 +506,9 @@ _again:
} }
break; break;
case 9: case 9:
#line 62 "../../src/hb-buffer-deserialize-text.rl" #line 62 "hb-buffer-deserialize-text.rl"
{ if (!parse_uint (tok, p, &info.cluster )) return false; } { if (!parse_uint (tok, p, &info.cluster )) return false; }
#line 43 "../../src/hb-buffer-deserialize-text.rl" #line 43 "hb-buffer-deserialize-text.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -518,9 +518,9 @@ _again:
} }
break; break;
case 11: case 11:
#line 64 "../../src/hb-buffer-deserialize-text.rl" #line 64 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; } { if (!parse_int (tok, p, &pos.y_offset )) return false; }
#line 43 "../../src/hb-buffer-deserialize-text.rl" #line 43 "hb-buffer-deserialize-text.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -530,9 +530,9 @@ _again:
} }
break; break;
case 6: case 6:
#line 65 "../../src/hb-buffer-deserialize-text.rl" #line 65 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; } { if (!parse_int (tok, p, &pos.x_advance)) return false; }
#line 43 "../../src/hb-buffer-deserialize-text.rl" #line 43 "hb-buffer-deserialize-text.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -542,9 +542,9 @@ _again:
} }
break; break;
case 8: case 8:
#line 66 "../../src/hb-buffer-deserialize-text.rl" #line 66 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; } { if (!parse_int (tok, p, &pos.y_advance)) return false; }
#line 43 "../../src/hb-buffer-deserialize-text.rl" #line 43 "hb-buffer-deserialize-text.rl"
{ {
buffer->add_info (info); buffer->add_info (info);
if (buffer->in_error) if (buffer->in_error)
@ -553,14 +553,14 @@ _again:
*end_ptr = p; *end_ptr = p;
} }
break; break;
#line 557 "hb-buffer-deserialize-text.hh.tmp" #line 557 "hb-buffer-deserialize-text.hh"
} }
} }
_out: {} _out: {}
} }
#line 119 "../../src/hb-buffer-deserialize-text.rl" #line 119 "hb-buffer-deserialize-text.rl"
*end_ptr = p; *end_ptr = p;

View File

@ -111,8 +111,8 @@ _hb_buffer_deserialize_glyphs_text (hb_buffer_t *buffer,
const char *eof = pe, *tok = NULL; const char *eof = pe, *tok = NULL;
int cs; int cs;
hb_glyph_info_t info; hb_glyph_info_t info = {0};
hb_glyph_position_t pos; hb_glyph_position_t pos = {0};
%%{ %%{
write init; write init;
write exec; write exec;

View File

@ -443,7 +443,7 @@ hb_buffer_t::reverse_range (unsigned int start,
{ {
unsigned int i, j; unsigned int i, j;
if (start == end - 1) if (end - start < 2)
return; return;
for (i = start, j = end - 1; i < j; i++, j--) { for (i = start, j = end - 1; i < j; i++, j--) {
@ -454,7 +454,7 @@ hb_buffer_t::reverse_range (unsigned int start,
info[j] = t; info[j] = t;
} }
if (pos) { if (have_positions) {
for (i = start, j = end - 1; i < j; i++, j--) { for (i = start, j = end - 1; i < j; i++, j--) {
hb_glyph_position_t t; hb_glyph_position_t t;
@ -967,7 +967,7 @@ hb_buffer_set_language (hb_buffer_t *buffer,
* *
* *
* *
* Return value: * Return value: (transfer none):
* *
* Since: 1.0 * Since: 1.0
**/ **/
@ -999,7 +999,7 @@ hb_buffer_set_segment_properties (hb_buffer_t *buffer,
/** /**
* hb_buffer_get_segment_properties: * hb_buffer_get_segment_properties:
* @buffer: a buffer. * @buffer: a buffer.
* @props: * @props: (out):
* *
* *
* *
@ -1328,15 +1328,15 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer)
buffer->guess_segment_properties (); buffer->guess_segment_properties ();
} }
template <bool validate, typename T> template <typename utf_t>
static inline void static inline void
hb_buffer_add_utf (hb_buffer_t *buffer, hb_buffer_add_utf (hb_buffer_t *buffer,
const T *text, const typename utf_t::codepoint_t *text,
int text_length, int text_length,
unsigned int item_offset, unsigned int item_offset,
int item_length) int item_length)
{ {
typedef hb_utf_t<T, true> utf_t; typedef typename utf_t::codepoint_t T;
const hb_codepoint_t replacement = buffer->replacement; const hb_codepoint_t replacement = buffer->replacement;
assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
@ -1400,7 +1400,7 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
/** /**
* hb_buffer_add_utf8: * hb_buffer_add_utf8:
* @buffer: a buffer. * @buffer: a buffer.
* @text: (array length=text_length): * @text: (array length=text_length) (element-type uint8_t):
* @text_length: * @text_length:
* @item_offset: * @item_offset:
* @item_length: * @item_length:
@ -1416,7 +1416,7 @@ hb_buffer_add_utf8 (hb_buffer_t *buffer,
unsigned int item_offset, unsigned int item_offset,
int item_length) int item_length)
{ {
hb_buffer_add_utf<true> (buffer, (const uint8_t *) text, text_length, item_offset, item_length); hb_buffer_add_utf<hb_utf8_t> (buffer, (const uint8_t *) text, text_length, item_offset, item_length);
} }
/** /**
@ -1438,7 +1438,7 @@ hb_buffer_add_utf16 (hb_buffer_t *buffer,
unsigned int item_offset, unsigned int item_offset,
int item_length) int item_length)
{ {
hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length); hb_buffer_add_utf<hb_utf16_t> (buffer, text, text_length, item_offset, item_length);
} }
/** /**
@ -1460,7 +1460,29 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
unsigned int item_offset, unsigned int item_offset,
int item_length) int item_length)
{ {
hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length); hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length);
}
/**
* hb_buffer_add_latin1:
* @buffer: a buffer.
* @text: (array length=text_length) (element-type uint8_t):
* @text_length:
* @item_offset:
* @item_length:
*
*
*
* Since: 1.0
**/
void
hb_buffer_add_latin1 (hb_buffer_t *buffer,
const uint8_t *text,
int text_length,
unsigned int item_offset,
int item_length)
{
hb_buffer_add_utf<hb_latin1_t> (buffer, text, text_length, item_offset, item_length);
} }
/** /**
@ -1482,7 +1504,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
unsigned int item_offset, unsigned int item_offset,
int item_length) int item_length)
{ {
hb_buffer_add_utf<false> (buffer, text, text_length, item_offset, item_length); hb_buffer_add_utf<hb_utf32_t<false> > (buffer, text, text_length, item_offset, item_length);
} }

View File

@ -253,6 +253,14 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
unsigned int item_offset, unsigned int item_offset,
int item_length); int item_length);
/* Allows only access to first 256 Unicode codepoints. */
void
hb_buffer_add_latin1 (hb_buffer_t *buffer,
const uint8_t *text,
int text_length,
unsigned int item_offset,
int item_length);
/* Like add_utf32 but does NOT check for invalid Unicode codepoints. */ /* Like add_utf32 but does NOT check for invalid Unicode codepoints. */
void void
hb_buffer_add_codepoints (hb_buffer_t *buffer, hb_buffer_add_codepoints (hb_buffer_t *buffer,

View File

@ -57,7 +57,7 @@ _hb_options_init (void)
/** /**
* hb_tag_from_string: * hb_tag_from_string:
* @str: (array length=len): * @str: (array length=len) (element-type uint8_t):
* @len: * @len:
* *
* *
@ -115,7 +115,7 @@ const char direction_strings[][4] = {
/** /**
* hb_direction_from_string: * hb_direction_from_string:
* @str: (array length=len): * @str: (array length=len) (element-type uint8_t):
* @len: * @len:
* *
* *
@ -179,7 +179,7 @@ static const char canon_map[256] = {
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0
}; };
static hb_bool_t static bool
lang_equal (hb_language_t v1, lang_equal (hb_language_t v1,
const void *v2) const void *v2)
{ {
@ -235,7 +235,7 @@ struct hb_language_item_t {
static hb_language_item_t *langs; static hb_language_item_t *langs;
#ifdef HB_USE_ATEXIT #ifdef HB_USE_ATEXIT
static inline static
void free_langs (void) void free_langs (void)
{ {
while (langs) { while (langs) {
@ -265,6 +265,7 @@ retry:
*lang = key; *lang = key;
if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) { if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
lang->finish ();
free (lang); free (lang);
goto retry; goto retry;
} }
@ -280,12 +281,12 @@ retry:
/** /**
* hb_language_from_string: * hb_language_from_string:
* @str: (array length=len): * @str: (array length=len) (element-type uint8_t):
* @len: * @len:
* *
* *
* *
* Return value: * Return value: (transfer none):
* *
* Since: 1.0 * Since: 1.0
**/ **/
@ -345,7 +346,7 @@ hb_language_get_default (void)
hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language); hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
if (unlikely (language == HB_LANGUAGE_INVALID)) { if (unlikely (language == HB_LANGUAGE_INVALID)) {
language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1); language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1);
hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language); (void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
} }
return default_language; return default_language;
@ -400,7 +401,7 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
/** /**
* hb_script_from_string: * hb_script_from_string:
* @s: (array length=len): * @s: (array length=len) (element-type uint8_t):
* @len: * @len:
* *
* *

View File

@ -140,6 +140,7 @@ hb_coretext_face_get_cg_font (hb_face_t *face)
struct hb_coretext_shaper_font_data_t { struct hb_coretext_shaper_font_data_t {
CTFontRef ct_font; CTFontRef ct_font;
CGFloat x_mult, y_mult; /* From CT space to HB space. */
}; };
hb_coretext_shaper_font_data_t * hb_coretext_shaper_font_data_t *
@ -154,7 +155,17 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
hb_face_t *face = font->face; hb_face_t *face = font->face;
hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
data->ct_font = CTFontCreateWithGraphicsFont (face_data, font->y_scale, NULL, NULL); /* Choose a CoreText font size and calculate multipliers to convert to HarfBuzz space. */
CGFloat font_size = 36.; /* Default... */
/* No idea if the following is even a good idea. */
if (font->y_ppem)
font_size = font->y_ppem;
if (font_size < 0)
font_size = -font_size;
data->x_mult = (CGFloat) font->x_scale / font_size;
data->y_mult = (CGFloat) font->y_scale / font_size;
data->ct_font = CTFontCreateWithGraphicsFont (face_data, font_size, NULL, NULL);
if (unlikely (!data->ct_font)) { if (unlikely (!data->ct_font)) {
DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed");
free (data); free (data);
@ -776,6 +787,18 @@ retry:
buffer->len = 0; buffer->len = 0;
uint32_t status_and = ~0, status_or = 0; uint32_t status_and = ~0, status_or = 0;
double advances_so_far = 0;
/* For right-to-left runs, CoreText returns the glyphs positioned such that
* any trailing whitespace is to the left of (0,0). Adjust coordinate system
* to fix for that. Test with any RTL string with trailing spaces.
* https://code.google.com/p/chromium/issues/detail?id=469028
*/
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
{
advances_so_far -= CTLineGetTrailingWhitespaceWidth (line);
if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
advances_so_far = -advances_so_far;
}
const CFRange range_all = CFRangeMake (0, 0); const CFRange range_all = CFRangeMake (0, 0);
@ -786,6 +809,10 @@ retry:
status_or |= run_status; status_or |= run_status;
status_and &= run_status; status_and &= run_status;
DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status); DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status);
double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL);
if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
run_advance = -run_advance;
DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance);
/* CoreText does automatic font fallback (AKA "cascading") for characters /* CoreText does automatic font fallback (AKA "cascading") for characters
* not supported by the requested font, and provides no way to turn it off, * not supported by the requested font, and provides no way to turn it off,
@ -860,8 +887,14 @@ retry:
goto resize_and_retry; goto resize_and_retry;
hb_glyph_info_t *info = buffer->info + buffer->len; hb_glyph_info_t *info = buffer->info + buffer->len;
CGGlyph notdef = 0; hb_codepoint_t notdef = 0;
double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, &notdef, NULL, 1); hb_direction_t dir = buffer->props.direction;
hb_position_t x_advance, y_advance, x_offset, y_offset;
hb_font_get_glyph_advance_for_direction (font, notdef, dir, &x_advance, &y_advance);
hb_font_get_glyph_origin_for_direction (font, notdef, dir, &x_offset, &y_offset);
hb_position_t advance = x_advance + y_advance;
x_offset = -x_offset;
y_offset = -y_offset;
unsigned int old_len = buffer->len; unsigned int old_len = buffer->len;
for (CFIndex j = range.location; j < range.location + range.length; j++) for (CFIndex j = range.location; j < range.location + range.length; j++)
@ -875,19 +908,22 @@ retry:
* for this one. */ * for this one. */
continue; continue;
} }
if (buffer->unicode->is_default_ignorable (ch))
continue;
info->codepoint = notdef; info->codepoint = notdef;
info->cluster = log_clusters[j]; info->cluster = log_clusters[j];
info->mask = advance; info->mask = advance;
info->var1.u32 = 0; info->var1.u32 = x_offset;
info->var2.u32 = 0; info->var2.u32 = y_offset;
info++; info++;
buffer->len++; buffer->len++;
} }
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
buffer->reverse_range (old_len, buffer->len); buffer->reverse_range (old_len, buffer->len);
advances_so_far += run_advance;
continue; continue;
} }
} }
@ -917,7 +953,7 @@ retry:
scratch_size = scratch_size_saved; \ scratch_size = scratch_size_saved; \
scratch = scratch_saved; scratch = scratch_saved;
{ { /* Setup glyphs */
SCRATCH_SAVE(); SCRATCH_SAVE();
const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : NULL; const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : NULL;
if (!glyphs) { if (!glyphs) {
@ -941,6 +977,11 @@ retry:
SCRATCH_RESTORE(); SCRATCH_RESTORE();
} }
{ {
/* Setup positions.
* Note that CoreText does not return advances for glyphs. As such,
* for all but last glyph, we use the delta position to next glyph as
* advance (in the advance direction only), and for last glyph we set
* whatever is needed to make the whole run's advance add up. */
SCRATCH_SAVE(); SCRATCH_SAVE();
const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : NULL; const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : NULL;
if (!positions) { if (!positions) {
@ -948,33 +989,42 @@ retry:
CTRunGetPositions (run, range_all, position_buf); CTRunGetPositions (run, range_all, position_buf);
positions = position_buf; positions = position_buf;
} }
double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL);
DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance);
hb_glyph_info_t *info = run_info; hb_glyph_info_t *info = run_info;
CGFloat x_mult = font_data->x_mult, y_mult = font_data->y_mult;
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
{ {
hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult;
for (unsigned int j = 0; j < num_glyphs; j++) for (unsigned int j = 0; j < num_glyphs; j++)
{ {
double advance = (j + 1 < num_glyphs ? positions[j + 1].x : positions[0].x + run_advance) - positions[j].x; double advance;
info->mask = advance; if (likely (j + 1 < num_glyphs))
info->var1.u32 = positions[0].x; /* Yes, zero. */ advance = positions[j + 1].x - positions[j].x;
info->var2.u32 = positions[j].y; else /* last glyph */
advance = run_advance - (positions[j].x - positions[0].x);
info->mask = advance * x_mult;
info->var1.u32 = x_offset;
info->var2.u32 = positions[j].y * y_mult;
info++; info++;
} }
} }
else else
{ {
run_advance = -run_advance; hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult;
for (unsigned int j = 0; j < num_glyphs; j++) for (unsigned int j = 0; j < num_glyphs; j++)
{ {
double advance = (j + 1 < num_glyphs ? positions[j + 1].y : positions[0].y + run_advance) - positions[j].y; double advance;
info->mask = advance; if (likely (j + 1 < num_glyphs))
info->var1.u32 = positions[j].x; advance = positions[j + 1].y - positions[j].y;
info->var2.u32 = positions[0].y; /* Yes, zero. */ else /* last glyph */
advance = run_advance - (positions[j].y - positions[0].y);
info->mask = advance * y_mult;
info->var1.u32 = positions[j].x * x_mult;
info->var2.u32 = y_offset;
info++; info++;
} }
} }
SCRATCH_RESTORE(); SCRATCH_RESTORE();
advances_so_far += run_advance;
} }
#undef SCRATCH_RESTORE #undef SCRATCH_RESTORE
#undef SCRATCH_SAVE #undef SCRATCH_SAVE

View File

@ -165,8 +165,8 @@ hb_face_create (hb_blob_t *blob,
{ {
hb_face_t *face; hb_face_t *face;
if (unlikely (!blob || !hb_blob_get_length (blob))) if (unlikely (!blob))
return hb_face_get_empty (); blob = hb_blob_get_empty ();
hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index); hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);

View File

@ -814,7 +814,7 @@ hb_font_glyph_to_string (hb_font_t *font,
/** /**
* hb_font_glyph_from_string: * hb_font_glyph_from_string:
* @font: a font. * @font: a font.
* @s: (array length=len): * @s: (array length=len) (element-type uint8_t):
* @len: * @len:
* @glyph: (out): * @glyph: (out):
* *
@ -854,8 +854,6 @@ hb_font_create (hb_face_t *face)
if (unlikely (!face)) if (unlikely (!face))
face = hb_face_get_empty (); face = hb_face_get_empty ();
if (unlikely (hb_object_is_inert (face)))
return hb_font_get_empty ();
if (!(font = hb_object_create<hb_font_t> ())) if (!(font = hb_object_create<hb_font_t> ()))
return hb_font_get_empty (); return hb_font_get_empty ();
@ -880,7 +878,7 @@ hb_font_t *
hb_font_create_sub_font (hb_font_t *parent) hb_font_create_sub_font (hb_font_t *parent)
{ {
if (unlikely (!parent)) if (unlikely (!parent))
return hb_font_get_empty (); parent = hb_font_get_empty ();
hb_font_t *font = hb_font_create (parent->face); hb_font_t *font = hb_font_create (parent->face);

View File

@ -51,6 +51,13 @@
* In particular, FT_Get_Advance() without the NO_HINTING flag seems to be * In particular, FT_Get_Advance() without the NO_HINTING flag seems to be
* buggy. * buggy.
* *
* FreeType works in 26.6 mode. Clients can decide to use that mode, and everything
* would work fine. However, we also abuse this API for performing in font-space,
* but don't pass the correct flags to FreeType. We just abuse the no-hinting mode
* for that, such that no rounding etc happens. As such, we don't set ppem, and
* pass NO_HINTING around. This seems to work best, until we go ahead and add a full
* load_flags API.
*
* - We don't handle / allow for emboldening / obliqueing. * - We don't handle / allow for emboldening / obliqueing.
* *
* - In the future, we should add constructors to create fonts in font space? * - In the future, we should add constructors to create fonts in font space?
@ -70,12 +77,10 @@ hb_ft_get_glyph (hb_font_t *font HB_UNUSED,
{ {
FT_Face ft_face = (FT_Face) font_data; FT_Face ft_face = (FT_Face) font_data;
#ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX
if (unlikely (variation_selector)) { if (unlikely (variation_selector)) {
*glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector); *glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
return *glyph != 0; return *glyph != 0;
} }
#endif
*glyph = FT_Get_Char_Index (ft_face, unicode); *glyph = FT_Get_Char_Index (ft_face, unicode);
return *glyph != 0; return *glyph != 0;
@ -94,6 +99,9 @@ hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v)))
return 0; return 0;
if (font->x_scale < 0)
v = -v;
return (v + (1<<9)) >> 10; return (v + (1<<9)) >> 10;
} }
@ -110,6 +118,9 @@ hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v)))
return 0; return 0;
if (font->y_scale < 0)
v = -v;
/* Note: FreeType's vertical metrics grows downward while other FreeType coordinates /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
* have a Y growing upward. Hence the extra negation. */ * have a Y growing upward. Hence the extra negation. */
return (-v + (1<<9)) >> 10; return (-v + (1<<9)) >> 10;
@ -146,6 +157,11 @@ hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
*x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX; *x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX;
*y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY); *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY);
if (font->x_scale < 0)
*x = -*x;
if (font->y_scale < 0)
*y = -*y;
return true; return true;
} }
@ -340,11 +356,7 @@ hb_ft_face_create (FT_Face ft_face,
blob = hb_blob_create ((const char *) ft_face->stream->base, blob = hb_blob_create ((const char *) ft_face->stream->base,
(unsigned int) ft_face->stream->size, (unsigned int) ft_face->stream->size,
/* TODO: We assume that it's mmap()'ed, but FreeType code HB_MEMORY_MODE_READONLY,
* suggests that there are cases we reach here but font is
* not mmapped. For example, when mmap() fails. No idea
* how to deal with it better here. */
HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE,
ft_face, destroy); ft_face, destroy);
face = hb_face_create (blob, ft_face->face_index); face = hb_face_create (blob, ft_face->face_index);
hb_blob_destroy (blob); hb_blob_destroy (blob);
@ -358,6 +370,22 @@ hb_ft_face_create (FT_Face ft_face,
return face; return face;
} }
/**
* hb_ft_face_create_referenced:
* @ft_face:
*
*
*
* Return value: (transfer full):
* Since: 1.0
**/
hb_face_t *
hb_ft_face_create_referenced (FT_Face ft_face)
{
FT_Reference_Face (ft_face);
return hb_ft_face_create (ft_face, (hb_destroy_func_t) FT_Done_Face);
}
static void static void
hb_ft_face_finalize (FT_Face ft_face) hb_ft_face_finalize (FT_Face ft_face)
{ {
@ -420,23 +448,43 @@ hb_ft_font_create (FT_Face ft_face,
hb_font_set_scale (font, hb_font_set_scale (font,
(int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16), (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16),
(int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16)); (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16));
#if 0 /* hb-ft works in no-hinting model */
hb_font_set_ppem (font, hb_font_set_ppem (font,
ft_face->size->metrics.x_ppem, ft_face->size->metrics.x_ppem,
ft_face->size->metrics.y_ppem); ft_face->size->metrics.y_ppem);
#endif
return font; return font;
} }
/**
* hb_ft_font_create_referenced:
* @ft_face:
*
*
*
* Return value: (transfer full):
* Since: 1.0
**/
hb_font_t *
hb_ft_font_create_referenced (FT_Face ft_face)
{
FT_Reference_Face (ft_face);
return hb_ft_font_create (ft_face, (hb_destroy_func_t) FT_Done_Face);
}
/* Thread-safe, lock-free, FT_Library */ /* Thread-safe, lock-free, FT_Library */
static FT_Library ft_library; static FT_Library ft_library;
static inline #ifdef HB_USE_ATEXIT
static
void free_ft_library (void) void free_ft_library (void)
{ {
FT_Done_FreeType (ft_library); FT_Done_FreeType (ft_library);
} }
#endif
static FT_Library static FT_Library
get_ft_library (void) get_ft_library (void)
@ -493,14 +541,19 @@ hb_ft_font_set_funcs (hb_font_t *font)
FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE); FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
assert (font->y_scale >= 0);
FT_Set_Char_Size (ft_face, FT_Set_Char_Size (ft_face,
font->x_scale, font->y_scale, abs (font->x_scale), abs (font->y_scale),
0, 0); 0, 0);
#if 0 #if 0
font->x_ppem * 72 * 64 / font->x_scale, font->x_ppem * 72 * 64 / font->x_scale,
font->y_ppem * 72 * 64 / font->y_scale); font->y_ppem * 72 * 64 / font->y_scale);
#endif #endif
if (font->x_scale < 0 || font->y_scale < 0)
{
FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
0, font->y_scale < 0 ? -1 : +1};
FT_Set_Transform (ft_face, &matrix, NULL);
}
ft_face->generic.data = blob; ft_face->generic.data = blob;
ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;

View File

@ -34,19 +34,76 @@
HB_BEGIN_DECLS HB_BEGIN_DECLS
/* Note: FreeType is not thread-safe. Hence, these functions are not either. */ /*
* Note: FreeType is not thread-safe.
* Hence, these functions are not either.
*/
/*
* hb-face from ft-face.
*/
/* This one creates a new hb-face for given ft-face.
* When the returned hb-face is destroyed, the destroy
* callback is called (if not NULL), with the ft-face passed
* to it.
*
* The client is responsible to make sure that ft-face is
* destroyed after hb-face is destroyed.
*
* Most often you don't want this function. You should use either
* hb_ft_face_create_cached(), or hb_ft_face_create_referenced().
* In particular, if you are going to pass NULL as destroy, you
* probably should use (the more recent) hb_ft_face_create_referenced()
* instead.
*/
hb_face_t * hb_face_t *
hb_ft_face_create (FT_Face ft_face, hb_ft_face_create (FT_Face ft_face,
hb_destroy_func_t destroy); hb_destroy_func_t destroy);
/* This version is like hb_ft_face_create(), except that it caches
* the hb-face using the generic pointer of the ft-face. This means
* that subsequent calls to this function with the same ft-face will
* return the same hb-face (correctly referenced).
*
* Client is still responsible for making sure that ft-face is destroyed
* after hb-face is.
*/
hb_face_t * hb_face_t *
hb_ft_face_create_cached (FT_Face ft_face); hb_ft_face_create_cached (FT_Face ft_face);
/* This version is like hb_ft_face_create(), except that it calls
* FT_Reference_Face() on ft-face, as such keeping ft-face alive
* as long as the hb-face is.
*
* This is the most convenient version to use. Use it unless you have
* very good reasons not to.
*/
hb_face_t *
hb_ft_face_create_referenced (FT_Face ft_face);
/*
* hb-font from ft-face.
*/
/*
* Note:
*
* Set face size on ft-face before creating hb-font from it.
* Otherwise hb-ft would NOT pick up the font size correctly.
*/
/* See notes on hb_ft_face_create(). Same issues re lifecycle-management
* apply here. Use hb_ft_font_create_referenced() if you can. */
hb_font_t * hb_font_t *
hb_ft_font_create (FT_Face ft_face, hb_ft_font_create (FT_Face ft_face,
hb_destroy_func_t destroy); hb_destroy_func_t destroy);
/* See notes on hb_ft_face_create_referenced() re lifecycle-management
* issues. */
hb_font_t *
hb_ft_font_create_referenced (FT_Face ft_face);
/* Makes an hb_font_t use FreeType internally to implement font functions. */ /* Makes an hb_font_t use FreeType internally to implement font functions. */

View File

@ -382,3 +382,14 @@ hb_glib_get_unicode_funcs (void)
return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs); return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
} }
hb_blob_t *
hb_glib_blob_create (GBytes *gbytes)
{
gsize size = 0;
gconstpointer data = g_bytes_get_data (gbytes, &size);
return hb_blob_create ((const char *) data,
size,
HB_MEMORY_MODE_READONLY,
g_bytes_ref (gbytes),
(hb_destroy_func_t) g_bytes_unref);
}

View File

@ -46,6 +46,9 @@ hb_glib_script_from_script (hb_script_t script);
hb_unicode_funcs_t * hb_unicode_funcs_t *
hb_glib_get_unicode_funcs (void); hb_glib_get_unicode_funcs (void);
hb_blob_t *
hb_glib_blob_create (GBytes *gbytes);
HB_END_DECLS HB_END_DECLS

View File

@ -363,10 +363,8 @@ hb_icu_get_unicode_funcs (void)
if (!hb_atomic_ptr_get (&normalizer)) { if (!hb_atomic_ptr_get (&normalizer)) {
UErrorCode icu_err = U_ZERO_ERROR; UErrorCode icu_err = U_ZERO_ERROR;
/* We ignore failure in getNFCInstace(). */ /* We ignore failure in getNFCInstace(). */
hb_atomic_ptr_cmpexch (&normalizer, NULL, unorm2_getNFCInstance (&icu_err)); (void) hb_atomic_ptr_cmpexch (&normalizer, NULL, unorm2_getNFCInstance (&icu_err));
} }
#endif #endif
return const_cast<hb_unicode_funcs_t *> (&_hb_icu_unicode_funcs); return const_cast<hb_unicode_funcs_t *> (&_hb_icu_unicode_funcs);
} }

View File

@ -39,7 +39,13 @@
/* We need external help for these */ /* We need external help for these */
#if 0 #if defined(HB_MUTEX_IMPL_INIT) \
&& defined(hb_mutex_impl_init) \
&& defined(hb_mutex_impl_lock) \
&& defined(hb_mutex_impl_unlock) \
&& defined(hb_mutex_impl_finish)
/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */
#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) #elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
@ -47,7 +53,11 @@
#include <windows.h> #include <windows.h>
typedef CRITICAL_SECTION hb_mutex_impl_t; typedef CRITICAL_SECTION hb_mutex_impl_t;
#define HB_MUTEX_IMPL_INIT {0} #define HB_MUTEX_IMPL_INIT {0}
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
#define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0)
#else
#define hb_mutex_impl_init(M) InitializeCriticalSection (M) #define hb_mutex_impl_init(M) InitializeCriticalSection (M)
#endif
#define hb_mutex_impl_lock(M) EnterCriticalSection (M) #define hb_mutex_impl_lock(M) EnterCriticalSection (M)
#define hb_mutex_impl_unlock(M) LeaveCriticalSection (M) #define hb_mutex_impl_unlock(M) LeaveCriticalSection (M)
#define hb_mutex_impl_finish(M) DeleteCriticalSection (M) #define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
@ -109,10 +119,12 @@ typedef int hb_mutex_impl_t;
#define hb_mutex_impl_unlock(M) HB_STMT_START {} HB_STMT_END #define hb_mutex_impl_unlock(M) HB_STMT_START {} HB_STMT_END
#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END #define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
#endif #endif
#define HB_MUTEX_INIT {HB_MUTEX_IMPL_INIT} #define HB_MUTEX_INIT {HB_MUTEX_IMPL_INIT}
struct hb_mutex_t struct hb_mutex_t
{ {
/* TODO Add tracing. */ /* TODO Add tracing. */

View File

@ -47,19 +47,20 @@
/* reference_count */ /* reference_count */
#define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1) #define HB_REFERENCE_COUNT_INVALID_VALUE -1
#define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE} #define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT(HB_REFERENCE_COUNT_INVALID_VALUE)}
struct hb_reference_count_t struct hb_reference_count_t
{ {
hb_atomic_int_t ref_count; hb_atomic_int_t ref_count;
inline void init (int v) { ref_count = v; } inline void init (int v) { ref_count.set_unsafe (v); }
inline int inc (void) { return hb_atomic_int_add (const_cast<hb_atomic_int_t &> (ref_count), 1); } inline int get_unsafe (void) const { return ref_count.get_unsafe (); }
inline int dec (void) { return hb_atomic_int_add (const_cast<hb_atomic_int_t &> (ref_count), -1); } inline int inc (void) { return ref_count.inc (); }
inline void finish (void) { ref_count = HB_REFERENCE_COUNT_INVALID_VALUE; } inline int dec (void) { return ref_count.dec (); }
inline void finish (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_INVALID_VALUE); }
inline bool is_invalid (void) const { return ref_count == HB_REFERENCE_COUNT_INVALID_VALUE; }
inline bool is_invalid (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INVALID_VALUE; }
}; };
@ -102,7 +103,7 @@ struct hb_object_header_t
hb_reference_count_t ref_count; hb_reference_count_t ref_count;
hb_user_data_array_t user_data; hb_user_data_array_t user_data;
#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID, HB_USER_DATA_ARRAY_INIT} #define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, HB_USER_DATA_ARRAY_INIT}
private: private:
ASSERT_POD (); ASSERT_POD ();
@ -117,7 +118,7 @@ static inline void hb_object_trace (const Type *obj, const char *function)
DEBUG_MSG (OBJECT, (void *) obj, DEBUG_MSG (OBJECT, (void *) obj,
"%s refcount=%d", "%s refcount=%d",
function, function,
obj ? obj->header.ref_count.ref_count : 0); obj ? obj->header.ref_count.get_unsafe () : 0);
} }
template <typename Type> template <typename Type>

View File

@ -53,7 +53,8 @@ struct TTCHeader;
typedef struct TableRecord typedef struct TableRecord
{ {
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this)); return TRACE_RETURN (c->check_struct (this));
} }
@ -102,7 +103,8 @@ typedef struct OffsetTable
} }
public: public:
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables)); return TRACE_RETURN (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables));
} }
@ -130,7 +132,8 @@ struct TTCHeaderVersion1
inline unsigned int get_face_count (void) const { return table.len; } inline unsigned int get_face_count (void) const { return table.len; }
inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; } inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (table.sanitize (c, this)); return TRACE_RETURN (table.sanitize (c, this));
} }
@ -169,7 +172,8 @@ struct TTCHeader
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!u.header.version.sanitize (c))) return TRACE_RETURN (false); if (unlikely (!u.header.version.sanitize (c))) return TRACE_RETURN (false);
switch (u.header.version.major) { switch (u.header.version.major) {
@ -233,7 +237,8 @@ struct OpenTypeFontFile
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!u.tag.sanitize (c))) return TRACE_RETURN (false); if (unlikely (!u.tag.sanitize (c))) return TRACE_RETURN (false);
switch (u.tag) { switch (u.tag) {

View File

@ -179,10 +179,13 @@ struct hb_sanitize_context_t
inline const char *get_name (void) { return "SANITIZE"; } inline const char *get_name (void) { return "SANITIZE"; }
static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE; static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE;
typedef bool return_t; typedef bool return_t;
template <typename T, typename F>
inline bool may_dispatch (const T *obj, const F *format)
{ return format->sanitize (this); }
template <typename T> template <typename T>
inline return_t dispatch (const T &obj) { return obj.sanitize (this); } inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
static return_t default_return_value (void) { return true; } static return_t default_return_value (void) { return true; }
bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; } bool stop_sublookup_iteration (const return_t r) const { return !r; }
inline void init (hb_blob_t *b) inline void init (hb_blob_t *b)
{ {
@ -270,9 +273,9 @@ struct hb_sanitize_context_t
} }
template <typename Type, typename ValueType> template <typename Type, typename ValueType>
inline bool try_set (Type *obj, const ValueType &v) { inline bool try_set (const Type *obj, const ValueType &v) {
if (this->may_edit (obj, obj->static_size)) { if (this->may_edit (obj, obj->static_size)) {
obj->set (v); const_cast<Type *> (obj)->set (v);
return true; return true;
} }
return false; return false;
@ -546,12 +549,6 @@ struct BEInt<Type, 2>
return (v[0] << 8) return (v[0] << 8)
+ (v[1] ); + (v[1] );
} }
inline bool operator == (const BEInt<Type, 2>& o) const
{
return v[0] == o.v[0]
&& v[1] == o.v[1];
}
inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
private: uint8_t v[2]; private: uint8_t v[2];
}; };
template <typename Type> template <typename Type>
@ -570,13 +567,6 @@ struct BEInt<Type, 3>
+ (v[1] << 8) + (v[1] << 8)
+ (v[2] ); + (v[2] );
} }
inline bool operator == (const BEInt<Type, 3>& o) const
{
return v[0] == o.v[0]
&& v[1] == o.v[1]
&& v[2] == o.v[2];
}
inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o); }
private: uint8_t v[3]; private: uint8_t v[3];
}; };
template <typename Type> template <typename Type>
@ -597,14 +587,6 @@ struct BEInt<Type, 4>
+ (v[2] << 8) + (v[2] << 8)
+ (v[3] ); + (v[3] );
} }
inline bool operator == (const BEInt<Type, 4>& o) const
{
return v[0] == o.v[0]
&& v[1] == o.v[1]
&& v[2] == o.v[2]
&& v[3] == o.v[3];
}
inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
private: uint8_t v[4]; private: uint8_t v[4];
}; };
@ -614,12 +596,19 @@ struct IntType
{ {
inline void set (Type i) { v.set (i); } inline void set (Type i) { v.set (i); }
inline operator Type(void) const { return v; } inline operator Type(void) const { return v; }
inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v; } inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v; } inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); } static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
inline int cmp (IntType<Type,Size> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; } inline int cmp (Type a) const
inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; } {
inline bool sanitize (hb_sanitize_context_t *c) { Type b = v;
if (sizeof (Type) < sizeof (int))
return (int) a - (int) b;
else
return a < b ? -1 : a == b ? 0 : +1;
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (likely (c->check_struct (this))); return TRACE_RETURN (likely (c->check_struct (this)));
} }
@ -646,7 +635,8 @@ typedef USHORT UFWORD;
* 1904. The value is represented as a signed 64-bit integer. */ * 1904. The value is represented as a signed 64-bit integer. */
struct LONGDATETIME struct LONGDATETIME
{ {
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (likely (c->check_struct (this))); return TRACE_RETURN (likely (c->check_struct (this)));
} }
@ -670,7 +660,10 @@ struct Tag : ULONG
DEFINE_NULL_DATA (Tag, " "); DEFINE_NULL_DATA (Tag, " ");
/* Glyph index number, same as uint16 (length = 16 bits) */ /* Glyph index number, same as uint16 (length = 16 bits) */
typedef USHORT GlyphID; struct GlyphID : USHORT {
static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT::cmp (*a); }
inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; }
};
/* Script/language-system/feature index */ /* Script/language-system/feature index */
struct Index : USHORT { struct Index : USHORT {
@ -719,7 +712,8 @@ struct FixedVersion
{ {
inline uint32_t to_int (void) const { return (major << 16) + minor; } inline uint32_t to_int (void) const { return (major << 16) + minor; }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this)); return TRACE_RETURN (c->check_struct (this));
} }
@ -747,33 +741,35 @@ struct OffsetTo : Offset<OffsetType>
return StructAtOffset<Type> (base, offset); return StructAtOffset<Type> (base, offset);
} }
inline Type& serialize (hb_serialize_context_t *c, void *base) inline Type& serialize (hb_serialize_context_t *c, const void *base)
{ {
Type *t = c->start_embed<Type> (); Type *t = c->start_embed<Type> ();
this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
return *t; return *t;
} }
inline bool sanitize (hb_sanitize_context_t *c, void *base) { inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
unsigned int offset = *this; unsigned int offset = *this;
if (unlikely (!offset)) return TRACE_RETURN (true); if (unlikely (!offset)) return TRACE_RETURN (true);
Type &obj = StructAtOffset<Type> (base, offset); const Type &obj = StructAtOffset<Type> (base, offset);
return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c)); return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c));
} }
template <typename T> template <typename T>
inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
unsigned int offset = *this; unsigned int offset = *this;
if (unlikely (!offset)) return TRACE_RETURN (true); if (unlikely (!offset)) return TRACE_RETURN (true);
Type &obj = StructAtOffset<Type> (base, offset); const Type &obj = StructAtOffset<Type> (base, offset);
return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c));
} }
/* Set the offset to Null */ /* Set the offset to Null */
inline bool neuter (hb_sanitize_context_t *c) { inline bool neuter (hb_sanitize_context_t *c) const {
return c->try_set (this, 0); return c->try_set (this, 0);
} }
DEFINE_SIZE_STATIC (sizeof(OffsetType)); DEFINE_SIZE_STATIC (sizeof(OffsetType));
@ -838,7 +834,8 @@ struct ArrayOf
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
@ -853,7 +850,8 @@ struct ArrayOf
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c, void *base) { inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
unsigned int count = len; unsigned int count = len;
@ -863,7 +861,8 @@ struct ArrayOf
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
template <typename T> template <typename T>
inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
unsigned int count = len; unsigned int count = len;
@ -884,7 +883,8 @@ struct ArrayOf
} }
private: private:
inline bool sanitize_shallow (hb_sanitize_context_t *c) { inline bool sanitize_shallow (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len)); return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len));
} }
@ -910,12 +910,14 @@ struct OffsetListOf : OffsetArrayOf<Type>
return this+this->array[i]; return this+this->array[i];
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this)); return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this));
} }
template <typename T> template <typename T>
inline bool sanitize (hb_sanitize_context_t *c, T user_data) { inline bool sanitize (hb_sanitize_context_t *c, T user_data) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data)); return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data));
} }
@ -949,12 +951,14 @@ struct HeadlessArrayOf
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize_shallow (hb_sanitize_context_t *c) { inline bool sanitize_shallow (hb_sanitize_context_t *c) const
{
return c->check_struct (this) return c->check_struct (this)
&& c->check_array (this, Type::static_size, len); && c->check_array (this, Type::static_size, len);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);

View File

@ -51,7 +51,8 @@ struct CmapSubtableFormat0
return true; return true;
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this)); return TRACE_RETURN (c->check_struct (this));
} }
@ -125,7 +126,7 @@ struct CmapSubtableFormat4
return true; return true;
} }
inline bool sanitize (hb_sanitize_context_t *c) inline bool sanitize (hb_sanitize_context_t *c) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this))) if (unlikely (!c->check_struct (this)))
@ -183,7 +184,8 @@ struct CmapSubtableLongGroup
return 0; return 0;
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this)); return TRACE_RETURN (c->check_struct (this));
} }
@ -210,7 +212,8 @@ struct CmapSubtableTrimmed
return true; return true;
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && glyphIdArray.sanitize (c)); return TRACE_RETURN (c->check_struct (this) && glyphIdArray.sanitize (c));
} }
@ -242,7 +245,8 @@ struct CmapSubtableLongSegmented
return true; return true;
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && groups.sanitize (c)); return TRACE_RETURN (c->check_struct (this) && groups.sanitize (c));
} }
@ -288,7 +292,8 @@ struct UnicodeValueRange
return 0; return 0;
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this)); return TRACE_RETURN (c->check_struct (this));
} }
@ -309,7 +314,8 @@ struct UVSMapping
return unicodeValue.cmp (codepoint); return unicodeValue.cmp (codepoint);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this)); return TRACE_RETURN (c->check_struct (this));
} }
@ -348,7 +354,8 @@ struct VariationSelectorRecord
return varSelector.cmp (variation_selector); return varSelector.cmp (variation_selector);
} }
inline bool sanitize (hb_sanitize_context_t *c, void *base) { inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && return TRACE_RETURN (c->check_struct (this) &&
defaultUVS.sanitize (c, base) && defaultUVS.sanitize (c, base) &&
@ -373,7 +380,8 @@ struct CmapSubtableFormat14
return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this); return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && return TRACE_RETURN (c->check_struct (this) &&
record.sanitize (c, this)); record.sanitize (c, this));
@ -418,7 +426,8 @@ struct CmapSubtable
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false); if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) { switch (u.format) {
@ -461,7 +470,8 @@ struct EncodingRecord
return 0; return 0;
} }
inline bool sanitize (hb_sanitize_context_t *c, void *base) { inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && return TRACE_RETURN (c->check_struct (this) &&
subtable.sanitize (c, base)); subtable.sanitize (c, base));
@ -496,7 +506,8 @@ struct cmap
return &(this+encodingRecord[result].subtable); return &(this+encodingRecord[result].subtable);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && return TRACE_RETURN (c->check_struct (this) &&
likely (version == 0) && likely (version == 0) &&

View File

@ -45,9 +45,9 @@ struct hb_ot_face_metrics_accelerator_t
inline void init (hb_face_t *face, inline void init (hb_face_t *face,
hb_tag_t _hea_tag, hb_tag_t _mtx_tag, hb_tag_t _hea_tag, hb_tag_t _mtx_tag,
unsigned int default_advance) unsigned int default_advance_)
{ {
this->default_advance = default_advance; this->default_advance = default_advance_;
this->num_metrics = face->get_num_glyphs (); this->num_metrics = face->get_num_glyphs ();
hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag)); hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag));
@ -114,6 +114,7 @@ struct hb_ot_face_cmap_accelerator_t
if (!subtable) subtable = cmap->find_subtable (0, 2); if (!subtable) subtable = cmap->find_subtable (0, 2);
if (!subtable) subtable = cmap->find_subtable (0, 1); if (!subtable) subtable = cmap->find_subtable (0, 1);
if (!subtable) subtable = cmap->find_subtable (0, 0); if (!subtable) subtable = cmap->find_subtable (0, 0);
if (!subtable) subtable = cmap->find_subtable (3, 0);
/* Meh. */ /* Meh. */
if (!subtable) subtable = &OT::Null(OT::CmapSubtable); if (!subtable) subtable = &OT::Null(OT::CmapSubtable);

View File

@ -45,13 +45,15 @@ struct head
{ {
static const hb_tag_t tableTag = HB_OT_TAG_head; static const hb_tag_t tableTag = HB_OT_TAG_head;
inline unsigned int get_upem (void) const { inline unsigned int get_upem (void) const
{
unsigned int upem = unitsPerEm; unsigned int upem = unitsPerEm;
/* If no valid head table found, assume 1000, which matches typical Type1 usage. */ /* If no valid head table found, assume 1000, which matches typical Type1 usage. */
return 16 <= upem && upem <= 16384 ? upem : 1000; return 16 <= upem && upem <= 16384 ? upem : 1000;
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1)); return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
} }

View File

@ -49,7 +49,8 @@ struct _hea
static const hb_tag_t hheaTag = HB_OT_TAG_hhea; static const hb_tag_t hheaTag = HB_OT_TAG_hhea;
static const hb_tag_t vheaTag = HB_OT_TAG_vhea; static const hb_tag_t vheaTag = HB_OT_TAG_vhea;
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1)); return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
} }

View File

@ -57,7 +57,8 @@ struct _mtx
static const hb_tag_t hmtxTag = HB_OT_TAG_hmtx; static const hb_tag_t hmtxTag = HB_OT_TAG_hmtx;
static const hb_tag_t vmtxTag = HB_OT_TAG_vmtx; static const hb_tag_t vmtxTag = HB_OT_TAG_vmtx;
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
/* We don't check for anything specific here. The users of the /* We don't check for anything specific here. The users of the
* struct do all the hard work... */ * struct do all the hard work... */

View File

@ -37,6 +37,12 @@
namespace OT { namespace OT {
#define TRACE_DISPATCH(this, format) \
hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"format %d", (int) format);
#define NOT_COVERED ((unsigned int) -1) #define NOT_COVERED ((unsigned int) -1)
#define MAX_NESTING_LEVEL 8 #define MAX_NESTING_LEVEL 8
#define MAX_CONTEXT_LENGTH 64 #define MAX_CONTEXT_LENGTH 64
@ -63,9 +69,10 @@ struct Record
struct sanitize_closure_t { struct sanitize_closure_t {
hb_tag_t tag; hb_tag_t tag;
void *list_base; const void *list_base;
}; };
inline bool sanitize (hb_sanitize_context_t *c, void *base) { inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
const sanitize_closure_t closure = {tag, base}; const sanitize_closure_t closure = {tag, base};
return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base, &closure)); return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base, &closure));
@ -121,7 +128,8 @@ struct RecordListOf : RecordArrayOf<Type>
inline const Type& operator [] (unsigned int i) const inline const Type& operator [] (unsigned int i) const
{ return this+RecordArrayOf<Type>::operator [](i).offset; } { return this+RecordArrayOf<Type>::operator [](i).offset; }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (RecordArrayOf<Type>::sanitize (c, this)); return TRACE_RETURN (RecordArrayOf<Type>::sanitize (c, this));
} }
@ -134,7 +142,8 @@ struct RangeRecord
return g < start ? -1 : g <= end ? 0 : +1 ; return g < start ? -1 : g <= end ? 0 : +1 ;
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this)); return TRACE_RETURN (c->check_struct (this));
} }
@ -199,7 +208,8 @@ struct LangSys
} }
inline bool sanitize (hb_sanitize_context_t *c, inline bool sanitize (hb_sanitize_context_t *c,
const Record<LangSys>::sanitize_closure_t * = NULL) { const Record<LangSys>::sanitize_closure_t * = NULL) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c)); return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c));
} }
@ -238,7 +248,8 @@ struct Script
inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
inline bool sanitize (hb_sanitize_context_t *c, inline bool sanitize (hb_sanitize_context_t *c,
const Record<Script>::sanitize_closure_t * = NULL) { const Record<Script>::sanitize_closure_t * = NULL) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this)); return TRACE_RETURN (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
} }
@ -260,7 +271,8 @@ typedef RecordListOf<Script> ScriptList;
/* http://www.microsoft.com/typography/otspec/features_pt.htm#size */ /* http://www.microsoft.com/typography/otspec/features_pt.htm#size */
struct FeatureParamsSize struct FeatureParamsSize
{ {
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
@ -371,7 +383,8 @@ struct FeatureParamsSize
/* http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx */ /* http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx */
struct FeatureParamsStylisticSet struct FeatureParamsStylisticSet
{ {
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
/* Right now minorVersion is at zero. Which means, any table supports /* Right now minorVersion is at zero. Which means, any table supports
* the uiNameID field. */ * the uiNameID field. */
@ -404,7 +417,8 @@ struct FeatureParamsStylisticSet
/* http://www.microsoft.com/typography/otspec/features_ae.htm#cv01-cv99 */ /* http://www.microsoft.com/typography/otspec/features_ae.htm#cv01-cv99 */
struct FeatureParamsCharacterVariants struct FeatureParamsCharacterVariants
{ {
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && return TRACE_RETURN (c->check_struct (this) &&
characters.sanitize (c)); characters.sanitize (c));
@ -444,7 +458,8 @@ struct FeatureParamsCharacterVariants
struct FeatureParams struct FeatureParams
{ {
inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) { inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (tag == HB_TAG ('s','i','z','e')) if (tag == HB_TAG ('s','i','z','e'))
return TRACE_RETURN (u.size.sanitize (c)); return TRACE_RETURN (u.size.sanitize (c));
@ -486,7 +501,8 @@ struct Feature
{ return this+featureParams; } { return this+featureParams; }
inline bool sanitize (hb_sanitize_context_t *c, inline bool sanitize (hb_sanitize_context_t *c,
const Record<Feature>::sanitize_closure_t *closure) { const Record<Feature>::sanitize_closure_t *closure) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c)))) if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
return TRACE_RETURN (false); return TRACE_RETURN (false);
@ -561,6 +577,17 @@ struct Lookup
{ {
inline unsigned int get_subtable_count (void) const { return subTable.len; } inline unsigned int get_subtable_count (void) const { return subTable.len; }
template <typename SubTableType>
inline const SubTableType& get_subtable (unsigned int i) const
{ return this+CastR<OffsetArrayOf<SubTableType> > (subTable)[i]; }
template <typename SubTableType>
inline const OffsetArrayOf<SubTableType>& get_subtables (void) const
{ return CastR<OffsetArrayOf<SubTableType> > (subTable); }
template <typename SubTableType>
inline OffsetArrayOf<SubTableType>& get_subtables (void)
{ return CastR<OffsetArrayOf<SubTableType> > (subTable); }
inline unsigned int get_type (void) const { return lookupType; } inline unsigned int get_type (void) const { return lookupType; }
/* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
@ -577,6 +604,20 @@ struct Lookup
return flag; return flag;
} }
template <typename SubTableType, typename context_t>
inline typename context_t::return_t dispatch (context_t *c) const
{
unsigned int lookup_type = get_type ();
TRACE_DISPATCH (this, lookup_type);
unsigned int count = get_subtable_count ();
for (unsigned int i = 0; i < count; i++) {
typename context_t::return_t r = get_subtable<SubTableType> (i).dispatch (c, lookup_type);
if (c->stop_sublookup_iteration (r))
return TRACE_RETURN (r);
}
return TRACE_RETURN (c->default_return_value ());
}
inline bool serialize (hb_serialize_context_t *c, inline bool serialize (hb_serialize_context_t *c,
unsigned int lookup_type, unsigned int lookup_type,
uint32_t lookup_props, uint32_t lookup_props,
@ -595,18 +636,20 @@ struct Lookup
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
/* Real sanitize of the subtables is done by GSUB/GPOS/... */ /* Real sanitize of the subtables is done by GSUB/GPOS/... */
if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false); if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false);
if (lookupFlag & LookupFlag::UseMarkFilteringSet) if (lookupFlag & LookupFlag::UseMarkFilteringSet)
{ {
USHORT &markFilteringSet = StructAfter<USHORT> (subTable); const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false); if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false);
} }
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
private:
USHORT lookupType; /* Different enumerations for GSUB and GPOS */ USHORT lookupType; /* Different enumerations for GSUB and GPOS */
USHORT lookupFlag; /* Lookup qualifiers */ USHORT lookupFlag; /* Lookup qualifiers */
ArrayOf<Offset<> > ArrayOf<Offset<> >
@ -651,7 +694,8 @@ struct CoverageFormat1
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (glyphArray.sanitize (c)); return TRACE_RETURN (glyphArray.sanitize (c));
} }
@ -737,7 +781,8 @@ struct CoverageFormat2
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (rangeRecord.sanitize (c)); return TRACE_RETURN (rangeRecord.sanitize (c));
} }
@ -832,7 +877,8 @@ struct Coverage
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false); if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) { switch (u.format) {
@ -938,12 +984,14 @@ struct ClassDefFormat1
private: private:
inline unsigned int get_class (hb_codepoint_t glyph_id) const inline unsigned int get_class (hb_codepoint_t glyph_id) const
{ {
if (unlikely ((unsigned int) (glyph_id - startGlyph) < classValue.len)) unsigned int i = (unsigned int) (glyph_id - startGlyph);
return classValue[glyph_id - startGlyph]; if (unlikely (i < classValue.len))
return classValue[i];
return 0; return 0;
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && classValue.sanitize (c)); return TRACE_RETURN (c->check_struct (this) && classValue.sanitize (c));
} }
@ -994,12 +1042,13 @@ struct ClassDefFormat2
inline unsigned int get_class (hb_codepoint_t glyph_id) const inline unsigned int get_class (hb_codepoint_t glyph_id) const
{ {
int i = rangeRecord.bsearch (glyph_id); int i = rangeRecord.bsearch (glyph_id);
if (i != -1) if (unlikely (i != -1))
return rangeRecord[i].value; return rangeRecord[i].value;
return 0; return 0;
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (rangeRecord.sanitize (c)); return TRACE_RETURN (rangeRecord.sanitize (c));
} }
@ -1056,7 +1105,8 @@ struct ClassDef
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false); if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) { switch (u.format) {
@ -1148,7 +1198,8 @@ struct Device
return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f))); return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && c->check_range (this, this->get_size ())); return TRACE_RETURN (c->check_struct (this) && c->check_range (this, this->get_size ()));
} }

View File

@ -71,7 +71,8 @@ struct AttachList
return points.len; return points.len;
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (coverage.sanitize (c, this) && attachPoint.sanitize (c, this)); return TRACE_RETURN (coverage.sanitize (c, this) && attachPoint.sanitize (c, this));
} }
@ -101,7 +102,8 @@ struct CaretValueFormat1
return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate); return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this)); return TRACE_RETURN (c->check_struct (this));
} }
@ -127,7 +129,8 @@ struct CaretValueFormat2
return 0; return 0;
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this)); return TRACE_RETURN (c->check_struct (this));
} }
@ -150,7 +153,8 @@ struct CaretValueFormat3
font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font); font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && deviceTable.sanitize (c, this)); return TRACE_RETURN (c->check_struct (this) && deviceTable.sanitize (c, this));
} }
@ -178,7 +182,8 @@ struct CaretValue
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false); if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) { switch (u.format) {
@ -219,7 +224,8 @@ struct LigGlyph
return carets.len; return carets.len;
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (carets.sanitize (c, this)); return TRACE_RETURN (carets.sanitize (c, this));
} }
@ -253,7 +259,8 @@ struct LigCaretList
return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this)); return TRACE_RETURN (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
} }
@ -275,7 +282,8 @@ struct MarkGlyphSetsFormat1
inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
{ return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (coverage.sanitize (c, this)); return TRACE_RETURN (coverage.sanitize (c, this));
} }
@ -299,7 +307,8 @@ struct MarkGlyphSets
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false); if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) { switch (u.format) {
@ -364,7 +373,8 @@ struct GDEF
inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
{ return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); } { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (version.sanitize (c) && return TRACE_RETURN (version.sanitize (c) &&
likely (version.major == 1) && likely (version.major == 1) &&

View File

@ -146,7 +146,8 @@ struct ValueFormat : USHORT
} }
private: private:
inline bool sanitize_value_devices (hb_sanitize_context_t *c, void *base, Value *values) { inline bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
{
unsigned int format = *this; unsigned int format = *this;
if (format & xPlacement) values++; if (format & xPlacement) values++;
@ -177,12 +178,14 @@ struct ValueFormat : USHORT
return (format & devices) != 0; return (format & devices) != 0;
} }
inline bool sanitize_value (hb_sanitize_context_t *c, void *base, Value *values) { inline bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values))); return TRACE_RETURN (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
} }
inline bool sanitize_values (hb_sanitize_context_t *c, void *base, Value *values, unsigned int count) { inline bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
unsigned int len = get_len (); unsigned int len = get_len ();
@ -200,7 +203,8 @@ struct ValueFormat : USHORT
} }
/* Just sanitize referenced Device tables. Doesn't check the values themselves. */ /* Just sanitize referenced Device tables. Doesn't check the values themselves. */
inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, void *base, Value *values, unsigned int count, unsigned int stride) { inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!has_device ()) return TRACE_RETURN (true); if (!has_device ()) return TRACE_RETURN (true);
@ -225,7 +229,8 @@ struct AnchorFormat1
*y = font->em_scale_y (yCoordinate); *y = font->em_scale_y (yCoordinate);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this)); return TRACE_RETURN (c->check_struct (this));
} }
@ -254,7 +259,8 @@ struct AnchorFormat2
*y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate); *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this)); return TRACE_RETURN (c->check_struct (this));
} }
@ -282,7 +288,8 @@ struct AnchorFormat3
*y += (this+yDeviceTable).get_x_delta (font); *y += (this+yDeviceTable).get_x_delta (font);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this)); return TRACE_RETURN (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
} }
@ -317,7 +324,8 @@ struct Anchor
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false); if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) { switch (u.format) {
@ -349,7 +357,8 @@ struct AnchorMatrix
return this+matrixZ[row * cols + col]; return this+matrixZ[row * cols + col];
} }
inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) { inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!c->check_struct (this)) return TRACE_RETURN (false); if (!c->check_struct (this)) return TRACE_RETURN (false);
if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return TRACE_RETURN (false); if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return TRACE_RETURN (false);
@ -374,7 +383,8 @@ struct MarkRecord
{ {
friend struct MarkArray; friend struct MarkArray;
inline bool sanitize (hb_sanitize_context_t *c, void *base) { inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && markAnchor.sanitize (c, base)); return TRACE_RETURN (c->check_struct (this) && markAnchor.sanitize (c, base));
} }
@ -421,7 +431,8 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (ArrayOf<MarkRecord>::sanitize (c, this)); return TRACE_RETURN (ArrayOf<MarkRecord>::sanitize (c, this));
} }
@ -457,9 +468,12 @@ struct SinglePosFormat1
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && valueFormat.sanitize_value (c, this, values)); return TRACE_RETURN (c->check_struct (this)
&& coverage.sanitize (c, this)
&& valueFormat.sanitize_value (c, this, values));
} }
protected: protected:
@ -506,9 +520,12 @@ struct SinglePosFormat2
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && valueFormat.sanitize_values (c, this, values, valueCount)); return TRACE_RETURN (c->check_struct (this)
&& coverage.sanitize (c, this)
&& valueFormat.sanitize_values (c, this, values, valueCount));
} }
protected: protected:
@ -531,6 +548,7 @@ struct SinglePos
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
TRACE_DISPATCH (this, u.format); TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 1: return TRACE_RETURN (c->dispatch (u.format1));
case 2: return TRACE_RETURN (c->dispatch (u.format2)); case 2: return TRACE_RETURN (c->dispatch (u.format2));
@ -538,16 +556,6 @@ struct SinglePos
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
case 2: return TRACE_RETURN (u.format2.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
@ -602,12 +610,24 @@ struct PairSet
unsigned int len2 = valueFormats[1].get_len (); unsigned int len2 = valueFormats[1].get_len ();
unsigned int record_size = USHORT::static_size * (1 + len1 + len2); unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
const PairValueRecord *record = CastP<PairValueRecord> (arrayZ); const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
unsigned int count = len; unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
/* Hand-coded bsearch. */
if (unlikely (!count))
return TRACE_RETURN (false);
hb_codepoint_t x = buffer->info[pos].codepoint;
int min = 0, max = (int) count - 1;
while (min <= max)
{ {
/* TODO bsearch */ int mid = (min + max) / 2;
if (buffer->info[pos].codepoint == record->secondGlyph) const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid);
hb_codepoint_t mid_x = record->secondGlyph;
if (x < mid_x)
max = mid - 1;
else if (x > mid_x)
min = mid + 1;
else
{ {
valueFormats[0].apply_value (c->font, c->direction, this, valueFormats[0].apply_value (c->font, c->direction, this,
&record->values[0], buffer->cur_pos()); &record->values[0], buffer->cur_pos());
@ -618,26 +638,26 @@ struct PairSet
buffer->idx = pos; buffer->idx = pos;
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
record = &StructAtOffset<PairValueRecord> (record, record_size);
} }
return TRACE_RETURN (false); return TRACE_RETURN (false);
} }
struct sanitize_closure_t { struct sanitize_closure_t {
void *base; const void *base;
ValueFormat *valueFormats; const ValueFormat *valueFormats;
unsigned int len1; /* valueFormats[0].get_len() */ unsigned int len1; /* valueFormats[0].get_len() */
unsigned int stride; /* 1 + len1 + len2 */ unsigned int stride; /* 1 + len1 + len2 */
}; };
inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) { inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!(c->check_struct (this) if (!(c->check_struct (this)
&& c->check_array (arrayZ, USHORT::static_size * closure->stride, len))) return TRACE_RETURN (false); && c->check_array (arrayZ, USHORT::static_size * closure->stride, len))) return TRACE_RETURN (false);
unsigned int count = len; unsigned int count = len;
PairValueRecord *record = CastP<PairValueRecord> (arrayZ); const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
return TRACE_RETURN (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) return TRACE_RETURN (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride)
&& closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride)); && closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
} }
@ -670,18 +690,18 @@ struct PairPosFormat1
{ {
TRACE_APPLY (this); TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer; hb_buffer_t *buffer = c->buffer;
hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, 1);
if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
if (!skippy_iter.next ()) return TRACE_RETURN (false); if (!skippy_iter.next ()) return TRACE_RETURN (false);
return TRACE_RETURN ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx)); return TRACE_RETURN ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx));
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
unsigned int len1 = valueFormat1.get_len (); unsigned int len1 = valueFormat1.get_len ();
@ -741,12 +761,11 @@ struct PairPosFormat2
{ {
TRACE_APPLY (this); TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer; hb_buffer_t *buffer = c->buffer;
hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, 1);
if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
if (!skippy_iter.next ()) return TRACE_RETURN (false); if (!skippy_iter.next ()) return TRACE_RETURN (false);
unsigned int len1 = valueFormat1.get_len (); unsigned int len1 = valueFormat1.get_len ();
@ -770,7 +789,8 @@ struct PairPosFormat2
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!(c->check_struct (this) if (!(c->check_struct (this)
&& coverage.sanitize (c, this) && coverage.sanitize (c, this)
@ -823,6 +843,7 @@ struct PairPos
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
TRACE_DISPATCH (this, u.format); TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 1: return TRACE_RETURN (c->dispatch (u.format1));
case 2: return TRACE_RETURN (c->dispatch (u.format2)); case 2: return TRACE_RETURN (c->dispatch (u.format2));
@ -830,16 +851,6 @@ struct PairPos
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
case 2: return TRACE_RETURN (u.format2.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
@ -853,7 +864,8 @@ struct EntryExitRecord
{ {
friend struct CursivePosFormat1; friend struct CursivePosFormat1;
inline bool sanitize (hb_sanitize_context_t *c, void *base) { inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base)); return TRACE_RETURN (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
} }
@ -892,12 +904,11 @@ struct CursivePosFormat1
/* We don't handle mark glyphs here. */ /* We don't handle mark glyphs here. */
if (unlikely (_hb_glyph_info_is_mark (&buffer->cur()))) return TRACE_RETURN (false); if (unlikely (_hb_glyph_info_is_mark (&buffer->cur()))) return TRACE_RETURN (false);
hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, 1);
if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)]; const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)];
if (!this_record.exitAnchor) return TRACE_RETURN (false); if (!this_record.exitAnchor) return TRACE_RETURN (false);
hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
if (!skippy_iter.next ()) return TRACE_RETURN (false); if (!skippy_iter.next ()) return TRACE_RETURN (false);
const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)]; const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
@ -967,7 +978,8 @@ struct CursivePosFormat1
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this)); return TRACE_RETURN (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
} }
@ -990,21 +1002,13 @@ struct CursivePos
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
TRACE_DISPATCH (this, u.format); TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 1: return TRACE_RETURN (c->dispatch (u.format1));
default:return TRACE_RETURN (c->default_return_value ()); default:return TRACE_RETURN (c->default_return_value ());
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
@ -1040,7 +1044,8 @@ struct MarkBasePosFormat1
if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false);
/* now we search backwards for a non-mark glyph */ /* now we search backwards for a non-mark glyph */
hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, buffer->idx, 1); hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
do { do {
if (!skippy_iter.prev ()) return TRACE_RETURN (false); if (!skippy_iter.prev ()) return TRACE_RETURN (false);
@ -1058,7 +1063,8 @@ struct MarkBasePosFormat1
return TRACE_RETURN ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx)); return TRACE_RETURN ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && baseCoverage.sanitize (c, this) && return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && baseCoverage.sanitize (c, this) &&
markArray.sanitize (c, this) && baseArray.sanitize (c, this, (unsigned int) classCount)); markArray.sanitize (c, this) && baseArray.sanitize (c, this, (unsigned int) classCount));
@ -1089,21 +1095,13 @@ struct MarkBasePos
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
TRACE_DISPATCH (this, u.format); TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 1: return TRACE_RETURN (c->dispatch (u.format1));
default:return TRACE_RETURN (c->default_return_value ()); default:return TRACE_RETURN (c->default_return_value ());
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
@ -1144,7 +1142,8 @@ struct MarkLigPosFormat1
if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false);
/* now we search backwards for a non-mark glyph */ /* now we search backwards for a non-mark glyph */
hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, buffer->idx, 1); hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
if (!skippy_iter.prev ()) return TRACE_RETURN (false); if (!skippy_iter.prev ()) return TRACE_RETURN (false);
@ -1178,7 +1177,8 @@ struct MarkLigPosFormat1
return TRACE_RETURN ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j)); return TRACE_RETURN ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && ligatureCoverage.sanitize (c, this) && return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && ligatureCoverage.sanitize (c, this) &&
markArray.sanitize (c, this) && ligatureArray.sanitize (c, this, (unsigned int) classCount)); markArray.sanitize (c, this) && ligatureArray.sanitize (c, this, (unsigned int) classCount));
@ -1210,21 +1210,13 @@ struct MarkLigPos
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
TRACE_DISPATCH (this, u.format); TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 1: return TRACE_RETURN (c->dispatch (u.format1));
default:return TRACE_RETURN (c->default_return_value ()); default:return TRACE_RETURN (c->default_return_value ());
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
@ -1260,7 +1252,8 @@ struct MarkMarkPosFormat1
if (likely (mark1_index == NOT_COVERED)) return TRACE_RETURN (false); if (likely (mark1_index == NOT_COVERED)) return TRACE_RETURN (false);
/* now we search backwards for a suitable mark glyph until a non-mark glyph */ /* now we search backwards for a suitable mark glyph until a non-mark glyph */
hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, buffer->idx, 1); hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags); skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
if (!skippy_iter.prev ()) return TRACE_RETURN (false); if (!skippy_iter.prev ()) return TRACE_RETURN (false);
@ -1295,7 +1288,8 @@ struct MarkMarkPosFormat1
return TRACE_RETURN ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j)); return TRACE_RETURN ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && mark1Coverage.sanitize (c, this) && return TRACE_RETURN (c->check_struct (this) && mark1Coverage.sanitize (c, this) &&
mark2Coverage.sanitize (c, this) && mark1Array.sanitize (c, this) mark2Coverage.sanitize (c, this) && mark1Array.sanitize (c, this)
@ -1329,21 +1323,13 @@ struct MarkMarkPos
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
TRACE_DISPATCH (this, u.format); TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 1: return TRACE_RETURN (c->dispatch (u.format1));
default:return TRACE_RETURN (c->default_return_value ()); default:return TRACE_RETURN (c->default_return_value ());
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
@ -1388,6 +1374,8 @@ struct PosLookupSubTable
inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
{ {
TRACE_DISPATCH (this, lookup_type); TRACE_DISPATCH (this, lookup_type);
/* The sub_format passed to may_dispatch is unnecessary but harmless. */
if (unlikely (!c->may_dispatch (this, &u.sub_format))) TRACE_RETURN (c->default_return_value ());
switch (lookup_type) { switch (lookup_type) {
case Single: return TRACE_RETURN (u.single.dispatch (c)); case Single: return TRACE_RETURN (u.single.dispatch (c));
case Pair: return TRACE_RETURN (u.pair.dispatch (c)); case Pair: return TRACE_RETURN (u.pair.dispatch (c));
@ -1402,29 +1390,9 @@ struct PosLookupSubTable
} }
} }
inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) {
TRACE_SANITIZE (this);
if (!u.header.sub_format.sanitize (c))
return TRACE_RETURN (false);
switch (lookup_type) {
case Single: return TRACE_RETURN (u.single.sanitize (c));
case Pair: return TRACE_RETURN (u.pair.sanitize (c));
case Cursive: return TRACE_RETURN (u.cursive.sanitize (c));
case MarkBase: return TRACE_RETURN (u.markBase.sanitize (c));
case MarkLig: return TRACE_RETURN (u.markLig.sanitize (c));
case MarkMark: return TRACE_RETURN (u.markMark.sanitize (c));
case Context: return TRACE_RETURN (u.context.sanitize (c));
case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c));
case Extension: return TRACE_RETURN (u.extension.sanitize (c));
default: return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
struct { USHORT sub_format;
USHORT sub_format;
} header;
SinglePos single; SinglePos single;
PairPos pair; PairPos pair;
CursivePos cursive; CursivePos cursive;
@ -1436,48 +1404,37 @@ struct PosLookupSubTable
ExtensionPos extension; ExtensionPos extension;
} u; } u;
public: public:
DEFINE_SIZE_UNION (2, header.sub_format); DEFINE_SIZE_UNION (2, sub_format);
}; };
struct PosLookup : Lookup struct PosLookup : Lookup
{ {
inline const PosLookupSubTable& get_subtable (unsigned int i) const inline const PosLookupSubTable& get_subtable (unsigned int i) const
{ return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; } { return Lookup::get_subtable<PosLookupSubTable> (i); }
inline bool is_reverse (void) const inline bool is_reverse (void) const
{ {
return false; return false;
} }
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY (this);
return TRACE_RETURN (dispatch (c));
}
inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
{ {
TRACE_COLLECT_GLYPHS (this); TRACE_COLLECT_GLYPHS (this);
c->set_recurse_func (NULL);
return TRACE_RETURN (dispatch (c)); return TRACE_RETURN (dispatch (c));
} }
template <typename set_t> template <typename set_t>
inline void add_coverage (set_t *glyphs) const inline void add_coverage (set_t *glyphs) const
{ {
hb_get_coverage_context_t c; hb_add_coverage_context_t<set_t> c (glyphs);
const Coverage *last = NULL; dispatch (&c);
unsigned int count = get_subtable_count ();
for (unsigned int i = 0; i < count; i++) {
const Coverage *coverage = &get_subtable (i).dispatch (&c, get_type ());
if (coverage != last) {
coverage->add_coverage (glyphs);
last = coverage;
}
}
}
inline bool apply_once (hb_apply_context_t *c) const
{
TRACE_APPLY (this);
if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props))
return TRACE_RETURN (false);
return TRACE_RETURN (dispatch (c));
} }
static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index); static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index);
@ -1487,23 +1444,13 @@ struct PosLookup : Lookup
template <typename context_t> template <typename context_t>
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ { return Lookup::dispatch<PosLookupSubTable> (c); }
unsigned int lookup_type = get_type ();
TRACE_DISPATCH (this, lookup_type);
unsigned int count = get_subtable_count ();
for (unsigned int i = 0; i < count; i++) {
typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type);
if (c->stop_sublookup_iteration (r))
return TRACE_RETURN (r);
}
return TRACE_RETURN (c->default_return_value ());
}
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false); if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
OffsetArrayOf<PosLookupSubTable> &list = CastR<OffsetArrayOf<PosLookupSubTable> > (subTable); return TRACE_RETURN (dispatch (c));
return TRACE_RETURN (list.sanitize (c, this, get_type ()));
} }
}; };
@ -1523,10 +1470,11 @@ struct GPOS : GSUBGPOS
static inline void position_start (hb_font_t *font, hb_buffer_t *buffer); static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer); static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer);
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false); if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false);
OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList); const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
return TRACE_RETURN (list.sanitize (c, this)); return TRACE_RETURN (list.sanitize (c, this));
} }
public: public:
@ -1621,8 +1569,8 @@ template <typename context_t>
const PosLookup &l = gpos.get_lookup (lookup_index); const PosLookup &l = gpos.get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props; unsigned int saved_lookup_props = c->lookup_props;
c->set_lookup (l); c->set_lookup (l);
bool ret = l.apply_once (c); bool ret = l.dispatch (c);
c->lookup_props = saved_lookup_props; c->set_lookup_props (saved_lookup_props);
return ret; return ret;
} }

View File

@ -97,7 +97,8 @@ struct SingleSubstFormat1
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c)); return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
} }
@ -173,7 +174,8 @@ struct SingleSubstFormat2
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c)); return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c));
} }
@ -223,6 +225,7 @@ struct SingleSubst
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
TRACE_DISPATCH (this, u.format); TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 1: return TRACE_RETURN (c->dispatch (u.format1));
case 2: return TRACE_RETURN (c->dispatch (u.format2)); case 2: return TRACE_RETURN (c->dispatch (u.format2));
@ -230,16 +233,6 @@ struct SingleSubst
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
case 2: return TRACE_RETURN (u.format2.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
@ -312,7 +305,8 @@ struct Sequence
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (substitute.sanitize (c)); return TRACE_RETURN (substitute.sanitize (c));
} }
@ -384,7 +378,8 @@ struct MultipleSubstFormat1
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, this)); return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, this));
} }
@ -423,21 +418,13 @@ struct MultipleSubst
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
TRACE_DISPATCH (this, u.format); TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 1: return TRACE_RETURN (c->dispatch (u.format1));
default:return TRACE_RETURN (c->default_return_value ()); default:return TRACE_RETURN (c->default_return_value ());
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
@ -535,7 +522,8 @@ struct AlternateSubstFormat1
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c, this)); return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
} }
@ -574,21 +562,13 @@ struct AlternateSubst
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
TRACE_DISPATCH (this, u.format); TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 1: return TRACE_RETURN (c->dispatch (u.format1));
default:return TRACE_RETURN (c->default_return_value ()); default:return TRACE_RETURN (c->default_return_value ());
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
@ -686,7 +666,8 @@ struct Ligature
} }
public: public:
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (ligGlyph.sanitize (c) && component.sanitize (c)); return TRACE_RETURN (ligGlyph.sanitize (c) && component.sanitize (c));
} }
@ -764,7 +745,8 @@ struct LigatureSet
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (ligature.sanitize (c, this)); return TRACE_RETURN (ligature.sanitize (c, this));
} }
@ -848,7 +830,8 @@ struct LigatureSubstFormat1
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this)); return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
} }
@ -890,21 +873,13 @@ struct LigatureSubst
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
TRACE_DISPATCH (this, u.format); TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 1: return TRACE_RETURN (c->dispatch (u.format1));
default:return TRACE_RETURN (c->default_return_value ()); default:return TRACE_RETURN (c->default_return_value ());
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
@ -1017,14 +992,15 @@ struct ReverseChainSingleSubstFormat1
return TRACE_RETURN (false); return TRACE_RETURN (false);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this))) if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
return TRACE_RETURN (false); return TRACE_RETURN (false);
OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
if (!lookahead.sanitize (c, this)) if (!lookahead.sanitize (c, this))
return TRACE_RETURN (false); return TRACE_RETURN (false);
ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
return TRACE_RETURN (substitute.sanitize (c)); return TRACE_RETURN (substitute.sanitize (c));
} }
@ -1054,21 +1030,13 @@ struct ReverseChainSingleSubst
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
TRACE_DISPATCH (this, u.format); TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 1: return TRACE_RETURN (c->dispatch (u.format1));
default:return TRACE_RETURN (c->default_return_value ()); default:return TRACE_RETURN (c->default_return_value ());
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
@ -1101,6 +1069,8 @@ struct SubstLookupSubTable
inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
{ {
TRACE_DISPATCH (this, lookup_type); TRACE_DISPATCH (this, lookup_type);
/* The sub_format passed to may_dispatch is unnecessary but harmless. */
if (unlikely (!c->may_dispatch (this, &u.sub_format))) TRACE_RETURN (c->default_return_value ());
switch (lookup_type) { switch (lookup_type) {
case Single: return TRACE_RETURN (u.single.dispatch (c)); case Single: return TRACE_RETURN (u.single.dispatch (c));
case Multiple: return TRACE_RETURN (u.multiple.dispatch (c)); case Multiple: return TRACE_RETURN (u.multiple.dispatch (c));
@ -1114,28 +1084,9 @@ struct SubstLookupSubTable
} }
} }
inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) {
TRACE_SANITIZE (this);
if (!u.header.sub_format.sanitize (c))
return TRACE_RETURN (false);
switch (lookup_type) {
case Single: return TRACE_RETURN (u.single.sanitize (c));
case Multiple: return TRACE_RETURN (u.multiple.sanitize (c));
case Alternate: return TRACE_RETURN (u.alternate.sanitize (c));
case Ligature: return TRACE_RETURN (u.ligature.sanitize (c));
case Context: return TRACE_RETURN (u.context.sanitize (c));
case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c));
case Extension: return TRACE_RETURN (u.extension.sanitize (c));
case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle.sanitize (c));
default: return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
struct { USHORT sub_format;
USHORT sub_format;
} header;
SingleSubst single; SingleSubst single;
MultipleSubst multiple; MultipleSubst multiple;
AlternateSubst alternate; AlternateSubst alternate;
@ -1146,14 +1097,14 @@ struct SubstLookupSubTable
ReverseChainSingleSubst reverseChainContextSingle; ReverseChainSingleSubst reverseChainContextSingle;
} u; } u;
public: public:
DEFINE_SIZE_UNION (2, header.sub_format); DEFINE_SIZE_UNION (2, sub_format);
}; };
struct SubstLookup : Lookup struct SubstLookup : Lookup
{ {
inline const SubstLookupSubTable& get_subtable (unsigned int i) const inline const SubstLookupSubTable& get_subtable (unsigned int i) const
{ return this+CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i]; } { return Lookup::get_subtable<SubstLookupSubTable> (i); }
inline static bool lookup_type_is_reverse (unsigned int lookup_type) inline static bool lookup_type_is_reverse (unsigned int lookup_type)
{ return lookup_type == SubstLookupSubTable::ReverseChainSingle; } { return lookup_type == SubstLookupSubTable::ReverseChainSingle; }
@ -1166,6 +1117,12 @@ struct SubstLookup : Lookup
return lookup_type_is_reverse (type); return lookup_type_is_reverse (type);
} }
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY (this);
return TRACE_RETURN (dispatch (c));
}
inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const
{ {
TRACE_CLOSURE (this); TRACE_CLOSURE (this);
@ -1183,39 +1140,24 @@ struct SubstLookup : Lookup
template <typename set_t> template <typename set_t>
inline void add_coverage (set_t *glyphs) const inline void add_coverage (set_t *glyphs) const
{ {
hb_get_coverage_context_t c; hb_add_coverage_context_t<set_t> c (glyphs);
const Coverage *last = NULL; dispatch (&c);
unsigned int count = get_subtable_count ();
for (unsigned int i = 0; i < count; i++) {
const Coverage *coverage = &get_subtable (i).dispatch (&c, get_type ());
if (coverage != last) {
coverage->add_coverage (glyphs);
last = coverage;
}
}
} }
inline bool would_apply (hb_would_apply_context_t *c, const hb_set_digest_t *digest) const inline bool would_apply (hb_would_apply_context_t *c,
const hb_ot_layout_lookup_accelerator_t *accel) const
{ {
TRACE_WOULD_APPLY (this); TRACE_WOULD_APPLY (this);
if (unlikely (!c->len)) return TRACE_RETURN (false); if (unlikely (!c->len)) return TRACE_RETURN (false);
if (!digest->may_have (c->glyphs[0])) return TRACE_RETURN (false); if (!accel->may_have (c->glyphs[0])) return TRACE_RETURN (false);
return TRACE_RETURN (dispatch (c)); return TRACE_RETURN (dispatch (c));
} }
inline bool apply_once (hb_apply_context_t *c) const
{
TRACE_APPLY (this);
if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props))
return TRACE_RETURN (false);
return TRACE_RETURN (dispatch (c));
}
static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index); static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index);
inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c, inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c,
unsigned int i) unsigned int i)
{ return CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i].serialize (c, this); } { return get_subtables<SubstLookupSubTable> ()[i].serialize (c, this); }
inline bool serialize_single (hb_serialize_context_t *c, inline bool serialize_single (hb_serialize_context_t *c,
uint32_t lookup_props, uint32_t lookup_props,
@ -1274,24 +1216,13 @@ struct SubstLookup : Lookup
template <typename context_t> template <typename context_t>
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ { return Lookup::dispatch<SubstLookupSubTable> (c); }
unsigned int lookup_type = get_type ();
TRACE_DISPATCH (this, lookup_type);
unsigned int count = get_subtable_count ();
for (unsigned int i = 0; i < count; i++) {
typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type);
if (c->stop_sublookup_iteration (r))
return TRACE_RETURN (r);
}
return TRACE_RETURN (c->default_return_value ());
}
inline bool sanitize (hb_sanitize_context_t *c) inline bool sanitize (hb_sanitize_context_t *c) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false); if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable); if (unlikely (!dispatch (c))) return TRACE_RETURN (false);
if (unlikely (!list.sanitize (c, this, get_type ()))) return TRACE_RETURN (false);
if (unlikely (get_type () == SubstLookupSubTable::Extension)) if (unlikely (get_type () == SubstLookupSubTable::Extension))
{ {
@ -1324,10 +1255,11 @@ struct GSUB : GSUBGPOS
static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer); static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer);
static inline void substitute_finish (hb_font_t *font, hb_buffer_t *buffer); static inline void substitute_finish (hb_font_t *font, hb_buffer_t *buffer);
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false); if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false);
OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList); const OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList);
return TRACE_RETURN (list.sanitize (c, this)); return TRACE_RETURN (list.sanitize (c, this));
} }
public: public:
@ -1362,7 +1294,7 @@ GSUB::substitute_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSE
{ {
unsigned int type = get_type (); unsigned int type = get_type ();
if (unlikely (type == SubstLookupSubTable::Extension)) if (unlikely (type == SubstLookupSubTable::Extension))
return CastR<ExtensionSubst> (get_subtable<SubstLookupSubTable>()).is_reverse (); return CastR<ExtensionSubst> (get_subtable<LookupSubTable>()).is_reverse ();
return SubstLookup::lookup_type_is_reverse (type); return SubstLookup::lookup_type_is_reverse (type);
} }
@ -1380,8 +1312,8 @@ template <typename context_t>
const SubstLookup &l = gsub.get_lookup (lookup_index); const SubstLookup &l = gsub.get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props; unsigned int saved_lookup_props = c->lookup_props;
c->set_lookup (l); c->set_lookup (l);
bool ret = l.apply_once (c); bool ret = l.dispatch (c);
c->lookup_props = saved_lookup_props; c->set_lookup_props (saved_lookup_props);
return ret; return ret;
} }

View File

@ -37,12 +37,6 @@
namespace OT { namespace OT {
#define TRACE_DISPATCH(this, format) \
hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"format %d", (int) format);
#ifndef HB_DEBUG_CLOSURE #ifndef HB_DEBUG_CLOSURE
#define HB_DEBUG_CLOSURE (HB_DEBUG+0) #define HB_DEBUG_CLOSURE (HB_DEBUG+0)
#endif #endif
@ -58,6 +52,8 @@ struct hb_closure_context_t
static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE; static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE;
typedef hb_void_t return_t; typedef hb_void_t return_t;
typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index); typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
template <typename T, typename F>
inline bool may_dispatch (const T *obj, const F *format) { return true; }
template <typename T> template <typename T>
inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; } inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
static return_t default_return_value (void) { return HB_VOID; } static return_t default_return_value (void) { return HB_VOID; }
@ -107,6 +103,8 @@ struct hb_would_apply_context_t
inline const char *get_name (void) { return "WOULD_APPLY"; } inline const char *get_name (void) { return "WOULD_APPLY"; }
static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY; static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY;
typedef bool return_t; typedef bool return_t;
template <typename T, typename F>
inline bool may_dispatch (const T *obj, const F *format) { return true; }
template <typename T> template <typename T>
inline return_t dispatch (const T &obj) { return obj.would_apply (this); } inline return_t dispatch (const T &obj) { return obj.would_apply (this); }
static return_t default_return_value (void) { return false; } static return_t default_return_value (void) { return false; }
@ -146,6 +144,8 @@ struct hb_collect_glyphs_context_t
static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS; static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS;
typedef hb_void_t return_t; typedef hb_void_t return_t;
typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index); typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
template <typename T, typename F>
inline bool may_dispatch (const T *obj, const F *format) { return true; }
template <typename T> template <typename T>
inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; } inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
static return_t default_return_value (void) { return HB_VOID; } static return_t default_return_value (void) { return HB_VOID; }
@ -232,18 +232,28 @@ struct hb_collect_glyphs_context_t
#define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0) #define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0)
#endif #endif
struct hb_get_coverage_context_t template <typename set_t>
struct hb_add_coverage_context_t
{ {
inline const char *get_name (void) { return "GET_COVERAGE"; } inline const char *get_name (void) { return "GET_COVERAGE"; }
static const unsigned int max_debug_depth = HB_DEBUG_GET_COVERAGE; static const unsigned int max_debug_depth = HB_DEBUG_GET_COVERAGE;
typedef const Coverage &return_t; typedef const Coverage &return_t;
template <typename T, typename F>
inline bool may_dispatch (const T *obj, const F *format) { return true; }
template <typename T> template <typename T>
inline return_t dispatch (const T &obj) { return obj.get_coverage (); } inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
static return_t default_return_value (void) { return Null(Coverage); } static return_t default_return_value (void) { return Null(Coverage); }
bool stop_sublookup_iteration (return_t r) const
{
r.add_coverage (set);
return false;
}
hb_get_coverage_context_t (void) : hb_add_coverage_context_t (set_t *set_) :
set (set_),
debug_depth (0) {} debug_depth (0) {}
set_t *set;
unsigned int debug_depth; unsigned int debug_depth;
}; };
@ -260,61 +270,6 @@ struct hb_get_coverage_context_t
struct hb_apply_context_t struct hb_apply_context_t
{ {
inline const char *get_name (void) { return "APPLY"; }
static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
typedef bool return_t;
typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
template <typename T>
inline return_t dispatch (const T &obj) { return obj.apply (this); }
static return_t default_return_value (void) { return false; }
bool stop_sublookup_iteration (return_t r) const { return r; }
return_t recurse (unsigned int lookup_index)
{
if (unlikely (nesting_level_left == 0 || !recurse_func))
return default_return_value ();
nesting_level_left--;
bool ret = recurse_func (this, lookup_index);
nesting_level_left++;
return ret;
}
unsigned int table_index; /* GSUB/GPOS */
hb_font_t *font;
hb_face_t *face;
hb_buffer_t *buffer;
hb_direction_t direction;
hb_mask_t lookup_mask;
bool auto_zwj;
recurse_func_t recurse_func;
unsigned int nesting_level_left;
unsigned int lookup_props;
const GDEF &gdef;
bool has_glyph_classes;
unsigned int debug_depth;
hb_apply_context_t (unsigned int table_index_,
hb_font_t *font_,
hb_buffer_t *buffer_) :
table_index (table_index_),
font (font_), face (font->face), buffer (buffer_),
direction (buffer_->props.direction),
lookup_mask (1),
auto_zwj (true),
recurse_func (NULL),
nesting_level_left (MAX_NESTING_LEVEL),
lookup_props (0),
gdef (*hb_ot_layout_from_face (face)->gdef),
has_glyph_classes (gdef.has_glyph_classes ()),
debug_depth (0) {}
inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); }
struct matcher_t struct matcher_t
{ {
inline matcher_t (void) : inline matcher_t (void) :
@ -390,29 +345,24 @@ struct hb_apply_context_t
const void *match_data; const void *match_data;
}; };
struct skipping_forward_iterator_t struct skipping_iterator_t
{ {
inline skipping_forward_iterator_t (hb_apply_context_t *c_, inline void init (hb_apply_context_t *c_, bool context_match = false)
unsigned int start_index_,
unsigned int num_items_,
bool context_match = false) :
idx (start_index_),
c (c_),
match_glyph_data (NULL),
num_items (num_items_),
end (c->buffer->len)
{ {
c = c_;
match_glyph_data = NULL,
matcher.set_match_func (NULL, NULL);
matcher.set_lookup_props (c->lookup_props); matcher.set_lookup_props (c->lookup_props);
/* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */ /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
matcher.set_ignore_zwnj (context_match || c->table_index == 1); matcher.set_ignore_zwnj (context_match || c->table_index == 1);
/* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */ /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj); matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj);
if (!context_match) matcher.set_mask (context_match ? -1 : c->lookup_mask);
matcher.set_mask (c->lookup_mask); }
matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); inline void set_lookup_props (unsigned int lookup_props)
{
matcher.set_lookup_props (lookup_props);
} }
inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); }
inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); }
inline void set_match_func (matcher_t::match_func_t match_func, inline void set_match_func (matcher_t::match_func_t match_func,
const void *match_data, const void *match_data,
const USHORT glyph_data[]) const USHORT glyph_data[])
@ -421,12 +371,21 @@ struct hb_apply_context_t
match_glyph_data = glyph_data; match_glyph_data = glyph_data;
} }
inline bool has_no_chance (void) const { return unlikely (num_items && idx + num_items >= end); } inline void reset (unsigned int start_index_,
unsigned int num_items_)
{
idx = start_index_;
num_items = num_items_;
end = c->buffer->len;
matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
}
inline void reject (void) { num_items++; match_glyph_data--; } inline void reject (void) { num_items++; match_glyph_data--; }
inline bool next (void) inline bool next (void)
{ {
assert (num_items > 0); assert (num_items > 0);
while (!has_no_chance ()) while (idx + num_items < end)
{ {
idx++; idx++;
const hb_glyph_info_t &info = c->buffer->info[idx]; const hb_glyph_info_t &info = c->buffer->info[idx];
@ -450,53 +409,10 @@ struct hb_apply_context_t
} }
return false; return false;
} }
unsigned int idx;
protected:
hb_apply_context_t *c;
matcher_t matcher;
const USHORT *match_glyph_data;
unsigned int num_items;
unsigned int end;
};
struct skipping_backward_iterator_t
{
inline skipping_backward_iterator_t (hb_apply_context_t *c_,
unsigned int start_index_,
unsigned int num_items_,
bool context_match = false) :
idx (start_index_),
c (c_),
match_glyph_data (NULL),
num_items (num_items_)
{
matcher.set_lookup_props (c->lookup_props);
/* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
matcher.set_ignore_zwnj (context_match || c->table_index == 1);
/* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj);
if (!context_match)
matcher.set_mask (c->lookup_mask);
matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
}
inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); }
inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); }
inline void set_match_func (matcher_t::match_func_t match_func,
const void *match_data,
const USHORT glyph_data[])
{
matcher.set_match_func (match_func, match_data);
match_glyph_data = glyph_data;
}
inline bool has_no_chance (void) const { return unlikely (idx < num_items); }
inline void reject (void) { num_items++; }
inline bool prev (void) inline bool prev (void)
{ {
assert (num_items > 0); assert (num_items > 0);
while (!has_no_chance ()) while (idx >= num_items)
{ {
idx--; idx--;
const hb_glyph_info_t &info = c->buffer->out_info[idx]; const hb_glyph_info_t &info = c->buffer->out_info[idx];
@ -528,44 +444,111 @@ struct hb_apply_context_t
const USHORT *match_glyph_data; const USHORT *match_glyph_data;
unsigned int num_items; unsigned int num_items;
unsigned int end;
}; };
inline const char *get_name (void) { return "APPLY"; }
static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
typedef bool return_t;
typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
template <typename T, typename F>
inline bool may_dispatch (const T *obj, const F *format) { return true; }
template <typename T>
inline return_t dispatch (const T &obj) { return obj.apply (this); }
static return_t default_return_value (void) { return false; }
bool stop_sublookup_iteration (return_t r) const { return r; }
return_t recurse (unsigned int lookup_index)
{
if (unlikely (nesting_level_left == 0 || !recurse_func))
return default_return_value ();
nesting_level_left--;
bool ret = recurse_func (this, lookup_index);
nesting_level_left++;
return ret;
}
unsigned int table_index; /* GSUB/GPOS */
hb_font_t *font;
hb_face_t *face;
hb_buffer_t *buffer;
hb_direction_t direction;
hb_mask_t lookup_mask;
bool auto_zwj;
recurse_func_t recurse_func;
unsigned int nesting_level_left;
unsigned int lookup_props;
const GDEF &gdef;
bool has_glyph_classes;
skipping_iterator_t iter_input, iter_context;
unsigned int debug_depth;
hb_apply_context_t (unsigned int table_index_,
hb_font_t *font_,
hb_buffer_t *buffer_) :
table_index (table_index_),
font (font_), face (font->face), buffer (buffer_),
direction (buffer_->props.direction),
lookup_mask (1),
auto_zwj (true),
recurse_func (NULL),
nesting_level_left (MAX_NESTING_LEVEL),
lookup_props (0),
gdef (*hb_ot_layout_from_face (face)->gdef),
has_glyph_classes (gdef.has_glyph_classes ()),
iter_input (),
iter_context (),
debug_depth (0) {}
inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
inline void set_lookup (const Lookup &l) { set_lookup_props (l.get_props ()); }
inline void set_lookup_props (unsigned int lookup_props_)
{
lookup_props = lookup_props_;
iter_input.init (this, false);
iter_context.init (this, true);
}
inline bool inline bool
match_properties_mark (hb_codepoint_t glyph, match_properties_mark (hb_codepoint_t glyph,
unsigned int glyph_props, unsigned int glyph_props,
unsigned int lookup_props) const unsigned int match_props) const
{ {
/* If using mark filtering sets, the high short of /* If using mark filtering sets, the high short of
* lookup_props has the set index. * match_props has the set index.
*/ */
if (lookup_props & LookupFlag::UseMarkFilteringSet) if (match_props & LookupFlag::UseMarkFilteringSet)
return gdef.mark_set_covers (lookup_props >> 16, glyph); return gdef.mark_set_covers (match_props >> 16, glyph);
/* The second byte of lookup_props has the meaning /* The second byte of match_props has the meaning
* "ignore marks of attachment type different than * "ignore marks of attachment type different than
* the attachment type specified." * the attachment type specified."
*/ */
if (lookup_props & LookupFlag::MarkAttachmentType) if (match_props & LookupFlag::MarkAttachmentType)
return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType); return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
return true; return true;
} }
inline bool inline bool
check_glyph_property (const hb_glyph_info_t *info, check_glyph_property (const hb_glyph_info_t *info,
unsigned int lookup_props) const unsigned int match_props) const
{ {
hb_codepoint_t glyph = info->codepoint; hb_codepoint_t glyph = info->codepoint;
unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info); unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
/* Not covered, if, for example, glyph class is ligature and /* Not covered, if, for example, glyph class is ligature and
* lookup_props includes LookupFlags::IgnoreLigatures * match_props includes LookupFlags::IgnoreLigatures
*/ */
if (glyph_props & lookup_props & LookupFlag::IgnoreFlags) if (glyph_props & match_props & LookupFlag::IgnoreFlags)
return false; return false;
if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
return match_properties_mark (glyph, glyph_props, lookup_props); return match_properties_mark (glyph, glyph_props, match_props);
return true; return true;
} }
@ -741,9 +724,9 @@ static inline bool match_input (hb_apply_context_t *c,
hb_buffer_t *buffer = c->buffer; hb_buffer_t *buffer = c->buffer;
hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, count - 1); hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, count - 1);
skippy_iter.set_match_func (match_func, match_data, input); skippy_iter.set_match_func (match_func, match_data, input);
if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
/* /*
* This is perhaps the trickiest part of OpenType... Remarks: * This is perhaps the trickiest part of OpenType... Remarks:
@ -910,9 +893,9 @@ static inline bool match_backtrack (hb_apply_context_t *c,
{ {
TRACE_APPLY (NULL); TRACE_APPLY (NULL);
hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true); hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
skippy_iter.reset (c->buffer->backtrack_len (), count);
skippy_iter.set_match_func (match_func, match_data, backtrack); skippy_iter.set_match_func (match_func, match_data, backtrack);
if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
if (!skippy_iter.prev ()) if (!skippy_iter.prev ())
@ -930,9 +913,9 @@ static inline bool match_lookahead (hb_apply_context_t *c,
{ {
TRACE_APPLY (NULL); TRACE_APPLY (NULL);
hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true); hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
skippy_iter.reset (c->buffer->idx + offset - 1, count);
skippy_iter.set_match_func (match_func, match_data, lookahead); skippy_iter.set_match_func (match_func, match_data, lookahead);
if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
if (!skippy_iter.next ()) if (!skippy_iter.next ())
@ -945,7 +928,8 @@ static inline bool match_lookahead (hb_apply_context_t *c,
struct LookupRecord struct LookupRecord
{ {
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this)); return TRACE_RETURN (c->check_struct (this));
} }
@ -1168,7 +1152,8 @@ struct Rule
} }
public: public:
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return inputCount.sanitize (c) return inputCount.sanitize (c)
&& lookupCount.sanitize (c) && lookupCount.sanitize (c)
@ -1232,7 +1217,8 @@ struct RuleSet
return TRACE_RETURN (false); return TRACE_RETURN (false);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (rule.sanitize (c, this)); return TRACE_RETURN (rule.sanitize (c, this));
} }
@ -1314,7 +1300,8 @@ struct ContextFormat1
return TRACE_RETURN (rule_set.apply (c, lookup_context)); return TRACE_RETURN (rule_set.apply (c, lookup_context));
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this)); return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
} }
@ -1406,7 +1393,8 @@ struct ContextFormat2
return TRACE_RETURN (rule_set.apply (c, lookup_context)); return TRACE_RETURN (rule_set.apply (c, lookup_context));
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this)); return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
} }
@ -1494,7 +1482,8 @@ struct ContextFormat3
return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context)); return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!c->check_struct (this)) return TRACE_RETURN (false); if (!c->check_struct (this)) return TRACE_RETURN (false);
unsigned int count = glyphCount; unsigned int count = glyphCount;
@ -1502,7 +1491,7 @@ struct ContextFormat3
if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return TRACE_RETURN (false); if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return TRACE_RETURN (false);
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
if (!coverageZ[i].sanitize (c, this)) return TRACE_RETURN (false); if (!coverageZ[i].sanitize (c, this)) return TRACE_RETURN (false);
LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count); const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount)); return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
} }
@ -1526,6 +1515,7 @@ struct Context
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
TRACE_DISPATCH (this, u.format); TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 1: return TRACE_RETURN (c->dispatch (u.format1));
case 2: return TRACE_RETURN (c->dispatch (u.format2)); case 2: return TRACE_RETURN (c->dispatch (u.format2));
@ -1534,17 +1524,6 @@ struct Context
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
case 2: return TRACE_RETURN (u.format2.sanitize (c));
case 3: return TRACE_RETURN (u.format3.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
@ -1726,14 +1705,15 @@ struct ChainRule
lookup.array, lookup_context)); lookup.array, lookup_context));
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!backtrack.sanitize (c)) return TRACE_RETURN (false); if (!backtrack.sanitize (c)) return TRACE_RETURN (false);
HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
if (!input.sanitize (c)) return TRACE_RETURN (false); if (!input.sanitize (c)) return TRACE_RETURN (false);
ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
if (!lookahead.sanitize (c)) return TRACE_RETURN (false); if (!lookahead.sanitize (c)) return TRACE_RETURN (false);
ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
return TRACE_RETURN (lookup.sanitize (c)); return TRACE_RETURN (lookup.sanitize (c));
} }
@ -1795,7 +1775,8 @@ struct ChainRuleSet
return TRACE_RETURN (false); return TRACE_RETURN (false);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (rule.sanitize (c, this)); return TRACE_RETURN (rule.sanitize (c, this));
} }
@ -1874,7 +1855,8 @@ struct ChainContextFormat1
return TRACE_RETURN (rule_set.apply (c, lookup_context)); return TRACE_RETURN (rule_set.apply (c, lookup_context));
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this)); return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
} }
@ -1984,7 +1966,8 @@ struct ChainContextFormat2
return TRACE_RETURN (rule_set.apply (c, lookup_context)); return TRACE_RETURN (rule_set.apply (c, lookup_context));
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) && return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) &&
inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) && inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) &&
@ -2105,15 +2088,16 @@ struct ChainContextFormat3
lookup.len, lookup.array, lookup_context)); lookup.len, lookup.array, lookup_context));
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false); if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack); const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
if (!input.sanitize (c, this)) return TRACE_RETURN (false); if (!input.sanitize (c, this)) return TRACE_RETURN (false);
if (!input.len) return TRACE_RETURN (false); /* To be consistent with Context. */ if (!input.len) return TRACE_RETURN (false); /* To be consistent with Context. */
OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input); const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false); if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
return TRACE_RETURN (lookup.sanitize (c)); return TRACE_RETURN (lookup.sanitize (c));
} }
@ -2144,6 +2128,7 @@ struct ChainContext
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
TRACE_DISPATCH (this, u.format); TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (c->dispatch (u.format1)); case 1: return TRACE_RETURN (c->dispatch (u.format1));
case 2: return TRACE_RETURN (c->dispatch (u.format2)); case 2: return TRACE_RETURN (c->dispatch (u.format2));
@ -2152,17 +2137,6 @@ struct ChainContext
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c));
case 2: return TRACE_RETURN (u.format2.sanitize (c));
case 3: return TRACE_RETURN (u.format3.sanitize (c));
default:return TRACE_RETURN (true);
}
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
@ -2173,14 +2147,32 @@ struct ChainContext
}; };
template <typename T>
struct ExtensionFormat1 struct ExtensionFormat1
{ {
inline unsigned int get_type (void) const { return extensionLookupType; } inline unsigned int get_type (void) const { return extensionLookupType; }
inline unsigned int get_offset (void) const { return extensionOffset; }
inline bool sanitize (hb_sanitize_context_t *c) { template <typename X>
inline const X& get_subtable (void) const
{
unsigned int offset = extensionOffset;
if (unlikely (!offset)) return Null(typename T::LookupSubTable);
return StructAtOffset<typename T::LookupSubTable> (this, offset);
}
template <typename context_t>
inline typename context_t::return_t dispatch (context_t *c) const
{
TRACE_DISPATCH (this, format);
if (unlikely (!c->may_dispatch (this, this))) TRACE_RETURN (c->default_return_value ());
return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ());
}
/* This is called from may_dispatch() above with hb_sanitize_context_t. */
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this)); return TRACE_RETURN (c->check_struct (this) && extensionOffset != 0);
} }
protected: protected:
@ -2204,49 +2196,30 @@ struct Extension
default:return 0; default:return 0;
} }
} }
inline unsigned int get_offset (void) const
{
switch (u.format) {
case 1: return u.format1.get_offset ();
default:return 0;
}
}
template <typename X> template <typename X>
inline const X& get_subtable (void) const inline const X& get_subtable (void) const
{ {
unsigned int offset = get_offset (); switch (u.format) {
if (unlikely (!offset)) return Null(typename T::LookupSubTable); case 1: return u.format1.template get_subtable<typename T::LookupSubTable> ();
return StructAtOffset<typename T::LookupSubTable> (this, offset); default:return Null(typename T::LookupSubTable);
}
} }
template <typename context_t> template <typename context_t>
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()); TRACE_DISPATCH (this, u.format);
} if (unlikely (!c->may_dispatch (this, &u.format))) TRACE_RETURN (c->default_return_value ());
inline bool sanitize_self (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) { switch (u.format) {
case 1: return TRACE_RETURN (u.format1.sanitize (c)); case 1: return TRACE_RETURN (u.format1.dispatch (c));
default:return TRACE_RETURN (true); default:return TRACE_RETURN (c->default_return_value ());
} }
} }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
if (!sanitize_self (c)) return TRACE_RETURN (false);
unsigned int offset = get_offset ();
if (unlikely (!offset)) return TRACE_RETURN (true);
return TRACE_RETURN (StructAtOffset<typename T::LookupSubTable> (this, offset).sanitize (c, get_type ()));
}
protected: protected:
union { union {
USHORT format; /* Format identifier */ USHORT format; /* Format identifier */
ExtensionFormat1 format1; ExtensionFormat1<T> format1;
} u; } u;
}; };
@ -2291,7 +2264,8 @@ struct GSUBGPOS
inline const Lookup& get_lookup (unsigned int i) const inline const Lookup& get_lookup (unsigned int i) const
{ return (this+lookupList)[i]; } { return (this+lookupList)[i]; }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) && return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
scriptList.sanitize (c, this) && scriptList.sanitize (c, this) &&

View File

@ -54,7 +54,8 @@ typedef OffsetListOf<PosLookup> JstfMax;
struct JstfPriority struct JstfPriority
{ {
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && return TRACE_RETURN (c->check_struct (this) &&
shrinkageEnableGSUB.sanitize (c, this) && shrinkageEnableGSUB.sanitize (c, this) &&
@ -123,7 +124,8 @@ struct JstfPriority
struct JstfLangSys : OffsetListOf<JstfPriority> struct JstfLangSys : OffsetListOf<JstfPriority>
{ {
inline bool sanitize (hb_sanitize_context_t *c, inline bool sanitize (hb_sanitize_context_t *c,
const Record<JstfLangSys>::sanitize_closure_t * = NULL) { const Record<JstfLangSys>::sanitize_closure_t * = NULL) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (OffsetListOf<JstfPriority>::sanitize (c)); return TRACE_RETURN (OffsetListOf<JstfPriority>::sanitize (c));
} }
@ -163,7 +165,8 @@ struct JstfScript
inline const JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } inline const JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
inline bool sanitize (hb_sanitize_context_t *c, inline bool sanitize (hb_sanitize_context_t *c,
const Record<JstfScript>::sanitize_closure_t * = NULL) { const Record<JstfScript>::sanitize_closure_t * = NULL) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (extenderGlyphs.sanitize (c, this) && return TRACE_RETURN (extenderGlyphs.sanitize (c, this) &&
defaultLangSys.sanitize (c, this) && defaultLangSys.sanitize (c, this) &&
@ -206,7 +209,8 @@ struct JSTF
inline bool find_script_index (hb_tag_t tag, unsigned int *index) const inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
{ return scriptList.find_index (tag, index); } { return scriptList.find_index (tag, index); }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) && return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
scriptList.sanitize (c, this)); scriptList.sanitize (c, this));

View File

@ -126,11 +126,15 @@ struct hb_ot_layout_lookup_accelerator_t
lookup.add_coverage (&digest); lookup.add_coverage (&digest);
} }
template <typename TLookup> inline void fini (void)
inline void fini (const TLookup &lookup HB_UNUSED)
{ {
} }
inline bool may_have (hb_codepoint_t g) const {
return digest.may_have (g);
}
private:
hb_set_digest_t digest; hb_set_digest_t digest;
}; };

View File

@ -84,9 +84,9 @@ void
_hb_ot_layout_destroy (hb_ot_layout_t *layout) _hb_ot_layout_destroy (hb_ot_layout_t *layout)
{ {
for (unsigned int i = 0; i < layout->gsub_lookup_count; i++) for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
layout->gsub_accels[i].fini (layout->gsub->get_lookup (i)); layout->gsub_accels[i].fini ();
for (unsigned int i = 0; i < layout->gpos_lookup_count; i++) for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
layout->gpos_accels[i].fini (layout->gpos->get_lookup (i)); layout->gpos_accels[i].fini ();
free (layout->gsub_accels); free (layout->gsub_accels);
free (layout->gpos_accels); free (layout->gpos_accels);
@ -699,7 +699,7 @@ hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face,
const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index); const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index].digest); return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]);
} }
void void
@ -829,26 +829,83 @@ struct GPOSProxy
}; };
template <typename Lookup> template <typename Obj>
static inline bool apply_once (OT::hb_apply_context_t *c, static inline bool
const Lookup &lookup) apply_forward (OT::hb_apply_context_t *c,
const Obj &obj,
const hb_ot_layout_lookup_accelerator_t &accel)
{ {
if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props)) bool ret = false;
return false; hb_buffer_t *buffer = c->buffer;
return lookup.dispatch (c); while (buffer->idx < buffer->len)
{
if (accel.may_have (buffer->cur().codepoint) &&
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props) &&
obj.apply (c))
ret = true;
else
buffer->next_glyph ();
}
return ret;
} }
template <typename Proxy> template <typename Obj>
static inline bool static inline bool
apply_backward (OT::hb_apply_context_t *c,
const Obj &obj,
const hb_ot_layout_lookup_accelerator_t &accel)
{
bool ret = false;
hb_buffer_t *buffer = c->buffer;
do
{
if (accel.may_have (buffer->cur().codepoint) &&
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props) &&
obj.apply (c))
ret = true;
/* The reverse lookup doesn't "advance" cursor (for good reason). */
buffer->idx--;
}
while ((int) buffer->idx >= 0);
return ret;
}
struct hb_apply_forward_context_t
{
inline const char *get_name (void) { return "APPLY_FORWARD"; }
static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
typedef bool return_t;
template <typename T, typename F>
inline bool may_dispatch (const T *obj, const F *format) { return true; }
template <typename T>
inline return_t dispatch (const T &obj) { return apply_forward (c, obj, accel); }
static return_t default_return_value (void) { return false; }
bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return true; }
hb_apply_forward_context_t (OT::hb_apply_context_t *c_,
const hb_ot_layout_lookup_accelerator_t &accel_) :
c (c_),
accel (accel_),
debug_depth (0) {}
OT::hb_apply_context_t *c;
const hb_ot_layout_lookup_accelerator_t &accel;
unsigned int debug_depth;
};
template <typename Proxy>
static inline void
apply_string (OT::hb_apply_context_t *c, apply_string (OT::hb_apply_context_t *c,
const typename Proxy::Lookup &lookup, const typename Proxy::Lookup &lookup,
const hb_ot_layout_lookup_accelerator_t &accel) const hb_ot_layout_lookup_accelerator_t &accel)
{ {
bool ret = false;
hb_buffer_t *buffer = c->buffer; hb_buffer_t *buffer = c->buffer;
if (unlikely (!buffer->len || !c->lookup_mask)) if (unlikely (!buffer->len || !c->lookup_mask))
return false; return;
c->set_lookup (lookup); c->set_lookup (lookup);
@ -859,21 +916,20 @@ apply_string (OT::hb_apply_context_t *c,
buffer->clear_output (); buffer->clear_output ();
buffer->idx = 0; buffer->idx = 0;
while (buffer->idx < buffer->len) bool ret;
if (lookup.get_subtable_count () == 1)
{ {
if (accel.digest.may_have (buffer->cur().codepoint) && hb_apply_forward_context_t c_forward (c, accel);
(buffer->cur().mask & c->lookup_mask) && ret = lookup.dispatch (&c_forward);
apply_once (c, lookup))
ret = true;
else
buffer->next_glyph ();
} }
else
ret = apply_forward (c, lookup, accel);
if (ret) if (ret)
{ {
if (!Proxy::inplace) if (!Proxy::inplace)
buffer->swap_buffers (); buffer->swap_buffers ();
else else
assert (!buffer->has_separate_output ()); assert (!buffer->has_separate_output ());
} }
} }
else else
@ -882,20 +938,9 @@ apply_string (OT::hb_apply_context_t *c,
if (Proxy::table_index == 0) if (Proxy::table_index == 0)
buffer->remove_output (); buffer->remove_output ();
buffer->idx = buffer->len - 1; buffer->idx = buffer->len - 1;
do
{
if (accel.digest.may_have (buffer->cur().codepoint) &&
(buffer->cur().mask & c->lookup_mask) &&
apply_once (c, lookup))
ret = true;
/* The reverse lookup doesn't "advance" cursor (for good reason). */
buffer->idx--;
} apply_backward (c, lookup, accel);
while ((int) buffer->idx >= 0);
} }
return ret;
} }
template <typename Proxy> template <typename Proxy>

View File

@ -43,11 +43,13 @@ struct maxp
{ {
static const hb_tag_t tableTag = HB_OT_TAG_maxp; static const hb_tag_t tableTag = HB_OT_TAG_maxp;
inline unsigned int get_num_glyphs (void) const { inline unsigned int get_num_glyphs (void) const
{
return numGlyphs; return numGlyphs;
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && return TRACE_RETURN (c->check_struct (this) &&
likely (version.major == 1 || (version.major == 0 && version.minor == 0x5000u))); likely (version.major == 1 || (version.major == 0 && version.minor == 0x5000u)));

View File

@ -56,7 +56,8 @@ struct NameRecord
return 0; return 0;
} }
inline bool sanitize (hb_sanitize_context_t *c, void *base) { inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
/* We can check from base all the way up to the end of string... */ /* We can check from base all the way up to the end of string... */
return TRACE_RETURN (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset)); return TRACE_RETURN (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset));
@ -101,7 +102,7 @@ struct name
inline unsigned int get_size (void) const inline unsigned int get_size (void) const
{ return min_size + count * nameRecord[0].min_size; } { return min_size + count * nameRecord[0].min_size; }
inline bool sanitize_records (hb_sanitize_context_t *c) { inline bool sanitize_records (hb_sanitize_context_t *c) const {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
char *string_pool = (char *) this + stringOffset; char *string_pool = (char *) this + stringOffset;
unsigned int _count = count; unsigned int _count = count;
@ -110,7 +111,8 @@ struct name
return TRACE_RETURN (true); return TRACE_RETURN (true);
} }
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && return TRACE_RETURN (c->check_struct (this) &&
likely (format == 0 || format == 1) && likely (format == 0 || format == 1) &&

View File

@ -327,7 +327,7 @@ arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++) for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
if (fallback_plan->lookup_array[i]) if (fallback_plan->lookup_array[i])
{ {
fallback_plan->accel_array[i].fini (fallback_plan->lookup_array[i]); fallback_plan->accel_array[i].fini ();
if (fallback_plan->free_lookups) if (fallback_plan->free_lookups)
free (fallback_plan->lookup_array[i]); free (fallback_plan->lookup_array[i]);
} }

View File

@ -133,7 +133,6 @@
*/ */
#define OT_LOOKUP_TYPE_SUBST_SINGLE 1u #define OT_LOOKUP_TYPE_SUBST_SINGLE 1u
#define OT_LOOKUP_TYPE_SUBST_MULTIPLE 2u
#define OT_LOOKUP_TYPE_SUBST_LIGATURE 4u #define OT_LOOKUP_TYPE_SUBST_LIGATURE 4u
#define OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(Name, FromGlyphs, ToGlyphs) \ #define OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(Name, FromGlyphs, ToGlyphs) \

File diff suppressed because it is too large Load Diff

View File

@ -861,41 +861,41 @@ hb_indic_get_categories (hb_codepoint_t u)
switch (u >> 12) switch (u >> 12)
{ {
case 0x0u: case 0x0u:
if (hb_in_range (u, 0x0028u, 0x0040u)) return indic_table[u - 0x0028u + indic_offset_0x0028u]; if (hb_in_range (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
if (hb_in_range (u, 0x00D0u, 0x00D8u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u]; if (hb_in_range (u, 0x00D0u, 0x00D7u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u];
if (hb_in_range (u, 0x0900u, 0x0DF8u)) return indic_table[u - 0x0900u + indic_offset_0x0900u]; if (hb_in_range (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
if (unlikely (u == 0x00A0u)) return _(CP,x); if (unlikely (u == 0x00A0u)) return _(CP,x);
break; break;
case 0x1u: case 0x1u:
if (hb_in_range (u, 0x1000u, 0x10A0u)) return indic_table[u - 0x1000u + indic_offset_0x1000u]; if (hb_in_range (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
if (hb_in_range (u, 0x1700u, 0x17F0u)) return indic_table[u - 0x1700u + indic_offset_0x1700u]; if (hb_in_range (u, 0x1700u, 0x17EFu)) return indic_table[u - 0x1700u + indic_offset_0x1700u];
if (hb_in_range (u, 0x1900u, 0x1AA0u)) return indic_table[u - 0x1900u + indic_offset_0x1900u]; if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return indic_table[u - 0x1900u + indic_offset_0x1900u];
if (hb_in_range (u, 0x1B00u, 0x1C50u)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u]; if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u];
if (hb_in_range (u, 0x1CD0u, 0x1CF8u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u]; if (hb_in_range (u, 0x1CD0u, 0x1CF7u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
break; break;
case 0x2u: case 0x2u:
if (hb_in_range (u, 0x2008u, 0x2018u)) return indic_table[u - 0x2008u + indic_offset_0x2008u]; if (hb_in_range (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
if (unlikely (u == 0x25CCu)) return _(CP,x); if (unlikely (u == 0x25CCu)) return _(CP,x);
break; break;
case 0xAu: case 0xAu:
if (hb_in_range (u, 0xA800u, 0xAAF8u)) return indic_table[u - 0xA800u + indic_offset_0xa800u]; if (hb_in_range (u, 0xA800u, 0xAAF7u)) return indic_table[u - 0xA800u + indic_offset_0xa800u];
if (hb_in_range (u, 0xABC0u, 0xAC00u)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u]; if (hb_in_range (u, 0xABC0u, 0xABFFu)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u];
break; break;
case 0x10u: case 0x10u:
if (hb_in_range (u, 0x10A00u, 0x10A48u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u]; if (hb_in_range (u, 0x10A00u, 0x10A47u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u];
break; break;
case 0x11u: case 0x11u:
if (hb_in_range (u, 0x11000u, 0x110C0u)) return indic_table[u - 0x11000u + indic_offset_0x11000u]; if (hb_in_range (u, 0x11000u, 0x110BFu)) return indic_table[u - 0x11000u + indic_offset_0x11000u];
if (hb_in_range (u, 0x11100u, 0x11238u)) return indic_table[u - 0x11100u + indic_offset_0x11100u]; if (hb_in_range (u, 0x11100u, 0x11237u)) return indic_table[u - 0x11100u + indic_offset_0x11100u];
if (hb_in_range (u, 0x112B0u, 0x11378u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u]; if (hb_in_range (u, 0x112B0u, 0x11377u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u];
if (hb_in_range (u, 0x11480u, 0x114E0u)) return indic_table[u - 0x11480u + indic_offset_0x11480u]; if (hb_in_range (u, 0x11480u, 0x114DFu)) return indic_table[u - 0x11480u + indic_offset_0x11480u];
if (hb_in_range (u, 0x11580u, 0x115C8u)) return indic_table[u - 0x11580u + indic_offset_0x11580u]; if (hb_in_range (u, 0x11580u, 0x115C7u)) return indic_table[u - 0x11580u + indic_offset_0x11580u];
if (hb_in_range (u, 0x11600u, 0x116D0u)) return indic_table[u - 0x11600u + indic_offset_0x11600u]; if (hb_in_range (u, 0x11600u, 0x116CFu)) return indic_table[u - 0x11600u + indic_offset_0x11600u];
break; break;
default: default:

View File

@ -1,5 +1,5 @@
#line 1 "../../src/hb-ot-shape-complex-myanmar-machine.rl" #line 1 "hb-ot-shape-complex-myanmar-machine.rl"
/* /*
* Copyright © 2011,2012 Google, Inc. * Copyright © 2011,2012 Google, Inc.
* *
@ -32,7 +32,7 @@
#include "hb-private.hh" #include "hb-private.hh"
#line 36 "hb-ot-shape-complex-myanmar-machine.hh.tmp" #line 36 "hb-ot-shape-complex-myanmar-machine.hh"
static const unsigned char _myanmar_syllable_machine_trans_keys[] = { static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
1u, 31u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 1u, 31u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u,
@ -261,11 +261,11 @@ static const int myanmar_syllable_machine_error = -1;
static const int myanmar_syllable_machine_en_main = 0; static const int myanmar_syllable_machine_en_main = 0;
#line 36 "../../src/hb-ot-shape-complex-myanmar-machine.rl" #line 36 "hb-ot-shape-complex-myanmar-machine.rl"
#line 93 "../../src/hb-ot-shape-complex-myanmar-machine.rl" #line 93 "hb-ot-shape-complex-myanmar-machine.rl"
#define found_syllable(syllable_type) \ #define found_syllable(syllable_type) \
@ -285,7 +285,7 @@ find_syllables (hb_buffer_t *buffer)
int cs; int cs;
hb_glyph_info_t *info = buffer->info; hb_glyph_info_t *info = buffer->info;
#line 289 "hb-ot-shape-complex-myanmar-machine.hh.tmp" #line 289 "hb-ot-shape-complex-myanmar-machine.hh"
{ {
cs = myanmar_syllable_machine_start; cs = myanmar_syllable_machine_start;
ts = 0; ts = 0;
@ -293,7 +293,7 @@ find_syllables (hb_buffer_t *buffer)
act = 0; act = 0;
} }
#line 114 "../../src/hb-ot-shape-complex-myanmar-machine.rl" #line 114 "hb-ot-shape-complex-myanmar-machine.rl"
p = 0; p = 0;
@ -302,7 +302,7 @@ find_syllables (hb_buffer_t *buffer)
unsigned int last = 0; unsigned int last = 0;
unsigned int syllable_serial = 1; unsigned int syllable_serial = 1;
#line 306 "hb-ot-shape-complex-myanmar-machine.hh.tmp" #line 306 "hb-ot-shape-complex-myanmar-machine.hh"
{ {
int _slen; int _slen;
int _trans; int _trans;
@ -316,7 +316,7 @@ _resume:
#line 1 "NONE" #line 1 "NONE"
{ts = p;} {ts = p;}
break; break;
#line 320 "hb-ot-shape-complex-myanmar-machine.hh.tmp" #line 320 "hb-ot-shape-complex-myanmar-machine.hh"
} }
_keys = _myanmar_syllable_machine_trans_keys + (cs<<1); _keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@ -335,38 +335,38 @@ _eof_trans:
switch ( _myanmar_syllable_machine_trans_actions[_trans] ) { switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
case 7: case 7:
#line 85 "../../src/hb-ot-shape-complex-myanmar-machine.rl" #line 85 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (consonant_syllable); }} {te = p+1;{ found_syllable (consonant_syllable); }}
break; break;
case 5: case 5:
#line 86 "../../src/hb-ot-shape-complex-myanmar-machine.rl" #line 86 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (non_myanmar_cluster); }} {te = p+1;{ found_syllable (non_myanmar_cluster); }}
break; break;
case 10: case 10:
#line 87 "../../src/hb-ot-shape-complex-myanmar-machine.rl" #line 87 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (punctuation_cluster); }} {te = p+1;{ found_syllable (punctuation_cluster); }}
break; break;
case 4: case 4:
#line 88 "../../src/hb-ot-shape-complex-myanmar-machine.rl" #line 88 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (broken_cluster); }} {te = p+1;{ found_syllable (broken_cluster); }}
break; break;
case 3: case 3:
#line 89 "../../src/hb-ot-shape-complex-myanmar-machine.rl" #line 89 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (non_myanmar_cluster); }} {te = p+1;{ found_syllable (non_myanmar_cluster); }}
break; break;
case 6: case 6:
#line 85 "../../src/hb-ot-shape-complex-myanmar-machine.rl" #line 85 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (consonant_syllable); }} {te = p;p--;{ found_syllable (consonant_syllable); }}
break; break;
case 8: case 8:
#line 88 "../../src/hb-ot-shape-complex-myanmar-machine.rl" #line 88 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (broken_cluster); }} {te = p;p--;{ found_syllable (broken_cluster); }}
break; break;
case 9: case 9:
#line 89 "../../src/hb-ot-shape-complex-myanmar-machine.rl" #line 89 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (non_myanmar_cluster); }} {te = p;p--;{ found_syllable (non_myanmar_cluster); }}
break; break;
#line 370 "hb-ot-shape-complex-myanmar-machine.hh.tmp" #line 370 "hb-ot-shape-complex-myanmar-machine.hh"
} }
_again: _again:
@ -375,7 +375,7 @@ _again:
#line 1 "NONE" #line 1 "NONE"
{ts = 0;} {ts = 0;}
break; break;
#line 379 "hb-ot-shape-complex-myanmar-machine.hh.tmp" #line 379 "hb-ot-shape-complex-myanmar-machine.hh"
} }
if ( ++p != pe ) if ( ++p != pe )
@ -391,7 +391,7 @@ _again:
} }
#line 123 "../../src/hb-ot-shape-complex-myanmar-machine.rl" #line 123 "hb-ot-shape-complex-myanmar-machine.rl"
} }

View File

@ -179,9 +179,12 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_PSALTER_PAHLAVI: case HB_SCRIPT_PSALTER_PAHLAVI:
/* For Arabic script, use the Arabic shaper even if no OT script tag was found. /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
* This is because we do fallback shaping for Arabic script (and not others). */ * This is because we do fallback shaping for Arabic script (and not others).
if (planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT || * But note that Arabic shaping is applicable only to horizontal layout; for
planner->props.script == HB_SCRIPT_ARABIC) * vertical text, just use the generic shaper instead. */
if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
planner->props.script == HB_SCRIPT_ARABIC) &&
HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
return &_hb_ot_complex_shaper_arabic; return &_hb_ot_complex_shaper_arabic;
else else
return &_hb_ot_complex_shaper_default; return &_hb_ot_complex_shaper_default;
@ -259,6 +262,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-4.1 additions */ /* Unicode-4.1 additions */
case HB_SCRIPT_KHAROSHTHI: case HB_SCRIPT_KHAROSHTHI:
case HB_SCRIPT_NEW_TAI_LUE:
case HB_SCRIPT_SYLOTI_NAGRI: case HB_SCRIPT_SYLOTI_NAGRI:
/* Unicode-5.1 additions */ /* Unicode-5.1 additions */
@ -339,7 +343,6 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-4.1 additions */ /* Unicode-4.1 additions */
case HB_SCRIPT_BUGINESE: case HB_SCRIPT_BUGINESE:
case HB_SCRIPT_NEW_TAI_LUE:
/* Unicode-5.1 additions */ /* Unicode-5.1 additions */
case HB_SCRIPT_CHAM: case HB_SCRIPT_CHAM:

View File

@ -1,5 +1,5 @@
#line 1 "../../src/hb-ot-shape-complex-sea-machine.rl" #line 1 "hb-ot-shape-complex-sea-machine.rl"
/* /*
* Copyright © 2011,2012,2013 Google, Inc. * Copyright © 2011,2012,2013 Google, Inc.
* *
@ -32,7 +32,7 @@
#include "hb-private.hh" #include "hb-private.hh"
#line 36 "hb-ot-shape-complex-sea-machine.hh.tmp" #line 36 "hb-ot-shape-complex-sea-machine.hh"
static const unsigned char _sea_syllable_machine_trans_keys[] = { static const unsigned char _sea_syllable_machine_trans_keys[] = {
1u, 1u, 1u, 1u, 1u, 29u, 3u, 29u, 3u, 29u, 1u, 1u, 0 1u, 1u, 1u, 1u, 1u, 29u, 3u, 29u, 3u, 29u, 1u, 1u, 0
}; };
@ -89,11 +89,11 @@ static const int sea_syllable_machine_error = -1;
static const int sea_syllable_machine_en_main = 2; static const int sea_syllable_machine_en_main = 2;
#line 36 "../../src/hb-ot-shape-complex-sea-machine.rl" #line 36 "hb-ot-shape-complex-sea-machine.rl"
#line 67 "../../src/hb-ot-shape-complex-sea-machine.rl" #line 67 "hb-ot-shape-complex-sea-machine.rl"
#define found_syllable(syllable_type) \ #define found_syllable(syllable_type) \
@ -113,7 +113,7 @@ find_syllables (hb_buffer_t *buffer)
int cs; int cs;
hb_glyph_info_t *info = buffer->info; hb_glyph_info_t *info = buffer->info;
#line 117 "hb-ot-shape-complex-sea-machine.hh.tmp" #line 117 "hb-ot-shape-complex-sea-machine.hh"
{ {
cs = sea_syllable_machine_start; cs = sea_syllable_machine_start;
ts = 0; ts = 0;
@ -121,7 +121,7 @@ find_syllables (hb_buffer_t *buffer)
act = 0; act = 0;
} }
#line 88 "../../src/hb-ot-shape-complex-sea-machine.rl" #line 88 "hb-ot-shape-complex-sea-machine.rl"
p = 0; p = 0;
@ -130,7 +130,7 @@ find_syllables (hb_buffer_t *buffer)
unsigned int last = 0; unsigned int last = 0;
unsigned int syllable_serial = 1; unsigned int syllable_serial = 1;
#line 134 "hb-ot-shape-complex-sea-machine.hh.tmp" #line 134 "hb-ot-shape-complex-sea-machine.hh"
{ {
int _slen; int _slen;
int _trans; int _trans;
@ -144,7 +144,7 @@ _resume:
#line 1 "NONE" #line 1 "NONE"
{ts = p;} {ts = p;}
break; break;
#line 148 "hb-ot-shape-complex-sea-machine.hh.tmp" #line 148 "hb-ot-shape-complex-sea-machine.hh"
} }
_keys = _sea_syllable_machine_trans_keys + (cs<<1); _keys = _sea_syllable_machine_trans_keys + (cs<<1);
@ -167,30 +167,30 @@ _eof_trans:
{te = p+1;} {te = p+1;}
break; break;
case 6: case 6:
#line 63 "../../src/hb-ot-shape-complex-sea-machine.rl" #line 63 "hb-ot-shape-complex-sea-machine.rl"
{te = p+1;{ found_syllable (non_sea_cluster); }} {te = p+1;{ found_syllable (non_sea_cluster); }}
break; break;
case 7: case 7:
#line 61 "../../src/hb-ot-shape-complex-sea-machine.rl" #line 61 "hb-ot-shape-complex-sea-machine.rl"
{te = p;p--;{ found_syllable (consonant_syllable); }} {te = p;p--;{ found_syllable (consonant_syllable); }}
break; break;
case 8: case 8:
#line 62 "../../src/hb-ot-shape-complex-sea-machine.rl" #line 62 "hb-ot-shape-complex-sea-machine.rl"
{te = p;p--;{ found_syllable (broken_cluster); }} {te = p;p--;{ found_syllable (broken_cluster); }}
break; break;
case 9: case 9:
#line 63 "../../src/hb-ot-shape-complex-sea-machine.rl" #line 63 "hb-ot-shape-complex-sea-machine.rl"
{te = p;p--;{ found_syllable (non_sea_cluster); }} {te = p;p--;{ found_syllable (non_sea_cluster); }}
break; break;
case 1: case 1:
#line 61 "../../src/hb-ot-shape-complex-sea-machine.rl" #line 61 "hb-ot-shape-complex-sea-machine.rl"
{{p = ((te))-1;}{ found_syllable (consonant_syllable); }} {{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
break; break;
case 3: case 3:
#line 62 "../../src/hb-ot-shape-complex-sea-machine.rl" #line 62 "hb-ot-shape-complex-sea-machine.rl"
{{p = ((te))-1;}{ found_syllable (broken_cluster); }} {{p = ((te))-1;}{ found_syllable (broken_cluster); }}
break; break;
#line 194 "hb-ot-shape-complex-sea-machine.hh.tmp" #line 194 "hb-ot-shape-complex-sea-machine.hh"
} }
_again: _again:
@ -199,7 +199,7 @@ _again:
#line 1 "NONE" #line 1 "NONE"
{ts = 0;} {ts = 0;}
break; break;
#line 203 "hb-ot-shape-complex-sea-machine.hh.tmp" #line 203 "hb-ot-shape-complex-sea-machine.hh"
} }
if ( ++p != pe ) if ( ++p != pe )
@ -215,7 +215,7 @@ _again:
} }
#line 97 "../../src/hb-ot-shape-complex-sea-machine.rl" #line 97 "hb-ot-shape-complex-sea-machine.rl"
} }

View File

@ -441,13 +441,15 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
OT::hb_apply_context_t c (1, font, buffer); OT::hb_apply_context_t c (1, font, buffer);
c.set_lookup_mask (plan->kern_mask); c.set_lookup_mask (plan->kern_mask);
c.set_lookup_props (OT::LookupFlag::IgnoreMarks); c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
OT::hb_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
skippy_iter.init (&c);
unsigned int count = buffer->len; unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info; hb_glyph_info_t *info = buffer->info;
hb_glyph_position_t *pos = buffer->pos; hb_glyph_position_t *pos = buffer->pos;
for (unsigned int idx = 0; idx < count;) for (unsigned int idx = 0; idx < count;)
{ {
OT::hb_apply_context_t::skipping_forward_iterator_t skippy_iter (&c, idx, 1); skippy_iter.reset (idx, 1);
if (!skippy_iter.next ()) if (!skippy_iter.next ())
{ {
idx++; idx++;

View File

@ -197,16 +197,17 @@ static inline void
decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shortest) decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shortest)
{ {
hb_buffer_t * const buffer = c->buffer; hb_buffer_t * const buffer = c->buffer;
hb_codepoint_t u = buffer->cur().codepoint;
hb_codepoint_t glyph; hb_codepoint_t glyph;
/* Kind of a cute waterfall here... */ /* Kind of a cute waterfall here... */
if (shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph)) if (shortest && c->font->get_glyph (u, 0, &glyph))
next_char (buffer, glyph); next_char (buffer, glyph);
else if (decompose (c, shortest, buffer->cur().codepoint)) else if (decompose (c, shortest, u))
skip_char (buffer); skip_char (buffer);
else if (!shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph)) else if (!shortest && c->font->get_glyph (u, 0, &glyph))
next_char (buffer, glyph); next_char (buffer, glyph);
else if (decompose_compatibility (c, buffer->cur().codepoint)) else if (decompose_compatibility (c, u))
skip_char (buffer); skip_char (buffer);
else else
next_char (buffer, glyph); /* glyph is initialized in earlier branches. */ next_char (buffer, glyph); /* glyph is initialized in earlier branches. */

View File

@ -676,7 +676,7 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
pos[i].y_advance = 0; pos[i].y_advance = 0;
} }
else else
continue; /* Delete it. */ continue; /* Delete it. XXX Merge clusters? */
} }
if (j != i) if (j != i)
{ {

View File

@ -94,20 +94,6 @@
# endif # endif
#endif #endif
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif
#ifdef _MSC_VER
#undef inline
#define inline __inline
#endif
#ifdef __STRICT_ANSI__
#undef inline
#define inline __inline__
#endif
#if __GNUC__ >= 3 #if __GNUC__ >= 3
#define HB_FUNC __PRETTY_FUNCTION__ #define HB_FUNC __PRETTY_FUNCTION__
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
@ -132,14 +118,21 @@
# ifndef STRICT # ifndef STRICT
# define STRICT 1 # define STRICT 1
# endif # endif
#endif
#ifdef _WIN32_WCE # if defined(_WIN32_WCE)
/* Some things not defined on Windows CE. */ /* Some things not defined on Windows CE. */
#define MemoryBarrier() # define strdup _strdup
#define getenv(Name) NULL # define getenv(Name) NULL
#define setlocale(Category, Locale) "C" # if _WIN32_WCE < 0x800
# define setlocale(Category, Locale) "C"
static int errno = 0; /* Use something better? */ static int errno = 0; /* Use something better? */
# endif
# elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
# define getenv(Name) NULL
# endif
# if defined(_MSC_VER) && _MSC_VER < 1900
# define snprintf _snprintf
# endif
#endif #endif
#if HAVE_ATEXIT #if HAVE_ATEXIT
@ -581,6 +574,30 @@ _hb_debug (unsigned int level,
#define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT)) #define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
#define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0)) #define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
static inline void
_hb_print_func (const char *func)
{
if (func)
{
unsigned int func_len = strlen (func);
/* Skip "static" */
if (0 == strncmp (func, "static ", 7))
func += 7;
/* Skip "typename" */
if (0 == strncmp (func, "typename ", 9))
func += 9;
/* Skip return type */
const char *space = strchr (func, ' ');
if (space)
func = space + 1;
/* Skip parameter list */
const char *paren = strchr (func, '(');
if (paren)
func_len = paren - func;
fprintf (stderr, "%.*s", func_len, func);
}
}
template <int max_level> static inline void template <int max_level> static inline void
_hb_debug_msg_va (const char *what, _hb_debug_msg_va (const char *what,
const void *obj, const void *obj,
@ -626,27 +643,13 @@ _hb_debug_msg_va (const char *what,
} else } else
fprintf (stderr, " " VRBAR LBAR); fprintf (stderr, " " VRBAR LBAR);
if (func) _hb_print_func (func);
{
unsigned int func_len = strlen (func);
#ifndef HB_DEBUG_VERBOSE
/* Skip "typename" */
if (0 == strncmp (func, "typename ", 9))
func += 9;
/* Skip return type */
const char *space = strchr (func, ' ');
if (space)
func = space + 1;
/* Skip parameter list */
const char *paren = strchr (func, '(');
if (paren)
func_len = paren - func;
#endif
fprintf (stderr, "%.*s: ", func_len, func);
}
if (message) if (message)
{
fprintf (stderr, ": ");
vfprintf (stderr, message, ap); vfprintf (stderr, message, ap);
}
fprintf (stderr, "\n"); fprintf (stderr, "\n");
} }
@ -818,7 +821,7 @@ hb_in_range (T u, T lo, T hi)
/* The sizeof() is here to force template instantiation. /* The sizeof() is here to force template instantiation.
* I'm sure there are better ways to do this but can't think of * I'm sure there are better ways to do this but can't think of
* one right now. Declaring a variable won't work as HB_UNUSED * one right now. Declaring a variable won't work as HB_UNUSED
* is unsable on some platforms and unused types are less likely * is unusable on some platforms and unused types are less likely
* to generate a warning than unused variables. */ * to generate a warning than unused variables. */
ASSERT_STATIC (sizeof (hb_assert_unsigned_t<T>) >= 0); ASSERT_STATIC (sizeof (hb_assert_unsigned_t<T>) >= 0);

View File

@ -145,6 +145,8 @@ typedef hb_set_digest_combiner_t
struct hb_set_t struct hb_set_t
{ {
friend struct hb_frozen_set_t;
hb_object_header_t header; hb_object_header_t header;
ASSERT_POD (); ASSERT_POD ();
bool in_error; bool in_error;
@ -326,7 +328,7 @@ struct hb_set_t
static const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID; static const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; } elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; }
elt_t elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; } elt_t const &elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; }
elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); } elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); }
elt_t elts[ELTS]; /* XXX 8kb */ elt_t elts[ELTS]; /* XXX 8kb */
@ -335,6 +337,58 @@ struct hb_set_t
ASSERT_STATIC (sizeof (elt_t) * 8 * ELTS > MAX_G); ASSERT_STATIC (sizeof (elt_t) * 8 * ELTS > MAX_G);
}; };
struct hb_frozen_set_t
{
static const unsigned int SHIFT = hb_set_t::SHIFT;
static const unsigned int BITS = hb_set_t::BITS;
static const unsigned int MASK = hb_set_t::MASK;
typedef hb_set_t::elt_t elt_t;
inline void init (const hb_set_t &set)
{
start = count = 0;
elts = NULL;
unsigned int max = set.get_max ();
if (max == set.INVALID)
return;
unsigned int min = set.get_min ();
const elt_t &min_elt = set.elt (min);
start = min & ~MASK;
count = max - start + 1;
unsigned int num_elts = (count + BITS - 1) / BITS;
unsigned int elts_size = num_elts * sizeof (elt_t);
elts = (elt_t *) malloc (elts_size);
if (unlikely (!elts))
{
start = count = 0;
return;
}
memcpy (elts, &min_elt, elts_size);
}
inline void fini (void)
{
if (elts)
free (elts);
}
inline bool has (hb_codepoint_t g) const
{
/* hb_codepoint_t is unsigned. */
g -= start;
if (unlikely (g > count)) return false;
return !!(elt (g) & mask (g));
}
elt_t const &elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; }
elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); }
private:
hb_codepoint_t start, count;
elt_t *elts;
};
#endif /* HB_SET_PRIVATE_HH */ #endif /* HB_SET_PRIVATE_HH */

View File

@ -126,7 +126,7 @@ hb_shape_plan_create (hb_face_t *face,
if (unlikely (!face)) if (unlikely (!face))
face = hb_face_get_empty (); face = hb_face_get_empty ();
if (unlikely (!props || hb_object_is_inert (face))) if (unlikely (!props))
return hb_shape_plan_get_empty (); return hb_shape_plan_get_empty ();
if (num_user_features && !(features = (hb_feature_t *) malloc (num_user_features * sizeof (hb_feature_t)))) if (num_user_features && !(features = (hb_feature_t *) malloc (num_user_features * sizeof (hb_feature_t))))
return hb_shape_plan_get_empty (); return hb_shape_plan_get_empty ();
@ -294,7 +294,6 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan,
shape_plan->shaper_func); shape_plan->shaper_func);
if (unlikely (hb_object_is_inert (shape_plan) || if (unlikely (hb_object_is_inert (shape_plan) ||
hb_object_is_inert (font) ||
hb_object_is_inert (buffer))) hb_object_is_inert (buffer)))
return false; return false;
@ -453,6 +452,10 @@ retry:
hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list); hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list);
/* Don't add to the cache if face is inert. */
if (unlikely (hb_object_is_inert (face)))
return shape_plan;
/* Don't add the plan to the cache if there were user features with non-global ranges */ /* Don't add the plan to the cache if there were user features with non-global ranges */
if (hb_non_global_user_features_present (user_features, num_user_features)) if (hb_non_global_user_features_present (user_features, num_user_features))

View File

@ -198,9 +198,9 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
/** /**
* hb_feature_from_string: * hb_feature_from_string:
* @str: (array length=len): * @str: (array length=len) (element-type uint8_t):
* @len: * @len:
* @feature: (out) (allow-none): * @feature: (out) (optional):
* *
* *
* *
@ -279,11 +279,13 @@ hb_feature_to_string (hb_feature_t *feature,
static const char **static_shaper_list; static const char **static_shaper_list;
static inline #ifdef HB_USE_ATEXIT
static
void free_static_shaper_list (void) void free_static_shaper_list (void)
{ {
free (static_shaper_list); free (static_shaper_list);
} }
#endif
/** /**
* hb_shape_list_shapers: * hb_shape_list_shapers:

View File

@ -79,10 +79,9 @@ struct hb_shaper_data_t {
HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data) HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data)
#define HB_SHAPER_DATA_DESTROY(shaper, object) \ #define HB_SHAPER_DATA_DESTROY(shaper, object) \
if (object->shaper_data.shaper && \ if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \
object->shaper_data.shaper != HB_SHAPER_DATA_INVALID && \ if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \
object->shaper_data.shaper != HB_SHAPER_DATA_SUCCEEDED) \ HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data);
HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA (shaper, object));
#define HB_SHAPER_DATA_ENSURE_DECLARE(shaper, object) \ #define HB_SHAPER_DATA_ENSURE_DECLARE(shaper, object) \
static inline bool \ static inline bool \

View File

@ -40,12 +40,14 @@ static const hb_shaper_pair_t all_shapers[] = {
static const hb_shaper_pair_t *static_shapers; static const hb_shaper_pair_t *static_shapers;
static inline #ifdef HB_USE_ATEXIT
static
void free_static_shapers (void) void free_static_shapers (void)
{ {
if (unlikely (static_shapers != all_shapers)) if (unlikely (static_shapers != all_shapers))
free ((void *) static_shapers); free ((void *) static_shapers);
} }
#endif
const hb_shaper_pair_t * const hb_shaper_pair_t *
_hb_shapers_get (void) _hb_shapers_get (void)

View File

@ -147,17 +147,17 @@ hb_unicode_funcs_get_default (void)
#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL) #if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma message("Could not find any Unicode functions implementation, you have to provide your own") #pragma error("Could not find any Unicode functions implementation, you have to provide your own.")
#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS") #pragma error("Consider building hb-ucdn.c. If you absolutely want to build without any, check the code.")
#else #else
#warning "Could not find any Unicode functions implementation, you have to provide your own" #error "Could not find any Unicode functions implementation, you have to provide your own"
#warning "To suppress this warning, define HB_NO_UNICODE_FUNCS" #error "Consider building hb-ucdn.c. If you absolutely want to build without any, check the code."
#endif #endif
#endif #endif
/** /**
* hb_unicode_funcs_create: (Xconstructor) * hb_unicode_funcs_create: (Xconstructor)
* @parent: (allow-none): * @parent: (nullable):
* *
* *
* *

View File

@ -29,14 +29,11 @@
#include "hb-private.hh" #include "hb-private.hh"
template <typename T, bool validate=true> struct hb_utf_t;
struct hb_utf8_t
/* UTF-8 */
template <>
struct hb_utf_t<uint8_t, true>
{ {
typedef uint8_t codepoint_t;
static inline const uint8_t * static inline const uint8_t *
next (const uint8_t *text, next (const uint8_t *text,
const uint8_t *end, const uint8_t *end,
@ -131,11 +128,10 @@ struct hb_utf_t<uint8_t, true>
}; };
/* UTF-16 */ struct hb_utf16_t
template <>
struct hb_utf_t<uint16_t, true>
{ {
typedef uint16_t codepoint_t;
static inline const uint16_t * static inline const uint16_t *
next (const uint16_t *text, next (const uint16_t *text,
const uint16_t *end, const uint16_t *end,
@ -204,11 +200,11 @@ struct hb_utf_t<uint16_t, true>
}; };
/* UTF-32 */ template <bool validate=true>
struct hb_utf32_t
template <bool validate>
struct hb_utf_t<uint32_t, validate>
{ {
typedef uint32_t codepoint_t;
static inline const uint32_t * static inline const uint32_t *
next (const uint32_t *text, next (const uint32_t *text,
const uint32_t *end HB_UNUSED, const uint32_t *end HB_UNUSED,
@ -246,4 +242,37 @@ struct hb_utf_t<uint32_t, validate>
}; };
struct hb_latin1_t
{
typedef uint8_t codepoint_t;
static inline const uint8_t *
next (const uint8_t *text,
const uint8_t *end HB_UNUSED,
hb_codepoint_t *unicode,
hb_codepoint_t replacement HB_UNUSED)
{
*unicode = *text++;
return text;
}
static inline const uint8_t *
prev (const uint8_t *text,
const uint8_t *start HB_UNUSED,
hb_codepoint_t *unicode,
hb_codepoint_t replacement)
{
*unicode = *--text;
return text;
}
static inline unsigned int
strlen (const uint8_t *text)
{
unsigned int l = 0;
while (*text++) l++;
return l;
}
};
#endif /* HB_UTF_PRIVATE_HH */ #endif /* HB_UTF_PRIVATE_HH */

View File

@ -38,9 +38,9 @@ HB_BEGIN_DECLS
#define HB_VERSION_MAJOR 0 #define HB_VERSION_MAJOR 0
#define HB_VERSION_MINOR 9 #define HB_VERSION_MINOR 9
#define HB_VERSION_MICRO 37 #define HB_VERSION_MICRO 40
#define HB_VERSION_STRING "0.9.37" #define HB_VERSION_STRING "0.9.40"
#define HB_VERSION_ATLEAST(major,minor,micro) \ #define HB_VERSION_ATLEAST(major,minor,micro) \
((major)*10000+(minor)*100+(micro) <= \ ((major)*10000+(minor)*100+(micro) <= \

View File

@ -30,26 +30,20 @@
#if defined(HB_ATOMIC_INT_NIL) #if defined(HB_ATOMIC_INT_NIL)
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma message("Could not find any system to define atomic_int macros, library may NOT be thread-safe") #pragma error("Could not find any system to define atomic_int macros, library WILL NOT be thread-safe")
#pragma error("Check hb-atomic-private.hh for possible resolutions.")
#else #else
#warning "Could not find any system to define atomic_int macros, library may NOT be thread-safe" #error "Could not find any system to define atomic_int macros, library WILL NOT be thread-safe"
#error "Check hb-atomic-private.hh for possible resolutions."
#endif #endif
#endif #endif
#if defined(HB_MUTEX_IMPL_NIL) #if defined(HB_MUTEX_IMPL_NIL)
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma message("Could not find any system to define mutex macros, library may NOT be thread-safe") #pragma error("Could not find any system to define mutex macros, library WILL NOT be thread-safe")
#pragma error("Check hb-mutex-private.hh for possible resolutions.")
#else #else
#warning "Could not find any system to define mutex macros, library may NOT be thread-safe" #error "Could not find any system to define mutex macros, library WILL NOT be thread-safe"
#error "Check hb-mutex-private.hh for possible resolutions."
#endif #endif
#endif #endif
#if defined(HB_ATOMIC_INT_NIL) || defined(HB_MUTEX_IMPL_NIL)
#ifdef _MSC_VER
#pragma message("To suppress these warnings, define HB_NO_MT")
#else
#warning "To suppress these warnings, define HB_NO_MT"
#endif
#endif

52
gfx/harfbuzz/src/sample.py Executable file
View File

@ -0,0 +1,52 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import print_function
import sys
from gi.repository import HarfBuzz as hb
from gi.repository import GLib
# Python 2/3 compatibility
try:
unicode
except NameError:
unicode = str
def tounicode(s, encoding='utf-8'):
if not isinstance(s, unicode):
return s.decode(encoding)
else:
return s
fontdata = open (sys.argv[1], 'rb').read ()
text = tounicode(sys.argv[2])
# Need to create GLib.Bytes explicitly until this bug is fixed:
# https://bugzilla.gnome.org/show_bug.cgi?id=729541
blob = hb.glib_blob_create (GLib.Bytes.new (fontdata))
face = hb.face_create (blob, 0)
del blob
font = hb.font_create (face)
upem = hb.face_get_upem (face)
del face
hb.font_set_scale (font, upem, upem)
#hb.ft_font_set_funcs (font)
hb.ot_font_set_funcs (font)
buf = hb.buffer_create ()
hb.buffer_add_utf8 (buf, text.encode('utf-8'), 0, -1)
hb.buffer_guess_segment_properties (buf)
hb.shape (font, buf, [])
del font
infos = hb.buffer_get_glyph_infos (buf)
positions = hb.buffer_get_glyph_positions (buf)
for info,pos in zip(infos, positions):
gid = info.codepoint
cluster = info.cluster
x_advance = pos.x_advance
x_offset = pos.x_offset
y_offset = pos.y_offset
print("gid%d=%d@%d,%d+%d" % (gid, cluster, x_advance, x_offset, y_offset))