Update bundled HarfBuzz-NG to 0.9.38
Most important changes: * Fixes for Arabic, Hangul, Hebrew, Indic, Mandaic, Myanmar, and New Tai Lue shapers. * Fixed out-of-bounds access in Indic shaper. * Build and stability fixes, various optimizations. Change-Id: I4f0e32c017f62fe576bee41a430d3da6d571de80 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
parent
3c1e16df75
commit
3de9bc9cb1
135
src/3rdparty/harfbuzz-ng/NEWS
vendored
135
src/3rdparty/harfbuzz-ng/NEWS
vendored
@ -1,3 +1,138 @@
|
|||||||
|
Overview of changes leading to 0.9.38
|
||||||
|
Friday, January 23, 2015
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
- Fix minor out-of-bounds access in Indic shaper.
|
||||||
|
- Change New Tai Lue shaping engine from South-East Asian to default,
|
||||||
|
reflecting change in Unicode encoding model.
|
||||||
|
- Add hb-shape --font-size. Can take up to two numbers for separate
|
||||||
|
x / y size.
|
||||||
|
- Fix CoreText and FreeType scale issues with negative scales.
|
||||||
|
- Reject blobs larger than 2GB. This might break some icu-le-hb clients
|
||||||
|
that need security fixes. See:
|
||||||
|
http://www.icu-project.org/trac/ticket/11450
|
||||||
|
- Avoid accessing font tables during face destruction, in casce rogue
|
||||||
|
clients released face data already.
|
||||||
|
- Fix up gobject-introspection a bit. Python bindings kinda working.
|
||||||
|
See README.python.
|
||||||
|
- Misc fixes.
|
||||||
|
- API additions:
|
||||||
|
hb_ft_face_create_referenced()
|
||||||
|
hb_ft_font_create_referenced()
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 0.9.37
|
||||||
|
Wednesday, December 17, 2014
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
- Fix out-of-bounds access in Context lookup format 3.
|
||||||
|
- Indic: Allow ZWJ/ZWNJ before syllable modifiers.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 0.9.36
|
||||||
|
Thursday, November 20, 2014
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
- First time that three months went by without a release since
|
||||||
|
0.9.2 was released on August 10, 2012!
|
||||||
|
- Fix performance bug in hb_ot_collect_glyphs():
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1090869
|
||||||
|
- Add basic vertical-text support to hb-ot-font.
|
||||||
|
- Misc build fixes.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 0.9.35
|
||||||
|
Saturday, August 13, 2014
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
- Fix major shape-plan caching bug when more than one shaper were
|
||||||
|
provided to hb_shape_full() (as exercised by XeTeX).
|
||||||
|
http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg1246370.html
|
||||||
|
- Fix Arabic fallback shaping regression. This was broken in 0.9.32.
|
||||||
|
- Major hb-coretext fixes. That backend is complete now, including
|
||||||
|
respecing buffer direction and language, down to vertical writing.
|
||||||
|
- Build fixes for Windows CE. Should build fine now.
|
||||||
|
- Misc fixes:
|
||||||
|
Use atexit() only if it's safe to call from shared library
|
||||||
|
https://bugs.freedesktop.org/show_bug.cgi?id=82246
|
||||||
|
Mandaic had errors in its Unicode Joining_Type
|
||||||
|
https://bugs.freedesktop.org/show_bug.cgi?id=82306
|
||||||
|
- API changes:
|
||||||
|
|
||||||
|
* hb_buffer_clear_contents() does not reset buffer flags now.
|
||||||
|
|
||||||
|
After 763e5466c0a03a7c27020e1e2598e488612529a7, one doesn't
|
||||||
|
need to set flags for different pieces of text. The flags now
|
||||||
|
are something the client sets up once, depending on how it
|
||||||
|
actually uses the buffer. As such, don't clear it in
|
||||||
|
clear_contents().
|
||||||
|
|
||||||
|
I don't expect any changes to be needed to any existing client.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 0.9.34
|
||||||
|
Saturday, August 2, 2014
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
- hb_feature_from_string() now accepts CSS font-feature-settings format.
|
||||||
|
- As a result, hb-shape / hb-view --features also accept CSS-style strings.
|
||||||
|
Eg, "'liga' off" is accepted now.
|
||||||
|
- Add old-spec Myanmar shaper:
|
||||||
|
https://bugs.freedesktop.org/show_bug.cgi?id=81775
|
||||||
|
- Don't apply 'calt' in Hangul shaper.
|
||||||
|
- Fix mark advance zeroing for Hebrew shaper:
|
||||||
|
https://bugs.freedesktop.org/show_bug.cgi?id=76767
|
||||||
|
- Implement Windows-1256 custom Arabic shaping. Only built on Windows,
|
||||||
|
and requires help from get_glyph(). Used by Firefox.
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1045139
|
||||||
|
- Disable 'liga' in vertical text.
|
||||||
|
- Build fixes.
|
||||||
|
- API changes:
|
||||||
|
|
||||||
|
* Make HB_BUFFER_FLAG_BOT/EOT easier to use.
|
||||||
|
|
||||||
|
Previously, we expected users to provide BOT/EOT flags when the
|
||||||
|
text *segment* was at paragraph boundaries. This meant that for
|
||||||
|
clients that provide full paragraph to HarfBuzz (eg. Pango), they
|
||||||
|
had code like this:
|
||||||
|
|
||||||
|
hb_buffer_set_flags (hb_buffer,
|
||||||
|
(item_offset == 0 ? HB_BUFFER_FLAG_BOT : 0) |
|
||||||
|
(item_offset + item_length == paragraph_length ?
|
||||||
|
HB_BUFFER_FLAG_EOT : 0));
|
||||||
|
|
||||||
|
hb_buffer_add_utf8 (hb_buffer,
|
||||||
|
paragraph_text, paragraph_length,
|
||||||
|
item_offset, item_length);
|
||||||
|
|
||||||
|
After this change such clients can simply say:
|
||||||
|
|
||||||
|
hb_buffer_set_flags (hb_buffer,
|
||||||
|
HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT);
|
||||||
|
|
||||||
|
hb_buffer_add_utf8 (hb_buffer,
|
||||||
|
paragraph_text, paragraph_length,
|
||||||
|
item_offset, item_length);
|
||||||
|
|
||||||
|
Ie, HarfBuzz itself checks whether the segment is at the beginning/end
|
||||||
|
of the paragraph. Clients that only pass item-at-a-time to HarfBuzz
|
||||||
|
continue not setting any flags whatsoever.
|
||||||
|
|
||||||
|
Another way to put it is: if there's pre-context text in the buffer,
|
||||||
|
HarfBuzz ignores the BOT flag. If there's post-context, it ignores
|
||||||
|
EOT flag.
|
||||||
|
|
||||||
|
|
||||||
|
Overview of changes leading to 0.9.33
|
||||||
|
Tuesday, July 22, 2014
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
- Turn off ARabic 'cswh' feature that was accidentally turned on.
|
||||||
|
- Add HB_TAG_MAX_SIGNED.
|
||||||
|
- Make hb_face_make_immutable() really make face immutable!
|
||||||
|
- Windows build fixes.
|
||||||
|
|
||||||
|
|
||||||
Overview of changes leading to 0.9.32
|
Overview of changes leading to 0.9.32
|
||||||
Thursday, July 17, 2014
|
Thursday, July 17, 2014
|
||||||
=====================================
|
=====================================
|
||||||
|
3
src/3rdparty/harfbuzz-ng/README
vendored
3
src/3rdparty/harfbuzz-ng/README
vendored
@ -1,3 +1,6 @@
|
|||||||
|
[](https://travis-ci.org/behdad/harfbuzz)
|
||||||
|
[](https://coveralls.io/r/behdad/harfbuzz)
|
||||||
|
|
||||||
This is HarfBuzz, a text shaping library.
|
This is HarfBuzz, a text shaping library.
|
||||||
|
|
||||||
For bug reports, mailing list, and other information please visit:
|
For bug reports, mailing list, and other information please visit:
|
||||||
|
1
src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
vendored
1
src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
vendored
@ -8,6 +8,7 @@ CONFIG += \
|
|||||||
load(qt_helper_lib)
|
load(qt_helper_lib)
|
||||||
|
|
||||||
DEFINES += HAVE_OT HAVE_ATEXIT HB_NO_UNICODE_FUNCS HB_DISABLE_DEPRECATED
|
DEFINES += HAVE_OT HAVE_ATEXIT HB_NO_UNICODE_FUNCS HB_DISABLE_DEPRECATED
|
||||||
|
win32: DEFINES += HB_NO_WIN1256
|
||||||
|
|
||||||
INCLUDEPATH += $$PWD/include
|
INCLUDEPATH += $$PWD/include
|
||||||
|
|
||||||
|
@ -44,7 +44,6 @@
|
|||||||
|
|
||||||
#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
|
#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
/* MinGW has a convoluted history of supporting MemoryBarrier
|
/* MinGW has a convoluted history of supporting MemoryBarrier
|
||||||
|
9
src/3rdparty/harfbuzz-ng/src/hb-blob.cc
vendored
9
src/3rdparty/harfbuzz-ng/src/hb-blob.cc
vendored
@ -78,8 +78,8 @@ _hb_blob_destroy_user_data (hb_blob_t *blob)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_blob_create: (Xconstructor)
|
* hb_blob_create: (skip)
|
||||||
* @data: (array length=length) (closure user_data) (destroy destroy) (scope notified) (transfer none): Pointer to blob data.
|
* @data: Pointer to blob data.
|
||||||
* @length: Length of @data in bytes.
|
* @length: Length of @data in bytes.
|
||||||
* @mode: Memory mode for @data.
|
* @mode: Memory mode for @data.
|
||||||
* @user_data: Data parameter to pass to @destroy.
|
* @user_data: Data parameter to pass to @destroy.
|
||||||
@ -102,7 +102,10 @@ hb_blob_create (const char *data,
|
|||||||
{
|
{
|
||||||
hb_blob_t *blob;
|
hb_blob_t *blob;
|
||||||
|
|
||||||
if (!length || !(blob = hb_object_create<hb_blob_t> ())) {
|
if (!length ||
|
||||||
|
length >= 1u << 31 ||
|
||||||
|
data + length < data /* overflows */ ||
|
||||||
|
!(blob = hb_object_create<hb_blob_t> ())) {
|
||||||
if (destroy)
|
if (destroy)
|
||||||
destroy (user_data);
|
destroy (user_data);
|
||||||
return hb_blob_get_empty ();
|
return hb_blob_get_empty ();
|
||||||
|
@ -459,8 +459,8 @@ _hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer,
|
|||||||
|
|
||||||
const char *tok = NULL;
|
const char *tok = NULL;
|
||||||
int cs;
|
int cs;
|
||||||
hb_glyph_info_t info;
|
hb_glyph_info_t info = {0};
|
||||||
hb_glyph_position_t pos;
|
hb_glyph_position_t pos = {0};
|
||||||
|
|
||||||
#line 466 "hb-buffer-deserialize-json.hh"
|
#line 466 "hb-buffer-deserialize-json.hh"
|
||||||
{
|
{
|
||||||
|
@ -48,15 +48,13 @@ struct hb_buffer_t {
|
|||||||
ASSERT_POD ();
|
ASSERT_POD ();
|
||||||
|
|
||||||
/* Information about how the text in the buffer should be treated */
|
/* Information about how the text in the buffer should be treated */
|
||||||
|
|
||||||
hb_unicode_funcs_t *unicode; /* Unicode functions */
|
hb_unicode_funcs_t *unicode; /* Unicode functions */
|
||||||
hb_segment_properties_t props; /* Script, language, direction */
|
|
||||||
hb_buffer_flags_t flags; /* BOT / EOT / etc. */
|
hb_buffer_flags_t flags; /* BOT / EOT / etc. */
|
||||||
hb_codepoint_t replacement; /* U+FFFD or something else. */
|
hb_codepoint_t replacement; /* U+FFFD or something else. */
|
||||||
|
|
||||||
/* Buffer contents */
|
/* Buffer contents */
|
||||||
|
|
||||||
hb_buffer_content_type_t content_type;
|
hb_buffer_content_type_t content_type;
|
||||||
|
hb_segment_properties_t props; /* Script, language, direction */
|
||||||
|
|
||||||
bool in_error; /* Allocation failed */
|
bool in_error; /* Allocation failed */
|
||||||
bool have_output; /* Whether we have an output buffer going on */
|
bool have_output; /* Whether we have an output buffer going on */
|
||||||
@ -183,6 +181,9 @@ struct hb_buffer_t {
|
|||||||
inline bool ensure (unsigned int size)
|
inline bool ensure (unsigned int size)
|
||||||
{ return likely (!size || size < allocated) ? true : enlarge (size); }
|
{ return likely (!size || size < allocated) ? true : enlarge (size); }
|
||||||
|
|
||||||
|
inline bool ensure_inplace (unsigned int size)
|
||||||
|
{ return likely (!size || size < allocated); }
|
||||||
|
|
||||||
HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
|
HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
|
||||||
HB_INTERNAL bool shift_forward (unsigned int count);
|
HB_INTERNAL bool shift_forward (unsigned int count);
|
||||||
|
|
||||||
|
6
src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
vendored
6
src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
vendored
@ -178,6 +178,7 @@ hb_buffer_t::reset (void)
|
|||||||
|
|
||||||
hb_unicode_funcs_destroy (unicode);
|
hb_unicode_funcs_destroy (unicode);
|
||||||
unicode = hb_unicode_funcs_get_default ();
|
unicode = hb_unicode_funcs_get_default ();
|
||||||
|
flags = HB_BUFFER_FLAG_DEFAULT;
|
||||||
replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
|
replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
|
||||||
|
|
||||||
clear ();
|
clear ();
|
||||||
@ -191,7 +192,6 @@ hb_buffer_t::clear (void)
|
|||||||
|
|
||||||
hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
|
hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
|
||||||
props = default_props;
|
props = default_props;
|
||||||
flags = HB_BUFFER_FLAG_DEFAULT;
|
|
||||||
|
|
||||||
content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
|
content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
|
||||||
in_error = false;
|
in_error = false;
|
||||||
@ -702,11 +702,11 @@ hb_buffer_get_empty (void)
|
|||||||
HB_OBJECT_HEADER_STATIC,
|
HB_OBJECT_HEADER_STATIC,
|
||||||
|
|
||||||
const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
|
const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
|
||||||
HB_SEGMENT_PROPERTIES_DEFAULT,
|
|
||||||
HB_BUFFER_FLAG_DEFAULT,
|
HB_BUFFER_FLAG_DEFAULT,
|
||||||
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
|
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
|
||||||
|
|
||||||
HB_BUFFER_CONTENT_TYPE_INVALID,
|
HB_BUFFER_CONTENT_TYPE_INVALID,
|
||||||
|
HB_SEGMENT_PROPERTIES_DEFAULT,
|
||||||
true, /* in_error */
|
true, /* in_error */
|
||||||
true, /* have_output */
|
true, /* have_output */
|
||||||
true /* have_positions */
|
true /* have_positions */
|
||||||
@ -1400,7 +1400,7 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
|
|||||||
/**
|
/**
|
||||||
* hb_buffer_add_utf8:
|
* hb_buffer_add_utf8:
|
||||||
* @buffer: a buffer.
|
* @buffer: a buffer.
|
||||||
* @text: (array length=text_length):
|
* @text: (array length=text_length) (element-type uint8_t):
|
||||||
* @text_length:
|
* @text_length:
|
||||||
* @item_offset:
|
* @item_offset:
|
||||||
* @item_length:
|
* @item_length:
|
||||||
|
12
src/3rdparty/harfbuzz-ng/src/hb-common.cc
vendored
12
src/3rdparty/harfbuzz-ng/src/hb-common.cc
vendored
@ -33,10 +33,6 @@
|
|||||||
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
|
||||||
#ifdef _WIN32_WCE
|
|
||||||
#define strdup(x) _strdup(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* hb_options_t */
|
/* hb_options_t */
|
||||||
|
|
||||||
@ -238,8 +234,8 @@ struct hb_language_item_t {
|
|||||||
|
|
||||||
static hb_language_item_t *langs;
|
static hb_language_item_t *langs;
|
||||||
|
|
||||||
#ifdef HAVE_ATEXIT
|
#ifdef HB_USE_ATEXIT
|
||||||
static inline
|
static
|
||||||
void free_langs (void)
|
void free_langs (void)
|
||||||
{
|
{
|
||||||
while (langs) {
|
while (langs) {
|
||||||
@ -273,7 +269,7 @@ retry:
|
|||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_ATEXIT
|
#ifdef HB_USE_ATEXIT
|
||||||
if (!first_lang)
|
if (!first_lang)
|
||||||
atexit (free_langs); /* First person registers atexit() callback. */
|
atexit (free_langs); /* First person registers atexit() callback. */
|
||||||
#endif
|
#endif
|
||||||
@ -349,7 +345,7 @@ hb_language_get_default (void)
|
|||||||
hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
|
hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
|
||||||
if (unlikely (language == HB_LANGUAGE_INVALID)) {
|
if (unlikely (language == HB_LANGUAGE_INVALID)) {
|
||||||
language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1);
|
language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1);
|
||||||
hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
|
(void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
|
||||||
}
|
}
|
||||||
|
|
||||||
return default_language;
|
return default_language;
|
||||||
|
22
src/3rdparty/harfbuzz-ng/src/hb-common.h
vendored
22
src/3rdparty/harfbuzz-ng/src/hb-common.h
vendored
@ -95,6 +95,7 @@ typedef uint32_t hb_tag_t;
|
|||||||
|
|
||||||
#define HB_TAG_NONE HB_TAG(0,0,0,0)
|
#define HB_TAG_NONE HB_TAG(0,0,0,0)
|
||||||
#define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff)
|
#define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff)
|
||||||
|
#define HB_TAG_MAX_SIGNED HB_TAG(0x7f,0xff,0xff,0xff)
|
||||||
|
|
||||||
/* len=-1 means str is NUL-terminated. */
|
/* len=-1 means str is NUL-terminated. */
|
||||||
hb_tag_t
|
hb_tag_t
|
||||||
@ -122,12 +123,13 @@ hb_direction_from_string (const char *str, int len);
|
|||||||
const char *
|
const char *
|
||||||
hb_direction_to_string (hb_direction_t direction);
|
hb_direction_to_string (hb_direction_t direction);
|
||||||
|
|
||||||
|
#define HB_DIRECTION_IS_VALID(dir) ((((unsigned int) (dir)) & ~3U) == 4)
|
||||||
|
/* Direction must be valid for the following */
|
||||||
#define HB_DIRECTION_IS_HORIZONTAL(dir) ((((unsigned int) (dir)) & ~1U) == 4)
|
#define HB_DIRECTION_IS_HORIZONTAL(dir) ((((unsigned int) (dir)) & ~1U) == 4)
|
||||||
#define HB_DIRECTION_IS_VERTICAL(dir) ((((unsigned int) (dir)) & ~1U) == 6)
|
#define HB_DIRECTION_IS_VERTICAL(dir) ((((unsigned int) (dir)) & ~1U) == 6)
|
||||||
#define HB_DIRECTION_IS_FORWARD(dir) ((((unsigned int) (dir)) & ~2U) == 4)
|
#define HB_DIRECTION_IS_FORWARD(dir) ((((unsigned int) (dir)) & ~2U) == 4)
|
||||||
#define HB_DIRECTION_IS_BACKWARD(dir) ((((unsigned int) (dir)) & ~2U) == 5)
|
#define HB_DIRECTION_IS_BACKWARD(dir) ((((unsigned int) (dir)) & ~2U) == 5)
|
||||||
#define HB_DIRECTION_IS_VALID(dir) ((((unsigned int) (dir)) & ~3U) == 4)
|
#define HB_DIRECTION_REVERSE(dir) ((hb_direction_t) (((unsigned int) (dir)) ^ 1))
|
||||||
#define HB_DIRECTION_REVERSE(dir) ((hb_direction_t) (((unsigned int) (dir)) ^ 1)) /* Direction must be valid */
|
|
||||||
|
|
||||||
|
|
||||||
/* hb_language_t */
|
/* hb_language_t */
|
||||||
@ -295,11 +297,17 @@ typedef enum
|
|||||||
/*7.0*/ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'),
|
/*7.0*/ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'),
|
||||||
|
|
||||||
/* No script set. */
|
/* No script set. */
|
||||||
/*---*/ HB_SCRIPT_INVALID = HB_TAG_NONE,
|
HB_SCRIPT_INVALID = HB_TAG_NONE,
|
||||||
|
|
||||||
/* Dummy value to ensure any hb_tag_t value can be passed/stored as hb_script_t
|
/* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t
|
||||||
* without risking undefined behavior. */
|
* without risking undefined behavior. Include both a signed and unsigned max,
|
||||||
/*---*/ _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX
|
* since technically enums are int, and indeed, hb_script_t ends up being signed.
|
||||||
|
* See this thread for technicalities:
|
||||||
|
*
|
||||||
|
* http://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html
|
||||||
|
*/
|
||||||
|
_HB_SCRIPT_MAX_VALUE = HB_TAG_MAX, /*< skip >*/
|
||||||
|
_HB_SCRIPT_MAX_VALUE_SIGNED = HB_TAG_MAX_SIGNED /*< skip >*/
|
||||||
|
|
||||||
} hb_script_t;
|
} hb_script_t;
|
||||||
|
|
||||||
@ -309,7 +317,7 @@ typedef enum
|
|||||||
hb_script_t
|
hb_script_t
|
||||||
hb_script_from_iso15924_tag (hb_tag_t tag);
|
hb_script_from_iso15924_tag (hb_tag_t tag);
|
||||||
|
|
||||||
/* suger for tag_from_string() then script_from_iso15924_tag */
|
/* sugar for tag_from_string() then script_from_iso15924_tag */
|
||||||
/* len=-1 means s is NUL-terminated */
|
/* len=-1 means s is NUL-terminated */
|
||||||
hb_script_t
|
hb_script_t
|
||||||
hb_script_from_string (const char *s, int len);
|
hb_script_from_string (const char *s, int len);
|
||||||
|
@ -66,7 +66,7 @@ struct hb_face_t {
|
|||||||
{
|
{
|
||||||
hb_blob_t *blob;
|
hb_blob_t *blob;
|
||||||
|
|
||||||
if (unlikely (!this || !reference_table_func))
|
if (unlikely (!reference_table_func))
|
||||||
return hb_blob_get_empty ();
|
return hb_blob_get_empty ();
|
||||||
|
|
||||||
blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
|
blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
|
||||||
|
8
src/3rdparty/harfbuzz-ng/src/hb-face.cc
vendored
8
src/3rdparty/harfbuzz-ng/src/hb-face.cc
vendored
@ -298,7 +298,7 @@ hb_face_get_user_data (hb_face_t *face,
|
|||||||
void
|
void
|
||||||
hb_face_make_immutable (hb_face_t *face)
|
hb_face_make_immutable (hb_face_t *face)
|
||||||
{
|
{
|
||||||
if (hb_object_is_inert (face))
|
if (unlikely (hb_object_is_inert (face)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
face->immutable = true;
|
face->immutable = true;
|
||||||
@ -368,7 +368,7 @@ void
|
|||||||
hb_face_set_index (hb_face_t *face,
|
hb_face_set_index (hb_face_t *face,
|
||||||
unsigned int index)
|
unsigned int index)
|
||||||
{
|
{
|
||||||
if (hb_object_is_inert (face))
|
if (face->immutable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
face->index = index;
|
face->index = index;
|
||||||
@ -403,7 +403,7 @@ void
|
|||||||
hb_face_set_upem (hb_face_t *face,
|
hb_face_set_upem (hb_face_t *face,
|
||||||
unsigned int upem)
|
unsigned int upem)
|
||||||
{
|
{
|
||||||
if (hb_object_is_inert (face))
|
if (face->immutable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
face->upem = upem;
|
face->upem = upem;
|
||||||
@ -447,7 +447,7 @@ void
|
|||||||
hb_face_set_glyph_count (hb_face_t *face,
|
hb_face_set_glyph_count (hb_face_t *face,
|
||||||
unsigned int glyph_count)
|
unsigned int glyph_count)
|
||||||
{
|
{
|
||||||
if (hb_object_is_inert (face))
|
if (face->immutable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
face->num_glyphs = glyph_count;
|
face->num_glyphs = glyph_count;
|
||||||
|
4
src/3rdparty/harfbuzz-ng/src/hb-font.cc
vendored
4
src/3rdparty/harfbuzz-ng/src/hb-font.cc
vendored
@ -357,7 +357,7 @@ hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
|
|||||||
void
|
void
|
||||||
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
|
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
|
||||||
{
|
{
|
||||||
if (hb_object_is_inert (ffuncs))
|
if (unlikely (hb_object_is_inert (ffuncs)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ffuncs->immutable = true;
|
ffuncs->immutable = true;
|
||||||
@ -1034,7 +1034,7 @@ hb_font_get_user_data (hb_font_t *font,
|
|||||||
void
|
void
|
||||||
hb_font_make_immutable (hb_font_t *font)
|
hb_font_make_immutable (hb_font_t *font)
|
||||||
{
|
{
|
||||||
if (hb_object_is_inert (font))
|
if (unlikely (hb_object_is_inert (font)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
font->immutable = true;
|
font->immutable = true;
|
||||||
|
13
src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh
vendored
13
src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh
vendored
@ -44,21 +44,10 @@
|
|||||||
|
|
||||||
#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
|
#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
typedef CRITICAL_SECTION hb_mutex_impl_t;
|
typedef CRITICAL_SECTION hb_mutex_impl_t;
|
||||||
#ifdef _WIN32_WCE
|
#define HB_MUTEX_IMPL_INIT {0}
|
||||||
#define HB_MUTEX_IMPL_INIT { 0, 0, NULL, NULL, 0 }
|
|
||||||
#else
|
|
||||||
#define HB_MUTEX_IMPL_INIT { NULL, 0, 0, NULL, NULL, 0 }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
|
|
||||||
#define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0)
|
|
||||||
#else
|
|
||||||
#define hb_mutex_impl_init(M) InitializeCriticalSection (M)
|
#define hb_mutex_impl_init(M) InitializeCriticalSection (M)
|
||||||
#endif
|
|
||||||
|
|
||||||
#define hb_mutex_impl_lock(M) EnterCriticalSection (M)
|
#define hb_mutex_impl_lock(M) EnterCriticalSection (M)
|
||||||
#define hb_mutex_impl_unlock(M) LeaveCriticalSection (M)
|
#define hb_mutex_impl_unlock(M) LeaveCriticalSection (M)
|
||||||
#define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
|
#define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
|
||||||
|
107
src/3rdparty/harfbuzz-ng/src/hb-object-private.hh
vendored
107
src/3rdparty/harfbuzz-ng/src/hb-object-private.hh
vendored
@ -68,8 +68,6 @@ struct hb_reference_count_t
|
|||||||
#define HB_USER_DATA_ARRAY_INIT {HB_MUTEX_INIT, HB_LOCKABLE_SET_INIT}
|
#define HB_USER_DATA_ARRAY_INIT {HB_MUTEX_INIT, HB_LOCKABLE_SET_INIT}
|
||||||
struct hb_user_data_array_t
|
struct hb_user_data_array_t
|
||||||
{
|
{
|
||||||
/* TODO Add tracing. */
|
|
||||||
|
|
||||||
struct hb_user_data_item_t {
|
struct hb_user_data_item_t {
|
||||||
hb_user_data_key_t *key;
|
hb_user_data_key_t *key;
|
||||||
void *data;
|
void *data;
|
||||||
@ -106,69 +104,6 @@ struct hb_object_header_t
|
|||||||
|
|
||||||
#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID, HB_USER_DATA_ARRAY_INIT}
|
#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID, HB_USER_DATA_ARRAY_INIT}
|
||||||
|
|
||||||
static inline void *create (unsigned int size) {
|
|
||||||
hb_object_header_t *obj = (hb_object_header_t *) calloc (1, size);
|
|
||||||
|
|
||||||
if (likely (obj))
|
|
||||||
obj->init ();
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void init (void) {
|
|
||||||
ref_count.init (1);
|
|
||||||
user_data.init ();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool is_inert (void) const {
|
|
||||||
return unlikely (ref_count.is_invalid ());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void reference (void) {
|
|
||||||
if (unlikely (!this || this->is_inert ()))
|
|
||||||
return;
|
|
||||||
ref_count.inc ();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool destroy (void) {
|
|
||||||
if (unlikely (!this || this->is_inert ()))
|
|
||||||
return false;
|
|
||||||
if (ref_count.dec () != 1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ref_count.finish (); /* Do this before user_data */
|
|
||||||
user_data.finish ();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool set_user_data (hb_user_data_key_t *key,
|
|
||||||
void * data,
|
|
||||||
hb_destroy_func_t destroy_func,
|
|
||||||
hb_bool_t replace) {
|
|
||||||
if (unlikely (!this || this->is_inert ()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return user_data.set (key, data, destroy_func, replace);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void *get_user_data (hb_user_data_key_t *key) {
|
|
||||||
if (unlikely (!this || this->is_inert ()))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return user_data.get (key);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void trace (const char *function) const {
|
|
||||||
if (unlikely (!this)) return;
|
|
||||||
/* TODO We cannot use DEBUG_MSG_FUNC here since that one currently only
|
|
||||||
* prints the class name and throws away the template info. */
|
|
||||||
DEBUG_MSG (OBJECT, (void *) this,
|
|
||||||
"%s refcount=%d",
|
|
||||||
function,
|
|
||||||
this ? ref_count.ref_count : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASSERT_POD ();
|
ASSERT_POD ();
|
||||||
};
|
};
|
||||||
@ -179,32 +114,56 @@ struct hb_object_header_t
|
|||||||
template <typename Type>
|
template <typename Type>
|
||||||
static inline void hb_object_trace (const Type *obj, const char *function)
|
static inline void hb_object_trace (const Type *obj, const char *function)
|
||||||
{
|
{
|
||||||
obj->header.trace (function);
|
DEBUG_MSG (OBJECT, (void *) obj,
|
||||||
|
"%s refcount=%d",
|
||||||
|
function,
|
||||||
|
obj ? obj->header.ref_count.ref_count : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
static inline Type *hb_object_create (void)
|
static inline Type *hb_object_create (void)
|
||||||
{
|
{
|
||||||
Type *obj = (Type *) hb_object_header_t::create (sizeof (Type));
|
Type *obj = (Type *) calloc (1, sizeof (Type));
|
||||||
|
|
||||||
|
if (unlikely (!obj))
|
||||||
|
return obj;
|
||||||
|
|
||||||
|
hb_object_init (obj);
|
||||||
hb_object_trace (obj, HB_FUNC);
|
hb_object_trace (obj, HB_FUNC);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
|
static inline void hb_object_init (Type *obj)
|
||||||
|
{
|
||||||
|
obj->header.ref_count.init (1);
|
||||||
|
obj->header.user_data.init ();
|
||||||
|
}
|
||||||
|
template <typename Type>
|
||||||
static inline bool hb_object_is_inert (const Type *obj)
|
static inline bool hb_object_is_inert (const Type *obj)
|
||||||
{
|
{
|
||||||
return unlikely (obj->header.is_inert ());
|
return unlikely (obj->header.ref_count.is_invalid ());
|
||||||
}
|
}
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
static inline Type *hb_object_reference (Type *obj)
|
static inline Type *hb_object_reference (Type *obj)
|
||||||
{
|
{
|
||||||
hb_object_trace (obj, HB_FUNC);
|
hb_object_trace (obj, HB_FUNC);
|
||||||
obj->header.reference ();
|
if (unlikely (!obj || hb_object_is_inert (obj)))
|
||||||
|
return obj;
|
||||||
|
obj->header.ref_count.inc ();
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
static inline bool hb_object_destroy (Type *obj)
|
static inline bool hb_object_destroy (Type *obj)
|
||||||
{
|
{
|
||||||
hb_object_trace (obj, HB_FUNC);
|
hb_object_trace (obj, HB_FUNC);
|
||||||
return obj->header.destroy ();
|
if (unlikely (!obj || hb_object_is_inert (obj)))
|
||||||
|
return false;
|
||||||
|
if (obj->header.ref_count.dec () != 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
obj->header.ref_count.finish (); /* Do this before user_data */
|
||||||
|
obj->header.user_data.finish ();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
static inline bool hb_object_set_user_data (Type *obj,
|
static inline bool hb_object_set_user_data (Type *obj,
|
||||||
@ -213,14 +172,18 @@ static inline bool hb_object_set_user_data (Type *obj,
|
|||||||
hb_destroy_func_t destroy,
|
hb_destroy_func_t destroy,
|
||||||
hb_bool_t replace)
|
hb_bool_t replace)
|
||||||
{
|
{
|
||||||
return obj->header.set_user_data (key, data, destroy, replace);
|
if (unlikely (!obj || hb_object_is_inert (obj)))
|
||||||
|
return false;
|
||||||
|
return obj->header.user_data.set (key, data, destroy, replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
static inline void *hb_object_get_user_data (Type *obj,
|
static inline void *hb_object_get_user_data (Type *obj,
|
||||||
hb_user_data_key_t *key)
|
hb_user_data_key_t *key)
|
||||||
{
|
{
|
||||||
return obj->header.get_user_data (key);
|
if (unlikely (!obj || hb_object_is_inert (obj)))
|
||||||
|
return NULL;
|
||||||
|
return obj->header.user_data.get (key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,6 +197,8 @@ struct TTCHeader
|
|||||||
|
|
||||||
struct OpenTypeFontFile
|
struct OpenTypeFontFile
|
||||||
{
|
{
|
||||||
|
static const hb_tag_t tableTag = HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */
|
||||||
|
|
||||||
static const hb_tag_t CFFTag = HB_TAG ('O','T','T','O'); /* OpenType with Postscript outlines */
|
static const hb_tag_t CFFTag = HB_TAG ('O','T','T','O'); /* OpenType with Postscript outlines */
|
||||||
static const hb_tag_t TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ); /* OpenType with TrueType outlines */
|
static const hb_tag_t TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ); /* OpenType with TrueType outlines */
|
||||||
static const hb_tag_t TTCTag = HB_TAG ('t','t','c','f'); /* TrueType Collection */
|
static const hb_tag_t TTCTag = HB_TAG ('t','t','c','f'); /* TrueType Collection */
|
||||||
|
124
src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh
vendored
124
src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh
vendored
@ -194,10 +194,11 @@ struct hb_sanitize_context_t
|
|||||||
{
|
{
|
||||||
this->start = hb_blob_get_data (this->blob, NULL);
|
this->start = hb_blob_get_data (this->blob, NULL);
|
||||||
this->end = this->start + hb_blob_get_length (this->blob);
|
this->end = this->start + hb_blob_get_length (this->blob);
|
||||||
|
assert (this->start <= this->end); /* Must not overflow. */
|
||||||
this->edit_count = 0;
|
this->edit_count = 0;
|
||||||
this->debug_depth = 0;
|
this->debug_depth = 0;
|
||||||
|
|
||||||
DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1,
|
DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
|
||||||
"start [%p..%p] (%lu bytes)",
|
"start [%p..%p] (%lu bytes)",
|
||||||
this->start, this->end,
|
this->start, this->end,
|
||||||
(unsigned long) (this->end - this->start));
|
(unsigned long) (this->end - this->start));
|
||||||
@ -205,7 +206,7 @@ struct hb_sanitize_context_t
|
|||||||
|
|
||||||
inline void end_processing (void)
|
inline void end_processing (void)
|
||||||
{
|
{
|
||||||
DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1,
|
DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
|
||||||
"end [%p..%p] %u edit requests",
|
"end [%p..%p] %u edit requests",
|
||||||
this->start, this->end, this->edit_count);
|
this->start, this->end, this->edit_count);
|
||||||
|
|
||||||
@ -217,28 +218,31 @@ struct hb_sanitize_context_t
|
|||||||
inline bool check_range (const void *base, unsigned int len) const
|
inline bool check_range (const void *base, unsigned int len) const
|
||||||
{
|
{
|
||||||
const char *p = (const char *) base;
|
const char *p = (const char *) base;
|
||||||
|
bool ok = this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len;
|
||||||
|
|
||||||
hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace
|
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
|
||||||
(&this->debug_depth, "SANITIZE", this->blob, NULL,
|
"check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
|
||||||
"check_range [%p..%p] (%d bytes) in [%p..%p]",
|
|
||||||
p, p + len, len,
|
p, p + len, len,
|
||||||
this->start, this->end);
|
this->start, this->end,
|
||||||
|
ok ? "OK" : "OUT-OF-RANGE");
|
||||||
|
|
||||||
return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len));
|
return likely (ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
|
inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
|
||||||
{
|
{
|
||||||
const char *p = (const char *) base;
|
const char *p = (const char *) base;
|
||||||
bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
|
bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
|
||||||
|
unsigned int array_size = record_size * len;
|
||||||
|
bool ok = !overflows && this->check_range (base, array_size);
|
||||||
|
|
||||||
hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace
|
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
|
||||||
(&this->debug_depth, "SANITIZE", this->blob, NULL,
|
"check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s",
|
||||||
"check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]",
|
p, p + (record_size * len), record_size, len, (unsigned int) array_size,
|
||||||
p, p + (record_size * len), record_size, len, (unsigned long) record_size * len,
|
this->start, this->end,
|
||||||
this->start, this->end);
|
overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE");
|
||||||
|
|
||||||
return TRACE_RETURN (likely (!overflows && this->check_range (base, record_size * len)));
|
return likely (ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
@ -255,15 +259,14 @@ struct hb_sanitize_context_t
|
|||||||
const char *p = (const char *) base;
|
const char *p = (const char *) base;
|
||||||
this->edit_count++;
|
this->edit_count++;
|
||||||
|
|
||||||
hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace
|
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
|
||||||
(&this->debug_depth, "SANITIZE", this->blob, NULL,
|
|
||||||
"may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
|
"may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
|
||||||
this->edit_count,
|
this->edit_count,
|
||||||
p, p + len, len,
|
p, p + len, len,
|
||||||
this->start, this->end,
|
this->start, this->end,
|
||||||
this->writable ? "GRANTED" : "DENIED");
|
this->writable ? "GRANTED" : "DENIED");
|
||||||
|
|
||||||
return TRACE_RETURN (this->writable);
|
return this->writable;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type, typename ValueType>
|
template <typename Type, typename ValueType>
|
||||||
@ -289,7 +292,7 @@ template <typename Type>
|
|||||||
struct Sanitizer
|
struct Sanitizer
|
||||||
{
|
{
|
||||||
static hb_blob_t *sanitize (hb_blob_t *blob) {
|
static hb_blob_t *sanitize (hb_blob_t *blob) {
|
||||||
hb_sanitize_context_t c[1] = {{0}};
|
hb_sanitize_context_t c[1] = {{0, NULL, NULL, false, 0, NULL}};
|
||||||
bool sane;
|
bool sane;
|
||||||
|
|
||||||
/* TODO is_sane() stuff */
|
/* TODO is_sane() stuff */
|
||||||
@ -297,7 +300,7 @@ struct Sanitizer
|
|||||||
c->init (blob);
|
c->init (blob);
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
DEBUG_MSG_FUNC (SANITIZE, blob, "start");
|
DEBUG_MSG_FUNC (SANITIZE, c->start, "start");
|
||||||
|
|
||||||
c->start_processing ();
|
c->start_processing ();
|
||||||
|
|
||||||
@ -311,13 +314,13 @@ struct Sanitizer
|
|||||||
sane = t->sanitize (c);
|
sane = t->sanitize (c);
|
||||||
if (sane) {
|
if (sane) {
|
||||||
if (c->edit_count) {
|
if (c->edit_count) {
|
||||||
DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count);
|
DEBUG_MSG_FUNC (SANITIZE, c->start, "passed first round with %d edits; going for second round", c->edit_count);
|
||||||
|
|
||||||
/* sanitize again to ensure no toe-stepping */
|
/* sanitize again to ensure no toe-stepping */
|
||||||
c->edit_count = 0;
|
c->edit_count = 0;
|
||||||
sane = t->sanitize (c);
|
sane = t->sanitize (c);
|
||||||
if (c->edit_count) {
|
if (c->edit_count) {
|
||||||
DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count);
|
DEBUG_MSG_FUNC (SANITIZE, c->start, "requested %d edits in second round; FAILLING", c->edit_count);
|
||||||
sane = false;
|
sane = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,7 +333,7 @@ struct Sanitizer
|
|||||||
if (c->start) {
|
if (c->start) {
|
||||||
c->writable = true;
|
c->writable = true;
|
||||||
/* ok, we made it writable by relocating. try again */
|
/* ok, we made it writable by relocating. try again */
|
||||||
DEBUG_MSG_FUNC (SANITIZE, blob, "retry");
|
DEBUG_MSG_FUNC (SANITIZE, c->start, "retry");
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,7 +341,7 @@ struct Sanitizer
|
|||||||
|
|
||||||
c->end_processing ();
|
c->end_processing ();
|
||||||
|
|
||||||
DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED");
|
DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED");
|
||||||
if (sane)
|
if (sane)
|
||||||
return blob;
|
return blob;
|
||||||
else {
|
else {
|
||||||
@ -533,32 +536,77 @@ template <typename Type>
|
|||||||
struct BEInt<Type, 2>
|
struct BEInt<Type, 2>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline void set (Type i) { hb_be_uint16_put (v,i); }
|
inline void set (Type V)
|
||||||
inline operator Type (void) const { return hb_be_uint16_get (v); }
|
{
|
||||||
inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_eq (v, o.v); }
|
v[0] = (V >> 8) & 0xFF;
|
||||||
|
v[1] = (V ) & 0xFF;
|
||||||
|
}
|
||||||
|
inline operator Type (void) const
|
||||||
|
{
|
||||||
|
return (v[0] << 8)
|
||||||
|
+ (v[1] );
|
||||||
|
}
|
||||||
|
inline bool operator == (const BEInt<Type, 2>& o) const
|
||||||
|
{
|
||||||
|
return v[0] == o.v[0]
|
||||||
|
&& v[1] == o.v[1];
|
||||||
|
}
|
||||||
inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
|
inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
|
||||||
private: uint8_t v[2];
|
private: uint8_t v[2];
|
||||||
};
|
};
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
struct BEInt<Type, 4>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline void set (Type i) { hb_be_uint32_put (v,i); }
|
|
||||||
inline operator Type (void) const { return hb_be_uint32_get (v); }
|
|
||||||
inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_eq (v, o.v); }
|
|
||||||
inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
|
|
||||||
private: uint8_t v[4];
|
|
||||||
};
|
|
||||||
template <typename Type>
|
|
||||||
struct BEInt<Type, 3>
|
struct BEInt<Type, 3>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline void set (Type i) { hb_be_uint24_put (v,i); }
|
inline void set (Type V)
|
||||||
inline operator Type (void) const { return hb_be_uint24_get (v); }
|
{
|
||||||
inline bool operator == (const BEInt<Type, 3>& o) const { return hb_be_uint24_eq (v, o.v); }
|
v[0] = (V >> 16) & 0xFF;
|
||||||
|
v[1] = (V >> 8) & 0xFF;
|
||||||
|
v[2] = (V ) & 0xFF;
|
||||||
|
}
|
||||||
|
inline operator Type (void) const
|
||||||
|
{
|
||||||
|
return (v[0] << 16)
|
||||||
|
+ (v[1] << 8)
|
||||||
|
+ (v[2] );
|
||||||
|
}
|
||||||
|
inline bool operator == (const BEInt<Type, 3>& o) const
|
||||||
|
{
|
||||||
|
return v[0] == o.v[0]
|
||||||
|
&& v[1] == o.v[1]
|
||||||
|
&& v[2] == o.v[2];
|
||||||
|
}
|
||||||
inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o); }
|
inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o); }
|
||||||
private: uint8_t v[3];
|
private: uint8_t v[3];
|
||||||
};
|
};
|
||||||
|
template <typename Type>
|
||||||
|
struct BEInt<Type, 4>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline void set (Type V)
|
||||||
|
{
|
||||||
|
v[0] = (V >> 24) & 0xFF;
|
||||||
|
v[1] = (V >> 16) & 0xFF;
|
||||||
|
v[2] = (V >> 8) & 0xFF;
|
||||||
|
v[3] = (V ) & 0xFF;
|
||||||
|
}
|
||||||
|
inline operator Type (void) const
|
||||||
|
{
|
||||||
|
return (v[0] << 24)
|
||||||
|
+ (v[1] << 16)
|
||||||
|
+ (v[2] << 8)
|
||||||
|
+ (v[3] );
|
||||||
|
}
|
||||||
|
inline bool operator == (const BEInt<Type, 4>& o) const
|
||||||
|
{
|
||||||
|
return v[0] == o.v[0]
|
||||||
|
&& v[1] == o.v[1]
|
||||||
|
&& v[2] == o.v[2]
|
||||||
|
&& v[3] == o.v[3];
|
||||||
|
}
|
||||||
|
inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
|
||||||
|
private: uint8_t v[4];
|
||||||
|
};
|
||||||
|
|
||||||
/* Integer types in big-endian order and no alignment requirement */
|
/* Integer types in big-endian order and no alignment requirement */
|
||||||
template <typename Type, unsigned int Size>
|
template <typename Type, unsigned int Size>
|
||||||
|
205
src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
vendored
205
src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
vendored
@ -35,17 +35,128 @@
|
|||||||
#include "hb-ot-hmtx-table.hh"
|
#include "hb-ot-hmtx-table.hh"
|
||||||
|
|
||||||
|
|
||||||
|
struct hb_ot_face_metrics_accelerator_t
|
||||||
|
{
|
||||||
|
unsigned int num_metrics;
|
||||||
|
unsigned int num_advances;
|
||||||
|
unsigned int default_advance;
|
||||||
|
const OT::_mtx *table;
|
||||||
|
hb_blob_t *blob;
|
||||||
|
|
||||||
|
inline void init (hb_face_t *face,
|
||||||
|
hb_tag_t _hea_tag, hb_tag_t _mtx_tag,
|
||||||
|
unsigned int default_advance)
|
||||||
|
{
|
||||||
|
this->default_advance = default_advance;
|
||||||
|
this->num_metrics = face->get_num_glyphs ();
|
||||||
|
|
||||||
|
hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag));
|
||||||
|
const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob);
|
||||||
|
this->num_advances = _hea->numberOfLongMetrics;
|
||||||
|
hb_blob_destroy (_hea_blob);
|
||||||
|
|
||||||
|
this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag));
|
||||||
|
if (unlikely (!this->num_advances ||
|
||||||
|
2 * (this->num_advances + this->num_metrics) < hb_blob_get_length (this->blob)))
|
||||||
|
{
|
||||||
|
this->num_metrics = this->num_advances = 0;
|
||||||
|
hb_blob_destroy (this->blob);
|
||||||
|
this->blob = hb_blob_get_empty ();
|
||||||
|
}
|
||||||
|
this->table = OT::Sanitizer<OT::_mtx>::lock_instance (this->blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void fini (void)
|
||||||
|
{
|
||||||
|
hb_blob_destroy (this->blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int get_advance (hb_codepoint_t glyph) const
|
||||||
|
{
|
||||||
|
if (unlikely (glyph >= this->num_metrics))
|
||||||
|
{
|
||||||
|
/* If this->num_metrics is zero, it means we don't have the metrics table
|
||||||
|
* for this direction: return one EM. Otherwise, it means that the glyph
|
||||||
|
* index is out of bound: return zero. */
|
||||||
|
if (this->num_metrics)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return this->default_advance;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glyph >= this->num_advances)
|
||||||
|
glyph = this->num_advances - 1;
|
||||||
|
|
||||||
|
return this->table->longMetric[glyph].advance;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hb_ot_face_cmap_accelerator_t
|
||||||
|
{
|
||||||
|
const OT::CmapSubtable *table;
|
||||||
|
const OT::CmapSubtable *uvs_table;
|
||||||
|
hb_blob_t *blob;
|
||||||
|
|
||||||
|
inline void init (hb_face_t *face)
|
||||||
|
{
|
||||||
|
this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap));
|
||||||
|
const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
|
||||||
|
const OT::CmapSubtable *subtable = NULL;
|
||||||
|
const OT::CmapSubtable *subtable_uvs = NULL;
|
||||||
|
|
||||||
|
/* 32-bit subtables. */
|
||||||
|
if (!subtable) subtable = cmap->find_subtable (3, 10);
|
||||||
|
if (!subtable) subtable = cmap->find_subtable (0, 6);
|
||||||
|
if (!subtable) subtable = cmap->find_subtable (0, 4);
|
||||||
|
/* 16-bit subtables. */
|
||||||
|
if (!subtable) subtable = cmap->find_subtable (3, 1);
|
||||||
|
if (!subtable) subtable = cmap->find_subtable (0, 3);
|
||||||
|
if (!subtable) subtable = cmap->find_subtable (0, 2);
|
||||||
|
if (!subtable) subtable = cmap->find_subtable (0, 1);
|
||||||
|
if (!subtable) subtable = cmap->find_subtable (0, 0);
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
this->table = subtable;
|
||||||
|
this->uvs_table = subtable_uvs;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void fini (void)
|
||||||
|
{
|
||||||
|
hb_blob_destroy (this->blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool get_glyph (hb_codepoint_t unicode,
|
||||||
|
hb_codepoint_t variation_selector,
|
||||||
|
hb_codepoint_t *glyph) const
|
||||||
|
{
|
||||||
|
if (unlikely (variation_selector))
|
||||||
|
{
|
||||||
|
switch (this->uvs_table->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 this->table->get_glyph (unicode, glyph);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct hb_ot_font_t
|
struct hb_ot_font_t
|
||||||
{
|
{
|
||||||
unsigned int num_glyphs;
|
hb_ot_face_cmap_accelerator_t cmap;
|
||||||
unsigned int num_hmetrics;
|
hb_ot_face_metrics_accelerator_t h_metrics;
|
||||||
const OT::hmtx *hmtx;
|
hb_ot_face_metrics_accelerator_t v_metrics;
|
||||||
hb_blob_t *hmtx_blob;
|
|
||||||
|
|
||||||
const OT::CmapSubtable *cmap;
|
|
||||||
const OT::CmapSubtable *cmap_uvs;
|
|
||||||
hb_blob_t *cmap_blob;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -53,50 +164,16 @@ static hb_ot_font_t *
|
|||||||
_hb_ot_font_create (hb_font_t *font)
|
_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));
|
hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
|
||||||
|
hb_face_t *face = font->face;
|
||||||
|
|
||||||
if (unlikely (!ot_font))
|
if (unlikely (!ot_font))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ot_font->num_glyphs = font->face->get_num_glyphs ();
|
unsigned int upem = face->get_upem ();
|
||||||
|
|
||||||
{
|
ot_font->cmap.init (face);
|
||||||
hb_blob_t *hhea_blob = OT::Sanitizer<OT::hhea>::sanitize (font->face->reference_table (HB_OT_TAG_hhea));
|
ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1);
|
||||||
const OT::hhea *hhea = OT::Sanitizer<OT::hhea>::lock_instance (hhea_blob);
|
ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* TODO Can we do this lazily? */
|
||||||
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;
|
return ot_font;
|
||||||
}
|
}
|
||||||
@ -104,8 +181,9 @@ _hb_ot_font_create (hb_font_t *font)
|
|||||||
static void
|
static void
|
||||||
_hb_ot_font_destroy (hb_ot_font_t *ot_font)
|
_hb_ot_font_destroy (hb_ot_font_t *ot_font)
|
||||||
{
|
{
|
||||||
hb_blob_destroy (ot_font->cmap_blob);
|
ot_font->cmap.fini ();
|
||||||
hb_blob_destroy (ot_font->hmtx_blob);
|
ot_font->h_metrics.fini ();
|
||||||
|
ot_font->v_metrics.fini ();
|
||||||
|
|
||||||
free (ot_font);
|
free (ot_font);
|
||||||
}
|
}
|
||||||
@ -121,20 +199,7 @@ hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
|
|||||||
|
|
||||||
{
|
{
|
||||||
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||||
|
return ot_font->cmap.get_glyph (unicode, variation_selector, glyph);
|
||||||
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
|
static hb_position_t
|
||||||
@ -144,14 +209,7 @@ hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
|
|||||||
void *user_data HB_UNUSED)
|
void *user_data HB_UNUSED)
|
||||||
{
|
{
|
||||||
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||||
|
return font->em_scale_x (ot_font->h_metrics.get_advance (glyph));
|
||||||
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
|
static hb_position_t
|
||||||
@ -160,8 +218,8 @@ hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
|
|||||||
hb_codepoint_t glyph,
|
hb_codepoint_t glyph,
|
||||||
void *user_data HB_UNUSED)
|
void *user_data HB_UNUSED)
|
||||||
{
|
{
|
||||||
/* TODO */
|
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||||
return 0;
|
return font->em_scale_y (-ot_font->v_metrics.get_advance (glyph));
|
||||||
}
|
}
|
||||||
|
|
||||||
static hb_bool_t
|
static hb_bool_t
|
||||||
@ -206,6 +264,7 @@ hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
|
|||||||
hb_codepoint_t bottom_glyph HB_UNUSED,
|
hb_codepoint_t bottom_glyph HB_UNUSED,
|
||||||
void *user_data HB_UNUSED)
|
void *user_data HB_UNUSED)
|
||||||
{
|
{
|
||||||
|
/* OpenType doesn't have vertical-kerning other than GPOS. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
65
src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh
vendored
65
src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh
vendored
@ -35,14 +35,19 @@ namespace OT {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* hhea -- The Horizontal Header Table
|
* hhea -- The Horizontal Header Table
|
||||||
|
* vhea -- The Vertical Header Table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define HB_OT_TAG_hhea HB_TAG('h','h','e','a')
|
#define HB_OT_TAG_hhea HB_TAG('h','h','e','a')
|
||||||
|
#define HB_OT_TAG_vhea HB_TAG('v','h','e','a')
|
||||||
|
|
||||||
|
|
||||||
struct hhea
|
struct _hea
|
||||||
{
|
{
|
||||||
static const hb_tag_t tableTag = HB_OT_TAG_hhea;
|
static const hb_tag_t tableTag = HB_TAG('_','h','e','a');
|
||||||
|
|
||||||
|
static const hb_tag_t hheaTag = HB_OT_TAG_hhea;
|
||||||
|
static const hb_tag_t vheaTag = HB_OT_TAG_vhea;
|
||||||
|
|
||||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
@ -51,45 +56,45 @@ struct hhea
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
FixedVersion version; /* 0x00010000u for version 1.0. */
|
FixedVersion version; /* 0x00010000u for version 1.0. */
|
||||||
FWORD ascender; /* Typographic ascent. <a
|
FWORD ascender; /* Typographic ascent. */
|
||||||
* href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html">
|
FWORD descender; /* Typographic descent. */
|
||||||
* (Distance from baseline of highest
|
FWORD lineGap; /* Typographic line gap. */
|
||||||
* ascender)</a> */
|
UFWORD advanceMax; /* Maximum advance width/height value in
|
||||||
FWORD descender; /* Typographic descent. <a
|
* metrics table. */
|
||||||
* href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html">
|
FWORD minLeadingBearing; /* Minimum left/top sidebearing value in
|
||||||
* (Distance from baseline of lowest
|
* metrics table. */
|
||||||
* descender)</a> */
|
FWORD minTrailingBearing; /* Minimum right/bottom sidebearing value;
|
||||||
FWORD lineGap; /* Typographic line gap. Negative
|
|
||||||
* LineGap values are treated as zero
|
|
||||||
* in Windows 3.1, System 6, and
|
|
||||||
* System 7. */
|
|
||||||
UFWORD advanceWidthMax; /* Maximum advance width value in
|
|
||||||
* 'hmtx' table. */
|
|
||||||
FWORD minLeftSideBearing; /* Minimum left sidebearing value in
|
|
||||||
* 'hmtx' table. */
|
|
||||||
FWORD minRightSideBearing; /* Minimum right sidebearing value;
|
|
||||||
* calculated as Min(aw - lsb -
|
* calculated as Min(aw - lsb -
|
||||||
* (xMax - xMin)). */
|
* (xMax - xMin)) for horizontal. */
|
||||||
FWORD xMaxExtent; /* Max(lsb + (xMax - xMin)). */
|
FWORD maxExtent; /* horizontal: Max(lsb + (xMax - xMin)),
|
||||||
|
* vertical: minLeadingBearing+(yMax-yMin). */
|
||||||
SHORT caretSlopeRise; /* Used to calculate the slope of the
|
SHORT caretSlopeRise; /* Used to calculate the slope of the
|
||||||
* cursor (rise/run); 1 for vertical. */
|
* cursor (rise/run); 1 for vertical caret,
|
||||||
SHORT caretSlopeRun; /* 0 for vertical. */
|
* 0 for horizontal.*/
|
||||||
|
SHORT caretSlopeRun; /* 0 for vertical caret, 1 for horizontal. */
|
||||||
SHORT caretOffset; /* The amount by which a slanted
|
SHORT caretOffset; /* The amount by which a slanted
|
||||||
* highlight on a glyph needs
|
* highlight on a glyph needs
|
||||||
* to be shifted to produce the
|
* to be shifted to produce the
|
||||||
* best appearance. Set to 0 for
|
* best appearance. Set to 0 for
|
||||||
* non--slanted fonts */
|
* non-slanted fonts. */
|
||||||
SHORT reserved1; /* set to 0 */
|
SHORT reserved1; /* Set to 0. */
|
||||||
SHORT reserved2; /* set to 0 */
|
SHORT reserved2; /* Set to 0. */
|
||||||
SHORT reserved3; /* set to 0 */
|
SHORT reserved3; /* Set to 0. */
|
||||||
SHORT reserved4; /* set to 0 */
|
SHORT reserved4; /* Set to 0. */
|
||||||
SHORT metricDataFormat; /* 0 for current format. */
|
SHORT metricDataFormat; /* 0 for current format. */
|
||||||
USHORT numberOfHMetrics; /* Number of hMetric entries in 'hmtx'
|
USHORT numberOfLongMetrics; /* Number of LongMetric entries in metric
|
||||||
* table */
|
* table. */
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_STATIC (36);
|
DEFINE_SIZE_STATIC (36);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct hhea : _hea {
|
||||||
|
static const hb_tag_t tableTag = HB_OT_TAG_hhea;
|
||||||
|
};
|
||||||
|
struct vhea : _hea {
|
||||||
|
static const hb_tag_t tableTag = HB_OT_TAG_vhea;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} /* namespace OT */
|
} /* namespace OT */
|
||||||
|
|
||||||
|
37
src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
vendored
37
src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
vendored
@ -35,22 +35,27 @@ namespace OT {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* hmtx -- The Horizontal Metrics Table
|
* hmtx -- The Horizontal Metrics Table
|
||||||
|
* vmtx -- The Vertical Metrics Table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define HB_OT_TAG_hmtx HB_TAG('h','m','t','x')
|
#define HB_OT_TAG_hmtx HB_TAG('h','m','t','x')
|
||||||
|
#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
|
||||||
|
|
||||||
|
|
||||||
struct LongHorMetric
|
struct LongMetric
|
||||||
{
|
{
|
||||||
USHORT advanceWidth;
|
USHORT advance; /* Advance width/height. */
|
||||||
SHORT lsb;
|
SHORT lsb; /* Leading (left/top) side bearing. */
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_STATIC (4);
|
DEFINE_SIZE_STATIC (4);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hmtx
|
struct _mtx
|
||||||
{
|
{
|
||||||
static const hb_tag_t tableTag = HB_OT_TAG_hmtx;
|
static const hb_tag_t tableTag = HB_TAG('_','m','t','x');
|
||||||
|
|
||||||
|
static const hb_tag_t hmtxTag = HB_OT_TAG_hmtx;
|
||||||
|
static const hb_tag_t vmtxTag = HB_OT_TAG_vmtx;
|
||||||
|
|
||||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
@ -60,7 +65,7 @@ struct hmtx
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LongHorMetric longHorMetric[VAR]; /* Paired advance width and left side
|
LongMetric longMetric[VAR]; /* Paired advance width and leading
|
||||||
* bearing values for each glyph. The
|
* bearing values for each glyph. The
|
||||||
* value numOfHMetrics comes from
|
* value numOfHMetrics comes from
|
||||||
* the 'hhea' table. If the font is
|
* the 'hhea' table. If the font is
|
||||||
@ -68,23 +73,29 @@ struct hmtx
|
|||||||
* be in the array, but that entry is
|
* be in the array, but that entry is
|
||||||
* required. The last entry applies to
|
* required. The last entry applies to
|
||||||
* all subsequent glyphs. */
|
* all subsequent glyphs. */
|
||||||
SHORT leftSideBearingX[VAR]; /* Here the advanceWidth is assumed
|
SHORT leadingBearingX[VAR]; /* Here the advance is assumed
|
||||||
* to be the same as the advanceWidth
|
* to be the same as the advance
|
||||||
* for the last entry above. The
|
* for the last entry above. The
|
||||||
* number of entries in this array is
|
* number of entries in this array is
|
||||||
* derived from numGlyphs (from 'maxp'
|
* derived from numGlyphs (from 'maxp'
|
||||||
* table) minus numberOfHMetrics. This
|
* table) minus numberOfLongMetrics.
|
||||||
* generally is used with a run of
|
* This generally is used with a run
|
||||||
* monospaced glyphs (e.g., Kanji
|
* of monospaced glyphs (e.g., Kanji
|
||||||
* fonts or Courier fonts). Only one
|
* fonts or Courier fonts). Only one
|
||||||
* run is allowed and it must be at
|
* run is allowed and it must be at
|
||||||
* the end. This allows a monospaced
|
* the end. This allows a monospaced
|
||||||
* font to vary the left side bearing
|
* font to vary the side bearing
|
||||||
* values for each glyph. */
|
* values for each glyph. */
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_ARRAY2 (0, longHorMetric, leftSideBearingX);
|
DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct hmtx : _mtx {
|
||||||
|
static const hb_tag_t tableTag = HB_OT_TAG_hmtx;
|
||||||
|
};
|
||||||
|
struct vmtx : _mtx {
|
||||||
|
static const hb_tag_t tableTag = HB_OT_TAG_vmtx;
|
||||||
|
};
|
||||||
|
|
||||||
} /* namespace OT */
|
} /* namespace OT */
|
||||||
|
|
||||||
|
@ -345,8 +345,8 @@ struct AnchorMatrix
|
|||||||
inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const {
|
inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const {
|
||||||
*found = false;
|
*found = false;
|
||||||
if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
|
if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
|
||||||
*found = !matrix[row * cols + col].is_null ();
|
*found = !matrixZ[row * cols + col].is_null ();
|
||||||
return this+matrix[row * cols + col];
|
return this+matrixZ[row * cols + col];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) {
|
inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) {
|
||||||
@ -354,19 +354,19 @@ struct AnchorMatrix
|
|||||||
if (!c->check_struct (this)) return TRACE_RETURN (false);
|
if (!c->check_struct (this)) return TRACE_RETURN (false);
|
||||||
if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return TRACE_RETURN (false);
|
if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return TRACE_RETURN (false);
|
||||||
unsigned int count = rows * cols;
|
unsigned int count = rows * cols;
|
||||||
if (!c->check_array (matrix, matrix[0].static_size, count)) return TRACE_RETURN (false);
|
if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return TRACE_RETURN (false);
|
||||||
for (unsigned int i = 0; i < count; i++)
|
for (unsigned int i = 0; i < count; i++)
|
||||||
if (!matrix[i].sanitize (c, this)) return TRACE_RETURN (false);
|
if (!matrixZ[i].sanitize (c, this)) return TRACE_RETURN (false);
|
||||||
return TRACE_RETURN (true);
|
return TRACE_RETURN (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
USHORT rows; /* Number of rows */
|
USHORT rows; /* Number of rows */
|
||||||
protected:
|
protected:
|
||||||
OffsetTo<Anchor>
|
OffsetTo<Anchor>
|
||||||
matrix[VAR]; /* Matrix of offsets to Anchor tables--
|
matrixZ[VAR]; /* Matrix of offsets to Anchor tables--
|
||||||
* from beginning of AnchorMatrix table */
|
* from beginning of AnchorMatrix table */
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_ARRAY (2, matrix);
|
DEFINE_SIZE_ARRAY (2, matrixZ);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -530,7 +530,7 @@ struct SinglePos
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, u.format);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
||||||
case 2: return TRACE_RETURN (c->dispatch (u.format2));
|
case 2: return TRACE_RETURN (c->dispatch (u.format2));
|
||||||
@ -583,7 +583,7 @@ struct PairSet
|
|||||||
unsigned int len2 = valueFormats[1].get_len ();
|
unsigned int len2 = valueFormats[1].get_len ();
|
||||||
unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
|
unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
|
||||||
|
|
||||||
const PairValueRecord *record = CastP<PairValueRecord> (array);
|
const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
|
||||||
unsigned int count = len;
|
unsigned int count = len;
|
||||||
for (unsigned int i = 0; i < count; i++)
|
for (unsigned int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
@ -602,12 +602,24 @@ struct PairSet
|
|||||||
unsigned int len2 = valueFormats[1].get_len ();
|
unsigned int len2 = valueFormats[1].get_len ();
|
||||||
unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
|
unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
|
||||||
|
|
||||||
const PairValueRecord *record = CastP<PairValueRecord> (array);
|
const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
|
||||||
unsigned int count = len;
|
unsigned int count = len;
|
||||||
for (unsigned int i = 0; i < count; i++)
|
|
||||||
|
/* Hand-coded bsearch. */
|
||||||
|
if (unlikely (!count))
|
||||||
|
return TRACE_RETURN (false);
|
||||||
|
hb_codepoint_t x = buffer->info[pos].codepoint;
|
||||||
|
int min = 0, max = (int) count - 1;
|
||||||
|
while (min <= max)
|
||||||
{
|
{
|
||||||
/* TODO bsearch */
|
int mid = (min + max) / 2;
|
||||||
if (buffer->info[pos].codepoint == record->secondGlyph)
|
const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid);
|
||||||
|
hb_codepoint_t mid_x = record->secondGlyph;
|
||||||
|
if (x < mid_x)
|
||||||
|
max = mid - 1;
|
||||||
|
else if (x > mid_x)
|
||||||
|
min = mid + 1;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
valueFormats[0].apply_value (c->font, c->direction, this,
|
valueFormats[0].apply_value (c->font, c->direction, this,
|
||||||
&record->values[0], buffer->cur_pos());
|
&record->values[0], buffer->cur_pos());
|
||||||
@ -618,7 +630,6 @@ struct PairSet
|
|||||||
buffer->idx = pos;
|
buffer->idx = pos;
|
||||||
return TRACE_RETURN (true);
|
return TRACE_RETURN (true);
|
||||||
}
|
}
|
||||||
record = &StructAtOffset<PairValueRecord> (record, record_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRACE_RETURN (false);
|
return TRACE_RETURN (false);
|
||||||
@ -634,20 +645,20 @@ struct PairSet
|
|||||||
inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) {
|
inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) {
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
if (!(c->check_struct (this)
|
if (!(c->check_struct (this)
|
||||||
&& c->check_array (array, USHORT::static_size * closure->stride, len))) return TRACE_RETURN (false);
|
&& c->check_array (arrayZ, USHORT::static_size * closure->stride, len))) return TRACE_RETURN (false);
|
||||||
|
|
||||||
unsigned int count = len;
|
unsigned int count = len;
|
||||||
PairValueRecord *record = CastP<PairValueRecord> (array);
|
PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
|
||||||
return TRACE_RETURN (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride)
|
return TRACE_RETURN (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride)
|
||||||
&& closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
|
&& closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
USHORT len; /* Number of PairValueRecords */
|
USHORT len; /* Number of PairValueRecords */
|
||||||
USHORT array[VAR]; /* Array of PairValueRecords--ordered
|
USHORT arrayZ[VAR]; /* Array of PairValueRecords--ordered
|
||||||
* by GlyphID of the second glyph */
|
* by GlyphID of the second glyph */
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_ARRAY (2, array);
|
DEFINE_SIZE_ARRAY (2, arrayZ);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PairPosFormat1
|
struct PairPosFormat1
|
||||||
@ -822,7 +833,7 @@ struct PairPos
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, u.format);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
||||||
case 2: return TRACE_RETURN (c->dispatch (u.format2));
|
case 2: return TRACE_RETURN (c->dispatch (u.format2));
|
||||||
@ -989,7 +1000,7 @@ struct CursivePos
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, u.format);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
||||||
default:return TRACE_RETURN (c->default_return_value ());
|
default:return TRACE_RETURN (c->default_return_value ());
|
||||||
@ -1088,7 +1099,7 @@ struct MarkBasePos
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, u.format);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
||||||
default:return TRACE_RETURN (c->default_return_value ());
|
default:return TRACE_RETURN (c->default_return_value ());
|
||||||
@ -1209,7 +1220,7 @@ struct MarkLigPos
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, u.format);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
||||||
default:return TRACE_RETURN (c->default_return_value ());
|
default:return TRACE_RETURN (c->default_return_value ());
|
||||||
@ -1328,7 +1339,7 @@ struct MarkMarkPos
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, u.format);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
||||||
default:return TRACE_RETURN (c->default_return_value ());
|
default:return TRACE_RETURN (c->default_return_value ());
|
||||||
@ -1387,7 +1398,7 @@ struct PosLookupSubTable
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
|
inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, lookup_type);
|
||||||
switch (lookup_type) {
|
switch (lookup_type) {
|
||||||
case Single: return TRACE_RETURN (u.single.dispatch (c));
|
case Single: return TRACE_RETURN (u.single.dispatch (c));
|
||||||
case Pair: return TRACE_RETURN (u.pair.dispatch (c));
|
case Pair: return TRACE_RETURN (u.pair.dispatch (c));
|
||||||
@ -1488,8 +1499,8 @@ struct PosLookup : Lookup
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
|
||||||
unsigned int lookup_type = get_type ();
|
unsigned int lookup_type = get_type ();
|
||||||
|
TRACE_DISPATCH (this, lookup_type);
|
||||||
unsigned int count = get_subtable_count ();
|
unsigned int count = get_subtable_count ();
|
||||||
for (unsigned int i = 0; i < count; i++) {
|
for (unsigned int i = 0; i < count; i++) {
|
||||||
typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type);
|
typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type);
|
||||||
@ -1589,6 +1600,8 @@ GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
|
|||||||
void
|
void
|
||||||
GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
|
GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
|
||||||
{
|
{
|
||||||
|
_hb_buffer_assert_gsubgpos_vars (buffer);
|
||||||
|
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
|
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
|
||||||
hb_direction_t direction = buffer->props.direction;
|
hb_direction_t direction = buffer->props.direction;
|
||||||
@ -1600,8 +1613,6 @@ GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
|
|||||||
/* Handle attachments */
|
/* Handle attachments */
|
||||||
for (unsigned int i = 0; i < len; i++)
|
for (unsigned int i = 0; i < len; i++)
|
||||||
fix_mark_attachment (pos, i, direction);
|
fix_mark_attachment (pos, i, direction);
|
||||||
|
|
||||||
_hb_buffer_deallocate_gsubgpos_vars (buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ struct SingleSubst
|
|||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
|
if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
|
||||||
unsigned int format = 2;
|
unsigned int format = 2;
|
||||||
int delta;
|
int delta = 0;
|
||||||
if (num_glyphs) {
|
if (num_glyphs) {
|
||||||
format = 1;
|
format = 1;
|
||||||
/* TODO(serialize) check for wrap-around */
|
/* TODO(serialize) check for wrap-around */
|
||||||
@ -222,7 +222,7 @@ struct SingleSubst
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, u.format);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
||||||
case 2: return TRACE_RETURN (c->dispatch (u.format2));
|
case 2: return TRACE_RETURN (c->dispatch (u.format2));
|
||||||
@ -422,7 +422,7 @@ struct MultipleSubst
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, u.format);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
||||||
default:return TRACE_RETURN (c->default_return_value ());
|
default:return TRACE_RETURN (c->default_return_value ());
|
||||||
@ -573,7 +573,7 @@ struct AlternateSubst
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, u.format);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
||||||
default:return TRACE_RETURN (c->default_return_value ());
|
default:return TRACE_RETURN (c->default_return_value ());
|
||||||
@ -889,7 +889,7 @@ struct LigatureSubst
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, u.format);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
||||||
default:return TRACE_RETURN (c->default_return_value ());
|
default:return TRACE_RETURN (c->default_return_value ());
|
||||||
@ -1053,7 +1053,7 @@ struct ReverseChainSingleSubst
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, u.format);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
||||||
default:return TRACE_RETURN (c->default_return_value ());
|
default:return TRACE_RETURN (c->default_return_value ());
|
||||||
@ -1100,7 +1100,7 @@ struct SubstLookupSubTable
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
|
inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, lookup_type);
|
||||||
switch (lookup_type) {
|
switch (lookup_type) {
|
||||||
case Single: return TRACE_RETURN (u.single.dispatch (c));
|
case Single: return TRACE_RETURN (u.single.dispatch (c));
|
||||||
case Multiple: return TRACE_RETURN (u.multiple.dispatch (c));
|
case Multiple: return TRACE_RETURN (u.multiple.dispatch (c));
|
||||||
@ -1275,8 +1275,8 @@ struct SubstLookup : Lookup
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
|
||||||
unsigned int lookup_type = get_type ();
|
unsigned int lookup_type = get_type ();
|
||||||
|
TRACE_DISPATCH (this, lookup_type);
|
||||||
unsigned int count = get_subtable_count ();
|
unsigned int count = get_subtable_count ();
|
||||||
for (unsigned int i = 0; i < count; i++) {
|
for (unsigned int i = 0; i < count; i++) {
|
||||||
typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type);
|
typename context_t::return_t r = get_subtable (i).dispatch (c, lookup_type);
|
||||||
@ -1338,7 +1338,7 @@ struct GSUB : GSUBGPOS
|
|||||||
void
|
void
|
||||||
GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
|
GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
|
||||||
{
|
{
|
||||||
_hb_buffer_allocate_gsubgpos_vars (buffer);
|
_hb_buffer_assert_gsubgpos_vars (buffer);
|
||||||
|
|
||||||
const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
|
const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
|
||||||
unsigned int count = buffer->len;
|
unsigned int count = buffer->len;
|
||||||
|
@ -38,10 +38,10 @@ namespace OT {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_DISPATCH(this) \
|
#define TRACE_DISPATCH(this, format) \
|
||||||
hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
|
hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
|
||||||
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
|
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
|
||||||
"");
|
"format %d", (int) format);
|
||||||
|
|
||||||
#ifndef HB_DEBUG_CLOSURE
|
#ifndef HB_DEBUG_CLOSURE
|
||||||
#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
|
#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
|
||||||
@ -168,6 +168,10 @@ struct hb_collect_glyphs_context_t
|
|||||||
if (output == hb_set_get_empty ())
|
if (output == hb_set_get_empty ())
|
||||||
return HB_VOID;
|
return HB_VOID;
|
||||||
|
|
||||||
|
/* Return if new lookup was recursed to before. */
|
||||||
|
if (recursed_lookups.has (lookup_index))
|
||||||
|
return HB_VOID;
|
||||||
|
|
||||||
hb_set_t *old_before = before;
|
hb_set_t *old_before = before;
|
||||||
hb_set_t *old_input = input;
|
hb_set_t *old_input = input;
|
||||||
hb_set_t *old_after = after;
|
hb_set_t *old_after = after;
|
||||||
@ -181,6 +185,8 @@ struct hb_collect_glyphs_context_t
|
|||||||
input = old_input;
|
input = old_input;
|
||||||
after = old_after;
|
after = old_after;
|
||||||
|
|
||||||
|
recursed_lookups.add (lookup_index);
|
||||||
|
|
||||||
return HB_VOID;
|
return HB_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +196,7 @@ struct hb_collect_glyphs_context_t
|
|||||||
hb_set_t *after;
|
hb_set_t *after;
|
||||||
hb_set_t *output;
|
hb_set_t *output;
|
||||||
recurse_func_t recurse_func;
|
recurse_func_t recurse_func;
|
||||||
|
hb_set_t recursed_lookups;
|
||||||
unsigned int nesting_level_left;
|
unsigned int nesting_level_left;
|
||||||
unsigned int debug_depth;
|
unsigned int debug_depth;
|
||||||
|
|
||||||
@ -205,18 +212,30 @@ struct hb_collect_glyphs_context_t
|
|||||||
after (glyphs_after ? glyphs_after : hb_set_get_empty ()),
|
after (glyphs_after ? glyphs_after : hb_set_get_empty ()),
|
||||||
output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
|
output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
|
||||||
recurse_func (NULL),
|
recurse_func (NULL),
|
||||||
|
recursed_lookups (),
|
||||||
nesting_level_left (nesting_level_left_),
|
nesting_level_left (nesting_level_left_),
|
||||||
debug_depth (0) {}
|
debug_depth (0)
|
||||||
|
{
|
||||||
|
recursed_lookups.init ();
|
||||||
|
}
|
||||||
|
~hb_collect_glyphs_context_t (void)
|
||||||
|
{
|
||||||
|
recursed_lookups.fini ();
|
||||||
|
}
|
||||||
|
|
||||||
void set_recurse_func (recurse_func_t func) { recurse_func = func; }
|
void set_recurse_func (recurse_func_t func) { recurse_func = func; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_GET_COVERAGE
|
||||||
|
#define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct hb_get_coverage_context_t
|
struct hb_get_coverage_context_t
|
||||||
{
|
{
|
||||||
inline const char *get_name (void) { return "GET_COVERAGE"; }
|
inline const char *get_name (void) { return "GET_COVERAGE"; }
|
||||||
static const unsigned int max_debug_depth = 0;
|
static const unsigned int max_debug_depth = HB_DEBUG_GET_COVERAGE;
|
||||||
typedef const Coverage &return_t;
|
typedef const Coverage &return_t;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
|
inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
|
||||||
@ -1117,9 +1136,9 @@ struct Rule
|
|||||||
inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
|
inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
|
||||||
{
|
{
|
||||||
TRACE_CLOSURE (this);
|
TRACE_CLOSURE (this);
|
||||||
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
|
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
|
||||||
context_closure_lookup (c,
|
context_closure_lookup (c,
|
||||||
inputCount, input,
|
inputCount, inputZ,
|
||||||
lookupCount, lookupRecord,
|
lookupCount, lookupRecord,
|
||||||
lookup_context);
|
lookup_context);
|
||||||
}
|
}
|
||||||
@ -1127,9 +1146,9 @@ struct Rule
|
|||||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
|
inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
|
||||||
{
|
{
|
||||||
TRACE_COLLECT_GLYPHS (this);
|
TRACE_COLLECT_GLYPHS (this);
|
||||||
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
|
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
|
||||||
context_collect_glyphs_lookup (c,
|
context_collect_glyphs_lookup (c,
|
||||||
inputCount, input,
|
inputCount, inputZ,
|
||||||
lookupCount, lookupRecord,
|
lookupCount, lookupRecord,
|
||||||
lookup_context);
|
lookup_context);
|
||||||
}
|
}
|
||||||
@ -1137,15 +1156,15 @@ struct Rule
|
|||||||
inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
|
inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
|
||||||
{
|
{
|
||||||
TRACE_WOULD_APPLY (this);
|
TRACE_WOULD_APPLY (this);
|
||||||
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
|
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
|
||||||
return TRACE_RETURN (context_would_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
|
return TRACE_RETURN (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
|
inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
|
||||||
{
|
{
|
||||||
TRACE_APPLY (this);
|
TRACE_APPLY (this);
|
||||||
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
|
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
|
||||||
return TRACE_RETURN (context_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
|
return TRACE_RETURN (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -1153,8 +1172,8 @@ struct Rule
|
|||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
return inputCount.sanitize (c)
|
return inputCount.sanitize (c)
|
||||||
&& lookupCount.sanitize (c)
|
&& lookupCount.sanitize (c)
|
||||||
&& c->check_range (input,
|
&& c->check_range (inputZ,
|
||||||
input[0].static_size * inputCount
|
inputZ[0].static_size * inputCount
|
||||||
+ lookupRecordX[0].static_size * lookupCount);
|
+ lookupRecordX[0].static_size * lookupCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1163,12 +1182,12 @@ struct Rule
|
|||||||
* glyph sequence--includes the first
|
* glyph sequence--includes the first
|
||||||
* glyph */
|
* glyph */
|
||||||
USHORT lookupCount; /* Number of LookupRecords */
|
USHORT lookupCount; /* Number of LookupRecords */
|
||||||
USHORT input[VAR]; /* Array of match inputs--start with
|
USHORT inputZ[VAR]; /* Array of match inputs--start with
|
||||||
* second glyph */
|
* second glyph */
|
||||||
LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
|
LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
|
||||||
* design order */
|
* design order */
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_ARRAY2 (4, input, lookupRecordX);
|
DEFINE_SIZE_ARRAY2 (4, inputZ, lookupRecordX);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RuleSet
|
struct RuleSet
|
||||||
@ -1413,16 +1432,16 @@ struct ContextFormat3
|
|||||||
inline void closure (hb_closure_context_t *c) const
|
inline void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_CLOSURE (this);
|
TRACE_CLOSURE (this);
|
||||||
if (!(this+coverage[0]).intersects (c->glyphs))
|
if (!(this+coverageZ[0]).intersects (c->glyphs))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
|
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
|
||||||
struct ContextClosureLookupContext lookup_context = {
|
struct ContextClosureLookupContext lookup_context = {
|
||||||
{intersects_coverage},
|
{intersects_coverage},
|
||||||
this
|
this
|
||||||
};
|
};
|
||||||
context_closure_lookup (c,
|
context_closure_lookup (c,
|
||||||
glyphCount, (const USHORT *) (coverage + 1),
|
glyphCount, (const USHORT *) (coverageZ + 1),
|
||||||
lookupCount, lookupRecord,
|
lookupCount, lookupRecord,
|
||||||
lookup_context);
|
lookup_context);
|
||||||
}
|
}
|
||||||
@ -1430,16 +1449,16 @@ struct ContextFormat3
|
|||||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_COLLECT_GLYPHS (this);
|
TRACE_COLLECT_GLYPHS (this);
|
||||||
(this+coverage[0]).add_coverage (c->input);
|
(this+coverageZ[0]).add_coverage (c->input);
|
||||||
|
|
||||||
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
|
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
|
||||||
struct ContextCollectGlyphsLookupContext lookup_context = {
|
struct ContextCollectGlyphsLookupContext lookup_context = {
|
||||||
{collect_coverage},
|
{collect_coverage},
|
||||||
this
|
this
|
||||||
};
|
};
|
||||||
|
|
||||||
context_collect_glyphs_lookup (c,
|
context_collect_glyphs_lookup (c,
|
||||||
glyphCount, (const USHORT *) (coverage + 1),
|
glyphCount, (const USHORT *) (coverageZ + 1),
|
||||||
lookupCount, lookupRecord,
|
lookupCount, lookupRecord,
|
||||||
lookup_context);
|
lookup_context);
|
||||||
}
|
}
|
||||||
@ -1448,41 +1467,42 @@ struct ContextFormat3
|
|||||||
{
|
{
|
||||||
TRACE_WOULD_APPLY (this);
|
TRACE_WOULD_APPLY (this);
|
||||||
|
|
||||||
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
|
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
|
||||||
struct ContextApplyLookupContext lookup_context = {
|
struct ContextApplyLookupContext lookup_context = {
|
||||||
{match_coverage},
|
{match_coverage},
|
||||||
this
|
this
|
||||||
};
|
};
|
||||||
return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
|
return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Coverage &get_coverage (void) const
|
inline const Coverage &get_coverage (void) const
|
||||||
{
|
{
|
||||||
return this+coverage[0];
|
return this+coverageZ[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool apply (hb_apply_context_t *c) const
|
inline bool apply (hb_apply_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_APPLY (this);
|
TRACE_APPLY (this);
|
||||||
unsigned int index = (this+coverage[0]).get_coverage (c->buffer->cur().codepoint);
|
unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
|
||||||
if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
|
if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
|
||||||
|
|
||||||
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
|
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
|
||||||
struct ContextApplyLookupContext lookup_context = {
|
struct ContextApplyLookupContext lookup_context = {
|
||||||
{match_coverage},
|
{match_coverage},
|
||||||
this
|
this
|
||||||
};
|
};
|
||||||
return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
|
return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
if (!c->check_struct (this)) return TRACE_RETURN (false);
|
if (!c->check_struct (this)) return TRACE_RETURN (false);
|
||||||
unsigned int count = glyphCount;
|
unsigned int count = glyphCount;
|
||||||
if (!c->check_array (coverage, coverage[0].static_size, count)) return TRACE_RETURN (false);
|
if (!count) return TRACE_RETURN (false); /* We want to access coverageZ[0] freely. */
|
||||||
|
if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return TRACE_RETURN (false);
|
||||||
for (unsigned int i = 0; i < count; i++)
|
for (unsigned int i = 0; i < count; i++)
|
||||||
if (!coverage[i].sanitize (c, this)) return TRACE_RETURN (false);
|
if (!coverageZ[i].sanitize (c, this)) return TRACE_RETURN (false);
|
||||||
LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * count);
|
LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
|
||||||
return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
|
return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1492,12 +1512,12 @@ struct ContextFormat3
|
|||||||
* sequence */
|
* sequence */
|
||||||
USHORT lookupCount; /* Number of LookupRecords */
|
USHORT lookupCount; /* Number of LookupRecords */
|
||||||
OffsetTo<Coverage>
|
OffsetTo<Coverage>
|
||||||
coverage[VAR]; /* Array of offsets to Coverage
|
coverageZ[VAR]; /* Array of offsets to Coverage
|
||||||
* table in glyph sequence order */
|
* table in glyph sequence order */
|
||||||
LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
|
LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
|
||||||
* design order */
|
* design order */
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_ARRAY2 (6, coverage, lookupRecordX);
|
DEFINE_SIZE_ARRAY2 (6, coverageZ, lookupRecordX);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Context
|
struct Context
|
||||||
@ -1505,7 +1525,7 @@ struct Context
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, u.format);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
||||||
case 2: return TRACE_RETURN (c->dispatch (u.format2));
|
case 2: return TRACE_RETURN (c->dispatch (u.format2));
|
||||||
@ -2090,6 +2110,7 @@ struct ChainContextFormat3
|
|||||||
if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
|
if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
|
||||||
OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
|
OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
|
||||||
if (!input.sanitize (c, this)) return TRACE_RETURN (false);
|
if (!input.sanitize (c, this)) return TRACE_RETURN (false);
|
||||||
|
if (!input.len) return TRACE_RETURN (false); /* To be consistent with Context. */
|
||||||
OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
|
OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
|
||||||
if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
|
if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
|
||||||
ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
|
ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
|
||||||
@ -2122,7 +2143,7 @@ struct ChainContext
|
|||||||
template <typename context_t>
|
template <typename context_t>
|
||||||
inline typename context_t::return_t dispatch (context_t *c) const
|
inline typename context_t::return_t dispatch (context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_DISPATCH (this);
|
TRACE_DISPATCH (this, u.format);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
case 1: return TRACE_RETURN (c->dispatch (u.format1));
|
||||||
case 2: return TRACE_RETURN (c->dispatch (u.format2));
|
case 2: return TRACE_RETURN (c->dispatch (u.format2));
|
||||||
|
@ -126,8 +126,7 @@ struct hb_ot_layout_lookup_accelerator_t
|
|||||||
lookup.add_coverage (&digest);
|
lookup.add_coverage (&digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TLookup>
|
inline void fini (void)
|
||||||
inline void fini (const TLookup &lookup)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,6 +418,13 @@ _hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
|
|||||||
HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props1);
|
HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
|
||||||
|
{
|
||||||
|
HB_BUFFER_ASSERT_VAR (buffer, unicode_props0);
|
||||||
|
HB_BUFFER_ASSERT_VAR (buffer, unicode_props1);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
_hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
|
_hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
|
||||||
{
|
{
|
||||||
@ -435,6 +441,14 @@ _hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
|
|||||||
HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
|
HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
|
||||||
|
{
|
||||||
|
HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
|
||||||
|
HB_BUFFER_ASSERT_VAR (buffer, lig_props);
|
||||||
|
HB_BUFFER_ASSERT_VAR (buffer, syllable);
|
||||||
|
}
|
||||||
|
|
||||||
/* Make sure no one directly touches our props... */
|
/* Make sure no one directly touches our props... */
|
||||||
#undef unicode_props0
|
#undef unicode_props0
|
||||||
#undef unicode_props1
|
#undef unicode_props1
|
||||||
|
4
src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
vendored
4
src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
vendored
@ -84,9 +84,9 @@ void
|
|||||||
_hb_ot_layout_destroy (hb_ot_layout_t *layout)
|
_hb_ot_layout_destroy (hb_ot_layout_t *layout)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
|
for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
|
||||||
layout->gsub_accels[i].fini (layout->gsub->get_lookup (i));
|
layout->gsub_accels[i].fini ();
|
||||||
for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
|
for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
|
||||||
layout->gpos_accels[i].fini (layout->gpos->get_lookup (i));
|
layout->gpos_accels[i].fini ();
|
||||||
|
|
||||||
free (layout->gsub_accels);
|
free (layout->gsub_accels);
|
||||||
free (layout->gpos_accels);
|
free (layout->gpos_accels);
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
#include "hb-ot-layout-gsub-table.hh"
|
#include "hb-ot-layout-gsub-table.hh"
|
||||||
|
|
||||||
|
|
||||||
|
/* Features ordered the same as the entries in shaping_table rows,
|
||||||
|
* followed by rlig. Don't change. */
|
||||||
static const hb_tag_t arabic_fallback_features[] =
|
static const hb_tag_t arabic_fallback_features[] =
|
||||||
{
|
{
|
||||||
HB_TAG('i','n','i','t'),
|
HB_TAG('i','n','i','t'),
|
||||||
@ -42,16 +44,6 @@ static const hb_tag_t arabic_fallback_features[] =
|
|||||||
HB_TAG('r','l','i','g'),
|
HB_TAG('r','l','i','g'),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Same order as the fallback feature array */
|
|
||||||
enum {
|
|
||||||
FALLBACK_INIT,
|
|
||||||
FALLBACK_MEDI,
|
|
||||||
FALLBACK_FINA,
|
|
||||||
FALLBACK_ISOL,
|
|
||||||
FALLBACK_RLIG,
|
|
||||||
ARABIC_NUM_FALLBACK_FEATURES
|
|
||||||
};
|
|
||||||
|
|
||||||
static OT::SubstLookup *
|
static OT::SubstLookup *
|
||||||
arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||||
hb_font_t *font,
|
hb_font_t *font,
|
||||||
@ -80,6 +72,9 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
|
|||||||
num_glyphs++;
|
num_glyphs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!num_glyphs)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* Bubble-sort!
|
/* Bubble-sort!
|
||||||
* May not be good-enough for presidential candidate interviews, but good-enough for us... */
|
* May not be good-enough for presidential candidate interviews, but good-enough for us... */
|
||||||
hb_bubble_sort (&glyphs[0], num_glyphs, OT::GlyphID::cmp, &substitutes[0]);
|
hb_bubble_sort (&glyphs[0], num_glyphs, OT::GlyphID::cmp, &substitutes[0]);
|
||||||
@ -157,6 +152,9 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!num_ligatures)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
OT::Supplier<OT::GlyphID> first_glyphs_supplier (first_glyphs, num_first_glyphs);
|
OT::Supplier<OT::GlyphID> first_glyphs_supplier (first_glyphs, num_first_glyphs);
|
||||||
OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs);
|
OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs);
|
||||||
OT::Supplier<OT::GlyphID> ligatures_supplier (ligature_list, num_ligatures);
|
OT::Supplier<OT::GlyphID> ligatures_supplier (ligature_list, num_ligatures);
|
||||||
@ -193,17 +191,108 @@ arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan,
|
|||||||
return arabic_fallback_synthesize_lookup_ligature (plan, font);
|
return arabic_fallback_synthesize_lookup_ligature (plan, font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ARABIC_FALLBACK_MAX_LOOKUPS 5
|
||||||
|
|
||||||
struct arabic_fallback_plan_t
|
struct arabic_fallback_plan_t
|
||||||
{
|
{
|
||||||
ASSERT_POD ();
|
ASSERT_POD ();
|
||||||
|
|
||||||
hb_mask_t mask_array[ARABIC_NUM_FALLBACK_FEATURES];
|
unsigned int num_lookups;
|
||||||
OT::SubstLookup *lookup_array[ARABIC_NUM_FALLBACK_FEATURES];
|
bool free_lookups;
|
||||||
hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_NUM_FALLBACK_FEATURES];
|
|
||||||
|
hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS];
|
||||||
|
OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS];
|
||||||
|
hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
|
||||||
};
|
};
|
||||||
|
|
||||||
static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
|
static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
|
||||||
|
|
||||||
|
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256)
|
||||||
|
#define HB_WITH_WIN1256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HB_WITH_WIN1256
|
||||||
|
#include "hb-ot-shape-complex-arabic-win1256.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ManifestLookup {
|
||||||
|
OT::Tag tag;
|
||||||
|
OT::OffsetTo<OT::SubstLookup> lookupOffset;
|
||||||
|
};
|
||||||
|
typedef OT::ArrayOf<ManifestLookup> Manifest;
|
||||||
|
|
||||||
|
static bool
|
||||||
|
arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan,
|
||||||
|
const hb_ot_shape_plan_t *plan,
|
||||||
|
hb_font_t *font)
|
||||||
|
{
|
||||||
|
#ifdef HB_WITH_WIN1256
|
||||||
|
/* Does this font look like it's Windows-1256-encoded? */
|
||||||
|
hb_codepoint_t g;
|
||||||
|
if (!(hb_font_get_glyph (font, 0x0627u, 0, &g) && g == 199 /* ALEF */ &&
|
||||||
|
hb_font_get_glyph (font, 0x0644u, 0, &g) && g == 225 /* LAM */ &&
|
||||||
|
hb_font_get_glyph (font, 0x0649u, 0, &g) && g == 236 /* ALEF MAKSURA */ &&
|
||||||
|
hb_font_get_glyph (font, 0x064Au, 0, &g) && g == 237 /* YEH */ &&
|
||||||
|
hb_font_get_glyph (font, 0x0652u, 0, &g) && g == 250 /* SUKUN */))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const Manifest &manifest = reinterpret_cast<const Manifest&> (arabic_win1256_gsub_lookups.manifest);
|
||||||
|
ASSERT_STATIC (sizeof (arabic_win1256_gsub_lookups.manifestData) / sizeof (ManifestLookup)
|
||||||
|
<= ARABIC_FALLBACK_MAX_LOOKUPS);
|
||||||
|
/* TODO sanitize the table? */
|
||||||
|
|
||||||
|
unsigned j = 0;
|
||||||
|
unsigned int count = manifest.len;
|
||||||
|
for (unsigned int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
fallback_plan->mask_array[j] = plan->map.get_1_mask (manifest[i].tag);
|
||||||
|
if (fallback_plan->mask_array[j])
|
||||||
|
{
|
||||||
|
fallback_plan->lookup_array[j] = const_cast<OT::SubstLookup*> (&(&manifest+manifest[i].lookupOffset));
|
||||||
|
if (fallback_plan->lookup_array[j])
|
||||||
|
{
|
||||||
|
fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fallback_plan->num_lookups = j;
|
||||||
|
fallback_plan->free_lookups = false;
|
||||||
|
|
||||||
|
return j > 0;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan,
|
||||||
|
const hb_ot_shape_plan_t *plan,
|
||||||
|
hb_font_t *font)
|
||||||
|
{
|
||||||
|
ASSERT_STATIC (ARRAY_LENGTH_CONST(arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS);
|
||||||
|
unsigned int j = 0;
|
||||||
|
for (unsigned int i = 0; i < ARRAY_LENGTH(arabic_fallback_features) ; i++)
|
||||||
|
{
|
||||||
|
fallback_plan->mask_array[j] = plan->map.get_1_mask (arabic_fallback_features[i]);
|
||||||
|
if (fallback_plan->mask_array[j])
|
||||||
|
{
|
||||||
|
fallback_plan->lookup_array[j] = arabic_fallback_synthesize_lookup (plan, font, i);
|
||||||
|
if (fallback_plan->lookup_array[j])
|
||||||
|
{
|
||||||
|
fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fallback_plan->num_lookups = j;
|
||||||
|
fallback_plan->free_lookups = true;
|
||||||
|
|
||||||
|
return j > 0;
|
||||||
|
}
|
||||||
|
|
||||||
static arabic_fallback_plan_t *
|
static arabic_fallback_plan_t *
|
||||||
arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
|
arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
|
||||||
hb_font_t *font)
|
hb_font_t *font)
|
||||||
@ -212,17 +301,21 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
|
|||||||
if (unlikely (!fallback_plan))
|
if (unlikely (!fallback_plan))
|
||||||
return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
|
return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
|
fallback_plan->num_lookups = 0;
|
||||||
{
|
fallback_plan->free_lookups = false;
|
||||||
fallback_plan->mask_array[i] = plan->map.get_1_mask (arabic_fallback_features[i]);
|
|
||||||
if (fallback_plan->mask_array[i]) {
|
|
||||||
fallback_plan->lookup_array[i] = arabic_fallback_synthesize_lookup (plan, font, i);
|
|
||||||
if (fallback_plan->lookup_array[i])
|
|
||||||
fallback_plan->accel_array[i].init (*fallback_plan->lookup_array[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fallback_plan;
|
/* Try synthesizing GSUB table using Unicode Arabic Presentation Forms,
|
||||||
|
* in case the font has cmap entries for the presentation-forms characters. */
|
||||||
|
if (arabic_fallback_plan_init_unicode (fallback_plan, plan, font))
|
||||||
|
return fallback_plan;
|
||||||
|
|
||||||
|
/* See if this looks like a Windows-1256-encoded font. If it does, use a
|
||||||
|
* hand-coded GSUB table. */
|
||||||
|
if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font))
|
||||||
|
return fallback_plan;
|
||||||
|
|
||||||
|
free (fallback_plan);
|
||||||
|
return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -231,11 +324,12 @@ arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
|
|||||||
if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil)
|
if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
|
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
|
||||||
if (fallback_plan->lookup_array[i])
|
if (fallback_plan->lookup_array[i])
|
||||||
{
|
{
|
||||||
fallback_plan->accel_array[i].fini (fallback_plan->lookup_array[i]);
|
fallback_plan->accel_array[i].fini ();
|
||||||
free (fallback_plan->lookup_array[i]);
|
if (fallback_plan->free_lookups)
|
||||||
|
free (fallback_plan->lookup_array[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
free (fallback_plan);
|
free (fallback_plan);
|
||||||
@ -247,7 +341,7 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
|
|||||||
hb_buffer_t *buffer)
|
hb_buffer_t *buffer)
|
||||||
{
|
{
|
||||||
OT::hb_apply_context_t c (0, font, buffer);
|
OT::hb_apply_context_t c (0, font, buffer);
|
||||||
for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
|
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
|
||||||
if (fallback_plan->lookup_array[i]) {
|
if (fallback_plan->lookup_array[i]) {
|
||||||
c.set_lookup_mask (fallback_plan->mask_array[i]);
|
c.set_lookup_mask (fallback_plan->mask_array[i]);
|
||||||
hb_ot_layout_substitute_lookup (&c,
|
hb_ot_layout_substitute_lookup (&c,
|
||||||
|
@ -70,7 +70,7 @@ static const uint8_t joining_table[] =
|
|||||||
|
|
||||||
/* Mandaic */
|
/* Mandaic */
|
||||||
|
|
||||||
/* 0840 */ R,D,D,D,D,D,R,D,D,R,D,D,D,D,D,R,D,D,D,D,R,D,U,U,U,X,X,X,X,X,X,X,
|
/* 0840 */ R,D,D,D,D,D,R,R,D,R,D,D,D,D,D,D,D,D,D,D,R,D,U,U,U,X,X,X,X,X,X,X,
|
||||||
/* 0860 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
/* 0860 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||||
/* 0880 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
/* 0880 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||||
|
|
||||||
|
@ -223,8 +223,8 @@ data_create_arabic (const hb_ot_shape_plan_t *plan)
|
|||||||
for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) {
|
for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) {
|
||||||
arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]);
|
arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]);
|
||||||
arabic_plan->do_fallback = arabic_plan->do_fallback &&
|
arabic_plan->do_fallback = arabic_plan->do_fallback &&
|
||||||
!FEATURE_IS_SYRIAC (arabic_features[i]) &&
|
(FEATURE_IS_SYRIAC (arabic_features[i]) ||
|
||||||
plan->map.needs_fallback (arabic_features[i]);
|
plan->map.needs_fallback (arabic_features[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return arabic_plan;
|
return arabic_plan;
|
||||||
@ -248,18 +248,17 @@ arabic_joining (hb_buffer_t *buffer)
|
|||||||
unsigned int prev = (unsigned int) -1, state = 0;
|
unsigned int prev = (unsigned int) -1, state = 0;
|
||||||
|
|
||||||
/* Check pre-context */
|
/* Check pre-context */
|
||||||
if (!(buffer->flags & HB_BUFFER_FLAG_BOT))
|
for (unsigned int i = 0; i < buffer->context_len[0]; i++)
|
||||||
for (unsigned int i = 0; i < buffer->context_len[0]; i++)
|
{
|
||||||
{
|
unsigned int this_type = get_joining_type (buffer->context[0][i], buffer->unicode->general_category (buffer->context[0][i]));
|
||||||
unsigned int this_type = get_joining_type (buffer->context[0][i], buffer->unicode->general_category (buffer->context[0][i]));
|
|
||||||
|
|
||||||
if (unlikely (this_type == JOINING_TYPE_T))
|
if (unlikely (this_type == JOINING_TYPE_T))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
|
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
|
||||||
state = entry->next_state;
|
state = entry->next_state;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < count; i++)
|
for (unsigned int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
@ -281,19 +280,18 @@ arabic_joining (hb_buffer_t *buffer)
|
|||||||
state = entry->next_state;
|
state = entry->next_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(buffer->flags & HB_BUFFER_FLAG_EOT))
|
for (unsigned int i = 0; i < buffer->context_len[1]; i++)
|
||||||
for (unsigned int i = 0; i < buffer->context_len[1]; i++)
|
{
|
||||||
{
|
unsigned int this_type = get_joining_type (buffer->context[1][i], buffer->unicode->general_category (buffer->context[1][i]));
|
||||||
unsigned int this_type = get_joining_type (buffer->context[1][i], buffer->unicode->general_category (buffer->context[1][i]));
|
|
||||||
|
|
||||||
if (unlikely (this_type == JOINING_TYPE_T))
|
if (unlikely (this_type == JOINING_TYPE_T))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
|
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
|
||||||
if (entry->prev_action != NONE && prev != (unsigned int) -1)
|
if (entry->prev_action != NONE && prev != (unsigned int) -1)
|
||||||
info[prev].arabic_shaping_action() = entry->prev_action;
|
info[prev].arabic_shaping_action() = entry->prev_action;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -59,6 +59,15 @@ collect_features_hangul (hb_ot_shape_planner_t *plan)
|
|||||||
map->add_feature (hangul_features[i], 1, F_NONE);
|
map->add_feature (hangul_features[i], 1, F_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
override_features_hangul (hb_ot_shape_planner_t *plan)
|
||||||
|
{
|
||||||
|
/* Uniscribe does not apply 'calt' for Hangul, and certain fonts
|
||||||
|
* (Noto Sans CJK, Source Sans Han, etc) apply all of jamo lookups
|
||||||
|
* in calt, which is not desirable. */
|
||||||
|
plan->map.add_feature (HB_TAG('c','a','l','t'), 0, F_GLOBAL);
|
||||||
|
}
|
||||||
|
|
||||||
struct hangul_shape_plan_t
|
struct hangul_shape_plan_t
|
||||||
{
|
{
|
||||||
ASSERT_POD ();
|
ASSERT_POD ();
|
||||||
@ -404,7 +413,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
|
|||||||
{
|
{
|
||||||
"hangul",
|
"hangul",
|
||||||
collect_features_hangul,
|
collect_features_hangul,
|
||||||
NULL, /* override_features */
|
override_features_hangul,
|
||||||
data_create_hangul, /* data_create */
|
data_create_hangul, /* data_create */
|
||||||
data_destroy_hangul, /* data_destroy */
|
data_destroy_hangul, /* data_destroy */
|
||||||
preprocess_text_hangul,
|
preprocess_text_hangul,
|
||||||
|
@ -167,6 +167,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
|
|||||||
NULL, /* decompose */
|
NULL, /* decompose */
|
||||||
compose_hebrew,
|
compose_hebrew,
|
||||||
NULL, /* setup_masks */
|
NULL, /* setup_masks */
|
||||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT,
|
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
|
||||||
true, /* fallback_position */
|
true, /* fallback_position */
|
||||||
};
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -861,41 +861,41 @@ hb_indic_get_categories (hb_codepoint_t u)
|
|||||||
switch (u >> 12)
|
switch (u >> 12)
|
||||||
{
|
{
|
||||||
case 0x0u:
|
case 0x0u:
|
||||||
if (hb_in_range (u, 0x0028u, 0x0040u)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
|
if (hb_in_range (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
|
||||||
if (hb_in_range (u, 0x00D0u, 0x00D8u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u];
|
if (hb_in_range (u, 0x00D0u, 0x00D7u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u];
|
||||||
if (hb_in_range (u, 0x0900u, 0x0DF8u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
|
if (hb_in_range (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
|
||||||
if (unlikely (u == 0x00A0u)) return _(CP,x);
|
if (unlikely (u == 0x00A0u)) return _(CP,x);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1u:
|
case 0x1u:
|
||||||
if (hb_in_range (u, 0x1000u, 0x10A0u)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
|
if (hb_in_range (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
|
||||||
if (hb_in_range (u, 0x1700u, 0x17F0u)) return indic_table[u - 0x1700u + indic_offset_0x1700u];
|
if (hb_in_range (u, 0x1700u, 0x17EFu)) return indic_table[u - 0x1700u + indic_offset_0x1700u];
|
||||||
if (hb_in_range (u, 0x1900u, 0x1AA0u)) return indic_table[u - 0x1900u + indic_offset_0x1900u];
|
if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return indic_table[u - 0x1900u + indic_offset_0x1900u];
|
||||||
if (hb_in_range (u, 0x1B00u, 0x1C50u)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u];
|
if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u];
|
||||||
if (hb_in_range (u, 0x1CD0u, 0x1CF8u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
|
if (hb_in_range (u, 0x1CD0u, 0x1CF7u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2u:
|
case 0x2u:
|
||||||
if (hb_in_range (u, 0x2008u, 0x2018u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
|
if (hb_in_range (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
|
||||||
if (unlikely (u == 0x25CCu)) return _(CP,x);
|
if (unlikely (u == 0x25CCu)) return _(CP,x);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xAu:
|
case 0xAu:
|
||||||
if (hb_in_range (u, 0xA800u, 0xAAF8u)) return indic_table[u - 0xA800u + indic_offset_0xa800u];
|
if (hb_in_range (u, 0xA800u, 0xAAF7u)) return indic_table[u - 0xA800u + indic_offset_0xa800u];
|
||||||
if (hb_in_range (u, 0xABC0u, 0xAC00u)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u];
|
if (hb_in_range (u, 0xABC0u, 0xABFFu)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x10u:
|
case 0x10u:
|
||||||
if (hb_in_range (u, 0x10A00u, 0x10A48u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u];
|
if (hb_in_range (u, 0x10A00u, 0x10A47u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x11u:
|
case 0x11u:
|
||||||
if (hb_in_range (u, 0x11000u, 0x110C0u)) return indic_table[u - 0x11000u + indic_offset_0x11000u];
|
if (hb_in_range (u, 0x11000u, 0x110BFu)) return indic_table[u - 0x11000u + indic_offset_0x11000u];
|
||||||
if (hb_in_range (u, 0x11100u, 0x11238u)) return indic_table[u - 0x11100u + indic_offset_0x11100u];
|
if (hb_in_range (u, 0x11100u, 0x11237u)) return indic_table[u - 0x11100u + indic_offset_0x11100u];
|
||||||
if (hb_in_range (u, 0x112B0u, 0x11378u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u];
|
if (hb_in_range (u, 0x112B0u, 0x11377u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u];
|
||||||
if (hb_in_range (u, 0x11480u, 0x114E0u)) return indic_table[u - 0x11480u + indic_offset_0x11480u];
|
if (hb_in_range (u, 0x11480u, 0x114DFu)) return indic_table[u - 0x11480u + indic_offset_0x11480u];
|
||||||
if (hb_in_range (u, 0x11580u, 0x115C8u)) return indic_table[u - 0x11580u + indic_offset_0x11580u];
|
if (hb_in_range (u, 0x11580u, 0x115C7u)) return indic_table[u - 0x11580u + indic_offset_0x11580u];
|
||||||
if (hb_in_range (u, 0x11600u, 0x116D0u)) return indic_table[u - 0x11600u + indic_offset_0x11600u];
|
if (hb_in_range (u, 0x11600u, 0x116CFu)) return indic_table[u - 0x11600u + indic_offset_0x11600u];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -921,14 +921,32 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
|||||||
info[start].indic_position() = POS_RA_TO_BECOME_REPH;
|
info[start].indic_position() = POS_RA_TO_BECOME_REPH;
|
||||||
|
|
||||||
/* For old-style Indic script tags, move the first post-base Halant after
|
/* For old-style Indic script tags, move the first post-base Halant after
|
||||||
* last consonant. Only do this if there is *not* a Halant after last
|
* last consonant.
|
||||||
* consonant. Otherwise it becomes messy. */
|
*
|
||||||
if (indic_plan->is_old_spec) {
|
* Reports suggest that in some scripts Uniscribe does this only if there
|
||||||
|
* is *not* a Halant after last consonant already (eg. Kannada), while it
|
||||||
|
* does it unconditionally in other scripts (eg. Malayalam). We don't
|
||||||
|
* currently know about other scripts, so we single out Malayalam for now.
|
||||||
|
*
|
||||||
|
* Kannada test case:
|
||||||
|
* U+0C9A,U+0CCD,U+0C9A,U+0CCD
|
||||||
|
* With some versions of Lohit Kannada.
|
||||||
|
* https://bugs.freedesktop.org/show_bug.cgi?id=59118
|
||||||
|
*
|
||||||
|
* Malayalam test case:
|
||||||
|
* U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D
|
||||||
|
* With lohit-ttf-20121122/Lohit-Malayalam.ttf
|
||||||
|
*/
|
||||||
|
if (indic_plan->is_old_spec)
|
||||||
|
{
|
||||||
|
bool disallow_double_halants = buffer->props.script != HB_SCRIPT_MALAYALAM;
|
||||||
for (unsigned int i = base + 1; i < end; i++)
|
for (unsigned int i = base + 1; i < end; i++)
|
||||||
if (info[i].indic_category() == OT_H) {
|
if (info[i].indic_category() == OT_H)
|
||||||
|
{
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
for (j = end - 1; j > i; j--)
|
for (j = end - 1; j > i; j--)
|
||||||
if (is_consonant (info[j]) || info[j].indic_category() == OT_H)
|
if (is_consonant (info[j]) ||
|
||||||
|
(disallow_double_halants && info[j].indic_category() == OT_H))
|
||||||
break;
|
break;
|
||||||
if (info[j].indic_category() != OT_H && j > i) {
|
if (info[j].indic_category() != OT_H && j > i) {
|
||||||
/* Move Halant to after last consonant. */
|
/* Move Halant to after last consonant. */
|
||||||
@ -1267,6 +1285,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||||||
info.cluster = buffer->cur().cluster;
|
info.cluster = buffer->cur().cluster;
|
||||||
info.mask = buffer->cur().mask;
|
info.mask = buffer->cur().mask;
|
||||||
info.syllable() = buffer->cur().syllable();
|
info.syllable() = buffer->cur().syllable();
|
||||||
|
/* TODO Set glyph_props? */
|
||||||
|
|
||||||
/* Insert dottedcircle after possible Repha. */
|
/* Insert dottedcircle after possible Repha. */
|
||||||
while (buffer->idx < buffer->len &&
|
while (buffer->idx < buffer->len &&
|
||||||
|
@ -536,6 +536,24 @@ final_reordering (const hb_ot_shape_plan_t *plan,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Uniscribe seems to have a shaper for 'mymr' that is like the
|
||||||
|
* generic shaper, except that it zeros mark advances GDEF_LATE. */
|
||||||
|
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old =
|
||||||
|
{
|
||||||
|
"default",
|
||||||
|
NULL, /* collect_features */
|
||||||
|
NULL, /* override_features */
|
||||||
|
NULL, /* data_create */
|
||||||
|
NULL, /* data_destroy */
|
||||||
|
NULL, /* preprocess_text */
|
||||||
|
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
|
||||||
|
NULL, /* decompose */
|
||||||
|
NULL, /* compose */
|
||||||
|
NULL, /* setup_masks */
|
||||||
|
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
|
||||||
|
true, /* fallback_position */
|
||||||
|
};
|
||||||
|
|
||||||
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
|
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
|
||||||
{
|
{
|
||||||
"myanmar",
|
"myanmar",
|
||||||
|
@ -56,6 +56,7 @@ enum hb_ot_shape_zero_width_marks_type_t {
|
|||||||
HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
|
HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
|
||||||
HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
|
HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
|
||||||
HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
|
HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
|
||||||
|
HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_old) \
|
||||||
HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
|
HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
|
||||||
HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
|
HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
|
||||||
HB_COMPLEX_SHAPER_IMPLEMENT (sea) \
|
HB_COMPLEX_SHAPER_IMPLEMENT (sea) \
|
||||||
@ -258,6 +259,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
|
|||||||
|
|
||||||
/* Unicode-4.1 additions */
|
/* Unicode-4.1 additions */
|
||||||
case HB_SCRIPT_KHAROSHTHI:
|
case HB_SCRIPT_KHAROSHTHI:
|
||||||
|
case HB_SCRIPT_NEW_TAI_LUE:
|
||||||
case HB_SCRIPT_SYLOTI_NAGRI:
|
case HB_SCRIPT_SYLOTI_NAGRI:
|
||||||
|
|
||||||
/* Unicode-5.1 additions */
|
/* Unicode-5.1 additions */
|
||||||
@ -329,16 +331,15 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
|
|||||||
return &_hb_ot_complex_shaper_default;
|
return &_hb_ot_complex_shaper_default;
|
||||||
|
|
||||||
case HB_SCRIPT_MYANMAR:
|
case HB_SCRIPT_MYANMAR:
|
||||||
/* For Myanmar, we only want to use the Myanmar shaper if the "new" script
|
|
||||||
* tag is found. For "old" script tag we want to use the default shaper. */
|
|
||||||
if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','2'))
|
if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','2'))
|
||||||
return &_hb_ot_complex_shaper_myanmar;
|
return &_hb_ot_complex_shaper_myanmar;
|
||||||
|
else if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
|
||||||
|
return &_hb_ot_complex_shaper_myanmar_old;
|
||||||
else
|
else
|
||||||
return &_hb_ot_complex_shaper_default;
|
return &_hb_ot_complex_shaper_default;
|
||||||
|
|
||||||
/* Unicode-4.1 additions */
|
/* Unicode-4.1 additions */
|
||||||
case HB_SCRIPT_BUGINESE:
|
case HB_SCRIPT_BUGINESE:
|
||||||
case HB_SCRIPT_NEW_TAI_LUE:
|
|
||||||
|
|
||||||
/* Unicode-5.1 additions */
|
/* Unicode-5.1 additions */
|
||||||
case HB_SCRIPT_CHAM:
|
case HB_SCRIPT_CHAM:
|
||||||
|
@ -415,6 +415,8 @@ _hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
|
|||||||
hb_font_t *font,
|
hb_font_t *font,
|
||||||
hb_buffer_t *buffer)
|
hb_buffer_t *buffer)
|
||||||
{
|
{
|
||||||
|
_hb_buffer_assert_gsubgpos_vars (buffer);
|
||||||
|
|
||||||
unsigned int start = 0;
|
unsigned int start = 0;
|
||||||
unsigned int last_cluster = buffer->info[0].cluster;
|
unsigned int last_cluster = buffer->info[0].cluster;
|
||||||
unsigned int count = buffer->len;
|
unsigned int count = buffer->len;
|
||||||
|
@ -289,6 +289,8 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
|
|||||||
hb_buffer_t *buffer,
|
hb_buffer_t *buffer,
|
||||||
hb_font_t *font)
|
hb_font_t *font)
|
||||||
{
|
{
|
||||||
|
_hb_buffer_assert_unicode_vars (buffer);
|
||||||
|
|
||||||
hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference;
|
hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference;
|
||||||
const hb_ot_shape_normalize_context_t c = {
|
const hb_ot_shape_normalize_context_t c = {
|
||||||
plan,
|
plan,
|
||||||
|
8
src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
vendored
8
src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
vendored
@ -43,7 +43,6 @@
|
|||||||
|
|
||||||
static hb_tag_t common_features[] = {
|
static hb_tag_t common_features[] = {
|
||||||
HB_TAG('c','c','m','p'),
|
HB_TAG('c','c','m','p'),
|
||||||
HB_TAG('l','i','g','a'),
|
|
||||||
HB_TAG('l','o','c','l'),
|
HB_TAG('l','o','c','l'),
|
||||||
HB_TAG('m','a','r','k'),
|
HB_TAG('m','a','r','k'),
|
||||||
HB_TAG('m','k','m','k'),
|
HB_TAG('m','k','m','k'),
|
||||||
@ -56,6 +55,7 @@ static hb_tag_t horizontal_features[] = {
|
|||||||
HB_TAG('c','l','i','g'),
|
HB_TAG('c','l','i','g'),
|
||||||
HB_TAG('c','u','r','s'),
|
HB_TAG('c','u','r','s'),
|
||||||
HB_TAG('k','e','r','n'),
|
HB_TAG('k','e','r','n'),
|
||||||
|
HB_TAG('l','i','g','a'),
|
||||||
HB_TAG('r','c','l','t'),
|
HB_TAG('r','c','l','t'),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -236,6 +236,7 @@ static void
|
|||||||
hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
|
hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
|
||||||
{
|
{
|
||||||
if (!(buffer->flags & HB_BUFFER_FLAG_BOT) ||
|
if (!(buffer->flags & HB_BUFFER_FLAG_BOT) ||
|
||||||
|
buffer->context_len[0] ||
|
||||||
_hb_glyph_info_get_general_category (&buffer->info[0]) !=
|
_hb_glyph_info_get_general_category (&buffer->info[0]) !=
|
||||||
HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
|
HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
|
||||||
return;
|
return;
|
||||||
@ -243,7 +244,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
|
|||||||
if (!font->has_glyph (0x25CCu))
|
if (!font->has_glyph (0x25CCu))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hb_glyph_info_t dottedcircle;
|
hb_glyph_info_t dottedcircle = {0};
|
||||||
dottedcircle.codepoint = 0x25CCu;
|
dottedcircle.codepoint = 0x25CCu;
|
||||||
_hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode);
|
_hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode);
|
||||||
|
|
||||||
@ -447,6 +448,7 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c)
|
|||||||
{
|
{
|
||||||
hb_buffer_t *buffer = c->buffer;
|
hb_buffer_t *buffer = c->buffer;
|
||||||
|
|
||||||
|
_hb_buffer_allocate_gsubgpos_vars (buffer);
|
||||||
hb_ot_layout_substitute_start (c->font, buffer);
|
hb_ot_layout_substitute_start (c->font, buffer);
|
||||||
|
|
||||||
if (!hb_ot_layout_has_glyph_classes (c->face))
|
if (!hb_ot_layout_has_glyph_classes (c->face))
|
||||||
@ -635,6 +637,8 @@ hb_ot_position (hb_ot_shape_context_t *c)
|
|||||||
|
|
||||||
if (fallback)
|
if (fallback)
|
||||||
_hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
|
_hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
|
||||||
|
|
||||||
|
_hb_buffer_deallocate_gsubgpos_vars (c->buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
123
src/3rdparty/harfbuzz-ng/src/hb-private.hh
vendored
123
src/3rdparty/harfbuzz-ng/src/hb-private.hh
vendored
@ -87,7 +87,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HB_INTERNAL
|
#ifndef HB_INTERNAL
|
||||||
# ifndef __MINGW32__
|
# if !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||||
# define HB_INTERNAL __attribute__((__visibility__("hidden")))
|
# define HB_INTERNAL __attribute__((__visibility__("hidden")))
|
||||||
# else
|
# else
|
||||||
# define HB_INTERNAL
|
# define HB_INTERNAL
|
||||||
@ -96,6 +96,8 @@
|
|||||||
|
|
||||||
#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
|
#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
|
/* Windows CE only has _strdup, while rest of Windows has both. */
|
||||||
|
#define strdup _strdup
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@ -116,15 +118,56 @@
|
|||||||
#define HB_FUNC __func__
|
#define HB_FUNC __func__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Take from https://github.com/behdad/harfbuzz/commit/26a963b9cb4af3119177f277a2d48a5d537458fb
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||||
#if defined(_WIN32_WCE)
|
/* We need Windows Vista for both Uniscribe backend and for
|
||||||
|
* MemoryBarrier. We don't support compiling on Windows XP,
|
||||||
|
* though we run on it fine. */
|
||||||
|
# if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
|
||||||
|
# undef _WIN32_WINNT
|
||||||
|
# endif
|
||||||
|
# ifndef _WIN32_WINNT
|
||||||
|
# define _WIN32_WINNT 0x0600
|
||||||
|
# endif
|
||||||
|
# ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
# define WIN32_LEAN_AND_MEAN 1
|
||||||
|
# endif
|
||||||
|
# ifndef STRICT
|
||||||
|
# define STRICT 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32_WCE
|
||||||
/* Some things not defined on Windows CE. */
|
/* Some things not defined on Windows CE. */
|
||||||
#define MemoryBarrier()
|
#define MemoryBarrier()
|
||||||
#define getenv(Name) NULL
|
#define getenv(Name) NULL
|
||||||
#define setlocale(Category, Locale) "C"
|
#define setlocale(Category, Locale) "C"
|
||||||
static int errno = 0; /* Use something better? */
|
static int errno = 0; /* Use something better? */
|
||||||
#elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
|
#endif
|
||||||
#define getenv(Name) NULL
|
|
||||||
|
#if HAVE_ATEXIT
|
||||||
|
/* atexit() is only safe to be called from shared libraries on certain
|
||||||
|
* platforms. Whitelist.
|
||||||
|
* https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
|
||||||
|
# if defined(__linux) && defined(__GLIBC_PREREQ)
|
||||||
|
# if __GLIBC_PREREQ(2,3)
|
||||||
|
/* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
|
||||||
|
# define HB_USE_ATEXIT 1
|
||||||
|
# endif
|
||||||
|
# elif defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
/* For MSVC:
|
||||||
|
* http://msdn.microsoft.com/en-ca/library/tze57ck3.aspx
|
||||||
|
* http://msdn.microsoft.com/en-ca/library/zk17ww08.aspx
|
||||||
|
* mingw32 headers say atexit is safe to use in shared libraries.
|
||||||
|
*/
|
||||||
|
# define HB_USE_ATEXIT 1
|
||||||
|
# elif defined(__ANDROID__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
||||||
|
/* This was fixed in Android NKD r8 or r8b:
|
||||||
|
* https://code.google.com/p/android/issues/detail?id=6455
|
||||||
|
* which introduced GCC 4.6:
|
||||||
|
* https://developer.android.com/tools/sdk/ndk/index.html
|
||||||
|
*/
|
||||||
|
# define HB_USE_ATEXIT 1
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Basics */
|
/* Basics */
|
||||||
@ -280,7 +323,7 @@ typedef int (*hb_compare_func_t) (const void *, const void *);
|
|||||||
/* arrays and maps */
|
/* arrays and maps */
|
||||||
|
|
||||||
|
|
||||||
#define HB_PREALLOCED_ARRAY_INIT {0}
|
#define HB_PREALLOCED_ARRAY_INIT {0, 0, NULL}
|
||||||
template <typename Type, unsigned int StaticSize=16>
|
template <typename Type, unsigned int StaticSize=16>
|
||||||
struct hb_prealloced_array_t
|
struct hb_prealloced_array_t
|
||||||
{
|
{
|
||||||
@ -496,47 +539,6 @@ struct hb_lockable_set_t
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Big-endian handling */
|
|
||||||
|
|
||||||
static inline uint16_t hb_be_uint16 (const uint16_t v)
|
|
||||||
{
|
|
||||||
const uint8_t *V = (const uint8_t *) &v;
|
|
||||||
return (V[0] << 8) | V[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint16_t hb_uint16_swap (const uint16_t v)
|
|
||||||
{
|
|
||||||
return (v >> 8) | (v << 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t hb_uint32_swap (const uint32_t v)
|
|
||||||
{
|
|
||||||
return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note, of the following macros, uint16_get is the one called many many times.
|
|
||||||
* If there is any optimizations to be done, it's in that macro. However, I
|
|
||||||
* already confirmed that on my T400 ThinkPad at least, using bswap_16(), which
|
|
||||||
* results in a single ror instruction, does NOT speed this up. In fact, it
|
|
||||||
* resulted in a minor slowdown. At any rate, note that v may not be correctly
|
|
||||||
* aligned, so I think the current implementation is optimal.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define hb_be_uint16_put(v,V) HB_STMT_START { v[0] = (V>>8); v[1] = (V); } HB_STMT_END
|
|
||||||
#define hb_be_uint16_get(v) (uint16_t) ((v[0] << 8) + v[1])
|
|
||||||
#define hb_be_uint16_eq(a,b) (a[0] == b[0] && a[1] == b[1])
|
|
||||||
|
|
||||||
#define hb_be_uint32_put(v,V) HB_STMT_START { v[0] = (V>>24); v[1] = (V>>16); v[2] = (V>>8); v[3] = (V); } HB_STMT_END
|
|
||||||
#define hb_be_uint32_get(v) (uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3])
|
|
||||||
#define hb_be_uint32_eq(a,b) (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])
|
|
||||||
|
|
||||||
#define hb_be_uint24_put(v,V) HB_STMT_START { v[0] = (V>>16); v[1] = (V>>8); v[2] = (V); } HB_STMT_END
|
|
||||||
#define hb_be_uint24_get(v) (uint32_t) ((v[0] << 16) + (v[1] << 8) + v[2])
|
|
||||||
#define hb_be_uint24_eq(a,b) (a[0] == b[0] && a[1] == b[1] && a[2] == b[2])
|
|
||||||
|
|
||||||
|
|
||||||
/* ASCII tag/character handling */
|
/* ASCII tag/character handling */
|
||||||
|
|
||||||
static inline bool ISALPHA (unsigned char c)
|
static inline bool ISALPHA (unsigned char c)
|
||||||
@ -581,6 +583,15 @@ _hb_debug (unsigned int level,
|
|||||||
#define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
|
#define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
|
||||||
#define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
|
#define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
|
||||||
|
|
||||||
|
template <int max_level> static inline void
|
||||||
|
_hb_debug_msg_va (const char *what,
|
||||||
|
const void *obj,
|
||||||
|
const char *func,
|
||||||
|
bool indented,
|
||||||
|
unsigned int level,
|
||||||
|
int level_dir,
|
||||||
|
const char *message,
|
||||||
|
va_list ap) HB_PRINTF_FUNC(7, 0);
|
||||||
template <int max_level> static inline void
|
template <int max_level> static inline void
|
||||||
_hb_debug_msg_va (const char *what,
|
_hb_debug_msg_va (const char *what,
|
||||||
const void *obj,
|
const void *obj,
|
||||||
@ -704,7 +715,9 @@ _hb_debug_msg<0> (const char *what HB_UNUSED,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct hb_printer_t {};
|
struct hb_printer_t {
|
||||||
|
const char *print (const T&) { return "something"; }
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct hb_printer_t<bool> {
|
struct hb_printer_t<bool> {
|
||||||
@ -811,7 +824,9 @@ hb_in_range (T u, T lo, T hi)
|
|||||||
* to generate a warning than unused variables. */
|
* to generate a warning than unused variables. */
|
||||||
ASSERT_STATIC (sizeof (hb_assert_unsigned_t<T>) >= 0);
|
ASSERT_STATIC (sizeof (hb_assert_unsigned_t<T>) >= 0);
|
||||||
|
|
||||||
return (u - lo) <= (hi - lo);
|
/* The casts below are important as if T is smaller than int,
|
||||||
|
* the subtract results will become a signed int! */
|
||||||
|
return (T)(u - lo) <= (T)(hi - lo);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> static inline bool
|
template <typename T> static inline bool
|
||||||
@ -835,7 +850,7 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
|
|||||||
#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
|
#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
|
||||||
|
|
||||||
|
|
||||||
template <typename T, typename T2> inline void
|
template <typename T, typename T2> static inline void
|
||||||
hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
|
hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
|
||||||
{
|
{
|
||||||
if (unlikely (!len))
|
if (unlikely (!len))
|
||||||
@ -868,7 +883,7 @@ hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *),
|
|||||||
} while (k);
|
} while (k);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> inline void
|
template <typename T> static inline void
|
||||||
hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
|
hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
|
||||||
{
|
{
|
||||||
hb_bubble_sort (array, len, compar, (int *) NULL);
|
hb_bubble_sort (array, len, compar, (int *) NULL);
|
||||||
@ -897,12 +912,12 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
|
|||||||
|
|
||||||
struct hb_options_t
|
struct hb_options_t
|
||||||
{
|
{
|
||||||
int initialized : 1;
|
unsigned int initialized : 1;
|
||||||
int uniscribe_bug_compatible : 1;
|
unsigned int uniscribe_bug_compatible : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
union hb_options_union_t {
|
union hb_options_union_t {
|
||||||
int i;
|
unsigned int i;
|
||||||
hb_options_t opts;
|
hb_options_t opts;
|
||||||
};
|
};
|
||||||
ASSERT_STATIC (sizeof (int) == sizeof (hb_options_union_t));
|
ASSERT_STATIC (sizeof (int) == sizeof (hb_options_union_t));
|
||||||
|
@ -150,7 +150,7 @@ struct hb_set_t
|
|||||||
bool in_error;
|
bool in_error;
|
||||||
|
|
||||||
inline void init (void) {
|
inline void init (void) {
|
||||||
header.init ();
|
hb_object_init (this);
|
||||||
clear ();
|
clear ();
|
||||||
}
|
}
|
||||||
inline void fini (void) {
|
inline void fini (void) {
|
||||||
|
53
src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc
vendored
53
src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc
vendored
@ -29,6 +29,12 @@
|
|||||||
#include "hb-font-private.hh"
|
#include "hb-font-private.hh"
|
||||||
#include "hb-buffer-private.hh"
|
#include "hb-buffer-private.hh"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_SHAPE_PLAN
|
||||||
|
#define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define HB_SHAPER_IMPLEMENT(shaper) \
|
#define HB_SHAPER_IMPLEMENT(shaper) \
|
||||||
HB_SHAPER_DATA_ENSURE_DECLARE(shaper, face) \
|
HB_SHAPER_DATA_ENSURE_DECLARE(shaper, face) \
|
||||||
HB_SHAPER_DATA_ENSURE_DECLARE(shaper, font)
|
HB_SHAPER_DATA_ENSURE_DECLARE(shaper, font)
|
||||||
@ -42,6 +48,11 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan,
|
|||||||
unsigned int num_user_features,
|
unsigned int num_user_features,
|
||||||
const char * const *shaper_list)
|
const char * const *shaper_list)
|
||||||
{
|
{
|
||||||
|
DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
|
||||||
|
"num_features=%d shaper_list=%p",
|
||||||
|
num_user_features,
|
||||||
|
shaper_list);
|
||||||
|
|
||||||
const hb_shaper_pair_t *shapers = _hb_shapers_get ();
|
const hb_shaper_pair_t *shapers = _hb_shapers_get ();
|
||||||
|
|
||||||
#define HB_SHAPER_PLAN(shaper) \
|
#define HB_SHAPER_PLAN(shaper) \
|
||||||
@ -104,6 +115,12 @@ hb_shape_plan_create (hb_face_t *face,
|
|||||||
unsigned int num_user_features,
|
unsigned int num_user_features,
|
||||||
const char * const *shaper_list)
|
const char * const *shaper_list)
|
||||||
{
|
{
|
||||||
|
DEBUG_MSG_FUNC (SHAPE_PLAN, NULL,
|
||||||
|
"face=%p num_features=%d shaper_list=%p",
|
||||||
|
face,
|
||||||
|
num_user_features,
|
||||||
|
shaper_list);
|
||||||
|
|
||||||
hb_shape_plan_t *shape_plan;
|
hb_shape_plan_t *shape_plan;
|
||||||
hb_feature_t *features = NULL;
|
hb_feature_t *features = NULL;
|
||||||
|
|
||||||
@ -271,6 +288,11 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan,
|
|||||||
const hb_feature_t *features,
|
const hb_feature_t *features,
|
||||||
unsigned int num_features)
|
unsigned int num_features)
|
||||||
{
|
{
|
||||||
|
DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
|
||||||
|
"num_features=%d shaper_func=%p",
|
||||||
|
num_features,
|
||||||
|
shape_plan->shaper_func);
|
||||||
|
|
||||||
if (unlikely (hb_object_is_inert (shape_plan) ||
|
if (unlikely (hb_object_is_inert (shape_plan) ||
|
||||||
hb_object_is_inert (font) ||
|
hb_object_is_inert (font) ||
|
||||||
hb_object_is_inert (buffer)))
|
hb_object_is_inert (buffer)))
|
||||||
@ -383,6 +405,12 @@ hb_shape_plan_create_cached (hb_face_t *face,
|
|||||||
unsigned int num_user_features,
|
unsigned int num_user_features,
|
||||||
const char * const *shaper_list)
|
const char * const *shaper_list)
|
||||||
{
|
{
|
||||||
|
DEBUG_MSG_FUNC (SHAPE_PLAN, NULL,
|
||||||
|
"face=%p num_features=%d shaper_list=%p",
|
||||||
|
face,
|
||||||
|
num_user_features,
|
||||||
|
shaper_list);
|
||||||
|
|
||||||
hb_shape_plan_proposal_t proposal = {
|
hb_shape_plan_proposal_t proposal = {
|
||||||
*props,
|
*props,
|
||||||
shaper_list,
|
shaper_list,
|
||||||
@ -392,25 +420,22 @@ hb_shape_plan_create_cached (hb_face_t *face,
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (shaper_list) {
|
if (shaper_list) {
|
||||||
/* Choose shaper. Adapted from hb_shape_plan_plan(). */
|
/* Choose shaper. Adapted from hb_shape_plan_plan().
|
||||||
#define HB_SHAPER_PLAN(shaper) \
|
* Must choose shaper exactly the same way as that function. */
|
||||||
HB_STMT_START { \
|
|
||||||
if (hb_##shaper##_shaper_face_data_ensure (face)) \
|
|
||||||
proposal.shaper_func = _hb_##shaper##_shape; \
|
|
||||||
} HB_STMT_END
|
|
||||||
|
|
||||||
for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_item++)
|
for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_item++)
|
||||||
if (0)
|
if (0)
|
||||||
;
|
;
|
||||||
#define HB_SHAPER_IMPLEMENT(shaper) \
|
#define HB_SHAPER_IMPLEMENT(shaper) \
|
||||||
else if (0 == strcmp (*shaper_item, #shaper)) \
|
else if (0 == strcmp (*shaper_item, #shaper) && \
|
||||||
HB_SHAPER_PLAN (shaper);
|
hb_##shaper##_shaper_face_data_ensure (face)) \
|
||||||
|
{ \
|
||||||
|
proposal.shaper_func = _hb_##shaper##_shape; \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
#include "hb-shaper-list.hh"
|
#include "hb-shaper-list.hh"
|
||||||
#undef HB_SHAPER_IMPLEMENT
|
#undef HB_SHAPER_IMPLEMENT
|
||||||
|
|
||||||
#undef HB_SHAPER_PLAN
|
if (unlikely (!proposal.shaper_func))
|
||||||
|
|
||||||
if (unlikely (!proposal.shaper_list))
|
|
||||||
return hb_shape_plan_get_empty ();
|
return hb_shape_plan_get_empty ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +444,10 @@ retry:
|
|||||||
hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atomic_ptr_get (&face->shape_plans);
|
hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atomic_ptr_get (&face->shape_plans);
|
||||||
for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next)
|
for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next)
|
||||||
if (hb_shape_plan_matches (node->shape_plan, &proposal))
|
if (hb_shape_plan_matches (node->shape_plan, &proposal))
|
||||||
|
{
|
||||||
|
DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache");
|
||||||
return hb_shape_plan_reference (node->shape_plan);
|
return hb_shape_plan_reference (node->shape_plan);
|
||||||
|
}
|
||||||
|
|
||||||
/* Not found. */
|
/* Not found. */
|
||||||
|
|
||||||
@ -442,6 +470,7 @@ retry:
|
|||||||
free (node);
|
free (node);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, "inserted into cache");
|
||||||
|
|
||||||
return hb_shape_plan_reference (shape_plan);
|
return hb_shape_plan_reference (shape_plan);
|
||||||
}
|
}
|
||||||
|
110
src/3rdparty/harfbuzz-ng/src/hb-shape.cc
vendored
110
src/3rdparty/harfbuzz-ng/src/hb-shape.cc
vendored
@ -34,15 +34,15 @@
|
|||||||
#include "hb-font-private.hh"
|
#include "hb-font-private.hh"
|
||||||
|
|
||||||
|
|
||||||
static void
|
static bool
|
||||||
parse_space (const char **pp, const char *end)
|
parse_space (const char **pp, const char *end)
|
||||||
{
|
{
|
||||||
char c;
|
while (*pp < end && ISSPACE (**pp))
|
||||||
while (*pp < end && (c = **pp, ISSPACE (c)))
|
|
||||||
(*pp)++;
|
(*pp)++;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hb_bool_t
|
static bool
|
||||||
parse_char (const char **pp, const char *end, char c)
|
parse_char (const char **pp, const char *end, char c)
|
||||||
{
|
{
|
||||||
parse_space (pp, end);
|
parse_space (pp, end);
|
||||||
@ -54,7 +54,7 @@ parse_char (const char **pp, const char *end, char c)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hb_bool_t
|
static bool
|
||||||
parse_uint (const char **pp, const char *end, unsigned int *pv)
|
parse_uint (const char **pp, const char *end, unsigned int *pv)
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[32];
|
||||||
@ -78,7 +78,27 @@ parse_uint (const char **pp, const char *end, unsigned int *pv)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hb_bool_t
|
static bool
|
||||||
|
parse_bool (const char **pp, const char *end, unsigned int *pv)
|
||||||
|
{
|
||||||
|
parse_space (pp, end);
|
||||||
|
|
||||||
|
const char *p = *pp;
|
||||||
|
while (*pp < end && ISALPHA(**pp))
|
||||||
|
(*pp)++;
|
||||||
|
|
||||||
|
/* CSS allows on/off as aliases 1/0. */
|
||||||
|
if (*pp - p == 2 || 0 == strncmp (p, "on", 2))
|
||||||
|
*pv = 1;
|
||||||
|
else if (*pp - p == 3 || 0 == strncmp (p, "off", 2))
|
||||||
|
*pv = 0;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
|
parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
|
||||||
{
|
{
|
||||||
if (parse_char (pp, end, '-'))
|
if (parse_char (pp, end, '-'))
|
||||||
@ -91,32 +111,48 @@ parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feat
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hb_bool_t
|
static bool
|
||||||
parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature)
|
parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature)
|
||||||
{
|
{
|
||||||
const char *p = *pp;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
parse_space (pp, end);
|
parse_space (pp, end);
|
||||||
|
|
||||||
#define ISALNUM(c) (('a' <= (c) && (c) <= 'z') || ('A' <= (c) && (c) <= 'Z') || ('0' <= (c) && (c) <= '9'))
|
char quote = 0;
|
||||||
while (*pp < end && (c = **pp, ISALNUM(c)))
|
|
||||||
(*pp)++;
|
|
||||||
#undef ISALNUM
|
|
||||||
|
|
||||||
if (p == *pp)
|
if (*pp < end && (**pp == '\'' || **pp == '"'))
|
||||||
|
{
|
||||||
|
quote = **pp;
|
||||||
|
(*pp)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *p = *pp;
|
||||||
|
while (*pp < end && ISALNUM(**pp))
|
||||||
|
(*pp)++;
|
||||||
|
|
||||||
|
if (p == *pp || *pp - p > 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
feature->tag = hb_tag_from_string (p, *pp - p);
|
feature->tag = hb_tag_from_string (p, *pp - p);
|
||||||
|
|
||||||
|
if (quote)
|
||||||
|
{
|
||||||
|
/* CSS expects exactly four bytes. And we only allow quotations for
|
||||||
|
* CSS compatibility. So, enforce the length. */
|
||||||
|
if (*pp - p != 4)
|
||||||
|
return false;
|
||||||
|
if (*pp == end || **pp != quote)
|
||||||
|
return false;
|
||||||
|
(*pp)++;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hb_bool_t
|
static bool
|
||||||
parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
|
parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
|
||||||
{
|
{
|
||||||
parse_space (pp, end);
|
parse_space (pp, end);
|
||||||
|
|
||||||
hb_bool_t has_start;
|
bool has_start;
|
||||||
|
|
||||||
feature->start = 0;
|
feature->start = 0;
|
||||||
feature->end = (unsigned int) -1;
|
feature->end = (unsigned int) -1;
|
||||||
@ -136,20 +172,27 @@ parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
|
|||||||
return parse_char (pp, end, ']');
|
return parse_char (pp, end, ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
static hb_bool_t
|
static bool
|
||||||
parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
|
parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
|
||||||
{
|
{
|
||||||
return !parse_char (pp, end, '=') || parse_uint (pp, end, &feature->value);
|
bool had_equal = parse_char (pp, end, '=');
|
||||||
|
bool had_value = parse_uint (pp, end, &feature->value) ||
|
||||||
|
parse_bool (pp, end, &feature->value);
|
||||||
|
/* CSS doesn't use equal-sign between tag and value.
|
||||||
|
* If there was an equal-sign, then there *must* be a value.
|
||||||
|
* A value without an eqaul-sign is ok, but not required. */
|
||||||
|
return !had_equal || had_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static hb_bool_t
|
static bool
|
||||||
parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
|
parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
|
||||||
{
|
{
|
||||||
return parse_feature_value_prefix (pp, end, feature) &&
|
return parse_feature_value_prefix (pp, end, feature) &&
|
||||||
parse_feature_tag (pp, end, feature) &&
|
parse_feature_tag (pp, end, feature) &&
|
||||||
parse_feature_indices (pp, end, feature) &&
|
parse_feature_indices (pp, end, feature) &&
|
||||||
parse_feature_value_postfix (pp, end, feature) &&
|
parse_feature_value_postfix (pp, end, feature) &&
|
||||||
|
parse_space (pp, end) &&
|
||||||
*pp == end;
|
*pp == end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +200,7 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
|
|||||||
* hb_feature_from_string:
|
* hb_feature_from_string:
|
||||||
* @str: (array length=len):
|
* @str: (array length=len):
|
||||||
* @len:
|
* @len:
|
||||||
* @feature: (out):
|
* @feature: (out) (optional):
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@ -169,10 +212,21 @@ hb_bool_t
|
|||||||
hb_feature_from_string (const char *str, int len,
|
hb_feature_from_string (const char *str, int len,
|
||||||
hb_feature_t *feature)
|
hb_feature_t *feature)
|
||||||
{
|
{
|
||||||
|
hb_feature_t feat;
|
||||||
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
len = strlen (str);
|
len = strlen (str);
|
||||||
|
|
||||||
return parse_one_feature (&str, str + len, feature);
|
if (likely (parse_one_feature (&str, str + len, &feat)))
|
||||||
|
{
|
||||||
|
if (feature)
|
||||||
|
*feature = feat;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feature)
|
||||||
|
memset (feature, 0, sizeof (*feature));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -203,18 +257,18 @@ hb_feature_to_string (hb_feature_t *feature,
|
|||||||
{
|
{
|
||||||
s[len++] = '[';
|
s[len++] = '[';
|
||||||
if (feature->start)
|
if (feature->start)
|
||||||
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->start));
|
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
|
||||||
if (feature->end != feature->start + 1) {
|
if (feature->end != feature->start + 1) {
|
||||||
s[len++] = ':';
|
s[len++] = ':';
|
||||||
if (feature->end != (unsigned int) -1)
|
if (feature->end != (unsigned int) -1)
|
||||||
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->end));
|
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
|
||||||
}
|
}
|
||||||
s[len++] = ']';
|
s[len++] = ']';
|
||||||
}
|
}
|
||||||
if (feature->value > 1)
|
if (feature->value > 1)
|
||||||
{
|
{
|
||||||
s[len++] = '=';
|
s[len++] = '=';
|
||||||
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->value));
|
len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
|
||||||
}
|
}
|
||||||
assert (len < ARRAY_LENGTH (s));
|
assert (len < ARRAY_LENGTH (s));
|
||||||
len = MIN (len, size - 1);
|
len = MIN (len, size - 1);
|
||||||
@ -225,11 +279,13 @@ hb_feature_to_string (hb_feature_t *feature,
|
|||||||
|
|
||||||
static const char **static_shaper_list;
|
static const char **static_shaper_list;
|
||||||
|
|
||||||
static inline
|
#ifdef HB_USE_ATEXIT
|
||||||
|
static
|
||||||
void free_static_shaper_list (void)
|
void free_static_shaper_list (void)
|
||||||
{
|
{
|
||||||
free (static_shaper_list);
|
free (static_shaper_list);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_shape_list_shapers:
|
* hb_shape_list_shapers:
|
||||||
@ -266,7 +322,7 @@ retry:
|
|||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_ATEXIT
|
#ifdef HB_USE_ATEXIT
|
||||||
atexit (free_static_shaper_list); /* First person registers atexit() callback. */
|
atexit (free_static_shaper_list); /* First person registers atexit() callback. */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
6
src/3rdparty/harfbuzz-ng/src/hb-shaper.cc
vendored
6
src/3rdparty/harfbuzz-ng/src/hb-shaper.cc
vendored
@ -40,12 +40,14 @@ static const hb_shaper_pair_t all_shapers[] = {
|
|||||||
|
|
||||||
static const hb_shaper_pair_t *static_shapers;
|
static const hb_shaper_pair_t *static_shapers;
|
||||||
|
|
||||||
static inline
|
#ifdef HB_USE_ATEXIT
|
||||||
|
static
|
||||||
void free_static_shapers (void)
|
void free_static_shapers (void)
|
||||||
{
|
{
|
||||||
if (unlikely (static_shapers != all_shapers))
|
if (unlikely (static_shapers != all_shapers))
|
||||||
free ((void *) static_shapers);
|
free ((void *) static_shapers);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
const hb_shaper_pair_t *
|
const hb_shaper_pair_t *
|
||||||
_hb_shapers_get (void)
|
_hb_shapers_get (void)
|
||||||
@ -100,7 +102,7 @@ retry:
|
|||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_ATEXIT
|
#ifdef HB_USE_ATEXIT
|
||||||
atexit (free_static_shapers); /* First person registers atexit() callback. */
|
atexit (free_static_shapers); /* First person registers atexit() callback. */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
4
src/3rdparty/harfbuzz-ng/src/hb-unicode.cc
vendored
4
src/3rdparty/harfbuzz-ng/src/hb-unicode.cc
vendored
@ -157,7 +157,7 @@ hb_unicode_funcs_get_default (void)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_unicode_funcs_create: (Xconstructor)
|
* hb_unicode_funcs_create: (Xconstructor)
|
||||||
* @parent: (allow-none):
|
* @parent: (nullable):
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@ -310,7 +310,7 @@ hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
|
|||||||
void
|
void
|
||||||
hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
|
hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
|
||||||
{
|
{
|
||||||
if (hb_object_is_inert (ufuncs))
|
if (unlikely (hb_object_is_inert (ufuncs)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ufuncs->immutable = true;
|
ufuncs->immutable = true;
|
||||||
|
4
src/3rdparty/harfbuzz-ng/src/hb-version.h
vendored
4
src/3rdparty/harfbuzz-ng/src/hb-version.h
vendored
@ -38,9 +38,9 @@ HB_BEGIN_DECLS
|
|||||||
|
|
||||||
#define HB_VERSION_MAJOR 0
|
#define HB_VERSION_MAJOR 0
|
||||||
#define HB_VERSION_MINOR 9
|
#define HB_VERSION_MINOR 9
|
||||||
#define HB_VERSION_MICRO 32
|
#define HB_VERSION_MICRO 38
|
||||||
|
|
||||||
#define HB_VERSION_STRING "0.9.32"
|
#define HB_VERSION_STRING "0.9.38"
|
||||||
|
|
||||||
#define HB_VERSION_ATLEAST(major,minor,micro) \
|
#define HB_VERSION_ATLEAST(major,minor,micro) \
|
||||||
((major)*10000+(minor)*100+(micro) <= \
|
((major)*10000+(minor)*100+(micro) <= \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user