Update bundled HarfBuzz-NG copy to 0.9.32
- Unicode 7.0 support - New shapers - Multiple improvements in Arabic, Indic, and Hebrew shapers - Build fixes, optimizations, etc. Change-Id: I0ba14b619c3e6fb35cddd9d65e694af41197d6ae Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
This commit is contained in:
parent
0078013693
commit
461c2b2004
@ -41,7 +41,7 @@
|
||||
|
||||
#include <harfbuzz/hb.h>
|
||||
|
||||
#if ((HB_VERSION_MAJOR*10000 + HB_VERSION_MINOR*100 + HB_VERSION_MICRO) < 912)
|
||||
#if !HB_VERSION_ATLEAST(0, 9, 31)
|
||||
# error "This version of harfbuzz is too old."
|
||||
#endif
|
||||
|
||||
|
1
src/3rdparty/harfbuzz-ng/AUTHORS
vendored
1
src/3rdparty/harfbuzz-ng/AUTHORS
vendored
@ -4,5 +4,6 @@ Martin Hosken
|
||||
Jonathan Kew
|
||||
Lars Knoll
|
||||
Werner Lemberg
|
||||
Roozbeh Pournader
|
||||
Owen Taylor
|
||||
David Turner
|
||||
|
119
src/3rdparty/harfbuzz-ng/NEWS
vendored
119
src/3rdparty/harfbuzz-ng/NEWS
vendored
@ -1,3 +1,122 @@
|
||||
Overview of changes leading to 0.9.32
|
||||
Thursday, July 17, 2014
|
||||
=====================================
|
||||
|
||||
- Apply Arabic shaping features in spec order exactly.
|
||||
- Another fix for Mongolian free variation selectors.
|
||||
- For non-Arabic scripts in Arabic shaper apply 'rlig' and 'calt'
|
||||
together.
|
||||
- Minor adjustment to U+FFFD logic.
|
||||
- Fix hb-coretext build.
|
||||
|
||||
|
||||
Overview of changes leading to 0.9.31
|
||||
Wednesday, July 16, 2014
|
||||
=====================================
|
||||
|
||||
- Only accept valid UTF-8/16/32; we missed many cases before.
|
||||
- Better shaping of invalid UTF-8/16/32. Falls back to
|
||||
U+FFFD REPLACEMENT CHARACTER now.
|
||||
- With all changes in this release, the buffer will contain fully
|
||||
valid Unicode after hb_buffer_add_utf8/16/32 no matter how
|
||||
broken the input is. This can be overriden though. See below.
|
||||
- Fix Mongolian Variation Selectors for fonts without GDEF.
|
||||
- Fix minor invalid buffer access.
|
||||
- Accept zh-Hant and zh-Hans language tags. hb_ot_tag_to_language()
|
||||
now uses these instead of private tags.
|
||||
- Build fixes.
|
||||
- New API:
|
||||
* hb_buffer_add_codepoints(). This does what hb_buffer_add_utf32()
|
||||
used to do, ie. no validity check on the input at all. add_utf32
|
||||
now replaces invalid Unicode codepoints with the replacement
|
||||
character (see below).
|
||||
* hb_buffer_set_replacement_codepoint()
|
||||
* hb_buffer_get_replacement_codepoint()
|
||||
Previously, in hb_buffer_add_utf8 and hb_buffer_add_utf16, when
|
||||
we detected broken input, we replaced that with (hb_codepoint_t)-1.
|
||||
This has changed to use U+FFFD now, but can be changed using these
|
||||
new API.
|
||||
|
||||
|
||||
Overview of changes leading to 0.9.30
|
||||
Wednesday, July 9, 2014
|
||||
=====================================
|
||||
|
||||
- Update to Unicode 7.0.0:
|
||||
* New scripts Manichaean and Psalter Pahlavi are shaped using
|
||||
Arabic shaper.
|
||||
* All the other new scripts to through the generic shaper for
|
||||
now.
|
||||
- Minor Indic improvements.
|
||||
- Fix graphite2 backend cluster mapping [crasher!]
|
||||
- API changes:
|
||||
* New HB_SCRIPT_* values for Unicode 7.0 scripts.
|
||||
* New function hb_ot_layout_language_get_required_feature().
|
||||
- Build fixes.
|
||||
|
||||
|
||||
Overview of changes leading to 0.9.29
|
||||
Thursday, May 29, 2014
|
||||
=====================================
|
||||
|
||||
- Implement cmap in hb-ot-font.h. No variation-selectors yet.
|
||||
- Myanmar: Allow MedialYa+Asat.
|
||||
- Various Indic fixes:
|
||||
* Support most characters in Extended Devanagary and Vedic
|
||||
Unicode blocks.
|
||||
* Allow digits and a some punctuation as consonant placeholders.
|
||||
- Build fixes.
|
||||
|
||||
|
||||
Overview of changes leading to 0.9.28
|
||||
Monday, April 28, 2014
|
||||
=====================================
|
||||
|
||||
- Unbreak old-spec Indic shaping. (bug 76705)
|
||||
- Fix shaping of U+17DD and U+0FC6.
|
||||
- Add HB_NO_MERGE_CLUSTERS build option. NOT to be enabled by default
|
||||
for shipping libraries. It's an option for further experimentation
|
||||
right now. When we are sure how to do it properly, we will add
|
||||
public run-time API for the functionality.
|
||||
- Build fixes.
|
||||
|
||||
|
||||
Overview of changes leading to 0.9.27
|
||||
Tuesday, March 18, 2014
|
||||
=====================================
|
||||
|
||||
- Don't use "register" storage class specifier
|
||||
- Wrap definition of free_langs() with HAVE_ATEXIT
|
||||
- Add coretext_aat shaper and hb_coretext_face_create() constructor
|
||||
- If HAVE_ICU_BUILTIN is defined, use hb-icu Unicode callbacks
|
||||
- Add Myanmar test case from OpenType Myanmar spec
|
||||
- Only do fallback Hebrew composition if no GPOS 'mark' available
|
||||
- Allow bootstrapping without gtk-doc
|
||||
- Use AM_MISSING_PROG for ragel and git
|
||||
- Typo in ucdn's Makefile.am
|
||||
- Improve MemoryBarrier() implementation
|
||||
|
||||
|
||||
Overview of changes leading to 0.9.26
|
||||
Thursday, January 30, 2014
|
||||
=====================================
|
||||
|
||||
- Misc fixes.
|
||||
- Fix application of 'rtlm' feature.
|
||||
- Automatically apply frac/numr/dnom around U+2044 FRACTION SLASH.
|
||||
- New header: hb-ot-shape.h
|
||||
- Uniscribe: fix scratch-buffer accounting.
|
||||
- Reorder Tai Tham SAKOT to after tone-marks.
|
||||
- Add Hangul shaper.
|
||||
- New files:
|
||||
hb-ot-shape-complex-hangul.cc
|
||||
hb-ot-shape-complex-hebrew.cc
|
||||
hb-ot-shape-complex-tibetan.cc
|
||||
- Disable 'cswh' feature in Arabic shaper.
|
||||
- Coretext: better handle surrogate pairs.
|
||||
- Add HB_TAG_MAX and _HB_SCRIPT_MAX_VALUE.
|
||||
|
||||
|
||||
Overview of changes leading to 0.9.25
|
||||
Wednesday, December 4, 2013
|
||||
=====================================
|
||||
|
7
src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
vendored
7
src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
vendored
@ -7,8 +7,7 @@ CONFIG += \
|
||||
|
||||
load(qt_helper_lib)
|
||||
|
||||
DEFINES += HAVE_CONFIG_H
|
||||
HEADERS += $$PWD/src/config.h
|
||||
DEFINES += HAVE_OT HAVE_ATEXIT HB_NO_UNICODE_FUNCS HB_DISABLE_DEPRECATED
|
||||
|
||||
INCLUDEPATH += $$PWD/include
|
||||
|
||||
@ -39,6 +38,7 @@ HEADERS += \
|
||||
$$PWD/src/hb-object-private.hh \
|
||||
$$PWD/src/hb-open-file-private.hh \
|
||||
$$PWD/src/hb-open-type-private.hh \
|
||||
$$PWD/src/hb-ot-cmap-table.hh \
|
||||
$$PWD/src/hb-ot-head-table.hh \
|
||||
$$PWD/src/hb-ot-hhea-table.hh \
|
||||
$$PWD/src/hb-ot-hmtx-table.hh \
|
||||
@ -58,6 +58,7 @@ HEADERS += \
|
||||
$$PWD/src/hb-blob.h \
|
||||
$$PWD/src/hb-buffer.h \
|
||||
$$PWD/src/hb-common.h \
|
||||
$$PWD/src/hb-deprecated.h \
|
||||
$$PWD/src/hb-face.h \
|
||||
$$PWD/src/hb-font.h \
|
||||
$$PWD/src/hb-set.h \
|
||||
@ -68,6 +69,7 @@ HEADERS += \
|
||||
|
||||
# Open Type
|
||||
SOURCES += \
|
||||
$$PWD/src/hb-ot-font.cc \
|
||||
$$PWD/src/hb-ot-layout.cc \
|
||||
$$PWD/src/hb-ot-map.cc \
|
||||
$$PWD/src/hb-ot-shape.cc \
|
||||
@ -106,6 +108,7 @@ HEADERS += \
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/src/hb-ot.h \
|
||||
$$PWD/src/hb-ot-font.h \
|
||||
$$PWD/src/hb-ot-layout.h \
|
||||
$$PWD/src/hb-ot-shape.h \
|
||||
$$PWD/src/hb-ot-tag.h
|
||||
|
1
src/3rdparty/harfbuzz-ng/include/harfbuzz/hb-ot-font.h
vendored
Normal file
1
src/3rdparty/harfbuzz-ng/include/harfbuzz/hb-ot-font.h
vendored
Normal file
@ -0,0 +1 @@
|
||||
#include "../../src/hb-ot-font.h"
|
14
src/3rdparty/harfbuzz-ng/src/config.h
vendored
14
src/3rdparty/harfbuzz-ng/src/config.h
vendored
@ -1,14 +0,0 @@
|
||||
#ifndef HB_CONFIG_H
|
||||
#define HB_CONFIG_H
|
||||
|
||||
#define HAVE_OT
|
||||
#define HAVE_ATEXIT
|
||||
|
||||
#define HB_NO_UNICODE_FUNCS
|
||||
|
||||
#define HB_DISABLE_DEPRECATED
|
||||
|
||||
// because strdup() is not part of strict Posix, declare it here
|
||||
extern "C" char *strdup(const char *src);
|
||||
|
||||
#endif /* HB_CONFIG_H */
|
@ -47,18 +47,22 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#if defined(__MINGW32__) && !defined(MemoryBarrier)
|
||||
/* MinGW has a convoluted history of supporting MemoryBarrier
|
||||
* properly. As such, define a function to wrap the whole
|
||||
* thing. */
|
||||
static inline void _HBMemoryBarrier (void) {
|
||||
#if !defined(MemoryBarrier)
|
||||
long dummy = 0;
|
||||
InterlockedExchange (&dummy, 1);
|
||||
}
|
||||
# define MemoryBarrier _HBMemoryBarrier
|
||||
#else
|
||||
MemoryBarrier ();
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef LONG hb_atomic_int_t;
|
||||
#define hb_atomic_int_add(AI, V) InterlockedExchangeAdd (&(AI), (V))
|
||||
|
||||
#define hb_atomic_ptr_get(P) (MemoryBarrier (), (void *) *(P))
|
||||
#define hb_atomic_ptr_get(P) (_HBMemoryBarrier (), (void *) *(P))
|
||||
#define hb_atomic_ptr_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
|
||||
|
||||
|
||||
@ -78,7 +82,7 @@ typedef int32_t hb_atomic_int_t;
|
||||
#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
|
||||
#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
|
||||
#else
|
||||
#if __ppc64__ || __x86_64__ || __arm64__
|
||||
#if __ppc64__ || __x86_64__ || __aarch64__
|
||||
#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P))
|
||||
#else
|
||||
#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P))
|
||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-blob.cc
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-blob.cc
vendored
@ -25,7 +25,9 @@
|
||||
*/
|
||||
|
||||
/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */
|
||||
#ifndef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
#endif
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
|
7
src/3rdparty/harfbuzz-ng/src/hb-blob.h
vendored
7
src/3rdparty/harfbuzz-ng/src/hb-blob.h
vendored
@ -47,14 +47,13 @@ HB_BEGIN_DECLS
|
||||
* - Use MODE_READONLY otherse, unless you really really
|
||||
* really know what you are doing,
|
||||
*
|
||||
* - MODE_WRITABLE is appropriate if you relaly made a
|
||||
* - MODE_WRITABLE is appropriate if you really made a
|
||||
* copy of data solely for the purpose of passing to
|
||||
* HarfBuzz and doing that just once (no reuse!),
|
||||
*
|
||||
* - If the font is mmap()ed, it's ok to use
|
||||
* READONLY_MAY_MAKE_WRITABLE, however, there were
|
||||
* design problems with that mode, so HarfBuzz do not
|
||||
* really use it anymore. If not sure, use MODE_READONLY.
|
||||
* READONLY_MAY_MAKE_WRITABLE, however, using that mode
|
||||
* correctly is very tricky. Use MODE_READONLY instead.
|
||||
*/
|
||||
typedef enum {
|
||||
HB_MEMORY_MODE_DUPLICATE,
|
||||
|
@ -52,6 +52,7 @@ struct hb_buffer_t {
|
||||
hb_unicode_funcs_t *unicode; /* Unicode functions */
|
||||
hb_segment_properties_t props; /* Script, language, direction */
|
||||
hb_buffer_flags_t flags; /* BOT / EOT / etc. */
|
||||
hb_codepoint_t replacement; /* U+FFFD or something else. */
|
||||
|
||||
/* Buffer contents */
|
||||
|
||||
|
@ -63,7 +63,7 @@ hb_buffer_serialize_format_t
|
||||
hb_buffer_serialize_format_from_string (const char *str, int len)
|
||||
{
|
||||
/* Upper-case it. */
|
||||
return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020);
|
||||
return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020u);
|
||||
}
|
||||
|
||||
/**
|
||||
|
87
src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
vendored
87
src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
vendored
@ -178,6 +178,7 @@ hb_buffer_t::reset (void)
|
||||
|
||||
hb_unicode_funcs_destroy (unicode);
|
||||
unicode = hb_unicode_funcs_get_default ();
|
||||
replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
|
||||
|
||||
clear ();
|
||||
}
|
||||
@ -500,6 +501,10 @@ void
|
||||
hb_buffer_t::merge_clusters (unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
#ifdef HB_NO_MERGE_CLUSTERS
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (unlikely (end - start < 2))
|
||||
return;
|
||||
|
||||
@ -528,6 +533,10 @@ void
|
||||
hb_buffer_t::merge_out_clusters (unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
#ifdef HB_NO_MERGE_CLUSTERS
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (unlikely (end - start < 2))
|
||||
return;
|
||||
|
||||
@ -695,6 +704,7 @@ hb_buffer_get_empty (void)
|
||||
const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
|
||||
HB_SEGMENT_PROPERTIES_DEFAULT,
|
||||
HB_BUFFER_FLAG_DEFAULT,
|
||||
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
|
||||
|
||||
HB_BUFFER_CONTENT_TYPE_INVALID,
|
||||
true, /* in_error */
|
||||
@ -1039,6 +1049,42 @@ hb_buffer_get_flags (hb_buffer_t *buffer)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hb_buffer_set_replacement_codepoint:
|
||||
* @buffer: a buffer.
|
||||
* @replacement:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 1.0
|
||||
**/
|
||||
void
|
||||
hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
|
||||
hb_codepoint_t replacement)
|
||||
{
|
||||
if (unlikely (hb_object_is_inert (buffer)))
|
||||
return;
|
||||
|
||||
buffer->replacement = replacement;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_buffer_get_replacement_codepoint:
|
||||
* @buffer: a buffer.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Since: 1.0
|
||||
**/
|
||||
hb_codepoint_t
|
||||
hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer)
|
||||
{
|
||||
return buffer->replacement;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hb_buffer_reset:
|
||||
* @buffer: a buffer.
|
||||
@ -1282,7 +1328,7 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer)
|
||||
buffer->guess_segment_properties ();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <bool validate, typename T>
|
||||
static inline void
|
||||
hb_buffer_add_utf (hb_buffer_t *buffer,
|
||||
const T *text,
|
||||
@ -1290,6 +1336,9 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
|
||||
unsigned int item_offset,
|
||||
int item_length)
|
||||
{
|
||||
typedef hb_utf_t<T, true> utf_t;
|
||||
const hb_codepoint_t replacement = buffer->replacement;
|
||||
|
||||
assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
|
||||
(!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
|
||||
|
||||
@ -1297,7 +1346,7 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
|
||||
return;
|
||||
|
||||
if (text_length == -1)
|
||||
text_length = hb_utf_strlen (text);
|
||||
text_length = utf_t::strlen (text);
|
||||
|
||||
if (item_length == -1)
|
||||
item_length = text_length - item_offset;
|
||||
@ -1320,7 +1369,7 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
|
||||
while (start < prev && buffer->context_len[0] < buffer->CONTEXT_LENGTH)
|
||||
{
|
||||
hb_codepoint_t u;
|
||||
prev = hb_utf_prev (prev, start, &u);
|
||||
prev = utf_t::prev (prev, start, &u, replacement);
|
||||
buffer->context[0][buffer->context_len[0]++] = u;
|
||||
}
|
||||
}
|
||||
@ -1331,7 +1380,7 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
|
||||
{
|
||||
hb_codepoint_t u;
|
||||
const T *old_next = next;
|
||||
next = hb_utf_next (next, end, &u);
|
||||
next = utf_t::next (next, end, &u, replacement);
|
||||
buffer->add (u, old_next - (const T *) text);
|
||||
}
|
||||
|
||||
@ -1341,7 +1390,7 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
|
||||
while (next < end && buffer->context_len[1] < buffer->CONTEXT_LENGTH)
|
||||
{
|
||||
hb_codepoint_t u;
|
||||
next = hb_utf_next (next, end, &u);
|
||||
next = utf_t::next (next, end, &u, replacement);
|
||||
buffer->context[1][buffer->context_len[1]++] = u;
|
||||
}
|
||||
|
||||
@ -1367,7 +1416,7 @@ hb_buffer_add_utf8 (hb_buffer_t *buffer,
|
||||
unsigned int item_offset,
|
||||
int item_length)
|
||||
{
|
||||
hb_buffer_add_utf (buffer, (const uint8_t *) text, text_length, item_offset, item_length);
|
||||
hb_buffer_add_utf<true> (buffer, (const uint8_t *) text, text_length, item_offset, item_length);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1389,7 +1438,7 @@ hb_buffer_add_utf16 (hb_buffer_t *buffer,
|
||||
unsigned int item_offset,
|
||||
int item_length)
|
||||
{
|
||||
hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length);
|
||||
hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1411,7 +1460,29 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
|
||||
unsigned int item_offset,
|
||||
int item_length)
|
||||
{
|
||||
hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length);
|
||||
hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_buffer_add_codepoints:
|
||||
* @buffer: a buffer.
|
||||
* @text: (array length=text_length):
|
||||
* @text_length:
|
||||
* @item_offset:
|
||||
* @item_length:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: 1.0
|
||||
**/
|
||||
void
|
||||
hb_buffer_add_codepoints (hb_buffer_t *buffer,
|
||||
const hb_codepoint_t *text,
|
||||
int text_length,
|
||||
unsigned int item_offset,
|
||||
int item_length)
|
||||
{
|
||||
hb_buffer_add_utf<false> (buffer, text, text_length, item_offset, item_length);
|
||||
}
|
||||
|
||||
|
||||
|
23
src/3rdparty/harfbuzz-ng/src/hb-buffer.h
vendored
23
src/3rdparty/harfbuzz-ng/src/hb-buffer.h
vendored
@ -186,12 +186,25 @@ hb_buffer_flags_t
|
||||
hb_buffer_get_flags (hb_buffer_t *buffer);
|
||||
|
||||
|
||||
|
||||
#define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu
|
||||
|
||||
/* Sets codepoint used to replace invalid UTF-8/16/32 entries.
|
||||
* Default is 0xFFFDu. */
|
||||
void
|
||||
hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
|
||||
hb_codepoint_t replacement);
|
||||
|
||||
hb_codepoint_t
|
||||
hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer);
|
||||
|
||||
|
||||
/* Resets the buffer. Afterwards it's as if it was just created,
|
||||
* except that it has a larger buffer allocated perhaps... */
|
||||
void
|
||||
hb_buffer_reset (hb_buffer_t *buffer);
|
||||
|
||||
/* Like reset, but does NOT clear unicode_funcs. */
|
||||
/* Like reset, but does NOT clear unicode_funcs and replacement_codepoint. */
|
||||
void
|
||||
hb_buffer_clear_contents (hb_buffer_t *buffer);
|
||||
|
||||
@ -240,6 +253,14 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
|
||||
unsigned int item_offset,
|
||||
int item_length);
|
||||
|
||||
/* Like add_utf32 but does NOT check for invalid Unicode codepoints. */
|
||||
void
|
||||
hb_buffer_add_codepoints (hb_buffer_t *buffer,
|
||||
const hb_codepoint_t *text,
|
||||
int text_length,
|
||||
unsigned int item_offset,
|
||||
int item_length);
|
||||
|
||||
|
||||
/* Clears any new items added at the end */
|
||||
hb_bool_t
|
||||
|
24
src/3rdparty/harfbuzz-ng/src/hb-common.cc
vendored
24
src/3rdparty/harfbuzz-ng/src/hb-common.cc
vendored
@ -234,6 +234,7 @@ struct hb_language_item_t {
|
||||
|
||||
static hb_language_item_t *langs;
|
||||
|
||||
#ifdef HAVE_ATEXIT
|
||||
static inline
|
||||
void free_langs (void)
|
||||
{
|
||||
@ -244,6 +245,7 @@ void free_langs (void)
|
||||
langs = next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static hb_language_item_t *
|
||||
lang_find_or_insert (const char *key)
|
||||
@ -297,9 +299,11 @@ hb_language_from_string (const char *str, int len)
|
||||
|
||||
if (len >= 0)
|
||||
{
|
||||
/* NUL-terminate it. */
|
||||
len = MIN (len, (int) sizeof (strbuf) - 1);
|
||||
str = (char *) memcpy (strbuf, str, len);
|
||||
memcpy (strbuf, str, len);
|
||||
strbuf[len] = '\0';
|
||||
str = strbuf;
|
||||
}
|
||||
|
||||
hb_language_item_t *item = lang_find_or_insert (str);
|
||||
@ -367,7 +371,7 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
|
||||
return HB_SCRIPT_INVALID;
|
||||
|
||||
/* Be lenient, adjust case (one capital letter followed by three small letters) */
|
||||
tag = (tag & 0xDFDFDFDF) | 0x00202020;
|
||||
tag = (tag & 0xDFDFDFDFu) | 0x00202020u;
|
||||
|
||||
switch (tag) {
|
||||
|
||||
@ -387,7 +391,7 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
|
||||
}
|
||||
|
||||
/* If it looks right, just use the tag as a script */
|
||||
if (((uint32_t) tag & 0xE0E0E0E0) == 0x40606060)
|
||||
if (((uint32_t) tag & 0xE0E0E0E0u) == 0x40606060u)
|
||||
return (hb_script_t) tag;
|
||||
|
||||
/* Otherwise, return unknown */
|
||||
@ -480,6 +484,14 @@ hb_script_get_horizontal_direction (hb_script_t script)
|
||||
case HB_SCRIPT_MEROITIC_CURSIVE:
|
||||
case HB_SCRIPT_MEROITIC_HIEROGLYPHS:
|
||||
|
||||
/* Unicode-7.0 additions */
|
||||
case HB_SCRIPT_MANICHAEAN:
|
||||
case HB_SCRIPT_MENDE_KIKAKUI:
|
||||
case HB_SCRIPT_NABATAEAN:
|
||||
case HB_SCRIPT_OLD_NORTH_ARABIAN:
|
||||
case HB_SCRIPT_PALMYRENE:
|
||||
case HB_SCRIPT_PSALTER_PAHLAVI:
|
||||
|
||||
return HB_DIRECTION_RTL;
|
||||
}
|
||||
|
||||
@ -557,7 +569,7 @@ hb_version_string (void)
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_version_check:
|
||||
* hb_version_atleast:
|
||||
* @major:
|
||||
* @minor:
|
||||
* @micro:
|
||||
@ -569,9 +581,9 @@ hb_version_string (void)
|
||||
* Since: 1.0
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_version_check (unsigned int major,
|
||||
hb_version_atleast (unsigned int major,
|
||||
unsigned int minor,
|
||||
unsigned int micro)
|
||||
{
|
||||
return HB_VERSION_CHECK (major, minor, micro);
|
||||
return HB_VERSION_ATLEAST (major, minor, micro);
|
||||
}
|
||||
|
27
src/3rdparty/harfbuzz-ng/src/hb-common.h
vendored
27
src/3rdparty/harfbuzz-ng/src/hb-common.h
vendored
@ -270,17 +270,6 @@ typedef enum
|
||||
/*6.1*/ HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'),
|
||||
/*6.1*/ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'),
|
||||
|
||||
/* No script set. */
|
||||
/*---*/ HB_SCRIPT_INVALID = HB_TAG_NONE,
|
||||
|
||||
/* Dummy value to ensure any hb_tag_t value can be passed/stored as hb_script_t
|
||||
* without risking undefined behavior. */
|
||||
/*---*/ _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX
|
||||
|
||||
} hb_script_t;
|
||||
|
||||
/* These are moved out of hb_script_t because glib-mkenums chokes otherwise. */
|
||||
#if 0
|
||||
/*7.0*/ HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'),
|
||||
/*7.0*/ HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'),
|
||||
/*7.0*/ HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'),
|
||||
@ -292,19 +281,27 @@ typedef enum
|
||||
/*7.0*/ HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'),
|
||||
/*7.0*/ HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'),
|
||||
/*7.0*/ HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'),
|
||||
/*7.0*/ HB_SCRIPT_MODI = ???
|
||||
/*7.0*/ HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'),
|
||||
/*7.0*/ HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'),
|
||||
/*7.0*/ HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'),
|
||||
/*7.0*/ HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'),
|
||||
/*7.0*/ HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'),
|
||||
/*7.0*/ HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'),
|
||||
/*7.0*/ HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'),
|
||||
/*7.0*/ HB_SCRIPT_PAU_CIN_HAU = ???
|
||||
/*7.0*/ HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'),
|
||||
/*7.0*/ HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'),
|
||||
/*7.0*/ HB_SCRIPT_SIDDHAM = ???
|
||||
/*7.0*/ HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'),
|
||||
/*7.0*/ HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'),
|
||||
/*7.0*/ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'),
|
||||
#endif
|
||||
|
||||
/* No script set. */
|
||||
/*---*/ HB_SCRIPT_INVALID = HB_TAG_NONE,
|
||||
|
||||
/* Dummy value to ensure any hb_tag_t value can be passed/stored as hb_script_t
|
||||
* without risking undefined behavior. */
|
||||
/*---*/ _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX
|
||||
|
||||
} hb_script_t;
|
||||
|
||||
|
||||
/* Script functions */
|
||||
|
198
src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
vendored
198
src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
vendored
@ -31,18 +31,12 @@
|
||||
|
||||
#include "hb-coretext.h"
|
||||
|
||||
#include "hb-face-private.hh"
|
||||
|
||||
|
||||
#ifndef HB_DEBUG_CORETEXT
|
||||
#define HB_DEBUG_CORETEXT (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face)
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font)
|
||||
|
||||
|
||||
typedef bool (*qt_get_font_table_func_t) (void *user_data, unsigned int tag, unsigned char *buffer, unsigned int *length);
|
||||
|
||||
struct FontEngineFaceData {
|
||||
@ -56,6 +50,42 @@ struct CoreTextFontEngineData {
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
release_table_data (void *user_data)
|
||||
{
|
||||
CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data);
|
||||
CFRelease(cf_data);
|
||||
}
|
||||
|
||||
static hb_blob_t *
|
||||
reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
{
|
||||
CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
|
||||
CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag);
|
||||
if (unlikely (!cf_data))
|
||||
return NULL;
|
||||
|
||||
const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data));
|
||||
const size_t length = CFDataGetLength (cf_data);
|
||||
if (!data || !length)
|
||||
return NULL;
|
||||
|
||||
return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
|
||||
reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
|
||||
release_table_data);
|
||||
}
|
||||
|
||||
hb_face_t *
|
||||
hb_coretext_face_create (CGFontRef cg_font)
|
||||
{
|
||||
return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), (hb_destroy_func_t) CGFontRelease);
|
||||
}
|
||||
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face)
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font)
|
||||
|
||||
|
||||
/*
|
||||
* shaper face data
|
||||
*/
|
||||
@ -76,31 +106,33 @@ release_data (void *info, const void *data, size_t size)
|
||||
hb_coretext_shaper_face_data_t *
|
||||
_hb_coretext_shaper_face_data_create (hb_face_t *face)
|
||||
{
|
||||
hb_blob_t *mort_blob = face->reference_table (HB_CORETEXT_TAG_MORT);
|
||||
/* Umm, we just reference the table to check whether it exists.
|
||||
* Maybe add better API for this? */
|
||||
if (!hb_blob_get_length (mort_blob))
|
||||
{
|
||||
hb_blob_destroy (mort_blob);
|
||||
mort_blob = face->reference_table (HB_CORETEXT_TAG_MORX);
|
||||
if (!hb_blob_get_length (mort_blob))
|
||||
{
|
||||
hb_blob_destroy (mort_blob);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
hb_blob_destroy (mort_blob);
|
||||
|
||||
hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) calloc (1, sizeof (hb_coretext_shaper_face_data_t));
|
||||
if (unlikely (!data))
|
||||
return NULL;
|
||||
#if 0
|
||||
if (face->destroy == (hb_destroy_func_t) CGFontRelease)
|
||||
{
|
||||
data->cg_font = CGFontRetain ((CGFontRef) face->user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
hb_blob_t *blob = hb_face_reference_blob (face);
|
||||
unsigned int blob_length;
|
||||
const char *blob_data = hb_blob_get_data (blob, &blob_length);
|
||||
if (unlikely (!blob_length))
|
||||
DEBUG_MSG (CORETEXT, face, "Face has empty blob");
|
||||
|
||||
CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data);
|
||||
data->cg_font = CGFontCreateWithDataProvider (provider);
|
||||
CGDataProviderRelease (provider);
|
||||
}
|
||||
#else
|
||||
FontEngineFaceData *fontEngineFaceData = (FontEngineFaceData *) face->user_data;
|
||||
CoreTextFontEngineData *coreTextFontEngineData = (CoreTextFontEngineData *) fontEngineFaceData->user_data;
|
||||
data->cg_font = coreTextFontEngineData->cgFont;
|
||||
if (likely (data->cg_font))
|
||||
CFRetain (data->cg_font);
|
||||
|
||||
#endif
|
||||
if (unlikely (!data->cg_font)) {
|
||||
DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed");
|
||||
free (data);
|
||||
@ -144,13 +176,17 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
|
||||
return NULL;
|
||||
|
||||
hb_face_t *face = font->face;
|
||||
#if 0
|
||||
hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
|
||||
|
||||
data->ct_font = CTFontCreateWithGraphicsFont (face_data->cg_font, font->y_scale, NULL, NULL);
|
||||
#else
|
||||
FontEngineFaceData *fontEngineFaceData = (FontEngineFaceData *) face->user_data;
|
||||
CoreTextFontEngineData *coreTextFontEngineData = (CoreTextFontEngineData *) fontEngineFaceData->user_data;
|
||||
data->ct_font = coreTextFontEngineData->ctFont;
|
||||
if (likely (data->ct_font))
|
||||
CFRetain (data->ct_font);
|
||||
|
||||
#endif
|
||||
if (unlikely (!data->ct_font)) {
|
||||
DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed");
|
||||
free (data);
|
||||
@ -468,7 +504,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
||||
event->start = false;
|
||||
event->feature = feature;
|
||||
}
|
||||
feature_events.sort ();
|
||||
feature_events.qsort ();
|
||||
/* Add a strategic final event. */
|
||||
{
|
||||
active_feature_t feature;
|
||||
@ -498,14 +534,12 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
||||
if (unlikely (!range))
|
||||
goto fail_features;
|
||||
|
||||
unsigned int offset = feature_records.len;
|
||||
|
||||
if (active_features.len)
|
||||
{
|
||||
CFMutableArrayRef features_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
|
||||
|
||||
/* TODO sort and resolve conflicting features? */
|
||||
/* active_features.sort (); */
|
||||
/* active_features.qsort (); */
|
||||
for (unsigned int j = 0; j < active_features.len; j++)
|
||||
{
|
||||
CFStringRef keys[2] = {
|
||||
@ -603,13 +637,13 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
||||
for (unsigned int i = 0; i < buffer->len; i++) {
|
||||
hb_codepoint_t c = buffer->info[i].codepoint;
|
||||
buffer->info[i].utf16_index() = chars_len;
|
||||
if (likely (c < 0x10000))
|
||||
if (likely (c <= 0xFFFFu))
|
||||
pchars[chars_len++] = c;
|
||||
else if (unlikely (c >= 0x110000))
|
||||
pchars[chars_len++] = 0xFFFD;
|
||||
else if (unlikely (c > 0x10FFFFu))
|
||||
pchars[chars_len++] = 0xFFFDu;
|
||||
else {
|
||||
pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10);
|
||||
pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1));
|
||||
pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
|
||||
pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -635,7 +669,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
||||
hb_codepoint_t c = buffer->info[i].codepoint;
|
||||
unsigned int cluster = buffer->info[i].cluster;
|
||||
log_clusters[chars_len++] = cluster;
|
||||
if (c >= 0x10000 && c < 0x110000)
|
||||
if (hb_in_range (c, 0x10000u, 0x10FFFFu))
|
||||
log_clusters[chars_len++] = cluster; /* Surrogates. */
|
||||
}
|
||||
|
||||
@ -705,10 +739,10 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
||||
for (CFIndex j = range.location; j < range.location + range.length; j++)
|
||||
{
|
||||
UniChar ch = CFStringGetCharacterAtIndex (string_ref, j);
|
||||
if (hb_in_range<UniChar> (ch, 0xDC00, 0xDFFF) && range.location < j)
|
||||
if (hb_in_range<UniChar> (ch, 0xDC00u, 0xDFFFu) && range.location < j)
|
||||
{
|
||||
ch = CFStringGetCharacterAtIndex (string_ref, j - 1);
|
||||
if (hb_in_range<UniChar> (ch, 0xD800, 0xDBFF))
|
||||
if (hb_in_range<UniChar> (ch, 0xD800u, 0xDBFFu))
|
||||
/* This is the second of a surrogate pair. Don't need .notdef
|
||||
* for this one. */
|
||||
continue;
|
||||
@ -866,3 +900,97 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AAT shaper
|
||||
*/
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, face)
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, font)
|
||||
|
||||
|
||||
/*
|
||||
* shaper face data
|
||||
*/
|
||||
|
||||
struct hb_coretext_aat_shaper_face_data_t {};
|
||||
|
||||
hb_coretext_aat_shaper_face_data_t *
|
||||
_hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
|
||||
{
|
||||
hb_blob_t *mort_blob = face->reference_table (HB_CORETEXT_TAG_MORT);
|
||||
/* Umm, we just reference the table to check whether it exists.
|
||||
* Maybe add better API for this? */
|
||||
if (!hb_blob_get_length (mort_blob))
|
||||
{
|
||||
hb_blob_destroy (mort_blob);
|
||||
mort_blob = face->reference_table (HB_CORETEXT_TAG_MORX);
|
||||
if (!hb_blob_get_length (mort_blob))
|
||||
{
|
||||
hb_blob_destroy (mort_blob);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
hb_blob_destroy (mort_blob);
|
||||
|
||||
return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* shaper font data
|
||||
*/
|
||||
|
||||
struct hb_coretext_aat_shaper_font_data_t {};
|
||||
|
||||
hb_coretext_aat_shaper_font_data_t *
|
||||
_hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
|
||||
{
|
||||
return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *data HB_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* shaper shape_plan data
|
||||
*/
|
||||
|
||||
struct hb_coretext_aat_shaper_shape_plan_data_t {};
|
||||
|
||||
hb_coretext_aat_shaper_shape_plan_data_t *
|
||||
_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
||||
const hb_feature_t *user_features HB_UNUSED,
|
||||
unsigned int num_user_features HB_UNUSED)
|
||||
{
|
||||
return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shaper_shape_plan_data_t *data HB_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* shaper
|
||||
*/
|
||||
|
||||
hb_bool_t
|
||||
_hb_coretext_aat_shape (hb_shape_plan_t *shape_plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features)
|
||||
{
|
||||
return _hb_coretext_shape (shape_plan, font, buffer, features, num_features);
|
||||
}
|
||||
|
6
src/3rdparty/harfbuzz-ng/src/hb-coretext.h
vendored
6
src/3rdparty/harfbuzz-ng/src/hb-coretext.h
vendored
@ -30,7 +30,7 @@
|
||||
#include "hb.h"
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
|
||||
#if TARGET_OS_IPHONE
|
||||
# include <CoreText/CoreText.h>
|
||||
# include <CoreGraphics/CoreGraphics.h>
|
||||
#else
|
||||
@ -44,6 +44,10 @@ HB_BEGIN_DECLS
|
||||
#define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x')
|
||||
|
||||
|
||||
hb_face_t *
|
||||
hb_coretext_face_create (CGFontRef cg_font);
|
||||
|
||||
|
||||
CGFontRef
|
||||
hb_coretext_face_get_cg_font (hb_face_t *face);
|
||||
|
||||
|
@ -110,9 +110,9 @@ typedef struct OffsetTable
|
||||
protected:
|
||||
Tag sfnt_version; /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
|
||||
USHORT numTables; /* Number of tables. */
|
||||
USHORT searchRange; /* (Maximum power of 2 <= numTables) x 16 */
|
||||
USHORT entrySelector; /* Log2(maximum power of 2 <= numTables). */
|
||||
USHORT rangeShift; /* NumTables x 16-searchRange. */
|
||||
USHORT searchRangeZ; /* (Maximum power of 2 <= numTables) x 16 */
|
||||
USHORT entrySelectorZ; /* Log2(maximum power of 2 <= numTables). */
|
||||
USHORT rangeShiftZ; /* NumTables x 16-searchRange. */
|
||||
TableRecord tables[VAR]; /* TableRecord entries. numTables items */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (12, tables);
|
||||
@ -138,8 +138,8 @@ struct TTCHeaderVersion1
|
||||
protected:
|
||||
Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
|
||||
FixedVersion version; /* Version of the TTC Header (1.0),
|
||||
* 0x00010000 */
|
||||
LongOffsetLongArrayOf<OffsetTable>
|
||||
* 0x00010000u */
|
||||
ArrayOf<OffsetTo<OffsetTable, ULONG>, ULONG>
|
||||
table; /* Array of offsets to the OffsetTable for each font
|
||||
* from the beginning of the file */
|
||||
public:
|
||||
@ -184,7 +184,7 @@ struct TTCHeader
|
||||
struct {
|
||||
Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
|
||||
FixedVersion version; /* Version of the TTC Header (1.0 or 2.0),
|
||||
* 0x00010000 or 0x00020000 */
|
||||
* 0x00010000u or 0x00020000u */
|
||||
} header;
|
||||
TTCHeaderVersion1 version1;
|
||||
} u;
|
||||
|
125
src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh
vendored
125
src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh
vendored
@ -42,36 +42,36 @@ namespace OT {
|
||||
|
||||
/* Cast to struct T, reference to reference */
|
||||
template<typename Type, typename TObject>
|
||||
inline const Type& CastR(const TObject &X)
|
||||
static inline const Type& CastR(const TObject &X)
|
||||
{ return reinterpret_cast<const Type&> (X); }
|
||||
template<typename Type, typename TObject>
|
||||
inline Type& CastR(TObject &X)
|
||||
static inline Type& CastR(TObject &X)
|
||||
{ return reinterpret_cast<Type&> (X); }
|
||||
|
||||
/* Cast to struct T, pointer to pointer */
|
||||
template<typename Type, typename TObject>
|
||||
inline const Type* CastP(const TObject *X)
|
||||
static inline const Type* CastP(const TObject *X)
|
||||
{ return reinterpret_cast<const Type*> (X); }
|
||||
template<typename Type, typename TObject>
|
||||
inline Type* CastP(TObject *X)
|
||||
static inline Type* CastP(TObject *X)
|
||||
{ return reinterpret_cast<Type*> (X); }
|
||||
|
||||
/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
|
||||
* location pointed to by P plus Ofs bytes. */
|
||||
template<typename Type>
|
||||
inline const Type& StructAtOffset(const void *P, unsigned int offset)
|
||||
static inline const Type& StructAtOffset(const void *P, unsigned int offset)
|
||||
{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
|
||||
template<typename Type>
|
||||
inline Type& StructAtOffset(void *P, unsigned int offset)
|
||||
static inline Type& StructAtOffset(void *P, unsigned int offset)
|
||||
{ return * reinterpret_cast<Type*> ((char *) P + offset); }
|
||||
|
||||
/* StructAfter<T>(X) returns the struct T& that is placed after X.
|
||||
* Works with X of variable size also. X must implement get_size() */
|
||||
template<typename Type, typename TObject>
|
||||
inline const Type& StructAfter(const TObject &X)
|
||||
static inline const Type& StructAfter(const TObject &X)
|
||||
{ return StructAtOffset<Type>(&X, X.get_size()); }
|
||||
template<typename Type, typename TObject>
|
||||
inline Type& StructAfter(TObject &X)
|
||||
static inline Type& StructAfter(TObject &X)
|
||||
{ return StructAtOffset<Type>(&X, X.get_size()); }
|
||||
|
||||
|
||||
@ -132,7 +132,7 @@ inline Type& StructAfter(TObject &X)
|
||||
|
||||
/* Global nul-content Null pool. Enlarge as necessary. */
|
||||
/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */
|
||||
static const void *_NullPool[64 / sizeof (void *)];
|
||||
static const void *_NullPool[(256+8) / sizeof (void *)];
|
||||
|
||||
/* Generic nul-content Null objects. */
|
||||
template <typename Type>
|
||||
@ -145,7 +145,7 @@ static inline const Type& Null (void) {
|
||||
#define DEFINE_NULL_DATA(Type, data) \
|
||||
static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \
|
||||
template <> \
|
||||
inline const Type& Null<Type> (void) { \
|
||||
/*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 */ \
|
||||
ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
|
||||
@ -266,6 +266,15 @@ struct hb_sanitize_context_t
|
||||
return TRACE_RETURN (this->writable);
|
||||
}
|
||||
|
||||
template <typename Type, typename ValueType>
|
||||
inline bool try_set (Type *obj, const ValueType &v) {
|
||||
if (this->may_edit (obj, obj->static_size)) {
|
||||
obj->set (v);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
mutable unsigned int debug_depth;
|
||||
const char *start, *end;
|
||||
bool writable;
|
||||
@ -572,6 +581,7 @@ struct IntType
|
||||
DEFINE_SIZE_STATIC (Size);
|
||||
};
|
||||
|
||||
typedef uint8_t BYTE; /* 8-bit unsigned integer. */
|
||||
typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */
|
||||
typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */
|
||||
typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */
|
||||
@ -616,24 +626,17 @@ typedef USHORT GlyphID;
|
||||
|
||||
/* Script/language-system/feature index */
|
||||
struct Index : USHORT {
|
||||
static const unsigned int NOT_FOUND_INDEX = 0xFFFF;
|
||||
static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
|
||||
};
|
||||
DEFINE_NULL_DATA (Index, "\xff\xff");
|
||||
|
||||
/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
|
||||
struct Offset : USHORT
|
||||
/* Offset, Null offset = 0 */
|
||||
template <typename Type=USHORT>
|
||||
struct Offset : Type
|
||||
{
|
||||
inline bool is_null (void) const { return 0 == *this; }
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */
|
||||
struct LongOffset : ULONG
|
||||
{
|
||||
inline bool is_null (void) const { return 0 == *this; }
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
DEFINE_SIZE_STATIC (sizeof(Type));
|
||||
};
|
||||
|
||||
|
||||
@ -682,12 +685,12 @@ struct FixedVersion
|
||||
|
||||
|
||||
/*
|
||||
* Template subclasses of Offset and LongOffset that do the dereferencing.
|
||||
* Template subclasses of Offset that do the dereferencing.
|
||||
* Use: (base+offset)
|
||||
*/
|
||||
|
||||
template <typename OffsetType, typename Type>
|
||||
struct GenericOffsetTo : OffsetType
|
||||
template <typename Type, typename OffsetType=USHORT>
|
||||
struct OffsetTo : Offset<OffsetType>
|
||||
{
|
||||
inline const Type& operator () (const void *base) const
|
||||
{
|
||||
@ -721,40 +724,25 @@ struct GenericOffsetTo : OffsetType
|
||||
return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c));
|
||||
}
|
||||
|
||||
inline bool try_set (hb_sanitize_context_t *c, const OffsetType &v) {
|
||||
if (c->may_edit (this, this->static_size)) {
|
||||
this->set (v);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/* Set the offset to Null */
|
||||
inline bool neuter (hb_sanitize_context_t *c) {
|
||||
if (c->may_edit (this, this->static_size)) {
|
||||
this->set (0); /* 0 is Null offset */
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return c->try_set (this, 0);
|
||||
}
|
||||
DEFINE_SIZE_STATIC (sizeof(OffsetType));
|
||||
};
|
||||
template <typename Base, typename OffsetType, typename Type>
|
||||
inline const Type& operator + (const Base &base, const GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); }
|
||||
static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
|
||||
template <typename Base, typename OffsetType, typename Type>
|
||||
inline Type& operator + (Base &base, GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); }
|
||||
|
||||
template <typename Type>
|
||||
struct OffsetTo : GenericOffsetTo<Offset, Type> {};
|
||||
|
||||
template <typename Type>
|
||||
struct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {};
|
||||
static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
|
||||
|
||||
|
||||
/*
|
||||
* Array Types
|
||||
*/
|
||||
|
||||
template <typename LenType, typename Type>
|
||||
struct GenericArrayOf
|
||||
/* An array with a number of elements. */
|
||||
template <typename Type, typename LenType=USHORT>
|
||||
struct ArrayOf
|
||||
{
|
||||
const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
|
||||
{
|
||||
@ -837,6 +825,16 @@ struct GenericArrayOf
|
||||
return TRACE_RETURN (true);
|
||||
}
|
||||
|
||||
template <typename SearchType>
|
||||
inline int lsearch (const SearchType &x) const
|
||||
{
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!this->array[i].cmp (x))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
private:
|
||||
inline bool sanitize_shallow (hb_sanitize_context_t *c) {
|
||||
TRACE_SANITIZE (this);
|
||||
@ -850,26 +848,10 @@ struct GenericArrayOf
|
||||
DEFINE_SIZE_ARRAY (sizeof (LenType), array);
|
||||
};
|
||||
|
||||
/* An array with a USHORT number of elements. */
|
||||
template <typename Type>
|
||||
struct ArrayOf : GenericArrayOf<USHORT, Type> {};
|
||||
|
||||
/* An array with a ULONG number of elements. */
|
||||
template <typename Type>
|
||||
struct LongArrayOf : GenericArrayOf<ULONG, Type> {};
|
||||
|
||||
/* Array of Offset's */
|
||||
template <typename Type>
|
||||
struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
|
||||
|
||||
/* Array of LongOffset's */
|
||||
template <typename Type>
|
||||
struct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {};
|
||||
|
||||
/* LongArray of LongOffset's */
|
||||
template <typename Type>
|
||||
struct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {};
|
||||
|
||||
/* Array of offsets relative to the beginning of the array itself. */
|
||||
template <typename Type>
|
||||
struct OffsetListOf : OffsetArrayOf<Type>
|
||||
@ -892,9 +874,8 @@ struct OffsetListOf : OffsetArrayOf<Type>
|
||||
};
|
||||
|
||||
|
||||
/* An array with a USHORT number of elements,
|
||||
* starting at second element. */
|
||||
template <typename Type>
|
||||
/* An array starting at second element. */
|
||||
template <typename Type, typename LenType=USHORT>
|
||||
struct HeadlessArrayOf
|
||||
{
|
||||
inline const Type& operator [] (unsigned int i) const
|
||||
@ -941,19 +922,19 @@ struct HeadlessArrayOf
|
||||
return TRACE_RETURN (true);
|
||||
}
|
||||
|
||||
USHORT len;
|
||||
LenType len;
|
||||
Type array[VAR];
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (sizeof (USHORT), array);
|
||||
DEFINE_SIZE_ARRAY (sizeof (LenType), array);
|
||||
};
|
||||
|
||||
|
||||
/* An array with sorted elements. Supports binary searching. */
|
||||
template <typename Type>
|
||||
struct SortedArrayOf : ArrayOf<Type> {
|
||||
|
||||
template <typename Type, typename LenType=USHORT>
|
||||
struct SortedArrayOf : ArrayOf<Type, LenType>
|
||||
{
|
||||
template <typename SearchType>
|
||||
inline int search (const SearchType &x) const
|
||||
inline int bsearch (const SearchType &x) const
|
||||
{
|
||||
/* Hand-coded bsearch here since this is in the hot inner loop. */
|
||||
int min = 0, max = (int) this->len - 1;
|
||||
|
517
src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh
vendored
Normal file
517
src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh
vendored
Normal file
@ -0,0 +1,517 @@
|
||||
/*
|
||||
* Copyright © 2014 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_CMAP_TABLE_HH
|
||||
#define HB_OT_CMAP_TABLE_HH
|
||||
|
||||
#include "hb-open-type-private.hh"
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
/*
|
||||
* cmap -- Character To Glyph Index Mapping Table
|
||||
*/
|
||||
|
||||
#define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
|
||||
|
||||
|
||||
struct CmapSubtableFormat0
|
||||
{
|
||||
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
|
||||
{
|
||||
hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0;
|
||||
if (!gid)
|
||||
return false;
|
||||
*glyph = gid;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||
TRACE_SANITIZE (this);
|
||||
return TRACE_RETURN (c->check_struct (this));
|
||||
}
|
||||
|
||||
protected:
|
||||
USHORT format; /* Format number is set to 0. */
|
||||
USHORT lengthZ; /* Byte length of this subtable. */
|
||||
USHORT languageZ; /* Ignore. */
|
||||
BYTE glyphIdArray[256];/* An array that maps character
|
||||
* code to glyph index values. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6 + 256);
|
||||
};
|
||||
|
||||
struct CmapSubtableFormat4
|
||||
{
|
||||
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
|
||||
{
|
||||
unsigned int segCount;
|
||||
const USHORT *endCount;
|
||||
const USHORT *startCount;
|
||||
const USHORT *idDelta;
|
||||
const USHORT *idRangeOffset;
|
||||
const USHORT *glyphIdArray;
|
||||
unsigned int glyphIdArrayLength;
|
||||
|
||||
segCount = this->segCountX2 / 2;
|
||||
endCount = this->values;
|
||||
startCount = endCount + segCount + 1;
|
||||
idDelta = startCount + segCount;
|
||||
idRangeOffset = idDelta + segCount;
|
||||
glyphIdArray = idRangeOffset + segCount;
|
||||
glyphIdArrayLength = (this->length - 16 - 8 * segCount) / 2;
|
||||
|
||||
/* Custom two-array bsearch. */
|
||||
int min = 0, max = (int) segCount - 1;
|
||||
unsigned int i;
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
if (codepoint < startCount[mid])
|
||||
max = mid - 1;
|
||||
else if (codepoint > endCount[mid])
|
||||
min = mid + 1;
|
||||
else
|
||||
{
|
||||
i = mid;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
found:
|
||||
hb_codepoint_t gid;
|
||||
unsigned int rangeOffset = idRangeOffset[i];
|
||||
if (rangeOffset == 0)
|
||||
gid = codepoint + idDelta[i];
|
||||
else
|
||||
{
|
||||
/* Somebody has been smoking... */
|
||||
unsigned int index = rangeOffset / 2 + (codepoint - startCount[i]) + i - segCount;
|
||||
if (unlikely (index >= glyphIdArrayLength))
|
||||
return false;
|
||||
gid = glyphIdArray[index];
|
||||
if (unlikely (!gid))
|
||||
return false;
|
||||
gid += idDelta[i];
|
||||
}
|
||||
|
||||
*glyph = gid & 0xFFFFu;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c)
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!c->check_struct (this)))
|
||||
return TRACE_RETURN (false);
|
||||
|
||||
if (unlikely (!c->check_range (this, length)))
|
||||
{
|
||||
/* Some broken fonts have too long of a "length" value.
|
||||
* If that is the case, just change the value to truncate
|
||||
* the subtable at the end of the blob. */
|
||||
uint16_t new_length = (uint16_t) MIN ((uintptr_t) 65535,
|
||||
(uintptr_t) (c->end -
|
||||
(char *) this));
|
||||
if (!c->try_set (&length, new_length))
|
||||
return TRACE_RETURN (false);
|
||||
}
|
||||
|
||||
return TRACE_RETURN (16 + 4 * (unsigned int) segCountX2 <= length);
|
||||
}
|
||||
|
||||
protected:
|
||||
USHORT format; /* Format number is set to 4. */
|
||||
USHORT length; /* This is the length in bytes of the
|
||||
* subtable. */
|
||||
USHORT languageZ; /* Ignore. */
|
||||
USHORT segCountX2; /* 2 x segCount. */
|
||||
USHORT searchRangeZ; /* 2 * (2**floor(log2(segCount))) */
|
||||
USHORT entrySelectorZ; /* log2(searchRange/2) */
|
||||
USHORT rangeShiftZ; /* 2 x segCount - searchRange */
|
||||
|
||||
USHORT values[VAR];
|
||||
#if 0
|
||||
USHORT endCount[segCount]; /* End characterCode for each segment,
|
||||
* last=0xFFFFu. */
|
||||
USHORT reservedPad; /* Set to 0. */
|
||||
USHORT startCount[segCount]; /* Start character code for each segment. */
|
||||
SHORT idDelta[segCount]; /* Delta for all character codes in segment. */
|
||||
USHORT idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
|
||||
USHORT glyphIdArray[VAR]; /* Glyph index array (arbitrary length) */
|
||||
#endif
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (14, values);
|
||||
};
|
||||
|
||||
struct CmapSubtableLongGroup
|
||||
{
|
||||
friend struct CmapSubtableFormat12;
|
||||
friend struct CmapSubtableFormat13;
|
||||
|
||||
int cmp (hb_codepoint_t codepoint) const
|
||||
{
|
||||
if (codepoint < startCharCode) return -1;
|
||||
if (codepoint > endCharCode) return +1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||
TRACE_SANITIZE (this);
|
||||
return TRACE_RETURN (c->check_struct (this));
|
||||
}
|
||||
|
||||
private:
|
||||
ULONG startCharCode; /* First character code in this group. */
|
||||
ULONG endCharCode; /* Last character code in this group. */
|
||||
ULONG glyphID; /* Glyph index; interpretation depends on
|
||||
* subtable format. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
};
|
||||
|
||||
template <typename UINT>
|
||||
struct CmapSubtableTrimmed
|
||||
{
|
||||
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
|
||||
{
|
||||
/* Rely on our implicit array bound-checking. */
|
||||
hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
|
||||
if (!gid)
|
||||
return false;
|
||||
*glyph = gid;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||
TRACE_SANITIZE (this);
|
||||
return TRACE_RETURN (c->check_struct (this) && glyphIdArray.sanitize (c));
|
||||
}
|
||||
|
||||
protected:
|
||||
UINT formatReserved; /* Subtable format and (maybe) padding. */
|
||||
UINT lengthZ; /* Byte length of this subtable. */
|
||||
UINT languageZ; /* Ignore. */
|
||||
UINT startCharCode; /* First character code covered. */
|
||||
ArrayOf<GlyphID, UINT>
|
||||
glyphIdArray; /* Array of glyph index values for character
|
||||
* codes in the range. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (5 * sizeof (UINT), glyphIdArray);
|
||||
};
|
||||
|
||||
struct CmapSubtableFormat6 : CmapSubtableTrimmed<USHORT> {};
|
||||
struct CmapSubtableFormat10 : CmapSubtableTrimmed<ULONG > {};
|
||||
|
||||
template <typename T>
|
||||
struct CmapSubtableLongSegmented
|
||||
{
|
||||
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
|
||||
{
|
||||
int i = groups.bsearch (codepoint);
|
||||
if (i == -1)
|
||||
return false;
|
||||
*glyph = T::group_get_glyph (groups[i], codepoint);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||
TRACE_SANITIZE (this);
|
||||
return TRACE_RETURN (c->check_struct (this) && groups.sanitize (c));
|
||||
}
|
||||
|
||||
protected:
|
||||
USHORT format; /* Subtable format; set to 12. */
|
||||
USHORT reservedZ; /* Reserved; set to 0. */
|
||||
ULONG lengthZ; /* Byte length of this subtable. */
|
||||
ULONG languageZ; /* Ignore. */
|
||||
SortedArrayOf<CmapSubtableLongGroup, ULONG>
|
||||
groups; /* Groupings. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (16, groups);
|
||||
};
|
||||
|
||||
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); }
|
||||
};
|
||||
|
||||
struct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
|
||||
{
|
||||
static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
|
||||
hb_codepoint_t u HB_UNUSED)
|
||||
{ return group.glyphID; }
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GLYPH_VARIANT_NOT_FOUND = 0,
|
||||
GLYPH_VARIANT_FOUND = 1,
|
||||
GLYPH_VARIANT_USE_DEFAULT = 2
|
||||
} glyph_variant_t;
|
||||
|
||||
struct UnicodeValueRange
|
||||
{
|
||||
inline int cmp (const hb_codepoint_t &codepoint) const
|
||||
{
|
||||
if (codepoint < startUnicodeValue) return -1;
|
||||
if (codepoint > startUnicodeValue + additionalCount) return +1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||
TRACE_SANITIZE (this);
|
||||
return TRACE_RETURN (c->check_struct (this));
|
||||
}
|
||||
|
||||
UINT24 startUnicodeValue; /* First value in this range. */
|
||||
BYTE additionalCount; /* Number of additional values in this
|
||||
* range. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
typedef SortedArrayOf<UnicodeValueRange, ULONG> DefaultUVS;
|
||||
|
||||
struct UVSMapping
|
||||
{
|
||||
inline int cmp (const hb_codepoint_t &codepoint) const
|
||||
{
|
||||
return unicodeValue.cmp (codepoint);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||
TRACE_SANITIZE (this);
|
||||
return TRACE_RETURN (c->check_struct (this));
|
||||
}
|
||||
|
||||
UINT24 unicodeValue; /* Base Unicode value of the UVS */
|
||||
GlyphID glyphID; /* Glyph ID of the UVS */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (5);
|
||||
};
|
||||
|
||||
typedef SortedArrayOf<UVSMapping, ULONG> NonDefaultUVS;
|
||||
|
||||
struct VariationSelectorRecord
|
||||
{
|
||||
inline glyph_variant_t get_glyph (hb_codepoint_t codepoint,
|
||||
hb_codepoint_t *glyph,
|
||||
const void *base) const
|
||||
{
|
||||
int i;
|
||||
const DefaultUVS &defaults = base+defaultUVS;
|
||||
i = defaults.bsearch (codepoint);
|
||||
if (i != -1)
|
||||
return GLYPH_VARIANT_USE_DEFAULT;
|
||||
const NonDefaultUVS &nonDefaults = base+nonDefaultUVS;
|
||||
i = nonDefaults.bsearch (codepoint);
|
||||
if (i != -1)
|
||||
{
|
||||
*glyph = nonDefaults[i].glyphID;
|
||||
return GLYPH_VARIANT_FOUND;
|
||||
}
|
||||
return GLYPH_VARIANT_NOT_FOUND;
|
||||
}
|
||||
|
||||
inline int cmp (const hb_codepoint_t &variation_selector) const
|
||||
{
|
||||
return varSelector.cmp (variation_selector);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c, void *base) {
|
||||
TRACE_SANITIZE (this);
|
||||
return TRACE_RETURN (c->check_struct (this) &&
|
||||
defaultUVS.sanitize (c, base) &&
|
||||
nonDefaultUVS.sanitize (c, base));
|
||||
}
|
||||
|
||||
UINT24 varSelector; /* Variation selector. */
|
||||
OffsetTo<DefaultUVS, ULONG>
|
||||
defaultUVS; /* Offset to Default UVS Table. May be 0. */
|
||||
OffsetTo<NonDefaultUVS, ULONG>
|
||||
nonDefaultUVS; /* Offset to Non-Default UVS Table. May be 0. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (11);
|
||||
};
|
||||
|
||||
struct CmapSubtableFormat14
|
||||
{
|
||||
inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
|
||||
hb_codepoint_t variation_selector,
|
||||
hb_codepoint_t *glyph) const
|
||||
{
|
||||
return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||
TRACE_SANITIZE (this);
|
||||
return TRACE_RETURN (c->check_struct (this) &&
|
||||
record.sanitize (c, this));
|
||||
}
|
||||
|
||||
protected:
|
||||
USHORT format; /* Format number is set to 0. */
|
||||
ULONG lengthZ; /* Byte length of this subtable. */
|
||||
SortedArrayOf<VariationSelectorRecord, ULONG>
|
||||
record; /* Variation selector records; sorted
|
||||
* in increasing order of `varSelector'. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (10, record);
|
||||
};
|
||||
|
||||
struct CmapSubtable
|
||||
{
|
||||
/* Note: We intentionally do NOT implement subtable formats 2 and 8. */
|
||||
|
||||
inline bool get_glyph (hb_codepoint_t codepoint,
|
||||
hb_codepoint_t *glyph) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 0: return u.format0 .get_glyph(codepoint, glyph);
|
||||
case 4: return u.format4 .get_glyph(codepoint, glyph);
|
||||
case 6: return u.format6 .get_glyph(codepoint, glyph);
|
||||
case 10: return u.format10.get_glyph(codepoint, glyph);
|
||||
case 12: return u.format12.get_glyph(codepoint, glyph);
|
||||
case 13: return u.format13.get_glyph(codepoint, glyph);
|
||||
case 14:
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
|
||||
hb_codepoint_t variation_selector,
|
||||
hb_codepoint_t *glyph) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 14: return u.format14.get_glyph_variant(codepoint, variation_selector, glyph);
|
||||
default: return GLYPH_VARIANT_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return TRACE_RETURN (false);
|
||||
switch (u.format) {
|
||||
case 0: return TRACE_RETURN (u.format0 .sanitize (c));
|
||||
case 4: return TRACE_RETURN (u.format4 .sanitize (c));
|
||||
case 6: return TRACE_RETURN (u.format6 .sanitize (c));
|
||||
case 10: return TRACE_RETURN (u.format10.sanitize (c));
|
||||
case 12: return TRACE_RETURN (u.format12.sanitize (c));
|
||||
case 13: return TRACE_RETURN (u.format13.sanitize (c));
|
||||
case 14: return TRACE_RETURN (u.format14.sanitize (c));
|
||||
default:return TRACE_RETURN (true);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
union {
|
||||
USHORT format; /* Format identifier */
|
||||
CmapSubtableFormat0 format0;
|
||||
CmapSubtableFormat4 format4;
|
||||
CmapSubtableFormat6 format6;
|
||||
CmapSubtableFormat10 format10;
|
||||
CmapSubtableFormat12 format12;
|
||||
CmapSubtableFormat13 format13;
|
||||
CmapSubtableFormat14 format14;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
};
|
||||
|
||||
|
||||
struct EncodingRecord
|
||||
{
|
||||
inline int cmp (const EncodingRecord &other) const
|
||||
{
|
||||
int ret;
|
||||
ret = platformID.cmp (other.platformID);
|
||||
if (ret) return ret;
|
||||
ret = encodingID.cmp (other.encodingID);
|
||||
if (ret) return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c, void *base) {
|
||||
TRACE_SANITIZE (this);
|
||||
return TRACE_RETURN (c->check_struct (this) &&
|
||||
subtable.sanitize (c, base));
|
||||
}
|
||||
|
||||
USHORT platformID; /* Platform ID. */
|
||||
USHORT encodingID; /* Platform-specific encoding ID. */
|
||||
OffsetTo<CmapSubtable, ULONG>
|
||||
subtable; /* Byte offset from beginning of table to the subtable for this encoding. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
};
|
||||
|
||||
struct cmap
|
||||
{
|
||||
static const hb_tag_t tableTag = HB_OT_TAG_cmap;
|
||||
|
||||
inline const CmapSubtable *find_subtable (unsigned int platform_id,
|
||||
unsigned int encoding_id) const
|
||||
{
|
||||
EncodingRecord key;
|
||||
key.platformID.set (platform_id);
|
||||
key.encodingID.set (encoding_id);
|
||||
|
||||
/* Note: We can use bsearch, but since it has no performance
|
||||
* implications, we use lsearch and as such accept fonts with
|
||||
* unsorted subtable list. */
|
||||
int result = encodingRecord./*bsearch*/lsearch (key);
|
||||
if (result == -1 || !encodingRecord[result].subtable)
|
||||
return NULL;
|
||||
|
||||
return &(this+encodingRecord[result].subtable);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||
TRACE_SANITIZE (this);
|
||||
return TRACE_RETURN (c->check_struct (this) &&
|
||||
likely (version == 0) &&
|
||||
encodingRecord.sanitize (c, this));
|
||||
}
|
||||
|
||||
USHORT version; /* Table version number (0). */
|
||||
SortedArrayOf<EncodingRecord>
|
||||
encodingRecord; /* Encoding tables. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, encodingRecord);
|
||||
};
|
||||
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* HB_OT_CMAP_TABLE_HH */
|
289
src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
vendored
Normal file
289
src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
vendored
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright © 2011,2014 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, Roozbeh Pournader
|
||||
*/
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-ot.h"
|
||||
|
||||
#include "hb-font-private.hh"
|
||||
|
||||
#include "hb-ot-cmap-table.hh"
|
||||
#include "hb-ot-hhea-table.hh"
|
||||
#include "hb-ot-hmtx-table.hh"
|
||||
|
||||
|
||||
|
||||
struct hb_ot_font_t
|
||||
{
|
||||
unsigned int num_glyphs;
|
||||
unsigned int num_hmetrics;
|
||||
const OT::hmtx *hmtx;
|
||||
hb_blob_t *hmtx_blob;
|
||||
|
||||
const OT::CmapSubtable *cmap;
|
||||
const OT::CmapSubtable *cmap_uvs;
|
||||
hb_blob_t *cmap_blob;
|
||||
};
|
||||
|
||||
|
||||
static hb_ot_font_t *
|
||||
_hb_ot_font_create (hb_font_t *font)
|
||||
{
|
||||
hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
|
||||
|
||||
if (unlikely (!ot_font))
|
||||
return NULL;
|
||||
|
||||
ot_font->num_glyphs = font->face->get_num_glyphs ();
|
||||
|
||||
{
|
||||
hb_blob_t *hhea_blob = OT::Sanitizer<OT::hhea>::sanitize (font->face->reference_table (HB_OT_TAG_hhea));
|
||||
const OT::hhea *hhea = OT::Sanitizer<OT::hhea>::lock_instance (hhea_blob);
|
||||
ot_font->num_hmetrics = hhea->numberOfHMetrics;
|
||||
hb_blob_destroy (hhea_blob);
|
||||
}
|
||||
ot_font->hmtx_blob = OT::Sanitizer<OT::hmtx>::sanitize (font->face->reference_table (HB_OT_TAG_hmtx));
|
||||
if (unlikely (!ot_font->num_hmetrics ||
|
||||
2 * (ot_font->num_hmetrics + ot_font->num_glyphs) < hb_blob_get_length (ot_font->hmtx_blob)))
|
||||
{
|
||||
hb_blob_destroy (ot_font->hmtx_blob);
|
||||
free (ot_font);
|
||||
return NULL;
|
||||
}
|
||||
ot_font->hmtx = OT::Sanitizer<OT::hmtx>::lock_instance (ot_font->hmtx_blob);
|
||||
|
||||
ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize (font->face->reference_table (HB_OT_TAG_cmap));
|
||||
const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (ot_font->cmap_blob);
|
||||
const OT::CmapSubtable *subtable = NULL;
|
||||
const OT::CmapSubtable *subtable_uvs = NULL;
|
||||
|
||||
/* 32-bit subtables. */
|
||||
if (!subtable) subtable = cmap->find_subtable (0, 6);
|
||||
if (!subtable) subtable = cmap->find_subtable (0, 4);
|
||||
if (!subtable) subtable = cmap->find_subtable (3, 10);
|
||||
/* 16-bit subtables. */
|
||||
if (!subtable) subtable = cmap->find_subtable (0, 3);
|
||||
if (!subtable) subtable = cmap->find_subtable (3, 1);
|
||||
/* Meh. */
|
||||
if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
|
||||
|
||||
/* UVS subtable. */
|
||||
if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
|
||||
/* Meh. */
|
||||
if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
|
||||
|
||||
ot_font->cmap = subtable;
|
||||
ot_font->cmap_uvs = subtable_uvs;
|
||||
|
||||
return ot_font;
|
||||
}
|
||||
|
||||
static void
|
||||
_hb_ot_font_destroy (hb_ot_font_t *ot_font)
|
||||
{
|
||||
hb_blob_destroy (ot_font->cmap_blob);
|
||||
hb_blob_destroy (ot_font->hmtx_blob);
|
||||
|
||||
free (ot_font);
|
||||
}
|
||||
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_codepoint_t unicode,
|
||||
hb_codepoint_t variation_selector,
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
|
||||
{
|
||||
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||
|
||||
if (unlikely (variation_selector))
|
||||
{
|
||||
switch (ot_font->cmap_uvs->get_glyph_variant (unicode,
|
||||
variation_selector,
|
||||
glyph))
|
||||
{
|
||||
case OT::GLYPH_VARIANT_NOT_FOUND: return false;
|
||||
case OT::GLYPH_VARIANT_FOUND: return true;
|
||||
case OT::GLYPH_VARIANT_USE_DEFAULT: break;
|
||||
}
|
||||
}
|
||||
|
||||
return ot_font->cmap->get_glyph (unicode, glyph);
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||
|
||||
if (unlikely (glyph >= ot_font->num_glyphs))
|
||||
return 0; /* Maybe better to return notdef's advance instead? */
|
||||
|
||||
if (glyph >= ot_font->num_hmetrics)
|
||||
glyph = ot_font->num_hmetrics - 1;
|
||||
|
||||
return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advanceWidth);
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph HB_UNUSED,
|
||||
hb_position_t *x HB_UNUSED,
|
||||
hb_position_t *y HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* We always work in the horizontal coordinates. */
|
||||
return true;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* TODO */
|
||||
return false;
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_ot_get_glyph_h_kerning (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t left_glyph,
|
||||
hb_codepoint_t right_glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t top_glyph HB_UNUSED,
|
||||
hb_codepoint_t bottom_glyph HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* TODO */
|
||||
return false;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
unsigned int point_index,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* TODO */
|
||||
return false;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
char *name, unsigned int size,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* TODO */
|
||||
return false;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
const char *name, int len, /* -1 means nul-terminated */
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* TODO */
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static hb_font_funcs_t *
|
||||
_hb_ot_get_font_funcs (void)
|
||||
{
|
||||
static const hb_font_funcs_t ot_ffuncs = {
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
true, /* immutable */
|
||||
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
}
|
||||
};
|
||||
|
||||
return const_cast<hb_font_funcs_t *> (&ot_ffuncs);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hb_ot_font_set_funcs (hb_font_t *font)
|
||||
{
|
||||
hb_ot_font_t *ot_font = _hb_ot_font_create (font);
|
||||
if (unlikely (!ot_font))
|
||||
return;
|
||||
|
||||
hb_font_set_funcs (font,
|
||||
_hb_ot_get_font_funcs (),
|
||||
ot_font,
|
||||
(hb_destroy_func_t) _hb_ot_font_destroy);
|
||||
}
|
41
src/3rdparty/harfbuzz-ng/src/hb-ot-font.h
vendored
Normal file
41
src/3rdparty/harfbuzz-ng/src/hb-ot-font.h
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright © 2014 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, Roozbeh Pournader
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_FONT_H
|
||||
#define HB_OT_FONT_H
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
|
||||
void
|
||||
hb_ot_font_set_funcs (hb_font_t *font);
|
||||
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_OT_FONT_H */
|
@ -58,12 +58,12 @@ struct head
|
||||
|
||||
protected:
|
||||
FixedVersion version; /* Version of the head table--currently
|
||||
* 0x00010000 for version 1.0. */
|
||||
* 0x00010000u for version 1.0. */
|
||||
FixedVersion fontRevision; /* Set by font manufacturer. */
|
||||
ULONG checkSumAdjustment; /* To compute: set it to 0, sum the
|
||||
* entire font as ULONG, then store
|
||||
* 0xB1B0AFBA - sum. */
|
||||
ULONG magicNumber; /* Set to 0x5F0F3CF5. */
|
||||
* 0xB1B0AFBAu - sum. */
|
||||
ULONG magicNumber; /* Set to 0x5F0F3CF5u. */
|
||||
USHORT flags; /* Bit 0: Baseline for font at y=0;
|
||||
* Bit 1: Left sidebearing point at x=0;
|
||||
* Bit 2: Instructions may depend on point size;
|
||||
|
@ -49,8 +49,8 @@ struct hhea
|
||||
return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
|
||||
}
|
||||
|
||||
protected:
|
||||
FixedVersion version; /* 0x00010000 for version 1.0. */
|
||||
public:
|
||||
FixedVersion version; /* 0x00010000u for version 1.0. */
|
||||
FWORD ascender; /* Typographic ascent. <a
|
||||
* href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html">
|
||||
* (Distance from baseline of highest
|
||||
|
@ -59,7 +59,7 @@ struct hmtx
|
||||
return TRACE_RETURN (true);
|
||||
}
|
||||
|
||||
protected:
|
||||
public:
|
||||
LongHorMetric longHorMetric[VAR]; /* Paired advance width and left side
|
||||
* bearing values for each glyph. The
|
||||
* value numOfHMetrics comes from
|
||||
|
@ -103,7 +103,8 @@ struct RecordArrayOf : SortedArrayOf<Record<Type> > {
|
||||
}
|
||||
inline bool find_index (hb_tag_t tag, unsigned int *index) const
|
||||
{
|
||||
int i = this->search (tag);
|
||||
/* If we want to allow non-sorted data, we can lsearch(). */
|
||||
int i = this->/*lsearch*/bsearch (tag);
|
||||
if (i != -1) {
|
||||
if (index) *index = i;
|
||||
return true;
|
||||
@ -189,10 +190,10 @@ struct LangSys
|
||||
unsigned int *feature_indexes /* OUT */) const
|
||||
{ return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
|
||||
|
||||
inline bool has_required_feature (void) const { return reqFeatureIndex != 0xffff; }
|
||||
inline bool has_required_feature (void) const { return reqFeatureIndex != 0xFFFFu; }
|
||||
inline unsigned int get_required_feature_index (void) const
|
||||
{
|
||||
if (reqFeatureIndex == 0xffff)
|
||||
if (reqFeatureIndex == 0xFFFFu)
|
||||
return Index::NOT_FOUND_INDEX;
|
||||
return reqFeatureIndex;;
|
||||
}
|
||||
@ -203,11 +204,11 @@ struct LangSys
|
||||
return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c));
|
||||
}
|
||||
|
||||
Offset lookupOrder; /* = Null (reserved for an offset to a
|
||||
Offset<> lookupOrderZ; /* = Null (reserved for an offset to a
|
||||
* reordering table) */
|
||||
USHORT reqFeatureIndex;/* Index of a feature required for this
|
||||
* language system--if no required features
|
||||
* = 0xFFFF */
|
||||
* = 0xFFFFu */
|
||||
IndexArray featureIndex; /* Array of indices into the FeatureList */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (6, featureIndex);
|
||||
@ -447,9 +448,9 @@ struct FeatureParams
|
||||
TRACE_SANITIZE (this);
|
||||
if (tag == HB_TAG ('s','i','z','e'))
|
||||
return TRACE_RETURN (u.size.sanitize (c));
|
||||
if ((tag & 0xFFFF0000) == HB_TAG ('s','s','\0','\0')) /* ssXX */
|
||||
if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
|
||||
return TRACE_RETURN (u.stylisticSet.sanitize (c));
|
||||
if ((tag & 0xFFFF0000) == HB_TAG ('c','v','\0','\0')) /* cvXX */
|
||||
if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
|
||||
return TRACE_RETURN (u.characterVariants.sanitize (c));
|
||||
return TRACE_RETURN (true);
|
||||
}
|
||||
@ -501,11 +502,11 @@ struct Feature
|
||||
* Adobe tools, only the 'size' feature had FeatureParams defined.
|
||||
*/
|
||||
|
||||
Offset orig_offset = featureParams;
|
||||
OffsetTo<FeatureParams> orig_offset = featureParams;
|
||||
if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
|
||||
return TRACE_RETURN (false);
|
||||
|
||||
if (likely (!orig_offset))
|
||||
if (likely (orig_offset.is_null ()))
|
||||
return TRACE_RETURN (true);
|
||||
|
||||
if (featureParams == 0 && closure &&
|
||||
@ -513,13 +514,13 @@ struct Feature
|
||||
closure->list_base && closure->list_base < this)
|
||||
{
|
||||
unsigned int new_offset_int = (unsigned int) orig_offset -
|
||||
((char *) this - (char *) closure->list_base);
|
||||
(((char *) this) - ((char *) closure->list_base));
|
||||
|
||||
Offset new_offset;
|
||||
OffsetTo<FeatureParams> new_offset;
|
||||
/* Check that it did not overflow. */
|
||||
new_offset.set (new_offset_int);
|
||||
if (new_offset == new_offset_int &&
|
||||
featureParams.try_set (c, new_offset) &&
|
||||
c->try_set (&featureParams, new_offset) &&
|
||||
!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
|
||||
return TRACE_RETURN (false);
|
||||
}
|
||||
@ -584,7 +585,7 @@ struct Lookup
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
|
||||
lookupType.set (lookup_type);
|
||||
lookupFlag.set (lookup_props & 0xFFFF);
|
||||
lookupFlag.set (lookup_props & 0xFFFFu);
|
||||
if (unlikely (!subTable.serialize (c, num_subtables))) return TRACE_RETURN (false);
|
||||
if (lookupFlag & LookupFlag::UseMarkFilteringSet)
|
||||
{
|
||||
@ -608,7 +609,7 @@ struct Lookup
|
||||
|
||||
USHORT lookupType; /* Different enumerations for GSUB and GPOS */
|
||||
USHORT lookupFlag; /* Lookup qualifiers */
|
||||
ArrayOf<Offset>
|
||||
ArrayOf<Offset<> >
|
||||
subTable; /* Array of SubTables */
|
||||
USHORT markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets
|
||||
* structure. This field is only present if bit
|
||||
@ -631,7 +632,7 @@ struct CoverageFormat1
|
||||
private:
|
||||
inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
int i = glyphArray.search (glyph_id);
|
||||
int i = glyphArray.bsearch (glyph_id);
|
||||
ASSERT_STATIC (((unsigned int) -1) == NOT_COVERED);
|
||||
return i;
|
||||
}
|
||||
@ -696,7 +697,7 @@ struct CoverageFormat2
|
||||
private:
|
||||
inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
int i = rangeRecord.search (glyph_id);
|
||||
int i = rangeRecord.bsearch (glyph_id);
|
||||
if (i != -1) {
|
||||
const RangeRecord &range = rangeRecord[i];
|
||||
return (unsigned int) range.value + (glyph_id - range.start);
|
||||
@ -992,7 +993,7 @@ struct ClassDefFormat2
|
||||
private:
|
||||
inline unsigned int get_class (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
int i = rangeRecord.search (glyph_id);
|
||||
int i = rangeRecord.bsearch (glyph_id);
|
||||
if (i != -1)
|
||||
return rangeRecord[i].value;
|
||||
return 0;
|
||||
@ -1130,7 +1131,7 @@ struct Device
|
||||
|
||||
unsigned int byte = deltaValue[s >> (4 - f)];
|
||||
unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
|
||||
unsigned int mask = (0xFFFF >> (16 - (1 << f)));
|
||||
unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
|
||||
|
||||
int delta = bits & mask;
|
||||
|
||||
|
@ -282,7 +282,7 @@ struct MarkGlyphSetsFormat1
|
||||
|
||||
protected:
|
||||
USHORT format; /* Format identifier--format = 1 */
|
||||
LongOffsetArrayOf<Coverage>
|
||||
ArrayOf<OffsetTo<Coverage, ULONG> >
|
||||
coverage; /* Array of long offsets to mark set
|
||||
* coverage tables */
|
||||
public:
|
||||
@ -360,9 +360,9 @@ struct GDEF
|
||||
hb_position_t *caret_array /* OUT */) const
|
||||
{ return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); }
|
||||
|
||||
inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002 && markGlyphSetsDef[0] != 0; }
|
||||
inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef[0] != 0; }
|
||||
inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
|
||||
{ return version.to_int () >= 0x00010002 && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
|
||||
{ return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||
TRACE_SANITIZE (this);
|
||||
@ -372,7 +372,7 @@ struct GDEF
|
||||
attachList.sanitize (c, this) &&
|
||||
ligCaretList.sanitize (c, this) &&
|
||||
markAttachClassDef.sanitize (c, this) &&
|
||||
(version.to_int () < 0x00010002 || markGlyphSetsDef[0].sanitize (c, this)));
|
||||
(version.to_int () < 0x00010002u || markGlyphSetsDef[0].sanitize (c, this)));
|
||||
}
|
||||
|
||||
|
||||
@ -400,7 +400,7 @@ struct GDEF
|
||||
|
||||
protected:
|
||||
FixedVersion version; /* Version of the GDEF table--currently
|
||||
* 0x00010002 */
|
||||
* 0x00010002u */
|
||||
OffsetTo<ClassDef>
|
||||
glyphClassDef; /* Offset to class definition table
|
||||
* for glyph type--from beginning of
|
||||
|
@ -49,18 +49,18 @@ typedef Value ValueRecord[VAR];
|
||||
struct ValueFormat : USHORT
|
||||
{
|
||||
enum Flags {
|
||||
xPlacement = 0x0001, /* Includes horizontal adjustment for placement */
|
||||
yPlacement = 0x0002, /* Includes vertical adjustment for placement */
|
||||
xAdvance = 0x0004, /* Includes horizontal adjustment for advance */
|
||||
yAdvance = 0x0008, /* Includes vertical adjustment for advance */
|
||||
xPlaDevice = 0x0010, /* Includes horizontal Device table for placement */
|
||||
yPlaDevice = 0x0020, /* Includes vertical Device table for placement */
|
||||
xAdvDevice = 0x0040, /* Includes horizontal Device table for advance */
|
||||
yAdvDevice = 0x0080, /* Includes vertical Device table for advance */
|
||||
ignored = 0x0F00, /* Was used in TrueType Open for MM fonts */
|
||||
reserved = 0xF000, /* For future use */
|
||||
xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */
|
||||
yPlacement = 0x0002u, /* Includes vertical adjustment for placement */
|
||||
xAdvance = 0x0004u, /* Includes horizontal adjustment for advance */
|
||||
yAdvance = 0x0008u, /* Includes vertical adjustment for advance */
|
||||
xPlaDevice = 0x0010u, /* Includes horizontal Device table for placement */
|
||||
yPlaDevice = 0x0020u, /* Includes vertical Device table for placement */
|
||||
xAdvDevice = 0x0040u, /* Includes horizontal Device table for advance */
|
||||
yAdvDevice = 0x0080u, /* Includes vertical Device table for advance */
|
||||
ignored = 0x0F00u, /* Was used in TrueType Open for MM fonts */
|
||||
reserved = 0xF000u, /* For future use */
|
||||
|
||||
devices = 0x00F0 /* Mask for having any Device table */
|
||||
devices = 0x00F0u /* Mask for having any Device table */
|
||||
};
|
||||
|
||||
/* All fields are options. Only those available advance the value pointer. */
|
||||
@ -1608,14 +1608,14 @@ GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
|
||||
/* Out-of-class implementation for methods recursing */
|
||||
|
||||
template <typename context_t>
|
||||
inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
|
||||
/*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
|
||||
const PosLookup &l = gpos.get_lookup (lookup_index);
|
||||
return l.dispatch (c);
|
||||
}
|
||||
|
||||
inline bool PosLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
|
||||
/*static*/ inline bool PosLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
|
||||
const PosLookup &l = gpos.get_lookup (lookup_index);
|
||||
|
@ -44,7 +44,7 @@ struct SingleSubstFormat1
|
||||
for (iter.init (this+coverage); iter.more (); iter.next ()) {
|
||||
hb_codepoint_t glyph_id = iter.get_glyph ();
|
||||
if (c->glyphs->has (glyph_id))
|
||||
c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFF);
|
||||
c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ struct SingleSubstFormat1
|
||||
for (iter.init (this+coverage); iter.more (); iter.next ()) {
|
||||
hb_codepoint_t glyph_id = iter.get_glyph ();
|
||||
c->input->add (glyph_id);
|
||||
c->output->add ((glyph_id + deltaGlyphID) & 0xFFFF);
|
||||
c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ struct SingleSubstFormat1
|
||||
|
||||
/* According to the Adobe Annotated OpenType Suite, result is always
|
||||
* limited to 16bit. */
|
||||
glyph_id = (glyph_id + deltaGlyphID) & 0xFFFF;
|
||||
glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu;
|
||||
c->replace_glyph (glyph_id);
|
||||
|
||||
return TRACE_RETURN (true);
|
||||
@ -270,23 +270,34 @@ struct Sequence
|
||||
inline bool apply (hb_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
if (unlikely (!substitute.len)) return TRACE_RETURN (false);
|
||||
unsigned int count = substitute.len;
|
||||
|
||||
/* TODO:
|
||||
* Testing shows that Uniscribe actually allows zero-len susbstitute,
|
||||
* which essentially deletes a glyph. We don't allow for now. It
|
||||
* can be confusing to the client since the cluster from the deleted
|
||||
* glyph won't be merged with any output cluster... Also, currently
|
||||
* buffer->move_to() makes assumptions about this too. Perhaps fix
|
||||
* in the future after figuring out what to do with the clusters.
|
||||
*/
|
||||
if (unlikely (!count)) return TRACE_RETURN (false);
|
||||
|
||||
/* Special-case to make it in-place and not consider this
|
||||
* as a "multiplied" substitution. */
|
||||
if (unlikely (count == 1))
|
||||
{
|
||||
c->replace_glyph (substitute.array[0]);
|
||||
return TRACE_RETURN (true);
|
||||
}
|
||||
|
||||
unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
|
||||
unsigned int count = substitute.len;
|
||||
if (count == 1) /* Special-case to make it in-place. */
|
||||
{
|
||||
c->replace_glyph (substitute.array[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
_hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
|
||||
c->output_glyph (substitute.array[i], klass);
|
||||
c->output_glyph_for_component (substitute.array[i], klass);
|
||||
}
|
||||
c->buffer->skip_glyph ();
|
||||
}
|
||||
|
||||
return TRACE_RETURN (true);
|
||||
}
|
||||
@ -624,7 +635,16 @@ struct Ligature
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
unsigned int count = component.len;
|
||||
if (unlikely (count < 1)) return TRACE_RETURN (false);
|
||||
|
||||
if (unlikely (!count)) return TRACE_RETURN (false);
|
||||
|
||||
/* Special-case to make it in-place and not consider this
|
||||
* as a "ligated" substitution. */
|
||||
if (unlikely (count == 1))
|
||||
{
|
||||
c->replace_glyph (ligGlyph);
|
||||
return TRACE_RETURN (true);
|
||||
}
|
||||
|
||||
bool is_mark_ligature = false;
|
||||
unsigned int total_component_count = 0;
|
||||
@ -1338,7 +1358,7 @@ GSUB::substitute_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSE
|
||||
|
||||
/* Out-of-class implementation for methods recursing */
|
||||
|
||||
inline bool ExtensionSubst::is_reverse (void) const
|
||||
/*static*/ inline bool ExtensionSubst::is_reverse (void) const
|
||||
{
|
||||
unsigned int type = get_type ();
|
||||
if (unlikely (type == SubstLookupSubTable::Extension))
|
||||
@ -1347,14 +1367,14 @@ inline bool ExtensionSubst::is_reverse (void) const
|
||||
}
|
||||
|
||||
template <typename context_t>
|
||||
inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
|
||||
/*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
|
||||
const SubstLookup &l = gsub.get_lookup (lookup_index);
|
||||
return l.dispatch (c);
|
||||
}
|
||||
|
||||
inline bool SubstLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
|
||||
/*static*/ inline bool SubstLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
|
||||
const SubstLookup &l = gsub.get_lookup (lookup_index);
|
||||
|
@ -349,11 +349,7 @@ struct hb_apply_context_t
|
||||
may_skip (const hb_apply_context_t *c,
|
||||
const hb_glyph_info_t &info) const
|
||||
{
|
||||
unsigned int property;
|
||||
|
||||
property = _hb_glyph_info_get_glyph_props (&info);
|
||||
|
||||
if (!c->match_properties (info.codepoint, property, lookup_props))
|
||||
if (!c->check_glyph_property (&info, lookup_props))
|
||||
return SKIP_YES;
|
||||
|
||||
if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
|
||||
@ -487,7 +483,6 @@ struct hb_apply_context_t
|
||||
const hb_glyph_info_t &info = c->buffer->out_info[idx];
|
||||
|
||||
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
|
||||
|
||||
if (unlikely (skip == matcher_t::SKIP_YES))
|
||||
continue;
|
||||
|
||||
@ -538,10 +533,12 @@ struct hb_apply_context_t
|
||||
}
|
||||
|
||||
inline bool
|
||||
match_properties (hb_codepoint_t glyph,
|
||||
unsigned int glyph_props,
|
||||
check_glyph_property (const hb_glyph_info_t *info,
|
||||
unsigned int lookup_props) const
|
||||
{
|
||||
hb_codepoint_t glyph = info->codepoint;
|
||||
unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
|
||||
|
||||
/* Not covered, if, for example, glyph class is ligature and
|
||||
* lookup_props includes LookupFlags::IgnoreLigatures
|
||||
*/
|
||||
@ -554,26 +551,27 @@ struct hb_apply_context_t
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
check_glyph_property (hb_glyph_info_t *info,
|
||||
unsigned int lookup_props) const
|
||||
{
|
||||
unsigned int property;
|
||||
|
||||
property = _hb_glyph_info_get_glyph_props (info);
|
||||
|
||||
return match_properties (info->codepoint, property, lookup_props);
|
||||
}
|
||||
|
||||
inline void _set_glyph_props (hb_codepoint_t glyph_index,
|
||||
unsigned int class_guess = 0,
|
||||
bool ligature = false) const
|
||||
bool ligature = false,
|
||||
bool component = false) const
|
||||
{
|
||||
unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
|
||||
add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
|
||||
if (ligature)
|
||||
{
|
||||
add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
|
||||
/* In the only place that the MULTIPLIED bit is used, Uniscribe
|
||||
* seems to only care about the "last" transformation between
|
||||
* Ligature and Multiple substitions. Ie. if you ligate, expand,
|
||||
* and ligate again, it forgives the multiplication and acts as
|
||||
* if only ligation happened. As such, clear MULTIPLIED bit.
|
||||
*/
|
||||
add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
|
||||
}
|
||||
if (component)
|
||||
add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
|
||||
if (likely (has_glyph_classes))
|
||||
_hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
|
||||
else if (class_guess)
|
||||
@ -596,10 +594,10 @@ struct hb_apply_context_t
|
||||
_set_glyph_props (glyph_index, class_guess, true);
|
||||
buffer->replace_glyph (glyph_index);
|
||||
}
|
||||
inline void output_glyph (hb_codepoint_t glyph_index,
|
||||
inline void output_glyph_for_component (hb_codepoint_t glyph_index,
|
||||
unsigned int class_guess) const
|
||||
{
|
||||
_set_glyph_props (glyph_index, class_guess);
|
||||
_set_glyph_props (glyph_index, class_guess, false, true);
|
||||
buffer->output_glyph (glyph_index);
|
||||
}
|
||||
};
|
||||
@ -882,6 +880,7 @@ static inline void ligate_input (hb_apply_context_t *c,
|
||||
break;
|
||||
}
|
||||
}
|
||||
TRACE_RETURN (true);
|
||||
}
|
||||
|
||||
static inline bool match_backtrack (hb_apply_context_t *c,
|
||||
@ -994,7 +993,9 @@ static inline bool apply_lookup (hb_apply_context_t *c,
|
||||
|
||||
/* Recursed lookup changed buffer len. Adjust. */
|
||||
|
||||
/* end can't go back past the current match position. */
|
||||
/* end can't go back past the current match position.
|
||||
* Note: this is only true because we do NOT allow MultipleSubst
|
||||
* with zero sequence len. */
|
||||
end = MAX ((int) match_positions[idx] + 1, int (end) + delta);
|
||||
|
||||
unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
|
||||
@ -2253,8 +2254,8 @@ struct GSUBGPOS
|
||||
|
||||
inline unsigned int get_feature_count (void) const
|
||||
{ return (this+featureList).len; }
|
||||
inline const Tag& get_feature_tag (unsigned int i) const
|
||||
{ return (this+featureList).get_tag (i); }
|
||||
inline hb_tag_t get_feature_tag (unsigned int i) const
|
||||
{ return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
|
||||
inline unsigned int get_feature_tags (unsigned int start_offset,
|
||||
unsigned int *feature_count /* IN/OUT */,
|
||||
hb_tag_t *feature_tags /* OUT */) const
|
||||
@ -2279,7 +2280,7 @@ struct GSUBGPOS
|
||||
|
||||
protected:
|
||||
FixedVersion version; /* Version of the GSUB/GPOS table--initially set
|
||||
* to 0x00010000 */
|
||||
* to 0x00010000u */
|
||||
OffsetTo<ScriptList>
|
||||
scriptList; /* ScriptList table */
|
||||
OffsetTo<FeatureList>
|
||||
|
@ -214,7 +214,7 @@ struct JSTF
|
||||
|
||||
protected:
|
||||
FixedVersion version; /* Version of the JSTF table--initially set
|
||||
* to 0x00010000 */
|
||||
* to 0x00010000u */
|
||||
RecordArrayOf<JstfScript>
|
||||
scriptList; /* Array of JstfScripts--listed
|
||||
* alphabetically by ScriptTag */
|
||||
|
@ -50,9 +50,11 @@ typedef enum
|
||||
/* The following are used internally; not derived from GDEF. */
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED = 0x10u,
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_LIGATED = 0x20u,
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED = 0x40u,
|
||||
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_LIGATED
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
|
||||
} hb_ot_layout_glyph_class_mask_t;
|
||||
|
||||
|
||||
@ -182,62 +184,62 @@ enum {
|
||||
MASK0_GEN_CAT = 0x1Fu
|
||||
};
|
||||
|
||||
inline void
|
||||
static inline void
|
||||
_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode)
|
||||
{
|
||||
/* XXX This shouldn't be inlined, or at least not while is_default_ignorable() is inline. */
|
||||
info->unicode_props0() = ((unsigned int) unicode->general_category (info->codepoint)) |
|
||||
(unicode->is_default_ignorable (info->codepoint) ? MASK0_IGNORABLE : 0) |
|
||||
(info->codepoint == 0x200C ? MASK0_ZWNJ : 0) |
|
||||
(info->codepoint == 0x200D ? MASK0_ZWJ : 0);
|
||||
(info->codepoint == 0x200Cu ? MASK0_ZWNJ : 0) |
|
||||
(info->codepoint == 0x200Du ? MASK0_ZWJ : 0);
|
||||
info->unicode_props1() = unicode->modified_combining_class (info->codepoint);
|
||||
}
|
||||
|
||||
inline void
|
||||
static inline void
|
||||
_hb_glyph_info_set_general_category (hb_glyph_info_t *info,
|
||||
hb_unicode_general_category_t gen_cat)
|
||||
{
|
||||
info->unicode_props0() = (unsigned int) gen_cat | ((info->unicode_props0()) & ~MASK0_GEN_CAT);
|
||||
}
|
||||
|
||||
inline hb_unicode_general_category_t
|
||||
static inline hb_unicode_general_category_t
|
||||
_hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
|
||||
{
|
||||
return (hb_unicode_general_category_t) (info->unicode_props0() & MASK0_GEN_CAT);
|
||||
}
|
||||
|
||||
inline void
|
||||
static inline void
|
||||
_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
|
||||
unsigned int modified_class)
|
||||
{
|
||||
info->unicode_props1() = modified_class;
|
||||
}
|
||||
|
||||
inline unsigned int
|
||||
static inline unsigned int
|
||||
_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
|
||||
{
|
||||
return info->unicode_props1();
|
||||
}
|
||||
|
||||
inline hb_bool_t
|
||||
static inline hb_bool_t
|
||||
_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
|
||||
{
|
||||
return !!(info->unicode_props0() & MASK0_IGNORABLE);
|
||||
}
|
||||
|
||||
inline hb_bool_t
|
||||
static inline hb_bool_t
|
||||
_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
|
||||
{
|
||||
return !!(info->unicode_props0() & MASK0_ZWNJ);
|
||||
}
|
||||
|
||||
inline hb_bool_t
|
||||
static inline hb_bool_t
|
||||
_hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
|
||||
{
|
||||
return !!(info->unicode_props0() & MASK0_ZWJ);
|
||||
}
|
||||
|
||||
inline void
|
||||
static inline void
|
||||
_hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
|
||||
{
|
||||
info->unicode_props0() ^= MASK0_ZWNJ | MASK0_ZWJ;
|
||||
@ -339,31 +341,31 @@ _hb_allocate_lig_id (hb_buffer_t *buffer) {
|
||||
|
||||
/* glyph_props: */
|
||||
|
||||
inline void
|
||||
static inline void
|
||||
_hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props)
|
||||
{
|
||||
info->glyph_props() = props;
|
||||
}
|
||||
|
||||
inline unsigned int
|
||||
static inline unsigned int
|
||||
_hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
|
||||
{
|
||||
return info->glyph_props();
|
||||
}
|
||||
|
||||
inline bool
|
||||
static inline bool
|
||||
_hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
|
||||
{
|
||||
return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
|
||||
}
|
||||
|
||||
inline bool
|
||||
static inline bool
|
||||
_hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
|
||||
{
|
||||
return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
|
||||
}
|
||||
|
||||
inline bool
|
||||
static inline bool
|
||||
_hb_glyph_info_is_mark (const hb_glyph_info_t *info)
|
||||
{
|
||||
return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
|
||||
@ -381,23 +383,43 @@ _hb_glyph_info_ligated (const hb_glyph_info_t *info)
|
||||
return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
_hb_glyph_info_multiplied (const hb_glyph_info_t *info)
|
||||
{
|
||||
return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
_hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
|
||||
{
|
||||
return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
|
||||
{
|
||||
info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
|
||||
}
|
||||
|
||||
|
||||
/* Allocation / deallocation. */
|
||||
|
||||
inline void
|
||||
static inline void
|
||||
_hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
|
||||
{
|
||||
HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props0);
|
||||
HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props1);
|
||||
}
|
||||
|
||||
inline void
|
||||
static inline void
|
||||
_hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
|
||||
{
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props0);
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props1);
|
||||
}
|
||||
|
||||
inline void
|
||||
static inline void
|
||||
_hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
|
||||
{
|
||||
HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
|
||||
@ -405,7 +427,7 @@ _hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
|
||||
HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
|
||||
}
|
||||
|
||||
inline void
|
||||
static inline void
|
||||
_hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
|
||||
{
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
|
||||
|
28
src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
vendored
28
src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
vendored
@ -327,9 +327,28 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
|
||||
unsigned int language_index,
|
||||
unsigned int *feature_index)
|
||||
{
|
||||
const OT::LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_index).get_lang_sys (language_index);
|
||||
return hb_ot_layout_language_get_required_feature (face,
|
||||
table_tag,
|
||||
script_index,
|
||||
language_index,
|
||||
feature_index,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (feature_index) *feature_index = l.get_required_feature_index ();
|
||||
hb_bool_t
|
||||
hb_ot_layout_language_get_required_feature (hb_face_t *face,
|
||||
hb_tag_t table_tag,
|
||||
unsigned int script_index,
|
||||
unsigned int language_index,
|
||||
unsigned int *feature_index,
|
||||
hb_tag_t *feature_tag)
|
||||
{
|
||||
const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
|
||||
const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
|
||||
|
||||
unsigned int index = l.get_required_feature_index ();
|
||||
if (feature_index) *feature_index = index;
|
||||
if (feature_tag) *feature_tag = g.get_feature_tag (index);
|
||||
|
||||
return l.has_required_feature ();
|
||||
}
|
||||
@ -468,11 +487,12 @@ _hb_ot_layout_collect_lookups_features (hb_face_t *face,
|
||||
if (!features)
|
||||
{
|
||||
unsigned int required_feature_index;
|
||||
if (hb_ot_layout_language_get_required_feature_index (face,
|
||||
if (hb_ot_layout_language_get_required_feature (face,
|
||||
table_tag,
|
||||
script_index,
|
||||
language_index,
|
||||
&required_feature_index))
|
||||
&required_feature_index,
|
||||
NULL))
|
||||
_hb_ot_layout_collect_lookups_lookups (face,
|
||||
table_tag,
|
||||
required_feature_index,
|
||||
|
14
src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
vendored
14
src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
vendored
@ -92,9 +92,9 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font,
|
||||
* GSUB/GPOS feature query and enumeration interface
|
||||
*/
|
||||
|
||||
#define HB_OT_LAYOUT_NO_SCRIPT_INDEX ((unsigned int) 0xFFFF)
|
||||
#define HB_OT_LAYOUT_NO_FEATURE_INDEX ((unsigned int) 0xFFFF)
|
||||
#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX ((unsigned int) 0xFFFF)
|
||||
#define HB_OT_LAYOUT_NO_SCRIPT_INDEX 0xFFFFu
|
||||
#define HB_OT_LAYOUT_NO_FEATURE_INDEX 0xFFFFu
|
||||
#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX 0xFFFFu
|
||||
|
||||
unsigned int
|
||||
hb_ot_layout_table_get_script_tags (hb_face_t *face,
|
||||
@ -146,6 +146,14 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
|
||||
unsigned int language_index,
|
||||
unsigned int *feature_index);
|
||||
|
||||
hb_bool_t
|
||||
hb_ot_layout_language_get_required_feature (hb_face_t *face,
|
||||
hb_tag_t table_tag,
|
||||
unsigned int script_index,
|
||||
unsigned int language_index,
|
||||
unsigned int *feature_index,
|
||||
hb_tag_t *feature_tag);
|
||||
|
||||
unsigned int
|
||||
hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
|
||||
hb_tag_t table_tag,
|
||||
|
@ -153,26 +153,26 @@ struct hb_ot_map_t
|
||||
};
|
||||
|
||||
enum hb_ot_map_feature_flags_t {
|
||||
F_NONE = 0x0000,
|
||||
F_GLOBAL = 0x0001,
|
||||
F_HAS_FALLBACK = 0x0002,
|
||||
F_MANUAL_ZWJ = 0x0004
|
||||
F_NONE = 0x0000u,
|
||||
F_GLOBAL = 0x0001u,
|
||||
F_HAS_FALLBACK = 0x0002u,
|
||||
F_MANUAL_ZWJ = 0x0004u
|
||||
};
|
||||
/* Macro version for where const is desired. */
|
||||
#define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r)))
|
||||
inline hb_ot_map_feature_flags_t
|
||||
static inline hb_ot_map_feature_flags_t
|
||||
operator | (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r)
|
||||
{ return hb_ot_map_feature_flags_t ((unsigned int) l | (unsigned int) r); }
|
||||
inline hb_ot_map_feature_flags_t
|
||||
static inline hb_ot_map_feature_flags_t
|
||||
operator & (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r)
|
||||
{ return hb_ot_map_feature_flags_t ((unsigned int) l & (unsigned int) r); }
|
||||
inline hb_ot_map_feature_flags_t
|
||||
static inline hb_ot_map_feature_flags_t
|
||||
operator ~ (hb_ot_map_feature_flags_t r)
|
||||
{ return hb_ot_map_feature_flags_t (~(unsigned int) r); }
|
||||
inline hb_ot_map_feature_flags_t&
|
||||
static inline hb_ot_map_feature_flags_t&
|
||||
operator |= (hb_ot_map_feature_flags_t &l, hb_ot_map_feature_flags_t r)
|
||||
{ l = l | r; return l; }
|
||||
inline hb_ot_map_feature_flags_t&
|
||||
static inline hb_ot_map_feature_flags_t&
|
||||
operator &= (hb_ot_map_feature_flags_t& l, hb_ot_map_feature_flags_t r)
|
||||
{ l = l & r; return l; }
|
||||
|
||||
|
54
src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
vendored
54
src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
vendored
@ -99,6 +99,7 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value,
|
||||
{
|
||||
feature_info_t *info = feature_infos.push();
|
||||
if (unlikely (!info)) return;
|
||||
if (unlikely (!tag)) return;
|
||||
info->tag = tag;
|
||||
info->seq = feature_infos.len;
|
||||
info->max_value = value;
|
||||
@ -131,9 +132,25 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
|
||||
{
|
||||
m.global_mask = 1;
|
||||
|
||||
for (unsigned int table_index = 0; table_index < 2; table_index++) {
|
||||
unsigned int required_feature_index[2];
|
||||
hb_tag_t required_feature_tag[2];
|
||||
/* We default to applying required feature in stage 0. If the required
|
||||
* feature has a tag that is known to the shaper, we apply required feature
|
||||
* in the stage for that tag.
|
||||
*/
|
||||
unsigned int required_feature_stage[2] = {0, 0};
|
||||
|
||||
for (unsigned int table_index = 0; table_index < 2; table_index++)
|
||||
{
|
||||
m.chosen_script[table_index] = chosen_script[table_index];
|
||||
m.found_script[table_index] = found_script[table_index];
|
||||
|
||||
hb_ot_layout_language_get_required_feature (face,
|
||||
table_tags[table_index],
|
||||
script_index[table_index],
|
||||
language_index[table_index],
|
||||
&required_feature_index[table_index],
|
||||
&required_feature_tag[table_index]);
|
||||
}
|
||||
|
||||
if (!feature_infos.len)
|
||||
@ -141,7 +158,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
|
||||
|
||||
/* Sort features and merge duplicates */
|
||||
{
|
||||
feature_infos.sort ();
|
||||
feature_infos.qsort ();
|
||||
unsigned int j = 0;
|
||||
for (unsigned int i = 1; i < feature_infos.len; i++)
|
||||
if (feature_infos[i].tag != feature_infos[j].tag)
|
||||
@ -166,7 +183,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
|
||||
|
||||
/* Allocate bits now */
|
||||
unsigned int next_bit = 1;
|
||||
for (unsigned int i = 0; i < feature_infos.len; i++) {
|
||||
for (unsigned int i = 0; i < feature_infos.len; i++)
|
||||
{
|
||||
const feature_info_t *info = &feature_infos[i];
|
||||
|
||||
unsigned int bits_needed;
|
||||
@ -184,12 +202,20 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
|
||||
hb_bool_t found = false;
|
||||
unsigned int feature_index[2];
|
||||
for (unsigned int table_index = 0; table_index < 2; table_index++)
|
||||
{
|
||||
if (required_feature_tag[table_index] == info->tag)
|
||||
{
|
||||
required_feature_stage[table_index] = info->stage[table_index];
|
||||
found = true;
|
||||
continue;
|
||||
}
|
||||
found |= hb_ot_layout_language_find_feature (face,
|
||||
table_tags[table_index],
|
||||
script_index[table_index],
|
||||
language_index[table_index],
|
||||
info->tag,
|
||||
&feature_index[table_index]);
|
||||
}
|
||||
if (!found && !(info->flags & F_HAS_FALLBACK))
|
||||
continue;
|
||||
|
||||
@ -224,23 +250,21 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
|
||||
add_gsub_pause (NULL);
|
||||
add_gpos_pause (NULL);
|
||||
|
||||
for (unsigned int table_index = 0; table_index < 2; table_index++) {
|
||||
hb_tag_t table_tag = table_tags[table_index];
|
||||
|
||||
for (unsigned int table_index = 0; table_index < 2; table_index++)
|
||||
{
|
||||
/* Collect lookup indices for features */
|
||||
|
||||
unsigned int required_feature_index;
|
||||
if (hb_ot_layout_language_get_required_feature_index (face,
|
||||
table_tag,
|
||||
script_index[table_index],
|
||||
language_index[table_index],
|
||||
&required_feature_index))
|
||||
m.add_lookups (face, table_index, required_feature_index, 1, true);
|
||||
|
||||
unsigned int stage_index = 0;
|
||||
unsigned int last_num_lookups = 0;
|
||||
for (unsigned stage = 0; stage < current_stage[table_index]; stage++)
|
||||
{
|
||||
if (required_feature_index[table_index] != HB_OT_LAYOUT_NO_FEATURE_INDEX &&
|
||||
required_feature_stage[table_index] == stage)
|
||||
m.add_lookups (face, table_index,
|
||||
required_feature_index[table_index],
|
||||
1 /* mask */,
|
||||
true /* auto_zwj */);
|
||||
|
||||
for (unsigned i = 0; i < m.features.len; i++)
|
||||
if (m.features[i].stage[table_index] == stage)
|
||||
m.add_lookups (face, table_index,
|
||||
@ -251,7 +275,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
|
||||
/* Sort lookups and merge duplicates */
|
||||
if (last_num_lookups < m.lookups[table_index].len)
|
||||
{
|
||||
m.lookups[table_index].sort (last_num_lookups, m.lookups[table_index].len);
|
||||
m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].len);
|
||||
|
||||
unsigned int j = last_num_lookups;
|
||||
for (unsigned int i = j + 1; i < m.lookups[table_index].len; i++)
|
||||
|
@ -50,13 +50,13 @@ struct maxp
|
||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||
TRACE_SANITIZE (this);
|
||||
return TRACE_RETURN (c->check_struct (this) &&
|
||||
likely (version.major == 1 || (version.major == 0 && version.minor == 0x5000)));
|
||||
likely (version.major == 1 || (version.major == 0 && version.minor == 0x5000u)));
|
||||
}
|
||||
|
||||
/* We only implement version 0.5 as none of the extra fields in version 1.0 are useful. */
|
||||
protected:
|
||||
FixedVersion version; /* Version of the maxp table (0.5 or 1.0),
|
||||
* 0x00005000 or 0x00010000. */
|
||||
* 0x00005000u or 0x00010000u. */
|
||||
USHORT numGlyphs; /* The number of glyphs in the font. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
|
@ -121,7 +121,7 @@ struct name
|
||||
/* We only implement format 0 for now. */
|
||||
USHORT format; /* Format selector (=0/1). */
|
||||
USHORT count; /* Number of name records. */
|
||||
Offset stringOffset; /* Offset to start of string storage (from start of table). */
|
||||
Offset<> stringOffset; /* Offset to start of string storage (from start of table). */
|
||||
NameRecord nameRecord[VAR]; /* The name records where count is the number of records. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (6, nameRecord);
|
||||
|
@ -71,7 +71,7 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
|
||||
!hb_font_get_glyph (font, u, 0, &u_glyph) ||
|
||||
!hb_font_get_glyph (font, s, 0, &s_glyph) ||
|
||||
u_glyph == s_glyph ||
|
||||
u_glyph > 0xFFFF || s_glyph > 0xFFFF)
|
||||
u_glyph > 0xFFFFu || s_glyph > 0xFFFFu)
|
||||
continue;
|
||||
|
||||
glyphs[num_glyphs].set (u_glyph);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -57,68 +57,41 @@ enum {
|
||||
|
||||
static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
|
||||
{
|
||||
if (likely (hb_in_range<hb_codepoint_t> (u, JOINING_TABLE_FIRST, JOINING_TABLE_LAST))) {
|
||||
unsigned int j_type = joining_table[u - JOINING_TABLE_FIRST];
|
||||
unsigned int j_type = joining_type(u);
|
||||
if (likely (j_type != JOINING_TYPE_X))
|
||||
return j_type;
|
||||
|
||||
return (FLAG(gen_cat) &
|
||||
(FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) |
|
||||
FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
|
||||
FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT))
|
||||
) ? JOINING_TYPE_T : JOINING_TYPE_U;
|
||||
}
|
||||
|
||||
/* Mongolian joining data is not in ArabicJoining.txt yet. */
|
||||
if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1800, 0x18AF)))
|
||||
{
|
||||
if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1880, 0x1886)))
|
||||
return JOINING_TYPE_U;
|
||||
|
||||
/* All letters, SIBE SYLLABLE BOUNDARY MARKER, and NIRUGU are D */
|
||||
if ((FLAG(gen_cat) & (FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) |
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER)))
|
||||
|| u == 0x1807 || u == 0x180A)
|
||||
return JOINING_TYPE_D;
|
||||
}
|
||||
|
||||
/* 'Phags-pa joining data is not in ArabicJoining.txt yet. */
|
||||
if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xA840, 0xA872)))
|
||||
{
|
||||
if (unlikely (u == 0xA872))
|
||||
return JOINING_TYPE_L;
|
||||
|
||||
return JOINING_TYPE_D;
|
||||
}
|
||||
|
||||
if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x200C, 0x200D)))
|
||||
{
|
||||
return u == 0x200C ? JOINING_TYPE_U : JOINING_TYPE_C;
|
||||
}
|
||||
|
||||
return (FLAG(gen_cat) & (FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT))) ?
|
||||
JOINING_TYPE_T : JOINING_TYPE_U;
|
||||
}
|
||||
#define FEATURE_IS_SYRIAC(tag) hb_in_range<unsigned char> ((unsigned char) (tag), '2', '3')
|
||||
|
||||
static const hb_tag_t arabic_features[] =
|
||||
{
|
||||
HB_TAG('i','n','i','t'),
|
||||
HB_TAG('m','e','d','i'),
|
||||
HB_TAG('f','i','n','a'),
|
||||
HB_TAG('i','s','o','l'),
|
||||
/* Syriac */
|
||||
HB_TAG('m','e','d','2'),
|
||||
HB_TAG('f','i','n','a'),
|
||||
HB_TAG('f','i','n','2'),
|
||||
HB_TAG('f','i','n','3'),
|
||||
HB_TAG('m','e','d','i'),
|
||||
HB_TAG('m','e','d','2'),
|
||||
HB_TAG('i','n','i','t'),
|
||||
HB_TAG_NONE
|
||||
};
|
||||
|
||||
|
||||
/* Same order as the feature array */
|
||||
enum {
|
||||
INIT,
|
||||
MEDI,
|
||||
FINA,
|
||||
ISOL,
|
||||
|
||||
/* Syriac */
|
||||
MED2,
|
||||
FINA,
|
||||
FIN2,
|
||||
FIN3,
|
||||
MEDI,
|
||||
MED2,
|
||||
INIT,
|
||||
|
||||
NONE,
|
||||
|
||||
@ -171,14 +144,23 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
|
||||
{
|
||||
hb_ot_map_builder_t *map = &plan->map;
|
||||
|
||||
/* For Language forms (in ArabicOT speak), we do the iso/fina/medi/init together,
|
||||
* then rlig and calt each in their own stage. This makes IranNastaliq's ALLAH
|
||||
* ligature work correctly. It's unfortunate though...
|
||||
/* We apply features according to the Arabic spec, with pauses
|
||||
* in between most.
|
||||
*
|
||||
* This also makes Arial Bold in Windows7 work. See:
|
||||
* The pause between init/medi/... and rlig is required. See eg:
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=644184
|
||||
*
|
||||
* TODO: Add test cases for these two.
|
||||
* The pauses between init/medi/... themselves are not necessarily
|
||||
* needed as only one of those features is applied to any character.
|
||||
* The only difference it makes is when fonts have contextual
|
||||
* substitutions. We now follow the order of the spec, which makes
|
||||
* for better experience if that's what Uniscribe is doing.
|
||||
*
|
||||
* At least for Arabic, looks like Uniscribe has a pause between
|
||||
* rlig and calt. Otherwise the IranNastaliq's ALLAH ligature won't
|
||||
* work. However, testing shows that rlig and calt are applied
|
||||
* together for Mongolian in Uniscribe. As such, we only add a
|
||||
* pause for Arabic, not other scripts.
|
||||
*/
|
||||
|
||||
map->add_gsub_pause (nuke_joiners);
|
||||
@ -189,16 +171,28 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
|
||||
map->add_gsub_pause (NULL);
|
||||
|
||||
for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++)
|
||||
map->add_feature (arabic_features[i], 1, i < 4 ? F_HAS_FALLBACK : F_NONE); /* The first four features have fallback. */
|
||||
|
||||
{
|
||||
bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]);
|
||||
map->add_feature (arabic_features[i], 1, has_fallback ? F_HAS_FALLBACK : F_NONE);
|
||||
map->add_gsub_pause (NULL);
|
||||
}
|
||||
|
||||
map->add_feature (HB_TAG('r','l','i','g'), 1, F_GLOBAL|F_HAS_FALLBACK);
|
||||
if (plan->props.script == HB_SCRIPT_ARABIC)
|
||||
map->add_gsub_pause (arabic_fallback_shape);
|
||||
|
||||
map->add_global_bool_feature (HB_TAG('c','a','l','t'));
|
||||
map->add_gsub_pause (NULL);
|
||||
|
||||
/* The spec includes 'cswh'. Earlier versions of Windows
|
||||
* used to enable this by default, but testing suggests
|
||||
* that Windows 8 and later do not enable it by default,
|
||||
* and spec now says 'Off by default'.
|
||||
* We disabled this in ae23c24c32.
|
||||
* Note that IranNastaliq uses this feature extensively
|
||||
* to fixup broken glyph sequences. Oh well...
|
||||
* Test case: U+0643,U+0640,U+0631. */
|
||||
//map->add_global_bool_feature (HB_TAG('c','s','w','h'));
|
||||
map->add_global_bool_feature (HB_TAG('m','s','e','t'));
|
||||
}
|
||||
|
||||
@ -228,8 +222,9 @@ data_create_arabic (const hb_ot_shape_plan_t *plan)
|
||||
arabic_plan->do_fallback = plan->props.script == HB_SCRIPT_ARABIC;
|
||||
for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) {
|
||||
arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]);
|
||||
if (i < 4)
|
||||
arabic_plan->do_fallback = arabic_plan->do_fallback && plan->map.needs_fallback (arabic_features[i]);
|
||||
arabic_plan->do_fallback = arabic_plan->do_fallback &&
|
||||
!FEATURE_IS_SYRIAC (arabic_features[i]) &&
|
||||
plan->map.needs_fallback (arabic_features[i]);
|
||||
}
|
||||
|
||||
return arabic_plan;
|
||||
@ -249,10 +244,9 @@ static void
|
||||
arabic_joining (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
unsigned int prev = (unsigned int) -1, state = 0;
|
||||
|
||||
HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action);
|
||||
|
||||
/* Check pre-context */
|
||||
if (!(buffer->flags & HB_BUFFER_FLAG_BOT))
|
||||
for (unsigned int i = 0; i < buffer->context_len[0]; i++)
|
||||
@ -269,20 +263,19 @@ arabic_joining (hb_buffer_t *buffer)
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
unsigned int this_type = get_joining_type (buffer->info[i].codepoint, _hb_glyph_info_get_general_category (&buffer->info[i]));
|
||||
unsigned int this_type = get_joining_type (info[i].codepoint, _hb_glyph_info_get_general_category (&info[i]));
|
||||
|
||||
if (unlikely (this_type == JOINING_TYPE_T)) {
|
||||
buffer->info[i].arabic_shaping_action() = NONE;
|
||||
info[i].arabic_shaping_action() = NONE;
|
||||
continue;
|
||||
}
|
||||
|
||||
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
|
||||
|
||||
if (entry->prev_action != NONE && prev != (unsigned int) -1)
|
||||
for (; prev < i; prev++)
|
||||
buffer->info[prev].arabic_shaping_action() = entry->prev_action;
|
||||
info[prev].arabic_shaping_action() = entry->prev_action;
|
||||
|
||||
buffer->info[i].arabic_shaping_action() = entry->curr_action;
|
||||
info[i].arabic_shaping_action() = entry->curr_action;
|
||||
|
||||
prev = i;
|
||||
state = entry->next_state;
|
||||
@ -298,12 +291,20 @@ arabic_joining (hb_buffer_t *buffer)
|
||||
|
||||
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
|
||||
if (entry->prev_action != NONE && prev != (unsigned int) -1)
|
||||
buffer->info[prev].arabic_shaping_action() = entry->prev_action;
|
||||
info[prev].arabic_shaping_action() = entry->prev_action;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
|
||||
static void
|
||||
mongolian_variation_selectors (hb_buffer_t *buffer)
|
||||
{
|
||||
/* Copy arabic_shaping_action() from base to Mongolian variation selectors. */
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 1; i < count; i++)
|
||||
if (unlikely (hb_in_range (info[i].codepoint, 0x180Bu, 0x180Du)))
|
||||
info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action();
|
||||
}
|
||||
|
||||
static void
|
||||
@ -311,12 +312,20 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font HB_UNUSED)
|
||||
{
|
||||
HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action);
|
||||
|
||||
const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
|
||||
|
||||
arabic_joining (buffer);
|
||||
if (plan->props.script == HB_SCRIPT_MONGOLIAN)
|
||||
mongolian_variation_selectors (buffer);
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
buffer->info[i].mask |= arabic_plan->mask_array[buffer->info[i].arabic_shaping_action()];
|
||||
info[i].mask |= arabic_plan->mask_array[info[i].arabic_shaping_action()];
|
||||
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
|
||||
}
|
||||
|
||||
|
||||
@ -326,9 +335,10 @@ nuke_joiners (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (_hb_glyph_info_is_zwj (&buffer->info[i]))
|
||||
_hb_glyph_info_flip_joiners (&buffer->info[i]);
|
||||
if (_hb_glyph_info_is_zwj (&info[i]))
|
||||
_hb_glyph_info_flip_joiners (&info[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -86,26 +86,26 @@ data_destroy_hangul (void *data)
|
||||
}
|
||||
|
||||
/* Constants for algorithmic hangul syllable [de]composition. */
|
||||
#define LBase 0x1100
|
||||
#define VBase 0x1161
|
||||
#define TBase 0x11A7
|
||||
#define LCount 19
|
||||
#define VCount 21
|
||||
#define TCount 28
|
||||
#define SBase 0xAC00
|
||||
#define LBase 0x1100u
|
||||
#define VBase 0x1161u
|
||||
#define TBase 0x11A7u
|
||||
#define LCount 19u
|
||||
#define VCount 21u
|
||||
#define TCount 28u
|
||||
#define SBase 0xAC00u
|
||||
#define NCount (VCount * TCount)
|
||||
#define SCount (LCount * NCount)
|
||||
|
||||
#define isCombiningL(u) (hb_in_range<hb_codepoint_t> ((u), LBase, LBase+LCount-1))
|
||||
#define isCombiningV(u) (hb_in_range<hb_codepoint_t> ((u), VBase, VBase+VCount-1))
|
||||
#define isCombiningT(u) (hb_in_range<hb_codepoint_t> ((u), TBase+1, TBase+TCount-1))
|
||||
#define isCombinedS(u) (hb_in_range<hb_codepoint_t> ((u), SBase, SBase+SCount-1))
|
||||
#define isCombiningL(u) (hb_in_range ((u), LBase, LBase+LCount-1))
|
||||
#define isCombiningV(u) (hb_in_range ((u), VBase, VBase+VCount-1))
|
||||
#define isCombiningT(u) (hb_in_range ((u), TBase+1, TBase+TCount-1))
|
||||
#define isCombinedS(u) (hb_in_range ((u), SBase, SBase+SCount-1))
|
||||
|
||||
#define isL(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1100, 0x115F, 0xA960, 0xA97C))
|
||||
#define isV(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1160, 0x11A7, 0xD7B0, 0xD7C6))
|
||||
#define isT(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x11A8, 0x11FF, 0xD7CB, 0xD7FB))
|
||||
#define isL(u) (hb_in_ranges ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu))
|
||||
#define isV(u) (hb_in_ranges ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u))
|
||||
#define isT(u) (hb_in_ranges ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu))
|
||||
|
||||
#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302e, 0x302f))
|
||||
#define isHangulTone(u) (hb_in_range ((u), 0x302Eu, 0x302Fu))
|
||||
|
||||
/* buffer var allocations */
|
||||
#define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */
|
||||
@ -211,14 +211,14 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
|
||||
else
|
||||
{
|
||||
/* No valid syllable as base for tone mark; try to insert dotted circle. */
|
||||
if (font->has_glyph (0x25cc))
|
||||
if (font->has_glyph (0x25CCu))
|
||||
{
|
||||
hb_codepoint_t chars[2];
|
||||
if (!is_zero_width_char (font, u)) {
|
||||
chars[0] = u;
|
||||
chars[1] = 0x25cc;
|
||||
chars[1] = 0x25CCu;
|
||||
} else {
|
||||
chars[0] = 0x25cc;
|
||||
chars[0] = 0x25CCu;
|
||||
chars[1] = u;
|
||||
}
|
||||
buffer->replace_glyphs (1, 2, chars);
|
||||
|
@ -35,116 +35,116 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
|
||||
{
|
||||
/* Hebrew presentation-form shaping.
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=728866
|
||||
* Hebrew presentation forms with dagesh, for characters 0x05D0..0x05EA;
|
||||
* Hebrew presentation forms with dagesh, for characters U+05D0..05EA;
|
||||
* Note that some letters do not have a dagesh presForm encoded.
|
||||
*/
|
||||
static const hb_codepoint_t sDageshForms[0x05EA - 0x05D0 + 1] = {
|
||||
0xFB30, /* ALEF */
|
||||
0xFB31, /* BET */
|
||||
0xFB32, /* GIMEL */
|
||||
0xFB33, /* DALET */
|
||||
0xFB34, /* HE */
|
||||
0xFB35, /* VAV */
|
||||
0xFB36, /* ZAYIN */
|
||||
0x0000, /* HET */
|
||||
0xFB38, /* TET */
|
||||
0xFB39, /* YOD */
|
||||
0xFB3A, /* FINAL KAF */
|
||||
0xFB3B, /* KAF */
|
||||
0xFB3C, /* LAMED */
|
||||
0x0000, /* FINAL MEM */
|
||||
0xFB3E, /* MEM */
|
||||
0x0000, /* FINAL NUN */
|
||||
0xFB40, /* NUN */
|
||||
0xFB41, /* SAMEKH */
|
||||
0x0000, /* AYIN */
|
||||
0xFB43, /* FINAL PE */
|
||||
0xFB44, /* PE */
|
||||
0x0000, /* FINAL TSADI */
|
||||
0xFB46, /* TSADI */
|
||||
0xFB47, /* QOF */
|
||||
0xFB48, /* RESH */
|
||||
0xFB49, /* SHIN */
|
||||
0xFB4A /* TAV */
|
||||
static const hb_codepoint_t sDageshForms[0x05EAu - 0x05D0u + 1] = {
|
||||
0xFB30u, /* ALEF */
|
||||
0xFB31u, /* BET */
|
||||
0xFB32u, /* GIMEL */
|
||||
0xFB33u, /* DALET */
|
||||
0xFB34u, /* HE */
|
||||
0xFB35u, /* VAV */
|
||||
0xFB36u, /* ZAYIN */
|
||||
0x0000u, /* HET */
|
||||
0xFB38u, /* TET */
|
||||
0xFB39u, /* YOD */
|
||||
0xFB3Au, /* FINAL KAF */
|
||||
0xFB3Bu, /* KAF */
|
||||
0xFB3Cu, /* LAMED */
|
||||
0x0000u, /* FINAL MEM */
|
||||
0xFB3Eu, /* MEM */
|
||||
0x0000u, /* FINAL NUN */
|
||||
0xFB40u, /* NUN */
|
||||
0xFB41u, /* SAMEKH */
|
||||
0x0000u, /* AYIN */
|
||||
0xFB43u, /* FINAL PE */
|
||||
0xFB44u, /* PE */
|
||||
0x0000u, /* FINAL TSADI */
|
||||
0xFB46u, /* TSADI */
|
||||
0xFB47u, /* QOF */
|
||||
0xFB48u, /* RESH */
|
||||
0xFB49u, /* SHIN */
|
||||
0xFB4Au /* TAV */
|
||||
};
|
||||
|
||||
bool found = c->unicode->compose (a, b, ab);
|
||||
|
||||
if (!found)
|
||||
if (!found && !c->plan->has_mark)
|
||||
{
|
||||
/* Special-case Hebrew presentation forms that are excluded from
|
||||
* standard normalization, but wanted for old fonts. */
|
||||
switch (b) {
|
||||
case 0x05B4: /* HIRIQ */
|
||||
if (a == 0x05D9) { /* YOD */
|
||||
*ab = 0xFB1D;
|
||||
case 0x05B4u: /* HIRIQ */
|
||||
if (a == 0x05D9u) { /* YOD */
|
||||
*ab = 0xFB1Du;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05B7: /* patah */
|
||||
if (a == 0x05F2) { /* YIDDISH YOD YOD */
|
||||
*ab = 0xFB1F;
|
||||
case 0x05B7u: /* patah */
|
||||
if (a == 0x05F2u) { /* YIDDISH YOD YOD */
|
||||
*ab = 0xFB1Fu;
|
||||
found = true;
|
||||
} else if (a == 0x05D0) { /* ALEF */
|
||||
*ab = 0xFB2E;
|
||||
} else if (a == 0x05D0u) { /* ALEF */
|
||||
*ab = 0xFB2Eu;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05B8: /* QAMATS */
|
||||
if (a == 0x05D0) { /* ALEF */
|
||||
*ab = 0xFB2F;
|
||||
case 0x05B8u: /* QAMATS */
|
||||
if (a == 0x05D0u) { /* ALEF */
|
||||
*ab = 0xFB2Fu;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05B9: /* HOLAM */
|
||||
if (a == 0x05D5) { /* VAV */
|
||||
*ab = 0xFB4B;
|
||||
case 0x05B9u: /* HOLAM */
|
||||
if (a == 0x05D5u) { /* VAV */
|
||||
*ab = 0xFB4Bu;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05BC: /* DAGESH */
|
||||
if (a >= 0x05D0 && a <= 0x05EA) {
|
||||
*ab = sDageshForms[a - 0x05D0];
|
||||
case 0x05BCu: /* DAGESH */
|
||||
if (a >= 0x05D0u && a <= 0x05EAu) {
|
||||
*ab = sDageshForms[a - 0x05D0u];
|
||||
found = (*ab != 0);
|
||||
} else if (a == 0xFB2A) { /* SHIN WITH SHIN DOT */
|
||||
*ab = 0xFB2C;
|
||||
} else if (a == 0xFB2Au) { /* SHIN WITH SHIN DOT */
|
||||
*ab = 0xFB2Cu;
|
||||
found = true;
|
||||
} else if (a == 0xFB2B) { /* SHIN WITH SIN DOT */
|
||||
*ab = 0xFB2D;
|
||||
} else if (a == 0xFB2Bu) { /* SHIN WITH SIN DOT */
|
||||
*ab = 0xFB2Du;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05BF: /* RAFE */
|
||||
case 0x05BFu: /* RAFE */
|
||||
switch (a) {
|
||||
case 0x05D1: /* BET */
|
||||
*ab = 0xFB4C;
|
||||
case 0x05D1u: /* BET */
|
||||
*ab = 0xFB4Cu;
|
||||
found = true;
|
||||
break;
|
||||
case 0x05DB: /* KAF */
|
||||
*ab = 0xFB4D;
|
||||
case 0x05DBu: /* KAF */
|
||||
*ab = 0xFB4Du;
|
||||
found = true;
|
||||
break;
|
||||
case 0x05E4: /* PE */
|
||||
*ab = 0xFB4E;
|
||||
case 0x05E4u: /* PE */
|
||||
*ab = 0xFB4Eu;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x05C1: /* SHIN DOT */
|
||||
if (a == 0x05E9) { /* SHIN */
|
||||
*ab = 0xFB2A;
|
||||
case 0x05C1u: /* SHIN DOT */
|
||||
if (a == 0x05E9u) { /* SHIN */
|
||||
*ab = 0xFB2Au;
|
||||
found = true;
|
||||
} else if (a == 0xFB49) { /* SHIN WITH DAGESH */
|
||||
*ab = 0xFB2C;
|
||||
} else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
|
||||
*ab = 0xFB2Cu;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05C2: /* SIN DOT */
|
||||
if (a == 0x05E9) { /* SHIN */
|
||||
*ab = 0xFB2B;
|
||||
case 0x05C2u: /* SIN DOT */
|
||||
if (a == 0x05E9u) { /* SHIN */
|
||||
*ab = 0xFB2Bu;
|
||||
found = true;
|
||||
} else if (a == 0xFB49) { /* SHIN WITH DAGESH */
|
||||
*ab = 0xFB2D;
|
||||
} else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
|
||||
*ab = 0xFB2Du;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -53,17 +53,29 @@ enum indic_category_t {
|
||||
OT_SM = 8,
|
||||
OT_VD = 9,
|
||||
OT_A = 10,
|
||||
OT_NBSP = 11,
|
||||
OT_PLACEHOLDER = 11,
|
||||
OT_DOTTEDCIRCLE = 12,
|
||||
OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */
|
||||
OT_Coeng = 14, /* Khmer-style Virama. */
|
||||
OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
|
||||
OT_Ra = 16,
|
||||
OT_CM = 17, /* Consonant-Medial. */
|
||||
OT_Avag = 18, /* Avagraha. */
|
||||
OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
|
||||
OT_CM2 = 31 /* Consonant-Medial, second slot. */
|
||||
};
|
||||
|
||||
#define MEDIAL_FLAGS (FLAG (OT_CM) | FLAG (OT_CM2))
|
||||
|
||||
/* Note:
|
||||
*
|
||||
* We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
|
||||
* cannot happen in a consonant syllable. The plus side however is, we can call the
|
||||
* consonant syllable logic from the vowel syllable function and get it all right! */
|
||||
#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
|
||||
#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
|
||||
#define HALANT_OR_COENG_FLAGS (FLAG (OT_H) | FLAG (OT_Coeng))
|
||||
|
||||
|
||||
/* Visual positions in a syllable from left to right. */
|
||||
enum indic_position_t {
|
||||
POS_START,
|
||||
@ -95,18 +107,28 @@ enum indic_position_t {
|
||||
enum indic_syllabic_category_t {
|
||||
INDIC_SYLLABIC_CATEGORY_OTHER = OT_X,
|
||||
|
||||
INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_Avag,
|
||||
INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_Symbol,
|
||||
INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM,
|
||||
INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER = OT_PLACEHOLDER, /* TODO */
|
||||
INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK = OT_A,
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C,
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C,
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_CM,
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C,
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_CM,
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_NBSP,
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_PLACEHOLDER,
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA = OT_Repha,
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM,
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA = OT_Repha,
|
||||
INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_N,
|
||||
INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM,
|
||||
INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_H, /* TODO */
|
||||
INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ,
|
||||
INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X,
|
||||
INDIC_SYLLABIC_CATEGORY_NON_JOINER = OT_ZWNJ,
|
||||
INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N,
|
||||
INDIC_SYLLABIC_CATEGORY_NUMBER = OT_PLACEHOLDER,
|
||||
INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* TODO */
|
||||
INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_H, /* TODO */
|
||||
INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_RS,
|
||||
INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X,
|
||||
INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_N,
|
||||
@ -135,7 +157,6 @@ enum indic_matra_category_t {
|
||||
INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
|
||||
INDIC_MATRA_CATEGORY_TOP_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
|
||||
|
||||
INDIC_MATRA_CATEGORY_INVISIBLE = INDIC_MATRA_CATEGORY_NOT_APPLICABLE,
|
||||
INDIC_MATRA_CATEGORY_OVERSTRUCK = POS_AFTER_MAIN,
|
||||
INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = POS_PRE_M
|
||||
};
|
||||
@ -143,7 +164,15 @@ enum indic_matra_category_t {
|
||||
/* Note: We use ASSERT_STATIC_EXPR_ZERO() instead of ASSERT_STATIC_EXPR() and the comma operation
|
||||
* because gcc fails to optimize the latter and fills the table in at runtime. */
|
||||
#define INDIC_COMBINE_CATEGORIES(S,M) \
|
||||
(ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || (S == INDIC_SYLLABIC_CATEGORY_VIRAMA || S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT)) + \
|
||||
(ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || \
|
||||
( \
|
||||
S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
|
||||
S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
|
||||
S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
|
||||
S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
|
||||
S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
|
||||
S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
|
||||
false)) + \
|
||||
ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
|
||||
((M << 8) | S))
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -37,19 +37,19 @@
|
||||
*/
|
||||
|
||||
|
||||
#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7F) == (Base))
|
||||
#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
|
||||
|
||||
#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900))
|
||||
#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980))
|
||||
#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00))
|
||||
#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80))
|
||||
#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00))
|
||||
#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80))
|
||||
#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00))
|
||||
#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80))
|
||||
#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00))
|
||||
#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80))
|
||||
#define IS_KHMR(u) (IN_HALF_BLOCK (u, 0x1780))
|
||||
#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
|
||||
#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
|
||||
#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
|
||||
#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
|
||||
#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
|
||||
#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
|
||||
#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
|
||||
#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
|
||||
#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
|
||||
#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
|
||||
#define IS_KHMR(u) (IN_HALF_BLOCK (u, 0x1780u))
|
||||
|
||||
|
||||
#define MATRA_POS_LEFT(u) POS_PRE_M
|
||||
@ -60,8 +60,8 @@
|
||||
IS_GUJR(u) ? POS_AFTER_POST : \
|
||||
IS_ORYA(u) ? POS_AFTER_POST : \
|
||||
IS_TAML(u) ? POS_AFTER_POST : \
|
||||
IS_TELU(u) ? (u <= 0x0C42 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
|
||||
IS_KNDA(u) ? (u < 0x0CC3 || u > 0xCD6 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
|
||||
IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
|
||||
IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
|
||||
IS_MLYM(u) ? POS_AFTER_POST : \
|
||||
IS_SINH(u) ? POS_AFTER_SUB : \
|
||||
IS_KHMR(u) ? POS_AFTER_POST : \
|
||||
@ -112,20 +112,20 @@ matra_position (hb_codepoint_t u, indic_position_t side)
|
||||
* Or completely remove it and just check in the tables.
|
||||
*/
|
||||
static const hb_codepoint_t ra_chars[] = {
|
||||
0x0930, /* Devanagari */
|
||||
0x09B0, /* Bengali */
|
||||
0x09F0, /* Bengali */
|
||||
0x0A30, /* Gurmukhi */ /* No Reph */
|
||||
0x0AB0, /* Gujarati */
|
||||
0x0B30, /* Oriya */
|
||||
0x0BB0, /* Tamil */ /* No Reph */
|
||||
0x0C30, /* Telugu */ /* Reph formed only with ZWJ */
|
||||
0x0CB0, /* Kannada */
|
||||
0x0D30, /* Malayalam */ /* No Reph, Logical Repha */
|
||||
0x0930u, /* Devanagari */
|
||||
0x09B0u, /* Bengali */
|
||||
0x09F0u, /* Bengali */
|
||||
0x0A30u, /* Gurmukhi */ /* No Reph */
|
||||
0x0AB0u, /* Gujarati */
|
||||
0x0B30u, /* Oriya */
|
||||
0x0BB0u, /* Tamil */ /* No Reph */
|
||||
0x0C30u, /* Telugu */ /* Reph formed only with ZWJ */
|
||||
0x0CB0u, /* Kannada */
|
||||
0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */
|
||||
|
||||
0x0DBB, /* Sinhala */ /* Reph formed only with ZWJ */
|
||||
0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
|
||||
|
||||
0x179A, /* Khmer */ /* No Reph, Visual Repha */
|
||||
0x179Au, /* Khmer */ /* No Reph, Visual Repha */
|
||||
};
|
||||
|
||||
static inline bool
|
||||
@ -145,28 +145,18 @@ is_one_of (const hb_glyph_info_t &info, unsigned int flags)
|
||||
return !!(FLAG (info.indic_category()) & flags);
|
||||
}
|
||||
|
||||
#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
|
||||
static inline bool
|
||||
is_joiner (const hb_glyph_info_t &info)
|
||||
{
|
||||
return is_one_of (info, JOINER_FLAGS);
|
||||
}
|
||||
|
||||
#define MEDIAL_FLAGS (FLAG (OT_CM) | FLAG (OT_CM2))
|
||||
|
||||
/* Note:
|
||||
*
|
||||
* We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
|
||||
* cannot happen in a consonant syllable. The plus side however is, we can call the
|
||||
* consonant syllable logic from the vowel syllable function and get it all right! */
|
||||
#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_DOTTEDCIRCLE))
|
||||
static inline bool
|
||||
is_consonant (const hb_glyph_info_t &info)
|
||||
{
|
||||
return is_one_of (info, CONSONANT_FLAGS);
|
||||
}
|
||||
|
||||
#define HALANT_OR_COENG_FLAGS (FLAG (OT_H) | FLAG (OT_Coeng))
|
||||
static inline bool
|
||||
is_halant_or_coeng (const hb_glyph_info_t &info)
|
||||
{
|
||||
@ -178,7 +168,7 @@ set_indic_properties (hb_glyph_info_t &info)
|
||||
{
|
||||
hb_codepoint_t u = info.codepoint;
|
||||
unsigned int type = hb_indic_get_categories (u);
|
||||
indic_category_t cat = (indic_category_t) (type & 0x7F);
|
||||
indic_category_t cat = (indic_category_t) (type & 0x7Fu);
|
||||
indic_position_t pos = (indic_position_t) (type >> 8);
|
||||
|
||||
|
||||
@ -188,48 +178,59 @@ set_indic_properties (hb_glyph_info_t &info)
|
||||
|
||||
|
||||
/* The spec says U+0952 is OT_A. However, testing shows that Uniscribe
|
||||
* treats U+0951..U+0954 all behave similarly.
|
||||
* TESTS:
|
||||
* treats a whole bunch of characters similarly.
|
||||
* TESTS: For example, for U+0951:
|
||||
* U+092E,U+0947,U+0952
|
||||
* U+092E,U+0952,U+0947
|
||||
* U+092E,U+0947,U+0951
|
||||
* U+092E,U+0951,U+0947
|
||||
* U+092E,U+0951,U+0952
|
||||
* U+092E,U+0952,U+0951
|
||||
*/
|
||||
if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0951, 0x0954)))
|
||||
if (unlikely (hb_in_ranges (u, 0x0951u, 0x0952u,
|
||||
0x1CD0u, 0x1CD2u,
|
||||
0x1CD4u, 0x1CE1u) ||
|
||||
u == 0x1CF4u))
|
||||
cat = OT_A;
|
||||
|
||||
if (unlikely (u == 0x17D1))
|
||||
cat = OT_X;
|
||||
if (cat == OT_X &&
|
||||
unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CB, 0x17D3))) /* Khmer Various signs */
|
||||
/* The following act more like the Bindus. */
|
||||
else if (unlikely (hb_in_range (u, 0x0953u, 0x0954u)))
|
||||
cat = OT_SM;
|
||||
/* The following act like consonants. */
|
||||
else if (unlikely (hb_in_ranges (u, 0x0A72u, 0x0A73u,
|
||||
0x1CF5u, 0x1CF6u)))
|
||||
cat = OT_C;
|
||||
/* TODO: The following should only be allowed after a Visarga.
|
||||
* For now, just treat them like regular tone marks. */
|
||||
else if (unlikely (hb_in_range (u, 0x1CE2u, 0x1CE8u)))
|
||||
cat = OT_A;
|
||||
/* TODO: The following should only be allowed after some of
|
||||
* the nasalization marks, maybe only for U+1CE9..U+1CF1.
|
||||
* For now, just treat them like tone marks. */
|
||||
else if (unlikely (u == 0x1CEDu))
|
||||
cat = OT_A;
|
||||
/* The following take marks in standalone clusters, similar to Avagraha. */
|
||||
else if (unlikely (hb_in_ranges (u, 0xA8F2u, 0xA8F7u,
|
||||
0x1CE9u, 0x1CECu,
|
||||
0x1CEEu, 0x1CF1u)))
|
||||
{
|
||||
cat = OT_Symbol;
|
||||
ASSERT_STATIC ((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol);
|
||||
}
|
||||
else if (unlikely (hb_in_range (u, 0x17CDu, 0x17D1u) ||
|
||||
u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */
|
||||
{
|
||||
/* These are like Top Matras. */
|
||||
cat = OT_M;
|
||||
pos = POS_ABOVE_C;
|
||||
}
|
||||
if (u == 0x17C6) /* Khmer Bindu doesn't like to be repositioned. */
|
||||
cat = OT_N;
|
||||
|
||||
if (unlikely (u == 0x17D2)) cat = OT_Coeng; /* Khmer coeng */
|
||||
else if (unlikely (u == 0x200C)) cat = OT_ZWNJ;
|
||||
else if (unlikely (u == 0x200D)) cat = OT_ZWJ;
|
||||
else if (unlikely (u == 0x25CC)) cat = OT_DOTTEDCIRCLE;
|
||||
else if (unlikely (u == 0x0A71)) cat = OT_SM; /* GURMUKHI ADDAK. Move it to the end. */
|
||||
else if (unlikely (u == 0xA982)) cat = OT_SM; /* Javanese repha. */
|
||||
else if (unlikely (u == 0xA9BE)) cat = OT_CM2; /* Javanese medial ya. */
|
||||
else if (unlikely (u == 0xA9BD)) { cat = OT_M; pos = POS_POST_C; } /* Javanese vocalic r. */
|
||||
|
||||
if (cat == OT_Repha) {
|
||||
/* There are two kinds of characters marked as Repha:
|
||||
* - The ones that are GenCat=Mn are already positioned visually, ie. after base. (eg. Khmer)
|
||||
* - The ones that are GenCat=Lo is encoded logically, ie. beginning of syllable. (eg. Malayalam)
|
||||
*
|
||||
* We recategorize the first kind to look like a Nukta and attached to the base directly.
|
||||
*/
|
||||
if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
|
||||
cat = OT_N;
|
||||
}
|
||||
|
||||
else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
|
||||
else if (unlikely (u == 0x17D2u)) cat = OT_Coeng; /* Khmer coeng */
|
||||
else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u)))
|
||||
cat = OT_PLACEHOLDER;
|
||||
else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
|
||||
else if (unlikely (u == 0xA982u)) cat = OT_SM; /* Javanese repha. */
|
||||
else if (unlikely (u == 0xA9BEu)) cat = OT_CM2; /* Javanese medial ya. */
|
||||
else if (unlikely (u == 0xA9BDu)) { cat = OT_M; pos = POS_POST_C; } /* Javanese vocalic r. */
|
||||
|
||||
|
||||
/*
|
||||
@ -246,12 +247,12 @@ set_indic_properties (hb_glyph_info_t &info)
|
||||
{
|
||||
pos = matra_position (u, pos);
|
||||
}
|
||||
else if ((FLAG (cat) & (FLAG (OT_SM) | FLAG (OT_VD) | FLAG (OT_A) | FLAG (OT_Avag))))
|
||||
else if ((FLAG (cat) & (FLAG (OT_SM) | FLAG (OT_VD) | FLAG (OT_A) | FLAG (OT_Symbol))))
|
||||
{
|
||||
pos = POS_SMVD;
|
||||
}
|
||||
|
||||
if (unlikely (u == 0x0B01)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
|
||||
if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
|
||||
|
||||
|
||||
|
||||
@ -316,19 +317,19 @@ static const indic_config_t indic_configs[] =
|
||||
{
|
||||
/* Default. Should be first. */
|
||||
{HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_1},
|
||||
{HB_SCRIPT_DEVANAGARI,true, 0x094D,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
|
||||
{HB_SCRIPT_BENGALI, true, 0x09CD,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
|
||||
{HB_SCRIPT_GURMUKHI, true, 0x0A4D,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
|
||||
{HB_SCRIPT_GUJARATI, true, 0x0ACD,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
|
||||
{HB_SCRIPT_ORIYA, true, 0x0B4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
|
||||
{HB_SCRIPT_TAMIL, true, 0x0BCD,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
|
||||
{HB_SCRIPT_TELUGU, true, 0x0C4D,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2},
|
||||
{HB_SCRIPT_KANNADA, true, 0x0CCD,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2},
|
||||
{HB_SCRIPT_MALAYALAM, true, 0x0D4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
|
||||
{HB_SCRIPT_SINHALA, false,0x0DCA,BASE_POS_LAST_SINHALA,
|
||||
{HB_SCRIPT_DEVANAGARI,true, 0x094Du,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
|
||||
{HB_SCRIPT_BENGALI, true, 0x09CDu,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
|
||||
{HB_SCRIPT_GURMUKHI, true, 0x0A4Du,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
|
||||
{HB_SCRIPT_GUJARATI, true, 0x0ACDu,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
|
||||
{HB_SCRIPT_ORIYA, true, 0x0B4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
|
||||
{HB_SCRIPT_TAMIL, true, 0x0BCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
|
||||
{HB_SCRIPT_TELUGU, true, 0x0C4Du,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2},
|
||||
{HB_SCRIPT_KANNADA, true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2},
|
||||
{HB_SCRIPT_MALAYALAM, true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
|
||||
{HB_SCRIPT_SINHALA, false,0x0DCAu,BASE_POS_LAST_SINHALA,
|
||||
REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
|
||||
{HB_SCRIPT_KHMER, false,0x17D2,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
|
||||
{HB_SCRIPT_JAVANESE, false,0xA9C0,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_1},
|
||||
{HB_SCRIPT_KHMER, false,0x17D2u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
|
||||
{HB_SCRIPT_JAVANESE, false,0xA9C0u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_1},
|
||||
};
|
||||
|
||||
|
||||
@ -552,12 +553,12 @@ data_create_indic (const hb_ot_shape_plan_t *plan)
|
||||
break;
|
||||
}
|
||||
|
||||
indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FF) != '2');
|
||||
indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
|
||||
indic_plan->virama_glyph = (hb_codepoint_t) -1;
|
||||
|
||||
/* Use zero-context would_substitute() matching for new-spec of the main
|
||||
* Indic scripts, but not for old-spec or scripts with one spec only. */
|
||||
bool zero_context = indic_plan->config->has_old_spec || !indic_plan->is_old_spec;
|
||||
* Indic scripts, and scripts with one spec only, but not for old-specs. */
|
||||
bool zero_context = !indic_plan->is_old_spec;
|
||||
indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f'), zero_context);
|
||||
indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context);
|
||||
indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context);
|
||||
@ -614,7 +615,7 @@ enum syllable_type_t {
|
||||
consonant_syllable,
|
||||
vowel_syllable,
|
||||
standalone_cluster,
|
||||
avagraha_cluster,
|
||||
symbol_cluster,
|
||||
broken_cluster,
|
||||
non_indic_cluster,
|
||||
};
|
||||
@ -634,8 +635,9 @@ setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
* and setup masks later on in a pause-callback. */
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
set_indic_properties (buffer->info[i]);
|
||||
set_indic_properties (info[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -672,10 +674,12 @@ update_consonant_positions (const hb_ot_shape_plan_t *plan,
|
||||
{
|
||||
hb_face_t *face = font->face;
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (buffer->info[i].indic_position() == POS_BASE_C) {
|
||||
hb_codepoint_t consonant = buffer->info[i].codepoint;
|
||||
buffer->info[i].indic_position() = consonant_position_from_face (indic_plan, consonant, virama, face);
|
||||
if (info[i].indic_position() == POS_BASE_C)
|
||||
{
|
||||
hb_codepoint_t consonant = info[i].codepoint;
|
||||
info[i].indic_position() = consonant_position_from_face (indic_plan, consonant, virama, face);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -725,8 +729,13 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
||||
))
|
||||
{
|
||||
/* See if it matches the 'rphf' feature. */
|
||||
hb_codepoint_t glyphs[2] = {info[start].codepoint, info[start + 1].codepoint};
|
||||
if (indic_plan->rphf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face))
|
||||
hb_codepoint_t glyphs[3] = {info[start].codepoint,
|
||||
info[start + 1].codepoint,
|
||||
indic_plan->config->reph_mode == REPH_MODE_EXPLICIT ?
|
||||
info[start + 2].codepoint : 0};
|
||||
if (indic_plan->rphf.would_substitute (glyphs, 2, face) ||
|
||||
(indic_plan->config->reph_mode == REPH_MODE_EXPLICIT &&
|
||||
indic_plan->rphf.would_substitute (glyphs, 3, face)))
|
||||
{
|
||||
limit += 2;
|
||||
while (limit < end && is_joiner (info[limit]))
|
||||
@ -801,7 +810,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
||||
case BASE_POS_LAST_SINHALA:
|
||||
{
|
||||
/* Sinhala base positioning is slightly different from main Indic, in that:
|
||||
* 1. It's ZWJ behavior is different,
|
||||
* 1. Its ZWJ behavior is different,
|
||||
* 2. We don't need to look into the font for consonant positions.
|
||||
*/
|
||||
|
||||
@ -1151,8 +1160,8 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int start, unsigned int end)
|
||||
{
|
||||
/* We treat NBSP/dotted-circle as if they are consonants, so we should just chain.
|
||||
* Only if not in compatibility mode that is... */
|
||||
/* We treat placeholder/dotted-circle as if they are consonants, so we
|
||||
* should just chain. Only if not in compatibility mode that is... */
|
||||
|
||||
if (hb_options ().uniscribe_bug_compatible)
|
||||
{
|
||||
@ -1177,7 +1186,7 @@ initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan,
|
||||
}
|
||||
|
||||
static void
|
||||
initial_reordering_avagraha_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
initial_reordering_symbol_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_face_t *face HB_UNUSED,
|
||||
hb_buffer_t *buffer HB_UNUSED,
|
||||
unsigned int start HB_UNUSED, unsigned int end HB_UNUSED)
|
||||
@ -1208,7 +1217,7 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
||||
case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return;
|
||||
case vowel_syllable: initial_reordering_vowel_syllable (plan, face, buffer, start, end); return;
|
||||
case standalone_cluster: initial_reordering_standalone_cluster (plan, face, buffer, start, end); return;
|
||||
case avagraha_cluster: initial_reordering_avagraha_cluster (plan, face, buffer, start, end); return;
|
||||
case symbol_cluster: initial_reordering_symbol_cluster (plan, face, buffer, start, end); return;
|
||||
case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return;
|
||||
case non_indic_cluster: initial_reordering_non_indic_cluster (plan, face, buffer, start, end); return;
|
||||
}
|
||||
@ -1222,8 +1231,10 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
/* Note: This loop is extra overhead, but should not be measurable. */
|
||||
bool has_broken_syllables = false;
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if ((buffer->info[i].syllable() & 0x0F) == broken_cluster) {
|
||||
if ((info[i].syllable() & 0x0F) == broken_cluster)
|
||||
{
|
||||
has_broken_syllables = true;
|
||||
break;
|
||||
}
|
||||
@ -1232,11 +1243,11 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
|
||||
|
||||
hb_codepoint_t dottedcircle_glyph;
|
||||
if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph))
|
||||
if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
|
||||
return;
|
||||
|
||||
hb_glyph_info_t dottedcircle = {0};
|
||||
dottedcircle.codepoint = 0x25CC;
|
||||
dottedcircle.codepoint = 0x25CCu;
|
||||
set_indic_properties (dottedcircle);
|
||||
dottedcircle.codepoint = dottedcircle_glyph;
|
||||
|
||||
@ -1302,6 +1313,27 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
||||
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
||||
|
||||
/* This function relies heavily on halant glyphs. Lots of ligation
|
||||
* and possibly multiplication 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. */
|
||||
if (indic_plan->virama_glyph)
|
||||
{
|
||||
unsigned int virama_glyph = indic_plan->virama_glyph;
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
if (info[i].codepoint == virama_glyph &&
|
||||
_hb_glyph_info_ligated (&info[i]) &&
|
||||
_hb_glyph_info_multiplied (&info[i]))
|
||||
{
|
||||
/* This will make sure that this glyph passes is_halant_or_coeng() test. */
|
||||
info[i].indic_category() = OT_H;
|
||||
_hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 4. Final reordering:
|
||||
*
|
||||
* After the localized forms and basic shaping forms GSUB features have been
|
||||
@ -1310,20 +1342,44 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
||||
* cluster.
|
||||
*/
|
||||
|
||||
bool try_pref = !!indic_plan->mask_array[PREF];
|
||||
|
||||
/* Find base again */
|
||||
unsigned int base;
|
||||
for (base = start; base < end; base++)
|
||||
if (info[base].indic_position() >= POS_BASE_C) {
|
||||
if (info[base].indic_position() >= POS_BASE_C)
|
||||
{
|
||||
if (try_pref && base + 1 < end && indic_plan->config->pref_len == 2)
|
||||
{
|
||||
for (unsigned int i = base + 1; i < end; i++)
|
||||
if ((info[i].mask & indic_plan->mask_array[PREF]) != 0)
|
||||
{
|
||||
if (!(_hb_glyph_info_substituted (&info[i]) &&
|
||||
_hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
|
||||
{
|
||||
/* Ok, this was a 'pref' candidate but didn't form any.
|
||||
* Base is around here... */
|
||||
base = i;
|
||||
while (base < end && is_halant_or_coeng (info[base]))
|
||||
base++;
|
||||
info[base].indic_position() = POS_BASE_C;
|
||||
|
||||
try_pref = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (start < base && info[base].indic_position() > POS_BASE_C)
|
||||
base--;
|
||||
break;
|
||||
}
|
||||
if (base == end && start < base &&
|
||||
info[base - 1].indic_category() != OT_ZWJ)
|
||||
is_one_of (info[base - 1], FLAG (OT_ZWJ)))
|
||||
base--;
|
||||
if (base < end)
|
||||
while (start < base &&
|
||||
(info[base].indic_category() == OT_H ||
|
||||
info[base].indic_category() == OT_N))
|
||||
is_one_of (info[base], (FLAG (OT_N) | HALANT_OR_COENG_FLAGS)))
|
||||
base--;
|
||||
|
||||
|
||||
@ -1349,7 +1405,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
||||
if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL)
|
||||
{
|
||||
while (new_pos > start &&
|
||||
!(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_H) | FLAG (OT_Coeng)))))
|
||||
!(is_one_of (info[new_pos], (FLAG (OT_M) | HALANT_OR_COENG_FLAGS))))
|
||||
new_pos--;
|
||||
|
||||
/* If we found no Halant we are done.
|
||||
@ -1412,7 +1468,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
||||
if (start + 1 < end &&
|
||||
info[start].indic_position() == POS_RA_TO_BECOME_REPH &&
|
||||
((info[start].indic_category() == OT_Repha) ^
|
||||
_hb_glyph_info_ligated (&info[start])))
|
||||
_hb_glyph_info_ligated_and_didnt_multiply (&info[start])))
|
||||
{
|
||||
unsigned int new_reph_pos;
|
||||
reph_position_t reph_pos = indic_plan->config->reph_pos;
|
||||
@ -1549,7 +1605,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
||||
* the following rules:
|
||||
*/
|
||||
|
||||
if (indic_plan->mask_array[PREF] && base + 1 < end) /* Otherwise there can't be any pre-base reordering Ra. */
|
||||
if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base reordering Ra. */
|
||||
{
|
||||
unsigned int pref_len = indic_plan->config->pref_len;
|
||||
for (unsigned int i = base + 1; i < end; i++)
|
||||
@ -1565,7 +1621,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
||||
* If pref len is longer than one, then only reorder if it ligated. If
|
||||
* pref len is one, only reorder if it didn't ligate with other things. */
|
||||
if (_hb_glyph_info_substituted (&info[i]) &&
|
||||
((pref_len == 1) ^ _hb_glyph_info_ligated (&info[i])))
|
||||
((pref_len == 1) ^ _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
|
||||
{
|
||||
/*
|
||||
* 2. Try to find a target position the same way as for pre-base matra.
|
||||
@ -1699,37 +1755,37 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
|
||||
switch (ab)
|
||||
{
|
||||
/* Don't decompose these. */
|
||||
case 0x0931 : return false;
|
||||
case 0x0B94 : return false;
|
||||
case 0x0931u : return false;
|
||||
case 0x0B94u : return false;
|
||||
|
||||
|
||||
/*
|
||||
* Decompose split matras that don't have Unicode decompositions.
|
||||
*/
|
||||
|
||||
case 0x0F77 : *a = 0x0FB2; *b= 0x0F81; return true;
|
||||
case 0x0F79 : *a = 0x0FB3; *b= 0x0F81; return true;
|
||||
case 0x17BE : *a = 0x17C1; *b= 0x17BE; return true;
|
||||
case 0x17BF : *a = 0x17C1; *b= 0x17BF; return true;
|
||||
case 0x17C0 : *a = 0x17C1; *b= 0x17C0; return true;
|
||||
case 0x17C4 : *a = 0x17C1; *b= 0x17C4; return true;
|
||||
case 0x17C5 : *a = 0x17C1; *b= 0x17C5; return true;
|
||||
case 0x1925 : *a = 0x1920; *b= 0x1923; return true;
|
||||
case 0x1926 : *a = 0x1920; *b= 0x1924; return true;
|
||||
case 0x1B3C : *a = 0x1B42; *b= 0x1B3C; return true;
|
||||
case 0x1112E : *a = 0x11127; *b= 0x11131; return true;
|
||||
case 0x1112F : *a = 0x11127; *b= 0x11132; return true;
|
||||
case 0x0F77u : *a = 0x0FB2u; *b= 0x0F81u; return true;
|
||||
case 0x0F79u : *a = 0x0FB3u; *b= 0x0F81u; return true;
|
||||
case 0x17BEu : *a = 0x17C1u; *b= 0x17BEu; return true;
|
||||
case 0x17BFu : *a = 0x17C1u; *b= 0x17BFu; return true;
|
||||
case 0x17C0u : *a = 0x17C1u; *b= 0x17C0u; return true;
|
||||
case 0x17C4u : *a = 0x17C1u; *b= 0x17C4u; return true;
|
||||
case 0x17C5u : *a = 0x17C1u; *b= 0x17C5u; return true;
|
||||
case 0x1925u : *a = 0x1920u; *b= 0x1923u; return true;
|
||||
case 0x1926u : *a = 0x1920u; *b= 0x1924u; return true;
|
||||
case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true;
|
||||
case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true;
|
||||
case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true;
|
||||
#if 0
|
||||
/* This one has no decomposition in Unicode, but needs no decomposition either. */
|
||||
/* case 0x0AC9 : return false; */
|
||||
case 0x0B57 : *a = no decomp, -> RIGHT; return true;
|
||||
case 0x1C29 : *a = no decomp, -> LEFT; return true;
|
||||
case 0xA9C0 : *a = no decomp, -> RIGHT; return true;
|
||||
case 0x111BF : *a = no decomp, -> ABOVE; return true;
|
||||
/* case 0x0AC9u : return false; */
|
||||
case 0x0B57u : *a = no decomp, -> RIGHT; return true;
|
||||
case 0x1C29u : *a = no decomp, -> LEFT; return true;
|
||||
case 0xA9C0u : *a = no decomp, -> RIGHT; return true;
|
||||
case 0x111BuF : *a = no decomp, -> ABOVE; return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((ab == 0x0DDA || hb_in_range<hb_codepoint_t> (ab, 0x0DDC, 0x0DDE)))
|
||||
if ((ab == 0x0DDAu || hb_in_range (ab, 0x0DDCu, 0x0DDEu)))
|
||||
{
|
||||
/*
|
||||
* Sinhala split matras... Let the fun begin.
|
||||
@ -1766,7 +1822,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
|
||||
indic_plan->pstf.would_substitute (&glyph, 1, c->font->face)))
|
||||
{
|
||||
/* Ok, safe to use Uniscribe-style decomposition. */
|
||||
*a = 0x0DD9;
|
||||
*a = 0x0DD9u;
|
||||
*b = ab;
|
||||
return true;
|
||||
}
|
||||
@ -1786,7 +1842,7 @@ compose_indic (const hb_ot_shape_normalize_context_t *c,
|
||||
return false;
|
||||
|
||||
/* Composition-exclusion exceptions that we want to recompose. */
|
||||
if (a == 0x09AF && b == 0x09BC) { *ab = 0x09DF; return true; }
|
||||
if (a == 0x09AFu && b == 0x09BCu) { *ab = 0x09DFu; return true; }
|
||||
|
||||
return c->unicode->compose (a, b, ab);
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ static const short _myanmar_syllable_machine_index_offsets[] = {
|
||||
|
||||
static const char _myanmar_syllable_machine_indicies[] = {
|
||||
1, 1, 2, 3, 4, 4, 0, 5,
|
||||
0, 6, 0, 1, 0, 0, 0, 7,
|
||||
0, 6, 1, 0, 0, 0, 0, 7,
|
||||
0, 8, 1, 0, 9, 10, 11, 12,
|
||||
13, 14, 15, 16, 17, 18, 19, 0,
|
||||
21, 22, 23, 23, 20, 24, 20, 25,
|
||||
@ -119,14 +119,14 @@ static const char _myanmar_syllable_machine_indicies[] = {
|
||||
20, 20, 20, 20, 20, 20, 20, 20,
|
||||
20, 31, 20, 33, 20, 35, 20, 21,
|
||||
20, 23, 23, 20, 24, 20, 25, 20,
|
||||
20, 20, 20, 20, 20, 20, 20, 20,
|
||||
20, 20, 20, 20, 20, 20, 34, 20,
|
||||
20, 27, 20, 29, 20, 31, 32, 33,
|
||||
34, 35, 20, 21, 20, 23, 23, 20,
|
||||
24, 20, 25, 20, 20, 20, 20, 20,
|
||||
20, 20, 34, 20, 20, 27, 20, 20,
|
||||
20, 31, 32, 33, 34, 35, 20, 21,
|
||||
20, 23, 23, 20, 24, 20, 25, 20,
|
||||
20, 20, 20, 20, 20, 20, 20, 20,
|
||||
20, 20, 20, 20, 20, 20, 34, 20,
|
||||
20, 27, 28, 29, 20, 31, 32, 33,
|
||||
34, 35, 20, 21, 22, 23, 23, 20,
|
||||
24, 20, 25, 20, 20, 20, 20, 20,
|
||||
@ -169,8 +169,8 @@ static const char _myanmar_syllable_machine_indicies[] = {
|
||||
25, 20, 20, 20, 20, 20, 20, 20,
|
||||
26, 20, 20, 27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35, 20, 1, 1, 2,
|
||||
3, 3, 3, 42, 5, 42, 6, 42,
|
||||
1, 42, 42, 42, 1, 42, 8, 1,
|
||||
3, 3, 3, 42, 5, 42, 6, 1,
|
||||
42, 42, 42, 42, 1, 42, 8, 1,
|
||||
42, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 42, 2, 42, 3, 3,
|
||||
42, 5, 42, 6, 42, 42, 42, 42,
|
||||
@ -191,14 +191,14 @@ static const char _myanmar_syllable_machine_indicies[] = {
|
||||
42, 42, 42, 42, 42, 42, 42, 42,
|
||||
42, 42, 13, 42, 15, 42, 17, 42,
|
||||
2, 42, 3, 3, 42, 5, 42, 6,
|
||||
42, 42, 42, 42, 42, 42, 42, 42,
|
||||
42, 42, 42, 42, 42, 42, 42, 16,
|
||||
42, 42, 9, 42, 11, 42, 13, 14,
|
||||
15, 16, 17, 42, 2, 42, 3, 3,
|
||||
42, 5, 42, 6, 42, 42, 42, 42,
|
||||
42, 42, 42, 16, 42, 42, 9, 42,
|
||||
42, 42, 13, 14, 15, 16, 17, 42,
|
||||
2, 42, 3, 3, 42, 5, 42, 6,
|
||||
42, 42, 42, 42, 42, 42, 42, 42,
|
||||
42, 42, 42, 42, 42, 42, 42, 16,
|
||||
42, 42, 9, 10, 11, 42, 13, 14,
|
||||
15, 16, 17, 42, 2, 3, 3, 3,
|
||||
42, 5, 42, 6, 42, 42, 42, 42,
|
||||
|
@ -134,7 +134,7 @@ enum myanmar_category_t {
|
||||
OT_D = 19, /* Digits except zero */
|
||||
OT_D0 = 20, /* Digit zero */
|
||||
OT_DB = OT_N, /* Dot below */
|
||||
OT_GB = OT_DOTTEDCIRCLE,
|
||||
OT_GB = OT_PLACEHOLDER,
|
||||
OT_MH = 21, /* Various consonant medial types */
|
||||
OT_MR = 22, /* Various consonant medial types */
|
||||
OT_MW = 23, /* Various consonant medial types */
|
||||
@ -157,12 +157,6 @@ is_one_of (const hb_glyph_info_t &info, unsigned int flags)
|
||||
return !!(FLAG (info.myanmar_category()) & flags);
|
||||
}
|
||||
|
||||
/* Note:
|
||||
*
|
||||
* We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
|
||||
* cannot happen in a consonant syllable. The plus side however is, we can call the
|
||||
* consonant syllable logic from the vowel syllable function and get it all right! */
|
||||
#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CM) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_GB))
|
||||
static inline bool
|
||||
is_consonant (const hb_glyph_info_t &info)
|
||||
{
|
||||
@ -175,82 +169,80 @@ set_myanmar_properties (hb_glyph_info_t &info)
|
||||
{
|
||||
hb_codepoint_t u = info.codepoint;
|
||||
unsigned int type = hb_indic_get_categories (u);
|
||||
indic_category_t cat = (indic_category_t) (type & 0x7F);
|
||||
indic_category_t cat = (indic_category_t) (type & 0x7Fu);
|
||||
indic_position_t pos = (indic_position_t) (type >> 8);
|
||||
|
||||
/* Myanmar
|
||||
* http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm#analyze
|
||||
*/
|
||||
if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00, 0xFE0F)))
|
||||
if (unlikely (hb_in_range (u, 0xFE00u, 0xFE0Fu)))
|
||||
cat = (indic_category_t) OT_VS;
|
||||
else if (unlikely (u == 0x200C)) cat = (indic_category_t) OT_ZWNJ;
|
||||
else if (unlikely (u == 0x200D)) cat = (indic_category_t) OT_ZWJ;
|
||||
|
||||
switch (u)
|
||||
{
|
||||
case 0x104E:
|
||||
case 0x104Eu:
|
||||
cat = (indic_category_t) OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
|
||||
break;
|
||||
|
||||
case 0x002D: case 0x00A0: case 0x00D7: case 0x2012:
|
||||
case 0x2013: case 0x2014: case 0x2015: case 0x2022:
|
||||
case 0x25CC: case 0x25FB: case 0x25FC: case 0x25FD:
|
||||
case 0x25FE:
|
||||
case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
|
||||
case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
|
||||
case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
|
||||
case 0x25FEu:
|
||||
cat = (indic_category_t) OT_GB;
|
||||
break;
|
||||
|
||||
case 0x1004: case 0x101B: case 0x105A:
|
||||
case 0x1004u: case 0x101Bu: case 0x105Au:
|
||||
cat = (indic_category_t) OT_Ra;
|
||||
break;
|
||||
|
||||
case 0x1032: case 0x1036:
|
||||
case 0x1032u: case 0x1036u:
|
||||
cat = (indic_category_t) OT_A;
|
||||
break;
|
||||
|
||||
case 0x103A:
|
||||
case 0x103Au:
|
||||
cat = (indic_category_t) OT_As;
|
||||
break;
|
||||
|
||||
case 0x1041: case 0x1042: case 0x1043: case 0x1044:
|
||||
case 0x1045: case 0x1046: case 0x1047: case 0x1048:
|
||||
case 0x1049: case 0x1090: case 0x1091: case 0x1092:
|
||||
case 0x1093: case 0x1094: case 0x1095: case 0x1096:
|
||||
case 0x1097: case 0x1098: case 0x1099:
|
||||
case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
|
||||
case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
|
||||
case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
|
||||
case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
|
||||
case 0x1097u: case 0x1098u: case 0x1099u:
|
||||
cat = (indic_category_t) OT_D;
|
||||
break;
|
||||
|
||||
case 0x1040:
|
||||
case 0x1040u:
|
||||
cat = (indic_category_t) OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
|
||||
break;
|
||||
|
||||
case 0x103E: case 0x1060:
|
||||
case 0x103Eu: case 0x1060u:
|
||||
cat = (indic_category_t) OT_MH;
|
||||
break;
|
||||
|
||||
case 0x103C:
|
||||
case 0x103Cu:
|
||||
cat = (indic_category_t) OT_MR;
|
||||
break;
|
||||
|
||||
case 0x103D: case 0x1082:
|
||||
case 0x103Du: case 0x1082u:
|
||||
cat = (indic_category_t) OT_MW;
|
||||
break;
|
||||
|
||||
case 0x103B: case 0x105E: case 0x105F:
|
||||
case 0x103Bu: case 0x105Eu: case 0x105Fu:
|
||||
cat = (indic_category_t) OT_MY;
|
||||
break;
|
||||
|
||||
case 0x1063: case 0x1064: case 0x1069: case 0x106A:
|
||||
case 0x106B: case 0x106C: case 0x106D: case 0xAA7B:
|
||||
case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
|
||||
case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
|
||||
cat = (indic_category_t) OT_PT;
|
||||
break;
|
||||
|
||||
case 0x1038: case 0x1087: case 0x1088: case 0x1089:
|
||||
case 0x108A: case 0x108B: case 0x108C: case 0x108D:
|
||||
case 0x108F: case 0x109A: case 0x109B: case 0x109C:
|
||||
case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
|
||||
case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
|
||||
case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
|
||||
cat = (indic_category_t) OT_SM;
|
||||
break;
|
||||
|
||||
case 0x104A: case 0x104B:
|
||||
case 0x104Au: case 0x104Bu:
|
||||
cat = (indic_category_t) OT_P;
|
||||
break;
|
||||
}
|
||||
@ -285,8 +277,9 @@ setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
* and setup masks later on in a pause-callback. */
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
set_myanmar_properties (buffer->info[i]);
|
||||
set_myanmar_properties (info[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -459,8 +452,10 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
/* Note: This loop is extra overhead, but should not be measurable. */
|
||||
bool has_broken_syllables = false;
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if ((buffer->info[i].syllable() & 0x0F) == broken_cluster) {
|
||||
if ((info[i].syllable() & 0x0F) == broken_cluster)
|
||||
{
|
||||
has_broken_syllables = true;
|
||||
break;
|
||||
}
|
||||
@ -469,11 +464,11 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
|
||||
|
||||
hb_codepoint_t dottedcircle_glyph;
|
||||
if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph))
|
||||
if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
|
||||
return;
|
||||
|
||||
hb_glyph_info_t dottedcircle = {0};
|
||||
dottedcircle.codepoint = 0x25CC;
|
||||
dottedcircle.codepoint = 0x25CCu;
|
||||
set_myanmar_properties (dottedcircle);
|
||||
dottedcircle.codepoint = dottedcircle_glyph;
|
||||
|
||||
|
@ -173,6 +173,10 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
|
||||
/* Unicode-6.0 additions */
|
||||
case HB_SCRIPT_MANDAIC:
|
||||
|
||||
/* Unicode-7.0 additions */
|
||||
case HB_SCRIPT_MANICHAEAN:
|
||||
case HB_SCRIPT_PSALTER_PAHLAVI:
|
||||
|
||||
/* 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). */
|
||||
if (planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
|
||||
|
@ -139,11 +139,11 @@ set_sea_properties (hb_glyph_info_t &info)
|
||||
{
|
||||
hb_codepoint_t u = info.codepoint;
|
||||
unsigned int type = hb_indic_get_categories (u);
|
||||
indic_category_t cat = (indic_category_t) (type & 0x7F);
|
||||
indic_category_t cat = (indic_category_t) (type & 0x7Fu);
|
||||
indic_position_t pos = (indic_position_t) (type >> 8);
|
||||
|
||||
/* Medial Ra */
|
||||
if (u == 0x1A55 || u == 0xAA34)
|
||||
if (u == 0x1A55u || u == 0xAA34u)
|
||||
cat = (indic_category_t) OT_MR;
|
||||
|
||||
if (cat == OT_M)
|
||||
@ -174,8 +174,9 @@ setup_masks_sea (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
* and setup masks later on in a pause-callback. */
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
set_sea_properties (buffer->info[i]);
|
||||
set_sea_properties (info[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -278,8 +279,10 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
/* Note: This loop is extra overhead, but should not be measurable. */
|
||||
bool has_broken_syllables = false;
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if ((buffer->info[i].syllable() & 0x0F) == broken_cluster) {
|
||||
if ((info[i].syllable() & 0x0F) == broken_cluster)
|
||||
{
|
||||
has_broken_syllables = true;
|
||||
break;
|
||||
}
|
||||
@ -288,11 +291,11 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
|
||||
|
||||
hb_codepoint_t dottedcircle_glyph;
|
||||
if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph))
|
||||
if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
|
||||
return;
|
||||
|
||||
hb_glyph_info_t dottedcircle = {0};
|
||||
dottedcircle.codepoint = 0x25CC;
|
||||
dottedcircle.codepoint = 0x25CCu;
|
||||
set_sea_properties (dottedcircle);
|
||||
dottedcircle.codepoint = dottedcircle_glyph;
|
||||
|
||||
|
@ -46,13 +46,13 @@ enum thai_consonant_type_t
|
||||
static thai_consonant_type_t
|
||||
get_consonant_type (hb_codepoint_t u)
|
||||
{
|
||||
if (u == 0x0E1B || u == 0x0E1D || u == 0x0E1F/* || u == 0x0E2C*/)
|
||||
if (u == 0x0E1Bu || u == 0x0E1Du || u == 0x0E1Fu/* || u == 0x0E2Cu*/)
|
||||
return AC;
|
||||
if (u == 0x0E0D || u == 0x0E10)
|
||||
if (u == 0x0E0Du || u == 0x0E10u)
|
||||
return RC;
|
||||
if (u == 0x0E0E || u == 0x0E0F)
|
||||
if (u == 0x0E0Eu || u == 0x0E0Fu)
|
||||
return DC;
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x0E01, 0x0E2E))
|
||||
if (hb_in_range (u, 0x0E01u, 0x0E2Eu))
|
||||
return NC;
|
||||
return NOT_CONSONANT;
|
||||
}
|
||||
@ -70,12 +70,12 @@ enum thai_mark_type_t
|
||||
static thai_mark_type_t
|
||||
get_mark_type (hb_codepoint_t u)
|
||||
{
|
||||
if (u == 0x0E31 || hb_in_range<hb_codepoint_t> (u, 0x0E34, 0x0E37) ||
|
||||
u == 0x0E47 || hb_in_range<hb_codepoint_t> (u, 0x0E4D, 0x0E4E))
|
||||
if (u == 0x0E31u || hb_in_range (u, 0x0E34u, 0x0E37u) ||
|
||||
u == 0x0E47u || hb_in_range (u, 0x0E4Du, 0x0E4Eu))
|
||||
return AV;
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x0E38, 0x0E3A))
|
||||
if (hb_in_range (u, 0x0E38u, 0x0E3Au))
|
||||
return BV;
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x0E48, 0x0E4C))
|
||||
if (hb_in_range (u, 0x0E48u, 0x0E4Cu))
|
||||
return T;
|
||||
return NOT_MARK;
|
||||
}
|
||||
@ -99,43 +99,43 @@ thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font)
|
||||
hb_codepoint_t mac_pua;
|
||||
} const *pua_mappings = NULL;
|
||||
static const thai_pua_mapping_t SD_mappings[] = {
|
||||
{0x0E48, 0xF70A, 0xF88B}, /* MAI EK */
|
||||
{0x0E49, 0xF70B, 0xF88E}, /* MAI THO */
|
||||
{0x0E4A, 0xF70C, 0xF891}, /* MAI TRI */
|
||||
{0x0E4B, 0xF70D, 0xF894}, /* MAI CHATTAWA */
|
||||
{0x0E4C, 0xF70E, 0xF897}, /* THANTHAKHAT */
|
||||
{0x0E38, 0xF718, 0xF89B}, /* SARA U */
|
||||
{0x0E39, 0xF719, 0xF89C}, /* SARA UU */
|
||||
{0x0E3A, 0xF71A, 0xF89D}, /* PHINTHU */
|
||||
{0x0000, 0x0000, 0x0000}
|
||||
{0x0E48u, 0xF70Au, 0xF88Bu}, /* MAI EK */
|
||||
{0x0E49u, 0xF70Bu, 0xF88Eu}, /* MAI THO */
|
||||
{0x0E4Au, 0xF70Cu, 0xF891u}, /* MAI TRI */
|
||||
{0x0E4Bu, 0xF70Du, 0xF894u}, /* MAI CHATTAWA */
|
||||
{0x0E4Cu, 0xF70Eu, 0xF897u}, /* THANTHAKHAT */
|
||||
{0x0E38u, 0xF718u, 0xF89Bu}, /* SARA U */
|
||||
{0x0E39u, 0xF719u, 0xF89Cu}, /* SARA UU */
|
||||
{0x0E3Au, 0xF71Au, 0xF89Du}, /* PHINTHU */
|
||||
{0x0000u, 0x0000u, 0x0000u}
|
||||
};
|
||||
static const thai_pua_mapping_t SDL_mappings[] = {
|
||||
{0x0E48, 0xF705, 0xF88C}, /* MAI EK */
|
||||
{0x0E49, 0xF706, 0xF88F}, /* MAI THO */
|
||||
{0x0E4A, 0xF707, 0xF892}, /* MAI TRI */
|
||||
{0x0E4B, 0xF708, 0xF895}, /* MAI CHATTAWA */
|
||||
{0x0E4C, 0xF709, 0xF898}, /* THANTHAKHAT */
|
||||
{0x0000, 0x0000, 0x0000}
|
||||
{0x0E48u, 0xF705u, 0xF88Cu}, /* MAI EK */
|
||||
{0x0E49u, 0xF706u, 0xF88Fu}, /* MAI THO */
|
||||
{0x0E4Au, 0xF707u, 0xF892u}, /* MAI TRI */
|
||||
{0x0E4Bu, 0xF708u, 0xF895u}, /* MAI CHATTAWA */
|
||||
{0x0E4Cu, 0xF709u, 0xF898u}, /* THANTHAKHAT */
|
||||
{0x0000u, 0x0000u, 0x0000u}
|
||||
};
|
||||
static const thai_pua_mapping_t SL_mappings[] = {
|
||||
{0x0E48, 0xF713, 0xF88A}, /* MAI EK */
|
||||
{0x0E49, 0xF714, 0xF88D}, /* MAI THO */
|
||||
{0x0E4A, 0xF715, 0xF890}, /* MAI TRI */
|
||||
{0x0E4B, 0xF716, 0xF893}, /* MAI CHATTAWA */
|
||||
{0x0E4C, 0xF717, 0xF896}, /* THANTHAKHAT */
|
||||
{0x0E31, 0xF710, 0xF884}, /* MAI HAN-AKAT */
|
||||
{0x0E34, 0xF701, 0xF885}, /* SARA I */
|
||||
{0x0E35, 0xF702, 0xF886}, /* SARA II */
|
||||
{0x0E36, 0xF703, 0xF887}, /* SARA UE */
|
||||
{0x0E37, 0xF704, 0xF888}, /* SARA UEE */
|
||||
{0x0E47, 0xF712, 0xF889}, /* MAITAIKHU */
|
||||
{0x0E4D, 0xF711, 0xF899}, /* NIKHAHIT */
|
||||
{0x0000, 0x0000, 0x0000}
|
||||
{0x0E48u, 0xF713u, 0xF88Au}, /* MAI EK */
|
||||
{0x0E49u, 0xF714u, 0xF88Du}, /* MAI THO */
|
||||
{0x0E4Au, 0xF715u, 0xF890u}, /* MAI TRI */
|
||||
{0x0E4Bu, 0xF716u, 0xF893u}, /* MAI CHATTAWA */
|
||||
{0x0E4Cu, 0xF717u, 0xF896u}, /* THANTHAKHAT */
|
||||
{0x0E31u, 0xF710u, 0xF884u}, /* MAI HAN-AKAT */
|
||||
{0x0E34u, 0xF701u, 0xF885u}, /* SARA I */
|
||||
{0x0E35u, 0xF702u, 0xF886u}, /* SARA II */
|
||||
{0x0E36u, 0xF703u, 0xF887u}, /* SARA UE */
|
||||
{0x0E37u, 0xF704u, 0xF888u}, /* SARA UEE */
|
||||
{0x0E47u, 0xF712u, 0xF889u}, /* MAITAIKHU */
|
||||
{0x0E4Du, 0xF711u, 0xF899u}, /* NIKHAHIT */
|
||||
{0x0000u, 0x0000u, 0x0000u}
|
||||
};
|
||||
static const thai_pua_mapping_t RD_mappings[] = {
|
||||
{0x0E0D, 0xF70F, 0xF89A}, /* YO YING */
|
||||
{0x0E10, 0xF700, 0xF89E}, /* THO THAN */
|
||||
{0x0000, 0x0000, 0x0000}
|
||||
{0x0E0Du, 0xF70Fu, 0xF89Au}, /* YO YING */
|
||||
{0x0E10u, 0xF700u, 0xF89Eu}, /* THO THAN */
|
||||
{0x0000u, 0x0000u, 0x0000u}
|
||||
};
|
||||
|
||||
switch (action) {
|
||||
@ -308,10 +308,10 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
|
||||
|
||||
/* We only get one script at a time, so a script-agnostic implementation
|
||||
* is adequate here. */
|
||||
#define IS_SARA_AM(x) (((x) & ~0x0080) == 0x0E33)
|
||||
#define NIKHAHIT_FROM_SARA_AM(x) ((x) - 0xE33 + 0xE4D)
|
||||
#define IS_SARA_AM(x) (((x) & ~0x0080u) == 0x0E33u)
|
||||
#define NIKHAHIT_FROM_SARA_AM(x) ((x) - 0x0E33u + 0x0E4Du)
|
||||
#define SARA_AA_FROM_SARA_AM(x) ((x) - 1)
|
||||
#define IS_TONE_MARK(x) (hb_in_ranges<hb_codepoint_t> ((x) & ~0x0080, 0x0E34, 0x0E37, 0x0E47, 0x0E4E, 0x0E31, 0x0E31))
|
||||
#define IS_TONE_MARK(x) (hb_in_ranges ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u))
|
||||
|
||||
buffer->clear_output ();
|
||||
unsigned int count = buffer->len;
|
||||
@ -330,8 +330,11 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
|
||||
if (unlikely (buffer->in_error))
|
||||
return;
|
||||
|
||||
/* Ok, let's see... */
|
||||
/* Make Nikhahit be recognized as a mark when zeroing widths. */
|
||||
unsigned int end = buffer->out_len;
|
||||
_hb_glyph_info_set_general_category (&buffer->out_info[end - 2], HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK);
|
||||
|
||||
/* Ok, let's see... */
|
||||
unsigned int start = end - 2;
|
||||
while (start > 0 && IS_TONE_MARK (buffer->out_info[start - 1].codepoint))
|
||||
start--;
|
||||
|
@ -35,42 +35,42 @@ recategorize_combining_class (hb_codepoint_t u,
|
||||
return klass;
|
||||
|
||||
/* Thai / Lao need some per-character work. */
|
||||
if ((u & ~0xFF) == 0x0E00)
|
||||
if ((u & ~0xFF) == 0x0E00u)
|
||||
{
|
||||
if (unlikely (klass == 0))
|
||||
{
|
||||
switch (u)
|
||||
{
|
||||
case 0x0E31:
|
||||
case 0x0E34:
|
||||
case 0x0E35:
|
||||
case 0x0E36:
|
||||
case 0x0E37:
|
||||
case 0x0E47:
|
||||
case 0x0E4C:
|
||||
case 0x0E4D:
|
||||
case 0x0E4E:
|
||||
case 0x0E31u:
|
||||
case 0x0E34u:
|
||||
case 0x0E35u:
|
||||
case 0x0E36u:
|
||||
case 0x0E37u:
|
||||
case 0x0E47u:
|
||||
case 0x0E4Cu:
|
||||
case 0x0E4Du:
|
||||
case 0x0E4Eu:
|
||||
klass = HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
|
||||
break;
|
||||
|
||||
case 0x0EB1:
|
||||
case 0x0EB4:
|
||||
case 0x0EB5:
|
||||
case 0x0EB6:
|
||||
case 0x0EB7:
|
||||
case 0x0EBB:
|
||||
case 0x0ECC:
|
||||
case 0x0ECD:
|
||||
case 0x0EB1u:
|
||||
case 0x0EB4u:
|
||||
case 0x0EB5u:
|
||||
case 0x0EB6u:
|
||||
case 0x0EB7u:
|
||||
case 0x0EBBu:
|
||||
case 0x0ECCu:
|
||||
case 0x0ECDu:
|
||||
klass = HB_UNICODE_COMBINING_CLASS_ABOVE;
|
||||
break;
|
||||
|
||||
case 0x0EBC:
|
||||
case 0x0EBCu:
|
||||
klass = HB_UNICODE_COMBINING_CLASS_BELOW;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Thai virama is below-right */
|
||||
if (u == 0x0E3A)
|
||||
if (u == 0x0E3Au)
|
||||
klass = HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT;
|
||||
}
|
||||
}
|
||||
@ -167,11 +167,12 @@ _hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *pla
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) {
|
||||
unsigned int combining_class = _hb_glyph_info_get_modified_combining_class (&buffer->info[i]);
|
||||
combining_class = recategorize_combining_class (buffer->info[i].codepoint, combining_class);
|
||||
_hb_glyph_info_set_modified_combining_class (&buffer->info[i], combining_class);
|
||||
if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) {
|
||||
unsigned int combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]);
|
||||
combining_class = recategorize_combining_class (info[i].codepoint, combining_class);
|
||||
_hb_glyph_info_set_modified_combining_class (&info[i], combining_class);
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,8 +182,9 @@ zero_mark_advances (hb_buffer_t *buffer,
|
||||
unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
|
||||
if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
|
||||
{
|
||||
buffer->pos[i].x_advance = 0;
|
||||
buffer->pos[i].y_advance = 0;
|
||||
@ -327,12 +329,13 @@ position_around_base (const hb_ot_shape_plan_t *plan,
|
||||
unsigned int last_lig_component = (unsigned int) -1;
|
||||
unsigned int last_combining_class = 255;
|
||||
hb_glyph_extents_t cluster_extents = base_extents; /* Initialization is just to shut gcc up. */
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = base + 1; i < end; i++)
|
||||
if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]))
|
||||
if (_hb_glyph_info_get_modified_combining_class (&info[i]))
|
||||
{
|
||||
if (num_lig_components > 1) {
|
||||
unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[i]);
|
||||
unsigned int this_lig_component = _hb_glyph_info_get_lig_comp (&buffer->info[i]) - 1;
|
||||
unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&info[i]);
|
||||
unsigned int this_lig_component = _hb_glyph_info_get_lig_comp (&info[i]) - 1;
|
||||
/* Conditions for attaching to the last component. */
|
||||
if (!lig_id || lig_id != this_lig_id || this_lig_component >= num_lig_components)
|
||||
this_lig_component = num_lig_components - 1;
|
||||
@ -355,7 +358,7 @@ position_around_base (const hb_ot_shape_plan_t *plan,
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int this_combining_class = _hb_glyph_info_get_modified_combining_class (&buffer->info[i]);
|
||||
unsigned int this_combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]);
|
||||
if (last_combining_class != this_combining_class)
|
||||
{
|
||||
last_combining_class = this_combining_class;
|
||||
@ -391,13 +394,14 @@ position_cluster (const hb_ot_shape_plan_t *plan,
|
||||
return;
|
||||
|
||||
/* Find the base glyph */
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[i])))
|
||||
if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))
|
||||
{
|
||||
/* Find mark glyphs */
|
||||
unsigned int j;
|
||||
for (j = i + 1; j < end; j++)
|
||||
if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[j])))
|
||||
if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[j])))
|
||||
break;
|
||||
|
||||
position_around_base (plan, font, buffer, i, j);
|
||||
@ -432,15 +436,13 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
|
||||
{
|
||||
if (!plan->has_kern) return;
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
|
||||
OT::hb_apply_context_t c (1, font, buffer);
|
||||
c.set_lookup_mask (plan->kern_mask);
|
||||
c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
hb_glyph_position_t *pos = buffer->pos;
|
||||
|
||||
for (unsigned int idx = 0; idx < count;)
|
||||
{
|
||||
OT::hb_apply_context_t::skipping_forward_iterator_t skippy_iter (&c, idx, 1);
|
||||
|
@ -44,6 +44,7 @@ struct hb_ot_shape_plan_t
|
||||
hb_mask_t kern_mask;
|
||||
unsigned int has_frac : 1;
|
||||
unsigned int has_kern : 1;
|
||||
unsigned int has_mark : 1;
|
||||
|
||||
inline void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
|
||||
{
|
||||
@ -92,6 +93,7 @@ struct hb_ot_shape_planner_t
|
||||
|
||||
plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
|
||||
plan.has_kern = !!plan.kern_mask;
|
||||
plan.has_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
|
||||
}
|
||||
|
||||
private:
|
||||
|
98
src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
vendored
98
src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
vendored
@ -37,6 +37,7 @@
|
||||
#include "hb-ot-shape-normalize-private.hh"
|
||||
|
||||
#include "hb-ot-layout-private.hh"
|
||||
#include "hb-unicode-private.hh"
|
||||
#include "hb-set-private.hh"
|
||||
|
||||
|
||||
@ -226,8 +227,9 @@ static void
|
||||
hb_set_unicode_props (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
_hb_glyph_info_set_unicode_props (&buffer->info[i], buffer->unicode);
|
||||
_hb_glyph_info_set_unicode_props (&info[i], buffer->unicode);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -238,11 +240,11 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
|
||||
HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
|
||||
return;
|
||||
|
||||
if (!font->has_glyph (0x25CC))
|
||||
if (!font->has_glyph (0x25CCu))
|
||||
return;
|
||||
|
||||
hb_glyph_info_t dottedcircle;
|
||||
dottedcircle.codepoint = 0x25CC;
|
||||
dottedcircle.codepoint = 0x25CCu;
|
||||
_hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode);
|
||||
|
||||
buffer->clear_output ();
|
||||
@ -262,8 +264,9 @@ static void
|
||||
hb_form_clusters (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 1; i < count; i++)
|
||||
if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[i])))
|
||||
if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))
|
||||
buffer->merge_clusters (i - 1, i + 1);
|
||||
}
|
||||
|
||||
@ -321,7 +324,7 @@ hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (info[i].codepoint == 0x2044) /* FRACTION SLASH */
|
||||
if (info[i].codepoint == 0x2044u) /* FRACTION SLASH */
|
||||
{
|
||||
unsigned int start = i, end = i + 1;
|
||||
while (start &&
|
||||
@ -381,8 +384,9 @@ hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
|
||||
{
|
||||
/* Normalization process sets up glyph_index(), we just copy it. */
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
buffer->info[i].codepoint = buffer->info[i].glyph_index();
|
||||
info[i].codepoint = info[i].glyph_index();
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -391,11 +395,24 @@ hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
|
||||
unsigned int count = c->buffer->len;
|
||||
hb_glyph_info_t *info = c->buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
_hb_glyph_info_set_glyph_props (&info[i],
|
||||
_hb_glyph_info_get_general_category (&info[i])
|
||||
== HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ?
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_MARK :
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
|
||||
{
|
||||
hb_ot_layout_glyph_class_mask_t klass;
|
||||
|
||||
/* Never mark default-ignorables as marks.
|
||||
* They won't get in the way of lookups anyway,
|
||||
* but having them as mark will cause them to be skipped
|
||||
* over if the lookup-flag says so, but at least for the
|
||||
* Mongolian variation selectors, looks like Uniscribe
|
||||
* marks them as non-mark. Some Mongolian fonts without
|
||||
* GDEF rely on this. Another notable character that
|
||||
* this applies to is COMBINING GRAPHEME JOINER. */
|
||||
klass = (_hb_glyph_info_get_general_category (&info[i]) !=
|
||||
HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
|
||||
_hb_glyph_info_is_default_ignorable (&info[i])) ?
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_MARK;
|
||||
_hb_glyph_info_set_glyph_props (&info[i], klass);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -452,26 +469,44 @@ hb_ot_substitute (hb_ot_shape_context_t *c)
|
||||
/* Position */
|
||||
|
||||
static inline void
|
||||
zero_mark_widths_by_unicode (hb_buffer_t *buffer)
|
||||
adjust_mark_offsets (hb_glyph_position_t *pos)
|
||||
{
|
||||
pos->x_offset -= pos->x_advance;
|
||||
pos->y_offset -= pos->y_advance;
|
||||
}
|
||||
|
||||
static inline void
|
||||
zero_mark_width (hb_glyph_position_t *pos)
|
||||
{
|
||||
pos->x_advance = 0;
|
||||
pos->y_advance = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
zero_mark_widths_by_unicode (hb_buffer_t *buffer, bool adjust_offsets)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
|
||||
if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
|
||||
{
|
||||
buffer->pos[i].x_advance = 0;
|
||||
buffer->pos[i].y_advance = 0;
|
||||
if (adjust_offsets)
|
||||
adjust_mark_offsets (&buffer->pos[i]);
|
||||
zero_mark_width (&buffer->pos[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
zero_mark_widths_by_gdef (hb_buffer_t *buffer)
|
||||
zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (_hb_glyph_info_is_mark (&buffer->info[i]))
|
||||
if (_hb_glyph_info_is_mark (&info[i]))
|
||||
{
|
||||
buffer->pos[i].x_advance = 0;
|
||||
buffer->pos[i].y_advance = 0;
|
||||
if (adjust_offsets)
|
||||
adjust_mark_offsets (&buffer->pos[i]);
|
||||
zero_mark_width (&buffer->pos[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -501,16 +536,28 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
|
||||
{
|
||||
bool ret = false;
|
||||
unsigned int count = c->buffer->len;
|
||||
bool has_positioning = hb_ot_layout_has_positioning (c->face);
|
||||
/* If the font has no GPOS, AND, no fallback positioning will
|
||||
* happen, AND, direction is forward, then when zeroing mark
|
||||
* widths, we shift the mark with it, such that the mark
|
||||
* is positioned hanging over the previous glyph. When
|
||||
* direction is backward we don't shift and it will end up
|
||||
* hanging over the next glyph after the final reordering.
|
||||
* If fallback positinoing happens or GPOS is present, we don't
|
||||
* care.
|
||||
*/
|
||||
bool adjust_offsets_when_zeroing = !(has_positioning || c->plan->shaper->fallback_position ||
|
||||
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction));
|
||||
|
||||
switch (c->plan->shaper->zero_width_marks)
|
||||
{
|
||||
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
|
||||
zero_mark_widths_by_gdef (c->buffer);
|
||||
zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
|
||||
break;
|
||||
|
||||
/* Not currently used for any shaper:
|
||||
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY:
|
||||
zero_mark_widths_by_unicode (c->buffer);
|
||||
zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing);
|
||||
break;
|
||||
*/
|
||||
|
||||
@ -521,7 +568,7 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
|
||||
break;
|
||||
}
|
||||
|
||||
if (hb_ot_layout_has_positioning (c->face))
|
||||
if (has_positioning)
|
||||
{
|
||||
hb_glyph_info_t *info = c->buffer->info;
|
||||
hb_glyph_position_t *pos = c->buffer->pos;
|
||||
@ -550,11 +597,11 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
|
||||
switch (c->plan->shaper->zero_width_marks)
|
||||
{
|
||||
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE:
|
||||
zero_mark_widths_by_unicode (c->buffer);
|
||||
zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing);
|
||||
break;
|
||||
|
||||
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
|
||||
zero_mark_widths_by_gdef (c->buffer);
|
||||
zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -731,8 +778,9 @@ hb_ot_shape_glyphs_closure (hb_font_t *font,
|
||||
bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_DIRECTION_RTL;
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
add_char (font, buffer->unicode, mirror, buffer->info[i].codepoint, glyphs);
|
||||
add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs);
|
||||
|
||||
hb_set_t lookups;
|
||||
lookups.init ();
|
||||
|
9
src/3rdparty/harfbuzz-ng/src/hb-ot-shape.h
vendored
9
src/3rdparty/harfbuzz-ng/src/hb-ot-shape.h
vendored
@ -24,15 +24,15 @@
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_H_IN
|
||||
#error "Include <hb-ot.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef HB_OT_SHAPE_H
|
||||
#define HB_OT_SHAPE_H
|
||||
#define HB_OT_SHAPE_H_IN
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
#include "hb-ot-layout.h"
|
||||
#include "hb-ot-tag.h"
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
/* TODO port to shape-plan / set. */
|
||||
@ -50,5 +50,4 @@ hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#undef HB_OT_SHAPE_H_IN
|
||||
#endif /* HB_OT_SHAPE_H */
|
||||
|
52
src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
vendored
52
src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
vendored
@ -57,7 +57,7 @@ hb_ot_old_tag_from_script (hb_script_t script)
|
||||
}
|
||||
|
||||
/* Else, just change first char to lowercase and return */
|
||||
return ((hb_tag_t) script) | 0x20000000;
|
||||
return ((hb_tag_t) script) | 0x20000000u;
|
||||
}
|
||||
|
||||
static hb_script_t
|
||||
@ -70,13 +70,13 @@ hb_ot_old_tag_to_script (hb_tag_t tag)
|
||||
|
||||
/* Any spaces at the end of the tag are replaced by repeating the last
|
||||
* letter. Eg 'nko ' -> 'Nkoo' */
|
||||
if (unlikely ((tag & 0x0000FF00) == 0x00002000))
|
||||
tag |= (tag >> 8) & 0x0000FF00; /* Copy second letter to third */
|
||||
if (unlikely ((tag & 0x000000FF) == 0x00000020))
|
||||
tag |= (tag >> 8) & 0x000000FF; /* Copy third letter to fourth */
|
||||
if (unlikely ((tag & 0x0000FF00u) == 0x00002000u))
|
||||
tag |= (tag >> 8) & 0x0000FF00u; /* Copy second letter to third */
|
||||
if (unlikely ((tag & 0x000000FFu) == 0x00000020u))
|
||||
tag |= (tag >> 8) & 0x000000FFu; /* Copy third letter to fourth */
|
||||
|
||||
/* Change first char to uppercase and return */
|
||||
return (hb_script_t) (tag & ~0x20000000);
|
||||
return (hb_script_t) (tag & ~0x20000000u);
|
||||
}
|
||||
|
||||
static hb_tag_t
|
||||
@ -146,7 +146,7 @@ hb_ot_tags_from_script (hb_script_t script,
|
||||
hb_script_t
|
||||
hb_ot_tag_to_script (hb_tag_t tag)
|
||||
{
|
||||
if (unlikely ((tag & 0x000000FF) == '2'))
|
||||
if (unlikely ((tag & 0x000000FFu) == '2'))
|
||||
return hb_ot_new_tag_to_script (tag);
|
||||
|
||||
return hb_ot_old_tag_to_script (tag);
|
||||
@ -156,7 +156,7 @@ hb_ot_tag_to_script (hb_tag_t tag)
|
||||
/* hb_language_t */
|
||||
|
||||
typedef struct {
|
||||
char language[6];
|
||||
char language[4];
|
||||
hb_tag_t tag;
|
||||
} LangTag;
|
||||
|
||||
@ -763,12 +763,18 @@ static const LangTag ot_languages[] = {
|
||||
/*{"??", HB_TAG('Z','H','P',' ')},*/ /* Chinese Phonetic */
|
||||
};
|
||||
|
||||
static const LangTag ot_languages_zh[] = {
|
||||
typedef struct {
|
||||
char language[8];
|
||||
hb_tag_t tag;
|
||||
} LangTagLong;
|
||||
static const LangTagLong ot_languages_zh[] = {
|
||||
{"zh-cn", HB_TAG('Z','H','S',' ')}, /* Chinese (China) */
|
||||
{"zh-hk", HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */
|
||||
{"zh-mo", HB_TAG('Z','H','T',' ')}, /* Chinese (Macao) */
|
||||
{"zh-sg", HB_TAG('Z','H','S',' ')}, /* Chinese (Singapore) */
|
||||
{"zh-tw", HB_TAG('Z','H','T',' ')} /* Chinese (Taiwan) */
|
||||
{"zh-tw", HB_TAG('Z','H','T',' ')}, /* Chinese (Taiwan) */
|
||||
{"zh-hans", HB_TAG('Z','H','S',' ')}, /* Chinese (Simplified) */
|
||||
{"zh-hant", HB_TAG('Z','H','T',' ')}, /* Chinese (Traditional) */
|
||||
};
|
||||
|
||||
static int
|
||||
@ -800,7 +806,6 @@ hb_tag_t
|
||||
hb_ot_tag_from_language (hb_language_t language)
|
||||
{
|
||||
const char *lang_str, *s;
|
||||
const LangTag *lang_tag;
|
||||
|
||||
if (language == HB_LANGUAGE_INVALID)
|
||||
return HB_OT_TAG_DEFAULT_LANGUAGE;
|
||||
@ -822,11 +827,14 @@ hb_ot_tag_from_language (hb_language_t language)
|
||||
}
|
||||
|
||||
/* Find a language matching in the first component */
|
||||
{
|
||||
const LangTag *lang_tag;
|
||||
lang_tag = (LangTag *) bsearch (lang_str, ot_languages,
|
||||
ARRAY_LENGTH (ot_languages), sizeof (LangTag),
|
||||
(hb_compare_func_t) lang_compare_first_component);
|
||||
if (lang_tag)
|
||||
return lang_tag->tag;
|
||||
}
|
||||
|
||||
/* Otherwise, check the Chinese ones */
|
||||
if (0 == lang_compare_first_component (lang_str, "zh"))
|
||||
@ -835,8 +843,9 @@ hb_ot_tag_from_language (hb_language_t language)
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH (ot_languages_zh); i++)
|
||||
{
|
||||
const LangTagLong *lang_tag;
|
||||
lang_tag = &ot_languages_zh[i];
|
||||
if (lang_matches (lang_tag->language, lang_str))
|
||||
if (lang_matches (lang_str, lang_tag->language))
|
||||
return lang_tag->tag;
|
||||
}
|
||||
|
||||
@ -849,7 +858,7 @@ hb_ot_tag_from_language (hb_language_t language)
|
||||
s = lang_str + strlen (lang_str);
|
||||
if (s - lang_str == 3) {
|
||||
/* Assume it's ISO-639-3 and upper-case and use it. */
|
||||
return hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000;
|
||||
return hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000u;
|
||||
}
|
||||
|
||||
return HB_OT_TAG_DEFAULT_LANGUAGE;
|
||||
@ -868,21 +877,12 @@ hb_ot_tag_to_language (hb_tag_t tag)
|
||||
return hb_language_from_string (ot_languages[i].language, -1);
|
||||
|
||||
/* If tag starts with ZH, it's Chinese */
|
||||
if ((tag & 0xFFFF0000) == 0x5A480000) {
|
||||
if ((tag & 0xFFFF0000u) == 0x5A480000u) {
|
||||
switch (tag) {
|
||||
case HB_TAG('Z','H','H',' '): return hb_language_from_string ("zh-hk", -1); /* Hong Kong */
|
||||
default: {
|
||||
/* Encode the tag... */
|
||||
unsigned char buf[14] = "zh-x-hbot";
|
||||
buf[9] = tag >> 24;
|
||||
buf[10] = (tag >> 16) & 0xFF;
|
||||
buf[11] = (tag >> 8) & 0xFF;
|
||||
buf[12] = tag & 0xFF;
|
||||
if (buf[12] == 0x20)
|
||||
buf[12] = '\0';
|
||||
buf[13] = '\0';
|
||||
return hb_language_from_string ((char *) buf, -1);
|
||||
}
|
||||
case HB_TAG('Z','H','S',' '): return hb_language_from_string ("zh-Hans", -1); /* Simplified */
|
||||
case HB_TAG('Z','H','T',' '): return hb_language_from_string ("zh-Hant", -1); /* Traditional */
|
||||
default: break; /* Fall through */
|
||||
}
|
||||
}
|
||||
|
||||
|
1
src/3rdparty/harfbuzz-ng/src/hb-ot.h
vendored
1
src/3rdparty/harfbuzz-ng/src/hb-ot.h
vendored
@ -30,6 +30,7 @@
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
#include "hb-ot-font.h"
|
||||
#include "hb-ot-layout.h"
|
||||
#include "hb-ot-tag.h"
|
||||
#include "hb-ot-shape.h"
|
||||
|
186
src/3rdparty/harfbuzz-ng/src/hb-private.hh
vendored
186
src/3rdparty/harfbuzz-ng/src/hb-private.hh
vendored
@ -54,23 +54,77 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
/* Compiler attributes */
|
||||
|
||||
/* Essentials */
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL ((void *) 0)
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
|
||||
#define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0)
|
||||
#define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1))
|
||||
#define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0))
|
||||
#else
|
||||
#define likely(expr) (expr)
|
||||
#define unlikely(expr) (expr)
|
||||
#endif
|
||||
|
||||
#ifndef __GNUC__
|
||||
#undef __attribute__
|
||||
#define __attribute__(x)
|
||||
#endif
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
#define HB_PURE_FUNC __attribute__((pure))
|
||||
#define HB_CONST_FUNC __attribute__((const))
|
||||
#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
|
||||
#else
|
||||
#define HB_PURE_FUNC
|
||||
#define HB_CONST_FUNC
|
||||
#define HB_PRINTF_FUNC(format_idx, arg_idx)
|
||||
#endif
|
||||
#if __GNUC__ >= 4
|
||||
#define HB_UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define HB_UNUSED
|
||||
#endif
|
||||
|
||||
#ifndef HB_INTERNAL
|
||||
# ifndef __MINGW32__
|
||||
# define HB_INTERNAL __attribute__((__visibility__("hidden")))
|
||||
# else
|
||||
# define HB_INTERNAL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#undef inline
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
#ifdef __STRICT_ANSI__
|
||||
#undef inline
|
||||
#define inline __inline__
|
||||
#endif
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
#define HB_FUNC __PRETTY_FUNCTION__
|
||||
#elif defined(_MSC_VER)
|
||||
#define HB_FUNC __FUNCSIG__
|
||||
#else
|
||||
#define HB_FUNC __func__
|
||||
#endif
|
||||
|
||||
/* Void! */
|
||||
struct _hb_void_t {};
|
||||
typedef const _hb_void_t &hb_void_t;
|
||||
#define HB_VOID (* (const _hb_void_t *) NULL)
|
||||
|
||||
|
||||
/* Basics */
|
||||
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL ((void *) 0)
|
||||
#endif
|
||||
|
||||
#undef MIN
|
||||
template <typename Type>
|
||||
static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
|
||||
@ -92,7 +146,7 @@ static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
|
||||
#define HB_STMT_START do
|
||||
#define HB_STMT_END while (0)
|
||||
|
||||
#define _ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
|
||||
#define _ASSERT_STATIC1(_line, _cond) HB_UNUSED typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
|
||||
#define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond))
|
||||
#define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond))
|
||||
|
||||
@ -139,7 +193,7 @@ ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
|
||||
|
||||
/* Check _assertion in a method environment */
|
||||
#define _ASSERT_POD1(_line) \
|
||||
inline void _static_assertion_on_line_##_line (void) const \
|
||||
HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \
|
||||
{ _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
|
||||
# define _ASSERT_POD0(_line) _ASSERT_POD1 (_line)
|
||||
# define ASSERT_POD() _ASSERT_POD0 (__LINE__)
|
||||
@ -148,68 +202,10 @@ ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
|
||||
|
||||
/* Misc */
|
||||
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
|
||||
#define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0)
|
||||
#define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1))
|
||||
#define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0))
|
||||
#else
|
||||
#define likely(expr) (expr)
|
||||
#define unlikely(expr) (expr)
|
||||
#endif
|
||||
|
||||
#ifndef __GNUC__
|
||||
#undef __attribute__
|
||||
#define __attribute__(x)
|
||||
#endif
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
#define HB_PURE_FUNC __attribute__((pure))
|
||||
#define HB_CONST_FUNC __attribute__((const))
|
||||
#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
|
||||
#else
|
||||
#define HB_PURE_FUNC
|
||||
#define HB_CONST_FUNC
|
||||
#define HB_PRINTF_FUNC(format_idx, arg_idx)
|
||||
#endif
|
||||
#if __GNUC__ >= 4
|
||||
#define HB_UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define HB_UNUSED
|
||||
#endif
|
||||
|
||||
#ifndef HB_INTERNAL
|
||||
# ifndef __MINGW32__
|
||||
# define HB_INTERNAL __attribute__((__visibility__("hidden")))
|
||||
# else
|
||||
# define HB_INTERNAL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#undef inline
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
#ifdef __STRICT_ANSI__
|
||||
#undef inline
|
||||
#define inline __inline__
|
||||
#endif
|
||||
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
#define HB_FUNC __PRETTY_FUNCTION__
|
||||
#elif defined(_MSC_VER)
|
||||
#define HB_FUNC __FUNCSIG__
|
||||
#else
|
||||
#define HB_FUNC __func__
|
||||
#endif
|
||||
|
||||
/* Void! */
|
||||
struct _hb_void_t {};
|
||||
typedef const _hb_void_t &hb_void_t;
|
||||
#define HB_VOID (* (const _hb_void_t *) NULL)
|
||||
|
||||
/* Return the number of 1 bits in mask. */
|
||||
static inline HB_CONST_FUNC unsigned int
|
||||
@ -219,7 +215,7 @@ _hb_popcount32 (uint32_t mask)
|
||||
return __builtin_popcount (mask);
|
||||
#else
|
||||
/* "HACKMEM 169" */
|
||||
register uint32_t y;
|
||||
uint32_t y;
|
||||
y = (mask >> 1) &033333333333;
|
||||
y = mask - y - ((y >>1) & 033333333333);
|
||||
return (((y + (y >> 3)) & 030707070707) % 077);
|
||||
@ -233,7 +229,7 @@ _hb_bit_storage (unsigned int number)
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
|
||||
return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0;
|
||||
#else
|
||||
register unsigned int n_bits = 0;
|
||||
unsigned int n_bits = 0;
|
||||
while (number) {
|
||||
n_bits++;
|
||||
number >>= 1;
|
||||
@ -249,7 +245,7 @@ _hb_ctz (unsigned int number)
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
|
||||
return likely (number) ? __builtin_ctz (number) : 0;
|
||||
#else
|
||||
register unsigned int n_bits = 0;
|
||||
unsigned int n_bits = 0;
|
||||
if (unlikely (!number)) return 0;
|
||||
while (!(number & 1)) {
|
||||
n_bits++;
|
||||
@ -276,7 +272,7 @@ typedef int (*hb_compare_func_t) (const void *, const void *);
|
||||
|
||||
|
||||
#define HB_PREALLOCED_ARRAY_INIT {0}
|
||||
template <typename Type, unsigned int StaticSize>
|
||||
template <typename Type, unsigned int StaticSize=16>
|
||||
struct hb_prealloced_array_t
|
||||
{
|
||||
unsigned int len;
|
||||
@ -357,14 +353,14 @@ struct hb_prealloced_array_t
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline void sort (void)
|
||||
inline void qsort (void)
|
||||
{
|
||||
qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
|
||||
::qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
|
||||
}
|
||||
|
||||
inline void sort (unsigned int start, unsigned int end)
|
||||
inline void qsort (unsigned int start, unsigned int end)
|
||||
{
|
||||
qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
|
||||
::qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -387,12 +383,11 @@ struct hb_prealloced_array_t
|
||||
}
|
||||
};
|
||||
|
||||
#define HB_AUTO_ARRAY_PREALLOCED 16
|
||||
template <typename Type>
|
||||
struct hb_auto_array_t : hb_prealloced_array_t <Type, HB_AUTO_ARRAY_PREALLOCED>
|
||||
struct hb_auto_array_t : hb_prealloced_array_t <Type>
|
||||
{
|
||||
hb_auto_array_t (void) { hb_prealloced_array_t<Type, HB_AUTO_ARRAY_PREALLOCED>::init (); }
|
||||
~hb_auto_array_t (void) { hb_prealloced_array_t<Type, HB_AUTO_ARRAY_PREALLOCED>::finish (); }
|
||||
hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); }
|
||||
~hb_auto_array_t (void) { hb_prealloced_array_t<Type>::finish (); }
|
||||
};
|
||||
|
||||
|
||||
@ -725,7 +720,7 @@ static inline void _hb_warn_no_return (bool returned)
|
||||
}
|
||||
}
|
||||
template <>
|
||||
inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
|
||||
/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
|
||||
{}
|
||||
|
||||
template <int max_level, typename ret_t>
|
||||
@ -791,20 +786,23 @@ struct hb_auto_trace_t<0, ret_t> {
|
||||
|
||||
/* Misc */
|
||||
|
||||
template <typename T> class hb_assert_unsigned_t;
|
||||
template <> class hb_assert_unsigned_t<unsigned char> {};
|
||||
template <> class hb_assert_unsigned_t<unsigned short> {};
|
||||
template <> class hb_assert_unsigned_t<unsigned int> {};
|
||||
template <> class hb_assert_unsigned_t<unsigned long> {};
|
||||
|
||||
/* Pre-mature optimization:
|
||||
* Checks for lo <= u <= hi but with an optimization if lo and hi
|
||||
* are only different in a contiguous set of lower-most bits.
|
||||
*/
|
||||
template <typename T> static inline bool
|
||||
hb_in_range (T u, T lo, T hi)
|
||||
{
|
||||
if ( ((lo^hi) & lo) == 0 &&
|
||||
((lo^hi) & hi) == (lo^hi) &&
|
||||
((lo^hi) & ((lo^hi) + 1)) == 0 )
|
||||
return (u & ~(lo^hi)) == lo;
|
||||
else
|
||||
return lo <= u && u <= hi;
|
||||
/* The sizeof() is here to force template instantiation.
|
||||
* I'm sure there are better ways to do this but can't think of
|
||||
* one right now. Declaring a variable won't work as HB_UNUSED
|
||||
* is unsable on some platforms and unused types are less likely
|
||||
* to generate a warning than unused variables. */
|
||||
ASSERT_STATIC (sizeof (hb_assert_unsigned_t<T>) >= 0);
|
||||
|
||||
return (u - lo) <= (hi - lo);
|
||||
}
|
||||
|
||||
template <typename T> static inline bool
|
||||
|
@ -104,8 +104,6 @@ hb_shape_plan_create (hb_face_t *face,
|
||||
unsigned int num_user_features,
|
||||
const char * const *shaper_list)
|
||||
{
|
||||
assert (props->direction != HB_DIRECTION_INVALID);
|
||||
|
||||
hb_shape_plan_t *shape_plan;
|
||||
hb_feature_t *features = NULL;
|
||||
|
||||
@ -120,6 +118,8 @@ hb_shape_plan_create (hb_face_t *face,
|
||||
return hb_shape_plan_get_empty ();
|
||||
}
|
||||
|
||||
assert (props->direction != HB_DIRECTION_INVALID);
|
||||
|
||||
hb_face_make_immutable (face);
|
||||
shape_plan->default_shaper_list = shaper_list == NULL;
|
||||
shape_plan->face_unsafe = face;
|
||||
|
12
src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh
vendored
12
src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh
vendored
@ -34,25 +34,21 @@
|
||||
/* Only picks up fonts that have a "Silf" table. */
|
||||
HB_SHAPER_IMPLEMENT (graphite2)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CORETEXT
|
||||
/* Only picks up fonts that have a "mort" or "morx" table. */
|
||||
HB_SHAPER_IMPLEMENT (coretext)
|
||||
HB_SHAPER_IMPLEMENT (coretext_aat)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OT
|
||||
HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HB_OLD
|
||||
HB_SHAPER_IMPLEMENT (old)
|
||||
#endif
|
||||
#ifdef HAVE_ICU_LE
|
||||
HB_SHAPER_IMPLEMENT (icu_le)
|
||||
#endif
|
||||
#ifdef HAVE_UNISCRIBE
|
||||
HB_SHAPER_IMPLEMENT (uniscribe)
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
HB_SHAPER_IMPLEMENT (coretext)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FALLBACK
|
||||
HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */
|
||||
|
111
src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh
vendored
111
src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh
vendored
@ -102,72 +102,70 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
inline unsigned int
|
||||
modified_combining_class (hb_codepoint_t unicode)
|
||||
{
|
||||
/* XXX This hack belongs to the Myanmar shaper. */
|
||||
if (unlikely (unicode == 0x1037)) unicode = 0x103A;
|
||||
if (unlikely (unicode == 0x1037u)) unicode = 0x103Au;
|
||||
|
||||
/* XXX This hack belongs to the SEA shaper (for Tai Tham):
|
||||
* Reorder SAKOT to ensure it comes after any tone marks. */
|
||||
if (unlikely (unicode == 0x1A60)) return 254;
|
||||
if (unlikely (unicode == 0x1A60u)) return 254;
|
||||
|
||||
/* XXX This hack belongs to the Tibetan shaper:
|
||||
* Reorder PADMA to ensure it comes after any vowel marks. */
|
||||
if (unlikely (unicode == 0x0FC6u)) return 254;
|
||||
|
||||
return _hb_modified_combining_class[combining_class (unicode)];
|
||||
}
|
||||
|
||||
inline hb_bool_t
|
||||
static inline hb_bool_t
|
||||
is_variation_selector (hb_codepoint_t unicode)
|
||||
{
|
||||
return unlikely (hb_in_ranges<hb_codepoint_t> (unicode,
|
||||
0x180B, 0x180D, /* MONGOLIAN FREE VARIATION SELECTOR ONE..THREE */
|
||||
0xFE00, 0xFE0F, /* VARIATION SELECTOR-1..16 */
|
||||
0xE0100, 0xE01EF)); /* VARIATION SELECTOR-17..256 */
|
||||
/* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the
|
||||
* Arabic shaper. No need to match them here. */
|
||||
return unlikely (hb_in_ranges (unicode,
|
||||
0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */
|
||||
0xE0100u, 0xE01EFu)); /* VARIATION SELECTOR-17..256 */
|
||||
}
|
||||
|
||||
/* Default_Ignorable codepoints:
|
||||
*
|
||||
* Note that as of Oct 2012 (Unicode 6.2), U+180E MONGOLIAN VOWEL SEPARATOR
|
||||
* is NOT Default_Ignorable, but it really behaves in a way that it should
|
||||
* be. That has been reported to the Unicode Technical Committee for
|
||||
* consideration. As such, we include it here, since Uniscribe removes it.
|
||||
* It *is* in Unicode 6.3 however. U+061C ARABIC LETTER MARK from Unicode
|
||||
* 6.3 is also added manually. The new Unicode 6.3 bidi formatting
|
||||
* characters are encoded in a block that was Default_Ignorable already.
|
||||
*
|
||||
* Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable,
|
||||
* we do NOT want to hide them, as the way Uniscribe has implemented them
|
||||
* is with regular spacing glyphs, and that's the way fonts are made to work.
|
||||
* As such, we make exceptions for those four.
|
||||
*
|
||||
* Gathered from:
|
||||
* http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:DI:]&abb=on&ucd=on&esc=on
|
||||
*
|
||||
* Last updated to the page with the following versions:
|
||||
* Version 3.6; ICU version: 50.0.1.0; Unicode version: 6.1.0.0
|
||||
*
|
||||
* 4,167 Code Points
|
||||
*
|
||||
* [\u00AD\u034F\u115F\u1160\u17B4\u17B5\u180B-\u180D\u200B-\u200F\u202A-\u202E\u2060-\u206F\u3164\uFE00-\uFE0F\uFEFF\uFFA0\uFFF0-\uFFF8\U0001D173-\U0001D17A\U000E0000-\U000E0FFF]
|
||||
*
|
||||
* 00AD ;SOFT HYPHEN
|
||||
* 034F ;COMBINING GRAPHEME JOINER
|
||||
* #115F ;HANGUL CHOSEONG FILLER
|
||||
* #1160 ;HANGUL JUNGSEONG FILLER
|
||||
* 17B4 ;KHMER VOWEL INHERENT AQ
|
||||
* 17B5 ;KHMER VOWEL INHERENT AA
|
||||
* 180B..180D ;MONGOLIAN FREE VARIATION SELECTOR THREE
|
||||
* 200B..200F ;RIGHT-TO-LEFT MARK
|
||||
* 202A..202E ;RIGHT-TO-LEFT OVERRIDE
|
||||
* 2060..206F ;NOMINAL DIGIT SHAPES
|
||||
* #3164 ;HANGUL FILLER
|
||||
* FE00..FE0F ;VARIATION SELECTOR-16
|
||||
* FEFF ;ZERO WIDTH NO-BREAK SPACE
|
||||
* #FFA0 ;HALFWIDTH HANGUL FILLER
|
||||
* FFF0..FFF8 ;<unassigned-FFF8>
|
||||
* 1D173..1D17A ;MUSICAL SYMBOL END PHRASE
|
||||
* E0000..E0FFF ;<unassigned-E0FFF>
|
||||
* Unicode 7.0:
|
||||
* $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
|
||||
* 00AD # Cf SOFT HYPHEN
|
||||
* 034F # Mn COMBINING GRAPHEME JOINER
|
||||
* 061C # Cf ARABIC LETTER MARK
|
||||
* 115F..1160 # Lo [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
|
||||
* 17B4..17B5 # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
|
||||
* 180B..180D # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
|
||||
* 180E # Cf MONGOLIAN VOWEL SEPARATOR
|
||||
* 200B..200F # Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
|
||||
* 202A..202E # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
|
||||
* 2060..2064 # Cf [5] WORD JOINER..INVISIBLE PLUS
|
||||
* 2065 # Cn <reserved-2065>
|
||||
* 2066..206F # Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
|
||||
* 3164 # Lo HANGUL FILLER
|
||||
* FE00..FE0F # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
|
||||
* FEFF # Cf ZERO WIDTH NO-BREAK SPACE
|
||||
* FFA0 # Lo HALFWIDTH HANGUL FILLER
|
||||
* FFF0..FFF8 # Cn [9] <reserved-FFF0>..<reserved-FFF8>
|
||||
* 1BCA0..1BCA3 # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
|
||||
* 1D173..1D17A # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
|
||||
* E0000 # Cn <reserved-E0000>
|
||||
* E0001 # Cf LANGUAGE TAG
|
||||
* E0002..E001F # Cn [30] <reserved-E0002>..<reserved-E001F>
|
||||
* E0020..E007F # Cf [96] TAG SPACE..CANCEL TAG
|
||||
* E0080..E00FF # Cn [128] <reserved-E0080>..<reserved-E00FF>
|
||||
* E0100..E01EF # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
|
||||
* E01F0..E0FFF # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
|
||||
*/
|
||||
inline hb_bool_t
|
||||
static inline hb_bool_t
|
||||
is_default_ignorable (hb_codepoint_t ch)
|
||||
{
|
||||
hb_codepoint_t plane = ch >> 16;
|
||||
@ -176,16 +174,16 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
||||
/* BMP */
|
||||
hb_codepoint_t page = ch >> 8;
|
||||
switch (page) {
|
||||
case 0x00: return unlikely (ch == 0x00AD);
|
||||
case 0x03: return unlikely (ch == 0x034F);
|
||||
case 0x06: return unlikely (ch == 0x061C);
|
||||
case 0x17: return hb_in_range<hb_codepoint_t> (ch, 0x17B4, 0x17B5);
|
||||
case 0x18: return hb_in_range<hb_codepoint_t> (ch, 0x180B, 0x180E);
|
||||
case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200B, 0x200F,
|
||||
0x202A, 0x202E,
|
||||
0x2060, 0x206F);
|
||||
case 0xFE: return hb_in_range<hb_codepoint_t> (ch, 0xFE00, 0xFE0F) || ch == 0xFEFF;
|
||||
case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0, 0xFFF8);
|
||||
case 0x00: return unlikely (ch == 0x00ADu);
|
||||
case 0x03: return unlikely (ch == 0x034Fu);
|
||||
case 0x06: return unlikely (ch == 0x061Cu);
|
||||
case 0x17: return hb_in_range (ch, 0x17B4u, 0x17B5u);
|
||||
case 0x18: return hb_in_range (ch, 0x180Bu, 0x180Eu);
|
||||
case 0x20: return hb_in_ranges (ch, 0x200Bu, 0x200Fu,
|
||||
0x202Au, 0x202Eu,
|
||||
0x2060u, 0x206Fu);
|
||||
case 0xFE: return hb_in_range (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu;
|
||||
case 0xFF: return hb_in_range (ch, 0xFFF0u, 0xFFF8u);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
@ -193,8 +191,9 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
||||
{
|
||||
/* Other planes */
|
||||
switch (plane) {
|
||||
case 0x01: return hb_in_range<hb_codepoint_t> (ch, 0x0001D173, 0x0001D17A);
|
||||
case 0x0E: return hb_in_range<hb_codepoint_t> (ch, 0x000E0000, 0x000E0FFF);
|
||||
case 0x01: return hb_in_ranges (ch, 0x1BCA0u, 0x1BCA3u,
|
||||
0x1D173u, 0x1D17Au);
|
||||
case 0x0E: return hb_in_range (ch, 0xE0000u, 0xE0FFFu);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
11
src/3rdparty/harfbuzz-ng/src/hb-unicode.cc
vendored
11
src/3rdparty/harfbuzz-ng/src/hb-unicode.cc
vendored
@ -133,7 +133,7 @@ hb_unicode_funcs_get_default (void)
|
||||
|
||||
#ifdef HAVE_GLIB
|
||||
HB_UNICODE_FUNCS_IMPLEMENT(glib)
|
||||
#elif 0 && defined(HAVE_ICU)
|
||||
#elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
|
||||
HB_UNICODE_FUNCS_IMPLEMENT(icu)
|
||||
#elif defined(HAVE_UCDN)
|
||||
HB_UNICODE_FUNCS_IMPLEMENT(ucdn)
|
||||
@ -146,8 +146,13 @@ hb_unicode_funcs_get_default (void)
|
||||
}
|
||||
|
||||
#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
|
||||
#pragma message("Could not find any Unicode functions implementation, you have to provide your own.")
|
||||
#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS.")
|
||||
#ifdef _MSC_VER
|
||||
#pragma message("Could not find any Unicode functions implementation, you have to provide your own")
|
||||
#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS")
|
||||
#else
|
||||
#warning "Could not find any Unicode functions implementation, you have to provide your own"
|
||||
#warning "To suppress this warning, define HB_NO_UNICODE_FUNCS"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
231
src/3rdparty/harfbuzz-ng/src/hb-utf-private.hh
vendored
231
src/3rdparty/harfbuzz-ng/src/hb-utf-private.hh
vendored
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2011,2012 Google, Inc.
|
||||
* Copyright © 2011,2012,2014 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
@ -29,176 +29,221 @@
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
template <typename T, bool validate=true> struct hb_utf_t;
|
||||
|
||||
|
||||
/* UTF-8 */
|
||||
|
||||
#define HB_UTF8_COMPUTE(Char, Mask, Len) \
|
||||
if (Char < 128) { Len = 1; Mask = 0x7f; } \
|
||||
else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \
|
||||
else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \
|
||||
else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \
|
||||
else Len = 0;
|
||||
|
||||
template <>
|
||||
struct hb_utf_t<uint8_t, true>
|
||||
{
|
||||
static inline const uint8_t *
|
||||
hb_utf_next (const uint8_t *text,
|
||||
next (const uint8_t *text,
|
||||
const uint8_t *end,
|
||||
hb_codepoint_t *unicode)
|
||||
hb_codepoint_t *unicode,
|
||||
hb_codepoint_t replacement)
|
||||
{
|
||||
hb_codepoint_t c = *text, mask;
|
||||
unsigned int len;
|
||||
/* Written to only accept well-formed sequences.
|
||||
* Based on ideas from ICU's U8_NEXT.
|
||||
* Generates one "replacement" for each ill-formed byte. */
|
||||
|
||||
/* TODO check for overlong sequences? */
|
||||
hb_codepoint_t c = *text++;
|
||||
|
||||
HB_UTF8_COMPUTE (c, mask, len);
|
||||
if (unlikely (!len || (unsigned int) (end - text) < len)) {
|
||||
*unicode = -1;
|
||||
return text + 1;
|
||||
} else {
|
||||
hb_codepoint_t result;
|
||||
unsigned int i;
|
||||
result = c & mask;
|
||||
for (i = 1; i < len; i++)
|
||||
if (c > 0x7Fu)
|
||||
{
|
||||
if (unlikely ((text[i] & 0xc0) != 0x80))
|
||||
if (hb_in_range (c, 0xC2u, 0xDFu)) /* Two-byte */
|
||||
{
|
||||
*unicode = -1;
|
||||
return text + 1;
|
||||
unsigned int t1;
|
||||
if (likely (text < end &&
|
||||
(t1 = text[0] - 0x80u) <= 0x3Fu))
|
||||
{
|
||||
c = ((c&0x1Fu)<<6) | t1;
|
||||
text++;
|
||||
}
|
||||
result <<= 6;
|
||||
result |= (text[i] & 0x3f);
|
||||
else
|
||||
goto error;
|
||||
}
|
||||
*unicode = result;
|
||||
return text + len;
|
||||
else if (hb_in_range (c, 0xE0u, 0xEFu)) /* Three-byte */
|
||||
{
|
||||
unsigned int t1, t2;
|
||||
if (likely (1 < end - text &&
|
||||
(t1 = text[0] - 0x80u) <= 0x3Fu &&
|
||||
(t2 = text[1] - 0x80u) <= 0x3Fu))
|
||||
{
|
||||
c = ((c&0xFu)<<12) | (t1<<6) | t2;
|
||||
if (unlikely (c < 0x0800u || hb_in_range (c, 0xD800u, 0xDFFFu)))
|
||||
goto error;
|
||||
text += 2;
|
||||
}
|
||||
else
|
||||
goto error;
|
||||
}
|
||||
else if (hb_in_range (c, 0xF0u, 0xF4u)) /* Four-byte */
|
||||
{
|
||||
unsigned int t1, t2, t3;
|
||||
if (likely (2 < end - text &&
|
||||
(t1 = text[0] - 0x80u) <= 0x3Fu &&
|
||||
(t2 = text[1] - 0x80u) <= 0x3Fu &&
|
||||
(t3 = text[2] - 0x80u) <= 0x3Fu))
|
||||
{
|
||||
c = ((c&0x7u)<<18) | (t1<<12) | (t2<<6) | t3;
|
||||
if (unlikely (!hb_in_range (c, 0x10000u, 0x10FFFFu)))
|
||||
goto error;
|
||||
text += 3;
|
||||
}
|
||||
else
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
goto error;
|
||||
}
|
||||
|
||||
*unicode = c;
|
||||
return text;
|
||||
|
||||
error:
|
||||
*unicode = replacement;
|
||||
return text;
|
||||
}
|
||||
|
||||
static inline const uint8_t *
|
||||
hb_utf_prev (const uint8_t *text,
|
||||
prev (const uint8_t *text,
|
||||
const uint8_t *start,
|
||||
hb_codepoint_t *unicode)
|
||||
hb_codepoint_t *unicode,
|
||||
hb_codepoint_t replacement)
|
||||
{
|
||||
const uint8_t *end = text--;
|
||||
while (start < text && (*text & 0xc0) == 0x80 && end - text < 4)
|
||||
text--;
|
||||
|
||||
hb_codepoint_t c = *text, mask;
|
||||
unsigned int len;
|
||||
|
||||
/* TODO check for overlong sequences? */
|
||||
|
||||
HB_UTF8_COMPUTE (c, mask, len);
|
||||
if (unlikely (!len || (unsigned int) (end - text) != len)) {
|
||||
*unicode = -1;
|
||||
return end - 1;
|
||||
} else {
|
||||
hb_codepoint_t result;
|
||||
unsigned int i;
|
||||
result = c & mask;
|
||||
for (i = 1; i < len; i++)
|
||||
{
|
||||
result <<= 6;
|
||||
result |= (text[i] & 0x3f);
|
||||
}
|
||||
*unicode = result;
|
||||
if (likely (next (text, end, unicode, replacement) == end))
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
*unicode = replacement;
|
||||
return end - 1;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
hb_utf_strlen (const uint8_t *text)
|
||||
strlen (const uint8_t *text)
|
||||
{
|
||||
return strlen ((const char *) text);
|
||||
return ::strlen ((const char *) text);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* UTF-16 */
|
||||
|
||||
template <>
|
||||
struct hb_utf_t<uint16_t, true>
|
||||
{
|
||||
static inline const uint16_t *
|
||||
hb_utf_next (const uint16_t *text,
|
||||
next (const uint16_t *text,
|
||||
const uint16_t *end,
|
||||
hb_codepoint_t *unicode)
|
||||
hb_codepoint_t *unicode,
|
||||
hb_codepoint_t replacement)
|
||||
{
|
||||
hb_codepoint_t c = *text++;
|
||||
|
||||
if (unlikely (hb_in_range<hb_codepoint_t> (c, 0xd800, 0xdbff)))
|
||||
if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu)))
|
||||
{
|
||||
/* high surrogate */
|
||||
hb_codepoint_t l;
|
||||
if (text < end && ((l = *text), likely (hb_in_range<hb_codepoint_t> (l, 0xdc00, 0xdfff))))
|
||||
{
|
||||
/* low surrogate */
|
||||
*unicode = (c << 10) + l - ((0xd800 << 10) - 0x10000 + 0xdc00);
|
||||
text++;
|
||||
} else
|
||||
*unicode = -1;
|
||||
} else
|
||||
*unicode = c;
|
||||
return text;
|
||||
}
|
||||
|
||||
if (likely (hb_in_range (c, 0xD800u, 0xDBFFu)))
|
||||
{
|
||||
/* High-surrogate in c */
|
||||
hb_codepoint_t l;
|
||||
if (text < end && ((l = *text), likely (hb_in_range (l, 0xDC00u, 0xDFFFu))))
|
||||
{
|
||||
/* Low-surrogate in l */
|
||||
*unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u);
|
||||
text++;
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
/* Lonely / out-of-order surrogate. */
|
||||
*unicode = replacement;
|
||||
return text;
|
||||
}
|
||||
|
||||
static inline const uint16_t *
|
||||
hb_utf_prev (const uint16_t *text,
|
||||
prev (const uint16_t *text,
|
||||
const uint16_t *start,
|
||||
hb_codepoint_t *unicode)
|
||||
hb_codepoint_t *unicode,
|
||||
hb_codepoint_t replacement)
|
||||
{
|
||||
hb_codepoint_t c = *--text;
|
||||
const uint16_t *end = text--;
|
||||
hb_codepoint_t c = *text;
|
||||
|
||||
if (unlikely (hb_in_range<hb_codepoint_t> (c, 0xdc00, 0xdfff)))
|
||||
if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu)))
|
||||
{
|
||||
/* low surrogate */
|
||||
hb_codepoint_t h;
|
||||
if (start < text && ((h = *(text - 1)), likely (hb_in_range<hb_codepoint_t> (h, 0xd800, 0xdbff))))
|
||||
{
|
||||
/* high surrogate */
|
||||
*unicode = (h << 10) + c - ((0xd800 << 10) - 0x10000 + 0xdc00);
|
||||
text--;
|
||||
} else
|
||||
*unicode = -1;
|
||||
} else
|
||||
*unicode = c;
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
if (likely (start < text && hb_in_range (c, 0xDC00u, 0xDFFFu)))
|
||||
text--;
|
||||
|
||||
if (likely (next (text, end, unicode, replacement) == end))
|
||||
return text;
|
||||
|
||||
*unicode = replacement;
|
||||
return end - 1;
|
||||
}
|
||||
|
||||
|
||||
static inline unsigned int
|
||||
hb_utf_strlen (const uint16_t *text)
|
||||
strlen (const uint16_t *text)
|
||||
{
|
||||
unsigned int l = 0;
|
||||
while (*text++) l++;
|
||||
return l;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* UTF-32 */
|
||||
|
||||
static inline const uint32_t *
|
||||
hb_utf_next (const uint32_t *text,
|
||||
const uint32_t *end HB_UNUSED,
|
||||
hb_codepoint_t *unicode)
|
||||
template <bool validate>
|
||||
struct hb_utf_t<uint32_t, validate>
|
||||
{
|
||||
*unicode = *text++;
|
||||
static inline const uint32_t *
|
||||
next (const uint32_t *text,
|
||||
const uint32_t *end HB_UNUSED,
|
||||
hb_codepoint_t *unicode,
|
||||
hb_codepoint_t replacement)
|
||||
{
|
||||
hb_codepoint_t c = *text++;
|
||||
if (validate && unlikely (c > 0x10FFFFu || hb_in_range (c, 0xD800u, 0xDFFFu)))
|
||||
goto error;
|
||||
*unicode = c;
|
||||
return text;
|
||||
|
||||
error:
|
||||
*unicode = replacement;
|
||||
return text;
|
||||
}
|
||||
|
||||
static inline const uint32_t *
|
||||
hb_utf_prev (const uint32_t *text,
|
||||
prev (const uint32_t *text,
|
||||
const uint32_t *start HB_UNUSED,
|
||||
hb_codepoint_t *unicode)
|
||||
hb_codepoint_t *unicode,
|
||||
hb_codepoint_t replacement)
|
||||
{
|
||||
*unicode = *--text;
|
||||
return text;
|
||||
next (text - 1, text, unicode, replacement);
|
||||
return text - 1;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
hb_utf_strlen (const uint32_t *text)
|
||||
strlen (const uint32_t *text)
|
||||
{
|
||||
unsigned int l = 0;
|
||||
while (*text++) l++;
|
||||
return l;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_UTF_PRIVATE_HH */
|
||||
|
10
src/3rdparty/harfbuzz-ng/src/hb-version.h
vendored
10
src/3rdparty/harfbuzz-ng/src/hb-version.h
vendored
@ -38,12 +38,12 @@ HB_BEGIN_DECLS
|
||||
|
||||
#define HB_VERSION_MAJOR 0
|
||||
#define HB_VERSION_MINOR 9
|
||||
#define HB_VERSION_MICRO 25
|
||||
#define HB_VERSION_MICRO 32
|
||||
|
||||
#define HB_VERSION_STRING "0.9.25"
|
||||
#define HB_VERSION_STRING "0.9.32"
|
||||
|
||||
#define HB_VERSION_CHECK(major,minor,micro) \
|
||||
((major)*10000+(minor)*100+(micro) >= \
|
||||
#define HB_VERSION_ATLEAST(major,minor,micro) \
|
||||
((major)*10000+(minor)*100+(micro) <= \
|
||||
HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ const char *
|
||||
hb_version_string (void);
|
||||
|
||||
hb_bool_t
|
||||
hb_version_check (unsigned int major,
|
||||
hb_version_atleast (unsigned int major,
|
||||
unsigned int minor,
|
||||
unsigned int micro);
|
||||
|
||||
|
11
src/3rdparty/harfbuzz-ng/src/hb-warning.cc
vendored
11
src/3rdparty/harfbuzz-ng/src/hb-warning.cc
vendored
@ -53,14 +53,3 @@
|
||||
#endif
|
||||
|
||||
|
||||
#include "hb-unicode-private.hh"
|
||||
|
||||
#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
|
||||
#ifdef _MSC_VER
|
||||
#pragma message("Could not find any Unicode functions implementation, you have to provide your own")
|
||||
#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS")
|
||||
#else
|
||||
#warning "Could not find any Unicode functions implementation, you have to provide your own"
|
||||
#warning "To suppress this warning, define HB_NO_UNICODE_FUNCS"
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1076,7 +1076,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
|
||||
hb_buffer_set_segment_properties(buffer, &props);
|
||||
hb_buffer_guess_segment_properties(buffer);
|
||||
|
||||
uint buffer_flags = 0; // HB_BUFFER_FLAG_DEFAULT
|
||||
uint buffer_flags = HB_BUFFER_FLAG_DEFAULT;
|
||||
// Symbol encoding used to encode various crap in the 32..255 character code range,
|
||||
// and thus might override U+00AD [SHY]; avoid hiding default ignorables
|
||||
if (actualFontEngine->symbol)
|
||||
|
Loading…
Reference in New Issue
Block a user