8205441: Upgrade to harfbuzz 1.8.1

Reviewed-by: serb
This commit is contained in:
Phil Race 2018-06-21 12:54:30 -07:00
parent a51fe99bfd
commit 1fc2c6f4a8
100 changed files with 4887 additions and 2520 deletions

View File

@ -529,7 +529,7 @@ endif
#### Begin harfbuzz configuration
HARFBUZZ_CFLAGS := -DHAVE_OT -DHAVE_FALLBACK -DHAVE_UCDN
HARFBUZZ_CFLAGS := -DHAVE_OT -DHAVE_FALLBACK -DHAVE_UCDN -DHAVE_ROUND
ifneq ($(OPENJDK_TARGET_OS), windows)
HARFBUZZ_CFLAGS += -DGETPAGESIZE -DHAVE_MPROTECT -DHAVE_PTHREAD \
@ -589,8 +589,6 @@ ifeq ($(TOOLCHAIN_TYPE), gcc)
# Turn off all warnings for sunFont.c. This is needed because the specific warning
# about discarding 'const' qualifier cannot be turned off individually.
BUILD_LIBFONTMANAGER_sunFont.c_CFLAGS := -w
# Turn off aliasing with GCC for ExtensionSubtables.cpp
BUILD_LIBFONTMANAGER_ExtensionSubtables.cpp_CXXFLAGS := -fno-strict-aliasing
endif
# LDFLAGS clarification:
@ -609,7 +607,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER, \
EXTRA_HEADER_DIRS := $(LIBFONTMANAGER_EXTRA_HEADER_DIRS), \
WARNINGS_AS_ERRORS_xlc := false, \
DISABLED_WARNINGS_gcc := sign-compare int-to-pointer-cast \
type-limits missing-field-initializers implicit-fallthrough, \
type-limits missing-field-initializers implicit-fallthrough strict-aliasing, \
DISABLED_WARNINGS_CXX_gcc := reorder delete-non-virtual-dtor strict-overflow \
maybe-uninitialized, \
DISABLED_WARNINGS_clang := unused-value incompatible-pointer-types \

View File

@ -1,4 +1,4 @@
## Harfbuzz v1.7.6
## Harfbuzz v1.8.1
### Harfbuzz License

View File

@ -63,7 +63,6 @@ static inline void _HBMemoryBarrier (void) {
}
typedef LONG hb_atomic_int_impl_t;
#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd (&(AI), (V))
#define hb_atomic_ptr_impl_get(P) (_HBMemoryBarrier (), (void *) *(P))
@ -73,7 +72,6 @@ typedef LONG hb_atomic_int_impl_t;
#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
typedef int hb_atomic_int_impl_t;
#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add (&(AI), (V))
#define hb_atomic_ptr_impl_get(P) (void *) (__sync_synchronize (), *(P))
@ -86,7 +84,6 @@ typedef int hb_atomic_int_impl_t;
#include <mbarrier.h>
typedef unsigned int hb_atomic_int_impl_t;
#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
#define hb_atomic_int_impl_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V))
#define hb_atomic_ptr_impl_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P))
@ -104,7 +101,6 @@ typedef unsigned int hb_atomic_int_impl_t;
typedef int32_t hb_atomic_int_impl_t;
#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
#define hb_atomic_ptr_impl_get(P) (OSMemoryBarrier (), (void *) *(P))
@ -138,7 +134,6 @@ 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_ptr_impl_get(P) (__sync(), (void *) *(P))
@ -149,7 +144,6 @@ typedef int hb_atomic_int_impl_t;
#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
typedef volatile int hb_atomic_int_impl_t;
#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V))
#define hb_atomic_ptr_impl_get(P) ((void *) *(P))
@ -159,7 +153,6 @@ typedef volatile int hb_atomic_int_impl_t;
#else /* HB_NO_MT */
typedef int hb_atomic_int_impl_t;
#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V))
#define hb_atomic_ptr_impl_get(P) ((void *) *(P))
@ -169,7 +162,7 @@ typedef int hb_atomic_int_impl_t;
#endif
#define HB_ATOMIC_INT_INIT(V) {HB_ATOMIC_INT_IMPL_INIT(V)}
#define HB_ATOMIC_INT_INIT(V) {V}
struct hb_atomic_int_t
{

View File

@ -0,0 +1,88 @@
/*
* Copyright © 2009 Red Hat, Inc.
* Copyright © 2018 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
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_BLOB_PRIVATE_HH
#define HB_BLOB_PRIVATE_HH
#include "hb-private.hh"
#include "hb-object-private.hh"
/*
* hb_blob_t
*/
struct hb_blob_t
{
inline void fini_shallow (void)
{
destroy_user_data ();
}
inline void destroy_user_data (void)
{
if (destroy)
{
destroy (user_data);
user_data = nullptr;
destroy = nullptr;
}
}
HB_INTERNAL bool try_make_writable (void);
HB_INTERNAL bool try_make_writable_inplace (void);
HB_INTERNAL bool try_make_writable_inplace_unix (void);
inline void lock (void)
{
hb_blob_make_immutable (this);
}
template <typename Type>
inline const Type* as (void) const
{
return unlikely (!data) ? &Null(Type) : reinterpret_cast<const Type *> (data);
}
public:
hb_object_header_t header;
ASSERT_POD ();
bool immutable;
const char *data;
unsigned int length;
hb_memory_mode_t mode;
void *user_data;
hb_destroy_func_t destroy;
};
#endif /* HB_BLOB_PRIVATE_HH */

View File

@ -1,5 +1,6 @@
/*
* Copyright © 2009 Red Hat, Inc.
* Copyright © 2018 Ebrahim Byagowi
*
* This is part of HarfBuzz, a text shaping library.
*
@ -31,8 +32,7 @@
#include "hb-private.hh"
#include "hb-debug.hh"
#include "hb-object-private.hh"
#include "hb-blob-private.hh"
#ifdef HAVE_SYS_MMAN_H
#ifdef HAVE_UNISTD_H
@ -43,35 +43,9 @@
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
struct hb_blob_t {
hb_object_header_t header;
ASSERT_POD ();
bool immutable;
const char *data;
unsigned int length;
hb_memory_mode_t mode;
void *user_data;
hb_destroy_func_t destroy;
};
static bool _try_writable (hb_blob_t *blob);
static void
_hb_blob_destroy_user_data (hb_blob_t *blob)
{
if (blob->destroy) {
blob->destroy (blob->user_data);
blob->user_data = nullptr;
blob->destroy = nullptr;
}
}
/**
* hb_blob_create: (skip)
* @data: Pointer to blob data.
@ -114,7 +88,7 @@ hb_blob_create (const char *data,
if (blob->mode == HB_MEMORY_MODE_DUPLICATE) {
blob->mode = HB_MEMORY_MODE_READONLY;
if (!_try_writable (blob)) {
if (!blob->try_make_writable ()) {
hb_blob_destroy (blob);
return hb_blob_get_empty ();
}
@ -260,7 +234,7 @@ hb_blob_destroy (hb_blob_t *blob)
{
if (!hb_object_destroy (blob)) return;
_hb_blob_destroy_user_data (blob);
blob->fini_shallow ();
free (blob);
}
@ -395,7 +369,7 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length)
char *
hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length)
{
if (!_try_writable (blob)) {
if (!blob->try_make_writable ()) {
if (length)
*length = 0;
@ -409,8 +383,8 @@ hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length)
}
static hb_bool_t
_try_make_writable_inplace_unix (hb_blob_t *blob)
bool
hb_blob_t::try_make_writable_inplace_unix (void)
{
#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT)
uintptr_t pagesize = -1, mask, length;
@ -425,25 +399,25 @@ _try_make_writable_inplace_unix (hb_blob_t *blob)
#endif
if ((uintptr_t) -1L == pagesize) {
DEBUG_MSG_FUNC (BLOB, blob, "failed to get pagesize: %s", strerror (errno));
DEBUG_MSG_FUNC (BLOB, this, "failed to get pagesize: %s", strerror (errno));
return false;
}
DEBUG_MSG_FUNC (BLOB, blob, "pagesize is %lu", (unsigned long) pagesize);
DEBUG_MSG_FUNC (BLOB, this, "pagesize is %lu", (unsigned long) pagesize);
mask = ~(pagesize-1);
addr = (const char *) (((uintptr_t) blob->data) & mask);
length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask) - addr;
DEBUG_MSG_FUNC (BLOB, blob,
addr = (const char *) (((uintptr_t) this->data) & mask);
length = (const char *) (((uintptr_t) this->data + this->length + pagesize-1) & mask) - addr;
DEBUG_MSG_FUNC (BLOB, this,
"calling mprotect on [%p..%p] (%lu bytes)",
addr, addr+length, (unsigned long) length);
if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) {
DEBUG_MSG_FUNC (BLOB, blob, "mprotect failed: %s", strerror (errno));
DEBUG_MSG_FUNC (BLOB, this, "mprotect failed: %s", strerror (errno));
return false;
}
blob->mode = HB_MEMORY_MODE_WRITABLE;
this->mode = HB_MEMORY_MODE_WRITABLE;
DEBUG_MSG_FUNC (BLOB, blob,
DEBUG_MSG_FUNC (BLOB, this,
"successfully made [%p..%p] (%lu bytes) writable\n",
addr, addr+length, (unsigned long) length);
return true;
@ -452,53 +426,185 @@ _try_make_writable_inplace_unix (hb_blob_t *blob)
#endif
}
static bool
_try_writable_inplace (hb_blob_t *blob)
bool
hb_blob_t::try_make_writable_inplace (void)
{
DEBUG_MSG_FUNC (BLOB, blob, "making writable inplace\n");
DEBUG_MSG_FUNC (BLOB, this, "making writable inplace\n");
if (_try_make_writable_inplace_unix (blob))
if (this->try_make_writable_inplace_unix ())
return true;
DEBUG_MSG_FUNC (BLOB, blob, "making writable -> FAILED\n");
DEBUG_MSG_FUNC (BLOB, this, "making writable -> FAILED\n");
/* Failed to make writable inplace, mark that */
blob->mode = HB_MEMORY_MODE_READONLY;
this->mode = HB_MEMORY_MODE_READONLY;
return false;
}
static bool
_try_writable (hb_blob_t *blob)
bool
hb_blob_t::try_make_writable (void)
{
if (blob->immutable)
if (this->immutable)
return false;
if (blob->mode == HB_MEMORY_MODE_WRITABLE)
if (this->mode == HB_MEMORY_MODE_WRITABLE)
return true;
if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE && _try_writable_inplace (blob))
if (this->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE && this->try_make_writable_inplace ())
return true;
if (blob->mode == HB_MEMORY_MODE_WRITABLE)
if (this->mode == HB_MEMORY_MODE_WRITABLE)
return true;
DEBUG_MSG_FUNC (BLOB, blob, "current data is -> %p\n", blob->data);
DEBUG_MSG_FUNC (BLOB, this, "current data is -> %p\n", this->data);
char *new_data;
new_data = (char *) malloc (blob->length);
new_data = (char *) malloc (this->length);
if (unlikely (!new_data))
return false;
DEBUG_MSG_FUNC (BLOB, blob, "dupped successfully -> %p\n", blob->data);
DEBUG_MSG_FUNC (BLOB, this, "dupped successfully -> %p\n", this->data);
memcpy (new_data, blob->data, blob->length);
_hb_blob_destroy_user_data (blob);
blob->mode = HB_MEMORY_MODE_WRITABLE;
blob->data = new_data;
blob->user_data = new_data;
blob->destroy = free;
memcpy (new_data, this->data, this->length);
this->destroy_user_data ();
this->mode = HB_MEMORY_MODE_WRITABLE;
this->data = new_data;
this->user_data = new_data;
this->destroy = free;
return true;
}
/*
* Mmap
*/
#ifdef HAVE_MMAP
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
#endif
#if defined(_WIN32) || defined(__CYGWIN__)
# include <windows.h>
#endif
#ifndef _O_BINARY
# define _O_BINARY 0
#endif
#ifndef MAP_NORESERVE
# define MAP_NORESERVE 0
#endif
struct hb_mapped_file_t
{
char *contents;
unsigned long length;
#if defined(_WIN32) || defined(__CYGWIN__)
HANDLE mapping;
#endif
};
static void
_hb_mapped_file_destroy (hb_mapped_file_t *file)
{
#ifdef HAVE_MMAP
munmap (file->contents, file->length);
#elif defined(_WIN32) || defined(__CYGWIN__)
UnmapViewOfFile (file->contents);
CloseHandle (file->mapping);
#else
free (file->contents);
#endif
free (file);
}
/**
* hb_blob_create_from_file:
* @file_name: font filename.
*
* Returns: A hb_blob_t pointer with the content of the file
*
* Since: 1.7.7
**/
hb_blob_t *
hb_blob_create_from_file (const char *file_name)
{
// Adopted from glib's gmappedfile.c with Matthias Clasen and
// Allison Lortie permission but changed a lot to suit our need.
bool writable = false;
hb_memory_mode_t mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
if (unlikely (!file)) return hb_blob_get_empty ();
#ifdef HAVE_MMAP
int fd = open (file_name, (writable ? O_RDWR : O_RDONLY) | _O_BINARY, 0);
# define CLOSE close
if (unlikely (fd == -1)) goto fail_without_close;
struct stat st;
if (unlikely (fstat (fd, &st) == -1)) goto fail;
// See https://github.com/GNOME/glib/blob/f9faac7/glib/gmappedfile.c#L139-L142
if (unlikely (st.st_size == 0 && S_ISREG (st.st_mode))) goto fail;
file->length = (unsigned long) st.st_size;
file->contents = (char *) mmap (nullptr, file->length,
writable ? PROT_READ|PROT_WRITE : PROT_READ,
MAP_PRIVATE | MAP_NORESERVE, fd, 0);
if (unlikely (file->contents == MAP_FAILED)) goto fail;
#elif defined(_WIN32) || defined(__CYGWIN__)
HANDLE fd = CreateFile (file_name,
writable ? GENERIC_READ|GENERIC_WRITE : GENERIC_READ,
FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, nullptr);
# define CLOSE CloseHandle
if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close;
file->length = (unsigned long) GetFileSize (fd, nullptr);
file->mapping = CreateFileMapping (fd, nullptr,
writable ? PAGE_WRITECOPY : PAGE_READONLY,
0, 0, nullptr);
if (unlikely (file->mapping == nullptr)) goto fail;
file->contents = (char *) MapViewOfFile (file->mapping,
writable ? FILE_MAP_COPY : FILE_MAP_READ,
0, 0, 0);
if (unlikely (file->contents == nullptr)) goto fail;
#else
mm = HB_MEMORY_MODE_WRITABLE;
FILE *fd = fopen (file_name, "rb");
# define CLOSE fclose
if (unlikely (!fd)) goto fail_without_close;
fseek (fd, 0, SEEK_END);
file->length = ftell (fd);
rewind (fd);
file->contents = (char *) malloc (file->length);
if (unlikely (!file->contents)) goto fail;
if (unlikely (fread (file->contents, 1, file->length, fd) != file->length))
goto fail;
#endif
CLOSE (fd);
return hb_blob_create (file->contents, file->length, mm, (void *) file,
(hb_destroy_func_t) _hb_mapped_file_destroy);
fail:
CLOSE (fd);
#undef CLOSE
fail_without_close:
free (file);
return hb_blob_get_empty ();
}

View File

@ -123,6 +123,8 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length);
HB_EXTERN char *
hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length);
HB_EXTERN hb_blob_t *
hb_blob_create_from_file (const char *file_name);
HB_END_DECLS

View File

@ -503,7 +503,7 @@ _resume:
#line 43 "hb-buffer-deserialize-json.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -554,7 +554,7 @@ _resume:
#line 43 "hb-buffer-deserialize-json.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -566,7 +566,7 @@ _resume:
#line 43 "hb-buffer-deserialize-json.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -578,7 +578,7 @@ _resume:
#line 43 "hb-buffer-deserialize-json.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -590,7 +590,7 @@ _resume:
#line 43 "hb-buffer-deserialize-json.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -602,7 +602,7 @@ _resume:
#line 43 "hb-buffer-deserialize-json.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -614,7 +614,7 @@ _resume:
#line 43 "hb-buffer-deserialize-json.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;

View File

@ -422,7 +422,7 @@ _resume:
#line 43 "hb-buffer-deserialize-text.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -434,7 +434,7 @@ _resume:
#line 43 "hb-buffer-deserialize-text.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -446,7 +446,7 @@ _resume:
#line 43 "hb-buffer-deserialize-text.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -458,7 +458,7 @@ _resume:
#line 43 "hb-buffer-deserialize-text.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -470,7 +470,7 @@ _resume:
#line 43 "hb-buffer-deserialize-text.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -499,7 +499,7 @@ _again:
#line 43 "hb-buffer-deserialize-text.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -511,7 +511,7 @@ _again:
#line 43 "hb-buffer-deserialize-text.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -523,7 +523,7 @@ _again:
#line 43 "hb-buffer-deserialize-text.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -535,7 +535,7 @@ _again:
#line 43 "hb-buffer-deserialize-text.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
@ -547,7 +547,7 @@ _again:
#line 43 "hb-buffer-deserialize-text.rl"
{
buffer->add_info (info);
if (buffer->in_error)
if (unlikely (!buffer->successful))
return false;
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;

View File

@ -101,7 +101,7 @@ struct hb_buffer_t {
hb_buffer_content_type_t content_type;
hb_segment_properties_t props; /* Script, language, direction */
bool in_error; /* Allocation failed */
bool successful; /* Allocations successful */
bool have_output; /* Whether we have an output buffer going on */
bool have_positions; /* Whether we have positions */

View File

@ -111,11 +111,11 @@ hb_segment_properties_hash (const hb_segment_properties_t *p)
bool
hb_buffer_t::enlarge (unsigned int size)
{
if (unlikely (in_error))
if (unlikely (!successful))
return false;
if (unlikely (size > max_len))
{
in_error = true;
successful = false;
return false;
}
@ -139,7 +139,7 @@ hb_buffer_t::enlarge (unsigned int size)
done:
if (unlikely (!new_pos || !new_info))
in_error = true;
successful = false;
if (likely (new_pos))
pos = new_pos;
@ -148,10 +148,10 @@ done:
info = new_info;
out_info = separate_out ? (hb_glyph_info_t *) pos : info;
if (likely (!in_error))
if (likely (successful))
allocated = new_allocated;
return likely (!in_error);
return likely (successful);
}
bool
@ -234,7 +234,7 @@ hb_buffer_t::clear (void)
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
in_error = false;
successful = true;
have_output = false;
have_positions = false;
@ -324,7 +324,7 @@ hb_buffer_t::clear_positions (void)
void
hb_buffer_t::swap_buffers (void)
{
if (unlikely (in_error)) return;
if (unlikely (!successful)) return;
assert (have_output);
have_output = false;
@ -409,7 +409,7 @@ hb_buffer_t::move_to (unsigned int i)
idx = i;
return true;
}
if (unlikely (in_error))
if (unlikely (!successful))
return false;
assert (i <= out_len + (len - idx));
@ -687,6 +687,8 @@ hb_buffer_t::guess_segment_properties (void)
/* If direction is set to INVALID, guess from script */
if (props.direction == HB_DIRECTION_INVALID) {
props.direction = hb_script_get_horizontal_direction (props.script);
if (props.direction == HB_DIRECTION_INVALID)
props.direction = HB_DIRECTION_LTR;
}
/* If language is not set, use default language from locale */
@ -754,7 +756,7 @@ hb_buffer_get_empty (void)
HB_BUFFER_CONTENT_TYPE_INVALID,
HB_SEGMENT_PROPERTIES_DEFAULT,
true, /* in_error */
false, /* successful */
true, /* have_output */
true /* have_positions */
@ -1269,7 +1271,7 @@ hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
hb_bool_t
hb_buffer_allocation_successful (hb_buffer_t *buffer)
{
return !buffer->in_error;
return buffer->successful;
}
/**
@ -1489,6 +1491,8 @@ hb_buffer_reverse_clusters (hb_buffer_t *buffer)
* Next, if buffer direction is not set (ie. is %HB_DIRECTION_INVALID),
* it will be set to the natural horizontal direction of the
* buffer script as returned by hb_script_get_horizontal_direction().
* If hb_script_get_horizontal_direction() returns %HB_DIRECTION_INVALID,
* then %HB_DIRECTION_LTR is used.
*
* Finally, if buffer language is not set (ie. is %HB_LANGUAGE_INVALID),
* it will be set to the process's default language as returned by
@ -1750,13 +1754,13 @@ hb_buffer_append (hb_buffer_t *buffer,
if (buffer->len + (end - start) < buffer->len) /* Overflows. */
{
buffer->in_error = true;
buffer->successful = false;
return;
}
unsigned int orig_len = buffer->len;
hb_buffer_set_length (buffer, buffer->len + (end - start));
if (buffer->in_error)
if (unlikely (!buffer->successful))
return;
memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));

View File

@ -225,7 +225,7 @@ struct hb_language_item_t {
inline hb_language_item_t & operator = (const char *s) {
/* If a custom allocated is used calling strdup() pairs
badly with a call to the custom free() in finish() below.
badly with a call to the custom free() in fini() below.
Therefore don't call strdup(), implement its behavior.
*/
size_t len = strlen(s) + 1;
@ -240,7 +240,7 @@ struct hb_language_item_t {
return *this;
}
void finish (void) { free ((void *) lang); }
void fini (void) { free ((void *) lang); }
};
@ -252,11 +252,16 @@ static hb_language_item_t *langs;
static void
free_langs (void)
{
while (langs) {
hb_language_item_t *next = langs->next;
langs->finish ();
free (langs);
langs = next;
retry:
hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs);
if (!hb_atomic_ptr_cmpexch (&langs, first_lang, nullptr))
goto retry;
while (first_lang) {
hb_language_item_t *next = first_lang->next;
first_lang->fini ();
free (first_lang);
first_lang = next;
}
}
#endif
@ -284,7 +289,7 @@ retry:
}
if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
lang->finish ();
lang->fini ();
free (lang);
goto retry;
}
@ -407,7 +412,7 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
case HB_TAG('Q','a','a','i'): return HB_SCRIPT_INHERITED;
case HB_TAG('Q','a','a','c'): return HB_SCRIPT_COPTIC;
/* Script variants from http://unicode.org/iso15924/ */
/* Script variants from https://unicode.org/iso15924/ */
case HB_TAG('C','y','r','s'): return HB_SCRIPT_CYRILLIC;
case HB_TAG('L','a','t','f'): return HB_SCRIPT_LATIN;
case HB_TAG('L','a','t','g'): return HB_SCRIPT_LATIN;
@ -475,7 +480,7 @@ hb_script_to_iso15924_tag (hb_script_t script)
hb_direction_t
hb_script_get_horizontal_direction (hb_script_t script)
{
/* http://goo.gl/x9ilM */
/* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */
switch ((hb_tag_t) script)
{
/* Unicode-1.1 additions */
@ -530,7 +535,18 @@ hb_script_get_horizontal_direction (hb_script_t script)
/* Unicode-9.0 additions */
case HB_SCRIPT_ADLAM:
/* Unicode-11.0 additions */
case HB_SCRIPT_HANIFI_ROHINGYA:
case HB_SCRIPT_OLD_SOGDIAN:
case HB_SCRIPT_SOGDIAN:
return HB_DIRECTION_RTL;
/* https://github.com/harfbuzz/harfbuzz/issues/1000 */
case HB_SCRIPT_OLD_ITALIC:
return HB_DIRECTION_INVALID;
}
return HB_DIRECTION_LTR;
@ -719,8 +735,14 @@ static HB_LOCALE_T C_locale;
static void
free_C_locale (void)
{
if (C_locale)
HB_FREE_LOCALE (C_locale);
retry:
HB_LOCALE_T locale = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale);
if (!hb_atomic_ptr_cmpexch (&C_locale, locale, nullptr))
goto retry;
if (locale)
HB_FREE_LOCALE (locale);
}
#endif

View File

@ -49,6 +49,16 @@
# include <inttypes.h>
#elif defined (_AIX)
# include <sys/inttypes.h>
#elif defined (_MSC_VER) && _MSC_VER < 1600
/* VS 2010 (_MSC_VER 1600) has stdint.h */
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
# include <stdint.h>
#endif
@ -142,8 +152,8 @@ hb_language_get_default (void);
/* hb_script_t */
/* http://unicode.org/iso15924/ */
/* http://goo.gl/x9ilM */
/* https://unicode.org/iso15924/ */
/* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */
/* Unicode Character Database property: Script (sc) */
typedef enum
{
@ -315,6 +325,17 @@ typedef enum
/*10.0*/HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'),
/*10.0*/HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'),
/*
* Since 1.8.0
*/
/*11.0*/HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'),
/*11.0*/HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'),
/*11.0*/HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'),
/*11.0*/HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'),
/*11.0*/HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'),
/*11.0*/HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'),
/*11.0*/HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'),
/* No script set. */
HB_SCRIPT_INVALID = HB_TAG_NONE,
@ -323,7 +344,7 @@ typedef enum
* since technically enums are int, and indeed, hb_script_t ends up being signed.
* See this thread for technicalities:
*
* http://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html
* https://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html
*/
_HB_SCRIPT_MAX_VALUE = HB_TAG_MAX, /*< skip >*/
_HB_SCRIPT_MAX_VALUE_SIGNED = HB_TAG_MAX_SIGNED /*< skip >*/

View File

@ -168,6 +168,10 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
if (CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSText")) ||
CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSDisplay")))
{
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
# define kCTFontUIFontSystem kCTFontSystemFontType
# define kCTFontUIFontEmphasizedSystem kCTFontEmphasizedSystemFontType
#endif
CTFontUIFontType font_type = kCTFontUIFontSystem;
if (CFStringHasSuffix (cg_postscript_name, CFSTR ("-Bold")))
font_type = kCTFontUIFontEmphasizedSystem;
@ -206,7 +210,18 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
return ct_font;
}
CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttribute);
CFURLRef original_url = nullptr;
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
ATSFontRef atsFont;
FSRef fsref;
OSStatus status;
atsFont = CTFontGetPlatformFont (ct_font, NULL);
status = ATSFontGetFileReference (atsFont, &fsref);
if (status == noErr)
original_url = CFURLCreateFromFSRef (NULL, &fsref);
#else
original_url = (CFURLRef) CTFontCopyAttribute (ct_font, kCTFontURLAttribute);
#endif
/* Create font copy with cascade list that has LastResort first; this speeds up CoreText
* font fallback which we don't need anyway. */
@ -225,7 +240,15 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
* system locations that we cannot access from the sandboxed renderer
* process in Blink. This can be detected by the new file URL location
* that the newly found font points to. */
CFURLRef new_url = (CFURLRef) CTFontCopyAttribute (new_ct_font, kCTFontURLAttribute);
CFURLRef new_url = nullptr;
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
atsFont = CTFontGetPlatformFont (new_ct_font, NULL);
status = ATSFontGetFileReference (atsFont, &fsref);
if (status == noErr)
new_url = CFURLCreateFromFSRef (NULL, &fsref);
#else
new_url = (CFURLRef) CTFontCopyAttribute (new_ct_font, kCTFontURLAttribute);
#endif
// Keep reconfigured font if URL cannot be retrieved (seems to be the case
// on Mac OS 10.12 Sierra), speculative fix for crbug.com/625606
if (!original_url || !new_url || CFEqual (original_url, new_url)) {
@ -618,8 +641,8 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
buffer->merge_clusters (i - 1, i + 1);
}
hb_auto_array_t<feature_record_t> feature_records;
hb_auto_array_t<range_record_t> range_records;
hb_auto_t<hb_vector_t<feature_record_t> > feature_records;
hb_auto_t<hb_vector_t<range_record_t> > range_records;
/*
* Set up features.
@ -628,7 +651,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
if (num_features)
{
/* Sort features by start/end events. */
hb_auto_array_t<feature_event_t> feature_events;
hb_auto_t<hb_vector_t<feature_event_t> > feature_events;
for (unsigned int i = 0; i < num_features; i++)
{
const feature_mapping_t * mapping = (const feature_mapping_t *) bsearch (&features[i].tag,
@ -647,15 +670,11 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
feature_event_t *event;
event = feature_events.push ();
if (unlikely (!event))
goto fail_features;
event->index = features[i].start;
event->start = true;
event->feature = feature;
event = feature_events.push ();
if (unlikely (!event))
goto fail_features;
event->index = features[i].end;
event->start = false;
event->feature = feature;
@ -669,15 +688,13 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
feature.order = num_features + 1;
feature_event_t *event = feature_events.push ();
if (unlikely (!event))
goto fail_features;
event->index = 0; /* This value does magic. */
event->start = false;
event->feature = feature;
}
/* Scan events and save features for each range. */
hb_auto_array_t<active_feature_t> active_features;
hb_auto_t<hb_vector_t<active_feature_t> > active_features;
unsigned int last_index = 0;
for (unsigned int i = 0; i < feature_events.len; i++)
{
@ -687,8 +704,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
{
/* Save a snapshot of active features and the range. */
range_record_t *range = range_records.push ();
if (unlikely (!range))
goto fail_features;
if (active_features.len)
{
@ -746,23 +761,16 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
last_index = event->index;
}
if (event->start) {
active_feature_t *feature = active_features.push ();
if (unlikely (!feature))
goto fail_features;
*feature = event->feature;
if (event->start)
{
active_features.push (event->feature);
} else {
active_feature_t *feature = active_features.find (&event->feature);
if (feature)
active_features.remove (feature - active_features.array);
active_features.remove (feature - active_features.arrayZ);
}
}
}
else
{
fail_features:
num_features = 0;
}
unsigned int scratch_size;
hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
@ -944,6 +952,9 @@ resize_and_retry:
int level = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
CFNumberRef level_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &level);
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
extern const CFStringRef kCTTypesetterOptionForcedEmbeddingLevel;
#endif
CFDictionaryRef options = CFDictionaryCreate (kCFAllocatorDefault,
(const void **) &kCTTypesetterOptionForcedEmbeddingLevel,
(const void **) &level_number,
@ -979,7 +990,7 @@ resize_and_retry:
/* For right-to-left runs, CoreText returns the glyphs positioned such that
* any trailing whitespace is to the left of (0,0). Adjust coordinate system
* to fix for that. Test with any RTL string with trailing spaces.
* https://code.google.com/p/chromium/issues/detail?id=469028
* https://crbug.com/469028
*/
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
{
@ -1032,7 +1043,7 @@ resize_and_retry:
* However, even that wouldn't work if we were passed in the CGFont to
* construct a hb_face to begin with.
*
* See: http://github.com/harfbuzz/harfbuzz/pull/36
* See: https://github.com/harfbuzz/harfbuzz/pull/36
*
* Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
*/
@ -1222,7 +1233,7 @@ resize_and_retry:
* directions. As such, disable the assert... It wouldn't crash, but
* cursoring will be off...
*
* http://crbug.com/419769
* https://crbug.com/419769
*/
if (0)
{

View File

@ -49,7 +49,7 @@ hb_bsearch_r (const void *key, const void *base,
else
return (void *) p;
}
return NULL;
return nullptr;
}

View File

@ -29,11 +29,35 @@
#include "hb-private.hh"
#include "hb-face-private.hh"
#include "hb-blob-private.hh"
#include "hb-open-file-private.hh"
#include "hb-ot-head-table.hh"
#include "hb-ot-maxp-table.hh"
/**
* hb_face_count: Get number of faces on the blob
* @blob:
*
*
*
* Return value: Number of faces on the blob
*
* Since: 1.7.7
**/
unsigned int
hb_face_count (hb_blob_t *blob)
{
if (unlikely (!blob))
return 0;
hb_blob_t *sanitized = OT::Sanitizer<OT::OpenTypeFontFile> ().sanitize (blob);
const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
return ot.get_face_count ();
}
/*
* hb_face_t
*/
@ -134,7 +158,7 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
if (tag == HB_TAG_NONE)
return hb_blob_reference (data->blob);
const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob);
const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
@ -425,7 +449,7 @@ void
hb_face_t::load_upem (void) const
{
hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (reference_table (HB_OT_TAG_head));
const OT::head *head_table = OT::Sanitizer<OT::head>::lock_instance (head_blob);
const OT::head *head_table = head_blob->as<OT::head> ();
upem = head_table->get_upem ();
hb_blob_destroy (head_blob);
}
@ -469,7 +493,7 @@ void
hb_face_t::load_num_glyphs (void) const
{
hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (reference_table (HB_OT_TAG_maxp));
const OT::maxp *maxp_table = OT::Sanitizer<OT::maxp>::lock_instance (maxp_blob);
const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
num_glyphs = maxp_table->get_num_glyphs ();
hb_blob_destroy (maxp_blob);
}
@ -499,7 +523,7 @@ hb_face_get_table_tags (hb_face_t *face,
hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob);
const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
return ot_face.get_table_tags (start_offset, table_count, table_tags);

View File

@ -37,6 +37,10 @@
HB_BEGIN_DECLS
HB_EXTERN unsigned int
hb_face_count (hb_blob_t *blob);
/*
* hb_face_t
*/

View File

@ -83,7 +83,11 @@ struct hb_font_funcs_t {
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
} f;
void (*array[VAR]) (void);
void (*array[0
#define HB_FONT_FUNC_IMPLEMENT(name) +1
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
]) (void);
} get;
};

View File

@ -127,7 +127,7 @@ hb_font_get_variation_glyph_parent (hb_font_t *font,
static hb_position_t
hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
hb_font_get_glyph_h_advance_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)
@ -144,7 +144,7 @@ hb_font_get_glyph_h_advance_parent (hb_font_t *font,
}
static hb_position_t
hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
hb_font_get_glyph_v_advance_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)

View File

@ -119,7 +119,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
if (font->immutable)
return;
if (font->destroy != _hb_ft_font_destroy)
if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
return;
hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
@ -139,7 +139,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
int
hb_ft_font_get_load_flags (hb_font_t *font)
{
if (font->destroy != _hb_ft_font_destroy)
if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
return 0;
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
@ -150,7 +150,7 @@ hb_ft_font_get_load_flags (hb_font_t *font)
FT_Face
hb_ft_font_get_face (hb_font_t *font)
{
if (font->destroy != _hb_ft_font_destroy)
if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
return nullptr;
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
@ -177,7 +177,7 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
/* For symbol-encoded OpenType fonts, we duplicate the
* U+F000..F0FF range at U+0000..U+00FF. That's what
* Windows seems to do, and that's hinted about at:
* http://www.microsoft.com/typography/otspec/recom.htm
* https://docs.microsoft.com/en-us/typography/opentype/spec/recom
* under "Non-Standard (Symbol) Fonts". */
g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode);
if (!g)
@ -210,7 +210,7 @@ hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
}
static hb_position_t
hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
hb_ft_get_glyph_h_advance (hb_font_t *font,
void *font_data,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)
@ -228,7 +228,7 @@ hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
}
static hb_position_t
hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
hb_ft_get_glyph_v_advance (hb_font_t *font,
void *font_data,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)
@ -248,7 +248,7 @@ hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
}
static hb_bool_t
hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
hb_ft_get_glyph_v_origin (hb_font_t *font,
void *font_data,
hb_codepoint_t glyph,
hb_position_t *x,
@ -292,7 +292,7 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
}
static hb_bool_t
hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
hb_ft_get_glyph_extents (hb_font_t *font,
void *font_data,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents,
@ -423,7 +423,12 @@ static hb_font_funcs_t *static_ft_funcs = nullptr;
static
void free_static_ft_funcs (void)
{
hb_font_funcs_destroy (static_ft_funcs);
retry:
hb_font_funcs_t *ft_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, ft_funcs, nullptr))
goto retry;
hb_font_funcs_destroy (ft_funcs);
}
#endif
@ -610,7 +615,7 @@ hb_ft_font_create (FT_Face ft_face,
void
hb_ft_font_changed (hb_font_t *font)
{
if (font->destroy != _hb_ft_font_destroy)
if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
return;
hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
@ -685,7 +690,12 @@ static FT_Library ft_library;
static
void free_ft_library (void)
{
FT_Done_FreeType (ft_library);
retry:
FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library);
if (!hb_atomic_ptr_cmpexch (&ft_library, library, nullptr))
goto retry;
FT_Done_FreeType (library);
}
#endif

View File

@ -0,0 +1,255 @@
/*
* Copyright © 2018 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_MAP_PRIVATE_HH
#define HB_MAP_PRIVATE_HH
#include "hb-private.hh"
#include "hb-object-private.hh"
template <typename T>
inline uint32_t Hash (const T &v)
{
/* Knuth's multiplicative method: */
return (uint32_t) v * 2654435761u;
}
/*
* hb_map_t
*/
struct hb_map_t
{
struct item_t
{
hb_codepoint_t key;
hb_codepoint_t value;
inline bool is_unused (void) const { return key == INVALID; }
inline bool is_tombstone (void) const { return key != INVALID && value == INVALID; }
};
hb_object_header_t header;
bool successful; /* Allocations successful */
unsigned int population; /* Not including tombstones. */
unsigned int occupancy; /* Including tombstones. */
unsigned int mask;
unsigned int prime;
item_t *items;
inline void init_shallow (void)
{
successful = true;
population = occupancy = 0;
mask = 0;
prime = 0;
items = nullptr;
}
inline void init (void)
{
hb_object_init (this);
init_shallow ();
}
inline void fini_shallow (void)
{
free (items);
}
inline void fini (void)
{
hb_object_fini (this);
fini_shallow ();
}
inline bool resize (void)
{
if (unlikely (!successful)) return false;
unsigned int power = _hb_bit_storage (population * 2 + 8);
unsigned int new_size = 1u << power;
item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t));
if (unlikely (!new_items))
{
successful = false;
return false;
}
memset (new_items, 0xFF, (size_t) new_size * sizeof (item_t));
unsigned int old_size = mask + 1;
item_t *old_items = items;
/* Switch to new, empty, array. */
population = occupancy = 0;
mask = new_size - 1;
prime = prime_for (power);
items = new_items;
/* Insert back old items. */
if (old_items)
for (unsigned int i = 0; i < old_size; i++)
if (old_items[i].key != INVALID && old_items[i].value != INVALID)
set (old_items[i].key, old_items[i].value);
free (old_items);
return true;
}
inline void set (hb_codepoint_t key, hb_codepoint_t value)
{
if (unlikely (!successful)) return;
if (unlikely (key == INVALID)) return;
if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
unsigned int i = bucket_for (key);
if (value == INVALID && items[i].key != key)
return; /* Trying to delete non-existent key. */
if (!items[i].is_unused ())
{
occupancy--;
if (items[i].is_tombstone ())
population--;
}
items[i].key = key;
items[i].value = value;
occupancy++;
if (!items[i].is_tombstone ())
population++;
}
inline hb_codepoint_t get (hb_codepoint_t key) const
{
if (unlikely (!items)) return INVALID;
unsigned int i = bucket_for (key);
return items[i].key == key ? items[i].value : INVALID;
}
inline void del (hb_codepoint_t key)
{
set (key, INVALID);
}
inline bool has (hb_codepoint_t key) const
{
return get (key) != INVALID;
}
inline hb_codepoint_t operator [] (unsigned int key) const
{ return get (key); }
static const hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID;
inline void clear (void)
{
memset (items, 0xFF, ((size_t) mask + 1) * sizeof (item_t));
population = occupancy = 0;
}
inline bool is_empty (void) const
{
return population != 0;
}
inline unsigned int get_population () const
{
return population;
}
protected:
inline unsigned int bucket_for (hb_codepoint_t key) const
{
unsigned int i = Hash (key) % prime;
unsigned int step = 0;
unsigned int tombstone = INVALID;
while (!items[i].is_unused ())
{
if (items[i].key == key)
return i;
if (tombstone == INVALID && items[i].is_tombstone ())
tombstone = i;
i = (i + ++step) & mask;
}
return tombstone == INVALID ? i : tombstone;
}
static inline unsigned int prime_for (unsigned int shift)
{
/* Following comment and table copied from glib. */
/* Each table size has an associated prime modulo (the first prime
* lower than the table size) used to find the initial bucket. Probing
* then works modulo 2^n. The prime modulo is necessary to get a
* good distribution with poor hash functions.
*/
/* Not declaring static to make all kinds of compilers happy... */
/*static*/ const unsigned int prime_mod [32] =
{
1, /* For 1 << 0 */
2,
3,
7,
13,
31,
61,
127,
251,
509,
1021,
2039,
4093,
8191,
16381,
32749,
65521, /* For 1 << 16 */
131071,
262139,
524287,
1048573,
2097143,
4194301,
8388593,
16777213,
33554393,
67108859,
134217689,
268435399,
536870909,
1073741789,
2147483647 /* For 1 << 31 */
};
if (unlikely (shift >= ARRAY_LENGTH (prime_mod)))
return prime_mod[ARRAY_LENGTH (prime_mod) - 1];
return prime_mod[shift];
}
};
#endif /* HB_MAP_PRIVATE_HH */

View File

@ -0,0 +1,261 @@
/*
* Copyright © 2018 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-map-private.hh"
/* Public API */
/**
* hb_map_create: (Xconstructor)
*
* Return value: (transfer full):
*
* Since: 1.7.7
**/
hb_map_t *
hb_map_create (void)
{
hb_map_t *map;
if (!(map = hb_object_create<hb_map_t> ()))
return hb_map_get_empty ();
map->init_shallow ();
return map;
}
/**
* hb_map_get_empty:
*
* Return value: (transfer full):
*
* Since: 1.7.7
**/
hb_map_t *
hb_map_get_empty (void)
{
return const_cast<hb_map_t *> (&Null(hb_map_t));
}
/**
* hb_map_reference: (skip)
* @map: a map.
*
* Return value: (transfer full):
*
* Since: 1.7.7
**/
hb_map_t *
hb_map_reference (hb_map_t *map)
{
return hb_object_reference (map);
}
/**
* hb_map_destroy: (skip)
* @map: a map.
*
* Since: 1.7.7
**/
void
hb_map_destroy (hb_map_t *map)
{
if (!hb_object_destroy (map)) return;
map->fini_shallow ();
free (map);
}
/**
* hb_map_set_user_data: (skip)
* @map: a map.
* @key:
* @data:
* @destroy:
* @replace:
*
* Return value:
*
* Since: 1.7.7
**/
hb_bool_t
hb_map_set_user_data (hb_map_t *map,
hb_user_data_key_t *key,
void * data,
hb_destroy_func_t destroy,
hb_bool_t replace)
{
return hb_object_set_user_data (map, key, data, destroy, replace);
}
/**
* hb_map_get_user_data: (skip)
* @map: a map.
* @key:
*
* Return value: (transfer none):
*
* Since: 1.7.7
**/
void *
hb_map_get_user_data (hb_map_t *map,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (map, key);
}
/**
* hb_map_allocation_successful:
* @map: a map.
*
*
*
* Return value:
*
* Since: 1.7.7
**/
hb_bool_t
hb_map_allocation_successful (const hb_map_t *map)
{
return map->successful;
}
/**
* hb_map_set:
* @map: a map.
* @key:
* @value:
*
*
*
* Return value:
*
* Since: 1.7.7
**/
void
hb_map_set (hb_map_t *map,
hb_codepoint_t key,
hb_codepoint_t value)
{
map->set (key, value);
}
/**
* hb_map_get:
* @map: a map.
* @key:
*
*
*
* Since: 1.7.7
**/
hb_codepoint_t
hb_map_get (const hb_map_t *map,
hb_codepoint_t key)
{
return map->get (key);
}
/**
* hb_map_del:
* @map: a map.
* @codepoint:
*
*
*
* Since: 1.7.7
**/
void
hb_map_del (hb_map_t *map,
hb_codepoint_t key)
{
map->del (key);
}
/**
* hb_map_has:
* @map: a map.
* @codepoint:
*
*
*
* Since: 1.7.7
**/
hb_bool_t
hb_map_has (const hb_map_t *map,
hb_codepoint_t key)
{
return map->has (key);
}
/**
* hb_map_clear:
* @map: a map.
*
*
*
* Since: 1.7.7
**/
void
hb_map_clear (hb_map_t *map)
{
return map->clear ();
}
/**
* hb_map_is_empty:
* @map: a map.
*
*
*
* Since: 1.7.7
**/
hb_bool_t
hb_map_is_empty (const hb_map_t *map)
{
return map->is_empty ();
}
/**
* hb_map_get_population:
* @map: a map.
*
*
*
* Since: 1.7.7
**/
unsigned int
hb_map_get_population (const hb_map_t *map)
{
return map->get_population ();
}

View File

@ -0,0 +1,104 @@
/*
* Copyright © 2018 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_H_IN
#error "Include <hb.h> instead."
#endif
#ifndef HB_MAP_H
#define HB_MAP_H
#include "hb-common.h"
HB_BEGIN_DECLS
/*
* Since: 1.7.7
*/
#define HB_MAP_VALUE_INVALID ((hb_codepoint_t) -1)
typedef struct hb_map_t hb_map_t;
HB_EXTERN hb_map_t *
hb_map_create (void);
HB_EXTERN hb_map_t *
hb_map_get_empty (void);
HB_EXTERN hb_map_t *
hb_map_reference (hb_map_t *map);
HB_EXTERN void
hb_map_destroy (hb_map_t *map);
HB_EXTERN hb_bool_t
hb_map_set_user_data (hb_map_t *map,
hb_user_data_key_t *key,
void * data,
hb_destroy_func_t destroy,
hb_bool_t replace);
HB_EXTERN void *
hb_map_get_user_data (hb_map_t *map,
hb_user_data_key_t *key);
/* Returns false if allocation has failed before */
HB_EXTERN hb_bool_t
hb_map_allocation_successful (const hb_map_t *map);
HB_EXTERN void
hb_map_clear (hb_map_t *map);
HB_EXTERN hb_bool_t
hb_map_is_empty (const hb_map_t *map);
HB_EXTERN unsigned int
hb_map_get_population (const hb_map_t *map);
HB_EXTERN void
hb_map_set (hb_map_t *map,
hb_codepoint_t key,
hb_codepoint_t value);
HB_EXTERN hb_codepoint_t
hb_map_get (const hb_map_t *map,
hb_codepoint_t key);
HB_EXTERN void
hb_map_del (hb_map_t *map,
hb_codepoint_t key);
HB_EXTERN hb_bool_t
hb_map_has (const hb_map_t *map,
hb_codepoint_t key);
HB_END_DECLS
#endif /* HB_MAP_H */

View File

@ -134,7 +134,7 @@ struct hb_mutex_t
inline void init (void) { hb_mutex_impl_init (&m); }
inline void lock (void) { hb_mutex_impl_lock (&m); }
inline void unlock (void) { hb_mutex_impl_unlock (&m); }
inline void finish (void) { hb_mutex_impl_finish (&m); }
inline void fini (void) { hb_mutex_impl_finish (&m); }
};

View File

@ -41,9 +41,9 @@
/* reference_count */
#define HB_REFERENCE_COUNT_INERT_VALUE -1
#define HB_REFERENCE_COUNT_INERT_VALUE 0
#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT(HB_REFERENCE_COUNT_INERT_VALUE)}
#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT (HB_REFERENCE_COUNT_INERT_VALUE)}
struct hb_reference_count_t
{
@ -53,7 +53,7 @@ struct hb_reference_count_t
inline int get_unsafe (void) const { return ref_count.get_unsafe (); }
inline int inc (void) { return ref_count.inc (); }
inline int dec (void) { return ref_count.dec (); }
inline void finish (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); }
inline void fini (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); }
inline bool is_inert (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; }
inline bool is_valid (void) const { return ref_count.get_unsafe () > 0; }
@ -62,7 +62,6 @@ struct hb_reference_count_t
/* user_data */
#define HB_USER_DATA_ARRAY_INIT {HB_MUTEX_INIT, HB_LOCKABLE_SET_INIT}
struct hb_user_data_array_t
{
struct hb_user_data_item_t {
@ -73,7 +72,7 @@ struct hb_user_data_array_t
inline bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; }
inline bool operator == (hb_user_data_item_t &other) const { return key == other.key; }
void finish (void) { if (destroy) destroy (data); }
void fini (void) { if (destroy) destroy (data); }
};
hb_mutex_t lock;
@ -88,7 +87,7 @@ struct hb_user_data_array_t
HB_INTERNAL void *get (hb_user_data_key_t *key);
inline void finish (void) { items.finish (lock); lock.finish (); }
inline void fini (void) { items.fini (lock); lock.fini (); }
};
@ -97,9 +96,9 @@ struct hb_user_data_array_t
struct hb_object_header_t
{
hb_reference_count_t ref_count;
hb_user_data_array_t user_data;
hb_user_data_array_t *user_data;
#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, HB_USER_DATA_ARRAY_INIT}
#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, nullptr}
private:
ASSERT_POD ();
@ -133,7 +132,7 @@ template <typename Type>
static inline void hb_object_init (Type *obj)
{
obj->header.ref_count.init (1);
obj->header.user_data.init ();
obj->header.user_data = nullptr;
}
template <typename Type>
static inline bool hb_object_is_inert (const Type *obj)
@ -165,11 +164,20 @@ static inline bool hb_object_destroy (Type *obj)
if (obj->header.ref_count.dec () != 1)
return false;
obj->header.ref_count.finish (); /* Do this before user_data */
obj->header.user_data.finish ();
hb_object_fini (obj);
return true;
}
template <typename Type>
static inline void hb_object_fini (Type *obj)
{
obj->header.ref_count.fini (); /* Do this before user_data */
if (obj->header.user_data)
{
obj->header.user_data->fini ();
free (obj->header.user_data);
}
}
template <typename Type>
static inline bool hb_object_set_user_data (Type *obj,
hb_user_data_key_t *key,
void * data,
@ -179,17 +187,34 @@ static inline bool hb_object_set_user_data (Type *obj,
if (unlikely (!obj || hb_object_is_inert (obj)))
return false;
assert (hb_object_is_valid (obj));
return obj->header.user_data.set (key, data, destroy, replace);
retry:
hb_user_data_array_t *user_data = (hb_user_data_array_t *) hb_atomic_ptr_get (&obj->header.user_data);
if (unlikely (!user_data))
{
user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1);
if (unlikely (!user_data))
return false;
user_data->init ();
if (unlikely (!hb_atomic_ptr_cmpexch (&obj->header.user_data, nullptr, user_data)))
{
user_data->fini ();
free (user_data);
goto retry;
}
}
return user_data->set (key, data, destroy, replace);
}
template <typename Type>
static inline void *hb_object_get_user_data (Type *obj,
hb_user_data_key_t *key)
{
if (unlikely (!obj || hb_object_is_inert (obj)))
if (unlikely (!obj || hb_object_is_inert (obj) || !obj->header.user_data))
return nullptr;
assert (hb_object_is_valid (obj));
return obj->header.user_data.get (key);
return obj->header.user_data->get (key);
}

View File

@ -100,7 +100,7 @@ typedef struct OffsetTable
else
*table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);
const TableRecord *sub_tables = tables.array + start_offset;
const TableRecord *sub_tables = tables.arrayZ + start_offset;
unsigned int count = *table_count;
for (unsigned int i = 0; i < count; i++)
table_tags[i] = sub_tables[i].tag;
@ -148,7 +148,7 @@ typedef struct OffsetTable
/* Write OffsetTables, alloc for and write actual table blobs. */
for (unsigned int i = 0; i < table_count; i++)
{
TableRecord &rec = tables.array[i];
TableRecord &rec = tables.arrayZ[i];
hb_blob_t *blob = blobs[i];
rec.tag.set (tags[i]);
rec.length.set (hb_blob_get_length (blob));
@ -188,7 +188,7 @@ typedef struct OffsetTable
checksum.set_for_data (this, dir_end - (const char *) this);
for (unsigned int i = 0; i < table_count; i++)
{
TableRecord &rec = tables.array[i];
TableRecord &rec = tables.arrayZ[i];
checksum.set (checksum + rec.checkSum);
}
@ -234,7 +234,7 @@ struct TTCHeaderVersion1
Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
FixedVersion<>version; /* Version of the TTC Header (1.0),
* 0x00010000u */
ArrayOf<LOffsetTo<OffsetTable>, HBUINT32>
LArrayOf<LOffsetTo<OffsetTable> >
table; /* Array of offsets to the OffsetTable for each font
* from the beginning of the file */
public:
@ -295,11 +295,13 @@ struct OpenTypeFontFile
{
static const hb_tag_t tableTag = HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */
static const hb_tag_t CFFTag = HB_TAG ('O','T','T','O'); /* OpenType with Postscript outlines */
static const hb_tag_t TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ); /* OpenType with TrueType outlines */
static const hb_tag_t TTCTag = HB_TAG ('t','t','c','f'); /* TrueType Collection */
static const hb_tag_t TrueTag = HB_TAG ('t','r','u','e'); /* Obsolete Apple TrueType */
static const hb_tag_t Typ1Tag = HB_TAG ('t','y','p','1'); /* Obsolete Apple Type1 font in SFNT container */
enum {
CFFTag = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
TTCTag = HB_TAG ('t','t','c','f'), /* TrueType Collection */
TrueTag = HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */
Typ1Tag = HB_TAG ('t','y','p','1') /* Obsolete Apple Type1 font in SFNT container */
};
inline hb_tag_t get_tag (void) const { return u.tag; }

View File

@ -31,6 +31,7 @@
#include "hb-private.hh"
#include "hb-debug.hh"
#include "hb-blob-private.hh"
#include "hb-face-private.hh"
@ -126,46 +127,6 @@ static inline Type& StructAfter(TObject &X)
/*
* Null objects
*/
/* Global nul-content Null pool. Enlarge as necessary. */
#define HB_NULL_POOL_SIZE 264
static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE.");
#ifdef HB_NO_VISIBILITY
static
#else
extern HB_INTERNAL
#endif
const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)]
#ifdef HB_NO_VISIBILITY
= {}
#endif
;
/* Generic nul-content Null objects. */
template <typename Type>
static inline const Type& Null (void) {
static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
return *CastP<Type> (_hb_NullPool);
}
/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
#define DEFINE_NULL_DATA(Type, data) \
static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \
template <> \
/*static*/ inline const Type& Null<Type> (void) { \
return *CastP<Type> (_Null##Type); \
} /* The following line really exists such that we end in a place needing semicolon */ \
static_assert (Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. Enlarge.")
/* Accessor macro. */
#define Null(Type) Null<Type>()
/*
* Dispatch
*/
@ -225,7 +186,7 @@ struct hb_sanitize_context_t :
inline void start_processing (void)
{
this->start = hb_blob_get_data (this->blob, nullptr);
this->end = this->start + hb_blob_get_length (this->blob);
this->end = this->start + this->blob->length;
assert (this->start <= this->end); /* Must not overflow. */
this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
(unsigned) HB_SANITIZE_MAX_OPS_MIN);
@ -288,7 +249,7 @@ struct hb_sanitize_context_t :
return likely (this->check_range (obj, obj->min_size));
}
inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED)
inline bool may_edit (const void *base, unsigned int len)
{
if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
return false;
@ -368,7 +329,7 @@ struct Sanitizer
unsigned int edit_count = c->edit_count;
if (edit_count && !c->writable) {
c->start = hb_blob_get_data_writable (blob, nullptr);
c->end = c->start + hb_blob_get_length (blob);
c->end = c->start + blob->length;
if (c->start) {
c->writable = true;
@ -383,19 +344,17 @@ struct Sanitizer
DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED");
if (sane)
{
blob->lock ();
return blob;
else {
}
else
{
hb_blob_destroy (blob);
return hb_blob_get_empty ();
}
}
static const Type* lock_instance (hb_blob_t *blob) {
hb_blob_make_immutable (blob);
const char *base = hb_blob_get_data (blob, nullptr);
return unlikely (!base) ? &Null(Type) : CastP<Type> (base);
}
inline void set_num_glyphs (unsigned int num_glyphs) { c->num_glyphs = num_glyphs; }
private:
@ -672,7 +631,7 @@ typedef IntType<uint16_t, 2> HBUINT16; /* 16-bit unsigned integer. */
typedef IntType<int16_t, 2> HBINT16; /* 16-bit signed integer. */
typedef IntType<uint32_t, 4> HBUINT32; /* 32-bit unsigned integer. */
typedef IntType<int32_t, 4> HBINT32; /* 32-bit signed integer. */
typedef IntType<uint32_t, 3> UINT24; /* 24-bit unsigned integer. */
typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */
/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
typedef HBINT16 FWORD;
@ -683,17 +642,19 @@ typedef HBUINT16 UFWORD;
/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
struct F2DOT14 : HBINT16
{
//inline float to_float (void) const { return ???; }
//inline void set_float (float f) { v.set (f * ???); }
// 16384 means 1<<14
inline float to_float (void) const { return ((int32_t) v) / 16384.f; }
inline void set_float (float f) { v.set (round (f * 16384.f)); }
public:
DEFINE_SIZE_STATIC (2);
};
/* 32-bit signed fixed-point number (16.16). */
struct Fixed: HBINT32
struct Fixed : HBINT32
{
inline float to_float (void) const { return ((int32_t) v) / 65536.0; }
inline void set_float (float f) { v.set (round (f * 65536.0)); }
// 65536 means 1<<16
inline float to_float (void) const { return ((int32_t) v) / 65536.f; }
inline void set_float (float f) { v.set (round (f * 65536.f)); }
public:
DEFINE_SIZE_STATIC (4);
};
@ -724,16 +685,19 @@ struct Tag : HBUINT32
public:
DEFINE_SIZE_STATIC (4);
};
DEFINE_NULL_DATA (Tag, " ");
DEFINE_NULL_DATA (OT, Tag, " ");
/* Glyph index number, same as uint16 (length = 16 bits) */
typedef HBUINT16 GlyphID;
/* Name-table index, same as uint16 (length = 16 bits) */
typedef HBUINT16 NameID;
/* Script/language-system/feature index */
struct Index : HBUINT16 {
static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
};
DEFINE_NULL_DATA (Index, "\xff\xff");
DEFINE_NULL_DATA (OT, Index, "\xff\xff");
/* Offset, Null offset = 0 */
template <typename Type>
@ -815,6 +779,12 @@ struct OffsetTo : Offset<OffsetType>
{
unsigned int offset = *this;
if (unlikely (!offset)) return Null(Type);
return StructAtOffset<const Type> (base, offset);
}
inline Type& operator () (void *base) const
{
unsigned int offset = *this;
if (unlikely (!offset)) return Crap(Type);
return StructAtOffset<Type> (base, offset);
}
@ -862,6 +832,89 @@ static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset)
* Array Types
*/
/* TODO Use it in ArrayOf, HeadlessArrayOf, and other places around the code base?? */
template <typename Type>
struct UnsizedArrayOf
{
inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; }
inline Type& operator [] (unsigned int i) { return arrayZ[i]; }
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
/* Note: for structs that do not reference other structs,
* we do not need to call their sanitize() as we already did
* a bound check on the aggregate array size. We just include
* a small unreachable expression to make sure the structs
* pointed to do have a simple sanitize(), ie. they do not
* reference other structs via offsets.
*/
(void) (false && arrayZ[0].sanitize (c));
return_trace (true);
}
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
for (unsigned int i = 0; i < count; i++)
if (unlikely (!arrayZ[i].sanitize (c, base)))
return_trace (false);
return_trace (true);
}
template <typename T>
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
for (unsigned int i = 0; i < count; i++)
if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
return_trace (false);
return_trace (true);
}
inline bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const
{
TRACE_SANITIZE (this);
return_trace (c->check_array (arrayZ, arrayZ[0].static_size, count));
}
public:
Type arrayZ[VAR];
public:
DEFINE_SIZE_ARRAY (0, arrayZ);
};
/* Unsized array of offset's */
template <typename Type, typename OffsetType>
struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType> > {};
/* Unsized array of offsets relative to the beginning of the array itself. */
template <typename Type, typename OffsetType>
struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType>
{
inline const Type& operator [] (unsigned int i) const
{
return this+this->arrayZ[i];
}
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
{
TRACE_SANITIZE (this);
return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this)));
}
template <typename T>
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
{
TRACE_SANITIZE (this);
return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this, user_data)));
}
};
/* An array with a number of elements. */
template <typename Type, typename LenType=HBUINT16>
struct ArrayOf
@ -875,17 +928,18 @@ struct ArrayOf
count -= start_offset;
count = MIN (count, *pcount);
*pcount = count;
return array + start_offset;
return arrayZ + start_offset;
}
inline const Type& operator [] (unsigned int i) const
{
if (unlikely (i >= len)) return Null(Type);
return array[i];
return arrayZ[i];
}
inline Type& operator [] (unsigned int i)
{
return array[i];
if (unlikely (i >= len)) return Crap(Type);
return arrayZ[i];
}
inline unsigned int get_size (void) const
{ return len.static_size + len * Type::static_size; }
@ -907,7 +961,7 @@ struct ArrayOf
TRACE_SERIALIZE (this);
if (unlikely (!serialize (c, items_len))) return_trace (false);
for (unsigned int i = 0; i < items_len; i++)
array[i] = items[i];
arrayZ[i] = items[i];
items += items_len;
return_trace (true);
}
@ -924,7 +978,7 @@ struct ArrayOf
* pointed to do have a simple sanitize(), ie. they do not
* reference other structs via offsets.
*/
(void) (false && array[0].sanitize (c));
(void) (false && arrayZ[0].sanitize (c));
return_trace (true);
}
@ -934,7 +988,7 @@ struct ArrayOf
if (unlikely (!sanitize_shallow (c))) return_trace (false);
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
if (unlikely (!array[i].sanitize (c, base)))
if (unlikely (!arrayZ[i].sanitize (c, base)))
return_trace (false);
return_trace (true);
}
@ -945,7 +999,7 @@ struct ArrayOf
if (unlikely (!sanitize_shallow (c))) return_trace (false);
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
if (unlikely (!array[i].sanitize (c, base, user_data)))
if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
return_trace (false);
return_trace (true);
}
@ -955,28 +1009,28 @@ struct ArrayOf
{
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
if (!this->array[i].cmp (x))
if (!this->arrayZ[i].cmp (x))
return i;
return -1;
}
inline void qsort (void)
{
::qsort (array, len, sizeof (Type), Type::cmp);
::qsort (arrayZ, len, sizeof (Type), Type::cmp);
}
private:
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (len.sanitize (c) && c->check_array (array, Type::static_size, len));
return_trace (len.sanitize (c) && c->check_array (arrayZ, Type::static_size, len));
}
public:
LenType len;
Type array[VAR];
Type arrayZ[VAR];
public:
DEFINE_SIZE_ARRAY (sizeof (LenType), array);
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
};
template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {};
@ -991,7 +1045,12 @@ struct OffsetListOf : OffsetArrayOf<Type>
inline const Type& operator [] (unsigned int i) const
{
if (unlikely (i >= this->len)) return Null(Type);
return this+this->array[i];
return this+this->arrayZ[i];
}
inline const Type& operator [] (unsigned int i)
{
if (unlikely (i >= this->len)) return Crap(Type);
return this+this->arrayZ[i];
}
inline bool sanitize (hb_sanitize_context_t *c) const
@ -1015,7 +1074,12 @@ struct HeadlessArrayOf
inline const Type& operator [] (unsigned int i) const
{
if (unlikely (i >= len || !i)) return Null(Type);
return array[i-1];
return arrayZ[i-1];
}
inline Type& operator [] (unsigned int i)
{
if (unlikely (i >= len || !i)) return Crap(Type);
return arrayZ[i-1];
}
inline unsigned int get_size (void) const
{ return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
@ -1030,7 +1094,7 @@ struct HeadlessArrayOf
if (unlikely (!items_len)) return_trace (true);
if (unlikely (!c->extend (*this))) return_trace (false);
for (unsigned int i = 0; i < items_len - 1; i++)
array[i] = items[i];
arrayZ[i] = items[i];
items += items_len - 1;
return_trace (true);
}
@ -1047,7 +1111,7 @@ struct HeadlessArrayOf
* pointed to do have a simple sanitize(), ie. they do not
* reference other structs via offsets.
*/
(void) (false && array[0].sanitize (c));
(void) (false && arrayZ[0].sanitize (c));
return_trace (true);
}
@ -1057,14 +1121,14 @@ struct HeadlessArrayOf
{
TRACE_SANITIZE (this);
return_trace (len.sanitize (c) &&
(!len || c->check_array (array, Type::static_size, len - 1)));
(!len || c->check_array (arrayZ, Type::static_size, len - 1)));
}
public:
LenType len;
Type array[VAR];
Type arrayZ[VAR];
public:
DEFINE_SIZE_ARRAY (sizeof (LenType), array);
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
};
@ -1078,7 +1142,7 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
inline int bsearch (const SearchType &x) const
{
/* Hand-coded bsearch here since this is in the hot inner loop. */
const Type *arr = this->array;
const Type *arr = this->arrayZ;
int min = 0, max = (int) this->len - 1;
while (min <= max)
{
@ -1113,18 +1177,18 @@ struct BinSearchHeader
{
len.set (v);
assert (len == v);
entrySelectorZ.set (MAX (1u, _hb_bit_storage (v)) - 1);
searchRangeZ.set (16 * (1u << entrySelectorZ));
rangeShiftZ.set (v * 16 > searchRangeZ
? 16 * v - searchRangeZ
: 0);
entrySelector.set (MAX (1u, _hb_bit_storage (v)) - 1);
searchRange.set (16 * (1u << entrySelector));
rangeShift.set (v * 16 > searchRange
? 16 * v - searchRange
: 0);
}
protected:
HBUINT16 len;
HBUINT16 searchRangeZ;
HBUINT16 entrySelectorZ;
HBUINT16 rangeShiftZ;
HBUINT16 searchRange;
HBUINT16 entrySelector;
HBUINT16 rangeShift;
public:
DEFINE_SIZE_STATIC (8);
@ -1136,7 +1200,7 @@ struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader> {};
/* Lazy struct and blob loaders. */
/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */
/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
template <typename T>
struct hb_lazy_loader_t
{
@ -1148,7 +1212,7 @@ struct hb_lazy_loader_t
inline void fini (void)
{
if (instance && instance != &OT::Null(T))
if (instance && instance != &Null(T))
{
instance->fini();
free (instance);
@ -1163,12 +1227,12 @@ struct hb_lazy_loader_t
{
p = (T *) calloc (1, sizeof (T));
if (unlikely (!p))
p = const_cast<T *> (&OT::Null(T));
p = const_cast<T *> (&Null(T));
else
p->init (face);
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p)))
{
if (p != &OT::Null(T))
if (p != &Null(T))
p->fini ();
goto retry;
}
@ -1186,15 +1250,14 @@ struct hb_lazy_loader_t
T *instance;
};
/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */
/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
template <typename T>
struct hb_lazy_table_loader_t
struct hb_table_lazy_loader_t
{
inline void init (hb_face_t *face_)
{
face = face_;
blob = nullptr;
instance = nullptr;
}
inline void fini (void)
@ -1205,19 +1268,18 @@ struct hb_lazy_table_loader_t
inline const T* get (void) const
{
retry:
T *p = (T *) hb_atomic_ptr_get (&instance);
if (unlikely (!p))
hb_blob_t *blob_ = (hb_blob_t *) hb_atomic_ptr_get (&blob);
if (unlikely (!blob_))
{
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), nullptr, p))
blob_ = OT::Sanitizer<T>().sanitize (face->reference_table (T::tableTag));
if (!hb_atomic_ptr_cmpexch (&blob, nullptr, blob_))
{
hb_blob_destroy (blob_);
goto retry;
}
blob = blob_;
}
return p;
return blob_->as<T> ();
}
inline const T* operator-> (void) const
@ -1225,10 +1287,9 @@ struct hb_lazy_table_loader_t
return get();
}
private:
hb_face_t *face;
mutable hb_blob_t *blob;
private:
mutable T *instance;
};

View File

@ -28,18 +28,19 @@
#define HB_OT_CMAP_TABLE_HH
#include "hb-open-type-private.hh"
#include "hb-set-private.hh"
#include "hb-subset-plan.hh"
namespace OT {
/*
* cmap -- Character To Glyph Index Mapping Table
* cmap -- Character to Glyph Index Mapping
* https://docs.microsoft.com/en-us/typography/opentype/spec/cmap
*/
#define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
namespace OT {
struct CmapSubtableFormat0
{
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
@ -59,8 +60,8 @@ struct CmapSubtableFormat0
protected:
HBUINT16 format; /* Format number is set to 0. */
HBUINT16 lengthZ; /* Byte length of this subtable. */
HBUINT16 languageZ; /* Ignore. */
HBUINT16 length; /* Byte length of this subtable. */
HBUINT16 language; /* Ignore. */
HBUINT8 glyphIdArray[256];/* An array that maps character
* code to glyph index values. */
public:
@ -69,6 +70,158 @@ struct CmapSubtableFormat0
struct CmapSubtableFormat4
{
struct segment_plan
{
HBUINT16 start_code;
HBUINT16 end_code;
bool use_delta;
};
bool serialize (hb_serialize_context_t *c,
const hb_subset_plan_t *plan,
const hb_vector_t<segment_plan> &segments)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return_trace (false);
this->format.set (4);
this->length.set (get_sub_table_size (segments));
this->segCountX2.set (segments.len * 2);
this->entrySelector.set (MAX (1u, _hb_bit_storage (segments.len)) - 1);
this->searchRange.set (2 * (1u << this->entrySelector));
this->rangeShift.set (segments.len * 2 > this->searchRange
? 2 * segments.len - this->searchRange
: 0);
HBUINT16 *end_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.len);
c->allocate_size<HBUINT16> (HBUINT16::static_size); // 2 bytes of padding.
HBUINT16 *start_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.len);
HBINT16 *id_delta = c->allocate_size<HBINT16> (HBUINT16::static_size * segments.len);
HBUINT16 *id_range_offset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.len);
if (id_range_offset == nullptr)
return_trace (false);
for (unsigned int i = 0; i < segments.len; i++)
{
end_count[i].set (segments[i].end_code);
start_count[i].set (segments[i].start_code);
if (segments[i].use_delta)
{
hb_codepoint_t cp = segments[i].start_code;
hb_codepoint_t start_gid = 0;
if (unlikely (!plan->new_gid_for_codepoint (cp, &start_gid) && cp != 0xFFFF))
return_trace (false);
id_delta[i].set (start_gid - segments[i].start_code);
} else {
id_delta[i].set (0);
unsigned int num_codepoints = segments[i].end_code - segments[i].start_code + 1;
HBUINT16 *glyph_id_array = c->allocate_size<HBUINT16> (HBUINT16::static_size * num_codepoints);
if (glyph_id_array == nullptr)
return_trace (false);
// From the cmap spec:
//
// id_range_offset[i]/2
// + (cp - segments[i].start_code)
// + (id_range_offset + i)
// =
// glyph_id_array + (cp - segments[i].start_code)
//
// So, solve for id_range_offset[i]:
//
// id_range_offset[i]
// =
// 2 * (glyph_id_array - id_range_offset - i)
id_range_offset[i].set (2 * (
glyph_id_array - id_range_offset - i));
for (unsigned int j = 0; j < num_codepoints; j++)
{
hb_codepoint_t cp = segments[i].start_code + j;
hb_codepoint_t new_gid;
if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
return_trace (false);
glyph_id_array[j].set (new_gid);
}
}
}
return_trace (true);
}
static inline size_t get_sub_table_size (const hb_vector_t<segment_plan> &segments)
{
size_t segment_size = 0;
for (unsigned int i = 0; i < segments.len; i++)
{
// Parallel array entries
segment_size +=
2 // end count
+ 2 // start count
+ 2 // delta
+ 2; // range offset
if (!segments[i].use_delta)
// Add bytes for the glyph index array entries for this segment.
segment_size += (segments[i].end_code - segments[i].start_code + 1) * 2;
}
return min_size
+ 2 // Padding
+ segment_size;
}
static inline bool create_sub_table_plan (const hb_subset_plan_t *plan,
hb_vector_t<segment_plan> *segments)
{
segment_plan *segment = nullptr;
hb_codepoint_t last_gid = 0;
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
while (plan->unicodes->next (&cp)) {
hb_codepoint_t new_gid;
if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
{
DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
return false;
}
if (cp > 0xFFFF) {
// We are now outside of unicode BMP, stop adding to this cmap.
break;
}
if (!segment
|| cp != segment->end_code + 1u)
{
segment = segments->push ();
segment->start_code.set (cp);
segment->end_code.set (cp);
segment->use_delta = true;
} else {
segment->end_code.set (cp);
if (last_gid + 1u != new_gid)
// gid's are not consecutive in this segment so delta
// cannot be used.
segment->use_delta = false;
}
last_gid = new_gid;
}
// There must be a final entry with end_code == 0xFFFF. Check if we need to add one.
if (segment == nullptr || segment->end_code != 0xFFFF)
{
segment = segments->push ();
segment->start_code.set (0xFFFF);
segment->end_code.set (0xFFFF);
segment->use_delta = true;
}
return true;
}
struct accelerator_t
{
inline void init (const CmapSubtableFormat4 *subtable)
@ -127,6 +280,17 @@ struct CmapSubtableFormat4
return true;
}
static inline void get_all_codepoints_func (const void *obj, hb_set_t *out)
{
const accelerator_t *thiz = (const accelerator_t *) obj;
for (unsigned int i = 0; i < thiz->segCount; i++)
{
if (thiz->startCount[i] != 0xFFFFu
|| thiz->endCount[i] != 0xFFFFu) // Skip the last segment (0xFFFF)
hb_set_add_range (out, thiz->startCount[i], thiz->endCount[i]);
}
}
const HBUINT16 *endCount;
const HBUINT16 *startCount;
const HBUINT16 *idDelta;
@ -164,15 +328,17 @@ struct CmapSubtableFormat4
return_trace (16 + 4 * (unsigned int) segCountX2 <= length);
}
protected:
HBUINT16 format; /* Format number is set to 4. */
HBUINT16 length; /* This is the length in bytes of the
* subtable. */
HBUINT16 languageZ; /* Ignore. */
HBUINT16 language; /* Ignore. */
HBUINT16 segCountX2; /* 2 x segCount. */
HBUINT16 searchRangeZ; /* 2 * (2**floor(log2(segCount))) */
HBUINT16 entrySelectorZ; /* log2(searchRange/2) */
HBUINT16 rangeShiftZ; /* 2 x segCount - searchRange */
HBUINT16 searchRange; /* 2 * (2**floor(log2(segCount))) */
HBUINT16 entrySelector; /* log2(searchRange/2) */
HBUINT16 rangeShift; /* 2 x segCount - searchRange */
HBUINT16 values[VAR];
#if 0
@ -193,6 +359,8 @@ struct CmapSubtableLongGroup
{
friend struct CmapSubtableFormat12;
friend struct CmapSubtableFormat13;
template<typename U>
friend struct CmapSubtableLongSegmented;
friend struct cmap;
int cmp (hb_codepoint_t codepoint) const
@ -238,8 +406,8 @@ struct CmapSubtableTrimmed
protected:
UINT formatReserved; /* Subtable format and (maybe) padding. */
UINT lengthZ; /* Byte length of this subtable. */
UINT languageZ; /* Ignore. */
UINT length; /* Byte length of this subtable. */
UINT language; /* Ignore. */
UINT startCharCode; /* First character code covered. */
ArrayOf<GlyphID, UINT>
glyphIdArray; /* Array of glyph index values for character
@ -265,6 +433,15 @@ struct CmapSubtableLongSegmented
return true;
}
inline void get_all_codepoints (hb_set_t *out) const
{
for (unsigned int i = 0; i < this->groups.len; i++) {
hb_set_add_range (out,
this->groups[i].startCharCode,
this->groups[i].endCharCode);
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -272,20 +449,20 @@ struct CmapSubtableLongSegmented
}
inline bool serialize (hb_serialize_context_t *c,
hb_prealloced_array_t<CmapSubtableLongGroup> &group_data)
const hb_vector_t<CmapSubtableLongGroup> &group_data)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return_trace (false);
Supplier<CmapSubtableLongGroup> supplier (group_data.array, group_data.len);
Supplier<CmapSubtableLongGroup> supplier (group_data.arrayZ, group_data.len);
if (unlikely (!groups.serialize (c, supplier, group_data.len))) return_trace (false);
return true;
}
protected:
HBUINT16 format; /* Subtable format; set to 12. */
HBUINT16 reservedZ; /* Reserved; set to 0. */
HBUINT32 lengthZ; /* Byte length of this subtable. */
HBUINT32 languageZ; /* Ignore. */
HBUINT16 reserved; /* Reserved; set to 0. */
HBUINT32 length; /* Byte length of this subtable. */
HBUINT32 language; /* Ignore. */
SortedArrayOf<CmapSubtableLongGroup, HBUINT32>
groups; /* Groupings. */
public:
@ -297,6 +474,69 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
hb_codepoint_t u)
{ return group.glyphID + (u - group.startCharCode); }
bool serialize (hb_serialize_context_t *c,
const hb_vector_t<CmapSubtableLongGroup> &groups)
{
if (unlikely (!c->extend_min (*this))) return false;
this->format.set (12);
this->reserved.set (0);
this->length.set (get_sub_table_size (groups));
return CmapSubtableLongSegmented<CmapSubtableFormat12>::serialize (c, groups);
}
static inline size_t get_sub_table_size (const hb_vector_t<CmapSubtableLongGroup> &groups)
{
return 16 + 12 * groups.len;
}
static inline bool create_sub_table_plan (const hb_subset_plan_t *plan,
hb_vector_t<CmapSubtableLongGroup> *groups)
{
CmapSubtableLongGroup *group = nullptr;
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
while (plan->unicodes->next (&cp)) {
hb_codepoint_t new_gid;
if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
{
DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
return false;
}
if (!group || !_is_gid_consecutive (group, cp, new_gid))
{
group = groups->push ();
group->startCharCode.set (cp);
group->endCharCode.set (cp);
group->glyphID.set (new_gid);
} else
{
group->endCharCode.set (cp);
}
}
DEBUG_MSG(SUBSET, nullptr, "cmap");
for (unsigned int i = 0; i < groups->len; i++) {
CmapSubtableLongGroup& group = (*groups)[i];
DEBUG_MSG(SUBSET, nullptr, " %d: U+%04X-U+%04X, gid %d-%d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID, (uint32_t) group.glyphID + ((uint32_t) group.endCharCode - (uint32_t) group.startCharCode));
}
return true;
}
private:
static inline bool _is_gid_consecutive (CmapSubtableLongGroup *group,
hb_codepoint_t cp,
hb_codepoint_t new_gid)
{
return (cp - 1 == group->endCharCode) &&
new_gid == group->glyphID + (cp - group->startCharCode);
}
};
struct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
@ -328,7 +568,7 @@ struct UnicodeValueRange
return_trace (c->check_struct (this));
}
UINT24 startUnicodeValue; /* First value in this range. */
HBUINT24 startUnicodeValue; /* First value in this range. */
HBUINT8 additionalCount; /* Number of additional values in this
* range. */
public:
@ -350,7 +590,7 @@ struct UVSMapping
return_trace (c->check_struct (this));
}
UINT24 unicodeValue; /* Base Unicode value of the UVS */
HBUINT24 unicodeValue; /* Base Unicode value of the UVS */
GlyphID glyphID; /* Glyph ID of the UVS */
public:
DEFINE_SIZE_STATIC (5);
@ -392,7 +632,7 @@ struct VariationSelectorRecord
nonDefaultUVS.sanitize (c, base));
}
UINT24 varSelector; /* Variation selector. */
HBUINT24 varSelector; /* Variation selector. */
LOffsetTo<DefaultUVS>
defaultUVS; /* Offset to Default UVS Table. May be 0. */
LOffsetTo<NonDefaultUVS>
@ -419,7 +659,7 @@ struct CmapSubtableFormat14
protected:
HBUINT16 format; /* Format number is set to 14. */
HBUINT32 lengthZ; /* Byte length of this subtable. */
HBUINT32 length; /* Byte length of this subtable. */
SortedArrayOf<VariationSelectorRecord, HBUINT32>
record; /* Variation selector records; sorted
* in increasing order of `varSelector'. */
@ -509,6 +749,33 @@ struct cmap
{
static const hb_tag_t tableTag = HB_OT_TAG_cmap;
struct subset_plan {
subset_plan(void)
{
format4_segments.init();
format12_groups.init();
}
~subset_plan(void)
{
format4_segments.fini();
format12_groups.fini();
}
inline size_t final_size() const
{
return 4 // header
+ 8 * 3 // 3 EncodingRecord
+ CmapSubtableFormat4::get_sub_table_size (this->format4_segments)
+ CmapSubtableFormat12::get_sub_table_size (this->format12_groups);
}
// Format 4
hb_vector_t<CmapSubtableFormat4::segment_plan> format4_segments;
// Format 12
hb_vector_t<CmapSubtableLongGroup> format12_groups;
};
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -517,41 +784,17 @@ struct cmap
encodingRecord.sanitize (c, this));
}
inline bool populate_groups (hb_subset_plan_t *plan,
hb_prealloced_array_t<CmapSubtableLongGroup> *groups) const
inline bool _create_plan (const hb_subset_plan_t *plan,
subset_plan *cmap_plan) const
{
CmapSubtableLongGroup *group = nullptr;
for (unsigned int i = 0; i < plan->codepoints.len; i++) {
if (unlikely( !CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments)))
return false;
hb_codepoint_t cp = plan->codepoints[i];
if (!group || cp - 1 != group->endCharCode)
{
group = groups->push ();
group->startCharCode.set (cp);
group->endCharCode.set (cp);
hb_codepoint_t new_gid;
if (unlikely (!hb_subset_plan_new_gid_for_codepoint (plan, cp, &new_gid)))
{
DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
return false;
}
group->glyphID.set (new_gid);
} else
{
group->endCharCode.set (cp);
}
}
DEBUG_MSG(SUBSET, nullptr, "cmap");
for (unsigned int i = 0; i < groups->len; i++) {
CmapSubtableLongGroup& group = (*groups)[i];
DEBUG_MSG(SUBSET, nullptr, " %d: U+%04X-U+%04X, gid %d-%d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID, (uint32_t) group.glyphID + ((uint32_t) group.endCharCode - (uint32_t) group.startCharCode));
}
return true;
return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->format12_groups);
}
inline bool _subset (hb_prealloced_array_t<CmapSubtableLongGroup> &groups,
inline bool _subset (const hb_subset_plan_t *plan,
const subset_plan &cmap_subset_plan,
size_t dest_sz,
void *dest) const
{
@ -565,25 +808,46 @@ struct cmap
cmap->version.set (0);
if (unlikely (!cmap->encodingRecord.serialize (&c, /* numTables */ 1))) return false;
if (unlikely (!cmap->encodingRecord.serialize (&c, /* numTables */ 3)))
return false;
EncodingRecord &rec = cmap->encodingRecord[0];
rec.platformID.set (3); // Windows
rec.encodingID.set (10); // Unicode UCS-4
// TODO(grieger): Convert the below to a for loop
/* capture offset to subtable */
CmapSubtable &subtable = rec.subtable.serialize (&c, cmap);
// Format 4, Plat 0 Encoding Record
EncodingRecord &format4_plat0_rec = cmap->encodingRecord[0];
format4_plat0_rec.platformID.set (0); // Unicode
format4_plat0_rec.encodingID.set (3);
subtable.u.format.set (12);
// Format 4, Plat 3 Encoding Record
EncodingRecord &format4_plat3_rec = cmap->encodingRecord[1];
format4_plat3_rec.platformID.set (3); // Windows
format4_plat3_rec.encodingID.set (1); // Unicode BMP
CmapSubtableFormat12 &format12 = subtable.u.format12;
if (unlikely (!c.extend_min (format12))) return false;
// Format 12 Encoding Record
EncodingRecord &format12_rec = cmap->encodingRecord[2];
format12_rec.platformID.set (3); // Windows
format12_rec.encodingID.set (10); // Unicode UCS-4
format12.format.set (12);
format12.reservedZ.set (0);
format12.lengthZ.set (16 + 12 * groups.len);
// Write out format 4 sub table
{
CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, cmap);
format4_plat3_rec.subtable.set (format4_plat0_rec.subtable);
subtable.u.format.set (4);
if (unlikely (!format12.serialize (&c, groups))) return false;
CmapSubtableFormat4 &format4 = subtable.u.format4;
if (unlikely (!format4.serialize (&c, plan, cmap_subset_plan.format4_segments)))
return false;
}
// Write out format 12 sub table.
{
CmapSubtable &subtable = format12_rec.subtable.serialize (&c, cmap);
subtable.u.format.set (12);
CmapSubtableFormat12 &format12 = subtable.u.format12;
if (unlikely (!format12.serialize (&c, cmap_subset_plan.format12_groups)))
return false;
}
c.end_serialize ();
@ -592,24 +856,25 @@ struct cmap
inline bool subset (hb_subset_plan_t *plan) const
{
hb_auto_array_t<CmapSubtableLongGroup> groups;
subset_plan cmap_subset_plan;
if (unlikely (!populate_groups (plan, &groups))) return false;
if (unlikely (!_create_plan (plan, &cmap_subset_plan)))
{
DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cmap subsetting plan.");
return false;
}
// We now know how big our blob needs to be
// TODO use APIs from the structs to get size?
size_t dest_sz = 4 // header
+ 8 // 1 EncodingRecord
+ 16 // Format 12 header
+ 12 * groups.len; // SequentialMapGroup records
size_t dest_sz = cmap_subset_plan.final_size();
void *dest = malloc (dest_sz);
if (unlikely (!dest)) {
DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for cmap subset output", (unsigned long) dest_sz);
return false;
}
if (unlikely (!_subset (groups, dest_sz, dest)))
if (unlikely (!_subset (plan, cmap_subset_plan, dest_sz, dest)))
{
DEBUG_MSG(SUBSET, nullptr, "Failed to perform subsetting of cmap.");
free (dest);
return false;
}
@ -620,7 +885,7 @@ struct cmap
HB_MEMORY_MODE_READONLY,
dest,
free);
bool result = hb_subset_plan_add_table (plan, HB_OT_TAG_cmap, cmap_prime);
bool result = plan->add_table (HB_OT_TAG_cmap, cmap_prime);
hb_blob_destroy (cmap_prime);
return result;
}
@ -630,7 +895,7 @@ struct cmap
inline void init (hb_face_t *face)
{
this->blob = OT::Sanitizer<OT::cmap>().sanitize (face->reference_table (HB_OT_TAG_cmap));
const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
const OT::cmap *cmap = this->blob->as<OT::cmap> ();
const OT::CmapSubtable *subtable = nullptr;
const OT::CmapSubtableFormat14 *subtable_uvs = nullptr;
@ -651,7 +916,7 @@ struct cmap
if (subtable) symbol = true;
}
/* Meh. */
if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
if (!subtable) subtable = &Null(OT::CmapSubtable);
/* UVS subtable. */
if (!subtable_uvs)
@ -661,26 +926,36 @@ struct cmap
subtable_uvs = &st->u.format14;
}
/* Meh. */
if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtableFormat14);
if (!subtable_uvs) subtable_uvs = &Null(OT::CmapSubtableFormat14);
this->uvs_table = subtable_uvs;
this->get_glyph_data = subtable;
if (unlikely (symbol))
{
this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>;
else
this->get_all_codepoints_func = null_get_all_codepoints_func;
} else {
switch (subtable->u.format) {
/* Accelerate format 4 and format 12. */
default: this->get_glyph_func = get_glyph_from<OT::CmapSubtable>; break;
case 12: this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>; break;
default:
this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;
this->get_all_codepoints_func = null_get_all_codepoints_func;
break;
case 12:
this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;
this->get_all_codepoints_func = get_all_codepoints_from<OT::CmapSubtableFormat12>;
break;
case 4:
{
this->format4_accel.init (&subtable->u.format4);
this->get_glyph_data = &this->format4_accel;
this->get_glyph_func = this->format4_accel.get_glyph_func;
this->get_all_codepoints_func = this->format4_accel.get_all_codepoints_func;
}
break;
}
}
}
inline void fini (void)
@ -710,10 +985,22 @@ struct cmap
return get_nominal_glyph (unicode, glyph);
}
inline void get_all_codepoints (hb_set_t *out) const
{
this->get_all_codepoints_func (get_glyph_data, out);
}
protected:
typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
hb_codepoint_t codepoint,
hb_codepoint_t *glyph);
typedef void (*hb_cmap_get_all_codepoints_func_t) (const void *obj,
hb_set_t *out);
static inline void null_get_all_codepoints_func (const void *obj, hb_set_t *out)
{
// NOOP
}
template <typename Type>
static inline bool get_glyph_from (const void *obj,
@ -724,6 +1011,14 @@ struct cmap
return typed_obj->get_glyph (codepoint, glyph);
}
template <typename Type>
static inline void get_all_codepoints_from (const void *obj,
hb_set_t *out)
{
const Type *typed_obj = (const Type *) obj;
typed_obj->get_all_codepoints (out);
}
template <typename Type>
static inline bool get_glyph_from_symbol (const void *obj,
hb_codepoint_t codepoint,
@ -738,7 +1033,7 @@ struct cmap
/* For symbol-encoded OpenType fonts, we duplicate the
* U+F000..F0FF range at U+0000..U+00FF. That's what
* Windows seems to do, and that's hinted about at:
* http://www.microsoft.com/typography/otspec/recom.htm
* https://docs.microsoft.com/en-us/typography/opentype/spec/recom
* under "Non-Standard (Symbol) Fonts". */
return typed_obj->get_glyph (0xF000u + codepoint, glyph);
}
@ -749,6 +1044,8 @@ struct cmap
private:
hb_cmap_get_glyph_func_t get_glyph_func;
const void *get_glyph_data;
hb_cmap_get_all_codepoints_func_t get_all_codepoints_func;
OT::CmapSubtableFormat4::accelerator_t format4_accel;
const OT::CmapSubtableFormat14 *uvs_table;

View File

@ -29,6 +29,18 @@
#include "hb-open-type-private.hh"
/*
* CBLC -- Color Bitmap Location
* https://docs.microsoft.com/en-us/typography/opentype/spec/cblc
* https://docs.microsoft.com/en-us/typography/opentype/spec/eblc
* CBDT -- Color Bitmap Data
* https://docs.microsoft.com/en-us/typography/opentype/spec/cbdt
* https://docs.microsoft.com/en-us/typography/opentype/spec/ebdt
*/
#define HB_OT_TAG_CBLC HB_TAG('C','B','L','C')
#define HB_OT_TAG_CBDT HB_TAG('C','B','D','T')
namespace OT {
struct SmallGlyphMetrics
@ -47,21 +59,21 @@ struct SmallGlyphMetrics
extents->height = -height;
}
HBUINT8 height;
HBUINT8 width;
HBINT8 bearingX;
HBINT8 bearingY;
HBUINT8 advance;
HBUINT8 height;
HBUINT8 width;
HBINT8 bearingX;
HBINT8 bearingY;
HBUINT8 advance;
public:
DEFINE_SIZE_STATIC(5);
};
struct BigGlyphMetrics : SmallGlyphMetrics
{
HBINT8 vertBearingX;
HBINT8 vertBearingY;
HBUINT8 vertAdvance;
HBINT8 vertBearingX;
HBINT8 vertBearingY;
HBUINT8 vertAdvance;
public:
DEFINE_SIZE_STATIC(8);
};
@ -73,19 +85,19 @@ struct SBitLineMetrics
return_trace (c->check_struct (this));
}
HBINT8 ascender;
HBINT8 decender;
HBUINT8 widthMax;
HBINT8 caretSlopeNumerator;
HBINT8 caretSlopeDenominator;
HBINT8 caretOffset;
HBINT8 minOriginSB;
HBINT8 minAdvanceSB;
HBINT8 maxBeforeBL;
HBINT8 minAfterBL;
HBINT8 padding1;
HBINT8 padding2;
HBINT8 ascender;
HBINT8 decender;
HBUINT8 widthMax;
HBINT8 caretSlopeNumerator;
HBINT8 caretSlopeDenominator;
HBINT8 caretOffset;
HBINT8 minOriginSB;
HBINT8 minAdvanceSB;
HBINT8 maxBeforeBL;
HBINT8 minAfterBL;
HBINT8 padding1;
HBINT8 padding2;
public:
DEFINE_SIZE_STATIC(12);
};
@ -102,10 +114,10 @@ struct IndexSubtableHeader
return_trace (c->check_struct (this));
}
HBUINT16 indexFormat;
HBUINT16 imageFormat;
HBUINT32 imageDataOffset;
HBUINT16 indexFormat;
HBUINT16 imageFormat;
HBUINT32 imageDataOffset;
public:
DEFINE_SIZE_STATIC(8);
};
@ -131,9 +143,9 @@ struct IndexSubtableFormat1Or3
return true;
}
IndexSubtableHeader header;
Offset<OffsetType> offsetArrayZ[VAR];
IndexSubtableHeader header;
Offset<OffsetType> offsetArrayZ[VAR];
public:
DEFINE_SIZE_ARRAY(8, offsetArrayZ);
};
@ -214,15 +226,17 @@ struct IndexSubtableRecord
offset, length, format);
}
HBUINT16 firstGlyphIndex;
HBUINT16 lastGlyphIndex;
LOffsetTo<IndexSubtable> offsetToSubtable;
GlyphID firstGlyphIndex;
GlyphID lastGlyphIndex;
LOffsetTo<IndexSubtable> offsetToSubtable;
public:
DEFINE_SIZE_STATIC(8);
};
struct IndexSubtableArray
{
friend struct CBDT;
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
{
TRACE_SANITIZE (this);
@ -249,8 +263,7 @@ struct IndexSubtableArray
}
protected:
IndexSubtableRecord indexSubtablesZ[VAR];
IndexSubtableRecord indexSubtablesZ[VAR];
public:
DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
};
@ -258,6 +271,7 @@ struct IndexSubtableArray
struct BitmapSizeTable
{
friend struct CBLC;
friend struct CBDT;
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
@ -275,19 +289,19 @@ struct BitmapSizeTable
}
protected:
LOffsetTo<IndexSubtableArray> indexSubtableArrayOffset;
HBUINT32 indexTablesSize;
HBUINT32 numberOfIndexSubtables;
HBUINT32 colorRef;
SBitLineMetrics horizontal;
SBitLineMetrics vertical;
HBUINT16 startGlyphIndex;
HBUINT16 endGlyphIndex;
HBUINT8 ppemX;
HBUINT8 ppemY;
HBUINT8 bitDepth;
HBINT8 flags;
LOffsetTo<IndexSubtableArray>
indexSubtableArrayOffset;
HBUINT32 indexTablesSize;
HBUINT32 numberOfIndexSubtables;
HBUINT32 colorRef;
SBitLineMetrics horizontal;
SBitLineMetrics vertical;
GlyphID startGlyphIndex;
GlyphID endGlyphIndex;
HBUINT8 ppemX;
HBUINT8 ppemY;
HBUINT8 bitDepth;
HBINT8 flags;
public:
DEFINE_SIZE_STATIC(48);
};
@ -299,19 +313,26 @@ struct BitmapSizeTable
struct GlyphBitmapDataFormat17
{
SmallGlyphMetrics glyphMetrics;
HBUINT32 dataLen;
HBUINT8 dataZ[VAR];
DEFINE_SIZE_ARRAY(9, dataZ);
SmallGlyphMetrics glyphMetrics;
LArrayOf<HBUINT8> data;
public:
DEFINE_SIZE_ARRAY(9, data);
};
struct GlyphBitmapDataFormat18
{
BigGlyphMetrics glyphMetrics;
LArrayOf<HBUINT8> data;
public:
DEFINE_SIZE_ARRAY(12, data);
};
/*
* CBLC -- Color Bitmap Location Table
*/
#define HB_OT_TAG_CBLC HB_TAG('C','B','L','C')
struct GlyphBitmapDataFormat19
{
LArrayOf<HBUINT8> data;
public:
DEFINE_SIZE_ARRAY(4, data);
};
struct CBLC
{
@ -336,8 +357,8 @@ struct CBLC
unsigned int count = sizeTables.len;
for (uint32_t i = 0; i < count; ++i)
{
unsigned int startGlyphIndex = sizeTables.array[i].startGlyphIndex;
unsigned int endGlyphIndex = sizeTables.array[i].endGlyphIndex;
unsigned int startGlyphIndex = sizeTables.arrayZ[i].startGlyphIndex;
unsigned int endGlyphIndex = sizeTables.arrayZ[i].endGlyphIndex;
if (startGlyphIndex <= glyph && glyph <= endGlyphIndex)
{
*x_ppem = sizeTables[i].ppemX;
@ -352,16 +373,10 @@ struct CBLC
protected:
FixedVersion<> version;
LArrayOf<BitmapSizeTable> sizeTables;
public:
DEFINE_SIZE_ARRAY(8, sizeTables);
};
/*
* CBDT -- Color Bitmap Data Table
*/
#define HB_OT_TAG_CBDT HB_TAG('C','B','D','T')
struct CBDT
{
static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
@ -388,8 +403,8 @@ struct CBDT
cbdt = nullptr;
return; /* Not a bitmap font. */
}
cblc = Sanitizer<CBLC>::lock_instance (cblc_blob);
cbdt = Sanitizer<CBDT>::lock_instance (cbdt_blob);
cblc = cblc_blob->as<CBLC> ();
cbdt = cbdt_blob->as<CBDT> ();
}
@ -447,6 +462,59 @@ struct CBDT
return true;
}
inline void dump (void (*callback) (const uint8_t* data, unsigned int length,
unsigned int group, unsigned int gid)) const
{
if (!cblc)
return; // Not a color bitmap font.
for (unsigned int i = 0; i < cblc->sizeTables.len; ++i)
{
const BitmapSizeTable &sizeTable = cblc->sizeTables[i];
const IndexSubtableArray &subtable_array = cblc+sizeTable.indexSubtableArrayOffset;
for (unsigned int j = 0; j < sizeTable.numberOfIndexSubtables; ++j)
{
const IndexSubtableRecord &subtable_record = subtable_array.indexSubtablesZ[j];
for (unsigned int gid = subtable_record.firstGlyphIndex;
gid <= subtable_record.lastGlyphIndex; ++gid)
{
unsigned int image_offset = 0, image_length = 0, image_format = 0;
if (!subtable_record.get_image_data (gid,
&image_offset, &image_length, &image_format))
continue;
switch (image_format)
{
case 17: {
const GlyphBitmapDataFormat17& glyphFormat17 =
StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
callback ((const uint8_t *) &glyphFormat17.data.arrayZ,
glyphFormat17.data.len, i, gid);
}
break;
case 18: {
const GlyphBitmapDataFormat18& glyphFormat18 =
StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
callback ((const uint8_t *) &glyphFormat18.data.arrayZ,
glyphFormat18.data.len, i, gid);
}
break;
case 19: {
const GlyphBitmapDataFormat19& glyphFormat19 =
StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
callback ((const uint8_t *) &glyphFormat19.data.arrayZ,
glyphFormat19.data.len, i, gid);
}
break;
default:
continue;
}
}
}
}
}
private:
hb_blob_t *cblc_blob;
hb_blob_t *cbdt_blob;
@ -459,9 +527,8 @@ struct CBDT
protected:
FixedVersion<>version;
HBUINT8 dataZ[VAR];
FixedVersion<> version;
HBUINT8 dataZ[VAR];
public:
DEFINE_SIZE_ARRAY(4, dataZ);
};

View File

@ -28,12 +28,12 @@
#include "hb-open-type-private.hh"
/*
* Color Palette
* http://www.microsoft.com/typography/otspec/colr.htm
* COLR -- Color
* https://docs.microsoft.com/en-us/typography/opentype/spec/colr
*/
#define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
namespace OT {
@ -48,8 +48,8 @@ struct LayerRecord
}
protected:
GlyphID gID; /* Glyph ID of layer glyph */
HBUINT16 paletteIndex; /* Index value to use with a selected color palette */
GlyphID glyphid; /* Glyph ID of layer glyph */
HBUINT16 colorIdx; /* Index value to use with a selected color palette */
public:
DEFINE_SIZE_STATIC (4);
};
@ -61,17 +61,28 @@ struct BaseGlyphRecord
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
return_trace (likely (c->check_struct (this)));
}
inline int cmp (hb_codepoint_t g) const {
return g < glyphid ? -1 : g > glyphid ? 1 : 0;
}
protected:
GlyphID gID; /* Glyph ID of reference glyph */
HBUINT16 firstLayerIndex; /* Index to the layer record */
HBUINT16 numLayers; /* Number of color layers associated with this glyph */
GlyphID glyphid; /* Glyph ID of reference glyph */
HBUINT16 firstLayerIdx; /* Index to the layer record */
HBUINT16 numLayers; /* Number of color layers associated with this glyph */
public:
DEFINE_SIZE_STATIC (6);
};
static int compare_bgr (const void *pa, const void *pb)
{
const hb_codepoint_t *a = (const hb_codepoint_t *) pa;
const BaseGlyphRecord *b = (const BaseGlyphRecord *) pb;
return b->cmp (*a);
}
struct COLR
{
static const hb_tag_t tableTag = HB_OT_TAG_COLR;
@ -79,59 +90,50 @@ struct COLR
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!(c->check_struct (this) &&
c->check_array ((const void*) &layerRecordsOffsetZ, sizeof (LayerRecord), numLayerRecords) &&
c->check_array ((const void*) &baseGlyphRecordsZ, sizeof (BaseGlyphRecord), numBaseGlyphRecords)))
return_trace (false);
const BaseGlyphRecord* base_glyph_records = &baseGlyphRecordsZ (this);
for (unsigned int i = 0; i < numBaseGlyphRecords; ++i)
if (base_glyph_records[i].firstLayerIndex +
base_glyph_records[i].numLayers > numLayerRecords)
return_trace (false);
return_trace (true);
return_trace (likely (c->check_struct (this) &&
(this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
(this+layersZ).sanitize (c, numLayers)));
}
inline bool get_base_glyph_record (
hb_codepoint_t glyph_id, unsigned int &first_layer, unsigned int &num_layers) const
inline bool get_base_glyph_record (hb_codepoint_t glyph_id,
unsigned int *first_layer /* OUT */,
unsigned int *num_layers /* OUT */) const
{
const BaseGlyphRecord* base_glyph_records = &baseGlyphRecordsZ (this);
unsigned int min = 0, max = numBaseGlyphRecords - 1;
while (min <= max)
const BaseGlyphRecord* record;
record = (BaseGlyphRecord *) bsearch (&glyph_id, &(this+baseGlyphsZ), numBaseGlyphs,
sizeof (BaseGlyphRecord), compare_bgr);
if (unlikely (!record))
return false;
*first_layer = record->firstLayerIdx;
*num_layers = record->numLayers;
return true;
}
inline bool get_layer_record (unsigned int record,
hb_codepoint_t *glyph_id /* OUT */,
unsigned int *palette_index /* OUT */) const
{
if (unlikely (record >= numLayers))
{
unsigned int mid = (min + max) / 2;
hb_codepoint_t gID = base_glyph_records[mid].gID;
if (gID > glyph_id)
max = mid - 1;
else if (gID < glyph_id)
min = mid + 1;
else
{
first_layer = base_glyph_records[mid].firstLayerIndex;
num_layers = base_glyph_records[mid].numLayers;
return true;
}
*glyph_id = 0;
*palette_index = 0xFFFF;
return false;
}
return false;
}
inline void get_layer_record (int layer,
hb_codepoint_t &glyph_id, unsigned int &palette_index) const
{
const LayerRecord* records = &layerRecordsOffsetZ (this);
glyph_id = records[layer].gID;
palette_index = records[layer].paletteIndex;
const LayerRecord &layer = (this+layersZ)[record];
*glyph_id = layer.glyphid;
*palette_index = layer.colorIdx;
return true;
}
protected:
HBUINT16 version; /* Table version number */
HBUINT16 numBaseGlyphRecords; /* Number of Base Glyph Records */
LOffsetTo<BaseGlyphRecord>
baseGlyphRecordsZ; /* Offset to Base Glyph records. */
LOffsetTo<LayerRecord>
layerRecordsOffsetZ; /* Offset to Layer Records */
HBUINT16 numLayerRecords; /* Number of Layer Records */
HBUINT16 version; /* Table version number */
HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records */
LOffsetTo<UnsizedArrayOf<BaseGlyphRecord> >
baseGlyphsZ; /* Offset to Base Glyph records. */
LOffsetTo<UnsizedArrayOf<LayerRecord> >
layersZ; /* Offset to Layer Records */
HBUINT16 numLayers; /* Number of Layer Records */
public:
DEFINE_SIZE_STATIC (14);
};

View File

@ -79,12 +79,12 @@ typedef enum { /*< flags >*/
/*
* Color Palette
* http://www.microsoft.com/typography/otspec/cpal.htm
* CPAL -- Color Palette
* https://docs.microsoft.com/en-us/typography/opentype/spec/cpal
*/
#define HB_OT_TAG_CPAL HB_TAG('C','P','A','L')
namespace OT {
@ -92,35 +92,44 @@ struct CPALV1Tail
{
friend struct CPAL;
inline bool sanitize (hb_sanitize_context_t *c, unsigned int palettes) const
inline bool
sanitize (hb_sanitize_context_t *c, const void *base, unsigned int palettes) const
{
TRACE_SANITIZE (this);
return_trace (
c->check_struct (this) &&
c->check_array ((const void*) &paletteFlags, sizeof (HBUINT32), palettes) &&
c->check_array ((const void*) &paletteLabel, sizeof (HBUINT16), palettes) &&
c->check_array ((const void*) &paletteEntryLabel, sizeof (HBUINT16), palettes));
return_trace (c->check_struct (this) &&
(base+paletteFlagsZ).sanitize (c, palettes) &&
(base+paletteLabelZ).sanitize (c, palettes) &&
(base+paletteEntryLabelZ).sanitize (c, palettes));
}
private:
inline hb_ot_color_palette_flags_t
get_palette_flags (const void *base, unsigned int palette) const
{
const HBUINT32* flags = &paletteFlags (base);
return (hb_ot_color_palette_flags_t) (uint32_t) flags[palette];
// range checked at the CPAL caller
return (hb_ot_color_palette_flags_t) (uint32_t) (base+paletteFlagsZ)[palette];
}
inline unsigned int
get_palette_name_id (const void *base, unsigned int palette) const
{
const HBUINT16* name_ids = &paletteLabel (base);
return name_ids[palette];
// range checked at the CPAL caller
return (base+paletteLabelZ)[palette];
}
protected:
LOffsetTo<HBUINT32> paletteFlags;
LOffsetTo<HBUINT16> paletteLabel;
LOffsetTo<HBUINT16> paletteEntryLabel;
LOffsetTo<UnsizedArrayOf<HBUINT32> >
paletteFlagsZ; /* Offset from the beginning of CPAL table to
* the Palette Type Array. Set to 0 if no array
* is provided. */
LOffsetTo<UnsizedArrayOf<HBUINT16> >
paletteLabelZ; /* Offset from the beginning of CPAL table to
* the Palette Labels Array. Set to 0 if no
* array is provided. */
LOffsetTo<UnsizedArrayOf<HBUINT16> >
paletteEntryLabelZ; /* Offset from the beginning of CPAL table to
* the Palette Entry Label Array. Set to 0
* if no array is provided. */
public:
DEFINE_SIZE_STATIC (12);
};
@ -134,13 +143,14 @@ struct CPAL
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!(c->check_struct (this) && // This checks colorRecordIndicesX sanity also, see #get_size
c->check_array ((const void*) &colorRecordsZ, sizeof (BGRAColor), numColorRecords)))
if (unlikely (!(c->check_struct (this) && // it checks colorRecordIndices also
// see #get_size
(this+colorRecordsZ).sanitize (c, numColorRecords))))
return_trace (false);
// Check for indices sanity so no need for doing it runtime
for (unsigned int i = 0; i < numPalettes; ++i)
if (colorRecordIndicesX[i] + numPaletteEntries > numColorRecords)
if (unlikely (colorRecordIndicesZ[i] + numPaletteEntries > numColorRecords))
return_trace (false);
// If version is zero, we are done here; otherwise we need to check tail also
@ -148,7 +158,7 @@ struct CPAL
return_trace (true);
const CPALV1Tail &v1 = StructAfter<CPALV1Tail> (*this);
return_trace (v1.sanitize (c, numPalettes));
return_trace (likely (v1.sanitize (c, this, numPalettes)));
}
inline unsigned int get_size (void) const
@ -158,7 +168,7 @@ struct CPAL
inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette) const
{
if (version == 0 || palette >= numPalettes)
if (unlikely (version == 0 || palette >= numPalettes))
return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
@ -167,7 +177,7 @@ struct CPAL
inline unsigned int get_palette_name_id (unsigned int palette) const
{
if (version == 0 || palette >= numPalettes)
if (unlikely (version == 0 || palette >= numPalettes))
return 0xFFFF;
const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
@ -179,27 +189,33 @@ struct CPAL
return numPalettes;
}
inline hb_ot_color_t get_color_record_argb (unsigned int color_index, unsigned int palette) const
inline hb_ot_color_t
get_color_record_argb (unsigned int color_index, unsigned int palette) const
{
if (color_index >= numPaletteEntries || palette >= numPalettes)
if (unlikely (color_index >= numPaletteEntries || palette >= numPalettes))
return 0;
const BGRAColor* records = &colorRecordsZ(this);
// No need for more range check as it is already done on #sanitize
return records[colorRecordIndicesX[palette] + color_index];
const UnsizedArrayOf<BGRAColor>& color_records = this+colorRecordsZ;
return color_records[colorRecordIndicesZ[palette] + color_index];
}
protected:
HBUINT16 version;
HBUINT16 version; /* Table version number */
/* Version 0 */
HBUINT16 numPaletteEntries;
HBUINT16 numPalettes;
HBUINT16 numColorRecords;
LOffsetTo<HBUINT32> colorRecordsZ;
HBUINT16 colorRecordIndicesX[VAR]; // VAR=numPalettes
/*CPALV1Tail v1[VAR];*/
HBUINT16 numPaletteEntries; /* Number of palette entries in each palette. */
HBUINT16 numPalettes; /* Number of palettes in the table. */
HBUINT16 numColorRecords; /* Total number of color records, combined for
* all palettes. */
LOffsetTo<UnsizedArrayOf<BGRAColor> >
colorRecordsZ; /* Offset from the beginning of CPAL table to
* the first ColorRecord. */
UnsizedArrayOf<HBUINT16>
colorRecordIndicesZ; /* Index of each palettes first color record in
* the combined color record array. */
/*CPALV1Tail v1;*/
public:
DEFINE_SIZE_ARRAY (12, colorRecordIndicesX);
DEFINE_SIZE_ARRAY (12, colorRecordIndicesZ);
};
} /* namespace OT */

View File

@ -0,0 +1,153 @@
/*
* Copyright © 2018 Ebrahim Byagowi
*
* 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.
*/
#ifndef HB_OT_COLOR_SBIX_TABLE_HH
#define HB_OT_COLOR_SBIX_TABLE_HH
#include "hb-open-type-private.hh"
/*
* sbix -- Standard Bitmap Graphics
* https://docs.microsoft.com/en-us/typography/opentype/spec/sbix
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6sbix.html
*/
#define HB_OT_TAG_sbix HB_TAG('s','b','i','x')
namespace OT {
struct SBIXGlyph
{
HBINT16 xOffset; /* The horizontal (x-axis) offset from the left
* edge of the graphic to the glyphs origin.
* That is, the x-coordinate of the point on the
* baseline at the left edge of the glyph. */
HBINT16 yOffset; /* The vertical (y-axis) offset from the bottom
* edge of the graphic to the glyphs origin.
* That is, the y-coordinate of the point on the
* baseline at the left edge of the glyph. */
Tag graphicType; /* Indicates the format of the embedded graphic
* data: one of 'jpg ', 'png ' or 'tiff', or the
* special format 'dupe'. */
UnsizedArrayOf<HBUINT8>
data; /* The actual embedded graphic data. The total
* length is inferred from sequential entries in
* the glyphDataOffsets array and the fixed size
* (8 bytes) of the preceding fields. */
public:
DEFINE_SIZE_ARRAY (8, data);
};
struct SBIXStrike
{
friend struct sbix;
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
imageOffsetsZ.sanitize_shallow (c, c->num_glyphs + 1));
}
protected:
HBUINT16 ppem; /* The PPEM size for which this strike was designed. */
HBUINT16 resolution; /* The device pixel density (in PPI) for which this
* strike was designed. (E.g., 96 PPI, 192 PPI.) */
UnsizedArrayOf<LOffsetTo<SBIXGlyph> >
imageOffsetsZ; /* Offset from the beginning of the strike data header
* to bitmap data for an individual glyph ID. */
public:
DEFINE_SIZE_STATIC (8);
};
struct sbix
{
static const hb_tag_t tableTag = HB_OT_TAG_sbix;
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) && strikes.sanitize (c, this)));
}
struct accelerator_t
{
inline void init (hb_face_t *face)
{
num_glyphs = hb_face_get_glyph_count (face);
OT::Sanitizer<OT::sbix> sanitizer;
sanitizer.set_num_glyphs (num_glyphs);
sbix_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_sbix));
sbix_len = hb_blob_get_length (sbix_blob);
sbix_table = sbix_blob->as<OT::sbix> ();
}
inline void fini (void)
{
hb_blob_destroy (sbix_blob);
}
inline void dump (void (*callback) (const uint8_t* data, unsigned int length,
unsigned int group, unsigned int gid)) const
{
for (unsigned group = 0; group < sbix_table->strikes.len; ++group)
{
const SBIXStrike &strike = sbix_table->strikes[group](sbix_table);
for (unsigned int glyph = 0; glyph < num_glyphs; ++glyph)
if (strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] > 0)
{
const SBIXGlyph &sbixGlyph = strike.imageOffsetsZ[glyph]((const void *) &strike);
callback ((const uint8_t*) &sbixGlyph.data,
strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] - 8,
group, glyph);
}
}
}
private:
hb_blob_t *sbix_blob;
const sbix *sbix_table;
unsigned int sbix_len;
unsigned int num_glyphs;
};
protected:
HBUINT16 version; /* Table version number — set to 1 */
HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines.
* Bits 2 to 15: reserved (set to 0). */
LArrayOf<LOffsetTo<SBIXStrike> >
strikes; /* Offsets from the beginning of the 'sbix'
* table to data for each individual bitmap strike. */
public:
DEFINE_SIZE_ARRAY (8, strikes);
};
} /* namespace OT */
#endif /* HB_OT_COLOR_SBIX_TABLE_HH */

View File

@ -0,0 +1,145 @@
/*
* Copyright © 2018 Ebrahim Byagowi
*
* 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.
*/
#ifndef HB_OT_COLOR_SVG_TABLE_HH
#define HB_OT_COLOR_SVG_TABLE_HH
#include "hb-open-type-private.hh"
/*
* SVG -- SVG (Scalable Vector Graphics)
* https://docs.microsoft.com/en-us/typography/opentype/spec/svg
*/
#define HB_OT_TAG_SVG HB_TAG('S','V','G',' ')
namespace OT {
struct SVGDocumentIndexEntry
{
friend struct SVG;
inline bool sanitize (hb_sanitize_context_t *c, const void* base) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
(base+svgDoc).sanitize (c, svgDocLength));
}
protected:
HBUINT16 startGlyphID; /* The first glyph ID in the range described by
* this index entry. */
HBUINT16 endGlyphID; /* The last glyph ID in the range described by
* this index entry. Must be >= startGlyphID. */
LOffsetTo<UnsizedArrayOf<HBUINT8> >
svgDoc; /* Offset from the beginning of the SVG Document Index
* to an SVG document. Must be non-zero. */
HBUINT32 svgDocLength; /* Length of the SVG document.
* Must be non-zero. */
public:
DEFINE_SIZE_STATIC (12);
};
struct SVGDocumentIndex
{
friend struct SVG;
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
entries.sanitize (c, this));
}
protected:
ArrayOf<SVGDocumentIndexEntry>
entries; /* Array of SVG Document Index Entries. */
public:
DEFINE_SIZE_ARRAY (2, entries);
};
struct SVG
{
static const hb_tag_t tableTag = HB_OT_TAG_SVG;
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
(this+svgDocIndex).sanitize (c)));
}
struct accelerator_t
{
inline void init (hb_face_t *face)
{
OT::Sanitizer<OT::SVG> sanitizer;
svg_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_SVG));
svg_len = hb_blob_get_length (svg_blob);
svg = svg_blob->as<OT::SVG> ();
}
inline void fini (void)
{
hb_blob_destroy (svg_blob);
}
inline void
dump (void (*callback) (const uint8_t* data, unsigned int length,
unsigned int start_glyph, unsigned int end_glyph)) const
{
const SVGDocumentIndex &index = svg+svg->svgDocIndex;
const ArrayOf<SVGDocumentIndexEntry> &entries = index.entries;
for (unsigned int i = 0; i < entries.len; ++i)
{
const SVGDocumentIndexEntry &entry = entries[i];
callback ((const uint8_t*) &entry.svgDoc (&index), entry.svgDocLength,
entry.startGlyphID, entry.endGlyphID);
}
}
private:
hb_blob_t *svg_blob;
const SVG *svg;
unsigned int svg_len;
};
protected:
HBUINT16 version; /* Table version (starting at 0). */
LOffsetTo<SVGDocumentIndex>
svgDocIndex; /* Offset (relative to the start of the SVG table) to the
* SVG Documents Index. Must be non-zero. */
HBUINT32 reserved; /* Set to 0. */
public:
DEFINE_SIZE_STATIC (10);
};
} /* namespace OT */
#endif /* HB_OT_COLOR_SVG_TABLE_HH */

View File

@ -143,7 +143,7 @@ hb_ot_get_glyph_h_kerning (hb_font_t *font,
}
static hb_bool_t
hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
hb_ot_get_glyph_extents (hb_font_t *font,
void *font_data,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents,
@ -184,7 +184,7 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
}
static hb_bool_t
hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED,
hb_ot_get_font_h_extents (hb_font_t *font,
void *font_data,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
@ -198,7 +198,7 @@ hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED,
}
static hb_bool_t
hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED,
hb_ot_get_font_v_extents (hb_font_t *font,
void *font_data,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
@ -217,7 +217,12 @@ static hb_font_funcs_t *static_ot_funcs = nullptr;
static
void free_static_ot_funcs (void)
{
hb_font_funcs_destroy (static_ot_funcs);
retry:
hb_font_funcs_t *ot_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs);
if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, ot_funcs, nullptr))
goto retry;
hb_font_funcs_destroy (ot_funcs);
}
#endif

View File

@ -38,8 +38,8 @@ namespace OT {
/*
* loca -- Index to Location
* https://docs.microsoft.com/en-us/typography/opentype/spec/loca
*/
#define HB_OT_TAG_loca HB_TAG('l','o','c','a')
@ -56,15 +56,15 @@ struct loca
}
protected:
HBUINT8 dataX[VAR]; /* Location data. */
DEFINE_SIZE_ARRAY (0, dataX);
HBUINT8 dataZ[VAR]; /* Location data. */
DEFINE_SIZE_ARRAY (0, dataZ);
};
/*
* glyf -- TrueType Glyph Data
* https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
*/
#define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
@ -88,9 +88,9 @@ struct glyf
bool success = true;
bool use_short_loca = false;
if (hb_subset_glyf_and_loca (plan, &use_short_loca, &glyf_prime, &loca_prime)) {
success = success && hb_subset_plan_add_table (plan, HB_OT_TAG_glyf, glyf_prime);
success = success && hb_subset_plan_add_table (plan, HB_OT_TAG_loca, loca_prime);
success = success && _add_head_and_set_loca_version (plan->source, use_short_loca, plan->dest);
success = success && plan->add_table (HB_OT_TAG_glyf, glyf_prime);
success = success && plan->add_table (HB_OT_TAG_loca, loca_prime);
success = success && _add_head_and_set_loca_version (plan, use_short_loca);
} else {
success = false;
}
@ -101,9 +101,9 @@ struct glyf
}
static bool
_add_head_and_set_loca_version (hb_face_t *source, bool use_short_loca, hb_face_t *dest)
_add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
{
hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (hb_face_reference_table (source, HB_OT_TAG_head));
hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_head));
hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
hb_blob_destroy (head_blob);
@ -112,7 +112,7 @@ struct glyf
OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1);
bool success = hb_subset_face_add_table (dest, HB_OT_TAG_head, head_prime_blob);
bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
hb_blob_destroy (head_prime_blob);
return success;
@ -134,18 +134,20 @@ struct glyf
struct CompositeGlyphHeader
{
static const uint16_t ARG_1_AND_2_ARE_WORDS = 0x0001;
static const uint16_t ARGS_ARE_XY_VALUES = 0x0002;
static const uint16_t ROUND_XY_TO_GRID = 0x0004;
static const uint16_t WE_HAVE_A_SCALE = 0x0008;
static const uint16_t MORE_COMPONENTS = 0x0020;
static const uint16_t WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
static const uint16_t WE_HAVE_A_TWO_BY_TWO = 0x0080;
static const uint16_t WE_HAVE_INSTRUCTIONS = 0x0100;
static const uint16_t USE_MY_METRICS = 0x0200;
static const uint16_t OVERLAP_COMPOUND = 0x0400;
static const uint16_t SCALED_COMPONENT_OFFSET = 0x0800;
static const uint16_t UNSCALED_COMPONENT_OFFSET = 0x1000;
enum composite_glyph_flag_t {
ARG_1_AND_2_ARE_WORDS = 0x0001,
ARGS_ARE_XY_VALUES = 0x0002,
ROUND_XY_TO_GRID = 0x0004,
WE_HAVE_A_SCALE = 0x0008,
MORE_COMPONENTS = 0x0020,
WE_HAVE_AN_X_AND_Y_SCALE = 0x0040,
WE_HAVE_A_TWO_BY_TWO = 0x0080,
WE_HAVE_INSTRUCTIONS = 0x0100,
USE_MY_METRICS = 0x0200,
OVERLAP_COMPOUND = 0x0400,
SCALED_COMPONENT_OFFSET = 0x0800,
UNSCALED_COMPONENT_OFFSET = 0x1000
};
HBUINT16 flags;
HBUINT16 glyphIndex;
@ -232,11 +234,13 @@ struct glyf
{
inline void init (hb_face_t *face)
{
memset (this, 0, sizeof (accelerator_t));
hb_blob_t *head_blob = Sanitizer<head>().sanitize (face->reference_table (HB_OT_TAG_head));
const head *head_table = Sanitizer<head>::lock_instance (head_blob);
if ((unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
const head *head_table = head_blob->as<head> ();
if (head_table == &Null(head) || (unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
{
/* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
/* head table is not present, or in an unknown format. Leave num_glyphs=0, that takes care of disabling us. */
hb_blob_destroy (head_blob);
return;
}
@ -244,9 +248,9 @@ struct glyf
hb_blob_destroy (head_blob);
loca_blob = Sanitizer<loca>().sanitize (face->reference_table (HB_OT_TAG_loca));
loca_table = Sanitizer<loca>::lock_instance (loca_blob);
loca_table = loca_blob->as<loca> ();
glyf_blob = Sanitizer<glyf>().sanitize (face->reference_table (HB_OT_TAG_glyf));
glyf_table = Sanitizer<glyf>::lock_instance (glyf_blob);
glyf_table = glyf_blob->as<glyf> ();
num_glyphs = MAX (1u, hb_blob_get_length (loca_blob) / (short_offset ? 2 : 4)) - 1;
glyf_len = hb_blob_get_length (glyf_blob);
@ -266,6 +270,9 @@ struct glyf
inline bool get_composite (hb_codepoint_t glyph,
CompositeGlyphHeader::Iterator *composite /* OUT */) const
{
if (this->glyf_table == &Null(glyf) || !num_glyphs)
return false;
unsigned int start_offset, end_offset;
if (!get_offsets (glyph, &start_offset, &end_offset))
return false; /* glyph not found */
@ -275,16 +282,18 @@ struct glyf
composite);
}
enum simple_glyph_flag_t {
FLAG_X_SHORT = 0x02,
FLAG_Y_SHORT = 0x04,
FLAG_REPEAT = 0x08,
FLAG_X_SAME = 0x10,
FLAG_Y_SAME = 0x20
};
/* based on FontTools _g_l_y_f.py::trim */
inline bool remove_padding(unsigned int start_offset,
unsigned int *end_offset) const
{
static const int FLAG_X_SHORT = 0x02;
static const int FLAG_Y_SHORT = 0x04;
static const int FLAG_REPEAT = 0x08;
static const int FLAG_X_SAME = 0x10;
static const int FLAG_Y_SAME = 0x20;
if (*end_offset - start_offset < GlyphHeader::static_size)
return true;
@ -368,13 +377,13 @@ struct glyf
if (short_offset)
{
const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataX;
const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ;
*start_offset = 2 * offsets[glyph];
*end_offset = 2 * offsets[glyph + 1];
}
else
{
const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataX;
const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ;
*start_offset = offsets[glyph];
*end_offset = offsets[glyph + 1];
@ -411,7 +420,7 @@ struct glyf
} while (composite_it.move_to_next());
if ( (uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
*instruction_start = ((char *) last - (char *) glyf_table->dataX) + last->get_size();
*instruction_start = ((char *) last - (char *) glyf_table->dataZ) + last->get_size();
else
*instruction_start = end_offset;
*instruction_end = end_offset;
@ -424,9 +433,23 @@ struct glyf
else
{
unsigned int instruction_length_offset = start_offset + GlyphHeader::static_size + 2 * num_contours;
if (unlikely (instruction_length_offset + 2 > end_offset))
{
DEBUG_MSG(SUBSET, nullptr, "Glyph size is too short, missing field instructionLength.");
return false;
}
const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (glyf_table, instruction_length_offset);
*instruction_start = instruction_length_offset + 2;
*instruction_end = *instruction_start + (uint16_t) instruction_length;
unsigned int start = instruction_length_offset + 2;
unsigned int end = start + (uint16_t) instruction_length;
if (unlikely (end > end_offset)) // Out of bounds of the current glyph
{
DEBUG_MSG(SUBSET, nullptr, "The instructions array overruns the glyph's boundaries.");
return false;
}
*instruction_start = start;
*instruction_end = end;
}
return true;
}
@ -462,9 +485,9 @@ struct glyf
};
protected:
HBUINT8 dataX[VAR]; /* Glyphs data. */
HBUINT8 dataZ[VAR]; /* Glyphs data. */
DEFINE_SIZE_ARRAY (0, dataX);
DEFINE_SIZE_ARRAY (0, dataZ);
};
} /* namespace OT */

View File

@ -31,16 +31,16 @@
#include "hb-open-type-private.hh"
/*
* head -- Font Header
* https://docs.microsoft.com/en-us/typography/opentype/spec/head
*/
#define HB_OT_TAG_head HB_TAG('h','e','a','d')
namespace OT {
/*
* head -- Font Header
*/
#define HB_OT_TAG_head HB_TAG('h','e','a','d')
struct head
{
friend struct OffsetTable;

View File

@ -29,18 +29,19 @@
#include "hb-open-type-private.hh"
/*
* hhea -- Horizontal Header
* https://docs.microsoft.com/en-us/typography/opentype/spec/hhea
* vhea -- Vertical Header
* https://docs.microsoft.com/en-us/typography/opentype/spec/vhea
*/
#define HB_OT_TAG_hhea HB_TAG('h','h','e','a')
#define HB_OT_TAG_vhea HB_TAG('v','h','e','a')
namespace OT {
/*
* hhea -- The Horizontal Header Table
* vhea -- The Vertical Header Table
*/
#define HB_OT_TAG_hhea HB_TAG('h','h','e','a')
#define HB_OT_TAG_vhea HB_TAG('v','h','e','a')
template <typename T>
struct _hea
{

View File

@ -31,20 +31,21 @@
#include "hb-ot-hhea-table.hh"
#include "hb-ot-os2-table.hh"
#include "hb-ot-var-hvar-table.hh"
#include "hb-subset-plan.hh"
/*
* hmtx -- Horizontal Metrics
* https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx
* vmtx -- Vertical Metrics
* https://docs.microsoft.com/en-us/typography/opentype/spec/vmtx
*/
#define HB_OT_TAG_hmtx HB_TAG('h','m','t','x')
#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
namespace OT {
/*
* hmtx -- The Horizontal Metrics Table
* vmtx -- The Vertical Metrics Table
*/
#define HB_OT_TAG_hmtx HB_TAG('h','m','t','x')
#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
struct LongMetric
{
UFWORD advance; /* Advance width/height. */
@ -80,7 +81,7 @@ struct hmtxvmtx
H *table = (H *) hb_blob_get_data (dest_blob, &length);
table->numberOfLongMetrics.set (num_hmetrics);
bool result = hb_subset_plan_add_table (plan, H::tableTag, dest_blob);
bool result = plan->add_table (H::tableTag, dest_blob);
hb_blob_destroy (dest_blob);
return result;
@ -93,7 +94,7 @@ struct hmtxvmtx
/* All the trailing glyphs with the same advance can use one LongMetric
* and just keep LSB */
hb_prealloced_array_t<hb_codepoint_t> &gids = plan->gids_to_retain_sorted;
hb_vector_t<hb_codepoint_t> &gids = plan->glyphs;
unsigned int num_advances = gids.len;
unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]);
while (num_advances > 1
@ -118,6 +119,8 @@ struct hmtxvmtx
LongMetric * old_metrics = (LongMetric *) source_table;
FWORD *lsbs = (FWORD *) (old_metrics + _mtx.num_advances);
char * dest_pos = (char *) dest;
bool failed = false;
for (unsigned int i = 0; i < gids.len; i++)
{
/* the last metric or the one for gids[i] */
@ -138,6 +141,13 @@ struct hmtxvmtx
}
else
{
if (gids[i] >= _mtx.num_metrics)
{
DEBUG_MSG(SUBSET, nullptr, "gid %d is >= number of source metrics %d",
gids[i], _mtx.num_metrics);
failed = true;
break;
}
FWORD src_lsb = *(lsbs + gids[i] - _mtx.num_advances);
if (i < num_advances)
{
@ -157,7 +167,7 @@ struct hmtxvmtx
_mtx.fini ();
// Amend header num hmetrics
if (unlikely (!subset_update_header (plan, num_advances)))
if (failed || unlikely (!subset_update_header (plan, num_advances)))
{
free (dest);
return false;
@ -168,7 +178,7 @@ struct hmtxvmtx
HB_MEMORY_MODE_READONLY,
dest,
free);
bool success = hb_subset_plan_add_table (plan, T::tableTag, result);
bool success = plan->add_table (T::tableTag, result);
hb_blob_destroy (result);
return success;
}
@ -186,7 +196,7 @@ struct hmtxvmtx
if (T::os2Tag)
{
hb_blob_t *os2_blob = Sanitizer<os2> ().sanitize (face->reference_table (T::os2Tag));
const os2 *os2_table = Sanitizer<os2>::lock_instance (os2_blob);
const os2 *os2_table = os2_blob->as<os2> ();
#define USE_TYPO_METRICS (1u<<7)
if (0 != (os2_table->fsSelection & USE_TYPO_METRICS))
{
@ -199,7 +209,7 @@ struct hmtxvmtx
}
hb_blob_t *_hea_blob = Sanitizer<H> ().sanitize (face->reference_table (H::tableTag));
const H *_hea_table = Sanitizer<H>::lock_instance (_hea_blob);
const H *_hea_table = _hea_blob->as<H> ();
num_advances = _hea_table->numberOfLongMetrics;
if (!got_font_extents)
{
@ -228,10 +238,10 @@ struct hmtxvmtx
hb_blob_destroy (blob);
blob = hb_blob_get_empty ();
}
table = Sanitizer<hmtxvmtx>::lock_instance (blob);
table = blob->as<hmtxvmtx> ();
var_blob = Sanitizer<HVARVVAR> ().sanitize (face->reference_table (T::variationsTag));
var_table = Sanitizer<HVARVVAR>::lock_instance (var_blob);
var_table = var_blob->as<HVARVVAR> ();
}
inline void fini (void)

View File

@ -29,15 +29,17 @@
#include "hb-open-type-private.hh"
namespace OT {
/*
* kern -- Kerning
* https://docs.microsoft.com/en-us/typography/opentype/spec/kern
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html
*/
#define HB_OT_TAG_kern HB_TAG('k','e','r','n')
namespace OT {
struct hb_glyph_pair_t
{
hb_codepoint_t left;
@ -205,7 +207,7 @@ struct KernSubTableWrapper
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (thiz()) &&
thiz()->length >= thiz()->min_size &&
thiz()->length >= T::min_size &&
c->check_array (thiz(), 1, thiz()->length) &&
thiz()->subtable.sanitize (c, thiz()->format));
}
@ -361,8 +363,8 @@ struct kern
inline void init (hb_face_t *face)
{
blob = Sanitizer<kern>().sanitize (face->reference_table (HB_OT_TAG_kern));
table = Sanitizer<kern>::lock_instance (blob);
table_length = hb_blob_get_length (blob);
table = blob->as<kern> ();
table_length = blob->length;
}
inline void fini (void)
{

View File

@ -36,7 +36,8 @@ namespace OT {
#define NOT_INDEXED ((unsigned int) -1)
/*
* BASE -- The BASE Table
* BASE -- Baseline
* https://docs.microsoft.com/en-us/typography/opentype/spec/base
*/
struct BaseCoordFormat1

View File

@ -165,7 +165,7 @@ struct RangeRecord
public:
DEFINE_SIZE_STATIC (6);
};
DEFINE_NULL_DATA (RangeRecord, "\000\001");
DEFINE_NULL_DATA (OT, RangeRecord, "\000\001");
struct IndexArray : ArrayOf<Index>
@ -225,7 +225,7 @@ struct LangSys
public:
DEFINE_SIZE_ARRAY (6, featureIndex);
};
DEFINE_NULL_DATA (LangSys, "\0\0\xFF\xFF");
DEFINE_NULL_DATA (OT, LangSys, "\0\0\xFF\xFF");
struct Script
@ -270,7 +270,7 @@ struct Script
typedef RecordListOf<Script> ScriptList;
/* http://www.microsoft.com/typography/otspec/features_pt.htm#size */
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
struct FeatureParamsSize
{
inline bool sanitize (hb_sanitize_context_t *c) const
@ -292,7 +292,7 @@ struct FeatureParamsSize
*
* The specification for this feature tag is in the "OpenType Layout Tag
* Registry". You can see a copy of this at:
* http://partners.adobe.com/public/developer/opentype/index_tag8.html#size
* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size
*
* Here is one set of rules to determine if the 'size' feature is built
* correctly, or as by the older versions of MakeOTF. You may be able to do
@ -382,7 +382,7 @@ struct FeatureParamsSize
DEFINE_SIZE_STATIC (10);
};
/* http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx */
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#ssxx */
struct FeatureParamsStylisticSet
{
inline bool sanitize (hb_sanitize_context_t *c) const
@ -398,7 +398,7 @@ struct FeatureParamsStylisticSet
* added to the end of this Feature Parameters
* table in the future. */
HBUINT16 uiNameID; /* The 'name' table name ID that specifies a
NameID uiNameID; /* The 'name' table name ID that specifies a
* string (or strings, for multiple languages)
* for a user-interface label for this
* feature. The values of uiLabelNameId and
@ -416,7 +416,7 @@ struct FeatureParamsStylisticSet
DEFINE_SIZE_STATIC (4);
};
/* http://www.microsoft.com/typography/otspec/features_ae.htm#cv01-cv99 */
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99 */
struct FeatureParamsCharacterVariants
{
inline bool sanitize (hb_sanitize_context_t *c) const
@ -427,29 +427,29 @@ struct FeatureParamsCharacterVariants
}
HBUINT16 format; /* Format number is set to 0. */
HBUINT16 featUILableNameID; /* The name table name ID that
NameID featUILableNameID; /* The name table name ID that
* specifies a string (or strings,
* for multiple languages) for a
* user-interface label for this
* feature. (May be nullptr.) */
HBUINT16 featUITooltipTextNameID;/* The name table name ID that
NameID featUITooltipTextNameID;/* The name table name ID that
* specifies a string (or strings,
* for multiple languages) that an
* application can use for tooltip
* text for this feature. (May be
* nullptr.) */
HBUINT16 sampleTextNameID; /* The name table name ID that
NameID sampleTextNameID; /* The name table name ID that
* specifies sample text that
* illustrates the effect of this
* feature. (May be nullptr.) */
HBUINT16 numNamedParameters; /* Number of named parameters. (May
* be zero.) */
HBUINT16 firstParamUILabelNameID;/* The first name table name ID
NameID firstParamUILabelNameID;/* The first name table name ID
* used to specify strings for
* user-interface labels for the
* feature parameters. (Must be zero
* if numParameters is zero.) */
ArrayOf<UINT24>
ArrayOf<HBUINT24>
characters; /* Array of the Unicode Scalar Value
* of the characters for which this
* feature provides glyph variants.
@ -716,7 +716,7 @@ struct CoverageFormat1
template <typename set_t>
inline bool add_coverage (set_t *glyphs) const {
return glyphs->add_sorted_array (glyphArray.array, glyphArray.len);
return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len);
}
public:
@ -1272,7 +1272,7 @@ struct VarRegionList
if (unlikely (region_index >= regionCount))
return 0.;
const VarRegionAxis *axes = axesZ + (region_index * axisCount);
const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
float v = 1.;
unsigned int count = axisCount;
@ -1280,7 +1280,7 @@ struct VarRegionList
{
int coord = i < coord_len ? coords[i] : 0;
float factor = axes[i].evaluate (coord);
if (factor == 0.)
if (factor == 0.f)
return 0.;
v *= factor;
}
@ -1291,14 +1291,14 @@ struct VarRegionList
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
c->check_array (axesZ, axesZ[0].static_size,
(unsigned int) axisCount * (unsigned int) regionCount));
axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount));
}
protected:
HBUINT16 axisCount;
HBUINT16 regionCount;
VarRegionAxis axesZ[VAR];
UnsizedArrayOf<VarRegionAxis>
axesZ;
public:
DEFINE_SIZE_ARRAY (4, axesZ);
};
@ -1330,13 +1330,13 @@ struct VarData
const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row);
for (; i < scount; i++)
{
float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count);
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
delta += scalar * *scursor++;
}
const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
for (; i < count; i++)
{
float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count);
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
delta += scalar * *bcursor++;
}
@ -1357,7 +1357,7 @@ struct VarData
HBUINT16 itemCount;
HBUINT16 shortCount;
ArrayOf<HBUINT16> regionIndices;
HBUINT8 bytesX[VAR];
HBUINT8 bytesX[VAR];
public:
DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX);
};
@ -1465,7 +1465,7 @@ struct ConditionSet
{
unsigned int count = conditions.len;
for (unsigned int i = 0; i < count; i++)
if (!(this+conditions.array[i]).evaluate (coords, coord_len))
if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len))
return false;
return true;
}
@ -1506,7 +1506,7 @@ struct FeatureTableSubstitution
unsigned int count = substitutions.len;
for (unsigned int i = 0; i < count; i++)
{
const FeatureTableSubstitutionRecord &record = substitutions.array[i];
const FeatureTableSubstitutionRecord &record = substitutions.arrayZ[i];
if (record.featureIndex == feature_index)
return &(this+record.feature);
}
@ -1559,7 +1559,7 @@ struct FeatureVariations
unsigned int count = varRecords.len;
for (unsigned int i = 0; i < count; i++)
{
const FeatureVariationRecord &record = varRecords.array[i];
const FeatureVariationRecord &record = varRecords.arrayZ[i];
if ((this+record.conditions).evaluate (coords, coord_len))
{
*index = i;

View File

@ -333,7 +333,8 @@ struct MarkGlyphSets
/*
* GDEF -- The Glyph Definition Table
* GDEF -- Glyph Definition
* https://docs.microsoft.com/en-us/typography/opentype/spec/gdef
*/
struct GDEF

View File

@ -262,7 +262,7 @@ struct AnchorFormat2
hb_font_t *font = c->font;
unsigned int x_ppem = font->x_ppem;
unsigned int y_ppem = font->y_ppem;
hb_position_t cx, cy;
hb_position_t cx = 0, cy = 0;
hb_bool_t ret;
ret = (x_ppem || y_ppem) &&
@ -1497,7 +1497,8 @@ struct PosLookup : Lookup
typedef OffsetListOf<PosLookup> PosLookupList;
/*
* GPOS -- The Glyph Positioning Table
* GPOS -- Glyph Positioning
* https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
*/
struct GPOS : GSUBGPOS

View File

@ -269,7 +269,7 @@ struct Sequence
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
TRACE_COLLECT_GLYPHS (this);
c->output->add_array (substitute.array, substitute.len);
c->output->add_array (substitute.arrayZ, substitute.len);
}
inline bool apply (hb_ot_apply_context_t *c) const
@ -281,7 +281,7 @@ struct Sequence
* as a "multiplied" substitution. */
if (unlikely (count == 1))
{
c->replace_glyph (substitute.array[0]);
c->replace_glyph (substitute.arrayZ[0]);
return_trace (true);
}
/* Spec disallows this, but Uniscribe allows it.
@ -297,7 +297,7 @@ struct Sequence
for (unsigned int i = 0; i < count; i++) {
_hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
c->output_glyph_for_component (substitute.array[i], klass);
c->output_glyph_for_component (substitute.arrayZ[i], klass);
}
c->buffer->skip_glyph ();
@ -480,7 +480,7 @@ struct AlternateSubstFormat1
if (unlikely (iter.get_coverage () >= count))
break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
c->output->add_array (alt_set.array, alt_set.len);
c->output->add_array (alt_set.arrayZ, alt_set.len);
}
}
@ -611,7 +611,7 @@ struct Ligature
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
TRACE_COLLECT_GLYPHS (this);
c->input->add_array (component.array, component.len ? component.len - 1 : 0);
c->input->add_array (component.arrayZ, component.len ? component.len - 1 : 0);
c->output->add (ligGlyph);
}
@ -979,7 +979,7 @@ struct ReverseChainSingleSubstFormat1
const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
count = substitute.len;
c->output->add_array (substitute.array, substitute.len);
c->output->add_array (substitute.arrayZ, substitute.len);
}
inline const Coverage &get_coverage (void) const
@ -1007,11 +1007,11 @@ struct ReverseChainSingleSubstFormat1
unsigned int start_index = 0, end_index = 0;
if (match_backtrack (c,
backtrack.len, (HBUINT16 *) backtrack.array,
backtrack.len, (HBUINT16 *) backtrack.arrayZ,
match_coverage, this,
&start_index) &&
match_lookahead (c,
lookahead.len, (HBUINT16 *) lookahead.array,
lookahead.len, (HBUINT16 *) lookahead.arrayZ,
match_coverage, this,
1, &end_index))
{
@ -1156,10 +1156,13 @@ struct SubstLookup : Lookup
return_trace (dispatch (c));
}
inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const
inline hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
{
TRACE_CLOSURE (this);
c->set_recurse_func (dispatch_recurse_func<hb_closure_context_t>);
if (!c->should_visit_lookup (this_index))
return_trace (HB_VOID);
c->set_recurse_func (dispatch_closure_recurse_func);
return_trace (dispatch (c));
}
@ -1258,6 +1261,13 @@ struct SubstLookup : Lookup
template <typename context_t>
static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
{
if (!c->should_visit_lookup (lookup_index))
return HB_VOID;
return dispatch_recurse_func (c, lookup_index);
}
template <typename context_t>
inline typename context_t::return_t dispatch (context_t *c) const
{ return Lookup::dispatch<SubstLookupSubTable> (c); }
@ -1287,7 +1297,8 @@ struct SubstLookup : Lookup
typedef OffsetListOf<SubstLookup> SubstLookupList;
/*
* GSUB -- The Glyph Substitution Table
* GSUB -- Glyph Substitution
* https://docs.microsoft.com/en-us/typography/opentype/spec/gsub
*/
struct GSUB : GSUBGPOS

View File

@ -32,6 +32,7 @@
#include "hb-private.hh"
#include "hb-debug.hh"
#include "hb-buffer-private.hh"
#include "hb-map-private.hh"
#include "hb-ot-layout-gdef-table.hh"
#include "hb-set-private.hh"
@ -59,6 +60,20 @@ struct hb_closure_context_t :
return HB_VOID;
}
bool should_visit_lookup (unsigned int lookup_index)
{
if (is_lookup_done (lookup_index))
return false;
done_lookups->set (lookup_index, glyphs->get_population ());
return true;
}
bool is_lookup_done (unsigned int lookup_index)
{
// Have we visited this lookup with the current set of glyphs?
return done_lookups->get (lookup_index) == glyphs->get_population ();
}
hb_face_t *face;
hb_set_t *glyphs;
recurse_func_t recurse_func;
@ -67,14 +82,19 @@ struct hb_closure_context_t :
hb_closure_context_t (hb_face_t *face_,
hb_set_t *glyphs_,
hb_map_t *done_lookups_,
unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
face (face_),
glyphs (glyphs_),
recurse_func (nullptr),
nesting_level_left (nesting_level_left_),
debug_depth (0) {}
debug_depth (0),
done_lookups (done_lookups_) {}
void set_recurse_func (recurse_func_t func) { recurse_func = func; }
private:
hb_map_t *done_lookups;
};
@ -855,7 +875,7 @@ static inline bool ligate_input (hb_ot_apply_context_t *c,
for (unsigned int i = 1; i < count; i++)
{
while (buffer->idx < match_positions[i] && !buffer->in_error)
while (buffer->idx < match_positions[i] && buffer->successful)
{
if (!is_mark_ligature) {
unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
@ -990,7 +1010,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
match_positions[j] += delta;
}
for (unsigned int i = 0; i < lookupCount && !buffer->in_error; i++)
for (unsigned int i = 0; i < lookupCount && buffer->successful; i++)
{
unsigned int idx = lookupRecord[i].sequenceIndex;
if (idx >= count)
@ -1713,10 +1733,10 @@ struct ChainRule
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
chain_context_closure_lookup (c,
backtrack.len, backtrack.array,
input.len, input.array,
lookahead.len, lookahead.array,
lookup.len, lookup.array,
backtrack.len, backtrack.arrayZ,
input.len, input.arrayZ,
lookahead.len, lookahead.arrayZ,
lookup.len, lookup.arrayZ,
lookup_context);
}
@ -1727,10 +1747,10 @@ struct ChainRule
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
chain_context_collect_glyphs_lookup (c,
backtrack.len, backtrack.array,
input.len, input.array,
lookahead.len, lookahead.array,
lookup.len, lookup.array,
backtrack.len, backtrack.arrayZ,
input.len, input.arrayZ,
lookahead.len, lookahead.arrayZ,
lookup.len, lookup.arrayZ,
lookup_context);
}
@ -1741,10 +1761,10 @@ struct ChainRule
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
return_trace (chain_context_would_apply_lookup (c,
backtrack.len, backtrack.array,
input.len, input.array,
lookahead.len, lookahead.array, lookup.len,
lookup.array, lookup_context));
backtrack.len, backtrack.arrayZ,
input.len, input.arrayZ,
lookahead.len, lookahead.arrayZ, lookup.len,
lookup.arrayZ, lookup_context));
}
inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
@ -1754,10 +1774,10 @@ struct ChainRule
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
return_trace (chain_context_apply_lookup (c,
backtrack.len, backtrack.array,
input.len, input.array,
lookahead.len, lookahead.array, lookup.len,
lookup.array, lookup_context));
backtrack.len, backtrack.arrayZ,
input.len, input.arrayZ,
lookahead.len, lookahead.arrayZ, lookup.len,
lookup.arrayZ, lookup_context));
}
inline bool sanitize (hb_sanitize_context_t *c) const
@ -2072,10 +2092,10 @@ struct ChainContextFormat3
{this, this, this}
};
chain_context_closure_lookup (c,
backtrack.len, (const HBUINT16 *) backtrack.array,
input.len, (const HBUINT16 *) input.array + 1,
lookahead.len, (const HBUINT16 *) lookahead.array,
lookup.len, lookup.array,
backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
input.len, (const HBUINT16 *) input.arrayZ + 1,
lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
lookup.len, lookup.arrayZ,
lookup_context);
}
@ -2093,10 +2113,10 @@ struct ChainContextFormat3
{this, this, this}
};
chain_context_collect_glyphs_lookup (c,
backtrack.len, (const HBUINT16 *) backtrack.array,
input.len, (const HBUINT16 *) input.array + 1,
lookahead.len, (const HBUINT16 *) lookahead.array,
lookup.len, lookup.array,
backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
input.len, (const HBUINT16 *) input.arrayZ + 1,
lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
lookup.len, lookup.arrayZ,
lookup_context);
}
@ -2112,10 +2132,10 @@ struct ChainContextFormat3
{this, this, this}
};
return_trace (chain_context_would_apply_lookup (c,
backtrack.len, (const HBUINT16 *) backtrack.array,
input.len, (const HBUINT16 *) input.array + 1,
lookahead.len, (const HBUINT16 *) lookahead.array,
lookup.len, lookup.array, lookup_context));
backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
input.len, (const HBUINT16 *) input.arrayZ + 1,
lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
lookup.len, lookup.arrayZ, lookup_context));
}
inline const Coverage &get_coverage (void) const
@ -2139,10 +2159,10 @@ struct ChainContextFormat3
{this, this, this}
};
return_trace (chain_context_apply_lookup (c,
backtrack.len, (const HBUINT16 *) backtrack.array,
input.len, (const HBUINT16 *) input.array + 1,
lookahead.len, (const HBUINT16 *) lookahead.array,
lookup.len, lookup.array, lookup_context));
backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
input.len, (const HBUINT16 *) input.arrayZ + 1,
lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
lookup.len, lookup.arrayZ, lookup_context));
}
inline bool sanitize (hb_sanitize_context_t *c) const

View File

@ -189,7 +189,8 @@ struct JstfScript
/*
* JSTF -- The Justification Table
* JSTF -- Justification
* https://docs.microsoft.com/en-us/typography/opentype/spec/jstf
*/
struct JSTF

View File

@ -105,12 +105,12 @@ HB_INTERNAL void
hb_ot_layout_position_start (hb_font_t *font,
hb_buffer_t *buffer);
/* Should be called after all the position_lookup's are done, to finish advances. */
/* Should be called after all the position_lookup's are done, to fini advances. */
HB_INTERNAL void
hb_ot_layout_position_finish_advances (hb_font_t *font,
hb_buffer_t *buffer);
/* Should be called after hb_ot_layout_position_finish_advances, to finish offsets. */
/* Should be called after hb_ot_layout_position_finish_advances, to fini offsets. */
HB_INTERNAL void
hb_ot_layout_position_finish_offsets (hb_font_t *font,
hb_buffer_t *buffer);
@ -172,16 +172,10 @@ struct hb_ot_layout_t
const struct OT::GPOS *gpos;
/* TODO Move the following out of this struct. */
OT::hb_lazy_table_loader_t<struct OT::BASE> base;
OT::hb_lazy_table_loader_t<struct OT::COLR> colr;
OT::hb_lazy_table_loader_t<struct OT::CPAL> cpal;
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;
OT::hb_lazy_table_loader_t<struct AAT::ankr> ankr;
OT::hb_lazy_table_loader_t<struct AAT::kerx> kerx;
OT::hb_lazy_table_loader_t<struct AAT::morx> morx;
OT::hb_lazy_table_loader_t<struct AAT::trak> trak;
OT::hb_table_lazy_loader_t<struct OT::BASE> base;
OT::hb_table_lazy_loader_t<struct OT::MATH> math;
OT::hb_table_lazy_loader_t<struct OT::fvar> fvar;
OT::hb_table_lazy_loader_t<struct OT::avar> avar;
unsigned int gsub_lookup_count;
unsigned int gpos_lookup_count;
@ -309,7 +303,7 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
* processing on. */
/* Only Mn and Mc can have non-zero ccc:
* http://www.unicode.org/policies/stability_policy.html#Property_Value
* https://unicode.org/policies/stability_policy.html#Property_Value
* """
* Canonical_Combining_Class, General_Category
* All characters other than those with General_Category property values

View File

@ -30,22 +30,21 @@
#include "hb-open-type-private.hh"
#include "hb-ot-layout-private.hh"
#include "hb-ot-map-private.hh"
#include "hb-ot-layout-base-table.hh"
#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" // Just so we compile it; unused otherwise.
#include "hb-ot-name-table.hh" // Just so we compile it; unused otherwise.
// Just so we compile them; unused otherwise:
#include "hb-ot-layout-base-table.hh"
#include "hb-ot-layout-jstf-table.hh"
#include "hb-ot-color-colr-table.hh"
#include "hb-ot-color-cpal-table.hh"
#include "hb-ot-map-private.hh"
#ifndef HB_NO_VISIBILITY
const void * const OT::_hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
#endif
#include "hb-ot-color-sbix-table.hh"
#include "hb-ot-color-svg-table.hh"
#include "hb-ot-name-table.hh"
#include "hb-map-private.hh"
hb_ot_layout_t *
@ -56,24 +55,17 @@ _hb_ot_layout_create (hb_face_t *face)
return nullptr;
layout->gdef_blob = OT::Sanitizer<OT::GDEF>().sanitize (face->reference_table (HB_OT_TAG_GDEF));
layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob);
layout->gdef = layout->gdef_blob->as<OT::GDEF> ();
layout->gsub_blob = OT::Sanitizer<OT::GSUB>().sanitize (face->reference_table (HB_OT_TAG_GSUB));
layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob);
layout->gsub = layout->gsub_blob->as<OT::GSUB> ();
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);
layout->gpos = layout->gpos_blob->as<OT::GPOS> ();
layout->base.init (face);
layout->colr.init (face);
layout->cpal.init (face);
layout->math.init (face);
layout->fvar.init (face);
layout->avar.init (face);
layout->ankr.init (face);
layout->kerx.init (face);
layout->morx.init (face);
layout->trak.init (face);
{
/*
@ -81,9 +73,9 @@ _hb_ot_layout_create (hb_face_t *face)
* See this thread for why we finally had to bend in and do this:
* https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
*/
unsigned int gdef_len = hb_blob_get_length (layout->gdef_blob);
unsigned int gsub_len = hb_blob_get_length (layout->gsub_blob);
unsigned int gpos_len = hb_blob_get_length (layout->gpos_blob);
unsigned int gdef_len = layout->gdef_blob->length;
unsigned int gsub_len = layout->gsub_blob->length;
unsigned int gpos_len = layout->gpos_blob->length;
if (0
/* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
|| (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len)
@ -106,7 +98,7 @@ _hb_ot_layout_create (hb_face_t *face)
* https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
*/
if (3 == layout->gdef->get_glyph_class (5))
layout->gdef = &OT::Null(OT::GDEF);
layout->gdef = &Null(OT::GDEF);
}
else if (0
/* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */
@ -178,7 +170,7 @@ _hb_ot_layout_create (hb_face_t *face)
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
*/
layout->gdef = &OT::Null(OT::GDEF);
layout->gdef = &Null(OT::GDEF);
}
}
@ -220,16 +212,9 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
hb_blob_destroy (layout->gsub_blob);
hb_blob_destroy (layout->gpos_blob);
layout->base.fini ();
layout->colr.fini ();
layout->cpal.fini ();
layout->math.fini ();
layout->fvar.fini ();
layout->avar.fini ();
layout->ankr.fini ();
layout->kerx.fini ();
layout->morx.fini ();
layout->trak.fini ();
free (layout);
}
@ -237,7 +222,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
// static inline const OT::BASE&
// _get_base (hb_face_t *face)
// {
// if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::BASE);
// if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::BASE);
// hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
// return *(layout->base.get ());
// }
@ -245,19 +230,19 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
static inline const OT::GDEF&
_get_gdef (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF);
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GDEF);
return *hb_ot_layout_from_face (face)->gdef;
}
static inline const OT::GSUB&
_get_gsub (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GSUB);
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GSUB);
return *hb_ot_layout_from_face (face)->gsub;
}
static inline const OT::GPOS&
_get_gpos (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS);
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GPOS);
return *hb_ot_layout_from_face (face)->gpos;
}
@ -329,7 +314,7 @@ get_gsubgpos_table (hb_face_t *face,
switch (table_tag) {
case HB_OT_TAG_GSUB: return _get_gsub (face);
case HB_OT_TAG_GPOS: return _get_gpos (face);
default: return OT::Null(OT::GSUBGPOS);
default: return Null(OT::GSUBGPOS);
}
}
@ -909,7 +894,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
hb_bool_t
hb_ot_layout_has_substitution (hb_face_t *face)
{
return &_get_gsub (face) != &OT::Null(OT::GSUB);
return &_get_gsub (face) != &Null(OT::GSUB);
}
/**
@ -959,11 +944,46 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
unsigned int lookup_index,
hb_set_t *glyphs)
{
OT::hb_closure_context_t c (face, glyphs);
hb_auto_t<hb_map_t> done_lookups;
OT::hb_closure_context_t c (face, glyphs, &done_lookups);
const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index);
l.closure (&c);
l.closure (&c, lookup_index);
}
/**
* hb_ot_layout_lookups_substitute_closure:
*
* Compute the transitive closure of glyphs needed for all of the
* provided lookups.
*
* Since: 1.8.1
**/
void
hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
const hb_set_t *lookups,
hb_set_t *glyphs)
{
hb_auto_t<hb_map_t> done_lookups;
OT::hb_closure_context_t c (face, glyphs, &done_lookups);
const OT::GSUB& gsub = _get_gsub (face);
unsigned int glyphs_length;
do
{
glyphs_length = glyphs->get_population ();
if (lookups != nullptr)
{
for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID; hb_set_next (lookups, &lookup_index);)
gsub.get_lookup (lookup_index).closure (&c, lookup_index);
}
else
{
for (unsigned int i = 0; i < gsub.get_lookup_count (); i++)
gsub.get_lookup (i).closure (&c, i);
}
} while (glyphs_length != glyphs->get_population ());
}
/*
@ -973,7 +993,7 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
hb_bool_t
hb_ot_layout_has_positioning (hb_face_t *face)
{
return &_get_gpos (face) != &OT::Null(OT::GPOS);
return &_get_gpos (face) != &Null(OT::GPOS);
}
void
@ -1107,7 +1127,7 @@ struct hb_get_subtables_context_t :
hb_apply_func_t apply_func;
};
typedef hb_auto_array_t<hb_applicable_t> array_t;
typedef hb_auto_t<hb_vector_t<hb_applicable_t> > array_t;
/* Dispatch interface. */
inline const char *get_name (void) { return "GET_SUBTABLES"; }
@ -1115,8 +1135,7 @@ struct hb_get_subtables_context_t :
inline return_t dispatch (const T &obj)
{
hb_applicable_t *entry = array.push();
if (likely (entry))
entry->init (&obj, apply_to<T>);
entry->init (&obj, apply_to<T>);
return HB_VOID;
}
static return_t default_return_value (void) { return HB_VOID; }
@ -1137,7 +1156,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
{
bool ret = false;
hb_buffer_t *buffer = c->buffer;
while (buffer->idx < buffer->len && !buffer->in_error)
while (buffer->idx < buffer->len && buffer->successful)
{
bool applied = false;
if (accel.may_have (buffer->cur().codepoint) &&
@ -1309,5 +1328,5 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
// hb_bool_t
// hb_ot_base_has_data (hb_face_t *face)
// {
// return &_get_base (face) != &OT::Null(OT::BASE);
// return &_get_base (face) != &Null(OT::BASE);
// }

View File

@ -277,6 +277,12 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
hb_set_t *glyphs
/*TODO , hb_bool_t inclusive */);
HB_EXTERN void
hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
const hb_set_t *lookups,
hb_set_t *glyphs);
#ifdef HB_NOT_IMPLEMENTED
/* Note: You better have GDEF when using this API, or marks won't do much. */
HB_EXTERN hb_bool_t
@ -307,7 +313,7 @@ Xhb_ot_layout_lookup_position (hb_font_t *font,
#endif
/* Optical 'size' feature info. Returns true if found.
* http://www.microsoft.com/typography/otspec/features_pt.htm#size */
* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
HB_EXTERN hb_bool_t
hb_ot_layout_get_size_params (hb_face_t *face,
unsigned int *design_size, /* OUT. May be NULL */

View File

@ -78,8 +78,26 @@ struct hb_ot_map_t
pause_func_t pause_func;
};
inline void init (void)
{
memset (this, 0, sizeof (*this));
hb_ot_map_t (void) { memset (this, 0, sizeof (*this)); }
features.init ();
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
lookups[table_index].init ();
stages[table_index].init ();
}
}
inline void fini (void)
{
features.fini ();
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
lookups[table_index].fini ();
stages[table_index].fini ();
}
}
inline hb_mask_t get_global_mask (void) const { return global_mask; }
@ -130,15 +148,6 @@ struct hb_ot_map_t
HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
inline void finish (void) {
features.finish ();
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
lookups[table_index].finish ();
stages[table_index].finish ();
}
}
public:
hb_tag_t chosen_script[2];
bool found_script[2];
@ -147,9 +156,9 @@ struct hb_ot_map_t
hb_mask_t global_mask;
hb_prealloced_array_t<feature_map_t, 8> features;
hb_prealloced_array_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */
hb_prealloced_array_t<stage_map_t, 4> stages[2]; /* GSUB/GPOS */
hb_vector_t<feature_map_t, 8> features;
hb_vector_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */
hb_vector_t<stage_map_t, 4> stages[2]; /* GSUB/GPOS */
};
enum hb_ot_map_feature_flags_t {
@ -172,6 +181,8 @@ struct hb_ot_map_builder_t
HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_,
const hb_segment_properties_t *props_);
HB_INTERNAL ~hb_ot_map_builder_t (void);
HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value,
hb_ot_map_feature_flags_t flags);
@ -187,14 +198,6 @@ struct hb_ot_map_builder_t
const int *coords,
unsigned int num_coords);
inline void finish (void) {
feature_infos.finish ();
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
stages[table_index].finish ();
}
}
private:
HB_INTERNAL void add_lookups (hb_ot_map_t &m,
@ -241,8 +244,8 @@ struct hb_ot_map_builder_t
private:
unsigned int current_stage[2]; /* GSUB/GPOS */
hb_prealloced_array_t<feature_info_t, 32> feature_infos;
hb_prealloced_array_t<stage_info_t, 8> stages[2]; /* GSUB/GPOS */
hb_vector_t<feature_info_t, 32> feature_infos;
hb_vector_t<stage_info_t, 8> stages[2]; /* GSUB/GPOS */
};

View File

@ -43,6 +43,10 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
{
memset (this, 0, sizeof (*this));
feature_infos.init ();
for (unsigned int table_index = 0; table_index < 2; table_index++)
stages[table_index].init ();
face = face_;
props = *props_;
@ -63,11 +67,17 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
}
}
hb_ot_map_builder_t::~hb_ot_map_builder_t (void)
{
feature_infos.fini ();
for (unsigned int table_index = 0; table_index < 2; table_index++)
stages[table_index].fini ();
}
void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value,
hb_ot_map_feature_flags_t flags)
{
feature_info_t *info = feature_infos.push();
if (unlikely (!info)) return;
if (unlikely (!tag)) return;
info->tag = tag;
info->seq = feature_infos.len;
@ -108,8 +118,6 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
if (lookup_indices[i] >= table_lookup_count)
continue;
hb_ot_map_t::lookup_map_t *lookup = m.lookups[table_index].push ();
if (unlikely (!lookup))
return;
lookup->mask = mask;
lookup->index = lookup_indices[i];
lookup->auto_zwnj = auto_zwnj;
@ -124,10 +132,8 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func)
{
stage_info_t *s = stages[table_index].push ();
if (likely (s)) {
s->index = current_stage[table_index];
s->pause_func = pause_func;
}
s->index = current_stage[table_index];
s->pause_func = pause_func;
current_stage[table_index]++;
}
@ -164,9 +170,6 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
&required_feature_tag[table_index]);
}
if (!feature_infos.len)
return;
/* Sort features and merge duplicates */
{
feature_infos.qsort ();
@ -241,8 +244,6 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
hb_ot_map_t::feature_map_t *map = m.features.push ();
if (unlikely (!map))
break;
map->tag = info->tag;
map->index[0] = feature_index[0];
@ -324,10 +325,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
if (stage_index < stages[table_index].len && stages[table_index][stage_index].index == stage) {
hb_ot_map_t::stage_map_t *stage_map = m.stages[table_index].push ();
if (likely (stage_map)) {
stage_map->last_lookup = last_num_lookups;
stage_map->pause_func = stages[table_index][stage_index].pause_func;
}
stage_map->last_lookup = last_num_lookups;
stage_map->pause_func = stages[table_index][stage_index].pause_func;
stage_index++;
}

View File

@ -34,7 +34,8 @@ namespace OT {
/*
* maxp -- The Maximum Profile Table
* maxp -- Maximum Profile
* https://docs.microsoft.com/en-us/typography/opentype/spec/maxp
*/
#define HB_OT_TAG_maxp HB_TAG('m','a','x','p')
@ -108,11 +109,11 @@ struct maxp
}
OT::maxp *maxp_prime = (OT::maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
maxp_prime->set_num_glyphs (plan->gids_to_retain_sorted.len);
maxp_prime->set_num_glyphs (plan->glyphs.len);
if (plan->drop_hints)
drop_hint_fields (plan, maxp_prime);
bool result = hb_subset_plan_add_table(plan, HB_OT_TAG_maxp, maxp_prime_blob);
bool result = plan->add_table (HB_OT_TAG_maxp, maxp_prime_blob);
hb_blob_destroy (maxp_prime_blob);
return result;
}

View File

@ -34,9 +34,9 @@ namespace OT {
/*
* name -- The Naming Table
* name -- Naming
* https://docs.microsoft.com/en-us/typography/opentype/spec/name
*/
#define HB_OT_TAG_name HB_TAG('n','a','m','e')

View File

@ -29,14 +29,14 @@
#include "hb-open-type-private.hh"
#include "hb-ot-os2-unicode-ranges.hh"
#include "hb-subset-plan.hh"
namespace OT {
/*
* OS/2 and Windows Metrics
* http://www.microsoft.com/typography/otspec/os2.htm
* https://docs.microsoft.com/en-us/typography/opentype/spec/os2
*/
#define HB_OT_TAG_os2 HB_TAG('O','S','/','2')
struct os2
@ -63,26 +63,25 @@ struct os2
}
uint16_t min_cp, max_cp;
find_min_and_max_codepoint (plan->codepoints, &min_cp, &max_cp);
find_min_and_max_codepoint (plan->unicodes, &min_cp, &max_cp);
os2_prime->usFirstCharIndex.set (min_cp);
os2_prime->usLastCharIndex.set (max_cp);
_update_unicode_ranges (plan->codepoints, os2_prime->ulUnicodeRange);
bool result = hb_subset_plan_add_table(plan, HB_OT_TAG_os2, os2_prime_blob);
_update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange);
bool result = plan->add_table (HB_OT_TAG_os2, os2_prime_blob);
hb_blob_destroy (os2_prime_blob);
return result;
}
inline void _update_unicode_ranges (const hb_prealloced_array_t<hb_codepoint_t> &codepoints,
inline void _update_unicode_ranges (const hb_set_t *codepoints,
HBUINT32 ulUnicodeRange[4]) const
{
for (unsigned int i = 0; i < 4; i++)
ulUnicodeRange[i].set (0);
for (unsigned int i = 0; i < codepoints.len; i++)
{
hb_codepoint_t cp = codepoints[i];
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
while (codepoints->next (&cp)) {
unsigned int bit = hb_get_unicode_range_bit (cp);
if (bit < 128)
{
@ -101,28 +100,30 @@ struct os2
}
}
static inline void find_min_and_max_codepoint (const hb_prealloced_array_t<hb_codepoint_t> &codepoints,
static inline void find_min_and_max_codepoint (const hb_set_t *codepoints,
uint16_t *min_cp, /* OUT */
uint16_t *max_cp /* OUT */)
{
hb_codepoint_t min = -1, max = 0;
*min_cp = codepoints->get_min ();
*max_cp = codepoints->get_max ();
}
for (unsigned int i = 0; i < codepoints.len; i++)
{
hb_codepoint_t cp = codepoints[i];
if (cp < min)
min = cp;
if (cp > max)
max = cp;
}
enum font_page_t {
HEBREW_FONT_PAGE = 0xB100, // Hebrew Windows 3.1 font page
SIMP_ARABIC_FONT_PAGE = 0xB200, // Simplified Arabic Windows 3.1 font page
TRAD_ARABIC_FONT_PAGE = 0xB300, // Traditional Arabic Windows 3.1 font page
OEM_ARABIC_FONT_PAGE = 0xB400, // OEM Arabic Windows 3.1 font page
SIMP_FARSI_FONT_PAGE = 0xBA00, // Simplified Farsi Windows 3.1 font page
TRAD_FARSI_FONT_PAGE = 0xBB00, // Traditional Farsi Windows 3.1 font page
THAI_FONT_PAGE = 0xDE00 // Thai Windows 3.1 font page
};
if (min > 0xFFFF)
min = 0xFFFF;
if (max > 0xFFFF)
max = 0xFFFF;
*min_cp = min;
*max_cp = max;
// https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681
inline font_page_t get_font_page () const
{
if (version != 0)
return (font_page_t) 0;
return (font_page_t) (fsSelection & 0xFF00);
}
public:

View File

@ -237,7 +237,7 @@ hb_get_unicode_range_bit (hb_codepoint_t cp)
sizeof (os2UnicodeRangesSorted) / sizeof(Range),
sizeof(Range),
_compare_range, nullptr);
if (range != NULL)
if (range != nullptr)
return range->bit;
return -1;
}

View File

@ -29,6 +29,7 @@
#include "hb-open-type-private.hh"
#include "hb-dsalgs.hh"
#include "hb-subset-plan.hh"
#define HB_STRING_ARRAY_NAME format1_names
#define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh"
@ -38,16 +39,16 @@
#define NUM_FORMAT1_NAMES 258
namespace OT {
/*
* post -- PostScript
* https://docs.microsoft.com/en-us/typography/opentype/spec/post
*/
#define HB_OT_TAG_post HB_TAG('p','o','s','t')
namespace OT {
struct postV2Tail
{
inline bool sanitize (hb_sanitize_context_t *c) const
@ -82,16 +83,39 @@ struct post
return_trace (true);
}
inline bool subset (hb_subset_plan_t *plan) const
{
unsigned int post_prime_length;
hb_blob_t *post_blob = OT::Sanitizer<post>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_post));
hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::static_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::static_size))
{
hb_blob_destroy (post_prime_blob);
DEBUG_MSG(SUBSET, nullptr, "Invalid source post table with length %d.", post_prime_length);
return false;
}
post_prime->version.major.set (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;
}
struct accelerator_t
{
inline void init (hb_face_t *face)
{
index_to_offset.init ();
blob = Sanitizer<post>().sanitize (face->reference_table (HB_OT_TAG_post));
const post *table = Sanitizer<post>::lock_instance (blob);
unsigned int table_length = hb_blob_get_length (blob);
const post *table = blob->as<post> ();
unsigned int table_length = blob->length;
version = table->version.to_int ();
index_to_offset.init ();
if (version != 0x00020000)
return;
@ -102,23 +126,18 @@ struct post
const uint8_t *end = (uint8_t *) table + table_length;
for (const uint8_t *data = pool; data < end && data + *data <= end; data += 1 + *data)
{
uint32_t *offset = index_to_offset.push ();
if (unlikely (!offset))
break;
*offset = data - pool;
}
index_to_offset.push (data - pool);
}
inline void fini (void)
{
index_to_offset.finish ();
index_to_offset.fini ();
free (gids_sorted_by_name);
}
inline bool get_glyph_name (hb_codepoint_t glyph,
char *buf, unsigned int buf_len) const
{
hb_string_t s = find_glyph_name (glyph);
hb_bytes_t s = find_glyph_name (glyph);
if (!s.len)
return false;
if (!buf_len)
@ -162,7 +181,7 @@ struct post
}
}
hb_string_t st (name, len);
hb_bytes_t st (name, len);
const uint16_t *gid = (const uint16_t *) hb_bsearch_r (&st, gids, count, sizeof (gids[0]), cmp_key, (void *) this);
if (gid)
{
@ -197,45 +216,45 @@ struct post
static inline int cmp_key (const void *pk, const void *po, void *arg)
{
const accelerator_t *thiz = (const accelerator_t *) arg;
const hb_string_t *key = (const hb_string_t *) pk;
const hb_bytes_t *key = (const hb_bytes_t *) pk;
uint16_t o = * (const uint16_t *) po;
return thiz->find_glyph_name (o).cmp (*key);
}
inline hb_string_t find_glyph_name (hb_codepoint_t glyph) const
inline hb_bytes_t find_glyph_name (hb_codepoint_t glyph) const
{
if (version == 0x00010000)
{
if (glyph >= NUM_FORMAT1_NAMES)
return hb_string_t ();
return hb_bytes_t ();
return format1_names (glyph);
}
if (version != 0x00020000 || glyph >= glyphNameIndex->len)
return hb_string_t ();
return hb_bytes_t ();
unsigned int index = glyphNameIndex->array[glyph];
unsigned int index = glyphNameIndex->arrayZ[glyph];
if (index < NUM_FORMAT1_NAMES)
return format1_names (index);
index -= NUM_FORMAT1_NAMES;
if (index >= index_to_offset.len)
return hb_string_t ();
unsigned int offset = index_to_offset.array[index];
return hb_bytes_t ();
unsigned int offset = index_to_offset.arrayZ[index];
const uint8_t *data = pool + offset;
unsigned int name_length = *data;
data++;
return hb_string_t ((const char *) data, name_length);
return hb_bytes_t ((const char *) data, name_length);
}
private:
hb_blob_t *blob;
uint32_t version;
const ArrayOf<HBUINT16> *glyphNameIndex;
hb_prealloced_array_t<uint32_t, 1> index_to_offset;
hb_vector_t<uint32_t, 1> index_to_offset;
const uint8_t *pool;
mutable uint16_t *gids_sorted_by_name;
};

View File

@ -6,10 +6,10 @@
*
* on files with these headers:
*
* # ArabicShaping-10.0.0.txt
* # Date: 2017-02-16, 00:00:00 GMT [RP, KW]
* # Blocks-10.0.0.txt
* # Date: 2017-04-12, 17:30:00 GMT [KW]
* # ArabicShaping-11.0.0.txt
* # Date: 2018-02-21, 14:50:00 GMT [KW, RP]
* # Blocks-11.0.0.txt
* # Date: 2017-10-16, 24:39:00 GMT [KW]
* UnicodeData.txt does not have a header.
*/
@ -45,7 +45,7 @@ static const uint8_t joining_table[] =
/* Syriac */
/* 0700 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,A,X,D,D,D,DR,DR,R,R,R,D,D,D,D,R,D,
/* 0700 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,T,A,X,D,D,D,DR,DR,R,R,R,D,D,D,D,R,D,
/* 0720 */ D,D,D,D,D,D,D,D,R,D,DR,D,R,D,D,DR,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
/* 0740 */ X,X,X,X,X,X,X,X,X,X,X,X,X,R,D,D,
@ -91,7 +91,7 @@ static const uint8_t joining_table[] =
/* 1800 */ U,D,X,X,C,X,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
/* 1820 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* 1840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* 1860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,
/* 1860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,
/* 1880 */ U,U,U,U,U,T,T,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* 18A0 */ D,D,D,D,D,D,D,D,D,X,D,
@ -125,7 +125,28 @@ static const uint8_t joining_table[] =
/* 10B80 */ D,R,D,R,R,R,D,D,D,R,D,D,R,D,R,R,D,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
/* 10BA0 */ X,X,X,X,X,X,X,X,X,R,R,R,R,D,D,U,
#define joining_offset_0x1e900u 1146
#define joining_offset_0x10d00u 1146
/* Hanifi Rohingya */
/* 10D00 */ L,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* 10D20 */ D,D,R,D,
#define joining_offset_0x10f30u 1182
/* Sogdian */
/* 10F20 */ D,D,D,R,D,D,D,D,D,D,D,D,D,D,D,D,
/* 10F40 */ D,D,D,D,D,U,X,X,X,X,X,X,X,X,X,X,X,D,D,D,R,
#define joining_offset_0x110bdu 1219
/* Kaithi */
/* 110A0 */ U,X,X,
/* 110C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,U,
#define joining_offset_0x1e900u 1236
/* Adlam */
@ -133,7 +154,7 @@ static const uint8_t joining_table[] =
/* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* 1E940 */ D,D,D,D,
}; /* Table items: 1214; occupancy: 55% */
}; /* Table items: 1304; occupancy: 56% */
static unsigned int
@ -160,6 +181,12 @@ joining_type (hb_codepoint_t u)
case 0x10u:
if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D23u)) return joining_table[u - 0x10D00u + joining_offset_0x10d00u];
if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10F54u)) return joining_table[u - 0x10F30u + joining_offset_0x10f30u];
break;
case 0x11u:
if (hb_in_range<hb_codepoint_t> (u, 0x110BDu, 0x110CDu)) return joining_table[u - 0x110BDu + joining_offset_0x110bdu];
break;
case 0x1Eu:

View File

@ -421,7 +421,7 @@ retry:
/*
* Stretch feature: "stch".
* See example here:
* https://www.microsoft.com/typography/OpenTypeDev/syriac/intro.htm
* https://docs.microsoft.com/en-us/typography/script-development/syriac
* We implement this in a generic way, such that the Arabic subtending
* marks can use it as well.
*/
@ -611,7 +611,7 @@ postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan,
HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
}
/* http://www.unicode.org/reports/tr53/tr53-1.pdf */
/* https://unicode.org/reports/tr53/tr53-1.pdf */
static hb_codepoint_t
modifier_combining_marks[] =

View File

@ -151,8 +151,8 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
* - <V>: U+1160..11A7, U+D7B0..D7C7
* - <T>: U+11A8..11FF, U+D7CB..D7FB
*
* - Only the <L,V> sequences for the 11xx ranges combine.
* - Only <LV,T> sequences for T in U+11A8..11C3 combine.
* - Only the <L,V> sequences for some of the U+11xx ranges combine.
* - Only <LV,T> sequences for some of the Ts in U+11xx range combine.
*
* Here is what we want to accomplish in this shaper:
*
@ -188,7 +188,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
*/
unsigned int count = buffer->len;
for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;)
for (buffer->idx = 0; buffer->idx < count && buffer->successful;)
{
hb_codepoint_t u = buffer->cur().codepoint;
@ -269,7 +269,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
if (font->has_glyph (s))
{
buffer->replace_glyphs (t ? 3 : 2, 1, &s);
if (unlikely (buffer->in_error))
if (unlikely (!buffer->successful))
return;
end = start + 1;
continue;
@ -319,7 +319,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
if (font->has_glyph (new_s))
{
buffer->replace_glyphs (2, 1, &new_s);
if (unlikely (buffer->in_error))
if (unlikely (!buffer->successful))
return;
end = start + 1;
continue;
@ -345,7 +345,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
{
unsigned int s_len = tindex ? 3 : 2;
buffer->replace_glyphs (1, s_len, decomposed);
if (unlikely (buffer->in_error))
if (unlikely (!buffer->successful))
return;
/* We decomposed S: apply jamo features to the individual glyphs

View File

@ -1129,7 +1129,7 @@ static const int indic_syllable_machine_en_main = 166;
static void
find_syllables (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
unsigned int p, pe, eof, ts HB_UNUSED, te, act;
int cs;
hb_glyph_info_t *info = buffer->info;

View File

@ -42,7 +42,7 @@
#define INDIC_TABLE_ELEMENT_TYPE uint16_t
/* Cateories used in the OpenType spec:
* https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx
* https://docs.microsoft.com/en-us/typography/script-development/devanagari
*/
/* Note: This enum is duplicated in the -machine.rl source file.
* Not sure how to avoid duplication. */

View File

@ -6,62 +6,63 @@
*
* on files with these headers:
*
* # IndicSyllabicCategory-10.0.0.txt
* # Date: 2017-05-31, 01:07:00 GMT [KW, RP]
* # IndicPositionalCategory-10.0.0.txt
* # Date: 2017-05-31, 01:07:00 GMT [RP]
* # Blocks-10.0.0.txt
* # Date: 2017-04-12, 17:30:00 GMT [KW]
* # IndicSyllabicCategory-11.0.0.txt
* # Date: 2018-05-21, 18:33:00 GMT [KW, RP]
* # IndicPositionalCategory-11.0.0.txt
* # Date: 2018-02-05, 16:21:00 GMT [KW, RP]
* # Blocks-11.0.0.txt
* # Date: 2017-10-16, 24:39:00 GMT [KW]
*/
#include "hb-ot-shape-complex-indic-private.hh"
#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 15 chars; Avagraha */
#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 80 chars; Bindu */
#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 16 chars; Avagraha */
#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 83 chars; Bindu */
#define ISC_BJN INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER /* 20 chars; Brahmi_Joining_Number */
#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 57 chars; Cantillation_Mark */
#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 2024 chars; Consonant */
#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 58 chars; Cantillation_Mark */
#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 2110 chars; Consonant */
#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 10 chars; Consonant_Dead */
#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 68 chars; Consonant_Final */
#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 67 chars; Consonant_Final */
#define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 5 chars; Consonant_Head_Letter */
#define ISC_CIP INDIC_SYLLABIC_CATEGORY_CONSONANT_INITIAL_POSTFIXED /* 1 chars; Consonant_Initial_Postfixed */
#define ISC_CK INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER /* 2 chars; Consonant_Killer */
#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 27 chars; Consonant_Medial */
#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 18 chars; Consonant_Placeholder */
#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 28 chars; Consonant_Medial */
#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 21 chars; Consonant_Placeholder */
#define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 2 chars; Consonant_Preceding_Repha */
#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 7 chars; Consonant_Prefixed */
#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 95 chars; Consonant_Subjoined */
#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 5 chars; Consonant_Succeeding_Repha */
#define ISC_CWS INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER /* 4 chars; Consonant_With_Stacker */
#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 4 chars; Consonant_Succeeding_Repha */
#define ISC_CWS INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER /* 6 chars; Consonant_With_Stacker */
#define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 3 chars; Gemination_Mark */
#define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 10 chars; Invisible_Stacker */
#define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 11 chars; Invisible_Stacker */
#define ISC_ZWJ INDIC_SYLLABIC_CATEGORY_JOINER /* 1 chars; Joiner */
#define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */
#define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER /* 1 chars; Non_Joiner */
#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 28 chars; Nukta */
#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 469 chars; Number */
#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 30 chars; Nukta */
#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 480 chars; Number */
#define ISC_NJ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER /* 1 chars; Number_Joiner */
#define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */
#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 21 chars; Pure_Killer */
#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 2 chars; Register_Shifter */
#define ISC_SM INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER /* 22 chars; Syllable_Modifier */
#define ISC_SM INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER /* 25 chars; Syllable_Modifier */
#define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */
#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 42 chars; Tone_Mark */
#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 24 chars; Virama */
#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 34 chars; Visarga */
#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 25 chars; Virama */
#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 36 chars; Visarga */
#define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 30 chars; Vowel */
#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 633 chars; Vowel_Dependent */
#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 443 chars; Vowel_Independent */
#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 660 chars; Vowel_Dependent */
#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 464 chars; Vowel_Independent */
#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 330 chars; Bottom */
#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 340 chars; Bottom */
#define IMC_BL INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT /* 1 chars; Bottom_And_Left */
#define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 2 chars; Bottom_And_Right */
#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 57 chars; Left */
#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 59 chars; Left */
#define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 21 chars; Left_And_Right */
#define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */
#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 10 chars; Overstruck */
#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 262 chars; Right */
#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 380 chars; Top */
#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 276 chars; Right */
#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 393 chars; Top */
#define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 10 chars; Top_And_Bottom */
#define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */
#define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 6 chars; Top_And_Left */
@ -119,7 +120,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* Bengali */
/* 0980 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0980 */ _(CP,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0988 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
/* 0990 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 0998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@ -134,7 +135,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 09E0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
/* 09E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 09F0 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 09F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(Bi,x), _(x,x), _(x,x), _(x,x),
/* 09F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(Bi,x), _(x,x), _(SM,T), _(x,x),
/* Gurmukhi */
@ -148,7 +149,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0A38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(x,x), _(M,R), _(M,L),
/* 0A40 */ _(M,R), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T),
/* 0A48 */ _(M,T), _(x,x), _(x,x), _(M,T), _(M,T), _(V,B), _(x,x), _(x,x),
/* 0A50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0A50 */ _(x,x), _(Ca,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0A58 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x),
/* 0A60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
/* 0A68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
@ -214,7 +215,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* Telugu */
/* 0C00 */ _(Bi,T), _(Bi,R), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0C00 */ _(Bi,T), _(Bi,R), _(Bi,R), _(Vs,R), _(Bi,T), _(VI,x), _(VI,x), _(VI,x),
/* 0C08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
/* 0C10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 0C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@ -301,7 +302,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,T), _(TM,B),
/* 1038 */ _(Vs,R), _(IS,x), _(PK,T), _(CM,R), _(CM,x), _(CM,B), _(CM,B), _(C,x),
/* 1040 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 1048 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), _(x,x),
/* 1048 */ _(Nd,x), _(Nd,x), _(x,x), _(CP,x), _(x,x), _(x,x), _(CP,x), _(x,x),
/* 1050 */ _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R),
/* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,B), _(CM,B),
/* 1060 */ _(CM,B), _(C,x), _(M,R), _(TM,R), _(TM,R), _(C,x), _(C,x), _(M,R),
@ -342,7 +343,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 1CD8 */ _(Ca,B), _(Ca,B), _(Ca,T), _(Ca,T), _(Ca,B), _(Ca,B), _(Ca,B), _(Ca,B),
/* 1CE0 */ _(Ca,T), _(Ca,R), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O),
/* 1CE8 */ _(x,O), _(x,x), _(x,x), _(x,x), _(x,x), _(x,B), _(x,x), _(x,x),
/* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(Ca,T), _(x,x), _(x,x), _(Ca,R),
/* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(Ca,T),_(CWS,x),_(CWS,x), _(Ca,R),
/* 1CF8 */ _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x2008u 1656
@ -370,8 +371,9 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* A8E0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
/* A8E8 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
/* A8F0 */ _(Ca,T), _(Ca,T), _(Bi,x), _(Bi,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A8F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x), _(M,T),
#define indic_offset_0xa9e0u 1720
#define indic_offset_0xa9e0u 1728
/* Myanmar Extended-B */
@ -381,7 +383,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* A9F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* A9F8 */ _(Nd,x), _(Nd,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
#define indic_offset_0xaa60u 1752
#define indic_offset_0xaa60u 1760
/* Myanmar Extended-A */
@ -391,7 +393,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(CP,x), _(CP,x), _(CP,x), _(x,x),
/* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,R), _(TM,T), _(TM,R), _(C,x), _(C,x),
}; /* Table items: 1784; occupancy: 70% */
}; /* Table items: 1792; occupancy: 70% */
INDIC_TABLE_ELEMENT_TYPE
hb_indic_get_categories (hb_codepoint_t u)
@ -418,7 +420,7 @@ hb_indic_get_categories (hb_codepoint_t u)
break;
case 0xAu:
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, 0xA8E0u, 0xA8FFu)) 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;
@ -430,7 +432,6 @@ hb_indic_get_categories (hb_codepoint_t u)
}
#undef _
#undef ISC_A
#undef ISC_Bi
#undef ISC_BJN
@ -439,6 +440,7 @@ hb_indic_get_categories (hb_codepoint_t u)
#undef ISC_CD
#undef ISC_CF
#undef ISC_CHL
#undef ISC_CIP
#undef ISC_CK
#undef ISC_CM
#undef ISC_CP
@ -466,7 +468,6 @@ hb_indic_get_categories (hb_codepoint_t u)
#undef ISC_Vo
#undef ISC_M
#undef ISC_VI
#undef IMC_B
#undef IMC_BL
#undef IMC_BR

View File

@ -86,7 +86,7 @@ static const indic_config_t indic_configs[] =
{HB_SCRIPT_KANNADA, true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY},
{HB_SCRIPT_MALAYALAM, true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST},
{HB_SCRIPT_SINHALA, false,0x0DCAu,BASE_POS_LAST_SINHALA,
REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST},
REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST},
};
@ -435,7 +435,7 @@ update_consonant_positions (const hb_ot_shape_plan_t *plan,
/* Rules from:
* https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx */
* https://docs.microsqoft.com/en-us/typography/script-development/devanagari */
static void
initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
@ -974,7 +974,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len && !buffer->in_error)
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
@ -989,7 +989,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
/* TODO Set glyph_props? */
/* Insert dottedcircle after possible Repha. */
while (buffer->idx < buffer->len && !buffer->in_error &&
while (buffer->idx < buffer->len && buffer->successful &&
last_syllable == buffer->cur().syllable() &&
buffer->cur().indic_category() == OT_Repha)
buffer->next_glyph ();
@ -1470,6 +1470,9 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
{
/* Don't decompose these. */
case 0x0931u : return false; /* DEVANAGARI LETTER RRA */
// https://github.com/harfbuzz/harfbuzz/issues/779
case 0x09DCu : return false; /* BENGALI LETTER RRA */
case 0x09DDu : return false; /* BENGALI LETTER RHA */
case 0x0B94u : return false; /* TAMIL LETTER AU */
@ -1512,7 +1515,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
* The Uniscribe behavior is now documented in the newly published Sinhala
* spec in 2012:
*
* http://www.microsoft.com/typography/OpenTypeDev/sinhala/intro.htm#shaping
* https://docs.microsoft.com/en-us/typography/script-development/sinhala#shaping
*/
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) c->plan->data;

View File

@ -173,7 +173,7 @@ static const int khmer_syllable_machine_en_main = 10;
static void
find_syllables (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
unsigned int p, pe, eof, ts HB_UNUSED, te, act HB_UNUSED;
int cs;
hb_glyph_info_t *info = buffer->info;

View File

@ -275,7 +275,7 @@ compare_khmer_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
/* Rules from:
* https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx */
* https://docs.microsoft.com/en-us/typography/script-development/devanagari */
static void
initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
@ -317,7 +317,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
if ((FLAG_UNSAFE (info[i].khmer_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_Coeng))))
{
info[i].khmer_position() = last_pos;
if (unlikely (info[i].khmer_category() == OT_H &&
if (unlikely (info[i].khmer_category() == OT_Coeng &&
info[i].khmer_position() == POS_PRE_M))
{
/*
@ -485,7 +485,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len && !buffer->in_error)
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
@ -500,7 +500,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
/* TODO Set glyph_props? */
/* Insert dottedcircle after possible Repha. */
while (buffer->idx < buffer->len && !buffer->in_error &&
while (buffer->idx < buffer->len && buffer->successful &&
last_syllable == buffer->cur().syllable() &&
buffer->cur().khmer_category() == OT_Repha)
buffer->next_glyph ();
@ -538,7 +538,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
* and possibly multiple substitutions happened prior to this
* phase, and that might have messed up our properties. Recover
* from a particular case of that where we're fairly sure that a
* class of OT_H is desired but has been lost. */
* class of OT_Coeng is desired but has been lost. */
if (khmer_plan->virama_glyph)
{
unsigned int virama_glyph = khmer_plan->virama_glyph;
@ -548,7 +548,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
_hb_glyph_info_multiplied (&info[i]))
{
/* This will make sure that this glyph passes is_coeng() test. */
info[i].khmer_category() = OT_H;
info[i].khmer_category() = OT_Coeng;
_hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
}
}

View File

@ -68,7 +68,7 @@ set_myanmar_properties (hb_glyph_info_t &info)
indic_position_t pos = (indic_position_t) (type >> 8);
/* Myanmar
* http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm#analyze
* https://docs.microsoft.com/en-us/typography/script-development/myanmar#analyze
*/
if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)))
cat = (indic_category_t) OT_VS;

View File

@ -161,7 +161,7 @@ compare_myanmar_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
/* Rules from:
* http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm */
* https://docs.microsoft.com/en-us/typography/script-development/myanmar */
static void
initial_reordering_consonant_syllable (hb_buffer_t *buffer,
@ -312,7 +312,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len && !buffer->in_error)
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);

View File

@ -205,6 +205,10 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-9.0 additions */
case HB_SCRIPT_ADLAM:
/* Unicode-11.0 additions */
case HB_SCRIPT_HANIFI_ROHINGYA:
case HB_SCRIPT_SOGDIAN:
/* 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
@ -380,6 +384,11 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_SOYOMBO:
case HB_SCRIPT_ZANABAZAR_SQUARE:
/* Unicode-11.0 additions */
case HB_SCRIPT_DOGRA:
case HB_SCRIPT_GUNJALA_GONDI:
case HB_SCRIPT_MAKASAR:
/* If the designer designed the font for the 'DFLT' script,
* (or we ended up arbitrarily pick 'latn'), use the default shaper.
* Otherwise, use the specific shaper.

View File

@ -260,7 +260,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
{
/* This function implements the shaping logic documented here:
*
* http://linux.thai.net/~thep/th-otf/shaping.html
* https://linux.thai.net/~thep/th-otf/shaping.html
*
* The first shaping rule listed there is needed even if the font has Thai
* OpenType tables. The rest do fallback positioning based on PUA codepoints.
@ -315,7 +315,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
buffer->clear_output ();
unsigned int count = buffer->len;
for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;)
for (buffer->idx = 0; buffer->idx < count && buffer->successful;)
{
hb_codepoint_t u = buffer->cur().codepoint;
if (likely (!IS_SARA_AM (u))) {
@ -327,7 +327,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
hb_codepoint_t decomposed[2] = {hb_codepoint_t (NIKHAHIT_FROM_SARA_AM (u)),
hb_codepoint_t (SARA_AA_FROM_SARA_AM (u))};
buffer->replace_glyphs (1, 2, decomposed);
if (unlikely (buffer->in_error))
if (unlikely (!buffer->successful))
return;
/* Make Nikhahit be recognized as a ccc=0 mark when zeroing widths. */

View File

@ -331,7 +331,7 @@ static const int use_syllable_machine_en_main = 4;
static void
find_syllables (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
unsigned int p, pe, eof, ts HB_UNUSED, te, act;
int cs;
hb_glyph_info_t *info = buffer->info;

View File

@ -38,7 +38,7 @@
#define USE_TABLE_ELEMENT_TYPE uint8_t
/* Cateories used in the Universal Shaping Engine spec:
* https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm
* https://docs.microsoft.com/en-us/typography/script-development/use
*/
/* Note: This enum is duplicated in the -machine.rl source file.
* Not sure how to avoid duplication. */

View File

@ -6,12 +6,12 @@
*
* on files with these headers:
*
* # IndicSyllabicCategory-10.0.0.txt
* # Date: 2017-05-31, 01:07:00 GMT [KW, RP]
* # IndicPositionalCategory-10.0.0.txt
* # Date: 2017-05-31, 01:07:00 GMT [RP]
* # Blocks-10.0.0.txt
* # Date: 2017-04-12, 17:30:00 GMT [KW]
* # IndicSyllabicCategory-11.0.0.txt
* # Date: 2018-05-21, 18:33:00 GMT [KW, RP]
* # IndicPositionalCategory-11.0.0.txt
* # Date: 2018-02-05, 16:21:00 GMT [KW, RP]
* # Blocks-11.0.0.txt
* # Date: 2017-10-16, 24:39:00 GMT [KW]
* UnicodeData.txt does not have a header.
*/
@ -97,14 +97,14 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Bengali */
/* 0980 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B,
/* 0980 */ GB, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B,
/* 0990 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 09A0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 09B0 */ B, O, B, O, O, O, B, B, B, B, O, O, CMBlw, B, VPst, VPre,
/* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, IND, O,
/* 09D0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, B, B, O, B,
/* 09E0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, O, O,
/* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, FM, O,
/* Gurmukhi */
@ -113,7 +113,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 0A20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 0A30 */ B, O, B, B, O, B, B, O, B, B, O, O, CMBlw, O, VPst, VPre,
/* 0A40 */ VPst, VBlw, VBlw, O, O, O, O, VAbv, VAbv, O, O, VAbv, VAbv, H, O, O,
/* 0A50 */ O, O, O, O, O, O, O, O, O, B, B, B, B, O, B, O,
/* 0A50 */ O, VMBlw, O, O, O, O, O, O, O, B, B, B, B, O, B, O,
/* 0A60 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0A70 */ VMAbv, CMAbv, GB, GB, O, MBlw, O, O, O, O, O, O, O, O, O, O,
@ -152,7 +152,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Telugu */
/* 0C00 */ VMAbv, VMPst, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B,
/* 0C00 */ VMAbv, VMPst, VMPst, VMPst, VMAbv, B, B, B, B, B, B, B, B, O, B, B,
/* 0C10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0C20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 0C30 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, VAbv, VAbv,
@ -203,7 +203,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 1010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1020 */ B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VAbv, VAbv, VBlw,
/* 1030 */ VBlw, VPre, VAbv, VAbv, VAbv, VAbv, VMAbv, VMBlw, VMPst, H, VAbv, MPst, MPre, MBlw, MBlw, B,
/* 1040 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, GB, O,
/* 1040 */ B, B, B, B, B, B, B, B, B, B, O, GB, O, O, GB, O,
/* 1050 */ B, B, B, B, B, B, VPst, VPst, VBlw, VBlw, B, B, B, B, MBlw, MBlw,
/* 1060 */ MBlw, B, VPst, VMPst, VMPst, B, B, VPst, VPst, VMPst, VMPst, VMPst, VMPst, VMPst, B, B,
/* 1070 */ B, VAbv, VAbv, VAbv, VAbv, B, B, B, B, B, B, B, B, B, B, B,
@ -330,7 +330,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 1CD0 */ VMAbv, VMAbv, VMAbv, O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw,
/* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O,
/* 1CF0 */ O, O, VMPst, VMPst, VMAbv, O, O, VMPst, VMAbv, VMAbv, O, O, O, O, O, O,
/* 1CF0 */ O, O, VMPst, VMPst, VMAbv, CS, CS, VMPst, VMAbv, VMAbv, O, O, O, O, O, O,
#define use_offset_0x1df8u 2560
@ -396,7 +396,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Devanagari Extended */
/* A8E0 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,
/* A8F0 */ VMAbv, VMAbv, B, B, O, O, O, O, O, O, O, O, O, O, O, O,
/* A8F0 */ VMAbv, VMAbv, B, B, O, O, O, O, O, O, O, O, O, O, B, VAbv,
/* Kayah Li */
@ -479,10 +479,10 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 10A00 */ B, VBlw, VBlw, VBlw, O, VAbv, VBlw, O, O, O, O, O, VBlw, VBlw, VMBlw, VMAbv,
/* 10A10 */ B, B, B, B, O, B, B, B, O, B, B, B, B, B, B, B,
/* 10A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 10A30 */ B, B, B, B, O, O, O, O, CMAbv, CMBlw, CMBlw, O, O, O, O, H,
/* 10A40 */ B, B, B, B, B, B, B, B,
/* 10A30 */ B, B, B, B, B, B, O, O, CMAbv, CMBlw, CMBlw, O, O, O, O, H,
/* 10A40 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O,
#define use_offset_0x11000u 3552
#define use_offset_0x11000u 3560
/* Brahmi */
@ -503,7 +503,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O,
#define use_offset_0x11100u 3744
#define use_offset_0x11100u 3752
/* Chakma */
@ -512,7 +512,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11120 */ B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VAbv, VAbv,
/* 11130 */ VAbv, VBlw, VBlw, H, VAbv, O, B, B, B, B, B, B, B, B, B, B,
/* 11140 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 11140 */ O, O, O, O, B, VPst, VPst, O, O, O, O, O, O, O, O, O,
/* Mahajani */
@ -526,7 +526,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 11190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv,
/* 111C0 */ H, B, R, R, O, O, O, O, O, O, CMBlw, VAbv, VBlw, O, O, O,
/* 111C0 */ H, B, R, R, O, O, O, O, O, FM, CMBlw, VAbv, VBlw, O, O, O,
/* 111D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* Sinhala Archaic Numbers */
@ -541,7 +541,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw,
/* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, O,
#define use_offset_0x11280u 4064
#define use_offset_0x11280u 4072
/* Multani */
@ -563,13 +563,13 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 11300 */ VMAbv, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B,
/* 11310 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11320 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 11330 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPst,
/* 11330 */ B, O, B, B, O, B, B, B, B, B, O, CMBlw, CMBlw, B, VPst, VPst,
/* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O,
/* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, B, B,
/* 11360 */ B, B, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O,
/* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O,
#define use_offset_0x11400u 4312
#define use_offset_0x11400u 4320
/* Newa */
@ -579,7 +579,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 11420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11430 */ B, B, B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv,
/* 11440 */ VPst, VPst, H, VMAbv, VMAbv, VMPst, CMBlw, B, O, O, O, O, O, O, O, O,
/* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, FM, O,
/* 11460 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 11470 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
@ -592,7 +592,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 114C0 */ VMAbv, VMPst, H, CMBlw, B, O, O, O, O, O, O, O, O, O, O, O,
/* 114D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
#define use_offset_0x11580u 4536
#define use_offset_0x11580u 4544
/* Siddham */
@ -631,11 +631,21 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Ahom */
/* 11700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11710 */ B, B, B, B, B, B, B, B, B, B, O, O, O, MBlw, MPre, MAbv,
/* 11710 */ B, B, B, B, B, B, B, B, B, B, B, O, O, MBlw, MPre, MAbv,
/* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O,
/* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O,
#define use_offset_0x11a00u 4984
#define use_offset_0x11800u 4992
/* Dogra */
/* 11800 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11820 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPre, VPst, VBlw,
/* 11830 */ VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VMAbv, VMPst, H, CMBlw, O, O, O, O, O,
#define use_offset_0x11a00u 5056
/* Zanabazar Square */
@ -652,9 +662,9 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 11A60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11A70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11A80 */ B, B, B, B, O, O, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw,
/* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, H, O, O, O, O, O, O,
/* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, H, O, O, O, B, O, O,
#define use_offset_0x11c00u 5144
#define use_offset_0x11c00u 5216
/* Bhaiksuki */
@ -675,7 +685,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
/* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, O,
#define use_offset_0x11d00u 5328
#define use_offset_0x11d00u 5400
/* Masaram Gondi */
@ -687,7 +697,23 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 11D40 */ VMAbv, VMAbv, CMBlw, VAbv, VBlw, H, R, MBlw, O, O, O, O, O, O, O, O,
/* 11D50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
}; /* Table items: 5424; occupancy: 73% */
/* Gunjala Gondi */
/* 11D60 */ B, B, B, B, B, B, O, B, B, O, B, B, B, B, B, B,
/* 11D70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11D80 */ B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VPst, VPst, O,
/* 11D90 */ VAbv, VAbv, O, VPst, VPst, VMAbv, VMPst, H, O, O, O, O, O, O, O, O,
/* 11DA0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
#define use_offset_0x11ee0u 5576
/* Makasar */
/* 11EE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11EF0 */ B, B, GB, VAbv, VBlw, VPre, VPst, O,
}; /* Table items: 5600; occupancy: 73% */
USE_TABLE_ELEMENT_TYPE
hb_use_get_category (hb_codepoint_t u)
@ -727,7 +753,7 @@ hb_use_get_category (hb_codepoint_t u)
break;
case 0x10u:
if (hb_in_range<hb_codepoint_t> (u, 0x10A00u, 0x10A47u)) return use_table[u - 0x10A00u + use_offset_0x10a00u];
if (hb_in_range<hb_codepoint_t> (u, 0x10A00u, 0x10A4Fu)) return use_table[u - 0x10A00u + use_offset_0x10a00u];
break;
case 0x11u:
@ -736,9 +762,11 @@ hb_use_get_category (hb_codepoint_t u)
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, 0x11800u, 0x1183Fu)) return use_table[u - 0x11800u + use_offset_0x11800u];
if (hb_in_range<hb_codepoint_t> (u, 0x11A00u, 0x11A9Fu)) return use_table[u - 0x11A00u + use_offset_0x11a00u];
if (hb_in_range<hb_codepoint_t> (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u];
if (hb_in_range<hb_codepoint_t> (u, 0x11D00u, 0x11D5Fu)) return use_table[u - 0x11D00u + use_offset_0x11d00u];
if (hb_in_range<hb_codepoint_t> (u, 0x11D00u, 0x11DAFu)) return use_table[u - 0x11D00u + use_offset_0x11d00u];
if (hb_in_range<hb_codepoint_t> (u, 0x11EE0u, 0x11EF7u)) return use_table[u - 0x11EE0u + use_offset_0x11ee0u];
break;
default:

View File

@ -35,7 +35,7 @@
/*
* Universal Shaping Engine.
* https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm
* https://docs.microsoft.com/en-us/typography/script-development/use
*/
static const hb_tag_t
@ -511,7 +511,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len && !buffer->in_error)
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
@ -526,7 +526,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
/* TODO Set glyph_props? */
/* Insert dottedcircle after possible Repha. */
while (buffer->idx < buffer->len && !buffer->in_error &&
while (buffer->idx < buffer->len && buffer->successful &&
last_syllable == buffer->cur().syllable() &&
buffer->cur().use_category() == USE_R)
buffer->next_glyph ();

View File

@ -548,7 +548,7 @@ _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
case t::SPACE_NARROW:
/* Half-space?
* Unicode doc http://www.unicode.org/charts/PDF/U2000.pdf says ~1/4 or 1/5 of EM.
* Unicode doc https://unicode.org/charts/PDF/U2000.pdf says ~1/4 or 1/5 of EM.
* However, in my testing, many fonts have their regular space being about that
* size. To me, a percentage of the space width makes more sense. Half is as
* good as any. */

View File

@ -119,7 +119,7 @@ skip_char (hb_buffer_t *buffer)
static inline unsigned int
decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint_t ab)
{
hb_codepoint_t a, b, a_glyph, b_glyph;
hb_codepoint_t a = 0, b = 0, a_glyph = 0, b_glyph = 0;
hb_buffer_t * const buffer = c->buffer;
hb_font_t * const font = c->font;
@ -164,7 +164,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
{
hb_buffer_t * const buffer = c->buffer;
hb_codepoint_t u = buffer->cur().codepoint;
hb_codepoint_t glyph;
hb_codepoint_t glyph = 0;
if (shortest && c->font->get_nominal_glyph (u, &glyph))
{
@ -218,7 +218,7 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, uns
/* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
hb_buffer_t * const buffer = c->buffer;
hb_font_t * const font = c->font;
for (; buffer->idx < end - 1 && !buffer->in_error;) {
for (; buffer->idx < end - 1 && buffer->successful;) {
if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) {
/* The next two lines are some ugly lines... But work. */
if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
@ -254,13 +254,13 @@ static inline void
decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit)
{
hb_buffer_t * const buffer = c->buffer;
for (unsigned int i = buffer->idx; i < end && !buffer->in_error; i++)
for (unsigned int i = buffer->idx; i < end && buffer->successful; i++)
if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) {
handle_variation_selector_cluster (c, end, short_circuit);
return;
}
while (buffer->idx < end && !buffer->in_error)
while (buffer->idx < end && buffer->successful)
decompose_current_character (c, short_circuit);
}
@ -320,7 +320,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
buffer->clear_output ();
count = buffer->len;
for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;)
for (buffer->idx = 0; buffer->idx < count && buffer->successful;)
{
unsigned int end;
for (end = buffer->idx + 1; end < count; end++)
@ -373,7 +373,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
count = buffer->len;
unsigned int starter = 0;
buffer->next_glyph ();
while (buffer->idx < count && !buffer->in_error)
while (buffer->idx < count && buffer->successful)
{
hb_codepoint_t composed, glyph;
if (/* We don't try to compose a non-mark character with it's preceding starter.
@ -396,7 +396,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
{
/* Composes. */
buffer->next_glyph (); /* Copy to out-buffer. */
if (unlikely (buffer->in_error))
if (unlikely (!buffer->successful))
return;
buffer->merge_out_clusters (starter, buffer->out_len);
buffer->out_len--; /* Remove the second composable. */

View File

@ -59,7 +59,14 @@ struct hb_ot_shape_plan_t
inline void substitute (hb_font_t *font, hb_buffer_t *buffer) const { map.substitute (this, font, buffer); }
inline void position (hb_font_t *font, hb_buffer_t *buffer) const { map.position (this, font, buffer); }
void finish (void) { map.finish (); }
void init (void)
{
memset (this, 0, sizeof (*this));
map.init ();
}
void fini (void) {
map.fini ();
}
};
struct hb_ot_shape_planner_t
@ -75,7 +82,6 @@ struct hb_ot_shape_planner_t
props (master_plan->props),
shaper (nullptr),
map (face, &props) {}
~hb_ot_shape_planner_t (void) { map.finish (); }
inline void compile (hb_ot_shape_plan_t &plan,
const int *coords,
@ -99,9 +105,7 @@ struct hb_ot_shape_planner_t
}
private:
/* No copy. */
hb_ot_shape_planner_t (const hb_ot_shape_planner_t &);
hb_ot_shape_planner_t &operator = (const hb_ot_shape_planner_t &);
HB_DISALLOW_COPY_AND_ASSIGN (hb_ot_shape_planner_t);
};

View File

@ -180,6 +180,8 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
if (unlikely (!plan))
return nullptr;
plan->init ();
hb_ot_shape_planner_t planner (shape_plan);
planner.shaper = hb_ot_shape_complex_categorize (&planner);
@ -204,7 +206,7 @@ _hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan)
if (plan->shaper->data_destroy)
plan->shaper->data_destroy (const_cast<void *> (plan->data));
plan->finish ();
plan->fini ();
free (plan);
}
@ -268,7 +270,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
info.cluster = buffer->cur().cluster;
info.mask = buffer->cur().mask;
buffer->output_info (info);
while (buffer->idx < buffer->len && !buffer->in_error)
while (buffer->idx < buffer->len && buffer->successful)
buffer->next_glyph ();
buffer->swap_buffers ();
@ -306,13 +308,16 @@ static void
hb_ensure_native_direction (hb_buffer_t *buffer)
{
hb_direction_t direction = buffer->props.direction;
hb_direction_t horiz_dir = hb_script_get_horizontal_direction (buffer->props.script);
/* TODO vertical:
* The only BTT vertical script is Ogham, but it's not clear to me whether OpenType
* Ogham fonts are supposed to be implemented BTT or not. Need to research that
* first. */
if ((HB_DIRECTION_IS_HORIZONTAL (direction) && direction != hb_script_get_horizontal_direction (buffer->props.script)) ||
(HB_DIRECTION_IS_VERTICAL (direction) && direction != HB_DIRECTION_TTB))
if ((HB_DIRECTION_IS_HORIZONTAL (direction) &&
direction != horiz_dir && horiz_dir != HB_DIRECTION_INVALID) ||
(HB_DIRECTION_IS_VERTICAL (direction) &&
direction != HB_DIRECTION_TTB))
{
/* Same loop as hb_form_clusters().
* Since form_clusters() merged clusters already, we don't merge. */
@ -939,8 +944,6 @@ hb_ot_shape_glyphs_closure (hb_font_t *font,
unsigned int num_features,
hb_set_t *glyphs)
{
hb_ot_shape_plan_t plan;
const char *shapers[] = {"ot", nullptr};
hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props,
features, num_features, shapers);
@ -954,15 +957,7 @@ hb_ot_shape_glyphs_closure (hb_font_t *font,
hb_set_t *lookups = hb_set_create ();
hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, lookups);
/* And find transitive closure. */
hb_set_t *copy = hb_set_create ();
do {
copy->set (glyphs);
for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID; hb_set_next (lookups, &lookup_index);)
hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs);
} while (!copy->is_equal (glyphs));
hb_set_destroy (copy);
hb_ot_layout_lookups_substitute_closure (font->face, lookups, glyphs);
hb_set_destroy (lookups);

View File

@ -116,8 +116,7 @@ hb_ot_new_tag_to_script (hb_tag_t tag)
/*
* Complete list at:
* https://www.microsoft.com/typography/otspec/scripttags.htm
* https://www.microsoft.com/typography/otspec160/scripttagsProposed.htm
* https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags
*
* Most of the script tags are the same as the ISO 15924 tag but lowercased.
* So we just do that, and handle the exceptional cases in a switch.
@ -159,7 +158,7 @@ typedef struct {
/*
* Complete list at:
* http://www.microsoft.com/typography/otspec/languagetags.htm
* https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags
*
* Generated by intersecting the OpenType language tag list from
* Draft OpenType 1.5 spec, with with the ISO 639-3 codes from
@ -176,7 +175,7 @@ typedef struct {
* Updated as of 2015-05-06: OT1.7 on MS website has some newer
* items that we don't have here, eg. Zazaki. This is the new
* items in OpenType 1.7 (red items), most of which we have:
* http://www.microsoft.com/typography/otspec170/languagetags.htm
* https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags
*/
static const LangTag ot_languages[] = {

View File

@ -29,6 +29,14 @@
#include "hb-open-type-private.hh"
/*
* avar -- Axis Variations
* https://docs.microsoft.com/en-us/typography/opentype/spec/avar
*/
#define HB_OT_TAG_avar HB_TAG('a','v','a','r')
namespace OT {
@ -62,38 +70,32 @@ struct SegmentMaps : ArrayOf<AxisValueMap>
if (!len)
return value;
else /* len == 1*/
return value - array[0].fromCoord + array[0].toCoord;
return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;
}
if (value <= array[0].fromCoord)
return value - array[0].fromCoord + array[0].toCoord;
if (value <= arrayZ[0].fromCoord)
return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;
unsigned int i;
unsigned int count = len;
for (i = 1; i < count && value > array[i].fromCoord; i++)
for (i = 1; i < count && value > arrayZ[i].fromCoord; i++)
;
if (value >= array[i].fromCoord)
return value - array[i].fromCoord + array[i].toCoord;
if (value >= arrayZ[i].fromCoord)
return value - arrayZ[i].fromCoord + arrayZ[i].toCoord;
if (unlikely (array[i-1].fromCoord == array[i].fromCoord))
return array[i-1].toCoord;
if (unlikely (arrayZ[i-1].fromCoord == arrayZ[i].fromCoord))
return arrayZ[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;
int denom = arrayZ[i].fromCoord - arrayZ[i-1].fromCoord;
return arrayZ[i-1].toCoord +
((arrayZ[i].toCoord - arrayZ[i-1].toCoord) *
(value - arrayZ[i-1].fromCoord) + denom/2) / denom;
}
DEFINE_SIZE_ARRAY (2, array);
DEFINE_SIZE_ARRAY (2, arrayZ);
};
/*
* 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;
@ -106,7 +108,7 @@ struct avar
c->check_struct (this))))
return_trace (false);
const SegmentMaps *map = &axisSegmentMapsZ;
const SegmentMaps *map = axisSegmentMapsZ;
unsigned int count = axisCount;
for (unsigned int i = 0; i < count; i++)
{
@ -122,7 +124,7 @@ struct avar
{
unsigned int count = MIN<unsigned int> (coords_length, axisCount);
const SegmentMaps *map = &axisSegmentMapsZ;
const SegmentMaps *map = axisSegmentMapsZ;
for (unsigned int i = 0; i < count; i++)
{
coords[i] = map->map (coords[i]);
@ -137,7 +139,7 @@ struct avar
HBUINT16 axisCount; /* The number of variation axes in the font. This
* must be the same number as axisCount in the
* 'fvar' table. */
SegmentMaps axisSegmentMapsZ;
SegmentMaps axisSegmentMapsZ[VAR];
public:
DEFINE_SIZE_MIN (8);

View File

@ -29,6 +29,14 @@
#include "hb-open-type-private.hh"
/*
* fvar -- Font Variations
* https://docs.microsoft.com/en-us/typography/opentype/spec/fvar
*/
#define HB_OT_TAG_fvar HB_TAG('f','v','a','r')
namespace OT {
@ -42,11 +50,11 @@ struct InstanceRecord
}
protected:
HBUINT16 subfamilyNameID;/* The name ID for entries in the 'name' table
NameID subfamilyNameID;/* The name ID for entries in the 'name' table
* that provide subfamily names for this instance. */
HBUINT16 reserved; /* Reserved for future use — set to 0. */
Fixed coordinates[VAR];/* The coordinates array for this instance. */
//HBUINT16 postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
//NameID postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
// * table that provide PostScript names for this
// * instance. */
@ -68,20 +76,13 @@ struct AxisRecord
Fixed defaultValue; /* The default coordinate value for the axis. */
Fixed maxValue; /* The maximum coordinate value for the axis. */
HBUINT16 reserved; /* Reserved for future use — set to 0. */
HBUINT16 axisNameID; /* The name ID for entries in the 'name' table that
NameID 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;

View File

@ -89,10 +89,11 @@ struct DeltaSetIndexMap
/*
* HVAR -- The Horizontal Metrics Variations Table
* VVAR -- The Vertical Metrics Variations Table
* HVAR -- Horizontal Metrics Variations
* https://docs.microsoft.com/en-us/typography/opentype/spec/hvar
* VVAR -- Vertical Metrics Variations
* https://docs.microsoft.com/en-us/typography/opentype/spec/vvar
*/
#define HB_OT_TAG_HVAR HB_TAG('H','V','A','R')
#define HB_OT_TAG_VVAR HB_TAG('V','V','A','R')

View File

@ -51,9 +51,9 @@ struct VariationValueRecord
/*
* MVAR -- Metrics Variations Table
* MVAR -- Metrics Variations
* https://docs.microsoft.com/en-us/typography/opentype/spec/mvar
*/
#define HB_OT_TAG_MVAR HB_TAG('M','V','A','R')
struct MVAR

View File

@ -39,14 +39,14 @@
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);
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return 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);
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::avar);
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
return *(layout->avar.get ());
}
@ -65,7 +65,7 @@ _get_avar (hb_face_t *face)
hb_bool_t
hb_ot_var_has_data (hb_face_t *face)
{
return &_get_fvar (face) != &OT::Null(OT::fvar);
return &_get_fvar (face) != &Null(OT::fvar);
}
/**

View File

@ -51,7 +51,7 @@
#include <stdio.h>
#include <stdarg.h>
#if defined(_MSC_VER) || defined(__MINGW32__)
#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
#include <intrin.h>
#endif
@ -90,6 +90,14 @@ extern "C" void hb_free_impl(void *ptr);
HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
#endif // static_assert
#ifdef __GNUC__
#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
#define thread_local __thread
#endif
#else
#define thread_local
#endif
#endif // __cplusplus < 201103L
#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
@ -221,16 +229,14 @@ static int errno = 0; /* Use something better? */
# endif
# elif defined(_MSC_VER) || defined(__MINGW32__)
/* For MSVC:
* http://msdn.microsoft.com/en-ca/library/tze57ck3.aspx
* http://msdn.microsoft.com/en-ca/library/zk17ww08.aspx
* https://msdn.microsoft.com/en-us/library/tze57ck3.aspx
* https://msdn.microsoft.com/en-us/library/zk17ww08.aspx
* mingw32 headers say atexit is safe to use in shared libraries.
*/
# define HB_USE_ATEXIT 1
# elif defined(__ANDROID__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
/* This was fixed in Android NKD r8 or r8b:
* https://code.google.com/p/android/issues/detail?id=6455
* which introduced GCC 4.6:
* https://developer.android.com/tools/sdk/ndk/index.html
# elif defined(__ANDROID__)
/* This is available since Android NKD r8 or r8b:
* https://issuetracker.google.com/code/p/android/issues/detail?id=6455
*/
# define HB_USE_ATEXIT 1
# elif defined(__APPLE__)
@ -241,6 +247,9 @@ static int errno = 0; /* Use something better? */
# define HB_USE_ATEXIT 1
# endif
#endif
#ifdef HB_NO_ATEXIT
# undef HB_USE_ATEXIT
#endif
/* Basics */
@ -314,7 +323,7 @@ static_assert ((sizeof (hb_var_int_t) == 4), "");
/* Misc */
/* Tiny functions */
/*
* Void!
@ -360,7 +369,7 @@ _hb_popcount (T v)
}
assert (0);
return 0;
return 0; /* Shut up stupid compiler. */
}
/* Returns the number of bits needed to store number */
@ -381,7 +390,7 @@ _hb_bit_storage (T v)
return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
#endif
#if defined(_MSC_VER) || defined(__MINGW32__)
#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
if (sizeof (T) <= sizeof (unsigned int))
{
unsigned long where;
@ -415,7 +424,7 @@ _hb_bit_storage (T v)
if (sizeof (T) <= 8)
{
/* "bithacks" */
const uint64_t b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000};
const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
const unsigned int S[] = {1, 2, 4, 8, 16, 32};
unsigned int r = 0;
for (int i = 5; i >= 0; i--)
@ -429,12 +438,12 @@ _hb_bit_storage (T v)
if (sizeof (T) == 16)
{
unsigned int shift = 64;
return (v >> shift) ? _hb_bit_storage<uint64_t> ((uint64_t) v >> shift) + shift :
return (v >> shift) ? _hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
_hb_bit_storage<uint64_t> ((uint64_t) v);
}
assert (0);
return 0;
return 0; /* Shut up stupid compiler. */
}
/* Returns the number of zero bits in the least significant side of v */
@ -455,7 +464,7 @@ _hb_ctz (T v)
return __builtin_ctzll (v);
#endif
#if defined(_MSC_VER) || defined(__MINGW32__)
#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
if (sizeof (T) <= sizeof (unsigned int))
{
unsigned long where;
@ -491,12 +500,12 @@ _hb_ctz (T v)
unsigned int c = 64;
v &= - (int64_t) (v);
if (v) c--;
if (v & 0x00000000FFFFFFFF) c -= 32;
if (v & 0x0000FFFF0000FFFF) c -= 16;
if (v & 0x00FF00FF00FF00FF) c -= 8;
if (v & 0x0F0F0F0F0F0F0F0F) c -= 4;
if (v & 0x3333333333333333) c -= 2;
if (v & 0x5555555555555555) c -= 1;
if (v & 0x00000000FFFFFFFFULL) c -= 32;
if (v & 0x0000FFFF0000FFFFULL) c -= 16;
if (v & 0x00FF00FF00FF00FFULL) c -= 8;
if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
if (v & 0x3333333333333333ULL) c -= 2;
if (v & 0x5555555555555555ULL) c -= 1;
return c;
}
if (sizeof (T) == 16)
@ -507,7 +516,7 @@ _hb_ctz (T v)
}
assert (0);
return 0;
return 0; /* Shut up stupid compiler. */
}
static inline bool
@ -524,39 +533,147 @@ _hb_ceil_to_4 (unsigned int v)
/*
*
* Utility types
*
*/
#define HB_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
/*
* Static pools
*/
/* Global nul-content Null pool. Enlarge as necessary. */
#define HB_NULL_POOL_SIZE 264
static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE.");
#ifdef HB_NO_VISIBILITY
static
#else
extern HB_INTERNAL
#endif
void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)]
#ifdef HB_NO_VISIBILITY
= {}
#endif
;
/* Generic nul-content Null objects. */
template <typename Type>
static inline Type const & Null (void) {
static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
return *reinterpret_cast<Type const *> (_hb_NullPool);
}
#define Null(Type) Null<Type>()
/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
#define DEFINE_NULL_DATA(Namespace, Type, data) \
} /* Close namespace. */ \
static const char _Null##Type[sizeof (Namespace::Type) + 1] = data; /* +1 is for nul-termination in data */ \
template <> \
/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
return *reinterpret_cast<const Namespace::Type *> (_Null##Type); \
} \
namespace Namespace { \
/* The following line really exists such that we end in a place needing semicolon */ \
static_assert (Namespace::Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. Enlarge.")
/* Global writable pool. Enlarge as necessary. */
/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
* for correct operation. It only exist to catch and divert program logic bugs instead of
* causing bad memory access. So, races there are not actually introducing incorrectness
* in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
#ifdef HB_NO_VISIBILITY
static
#else
extern HB_INTERNAL
#endif
/*thread_local*/ void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)]
#ifdef HB_NO_VISIBILITY
= {}
#endif
;
/* CRAP pool: Common Region for Access Protection. */
template <typename Type>
static inline Type& Crap (void) {
static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
*obj = Null(Type);
return *obj;
}
#define Crap(Type) Crap<Type>()
template <typename Type>
struct CrapOrNull {
static inline Type & get (void) { return Crap(Type); }
};
template <typename Type>
struct CrapOrNull<const Type> {
static inline Type const & get (void) { return Null(Type); }
};
#define CrapOrNull(Type) CrapOrNull<Type>::get ()
/* arrays and maps */
#define HB_PREALLOCED_ARRAY_INIT {0, 0, nullptr}
template <typename Type, unsigned int StaticSize=16>
struct hb_prealloced_array_t
template <typename Type, unsigned int StaticSize=8>
struct hb_vector_t
{
unsigned int len;
unsigned int allocated;
Type *array;
bool successful;
Type *arrayZ;
Type static_array[StaticSize];
void init (void)
{
len = 0;
allocated = ARRAY_LENGTH (static_array);
array = static_array;
successful = true;
arrayZ = static_array;
}
inline Type& operator [] (unsigned int i) { return array[i]; }
inline const Type& operator [] (unsigned int i) const { return array[i]; }
inline Type& operator [] (unsigned int i)
{
if (unlikely (i >= len))
return Crap (Type);
return arrayZ[i];
}
inline const Type& operator [] (unsigned int i) const
{
if (unlikely (i >= len))
return Null(Type);
return arrayZ[i];
}
inline Type *push (void)
{
if (unlikely (!resize (len + 1)))
return nullptr;
return &array[len - 1];
return &Crap(Type);
return &arrayZ[len - 1];
}
inline Type *push (const Type& v)
{
Type *p = push ();
*p = v;
return p;
}
/* Allocate for size but don't adjust len. */
inline bool alloc(unsigned int size)
inline bool alloc (unsigned int size)
{
if (unlikely (!successful))
return false;
if (likely (size <= allocated))
return true;
@ -568,37 +685,47 @@ struct hb_prealloced_array_t
Type *new_array = nullptr;
if (array == static_array) {
if (arrayZ == static_array)
{
new_array = (Type *) calloc (new_allocated, sizeof (Type));
if (new_array)
memcpy (new_array, array, len * sizeof (Type));
} else {
memcpy (new_array, arrayZ, len * sizeof (Type));
}
else
{
bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
if (likely (!overflows)) {
new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
}
if (likely (!overflows))
new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
}
if (unlikely (!new_array))
{
successful = false;
return false;
}
array = new_array;
arrayZ = new_array;
allocated = new_allocated;
return true;
}
inline bool resize (unsigned int size)
inline bool resize (int size_)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
if (!alloc (size))
return false;
if (size > len)
memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ));
len = size;
return true;
}
inline void pop (void)
{
if (!len) return;
len--;
}
@ -606,54 +733,55 @@ struct hb_prealloced_array_t
{
if (unlikely (i >= len))
return;
memmove (static_cast<void *> (&array[i]),
static_cast<void *> (&array[i + 1]),
memmove (static_cast<void *> (&arrayZ[i]),
static_cast<void *> (&arrayZ[i + 1]),
(len - i - 1) * sizeof (Type));
len--;
}
inline void shrink (unsigned int l)
inline void shrink (int size_)
{
if (l < len)
len = l;
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
if (size < len)
len = size;
}
template <typename T>
inline Type *find (T v) {
for (unsigned int i = 0; i < len; i++)
if (array[i] == v)
return &array[i];
if (arrayZ[i] == v)
return &arrayZ[i];
return nullptr;
}
template <typename T>
inline const Type *find (T v) const {
for (unsigned int i = 0; i < len; i++)
if (array[i] == v)
return &array[i];
if (arrayZ[i] == v)
return &arrayZ[i];
return nullptr;
}
inline void qsort (int (*cmp)(const void*, const void*))
{
::qsort (array, len, sizeof (Type), cmp);
::qsort (arrayZ, len, sizeof (Type), cmp);
}
inline void qsort (void)
{
::qsort (array, len, sizeof (Type), Type::cmp);
::qsort (arrayZ, len, sizeof (Type), Type::cmp);
}
inline void qsort (unsigned int start, unsigned int end)
{
::qsort (array + start, end - start, sizeof (Type), Type::cmp);
::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp);
}
template <typename T>
inline Type *lsearch (const T &x)
{
for (unsigned int i = 0; i < len; i++)
if (0 == this->array[i].cmp (&x))
return &array[i];
if (0 == this->arrayZ[i].cmp (&x))
return &arrayZ[i];
return nullptr;
}
@ -661,13 +789,13 @@ struct hb_prealloced_array_t
inline Type *bsearch (const T &x)
{
unsigned int i;
return bfind (x, &i) ? &array[i] : nullptr;
return bfind (x, &i) ? &arrayZ[i] : nullptr;
}
template <typename T>
inline const Type *bsearch (const T &x) const
{
unsigned int i;
return bfind (x, &i) ? &array[i] : nullptr;
return bfind (x, &i) ? &arrayZ[i] : nullptr;
}
template <typename T>
inline bool bfind (const T &x, unsigned int *i) const
@ -676,7 +804,7 @@ struct hb_prealloced_array_t
while (min <= max)
{
int mid = (min + max) / 2;
int c = this->array[mid].cmp (&x);
int c = this->arrayZ[mid].cmp (&x);
if (c < 0)
max = mid - 1;
else if (c > 0)
@ -687,34 +815,39 @@ struct hb_prealloced_array_t
return true;
}
}
if (max < 0 || (max < (int) this->len && this->array[max].cmp (&x) > 0))
if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0))
max++;
*i = max;
return false;
}
inline void finish (void)
inline void fini (void)
{
if (array != static_array)
free (array);
array = nullptr;
if (arrayZ != static_array)
free (arrayZ);
arrayZ = nullptr;
allocated = len = 0;
}
};
template <typename Type>
struct hb_auto_array_t : hb_prealloced_array_t <Type>
struct hb_auto_t : Type
{
hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); }
~hb_auto_array_t (void) { hb_prealloced_array_t<Type>::finish (); }
hb_auto_t (void) { Type::init (); }
~hb_auto_t (void) { Type::fini (); }
private: /* Hide */
void init (void) {}
void fini (void) {}
};
template <typename Type>
struct hb_auto_array_t : hb_auto_t <hb_vector_t <Type> > {};
#define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT}
template <typename item_t, typename lock_t>
struct hb_lockable_set_t
{
hb_prealloced_array_t <item_t, 1> items;
hb_vector_t <item_t, 1> items;
inline void init (void) { items.init (); }
@ -728,16 +861,14 @@ struct hb_lockable_set_t
item_t old = *item;
*item = v;
l.unlock ();
old.finish ();
old.fini ();
}
else {
item = nullptr;
l.unlock ();
}
} else {
item = items.push ();
if (likely (item))
*item = v;
item = items.push (v);
l.unlock ();
}
return item;
@ -753,7 +884,7 @@ struct hb_lockable_set_t
*item = items[items.len - 1];
items.pop ();
l.unlock ();
old.finish ();
old.fini ();
} else {
l.unlock ();
}
@ -776,19 +907,17 @@ struct hb_lockable_set_t
l.lock ();
item_t *item = items.find (v);
if (!item) {
item = items.push ();
if (likely (item))
*item = v;
item = items.push (v);
}
l.unlock ();
return item;
}
inline void finish (lock_t &l)
inline void fini (lock_t &l)
{
if (!items.len) {
/* No need for locking. */
items.finish ();
items.fini ();
return;
}
l.lock ();
@ -796,10 +925,10 @@ struct hb_lockable_set_t
item_t old = items[items.len - 1];
items.pop ();
l.unlock ();
old.finish ();
old.fini ();
l.lock ();
}
items.finish ();
items.fini ();
l.unlock ();
}
@ -826,7 +955,7 @@ static inline unsigned char TOLOWER (unsigned char c)
* light-weight) to be enabled, then HB_DEBUG can be defined to disable
* the costlier checks. */
#ifdef NDEBUG
#define HB_NDEBUG
#define HB_NDEBUG 1
#endif
@ -975,19 +1104,35 @@ struct HbOpXor
template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
};
/* Compiler-assisted vectorization. */
/* The `vector_size' attribute was introduced in gcc 3.1. */
#if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
#define HB_VECTOR_SIZE 128
#elif !defined(HB_VECTOR_SIZE)
#define HB_VECTOR_SIZE 0
#endif
/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))). */
template <typename elt_t, unsigned int byte_size>
struct hb_vector_size_t
{
elt_t& operator [] (unsigned int i) { return v[i]; }
const elt_t& operator [] (unsigned int i) const { return v[i]; }
elt_t& operator [] (unsigned int i) { return u.v[i]; }
const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
template <class Op>
inline hb_vector_size_t process (const hb_vector_size_t &o) const
{
hb_vector_size_t r;
for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
Op::process (r.v[i], v[i], o.v[i]);
#if HB_VECTOR_SIZE
if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]);
else
#endif
for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
Op::process (r.u.v[i], u.v[i], o.u.v[i]);
return r;
}
inline hb_vector_size_t operator | (const hb_vector_size_t &o) const
@ -999,20 +1144,27 @@ struct hb_vector_size_t
inline hb_vector_size_t operator ~ () const
{
hb_vector_size_t r;
for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
r.v[i] = ~v[i];
#if HB_VECTOR_SIZE && 0
if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
r.u.vec[i] = ~u.vec[i];
else
#endif
for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
r.u.v[i] = ~u.v[i];
return r;
}
private:
static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
elt_t v[byte_size / sizeof (elt_t)];
};
/* The `vector_size' attribute was introduced in gcc 3.1. */
#if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
#define HAVE_VECTOR_SIZE 1
union {
elt_t v[byte_size / sizeof (elt_t)];
#if HB_VECTOR_SIZE
typedef unsigned long vec_t __attribute__((vector_size (HB_VECTOR_SIZE / 8)));
vec_t vec[byte_size / sizeof (vec_t)];
#endif
} u;
};
/* Global runtime options. */
@ -1049,12 +1201,12 @@ hb_options (void)
/* String type. */
struct hb_string_t
struct hb_bytes_t
{
inline hb_string_t (void) : bytes (nullptr), len (0) {}
inline hb_string_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {}
inline hb_bytes_t (void) : bytes (nullptr), len (0) {}
inline hb_bytes_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {}
inline int cmp (const hb_string_t &a) const
inline int cmp (const hb_bytes_t &a) const
{
if (len != a.len)
return (int) a.len - (int) len;
@ -1063,8 +1215,8 @@ struct hb_string_t
}
static inline int cmp (const void *pa, const void *pb)
{
hb_string_t *a = (hb_string_t *) pa;
hb_string_t *b = (hb_string_t *) pb;
hb_bytes_t *a = (hb_bytes_t *) pa;
hb_bytes_t *b = (hb_bytes_t *) pb;
return b->cmp (*a);
}
@ -1073,4 +1225,17 @@ struct hb_string_t
};
/* fallback for round() */
#if !defined (HAVE_ROUND) && !defined (HAVE_DECL_ROUND)
static inline double
round (double x)
{
if (x >= 0)
return floor (x + 0.5);
else
return ceil (x - 0.5);
}
#endif
#endif /* HB_PRIVATE_HH */

View File

@ -158,21 +158,13 @@ struct hb_set_t
}
typedef unsigned long long elt_t;
static const unsigned int PAGE_BITS = 1024;
static const unsigned int PAGE_BITS = 512;
static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
static inline unsigned int elt_get_min (const elt_t &elt) { return _hb_ctz (elt); }
static inline unsigned int elt_get_max (const elt_t &elt) { return _hb_bit_storage (elt) - 1; }
#if 0 && HAVE_VECTOR_SIZE
/* The vectorized version does not work with clang as non-const
* elt() errs "non-const reference cannot bind to vector element". */
typedef elt_t vector_t __attribute__((vector_size (PAGE_BITS / 8)));
#else
typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
#endif
vector_t v;
static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
static const unsigned int ELT_MASK = ELT_BITS - 1;
@ -183,34 +175,47 @@ struct hb_set_t
elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; }
elt_t const &elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & ELT_MASK); }
vector_t v;
};
static_assert (page_t::PAGE_BITS == sizeof (page_t) * 8, "");
hb_object_header_t header;
ASSERT_POD ();
bool in_error;
hb_prealloced_array_t<page_map_t, 8> page_map;
hb_prealloced_array_t<page_t, 1> pages;
bool successful; /* Allocations successful */
mutable unsigned int population;
hb_vector_t<page_map_t, 1> page_map;
hb_vector_t<page_t, 1> pages;
inline void init (void)
inline void init_shallow (void)
{
in_error = false;
successful = true;
population = 0;
page_map.init ();
pages.init ();
}
inline void finish (void)
inline void init (void)
{
page_map.finish ();
pages.finish ();
hb_object_init (this);
init_shallow ();
}
inline void fini_shallow (void)
{
page_map.fini ();
pages.fini ();
}
inline void fini (void)
{
hb_object_fini (this);
fini_shallow ();
}
inline bool resize (unsigned int count)
{
if (unlikely (in_error)) return false;
if (unlikely (!successful)) return false;
if (!pages.resize (count) || !page_map.resize (count))
{
pages.resize (page_map.len);
in_error = true;
successful = false;
return false;
}
return true;
@ -219,7 +224,8 @@ struct hb_set_t
inline void clear (void) {
if (unlikely (hb_object_is_inert (this)))
return;
in_error = false;
successful = true;
population = 0;
page_map.resize (0);
pages.resize (0);
}
@ -231,17 +237,21 @@ struct hb_set_t
return true;
}
inline void dirty (void) { population = (unsigned int) -1; }
inline void add (hb_codepoint_t g)
{
if (unlikely (in_error)) return;
if (unlikely (!successful)) return;
if (unlikely (g == INVALID)) return;
dirty ();
page_t *page = page_for_insert (g); if (unlikely (!page)) return;
page->add (g);
}
inline bool add_range (hb_codepoint_t a, hb_codepoint_t b)
{
if (unlikely (in_error)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
dirty ();
unsigned int ma = get_major (a);
unsigned int mb = get_major (b);
if (ma == mb)
@ -269,8 +279,9 @@ struct hb_set_t
template <typename T>
inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
{
if (unlikely (in_error)) return;
if (unlikely (!successful)) return;
if (!count) return;
dirty ();
hb_codepoint_t g = *array;
while (count)
{
@ -294,8 +305,9 @@ struct hb_set_t
template <typename T>
inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
{
if (unlikely (in_error)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
if (!count) return true;
dirty ();
hb_codepoint_t g = *array;
hb_codepoint_t last_g = g;
while (count)
@ -321,16 +333,19 @@ struct hb_set_t
inline void del (hb_codepoint_t g)
{
if (unlikely (in_error)) return;
/* TODO perform op even if !successful. */
if (unlikely (!successful)) return;
page_t *p = page_for (g);
if (!p)
return;
dirty ();
p->del (g);
}
inline void del_range (hb_codepoint_t a, hb_codepoint_t b)
{
/* TODO perform op even if !successful. */
/* TODO Optimize, like add_range(). */
if (unlikely (in_error)) return;
if (unlikely (!successful)) return;
for (unsigned int i = a; i < b + 1; i++)
del (i);
}
@ -349,17 +364,20 @@ struct hb_set_t
}
inline void set (const hb_set_t *other)
{
if (unlikely (in_error)) return;
if (unlikely (!successful)) return;
unsigned int count = other->pages.len;
if (!resize (count))
return;
memcpy (pages.array, other->pages.array, count * sizeof (pages.array[0]));
memcpy (page_map.array, other->page_map.array, count * sizeof (page_map.array[0]));
population = other->population;
memcpy (pages.arrayZ, other->pages.arrayZ, count * sizeof (pages.arrayZ[0]));
memcpy (page_map.arrayZ, other->page_map.arrayZ, count * sizeof (page_map.arrayZ[0]));
}
inline bool is_equal (const hb_set_t *other) const
{
if (get_population () != other->get_population ())
return false;
unsigned int na = pages.len;
unsigned int nb = other->pages.len;
@ -382,16 +400,31 @@ struct hb_set_t
return true;
}
inline bool is_subset (const hb_set_t *larger_set) const
{
if (get_population () > larger_set->get_population ())
return false;
hb_codepoint_t c = INVALID;
while (next (&c))
if (!larger_set->has (c))
return false;
return true;
}
template <class Op>
inline void process (const hb_set_t *other)
{
if (unlikely (in_error)) return;
if (unlikely (!successful)) return;
dirty ();
unsigned int na = pages.len;
unsigned int nb = other->pages.len;
unsigned int next_page = na;
unsigned int count = 0;
unsigned int count = 0, newCount = 0;
unsigned int a = 0, b = 0;
for (; a < na && b < nb; )
{
@ -419,8 +452,10 @@ struct hb_set_t
if (Op::passthru_right)
count += nb - b;
if (!resize (count))
return;
if (count > pages.len)
if (!resize (count))
return;
newCount = count;
/* Process in-place backward. */
a = na;
@ -473,6 +508,8 @@ struct hb_set_t
page_at (count).v = other->page_at (b).v;
}
assert (!count);
if (pages.len > newCount)
resize (newCount);
}
inline void union_ (const hb_set_t *other)
@ -592,10 +629,15 @@ struct hb_set_t
inline unsigned int get_population (void) const
{
if (population != (unsigned int) -1)
return population;
unsigned int pop = 0;
unsigned int count = pages.len;
for (unsigned int i = 0; i < count; i++)
pop += pages[i].get_population ();
population = pop;
return pop;
}
inline hb_codepoint_t get_min (void) const

View File

@ -45,18 +45,11 @@ hb_set_create (void)
if (!(set = hb_object_create<hb_set_t> ()))
return hb_set_get_empty ();
set->init ();
set->init_shallow ();
return set;
}
static const hb_set_t _hb_set_nil = {
HB_OBJECT_HEADER_STATIC,
true, /* in_error */
{0} /* elts */
};
/**
* hb_set_get_empty:
*
@ -67,7 +60,7 @@ static const hb_set_t _hb_set_nil = {
hb_set_t *
hb_set_get_empty (void)
{
return const_cast<hb_set_t *> (&_hb_set_nil);
return const_cast<hb_set_t *> (&Null(hb_set_t));
}
/**
@ -95,7 +88,7 @@ hb_set_destroy (hb_set_t *set)
{
if (!hb_object_destroy (set)) return;
set->finish ();
set->fini_shallow ();
free (set);
}
@ -150,9 +143,9 @@ hb_set_get_user_data (hb_set_t *set,
* Since: 0.9.2
**/
hb_bool_t
hb_set_allocation_successful (const hb_set_t *set HB_UNUSED)
hb_set_allocation_successful (const hb_set_t *set)
{
return !set->in_error;
return set->successful;
}
/**
@ -274,11 +267,11 @@ hb_set_del_range (hb_set_t *set,
/**
* hb_set_is_equal:
* @set: a set.
* @other:
* @other: other set.
*
*
*
* Return value:
* Return value: %TRUE if the two sets are equal, %FALSE otherwise.
*
* Since: 0.9.7
**/
@ -289,6 +282,24 @@ hb_set_is_equal (const hb_set_t *set,
return set->is_equal (other);
}
/**
* hb_set_is_subset:
* @set: a set.
* @larger_set: other set.
*
*
*
* Return value: %TRUE if the @set is a subset of (or equal to) @larger_set, %FALSE otherwise.
*
* Since: 1.8.1
**/
hb_bool_t
hb_set_is_subset (const hb_set_t *set,
const hb_set_t *larger_set)
{
return set->is_subset (larger_set);
}
/**
* hb_set_set:
* @set: a set.

View File

@ -82,8 +82,6 @@ HB_EXTERN hb_bool_t
hb_set_has (const hb_set_t *set,
hb_codepoint_t codepoint);
/* Right now limited to 16-bit integers. Eventually will do full codepoint range, sans -1
* which we will use as a sentinel. */
HB_EXTERN void
hb_set_add (hb_set_t *set,
hb_codepoint_t codepoint);
@ -106,6 +104,10 @@ HB_EXTERN hb_bool_t
hb_set_is_equal (const hb_set_t *set,
const hb_set_t *other);
HB_EXTERN hb_bool_t
hb_set_is_subset (const hb_set_t *set,
const hb_set_t *larger_set);
HB_EXTERN void
hb_set_set (hb_set_t *set,
const hb_set_t *other);

View File

@ -51,7 +51,12 @@ static const char **static_shaper_list;
static
void free_static_shaper_list (void)
{
free (static_shaper_list);
retry:
const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
if (!hb_atomic_ptr_cmpexch (&static_shaper_list, shaper_list, nullptr))
goto retry;
free (shaper_list);
}
#endif

View File

@ -44,8 +44,13 @@ static const hb_shaper_pair_t *static_shapers;
static
void free_static_shapers (void)
{
if (unlikely (static_shapers != all_shapers))
free ((void *) static_shapers);
retry:
hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_shapers);
if (!hb_atomic_ptr_cmpexch (&static_shapers, shapers, nullptr))
goto retry;
if (unlikely (shapers != all_shapers))
free ((void *) shapers);
}
#endif

View File

@ -0,0 +1,32 @@
/*
* Copyright © 2018 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-private.hh"
#ifndef HB_NO_VISIBILITY
void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
/*thread_local*/ void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
#endif

View File

@ -42,7 +42,7 @@ static const union HB_STRING_ARRAY_TYPE_NAME {
struct {
/* I like to avoid storing the nul-termination byte since we don't need it,
* but C++ does not allow that.
* https://stackoverflow.com/questions/28433862/why-initializer-string-for-array-of-chars-is-too-long-compiles-fine-in-c-not
* https://stackoverflow.com/q/28433862
*/
#define _S(s) char HB_PASTE (str, __LINE__)[sizeof (s)];
#include HB_STRING_ARRAY_LIST
@ -66,12 +66,12 @@ static const unsigned int HB_STRING_ARRAY_OFFS_NAME[] =
sizeof (HB_STRING_ARRAY_TYPE_NAME)
};
static inline hb_string_t
static inline hb_bytes_t
HB_STRING_ARRAY_NAME (unsigned int i)
{
assert (i < ARRAY_LENGTH (HB_STRING_ARRAY_OFFS_NAME) - 1);
return hb_string_t (HB_STRING_ARRAY_POOL_NAME.str + HB_STRING_ARRAY_OFFS_NAME[i],
HB_STRING_ARRAY_OFFS_NAME[i + 1] - HB_STRING_ARRAY_OFFS_NAME[i] - 1);
return hb_bytes_t (HB_STRING_ARRAY_POOL_NAME.str + HB_STRING_ARRAY_OFFS_NAME[i],
HB_STRING_ARRAY_OFFS_NAME[i + 1] - HB_STRING_ARRAY_OFFS_NAME[i] - 1);
}
#undef HB_STRING_ARRAY_TYPE_NAME

View File

@ -30,31 +30,68 @@
#include "hb-private.hh"
#include "hb-subset.h"
#include "hb-subset-private.hh"
#include "hb-object-private.hh"
#include "hb-map-private.hh"
struct hb_subset_plan_t {
struct hb_subset_plan_t
{
hb_object_header_t header;
ASSERT_POD ();
hb_bool_t drop_hints;
hb_bool_t drop_ot_layout;
// TODO(Q1) actual map, drop this crap
// Look at me ma, I'm a poor mans map codepoint : new gid
// codepoints is sorted and aligned with gids_to_retain.
// These first two lists provide a mapping from cp -> gid
// As a result it does not list the full set of glyphs to retain.
hb_prealloced_array_t<hb_codepoint_t> codepoints;
hb_prealloced_array_t<hb_codepoint_t> gids_to_retain;
// For each cp that we'd like to retain maps to the corresponding gid.
hb_set_t *unicodes;
// This list contains the complete set of glyphs to retain and may contain
// more glyphs then the lists above.
hb_prealloced_array_t<hb_codepoint_t> gids_to_retain_sorted;
hb_vector_t<hb_codepoint_t> glyphs;
hb_map_t *codepoint_to_glyph;
hb_map_t *glyph_map;
// Plan is only good for a specific source/dest so keep them with it
hb_face_t *source;
hb_face_t *dest;
inline hb_bool_t
new_gid_for_codepoint (hb_codepoint_t codepoint,
hb_codepoint_t *new_gid) const
{
hb_codepoint_t old_gid = codepoint_to_glyph->get (codepoint);
if (old_gid == HB_MAP_VALUE_INVALID)
return false;
return new_gid_for_old_gid (old_gid, new_gid);
}
inline hb_bool_t
new_gid_for_old_gid (hb_codepoint_t old_gid,
hb_codepoint_t *new_gid) const
{
hb_codepoint_t gid = glyph_map->get (old_gid);
if (gid == HB_MAP_VALUE_INVALID)
return false;
*new_gid = gid;
return true;
}
inline hb_bool_t
add_table (hb_tag_t tag,
hb_blob_t *contents)
{
hb_blob_t *source_blob = source->reference_table (tag);
DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %d bytes, source %d bytes",
HB_UNTAG(tag),
hb_blob_get_length (contents),
hb_blob_get_length (source_blob));
hb_blob_destroy (source_blob);
return hb_subset_face_add_table(dest, tag, contents);
}
};
typedef struct hb_subset_plan_t hb_subset_plan_t;
@ -64,21 +101,6 @@ hb_subset_plan_create (hb_face_t *face,
hb_subset_profile_t *profile,
hb_subset_input_t *input);
HB_INTERNAL hb_bool_t
hb_subset_plan_new_gid_for_old_id(hb_subset_plan_t *plan,
hb_codepoint_t old_gid,
hb_codepoint_t *new_gid /* OUT */);
HB_INTERNAL hb_bool_t
hb_subset_plan_new_gid_for_codepoint(hb_subset_plan_t *plan,
hb_codepoint_t codepont,
hb_codepoint_t *new_gid /* OUT */);
HB_INTERNAL hb_bool_t
hb_subset_plan_add_table(hb_subset_plan_t *plan,
hb_tag_t tag,
hb_blob_t *contents);
HB_INTERNAL void
hb_subset_plan_destroy (hb_subset_plan_t *plan);

View File

@ -44,6 +44,7 @@ struct hb_subset_input_t {
hb_set_t *glyphs;
hb_bool_t drop_hints;
hb_bool_t drop_ot_layout;
/* TODO
*
* features

View File

@ -71,13 +71,19 @@ hb_subset_input_glyph_set (hb_subset_input_t *subset_input);
HB_EXTERN hb_bool_t *
hb_subset_input_drop_hints (hb_subset_input_t *subset_input);
/* hb_subset() */
HB_EXTERN hb_bool_t *
hb_subset_input_drop_ot_layout (hb_subset_input_t *subset_input);
/* hb_subset() */
HB_EXTERN hb_face_t *
hb_subset (hb_face_t *source,
hb_subset_profile_t *profile,
hb_subset_input_t *input);
/* hb_subset_get_all_codepoints */
HB_EXTERN void
hb_subset_get_all_codepoints (hb_face_t *source, hb_set_t *out);
HB_END_DECLS
#endif /* HB_SUBSET_H */

View File

@ -164,6 +164,13 @@ static const hb_script_t ucdn_script_translate[] =
HB_SCRIPT_NUSHU,
HB_SCRIPT_SOYOMBO,
HB_SCRIPT_ZANABAZAR_SQUARE,
HB_SCRIPT_DOGRA,
HB_SCRIPT_GUNJALA_GONDI,
HB_SCRIPT_HANIFI_ROHINGYA,
HB_SCRIPT_MAKASAR,
HB_SCRIPT_MEDEFAIDRIN,
HB_SCRIPT_OLD_SOGDIAN,
HB_SCRIPT_SOGDIAN,
};
static hb_unicode_combining_class_t
@ -237,7 +244,12 @@ static hb_unicode_funcs_t *static_ucdn_funcs = nullptr;
static
void free_static_ucdn_funcs (void)
{
hb_unicode_funcs_destroy (static_ucdn_funcs);
retry:
hb_unicode_funcs_t *ucdn_funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs);
if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, ucdn_funcs, nullptr))
goto retry;
hb_unicode_funcs_destroy (ucdn_funcs);
}
#endif

View File

@ -42,6 +42,16 @@ HB_BEGIN_HEADER
# include <inttypes.h>
#elif defined (_AIX)
# include <sys/inttypes.h>
#elif defined (_MSC_VER) && _MSC_VER < 1600
/* VS 2010 (_MSC_VER 1600) has stdint.h */
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
# include <stdint.h>
#endif

View File

@ -202,8 +202,8 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
}
/* Space estimates based on:
* http://www.unicode.org/charts/PDF/U2000.pdf
* https://www.microsoft.com/typography/developers/fdsspec/spaces.aspx
* https://unicode.org/charts/PDF/U2000.pdf
* https://docs.microsoft.com/en-us/typography/develop/character-design-standards/whitespace
*/
enum space_t {
NOT_SPACE = 0,
@ -276,10 +276,10 @@ extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
* We permute the "fixed-position" classes 10-26 into the order
* described in the SBL Hebrew manual:
*
* http://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf
* https://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf
*
* (as recommended by:
* http://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering-t6751.0.html)
* https://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering/msg22823/)
*
* More details here:
* https://bugzilla.mozilla.org/show_bug.cgi?id=662055
@ -306,8 +306,8 @@ extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
* Arabic
*
* Modify to move Shadda (ccc=33) before other marks. See:
* http://unicode.org/faq/normalization.html#8
* http://unicode.org/faq/normalization.html#9
* https://unicode.org/faq/normalization.html#8
* https://unicode.org/faq/normalization.html#9
*/
#define HB_MODIFIED_COMBINING_CLASS_CCC27 28 /* fathatan */
#define HB_MODIFIED_COMBINING_CLASS_CCC28 29 /* dammatan */

View File

@ -64,7 +64,7 @@ hb_unicode_general_category_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
static hb_codepoint_t
hb_unicode_mirroring_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
hb_codepoint_t unicode HB_UNUSED,
hb_codepoint_t unicode,
void *user_data HB_UNUSED)
{
return unicode;

View File

@ -37,10 +37,10 @@ HB_BEGIN_DECLS
#define HB_VERSION_MAJOR 1
#define HB_VERSION_MINOR 7
#define HB_VERSION_MICRO 6
#define HB_VERSION_MINOR 8
#define HB_VERSION_MICRO 1
#define HB_VERSION_STRING "1.7.6"
#define HB_VERSION_STRING "1.8.1"
#define HB_VERSION_ATLEAST(major,minor,micro) \
((major)*10000+(minor)*100+(micro) <= \

View File

@ -38,6 +38,7 @@
#include "hb-deprecated.h"
#include "hb-face.h"
#include "hb-font.h"
#include "hb-map.h"
#include "hb-set.h"
#include "hb-shape.h"
#include "hb-shape-plan.h"