Merge branch 'master' into var-subset
This commit is contained in:
commit
5763a92749
|
@ -45,7 +45,7 @@ jobs:
|
|||
- run: rm -rf harfbuzz-*
|
||||
- run: make distdir && cd harfbuzz-* && cmake -DHB_CHECK=ON -Bbuild -H. -GNinja && ninja -Cbuild && CTEST_OUTPUT_ON_FAILURE=1 ninja -Cbuild test && ninja -Cbuild install
|
||||
|
||||
alpine-O3-NOMMAP:
|
||||
alpine-O3-Os-NOMMAP:
|
||||
docker:
|
||||
- image: alpine
|
||||
steps:
|
||||
|
@ -55,6 +55,10 @@ jobs:
|
|||
- run: CFLAGS="-O3" CXXFLAGS="-O3 -DHB_NO_MMAP" ./autogen.sh
|
||||
- run: make -j32
|
||||
- run: make check || .ci/fail.sh
|
||||
- run: make clean
|
||||
- run: CFLAGS="-Os -DHB_OPTIMIZE_SIZE" CXXFLAGS="-Os -DHB_NO_MMAP -DHB_OPTIMIZE_SIZE" ./autogen.sh
|
||||
- run: make -j32
|
||||
- run: make check || .ci/fail.sh
|
||||
|
||||
archlinux-py3-all:
|
||||
docker:
|
||||
|
@ -197,7 +201,7 @@ jobs:
|
|||
- image: fedora
|
||||
steps:
|
||||
- checkout
|
||||
- run: dnf install -y pkg-config ragel gcc gcc-c++ automake autoconf libtool make which glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python wine mingw32-gcc-c++ mingw64-gcc-c++ mingw32-glib2 mingw32-cairo mingw32-freetype mingw64-glib2 mingw64-cairo mingw64-freetype glibc-devel.i686 || true
|
||||
- run: dnf install -y pkg-config ragel gcc gcc-c++ automake autoconf libtool make which glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python mingw32-gcc-c++ mingw64-gcc-c++ mingw32-glib2 mingw32-cairo mingw32-freetype mingw64-glib2 mingw64-cairo mingw64-freetype glibc-devel.i686 || true
|
||||
- run: CFLAGS="-O0" CXXFLAGS="-O0" CPPFLAGS="-DHB_DEBUG" NOCONFIGURE=1 ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2
|
||||
- run: mkdir build && cd build && ../configure && make -j32 && (make check || ../.ci/fail.sh)
|
||||
- run: pip install pefile
|
||||
|
@ -307,7 +311,7 @@ workflows:
|
|||
- distcheck
|
||||
|
||||
# autotools based builds
|
||||
- alpine-O3-NOMMAP
|
||||
- alpine-O3-Os-NOMMAP
|
||||
- archlinux-py3-all
|
||||
#- void-notest
|
||||
- gcc-valgrind
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Build Configuration for Travis
|
||||
dist: xenial
|
||||
dist: trusty
|
||||
|
||||
language: cpp
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ endmacro ()
|
|||
if (UNIX)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES m)
|
||||
endif ()
|
||||
check_funcs(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l round)
|
||||
check_funcs(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l)
|
||||
check_include_file(unistd.h HAVE_UNISTD_H)
|
||||
if (${HAVE_UNISTD_H})
|
||||
add_definitions(-DHAVE_UNISTD_H)
|
||||
|
|
|
@ -78,12 +78,6 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
|
|||
|
||||
# Functions and headers
|
||||
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l posix_memalign)
|
||||
|
||||
save_libs="$LIBS"
|
||||
LIBS="$LIBS -lm"
|
||||
AC_CHECK_FUNCS([round], ,[AC_CHECK_DECLS([round], , ,[#include <math.h>])])
|
||||
LIBS="$save_libs"
|
||||
|
||||
AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h stdbool.h)
|
||||
|
||||
# Compiler flags
|
||||
|
|
|
@ -31,14 +31,15 @@ ce = {i for i,u in enumerate(ucd) if u['Comp_Ex'] == 'Y'}
|
|||
|
||||
assert not any(v for v in dm.values() if len(v) not in (1,2))
|
||||
dm1 = sorted(set(v for v in dm.values() if len(v) == 1))
|
||||
dm1_array = ['0x%04Xu' % v for v in dm1]
|
||||
dm1_u16_array = ['0x%04Xu' % v for v in dm1 if v[0] <= 0xFFFF]
|
||||
dm1_u32_array = ['0x%04Xu' % v for v in dm1 if v[0] > 0xFFFF]
|
||||
dm1_order = {v:i+1 for i,v in enumerate(dm1)}
|
||||
dm2 = sorted((v, i) for i,v in dm.items() if len(v) == 2)
|
||||
dm2 = [("HB_CODEPOINT_ENCODE3 (0x%04Xu, 0x%04Xu, 0x%04Xu)" %
|
||||
(v+(i if i not in ce and not ccc[i] else 0,)), v)
|
||||
for v,i in dm2]
|
||||
dm2_array = [s for s,v in dm2]
|
||||
l = 1 + len(dm1_array)
|
||||
l = 1 + len(dm1_u16_array) + len(dm1_u32_array)
|
||||
dm2_order = {v[1]:i+l for i,v in enumerate(dm2)}
|
||||
dm_order = {None: 0}
|
||||
dm_order.update(dm1_order)
|
||||
|
@ -89,7 +90,8 @@ print()
|
|||
|
||||
code = packTab.Code('_hb_ucd')
|
||||
sc_array, _ = code.addArray('hb_script_t', 'sc_map', sc_array)
|
||||
dm1_array, _ = code.addArray('hb_codepoint_t', 'dm1_map', dm1_array)
|
||||
dm1_16_array, _ = code.addArray('uint16_t', 'dm1_u16_map', dm1_u16_array)
|
||||
dm1_32_array, _ = code.addArray('uint32_t', 'dm1_u32_map', dm1_u32_array)
|
||||
dm2_array, _ = code.addArray('uint64_t', 'dm2_map', dm2_array)
|
||||
code.print_c(linkage='static inline')
|
||||
|
||||
|
|
240
src/hb-algs.hh
240
src/hb-algs.hh
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright © 2017 Google, Inc.
|
||||
* Copyright © 2019 Google, Inc.
|
||||
* Copyright © 2019 Facebook, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
@ -167,19 +167,37 @@ template <unsigned Pos=1, typename Appl, typename V>
|
|||
auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN
|
||||
(( hb_partial_t<Pos, Appl, V> (a, v) ))
|
||||
|
||||
/* The following hacky replacement version is to make Visual Stuiod build:. */ \
|
||||
/* https://github.com/harfbuzz/harfbuzz/issues/1730 */ \
|
||||
/* The following, HB_PARTIALIZE, macro uses a particular corner-case
|
||||
* of C++11 that is not particularly well-supported by all compilers.
|
||||
* What's happening is that it's using "this" in a trailing return-type
|
||||
* via decltype(). Broken compilers deduce the type of "this" pointer
|
||||
* in that context differently from what it resolves to in the body
|
||||
* of the function.
|
||||
*
|
||||
* One probable cause of this is that at the time of trailing return
|
||||
* type declaration, "this" points to an incomplete type, whereas in
|
||||
* the function body the type is complete. That doesn't justify the
|
||||
* error in any way, but is probably what's happening.
|
||||
*
|
||||
* In the case of MSVC, we get around this by using C++14 "decltype(auto)"
|
||||
* which deduces the type from the actual return statement. For gcc 4.8
|
||||
* we use "+this" instead of "this" which produces an rvalue that seems
|
||||
* to be deduced as the same type with this particular compiler, and seem
|
||||
* to be fine as default code path as well.
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
/* https://github.com/harfbuzz/harfbuzz/issues/1730 */ \
|
||||
#define HB_PARTIALIZE(Pos) \
|
||||
template <typename _T> \
|
||||
decltype(auto) operator () (_T&& _v) const \
|
||||
{ return hb_partial<Pos> (this, hb_forward<_T> (_v)); } \
|
||||
static_assert (true, "")
|
||||
#else
|
||||
/* https://github.com/harfbuzz/harfbuzz/issues/1724 */
|
||||
#define HB_PARTIALIZE(Pos) \
|
||||
template <typename _T> \
|
||||
auto operator () (_T&& _v) const HB_AUTO_RETURN \
|
||||
(hb_partial<Pos> (this, hb_forward<_T> (_v))) \
|
||||
(hb_partial<Pos> (+this, hb_forward<_T> (_v))) \
|
||||
static_assert (true, "")
|
||||
#endif
|
||||
|
||||
|
@ -400,7 +418,7 @@ hb_bit_storage (T v)
|
|||
return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
|
||||
#endif
|
||||
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
|
||||
if (sizeof (T) <= sizeof (unsigned int))
|
||||
{
|
||||
unsigned long where;
|
||||
|
@ -474,7 +492,7 @@ hb_ctz (T v)
|
|||
return __builtin_ctzll (v);
|
||||
#endif
|
||||
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
|
||||
if (sizeof (T) <= sizeof (unsigned int))
|
||||
{
|
||||
unsigned long where;
|
||||
|
@ -628,115 +646,213 @@ hb_bsearch (const void *key, const void *base,
|
|||
|
||||
|
||||
/* From https://github.com/noporpoise/sort_r
|
||||
* With following modifications:
|
||||
*
|
||||
* 10 November 2018:
|
||||
* https://github.com/noporpoise/sort_r/issues/7
|
||||
*/
|
||||
Feb 5, 2019 (c8c65c1e)
|
||||
Modified to support optional argument using templates */
|
||||
|
||||
/* Isaac Turner 29 April 2014 Public Domain */
|
||||
|
||||
/*
|
||||
|
||||
hb_sort_r function to be exported.
|
||||
|
||||
hb_qsort function to be exported.
|
||||
Parameters:
|
||||
base is the array to be sorted
|
||||
nel is the number of elements in the array
|
||||
width is the size in bytes of each element of the array
|
||||
compar is the comparison function
|
||||
arg is a pointer to be passed to the comparison function
|
||||
arg (optional) is a pointer to be passed to the comparison function
|
||||
|
||||
void hb_sort_r(void *base, size_t nel, size_t width,
|
||||
int (*compar)(const void *_a, const void *_b, void *_arg),
|
||||
void *arg);
|
||||
void hb_qsort(void *base, size_t nel, size_t width,
|
||||
int (*compar)(const void *_a, const void *_b, [void *_arg]),
|
||||
[void *arg]);
|
||||
*/
|
||||
|
||||
#define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp))
|
||||
|
||||
/* swap a, b iff a>b */
|
||||
/* __restrict is same as restrict but better support on old machines */
|
||||
static int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w,
|
||||
int (*compar)(const void *_a, const void *_b,
|
||||
void *_arg),
|
||||
void *arg)
|
||||
/* swap a and b */
|
||||
/* a and b must not be equal! */
|
||||
static inline void sort_r_swap(char *__restrict a, char *__restrict b,
|
||||
size_t w)
|
||||
{
|
||||
char tmp, *end = a+w;
|
||||
if(compar(a, b, arg) > 0) {
|
||||
for(; a < end; a++, b++) { tmp = *a; *a = *b; *b = tmp; }
|
||||
for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp); }
|
||||
}
|
||||
|
||||
/* swap a, b iff a>b */
|
||||
/* a and b must not be equal! */
|
||||
/* __restrict is same as restrict but better support on old machines */
|
||||
template <typename ...Ts>
|
||||
static inline int sort_r_cmpswap(char *__restrict a,
|
||||
char *__restrict b, size_t w,
|
||||
int (*compar)(const void *_a,
|
||||
const void *_b,
|
||||
Ts... _ds),
|
||||
Ts... ds)
|
||||
{
|
||||
if(compar(a, b, ds...) > 0) {
|
||||
sort_r_swap(a, b, w);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Swap consecutive blocks of bytes of size na and nb starting at memory addr ptr,
|
||||
with the smallest swap so that the blocks are in the opposite order. Blocks may
|
||||
be internally re-ordered e.g.
|
||||
12345ab -> ab34512
|
||||
123abc -> abc123
|
||||
12abcde -> deabc12
|
||||
*/
|
||||
static inline void sort_r_swap_blocks(char *ptr, size_t na, size_t nb)
|
||||
{
|
||||
if(na > 0 && nb > 0) {
|
||||
if(na > nb) { sort_r_swap(ptr, ptr+na, nb); }
|
||||
else { sort_r_swap(ptr, ptr+nb, na); }
|
||||
}
|
||||
}
|
||||
|
||||
/* Implement recursive quicksort ourselves */
|
||||
/* Note: quicksort is not stable, equivalent values may be swapped */
|
||||
template <typename ...Ts>
|
||||
static inline void sort_r_simple(void *base, size_t nel, size_t w,
|
||||
int (*compar)(const void *_a, const void *_b,
|
||||
void *_arg),
|
||||
void *arg)
|
||||
int (*compar)(const void *_a,
|
||||
const void *_b,
|
||||
Ts... _ds),
|
||||
Ts... ds)
|
||||
{
|
||||
char *b = (char *)base, *end = b + nel*w;
|
||||
if(nel < 7) {
|
||||
|
||||
/* for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
|
||||
printf("\n"); */
|
||||
|
||||
if(nel < 10) {
|
||||
/* Insertion sort for arbitrarily small inputs */
|
||||
char *pi, *pj;
|
||||
for(pi = b+w; pi < end; pi += w) {
|
||||
for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {}
|
||||
for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,ds...); pj -= w) {}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* nel > 6; Quicksort */
|
||||
/* nel > 9; Quicksort */
|
||||
|
||||
/* Use median of first, middle and last items as pivot */
|
||||
char *x, *y, *xend, ch;
|
||||
char *pl, *pm, *pr;
|
||||
int cmp;
|
||||
char *pl, *ple, *pr, *pre, *pivot;
|
||||
char *last = b+w*(nel-1), *tmp;
|
||||
|
||||
/*
|
||||
Use median of second, middle and second-last items as pivot.
|
||||
First and last may have been swapped with pivot and therefore be extreme
|
||||
*/
|
||||
char *l[3];
|
||||
l[0] = b;
|
||||
l[0] = b + w;
|
||||
l[1] = b+w*(nel/2);
|
||||
l[2] = last;
|
||||
l[2] = last - w;
|
||||
|
||||
if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
|
||||
if(compar(l[1],l[2],arg) > 0) {
|
||||
tmp=l[1]; l[1]=l[2]; l[2]=tmp; /* swap(l[1],l[2]) */
|
||||
if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
|
||||
/* printf("pivots: %i, %i, %i\n", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */
|
||||
|
||||
if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
|
||||
if(compar(l[1],l[2],ds...) > 0) {
|
||||
SORT_R_SWAP(l[1], l[2], tmp);
|
||||
if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
|
||||
}
|
||||
|
||||
/* swap l[id], l[2] to put pivot as last element */
|
||||
for(x = l[1], y = last, xend = x+w; x<xend; x++, y++) {
|
||||
ch = *x; *x = *y; *y = ch;
|
||||
}
|
||||
/* swap mid value (l[1]), and last element to put pivot as last element */
|
||||
if(l[1] != last) { sort_r_swap(l[1], last, w); }
|
||||
|
||||
pl = b;
|
||||
pr = last;
|
||||
/*
|
||||
pl is the next item on the left to be compared to the pivot
|
||||
pr is the last item on the right that was compared to the pivot
|
||||
ple is the left position to put the next item that equals the pivot
|
||||
ple is the last right position where we put an item that equals the pivot
|
||||
v- end (beyond the array)
|
||||
EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE.
|
||||
^- b ^- ple ^- pl ^- pr ^- pre ^- last (where the pivot is)
|
||||
Pivot comparison key:
|
||||
E = equal, L = less than, u = unknown, G = greater than, E = equal
|
||||
*/
|
||||
pivot = last;
|
||||
ple = pl = b;
|
||||
pre = pr = last;
|
||||
|
||||
/*
|
||||
Strategy:
|
||||
Loop into the list from the left and right at the same time to find:
|
||||
- an item on the left that is greater than the pivot
|
||||
- an item on the right that is less than the pivot
|
||||
Once found, they are swapped and the loop continues.
|
||||
Meanwhile items that are equal to the pivot are moved to the edges of the
|
||||
array.
|
||||
*/
|
||||
while(pl < pr) {
|
||||
pm = pl+((pr-pl+1)>>1);
|
||||
for(; pl < pm; pl += w) {
|
||||
if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
|
||||
pr -= w; /* pivot now at pl */
|
||||
break;
|
||||
/* Move left hand items which are equal to the pivot to the far left.
|
||||
break when we find an item that is greater than the pivot */
|
||||
for(; pl < pr; pl += w) {
|
||||
cmp = compar(pl, pivot, ds...);
|
||||
if(cmp > 0) { break; }
|
||||
else if(cmp == 0) {
|
||||
if(ple < pl) { sort_r_swap(ple, pl, w); }
|
||||
ple += w;
|
||||
}
|
||||
}
|
||||
pm = pl+((pr-pl)>>1);
|
||||
for(; pm < pr; pr -= w) {
|
||||
if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
|
||||
pl += w; /* pivot now at pr */
|
||||
/* break if last batch of left hand items were equal to pivot */
|
||||
if(pl >= pr) { break; }
|
||||
/* Move right hand items which are equal to the pivot to the far right.
|
||||
break when we find an item that is less than the pivot */
|
||||
for(; pl < pr; ) {
|
||||
pr -= w; /* Move right pointer onto an unprocessed item */
|
||||
cmp = compar(pr, pivot, ds...);
|
||||
if(cmp == 0) {
|
||||
pre -= w;
|
||||
if(pr < pre) { sort_r_swap(pr, pre, w); }
|
||||
}
|
||||
else if(cmp < 0) {
|
||||
if(pl < pr) { sort_r_swap(pl, pr, w); }
|
||||
pl += w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort_r_simple(b, (pl-b)/w, w, compar, arg);
|
||||
sort_r_simple(pl+w, (end-(pl+w))/w, w, compar, arg);
|
||||
pl = pr; /* pr may have gone below pl */
|
||||
|
||||
/*
|
||||
Now we need to go from: EEELLLGGGGEEEE
|
||||
to: LLLEEEEEEEGGGG
|
||||
Pivot comparison key:
|
||||
E = equal, L = less than, u = unknown, G = greater than, E = equal
|
||||
*/
|
||||
sort_r_swap_blocks(b, ple-b, pl-ple);
|
||||
sort_r_swap_blocks(pr, pre-pr, end-pre);
|
||||
|
||||
/*for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
|
||||
printf("\n");*/
|
||||
|
||||
sort_r_simple(b, (pl-ple)/w, w, compar, ds...);
|
||||
sort_r_simple(end-(pre-pr), (pre-pr)/w, w, compar, ds...);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
hb_sort_r (void *base, size_t nel, size_t width,
|
||||
int (*compar)(const void *_a, const void *_b, void *_arg),
|
||||
void *arg)
|
||||
hb_qsort (void *base, size_t nel, size_t width,
|
||||
int (*compar)(const void *_a, const void *_b))
|
||||
{
|
||||
sort_r_simple(base, nel, width, compar, arg);
|
||||
#if defined(__OPTIMIZE_SIZE__) && !defined(HB_USE_INTERNAL_QSORT)
|
||||
qsort (base, nel, width, compar);
|
||||
#else
|
||||
sort_r_simple (base, nel, width, compar);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
hb_qsort (void *base, size_t nel, size_t width,
|
||||
int (*compar)(const void *_a, const void *_b, void *_arg),
|
||||
void *arg)
|
||||
{
|
||||
#ifdef HAVE_GNU_QSORT_R
|
||||
qsort_r (base, nel, width, compar, arg);
|
||||
#else
|
||||
sort_r_simple (base, nel, width, compar, arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -141,13 +141,13 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
|||
hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*))
|
||||
{
|
||||
if (likely (length))
|
||||
::qsort (arrayZ, length, this->item_size, cmp_);
|
||||
hb_qsort (arrayZ, length, this->item_size, cmp_);
|
||||
return hb_sorted_array_t<Type> (*this);
|
||||
}
|
||||
hb_sorted_array_t<Type> qsort ()
|
||||
{
|
||||
if (likely (length))
|
||||
::qsort (arrayZ, length, this->item_size, Type::cmp);
|
||||
hb_qsort (arrayZ, length, this->item_size, Type::cmp);
|
||||
return hb_sorted_array_t<Type> (*this);
|
||||
}
|
||||
void qsort (unsigned int start, unsigned int end)
|
||||
|
@ -155,7 +155,7 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
|||
end = hb_min (end, length);
|
||||
assert (start <= end);
|
||||
if (likely (start < end))
|
||||
::qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
|
||||
hb_qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -107,7 +107,7 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
|
|||
|
||||
static inline void _hb_memory_barrier ()
|
||||
{
|
||||
#ifndef MemoryBarrier
|
||||
#if !defined(MemoryBarrier) && !defined(__MINGW32_VERSION)
|
||||
/* MinGW has a convoluted history of supporting MemoryBarrier. */
|
||||
LONG dummy = 0;
|
||||
InterlockedExchange (&dummy, 1);
|
||||
|
|
|
@ -543,6 +543,10 @@ _hb_mapped_file_destroy (void *file_)
|
|||
hb_blob_t *
|
||||
hb_blob_create_from_file (const char *file_name)
|
||||
{
|
||||
#ifdef HB_NO_OPEN
|
||||
return hb_blob_get_empty ();
|
||||
#endif
|
||||
|
||||
/* Adopted from glib's gmappedfile.c with Matthias Clasen and
|
||||
Allison Lortie permission but changed a lot to suit our need. */
|
||||
#if defined(HAVE_MMAP) && !defined(HB_NO_MMAP)
|
||||
|
|
|
@ -2026,9 +2026,6 @@ hb_buffer_set_message_func (hb_buffer_t *buffer,
|
|||
bool
|
||||
hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
|
||||
{
|
||||
#ifdef HB_NO_BUFFER_MESSAGE
|
||||
return false;
|
||||
#endif
|
||||
char buf[100];
|
||||
vsnprintf (buf, sizeof (buf), fmt, ap);
|
||||
return (bool) this->message_func (this, font, buf, this->message_data);
|
||||
|
|
|
@ -347,7 +347,13 @@ struct hb_buffer_t
|
|||
|
||||
HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
|
||||
|
||||
bool messaging () { return unlikely (message_func); }
|
||||
bool messaging ()
|
||||
{
|
||||
#ifdef HB_NO_BUFFER_MESSAGE
|
||||
return false;
|
||||
#endif
|
||||
return unlikely (message_func);
|
||||
}
|
||||
bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
|
||||
{
|
||||
if (!messaging ())
|
||||
|
|
|
@ -76,8 +76,8 @@ struct biased_subrs_t
|
|||
|
||||
void fini () {}
|
||||
|
||||
unsigned int get_count () const { return (subrs == nullptr)? 0: subrs->count; }
|
||||
unsigned int get_bias () const { return bias; }
|
||||
unsigned int get_count () const { return (subrs == nullptr) ? 0 : subrs->count; }
|
||||
unsigned int get_bias () const { return bias; }
|
||||
|
||||
byte_str_t operator [] (unsigned int index) const
|
||||
{
|
||||
|
|
|
@ -134,10 +134,10 @@ struct dict_opset_t : opset_t<number_t>
|
|||
return value;
|
||||
|
||||
case END:
|
||||
value = (double)(neg? -int_part: int_part);
|
||||
value = (double) (neg ? -int_part : int_part);
|
||||
if (frac_count > 0)
|
||||
{
|
||||
double frac = (frac_part / pow (10.0, (double)frac_count));
|
||||
double frac = (frac_part / pow (10.0, (double) frac_count));
|
||||
if (neg) frac = -frac;
|
||||
value += frac;
|
||||
}
|
||||
|
@ -146,16 +146,16 @@ struct dict_opset_t : opset_t<number_t>
|
|||
if (value == 0.0)
|
||||
return value;
|
||||
if (exp_neg)
|
||||
return neg? -DBL_MIN: DBL_MIN;
|
||||
return neg ? -DBL_MIN : DBL_MIN;
|
||||
else
|
||||
return neg? -DBL_MAX: DBL_MAX;
|
||||
return neg ? -DBL_MAX : DBL_MAX;
|
||||
}
|
||||
if (exp_part != 0)
|
||||
{
|
||||
if (exp_neg)
|
||||
value /= pow (10.0, (double)exp_part);
|
||||
value /= pow (10.0, (double) exp_part);
|
||||
else
|
||||
value *= pow (10.0, (double)exp_part);
|
||||
value *= pow (10.0, (double) exp_part);
|
||||
}
|
||||
return value;
|
||||
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
#include <xlocale.h>
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_SETLOCALE
|
||||
#define setlocale(Category, Locale) "C"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION:hb-common
|
||||
|
|
|
@ -60,7 +60,10 @@
|
|||
#define HB_NO_GETENV
|
||||
#define HB_NO_LAYOUT_UNUSED
|
||||
#define HB_NO_MATH
|
||||
#define HB_NO_MMAP
|
||||
#define HB_NO_NAME
|
||||
#define HB_NO_OPEN
|
||||
#define HB_NO_SETLOCALE
|
||||
#define HB_NO_SUBSET_LAYOUT
|
||||
#endif
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ typedef volatile int hb_mutex_impl_t;
|
|||
#define HB_MUTEX_IMPL_INIT 0
|
||||
#define hb_mutex_impl_init(M) *(M) = 0
|
||||
#define hb_mutex_impl_lock(M) HB_STMT_START { while (*(M)) HB_SCHED_YIELD (); (*(M))++; } HB_STMT_END
|
||||
#define hb_mutex_impl_unlock(M) (*(M))--;
|
||||
#define hb_mutex_impl_unlock(M) (*(M))--
|
||||
#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
|
||||
|
||||
|
||||
|
|
|
@ -82,22 +82,14 @@ struct str_buff_vec_t : hb_vector_t<str_buff_t>
|
|||
template <typename COUNT>
|
||||
struct CFFIndex
|
||||
{
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */
|
||||
(c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
|
||||
c->check_array (offsets, offSize, count + 1) &&
|
||||
c->check_array ((const HBUINT8*)data_base (), 1, max_offset () - 1))));
|
||||
}
|
||||
|
||||
static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count)
|
||||
{ return offSize * (count + 1); }
|
||||
|
||||
unsigned int offset_array_size () const
|
||||
{ return calculate_offset_array_size (offSize, count); }
|
||||
|
||||
static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count, unsigned int dataSize)
|
||||
static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count,
|
||||
unsigned int dataSize)
|
||||
{
|
||||
if (count == 0)
|
||||
return COUNT::static_size;
|
||||
|
@ -199,11 +191,11 @@ struct CFFIndex
|
|||
|
||||
unsigned int length_at (unsigned int index) const
|
||||
{
|
||||
if (likely ((offset_at (index + 1) >= offset_at (index)) &&
|
||||
(offset_at (index + 1) <= offset_at (count))))
|
||||
return offset_at (index + 1) - offset_at (index);
|
||||
else
|
||||
return 0;
|
||||
if (likely ((offset_at (index + 1) >= offset_at (index)) &&
|
||||
(offset_at (index + 1) <= offset_at (count))))
|
||||
return offset_at (index + 1) - offset_at (index);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const unsigned char *data_base () const
|
||||
|
@ -216,12 +208,12 @@ struct CFFIndex
|
|||
if (likely (index < count))
|
||||
return byte_str_t (data_base () + offset_at (index) - 1, length_at (index));
|
||||
else
|
||||
return Null(byte_str_t);
|
||||
return Null (byte_str_t);
|
||||
}
|
||||
|
||||
unsigned int get_size () const
|
||||
{
|
||||
if (this != &Null(CFFIndex))
|
||||
if (this != &Null (CFFIndex))
|
||||
{
|
||||
if (count > 0)
|
||||
return min_size + offset_array_size () + (offset_at (count) - 1);
|
||||
|
@ -232,6 +224,15 @@ struct CFFIndex
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */
|
||||
(c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
|
||||
c->check_array (offsets, offSize, count + 1) &&
|
||||
c->check_array ((const HBUINT8*) data_base (), 1, max_offset () - 1))));
|
||||
}
|
||||
|
||||
protected:
|
||||
unsigned int max_offset () const
|
||||
{
|
||||
|
@ -245,10 +246,10 @@ struct CFFIndex
|
|||
}
|
||||
|
||||
public:
|
||||
COUNT count; /* Number of object data. Note there are (count+1) offsets */
|
||||
HBUINT8 offSize; /* The byte size of each offset in the offsets array. */
|
||||
HBUINT8 offsets[VAR]; /* The array of (count + 1) offsets into objects array (1-base). */
|
||||
/* HBUINT8 data[VAR]; Object data */
|
||||
COUNT count; /* Number of object data. Note there are (count+1) offsets */
|
||||
HBUINT8 offSize; /* The byte size of each offset in the offsets array. */
|
||||
HBUINT8 offsets[VAR]; /* The array of (count + 1) offsets into objects array (1-base). */
|
||||
/* HBUINT8 data[VAR]; Object data */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets);
|
||||
};
|
||||
|
@ -293,7 +294,7 @@ struct CFFIndexOf : CFFIndex<COUNT>
|
|||
/* serialize data */
|
||||
for (unsigned int i = 0; i < dataArrayLen; i++)
|
||||
{
|
||||
TYPE *dest = c->start_embed<TYPE> ();
|
||||
TYPE *dest = c->start_embed<TYPE> ();
|
||||
if (unlikely (dest == nullptr ||
|
||||
!dest->serialize (c, dataArray[i], param1, param2)))
|
||||
return_trace (false);
|
||||
|
@ -310,7 +311,7 @@ struct CFFIndexOf : CFFIndex<COUNT>
|
|||
const PARAM ¶m)
|
||||
{
|
||||
/* determine offset size */
|
||||
unsigned int totalDataSize = 0;
|
||||
unsigned int totalDataSize = 0;
|
||||
for (unsigned int i = 0; i < dataArrayLen; i++)
|
||||
{
|
||||
unsigned int dataSize = TYPE::calculate_serialized_size (dataArray[i], param);
|
||||
|
@ -334,10 +335,9 @@ struct Dict : UnsizedByteStr
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
for (unsigned int i = 0; i < dictval.get_count (); i++)
|
||||
{
|
||||
if (unlikely (!opszr.serialize (c, dictval[i], param)))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
@ -391,14 +391,10 @@ struct Dict : UnsizedByteStr
|
|||
{ return serialize_int_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); }
|
||||
|
||||
static bool serialize_offset4_op (hb_serialize_context_t *c, op_code_t op, int value)
|
||||
{
|
||||
return serialize_uint4_op (c, op, value);
|
||||
}
|
||||
{ return serialize_uint4_op (c, op, value); }
|
||||
|
||||
static bool serialize_offset2_op (hb_serialize_context_t *c, op_code_t op, int value)
|
||||
{
|
||||
return serialize_uint2_op (c, op, value);
|
||||
}
|
||||
{ return serialize_uint2_op (c, op, value); }
|
||||
};
|
||||
|
||||
struct TopDict : Dict {};
|
||||
|
@ -432,7 +428,7 @@ struct FDArray : CFFIndexOf<COUNT, FontDict>
|
|||
return_trace (false);
|
||||
|
||||
/* serialize font dict offsets */
|
||||
unsigned int offset = 1;
|
||||
unsigned int offset = 1;
|
||||
unsigned int fid = 0;
|
||||
for (; fid < fontDicts.length; fid++)
|
||||
{
|
||||
|
@ -524,9 +520,7 @@ struct FDSelect0 {
|
|||
}
|
||||
|
||||
hb_codepoint_t get_fd (hb_codepoint_t glyph) const
|
||||
{
|
||||
return (hb_codepoint_t)fds[glyph];
|
||||
}
|
||||
{ return (hb_codepoint_t) fds[glyph]; }
|
||||
|
||||
unsigned int get_size (unsigned int num_glyphs) const
|
||||
{ return HBUINT8::static_size * num_glyphs; }
|
||||
|
@ -537,7 +531,8 @@ struct FDSelect0 {
|
|||
};
|
||||
|
||||
template <typename GID_TYPE, typename FD_TYPE>
|
||||
struct FDSelect3_4_Range {
|
||||
struct FDSelect3_4_Range
|
||||
{
|
||||
bool sanitize (hb_sanitize_context_t *c, const void * /*nullptr*/, unsigned int fdcount) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -546,12 +541,13 @@ struct FDSelect3_4_Range {
|
|||
|
||||
GID_TYPE first;
|
||||
FD_TYPE fd;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (GID_TYPE::static_size + FD_TYPE::static_size);
|
||||
};
|
||||
|
||||
template <typename GID_TYPE, typename FD_TYPE>
|
||||
struct FDSelect3_4 {
|
||||
struct FDSelect3_4
|
||||
{
|
||||
unsigned int get_size () const
|
||||
{ return GID_TYPE::static_size * 2 + ranges.get_size (); }
|
||||
|
||||
|
@ -563,10 +559,8 @@ struct FDSelect3_4 {
|
|||
return_trace (false);
|
||||
|
||||
for (unsigned int i = 1; i < nRanges (); i++)
|
||||
{
|
||||
if (unlikely (ranges[i - 1].first >= ranges[i].first))
|
||||
return_trace (false);
|
||||
}
|
||||
return_trace (false);
|
||||
|
||||
if (unlikely (!sentinel().sanitize (c) || (sentinel() != c->get_num_glyphs ())))
|
||||
return_trace (false);
|
||||
|
@ -598,17 +592,8 @@ struct FDSelect3_4 {
|
|||
typedef FDSelect3_4<HBUINT16, HBUINT8> FDSelect3;
|
||||
typedef FDSelect3_4_Range<HBUINT16, HBUINT8> FDSelect3_Range;
|
||||
|
||||
struct FDSelect {
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
||||
return_trace (likely (c->check_struct (this) && (format == 0 || format == 3) &&
|
||||
((format == 0)?
|
||||
u.format0.sanitize (c, fdcount):
|
||||
u.format3.sanitize (c, fdcount))));
|
||||
}
|
||||
|
||||
struct FDSelect
|
||||
{
|
||||
bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
@ -624,30 +609,46 @@ struct FDSelect {
|
|||
|
||||
unsigned int get_size (unsigned int num_glyphs) const
|
||||
{
|
||||
unsigned int size = format.static_size;
|
||||
if (format == 0)
|
||||
size += u.format0.get_size (num_glyphs);
|
||||
else
|
||||
size += u.format3.get_size ();
|
||||
return size;
|
||||
switch (format)
|
||||
{
|
||||
case 0: return format.static_size + u.format0.get_size (num_glyphs);
|
||||
case 3: return format.static_size + u.format3.get_size ();
|
||||
default:return 0;
|
||||
}
|
||||
}
|
||||
|
||||
hb_codepoint_t get_fd (hb_codepoint_t glyph) const
|
||||
{
|
||||
if (this == &Null(FDSelect))
|
||||
if (this == &Null (FDSelect))
|
||||
return 0;
|
||||
if (format == 0)
|
||||
return u.format0.get_fd (glyph);
|
||||
else
|
||||
return u.format3.get_fd (glyph);
|
||||
switch (format)
|
||||
{
|
||||
case 0: return u.format0.get_fd (glyph);
|
||||
case 3: return u.format3.get_fd (glyph);
|
||||
default:return 0;
|
||||
}
|
||||
}
|
||||
|
||||
HBUINT8 format;
|
||||
union {
|
||||
FDSelect0 format0;
|
||||
FDSelect3 format3;
|
||||
} u;
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!c->check_struct (this)))
|
||||
return_trace (false);
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case 0: return_trace (u.format0.sanitize (c, fdcount));
|
||||
case 3: return_trace (u.format3.sanitize (c, fdcount));
|
||||
default:return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
HBUINT8 format;
|
||||
union {
|
||||
FDSelect0 format0;
|
||||
FDSelect3 format3;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_MIN (1);
|
||||
};
|
||||
|
||||
|
|
|
@ -161,21 +161,8 @@ struct CFF1SuppEncData {
|
|||
DEFINE_SIZE_ARRAY_SIZED (1, supps);
|
||||
};
|
||||
|
||||
struct Encoding {
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
||||
if (unlikely (!c->check_struct (this)))
|
||||
return_trace (false);
|
||||
unsigned int fmt = format & 0x7F;
|
||||
if (unlikely (fmt > 1))
|
||||
return_trace (false);
|
||||
if (unlikely (!((fmt == 0)? u.format0.sanitize (c): u.format1.sanitize (c))))
|
||||
return_trace (false);
|
||||
return_trace (((format & 0x80) == 0) || suppEncData ().sanitize (c));
|
||||
}
|
||||
|
||||
struct Encoding
|
||||
{
|
||||
/* serialize a fullset Encoding */
|
||||
bool serialize (hb_serialize_context_t *c, const Encoding &src)
|
||||
{
|
||||
|
@ -197,11 +184,12 @@ struct Encoding {
|
|||
TRACE_SERIALIZE (this);
|
||||
Encoding *dest = c->extend_min (*this);
|
||||
if (unlikely (dest == nullptr)) return_trace (false);
|
||||
dest->format = format | ((supp_codes.length > 0)? 0x80: 0);
|
||||
if (format == 0)
|
||||
dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
|
||||
switch (format) {
|
||||
case 0:
|
||||
{
|
||||
Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
|
||||
if (unlikely (fmt0 == nullptr)) return_trace (false);
|
||||
if (unlikely (fmt0 == nullptr)) return_trace (false);
|
||||
fmt0->nCodes () = enc_count;
|
||||
unsigned int glyph = 0;
|
||||
for (unsigned int i = 0; i < code_ranges.length; i++)
|
||||
|
@ -213,7 +201,9 @@ struct Encoding {
|
|||
return_trace (false);
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
|
||||
if (unlikely (fmt1 == nullptr)) return_trace (false);
|
||||
|
@ -226,7 +216,11 @@ struct Encoding {
|
|||
fmt1->ranges[i].nLeft = code_ranges[i].glyph;
|
||||
}
|
||||
}
|
||||
if (supp_codes.length > 0)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (supp_codes.length)
|
||||
{
|
||||
CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
|
||||
if (unlikely (suppData == nullptr)) return_trace (false);
|
||||
|
@ -237,6 +231,7 @@ struct Encoding {
|
|||
suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
|
||||
}
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
@ -245,11 +240,13 @@ struct Encoding {
|
|||
unsigned int enc_count,
|
||||
unsigned int supp_count)
|
||||
{
|
||||
unsigned int size = min_size;
|
||||
if (format == 0)
|
||||
size += Encoding0::min_size + HBUINT8::static_size * enc_count;
|
||||
else
|
||||
size += Encoding1::min_size + Encoding1_Range::static_size * enc_count;
|
||||
unsigned int size = min_size;
|
||||
switch (format)
|
||||
{
|
||||
case 0: size += Encoding0::min_size + HBUINT8::static_size * enc_count; break;
|
||||
case 1: size += Encoding1::min_size + Encoding1_Range::static_size * enc_count; break;
|
||||
default:return 0;
|
||||
}
|
||||
if (supp_count > 0)
|
||||
size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
|
||||
return size;
|
||||
|
@ -258,10 +255,11 @@ struct Encoding {
|
|||
unsigned int get_size () const
|
||||
{
|
||||
unsigned int size = min_size;
|
||||
if (table_format () == 0)
|
||||
size += u.format0.get_size ();
|
||||
else
|
||||
size += u.format1.get_size ();
|
||||
switch (table_format ())
|
||||
{
|
||||
case 0: size += u.format0.get_size (); break;
|
||||
case 1: size += u.format1.get_size (); break;
|
||||
}
|
||||
if (has_supplement ())
|
||||
size += suppEncData ().get_size ();
|
||||
return size;
|
||||
|
@ -269,14 +267,16 @@ struct Encoding {
|
|||
|
||||
hb_codepoint_t get_code (hb_codepoint_t glyph) const
|
||||
{
|
||||
if (table_format () == 0)
|
||||
return u.format0.get_code (glyph);
|
||||
else
|
||||
return u.format1.get_code (glyph);
|
||||
switch (table_format ())
|
||||
{
|
||||
case 0: return u.format0.get_code (glyph);
|
||||
case 1: return u.format1.get_code (glyph);
|
||||
default:return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t table_format () const { return (format & 0x7F); }
|
||||
bool has_supplement () const { return (format & 0x80) != 0; }
|
||||
uint8_t table_format () const { return format & 0x7F; }
|
||||
bool has_supplement () const { return format & 0x80; }
|
||||
|
||||
void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
|
||||
{
|
||||
|
@ -285,21 +285,37 @@ struct Encoding {
|
|||
suppEncData().get_codes (sid, codes);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!c->check_struct (this)))
|
||||
return_trace (false);
|
||||
|
||||
switch (table_format ())
|
||||
{
|
||||
case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
|
||||
case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
|
||||
default:return_trace (false);
|
||||
}
|
||||
return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
|
||||
}
|
||||
|
||||
protected:
|
||||
const CFF1SuppEncData &suppEncData () const
|
||||
{
|
||||
if ((format & 0x7F) == 0)
|
||||
return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
|
||||
else
|
||||
return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
|
||||
switch (table_format ())
|
||||
{
|
||||
case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
|
||||
case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
|
||||
default:return Null (CFF1SuppEncData);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
HBUINT8 format;
|
||||
|
||||
HBUINT8 format;
|
||||
union {
|
||||
Encoding0 format0;
|
||||
Encoding1 format1;
|
||||
Encoding0 format0;
|
||||
Encoding1 format1;
|
||||
} u;
|
||||
/* CFF1SuppEncData suppEncData; */
|
||||
|
||||
|
@ -433,23 +449,8 @@ typedef Charset1_2<HBUINT16> Charset2;
|
|||
typedef Charset_Range<HBUINT8> Charset1_Range;
|
||||
typedef Charset_Range<HBUINT16> Charset2_Range;
|
||||
|
||||
struct Charset {
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
||||
if (unlikely (!c->check_struct (this)))
|
||||
return_trace (false);
|
||||
if (format == 0)
|
||||
return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
|
||||
else if (format == 1)
|
||||
return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
|
||||
else if (likely (format == 2))
|
||||
return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
|
||||
else
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
struct Charset
|
||||
{
|
||||
/* serialize a fullset Charset */
|
||||
bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
|
||||
{
|
||||
|
@ -471,10 +472,12 @@ struct Charset {
|
|||
Charset *dest = c->extend_min (*this);
|
||||
if (unlikely (dest == nullptr)) return_trace (false);
|
||||
dest->format = format;
|
||||
if (format == 0)
|
||||
switch (format)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
|
||||
if (unlikely (fmt0 == nullptr)) return_trace (false);
|
||||
if (unlikely (fmt0 == nullptr)) return_trace (false);
|
||||
unsigned int glyph = 0;
|
||||
for (unsigned int i = 0; i < sid_ranges.length; i++)
|
||||
{
|
||||
|
@ -483,7 +486,9 @@ struct Charset {
|
|||
fmt0->sids[glyph++] = sid++;
|
||||
}
|
||||
}
|
||||
else if (format == 1)
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
|
||||
if (unlikely (fmt1 == nullptr)) return_trace (false);
|
||||
|
@ -495,7 +500,9 @@ struct Charset {
|
|||
fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
|
||||
}
|
||||
}
|
||||
else /* format 2 */
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
|
||||
if (unlikely (fmt2 == nullptr)) return_trace (false);
|
||||
|
@ -506,56 +513,72 @@ struct Charset {
|
|||
fmt2->ranges[i].first = sid_ranges[i].code;
|
||||
fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
/* parallel to above: calculate the size of a subset Charset */
|
||||
static unsigned int calculate_serialized_size (
|
||||
uint8_t format,
|
||||
unsigned int count)
|
||||
static unsigned int calculate_serialized_size (uint8_t format,
|
||||
unsigned int count)
|
||||
{
|
||||
unsigned int size = min_size;
|
||||
if (format == 0)
|
||||
size += Charset0::min_size + HBUINT16::static_size * (count - 1);
|
||||
else if (format == 1)
|
||||
size += Charset1::min_size + Charset1_Range::static_size * count;
|
||||
else
|
||||
size += Charset2::min_size + Charset2_Range::static_size * count;
|
||||
|
||||
return size;
|
||||
switch (format)
|
||||
{
|
||||
case 0: return min_size + Charset0::min_size + HBUINT16::static_size * (count - 1);
|
||||
case 1: return min_size + Charset1::min_size + Charset1_Range::static_size * count;
|
||||
case 2: return min_size + Charset2::min_size + Charset2_Range::static_size * count;
|
||||
default:return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int get_size (unsigned int num_glyphs) const
|
||||
{
|
||||
unsigned int size = min_size;
|
||||
if (format == 0)
|
||||
size += u.format0.get_size (num_glyphs);
|
||||
else if (format == 1)
|
||||
size += u.format1.get_size (num_glyphs);
|
||||
else
|
||||
size += u.format2.get_size (num_glyphs);
|
||||
return size;
|
||||
switch (format)
|
||||
{
|
||||
case 0: return min_size + u.format0.get_size (num_glyphs);
|
||||
case 1: return min_size + u.format1.get_size (num_glyphs);
|
||||
case 2: return min_size + u.format2.get_size (num_glyphs);
|
||||
default:return 0;
|
||||
}
|
||||
}
|
||||
|
||||
hb_codepoint_t get_sid (hb_codepoint_t glyph) const
|
||||
{
|
||||
if (format == 0)
|
||||
return u.format0.get_sid (glyph);
|
||||
else if (format == 1)
|
||||
return u.format1.get_sid (glyph);
|
||||
else
|
||||
return u.format2.get_sid (glyph);
|
||||
switch (format)
|
||||
{
|
||||
case 0: return u.format0.get_sid (glyph);
|
||||
case 1: return u.format1.get_sid (glyph);
|
||||
case 2: return u.format2.get_sid (glyph);
|
||||
default:return 0;
|
||||
}
|
||||
}
|
||||
|
||||
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
|
||||
{
|
||||
if (format == 0)
|
||||
return u.format0.get_glyph (sid, num_glyphs);
|
||||
else if (format == 1)
|
||||
return u.format1.get_glyph (sid, num_glyphs);
|
||||
else
|
||||
return u.format2.get_glyph (sid, num_glyphs);
|
||||
switch (format)
|
||||
{
|
||||
case 0: return u.format0.get_glyph (sid, num_glyphs);
|
||||
case 1: return u.format1.get_glyph (sid, num_glyphs);
|
||||
case 2: return u.format2.get_glyph (sid, num_glyphs);
|
||||
default:return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!c->check_struct (this)))
|
||||
return_trace (false);
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
|
||||
case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
|
||||
case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
|
||||
default:return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
HBUINT8 format;
|
||||
|
|
|
@ -51,18 +51,6 @@ typedef FDSelect3_4_Range<HBUINT32, HBUINT16> FDSelect4_Range;
|
|||
|
||||
struct CFF2FDSelect
|
||||
{
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
||||
return_trace (likely (c->check_struct (this) && (format == 0 || format == 3 || format == 4) &&
|
||||
((format == 0)?
|
||||
u.format0.sanitize (c, fdcount):
|
||||
((format == 3)?
|
||||
u.format3.sanitize (c, fdcount):
|
||||
u.format4.sanitize (c, fdcount)))));
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
@ -78,35 +66,51 @@ struct CFF2FDSelect
|
|||
|
||||
unsigned int get_size (unsigned int num_glyphs) const
|
||||
{
|
||||
unsigned int size = format.static_size;
|
||||
if (format == 0)
|
||||
size += u.format0.get_size (num_glyphs);
|
||||
else if (format == 3)
|
||||
size += u.format3.get_size ();
|
||||
else
|
||||
size += u.format4.get_size ();
|
||||
return size;
|
||||
switch (format)
|
||||
{
|
||||
case 0: return format.static_size + u.format0.get_size (num_glyphs);
|
||||
case 3: return format.static_size + u.format3.get_size ();
|
||||
case 4: return format.static_size + u.format4.get_size ();
|
||||
default:return 0;
|
||||
}
|
||||
}
|
||||
|
||||
hb_codepoint_t get_fd (hb_codepoint_t glyph) const
|
||||
{
|
||||
if (this == &Null(CFF2FDSelect))
|
||||
if (this == &Null (CFF2FDSelect))
|
||||
return 0;
|
||||
if (format == 0)
|
||||
return u.format0.get_fd (glyph);
|
||||
else if (format == 3)
|
||||
return u.format3.get_fd (glyph);
|
||||
else
|
||||
return u.format4.get_fd (glyph);
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case 0: return u.format0.get_fd (glyph);
|
||||
case 3: return u.format3.get_fd (glyph);
|
||||
case 4: return u.format4.get_fd (glyph);
|
||||
default:return 0;
|
||||
}
|
||||
}
|
||||
|
||||
HBUINT8 format;
|
||||
union {
|
||||
FDSelect0 format0;
|
||||
FDSelect3 format3;
|
||||
FDSelect4 format4;
|
||||
} u;
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!c->check_struct (this)))
|
||||
return_trace (false);
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case 0: return_trace (u.format0.sanitize (c, fdcount));
|
||||
case 3: return_trace (u.format3.sanitize (c, fdcount));
|
||||
case 4: return_trace (u.format4.sanitize (c, fdcount));
|
||||
default:return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
HBUINT8 format;
|
||||
union {
|
||||
FDSelect0 format0;
|
||||
FDSelect3 format3;
|
||||
FDSelect4 format4;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_MIN (2);
|
||||
};
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ struct glyf
|
|||
|
||||
+ hb_range (plan->num_output_glyphs ())
|
||||
| hb_map ([&] (hb_codepoint_t new_gid) {
|
||||
SubsetGlyph subset_glyph;
|
||||
SubsetGlyph subset_glyph = {0};
|
||||
subset_glyph.new_gid = new_gid;
|
||||
|
||||
// should never fail: all old gids should be mapped
|
||||
|
|
|
@ -94,39 +94,35 @@ struct maxp
|
|||
return_trace (likely (version.major == 0 && version.minor == 0x5000u));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_plan_t *plan) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
hb_blob_t *maxp_blob = hb_sanitize_context_t().reference_table<maxp> (plan->source);
|
||||
hb_blob_t *maxp_prime_blob = hb_blob_copy_writable_or_fail (maxp_blob);
|
||||
hb_blob_destroy (maxp_blob);
|
||||
TRACE_SUBSET (this);
|
||||
maxp *maxp_prime = c->serializer->embed (this);
|
||||
if (unlikely (!maxp_prime)) return_trace (false);
|
||||
|
||||
if (unlikely (!maxp_prime_blob)) {
|
||||
return false;
|
||||
}
|
||||
maxp *maxp_prime = (maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
|
||||
|
||||
maxp_prime->set_num_glyphs (plan->num_output_glyphs ());
|
||||
if (plan->drop_hints)
|
||||
drop_hint_fields (plan, maxp_prime);
|
||||
|
||||
bool result = plan->add_table (HB_OT_TAG_maxp, maxp_prime_blob);
|
||||
hb_blob_destroy (maxp_prime_blob);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void drop_hint_fields (hb_subset_plan_t *plan HB_UNUSED, maxp *maxp_prime)
|
||||
{
|
||||
maxp_prime->numGlyphs = c->plan->num_output_glyphs ();
|
||||
if (maxp_prime->version.major == 1)
|
||||
{
|
||||
maxpV1Tail &v1 = StructAfter<maxpV1Tail> (*maxp_prime);
|
||||
v1.maxZones = 1;
|
||||
v1.maxTwilightPoints = 0;
|
||||
v1.maxStorage = 0;
|
||||
v1.maxFunctionDefs = 0;
|
||||
v1.maxInstructionDefs = 0;
|
||||
v1.maxStackElements = 0;
|
||||
v1.maxSizeOfInstructions = 0;
|
||||
const maxpV1Tail *src_v1 = &StructAfter<maxpV1Tail> (*this);
|
||||
maxpV1Tail *dest_v1 = c->serializer->embed<maxpV1Tail> (src_v1);
|
||||
if (unlikely (!dest_v1)) return_trace (false);
|
||||
|
||||
if (c->plan->drop_hints)
|
||||
drop_hint_fields (dest_v1);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
static void drop_hint_fields (maxpV1Tail* dest_v1)
|
||||
{
|
||||
dest_v1->maxZones = 1;
|
||||
dest_v1->maxTwilightPoints = 0;
|
||||
dest_v1->maxStorage = 0;
|
||||
dest_v1->maxFunctionDefs = 0;
|
||||
dest_v1->maxInstructionDefs = 0;
|
||||
dest_v1->maxStackElements = 0;
|
||||
dest_v1->maxSizeOfInstructions = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -145,29 +145,20 @@ struct OS2
|
|||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_plan_t *plan) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
hb_blob_t *os2_blob = hb_sanitize_context_t ().reference_table<OS2> (plan->source);
|
||||
hb_blob_t *os2_prime_blob = hb_blob_create_sub_blob (os2_blob, 0, -1);
|
||||
// TODO(grieger): move to hb_blob_copy_writable_or_fail
|
||||
hb_blob_destroy (os2_blob);
|
||||
|
||||
OS2 *os2_prime = (OS2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
|
||||
if (unlikely (!os2_prime)) {
|
||||
hb_blob_destroy (os2_prime_blob);
|
||||
return false;
|
||||
}
|
||||
TRACE_SUBSET (this);
|
||||
OS2 *os2_prime = c->serializer->embed (this);
|
||||
if (unlikely (!os2_prime)) return_trace (false);
|
||||
|
||||
uint16_t min_cp, max_cp;
|
||||
find_min_and_max_codepoint (plan->unicodes, &min_cp, &max_cp);
|
||||
find_min_and_max_codepoint (c->plan->unicodes, &min_cp, &max_cp);
|
||||
os2_prime->usFirstCharIndex = min_cp;
|
||||
os2_prime->usLastCharIndex = max_cp;
|
||||
|
||||
_update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange);
|
||||
bool result = plan->add_table (HB_OT_TAG_OS2, os2_prime_blob);
|
||||
_update_unicode_ranges (c->plan->unicodes, os2_prime->ulUnicodeRange);
|
||||
|
||||
hb_blob_destroy (os2_prime_blob);
|
||||
return result;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
void _update_unicode_ranges (const hb_set_t *codepoints,
|
||||
|
@ -218,6 +209,15 @@ struct OS2
|
|||
font_page_t get_font_page () const
|
||||
{ return (font_page_t) (version == 0 ? fsSelection & 0xFF00 : 0); }
|
||||
|
||||
unsigned get_size () const
|
||||
{
|
||||
unsigned result = min_size;
|
||||
if (version >= 1) result += v1X.get_size ();
|
||||
if (version >= 2) result += v2X.get_size ();
|
||||
if (version >= 5) result += v5X.get_size ();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
|
@ -73,26 +73,25 @@ struct post
|
|||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_post;
|
||||
|
||||
bool subset (hb_subset_plan_t *plan) const
|
||||
void serialize (hb_serialize_context_t *c) const
|
||||
{
|
||||
unsigned int post_prime_length;
|
||||
hb_blob_t *post_blob = hb_sanitize_context_t ().reference_table<post>(plan->source);
|
||||
hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::min_size);
|
||||
post *post_prime = (post *) hb_blob_get_data_writable (post_prime_blob, &post_prime_length);
|
||||
hb_blob_destroy (post_blob);
|
||||
|
||||
if (unlikely (!post_prime || post_prime_length != post::min_size))
|
||||
{
|
||||
hb_blob_destroy (post_prime_blob);
|
||||
DEBUG_MSG(SUBSET, nullptr, "Invalid source post table with length %d.", post_prime_length);
|
||||
return false;
|
||||
}
|
||||
post *post_prime = c->allocate_min<post> ();
|
||||
if (unlikely (!post_prime)) return;
|
||||
|
||||
memcpy (post_prime, this, post::min_size);
|
||||
post_prime->version.major = 3; // Version 3 does not have any glyph names.
|
||||
bool result = plan->add_table (HB_OT_TAG_post, post_prime_blob);
|
||||
hb_blob_destroy (post_prime_blob);
|
||||
}
|
||||
|
||||
return result;
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
post *post_prime = c->serializer->start_embed<post> ();
|
||||
if (unlikely (!post_prime)) return_trace (false);
|
||||
|
||||
serialize (c->serializer);
|
||||
if (c->serializer->in_error () || c->serializer->ran_out_of_room) return_trace (false);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
struct accelerator_t
|
||||
|
@ -158,7 +157,7 @@ struct post
|
|||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
gids[i] = i;
|
||||
hb_sort_r (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
|
||||
hb_qsort (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
|
||||
|
||||
if (unlikely (!gids_sorted_by_name.cmpexch (nullptr, gids)))
|
||||
{
|
||||
|
|
|
@ -59,14 +59,14 @@ enum
|
|||
|
||||
struct AxisValueFormat1
|
||||
{
|
||||
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this)));
|
||||
}
|
||||
|
||||
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
|
||||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier — set to 1. */
|
||||
HBUINT16 axisIndex; /* Zero-base index into the axis record array
|
||||
|
@ -84,14 +84,14 @@ struct AxisValueFormat1
|
|||
|
||||
struct AxisValueFormat2
|
||||
{
|
||||
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this)));
|
||||
}
|
||||
|
||||
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
|
||||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier — set to 2. */
|
||||
HBUINT16 axisIndex; /* Zero-base index into the axis record array
|
||||
|
@ -113,14 +113,14 @@ struct AxisValueFormat2
|
|||
|
||||
struct AxisValueFormat3
|
||||
{
|
||||
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this)));
|
||||
}
|
||||
|
||||
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
|
||||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier — set to 3. */
|
||||
HBUINT16 axisIndex; /* Zero-base index into the axis record array
|
||||
|
@ -157,14 +157,14 @@ struct AxisValueRecord
|
|||
|
||||
struct AxisValueFormat4
|
||||
{
|
||||
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this)));
|
||||
}
|
||||
|
||||
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
|
||||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier — set to 4. */
|
||||
HBUINT16 axisCount; /* The total number of axes contributing to
|
||||
|
@ -183,6 +183,18 @@ struct AxisValueFormat4
|
|||
|
||||
struct AxisValue
|
||||
{
|
||||
hb_ot_name_id_t get_value_name_id () const
|
||||
{
|
||||
switch (u.format)
|
||||
{
|
||||
case 1: return u.format1.get_value_name_id ();
|
||||
case 2: return u.format2.get_value_name_id ();
|
||||
case 3: return u.format3.get_value_name_id ();
|
||||
case 4: return u.format4.get_value_name_id ();
|
||||
default:return HB_OT_NAME_ID_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -191,23 +203,11 @@ struct AxisValue
|
|||
|
||||
switch (u.format)
|
||||
{
|
||||
case 1: return_trace (likely (u.format1.sanitize (c)));
|
||||
case 2: return_trace (likely (u.format2.sanitize (c)));
|
||||
case 3: return_trace (likely (u.format3.sanitize (c)));
|
||||
case 4: return_trace (likely (u.format4.sanitize (c)));
|
||||
default: return_trace (true);
|
||||
}
|
||||
}
|
||||
|
||||
hb_ot_name_id_t get_value_name_id () const
|
||||
{
|
||||
switch (u.format)
|
||||
{
|
||||
case 1: return u.format1.get_value_name_id ();
|
||||
case 2: return u.format2.get_value_name_id ();
|
||||
case 3: return u.format3.get_value_name_id ();
|
||||
case 4: return u.format4.get_value_name_id ();
|
||||
default: return HB_OT_NAME_ID_INVALID;
|
||||
case 1: return_trace (u.format1.sanitize (c));
|
||||
case 2: return_trace (u.format2.sanitize (c));
|
||||
case 3: return_trace (u.format3.sanitize (c));
|
||||
case 4: return_trace (u.format4.sanitize (c));
|
||||
default:return_trace (true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,14 +226,14 @@ struct AxisValue
|
|||
|
||||
struct StatAxisRecord
|
||||
{
|
||||
hb_ot_name_id_t get_name_id () const { return nameID; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this)));
|
||||
}
|
||||
|
||||
hb_ot_name_id_t get_name_id () const { return nameID; }
|
||||
|
||||
protected:
|
||||
Tag tag; /* A tag identifying the axis of design variation. */
|
||||
NameID nameID; /* The name ID for entries in the 'name' table that
|
||||
|
@ -249,16 +249,6 @@ struct STAT
|
|||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_STAT;
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
version.major == 1 &&
|
||||
version.minor > 0 &&
|
||||
designAxesOffset.sanitize (c, this, designAxisCount) &&
|
||||
offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
|
||||
}
|
||||
|
||||
bool has_data () const { return version.to_int (); }
|
||||
|
||||
unsigned get_design_axis_count () const { return designAxisCount; }
|
||||
|
@ -295,6 +285,16 @@ struct STAT
|
|||
;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
version.major == 1 &&
|
||||
version.minor > 0 &&
|
||||
designAxesOffset.sanitize (c, this, designAxisCount) &&
|
||||
offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
|
||||
}
|
||||
|
||||
protected:
|
||||
hb_array_t<const StatAxisRecord> const get_design_axes () const
|
||||
{ return (this+designAxesOffset).as_array (designAxisCount); }
|
||||
|
|
|
@ -145,7 +145,9 @@ hb_ot_all_tags_from_script (hb_script_t script,
|
|||
hb_tag_t new_tag = hb_ot_new_tag_from_script (script);
|
||||
if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT))
|
||||
{
|
||||
tags[i++] = new_tag | '3';
|
||||
/* HB_SCRIPT_MYANMAR maps to 'mym2', but there is no 'mym3'. */
|
||||
if (new_tag != HB_TAG('m','y','m','2'))
|
||||
tags[i++] = new_tag | '3';
|
||||
if (*count > i)
|
||||
tags[i++] = new_tag;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
|
|||
subset_fd_count = 0;
|
||||
subset_fdselect_size = 0;
|
||||
subset_fdselect_format = 0;
|
||||
unsigned int num_ranges = 0;
|
||||
unsigned int num_ranges = 0;
|
||||
|
||||
unsigned int subset_num_glyphs = plan->num_output_glyphs ();
|
||||
if (subset_num_glyphs == 0)
|
||||
|
@ -63,14 +63,14 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
|
|||
|
||||
{
|
||||
/* use hb_set to determine the subset of font dicts */
|
||||
hb_set_t *set = hb_set_create ();
|
||||
hb_set_t *set = hb_set_create ();
|
||||
if (set == &Null (hb_set_t))
|
||||
return false;
|
||||
hb_codepoint_t prev_fd = CFF_UNDEF_CODE;
|
||||
hb_codepoint_t prev_fd = CFF_UNDEF_CODE;
|
||||
for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++)
|
||||
{
|
||||
hb_codepoint_t glyph;
|
||||
hb_codepoint_t fd;
|
||||
hb_codepoint_t glyph;
|
||||
hb_codepoint_t fd;
|
||||
if (!plan->old_gid_for_new_gid (i, &glyph))
|
||||
{
|
||||
/* fonttools retains FDSelect & font dicts for missing glyphs. do the same */
|
||||
|
@ -145,10 +145,10 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
|
|||
template <typename FDSELECT3_4>
|
||||
static inline bool
|
||||
serialize_fdselect_3_4 (hb_serialize_context_t *c,
|
||||
const unsigned int num_glyphs,
|
||||
const FDSelect &src,
|
||||
unsigned int size,
|
||||
const hb_vector_t<code_pair_t> &fdselect_ranges)
|
||||
const unsigned int num_glyphs,
|
||||
const FDSelect &src,
|
||||
unsigned int size,
|
||||
const hb_vector_t<code_pair_t> &fdselect_ranges)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
FDSELECT3_4 *p = c->allocate_size<FDSELECT3_4> (size);
|
||||
|
@ -159,7 +159,7 @@ serialize_fdselect_3_4 (hb_serialize_context_t *c,
|
|||
p->ranges[i].first = fdselect_ranges[i].glyph;
|
||||
p->ranges[i].fd = fdselect_ranges[i].code;
|
||||
}
|
||||
p->sentinel() = num_glyphs;
|
||||
p->sentinel () = num_glyphs;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
@ -169,15 +169,15 @@ serialize_fdselect_3_4 (hb_serialize_context_t *c,
|
|||
**/
|
||||
bool
|
||||
hb_serialize_cff_fdselect (hb_serialize_context_t *c,
|
||||
const unsigned int num_glyphs,
|
||||
const FDSelect &src,
|
||||
unsigned int fd_count,
|
||||
unsigned int fdselect_format,
|
||||
unsigned int size,
|
||||
const hb_vector_t<code_pair_t> &fdselect_ranges)
|
||||
const unsigned int num_glyphs,
|
||||
const FDSelect &src,
|
||||
unsigned int fd_count,
|
||||
unsigned int fdselect_format,
|
||||
unsigned int size,
|
||||
const hb_vector_t<code_pair_t> &fdselect_ranges)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
FDSelect *p = c->allocate_min<FDSelect> ();
|
||||
FDSelect *p = c->allocate_min<FDSelect> ();
|
||||
if (unlikely (p == nullptr)) return_trace (false);
|
||||
p->format = fdselect_format;
|
||||
size -= FDSelect::min_size;
|
||||
|
@ -185,42 +185,34 @@ hb_serialize_cff_fdselect (hb_serialize_context_t *c,
|
|||
switch (fdselect_format)
|
||||
{
|
||||
#if CFF_SERIALIZE_FDSELECT_0
|
||||
case 0:
|
||||
case 0:
|
||||
{
|
||||
FDSelect0 *p = c->allocate_size<FDSelect0> (size);
|
||||
if (unlikely (p == nullptr)) return_trace (false);
|
||||
unsigned int range_index = 0;
|
||||
unsigned int fd = fdselect_ranges[range_index++].code;
|
||||
for (unsigned int i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
FDSelect0 *p = c->allocate_size<FDSelect0> (size);
|
||||
if (unlikely (p == nullptr)) return_trace (false);
|
||||
unsigned int range_index = 0;
|
||||
unsigned int fd = fdselect_ranges[range_index++].code;
|
||||
for (unsigned int i = 0; i < num_glyphs; i++)
|
||||
if ((range_index < fdselect_ranges.len) &&
|
||||
(i >= fdselect_ranges[range_index].glyph))
|
||||
{
|
||||
if ((range_index < fdselect_ranges.len) &&
|
||||
(i >= fdselect_ranges[range_index].glyph))
|
||||
{
|
||||
fd = fdselect_ranges[range_index++].code;
|
||||
}
|
||||
p->fds[i] = fd;
|
||||
fd = fdselect_ranges[range_index++].code;
|
||||
}
|
||||
break;
|
||||
p->fds[i] = fd;
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
#endif /* CFF_SERIALIZE_FDSELECT_0 */
|
||||
|
||||
case 3:
|
||||
return serialize_fdselect_3_4<FDSelect3> (c,
|
||||
num_glyphs,
|
||||
src,
|
||||
size,
|
||||
fdselect_ranges);
|
||||
case 3:
|
||||
return serialize_fdselect_3_4<FDSelect3> (c, num_glyphs, src,
|
||||
size, fdselect_ranges);
|
||||
|
||||
case 4:
|
||||
return serialize_fdselect_3_4<FDSelect4> (c,
|
||||
num_glyphs,
|
||||
src,
|
||||
size,
|
||||
fdselect_ranges);
|
||||
case 4:
|
||||
return serialize_fdselect_3_4<FDSelect4> (c, num_glyphs, src,
|
||||
size, fdselect_ranges);
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
default:
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
|
@ -1037,7 +1037,7 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
|
|||
bool result;
|
||||
cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
|
||||
/* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
|
||||
unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0;
|
||||
unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0;
|
||||
result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
|
||||
if (unlikely (!result))
|
||||
{
|
||||
|
|
|
@ -545,7 +545,7 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
|
|||
bool result;
|
||||
cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
|
||||
/* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
|
||||
unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0;
|
||||
unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0;
|
||||
result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
|
||||
if (unlikely (!result))
|
||||
{
|
||||
|
|
|
@ -183,7 +183,7 @@ _subset_table (hb_subset_plan_t *plan,
|
|||
result = _subset2<const OT::vmtx> (plan);
|
||||
break;
|
||||
case HB_OT_TAG_maxp:
|
||||
result = _subset<const OT::maxp> (plan);
|
||||
result = _subset2<const OT::maxp> (plan);
|
||||
break;
|
||||
case HB_OT_TAG_loca:
|
||||
DEBUG_MSG(SUBSET, nullptr, "skip loca handled by glyf");
|
||||
|
@ -192,10 +192,10 @@ _subset_table (hb_subset_plan_t *plan,
|
|||
result = _subset<const OT::cmap> (plan);
|
||||
break;
|
||||
case HB_OT_TAG_OS2:
|
||||
result = _subset<const OT::OS2> (plan);
|
||||
result = _subset2<const OT::OS2> (plan);
|
||||
break;
|
||||
case HB_OT_TAG_post:
|
||||
result = _subset<const OT::post> (plan);
|
||||
result = _subset2<const OT::post> (plan);
|
||||
break;
|
||||
|
||||
#ifndef HB_NO_SUBSET_CFF
|
||||
|
|
|
@ -86,8 +86,8 @@ _hb_ucd_sc_map[138] =
|
|||
HB_SCRIPT_MARCHEN, HB_SCRIPT_OSAGE,
|
||||
HB_SCRIPT_TANGUT, HB_SCRIPT_NEWA,
|
||||
};
|
||||
static const hb_codepoint_t
|
||||
_hb_ucd_dm1_map[935] =
|
||||
static const uint16_t
|
||||
_hb_ucd_dm1_u16_map[825] =
|
||||
{
|
||||
0x003Bu, 0x004Bu, 0x0060u, 0x00B4u, 0x00B7u, 0x00C5u, 0x02B9u, 0x0300u,
|
||||
0x0301u, 0x0313u, 0x0385u, 0x0386u, 0x0388u, 0x0389u, 0x038Au, 0x038Cu,
|
||||
|
@ -192,20 +192,25 @@ _hb_ucd_dm1_map[935] =
|
|||
0x9A6Au, 0x9B12u, 0x9B6Fu, 0x9C40u, 0x9C57u, 0x9CFDu, 0x9D67u, 0x9DB4u,
|
||||
0x9DFAu, 0x9E1Eu, 0x9E7Fu, 0x9E97u, 0x9E9Fu, 0x9EBBu, 0x9ECEu, 0x9EF9u,
|
||||
0x9EFEu, 0x9F05u, 0x9F0Fu, 0x9F16u, 0x9F3Bu, 0x9F43u, 0x9F8Du, 0x9F8Eu,
|
||||
0x9F9Cu,0x20122u,0x2051Cu,0x20525u,0x2054Bu,0x2063Au,0x20804u,0x208DEu,
|
||||
0x20A2Cu,0x20B63u,0x214E4u,0x216A8u,0x216EAu,0x219C8u,0x21B18u,0x21D0Bu,
|
||||
0x21DE4u,0x21DE6u,0x22183u,0x2219Fu,0x22331u,0x226D4u,0x22844u,0x2284Au,
|
||||
0x22B0Cu,0x22BF1u,0x2300Au,0x232B8u,0x2335Fu,0x23393u,0x2339Cu,0x233C3u,
|
||||
0x233D5u,0x2346Du,0x236A3u,0x238A7u,0x23A8Du,0x23AFAu,0x23CBCu,0x23D1Eu,
|
||||
0x23ED1u,0x23F5Eu,0x23F8Eu,0x24263u,0x242EEu,0x243ABu,0x24608u,0x24735u,
|
||||
0x24814u,0x24C36u,0x24C92u,0x24FA1u,0x24FB8u,0x25044u,0x250F2u,0x250F3u,
|
||||
0x25119u,0x25133u,0x25249u,0x2541Du,0x25626u,0x2569Au,0x256C5u,0x2597Cu,
|
||||
0x25AA7u,0x25BABu,0x25C80u,0x25CD0u,0x25F86u,0x261DAu,0x26228u,0x26247u,
|
||||
0x262D9u,0x2633Eu,0x264DAu,0x26523u,0x265A8u,0x267A7u,0x267B5u,0x26B3Cu,
|
||||
0x26C36u,0x26CD5u,0x26D6Bu,0x26F2Cu,0x26FB1u,0x270D2u,0x273CAu,0x27667u,
|
||||
0x278AEu,0x27966u,0x27CA8u,0x27ED3u,0x27F2Fu,0x285D2u,0x285EDu,0x2872Eu,
|
||||
0x28BFAu,0x28D77u,0x29145u,0x291DFu,0x2921Au,0x2940Au,0x29496u,0x295B6u,
|
||||
0x29B30u,0x2A0CEu,0x2A105u,0x2A20Eu,0x2A291u,0x2A392u,0x2A600u,
|
||||
0x9F9Cu,
|
||||
};
|
||||
static const uint32_t
|
||||
_hb_ucd_dm1_u32_map[110] =
|
||||
{
|
||||
0x20122u,0x2051Cu,0x20525u,0x2054Bu,0x2063Au,0x20804u,0x208DEu,0x20A2Cu,
|
||||
0x20B63u,0x214E4u,0x216A8u,0x216EAu,0x219C8u,0x21B18u,0x21D0Bu,0x21DE4u,
|
||||
0x21DE6u,0x22183u,0x2219Fu,0x22331u,0x226D4u,0x22844u,0x2284Au,0x22B0Cu,
|
||||
0x22BF1u,0x2300Au,0x232B8u,0x2335Fu,0x23393u,0x2339Cu,0x233C3u,0x233D5u,
|
||||
0x2346Du,0x236A3u,0x238A7u,0x23A8Du,0x23AFAu,0x23CBCu,0x23D1Eu,0x23ED1u,
|
||||
0x23F5Eu,0x23F8Eu,0x24263u,0x242EEu,0x243ABu,0x24608u,0x24735u,0x24814u,
|
||||
0x24C36u,0x24C92u,0x24FA1u,0x24FB8u,0x25044u,0x250F2u,0x250F3u,0x25119u,
|
||||
0x25133u,0x25249u,0x2541Du,0x25626u,0x2569Au,0x256C5u,0x2597Cu,0x25AA7u,
|
||||
0x25BABu,0x25C80u,0x25CD0u,0x25F86u,0x261DAu,0x26228u,0x26247u,0x262D9u,
|
||||
0x2633Eu,0x264DAu,0x26523u,0x265A8u,0x267A7u,0x267B5u,0x26B3Cu,0x26C36u,
|
||||
0x26CD5u,0x26D6Bu,0x26F2Cu,0x26FB1u,0x270D2u,0x273CAu,0x27667u,0x278AEu,
|
||||
0x27966u,0x27CA8u,0x27ED3u,0x27F2Fu,0x285D2u,0x285EDu,0x2872Eu,0x28BFAu,
|
||||
0x28D77u,0x29145u,0x291DFu,0x2921Au,0x2940Au,0x29496u,0x295B6u,0x29B30u,
|
||||
0x2A0CEu,0x2A105u,0x2A20Eu,0x2A291u,0x2A392u,0x2A600u,
|
||||
};
|
||||
static const uint64_t
|
||||
_hb_ucd_dm2_map[1025] =
|
||||
|
|
|
@ -148,13 +148,19 @@ hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
|||
if (likely (!i)) return false;
|
||||
i--;
|
||||
|
||||
if (i < ARRAY_LENGTH (_hb_ucd_dm1_map))
|
||||
if (i < ARRAY_LENGTH (_hb_ucd_dm1_u16_map) + ARRAY_LENGTH (_hb_ucd_dm1_u32_map))
|
||||
{
|
||||
*a = _hb_ucd_dm1_map[i];
|
||||
if (i < ARRAY_LENGTH (_hb_ucd_dm1_u16_map))
|
||||
*a = _hb_ucd_dm1_u16_map[i];
|
||||
else
|
||||
{
|
||||
i -= ARRAY_LENGTH (_hb_ucd_dm1_u16_map);
|
||||
*a = _hb_ucd_dm1_u32_map[i];
|
||||
}
|
||||
*b = 0;
|
||||
return true;
|
||||
}
|
||||
i -= ARRAY_LENGTH (_hb_ucd_dm1_map);
|
||||
i -= ARRAY_LENGTH (_hb_ucd_dm1_u16_map) + ARRAY_LENGTH (_hb_ucd_dm1_u32_map);
|
||||
|
||||
uint64_t v = _hb_ucd_dm2_map[i];
|
||||
*a = HB_CODEPOINT_DECODE3_1 (v);
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
#include <usp10.h>
|
||||
#include <rpc.h>
|
||||
|
||||
#ifndef E_NOT_SUFFICIENT_BUFFER
|
||||
#define E_NOT_SUFFICIENT_BUFFER HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)
|
||||
#endif
|
||||
|
||||
#include "hb-uniscribe.h"
|
||||
|
||||
#include "hb-open-file.hh"
|
||||
|
|
25
src/hb.hh
25
src/hb.hh
|
@ -66,7 +66,6 @@
|
|||
#pragma GCC diagnostic error "-Wcast-align"
|
||||
#pragma GCC diagnostic error "-Wcast-function-type"
|
||||
#pragma GCC diagnostic error "-Wdelete-non-virtual-dtor"
|
||||
#pragma GCC diagnostic error "-Wdouble-promotion"
|
||||
#pragma GCC diagnostic error "-Wextra-semi-stmt"
|
||||
#pragma GCC diagnostic error "-Wformat-security"
|
||||
#pragma GCC diagnostic error "-Wimplicit-function-declaration"
|
||||
|
@ -99,6 +98,7 @@
|
|||
#pragma GCC diagnostic warning "-Wbuiltin-macro-redefined"
|
||||
#pragma GCC diagnostic warning "-Wdeprecated"
|
||||
#pragma GCC diagnostic warning "-Wdisabled-optimization"
|
||||
#pragma GCC diagnostic warning "-Wdouble-promotion"
|
||||
#pragma GCC diagnostic warning "-Wformat=2"
|
||||
#pragma GCC diagnostic warning "-Wignored-pragma-optimize"
|
||||
#pragma GCC diagnostic warning "-Wlogical-op"
|
||||
|
@ -183,8 +183,15 @@
|
|||
#include <stdarg.h>
|
||||
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
|
||||
#ifdef __MINGW32_VERSION
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define HB_PASTE1(a,b) a##b
|
||||
#define HB_PASTE(a,b) HB_PASTE1(a,b)
|
||||
|
@ -352,7 +359,7 @@ extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
|
|||
# define HB_NO_GETENV
|
||||
# endif
|
||||
# if _WIN32_WCE < 0x800
|
||||
# define setlocale(Category, Locale) "C"
|
||||
# define HB_NO_SETLOCALE
|
||||
static int errno = 0; /* Use something better? */
|
||||
# endif
|
||||
# elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
|
||||
|
@ -508,20 +515,6 @@ typedef uint64_t hb_vector_size_impl_t;
|
|||
#define VAR 1
|
||||
|
||||
|
||||
/* fallback for round() */
|
||||
static inline double
|
||||
_hb_round (double x)
|
||||
{
|
||||
if (x >= 0)
|
||||
return floor (x + 0.5);
|
||||
else
|
||||
return ceil (x - 0.5);
|
||||
}
|
||||
#if !defined (HAVE_ROUND) && !defined (HAVE_DECL_ROUND)
|
||||
#define round(x) _hb_round(x)
|
||||
#endif
|
||||
|
||||
|
||||
/* fallback for posix_memalign() */
|
||||
static inline int
|
||||
_hb_memalign(void **memptr, size_t alignment, size_t size)
|
||||
|
|
|
@ -190,7 +190,6 @@ test_ot_tag_script_indic (void)
|
|||
test_indic_tags ("ory3", "ory2", "orya", HB_SCRIPT_ORIYA);
|
||||
test_indic_tags ("tml3", "tml2", "taml", HB_SCRIPT_TAMIL);
|
||||
test_indic_tags ("tel3", "tel2", "telu", HB_SCRIPT_TELUGU);
|
||||
test_indic_tags ("mym3", "mym2", "mymr", HB_SCRIPT_MYANMAR);
|
||||
}
|
||||
|
||||
|
||||
|
@ -506,6 +505,7 @@ test_ot_tag_full (void)
|
|||
test_tags (HB_SCRIPT_INVALID, "x-hbsc5678-hbot1234", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "5678", "1234");
|
||||
test_tags (HB_SCRIPT_MALAYALAM, "ml", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 3, 2, "mlm3", "mlm2", "mlym", "MAL", "MLR");
|
||||
test_tags (HB_SCRIPT_MALAYALAM, "ml", 1, 1, 1, 1, "mlm3", "MAL");
|
||||
test_tags (HB_SCRIPT_MYANMAR, "und", HB_OT_MAX_TAGS_PER_SCRIPT, 0, 2, 0, "mym2", "mymr");
|
||||
test_tags (HB_SCRIPT_INVALID, "xyz", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "XYZ");
|
||||
test_tags (HB_SCRIPT_INVALID, "xy", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 0);
|
||||
}
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue