mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 00:08:39 +09:00
harfbuzz: update harfbuzz to 1.5.1
This commit is contained in:
parent
113a86e60a
commit
26d0be66f3
85 changed files with 5230 additions and 906 deletions
|
|
@ -11,6 +11,7 @@ EXTRA_DIST = \
|
|||
harfbuzz.doap \
|
||||
README.python \
|
||||
BUILD.md \
|
||||
CMakeLists.txt \
|
||||
$(NULL)
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
|
|
|
|||
1694
gfx/harfbuzz/NEWS
Normal file
1694
gfx/harfbuzz/NEWS
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +1,9 @@
|
|||
gfx/harfbuzz status as of 2017-01-05:
|
||||
gfx/harfbuzz status as of 2017-09-05:
|
||||
|
||||
This directory contains the harfbuzz source from the 'master' branch of
|
||||
https://github.com/behdad/harfbuzz.
|
||||
|
||||
Current version: 1.4.1
|
||||
Current version: 1.5.1
|
||||
|
||||
UPDATING:
|
||||
|
||||
|
|
|
|||
7
gfx/harfbuzz/THANKS
Normal file
7
gfx/harfbuzz/THANKS
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Bradley Grainger
|
||||
Khaled Hosny
|
||||
Kenichi Ishibashi
|
||||
Ryan Lortie
|
||||
Jeff Muizelaar
|
||||
suzuki toshiya
|
||||
Philip Withnall
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
AC_PREREQ([2.64])
|
||||
AC_INIT([HarfBuzz],
|
||||
[1.4.1],
|
||||
[1.5.1],
|
||||
[https://github.com/behdad/harfbuzz/issues/new],
|
||||
[harfbuzz],
|
||||
[http://harfbuzz.org/])
|
||||
|
|
|
|||
|
|
@ -25,11 +25,13 @@ HBLIBS =
|
|||
HBNONPCLIBS =
|
||||
HBDEPS =
|
||||
HBSOURCES = $(HB_BASE_sources)
|
||||
HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
|
||||
HBHEADERS = $(HB_BASE_headers)
|
||||
HBNODISTHEADERS = $(HB_NODIST_headers)
|
||||
|
||||
if HAVE_OT
|
||||
HBSOURCES += $(HB_OT_sources)
|
||||
HBSOURCES += $(HB_OT_RAGEL_GENERATED_sources)
|
||||
HBHEADERS += $(HB_OT_headers)
|
||||
endif
|
||||
|
||||
|
|
@ -218,7 +220,7 @@ harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS)
|
|||
(cat $^ || echo 'hb_ERROR ()' ) | \
|
||||
$(EGREP) '^hb_.* \(' | \
|
||||
sed -e 's/ (.*//' | \
|
||||
LANG=C sort; \
|
||||
LC_ALL=C sort; \
|
||||
echo LIBRARY libharfbuzz-0.dll; \
|
||||
) >"$@"
|
||||
@ ! grep -q hb_ERROR "$@" \
|
||||
|
|
@ -251,19 +253,13 @@ built-sources: $(BUILT_SOURCES)
|
|||
.PHONY: unicode-tables arabic-table indic-table use-table built-sources
|
||||
|
||||
RAGEL_GENERATED = \
|
||||
$(srcdir)/hb-buffer-deserialize-json.hh \
|
||||
$(srcdir)/hb-buffer-deserialize-text.hh \
|
||||
$(srcdir)/hb-ot-shape-complex-indic-machine.hh \
|
||||
$(srcdir)/hb-ot-shape-complex-myanmar-machine.hh \
|
||||
$(srcdir)/hb-ot-shape-complex-use-machine.hh \
|
||||
$(patsubst %,$(srcdir)/%,$(HB_BASE_RAGEL_GENERATED_sources)) \
|
||||
$(patsubst %,$(srcdir)/%,$(HB_OT_RAGEL_GENERATED_sources)) \
|
||||
$(NULL)
|
||||
BUILT_SOURCES += $(RAGEL_GENERATED)
|
||||
EXTRA_DIST += \
|
||||
hb-buffer-deserialize-json.rl \
|
||||
hb-buffer-deserialize-text.rl \
|
||||
hb-ot-shape-complex-indic-machine.rl \
|
||||
hb-ot-shape-complex-myanmar-machine.rl \
|
||||
hb-ot-shape-complex-use-machine.rl \
|
||||
$(HB_BASE_RAGEL_sources) \
|
||||
$(HB_OT_RAGEL_sources) \
|
||||
$(NULL)
|
||||
MAINTAINERCLEANFILES += $(RAGEL_GENERATED)
|
||||
$(srcdir)/%.hh: $(srcdir)/%.rl
|
||||
|
|
@ -299,6 +295,8 @@ test_buffer_serialize_SOURCES = test-buffer-serialize.cc
|
|||
test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
|
||||
test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
check: harfbuzz.def # For check-defs.sh
|
||||
|
||||
dist_check_SCRIPTS = \
|
||||
check-c-linkage-decls.sh \
|
||||
check-defs.sh \
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ 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`"
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ for suffix in so dylib; do
|
|||
so=.libs/libharfbuzz.$suffix
|
||||
if ! test -f "$so"; then continue; fi
|
||||
|
||||
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\>\| ___gcov_flush\>\| llvm_\| _llvm_' | cut -d' ' -f3`"
|
||||
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\>\| ___gcov_flush\>\| llvm_\| _llvm_' | cut -d' ' -f3`"
|
||||
|
||||
prefix=`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'`
|
||||
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ def print_joining_table(f):
|
|||
for (start,end) in ranges:
|
||||
if p not in [start>>page_bits, end>>page_bits]: continue
|
||||
offset = "joining_offset_0x%04xu" % start
|
||||
print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return joining_table[u - 0x%04Xu + %s];" % (start, end, start, offset)
|
||||
print " if (hb_in_range<hb_codepoint_t> (u, 0x%04Xu, 0x%04Xu)) return joining_table[u - 0x%04Xu + %s];" % (start, end, start, offset)
|
||||
print " break;"
|
||||
print ""
|
||||
print " default:"
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ for p in sorted(pages):
|
|||
for (start,end) in zip (starts, ends):
|
||||
if p not in [start>>page_bits, end>>page_bits]: continue
|
||||
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-1, start, offset)
|
||||
print " if (hb_in_range<hb_codepoint_t> (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset)
|
||||
for u,d in singles.items ():
|
||||
if p != u>>page_bits: continue
|
||||
print " if (unlikely (u == 0x%04Xu)) return _(%s,%s);" % (u, short[0][d[0]], short[1][d[1]])
|
||||
|
|
|
|||
|
|
@ -210,11 +210,13 @@ def is_SYM_MOD(U, UISC, UGC):
|
|||
def is_VARIATION_SELECTOR(U, UISC, UGC):
|
||||
return 0xFE00 <= U <= 0xFE0F
|
||||
def is_VOWEL(U, UISC, UGC):
|
||||
# https://github.com/roozbehp/unicode-data/issues/6
|
||||
return (UISC == Pure_Killer or
|
||||
(UGC != Lo and UISC in [Vowel, Vowel_Dependent]))
|
||||
(UGC != Lo and UISC in [Vowel, Vowel_Dependent] and U not in [0xAA29]))
|
||||
def is_VOWEL_MOD(U, UISC, UGC):
|
||||
# https://github.com/roozbehp/unicode-data/issues/6
|
||||
return (UISC in [Tone_Mark, Cantillation_Mark, Register_Shifter, Visarga] or
|
||||
(UGC != Lo and UISC == Bindu))
|
||||
(UGC != Lo and (UISC == Bindu or U in [0xAA29])))
|
||||
|
||||
use_mapping = {
|
||||
'B': is_BASE,
|
||||
|
|
@ -449,7 +451,7 @@ for p in sorted(pages):
|
|||
for (start,end) in zip (starts, ends):
|
||||
if p not in [start>>page_bits, end>>page_bits]: continue
|
||||
offset = "use_offset_0x%04xu" % start
|
||||
print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return use_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset)
|
||||
print " if (hb_in_range<hb_codepoint_t> (u, 0x%04Xu, 0x%04Xu)) return use_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset)
|
||||
for u,d in singles.items ():
|
||||
if p != u>>page_bits: continue
|
||||
print " if (unlikely (u == 0x%04Xu)) return %s;" % (u, d[0])
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ includedir=/usr/local/include
|
|||
|
||||
Name: harfbuzz
|
||||
Description: HarfBuzz text shaping library ICU integration
|
||||
Version: 1.4.1
|
||||
Version: 1.5.1
|
||||
|
||||
Requires: harfbuzz
|
||||
Requires.private: icu-uc
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ includedir=/usr/local/include
|
|||
|
||||
Name: harfbuzz
|
||||
Description: HarfBuzz text shaping library
|
||||
Version: 1.4.1
|
||||
Version: 1.5.1
|
||||
|
||||
Libs: -L${libdir} -lharfbuzz
|
||||
Libs.private:
|
||||
|
|
|
|||
|
|
@ -124,13 +124,13 @@ typedef unsigned int hb_atomic_int_impl_t;
|
|||
#include <builtins.h>
|
||||
|
||||
|
||||
static inline int hb_fetch_and_add(volatile int* AI, unsigned int V) {
|
||||
static inline int _hb_fetch_and_add(volatile int* AI, unsigned int V) {
|
||||
__lwsync();
|
||||
int result = __fetch_and_add(AI, V);
|
||||
__isync();
|
||||
return result;
|
||||
}
|
||||
static inline int hb_compare_and_swaplp(volatile long* P, long O, long N) {
|
||||
static inline int _hb_compare_and_swaplp(volatile long* P, long O, long N) {
|
||||
__sync();
|
||||
int result = __compare_and_swaplp (P, &O, N);
|
||||
__sync();
|
||||
|
|
@ -139,10 +139,10 @@ static inline int hb_compare_and_swaplp(volatile long* P, long O, long N) {
|
|||
|
||||
typedef int hb_atomic_int_impl_t;
|
||||
#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
|
||||
#define hb_atomic_int_impl_add(AI, V) hb_fetch_and_add (&(AI), (V))
|
||||
#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add (&(AI), (V))
|
||||
|
||||
#define hb_atomic_ptr_impl_get(P) (__sync(), (void *) *(P))
|
||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N))
|
||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N))
|
||||
|
||||
#elif !defined(HB_NO_MT)
|
||||
|
||||
|
|
|
|||
|
|
@ -327,6 +327,7 @@ hb_blob_is_immutable (hb_blob_t *blob)
|
|||
unsigned int
|
||||
hb_blob_get_length (hb_blob_t *blob)
|
||||
{
|
||||
if(unlikely(!blob)) return 0; // wallpaper TenFourFox issue 309
|
||||
return blob->length;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t));
|
|||
|
||||
HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
|
||||
HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
|
||||
HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
|
||||
|
||||
enum hb_buffer_scratch_flags_t {
|
||||
HB_BUFFER_SCRATCH_FLAG_DEFAULT = 0x00000000u,
|
||||
|
|
@ -57,6 +58,8 @@ enum hb_buffer_scratch_flags_t {
|
|||
HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK = 0x00000010u,
|
||||
|
||||
/* Reserved for complex shapers' internal use. */
|
||||
HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u,
|
||||
HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u,
|
||||
|
|
@ -232,25 +235,31 @@ struct hb_buffer_t {
|
|||
for (unsigned int j = 0; j < len; j++)
|
||||
info[j].mask |= mask;
|
||||
}
|
||||
HB_INTERNAL void set_masks (hb_mask_t value,
|
||||
hb_mask_t mask,
|
||||
unsigned int cluster_start,
|
||||
unsigned int cluster_end);
|
||||
HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
|
||||
unsigned int cluster_start, unsigned int cluster_end);
|
||||
|
||||
HB_INTERNAL void merge_clusters (unsigned int start,
|
||||
unsigned int end)
|
||||
inline void merge_clusters (unsigned int start, unsigned int end)
|
||||
{
|
||||
if (end - start < 2)
|
||||
return;
|
||||
merge_clusters_impl (start, end);
|
||||
}
|
||||
HB_INTERNAL void merge_clusters_impl (unsigned int start,
|
||||
unsigned int end);
|
||||
HB_INTERNAL void merge_out_clusters (unsigned int start,
|
||||
unsigned int end);
|
||||
HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end);
|
||||
HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
|
||||
/* Merge clusters for deleting current glyph, and skip it. */
|
||||
HB_INTERNAL void delete_glyph (void);
|
||||
|
||||
inline void unsafe_to_break (unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
if (end - start < 2)
|
||||
return;
|
||||
unsafe_to_break_impl (start, end);
|
||||
}
|
||||
HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
|
||||
HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
|
||||
|
||||
|
||||
/* Internal methods */
|
||||
HB_INTERNAL bool enlarge (unsigned int size);
|
||||
|
||||
|
|
@ -282,9 +291,66 @@ struct hb_buffer_t {
|
|||
return ret;
|
||||
}
|
||||
HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
|
||||
|
||||
static inline void
|
||||
set_cluster (hb_glyph_info_t &info, unsigned int cluster, unsigned int mask = 0)
|
||||
{
|
||||
if (info.cluster != cluster)
|
||||
{
|
||||
if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
|
||||
info.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
else
|
||||
info.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
}
|
||||
info.cluster = cluster;
|
||||
}
|
||||
|
||||
int
|
||||
_unsafe_to_break_find_min_cluster (const hb_glyph_info_t *info,
|
||||
unsigned int start, unsigned int end,
|
||||
unsigned int cluster) const
|
||||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
cluster = MIN (cluster, info[i].cluster);
|
||||
return cluster;
|
||||
}
|
||||
void
|
||||
_unsafe_to_break_set_mask (hb_glyph_info_t *info,
|
||||
unsigned int start, unsigned int end,
|
||||
unsigned int cluster)
|
||||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
if (cluster != info[i].cluster)
|
||||
{
|
||||
scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
|
||||
info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Loop over clusters. Duplicated in foreach_syllable(). */
|
||||
#define foreach_cluster(buffer, start, end) \
|
||||
for (unsigned int \
|
||||
_count = buffer->len, \
|
||||
start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
|
||||
start < _count; \
|
||||
start = end, end = _next_cluster (buffer, start))
|
||||
|
||||
static inline unsigned int
|
||||
_next_cluster (hb_buffer_t *buffer, unsigned int start)
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
unsigned int count = buffer->len;
|
||||
|
||||
unsigned int cluster = info[start].cluster;
|
||||
while (++start < count && cluster == info[start].cluster)
|
||||
;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
|
||||
b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
|
||||
sizeof (b->info[0].var))
|
||||
|
|
|
|||
|
|
@ -145,10 +145,16 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
|
|||
|
||||
if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
|
||||
{
|
||||
p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
|
||||
pos[i].x_offset, pos[i].y_offset);
|
||||
p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
|
||||
pos[i].x_advance, pos[i].y_advance);
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
|
||||
pos[i].x_offset, pos[i].y_offset));
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
|
||||
pos[i].x_advance, pos[i].y_advance));
|
||||
}
|
||||
|
||||
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
|
||||
{
|
||||
if (info[i].mask & HB_GLYPH_FLAG_DEFINED)
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED));
|
||||
}
|
||||
|
||||
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
|
||||
|
|
@ -156,9 +162,9 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
|
|||
hb_glyph_extents_t extents;
|
||||
hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
|
||||
extents.x_bearing, extents.y_bearing));
|
||||
extents.x_bearing, extents.y_bearing));
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
|
||||
extents.width, extents.height));
|
||||
extents.width, extents.height));
|
||||
}
|
||||
|
||||
*p++ = '}';
|
||||
|
|
@ -226,6 +232,12 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
|
|||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance));
|
||||
}
|
||||
|
||||
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
|
||||
{
|
||||
if (info[i].mask &HB_GLYPH_FLAG_DEFINED)
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED));
|
||||
}
|
||||
|
||||
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
|
||||
{
|
||||
hb_glyph_extents_t extents;
|
||||
|
|
@ -311,6 +323,8 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
|
|||
if (!buf_consumed)
|
||||
buf_consumed = &sconsumed;
|
||||
*buf_consumed = 0;
|
||||
if (buf_size)
|
||||
*buf = '\0';
|
||||
|
||||
assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
|
||||
buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
|
||||
|
|
|
|||
|
|
@ -31,10 +31,6 @@
|
|||
#include "hb-utf-private.hh"
|
||||
|
||||
|
||||
#ifndef HB_DEBUG_BUFFER
|
||||
#define HB_DEBUG_BUFFER (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION: hb-buffer
|
||||
* @title: Buffers
|
||||
|
|
@ -267,7 +263,7 @@ hb_buffer_t::add (hb_codepoint_t codepoint,
|
|||
|
||||
memset (glyph, 0, sizeof (*glyph));
|
||||
glyph->codepoint = codepoint;
|
||||
glyph->mask = 1;
|
||||
glyph->mask = 0;
|
||||
glyph->cluster = cluster;
|
||||
|
||||
len++;
|
||||
|
|
@ -550,7 +546,10 @@ hb_buffer_t::merge_clusters_impl (unsigned int start,
|
|||
unsigned int end)
|
||||
{
|
||||
if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
|
||||
{
|
||||
unsafe_to_break (start, end);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int cluster = info[start].cluster;
|
||||
|
||||
|
|
@ -568,10 +567,10 @@ hb_buffer_t::merge_clusters_impl (unsigned int start,
|
|||
/* If we hit the start of buffer, continue in out-buffer. */
|
||||
if (idx == start)
|
||||
for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--)
|
||||
out_info[i - 1].cluster = cluster;
|
||||
set_cluster (out_info[i - 1], cluster);
|
||||
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
info[i].cluster = cluster;
|
||||
set_cluster (info[i], cluster);
|
||||
}
|
||||
void
|
||||
hb_buffer_t::merge_out_clusters (unsigned int start,
|
||||
|
|
@ -599,14 +598,16 @@ hb_buffer_t::merge_out_clusters (unsigned int start,
|
|||
/* If we hit the end of out-buffer, continue in buffer. */
|
||||
if (end == out_len)
|
||||
for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++)
|
||||
info[i].cluster = cluster;
|
||||
set_cluster (info[i], cluster);
|
||||
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
out_info[i].cluster = cluster;
|
||||
set_cluster (out_info[i], cluster);
|
||||
}
|
||||
void
|
||||
hb_buffer_t::delete_glyph ()
|
||||
{
|
||||
/* The logic here is duplicated in hb_ot_hide_default_ignorables(). */
|
||||
|
||||
unsigned int cluster = info[idx].cluster;
|
||||
if (idx + 1 < len && cluster == info[idx + 1].cluster)
|
||||
{
|
||||
|
|
@ -619,9 +620,10 @@ hb_buffer_t::delete_glyph ()
|
|||
/* Merge cluster backward. */
|
||||
if (cluster < out_info[out_len - 1].cluster)
|
||||
{
|
||||
unsigned int mask = info[idx].mask;
|
||||
unsigned int old_cluster = out_info[out_len - 1].cluster;
|
||||
for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--)
|
||||
out_info[i - 1].cluster = cluster;
|
||||
set_cluster (out_info[i - 1], cluster, mask);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -637,6 +639,32 @@ done:
|
|||
skip_glyph ();
|
||||
}
|
||||
|
||||
void
|
||||
hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end)
|
||||
{
|
||||
unsigned int cluster = (unsigned int) -1;
|
||||
cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster);
|
||||
_unsafe_to_break_set_mask (info, start, end, cluster);
|
||||
}
|
||||
void
|
||||
hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end)
|
||||
{
|
||||
if (!have_output)
|
||||
{
|
||||
unsafe_to_break_impl (start, end);
|
||||
return;
|
||||
}
|
||||
|
||||
assert (start <= out_len);
|
||||
assert (idx <= end);
|
||||
|
||||
unsigned int cluster = (unsigned int) -1;
|
||||
cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster);
|
||||
cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster);
|
||||
_unsafe_to_break_set_mask (out_info, start, out_len, cluster);
|
||||
_unsafe_to_break_set_mask (info, idx, end, cluster);
|
||||
}
|
||||
|
||||
void
|
||||
hb_buffer_t::guess_segment_properties (void)
|
||||
{
|
||||
|
|
@ -1379,6 +1407,23 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
|
|||
return (hb_glyph_position_t *) buffer->pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_glyph_info_get_glyph_flags:
|
||||
* @info: a #hb_glyph_info_t.
|
||||
*
|
||||
* Returns glyph flags encoded within a #hb_glyph_info_t.
|
||||
*
|
||||
* Return value:
|
||||
* The #hb_glyph_flags_t encoded within @info.
|
||||
*
|
||||
* Since: 1.5.0
|
||||
**/
|
||||
hb_glyph_flags_t
|
||||
(hb_glyph_info_get_glyph_flags) (const hb_glyph_info_t *info)
|
||||
{
|
||||
return hb_glyph_info_get_glyph_flags (info);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_buffer_reverse:
|
||||
* @buffer: an #hb_buffer_t.
|
||||
|
|
@ -1666,6 +1711,58 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* hb_buffer_append:
|
||||
* @buffer: an #hb_buffer_t.
|
||||
* @source: source #hb_buffer_t.
|
||||
* @start: start index into source buffer to copy. Use 0 to copy from start of buffer.
|
||||
* @end: end index into source buffer to copy. Use (unsigned int) -1 to copy to end of buffer.
|
||||
*
|
||||
* Append (part of) contents of another buffer to this buffer.
|
||||
*
|
||||
* Since: 1.5.0
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_buffer_append (hb_buffer_t *buffer,
|
||||
hb_buffer_t *source,
|
||||
unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
assert (!buffer->have_output && !source->have_output);
|
||||
assert (buffer->have_positions == source->have_positions ||
|
||||
!buffer->len || !source->len);
|
||||
assert (buffer->content_type == source->content_type ||
|
||||
!buffer->len || !source->len);
|
||||
|
||||
if (end > source->len)
|
||||
end = source->len;
|
||||
if (start > end)
|
||||
start = end;
|
||||
if (start == end)
|
||||
return;
|
||||
|
||||
if (!buffer->len)
|
||||
buffer->content_type = source->content_type;
|
||||
if (!buffer->have_positions && source->have_positions)
|
||||
buffer->clear_positions ();
|
||||
|
||||
if (buffer->len + (end - start) < buffer->len) /* Overflows. */
|
||||
{
|
||||
buffer->in_error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int orig_len = buffer->len;
|
||||
hb_buffer_set_length (buffer, buffer->len + (end - start));
|
||||
if (buffer->in_error)
|
||||
return;
|
||||
|
||||
memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
|
||||
if (buffer->have_positions)
|
||||
memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
compare_info_codepoint (const hb_glyph_info_t *pa,
|
||||
const hb_glyph_info_t *pb)
|
||||
|
|
@ -1736,7 +1833,8 @@ void
|
|||
hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
|
||||
{
|
||||
assert (buffer->have_positions);
|
||||
assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
|
||||
assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS ||
|
||||
(!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
|
||||
|
||||
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
|
||||
|
||||
|
|
@ -1775,6 +1873,98 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Comparing buffers.
|
||||
*/
|
||||
|
||||
/**
|
||||
* hb_buffer_diff:
|
||||
*
|
||||
* If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
|
||||
* and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned. This should be used by most
|
||||
* callers if just comparing two buffers is needed.
|
||||
*
|
||||
* Since: 1.5.0
|
||||
**/
|
||||
hb_buffer_diff_flags_t
|
||||
hb_buffer_diff (hb_buffer_t *buffer,
|
||||
hb_buffer_t *reference,
|
||||
hb_codepoint_t dottedcircle_glyph,
|
||||
unsigned int position_fuzz)
|
||||
{
|
||||
if (buffer->content_type != reference->content_type && buffer->len && reference->len)
|
||||
return HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH;
|
||||
|
||||
hb_buffer_diff_flags_t result = HB_BUFFER_DIFF_FLAG_EQUAL;
|
||||
bool contains = dottedcircle_glyph != (hb_codepoint_t) -1;
|
||||
|
||||
unsigned int count = reference->len;
|
||||
|
||||
if (buffer->len != count)
|
||||
{
|
||||
/*
|
||||
* we can't compare glyph-by-glyph, but we do want to know if there
|
||||
* are .notdef or dottedcircle glyphs present in the reference buffer
|
||||
*/
|
||||
const hb_glyph_info_t *info = reference->info;
|
||||
unsigned int i;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (contains && info[i].codepoint == dottedcircle_glyph)
|
||||
result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT;
|
||||
if (contains && info[i].codepoint == 0)
|
||||
result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT;
|
||||
}
|
||||
result |= HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH;
|
||||
return hb_buffer_diff_flags_t (result);
|
||||
}
|
||||
|
||||
if (!count)
|
||||
return hb_buffer_diff_flags_t (result);
|
||||
|
||||
const hb_glyph_info_t *buf_info = buffer->info;
|
||||
const hb_glyph_info_t *ref_info = reference->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (buf_info->codepoint != ref_info->codepoint)
|
||||
result |= HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH;
|
||||
if (buf_info->cluster != ref_info->cluster)
|
||||
result |= HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH;
|
||||
if ((buf_info->mask & HB_GLYPH_FLAG_DEFINED) != (ref_info->mask & HB_GLYPH_FLAG_DEFINED))
|
||||
result |= HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH;
|
||||
if (contains && ref_info->codepoint == dottedcircle_glyph)
|
||||
result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT;
|
||||
if (contains && ref_info->codepoint == 0)
|
||||
result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT;
|
||||
buf_info++;
|
||||
ref_info++;
|
||||
}
|
||||
|
||||
if (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS)
|
||||
{
|
||||
assert (buffer->have_positions);
|
||||
const hb_glyph_position_t *buf_pos = buffer->pos;
|
||||
const hb_glyph_position_t *ref_pos = reference->pos;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if ((unsigned int) abs (buf_pos->x_advance - ref_pos->x_advance) > position_fuzz ||
|
||||
(unsigned int) abs (buf_pos->y_advance - ref_pos->y_advance) > position_fuzz ||
|
||||
(unsigned int) abs (buf_pos->x_offset - ref_pos->x_offset) > position_fuzz ||
|
||||
(unsigned int) abs (buf_pos->y_offset - ref_pos->y_offset) > position_fuzz)
|
||||
{
|
||||
result |= HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH;
|
||||
break;
|
||||
}
|
||||
buf_pos++;
|
||||
ref_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Debugging.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ HB_BEGIN_DECLS
|
|||
*/
|
||||
typedef struct hb_glyph_info_t {
|
||||
hb_codepoint_t codepoint;
|
||||
hb_mask_t mask;
|
||||
hb_mask_t mask; /* Holds hb_glyph_flags_t after hb_shape(), plus other things. */
|
||||
uint32_t cluster;
|
||||
|
||||
/*< private >*/
|
||||
|
|
@ -71,6 +71,19 @@ typedef struct hb_glyph_info_t {
|
|||
hb_var_int_t var2;
|
||||
} hb_glyph_info_t;
|
||||
|
||||
typedef enum { /*< flags >*/
|
||||
HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
|
||||
|
||||
HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */
|
||||
} hb_glyph_flags_t;
|
||||
|
||||
HB_EXTERN hb_glyph_flags_t
|
||||
hb_glyph_info_get_glyph_flags (const hb_glyph_info_t *info);
|
||||
|
||||
#define hb_glyph_info_get_glyph_flags(info) \
|
||||
((hb_glyph_flags_t) ((unsigned int) (info)->mask & HB_GLYPH_FLAG_DEFINED))
|
||||
|
||||
|
||||
/**
|
||||
* hb_glyph_position_t:
|
||||
* @x_advance: how much the line advances after drawing this glyph when setting
|
||||
|
|
@ -163,6 +176,7 @@ HB_EXTERN void *
|
|||
hb_buffer_get_user_data (hb_buffer_t *buffer,
|
||||
hb_user_data_key_t *key);
|
||||
|
||||
|
||||
/**
|
||||
* hb_buffer_content_type_t:
|
||||
* @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer.
|
||||
|
|
@ -359,6 +373,11 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
|
|||
unsigned int item_offset,
|
||||
int item_length);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_buffer_append (hb_buffer_t *buffer,
|
||||
hb_buffer_t *source,
|
||||
unsigned int start,
|
||||
unsigned int end);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_buffer_set_length (hb_buffer_t *buffer,
|
||||
|
|
@ -403,7 +422,8 @@ typedef enum { /*< flags >*/
|
|||
HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001u,
|
||||
HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002u,
|
||||
HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u,
|
||||
HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u
|
||||
HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u,
|
||||
HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS = 0x00000010u
|
||||
} hb_buffer_serialize_flags_t;
|
||||
|
||||
/**
|
||||
|
|
@ -452,6 +472,45 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
|
|||
hb_buffer_serialize_format_t format);
|
||||
|
||||
|
||||
/*
|
||||
* Compare buffers
|
||||
*/
|
||||
|
||||
typedef enum { /*< flags >*/
|
||||
HB_BUFFER_DIFF_FLAG_EQUAL = 0x0000,
|
||||
|
||||
/* Buffers with different content_type cannot be meaningfully compared
|
||||
* in any further detail. */
|
||||
HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH = 0x0001,
|
||||
|
||||
/* For buffers with differing length, the per-glyph comparison is not
|
||||
* attempted, though we do still scan reference for dottedcircle / .notdef
|
||||
* glyphs. */
|
||||
HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH = 0x0002,
|
||||
|
||||
/* We want to know if dottedcircle / .notdef glyphs are present in the
|
||||
* reference, as we may not care so much about other differences in this
|
||||
* case. */
|
||||
HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT = 0x0004,
|
||||
HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT = 0x0008,
|
||||
|
||||
/* If the buffers have the same length, we compare them glyph-by-glyph
|
||||
* and report which aspect(s) of the glyph info/position are different. */
|
||||
HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH = 0x0010,
|
||||
HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH = 0x0020,
|
||||
HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH = 0x0040,
|
||||
HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH = 0x0080
|
||||
|
||||
} hb_buffer_diff_flags_t;
|
||||
|
||||
/* Compare the contents of two buffers, report types of differences. */
|
||||
hb_buffer_diff_flags_t
|
||||
hb_buffer_diff (hb_buffer_t *buffer,
|
||||
hb_buffer_t *reference,
|
||||
hb_codepoint_t dottedcircle_glyph,
|
||||
unsigned int position_fuzz);
|
||||
|
||||
|
||||
/*
|
||||
* Debugging.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -186,8 +186,10 @@ lang_equal (hb_language_t v1,
|
|||
const unsigned char *p1 = (const unsigned char *) v1;
|
||||
const unsigned char *p2 = (const unsigned char *) v2;
|
||||
|
||||
while (*p1 && *p1 == canon_map[*p2])
|
||||
p1++, p2++;
|
||||
while (*p1 && *p1 == canon_map[*p2]) {
|
||||
p1++;
|
||||
p2++;
|
||||
}
|
||||
|
||||
return *p1 == canon_map[*p2];
|
||||
}
|
||||
|
|
@ -219,9 +221,18 @@ struct hb_language_item_t {
|
|||
}
|
||||
|
||||
inline hb_language_item_t & operator = (const char *s) {
|
||||
lang = (hb_language_t) strdup (s);
|
||||
for (unsigned char *p = (unsigned char *) lang; *p; p++)
|
||||
*p = canon_map[*p];
|
||||
/* If a custom allocated is used calling strdup() pairs
|
||||
badly with a call to the custom free() in finish() below.
|
||||
Therefore don't call strdup(), implement its behavior.
|
||||
*/
|
||||
size_t len = strlen(s) + 1;
|
||||
lang = (hb_language_t) malloc(len);
|
||||
if (likely (lang))
|
||||
{
|
||||
memcpy((unsigned char *) lang, s, len);
|
||||
for (unsigned char *p = (unsigned char *) lang; *p; p++)
|
||||
*p = canon_map[*p];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -263,6 +274,11 @@ retry:
|
|||
return NULL;
|
||||
lang->next = first_lang;
|
||||
*lang = key;
|
||||
if (unlikely (!lang->lang))
|
||||
{
|
||||
free (lang);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
|
||||
lang->finish ();
|
||||
|
|
@ -605,3 +621,371 @@ hb_version_atleast (unsigned int major,
|
|||
{
|
||||
return HB_VERSION_ATLEAST (major, minor, micro);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* hb_feature_t and hb_variation_t */
|
||||
|
||||
static bool
|
||||
parse_space (const char **pp, const char *end)
|
||||
{
|
||||
while (*pp < end && ISSPACE (**pp))
|
||||
(*pp)++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_char (const char **pp, const char *end, char c)
|
||||
{
|
||||
parse_space (pp, end);
|
||||
|
||||
if (*pp == end || **pp != c)
|
||||
return false;
|
||||
|
||||
(*pp)++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_uint (const char **pp, const char *end, unsigned int *pv)
|
||||
{
|
||||
char buf[32];
|
||||
unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
|
||||
strncpy (buf, *pp, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
char *p = buf;
|
||||
char *pend = p;
|
||||
unsigned int v;
|
||||
|
||||
/* Intentionally use strtol instead of strtoul, such that
|
||||
* -1 turns into "big number"... */
|
||||
errno = 0;
|
||||
v = strtol (p, &pend, 0);
|
||||
if (errno || p == pend)
|
||||
return false;
|
||||
|
||||
*pv = v;
|
||||
*pp += pend - p;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_uint32 (const char **pp, const char *end, uint32_t *pv)
|
||||
{
|
||||
char buf[32];
|
||||
unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
|
||||
strncpy (buf, *pp, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
char *p = buf;
|
||||
char *pend = p;
|
||||
unsigned int v;
|
||||
|
||||
/* Intentionally use strtol instead of strtoul, such that
|
||||
* -1 turns into "big number"... */
|
||||
errno = 0;
|
||||
v = strtol (p, &pend, 0);
|
||||
if (errno || p == pend)
|
||||
return false;
|
||||
|
||||
*pv = v;
|
||||
*pp += pend - p;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_float (const char **pp, const char *end, float *pv)
|
||||
{
|
||||
char buf[32];
|
||||
unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
|
||||
strncpy (buf, *pp, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
char *p = buf;
|
||||
char *pend = p;
|
||||
float v;
|
||||
|
||||
errno = 0;
|
||||
v = strtod (p, &pend);
|
||||
if (errno || p == pend)
|
||||
return false;
|
||||
|
||||
*pv = v;
|
||||
*pp += pend - p;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_bool (const char **pp, const char *end, uint32_t *pv)
|
||||
{
|
||||
parse_space (pp, end);
|
||||
|
||||
const char *p = *pp;
|
||||
while (*pp < end && ISALPHA(**pp))
|
||||
(*pp)++;
|
||||
|
||||
/* CSS allows on/off as aliases 1/0. */
|
||||
if (*pp - p == 2 || 0 == strncmp (p, "on", 2))
|
||||
*pv = 1;
|
||||
else if (*pp - p == 3 || 0 == strncmp (p, "off", 2))
|
||||
*pv = 0;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* hb_feature_t */
|
||||
|
||||
static bool
|
||||
parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
|
||||
{
|
||||
if (parse_char (pp, end, '-'))
|
||||
feature->value = 0;
|
||||
else {
|
||||
parse_char (pp, end, '+');
|
||||
feature->value = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_tag (const char **pp, const char *end, hb_tag_t *tag)
|
||||
{
|
||||
parse_space (pp, end);
|
||||
|
||||
char quote = 0;
|
||||
|
||||
if (*pp < end && (**pp == '\'' || **pp == '"'))
|
||||
{
|
||||
quote = **pp;
|
||||
(*pp)++;
|
||||
}
|
||||
|
||||
const char *p = *pp;
|
||||
while (*pp < end && ISALNUM(**pp))
|
||||
(*pp)++;
|
||||
|
||||
if (p == *pp || *pp - p > 4)
|
||||
return false;
|
||||
|
||||
*tag = hb_tag_from_string (p, *pp - p);
|
||||
|
||||
if (quote)
|
||||
{
|
||||
/* CSS expects exactly four bytes. And we only allow quotations for
|
||||
* CSS compatibility. So, enforce the length. */
|
||||
if (*pp - p != 4)
|
||||
return false;
|
||||
if (*pp == end || **pp != quote)
|
||||
return false;
|
||||
(*pp)++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
|
||||
{
|
||||
parse_space (pp, end);
|
||||
|
||||
bool has_start;
|
||||
|
||||
feature->start = 0;
|
||||
feature->end = (unsigned int) -1;
|
||||
|
||||
if (!parse_char (pp, end, '['))
|
||||
return true;
|
||||
|
||||
has_start = parse_uint (pp, end, &feature->start);
|
||||
|
||||
if (parse_char (pp, end, ':')) {
|
||||
parse_uint (pp, end, &feature->end);
|
||||
} else {
|
||||
if (has_start)
|
||||
feature->end = feature->start + 1;
|
||||
}
|
||||
|
||||
return parse_char (pp, end, ']');
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
|
||||
{
|
||||
bool had_equal = parse_char (pp, end, '=');
|
||||
bool had_value = parse_uint32 (pp, end, &feature->value) ||
|
||||
parse_bool (pp, end, &feature->value);
|
||||
/* CSS doesn't use equal-sign between tag and value.
|
||||
* If there was an equal-sign, then there *must* be a value.
|
||||
* A value without an eqaul-sign is ok, but not required. */
|
||||
return !had_equal || had_value;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
|
||||
{
|
||||
return parse_feature_value_prefix (pp, end, feature) &&
|
||||
parse_tag (pp, end, &feature->tag) &&
|
||||
parse_feature_indices (pp, end, feature) &&
|
||||
parse_feature_value_postfix (pp, end, feature) &&
|
||||
parse_space (pp, end) &&
|
||||
*pp == end;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_feature_from_string:
|
||||
* @str: (array length=len) (element-type uint8_t): a string to parse
|
||||
* @len: length of @str, or -1 if string is %NULL terminated
|
||||
* @feature: (out): the #hb_feature_t to initialize with the parsed values
|
||||
*
|
||||
* Parses a string into a #hb_feature_t.
|
||||
*
|
||||
* TODO: document the syntax here.
|
||||
*
|
||||
* Return value:
|
||||
* %true if @str is successfully parsed, %false otherwise.
|
||||
*
|
||||
* Since: 0.9.5
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_feature_from_string (const char *str, int len,
|
||||
hb_feature_t *feature)
|
||||
{
|
||||
hb_feature_t feat;
|
||||
|
||||
if (len < 0)
|
||||
len = strlen (str);
|
||||
|
||||
if (likely (parse_one_feature (&str, str + len, &feat)))
|
||||
{
|
||||
if (feature)
|
||||
*feature = feat;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (feature)
|
||||
memset (feature, 0, sizeof (*feature));
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_feature_to_string:
|
||||
* @feature: an #hb_feature_t to convert
|
||||
* @buf: (array length=size) (out): output string
|
||||
* @size: the allocated size of @buf
|
||||
*
|
||||
* Converts a #hb_feature_t into a %NULL-terminated string in the format
|
||||
* understood by hb_feature_from_string(). The client in responsible for
|
||||
* allocating big enough size for @buf, 128 bytes is more than enough.
|
||||
*
|
||||
* Since: 0.9.5
|
||||
**/
|
||||
void
|
||||
hb_feature_to_string (hb_feature_t *feature,
|
||||
char *buf, unsigned int size)
|
||||
{
|
||||
if (unlikely (!size)) return;
|
||||
|
||||
char s[128];
|
||||
unsigned int len = 0;
|
||||
if (feature->value == 0)
|
||||
s[len++] = '-';
|
||||
hb_tag_to_string (feature->tag, s + len);
|
||||
len += 4;
|
||||
while (len && s[len - 1] == ' ')
|
||||
len--;
|
||||
if (feature->start != 0 || feature->end != (unsigned int) -1)
|
||||
{
|
||||
s[len++] = '[';
|
||||
if (feature->start)
|
||||
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
|
||||
if (feature->end != feature->start + 1) {
|
||||
s[len++] = ':';
|
||||
if (feature->end != (unsigned int) -1)
|
||||
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
|
||||
}
|
||||
s[len++] = ']';
|
||||
}
|
||||
if (feature->value > 1)
|
||||
{
|
||||
s[len++] = '=';
|
||||
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
|
||||
}
|
||||
assert (len < ARRAY_LENGTH (s));
|
||||
len = MIN (len, size - 1);
|
||||
memcpy (buf, s, len);
|
||||
buf[len] = '\0';
|
||||
}
|
||||
|
||||
/* hb_variation_t */
|
||||
|
||||
static bool
|
||||
parse_variation_value (const char **pp, const char *end, hb_variation_t *variation)
|
||||
{
|
||||
parse_char (pp, end, '='); /* Optional. */
|
||||
return parse_float (pp, end, &variation->value);
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_one_variation (const char **pp, const char *end, hb_variation_t *variation)
|
||||
{
|
||||
return parse_tag (pp, end, &variation->tag) &&
|
||||
parse_variation_value (pp, end, variation) &&
|
||||
parse_space (pp, end) &&
|
||||
*pp == end;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_variation_from_string:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
*/
|
||||
hb_bool_t
|
||||
hb_variation_from_string (const char *str, int len,
|
||||
hb_variation_t *variation)
|
||||
{
|
||||
hb_variation_t var;
|
||||
|
||||
if (len < 0)
|
||||
len = strlen (str);
|
||||
|
||||
if (likely (parse_one_variation (&str, str + len, &var)))
|
||||
{
|
||||
if (variation)
|
||||
*variation = var;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (variation)
|
||||
memset (variation, 0, sizeof (*variation));
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_variation_to_string:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
*/
|
||||
void
|
||||
hb_variation_to_string (hb_variation_t *variation,
|
||||
char *buf, unsigned int size)
|
||||
{
|
||||
if (unlikely (!size)) return;
|
||||
|
||||
char s[128];
|
||||
unsigned int len = 0;
|
||||
hb_tag_to_string (variation->tag, s + len);
|
||||
len += 4;
|
||||
while (len && s[len - 1] == ' ')
|
||||
len--;
|
||||
s[len++] = '=';
|
||||
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", variation->value));
|
||||
|
||||
assert (len < ARRAY_LENGTH (s));
|
||||
len = MIN (len, size - 1);
|
||||
memcpy (buf, s, len);
|
||||
buf[len] = '\0';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -362,6 +362,42 @@ typedef struct hb_user_data_key_t {
|
|||
typedef void (*hb_destroy_func_t) (void *user_data);
|
||||
|
||||
|
||||
/* Font features and variations. */
|
||||
|
||||
typedef struct hb_feature_t {
|
||||
hb_tag_t tag;
|
||||
uint32_t value;
|
||||
unsigned int start;
|
||||
unsigned int end;
|
||||
} hb_feature_t;
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_feature_from_string (const char *str, int len,
|
||||
hb_feature_t *feature);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_feature_to_string (hb_feature_t *feature,
|
||||
char *buf, unsigned int size);
|
||||
|
||||
/**
|
||||
* hb_variation_t:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
*/
|
||||
typedef struct hb_variation_t {
|
||||
hb_tag_t tag;
|
||||
float value;
|
||||
} hb_variation_t;
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_variation_from_string (const char *str, int len,
|
||||
hb_variation_t *variation);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_variation_to_string (hb_variation_t *variation,
|
||||
char *buf, unsigned int size);
|
||||
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_COMMON_H */
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ hb_coretext_face_create (CGFontRef cg_font)
|
|||
}
|
||||
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face)
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(coretext, font)
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -641,22 +641,23 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||
/* active_features.qsort (); */
|
||||
for (unsigned int j = 0; j < active_features.len; j++)
|
||||
{
|
||||
CFStringRef keys[2] = {
|
||||
CFStringRef keys[] = {
|
||||
kCTFontFeatureTypeIdentifierKey,
|
||||
kCTFontFeatureSelectorIdentifierKey
|
||||
};
|
||||
CFNumberRef values[2] = {
|
||||
CFNumberRef values[] = {
|
||||
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.feature),
|
||||
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.setting)
|
||||
};
|
||||
ASSERT_STATIC (ARRAY_LENGTH (keys) == ARRAY_LENGTH (values));
|
||||
CFDictionaryRef dict = CFDictionaryCreate (kCFAllocatorDefault,
|
||||
(const void **) keys,
|
||||
(const void **) values,
|
||||
2,
|
||||
ARRAY_LENGTH (keys),
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
CFRelease (values[0]);
|
||||
CFRelease (values[1]);
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (values); i++)
|
||||
CFRelease (values[i]);
|
||||
|
||||
CFArrayAppendValue (features_array, dict);
|
||||
CFRelease (dict);
|
||||
|
|
@ -699,9 +700,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||
active_features.remove (feature - active_features.array);
|
||||
}
|
||||
}
|
||||
|
||||
if (!range_records.len) /* No active feature found. */
|
||||
goto fail_features;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -833,7 +831,7 @@ resize_and_retry:
|
|||
CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
|
||||
kCTFontAttributeName, face_data->ct_font);
|
||||
|
||||
if (num_features)
|
||||
if (num_features && range_records.len)
|
||||
{
|
||||
unsigned int start = 0;
|
||||
range_record_t *last_range = &range_records[0];
|
||||
|
|
@ -859,6 +857,30 @@ resize_and_retry:
|
|||
CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, chars_len - start),
|
||||
kCTFontAttributeName, last_range->font);
|
||||
}
|
||||
/* Enable/disable kern if requested.
|
||||
*
|
||||
* Note: once kern is disabled, reenabling it doesn't currently seem to work in CoreText.
|
||||
*/
|
||||
if (num_features)
|
||||
{
|
||||
unsigned int zeroint = 0;
|
||||
CFNumberRef zero = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &zeroint);
|
||||
for (unsigned int i = 0; i < num_features; i++)
|
||||
{
|
||||
const hb_feature_t &feature = features[i];
|
||||
if (feature.tag == HB_TAG('k','e','r','n') &&
|
||||
feature.start < chars_len && feature.start < feature.end)
|
||||
{
|
||||
CFRange feature_range = CFRangeMake (feature.start,
|
||||
MIN (feature.end, chars_len) - feature.start);
|
||||
if (feature.value)
|
||||
CFAttributedStringRemoveAttribute (attr_string, feature_range, kCTKernAttributeName);
|
||||
else
|
||||
CFAttributedStringSetAttribute (attr_string, feature_range, kCTKernAttributeName, zero);
|
||||
}
|
||||
}
|
||||
CFRelease (zero);
|
||||
}
|
||||
|
||||
int level = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
|
||||
CFNumberRef level_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &level);
|
||||
|
|
@ -868,6 +890,7 @@ resize_and_retry:
|
|||
1,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
CFRelease (level_number);
|
||||
if (unlikely (!options))
|
||||
FAIL ("CFDictionaryCreate failed");
|
||||
|
||||
|
|
@ -1157,6 +1180,9 @@ resize_and_retry:
|
|||
pos->x_advance = info->mask;
|
||||
pos->x_offset = info->var1.i32;
|
||||
pos->y_offset = info->var2.i32;
|
||||
|
||||
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
|
||||
info++, pos++;
|
||||
}
|
||||
else
|
||||
|
|
@ -1165,6 +1191,9 @@ resize_and_retry:
|
|||
pos->y_advance = info->mask;
|
||||
pos->x_offset = info->var1.i32;
|
||||
pos->y_offset = info->var2.i32;
|
||||
|
||||
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
|
||||
info++, pos++;
|
||||
}
|
||||
|
||||
|
|
@ -1222,6 +1251,9 @@ fail:
|
|||
* AAT shaper
|
||||
*/
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, face)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font)
|
||||
|
||||
/*
|
||||
* shaper face data
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@
|
|||
#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, face)
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, font)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, face)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, font)
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -671,7 +671,7 @@ retry_getglyphs:
|
|||
DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*)
|
||||
malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES));
|
||||
|
||||
hr = analyzer->GetGlyphs (textString, textLength, fontFace, FALSE,
|
||||
hr = analyzer->GetGlyphs (textString, textLength, fontFace, false,
|
||||
isRightToLeft, &runHead->mScript, localeName, NULL, &dwFeatures,
|
||||
featureRangeLengths, 1, maxGlyphCount, clusterMap, textProperties, glyphIndices,
|
||||
glyphProperties, &glyphCount);
|
||||
|
|
@ -719,7 +719,7 @@ retry_getglyphs:
|
|||
hr = analyzer->GetGlyphPlacements (textString,
|
||||
clusterMap, textProperties, textLength, glyphIndices,
|
||||
glyphProperties, glyphCount, fontFace, fontEmSize,
|
||||
FALSE, isRightToLeft, &runHead->mScript, localeName,
|
||||
false, isRightToLeft, &runHead->mScript, localeName,
|
||||
&dwFeatures, featureRangeLengths, 1,
|
||||
glyphAdvances, glyphOffsets);
|
||||
|
||||
|
|
@ -880,6 +880,8 @@ retry_getglyphs:
|
|||
pos->x_offset =
|
||||
x_mult * (isRightToLeft ? -info->var1.i32 : info->var1.i32);
|
||||
pos->y_offset = y_mult * info->var2.i32;
|
||||
|
||||
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
}
|
||||
|
||||
if (isRightToLeft)
|
||||
|
|
@ -915,7 +917,7 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
|
|||
*/
|
||||
|
||||
hb_bool_t
|
||||
hb_shape_dwrite_experimental_width(hb_font_t *font,
|
||||
hb_directwrite_shape_experimental_width(hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
HB_BEGIN_DECLS
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_shape_dwrite_experimental_width(hb_font_t *font, hb_buffer_t *buffer,
|
||||
hb_directwrite_shape_experimental_width(hb_font_t *font, hb_buffer_t *buffer,
|
||||
const hb_feature_t *features, unsigned int num_features, float width);
|
||||
|
||||
HB_END_DECLS
|
||||
|
|
|
|||
|
|
@ -50,12 +50,23 @@ struct hb_face_t {
|
|||
void *user_data;
|
||||
hb_destroy_func_t destroy;
|
||||
|
||||
unsigned int index;
|
||||
mutable unsigned int upem;
|
||||
mutable unsigned int num_glyphs;
|
||||
unsigned int index; /* Face index in a collection, zero-based. */
|
||||
mutable unsigned int upem; /* Units-per-EM. */
|
||||
mutable unsigned int num_glyphs; /* Number of glyphs. */
|
||||
|
||||
struct hb_shaper_data_t shaper_data;
|
||||
enum dirty_t {
|
||||
DIRTY_NOTHING = 0x0000,
|
||||
DIRTY_INDEX = 0x0001,
|
||||
DIRTY_UPEM = 0x0002,
|
||||
DIRTY_NUM_GLYPHS = 0x0004,
|
||||
} dirty;
|
||||
|
||||
struct hb_shaper_data_t shaper_data; /* Various shaper data. */
|
||||
|
||||
/* Various non-shaping data. */
|
||||
/* ... */
|
||||
|
||||
/* Cache */
|
||||
struct plan_node_t {
|
||||
hb_shape_plan_t *shape_plan;
|
||||
plan_node_t *next;
|
||||
|
|
@ -95,6 +106,8 @@ struct hb_face_t {
|
|||
HB_INTERNAL void load_num_glyphs (void) const;
|
||||
};
|
||||
|
||||
HB_MARK_AS_FLAG_T (hb_face_t::dirty_t);
|
||||
|
||||
extern HB_INTERNAL const hb_face_t _hb_face_nil;
|
||||
|
||||
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
|
||||
|
|
|
|||
|
|
@ -28,15 +28,11 @@
|
|||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-ot-layout-private.hh"
|
||||
|
||||
#include "hb-font-private.hh"
|
||||
#include "hb-face-private.hh"
|
||||
#include "hb-open-file-private.hh"
|
||||
#include "hb-ot-head-table.hh"
|
||||
#include "hb-ot-maxp-table.hh"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*
|
||||
* hb_face_t
|
||||
|
|
@ -55,6 +51,8 @@ const hb_face_t _hb_face_nil = {
|
|||
1000, /* upem */
|
||||
0, /* num_glyphs */
|
||||
|
||||
hb_face_t::DIRTY_NOTHING, /* dirty */
|
||||
|
||||
{
|
||||
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
|
||||
#include "hb-shaper-list.hh"
|
||||
|
|
@ -175,7 +173,7 @@ hb_face_create (hb_blob_t *blob,
|
|||
closure,
|
||||
(hb_destroy_func_t) _hb_face_for_data_closure_destroy);
|
||||
|
||||
hb_face_set_index (face, index);
|
||||
face->index = index;
|
||||
|
||||
return face;
|
||||
}
|
||||
|
|
@ -369,6 +367,11 @@ hb_face_set_index (hb_face_t *face,
|
|||
if (face->immutable)
|
||||
return;
|
||||
|
||||
if (face->index == index)
|
||||
return;
|
||||
|
||||
face->dirty |= face->DIRTY_INDEX;
|
||||
|
||||
face->index = index;
|
||||
}
|
||||
|
||||
|
|
@ -404,6 +407,11 @@ hb_face_set_upem (hb_face_t *face,
|
|||
if (face->immutable)
|
||||
return;
|
||||
|
||||
if (face->upem == upem)
|
||||
return;
|
||||
|
||||
face->dirty |= face->DIRTY_UPEM;
|
||||
|
||||
face->upem = upem;
|
||||
}
|
||||
|
||||
|
|
@ -448,6 +456,11 @@ hb_face_set_glyph_count (hb_face_t *face,
|
|||
if (face->immutable)
|
||||
return;
|
||||
|
||||
if (face->num_glyphs == glyph_count)
|
||||
return;
|
||||
|
||||
face->dirty |= face->DIRTY_NUM_GLYPHS;
|
||||
|
||||
face->num_glyphs = glyph_count;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@
|
|||
#include "hb-shaper-impl-private.hh"
|
||||
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(fallback, face)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font)
|
||||
|
||||
|
||||
/*
|
||||
* shaper face data
|
||||
*/
|
||||
|
|
@ -125,7 +129,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
|
|||
pos[i].y_advance = 0;
|
||||
continue;
|
||||
}
|
||||
font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint);
|
||||
(void) font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint);
|
||||
font->get_glyph_advance_for_direction (info[i].codepoint,
|
||||
direction,
|
||||
&pos[i].x_advance,
|
||||
|
|
|
|||
|
|
@ -116,6 +116,16 @@ struct hb_font_t {
|
|||
void *user_data;
|
||||
hb_destroy_func_t destroy;
|
||||
|
||||
enum dirty_t {
|
||||
DIRTY_NOTHING = 0x0000,
|
||||
DIRTY_FACE = 0x0001,
|
||||
DIRTY_PARENT = 0x0002,
|
||||
DIRTY_FUNCS = 0x0004,
|
||||
DIRTY_SCALE = 0x0008,
|
||||
DIRTY_PPEM = 0x0010,
|
||||
DIRTY_VARIATIONS = 0x0020,
|
||||
} dirty;
|
||||
|
||||
struct hb_shaper_data_t shaper_data;
|
||||
|
||||
|
||||
|
|
@ -543,6 +553,8 @@ struct hb_font_t {
|
|||
}
|
||||
};
|
||||
|
||||
HB_MARK_AS_FLAG_T (hb_font_t::dirty_t);
|
||||
|
||||
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
|
||||
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
|
||||
#include "hb-shaper-list.hh"
|
||||
|
|
|
|||
|
|
@ -28,14 +28,7 @@
|
|||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-ot-layout-private.hh"
|
||||
|
||||
#include "hb-font-private.hh"
|
||||
#include "hb-open-file-private.hh"
|
||||
#include "hb-ot-head-table.hh"
|
||||
#include "hb-ot-maxp-table.hh"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -1203,6 +1196,8 @@ hb_font_get_empty (void)
|
|||
NULL, /* user_data */
|
||||
NULL, /* destroy */
|
||||
|
||||
hb_font_t::DIRTY_NOTHING, /* dirty */
|
||||
|
||||
{
|
||||
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
|
||||
#include "hb-shaper-list.hh"
|
||||
|
|
@ -1355,6 +1350,11 @@ hb_font_set_parent (hb_font_t *font,
|
|||
if (!parent)
|
||||
parent = hb_font_get_empty ();
|
||||
|
||||
if (parent == font->parent)
|
||||
return;
|
||||
|
||||
font->dirty |= font->DIRTY_PARENT;
|
||||
|
||||
hb_font_t *old = font->parent;
|
||||
|
||||
font->parent = hb_font_reference (parent);
|
||||
|
|
@ -1378,6 +1378,37 @@ hb_font_get_parent (hb_font_t *font)
|
|||
return font->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_face:
|
||||
* @font: a font.
|
||||
* @face: new face.
|
||||
*
|
||||
* Sets font-face of @font.
|
||||
*
|
||||
* Since: 1.4.3
|
||||
**/
|
||||
void
|
||||
hb_font_set_face (hb_font_t *font,
|
||||
hb_face_t *face)
|
||||
{
|
||||
if (font->immutable)
|
||||
return;
|
||||
|
||||
if (unlikely (!face))
|
||||
face = hb_face_get_empty ();
|
||||
|
||||
if (font->face == face)
|
||||
return;
|
||||
|
||||
font->dirty |= font->DIRTY_FACE;
|
||||
|
||||
hb_face_t *old = font->face;
|
||||
|
||||
font->face = hb_face_reference (face);
|
||||
|
||||
hb_face_destroy (old);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_get_face:
|
||||
* @font: a font.
|
||||
|
|
@ -1424,6 +1455,8 @@ hb_font_set_funcs (hb_font_t *font,
|
|||
if (!klass)
|
||||
klass = hb_font_funcs_get_empty ();
|
||||
|
||||
font->dirty |= font->DIRTY_FUNCS;
|
||||
|
||||
hb_font_funcs_reference (klass);
|
||||
hb_font_funcs_destroy (font->klass);
|
||||
font->klass = klass;
|
||||
|
|
@ -1479,6 +1512,11 @@ hb_font_set_scale (hb_font_t *font,
|
|||
if (font->immutable)
|
||||
return;
|
||||
|
||||
if (font->x_scale == x_scale && font->y_scale == y_scale)
|
||||
return;
|
||||
|
||||
font->dirty |= font->DIRTY_SCALE;
|
||||
|
||||
font->x_scale = x_scale;
|
||||
font->y_scale = y_scale;
|
||||
}
|
||||
|
|
@ -1520,6 +1558,11 @@ hb_font_set_ppem (hb_font_t *font,
|
|||
if (font->immutable)
|
||||
return;
|
||||
|
||||
if (font->x_ppem == x_ppem && font->y_ppem == y_ppem)
|
||||
return;
|
||||
|
||||
font->dirty |= font->DIRTY_PPEM;
|
||||
|
||||
font->x_ppem = x_ppem;
|
||||
font->y_ppem = y_ppem;
|
||||
}
|
||||
|
|
@ -1543,30 +1586,122 @@ hb_font_get_ppem (hb_font_t *font,
|
|||
if (y_ppem) *y_ppem = font->y_ppem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Variations
|
||||
*/
|
||||
|
||||
static void
|
||||
_hb_font_adopt_var_coords_normalized (hb_font_t *font,
|
||||
int *coords, /* 2.14 normalized */
|
||||
unsigned int coords_length)
|
||||
{
|
||||
if (font->num_coords == coords_length &&
|
||||
(coords_length == 0 ||
|
||||
0 == memcmp (font->coords, coords, coords_length * sizeof (coords[0]))))
|
||||
{
|
||||
free (coords);
|
||||
return;
|
||||
}
|
||||
|
||||
font->dirty |= font->DIRTY_VARIATIONS;
|
||||
|
||||
free (font->coords);
|
||||
|
||||
font->coords = coords;
|
||||
font->num_coords = coords_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_variations:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
*/
|
||||
void
|
||||
hb_font_set_variations (hb_font_t *font,
|
||||
const hb_variation_t *variations,
|
||||
unsigned int variations_length)
|
||||
{
|
||||
if (font->immutable)
|
||||
return;
|
||||
|
||||
if (!variations_length)
|
||||
{
|
||||
hb_font_set_var_coords_normalized (font, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int coords_length = hb_ot_var_get_axis_count (font->face);
|
||||
|
||||
int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : NULL;
|
||||
if (unlikely (coords_length && !normalized))
|
||||
return;
|
||||
|
||||
hb_ot_var_normalize_variations (font->face,
|
||||
variations, variations_length,
|
||||
normalized, coords_length);
|
||||
_hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_var_coords_design:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
*/
|
||||
void
|
||||
hb_font_set_var_coords_design (hb_font_t *font,
|
||||
const float *coords,
|
||||
unsigned int coords_length)
|
||||
{
|
||||
if (font->immutable)
|
||||
return;
|
||||
|
||||
int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : NULL;
|
||||
if (unlikely (coords_length && !normalized))
|
||||
return;
|
||||
|
||||
hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
|
||||
_hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_var_coords_normalized:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
*/
|
||||
void
|
||||
hb_font_set_var_coords_normalized (hb_font_t *font,
|
||||
int *coords, /* XXX 2.14 normalized */
|
||||
const int *coords, /* 2.14 normalized */
|
||||
unsigned int coords_length)
|
||||
{
|
||||
if (font->immutable)
|
||||
return;
|
||||
|
||||
/* Skip tail zero entries. */
|
||||
while (coords_length && !coords[coords_length - 1])
|
||||
coords_length--;
|
||||
|
||||
int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : NULL;
|
||||
if (unlikely (coords_length && !copy))
|
||||
return;
|
||||
|
||||
free (font->coords);
|
||||
|
||||
if (coords_length)
|
||||
memcpy (copy, coords, coords_length * sizeof (coords[0]));
|
||||
|
||||
font->coords = copy;
|
||||
font->num_coords = coords_length;
|
||||
_hb_font_adopt_var_coords_normalized (font, copy, coords_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_get_var_coords_normalized:
|
||||
*
|
||||
* Return value is valid as long as variation coordinates of the font
|
||||
* are not modified.
|
||||
*
|
||||
* Since: 1.4.2
|
||||
*/
|
||||
const int *
|
||||
hb_font_get_var_coords_normalized (hb_font_t *font,
|
||||
unsigned int *length)
|
||||
{
|
||||
if (length)
|
||||
*length = font->num_coords;
|
||||
|
||||
return font->coords;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -563,6 +563,10 @@ hb_font_set_parent (hb_font_t *font,
|
|||
HB_EXTERN hb_font_t *
|
||||
hb_font_get_parent (hb_font_t *font);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_face (hb_font_t *font,
|
||||
hb_face_t *face);
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_font_get_face (hb_font_t *font);
|
||||
|
||||
|
|
@ -603,12 +607,25 @@ hb_font_get_ppem (hb_font_t *font,
|
|||
unsigned int *x_ppem,
|
||||
unsigned int *y_ppem);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_variations (hb_font_t *font,
|
||||
const hb_variation_t *variations,
|
||||
unsigned int variations_length);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_var_coords_design (hb_font_t *font,
|
||||
const float *coords,
|
||||
unsigned int coords_length);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_var_coords_normalized (hb_font_t *font,
|
||||
int *coords, /* XXX 2.14 normalized */
|
||||
const int *coords, /* 2.14 normalized */
|
||||
unsigned int coords_length);
|
||||
|
||||
HB_EXTERN const int *
|
||||
hb_font_get_var_coords_normalized (hb_font_t *font,
|
||||
unsigned int *length);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_FONT_H */
|
||||
|
|
|
|||
|
|
@ -493,7 +493,7 @@ reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
|||
return NULL;
|
||||
|
||||
buffer = (FT_Byte *) malloc (length);
|
||||
if (buffer == NULL)
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
|
||||
|
|
@ -521,7 +521,7 @@ hb_ft_face_create (FT_Face ft_face,
|
|||
{
|
||||
hb_face_t *face;
|
||||
|
||||
if (ft_face->stream->read == NULL) {
|
||||
if (!ft_face->stream->read) {
|
||||
hb_blob_t *blob;
|
||||
|
||||
blob = hb_blob_create ((const char *) ft_face->stream->base,
|
||||
|
|
@ -621,17 +621,22 @@ hb_ft_font_create (FT_Face ft_face,
|
|||
FT_MM_Var *mm_var = NULL;
|
||||
if (!FT_Get_MM_Var (ft_face, &mm_var))
|
||||
{
|
||||
FT_Fixed coords[mm_var->num_axis];
|
||||
int hbCoords[mm_var->num_axis];
|
||||
if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, coords))
|
||||
FT_Fixed *ft_coords = (FT_Fixed *) calloc (mm_var->num_axis, sizeof (FT_Fixed));
|
||||
int *coords = (int *) calloc (mm_var->num_axis, sizeof (int));
|
||||
if (coords && ft_coords)
|
||||
{
|
||||
for (int i = 0; i < mm_var->num_axis; ++i)
|
||||
hbCoords[i] = coords[i] >> 2;
|
||||
if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, ft_coords))
|
||||
{
|
||||
for (unsigned int i = 0; i < mm_var->num_axis; ++i)
|
||||
coords[i] = ft_coords[i] >>= 2;
|
||||
|
||||
hb_font_set_var_coords_normalized (font, hbCoords, mm_var->num_axis);
|
||||
hb_font_set_var_coords_normalized (font, coords, mm_var->num_axis);
|
||||
}
|
||||
}
|
||||
free (coords);
|
||||
free (ft_coords);
|
||||
free (mm_var);
|
||||
}
|
||||
free (mm_var);
|
||||
#endif
|
||||
|
||||
return font;
|
||||
|
|
@ -736,6 +741,20 @@ hb_ft_font_set_funcs (hb_font_t *font)
|
|||
FT_Set_Transform (ft_face, &matrix, NULL);
|
||||
}
|
||||
|
||||
unsigned int num_coords;
|
||||
const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
|
||||
if (num_coords)
|
||||
{
|
||||
FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed));
|
||||
if (ft_coords)
|
||||
{
|
||||
for (unsigned int i = 0; i < num_coords; i++)
|
||||
ft_coords[i] = coords[i] << 2;
|
||||
FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
|
||||
free (ft_coords);
|
||||
}
|
||||
}
|
||||
|
||||
ft_face->generic.data = blob;
|
||||
ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
*/
|
||||
|
||||
#define HB_SHAPER graphite2
|
||||
#define hb_graphite2_shaper_font_data_t gr_font
|
||||
#include "hb-shaper-impl-private.hh"
|
||||
|
||||
#include "hb-graphite2.h"
|
||||
|
|
@ -35,8 +34,8 @@
|
|||
#include <graphite2/Segment.h>
|
||||
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, face)
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, font)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, face)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, font)
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -153,26 +152,17 @@ hb_graphite2_face_get_gr_face (hb_face_t *face)
|
|||
* shaper font data
|
||||
*/
|
||||
|
||||
static float hb_graphite2_get_advance (const void *hb_font, unsigned short gid)
|
||||
{
|
||||
return ((hb_font_t *) hb_font)->get_glyph_h_advance (gid);
|
||||
}
|
||||
struct hb_graphite2_shaper_font_data_t {};
|
||||
|
||||
hb_graphite2_shaper_font_data_t *
|
||||
_hb_graphite2_shaper_font_data_create (hb_font_t *font)
|
||||
_hb_graphite2_shaper_font_data_create (hb_font_t *font HB_UNUSED)
|
||||
{
|
||||
if (unlikely (!hb_graphite2_shaper_face_data_ensure (font->face))) return NULL;
|
||||
|
||||
hb_face_t *face = font->face;
|
||||
hb_graphite2_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
|
||||
|
||||
return gr_make_font_with_advance_fn (font->x_scale, font, &hb_graphite2_get_advance, face_data->grface);
|
||||
return (hb_graphite2_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data)
|
||||
_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data HB_UNUSED)
|
||||
{
|
||||
gr_font_destroy (data);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -181,8 +171,7 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data)
|
|||
gr_font *
|
||||
hb_graphite2_font_get_gr_font (hb_font_t *font)
|
||||
{
|
||||
if (unlikely (!hb_graphite2_shaper_font_data_ensure (font))) return NULL;
|
||||
return HB_SHAPER_DATA_GET (font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -230,7 +219,6 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
|
|||
{
|
||||
hb_face_t *face = font->face;
|
||||
gr_face *grface = HB_SHAPER_DATA_GET (face)->grface;
|
||||
gr_font *grfont = HB_SHAPER_DATA_GET (font);
|
||||
|
||||
const char *lang = hb_language_to_string (hb_buffer_get_language (buffer));
|
||||
const char *lang_end = lang ? strchr (lang, '-') : NULL;
|
||||
|
|
@ -262,7 +250,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
|
|||
hb_tag_t script_tag[2];
|
||||
hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]);
|
||||
|
||||
seg = gr_make_seg (grfont, grface,
|
||||
seg = gr_make_seg (NULL, grface,
|
||||
script_tag[1] == HB_TAG_NONE ? script_tag[0] : script_tag[1],
|
||||
feats,
|
||||
gr_utf32, chars, buffer->len,
|
||||
|
|
@ -313,7 +301,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
|
|||
|
||||
hb_codepoint_t *pg = gids;
|
||||
clusters[0].cluster = buffer->info[0].cluster;
|
||||
float curradv = HB_DIRECTION_IS_BACKWARD(buffer->props.direction) ? gr_slot_origin_X(gr_seg_first_slot(seg)) : 0.;
|
||||
float curradv = 0.;
|
||||
if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
|
||||
{
|
||||
curradv = gr_slot_origin_X(gr_seg_first_slot(seg));
|
||||
|
|
@ -342,13 +330,10 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
|
|||
c->base_glyph = ic;
|
||||
c->num_glyphs = 0;
|
||||
if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
|
||||
{
|
||||
ci++;
|
||||
clusters[ci].advance = curradv - gr_slot_origin_X(is);
|
||||
} else {
|
||||
c->advance = curradv - gr_slot_origin_X(is);
|
||||
else
|
||||
clusters[ci].advance = gr_slot_origin_X(is) - curradv;
|
||||
ci++;
|
||||
}
|
||||
ci++;
|
||||
curradv = gr_slot_origin_X(is);
|
||||
}
|
||||
clusters[ci].num_glyphs++;
|
||||
|
|
@ -357,7 +342,9 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
|
|||
clusters[ci].num_chars = after + 1 - clusters[ci].base_char;
|
||||
}
|
||||
|
||||
if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
|
||||
if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
|
||||
clusters[ci].advance += curradv;
|
||||
else
|
||||
clusters[ci].advance = gr_seg_advance_X(seg) - curradv;
|
||||
ci++;
|
||||
|
||||
|
|
@ -368,53 +355,54 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
|
|||
hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j];
|
||||
info->codepoint = gids[clusters[i].base_glyph + j];
|
||||
info->cluster = clusters[i].cluster;
|
||||
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
info->var1.i32 = clusters[i].advance; // all glyphs in the cluster get the same advance
|
||||
}
|
||||
}
|
||||
buffer->len = glyph_count;
|
||||
|
||||
float yscale = font->y_scale / font->x_scale;
|
||||
unsigned int upem = hb_face_get_upem (face);
|
||||
float xscale = (float) font->x_scale / upem;
|
||||
float yscale = (float) font->y_scale / upem;
|
||||
yscale *= yscale / xscale;
|
||||
/* Positioning. */
|
||||
unsigned int currclus = (unsigned int) -1;
|
||||
const hb_glyph_info_t *info = buffer->info;
|
||||
hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL);
|
||||
if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
|
||||
{
|
||||
int currclus = -1;
|
||||
const hb_glyph_info_t *info = buffer->info;
|
||||
hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL);
|
||||
curradvx = 0;
|
||||
for (is = gr_seg_first_slot (seg); is; pPos++, ++info, is = gr_slot_next_in_segment (is))
|
||||
{
|
||||
pPos->x_offset = gr_slot_origin_X (is) - curradvx;
|
||||
pPos->x_offset = gr_slot_origin_X (is) * xscale - curradvx;
|
||||
pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy;
|
||||
if (info->cluster != currclus) {
|
||||
pPos->x_advance = info->var1.i32;
|
||||
pPos->x_advance = info->var1.i32 * xscale;
|
||||
curradvx += pPos->x_advance;
|
||||
currclus = info->cluster;
|
||||
} else
|
||||
pPos->x_advance = 0.;
|
||||
|
||||
pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale;
|
||||
pPos->y_advance = gr_slot_advance_Y (is, grface, NULL) * yscale;
|
||||
curradvy += pPos->y_advance;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int currclus = -1;
|
||||
const hb_glyph_info_t *info = buffer->info;
|
||||
hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL);
|
||||
curradvx = gr_seg_advance_X(seg);
|
||||
for (is = gr_seg_first_slot (seg); is; pPos++, info++, is = gr_slot_next_in_segment (is))
|
||||
{
|
||||
if (info->cluster != currclus)
|
||||
{
|
||||
pPos->x_advance = info->var1.i32;
|
||||
if (currclus != -1) curradvx -= info[-1].var1.i32;
|
||||
pPos->x_advance = info->var1.i32 * xscale;
|
||||
curradvx -= pPos->x_advance;
|
||||
currclus = info->cluster;
|
||||
} else
|
||||
pPos->x_advance = 0.;
|
||||
pPos->x_advance = 0.;
|
||||
|
||||
pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale;
|
||||
pPos->y_advance = gr_slot_advance_Y (is, grface, NULL) * yscale;
|
||||
curradvy -= pPos->y_advance;
|
||||
pPos->x_offset = gr_slot_origin_X (is) - curradvx + pPos->x_advance;
|
||||
pPos->x_offset = (gr_slot_origin_X (is) - info->var1.i32) * xscale - curradvx + pPos->x_advance;
|
||||
pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy;
|
||||
}
|
||||
hb_buffer_reverse_clusters (buffer);
|
||||
|
|
|
|||
|
|
@ -39,9 +39,13 @@ HB_BEGIN_DECLS
|
|||
HB_EXTERN gr_face *
|
||||
hb_graphite2_face_get_gr_face (hb_face_t *face);
|
||||
|
||||
#ifndef HB_DISABLE_DEPRECATED
|
||||
|
||||
HB_EXTERN gr_font *
|
||||
hb_graphite2_font_get_gr_font (hb_font_t *font);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ struct TTCHeaderVersion1
|
|||
Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
|
||||
FixedVersion<>version; /* Version of the TTC Header (1.0),
|
||||
* 0x00010000u */
|
||||
ArrayOf<OffsetTo<OffsetTable, ULONG>, ULONG>
|
||||
ArrayOf<LOffsetTo<OffsetTable>, ULONG>
|
||||
table; /* Array of offsets to the OffsetTable for each font
|
||||
* from the beginning of the file */
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#define HB_OPEN_TYPE_PRIVATE_HH
|
||||
|
||||
#include "hb-private.hh"
|
||||
#include "hb-face-private.hh"
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
|
@ -829,6 +830,7 @@ struct OffsetTo : Offset<OffsetType>
|
|||
}
|
||||
DEFINE_SIZE_STATIC (sizeof(OffsetType));
|
||||
};
|
||||
template <typename Type> struct LOffsetTo : OffsetTo<Type, ULONG> {};
|
||||
template <typename Base, typename OffsetType, typename Type>
|
||||
static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
|
||||
template <typename Base, typename OffsetType, typename Type>
|
||||
|
|
@ -950,6 +952,7 @@ struct ArrayOf
|
|||
public:
|
||||
DEFINE_SIZE_ARRAY (sizeof (LenType), array);
|
||||
};
|
||||
template <typename Type> struct LArrayOf : ArrayOf<Type, ULONG> {};
|
||||
|
||||
/* Array of Offset's */
|
||||
template <typename Type, typename OffsetType=USHORT>
|
||||
|
|
@ -1061,6 +1064,104 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
|
|||
};
|
||||
|
||||
|
||||
/* Lazy struct and blob loaders. */
|
||||
|
||||
/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */
|
||||
template <typename T>
|
||||
struct hb_lazy_loader_t
|
||||
{
|
||||
inline void init (hb_face_t *face_)
|
||||
{
|
||||
face = face_;
|
||||
instance = NULL;
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
{
|
||||
if (instance && instance != &OT::Null(T))
|
||||
{
|
||||
instance->fini();
|
||||
free (instance);
|
||||
}
|
||||
}
|
||||
|
||||
inline const T* get (void) const
|
||||
{
|
||||
retry:
|
||||
T *p = (T *) hb_atomic_ptr_get (&instance);
|
||||
if (unlikely (!p))
|
||||
{
|
||||
p = (T *) calloc (1, sizeof (T));
|
||||
if (unlikely (!p))
|
||||
p = const_cast<T *> (&OT::Null(T));
|
||||
else
|
||||
p->init (face);
|
||||
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), NULL, p)))
|
||||
{
|
||||
if (p != &OT::Null(T))
|
||||
p->fini ();
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
inline const T* operator-> (void) const
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
|
||||
private:
|
||||
hb_face_t *face;
|
||||
T *instance;
|
||||
};
|
||||
|
||||
/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */
|
||||
template <typename T>
|
||||
struct hb_lazy_table_loader_t
|
||||
{
|
||||
inline void init (hb_face_t *face_)
|
||||
{
|
||||
face = face_;
|
||||
instance = NULL;
|
||||
blob = NULL;
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
{
|
||||
hb_blob_destroy (blob);
|
||||
}
|
||||
|
||||
inline const T* get (void) const
|
||||
{
|
||||
retry:
|
||||
T *p = (T *) hb_atomic_ptr_get (&instance);
|
||||
if (unlikely (!p))
|
||||
{
|
||||
hb_blob_t *blob_ = OT::Sanitizer<T>::sanitize (face->reference_table (T::tableTag));
|
||||
p = const_cast<T *>(OT::Sanitizer<T>::lock_instance (blob_));
|
||||
if (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), NULL, p))
|
||||
{
|
||||
hb_blob_destroy (blob_);
|
||||
goto retry;
|
||||
}
|
||||
blob = blob_;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
inline const T* operator-> (void) const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
private:
|
||||
hb_face_t *face;
|
||||
T *instance;
|
||||
mutable hb_blob_t *blob;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ struct IndexSubtableRecord
|
|||
|
||||
USHORT firstGlyphIndex;
|
||||
USHORT lastGlyphIndex;
|
||||
OffsetTo<IndexSubtable, ULONG> offsetToSubtable;
|
||||
LOffsetTo<IndexSubtable> offsetToSubtable;
|
||||
|
||||
DEFINE_SIZE_STATIC(8);
|
||||
};
|
||||
|
|
@ -275,7 +275,7 @@ struct BitmapSizeTable
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<IndexSubtableArray, ULONG> indexSubtableArrayOffset;
|
||||
LOffsetTo<IndexSubtableArray> indexSubtableArrayOffset;
|
||||
ULONG indexTablesSize;
|
||||
ULONG numberOfIndexSubtables;
|
||||
ULONG colorRef;
|
||||
|
|
@ -348,8 +348,8 @@ struct CBLC
|
|||
}
|
||||
|
||||
protected:
|
||||
FixedVersion<>version;
|
||||
ArrayOf<BitmapSizeTable, ULONG> sizeTables;
|
||||
FixedVersion<> version;
|
||||
LArrayOf<BitmapSizeTable> sizeTables;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY(8, sizeTables);
|
||||
|
|
|
|||
|
|
@ -380,9 +380,9 @@ struct VariationSelectorRecord
|
|||
}
|
||||
|
||||
UINT24 varSelector; /* Variation selector. */
|
||||
OffsetTo<DefaultUVS, ULONG>
|
||||
LOffsetTo<DefaultUVS>
|
||||
defaultUVS; /* Offset to Default UVS Table. May be 0. */
|
||||
OffsetTo<NonDefaultUVS, ULONG>
|
||||
LOffsetTo<NonDefaultUVS>
|
||||
nonDefaultUVS; /* Offset to Non-Default UVS Table. May be 0. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (11);
|
||||
|
|
@ -486,7 +486,7 @@ struct EncodingRecord
|
|||
|
||||
USHORT platformID; /* Platform ID. */
|
||||
USHORT encodingID; /* Platform-specific encoding ID. */
|
||||
OffsetTo<CmapSubtable, ULONG>
|
||||
LOffsetTo<CmapSubtable>
|
||||
subtable; /* Byte offset from beginning of table to the subtable for this encoding. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "hb-ot-hhea-table.hh"
|
||||
#include "hb-ot-hmtx-table.hh"
|
||||
#include "hb-ot-os2-table.hh"
|
||||
#include "hb-ot-var-hvar-table.hh"
|
||||
//#include "hb-ot-post-table.hh"
|
||||
|
||||
|
||||
|
|
@ -50,12 +51,16 @@ struct hb_ot_face_metrics_accelerator_t
|
|||
unsigned short line_gap;
|
||||
bool has_font_extents;
|
||||
|
||||
const OT::_mtx *table;
|
||||
const OT::hmtxvmtx *table;
|
||||
hb_blob_t *blob;
|
||||
|
||||
const OT::HVARVVAR *var;
|
||||
hb_blob_t *var_blob;
|
||||
|
||||
inline void init (hb_face_t *face,
|
||||
hb_tag_t _hea_tag,
|
||||
hb_tag_t _mtx_tag,
|
||||
hb_tag_t _var_tag,
|
||||
hb_tag_t os2_tag,
|
||||
unsigned int default_advance = 0)
|
||||
{
|
||||
|
|
@ -91,7 +96,7 @@ struct hb_ot_face_metrics_accelerator_t
|
|||
|
||||
this->has_font_extents = got_font_extents;
|
||||
|
||||
this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag));
|
||||
this->blob = OT::Sanitizer<OT::hmtxvmtx>::sanitize (face->reference_table (_mtx_tag));
|
||||
|
||||
/* Cap num_metrics() and num_advances() based on table length. */
|
||||
unsigned int len = hb_blob_get_length (this->blob);
|
||||
|
|
@ -107,15 +112,20 @@ struct hb_ot_face_metrics_accelerator_t
|
|||
hb_blob_destroy (this->blob);
|
||||
this->blob = hb_blob_get_empty ();
|
||||
}
|
||||
this->table = OT::Sanitizer<OT::_mtx>::lock_instance (this->blob);
|
||||
this->table = OT::Sanitizer<OT::hmtxvmtx>::lock_instance (this->blob);
|
||||
|
||||
this->var_blob = OT::Sanitizer<OT::HVARVVAR>::sanitize (face->reference_table (_var_tag));
|
||||
this->var = OT::Sanitizer<OT::HVARVVAR>::lock_instance (this->var_blob);
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
{
|
||||
hb_blob_destroy (this->blob);
|
||||
hb_blob_destroy (this->var_blob);
|
||||
}
|
||||
|
||||
inline unsigned int get_advance (hb_codepoint_t glyph) const
|
||||
inline unsigned int get_advance (hb_codepoint_t glyph,
|
||||
hb_font_t *font) const
|
||||
{
|
||||
if (unlikely (glyph >= this->num_metrics))
|
||||
{
|
||||
|
|
@ -128,10 +138,8 @@ struct hb_ot_face_metrics_accelerator_t
|
|||
return this->default_advance;
|
||||
}
|
||||
|
||||
if (glyph >= this->num_advances)
|
||||
glyph = this->num_advances - 1;
|
||||
|
||||
return this->table->longMetric[glyph].advance;
|
||||
return this->table->longMetric[MIN (glyph, (uint32_t) this->num_advances - 1)].advance
|
||||
+ this->var->get_advance_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -216,7 +224,7 @@ struct hb_ot_face_cbdt_accelerator_t
|
|||
const OT::CBDT *cbdt;
|
||||
|
||||
unsigned int cbdt_len;
|
||||
float upem;
|
||||
unsigned int upem;
|
||||
|
||||
inline void init (hb_face_t *face)
|
||||
{
|
||||
|
|
@ -246,11 +254,11 @@ struct hb_ot_face_cbdt_accelerator_t
|
|||
{
|
||||
unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */
|
||||
|
||||
if (cblc == NULL)
|
||||
if (!cblc)
|
||||
return false; // Not a color bitmap font.
|
||||
|
||||
const OT::IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem);
|
||||
if (subtable_record == NULL)
|
||||
if (!subtable_record || !x_ppem || !y_ppem)
|
||||
return false;
|
||||
|
||||
if (subtable_record->get_extents (extents))
|
||||
|
|
@ -421,55 +429,13 @@ struct hb_ot_face_cmap_accelerator_t
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct hb_lazy_loader_t
|
||||
{
|
||||
inline void init (hb_face_t *face_)
|
||||
{
|
||||
face = face_;
|
||||
instance = NULL;
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
{
|
||||
if (instance && instance != &OT::Null(T))
|
||||
{
|
||||
instance->fini();
|
||||
free (instance);
|
||||
}
|
||||
}
|
||||
|
||||
inline const T* operator-> (void) const
|
||||
{
|
||||
retry:
|
||||
T *p = (T *) hb_atomic_ptr_get (&instance);
|
||||
if (unlikely (!p))
|
||||
{
|
||||
p = (T *) calloc (1, sizeof (T));
|
||||
if (unlikely (!p))
|
||||
return &OT::Null(T);
|
||||
p->init (face);
|
||||
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), NULL, p)))
|
||||
{
|
||||
p->fini ();
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
hb_face_t *face;
|
||||
T *instance;
|
||||
};
|
||||
|
||||
struct hb_ot_font_t
|
||||
{
|
||||
hb_ot_face_cmap_accelerator_t cmap;
|
||||
hb_ot_face_metrics_accelerator_t h_metrics;
|
||||
hb_ot_face_metrics_accelerator_t v_metrics;
|
||||
hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf;
|
||||
hb_lazy_loader_t<hb_ot_face_cbdt_accelerator_t> cbdt;
|
||||
OT::hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf;
|
||||
OT::hb_lazy_loader_t<hb_ot_face_cbdt_accelerator_t> cbdt;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -482,8 +448,8 @@ _hb_ot_font_create (hb_face_t *face)
|
|||
return NULL;
|
||||
|
||||
ot_font->cmap.init (face);
|
||||
ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_os2);
|
||||
ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE,
|
||||
ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_HVAR, HB_OT_TAG_os2);
|
||||
ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_OT_TAG_VVAR, HB_TAG_NONE,
|
||||
ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
|
||||
ot_font->glyf.init (face);
|
||||
ot_font->cbdt.init (face);
|
||||
|
|
@ -529,23 +495,23 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
|
|||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
|
||||
hb_ot_get_glyph_h_advance (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||
return font->em_scale_x (ot_font->h_metrics.get_advance (glyph));
|
||||
return font->em_scale_x (ot_font->h_metrics.get_advance (glyph, font));
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
|
||||
hb_ot_get_glyph_v_advance (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||
return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph));
|
||||
return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font));
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
|
|
@ -559,6 +525,7 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
|
|||
bool ret = ot_font->glyf->get_extents (glyph, extents);
|
||||
if (!ret)
|
||||
ret = ot_font->cbdt->get_extents (glyph, extents);
|
||||
// TODO Hook up side-bearings variations.
|
||||
extents->x_bearing = font->em_scale_x (extents->x_bearing);
|
||||
extents->y_bearing = font->em_scale_y (extents->y_bearing);
|
||||
extents->width = font->em_scale_x (extents->width);
|
||||
|
|
@ -576,6 +543,7 @@ hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED,
|
|||
metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender);
|
||||
metrics->descender = font->em_scale_y (ot_font->h_metrics.descender);
|
||||
metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap);
|
||||
// TODO Hook up variations.
|
||||
return ot_font->h_metrics.has_font_extents;
|
||||
}
|
||||
|
||||
|
|
@ -589,6 +557,7 @@ hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED,
|
|||
metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender);
|
||||
metrics->descender = font->em_scale_x (ot_font->v_metrics.descender);
|
||||
metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap);
|
||||
// TODO Hook up variations.
|
||||
return ot_font->v_metrics.has_font_extents;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,10 +50,8 @@ struct LongMetric
|
|||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
struct _mtx
|
||||
struct hmtxvmtx
|
||||
{
|
||||
static const hb_tag_t tableTag = HB_TAG('_','m','t','x');
|
||||
|
||||
static const hb_tag_t hmtxTag = HB_OT_TAG_hmtx;
|
||||
static const hb_tag_t vmtxTag = HB_OT_TAG_vmtx;
|
||||
|
||||
|
|
@ -91,10 +89,10 @@ struct _mtx
|
|||
DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX);
|
||||
};
|
||||
|
||||
struct hmtx : _mtx {
|
||||
struct hmtx : hmtxvmtx {
|
||||
static const hb_tag_t tableTag = HB_OT_TAG_hmtx;
|
||||
};
|
||||
struct vmtx : _mtx {
|
||||
struct vmtx : hmtxvmtx {
|
||||
static const hb_tag_t tableTag = HB_OT_TAG_vmtx;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -941,7 +941,7 @@ struct Coverage
|
|||
}
|
||||
|
||||
struct Iter {
|
||||
Iter (void) : format (0) {};
|
||||
Iter (void) : format (0), u () {};
|
||||
inline void init (const Coverage &c_) {
|
||||
format = c_.u.format;
|
||||
switch (format) {
|
||||
|
|
@ -982,8 +982,8 @@ struct Coverage
|
|||
private:
|
||||
unsigned int format;
|
||||
union {
|
||||
CoverageFormat2::Iter format2; /* Put this one first since it's larger; helps shut up compiler. */
|
||||
CoverageFormat1::Iter format1;
|
||||
CoverageFormat2::Iter format2;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
|
@ -1323,6 +1323,14 @@ struct VariationStore
|
|||
this+regions);
|
||||
}
|
||||
|
||||
inline float get_delta (unsigned int index,
|
||||
int *coords, unsigned int coord_count) const
|
||||
{
|
||||
unsigned int outer = index >> 16;
|
||||
unsigned int inner = index & 0xFFFF;
|
||||
return get_delta (outer, inner, coords, coord_count);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -1334,7 +1342,7 @@ struct VariationStore
|
|||
|
||||
protected:
|
||||
USHORT format;
|
||||
OffsetTo<VarRegionList, ULONG> regions;
|
||||
LOffsetTo<VarRegionList> regions;
|
||||
OffsetArrayOf<VarData, ULONG> dataSets;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, dataSets);
|
||||
|
|
@ -1433,8 +1441,8 @@ struct FeatureTableSubstitutionRecord
|
|||
}
|
||||
|
||||
protected:
|
||||
USHORT featureIndex;
|
||||
OffsetTo<Feature, ULONG> feature;
|
||||
USHORT featureIndex;
|
||||
LOffsetTo<Feature> feature;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
|
|
@ -1481,9 +1489,9 @@ struct FeatureVariationRecord
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<ConditionSet, ULONG>
|
||||
LOffsetTo<ConditionSet>
|
||||
conditions;
|
||||
OffsetTo<FeatureTableSubstitution, ULONG>
|
||||
LOffsetTo<FeatureTableSubstitution>
|
||||
substitutions;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
|
|
@ -1527,7 +1535,7 @@ struct FeatureVariations
|
|||
|
||||
protected:
|
||||
FixedVersion<> version; /* Version--0x00010000u */
|
||||
ArrayOf<FeatureVariationRecord, ULONG>
|
||||
LArrayOf<FeatureVariationRecord>
|
||||
varRecords;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, varRecords);
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ struct MarkGlyphSetsFormat1
|
|||
|
||||
protected:
|
||||
USHORT format; /* Format identifier--format = 1 */
|
||||
ArrayOf<OffsetTo<Coverage, ULONG> >
|
||||
ArrayOf<LOffsetTo<Coverage> >
|
||||
coverage; /* Array of long offsets to mark set
|
||||
* coverage tables */
|
||||
public:
|
||||
|
|
@ -443,7 +443,7 @@ struct GDEF
|
|||
* definitions--from beginning of GDEF
|
||||
* header (may be NULL). Introduced
|
||||
* in version 0x00010002. */
|
||||
OffsetTo<VariationStore, ULONG>
|
||||
LOffsetTo<VariationStore>
|
||||
varStore; /* Offset to the table of Item Variation
|
||||
* Store--from beginning of GDEF
|
||||
* header (may be NULL). Introduced
|
||||
|
|
|
|||
|
|
@ -432,6 +432,7 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
|
|||
|
||||
hb_position_t mark_x, mark_y, base_x, base_y;
|
||||
|
||||
buffer->unsafe_to_break (glyph_pos, buffer->idx);
|
||||
mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
|
||||
glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
|
||||
|
||||
|
|
@ -643,6 +644,7 @@ struct PairSet
|
|||
min = mid + 1;
|
||||
else
|
||||
{
|
||||
buffer->unsafe_to_break (buffer->idx, pos + 1);
|
||||
valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
|
||||
valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
|
||||
if (len2)
|
||||
|
|
@ -790,6 +792,7 @@ struct PairPosFormat2
|
|||
unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
|
||||
if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
|
||||
|
||||
buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
|
||||
const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
|
||||
valueFormat1.apply_value (c, this, v, buffer->cur_pos());
|
||||
valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
|
||||
|
|
@ -929,6 +932,7 @@ struct CursivePosFormat1
|
|||
unsigned int i = buffer->idx;
|
||||
unsigned int j = skippy_iter.idx;
|
||||
|
||||
buffer->unsafe_to_break (i, j);
|
||||
hb_position_t entry_x, entry_y, exit_x, exit_y;
|
||||
(this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
|
||||
(this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
|
||||
|
|
|
|||
|
|
@ -1014,14 +1014,17 @@ struct ReverseChainSingleSubstFormat1
|
|||
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
|
||||
const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
|
||||
|
||||
unsigned int start_index = 0, end_index = 0;
|
||||
if (match_backtrack (c,
|
||||
backtrack.len, (USHORT *) backtrack.array,
|
||||
match_coverage, this) &&
|
||||
match_coverage, this,
|
||||
&start_index) &&
|
||||
match_lookahead (c,
|
||||
lookahead.len, (USHORT *) lookahead.array,
|
||||
match_coverage, this,
|
||||
1))
|
||||
1, &end_index))
|
||||
{
|
||||
c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
|
||||
c->replace_glyph_inplace (substitute[index]);
|
||||
/* Note: We DON'T decrease buffer->idx. The main loop does it
|
||||
* for us. This is useful for preventing surprises if someone
|
||||
|
|
|
|||
|
|
@ -319,7 +319,7 @@ struct hb_apply_context_t :
|
|||
if (!c->check_glyph_property (&info, lookup_props))
|
||||
return SKIP_YES;
|
||||
|
||||
if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_fvs (&info) &&
|
||||
if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) &&
|
||||
(ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
|
||||
(ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
|
||||
return SKIP_MAYBE;
|
||||
|
|
@ -342,13 +342,13 @@ struct hb_apply_context_t :
|
|||
inline void init (hb_apply_context_t *c_, bool context_match = false)
|
||||
{
|
||||
c = c_;
|
||||
match_glyph_data = NULL,
|
||||
match_glyph_data = NULL;
|
||||
matcher.set_match_func (NULL, NULL);
|
||||
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);
|
||||
matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
|
||||
/* 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 (c->table_index == 1 || (context_match || c->auto_zwj));
|
||||
matcher.set_mask (context_match ? -1 : c->lookup_mask);
|
||||
}
|
||||
inline void set_lookup_props (unsigned int lookup_props)
|
||||
|
|
@ -457,45 +457,50 @@ struct hb_apply_context_t :
|
|||
return ret;
|
||||
}
|
||||
|
||||
unsigned int table_index; /* GSUB/GPOS */
|
||||
skipping_iterator_t iter_input, iter_context;
|
||||
|
||||
hb_font_t *font;
|
||||
hb_face_t *face;
|
||||
hb_buffer_t *buffer;
|
||||
recurse_func_t recurse_func;
|
||||
const GDEF &gdef;
|
||||
const VariationStore &var_store;
|
||||
|
||||
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;
|
||||
const VariationStore &var_store;
|
||||
skipping_iterator_t iter_input, iter_context;
|
||||
unsigned int table_index; /* GSUB/GPOS */
|
||||
unsigned int lookup_index;
|
||||
unsigned int lookup_props;
|
||||
unsigned int nesting_level_left;
|
||||
unsigned int debug_depth;
|
||||
|
||||
bool auto_zwnj;
|
||||
bool auto_zwj;
|
||||
bool has_glyph_classes;
|
||||
|
||||
|
||||
hb_apply_context_t (unsigned int table_index_,
|
||||
hb_font_t *font_,
|
||||
hb_buffer_t *buffer_) :
|
||||
table_index (table_index_),
|
||||
iter_input (), iter_context (),
|
||||
font (font_), face (font->face), buffer (buffer_),
|
||||
recurse_func (NULL),
|
||||
gdef (*hb_ot_layout_from_face (face)->gdef),
|
||||
var_store (gdef.get_var_store ()),
|
||||
direction (buffer_->props.direction),
|
||||
lookup_mask (1),
|
||||
auto_zwj (true),
|
||||
recurse_func (NULL),
|
||||
nesting_level_left (HB_MAX_NESTING_LEVEL),
|
||||
lookup_props (0),
|
||||
gdef (*hb_ot_layout_from_face (face)->gdef),
|
||||
has_glyph_classes (gdef.has_glyph_classes ()),
|
||||
var_store (gdef.get_var_store ()),
|
||||
iter_input (),
|
||||
iter_context (),
|
||||
table_index (table_index_),
|
||||
lookup_index ((unsigned int) -1),
|
||||
debug_depth (0) {}
|
||||
lookup_props (0),
|
||||
nesting_level_left (HB_MAX_NESTING_LEVEL),
|
||||
debug_depth (0),
|
||||
auto_zwnj (true),
|
||||
auto_zwj (true),
|
||||
has_glyph_classes (gdef.has_glyph_classes ()) {}
|
||||
|
||||
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_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; }
|
||||
inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
|
||||
inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
|
||||
inline void set_lookup_props (unsigned int lookup_props_)
|
||||
|
|
@ -886,7 +891,8 @@ static inline bool match_backtrack (hb_apply_context_t *c,
|
|||
unsigned int count,
|
||||
const USHORT backtrack[],
|
||||
match_func_t match_func,
|
||||
const void *match_data)
|
||||
const void *match_data,
|
||||
unsigned int *match_start)
|
||||
{
|
||||
TRACE_APPLY (NULL);
|
||||
|
||||
|
|
@ -898,6 +904,8 @@ static inline bool match_backtrack (hb_apply_context_t *c,
|
|||
if (!skippy_iter.prev ())
|
||||
return_trace (false);
|
||||
|
||||
*match_start = skippy_iter.idx;
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
|
@ -906,7 +914,8 @@ static inline bool match_lookahead (hb_apply_context_t *c,
|
|||
const USHORT lookahead[],
|
||||
match_func_t match_func,
|
||||
const void *match_data,
|
||||
unsigned int offset)
|
||||
unsigned int offset,
|
||||
unsigned int *end_index)
|
||||
{
|
||||
TRACE_APPLY (NULL);
|
||||
|
||||
|
|
@ -918,6 +927,8 @@ static inline bool match_lookahead (hb_apply_context_t *c,
|
|||
if (!skippy_iter.next ())
|
||||
return_trace (false);
|
||||
|
||||
*end_index = skippy_iter.idx + 1;
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
|
@ -996,7 +1007,29 @@ static inline bool apply_lookup (hb_apply_context_t *c,
|
|||
if (!delta)
|
||||
continue;
|
||||
|
||||
/* Recursed lookup changed buffer len. Adjust. */
|
||||
/* Recursed lookup changed buffer len. Adjust.
|
||||
*
|
||||
* TODO:
|
||||
*
|
||||
* Right now, if buffer length increased by n, we assume n new glyphs
|
||||
* were added right after the current position, and if buffer length
|
||||
* was decreased by n, we assume n match positions after the current
|
||||
* one where removed. The former (buffer length increased) case is
|
||||
* fine, but the decrease case can be improved in at least two ways,
|
||||
* both of which are significant:
|
||||
*
|
||||
* - If recursed-to lookup is MultipleSubst and buffer length
|
||||
* decreased, then it's current match position that was deleted,
|
||||
* NOT the one after it.
|
||||
*
|
||||
* - If buffer length was decreased by n, it does not necessarily
|
||||
* mean that n match positions where removed, as there might
|
||||
* have been marks and default-ignorables in the sequence. We
|
||||
* should instead drop match positions between current-position
|
||||
* and current-position + n instead.
|
||||
*
|
||||
* It should be possible to construct tests for both of these cases.
|
||||
*/
|
||||
|
||||
end += delta;
|
||||
if (end <= int (match_positions[idx]))
|
||||
|
|
@ -1118,10 +1151,11 @@ static inline bool context_apply_lookup (hb_apply_context_t *c,
|
|||
inputCount, input,
|
||||
lookup_context.funcs.match, lookup_context.match_data,
|
||||
&match_length, match_positions)
|
||||
&& apply_lookup (c,
|
||||
&& (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length),
|
||||
apply_lookup (c,
|
||||
inputCount, match_positions,
|
||||
lookupCount, lookupRecord,
|
||||
match_length);
|
||||
match_length));
|
||||
}
|
||||
|
||||
struct Rule
|
||||
|
|
@ -1639,7 +1673,7 @@ static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
|
|||
const LookupRecord lookupRecord[],
|
||||
ChainContextApplyLookupContext &lookup_context)
|
||||
{
|
||||
unsigned int match_length = 0;
|
||||
unsigned int start_index = 0, match_length = 0, end_index = 0;
|
||||
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
|
||||
return match_input (c,
|
||||
inputCount, input,
|
||||
|
|
@ -1647,15 +1681,17 @@ static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
|
|||
&match_length, match_positions)
|
||||
&& match_backtrack (c,
|
||||
backtrackCount, backtrack,
|
||||
lookup_context.funcs.match, lookup_context.match_data[0])
|
||||
lookup_context.funcs.match, lookup_context.match_data[0],
|
||||
&start_index)
|
||||
&& match_lookahead (c,
|
||||
lookaheadCount, lookahead,
|
||||
lookup_context.funcs.match, lookup_context.match_data[2],
|
||||
match_length)
|
||||
&& apply_lookup (c,
|
||||
match_length, &end_index)
|
||||
&& (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
|
||||
apply_lookup (c,
|
||||
inputCount, match_positions,
|
||||
lookupCount, lookupRecord,
|
||||
match_length);
|
||||
match_length));
|
||||
}
|
||||
|
||||
struct ChainRule
|
||||
|
|
@ -2313,7 +2349,7 @@ struct GSUBGPOS
|
|||
featureList; /* FeatureList table */
|
||||
OffsetTo<LookupList>
|
||||
lookupList; /* LookupList table */
|
||||
OffsetTo<FeatureVariations, ULONG>
|
||||
LOffsetTo<FeatureVariations>
|
||||
featureVars; /* Offset to Feature Variations
|
||||
table--from beginning of table
|
||||
* (may be NULL). Introduced
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "hb-font-private.hh"
|
||||
#include "hb-buffer-private.hh"
|
||||
#include "hb-set-private.hh"
|
||||
#include "hb-open-type-private.hh"
|
||||
|
||||
|
||||
/* Private API corresponding to hb-ot-layout.h: */
|
||||
|
|
@ -125,6 +126,8 @@ namespace OT {
|
|||
struct GSUB;
|
||||
struct GPOS;
|
||||
struct MATH;
|
||||
struct fvar;
|
||||
struct avar;
|
||||
}
|
||||
|
||||
struct hb_ot_layout_lookup_accelerator_t
|
||||
|
|
@ -153,12 +156,15 @@ struct hb_ot_layout_t
|
|||
hb_blob_t *gdef_blob;
|
||||
hb_blob_t *gsub_blob;
|
||||
hb_blob_t *gpos_blob;
|
||||
hb_blob_t *math_blob;
|
||||
|
||||
const struct OT::GDEF *gdef;
|
||||
const struct OT::GSUB *gsub;
|
||||
const struct OT::GPOS *gpos;
|
||||
const struct OT::MATH *math;
|
||||
|
||||
/* TODO Move the following out of this struct. */
|
||||
OT::hb_lazy_table_loader_t<struct OT::MATH> math;
|
||||
OT::hb_lazy_table_loader_t<struct OT::fvar> fvar;
|
||||
OT::hb_lazy_table_loader_t<struct OT::avar> avar;
|
||||
|
||||
unsigned int gsub_lookup_count;
|
||||
unsigned int gpos_lookup_count;
|
||||
|
|
@ -191,8 +197,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout);
|
|||
#define syllable() var1.u8[3] /* GSUB/GPOS shaping boundaries */
|
||||
|
||||
|
||||
/* loop over syllables */
|
||||
|
||||
/* Loop over syllables. Based on foreach_cluster(). */
|
||||
#define foreach_syllable(buffer, start, end) \
|
||||
for (unsigned int \
|
||||
_count = buffer->len, \
|
||||
|
|
@ -234,7 +239,8 @@ _next_syllable (hb_buffer_t *buffer, unsigned int start)
|
|||
enum hb_unicode_props_flags_t {
|
||||
UPROPS_MASK_GEN_CAT = 0x001Fu,
|
||||
UPROPS_MASK_IGNORABLE = 0x0020u,
|
||||
UPROPS_MASK_FVS = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3 */
|
||||
UPROPS_MASK_HIDDEN = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3,
|
||||
* or TAG characters */
|
||||
|
||||
/* If GEN_CAT=FORMAT, top byte masks: */
|
||||
UPROPS_MASK_Cf_ZWJ = 0x0100u,
|
||||
|
|
@ -267,7 +273,11 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
|
|||
* Fixes:
|
||||
* https://github.com/behdad/harfbuzz/issues/234
|
||||
*/
|
||||
if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_FVS;
|
||||
if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN;
|
||||
/* TAG characters need similar treatment. Fixes:
|
||||
* https://github.com/behdad/harfbuzz/issues/463
|
||||
*/
|
||||
if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
|
||||
}
|
||||
else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat)))
|
||||
{
|
||||
|
|
@ -367,9 +377,9 @@ _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
|
|||
!_hb_glyph_info_ligated (info);
|
||||
}
|
||||
static inline hb_bool_t
|
||||
_hb_glyph_info_is_default_ignorable_and_not_fvs (const hb_glyph_info_t *info)
|
||||
_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
|
||||
{
|
||||
return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_FVS))
|
||||
return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
|
||||
== UPROPS_MASK_IGNORABLE) &&
|
||||
!_hb_glyph_info_ligated (info);
|
||||
}
|
||||
|
|
@ -617,5 +627,4 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
|
|||
#undef lig_props
|
||||
#undef glyph_props
|
||||
|
||||
|
||||
#endif /* HB_OT_LAYOUT_PRIVATE_HH */
|
||||
|
|
|
|||
|
|
@ -34,15 +34,10 @@
|
|||
#include "hb-ot-layout-gdef-table.hh"
|
||||
#include "hb-ot-layout-gsub-table.hh"
|
||||
#include "hb-ot-layout-gpos-table.hh"
|
||||
#include "hb-ot-layout-jstf-table.hh"
|
||||
#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise.
|
||||
|
||||
#include "hb-ot-map-private.hh"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
|
||||
|
||||
hb_ot_layout_t *
|
||||
_hb_ot_layout_create (hb_face_t *face)
|
||||
|
|
@ -60,9 +55,9 @@ _hb_ot_layout_create (hb_face_t *face)
|
|||
layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
|
||||
layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
|
||||
|
||||
/* The MATH table is rarely used, so only try and load it in _get_math. */
|
||||
layout->math_blob = NULL;
|
||||
layout->math = NULL;
|
||||
layout->math.init (face);
|
||||
layout->fvar.init (face);
|
||||
layout->avar.init (face);
|
||||
|
||||
{
|
||||
/*
|
||||
|
|
@ -106,10 +101,18 @@ _hb_ot_layout_create (hb_face_t *face)
|
|||
|| (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len)
|
||||
/* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */
|
||||
|| (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len)
|
||||
/* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|
||||
|| (964 == gdef_len && 60072 == gpos_len && 23836 == gsub_len)
|
||||
/* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|
||||
|| (976 == gdef_len && 61456 == gpos_len && 23832 == gsub_len)
|
||||
/* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */
|
||||
|| (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len)
|
||||
/* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */
|
||||
|| (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len)
|
||||
/* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|
||||
|| (1006 == gdef_len && 61346 == gpos_len && 24576 == gsub_len)
|
||||
/* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|
||||
|| (1018 == gdef_len && 62828 == gpos_len && 24572 == gsub_len)
|
||||
/* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */
|
||||
|| (1006 == gdef_len && 61352 == gpos_len && 24576 == gsub_len)
|
||||
/* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */
|
||||
|
|
@ -130,6 +133,14 @@ _hb_ot_layout_create (hb_face_t *face)
|
|||
/* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
|
||||
/* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
|
||||
|| (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len)
|
||||
/* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
|
||||
|| (1058 == gdef_len && 11818 == gpos_len && 47032 == gsub_len)
|
||||
/* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
|
||||
|| (1046 == gdef_len && 12600 == gpos_len && 47030 == gsub_len)
|
||||
/* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
|
||||
|| (1058 == gdef_len && 16770 == gpos_len && 71796 == gsub_len)
|
||||
/* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
|
||||
|| (1046 == gdef_len && 17862 == gpos_len && 71790 == gsub_len)
|
||||
/* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
|
||||
|| (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len)
|
||||
/* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
|
||||
|
|
@ -138,6 +149,9 @@ _hb_ot_layout_create (hb_face_t *face)
|
|||
|| (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len)
|
||||
/* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
|
||||
|| (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len)
|
||||
/* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf
|
||||
* "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
|
||||
|| (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len)
|
||||
)
|
||||
{
|
||||
/* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks
|
||||
|
|
@ -187,7 +201,10 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
|
|||
hb_blob_destroy (layout->gdef_blob);
|
||||
hb_blob_destroy (layout->gsub_blob);
|
||||
hb_blob_destroy (layout->gpos_blob);
|
||||
hb_blob_destroy (layout->math_blob);
|
||||
|
||||
layout->math.fini ();
|
||||
layout->fvar.fini ();
|
||||
layout->avar.fini ();
|
||||
|
||||
free (layout);
|
||||
}
|
||||
|
|
@ -262,7 +279,7 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font,
|
|||
hb_codepoint_t glyph,
|
||||
unsigned int start_offset,
|
||||
unsigned int *caret_count /* IN/OUT */,
|
||||
int *caret_array /* OUT */)
|
||||
hb_position_t *caret_array /* OUT */)
|
||||
{
|
||||
return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
|
||||
}
|
||||
|
|
@ -1202,6 +1219,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
|||
c.set_lookup_index (lookup_index);
|
||||
c.set_lookup_mask (lookups[table_index][i].mask);
|
||||
c.set_auto_zwj (lookups[table_index][i].auto_zwj);
|
||||
c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
|
||||
apply_string<Proxy> (&c,
|
||||
proxy.table.get_lookup (lookup_index),
|
||||
proxy.accels[lookup_index]);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ struct hb_ot_map_t
|
|||
hb_mask_t mask;
|
||||
hb_mask_t _1_mask; /* mask for value=1, for quick access */
|
||||
unsigned int needs_fallback : 1;
|
||||
unsigned int auto_zwnj : 1;
|
||||
unsigned int auto_zwj : 1;
|
||||
|
||||
static int cmp (const feature_map_t *a, const feature_map_t *b)
|
||||
|
|
@ -58,6 +59,7 @@ struct hb_ot_map_t
|
|||
|
||||
struct lookup_map_t {
|
||||
unsigned short index;
|
||||
unsigned short auto_zwnj : 1;
|
||||
unsigned short auto_zwj : 1;
|
||||
hb_mask_t mask;
|
||||
|
||||
|
|
@ -113,7 +115,7 @@ struct hb_ot_map_t
|
|||
assert (stage <= stages[table_index].len);
|
||||
unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0;
|
||||
unsigned int end = stage < stages[table_index].len ? stages[table_index][stage].last_lookup : lookups[table_index].len;
|
||||
*plookups = &lookups[table_index][start];
|
||||
*plookups = end == start ? NULL : &lookups[table_index][start];
|
||||
*lookup_count = end - start;
|
||||
}
|
||||
|
||||
|
|
@ -150,8 +152,9 @@ enum hb_ot_map_feature_flags_t {
|
|||
F_NONE = 0x0000u,
|
||||
F_GLOBAL = 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */
|
||||
F_HAS_FALLBACK = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */
|
||||
F_MANUAL_ZWJ = 0x0004u, /* Don't skip over ZWJ when matching. */
|
||||
F_GLOBAL_SEARCH = 0x0008u /* If feature not found in LangSys, look for it in global feature list and pick one. */
|
||||
F_MANUAL_ZWNJ = 0x0004u, /* Don't skip over ZWNJ when matching **context**. */
|
||||
F_MANUAL_ZWJ = 0x0008u, /* Don't skip over ZWJ when matching **input**. */
|
||||
F_GLOBAL_SEARCH = 0x0010u /* If feature not found in LangSys, look for it in global feature list and pick one. */
|
||||
};
|
||||
HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
|
||||
/* Macro version for where const is desired. */
|
||||
|
|
@ -196,7 +199,8 @@ struct hb_ot_map_builder_t
|
|||
unsigned int feature_index,
|
||||
unsigned int variations_index,
|
||||
hb_mask_t mask,
|
||||
bool auto_zwj);
|
||||
bool auto_zwnj = true,
|
||||
bool auto_zwj = true);
|
||||
|
||||
struct feature_info_t {
|
||||
hb_tag_t tag;
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
|
|||
unsigned int feature_index,
|
||||
unsigned int variations_index,
|
||||
hb_mask_t mask,
|
||||
bool auto_zwnj,
|
||||
bool auto_zwj)
|
||||
{
|
||||
unsigned int lookup_indices[32];
|
||||
|
|
@ -112,6 +113,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
|
|||
return;
|
||||
lookup->mask = mask;
|
||||
lookup->index = lookup_indices[i];
|
||||
lookup->auto_zwnj = auto_zwnj;
|
||||
lookup->auto_zwj = auto_zwj;
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +138,11 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
const int *coords,
|
||||
unsigned int num_coords)
|
||||
{
|
||||
m.global_mask = 1;
|
||||
ASSERT_STATIC (!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1)));
|
||||
unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1;
|
||||
unsigned int global_bit_shift = _hb_popcount32 (HB_GLYPH_FLAG_DEFINED);
|
||||
|
||||
m.global_mask = global_bit_mask;
|
||||
|
||||
unsigned int required_feature_index[2];
|
||||
hb_tag_t required_feature_tag[2];
|
||||
|
|
@ -188,7 +194,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
|
||||
|
||||
/* Allocate bits now */
|
||||
unsigned int next_bit = 1;
|
||||
unsigned int next_bit = global_bit_shift + 1;
|
||||
|
||||
for (unsigned int i = 0; i < feature_infos.len; i++)
|
||||
{
|
||||
const feature_info_t *info = &feature_infos[i];
|
||||
|
|
@ -243,11 +250,12 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
map->index[1] = feature_index[1];
|
||||
map->stage[0] = info->stage[0];
|
||||
map->stage[1] = info->stage[1];
|
||||
map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ);
|
||||
map->auto_zwj = !(info->flags & F_MANUAL_ZWJ);
|
||||
if ((info->flags & F_GLOBAL) && info->max_value == 1) {
|
||||
/* Uses the global bit */
|
||||
map->shift = 0;
|
||||
map->mask = 1;
|
||||
map->shift = global_bit_shift;
|
||||
map->mask = global_bit_mask;
|
||||
} else {
|
||||
map->shift = next_bit;
|
||||
map->mask = (1u << (next_bit + bits_needed)) - (1u << next_bit);
|
||||
|
|
@ -284,8 +292,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
add_lookups (m, face, table_index,
|
||||
required_feature_index[table_index],
|
||||
variations_index,
|
||||
1 /* mask */,
|
||||
true /* auto_zwj */);
|
||||
global_bit_mask);
|
||||
|
||||
for (unsigned i = 0; i < m.features.len; i++)
|
||||
if (m.features[i].stage[table_index] == stage)
|
||||
|
|
@ -293,6 +300,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
m.features[i].index[table_index],
|
||||
variations_index,
|
||||
m.features[i].mask,
|
||||
m.features[i].auto_zwnj,
|
||||
m.features[i].auto_zwj);
|
||||
|
||||
/* Sort lookups and merge duplicates */
|
||||
|
|
@ -307,6 +315,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
else
|
||||
{
|
||||
m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask;
|
||||
m.lookups[table_index][j].auto_zwnj &= m.lookups[table_index][i].auto_zwnj;
|
||||
m.lookups[table_index][j].auto_zwj &= m.lookups[table_index][i].auto_zwj;
|
||||
}
|
||||
m.lookups[table_index].shrink (j + 1);
|
||||
|
|
|
|||
722
gfx/harfbuzz/src/hb-ot-math-table.hh
Normal file
722
gfx/harfbuzz/src/hb-ot-math-table.hh
Normal file
|
|
@ -0,0 +1,722 @@
|
|||
/*
|
||||
* Copyright © 2016 Igalia S.L.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Igalia Author(s): Frédéric Wang
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_MATH_TABLE_HH
|
||||
#define HB_OT_MATH_TABLE_HH
|
||||
|
||||
#include "hb-open-type-private.hh"
|
||||
#include "hb-ot-layout-common-private.hh"
|
||||
#include "hb-ot-math.h"
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
struct MathValueRecord
|
||||
{
|
||||
inline hb_position_t get_x_value (hb_font_t *font, const void *base) const
|
||||
{ return font->em_scale_x (value) + (base+deviceTable).get_x_delta (font); }
|
||||
inline hb_position_t get_y_value (hb_font_t *font, const void *base) const
|
||||
{ return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); }
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) && deviceTable.sanitize (c, base));
|
||||
}
|
||||
|
||||
protected:
|
||||
SHORT value; /* The X or Y value in design units */
|
||||
OffsetTo<Device> deviceTable; /* Offset to the device table - from the
|
||||
* beginning of parent table. May be NULL.
|
||||
* Suggested format for device table is 1. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
struct MathConstants
|
||||
{
|
||||
inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
||||
unsigned int count = ARRAY_LENGTH (mathValueRecords);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!mathValueRecords[i].sanitize (c, this))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) && sanitize_math_value_records(c));
|
||||
}
|
||||
|
||||
inline hb_position_t get_value (hb_ot_math_constant_t constant,
|
||||
hb_font_t *font) const
|
||||
{
|
||||
switch (constant) {
|
||||
|
||||
case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN:
|
||||
case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN:
|
||||
return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN];
|
||||
|
||||
case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT:
|
||||
case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT:
|
||||
return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]);
|
||||
|
||||
case HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE:
|
||||
case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE:
|
||||
case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP:
|
||||
case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT:
|
||||
return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value(font, this);
|
||||
|
||||
case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT:
|
||||
case HB_OT_MATH_CONSTANT_AXIS_HEIGHT:
|
||||
case HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT:
|
||||
case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN:
|
||||
case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN:
|
||||
case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN:
|
||||
case HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN:
|
||||
case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP:
|
||||
case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN:
|
||||
case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP:
|
||||
case HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN:
|
||||
case HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS:
|
||||
case HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN:
|
||||
case HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN:
|
||||
case HB_OT_MATH_CONSTANT_MATH_LEADING:
|
||||
case HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER:
|
||||
case HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS:
|
||||
case HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP:
|
||||
case HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP:
|
||||
case HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER:
|
||||
case HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS:
|
||||
case HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP:
|
||||
case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP:
|
||||
case HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN:
|
||||
case HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN:
|
||||
case HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN:
|
||||
case HB_OT_MATH_CONSTANT_STACK_GAP_MIN:
|
||||
case HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP:
|
||||
case HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP:
|
||||
case HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN:
|
||||
case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN:
|
||||
case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN:
|
||||
case HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP:
|
||||
case HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN:
|
||||
case HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN:
|
||||
case HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX:
|
||||
case HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN:
|
||||
case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX:
|
||||
case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT:
|
||||
case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN:
|
||||
case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP:
|
||||
case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED:
|
||||
case HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER:
|
||||
case HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS:
|
||||
case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP:
|
||||
case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN:
|
||||
case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN:
|
||||
return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this);
|
||||
|
||||
case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT:
|
||||
return radicalDegreeBottomRaisePercent;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
SHORT percentScaleDown[2];
|
||||
USHORT minHeight[2];
|
||||
MathValueRecord mathValueRecords[51];
|
||||
SHORT radicalDegreeBottomRaisePercent;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (214);
|
||||
};
|
||||
|
||||
struct MathItalicsCorrectionInfo
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
coverage.sanitize (c, this) &&
|
||||
italicsCorrection.sanitize (c, this));
|
||||
}
|
||||
|
||||
inline hb_position_t get_value (hb_codepoint_t glyph,
|
||||
hb_font_t *font) const
|
||||
{
|
||||
unsigned int index = (this+coverage).get_coverage (glyph);
|
||||
return italicsCorrection[index].get_x_value (font, this);
|
||||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<Coverage> coverage; /* Offset to Coverage table -
|
||||
* from the beginning of
|
||||
* MathItalicsCorrectionInfo
|
||||
* table. */
|
||||
ArrayOf<MathValueRecord> italicsCorrection; /* Array of MathValueRecords
|
||||
* defining italics correction
|
||||
* values for each
|
||||
* covered glyph. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, italicsCorrection);
|
||||
};
|
||||
|
||||
struct MathTopAccentAttachment
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
topAccentCoverage.sanitize (c, this) &&
|
||||
topAccentAttachment.sanitize (c, this));
|
||||
}
|
||||
|
||||
inline hb_position_t get_value (hb_codepoint_t glyph,
|
||||
hb_font_t *font) const
|
||||
{
|
||||
unsigned int index = (this+topAccentCoverage).get_coverage (glyph);
|
||||
if (index == NOT_COVERED)
|
||||
return font->get_glyph_h_advance (glyph) / 2;
|
||||
return topAccentAttachment[index].get_x_value(font, this);
|
||||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<Coverage> topAccentCoverage; /* Offset to Coverage table -
|
||||
* from the beginning of
|
||||
* MathTopAccentAttachment
|
||||
* table. */
|
||||
ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
|
||||
* defining top accent
|
||||
* attachment points for each
|
||||
* covered glyph. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment);
|
||||
};
|
||||
|
||||
struct MathKern
|
||||
{
|
||||
inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
unsigned int count = 2 * heightCount + 1;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!mathValueRecords[i].sanitize (c, this)) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
c->check_array (mathValueRecords,
|
||||
mathValueRecords[0].static_size,
|
||||
2 * heightCount + 1) &&
|
||||
sanitize_math_value_records (c));
|
||||
}
|
||||
|
||||
inline hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const
|
||||
{
|
||||
const MathValueRecord* correctionHeight = mathValueRecords;
|
||||
const MathValueRecord* kernValue = mathValueRecords + heightCount;
|
||||
int sign = font->y_scale < 0 ? -1 : +1;
|
||||
|
||||
/* The description of the MathKern table is a ambiguous, but interpreting
|
||||
* "between the two heights found at those indexes" for 0 < i < len as
|
||||
*
|
||||
* correctionHeight[i-1] < correction_height <= correctionHeight[i]
|
||||
*
|
||||
* makes the result consistent with the limit cases and we can just use the
|
||||
* binary search algorithm of std::upper_bound:
|
||||
*/
|
||||
unsigned int i = 0;
|
||||
unsigned int count = heightCount;
|
||||
while (count > 0)
|
||||
{
|
||||
unsigned int half = count / 2;
|
||||
hb_position_t height = correctionHeight[i + half].get_y_value(font, this);
|
||||
if (sign * height < sign * correction_height)
|
||||
{
|
||||
i += half + 1;
|
||||
count -= half + 1;
|
||||
} else
|
||||
count = half;
|
||||
}
|
||||
return kernValue[i].get_x_value(font, this);
|
||||
}
|
||||
|
||||
protected:
|
||||
USHORT heightCount;
|
||||
MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
|
||||
* which the kern value changes.
|
||||
* Sorted by the height value in
|
||||
* design units (heightCount entries),
|
||||
* Followed by:
|
||||
* Array of kern values corresponding
|
||||
* to heights. (heightCount+1 entries).
|
||||
*/
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2, mathValueRecords);
|
||||
};
|
||||
|
||||
struct MathKernInfoRecord
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
||||
unsigned int count = ARRAY_LENGTH (mathKern);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (!mathKern[i].sanitize (c, base)))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
inline hb_position_t get_kerning (hb_ot_math_kern_t kern,
|
||||
hb_position_t correction_height,
|
||||
hb_font_t *font,
|
||||
const void *base) const
|
||||
{
|
||||
unsigned int idx = kern;
|
||||
if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0;
|
||||
return (base+mathKern[idx]).get_value (correction_height, font);
|
||||
}
|
||||
|
||||
protected:
|
||||
/* Offset to MathKern table for each corner -
|
||||
* from the beginning of MathKernInfo table. May be NULL. */
|
||||
OffsetTo<MathKern> mathKern[4];
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
};
|
||||
|
||||
struct MathKernInfo
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
mathKernCoverage.sanitize (c, this) &&
|
||||
mathKernInfoRecords.sanitize (c, this));
|
||||
}
|
||||
|
||||
inline hb_position_t get_kerning (hb_codepoint_t glyph,
|
||||
hb_ot_math_kern_t kern,
|
||||
hb_position_t correction_height,
|
||||
hb_font_t *font) const
|
||||
{
|
||||
unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
|
||||
return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this);
|
||||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<Coverage> mathKernCoverage; /* Offset to Coverage table -
|
||||
* from the beginning of the
|
||||
* MathKernInfo table. */
|
||||
ArrayOf<MathKernInfoRecord> mathKernInfoRecords; /* Array of
|
||||
* MathKernInfoRecords,
|
||||
* per-glyph information for
|
||||
* mathematical positioning
|
||||
* of subscripts and
|
||||
* superscripts. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, mathKernInfoRecords);
|
||||
};
|
||||
|
||||
struct MathGlyphInfo
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
mathItalicsCorrectionInfo.sanitize (c, this) &&
|
||||
mathTopAccentAttachment.sanitize (c, this) &&
|
||||
extendedShapeCoverage.sanitize (c, this) &&
|
||||
mathKernInfo.sanitize(c, this));
|
||||
}
|
||||
|
||||
inline hb_position_t
|
||||
get_italics_correction (hb_codepoint_t glyph, hb_font_t *font) const
|
||||
{ return (this+mathItalicsCorrectionInfo).get_value (glyph, font); }
|
||||
|
||||
inline hb_position_t
|
||||
get_top_accent_attachment (hb_codepoint_t glyph, hb_font_t *font) const
|
||||
{ return (this+mathTopAccentAttachment).get_value (glyph, font); }
|
||||
|
||||
inline bool is_extended_shape (hb_codepoint_t glyph) const
|
||||
{ return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; }
|
||||
|
||||
inline hb_position_t get_kerning (hb_codepoint_t glyph,
|
||||
hb_ot_math_kern_t kern,
|
||||
hb_position_t correction_height,
|
||||
hb_font_t *font) const
|
||||
{ return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); }
|
||||
|
||||
protected:
|
||||
/* Offset to MathItalicsCorrectionInfo table -
|
||||
* from the beginning of MathGlyphInfo table. */
|
||||
OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
|
||||
|
||||
/* Offset to MathTopAccentAttachment table -
|
||||
* from the beginning of MathGlyphInfo table. */
|
||||
OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment;
|
||||
|
||||
/* Offset to coverage table for Extended Shape glyphs -
|
||||
* from the beginning of MathGlyphInfo table. When the left or right glyph of
|
||||
* a box is an extended shape variant, the (ink) box (and not the default
|
||||
* position defined by values in MathConstants table) should be used for
|
||||
* vertical positioning purposes. May be NULL.. */
|
||||
OffsetTo<Coverage> extendedShapeCoverage;
|
||||
|
||||
/* Offset to MathKernInfo table -
|
||||
* from the beginning of MathGlyphInfo table. */
|
||||
OffsetTo<MathKernInfo> mathKernInfo;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
};
|
||||
|
||||
struct MathGlyphVariantRecord
|
||||
{
|
||||
friend struct MathGlyphConstruction;
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
protected:
|
||||
GlyphID variantGlyph; /* Glyph ID for the variant. */
|
||||
USHORT advanceMeasurement; /* Advance width/height, in design units, of the
|
||||
* variant, in the direction of requested
|
||||
* glyph extension. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
struct PartFlags : USHORT
|
||||
{
|
||||
enum Flags {
|
||||
Extender = 0x0001u, /* If set, the part can be skipped or repeated. */
|
||||
|
||||
Defined = 0x0001u, /* All defined flags. */
|
||||
};
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
struct MathGlyphPartRecord
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
inline void extract (hb_ot_math_glyph_part_t &out,
|
||||
int scale,
|
||||
hb_font_t *font) const
|
||||
{
|
||||
out.glyph = glyph;
|
||||
|
||||
out.start_connector_length = font->em_scale (startConnectorLength, scale);
|
||||
out.end_connector_length = font->em_scale (endConnectorLength, scale);
|
||||
out.full_advance = font->em_scale (fullAdvance, scale);
|
||||
|
||||
ASSERT_STATIC ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER ==
|
||||
(unsigned int) PartFlags::Extender);
|
||||
|
||||
out.flags = (hb_ot_math_glyph_part_flags_t)
|
||||
(unsigned int)
|
||||
(partFlags & PartFlags::Defined);
|
||||
}
|
||||
|
||||
protected:
|
||||
GlyphID glyph; /* Glyph ID for the part. */
|
||||
USHORT startConnectorLength; /* Advance width/ height of the straight bar
|
||||
* connector material, in design units, is at
|
||||
* the beginning of the glyph, in the
|
||||
* direction of the extension. */
|
||||
USHORT endConnectorLength; /* Advance width/ height of the straight bar
|
||||
* connector material, in design units, is at
|
||||
* the end of the glyph, in the direction of
|
||||
* the extension. */
|
||||
USHORT fullAdvance; /* Full advance width/height for this part,
|
||||
* in the direction of the extension.
|
||||
* In design units. */
|
||||
PartFlags partFlags; /* Part qualifiers. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (10);
|
||||
};
|
||||
|
||||
struct MathGlyphAssembly
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
italicsCorrection.sanitize(c, this) &&
|
||||
partRecords.sanitize(c));
|
||||
}
|
||||
|
||||
inline unsigned int get_parts (hb_direction_t direction,
|
||||
hb_font_t *font,
|
||||
unsigned int start_offset,
|
||||
unsigned int *parts_count, /* IN/OUT */
|
||||
hb_ot_math_glyph_part_t *parts /* OUT */,
|
||||
hb_position_t *italics_correction /* OUT */) const
|
||||
{
|
||||
if (parts_count)
|
||||
{
|
||||
int scale = font->dir_scale (direction);
|
||||
const MathGlyphPartRecord *arr =
|
||||
partRecords.sub_array (start_offset, parts_count);
|
||||
unsigned int count = *parts_count;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
arr[i].extract (parts[i], scale, font);
|
||||
}
|
||||
|
||||
if (italics_correction)
|
||||
*italics_correction = italicsCorrection.get_x_value (font, this);
|
||||
|
||||
return partRecords.len;
|
||||
}
|
||||
|
||||
protected:
|
||||
MathValueRecord italicsCorrection; /* Italics correction of this
|
||||
* MathGlyphAssembly. Should not
|
||||
* depend on the assembly size. */
|
||||
ArrayOf<MathGlyphPartRecord> partRecords; /* Array of part records, from
|
||||
* left to right and bottom to
|
||||
* top. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (6, partRecords);
|
||||
};
|
||||
|
||||
struct MathGlyphConstruction
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
glyphAssembly.sanitize(c, this) &&
|
||||
mathGlyphVariantRecord.sanitize(c));
|
||||
}
|
||||
|
||||
inline const MathGlyphAssembly &get_assembly (void) const
|
||||
{ return this+glyphAssembly; }
|
||||
|
||||
inline unsigned int get_variants (hb_direction_t direction,
|
||||
hb_font_t *font,
|
||||
unsigned int start_offset,
|
||||
unsigned int *variants_count, /* IN/OUT */
|
||||
hb_ot_math_glyph_variant_t *variants /* OUT */) const
|
||||
{
|
||||
if (variants_count)
|
||||
{
|
||||
int scale = font->dir_scale (direction);
|
||||
const MathGlyphVariantRecord *arr =
|
||||
mathGlyphVariantRecord.sub_array (start_offset, variants_count);
|
||||
unsigned int count = *variants_count;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
variants[i].glyph = arr[i].variantGlyph;
|
||||
variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale);
|
||||
}
|
||||
}
|
||||
return mathGlyphVariantRecord.len;
|
||||
}
|
||||
|
||||
protected:
|
||||
/* Offset to MathGlyphAssembly table for this shape - from the beginning of
|
||||
MathGlyphConstruction table. May be NULL. */
|
||||
OffsetTo<MathGlyphAssembly> glyphAssembly;
|
||||
|
||||
/* MathGlyphVariantRecords for alternative variants of the glyphs. */
|
||||
ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord);
|
||||
};
|
||||
|
||||
struct MathVariants
|
||||
{
|
||||
inline bool sanitize_offsets (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
unsigned int count = vertGlyphCount + horizGlyphCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!glyphConstruction[i].sanitize (c, this)) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
vertGlyphCoverage.sanitize (c, this) &&
|
||||
horizGlyphCoverage.sanitize (c, this) &&
|
||||
c->check_array (glyphConstruction,
|
||||
glyphConstruction[0].static_size,
|
||||
vertGlyphCount + horizGlyphCount) &&
|
||||
sanitize_offsets (c));
|
||||
}
|
||||
|
||||
inline hb_position_t get_min_connector_overlap (hb_direction_t direction,
|
||||
hb_font_t *font) const
|
||||
{ return font->em_scale_dir (minConnectorOverlap, direction); }
|
||||
|
||||
inline unsigned int get_glyph_variants (hb_codepoint_t glyph,
|
||||
hb_direction_t direction,
|
||||
hb_font_t *font,
|
||||
unsigned int start_offset,
|
||||
unsigned int *variants_count, /* IN/OUT */
|
||||
hb_ot_math_glyph_variant_t *variants /* OUT */) const
|
||||
{ return get_glyph_construction (glyph, direction, font)
|
||||
.get_variants (direction, font, start_offset, variants_count, variants); }
|
||||
|
||||
inline unsigned int get_glyph_parts (hb_codepoint_t glyph,
|
||||
hb_direction_t direction,
|
||||
hb_font_t *font,
|
||||
unsigned int start_offset,
|
||||
unsigned int *parts_count, /* IN/OUT */
|
||||
hb_ot_math_glyph_part_t *parts /* OUT */,
|
||||
hb_position_t *italics_correction /* OUT */) const
|
||||
{ return get_glyph_construction (glyph, direction, font)
|
||||
.get_assembly ()
|
||||
.get_parts (direction, font,
|
||||
start_offset, parts_count, parts,
|
||||
italics_correction); }
|
||||
|
||||
private:
|
||||
inline const MathGlyphConstruction &
|
||||
get_glyph_construction (hb_codepoint_t glyph,
|
||||
hb_direction_t direction,
|
||||
hb_font_t *font) const
|
||||
{
|
||||
bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
|
||||
unsigned int count = vertical ? vertGlyphCount : horizGlyphCount;
|
||||
const OffsetTo<Coverage> &coverage = vertical ? vertGlyphCoverage
|
||||
: horizGlyphCoverage;
|
||||
|
||||
unsigned int index = (this+coverage).get_coverage (glyph);
|
||||
if (unlikely (index >= count)) return Null(MathGlyphConstruction);
|
||||
|
||||
if (!vertical)
|
||||
index += vertGlyphCount;
|
||||
|
||||
return this+glyphConstruction[index];
|
||||
}
|
||||
|
||||
protected:
|
||||
USHORT minConnectorOverlap; /* Minimum overlap of connecting
|
||||
* glyphs during glyph construction,
|
||||
* in design units. */
|
||||
OffsetTo<Coverage> vertGlyphCoverage; /* Offset to Coverage table -
|
||||
* from the beginning of MathVariants
|
||||
* table. */
|
||||
OffsetTo<Coverage> horizGlyphCoverage; /* Offset to Coverage table -
|
||||
* from the beginning of MathVariants
|
||||
* table. */
|
||||
USHORT vertGlyphCount; /* Number of glyphs for which
|
||||
* information is provided for
|
||||
* vertically growing variants. */
|
||||
USHORT horizGlyphCount; /* Number of glyphs for which
|
||||
* information is provided for
|
||||
* horizontally growing variants. */
|
||||
|
||||
/* Array of offsets to MathGlyphConstruction tables - from the beginning of
|
||||
the MathVariants table, for shapes growing in vertical/horizontal
|
||||
direction. */
|
||||
OffsetTo<MathGlyphConstruction> glyphConstruction[VAR];
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (10, glyphConstruction);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* MATH -- The MATH Table
|
||||
*/
|
||||
|
||||
struct MATH
|
||||
{
|
||||
static const hb_tag_t tableTag = HB_OT_TAG_MATH;
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (version.sanitize (c) &&
|
||||
likely (version.major == 1) &&
|
||||
mathConstants.sanitize (c, this) &&
|
||||
mathGlyphInfo.sanitize (c, this) &&
|
||||
mathVariants.sanitize (c, this));
|
||||
}
|
||||
|
||||
inline hb_position_t get_constant (hb_ot_math_constant_t constant,
|
||||
hb_font_t *font) const
|
||||
{ return (this+mathConstants).get_value (constant, font); }
|
||||
|
||||
inline const MathGlyphInfo &get_math_glyph_info (void) const
|
||||
{ return this+mathGlyphInfo; }
|
||||
|
||||
inline const MathVariants &get_math_variants (void) const
|
||||
{ return this+mathVariants; }
|
||||
|
||||
protected:
|
||||
FixedVersion<>version; /* Version of the MATH table
|
||||
* initially set to 0x00010000u */
|
||||
OffsetTo<MathConstants> mathConstants;/* MathConstants table */
|
||||
OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */
|
||||
OffsetTo<MathVariants> mathVariants; /* MathVariants table */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (10);
|
||||
};
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* HB_OT_MATH_TABLE_HH */
|
||||
|
|
@ -26,33 +26,15 @@
|
|||
|
||||
#include "hb-open-type-private.hh"
|
||||
|
||||
#include "hb-ot-layout-math-table.hh"
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
|
||||
#include "hb-ot-layout-private.hh"
|
||||
#include "hb-ot-math-table.hh"
|
||||
|
||||
static inline const OT::MATH&
|
||||
_get_math (hb_face_t *face)
|
||||
{
|
||||
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH);
|
||||
|
||||
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
|
||||
|
||||
retry:
|
||||
const OT::MATH *math = (const OT::MATH *) hb_atomic_ptr_get (&layout->math);
|
||||
|
||||
if (unlikely (!math))
|
||||
{
|
||||
hb_blob_t *blob = OT::Sanitizer<OT::MATH>::sanitize (face->reference_table (HB_OT_TAG_MATH));
|
||||
math = OT::Sanitizer<OT::MATH>::lock_instance (blob);
|
||||
if (!hb_atomic_ptr_cmpexch (&layout->math, NULL, math))
|
||||
{
|
||||
hb_blob_destroy (blob);
|
||||
goto retry;
|
||||
}
|
||||
layout->math_blob = blob;
|
||||
}
|
||||
|
||||
return *math;
|
||||
return *(layout->math.get ());
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -64,10 +46,9 @@ retry:
|
|||
* @face: #hb_face_t to test
|
||||
*
|
||||
* This function allows to verify the presence of an OpenType MATH table on the
|
||||
* face. If so, such a table will be loaded into memory and sanitized. You can
|
||||
* then safely call other functions for math layout and shaping.
|
||||
* face.
|
||||
*
|
||||
* Return value: #TRUE if face has a MATH table and #FALSE otherwise
|
||||
* Return value: true if face has a MATH table, false otherwise
|
||||
*
|
||||
* Since: 1.3.3
|
||||
**/
|
||||
|
|
@ -136,10 +117,10 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
|
|||
|
||||
/**
|
||||
* hb_ot_math_is_glyph_extended_shape:
|
||||
* @font: a #hb_font_t to test
|
||||
* @face: a #hb_face_t to test
|
||||
* @glyph: a glyph index to test
|
||||
*
|
||||
* Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise
|
||||
* Return value: true if the glyph is an extended shape, false otherwise
|
||||
*
|
||||
* Since: 1.3.3
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -139,28 +139,28 @@ joining_type (hb_codepoint_t u)
|
|||
switch (u >> 12)
|
||||
{
|
||||
case 0x0u:
|
||||
if (hb_in_range (u, 0x0600u, 0x08E2u)) return joining_table[u - 0x0600u + joining_offset_0x0600u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x0600u, 0x08E2u)) return joining_table[u - 0x0600u + joining_offset_0x0600u];
|
||||
break;
|
||||
|
||||
case 0x1u:
|
||||
if (hb_in_range (u, 0x1806u, 0x18AAu)) return joining_table[u - 0x1806u + joining_offset_0x1806u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x1806u, 0x18AAu)) return joining_table[u - 0x1806u + joining_offset_0x1806u];
|
||||
break;
|
||||
|
||||
case 0x2u:
|
||||
if (hb_in_range (u, 0x200Cu, 0x2069u)) return joining_table[u - 0x200Cu + joining_offset_0x200cu];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x200Cu, 0x2069u)) return joining_table[u - 0x200Cu + joining_offset_0x200cu];
|
||||
break;
|
||||
|
||||
case 0xAu:
|
||||
if (hb_in_range (u, 0xA840u, 0xA873u)) return joining_table[u - 0xA840u + joining_offset_0xa840u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0xA840u, 0xA873u)) return joining_table[u - 0xA840u + joining_offset_0xa840u];
|
||||
break;
|
||||
|
||||
case 0x10u:
|
||||
if (hb_in_range (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
|
||||
if (hb_in_range (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
|
||||
break;
|
||||
|
||||
case 0x1Eu:
|
||||
if (hb_in_range (u, 0x1E900u, 0x1E943u)) return joining_table[u - 0x1E900u + joining_offset_0x1e900u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x1E900u, 0x1E943u)) return joining_table[u - 0x1E900u + joining_offset_0x1e900u];
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -199,6 +199,9 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
|
|||
* work. However, testing shows that rlig and calt are applied
|
||||
* together for Mongolian in Uniscribe. As such, we only add a
|
||||
* pause for Arabic, not other scripts.
|
||||
*
|
||||
* A pause after calt is required to make KFGQPC Uthmanic Script HAFS
|
||||
* work correctly. See https://github.com/behdad/harfbuzz/issues/505
|
||||
*/
|
||||
|
||||
map->add_gsub_pause (nuke_joiners);
|
||||
|
|
@ -222,7 +225,10 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
|
|||
if (plan->props.script == HB_SCRIPT_ARABIC)
|
||||
map->add_gsub_pause (arabic_fallback_shape);
|
||||
|
||||
/* No pause after rclt. See 98460779bae19e4d64d29461ff154b3527bf8420. */
|
||||
map->add_global_bool_feature (HB_TAG('r','c','l','t'));
|
||||
map->add_global_bool_feature (HB_TAG('c','a','l','t'));
|
||||
map->add_gsub_pause (NULL);
|
||||
|
||||
/* The spec includes 'cswh'. Earlier versions of Windows
|
||||
* used to enable this by default, but testing suggests
|
||||
|
|
@ -232,7 +238,6 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
|
|||
* Note that IranNastaliq uses this feature extensively
|
||||
* to fixup broken glyph sequences. Oh well...
|
||||
* Test case: U+0643,U+0640,U+0631. */
|
||||
//map->add_gsub_pause (NULL);
|
||||
//map->add_global_bool_feature (HB_TAG('c','s','w','h'));
|
||||
map->add_global_bool_feature (HB_TAG('m','s','e','t'));
|
||||
}
|
||||
|
|
@ -316,7 +321,10 @@ arabic_joining (hb_buffer_t *buffer)
|
|||
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
|
||||
|
||||
if (entry->prev_action != NONE && prev != (unsigned int) -1)
|
||||
{
|
||||
info[prev].arabic_shaping_action() = entry->prev_action;
|
||||
buffer->unsafe_to_break (prev, i + 1);
|
||||
}
|
||||
|
||||
info[i].arabic_shaping_action() = entry->curr_action;
|
||||
|
||||
|
|
@ -345,7 +353,7 @@ mongolian_variation_selectors (hb_buffer_t *buffer)
|
|||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 1; i < count; i++)
|
||||
if (unlikely (hb_in_range (info[i].codepoint, 0x180Bu, 0x180Du)))
|
||||
if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x180Bu, 0x180Du)))
|
||||
info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action();
|
||||
}
|
||||
|
||||
|
|
@ -540,7 +548,7 @@ apply_stch (const hb_ot_shape_plan_t *plan,
|
|||
/* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */
|
||||
hb_position_t extra_repeat_overlap = 0;
|
||||
hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1);
|
||||
if (shortfall > 0)
|
||||
if (shortfall > 0 && n_repeating > 0)
|
||||
{
|
||||
++n_copies;
|
||||
hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
/* Same order as the feature array below */
|
||||
enum {
|
||||
NONE,
|
||||
_JMO,
|
||||
|
||||
LJMO,
|
||||
VJMO,
|
||||
|
|
@ -105,16 +105,16 @@ data_destroy_hangul (void *data)
|
|||
#define NCount (VCount * TCount)
|
||||
#define SCount (LCount * NCount)
|
||||
|
||||
#define isCombiningL(u) (hb_in_range ((u), LBase, LBase+LCount-1))
|
||||
#define isCombiningV(u) (hb_in_range ((u), VBase, VBase+VCount-1))
|
||||
#define isCombiningT(u) (hb_in_range ((u), TBase+1, TBase+TCount-1))
|
||||
#define isCombinedS(u) (hb_in_range ((u), SBase, SBase+SCount-1))
|
||||
#define isCombiningL(u) (hb_in_range<hb_codepoint_t> ((u), LBase, LBase+LCount-1))
|
||||
#define isCombiningV(u) (hb_in_range<hb_codepoint_t> ((u), VBase, VBase+VCount-1))
|
||||
#define isCombiningT(u) (hb_in_range<hb_codepoint_t> ((u), TBase+1, TBase+TCount-1))
|
||||
#define isCombinedS(u) (hb_in_range<hb_codepoint_t> ((u), SBase, SBase+SCount-1))
|
||||
|
||||
#define isL(u) (hb_in_ranges ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu))
|
||||
#define isV(u) (hb_in_ranges ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u))
|
||||
#define isT(u) (hb_in_ranges ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu))
|
||||
#define isL(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu))
|
||||
#define isV(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u))
|
||||
#define isT(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu))
|
||||
|
||||
#define isHangulTone(u) (hb_in_range ((u), 0x302Eu, 0x302Fu))
|
||||
#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302Eu, 0x302Fu))
|
||||
|
||||
/* buffer var allocations */
|
||||
#define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */
|
||||
|
|
@ -202,6 +202,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
|
|||
if (start < end && end == buffer->out_len)
|
||||
{
|
||||
/* Tone mark follows a valid syllable; move it in front, unless it's zero width. */
|
||||
buffer->unsafe_to_break_from_outbuffer (start, buffer->idx);
|
||||
buffer->next_glyph ();
|
||||
if (!is_zero_width_char (font, u))
|
||||
{
|
||||
|
|
@ -258,6 +259,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
|
|||
else
|
||||
t = 0; /* The next character was not a trailing jamo. */
|
||||
}
|
||||
buffer->unsafe_to_break (buffer->idx, buffer->idx + (t ? 3 : 2));
|
||||
|
||||
/* We've got a syllable <L,V,T?>; see if it can potentially be composed. */
|
||||
if (isCombiningL (l) && isCombiningV (v) && (t == 0 || isCombiningT (t)))
|
||||
|
|
@ -322,6 +324,8 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
|
|||
end = start + 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */
|
||||
}
|
||||
|
||||
/* Otherwise, decompose if font doesn't support <LV> or <LVT>,
|
||||
|
|
@ -368,6 +372,8 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
|
|||
buffer->merge_out_clusters (start, end);
|
||||
continue;
|
||||
}
|
||||
else if ((!tindex && buffer->idx + 1 < count && isT (buffer->cur(+1).codepoint)))
|
||||
buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */
|
||||
}
|
||||
|
||||
if (has_glyph)
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ enum indic_syllabic_category_t {
|
|||
INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED = OT_X, /* Don't care. */
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM,
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_N,
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_Repha, /* TODO */
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_C,
|
||||
INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM,
|
||||
INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_Coeng,
|
||||
INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ,
|
||||
|
|
@ -132,7 +132,7 @@ enum indic_syllabic_category_t {
|
|||
INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* Don't care. */
|
||||
INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_M, /* Is like a vowel matra. */
|
||||
INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_RS,
|
||||
INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER = OT_M, /* Misc Khmer signs. */
|
||||
INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER = OT_SM,
|
||||
INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X,
|
||||
INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_N,
|
||||
INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H,
|
||||
|
|
|
|||
|
|
@ -398,28 +398,35 @@ hb_indic_get_categories (hb_codepoint_t u)
|
|||
switch (u >> 12)
|
||||
{
|
||||
case 0x0u:
|
||||
if (hb_in_range (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
|
||||
if (hb_in_range (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u];
|
||||
if (hb_in_range (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
|
||||
if (unlikely (u == 0x00A0u)) return _(CP,x);
|
||||
break;
|
||||
|
||||
case 0x1u:
|
||||
if (hb_in_range (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
|
||||
if (hb_in_range (u, 0x1780u, 0x17EFu)) return indic_table[u - 0x1780u + indic_offset_0x1780u];
|
||||
if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x1780u, 0x17EFu)) return indic_table[u - 0x1780u + indic_offset_0x1780u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
|
||||
break;
|
||||
|
||||
case 0x2u:
|
||||
if (hb_in_range (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
|
||||
if (hb_in_range (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u];
|
||||
if (unlikely (u == 0x25CCu)) return _(CP,x);
|
||||
break;
|
||||
|
||||
case 0xAu:
|
||||
if (hb_in_range (u, 0xA8E0u, 0xA8F7u)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u];
|
||||
if (hb_in_range (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u];
|
||||
if (hb_in_range (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0xA8E0u, 0xA8F7u)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u];
|
||||
break;
|
||||
|
||||
case 0x11u:
|
||||
// According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
|
||||
// so the Indic shaper needs to know their categories.
|
||||
if (unlikely (u == 0x11303)) return _(Vs,R);
|
||||
if (unlikely (u == 0x1133c)) return _(N,B);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -177,15 +177,15 @@ set_indic_properties (hb_glyph_info_t &info)
|
|||
*/
|
||||
|
||||
/* The following act more like the Bindus. */
|
||||
if (unlikely (hb_in_range (u, 0x0953u, 0x0954u)))
|
||||
if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0953u, 0x0954u)))
|
||||
cat = OT_SM;
|
||||
/* The following act like consonants. */
|
||||
else if (unlikely (hb_in_ranges (u, 0x0A72u, 0x0A73u,
|
||||
else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x0A72u, 0x0A73u,
|
||||
0x1CF5u, 0x1CF6u)))
|
||||
cat = OT_C;
|
||||
/* TODO: The following should only be allowed after a Visarga.
|
||||
* For now, just treat them like regular tone marks. */
|
||||
else if (unlikely (hb_in_range (u, 0x1CE2u, 0x1CE8u)))
|
||||
else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1CE2u, 0x1CE8u)))
|
||||
cat = OT_A;
|
||||
/* TODO: The following should only be allowed after some of
|
||||
* the nasalization marks, maybe only for U+1CE9..U+1CF1.
|
||||
|
|
@ -193,15 +193,24 @@ set_indic_properties (hb_glyph_info_t &info)
|
|||
else if (unlikely (u == 0x1CEDu))
|
||||
cat = OT_A;
|
||||
/* The following take marks in standalone clusters, similar to Avagraha. */
|
||||
else if (unlikely (hb_in_ranges (u, 0xA8F2u, 0xA8F7u,
|
||||
else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0xA8F2u, 0xA8F7u,
|
||||
0x1CE9u, 0x1CECu,
|
||||
0x1CEEu, 0x1CF1u)))
|
||||
{
|
||||
cat = OT_Symbol;
|
||||
ASSERT_STATIC ((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol);
|
||||
}
|
||||
else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CDu, 0x17D1u) ||
|
||||
u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */
|
||||
{
|
||||
/* These can occur mid-syllable (eg. before matras), even though Unicode marks them as Syllable_Modifier.
|
||||
* https://github.com/roozbehp/unicode-data/issues/5 */
|
||||
cat = OT_M;
|
||||
pos = POS_ABOVE_C;
|
||||
}
|
||||
|
||||
else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
|
||||
else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u)))
|
||||
else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
|
||||
cat = OT_PLACEHOLDER;
|
||||
else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
|
||||
|
||||
|
|
@ -411,12 +420,12 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
|
|||
unsigned int i = 0;
|
||||
map->add_gsub_pause (initial_reordering);
|
||||
for (; i < INDIC_BASIC_FEATURES; i++) {
|
||||
map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ);
|
||||
map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
|
||||
map->add_gsub_pause (NULL);
|
||||
}
|
||||
map->add_gsub_pause (final_reordering);
|
||||
for (; i < INDIC_NUM_FEATURES; i++) {
|
||||
map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ);
|
||||
map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
|
||||
}
|
||||
|
||||
map->add_global_bool_feature (HB_TAG('c','a','l','t'));
|
||||
|
|
@ -615,6 +624,8 @@ setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
hb_buffer_t *buffer)
|
||||
{
|
||||
find_syllables (buffer);
|
||||
foreach_syllable (buffer, start, end)
|
||||
buffer->unsafe_to_break (start, end);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -1497,7 +1508,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
|||
if (reph_pos == REPH_POS_AFTER_SUB)
|
||||
{
|
||||
new_reph_pos = base;
|
||||
while (new_reph_pos < end &&
|
||||
while (new_reph_pos + 1 < end &&
|
||||
!( FLAG_SAFE (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD))))
|
||||
new_reph_pos++;
|
||||
if (new_reph_pos < end)
|
||||
|
|
@ -1738,7 +1749,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
|
|||
#endif
|
||||
}
|
||||
|
||||
if ((ab == 0x0DDAu || hb_in_range (ab, 0x0DDCu, 0x0DDEu)))
|
||||
if ((ab == 0x0DDAu || hb_in_range<hb_codepoint_t> (ab, 0x0DDCu, 0x0DDEu)))
|
||||
{
|
||||
/*
|
||||
* Sinhala split matras... Let the fun begin.
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ set_myanmar_properties (hb_glyph_info_t &info)
|
|||
/* Myanmar
|
||||
* http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm#analyze
|
||||
*/
|
||||
if (unlikely (hb_in_range (u, 0xFE00u, 0xFE0Fu)))
|
||||
if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)))
|
||||
cat = (indic_category_t) OT_VS;
|
||||
|
||||
switch (u)
|
||||
|
|
@ -297,6 +297,8 @@ setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
hb_buffer_t *buffer)
|
||||
{
|
||||
find_syllables (buffer);
|
||||
foreach_syllable (buffer, start, end)
|
||||
buffer->unsafe_to_break (start, end);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
|
|
@ -191,6 +191,9 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
|
|||
case HB_SCRIPT_MANICHAEAN:
|
||||
case HB_SCRIPT_PSALTER_PAHLAVI:
|
||||
|
||||
/* Unicode-9.0 additions */
|
||||
case HB_SCRIPT_ADLAM:
|
||||
|
||||
/* 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).
|
||||
* But note that Arabic shaping is applicable only to horizontal layout; for
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ get_consonant_type (hb_codepoint_t u)
|
|||
return RC;
|
||||
if (u == 0x0E0Eu || u == 0x0E0Fu)
|
||||
return DC;
|
||||
if (hb_in_range (u, 0x0E01u, 0x0E2Eu))
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x0E01u, 0x0E2Eu))
|
||||
return NC;
|
||||
return NOT_CONSONANT;
|
||||
}
|
||||
|
|
@ -70,12 +70,12 @@ enum thai_mark_type_t
|
|||
static thai_mark_type_t
|
||||
get_mark_type (hb_codepoint_t u)
|
||||
{
|
||||
if (u == 0x0E31u || hb_in_range (u, 0x0E34u, 0x0E37u) ||
|
||||
u == 0x0E47u || hb_in_range (u, 0x0E4Du, 0x0E4Eu))
|
||||
if (u == 0x0E31u || hb_in_range<hb_codepoint_t> (u, 0x0E34u, 0x0E37u) ||
|
||||
u == 0x0E47u || hb_in_range<hb_codepoint_t> (u, 0x0E4Du, 0x0E4Eu))
|
||||
return AV;
|
||||
if (hb_in_range (u, 0x0E38u, 0x0E3Au))
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x0E38u, 0x0E3Au))
|
||||
return BV;
|
||||
if (hb_in_range (u, 0x0E48u, 0x0E4Cu))
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x0E48u, 0x0E4Cu))
|
||||
return T;
|
||||
return NOT_MARK;
|
||||
}
|
||||
|
|
@ -244,6 +244,7 @@ do_thai_pua_shaping (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
/* At least one of the above/below actions is NOP. */
|
||||
thai_action_t action = above_edge.action != NOP ? above_edge.action : below_edge.action;
|
||||
|
||||
buffer->unsafe_to_break (base, i);
|
||||
if (action == RD)
|
||||
info[base].codepoint = thai_pua_shape (info[base].codepoint, action, font);
|
||||
else
|
||||
|
|
@ -310,7 +311,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
|
|||
#define IS_SARA_AM(x) (((x) & ~0x0080u) == 0x0E33u)
|
||||
#define NIKHAHIT_FROM_SARA_AM(x) ((x) - 0x0E33u + 0x0E4Du)
|
||||
#define SARA_AA_FROM_SARA_AM(x) ((x) - 1)
|
||||
#define IS_TONE_MARK(x) (hb_in_ranges ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u))
|
||||
#define IS_TONE_MARK(x) (hb_in_ranges<hb_codepoint_t> ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u))
|
||||
|
||||
buffer->clear_output ();
|
||||
unsigned int count = buffer->len;
|
||||
|
|
|
|||
|
|
@ -38,31 +38,31 @@
|
|||
static const unsigned char _use_syllable_machine_trans_keys[] = {
|
||||
1u, 1u, 0u, 39u, 21u, 21u, 8u, 39u, 8u, 39u, 1u, 1u, 8u, 39u, 8u, 39u,
|
||||
8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
|
||||
8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 13u, 21u,
|
||||
4u, 4u, 13u, 13u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u,
|
||||
8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
|
||||
8u, 39u, 8u, 39u, 8u, 39u, 1u, 1u, 1u, 39u, 8u, 39u, 21u, 42u, 41u, 42u,
|
||||
42u, 42u, 0
|
||||
8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
|
||||
13u, 21u, 4u, 4u, 13u, 13u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u,
|
||||
8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
|
||||
8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 1u, 1u, 1u, 39u, 8u, 39u,
|
||||
21u, 42u, 41u, 42u, 42u, 42u, 0
|
||||
};
|
||||
|
||||
static const char _use_syllable_machine_key_spans[] = {
|
||||
1, 40, 1, 32, 32, 1, 32, 32,
|
||||
32, 19, 19, 19, 32, 32, 32, 32,
|
||||
32, 32, 32, 32, 32, 32, 32, 9,
|
||||
1, 1, 32, 32, 32, 32, 19, 19,
|
||||
19, 32, 32, 32, 32, 32, 32, 32,
|
||||
32, 32, 32, 1, 39, 32, 22, 2,
|
||||
1
|
||||
32, 32, 32, 32, 32, 32, 32, 32,
|
||||
9, 1, 1, 32, 32, 32, 32, 19,
|
||||
19, 19, 32, 32, 32, 32, 32, 32,
|
||||
32, 32, 32, 32, 32, 1, 39, 32,
|
||||
22, 2, 1
|
||||
};
|
||||
|
||||
static const short _use_syllable_machine_index_offsets[] = {
|
||||
0, 2, 43, 45, 78, 111, 113, 146,
|
||||
179, 212, 232, 252, 272, 305, 338, 371,
|
||||
404, 437, 470, 503, 536, 569, 602, 635,
|
||||
645, 647, 649, 682, 715, 748, 781, 801,
|
||||
821, 841, 874, 907, 940, 973, 1006, 1039,
|
||||
1072, 1105, 1138, 1171, 1173, 1213, 1246, 1269,
|
||||
1272
|
||||
668, 678, 680, 682, 715, 748, 781, 814,
|
||||
834, 854, 874, 907, 940, 973, 1006, 1039,
|
||||
1072, 1105, 1138, 1171, 1204, 1237, 1239, 1279,
|
||||
1312, 1335, 1338
|
||||
};
|
||||
|
||||
static const char _use_syllable_machine_indicies[] = {
|
||||
|
|
@ -131,112 +131,120 @@ static const char _use_syllable_machine_indicies[] = {
|
|||
43, 44, 28, 45, 46, 47, 28, 29,
|
||||
28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 33, 34, 35,
|
||||
36, 37, 28, 28, 33, 28, 28, 28,
|
||||
36, 37, 28, 50, 33, 28, 28, 28,
|
||||
42, 43, 44, 28, 45, 46, 47, 28,
|
||||
29, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 33, 34,
|
||||
35, 36, 37, 38, 39, 33, 28, 28,
|
||||
35, 36, 37, 28, 28, 33, 28, 28,
|
||||
28, 42, 43, 44, 28, 45, 46, 47,
|
||||
28, 29, 28, 28, 30, 31, 28, 28,
|
||||
28, 29, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 33,
|
||||
34, 35, 36, 37, 38, 39, 33, 40,
|
||||
28, 41, 42, 43, 44, 28, 45, 46,
|
||||
34, 35, 36, 37, 38, 39, 33, 28,
|
||||
28, 28, 42, 43, 44, 28, 45, 46,
|
||||
47, 28, 29, 28, 28, 30, 31, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28,
|
||||
33, 34, 35, 36, 37, 38, 39, 33,
|
||||
40, 32, 41, 42, 43, 44, 28, 45,
|
||||
46, 47, 28, 51, 50, 50, 50, 50,
|
||||
50, 50, 50, 52, 50, 5, 53, 51,
|
||||
50, 6, 54, 54, 1, 55, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 56, 10,
|
||||
11, 12, 13, 14, 15, 16, 10, 17,
|
||||
19, 19, 20, 21, 22, 54, 23, 24,
|
||||
25, 54, 6, 54, 54, 1, 55, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
40, 28, 41, 42, 43, 44, 28, 45,
|
||||
46, 47, 28, 29, 28, 28, 30, 31,
|
||||
28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 33, 34, 35, 36, 37, 38, 39,
|
||||
33, 40, 32, 41, 42, 43, 44, 28,
|
||||
45, 46, 47, 28, 52, 51, 51, 51,
|
||||
51, 51, 51, 51, 53, 51, 5, 54,
|
||||
52, 51, 6, 55, 55, 1, 56, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 57,
|
||||
10, 11, 12, 13, 14, 15, 16, 10,
|
||||
17, 19, 19, 20, 21, 22, 54, 23,
|
||||
24, 25, 54, 6, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 10, 11, 12, 13, 14, 54, 54,
|
||||
54, 54, 54, 54, 20, 21, 22, 54,
|
||||
23, 24, 25, 54, 6, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 11, 12, 13, 14, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 23, 24, 25, 54, 6, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 12, 13, 14,
|
||||
54, 6, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 13, 14, 54, 6, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 14,
|
||||
54, 6, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 12, 13, 14, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 23, 24,
|
||||
25, 54, 6, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 12, 13, 14, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
24, 25, 54, 6, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 12, 13, 14, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 25, 54, 6, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 11, 12, 13, 14, 54,
|
||||
54, 54, 54, 54, 54, 20, 21, 22,
|
||||
54, 23, 24, 25, 54, 6, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 11, 12, 13, 14,
|
||||
54, 54, 54, 54, 54, 54, 54, 21,
|
||||
22, 54, 23, 24, 25, 54, 6, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 11, 12, 13,
|
||||
14, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 22, 54, 23, 24, 25, 54, 6,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 10, 11, 12,
|
||||
13, 14, 54, 16, 10, 54, 54, 54,
|
||||
20, 21, 22, 54, 23, 24, 25, 54,
|
||||
6, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 10, 11,
|
||||
12, 13, 14, 54, 54, 10, 54, 54,
|
||||
54, 20, 21, 22, 54, 23, 24, 25,
|
||||
54, 6, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 10,
|
||||
11, 12, 13, 14, 15, 16, 10, 54,
|
||||
54, 54, 20, 21, 22, 54, 23, 24,
|
||||
25, 54, 6, 54, 54, 1, 55, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54,
|
||||
10, 11, 12, 13, 14, 15, 16, 10,
|
||||
17, 54, 19, 20, 21, 22, 54, 23,
|
||||
24, 25, 54, 1, 57, 3, 54, 54,
|
||||
54, 3, 54, 54, 6, 54, 54, 1,
|
||||
55, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 10, 11, 12, 13, 14, 15,
|
||||
16, 10, 17, 18, 19, 20, 21, 22,
|
||||
54, 23, 24, 25, 54, 6, 54, 54,
|
||||
1, 55, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 10, 11, 12, 13, 14,
|
||||
15, 16, 10, 17, 18, 19, 20, 21,
|
||||
22, 54, 23, 24, 25, 54, 59, 58,
|
||||
58, 58, 58, 58, 58, 58, 58, 58,
|
||||
58, 58, 58, 58, 58, 58, 58, 58,
|
||||
58, 58, 59, 60, 58, 59, 60, 58,
|
||||
60, 58, 0
|
||||
17, 19, 19, 20, 21, 22, 55, 23,
|
||||
24, 25, 55, 6, 55, 55, 1, 56,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 10, 11, 12, 13, 14, 15, 16,
|
||||
10, 17, 19, 19, 20, 21, 22, 55,
|
||||
23, 24, 25, 55, 6, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 10, 11, 12, 13, 14, 55,
|
||||
55, 55, 55, 55, 55, 20, 21, 22,
|
||||
55, 23, 24, 25, 55, 6, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 11, 12, 13, 14,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 23, 24, 25, 55, 6, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 12, 13,
|
||||
14, 55, 6, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 13, 14, 55, 6, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
14, 55, 6, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 12, 13, 14, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 23,
|
||||
24, 25, 55, 6, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 12, 13, 14, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 24, 25, 55, 6, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 12, 13, 14, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 25, 55, 6, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 11, 12, 13, 14,
|
||||
55, 55, 55, 55, 55, 55, 20, 21,
|
||||
22, 55, 23, 24, 25, 55, 6, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 11, 12, 13,
|
||||
14, 55, 55, 55, 55, 55, 55, 55,
|
||||
21, 22, 55, 23, 24, 25, 55, 6,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 11, 12,
|
||||
13, 14, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 22, 55, 23, 24, 25, 55,
|
||||
6, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 10, 11,
|
||||
12, 13, 14, 55, 16, 10, 55, 55,
|
||||
55, 20, 21, 22, 55, 23, 24, 25,
|
||||
55, 6, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 10,
|
||||
11, 12, 13, 14, 55, 58, 10, 55,
|
||||
55, 55, 20, 21, 22, 55, 23, 24,
|
||||
25, 55, 6, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
10, 11, 12, 13, 14, 55, 55, 10,
|
||||
55, 55, 55, 20, 21, 22, 55, 23,
|
||||
24, 25, 55, 6, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 10, 11, 12, 13, 14, 15, 16,
|
||||
10, 55, 55, 55, 20, 21, 22, 55,
|
||||
23, 24, 25, 55, 6, 55, 55, 1,
|
||||
56, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 10, 11, 12, 13, 14, 15,
|
||||
16, 10, 17, 55, 19, 20, 21, 22,
|
||||
55, 23, 24, 25, 55, 1, 59, 3,
|
||||
55, 55, 55, 3, 55, 55, 6, 55,
|
||||
55, 1, 56, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 10, 11, 12, 13,
|
||||
14, 15, 16, 10, 17, 18, 19, 20,
|
||||
21, 22, 55, 23, 24, 25, 55, 6,
|
||||
55, 55, 1, 56, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 10, 11, 12,
|
||||
13, 14, 15, 16, 10, 17, 18, 19,
|
||||
20, 21, 22, 55, 23, 24, 25, 55,
|
||||
61, 60, 60, 60, 60, 60, 60, 60,
|
||||
60, 60, 60, 60, 60, 60, 60, 60,
|
||||
60, 60, 60, 60, 61, 62, 60, 61,
|
||||
62, 60, 62, 60, 0
|
||||
};
|
||||
|
||||
static const char _use_syllable_machine_trans_targs[] = {
|
||||
1, 26, 2, 3, 1, 23, 1, 43,
|
||||
44, 46, 28, 29, 30, 31, 32, 39,
|
||||
40, 41, 45, 42, 36, 37, 38, 33,
|
||||
34, 35, 1, 1, 1, 1, 4, 5,
|
||||
22, 7, 8, 9, 10, 11, 18, 19,
|
||||
20, 21, 15, 16, 17, 12, 13, 14,
|
||||
6, 1, 1, 24, 25, 1, 1, 0,
|
||||
27, 1, 1, 47, 48
|
||||
1, 27, 2, 3, 1, 24, 1, 45,
|
||||
46, 48, 29, 30, 31, 32, 33, 40,
|
||||
41, 43, 47, 44, 37, 38, 39, 34,
|
||||
35, 36, 1, 1, 1, 1, 4, 5,
|
||||
23, 7, 8, 9, 10, 11, 18, 19,
|
||||
21, 22, 15, 16, 17, 12, 13, 14,
|
||||
6, 1, 20, 1, 25, 26, 1, 1,
|
||||
0, 28, 42, 1, 1, 49, 50
|
||||
};
|
||||
|
||||
static const char _use_syllable_machine_trans_actions[] = {
|
||||
|
|
@ -246,8 +254,8 @@ static const char _use_syllable_machine_trans_actions[] = {
|
|||
0, 0, 7, 8, 9, 10, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 11, 12, 0, 0, 13, 14, 0,
|
||||
2, 15, 16, 0, 0
|
||||
0, 11, 0, 12, 0, 0, 13, 14,
|
||||
0, 2, 0, 15, 16, 0, 0
|
||||
};
|
||||
|
||||
static const char _use_syllable_machine_to_state_actions[] = {
|
||||
|
|
@ -257,7 +265,7 @@ static const char _use_syllable_machine_to_state_actions[] = {
|
|||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
static const char _use_syllable_machine_from_state_actions[] = {
|
||||
|
|
@ -267,17 +275,17 @@ static const char _use_syllable_machine_from_state_actions[] = {
|
|||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
static const short _use_syllable_machine_eof_trans[] = {
|
||||
1, 0, 27, 29, 29, 50, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 51,
|
||||
54, 51, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 55, 55, 55, 55, 55,
|
||||
55, 55, 55, 58, 55, 55, 59, 59,
|
||||
59
|
||||
29, 29, 29, 29, 29, 29, 29, 29,
|
||||
52, 55, 52, 56, 56, 56, 56, 56,
|
||||
56, 56, 56, 56, 56, 56, 56, 56,
|
||||
56, 56, 56, 56, 56, 60, 56, 56,
|
||||
61, 61, 61
|
||||
};
|
||||
|
||||
static const int use_syllable_machine_start = 1;
|
||||
|
|
@ -291,7 +299,7 @@ static const int use_syllable_machine_en_main = 1;
|
|||
|
||||
|
||||
|
||||
#line 138 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 139 "hb-ot-shape-complex-use-machine.rl"
|
||||
|
||||
|
||||
#define found_syllable(syllable_type) \
|
||||
|
|
@ -311,7 +319,7 @@ find_syllables (hb_buffer_t *buffer)
|
|||
int cs;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
||||
#line 315 "hb-ot-shape-complex-use-machine.hh"
|
||||
#line 323 "hb-ot-shape-complex-use-machine.hh"
|
||||
{
|
||||
cs = use_syllable_machine_start;
|
||||
ts = 0;
|
||||
|
|
@ -319,7 +327,7 @@ find_syllables (hb_buffer_t *buffer)
|
|||
act = 0;
|
||||
}
|
||||
|
||||
#line 159 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 160 "hb-ot-shape-complex-use-machine.rl"
|
||||
|
||||
|
||||
p = 0;
|
||||
|
|
@ -328,7 +336,7 @@ find_syllables (hb_buffer_t *buffer)
|
|||
unsigned int last = 0;
|
||||
unsigned int syllable_serial = 1;
|
||||
|
||||
#line 332 "hb-ot-shape-complex-use-machine.hh"
|
||||
#line 340 "hb-ot-shape-complex-use-machine.hh"
|
||||
{
|
||||
int _slen;
|
||||
int _trans;
|
||||
|
|
@ -342,7 +350,7 @@ _resume:
|
|||
#line 1 "NONE"
|
||||
{ts = p;}
|
||||
break;
|
||||
#line 346 "hb-ot-shape-complex-use-machine.hh"
|
||||
#line 354 "hb-ot-shape-complex-use-machine.hh"
|
||||
}
|
||||
|
||||
_keys = _use_syllable_machine_trans_keys + (cs<<1);
|
||||
|
|
@ -365,58 +373,58 @@ _eof_trans:
|
|||
{te = p+1;}
|
||||
break;
|
||||
case 8:
|
||||
#line 127 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 128 "hb-ot-shape-complex-use-machine.rl"
|
||||
{te = p+1;{ found_syllable (independent_cluster); }}
|
||||
break;
|
||||
case 10:
|
||||
#line 129 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 130 "hb-ot-shape-complex-use-machine.rl"
|
||||
{te = p+1;{ found_syllable (standard_cluster); }}
|
||||
break;
|
||||
case 6:
|
||||
#line 133 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 134 "hb-ot-shape-complex-use-machine.rl"
|
||||
{te = p+1;{ found_syllable (broken_cluster); }}
|
||||
break;
|
||||
case 5:
|
||||
#line 134 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 135 "hb-ot-shape-complex-use-machine.rl"
|
||||
{te = p+1;{ found_syllable (non_cluster); }}
|
||||
break;
|
||||
case 7:
|
||||
#line 127 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 128 "hb-ot-shape-complex-use-machine.rl"
|
||||
{te = p;p--;{ found_syllable (independent_cluster); }}
|
||||
break;
|
||||
case 11:
|
||||
#line 128 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 129 "hb-ot-shape-complex-use-machine.rl"
|
||||
{te = p;p--;{ found_syllable (virama_terminated_cluster); }}
|
||||
break;
|
||||
case 9:
|
||||
#line 129 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 130 "hb-ot-shape-complex-use-machine.rl"
|
||||
{te = p;p--;{ found_syllable (standard_cluster); }}
|
||||
break;
|
||||
case 13:
|
||||
#line 130 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 131 "hb-ot-shape-complex-use-machine.rl"
|
||||
{te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }}
|
||||
break;
|
||||
case 12:
|
||||
#line 131 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 132 "hb-ot-shape-complex-use-machine.rl"
|
||||
{te = p;p--;{ found_syllable (numeral_cluster); }}
|
||||
break;
|
||||
case 16:
|
||||
#line 132 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 133 "hb-ot-shape-complex-use-machine.rl"
|
||||
{te = p;p--;{ found_syllable (symbol_cluster); }}
|
||||
break;
|
||||
case 14:
|
||||
#line 133 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 134 "hb-ot-shape-complex-use-machine.rl"
|
||||
{te = p;p--;{ found_syllable (broken_cluster); }}
|
||||
break;
|
||||
case 15:
|
||||
#line 134 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 135 "hb-ot-shape-complex-use-machine.rl"
|
||||
{te = p;p--;{ found_syllable (non_cluster); }}
|
||||
break;
|
||||
case 1:
|
||||
#line 133 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 134 "hb-ot-shape-complex-use-machine.rl"
|
||||
{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
|
||||
break;
|
||||
#line 420 "hb-ot-shape-complex-use-machine.hh"
|
||||
#line 428 "hb-ot-shape-complex-use-machine.hh"
|
||||
}
|
||||
|
||||
_again:
|
||||
|
|
@ -425,7 +433,7 @@ _again:
|
|||
#line 1 "NONE"
|
||||
{ts = 0;}
|
||||
break;
|
||||
#line 429 "hb-ot-shape-complex-use-machine.hh"
|
||||
#line 437 "hb-ot-shape-complex-use-machine.hh"
|
||||
}
|
||||
|
||||
if ( ++p != pe )
|
||||
|
|
@ -441,7 +449,7 @@ _again:
|
|||
|
||||
}
|
||||
|
||||
#line 168 "hb-ot-shape-complex-use-machine.rl"
|
||||
#line 169 "hb-ot-shape-complex-use-machine.rl"
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,8 @@ SMBlw = 42; # SYM_MOD_BELOW
|
|||
|
||||
|
||||
consonant_modifiers = CMAbv* CMBlw* ((H B | SUB) VS? CMAbv? CMBlw*)*;
|
||||
medial_consonants = MPre? MAbv? MBlw? MPst?;
|
||||
# Override: Allow two MBlw. https://github.com/behdad/harfbuzz/issues/376
|
||||
medial_consonants = MPre? MAbv? MBlw?.MBlw? MPst?;
|
||||
dependent_vowels = VPre* VAbv* VBlw* VPst*;
|
||||
vowel_modifiers = VMPre* VMAbv* VMBlw* VMPst*;
|
||||
final_consonants = FAbv* FBlw* FPst* FM?;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
* # IndicSyllabicCategory-9.0.0.txt
|
||||
* # Date: 2016-05-21, 02:46:00 GMT [RP]
|
||||
* # IndicPositionalCategory-9.0.0.txt
|
||||
* # Date: 2016-02-25, 00:48:00 GMT [RP]
|
||||
* # Date: 2016-06-09, 19:33:00 GMT [RP]
|
||||
* # Blocks-9.0.0.txt
|
||||
* # Date: 2016-02-05, 23:48:00 GMT [KW]
|
||||
* UnicodeData.txt does not have a header.
|
||||
|
|
@ -410,7 +410,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
|
|||
|
||||
/* AA00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
|
||||
/* AA10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
|
||||
/* AA20 */ B, B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre,
|
||||
/* AA20 */ B, B, B, B, B, B, B, B, B, VMAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre,
|
||||
/* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MBlw, MBlw, O, O, O, O, O, O, O, O, O,
|
||||
/* AA40 */ B, B, B, FAbv, B, B, B, B, B, B, B, B, FAbv, FPst, O, O,
|
||||
/* AA50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
|
||||
|
|
@ -644,47 +644,47 @@ hb_use_get_categories (hb_codepoint_t u)
|
|||
switch (u >> 12)
|
||||
{
|
||||
case 0x0u:
|
||||
if (hb_in_range (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u];
|
||||
if (hb_in_range (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u];
|
||||
if (hb_in_range (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u];
|
||||
if (unlikely (u == 0x034Fu)) return CGJ;
|
||||
break;
|
||||
|
||||
case 0x1u:
|
||||
if (hb_in_range (u, 0x1000u, 0x109Fu)) return use_table[u - 0x1000u + use_offset_0x1000u];
|
||||
if (hb_in_range (u, 0x1700u, 0x17EFu)) return use_table[u - 0x1700u + use_offset_0x1700u];
|
||||
if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u];
|
||||
if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u];
|
||||
if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u];
|
||||
if (hb_in_range (u, 0x1DF8u, 0x1DFFu)) return use_table[u - 0x1DF8u + use_offset_0x1df8u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return use_table[u - 0x1000u + use_offset_0x1000u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x1700u, 0x17EFu)) return use_table[u - 0x1700u + use_offset_0x1700u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x1DF8u, 0x1DFFu)) return use_table[u - 0x1DF8u + use_offset_0x1df8u];
|
||||
break;
|
||||
|
||||
case 0x2u:
|
||||
if (hb_in_range (u, 0x2008u, 0x2017u)) return use_table[u - 0x2008u + use_offset_0x2008u];
|
||||
if (hb_in_range (u, 0x2060u, 0x2087u)) return use_table[u - 0x2060u + use_offset_0x2060u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2017u)) return use_table[u - 0x2008u + use_offset_0x2008u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x2060u, 0x2087u)) return use_table[u - 0x2060u + use_offset_0x2060u];
|
||||
if (unlikely (u == 0x25CCu)) return GB;
|
||||
break;
|
||||
|
||||
case 0xAu:
|
||||
if (hb_in_range (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u];
|
||||
if (hb_in_range (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u];
|
||||
break;
|
||||
|
||||
case 0xFu:
|
||||
if (hb_in_range (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u];
|
||||
break;
|
||||
|
||||
case 0x10u:
|
||||
if (hb_in_range (u, 0x10A00u, 0x10A47u)) return use_table[u - 0x10A00u + use_offset_0x10a00u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10A00u, 0x10A47u)) return use_table[u - 0x10A00u + use_offset_0x10a00u];
|
||||
break;
|
||||
|
||||
case 0x11u:
|
||||
if (hb_in_range (u, 0x11000u, 0x110BFu)) return use_table[u - 0x11000u + use_offset_0x11000u];
|
||||
if (hb_in_range (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u];
|
||||
if (hb_in_range (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u];
|
||||
if (hb_in_range (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u];
|
||||
if (hb_in_range (u, 0x11580u, 0x1173Fu)) return use_table[u - 0x11580u + use_offset_0x11580u];
|
||||
if (hb_in_range (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x11000u, 0x110BFu)) return use_table[u - 0x11000u + use_offset_0x11000u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x11580u, 0x1173Fu)) return use_table[u - 0x11580u + use_offset_0x11580u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u];
|
||||
if (unlikely (u == 0x1107Fu)) return HN;
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -354,6 +354,8 @@ setup_syllables (const hb_ot_shape_plan_t *plan,
|
|||
hb_buffer_t *buffer)
|
||||
{
|
||||
find_syllables (buffer);
|
||||
foreach_syllable (buffer, start, end)
|
||||
buffer->unsafe_to_break (start, end);
|
||||
setup_rphf_mask (plan, buffer);
|
||||
setup_topographical_masks (plan, buffer);
|
||||
}
|
||||
|
|
@ -572,28 +574,6 @@ decompose_use (const hb_ot_shape_normalize_context_t *c,
|
|||
*/
|
||||
case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true;
|
||||
case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true;
|
||||
|
||||
/*
|
||||
* Decompose split matras that don't have Unicode decompositions.
|
||||
*/
|
||||
|
||||
/* Limbu */
|
||||
case 0x1925u : *a = 0x1920u; *b= 0x1923u; return true;
|
||||
case 0x1926u : *a = 0x1920u; *b= 0x1924u; return true;
|
||||
|
||||
/* Balinese */
|
||||
case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true;
|
||||
|
||||
#if 0
|
||||
/* Lepcha */
|
||||
case 0x1C29u : *a = no decomp, -> LEFT; return true;
|
||||
|
||||
/* Javanese */
|
||||
case 0xA9C0u : *a = no decomp, -> RIGHT; return true;
|
||||
|
||||
/* Sharada */
|
||||
case 0x111BFu : *a = no decomp, -> ABOVE; return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
return (bool) c->unicode->decompose (ab, a, b);
|
||||
|
|
|
|||
|
|
@ -307,6 +307,9 @@ position_around_base (const hb_ot_shape_plan_t *plan,
|
|||
unsigned int end)
|
||||
{
|
||||
hb_direction_t horiz_dir = HB_DIRECTION_INVALID;
|
||||
|
||||
buffer->unsafe_to_break (base, end);
|
||||
|
||||
hb_glyph_extents_t base_extents;
|
||||
if (!font->get_glyph_extents (buffer->info[base].codepoint,
|
||||
&base_extents))
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ compose_unicode (const hb_ot_shape_normalize_context_t *c,
|
|||
static inline void
|
||||
set_glyph (hb_glyph_info_t &info, hb_font_t *font)
|
||||
{
|
||||
font->get_nominal_glyph (info.codepoint, &info.glyph_index());
|
||||
(void) font->get_nominal_glyph (info.codepoint, &info.glyph_index());
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
|
|||
|
|
@ -128,6 +128,8 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
|
|||
* shaper face data
|
||||
*/
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(ot, face)
|
||||
|
||||
hb_ot_shaper_face_data_t *
|
||||
_hb_ot_shaper_face_data_create (hb_face_t *face)
|
||||
{
|
||||
|
|
@ -145,6 +147,8 @@ _hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
|
|||
* shaper font data
|
||||
*/
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(ot, font)
|
||||
|
||||
struct hb_ot_shaper_font_data_t {};
|
||||
|
||||
hb_ot_shaper_font_data_t *
|
||||
|
|
@ -271,8 +275,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
|
|||
static void
|
||||
hb_form_clusters (hb_buffer_t *buffer)
|
||||
{
|
||||
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
|
||||
buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
|
||||
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII))
|
||||
return;
|
||||
|
||||
/* Loop duplicated in hb_ensure_native_direction(), and in _hb-coretext.cc */
|
||||
|
|
@ -284,11 +287,17 @@ hb_form_clusters (hb_buffer_t *buffer)
|
|||
if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])) &&
|
||||
!_hb_glyph_info_is_joiner (&info[i])))
|
||||
{
|
||||
buffer->merge_clusters (base, i);
|
||||
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
|
||||
buffer->merge_clusters (base, i);
|
||||
else
|
||||
buffer->unsafe_to_break (base, i);
|
||||
base = i;
|
||||
}
|
||||
}
|
||||
buffer->merge_clusters (base, count);
|
||||
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
|
||||
buffer->merge_clusters (base, count);
|
||||
else
|
||||
buffer->unsafe_to_break (base, count);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -362,7 +371,18 @@ hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
|
|||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
/* TODO look in pre/post context text also. */
|
||||
hb_mask_t pre_mask, post_mask;
|
||||
if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
|
||||
{
|
||||
pre_mask = c->plan->numr_mask | c->plan->frac_mask;
|
||||
post_mask = c->plan->frac_mask | c->plan->dnom_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
pre_mask = c->plan->frac_mask | c->plan->dnom_mask;
|
||||
post_mask = c->plan->numr_mask | c->plan->frac_mask;
|
||||
}
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
|
|
@ -379,11 +399,13 @@ hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
|
|||
HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
|
||||
end++;
|
||||
|
||||
buffer->unsafe_to_break (start, end);
|
||||
|
||||
for (unsigned int j = start; j < i; j++)
|
||||
info[j].mask |= c->plan->numr_mask | c->plan->frac_mask;
|
||||
info[j].mask |= pre_mask;
|
||||
info[i].mask |= c->plan->frac_mask;
|
||||
for (unsigned int j = i + 1; j < end; j++)
|
||||
info[j].mask |= c->plan->frac_mask | c->plan->dnom_mask;
|
||||
info[j].mask |= post_mask;
|
||||
|
||||
i = end - 1;
|
||||
}
|
||||
|
|
@ -494,9 +516,10 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
|
|||
/* Merge cluster backward. */
|
||||
if (cluster < info[j - 1].cluster)
|
||||
{
|
||||
unsigned int mask = info[i].mask;
|
||||
unsigned int old_cluster = info[j - 1].cluster;
|
||||
for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
|
||||
info[k - 1].cluster = cluster;
|
||||
buffer->set_cluster (info[k - 1], cluster, mask);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -562,8 +585,6 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c)
|
|||
{
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
hb_ot_shape_initialize_masks (c);
|
||||
|
||||
hb_ot_mirror_chars (c);
|
||||
|
||||
HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index);
|
||||
|
|
@ -767,6 +788,31 @@ hb_ot_position (hb_ot_shape_context_t *c)
|
|||
_hb_buffer_deallocate_gsubgpos_vars (c->buffer);
|
||||
}
|
||||
|
||||
static inline void
|
||||
hb_propagate_flags (hb_buffer_t *buffer)
|
||||
{
|
||||
/* Propagate cluster-level glyph flags to be the same on all cluster glyphs.
|
||||
* Simplifies using them. */
|
||||
|
||||
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK))
|
||||
return;
|
||||
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
||||
foreach_cluster (buffer, start, end)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
|
||||
{
|
||||
mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
break;
|
||||
}
|
||||
if (mask)
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
info[i].mask |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pull it all together! */
|
||||
|
||||
|
|
@ -793,8 +839,10 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
|
|||
|
||||
c->buffer->clear_output ();
|
||||
|
||||
hb_ot_shape_initialize_masks (c);
|
||||
hb_set_unicode_props (c->buffer);
|
||||
hb_insert_dotted_circle (c->buffer, c->font);
|
||||
|
||||
hb_form_clusters (c->buffer);
|
||||
|
||||
hb_ensure_native_direction (c->buffer);
|
||||
|
|
@ -810,6 +858,8 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
|
|||
if (c->plan->shaper->postprocess_glyphs)
|
||||
c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
|
||||
|
||||
hb_propagate_flags (c->buffer);
|
||||
|
||||
_hb_buffer_deallocate_unicode_vars (c->buffer);
|
||||
|
||||
c->buffer->props.direction = c->target_direction;
|
||||
|
|
|
|||
|
|
@ -28,9 +28,6 @@
|
|||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
/* hb_script_t */
|
||||
|
||||
|
|
@ -201,6 +198,7 @@ static const LangTag ot_languages[] = {
|
|||
{"alt", HB_TAG('A','L','T',' ')}, /* [Southern] Altai */
|
||||
{"am", HB_TAG('A','M','H',' ')}, /* Amharic */
|
||||
{"amf", HB_TAG('H','B','N',' ')}, /* Hammer-Banna */
|
||||
{"amw", HB_TAG('S','Y','R',' ')}, /* Western Neo-Aramaic */
|
||||
{"an", HB_TAG('A','R','G',' ')}, /* Aragonese */
|
||||
{"ang", HB_TAG('A','N','G',' ')}, /* Old English (ca. 450-1100) */
|
||||
{"ar", HB_TAG('A','R','A',' ')}, /* Arabic [macrolanguage] */
|
||||
|
|
@ -239,6 +237,7 @@ static const LangTag ot_languages[] = {
|
|||
{"bg", HB_TAG('B','G','R',' ')}, /* Bulgarian */
|
||||
{"bgc", HB_TAG('B','G','C',' ')}, /* Haryanvi */
|
||||
{"bgq", HB_TAG('B','G','Q',' ')}, /* Bagri */
|
||||
{"bgr", HB_TAG('Q','I','N',' ')}, /* Bawm Chin */
|
||||
{"bhb", HB_TAG('B','H','I',' ')}, /* Bhili */
|
||||
{"bhk", HB_TAG('B','I','K',' ')}, /* Albay Bicolano (retired code) */
|
||||
{"bho", HB_TAG('B','H','O',' ')}, /* Bhojpuri */
|
||||
|
|
@ -270,8 +269,10 @@ static const LangTag ot_languages[] = {
|
|||
{"ca", HB_TAG('C','A','T',' ')}, /* Catalan */
|
||||
{"cak", HB_TAG('C','A','K',' ')}, /* Kaqchikel */
|
||||
{"cbk", HB_TAG('C','B','K',' ')}, /* Chavacano */
|
||||
{"cbl", HB_TAG('Q','I','N',' ')}, /* Bualkhaw Chin */
|
||||
{"ce", HB_TAG('C','H','E',' ')}, /* Chechen */
|
||||
{"ceb", HB_TAG('C','E','B',' ')}, /* Cebuano */
|
||||
{"cfm", HB_TAG('H','A','L',' ')}, /* Halam/Falam Chin */
|
||||
{"cgg", HB_TAG('C','G','G',' ')}, /* Chiga */
|
||||
{"ch", HB_TAG('C','H','A',' ')}, /* Chamorro */
|
||||
{"chk", HB_TAG('C','H','K','0')}, /* Chuukese */
|
||||
|
|
@ -279,8 +280,17 @@ static const LangTag ot_languages[] = {
|
|||
{"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */
|
||||
{"chr", HB_TAG('C','H','R',' ')}, /* Cherokee */
|
||||
{"chy", HB_TAG('C','H','Y',' ')}, /* Cheyenne */
|
||||
{"cja", HB_TAG('C','J','A',' ')}, /* Western Cham */
|
||||
{"cjm", HB_TAG('C','J','M',' ')}, /* Eastern Cham */
|
||||
{"cka", HB_TAG('Q','I','N',' ')}, /* Khumi Awa Chin */
|
||||
{"ckb", HB_TAG('K','U','R',' ')}, /* Central Kurdish (Sorani) */
|
||||
{"ckt", HB_TAG('C','H','K',' ')}, /* Chukchi */
|
||||
{"cld", HB_TAG('S','Y','R',' ')}, /* Chaldean Neo-Aramaic */
|
||||
{"cmr", HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin */
|
||||
{"cnb", HB_TAG('Q','I','N',' ')}, /* Chinbon Chin */
|
||||
{"cnh", HB_TAG('Q','I','N',' ')}, /* Hakha Chin */
|
||||
{"cnk", HB_TAG('Q','I','N',' ')}, /* Khumi Chin */
|
||||
{"cnw", HB_TAG('Q','I','N',' ')}, /* Ngawn Chin */
|
||||
{"cop", HB_TAG('C','O','P',' ')}, /* Coptic */
|
||||
{"cpp", HB_TAG('C','P','P',' ')}, /* Creoles */
|
||||
{"cr", HB_TAG('C','R','E',' ')}, /* Cree */
|
||||
|
|
@ -293,6 +303,9 @@ static const LangTag ot_languages[] = {
|
|||
{"crx", HB_TAG('C','R','R',' ')}, /* Carrier */
|
||||
{"cs", HB_TAG('C','S','Y',' ')}, /* Czech */
|
||||
{"csb", HB_TAG('C','S','B',' ')}, /* Kashubian */
|
||||
{"csh", HB_TAG('Q','I','N',' ')}, /* Asho Chin */
|
||||
{"csy", HB_TAG('Q','I','N',' ')}, /* Siyin Chin */
|
||||
{"ctd", HB_TAG('Q','I','N',' ')}, /* Tedim Chin */
|
||||
{"ctg", HB_TAG('C','T','G',' ')}, /* Chittagonian */
|
||||
{"cts", HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol */
|
||||
{"cu", HB_TAG('C','S','L',' ')}, /* Church Slavic */
|
||||
|
|
@ -300,7 +313,9 @@ static const LangTag ot_languages[] = {
|
|||
{"cv", HB_TAG('C','H','U',' ')}, /* Chuvash */
|
||||
{"cwd", HB_TAG('D','C','R',' ')}, /* Woods Cree */
|
||||
{"cy", HB_TAG('W','E','L',' ')}, /* Welsh */
|
||||
{"czt", HB_TAG('Q','I','N',' ')}, /* Zotung Chin */
|
||||
{"da", HB_TAG('D','A','N',' ')}, /* Danish */
|
||||
{"dao", HB_TAG('Q','I','N',' ')}, /* Daai Chin */
|
||||
{"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) */
|
||||
{"dar", HB_TAG('D','A','R',' ')}, /* Dargwa */
|
||||
{"dax", HB_TAG('D','A','X',' ')}, /* Dayi */
|
||||
|
|
@ -343,7 +358,7 @@ static const LangTag ot_languages[] = {
|
|||
{"fi", HB_TAG('F','I','N',' ')}, /* Finnish */
|
||||
{"fil", HB_TAG('P','I','L',' ')}, /* Filipino */
|
||||
{"fj", HB_TAG('F','J','I',' ')}, /* Fijian */
|
||||
{"flm", HB_TAG('H','A','L',' ')}, /* Halam */
|
||||
{"flm", HB_TAG('H','A','L',' ')}, /* Halam/Falam Chin [retired ISO639 code] */
|
||||
{"fo", HB_TAG('F','O','S',' ')}, /* Faroese */
|
||||
{"fon", HB_TAG('F','O','N',' ')}, /* Fon */
|
||||
{"fr", HB_TAG('F','R','A',' ')}, /* French */
|
||||
|
|
@ -390,6 +405,7 @@ static const LangTag ot_languages[] = {
|
|||
{"he", HB_TAG('I','W','R',' ')}, /* Hebrew */
|
||||
{"hi", HB_TAG('H','I','N',' ')}, /* Hindi */
|
||||
{"hil", HB_TAG('H','I','L',' ')}, /* Hiligaynon */
|
||||
{"hlt", HB_TAG('Q','I','N',' ')}, /* Matu Chin */
|
||||
{"hmn", HB_TAG('H','M','N',' ')}, /* Hmong */
|
||||
{"hnd", HB_TAG('H','N','D',' ')}, /* [Southern] Hindko */
|
||||
{"hne", HB_TAG('C','H','H',' ')}, /* Chattisgarhi */
|
||||
|
|
@ -553,6 +569,7 @@ static const LangTag ot_languages[] = {
|
|||
{"mos", HB_TAG('M','O','S',' ')}, /* Mossi */
|
||||
{"mpe", HB_TAG('M','A','J',' ')}, /* Majang */
|
||||
{"mr", HB_TAG('M','A','R',' ')}, /* Marathi */
|
||||
{"mrh", HB_TAG('Q','I','N',' ')}, /* Mara Chin */
|
||||
{"mrj", HB_TAG('H','M','A',' ')}, /* High Mari */
|
||||
{"ms", HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */
|
||||
{"msc", HB_TAG('M','N','K',' ')}, /* Sankaran Maninka */
|
||||
|
|
@ -617,6 +634,7 @@ static const LangTag ot_languages[] = {
|
|||
{"pcc", HB_TAG('P','C','C',' ')}, /* Bouyei */
|
||||
{"pcd", HB_TAG('P','C','D',' ')}, /* Picard */
|
||||
{"pce", HB_TAG('P','L','G',' ')}, /* [Ruching] Palaung */
|
||||
{"pck", HB_TAG('Q','I','N',' ')}, /* Paite Chin */
|
||||
{"pdc", HB_TAG('P','D','C',' ')}, /* Pennsylvania German */
|
||||
{"pes", HB_TAG('F','A','R',' ')}, /* Iranian Persian */
|
||||
{"phk", HB_TAG('P','H','K',' ')}, /* Phake */
|
||||
|
|
@ -674,6 +692,7 @@ static const LangTag ot_languages[] = {
|
|||
{"se", HB_TAG('N','S','M',' ')}, /* Northern Sami */
|
||||
{"seh", HB_TAG('S','N','A',' ')}, /* Sena */
|
||||
{"sel", HB_TAG('S','E','L',' ')}, /* Selkup */
|
||||
{"sez", HB_TAG('Q','I','N',' ')}, /* Senthang Chin */
|
||||
{"sg", HB_TAG('S','G','O',' ')}, /* Sango */
|
||||
{"sga", HB_TAG('S','G','A',' ')}, /* Old Irish (to 900) */
|
||||
{"sgs", HB_TAG('S','G','S',' ')}, /* Samogitian */
|
||||
|
|
@ -713,12 +732,15 @@ static const LangTag ot_languages[] = {
|
|||
{"swh", HB_TAG('S','W','K',' ')}, /* Kiswahili/Swahili */
|
||||
{"swv", HB_TAG('M','A','W',' ')}, /* Shekhawati */
|
||||
{"sxu", HB_TAG('S','X','U',' ')}, /* Upper Saxon */
|
||||
{"syc", HB_TAG('S','Y','R',' ')}, /* Classical Syriac */
|
||||
{"syl", HB_TAG('S','Y','L',' ')}, /* Sylheti */
|
||||
{"syr", HB_TAG('S','Y','R',' ')}, /* Syriac [macrolanguage] */
|
||||
{"szl", HB_TAG('S','Z','L',' ')}, /* Silesian */
|
||||
{"ta", HB_TAG('T','A','M',' ')}, /* Tamil */
|
||||
{"tab", HB_TAG('T','A','B',' ')}, /* Tabasaran */
|
||||
{"tcp", HB_TAG('Q','I','N',' ')}, /* Tawr Chin */
|
||||
{"tcy", HB_TAG('T','U','L',' ')}, /* Tulu */
|
||||
{"tcz", HB_TAG('Q','I','N',' ')}, /* Thado Chin */
|
||||
{"tdd", HB_TAG('T','D','D',' ')}, /* Tai Nüa */
|
||||
{"te", HB_TAG('T','E','L',' ')}, /* Telugu */
|
||||
{"tem", HB_TAG('T','M','N',' ')}, /* Temne */
|
||||
|
|
@ -786,11 +808,13 @@ static const LangTag ot_languages[] = {
|
|||
{"yap", HB_TAG('Y','A','P',' ')}, /* Yapese */
|
||||
{"yi", HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */
|
||||
{"yo", HB_TAG('Y','B','A',' ')}, /* Yoruba */
|
||||
{"yos", HB_TAG('Q','I','N',' ')}, /* Yos, deprecated by IANA in favor of Zou [zom] */
|
||||
{"yso", HB_TAG('N','I','S',' ')}, /* Nisi (China) */
|
||||
{"za", HB_TAG('Z','H','A',' ')}, /* Chuang/Zhuang [macrolanguage] */
|
||||
{"zea", HB_TAG('Z','E','A',' ')}, /* Zeeuws */
|
||||
{"zgh", HB_TAG('Z','G','H',' ')}, /* Standard Morrocan Tamazigh */
|
||||
{"zne", HB_TAG('Z','N','D',' ')}, /* Zande */
|
||||
{"zom", HB_TAG('Q','I','N',' ')}, /* Zou */
|
||||
{"zu", HB_TAG('Z','U','L',' ')}, /* Zulu */
|
||||
{"zum", HB_TAG('L','R','C',' ')}, /* Kumzari */
|
||||
{"zza", HB_TAG('Z','Z','A',' ')}, /* Zazaki */
|
||||
|
|
@ -907,6 +931,30 @@ hb_ot_tag_from_language (hb_language_t language)
|
|||
return HB_TAG('A','P','P','H'); /* Phonetic transcription—Americanist conventions */
|
||||
}
|
||||
|
||||
/*
|
||||
* "Syre" is a BCP-47 script tag, meaning the Estrangela variant of the Syriac script.
|
||||
* It can be applied to any language.
|
||||
*/
|
||||
if (strstr (lang_str, "-syre")) {
|
||||
return HB_TAG('S','Y','R','E'); /* Estrangela Syriac */
|
||||
}
|
||||
|
||||
/*
|
||||
* "Syrj" is a BCP-47 script tag, meaning the Western variant of the Syriac script.
|
||||
* It can be applied to any language.
|
||||
*/
|
||||
if (strstr (lang_str, "-syrj")) {
|
||||
return HB_TAG('S','Y','R','J'); /* Western Syriac */
|
||||
}
|
||||
|
||||
/*
|
||||
* "Syrn" is a BCP-47 script tag, meaning the Eastern variant of the Syriac script.
|
||||
* It can be applied to any language.
|
||||
*/
|
||||
if (strstr (lang_str, "-syrn")) {
|
||||
return HB_TAG('S','Y','R','N'); /* Eastern Syriac */
|
||||
}
|
||||
|
||||
/* Find a language matching in the first component */
|
||||
{
|
||||
const LangTag *lang_tag;
|
||||
|
|
@ -962,6 +1010,22 @@ hb_ot_tag_to_language (hb_tag_t tag)
|
|||
if (tag == HB_OT_TAG_DEFAULT_LANGUAGE)
|
||||
return NULL;
|
||||
|
||||
/* struct LangTag has only room for 3-letter language tags. */
|
||||
switch (tag) {
|
||||
case HB_TAG('A','P','P','H'): /* Phonetic transcription—Americanist conventions */
|
||||
return hb_language_from_string ("und-fonnapa", -1);
|
||||
case HB_TAG('I','P','P','H'): /* Phonetic transcription—IPA conventions */
|
||||
return hb_language_from_string ("und-fonipa", -1);
|
||||
case HB_TAG('S','Y','R',' '): /* Syriac [macrolanguage] */
|
||||
return hb_language_from_string ("syr", -1);
|
||||
case HB_TAG('S','Y','R','E'): /* Estrangela Syriac */
|
||||
return hb_language_from_string ("und-Syre", -1);
|
||||
case HB_TAG('S','Y','R','J'): /* Western Syriac */
|
||||
return hb_language_from_string ("und-Syrj", -1);
|
||||
case HB_TAG('S','Y','R','N'): /* Eastern Syriac */
|
||||
return hb_language_from_string ("und-Syrn", -1);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH (ot_languages); i++)
|
||||
if (ot_languages[i].tag == tag)
|
||||
return hb_language_from_string (ot_languages[i].language, -1);
|
||||
|
|
@ -976,14 +1040,6 @@ hb_ot_tag_to_language (hb_tag_t tag)
|
|||
}
|
||||
}
|
||||
|
||||
/* struct LangTag has only room for 3-letter language tags. */
|
||||
switch (tag) {
|
||||
case HB_TAG('A','P','P','H'): /* Phonetic transcription—Americanist conventions */
|
||||
return hb_language_from_string ("und-fonnapa", -1);
|
||||
case HB_TAG('I','P','P','H'): /* Phonetic transcription—IPA conventions */
|
||||
return hb_language_from_string ("und-fonipa", -1);
|
||||
}
|
||||
|
||||
/* Else return a custom language in the form of "x-hbotABCD" */
|
||||
{
|
||||
unsigned char buf[11] = "x-hbot";
|
||||
|
|
|
|||
149
gfx/harfbuzz/src/hb-ot-var-avar-table.hh
Normal file
149
gfx/harfbuzz/src/hb-ot-var-avar-table.hh
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright © 2017 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_VAR_AVAR_TABLE_HH
|
||||
#define HB_OT_VAR_AVAR_TABLE_HH
|
||||
|
||||
#include "hb-open-type-private.hh"
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
struct AxisValueMap
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
public:
|
||||
F2DOT14 fromCoord; /* A normalized coordinate value obtained using
|
||||
* default normalization. */
|
||||
F2DOT14 toCoord; /* The modified, normalized coordinate value. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
struct SegmentMaps : ArrayOf<AxisValueMap>
|
||||
{
|
||||
inline int map (int value) const
|
||||
{
|
||||
/* The following special-cases are not part of OpenType, which requires
|
||||
* that at least -1, 0, and +1 must be mapped. But we include these as
|
||||
* part of a better error recovery scheme. */
|
||||
|
||||
if (len < 2)
|
||||
{
|
||||
if (!len)
|
||||
return value;
|
||||
else /* len == 1*/
|
||||
return value - array[0].fromCoord + array[0].toCoord;
|
||||
}
|
||||
|
||||
if (value <= array[0].fromCoord)
|
||||
return value - array[0].fromCoord + array[0].toCoord;
|
||||
|
||||
unsigned int i;
|
||||
unsigned int count = len;
|
||||
for (i = 1; i < count && value > array[i].fromCoord; i++)
|
||||
;
|
||||
|
||||
if (value >= array[i].fromCoord)
|
||||
return value - array[i].fromCoord + array[i].toCoord;
|
||||
|
||||
if (unlikely (array[i-1].fromCoord == array[i].fromCoord))
|
||||
return array[i-1].toCoord;
|
||||
|
||||
int denom = array[i].fromCoord - array[i-1].fromCoord;
|
||||
return array[i-1].toCoord +
|
||||
((array[i].toCoord - array[i-1].toCoord) *
|
||||
(value - array[i-1].fromCoord) + denom/2) / denom;
|
||||
}
|
||||
|
||||
DEFINE_SIZE_ARRAY (2, array);
|
||||
};
|
||||
|
||||
/*
|
||||
* avar — Axis Variations Table
|
||||
*/
|
||||
|
||||
#define HB_OT_TAG_avar HB_TAG('a','v','a','r')
|
||||
|
||||
struct avar
|
||||
{
|
||||
static const hb_tag_t tableTag = HB_OT_TAG_avar;
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!(version.sanitize (c) &&
|
||||
version.major == 1 &&
|
||||
c->check_struct (this))))
|
||||
return_trace (false);
|
||||
|
||||
const SegmentMaps *map = &axisSegmentMapsZ;
|
||||
unsigned int count = axisCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (unlikely (!map->sanitize (c)))
|
||||
return_trace (false);
|
||||
map = &StructAfter<SegmentMaps> (*map);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
inline void map_coords (int *coords, unsigned int coords_length) const
|
||||
{
|
||||
unsigned int count = MIN<unsigned int> (coords_length, axisCount);
|
||||
|
||||
const SegmentMaps *map = &axisSegmentMapsZ;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
coords[i] = map->map (coords[i]);
|
||||
map = &StructAfter<SegmentMaps> (*map);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
FixedVersion<>version; /* Version of the avar table
|
||||
* initially set to 0x00010000u */
|
||||
USHORT reserved; /* This field is permanently reserved. Set to 0. */
|
||||
USHORT axisCount; /* The number of variation axes in the font. This
|
||||
* must be the same number as axisCount in the
|
||||
* 'fvar' table. */
|
||||
SegmentMaps axisSegmentMapsZ;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_MIN (8);
|
||||
};
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* HB_OT_VAR_AVAR_TABLE_HH */
|
||||
209
gfx/harfbuzz/src/hb-ot-var-fvar-table.hh
Normal file
209
gfx/harfbuzz/src/hb-ot-var-fvar-table.hh
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Copyright © 2017 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_VAR_FVAR_TABLE_HH
|
||||
#define HB_OT_VAR_FVAR_TABLE_HH
|
||||
|
||||
#include "hb-open-type-private.hh"
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
struct InstanceRecord
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
c->check_array (coordinates, coordinates[0].static_size, axis_count));
|
||||
}
|
||||
|
||||
protected:
|
||||
USHORT subfamilyNameID;/* The name ID for entries in the 'name' table
|
||||
* that provide subfamily names for this instance. */
|
||||
USHORT reserved; /* Reserved for future use — set to 0. */
|
||||
Fixed coordinates[VAR];/* The coordinates array for this instance. */
|
||||
//USHORT postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
|
||||
// * table that provide PostScript names for this
|
||||
// * instance. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, coordinates);
|
||||
};
|
||||
|
||||
struct AxisRecord
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
public:
|
||||
Tag axisTag; /* Tag identifying the design variation for the axis. */
|
||||
Fixed minValue; /* The minimum coordinate value for the axis. */
|
||||
Fixed defaultValue; /* The default coordinate value for the axis. */
|
||||
Fixed maxValue; /* The maximum coordinate value for the axis. */
|
||||
USHORT reserved; /* Reserved for future use — set to 0. */
|
||||
USHORT axisNameID; /* The name ID for entries in the 'name' table that
|
||||
* provide a display name for this axis. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (20);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* fvar — Font Variations Table
|
||||
*/
|
||||
|
||||
#define HB_OT_TAG_fvar HB_TAG('f','v','a','r')
|
||||
|
||||
struct fvar
|
||||
{
|
||||
static const hb_tag_t tableTag = HB_OT_TAG_fvar;
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (version.sanitize (c) &&
|
||||
likely (version.major == 1) &&
|
||||
c->check_struct (this) &&
|
||||
instanceSize >= axisCount * 4 + 4 &&
|
||||
axisSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */
|
||||
instanceSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */
|
||||
c->check_range (this, things) &&
|
||||
c->check_range (&StructAtOffset<char> (this, things),
|
||||
axisCount * axisSize + instanceCount * instanceSize));
|
||||
}
|
||||
|
||||
inline unsigned int get_axis_count (void) const
|
||||
{ return axisCount; }
|
||||
|
||||
inline bool get_axis (unsigned int index, hb_ot_var_axis_t *info) const
|
||||
{
|
||||
if (unlikely (index >= axisCount))
|
||||
return false;
|
||||
|
||||
if (info)
|
||||
{
|
||||
const AxisRecord &axis = get_axes ()[index];
|
||||
info->tag = axis.axisTag;
|
||||
info->name_id = axis.axisNameID;
|
||||
info->default_value = axis.defaultValue / 65536.;
|
||||
/* Ensure order, to simplify client math. */
|
||||
info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
|
||||
info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline unsigned int get_axis_infos (unsigned int start_offset,
|
||||
unsigned int *axes_count /* IN/OUT */,
|
||||
hb_ot_var_axis_t *axes_array /* OUT */) const
|
||||
{
|
||||
if (axes_count)
|
||||
{
|
||||
unsigned int count = axisCount;
|
||||
start_offset = MIN (start_offset, count);
|
||||
|
||||
count -= start_offset;
|
||||
axes_array += start_offset;
|
||||
|
||||
count = MIN (count, *axes_count);
|
||||
*axes_count = count;
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
get_axis (start_offset + i, axes_array + i);
|
||||
}
|
||||
return axisCount;
|
||||
}
|
||||
|
||||
inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const
|
||||
{
|
||||
const AxisRecord *axes = get_axes ();
|
||||
unsigned int count = get_axis_count ();
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (axes[i].axisTag == tag)
|
||||
{
|
||||
if (index)
|
||||
*index = i;
|
||||
return get_axis (i, info);
|
||||
}
|
||||
if (index)
|
||||
*index = HB_OT_VAR_NO_AXIS_INDEX;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline int normalize_axis_value (unsigned int axis_index, float v) const
|
||||
{
|
||||
hb_ot_var_axis_t axis;
|
||||
if (!get_axis (axis_index, &axis))
|
||||
return 0;
|
||||
|
||||
v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */
|
||||
|
||||
if (v == axis.default_value)
|
||||
return 0;
|
||||
else if (v < axis.default_value)
|
||||
v = (v - axis.default_value) / (axis.default_value - axis.min_value);
|
||||
else
|
||||
v = (v - axis.default_value) / (axis.max_value - axis.default_value);
|
||||
return (int) (v * 16384. + (v >= 0. ? .5 : -.5));
|
||||
}
|
||||
|
||||
protected:
|
||||
inline const AxisRecord * get_axes (void) const
|
||||
{ return &StructAtOffset<AxisRecord> (this, things); }
|
||||
|
||||
inline const InstanceRecord * get_instances (void) const
|
||||
{ return &StructAtOffset<InstanceRecord> (get_axes () + axisCount, 0); }
|
||||
|
||||
protected:
|
||||
FixedVersion<>version; /* Version of the fvar table
|
||||
* initially set to 0x00010000u */
|
||||
Offset<> things; /* Offset in bytes from the beginning of the table
|
||||
* to the start of the AxisRecord array. */
|
||||
USHORT reserved; /* This field is permanently reserved. Set to 2. */
|
||||
USHORT axisCount; /* The number of variation axes in the font (the
|
||||
* number of records in the axes array). */
|
||||
USHORT axisSize; /* The size in bytes of each VariationAxisRecord —
|
||||
* set to 20 (0x0014) for this version. */
|
||||
USHORT instanceCount; /* The number of named instances defined in the font
|
||||
* (the number of records in the instances array). */
|
||||
USHORT instanceSize; /* The size in bytes of each InstanceRecord — set
|
||||
* to either axisCount * sizeof(Fixed) + 4, or to
|
||||
* axisCount * sizeof(Fixed) + 6. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (16);
|
||||
};
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* HB_OT_VAR_FVAR_TABLE_HH */
|
||||
165
gfx/harfbuzz/src/hb-ot-var-hvar-table.hh
Normal file
165
gfx/harfbuzz/src/hb-ot-var-hvar-table.hh
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright © 2017 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_VAR_HVAR_TABLE_HH
|
||||
#define HB_OT_VAR_HVAR_TABLE_HH
|
||||
|
||||
#include "hb-ot-layout-common-private.hh"
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
struct DeltaSetIndexMap
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
c->check_array (mapData, get_width (), mapCount));
|
||||
}
|
||||
|
||||
unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */
|
||||
{
|
||||
/* If count is zero, pass value unchanged. This takes
|
||||
* care of direct mapping for advance map. */
|
||||
if (!mapCount)
|
||||
return v;
|
||||
|
||||
if (v >= mapCount)
|
||||
v = mapCount - 1;
|
||||
|
||||
unsigned int u = 0;
|
||||
{ /* Fetch it. */
|
||||
unsigned int w = get_width ();
|
||||
const BYTE *p = mapData + w * v;
|
||||
for (; w; w--)
|
||||
u = (u << 8) + *p++;
|
||||
}
|
||||
|
||||
{ /* Repack it. */
|
||||
unsigned int n = get_inner_bitcount ();
|
||||
unsigned int outer = u >> n;
|
||||
unsigned int inner = u & ((1 << n) - 1);
|
||||
u = (outer<<16) | inner;
|
||||
}
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
protected:
|
||||
inline unsigned int get_width (void) const
|
||||
{ return ((format >> 4) & 3) + 1; }
|
||||
|
||||
inline unsigned int get_inner_bitcount (void) const
|
||||
{ return (format & 0xF) + 1; }
|
||||
|
||||
protected:
|
||||
USHORT format; /* A packed field that describes the compressed
|
||||
* representation of delta-set indices. */
|
||||
USHORT mapCount; /* The number of mapping entries. */
|
||||
BYTE mapData[VAR]; /* The delta-set index mapping data. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, mapData);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* HVAR -- The Horizontal Metrics Variations Table
|
||||
* VVAR -- The Vertical Metrics Variations Table
|
||||
*/
|
||||
|
||||
#define HB_OT_TAG_HVAR HB_TAG('H','V','A','R')
|
||||
#define HB_OT_TAG_VVAR HB_TAG('V','V','A','R')
|
||||
|
||||
struct HVARVVAR
|
||||
{
|
||||
static const hb_tag_t HVARTag = HB_OT_TAG_HVAR;
|
||||
static const hb_tag_t VVARTag = HB_OT_TAG_VVAR;
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (version.sanitize (c) &&
|
||||
likely (version.major == 1) &&
|
||||
varStore.sanitize (c, this) &&
|
||||
advMap.sanitize (c, this) &&
|
||||
lsbMap.sanitize (c, this) &&
|
||||
rsbMap.sanitize (c, this));
|
||||
}
|
||||
|
||||
inline float get_advance_var (hb_codepoint_t glyph,
|
||||
int *coords, unsigned int coord_count) const
|
||||
{
|
||||
unsigned int varidx = (this+advMap).map (glyph);
|
||||
return (this+varStore).get_delta (varidx, coords, coord_count);
|
||||
}
|
||||
|
||||
inline bool has_sidebearing_deltas (void) const
|
||||
{ return lsbMap && rsbMap; }
|
||||
|
||||
protected:
|
||||
FixedVersion<>version; /* Version of the metrics variation table
|
||||
* initially set to 0x00010000u */
|
||||
LOffsetTo<VariationStore>
|
||||
varStore; /* Offset to item variation store table. */
|
||||
LOffsetTo<DeltaSetIndexMap>
|
||||
advMap; /* Offset to advance var-idx mapping. */
|
||||
LOffsetTo<DeltaSetIndexMap>
|
||||
lsbMap; /* Offset to lsb/tsb var-idx mapping. */
|
||||
LOffsetTo<DeltaSetIndexMap>
|
||||
rsbMap; /* Offset to rsb/bsb var-idx mapping. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (20);
|
||||
};
|
||||
|
||||
struct HVAR : HVARVVAR {
|
||||
static const hb_tag_t tableTag = HB_OT_TAG_HVAR;
|
||||
};
|
||||
struct VVAR : HVARVVAR {
|
||||
static const hb_tag_t tableTag = HB_OT_TAG_VVAR;
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (static_cast<const HVARVVAR *> (this)->sanitize (c) &&
|
||||
vorgMap.sanitize (c, this));
|
||||
}
|
||||
|
||||
protected:
|
||||
LOffsetTo<DeltaSetIndexMap>
|
||||
vorgMap; /* Offset to vertical-origin var-idx mapping. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (24);
|
||||
};
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* HB_OT_VAR_HVAR_TABLE_HH */
|
||||
110
gfx/harfbuzz/src/hb-ot-var-mvar-table.hh
Normal file
110
gfx/harfbuzz/src/hb-ot-var-mvar-table.hh
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright © 2017 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_VAR_MVAR_TABLE_HH
|
||||
#define HB_OT_VAR_MVAR_TABLE_HH
|
||||
|
||||
#include "hb-ot-layout-common-private.hh"
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
struct VariationValueRecord
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
public:
|
||||
Tag valueTag; /* Four-byte tag identifying a font-wide measure. */
|
||||
ULONG varIdx; /* Outer/inner index into VariationStore item. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* MVAR -- Metrics Variations Table
|
||||
*/
|
||||
|
||||
#define HB_OT_TAG_MVAR HB_TAG('M','V','A','R')
|
||||
|
||||
struct MVAR
|
||||
{
|
||||
static const hb_tag_t tableTag = HB_OT_TAG_MVAR;
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (version.sanitize (c) &&
|
||||
likely (version.major == 1) &&
|
||||
c->check_struct (this) &&
|
||||
valueRecordSize >= VariationValueRecord::static_size &&
|
||||
varStore.sanitize (c, this) &&
|
||||
c->check_array (values, valueRecordSize, valueRecordCount));
|
||||
}
|
||||
|
||||
inline float get_var (hb_tag_t tag,
|
||||
int *coords, unsigned int coord_count) const
|
||||
{
|
||||
const VariationValueRecord *record;
|
||||
record = (VariationValueRecord *) bsearch (&tag, values,
|
||||
valueRecordCount, valueRecordSize,
|
||||
(hb_compare_func_t) tag_compare);
|
||||
if (!record)
|
||||
return 0.;
|
||||
|
||||
return (this+varStore).get_delta (record->varIdx, coords, coord_count);
|
||||
}
|
||||
|
||||
protected:
|
||||
static inline int tag_compare (const hb_tag_t *a, const Tag *b)
|
||||
{ return b->cmp (*a); }
|
||||
|
||||
protected:
|
||||
FixedVersion<>version; /* Version of the metrics variation table
|
||||
* initially set to 0x00010000u */
|
||||
USHORT reserved; /* Not used; set to 0. */
|
||||
USHORT valueRecordSize;/* The size in bytes of each value record —
|
||||
* must be greater than zero. */
|
||||
USHORT valueRecordCount;/* The number of value records — may be zero. */
|
||||
OffsetTo<VariationStore>
|
||||
varStore; /* Offset to item variation store table. */
|
||||
BYTE values[VAR]; /* Array of value records. The records must be
|
||||
* in binary order of their valueTag field. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (12, values);
|
||||
};
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* HB_OT_VAR_MVAR_TABLE_HH */
|
||||
159
gfx/harfbuzz/src/hb-ot-var.cc
Normal file
159
gfx/harfbuzz/src/hb-ot-var.cc
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright © 2017 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb-open-type-private.hh"
|
||||
|
||||
#include "hb-ot-layout-private.hh"
|
||||
#include "hb-ot-var-avar-table.hh"
|
||||
#include "hb-ot-var-fvar-table.hh"
|
||||
#include "hb-ot-var-mvar-table.hh"
|
||||
#include "hb-ot-var.h"
|
||||
|
||||
/*
|
||||
* fvar/avar
|
||||
*/
|
||||
|
||||
static inline const OT::fvar&
|
||||
_get_fvar (hb_face_t *face)
|
||||
{
|
||||
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::fvar);
|
||||
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
|
||||
return *(layout->fvar.get ());
|
||||
}
|
||||
static inline const OT::avar&
|
||||
_get_avar (hb_face_t *face)
|
||||
{
|
||||
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::avar);
|
||||
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
|
||||
return *(layout->avar.get ());
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ot_var_has_data:
|
||||
* @face: #hb_face_t to test
|
||||
*
|
||||
* This function allows to verify the presence of OpenType variation data on the face.
|
||||
* Alternatively, use hb_ot_var_get_axis_count().
|
||||
*
|
||||
* Return value: true if face has a `fvar' table and false otherwise
|
||||
*
|
||||
* Since: 1.4.2
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_ot_var_has_data (hb_face_t *face)
|
||||
{
|
||||
return &_get_fvar (face) != &OT::Null(OT::fvar);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ot_var_get_axis_count:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
**/
|
||||
unsigned int
|
||||
hb_ot_var_get_axis_count (hb_face_t *face)
|
||||
{
|
||||
const OT::fvar &fvar = _get_fvar (face);
|
||||
return fvar.get_axis_count ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ot_var_get_axes:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
**/
|
||||
unsigned int
|
||||
hb_ot_var_get_axes (hb_face_t *face,
|
||||
unsigned int start_offset,
|
||||
unsigned int *axes_count /* IN/OUT */,
|
||||
hb_ot_var_axis_t *axes_array /* OUT */)
|
||||
{
|
||||
const OT::fvar &fvar = _get_fvar (face);
|
||||
return fvar.get_axis_infos (start_offset, axes_count, axes_array);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ot_var_find_axis:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_ot_var_find_axis (hb_face_t *face,
|
||||
hb_tag_t axis_tag,
|
||||
unsigned int *axis_index,
|
||||
hb_ot_var_axis_t *axis_info)
|
||||
{
|
||||
const OT::fvar &fvar = _get_fvar (face);
|
||||
return fvar.find_axis (axis_tag, axis_index, axis_info);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hb_ot_var_normalize_variations:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
**/
|
||||
void
|
||||
hb_ot_var_normalize_variations (hb_face_t *face,
|
||||
const hb_variation_t *variations, /* IN */
|
||||
unsigned int variations_length,
|
||||
int *coords, /* OUT */
|
||||
unsigned int coords_length)
|
||||
{
|
||||
for (unsigned int i = 0; i < coords_length; i++)
|
||||
coords[i] = 0;
|
||||
|
||||
const OT::fvar &fvar = _get_fvar (face);
|
||||
for (unsigned int i = 0; i < variations_length; i++)
|
||||
{
|
||||
unsigned int axis_index;
|
||||
if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, NULL) &&
|
||||
axis_index < coords_length)
|
||||
coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value);
|
||||
}
|
||||
|
||||
const OT::avar &avar = _get_avar (face);
|
||||
avar.map_coords (coords, coords_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ot_var_normalize_coords:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
**/
|
||||
void
|
||||
hb_ot_var_normalize_coords (hb_face_t *face,
|
||||
unsigned int coords_length,
|
||||
const float *design_coords, /* IN */
|
||||
int *normalized_coords /* OUT */)
|
||||
{
|
||||
const OT::fvar &fvar = _get_fvar (face);
|
||||
for (unsigned int i = 0; i < coords_length; i++)
|
||||
normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]);
|
||||
|
||||
const OT::avar &avar = _get_avar (face);
|
||||
avar.map_coords (normalized_coords, coords_length);
|
||||
}
|
||||
105
gfx/harfbuzz/src/hb-ot-var.h
Normal file
105
gfx/harfbuzz/src/hb-ot-var.h
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright © 2017 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_H_IN
|
||||
#error "Include <hb-ot.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef HB_OT_VAR_H
|
||||
#define HB_OT_VAR_H
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
|
||||
#define HB_OT_TAG_VAR_AXIS_ITALIC HB_TAG('i','t','a','l')
|
||||
#define HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE HB_TAG('o','p','s','z')
|
||||
#define HB_OT_TAG_VAR_AXIS_SLANT HB_TAG('s','l','n','t')
|
||||
#define HB_OT_TAG_VAR_AXIS_WIDTH HB_TAG('w','d','t','h')
|
||||
#define HB_OT_TAG_VAR_AXIS_WEIGHT HB_TAG('w','g','h','t')
|
||||
|
||||
|
||||
/*
|
||||
* fvar / avar
|
||||
*/
|
||||
|
||||
/**
|
||||
* hb_ot_var_axis_t:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
*/
|
||||
typedef struct hb_ot_var_axis_t {
|
||||
hb_tag_t tag;
|
||||
unsigned int name_id;
|
||||
float min_value;
|
||||
float default_value;
|
||||
float max_value;
|
||||
} hb_ot_var_axis_t;
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_ot_var_has_data (hb_face_t *face);
|
||||
|
||||
/**
|
||||
* HB_OT_VAR_NO_AXIS_INDEX:
|
||||
*
|
||||
* Since: 1.4.2
|
||||
*/
|
||||
#define HB_OT_VAR_NO_AXIS_INDEX 0xFFFFFFFFu
|
||||
|
||||
HB_EXTERN unsigned int
|
||||
hb_ot_var_get_axis_count (hb_face_t *face);
|
||||
|
||||
HB_EXTERN unsigned int
|
||||
hb_ot_var_get_axes (hb_face_t *face,
|
||||
unsigned int start_offset,
|
||||
unsigned int *axes_count /* IN/OUT */,
|
||||
hb_ot_var_axis_t *axes_array /* OUT */);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_ot_var_find_axis (hb_face_t *face,
|
||||
hb_tag_t axis_tag,
|
||||
unsigned int *axis_index,
|
||||
hb_ot_var_axis_t *axis_info);
|
||||
|
||||
|
||||
HB_EXTERN void
|
||||
hb_ot_var_normalize_variations (hb_face_t *face,
|
||||
const hb_variation_t *variations, /* IN */
|
||||
unsigned int variations_length,
|
||||
int *coords, /* OUT */
|
||||
unsigned int coords_length);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_ot_var_normalize_coords (hb_face_t *face,
|
||||
unsigned int coords_length,
|
||||
const float *design_coords, /* IN */
|
||||
int *normalized_coords /* OUT */);
|
||||
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_OT_VAR_H */
|
||||
|
|
@ -35,6 +35,7 @@
|
|||
#include "hb-ot-math.h"
|
||||
#include "hb-ot-tag.h"
|
||||
#include "hb-ot-shape.h"
|
||||
#include "hb-ot-var.h"
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -74,10 +74,9 @@ extern "C" void hb_free_impl(void *ptr);
|
|||
/* Compiler attributes */
|
||||
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
|
||||
#define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0)
|
||||
#define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1))
|
||||
#define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0))
|
||||
#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
|
||||
#define likely(expr) (__builtin_expect (!!(expr), 1))
|
||||
#define unlikely(expr) (__builtin_expect (!!(expr), 0))
|
||||
#else
|
||||
#define likely(expr) (expr)
|
||||
#define unlikely(expr) (expr)
|
||||
|
|
@ -168,7 +167,6 @@ extern "C" void hb_free_impl(void *ptr);
|
|||
|
||||
# if defined(_WIN32_WCE)
|
||||
/* Some things not defined on Windows CE. */
|
||||
# define strdup _strdup
|
||||
# define vsnprintf _vsnprintf
|
||||
# define getenv(Name) NULL
|
||||
# if _WIN32_WCE < 0x800
|
||||
|
|
@ -180,9 +178,6 @@ static int errno = 0; /* Use something better? */
|
|||
# endif
|
||||
# if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
# define snprintf _snprintf
|
||||
# elif defined(_MSC_VER) && _MSC_VER >= 1900
|
||||
# /* Covers VC++ Error for strdup being a deprecated POSIX name and to instead use _strdup instead */
|
||||
# define strdup _strdup
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ hb_set_destroy (hb_set_t *set)
|
|||
* @set: a set.
|
||||
* @key:
|
||||
* @data:
|
||||
* @destroy (closure data):
|
||||
* @destroy:
|
||||
* @replace:
|
||||
*
|
||||
* Return value:
|
||||
|
|
|
|||
|
|
@ -35,13 +35,6 @@
|
|||
#endif
|
||||
|
||||
|
||||
#define HB_SHAPER_IMPLEMENT(shaper) \
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(shaper, face) \
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(shaper, font)
|
||||
#include "hb-shaper-list.hh"
|
||||
#undef HB_SHAPER_IMPLEMENT
|
||||
|
||||
|
||||
static void
|
||||
hb_shape_plan_plan (hb_shape_plan_t *shape_plan,
|
||||
const hb_feature_t *user_features,
|
||||
|
|
@ -167,7 +160,7 @@ hb_shape_plan_create2 (hb_face_t *face,
|
|||
assert (props->direction != HB_DIRECTION_INVALID);
|
||||
|
||||
hb_face_make_immutable (face);
|
||||
shape_plan->default_shaper_list = shaper_list == NULL;
|
||||
shape_plan->default_shaper_list = !shaper_list;
|
||||
shape_plan->face_unsafe = face;
|
||||
shape_plan->props = *props;
|
||||
shape_plan->num_user_features = num_user_features;
|
||||
|
|
@ -430,7 +423,7 @@ hb_shape_plan_matches (const hb_shape_plan_t *shape_plan,
|
|||
return hb_segment_properties_equal (&shape_plan->props, &proposal->props) &&
|
||||
hb_shape_plan_user_features_match (shape_plan, proposal) &&
|
||||
hb_shape_plan_coords_match (shape_plan, proposal) &&
|
||||
((shape_plan->default_shaper_list && proposal->shaper_list == NULL) ||
|
||||
((shape_plan->default_shaper_list && !proposal->shaper_list) ||
|
||||
(shape_plan->shaper_func == proposal->shaper_func));
|
||||
}
|
||||
|
||||
|
|
@ -438,11 +431,12 @@ static inline hb_bool_t
|
|||
hb_non_global_user_features_present (const hb_feature_t *user_features,
|
||||
unsigned int num_user_features)
|
||||
{
|
||||
while (num_user_features)
|
||||
while (num_user_features) {
|
||||
if (user_features->start != 0 || user_features->end != (unsigned int) -1)
|
||||
return true;
|
||||
else
|
||||
num_user_features--, user_features++;
|
||||
num_user_features--;
|
||||
user_features++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,254 +45,6 @@
|
|||
* contains the output glyphs and their positions.
|
||||
**/
|
||||
|
||||
static bool
|
||||
parse_space (const char **pp, const char *end)
|
||||
{
|
||||
while (*pp < end && ISSPACE (**pp))
|
||||
(*pp)++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_char (const char **pp, const char *end, char c)
|
||||
{
|
||||
parse_space (pp, end);
|
||||
|
||||
if (*pp == end || **pp != c)
|
||||
return false;
|
||||
|
||||
(*pp)++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_uint (const char **pp, const char *end, unsigned int *pv)
|
||||
{
|
||||
char buf[32];
|
||||
unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
|
||||
strncpy (buf, *pp, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
char *p = buf;
|
||||
char *pend = p;
|
||||
unsigned int v;
|
||||
|
||||
/* Intentionally use strtol instead of strtoul, such that
|
||||
* -1 turns into "big number"... */
|
||||
errno = 0;
|
||||
v = strtol (p, &pend, 0);
|
||||
if (errno || p == pend)
|
||||
return false;
|
||||
|
||||
*pv = v;
|
||||
*pp += pend - p;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_bool (const char **pp, const char *end, unsigned int *pv)
|
||||
{
|
||||
parse_space (pp, end);
|
||||
|
||||
const char *p = *pp;
|
||||
while (*pp < end && ISALPHA(**pp))
|
||||
(*pp)++;
|
||||
|
||||
/* CSS allows on/off as aliases 1/0. */
|
||||
if (*pp - p == 2 || 0 == strncmp (p, "on", 2))
|
||||
*pv = 1;
|
||||
else if (*pp - p == 3 || 0 == strncmp (p, "off", 2))
|
||||
*pv = 0;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
|
||||
{
|
||||
if (parse_char (pp, end, '-'))
|
||||
feature->value = 0;
|
||||
else {
|
||||
parse_char (pp, end, '+');
|
||||
feature->value = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature)
|
||||
{
|
||||
parse_space (pp, end);
|
||||
|
||||
char quote = 0;
|
||||
|
||||
if (*pp < end && (**pp == '\'' || **pp == '"'))
|
||||
{
|
||||
quote = **pp;
|
||||
(*pp)++;
|
||||
}
|
||||
|
||||
const char *p = *pp;
|
||||
while (*pp < end && ISALNUM(**pp))
|
||||
(*pp)++;
|
||||
|
||||
if (p == *pp || *pp - p > 4)
|
||||
return false;
|
||||
|
||||
feature->tag = hb_tag_from_string (p, *pp - p);
|
||||
|
||||
if (quote)
|
||||
{
|
||||
/* CSS expects exactly four bytes. And we only allow quotations for
|
||||
* CSS compatibility. So, enforce the length. */
|
||||
if (*pp - p != 4)
|
||||
return false;
|
||||
if (*pp == end || **pp != quote)
|
||||
return false;
|
||||
(*pp)++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
|
||||
{
|
||||
parse_space (pp, end);
|
||||
|
||||
bool has_start;
|
||||
|
||||
feature->start = 0;
|
||||
feature->end = (unsigned int) -1;
|
||||
|
||||
if (!parse_char (pp, end, '['))
|
||||
return true;
|
||||
|
||||
has_start = parse_uint (pp, end, &feature->start);
|
||||
|
||||
if (parse_char (pp, end, ':')) {
|
||||
parse_uint (pp, end, &feature->end);
|
||||
} else {
|
||||
if (has_start)
|
||||
feature->end = feature->start + 1;
|
||||
}
|
||||
|
||||
return parse_char (pp, end, ']');
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
|
||||
{
|
||||
bool had_equal = parse_char (pp, end, '=');
|
||||
bool had_value = parse_uint (pp, end, &feature->value) ||
|
||||
parse_bool (pp, end, &feature->value);
|
||||
/* CSS doesn't use equal-sign between tag and value.
|
||||
* If there was an equal-sign, then there *must* be a value.
|
||||
* A value without an eqaul-sign is ok, but not required. */
|
||||
return !had_equal || had_value;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
|
||||
{
|
||||
return parse_feature_value_prefix (pp, end, feature) &&
|
||||
parse_feature_tag (pp, end, feature) &&
|
||||
parse_feature_indices (pp, end, feature) &&
|
||||
parse_feature_value_postfix (pp, end, feature) &&
|
||||
parse_space (pp, end) &&
|
||||
*pp == end;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_feature_from_string:
|
||||
* @str: (array length=len) (element-type uint8_t): a string to parse
|
||||
* @len: length of @str, or -1 if string is %NULL terminated
|
||||
* @feature: (out): the #hb_feature_t to initialize with the parsed values
|
||||
*
|
||||
* Parses a string into a #hb_feature_t.
|
||||
*
|
||||
* TODO: document the syntax here.
|
||||
*
|
||||
* Return value:
|
||||
* %true if @str is successfully parsed, %false otherwise.
|
||||
*
|
||||
* Since: 0.9.5
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_feature_from_string (const char *str, int len,
|
||||
hb_feature_t *feature)
|
||||
{
|
||||
hb_feature_t feat;
|
||||
|
||||
if (len < 0)
|
||||
len = strlen (str);
|
||||
|
||||
if (likely (parse_one_feature (&str, str + len, &feat)))
|
||||
{
|
||||
if (feature)
|
||||
*feature = feat;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (feature)
|
||||
memset (feature, 0, sizeof (*feature));
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_feature_to_string:
|
||||
* @feature: an #hb_feature_t to convert
|
||||
* @buf: (array length=size) (out): output string
|
||||
* @size: the allocated size of @buf
|
||||
*
|
||||
* Converts a #hb_feature_t into a %NULL-terminated string in the format
|
||||
* understood by hb_feature_from_string(). The client in responsible for
|
||||
* allocating big enough size for @buf, 128 bytes is more than enough.
|
||||
*
|
||||
* Since: 0.9.5
|
||||
**/
|
||||
void
|
||||
hb_feature_to_string (hb_feature_t *feature,
|
||||
char *buf, unsigned int size)
|
||||
{
|
||||
if (unlikely (!size)) return;
|
||||
|
||||
char s[128];
|
||||
unsigned int len = 0;
|
||||
if (feature->value == 0)
|
||||
s[len++] = '-';
|
||||
hb_tag_to_string (feature->tag, s + len);
|
||||
len += 4;
|
||||
while (len && s[len - 1] == ' ')
|
||||
len--;
|
||||
if (feature->start != 0 || feature->end != (unsigned int) -1)
|
||||
{
|
||||
s[len++] = '[';
|
||||
if (feature->start)
|
||||
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
|
||||
if (feature->end != feature->start + 1) {
|
||||
s[len++] = ':';
|
||||
if (feature->end != (unsigned int) -1)
|
||||
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
|
||||
}
|
||||
s[len++] = ']';
|
||||
}
|
||||
if (feature->value > 1)
|
||||
{
|
||||
s[len++] = '=';
|
||||
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
|
||||
}
|
||||
assert (len < ARRAY_LENGTH (s));
|
||||
len = MIN (len, size - 1);
|
||||
memcpy (buf, s, len);
|
||||
buf[len] = '\0';
|
||||
}
|
||||
|
||||
|
||||
static const char **static_shaper_list;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
|
|
@ -362,7 +114,7 @@ retry:
|
|||
* shapers will be used in the given order, otherwise the default shapers list
|
||||
* will be used.
|
||||
*
|
||||
* Return value: %FALSE if all shapers failed, %TRUE otherwise
|
||||
* Return value: false if all shapers failed, true otherwise
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -40,22 +40,6 @@
|
|||
HB_BEGIN_DECLS
|
||||
|
||||
|
||||
typedef struct hb_feature_t {
|
||||
hb_tag_t tag;
|
||||
uint32_t value;
|
||||
unsigned int start;
|
||||
unsigned int end;
|
||||
} hb_feature_t;
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_feature_from_string (const char *str, int len,
|
||||
hb_feature_t *feature);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_feature_to_string (hb_feature_t *feature,
|
||||
char *buf, unsigned int size);
|
||||
|
||||
|
||||
HB_EXTERN void
|
||||
hb_shape (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
|
|
|
|||
|
|
@ -65,27 +65,31 @@ struct hb_shaper_data_t {
|
|||
#define HB_SHAPER_DATA_INVALID ((void *) -1)
|
||||
#define HB_SHAPER_DATA_IS_INVALID(data) ((void *) (data) == HB_SHAPER_DATA_INVALID)
|
||||
|
||||
#define HB_SHAPER_DATA_TYPE(shaper, object) struct hb_##shaper##_shaper_##object##_data_t
|
||||
#define HB_SHAPER_DATA_TYPE_NAME(shaper, object) hb_##shaper##_shaper_##object##_data_t
|
||||
#define HB_SHAPER_DATA_TYPE(shaper, object) struct HB_SHAPER_DATA_TYPE_NAME(shaper, object)
|
||||
#define HB_SHAPER_DATA_INSTANCE(shaper, object, instance) (* (HB_SHAPER_DATA_TYPE(shaper, object) **) &(instance)->shaper_data.shaper)
|
||||
#define HB_SHAPER_DATA(shaper, object) HB_SHAPER_DATA_INSTANCE (shaper, object, object)
|
||||
#define HB_SHAPER_DATA(shaper, object) HB_SHAPER_DATA_INSTANCE(shaper, object, object)
|
||||
#define HB_SHAPER_DATA_CREATE_FUNC(shaper, object) _hb_##shaper##_shaper_##object##_data_create
|
||||
#define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object) _hb_##shaper##_shaper_##object##_data_destroy
|
||||
#define HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) hb_##shaper##_shaper_##object##_data_ensure
|
||||
|
||||
#define HB_SHAPER_DATA_PROTOTYPE(shaper, object) \
|
||||
HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \
|
||||
extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \
|
||||
HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS); \
|
||||
extern "C" HB_INTERNAL void \
|
||||
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); \
|
||||
extern "C" HB_INTERNAL bool \
|
||||
HB_SHAPER_DATA_ENSURE_FUNC (shaper, object) (hb_##object##_t *object)
|
||||
|
||||
#define HB_SHAPER_DATA_DESTROY(shaper, object) \
|
||||
if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \
|
||||
if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \
|
||||
HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data);
|
||||
|
||||
#define HB_SHAPER_DATA_ENSURE_DECLARE(shaper, object) \
|
||||
static inline bool \
|
||||
hb_##shaper##_shaper_##object##_data_ensure (hb_##object##_t *object) \
|
||||
#define HB_SHAPER_DATA_ENSURE_DEFINE(shaper, object) \
|
||||
bool \
|
||||
HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \
|
||||
{\
|
||||
retry: \
|
||||
HB_SHAPER_DATA_TYPE (shaper, object) *data = (HB_SHAPER_DATA_TYPE (shaper, object) *) hb_atomic_ptr_get (&HB_SHAPER_DATA (shaper, object)); \
|
||||
|
|
|
|||
|
|
@ -105,6 +105,10 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
|||
inline unsigned int
|
||||
modified_combining_class (hb_codepoint_t unicode)
|
||||
{
|
||||
/* XXX This hack belongs to the Arabic shaper:
|
||||
* Put HAMZA ABOVE in the same class as SHADDA. */
|
||||
if (unlikely (unicode == 0x0654u)) unicode = 0x0651u;
|
||||
|
||||
/* XXX This hack belongs to the Myanmar shaper. */
|
||||
if (unlikely (unicode == 0x1037u)) unicode = 0x103Au;
|
||||
|
||||
|
|
@ -126,7 +130,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
|||
{
|
||||
/* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the
|
||||
* Arabic shaper. No need to match them here. */
|
||||
return unlikely (hb_in_ranges (unicode,
|
||||
return unlikely (hb_in_ranges<hb_codepoint_t> (unicode,
|
||||
0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */
|
||||
0xE0100u, 0xE01EFu)); /* VARIATION SELECTOR-17..256 */
|
||||
}
|
||||
|
|
@ -179,13 +183,13 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
|||
case 0x00: return unlikely (ch == 0x00ADu);
|
||||
case 0x03: return unlikely (ch == 0x034Fu);
|
||||
case 0x06: return unlikely (ch == 0x061Cu);
|
||||
case 0x17: return hb_in_range (ch, 0x17B4u, 0x17B5u);
|
||||
case 0x18: return hb_in_range (ch, 0x180Bu, 0x180Eu);
|
||||
case 0x20: return hb_in_ranges (ch, 0x200Bu, 0x200Fu,
|
||||
case 0x17: return hb_in_range<hb_codepoint_t> (ch, 0x17B4u, 0x17B5u);
|
||||
case 0x18: return hb_in_range<hb_codepoint_t> (ch, 0x180Bu, 0x180Eu);
|
||||
case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200Bu, 0x200Fu,
|
||||
0x202Au, 0x202Eu,
|
||||
0x2060u, 0x206Fu);
|
||||
case 0xFE: return hb_in_range (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu;
|
||||
case 0xFF: return hb_in_range (ch, 0xFFF0u, 0xFFF8u);
|
||||
case 0xFE: return hb_in_range<hb_codepoint_t> (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu;
|
||||
case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0u, 0xFFF8u);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -193,9 +197,9 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
|||
{
|
||||
/* Other planes */
|
||||
switch (plane) {
|
||||
case 0x01: return hb_in_ranges (ch, 0x1BCA0u, 0x1BCA3u,
|
||||
case 0x01: return hb_in_ranges<hb_codepoint_t> (ch, 0x1BCA0u, 0x1BCA3u,
|
||||
0x1D173u, 0x1D17Au);
|
||||
case 0x0E: return hb_in_range (ch, 0xE0000u, 0xE0FFFu);
|
||||
case 0x0E: return hb_in_range<hb_codepoint_t> (ch, 0xE0000u, 0xE0FFFu);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -346,12 +350,13 @@ extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
|
|||
#define HB_MODIFIED_COMBINING_CLASS_CCC122 122 /* mai * */
|
||||
|
||||
/* Tibetan
|
||||
* Modify U+0F74 (ccc=132) to reorder before ccc=130 marks.
|
||||
*
|
||||
* In case of multiple vowel-signs, use u first (but after achung)
|
||||
* this allows Dzongkha multi-vowel shortcuts to render correctly
|
||||
*/
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC129 129 /* sign aa */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC130 130 /* sign i */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC132 128 /* sign u */
|
||||
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC130 132 /* sign i */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC132 131 /* sign u */
|
||||
|
||||
/* Misc */
|
||||
|
||||
|
|
|
|||
|
|
@ -293,8 +293,8 @@ struct range_record_t {
|
|||
unsigned int index_last; /* == end - 1 */
|
||||
};
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, face)
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, font)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, face)
|
||||
HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, font)
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -1024,6 +1024,8 @@ retry:
|
|||
pos->x_advance = x_mult * (int32_t) info->mask;
|
||||
pos->x_offset = x_mult * (backward ? -info->var1.i32 : info->var1.i32);
|
||||
pos->y_offset = y_mult * info->var2.i32;
|
||||
|
||||
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
}
|
||||
|
||||
if (backward)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ struct hb_utf8_t
|
|||
|
||||
if (c > 0x7Fu)
|
||||
{
|
||||
if (hb_in_range (c, 0xC2u, 0xDFu)) /* Two-byte */
|
||||
if (hb_in_range<hb_codepoint_t> (c, 0xC2u, 0xDFu)) /* Two-byte */
|
||||
{
|
||||
unsigned int t1;
|
||||
if (likely (text < end &&
|
||||
|
|
@ -60,7 +60,7 @@ struct hb_utf8_t
|
|||
else
|
||||
goto error;
|
||||
}
|
||||
else if (hb_in_range (c, 0xE0u, 0xEFu)) /* Three-byte */
|
||||
else if (hb_in_range<hb_codepoint_t> (c, 0xE0u, 0xEFu)) /* Three-byte */
|
||||
{
|
||||
unsigned int t1, t2;
|
||||
if (likely (1 < end - text &&
|
||||
|
|
@ -68,14 +68,14 @@ struct hb_utf8_t
|
|||
(t2 = text[1] - 0x80u) <= 0x3Fu))
|
||||
{
|
||||
c = ((c&0xFu)<<12) | (t1<<6) | t2;
|
||||
if (unlikely (c < 0x0800u || hb_in_range (c, 0xD800u, 0xDFFFu)))
|
||||
if (unlikely (c < 0x0800u || hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
|
||||
goto error;
|
||||
text += 2;
|
||||
}
|
||||
else
|
||||
goto error;
|
||||
}
|
||||
else if (hb_in_range (c, 0xF0u, 0xF4u)) /* Four-byte */
|
||||
else if (hb_in_range<hb_codepoint_t> (c, 0xF0u, 0xF4u)) /* Four-byte */
|
||||
{
|
||||
unsigned int t1, t2, t3;
|
||||
if (likely (2 < end - text &&
|
||||
|
|
@ -84,7 +84,7 @@ struct hb_utf8_t
|
|||
(t3 = text[2] - 0x80u) <= 0x3Fu))
|
||||
{
|
||||
c = ((c&0x7u)<<18) | (t1<<12) | (t2<<6) | t3;
|
||||
if (unlikely (!hb_in_range (c, 0x10000u, 0x10FFFFu)))
|
||||
if (unlikely (!hb_in_range<hb_codepoint_t> (c, 0x10000u, 0x10FFFFu)))
|
||||
goto error;
|
||||
text += 3;
|
||||
}
|
||||
|
|
@ -140,7 +140,7 @@ struct hb_utf16_t
|
|||
{
|
||||
hb_codepoint_t c = *text++;
|
||||
|
||||
if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu)))
|
||||
if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
|
||||
{
|
||||
*unicode = c;
|
||||
return text;
|
||||
|
|
@ -150,7 +150,7 @@ struct hb_utf16_t
|
|||
{
|
||||
/* High-surrogate in c */
|
||||
hb_codepoint_t l = *text;
|
||||
if (likely (hb_in_range (l, 0xDC00u, 0xDFFFu)))
|
||||
if (likely (hb_in_range<hb_codepoint_t> (l, 0xDC00u, 0xDFFFu)))
|
||||
{
|
||||
/* Low-surrogate in l */
|
||||
*unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u);
|
||||
|
|
@ -172,7 +172,7 @@ struct hb_utf16_t
|
|||
{
|
||||
hb_codepoint_t c = *--text;
|
||||
|
||||
if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu)))
|
||||
if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
|
||||
{
|
||||
*unicode = c;
|
||||
return text;
|
||||
|
|
@ -182,7 +182,7 @@ struct hb_utf16_t
|
|||
{
|
||||
/* Low-surrogate in c */
|
||||
hb_codepoint_t h = text[-1];
|
||||
if (likely (hb_in_range (h, 0xD800u, 0xDBFFu)))
|
||||
if (likely (hb_in_range<hb_codepoint_t> (h, 0xD800u, 0xDBFFu)))
|
||||
{
|
||||
/* High-surrogate in h */
|
||||
*unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u);
|
||||
|
|
|
|||
|
|
@ -37,10 +37,10 @@ HB_BEGIN_DECLS
|
|||
|
||||
|
||||
#define HB_VERSION_MAJOR 1
|
||||
#define HB_VERSION_MINOR 4
|
||||
#define HB_VERSION_MINOR 5
|
||||
#define HB_VERSION_MICRO 1
|
||||
|
||||
#define HB_VERSION_STRING "1.4.1"
|
||||
#define HB_VERSION_STRING "1.5.1"
|
||||
|
||||
#define HB_VERSION_ATLEAST(major,minor,micro) \
|
||||
((major)*10000+(minor)*100+(micro) <= \
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ EXPORTS.harfbuzz += [
|
|||
'hb-ot-math.h',
|
||||
'hb-ot-shape.h',
|
||||
'hb-ot-tag.h',
|
||||
'hb-ot-var.h',
|
||||
'hb-ot.h',
|
||||
'hb-set.h',
|
||||
'hb-shape-plan.h',
|
||||
|
|
@ -39,7 +40,6 @@ SOURCES += [
|
|||
UNIFIED_SOURCES += [
|
||||
'hb-buffer.cc',
|
||||
'hb-face.cc',
|
||||
'hb-fallback-shape.cc',
|
||||
'hb-font.cc',
|
||||
'hb-ot-layout.cc',
|
||||
'hb-ot-map.cc',
|
||||
|
|
@ -54,6 +54,7 @@ UNIFIED_SOURCES += [
|
|||
'hb-ot-shape-fallback.cc',
|
||||
'hb-ot-shape-normalize.cc',
|
||||
'hb-ot-tag.cc',
|
||||
'hb-ot-var.cc',
|
||||
'hb-set.cc',
|
||||
'hb-shape.cc',
|
||||
'hb-shaper.cc',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue