diff options
author | wangxianzhu@chromium.org <wangxianzhu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-15 00:39:48 +0000 |
---|---|---|
committer | wangxianzhu@chromium.org <wangxianzhu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-15 00:39:48 +0000 |
commit | f684a6777acc0d5e09b0e8c32de9afe27ac7e900 (patch) | |
tree | 9daa9fc18ce8ba3b6855a5fe034d60a5f61db23e /third_party/harfbuzz-ng/src | |
parent | 19fef4baed97a11413a4847eef4df31d03c8f4cf (diff) | |
download | chromium_src-f684a6777acc0d5e09b0e8c32de9afe27ac7e900.zip chromium_src-f684a6777acc0d5e09b0e8c32de9afe27ac7e900.tar.gz chromium_src-f684a6777acc0d5e09b0e8c32de9afe27ac7e900.tar.bz2 |
Update harfbuzz from 0.9.24 to 0.9.26
BUG=335156
Review URL: https://codereview.chromium.org/200323004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@257270 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party/harfbuzz-ng/src')
47 files changed, 1483 insertions, 588 deletions
diff --git a/third_party/harfbuzz-ng/src/hb-atomic-private.hh b/third_party/harfbuzz-ng/src/hb-atomic-private.hh index 9cc3bc5..b5d6485 100644 --- a/third_party/harfbuzz-ng/src/hb-atomic-private.hh +++ b/third_party/harfbuzz-ng/src/hb-atomic-private.hh @@ -78,7 +78,7 @@ typedef int32_t hb_atomic_int_t; #if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100) #define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P)) #else -#if __ppc64__ || __x86_64__ +#if __ppc64__ || __x86_64__ || __arm64__ #define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P)) #else #define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P)) diff --git a/third_party/harfbuzz-ng/src/hb-blob.cc b/third_party/harfbuzz-ng/src/hb-blob.cc index da2509c..b8c93a0 100644 --- a/third_party/harfbuzz-ng/src/hb-blob.cc +++ b/third_party/harfbuzz-ng/src/hb-blob.cc @@ -32,7 +32,6 @@ #include "hb-private.hh" -#include "hb-blob.h" #include "hb-object-private.hh" #ifdef HAVE_SYS_MMAN_H diff --git a/third_party/harfbuzz-ng/src/hb-buffer-private.hh b/third_party/harfbuzz-ng/src/hb-buffer-private.hh index d3ed449..3a2b9ab 100644 --- a/third_party/harfbuzz-ng/src/hb-buffer-private.hh +++ b/third_party/harfbuzz-ng/src/hb-buffer-private.hh @@ -31,7 +31,6 @@ #define HB_BUFFER_PRIVATE_HH #include "hb-private.hh" -#include "hb-buffer.h" #include "hb-object-private.hh" #include "hb-unicode-private.hh" @@ -181,7 +180,7 @@ struct hb_buffer_t { HB_INTERNAL bool enlarge (unsigned int size); inline bool ensure (unsigned int size) - { return likely (size < allocated) ? true : enlarge (size); } + { return likely (!size || size < allocated) ? true : enlarge (size); } HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out); HB_INTERNAL bool shift_forward (unsigned int count); diff --git a/third_party/harfbuzz-ng/src/hb-buffer-serialize.cc b/third_party/harfbuzz-ng/src/hb-buffer-serialize.cc index 4541db2..263bc81 100644 --- a/third_party/harfbuzz-ng/src/hb-buffer-serialize.cc +++ b/third_party/harfbuzz-ng/src/hb-buffer-serialize.cc @@ -204,7 +204,7 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, *p++ = '+'; p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance)); - if (pos->y_advance) + if (pos[i].y_advance) p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance)); } diff --git a/third_party/harfbuzz-ng/src/hb-buffer.cc b/third_party/harfbuzz-ng/src/hb-buffer.cc index bbf8ea0..d6c6fcb 100644 --- a/third_party/harfbuzz-ng/src/hb-buffer.cc +++ b/third_party/harfbuzz-ng/src/hb-buffer.cc @@ -1150,7 +1150,10 @@ hb_buffer_set_length (hb_buffer_t *buffer, buffer->len = length; if (!length) + { + buffer->content_type = HB_BUFFER_CONTENT_TYPE_INVALID; buffer->clear_context (0); + } buffer->clear_context (1); return true; diff --git a/third_party/harfbuzz-ng/src/hb-common.cc b/third_party/harfbuzz-ng/src/hb-common.cc index cf24660..0fd790b 100644 --- a/third_party/harfbuzz-ng/src/hb-common.cc +++ b/third_party/harfbuzz-ng/src/hb-common.cc @@ -28,8 +28,6 @@ #include "hb-private.hh" -#include "hb-version.h" - #include "hb-mutex-private.hh" #include "hb-object-private.hh" diff --git a/third_party/harfbuzz-ng/src/hb-common.h b/third_party/harfbuzz-ng/src/hb-common.h index e445504..c8bfd88 100644 --- a/third_party/harfbuzz-ng/src/hb-common.h +++ b/third_party/harfbuzz-ng/src/hb-common.h @@ -94,6 +94,7 @@ typedef uint32_t hb_tag_t; #define HB_UNTAG(tag) ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag)) #define HB_TAG_NONE HB_TAG(0,0,0,0) +#define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff) /* len=-1 means str is NUL-terminated. */ hb_tag_t @@ -270,7 +271,12 @@ typedef enum /*6.1*/ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), /* 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 + * without risking undefined behavior. */ + /*---*/ _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX + } hb_script_t; /* These are moved out of hb_script_t because glib-mkenums chokes otherwise. */ diff --git a/third_party/harfbuzz-ng/src/hb-coretext.cc b/third_party/harfbuzz-ng/src/hb-coretext.cc index ba80136..87dd779 100644 --- a/third_party/harfbuzz-ng/src/hb-coretext.cc +++ b/third_party/harfbuzz-ng/src/hb-coretext.cc @@ -394,6 +394,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, unsigned int num_features) { hb_face_t *face = font->face; + hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); hb_coretext_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); /* @@ -590,7 +591,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, CFMutableAttributedStringRef attr_string = CFAttributedStringCreateMutable (NULL, chars_len); CFAttributedStringReplaceString (attr_string, CFRangeMake (0, 0), string_ref); - CFRelease (string_ref); CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), kCTFontAttributeName, font_data->ct_font); @@ -648,9 +648,60 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, const CFRange range_all = CFRangeMake (0, 0); - for (unsigned int i = 0; i < num_runs; i++) { + for (unsigned int i = 0; i < num_runs; i++) + { CTRunRef run = (CTRunRef) CFArrayGetValueAtIndex (glyph_runs, i); + /* CoreText does automatic font fallback (AKA "cascading") for characters + * not supported by the requested font, and provides no way to turn it off, + * so we detect if the returned run uses a font other than the requested + * one and fill in the buffer with .notdef glyphs instead of random glyph + * indices from a different font. + */ + CFDictionaryRef attributes = CTRunGetAttributes (run); + CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName)); + CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0); + if (!CFEqual (run_cg_font, face_data->cg_font)) + { + CFRelease (run_cg_font); + + CFRange range = CTRunGetStringRange (run); + buffer->ensure (buffer->len + range.length); + if (buffer->in_error) + FAIL ("Buffer resize failed"); + hb_glyph_info_t *info = buffer->info + buffer->len; + + CGGlyph notdef = 0; + double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, ¬def, NULL, 1); + + for (CFIndex j = range.location; j < range.location + range.length; j++) + { + UniChar ch = CFStringGetCharacterAtIndex (string_ref, j); + if (hb_in_range<UniChar> (ch, 0xDC00, 0xDFFF) && range.location < j) + { + ch = CFStringGetCharacterAtIndex (string_ref, j - 1); + if (hb_in_range<UniChar> (ch, 0xD800, 0xDBFF)) + /* This is the second of a surrogate pair. Don't need .notdef + * for this one. */ + continue; + } + + info->codepoint = notdef; + /* TODO We have to fixup clusters later. See vis_clusters in + * hb-uniscribe.cc for example. */ + info->cluster = j; + + info->mask = advance; + info->var1.u32 = 0; + info->var2.u32 = 0; + + info++; + buffer->len++; + } + continue; + } + CFRelease (run_cg_font); + unsigned int num_glyphs = CTRunGetGlyphCount (run); if (num_glyphs == 0) continue; @@ -754,6 +805,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, } } + CFRelease (string_ref); CFRelease (line); return true; diff --git a/third_party/harfbuzz-ng/src/hb-face-private.hh b/third_party/harfbuzz-ng/src/hb-face-private.hh index b33be0e..6520d3d 100644 --- a/third_party/harfbuzz-ng/src/hb-face-private.hh +++ b/third_party/harfbuzz-ng/src/hb-face-private.hh @@ -31,7 +31,6 @@ #include "hb-private.hh" -#include "hb-font.h" #include "hb-object-private.hh" #include "hb-shaper-private.hh" #include "hb-shape-plan-private.hh" diff --git a/third_party/harfbuzz-ng/src/hb-face.cc b/third_party/harfbuzz-ng/src/hb-face.cc index ebe8ec5..71cf49a 100644 --- a/third_party/harfbuzz-ng/src/hb-face.cc +++ b/third_party/harfbuzz-ng/src/hb-face.cc @@ -31,7 +31,6 @@ #include "hb-ot-layout-private.hh" #include "hb-font-private.hh" -#include "hb-blob.h" #include "hb-open-file-private.hh" #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" diff --git a/third_party/harfbuzz-ng/src/hb-fallback-shape.cc b/third_party/harfbuzz-ng/src/hb-fallback-shape.cc index 1a1fcfb..ea54bb8 100644 --- a/third_party/harfbuzz-ng/src/hb-fallback-shape.cc +++ b/third_party/harfbuzz-ng/src/hb-fallback-shape.cc @@ -95,8 +95,19 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *features HB_UNUSED, unsigned int num_features HB_UNUSED) { + /* TODO + * + * - Apply fallback kern. + * - Handle Variation Selectors? + * - Apply normalization? + * + * This will make the fallback shaper into a dumb "TrueType" + * shaper which many people unfortunately still request. + */ + + bool has_space; hb_codepoint_t space; - font->get_glyph (' ', 0, &space); + has_space = font->get_glyph (' ', 0, &space); buffer->clear_positions (); @@ -104,7 +115,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, for (unsigned int i = 0; i < count; i++) { - if (buffer->unicode->is_default_ignorable (buffer->info[i].codepoint)) { + if (has_space && buffer->unicode->is_default_ignorable (buffer->info[i].codepoint)) { buffer->info[i].codepoint = space; buffer->pos[i].x_advance = 0; buffer->pos[i].y_advance = 0; diff --git a/third_party/harfbuzz-ng/src/hb-font-private.hh b/third_party/harfbuzz-ng/src/hb-font-private.hh index aa6c515..33bbf71 100644 --- a/third_party/harfbuzz-ng/src/hb-font-private.hh +++ b/third_party/harfbuzz-ng/src/hb-font-private.hh @@ -31,7 +31,6 @@ #include "hb-private.hh" -#include "hb-font.h" #include "hb-object-private.hh" #include "hb-face-private.hh" #include "hb-shaper-private.hh" @@ -145,6 +144,12 @@ struct hb_font_t { /* Public getters */ + inline hb_bool_t has_glyph (hb_codepoint_t unicode) + { + hb_codepoint_t glyph; + return get_glyph (unicode, 0, &glyph); + } + inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, hb_codepoint_t *glyph) { diff --git a/third_party/harfbuzz-ng/src/hb-font.cc b/third_party/harfbuzz-ng/src/hb-font.cc index 8558643..fc4c8eb 100644 --- a/third_party/harfbuzz-ng/src/hb-font.cc +++ b/third_party/harfbuzz-ng/src/hb-font.cc @@ -31,7 +31,6 @@ #include "hb-ot-layout-private.hh" #include "hb-font-private.hh" -#include "hb-blob.h" #include "hb-open-file-private.hh" #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" diff --git a/third_party/harfbuzz-ng/src/hb-graphite2.cc b/third_party/harfbuzz-ng/src/hb-graphite2.cc index 60d68d6..a309ca8 100644 --- a/third_party/harfbuzz-ng/src/hb-graphite2.cc +++ b/third_party/harfbuzz-ng/src/hb-graphite2.cc @@ -34,8 +34,6 @@ #include <graphite2/Segment.h> -#include "hb-ot-tag.h" - HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, face) HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, font) @@ -109,7 +107,7 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face) hb_graphite2_shaper_face_data_t *data = (hb_graphite2_shaper_face_data_t *) calloc (1, sizeof (hb_graphite2_shaper_face_data_t)); if (unlikely (!data)) - hb_blob_destroy (silf_blob); + return NULL; data->face = face; data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll); diff --git a/third_party/harfbuzz-ng/src/hb-open-type-private.hh b/third_party/harfbuzz-ng/src/hb-open-type-private.hh index ee3a21d..558103a 100644 --- a/third_party/harfbuzz-ng/src/hb-open-type-private.hh +++ b/third_party/harfbuzz-ng/src/hb-open-type-private.hh @@ -31,8 +31,6 @@ #include "hb-private.hh" -#include "hb-blob.h" - namespace OT { @@ -594,7 +592,7 @@ struct LONGDATETIME TRACE_SANITIZE (this); return TRACE_RETURN (likely (c->check_struct (this))); } - private: + protected: LONG major; ULONG minor; public: diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh index 367db95..02d0d0f 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh @@ -377,7 +377,7 @@ struct FeatureParamsStylisticSet return TRACE_RETURN (c->check_struct (this)); } - USHORT minorVersion; /* (set to 0): This corresponds to a “minor” + USHORT version; /* (set to 0): This corresponds to a “minor” * version number. Additional data may be * added to the end of this Feature Parameters * table in the future. */ @@ -400,6 +400,7 @@ struct FeatureParamsStylisticSet DEFINE_SIZE_STATIC (4); }; +/* http://www.microsoft.com/typography/otspec/features_ae.htm#cv01-cv99 */ struct FeatureParamsCharacterVariants { inline bool sanitize (hb_sanitize_context_t *c) { diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh index 5e4326ef..7c0a4ea 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh @@ -109,11 +109,13 @@ struct ValueFormat : USHORT if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++)); if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++)); if (format & xAdvance) { - if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values++)); else values++; + if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values)); + values++; } /* y_advance values grow downward but font-space grows upward, hence negation */ if (format & yAdvance) { - if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values++)); else values++; + if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values)); + values++; } if (!has_device ()) return; @@ -125,17 +127,21 @@ struct ValueFormat : USHORT /* pixel -> fractional pixel */ if (format & xPlaDevice) { - if (x_ppem) glyph_pos.x_offset += (base + get_device (values++)).get_x_delta (font); else values++; + if (x_ppem) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font); + values++; } if (format & yPlaDevice) { - if (y_ppem) glyph_pos.y_offset += (base + get_device (values++)).get_y_delta (font); else values++; + if (y_ppem) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font); + values++; } if (format & xAdvDevice) { - if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values++)).get_x_delta (font); else values++; + if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font); + values++; } if (format & yAdvDevice) { /* y_advance values grow downward but font-space grows upward, hence negation */ - if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values++)).get_y_delta (font); else values++; + if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font); + values++; } } @@ -240,12 +246,12 @@ struct AnchorFormat2 unsigned int x_ppem = font->x_ppem; unsigned int y_ppem = font->y_ppem; hb_position_t cx, cy; - hb_bool_t ret = false; + hb_bool_t ret; - if (x_ppem || y_ppem) - ret = font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); - *x = x_ppem && ret ? cx : font->em_scale_x (xCoordinate); - *y = y_ppem && ret ? cy : font->em_scale_y (yCoordinate); + ret = (x_ppem || y_ppem) && + font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); + *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate); + *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate); } inline bool sanitize (hb_sanitize_context_t *c) { diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh index 139e33f..0a0a54b 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh @@ -31,8 +31,6 @@ #include "hb-private.hh" -#include "hb-ot-layout.h" - #include "hb-font-private.hh" #include "hb-buffer-private.hh" #include "hb-set-private.hh" diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout.h b/third_party/harfbuzz-ng/src/hb-ot-layout.h index dfc7f24..d90eff37 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-layout.h +++ b/third_party/harfbuzz-ng/src/hb-ot-layout.h @@ -194,11 +194,6 @@ hb_ot_layout_collect_lookups (hb_face_t *face, hb_set_t *lookup_indexes /* OUT */); void -hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan, - hb_tag_t table_tag, - hb_set_t *lookup_indexes /* OUT */); - -void hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, hb_tag_t table_tag, unsigned int lookup_index, diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc index 4f6c86e..ea6d85c 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc @@ -199,7 +199,6 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) map->add_global_bool_feature (HB_TAG('c','a','l','t')); map->add_gsub_pause (NULL); - map->add_global_bool_feature (HB_TAG('c','s','w','h')); map->add_global_bool_feature (HB_TAG('m','s','e','t')); } @@ -366,7 +365,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic = data_create_arabic, data_destroy_arabic, NULL, /* preprocess_text_arabic */ - NULL, /* normalization_preference */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, NULL, /* decompose */ NULL, /* compose */ setup_masks_arabic, diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc index d6afa0e..f7f097e 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc @@ -27,194 +27,18 @@ #include "hb-ot-shape-complex-private.hh" -/* TODO Add kana, and other small shapers here */ - - -/* The default shaper *only* adds additional per-script features.*/ - -static const hb_tag_t hangul_features[] = -{ - HB_TAG('l','j','m','o'), - HB_TAG('v','j','m','o'), - HB_TAG('t','j','m','o'), - HB_TAG_NONE -}; - -static const hb_tag_t tibetan_features[] = -{ - HB_TAG('a','b','v','s'), - HB_TAG('b','l','w','s'), - HB_TAG('a','b','v','m'), - HB_TAG('b','l','w','m'), - HB_TAG_NONE -}; - -static void -collect_features_default (hb_ot_shape_planner_t *plan) -{ - const hb_tag_t *script_features = NULL; - - switch ((hb_tag_t) plan->props.script) - { - /* Unicode-1.1 additions */ - case HB_SCRIPT_HANGUL: - script_features = hangul_features; - break; - - /* Unicode-2.0 additions */ - case HB_SCRIPT_TIBETAN: - script_features = tibetan_features; - break; - } - - for (; script_features && *script_features; script_features++) - plan->map.add_global_bool_feature (*script_features); -} - -static hb_ot_shape_normalization_mode_t -normalization_preference_default (const hb_segment_properties_t *props) -{ - return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS; -} - -static bool -compose_default (const hb_ot_shape_normalize_context_t *c, - hb_codepoint_t a, - hb_codepoint_t b, - hb_codepoint_t *ab) -{ - /* Hebrew presentation-form shaping. - * https://bugzilla.mozilla.org/show_bug.cgi?id=728866 - * Hebrew presentation forms with dagesh, for characters 0x05D0..0x05EA; - * Note that some letters do not have a dagesh presForm encoded. - */ - static const hb_codepoint_t sDageshForms[0x05EA - 0x05D0 + 1] = { - 0xFB30, /* ALEF */ - 0xFB31, /* BET */ - 0xFB32, /* GIMEL */ - 0xFB33, /* DALET */ - 0xFB34, /* HE */ - 0xFB35, /* VAV */ - 0xFB36, /* ZAYIN */ - 0x0000, /* HET */ - 0xFB38, /* TET */ - 0xFB39, /* YOD */ - 0xFB3A, /* FINAL KAF */ - 0xFB3B, /* KAF */ - 0xFB3C, /* LAMED */ - 0x0000, /* FINAL MEM */ - 0xFB3E, /* MEM */ - 0x0000, /* FINAL NUN */ - 0xFB40, /* NUN */ - 0xFB41, /* SAMEKH */ - 0x0000, /* AYIN */ - 0xFB43, /* FINAL PE */ - 0xFB44, /* PE */ - 0x0000, /* FINAL TSADI */ - 0xFB46, /* TSADI */ - 0xFB47, /* QOF */ - 0xFB48, /* RESH */ - 0xFB49, /* SHIN */ - 0xFB4A /* TAV */ - }; - - bool found = c->unicode->compose (a, b, ab); - - if (!found && (b & ~0x7F) == 0x0580) { - /* Special-case Hebrew presentation forms that are excluded from - * standard normalization, but wanted for old fonts. */ - switch (b) { - case 0x05B4: /* HIRIQ */ - if (a == 0x05D9) { /* YOD */ - *ab = 0xFB1D; - found = true; - } - break; - case 0x05B7: /* patah */ - if (a == 0x05F2) { /* YIDDISH YOD YOD */ - *ab = 0xFB1F; - found = true; - } else if (a == 0x05D0) { /* ALEF */ - *ab = 0xFB2E; - found = true; - } - break; - case 0x05B8: /* QAMATS */ - if (a == 0x05D0) { /* ALEF */ - *ab = 0xFB2F; - found = true; - } - break; - case 0x05B9: /* HOLAM */ - if (a == 0x05D5) { /* VAV */ - *ab = 0xFB4B; - found = true; - } - break; - case 0x05BC: /* DAGESH */ - if (a >= 0x05D0 && a <= 0x05EA) { - *ab = sDageshForms[a - 0x05D0]; - found = (*ab != 0); - } else if (a == 0xFB2A) { /* SHIN WITH SHIN DOT */ - *ab = 0xFB2C; - found = true; - } else if (a == 0xFB2B) { /* SHIN WITH SIN DOT */ - *ab = 0xFB2D; - found = true; - } - break; - case 0x05BF: /* RAFE */ - switch (a) { - case 0x05D1: /* BET */ - *ab = 0xFB4C; - found = true; - break; - case 0x05DB: /* KAF */ - *ab = 0xFB4D; - found = true; - break; - case 0x05E4: /* PE */ - *ab = 0xFB4E; - found = true; - break; - } - break; - case 0x05C1: /* SHIN DOT */ - if (a == 0x05E9) { /* SHIN */ - *ab = 0xFB2A; - found = true; - } else if (a == 0xFB49) { /* SHIN WITH DAGESH */ - *ab = 0xFB2C; - found = true; - } - break; - case 0x05C2: /* SIN DOT */ - if (a == 0x05E9) { /* SHIN */ - *ab = 0xFB2B; - found = true; - } else if (a == 0xFB49) { /* SHIN WITH DAGESH */ - *ab = 0xFB2D; - found = true; - } - break; - } - } - - return found; -} - const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default = { "default", - collect_features_default, + NULL, /* collect_features */ NULL, /* override_features */ NULL, /* data_create */ NULL, /* data_destroy */ NULL, /* preprocess_text */ - normalization_preference_default, + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, NULL, /* decompose */ - compose_default, + NULL, /* compose */ NULL, /* setup_masks */ - HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, true, /* fallback_position */ }; diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc new file mode 100644 index 0000000..47aa44f --- /dev/null +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc @@ -0,0 +1,417 @@ +/* + * Copyright © 2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-ot-shape-complex-private.hh" + + +/* Hangul shaper */ + + +/* Same order as the feature array below */ +enum { + NONE, + + LJMO, + VJMO, + TJMO, + + FIRST_HANGUL_FEATURE = LJMO, + HANGUL_FEATURE_COUNT = TJMO + 1 +}; + +static const hb_tag_t hangul_features[HANGUL_FEATURE_COUNT] = +{ + HB_TAG_NONE, + HB_TAG('l','j','m','o'), + HB_TAG('v','j','m','o'), + HB_TAG('t','j','m','o') +}; + +static void +collect_features_hangul (hb_ot_shape_planner_t *plan) +{ + hb_ot_map_builder_t *map = &plan->map; + + for (unsigned int i = FIRST_HANGUL_FEATURE; i < HANGUL_FEATURE_COUNT; i++) + map->add_feature (hangul_features[i], 1, F_NONE); +} + +struct hangul_shape_plan_t +{ + ASSERT_POD (); + + hb_mask_t mask_array[HANGUL_FEATURE_COUNT]; +}; + +static void * +data_create_hangul (const hb_ot_shape_plan_t *plan) +{ + hangul_shape_plan_t *hangul_plan = (hangul_shape_plan_t *) calloc (1, sizeof (hangul_shape_plan_t)); + if (unlikely (!hangul_plan)) + return NULL; + + for (unsigned int i = 0; i < HANGUL_FEATURE_COUNT; i++) + hangul_plan->mask_array[i] = plan->map.get_1_mask (hangul_features[i]); + + return hangul_plan; +} + +static void +data_destroy_hangul (void *data) +{ + free (data); +} + +/* Constants for algorithmic hangul syllable [de]composition. */ +#define LBase 0x1100 +#define VBase 0x1161 +#define TBase 0x11A7 +#define LCount 19 +#define VCount 21 +#define TCount 28 +#define SBase 0xAC00 +#define NCount (VCount * TCount) +#define SCount (LCount * NCount) + +#define isCombiningL(u) (hb_in_range<hb_codepoint_t> ((u), LBase, LBase+LCount-1)) +#define isCombiningV(u) (hb_in_range<hb_codepoint_t> ((u), VBase, VBase+VCount-1)) +#define isCombiningT(u) (hb_in_range<hb_codepoint_t> ((u), TBase+1, TBase+TCount-1)) +#define isCombinedS(u) (hb_in_range<hb_codepoint_t> ((u), SBase, SBase+SCount-1)) + +#define isL(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1100, 0x115F, 0xA960, 0xA97C)) +#define isV(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1160, 0x11A7, 0xD7B0, 0xD7C6)) +#define isT(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x11A8, 0x11FF, 0xD7CB, 0xD7FB)) + +#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302e, 0x302f)) + +/* buffer var allocations */ +#define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */ + +static bool +is_zero_width_char (hb_font_t *font, + hb_codepoint_t unicode) +{ + hb_codepoint_t glyph; + return hb_font_get_glyph (font, unicode, 0, &glyph) && hb_font_get_glyph_h_advance (font, glyph) == 0; +} + +static void +preprocess_text_hangul (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font) +{ + HB_BUFFER_ALLOCATE_VAR (buffer, hangul_shaping_feature); + + /* Hangul syllables come in two shapes: LV, and LVT. Of those: + * + * - LV can be precomposed, or decomposed. Lets call those + * <LV> and <L,V>, + * - LVT can be fully precomposed, partically precomposed, or + * fully decomposed. Ie. <LVT>, <LV,T>, or <L,V,T>. + * + * The composition / decomposition is mechanical. However, not + * all <L,V> sequences compose, and not all <LV,T> sequences + * compose. + * + * Here are the specifics: + * + * - <L>: U+1100..115F, U+A960..A97F + * - <V>: U+1160..11A7, U+D7B0..D7C7 + * - <T>: U+11A8..11FF, U+D7CB..D7FB + * + * - Only the <L,V> sequences for the 11xx ranges combine. + * - Only <LV,T> sequences for T in U+11A8..11C3 combine. + * + * Here is what we want to accomplish in this shaper: + * + * - If the whole syllable can be precomposed, do that, + * - Otherwise, fully decompose and apply ljmo/vjmo/tjmo features. + * - If a valid syllable is followed by a Hangul tone mark, reorder the tone + * mark to precede the whole syllable - unless it is a zero-width glyph, in + * which case we leave it untouched, assuming it's designed to overstrike. + * + * That is, of the different possible syllables: + * + * <L> + * <L,V> + * <L,V,T> + * <LV> + * <LVT> + * <LV, T> + * + * - <L> needs no work. + * + * - <LV> and <LVT> can stay the way they are if the font supports them, otherwise we + * should fully decompose them if font supports. + * + * - <L,V> and <L,V,T> we should compose if the whole thing can be composed. + * + * - <LV,T> we should compose if the whole thing can be composed, otherwise we should + * decompose. + */ + + buffer->clear_output (); + unsigned int start = 0, end = 0; /* Extent of most recently seen syllable; + * valid only if start < end + */ + unsigned int count = buffer->len; + + for (buffer->idx = 0; buffer->idx < count;) + { + hb_codepoint_t u = buffer->cur().codepoint; + + if (isHangulTone (u)) + { + /* + * We could cache the width of the tone marks and the existence of dotted-circle, + * but the use of the Hangul tone mark characters seems to be rare enough that + * I didn't bother for now. + */ + if (start < end && end == buffer->out_len) + { + /* Tone mark follows a valid syllable; move it in front, unless it's zero width. */ + buffer->next_glyph (); + if (!is_zero_width_char (font, u)) + { + hb_glyph_info_t *info = buffer->out_info; + hb_glyph_info_t tone = info[end]; + memmove (&info[start + 1], &info[start], (end - start) * sizeof (hb_glyph_info_t)); + info[start] = tone; + } + /* Merge clusters across the (possibly reordered) syllable+tone. + * We want to merge even in the zero-width tone mark case here, + * so that clustering behavior isn't dependent on how the tone mark + * is handled by the font. + */ + buffer->merge_out_clusters (start, end + 1); + } + else + { + /* No valid syllable as base for tone mark; try to insert dotted circle. */ + if (font->has_glyph (0x25cc)) + { + hb_codepoint_t chars[2]; + if (!is_zero_width_char (font, u)) { + chars[0] = u; + chars[1] = 0x25cc; + } else { + chars[0] = 0x25cc; + chars[1] = u; + } + buffer->replace_glyphs (1, 2, chars); + } + else + { + /* No dotted circle available in the font; just leave tone mark untouched. */ + buffer->next_glyph (); + } + } + start = end = buffer->out_len; + continue; + } + + start = buffer->out_len; /* Remember current position as a potential syllable start; + * will only be used if we set end to a later position. + */ + + if (isL (u) && buffer->idx + 1 < count) + { + hb_codepoint_t l = u; + hb_codepoint_t v = buffer->cur(+1).codepoint; + if (isV (v)) + { + /* Have <L,V> or <L,V,T>. */ + hb_codepoint_t t = 0; + unsigned int tindex = 0; + if (buffer->idx + 2 < count) + { + t = buffer->cur(+2).codepoint; + if (isT (t)) + tindex = t - TBase; /* Only used if isCombiningT (t); otherwise invalid. */ + else + t = 0; /* The next character was not a trailing jamo. */ + } + + /* We've got a syllable <L,V,T?>; see if it can potentially be composed. */ + if (isCombiningL (l) && isCombiningV (v) && (t == 0 || isCombiningT (t))) + { + /* Try to compose; if this succeeds, end is set to start+1. */ + hb_codepoint_t s = SBase + (l - LBase) * NCount + (v - VBase) * TCount + tindex; + if (font->has_glyph (s)) + { + buffer->replace_glyphs (t ? 3 : 2, 1, &s); + if (unlikely (buffer->in_error)) + return; + end = start + 1; + continue; + } + } + + /* We didn't compose, either because it's an Old Hangul syllable without a + * precomposed character in Unicode, or because the font didn't support the + * necessary precomposed glyph. + * Set jamo features on the individual glyphs, and advance past them. + */ + buffer->cur().hangul_shaping_feature() = LJMO; + buffer->next_glyph (); + buffer->cur().hangul_shaping_feature() = VJMO; + buffer->next_glyph (); + if (t) + { + buffer->cur().hangul_shaping_feature() = TJMO; + buffer->next_glyph (); + end = start + 3; + } + else + end = start + 2; + buffer->merge_out_clusters (start, end); + continue; + } + } + + else if (isCombinedS (u)) + { + /* Have <LV>, <LVT>, or <LV,T> */ + hb_codepoint_t s = u; + bool has_glyph = font->has_glyph (s); + unsigned int lindex = (s - SBase) / NCount; + unsigned int nindex = (s - SBase) % NCount; + unsigned int vindex = nindex / TCount; + unsigned int tindex = nindex % TCount; + + if (!tindex && + buffer->idx + 1 < count && + isCombiningT (buffer->cur(+1).codepoint)) + { + /* <LV,T>, try to combine. */ + unsigned int new_tindex = buffer->cur(+1).codepoint - TBase; + hb_codepoint_t new_s = s + new_tindex; + if (font->has_glyph (new_s)) + { + buffer->replace_glyphs (2, 1, &new_s); + if (unlikely (buffer->in_error)) + return; + end = start + 1; + continue; + } + } + + /* Otherwise, decompose if font doesn't support <LV> or <LVT>, + * or if having non-combining <LV,T>. Note that we already handled + * combining <LV,T> above. */ + if (!has_glyph || + (!tindex && + buffer->idx + 1 < count && + isT (buffer->cur(+1).codepoint))) + { + hb_codepoint_t decomposed[3] = {LBase + lindex, + VBase + vindex, + TBase + tindex}; + if (font->has_glyph (decomposed[0]) && + font->has_glyph (decomposed[1]) && + (!tindex || font->has_glyph (decomposed[2]))) + { + unsigned int s_len = tindex ? 3 : 2; + buffer->replace_glyphs (1, s_len, decomposed); + if (unlikely (buffer->in_error)) + return; + + /* We decomposed S: apply jamo features to the individual glyphs + * that are now in buffer->out_info. + */ + hb_glyph_info_t *info = buffer->out_info; + + /* If we decomposed an LV because of a non-combining T following, + * we want to include this T in the syllable. + */ + if (has_glyph && !tindex) + { + buffer->next_glyph (); + s_len++; + } + end = start + s_len; + + unsigned int i = start; + info[i++].hangul_shaping_feature() = LJMO; + info[i++].hangul_shaping_feature() = VJMO; + if (i < end) + info[i++].hangul_shaping_feature() = TJMO; + buffer->merge_out_clusters (start, end); + continue; + } + } + + if (has_glyph) + { + /* We didn't decompose the S, so just advance past it. */ + end = start + 1; + buffer->next_glyph (); + continue; + } + } + + /* Didn't find a recognizable syllable, so we leave end <= start; + * this will prevent tone-mark reordering happening. + */ + buffer->next_glyph (); + } + buffer->swap_buffers (); +} + +static void +setup_masks_hangul (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font HB_UNUSED) +{ + const hangul_shape_plan_t *hangul_plan = (const hangul_shape_plan_t *) plan->data; + + if (likely (hangul_plan)) + { + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 0; i < count; i++, info++) + info->mask |= hangul_plan->mask_array[info->hangul_shaping_feature()]; + } + + HB_BUFFER_DEALLOCATE_VAR (buffer, hangul_shaping_feature); +} + + +const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul = +{ + "hangul", + collect_features_hangul, + NULL, /* override_features */ + data_create_hangul, /* data_create */ + data_destroy_hangul, /* data_destroy */ + preprocess_text_hangul, + HB_OT_SHAPE_NORMALIZATION_MODE_NONE, + NULL, /* decompose */ + NULL, /* compose */ + setup_masks_hangul, /* setup_masks */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, + false, /* fallback_position */ +}; diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc new file mode 100644 index 0000000..efef8c1 --- /dev/null +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc @@ -0,0 +1,172 @@ +/* + * Copyright © 2010,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-ot-shape-complex-private.hh" + + +static bool +compose_hebrew (const hb_ot_shape_normalize_context_t *c, + hb_codepoint_t a, + hb_codepoint_t b, + hb_codepoint_t *ab) +{ + /* Hebrew presentation-form shaping. + * https://bugzilla.mozilla.org/show_bug.cgi?id=728866 + * Hebrew presentation forms with dagesh, for characters 0x05D0..0x05EA; + * Note that some letters do not have a dagesh presForm encoded. + */ + static const hb_codepoint_t sDageshForms[0x05EA - 0x05D0 + 1] = { + 0xFB30, /* ALEF */ + 0xFB31, /* BET */ + 0xFB32, /* GIMEL */ + 0xFB33, /* DALET */ + 0xFB34, /* HE */ + 0xFB35, /* VAV */ + 0xFB36, /* ZAYIN */ + 0x0000, /* HET */ + 0xFB38, /* TET */ + 0xFB39, /* YOD */ + 0xFB3A, /* FINAL KAF */ + 0xFB3B, /* KAF */ + 0xFB3C, /* LAMED */ + 0x0000, /* FINAL MEM */ + 0xFB3E, /* MEM */ + 0x0000, /* FINAL NUN */ + 0xFB40, /* NUN */ + 0xFB41, /* SAMEKH */ + 0x0000, /* AYIN */ + 0xFB43, /* FINAL PE */ + 0xFB44, /* PE */ + 0x0000, /* FINAL TSADI */ + 0xFB46, /* TSADI */ + 0xFB47, /* QOF */ + 0xFB48, /* RESH */ + 0xFB49, /* SHIN */ + 0xFB4A /* TAV */ + }; + + bool found = c->unicode->compose (a, b, ab); + + if (!found) + { + /* Special-case Hebrew presentation forms that are excluded from + * standard normalization, but wanted for old fonts. */ + switch (b) { + case 0x05B4: /* HIRIQ */ + if (a == 0x05D9) { /* YOD */ + *ab = 0xFB1D; + found = true; + } + break; + case 0x05B7: /* patah */ + if (a == 0x05F2) { /* YIDDISH YOD YOD */ + *ab = 0xFB1F; + found = true; + } else if (a == 0x05D0) { /* ALEF */ + *ab = 0xFB2E; + found = true; + } + break; + case 0x05B8: /* QAMATS */ + if (a == 0x05D0) { /* ALEF */ + *ab = 0xFB2F; + found = true; + } + break; + case 0x05B9: /* HOLAM */ + if (a == 0x05D5) { /* VAV */ + *ab = 0xFB4B; + found = true; + } + break; + case 0x05BC: /* DAGESH */ + if (a >= 0x05D0 && a <= 0x05EA) { + *ab = sDageshForms[a - 0x05D0]; + found = (*ab != 0); + } else if (a == 0xFB2A) { /* SHIN WITH SHIN DOT */ + *ab = 0xFB2C; + found = true; + } else if (a == 0xFB2B) { /* SHIN WITH SIN DOT */ + *ab = 0xFB2D; + found = true; + } + break; + case 0x05BF: /* RAFE */ + switch (a) { + case 0x05D1: /* BET */ + *ab = 0xFB4C; + found = true; + break; + case 0x05DB: /* KAF */ + *ab = 0xFB4D; + found = true; + break; + case 0x05E4: /* PE */ + *ab = 0xFB4E; + found = true; + break; + } + break; + case 0x05C1: /* SHIN DOT */ + if (a == 0x05E9) { /* SHIN */ + *ab = 0xFB2A; + found = true; + } else if (a == 0xFB49) { /* SHIN WITH DAGESH */ + *ab = 0xFB2C; + found = true; + } + break; + case 0x05C2: /* SIN DOT */ + if (a == 0x05E9) { /* SHIN */ + *ab = 0xFB2B; + found = true; + } else if (a == 0xFB49) { /* SHIN WITH DAGESH */ + *ab = 0xFB2D; + found = true; + } + break; + } + } + + return found; +} + + +const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew = +{ + "hebrew", + NULL, /* collect_features */ + NULL, /* override_features */ + NULL, /* data_create */ + NULL, /* data_destroy */ + NULL, /* preprocess_text */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, + NULL, /* decompose */ + compose_hebrew, + NULL, /* setup_masks */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, + true, /* fallback_position */ +}; diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc index 9edefe3..1e07d33 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc @@ -1690,12 +1690,6 @@ clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, } -static hb_ot_shape_normalization_mode_t -normalization_preference_indic (const hb_segment_properties_t *props HB_UNUSED) -{ - return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT; -} - static bool decompose_indic (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t ab, @@ -1806,7 +1800,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic = data_create_indic, data_destroy_indic, NULL, /* preprocess_text */ - normalization_preference_indic, + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, decompose_indic, compose_indic, setup_masks_indic, diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh index 9d6f62f..8cbf52a 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh @@ -34,196 +34,197 @@ #line 36 "hb-ot-shape-complex-myanmar-machine.hh.tmp" static const unsigned char _myanmar_syllable_machine_trans_keys[] = { - 1u, 30u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, + 1u, 31u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 1u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, - 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 0 + 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 8u, 8u, 0 }; static const char _myanmar_syllable_machine_key_spans[] = { - 30, 28, 25, 4, 25, 23, 21, 21, + 31, 28, 25, 4, 25, 23, 21, 21, 27, 27, 27, 27, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 25, 4, 25, 23, 21, 21, 27, 27, 27, 27, 28, 27, 30, 27, 27, 27, 27, 27, - 27, 27, 27, 27 + 27, 27, 27, 27, 1 }; static const short _myanmar_syllable_machine_index_offsets[] = { - 0, 31, 60, 86, 91, 117, 141, 163, - 185, 213, 241, 269, 297, 314, 342, 370, - 398, 426, 454, 482, 510, 538, 566, 592, - 597, 623, 647, 669, 691, 719, 747, 775, - 803, 832, 860, 891, 919, 947, 975, 1003, - 1031, 1059, 1087, 1115 + 0, 32, 61, 87, 92, 118, 142, 164, + 186, 214, 242, 270, 298, 315, 343, 371, + 399, 427, 455, 483, 511, 539, 567, 593, + 598, 624, 648, 670, 692, 720, 748, 776, + 804, 833, 861, 892, 920, 948, 976, 1004, + 1032, 1060, 1088, 1116, 1144 }; static const char _myanmar_syllable_machine_indicies[] = { 1, 1, 2, 3, 4, 4, 0, 5, 0, 6, 0, 1, 0, 0, 0, 7, 0, 8, 1, 0, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 0, 20, - 21, 22, 22, 19, 23, 19, 24, 19, - 19, 19, 19, 19, 19, 19, 25, 19, - 19, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 19, 22, 22, 19, 23, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 36, 19, 19, 19, 19, 19, 19, - 30, 19, 19, 19, 34, 19, 22, 22, - 19, 23, 19, 22, 22, 19, 23, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 30, - 19, 19, 19, 34, 19, 37, 19, 22, - 22, 19, 23, 19, 30, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 30, 19, 22, 22, 19, - 23, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 38, 19, 19, 19, 19, 19, - 19, 30, 19, 22, 22, 19, 23, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 30, - 19, 20, 19, 22, 22, 19, 23, 19, - 24, 19, 19, 19, 19, 19, 19, 19, - 39, 19, 19, 39, 19, 19, 19, 30, - 40, 19, 19, 34, 19, 20, 19, 22, - 22, 19, 23, 19, 24, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 30, 19, 19, 19, 34, - 19, 20, 19, 22, 22, 19, 23, 19, - 24, 19, 19, 19, 19, 19, 19, 19, - 39, 19, 19, 19, 19, 19, 19, 30, - 40, 19, 19, 34, 19, 20, 19, 22, - 22, 19, 23, 19, 24, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 30, 40, 19, 19, 34, - 19, 1, 1, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 1, 19, 20, 19, 22, 22, 19, 23, - 19, 24, 19, 19, 19, 19, 19, 19, - 19, 25, 19, 19, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 19, 20, 19, - 22, 22, 19, 23, 19, 24, 19, 19, - 19, 19, 19, 19, 19, 33, 19, 19, - 19, 19, 19, 19, 30, 31, 32, 33, - 34, 19, 20, 19, 22, 22, 19, 23, - 19, 24, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 30, 31, 32, 33, 34, 19, 20, 19, - 22, 22, 19, 23, 19, 24, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 30, 31, 32, 19, - 34, 19, 20, 19, 22, 22, 19, 23, - 19, 24, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 30, 19, 32, 19, 34, 19, 20, 19, - 22, 22, 19, 23, 19, 24, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 26, 19, 28, 19, 30, 31, 32, 33, - 34, 19, 20, 19, 22, 22, 19, 23, - 19, 24, 19, 19, 19, 19, 19, 19, - 19, 33, 19, 19, 26, 19, 19, 19, - 30, 31, 32, 33, 34, 19, 20, 19, - 22, 22, 19, 23, 19, 24, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 26, 27, 28, 19, 30, 31, 32, 33, - 34, 19, 20, 21, 22, 22, 19, 23, - 19, 24, 19, 19, 19, 19, 19, 19, - 19, 25, 19, 19, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 19, 3, 3, - 41, 5, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 42, 41, 41, 41, 41, - 41, 41, 13, 41, 41, 41, 17, 41, - 3, 3, 41, 5, 41, 3, 3, 41, - 5, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, - 41, 13, 41, 41, 41, 17, 41, 43, - 41, 3, 3, 41, 5, 41, 13, 41, - 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 13, 41, 3, - 3, 41, 5, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 44, 41, 41, 41, - 41, 41, 41, 13, 41, 3, 3, 41, - 5, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, - 41, 13, 41, 2, 41, 3, 3, 41, - 5, 41, 6, 41, 41, 41, 41, 41, - 41, 41, 45, 41, 41, 45, 41, 41, - 41, 13, 46, 41, 41, 17, 41, 2, - 41, 3, 3, 41, 5, 41, 6, 41, - 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 13, 41, 41, - 41, 17, 41, 2, 41, 3, 3, 41, - 5, 41, 6, 41, 41, 41, 41, 41, - 41, 41, 45, 41, 41, 41, 41, 41, - 41, 13, 46, 41, 41, 17, 41, 2, - 41, 3, 3, 41, 5, 41, 6, 41, - 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 13, 46, 41, - 41, 17, 41, 20, 21, 22, 22, 19, - 23, 19, 24, 19, 19, 19, 19, 19, - 19, 19, 47, 19, 19, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 19, - 20, 48, 22, 22, 19, 23, 19, 24, - 19, 19, 19, 19, 19, 19, 19, 25, - 19, 19, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 19, 1, 1, 2, 3, - 3, 3, 41, 5, 41, 6, 41, 1, - 41, 41, 41, 1, 41, 8, 1, 41, - 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 41, 2, 41, 3, 3, 41, - 5, 41, 6, 41, 41, 41, 41, 41, - 41, 41, 8, 41, 41, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 41, 2, - 41, 3, 3, 41, 5, 41, 6, 41, - 41, 41, 41, 41, 41, 41, 16, 41, - 41, 41, 41, 41, 41, 13, 14, 15, - 16, 17, 41, 2, 41, 3, 3, 41, - 5, 41, 6, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, - 41, 13, 14, 15, 16, 17, 41, 2, - 41, 3, 3, 41, 5, 41, 6, 41, - 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 13, 14, 15, - 41, 17, 41, 2, 41, 3, 3, 41, - 5, 41, 6, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, - 41, 13, 41, 15, 41, 17, 41, 2, - 41, 3, 3, 41, 5, 41, 6, 41, - 41, 41, 41, 41, 41, 41, 41, 41, - 41, 9, 41, 11, 41, 13, 14, 15, - 16, 17, 41, 2, 41, 3, 3, 41, - 5, 41, 6, 41, 41, 41, 41, 41, - 41, 41, 16, 41, 41, 9, 41, 41, - 41, 13, 14, 15, 16, 17, 41, 2, - 41, 3, 3, 41, 5, 41, 6, 41, - 41, 41, 41, 41, 41, 41, 41, 41, - 41, 9, 10, 11, 41, 13, 14, 15, - 16, 17, 41, 2, 3, 3, 3, 41, - 5, 41, 6, 41, 41, 41, 41, 41, - 41, 41, 8, 41, 41, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 41, 0 + 13, 14, 15, 16, 17, 18, 19, 0, + 21, 22, 23, 23, 20, 24, 20, 25, + 20, 20, 20, 20, 20, 20, 20, 26, + 20, 20, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 20, 23, 23, 20, + 24, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 37, 20, 20, 20, 20, 20, + 20, 31, 20, 20, 20, 35, 20, 23, + 23, 20, 24, 20, 23, 23, 20, 24, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 31, 20, 20, 20, 35, 20, 38, 20, + 23, 23, 20, 24, 20, 31, 20, 20, + 20, 20, 20, 20, 20, 39, 20, 20, + 20, 20, 20, 20, 31, 20, 23, 23, + 20, 24, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 39, 20, 20, 20, 20, + 20, 20, 31, 20, 23, 23, 20, 24, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 31, 20, 21, 20, 23, 23, 20, 24, + 20, 25, 20, 20, 20, 20, 20, 20, + 20, 40, 20, 20, 40, 20, 20, 20, + 31, 41, 20, 20, 35, 20, 21, 20, + 23, 23, 20, 24, 20, 25, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 31, 20, 20, 20, + 35, 20, 21, 20, 23, 23, 20, 24, + 20, 25, 20, 20, 20, 20, 20, 20, + 20, 40, 20, 20, 20, 20, 20, 20, + 31, 41, 20, 20, 35, 20, 21, 20, + 23, 23, 20, 24, 20, 25, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 31, 41, 20, 20, + 35, 20, 1, 1, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 1, 20, 21, 20, 23, 23, 20, + 24, 20, 25, 20, 20, 20, 20, 20, + 20, 20, 26, 20, 20, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 20, 21, + 20, 23, 23, 20, 24, 20, 25, 20, + 20, 20, 20, 20, 20, 20, 34, 20, + 20, 20, 20, 20, 20, 31, 32, 33, + 34, 35, 20, 21, 20, 23, 23, 20, + 24, 20, 25, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 31, 32, 33, 34, 35, 20, 21, + 20, 23, 23, 20, 24, 20, 25, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 31, 32, 33, + 20, 35, 20, 21, 20, 23, 23, 20, + 24, 20, 25, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 31, 20, 33, 20, 35, 20, 21, + 20, 23, 23, 20, 24, 20, 25, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 27, 20, 29, 20, 31, 32, 33, + 34, 35, 20, 21, 20, 23, 23, 20, + 24, 20, 25, 20, 20, 20, 20, 20, + 20, 20, 34, 20, 20, 27, 20, 20, + 20, 31, 32, 33, 34, 35, 20, 21, + 20, 23, 23, 20, 24, 20, 25, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 27, 28, 29, 20, 31, 32, 33, + 34, 35, 20, 21, 22, 23, 23, 20, + 24, 20, 25, 20, 20, 20, 20, 20, + 20, 20, 26, 20, 20, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 20, 3, + 3, 42, 5, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 43, 42, 42, 42, + 42, 42, 42, 13, 42, 42, 42, 17, + 42, 3, 3, 42, 5, 42, 3, 3, + 42, 5, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 13, 42, 42, 42, 17, 42, + 44, 42, 3, 3, 42, 5, 42, 13, + 42, 42, 42, 42, 42, 42, 42, 45, + 42, 42, 42, 42, 42, 42, 13, 42, + 3, 3, 42, 5, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 45, 42, 42, + 42, 42, 42, 42, 13, 42, 3, 3, + 42, 5, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 13, 42, 2, 42, 3, 3, + 42, 5, 42, 6, 42, 42, 42, 42, + 42, 42, 42, 46, 42, 42, 46, 42, + 42, 42, 13, 47, 42, 42, 17, 42, + 2, 42, 3, 3, 42, 5, 42, 6, + 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 13, 42, + 42, 42, 17, 42, 2, 42, 3, 3, + 42, 5, 42, 6, 42, 42, 42, 42, + 42, 42, 42, 46, 42, 42, 42, 42, + 42, 42, 13, 47, 42, 42, 17, 42, + 2, 42, 3, 3, 42, 5, 42, 6, + 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 13, 47, + 42, 42, 17, 42, 21, 22, 23, 23, + 20, 24, 20, 25, 20, 20, 20, 20, + 20, 20, 20, 48, 20, 20, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, + 20, 21, 49, 23, 23, 20, 24, 20, + 25, 20, 20, 20, 20, 20, 20, 20, + 26, 20, 20, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 20, 1, 1, 2, + 3, 3, 3, 42, 5, 42, 6, 42, + 1, 42, 42, 42, 1, 42, 8, 1, + 42, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 42, 2, 42, 3, 3, + 42, 5, 42, 6, 42, 42, 42, 42, + 42, 42, 42, 8, 42, 42, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 42, + 2, 42, 3, 3, 42, 5, 42, 6, + 42, 42, 42, 42, 42, 42, 42, 16, + 42, 42, 42, 42, 42, 42, 13, 14, + 15, 16, 17, 42, 2, 42, 3, 3, + 42, 5, 42, 6, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 13, 14, 15, 16, 17, 42, + 2, 42, 3, 3, 42, 5, 42, 6, + 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 13, 14, + 15, 42, 17, 42, 2, 42, 3, 3, + 42, 5, 42, 6, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 13, 42, 15, 42, 17, 42, + 2, 42, 3, 3, 42, 5, 42, 6, + 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 9, 42, 11, 42, 13, 14, + 15, 16, 17, 42, 2, 42, 3, 3, + 42, 5, 42, 6, 42, 42, 42, 42, + 42, 42, 42, 16, 42, 42, 9, 42, + 42, 42, 13, 14, 15, 16, 17, 42, + 2, 42, 3, 3, 42, 5, 42, 6, + 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 9, 10, 11, 42, 13, 14, + 15, 16, 17, 42, 2, 3, 3, 3, + 42, 5, 42, 6, 42, 42, 42, 42, + 42, 42, 42, 8, 42, 42, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 42, + 51, 50, 0 }; static const char _myanmar_syllable_machine_trans_targs[] = { 0, 1, 22, 0, 0, 23, 29, 32, 35, 36, 40, 41, 42, 25, 38, 39, - 37, 28, 43, 0, 2, 12, 0, 3, - 9, 13, 14, 18, 19, 20, 5, 16, - 17, 15, 8, 21, 4, 6, 7, 10, - 11, 0, 24, 26, 27, 30, 31, 33, - 34 + 37, 28, 43, 44, 0, 2, 12, 0, + 3, 9, 13, 14, 18, 19, 20, 5, + 16, 17, 15, 8, 21, 4, 6, 7, + 10, 11, 0, 24, 26, 27, 30, 31, + 33, 34, 0, 0 }; static const char _myanmar_syllable_machine_trans_actions[] = { 3, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 6, 0, 0, 7, 0, + 0, 0, 0, 0, 6, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 8, 0, 0, 0, 0, 0, 0, - 0 + 0, 0, 8, 0, 0, 0, 0, 0, + 0, 0, 9, 10 }; static const char _myanmar_syllable_machine_to_state_actions[] = { @@ -232,7 +233,7 @@ static const char _myanmar_syllable_machine_to_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 + 0, 0, 0, 0, 0 }; static const char _myanmar_syllable_machine_from_state_actions[] = { @@ -241,16 +242,16 @@ static const char _myanmar_syllable_machine_from_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 + 0, 0, 0, 0, 0 }; static const short _myanmar_syllable_machine_eof_trans[] = { - 0, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, - 20, 20, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42 + 0, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + 21, 21, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 51 }; static const int myanmar_syllable_machine_start = 0; @@ -264,7 +265,7 @@ static const int myanmar_syllable_machine_en_main = 0; -#line 90 "hb-ot-shape-complex-myanmar-machine.rl" +#line 93 "hb-ot-shape-complex-myanmar-machine.rl" #define found_syllable(syllable_type) \ @@ -284,7 +285,7 @@ find_syllables (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 288 "hb-ot-shape-complex-myanmar-machine.hh.tmp" +#line 289 "hb-ot-shape-complex-myanmar-machine.hh.tmp" { cs = myanmar_syllable_machine_start; ts = 0; @@ -292,7 +293,7 @@ find_syllables (hb_buffer_t *buffer) act = 0; } -#line 111 "hb-ot-shape-complex-myanmar-machine.rl" +#line 114 "hb-ot-shape-complex-myanmar-machine.rl" p = 0; @@ -301,7 +302,7 @@ find_syllables (hb_buffer_t *buffer) unsigned int last = 0; unsigned int syllable_serial = 1; -#line 305 "hb-ot-shape-complex-myanmar-machine.hh.tmp" +#line 306 "hb-ot-shape-complex-myanmar-machine.hh.tmp" { int _slen; int _trans; @@ -315,7 +316,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 319 "hb-ot-shape-complex-myanmar-machine.hh.tmp" +#line 320 "hb-ot-shape-complex-myanmar-machine.hh.tmp" } _keys = _myanmar_syllable_machine_trans_keys + (cs<<1); @@ -334,30 +335,38 @@ _eof_trans: switch ( _myanmar_syllable_machine_trans_actions[_trans] ) { case 7: -#line 83 "hb-ot-shape-complex-myanmar-machine.rl" +#line 85 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (consonant_syllable); }} break; case 5: -#line 84 "hb-ot-shape-complex-myanmar-machine.rl" +#line 86 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (non_myanmar_cluster); }} break; + case 10: +#line 87 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (punctuation_cluster); }} + break; case 4: -#line 85 "hb-ot-shape-complex-myanmar-machine.rl" +#line 88 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (broken_cluster); }} break; case 3: -#line 86 "hb-ot-shape-complex-myanmar-machine.rl" +#line 89 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (non_myanmar_cluster); }} break; case 6: -#line 83 "hb-ot-shape-complex-myanmar-machine.rl" +#line 85 "hb-ot-shape-complex-myanmar-machine.rl" {te = p;p--;{ found_syllable (consonant_syllable); }} break; case 8: -#line 85 "hb-ot-shape-complex-myanmar-machine.rl" +#line 88 "hb-ot-shape-complex-myanmar-machine.rl" {te = p;p--;{ found_syllable (broken_cluster); }} break; -#line 361 "hb-ot-shape-complex-myanmar-machine.hh.tmp" + case 9: +#line 89 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p;p--;{ found_syllable (non_myanmar_cluster); }} + break; +#line 370 "hb-ot-shape-complex-myanmar-machine.hh.tmp" } _again: @@ -366,7 +375,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 370 "hb-ot-shape-complex-myanmar-machine.hh.tmp" +#line 379 "hb-ot-shape-complex-myanmar-machine.hh.tmp" } if ( ++p != pe ) @@ -382,7 +391,7 @@ _again: } -#line 120 "hb-ot-shape-complex-myanmar-machine.rl" +#line 123 "hb-ot-shape-complex-myanmar-machine.rl" } diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc index a32405a..50209ff 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc @@ -119,6 +119,7 @@ override_features_myanmar (hb_ot_shape_planner_t *plan) enum syllable_type_t { consonant_syllable, + punctuation_cluster, broken_cluster, non_myanmar_cluster, }; @@ -143,7 +144,8 @@ enum myanmar_category_t { OT_VBlw = 27, OT_VPre = 28, OT_VPst = 29, - OT_VS = 30 /* Variation selectors */ + OT_VS = 30, /* Variation selectors */ + OT_P = 31 /* Punctuation */ }; @@ -186,6 +188,10 @@ set_myanmar_properties (hb_glyph_info_t &info) switch (u) { + case 0x104E: + cat = (indic_category_t) OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */ + break; + case 0x002D: case 0x00A0: case 0x00D7: case 0x2012: case 0x2013: case 0x2014: case 0x2015: case 0x2022: case 0x25CC: case 0x25FB: case 0x25FC: case 0x25FD: @@ -243,6 +249,10 @@ set_myanmar_properties (hb_glyph_info_t &info) case 0x108F: case 0x109A: case 0x109B: case 0x109C: cat = (indic_category_t) OT_SM; break; + + case 0x104A: case 0x104B: + cat = (indic_category_t) OT_P; + break; } if (cat == OT_M) @@ -406,6 +416,16 @@ initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan, } static void +initial_reordering_punctuation_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_face_t *face HB_UNUSED, + hb_buffer_t *buffer HB_UNUSED, + unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) +{ + /* Nothing to do right now. If we ever switch to using the output + * buffer in the reordering process, we'd need to next_glyph() here. */ +} + +static void initial_reordering_non_myanmar_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_face_t *face HB_UNUSED, hb_buffer_t *buffer HB_UNUSED, @@ -425,6 +445,7 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan, syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); switch (syllable_type) { case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return; + case punctuation_cluster: initial_reordering_punctuation_cluster (plan, face, buffer, start, end); return; case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return; case non_myanmar_cluster: initial_reordering_non_myanmar_cluster (plan, face, buffer, start, end); return; } @@ -520,13 +541,6 @@ final_reordering (const hb_ot_shape_plan_t *plan, } -static hb_ot_shape_normalization_mode_t -normalization_preference_myanmar (const hb_segment_properties_t *props HB_UNUSED) -{ - return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT; -} - - const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar = { "myanmar", @@ -535,7 +549,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar = NULL, /* data_create */ NULL, /* data_destroy */ NULL, /* preprocess_text */ - normalization_preference_myanmar, + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, NULL, /* decompose */ NULL, /* compose */ setup_masks_myanmar, diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh index ac0072b..104726e 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh @@ -44,7 +44,9 @@ enum hb_ot_shape_zero_width_marks_type_t { // HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, - HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, + + HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT = HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE }; @@ -52,10 +54,13 @@ enum hb_ot_shape_zero_width_marks_type_t { #define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \ HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \ HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \ + HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \ + HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \ HB_COMPLEX_SHAPER_IMPLEMENT (indic) \ HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \ HB_COMPLEX_SHAPER_IMPLEMENT (sea) \ HB_COMPLEX_SHAPER_IMPLEMENT (thai) \ + HB_COMPLEX_SHAPER_IMPLEMENT (tibetan) \ /* ^--- Add new shapers here */ @@ -105,12 +110,7 @@ struct hb_ot_complex_shaper_t hb_font_t *font); - /* normalization_preference() - * Called during shape(). - * May be NULL. - */ - hb_ot_shape_normalization_mode_t - (*normalization_preference) (const hb_segment_properties_t *props); + hb_ot_shape_normalization_mode_t normalization_preference; /* decompose() * Called during shape()'s normalization. @@ -189,19 +189,22 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) return &_hb_ot_complex_shaper_thai; -#if 0 - /* Note: - * Currently we don't have a separate Hangul shaper. The default shaper handles - * Hangul by enabling jamo features. We may want to implement a separate shaper - * in the future. See this thread for details of what such a shaper would do: - * - * http://lists.freedesktop.org/archives/harfbuzz/2013-April/003070.html - */ /* Unicode-1.1 additions */ case HB_SCRIPT_HANGUL: return &_hb_ot_complex_shaper_hangul; -#endif + + + /* Unicode-2.0 additions */ + case HB_SCRIPT_TIBETAN: + + return &_hb_ot_complex_shaper_tibetan; + + + /* Unicode-1.1 additions */ + case HB_SCRIPT_HEBREW: + + return &_hb_ot_complex_shaper_hebrew; /* ^--- Add new shapers here */ @@ -241,9 +244,6 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_LAO: case HB_SCRIPT_THAI: - /* Unicode-2.0 additions */ - case HB_SCRIPT_TIBETAN: - /* Unicode-3.2 additions */ case HB_SCRIPT_TAGALOG: case HB_SCRIPT_TAGBANWA: diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc index da687ed..6288a90 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc @@ -360,13 +360,6 @@ final_reordering (const hb_ot_shape_plan_t *plan, } -static hb_ot_shape_normalization_mode_t -normalization_preference_sea (const hb_segment_properties_t *props HB_UNUSED) -{ - return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT; -} - - const hb_ot_complex_shaper_t _hb_ot_complex_shaper_sea = { "sea", @@ -375,7 +368,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_sea = NULL, /* data_create */ NULL, /* data_destroy */ NULL, /* preprocess_text */ - normalization_preference_sea, + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, NULL, /* decompose */ NULL, /* compose */ setup_masks_sea, diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc index 4594533..8664eca 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc @@ -369,10 +369,10 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai = NULL, /* data_create */ NULL, /* data_destroy */ preprocess_text_thai, - NULL, /* normalization_preference */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, NULL, /* decompose */ NULL, /* compose */ NULL, /* setup_masks */ - HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, false,/* fallback_position */ }; diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc new file mode 100644 index 0000000..01465a4 --- /dev/null +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc @@ -0,0 +1,61 @@ +/* + * Copyright © 2010,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-ot-shape-complex-private.hh" + + +static const hb_tag_t tibetan_features[] = +{ + HB_TAG('a','b','v','s'), + HB_TAG('b','l','w','s'), + HB_TAG('a','b','v','m'), + HB_TAG('b','l','w','m'), + HB_TAG_NONE +}; + +static void +collect_features_tibetan (hb_ot_shape_planner_t *plan) +{ + for (const hb_tag_t *script_features = tibetan_features; script_features && *script_features; script_features++) + plan->map.add_global_bool_feature (*script_features); +} + + +const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan = +{ + "default", + collect_features_tibetan, + 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_DEFAULT, + true, /* fallback_position */ +}; diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc index 449b64e..5d526c3 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc @@ -430,14 +430,12 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { - hb_mask_t kern_mask = plan->map.get_1_mask (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ? - HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n')); - if (!kern_mask) return; + if (!plan->has_kern) return; unsigned int count = buffer->len; OT::hb_apply_context_t c (1, font, buffer); - c.set_lookup_mask (kern_mask); + c.set_lookup_mask (plan->kern_mask); c.set_lookup_props (OT::LookupFlag::IgnoreMarks); hb_glyph_info_t *info = buffer->info; diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh index 085d485..c744e26 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh @@ -29,8 +29,6 @@ #include "hb-private.hh" -#include "hb-font.h" -#include "hb-buffer.h" /* buffer var allocations, used during the normalization process */ #define glyph_index() var1.u32 @@ -38,6 +36,7 @@ struct hb_ot_shape_plan_t; enum hb_ot_shape_normalization_mode_t { + HB_OT_SHAPE_NORMALIZATION_MODE_NONE, HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED, HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* never composes base-to-base */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* always fully decomposes and then recompose back */ diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc index 6531e1b..2a6a439 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc @@ -213,8 +213,9 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor } static inline void -handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end) +handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit) { + /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */ hb_buffer_t * const buffer = c->buffer; hb_font_t * const font = c->font; for (; buffer->idx < end - 1;) { @@ -250,27 +251,26 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, uns } static inline void -decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end) +decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit) { hb_buffer_t * const buffer = c->buffer; - /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */ for (unsigned int i = buffer->idx; i < end; i++) if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) { - handle_variation_selector_cluster (c, end); + handle_variation_selector_cluster (c, end, short_circuit); return; } while (buffer->idx < end) - decompose_current_character (c, false); + decompose_current_character (c, short_circuit); } static inline void -decompose_cluster (const hb_ot_shape_normalize_context_t *c, bool short_circuit, unsigned int end) +decompose_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool might_short_circuit, bool always_short_circuit) { if (likely (c->buffer->idx + 1 == end)) - decompose_current_character (c, short_circuit); + decompose_current_character (c, might_short_circuit); else - decompose_multi_char_cluster (c, end); + decompose_multi_char_cluster (c, end, always_short_circuit); } @@ -289,9 +289,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, hb_font_t *font) { - hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference ? - plan->shaper->normalization_preference (&buffer->props) : - HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT; + hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference; const hb_ot_shape_normalize_context_t c = { plan, buffer, @@ -301,8 +299,10 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, plan->shaper->compose ? plan->shaper->compose : compose_unicode }; - bool short_circuit = mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED && - mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT; + bool always_short_circuit = mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE; + bool might_short_circuit = always_short_circuit || + (mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED && + mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT); unsigned int count; /* We do a fairly straightforward yet custom normalization process in three @@ -323,7 +323,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, if (buffer->cur().cluster != buffer->info[end].cluster) break; - decompose_cluster (&c, short_circuit, end); + decompose_cluster (&c, end, might_short_circuit, always_short_circuit); } buffer->swap_buffers (); @@ -355,7 +355,8 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, } - if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED) + if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE || + mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED) return; /* Third round, recompose */ @@ -393,8 +394,9 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, return; buffer->merge_out_clusters (starter, buffer->out_len); buffer->out_len--; /* Remove the second composable. */ - buffer->out_info[starter].codepoint = composed; /* Modify starter and carry on. */ - set_glyph (buffer->out_info[starter], font); + /* Modify starter and carry on. */ + buffer->out_info[starter].codepoint = composed; + buffer->out_info[starter].glyph_index() = glyph; _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unicode); continue; diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh index 8171471..df81fa2 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh +++ b/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh @@ -40,6 +40,10 @@ struct hb_ot_shape_plan_t const struct hb_ot_complex_shaper_t *shaper; hb_ot_map_t map; const void *data; + hb_mask_t rtlm_mask, frac_mask, numr_mask, dnom_mask; + hb_mask_t kern_mask; + unsigned int has_frac : 1; + unsigned int has_kern : 1; inline void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const { @@ -66,7 +70,7 @@ struct hb_ot_shape_planner_t hb_ot_map_builder_t map; hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan) : - face (master_plan->face), + face (master_plan->face_unsafe), props (master_plan->props), shaper (NULL), map (face, &props) {} @@ -77,6 +81,17 @@ struct hb_ot_shape_planner_t plan.props = props; plan.shaper = shaper; map.compile (plan.map); + + plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m')); + plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); + plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r')); + plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m')); + + plan.kern_mask = plan.map.get_mask (HB_DIRECTION_IS_HORIZONTAL (plan.props.direction) ? + HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n')); + + plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask); + plan.has_kern = !!plan.kern_mask; } private: diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape.cc b/third_party/harfbuzz-ng/src/hb-ot-shape.cc index 63c36f9..3080a1d 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-shape.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-shape.cc @@ -88,6 +88,10 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, break; } + map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE); + map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE); + map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE); + if (planner->shaper->collect_features) planner->shaper->collect_features (planner); @@ -234,8 +238,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) return; - hb_codepoint_t dottedcircle_glyph; - if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph)) + if (!font->has_glyph (0x25CC)) return; hb_glyph_info_t dottedcircle; @@ -292,7 +295,7 @@ hb_ot_mirror_chars (hb_ot_shape_context_t *c) hb_buffer_t *buffer = c->buffer; hb_unicode_funcs_t *unicode = buffer->unicode; - hb_mask_t rtlm_mask = c->plan->map.get_1_mask (HB_TAG ('r','t','l','m')); + hb_mask_t rtlm_mask = c->plan->rtlm_mask; unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; @@ -306,13 +309,58 @@ hb_ot_mirror_chars (hb_ot_shape_context_t *c) } static inline void -hb_ot_shape_setup_masks (hb_ot_shape_context_t *c) +hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c) +{ + if (!c->plan->has_frac) + return; + + hb_buffer_t *buffer = c->buffer; + + /* TODO look in pre/post context text also. */ + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 0; i < count; i++) + { + if (info[i].codepoint == 0x2044) /* FRACTION SLASH */ + { + unsigned int start = i, end = i + 1; + while (start && + _hb_glyph_info_get_general_category (&info[start - 1]) == + HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) + start--; + while (end < count && + _hb_glyph_info_get_general_category (&info[end]) == + HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) + end++; + + for (unsigned int j = start; j < i; j++) + info[j].mask |= c->plan->numr_mask | c->plan->frac_mask; + info[i].mask |= c->plan->frac_mask; + for (unsigned int j = i + 1; j < end; j++) + info[j].mask |= c->plan->frac_mask | c->plan->dnom_mask; + + i = end - 1; + } + } +} + +static inline void +hb_ot_shape_initialize_masks (hb_ot_shape_context_t *c) { hb_ot_map_t *map = &c->plan->map; hb_buffer_t *buffer = c->buffer; hb_mask_t global_mask = map->get_global_mask (); buffer->reset_masks (global_mask); +} + +static inline void +hb_ot_shape_setup_masks (hb_ot_shape_context_t *c) +{ + hb_ot_map_t *map = &c->plan->map; + hb_buffer_t *buffer = c->buffer; + + hb_ot_shape_setup_masks_fraction (c); if (c->plan->shaper->setup_masks) c->plan->shaper->setup_masks (c->plan, buffer, c->font); @@ -358,6 +406,8 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c) if (c->plan->shaper->preprocess_text) c->plan->shaper->preprocess_text (c->plan, buffer, c->font); + hb_ot_shape_initialize_masks (c); + hb_ot_mirror_chars (c); HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index); diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape.h b/third_party/harfbuzz-ng/src/hb-ot-shape.h new file mode 100644 index 0000000..afe6fe9 --- /dev/null +++ b/third_party/harfbuzz-ng/src/hb-ot-shape.h @@ -0,0 +1,54 @@ +/* + * Copyright © 2013 Red Hat, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_SHAPE_H +#define HB_OT_SHAPE_H +#define HB_OT_SHAPE_H_IN + +#include "hb.h" + +#include "hb-ot-layout.h" +#include "hb-ot-tag.h" + +HB_BEGIN_DECLS + +/* TODO port to shape-plan / set. */ +void +hb_ot_shape_glyphs_closure (hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features, + hb_set_t *glyphs); + +void +hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan, + hb_tag_t table_tag, + hb_set_t *lookup_indexes /* OUT */); + +HB_END_DECLS + +#undef HB_OT_SHAPE_H_IN +#endif /* HB_OT_SHAPE_H */ diff --git a/third_party/harfbuzz-ng/src/hb-ot-tag.cc b/third_party/harfbuzz-ng/src/hb-ot-tag.cc index 91ebec7..5594ef5 100644 --- a/third_party/harfbuzz-ng/src/hb-ot-tag.cc +++ b/third_party/harfbuzz-ng/src/hb-ot-tag.cc @@ -27,7 +27,6 @@ */ #include "hb-private.hh" -#include "hb-ot.h" #include <string.h> @@ -167,9 +166,12 @@ typedef struct { * * Generated by intersecting the OpenType language tag list from * Draft OpenType 1.5 spec, with with the ISO 639-3 codes from - * 2008/08/04, matching on name, and finally adjusted manually. + * 2008-08-04, matching on name, and finally adjusted manually. * - * Updated on 2012/12/07 with more research into remaining codes. + * Updated on 2012-12-07 with more research into remaining codes. + * + * Updated on 2013-11-23 based on usage in SIL and Microsoft fonts, + * the new proposal from Microsoft, and latest ISO 639-3 names. * * Some items still missing. Those are commented out at the end. * Keep sorted for bsearch. @@ -179,57 +181,90 @@ static const LangTag ot_languages[] = { {"aa", HB_TAG('A','F','R',' ')}, /* Afar */ {"ab", HB_TAG('A','B','K',' ')}, /* Abkhazian */ {"abq", HB_TAG('A','B','A',' ')}, /* Abaza */ + {"ach", HB_TAG('A','C','H',' ')}, /* Acoli */ {"ada", HB_TAG('D','N','G',' ')}, /* Dangme */ {"ady", HB_TAG('A','D','Y',' ')}, /* Adyghe */ {"af", HB_TAG('A','F','K',' ')}, /* Afrikaans */ {"aii", HB_TAG('S','W','A',' ')}, /* Swadaya Aramaic */ + {"aio", HB_TAG('A','I','O',' ')}, /* Aiton */ {"aiw", HB_TAG('A','R','I',' ')}, /* Aari */ + {"ak", HB_TAG('T','W','I',' ')}, /* Akan [macrolanguage] */ {"alt", HB_TAG('A','L','T',' ')}, /* [Southern] Altai */ {"am", HB_TAG('A','M','H',' ')}, /* Amharic */ {"amf", HB_TAG('H','B','N',' ')}, /* Hammer-Banna */ - {"ar", HB_TAG('A','R','A',' ')}, /* Arabic */ + {"an", HB_TAG('A','R','G',' ')}, /* Aragonese */ + {"ang", HB_TAG('A','N','G',' ')}, /* Old English (ca. 450-1100) */ + {"ar", HB_TAG('A','R','A',' ')}, /* Arabic [macrolanguage] */ + {"arb", HB_TAG('A','R','A',' ')}, /* Standard Arabic */ {"arn", HB_TAG('M','A','P',' ')}, /* Mapudungun */ + {"ary", HB_TAG('M','O','R',' ')}, /* Moroccan Arabic */ {"as", HB_TAG('A','S','M',' ')}, /* Assamese */ + {"ast", HB_TAG('A','S','T',' ')}, /* Asturian/Asturleonese/Bable/Leonese */ {"ath", HB_TAG('A','T','H',' ')}, /* Athapaskan [family] */ {"atv", HB_TAG('A','L','T',' ')}, /* [Northern] Altai */ {"av", HB_TAG('A','V','R',' ')}, /* Avaric */ {"awa", HB_TAG('A','W','A',' ')}, /* Awadhi */ - {"ay", HB_TAG('A','Y','M',' ')}, /* Aymara */ - {"az", HB_TAG('A','Z','E',' ')}, /* Azerbaijani */ + {"ay", HB_TAG('A','Y','M',' ')}, /* Aymara [macrolanguage] */ + {"az", HB_TAG('A','Z','E',' ')}, /* Azerbaijani [macrolanguage] */ + {"azb", HB_TAG('A','Z','B',' ')}, /* South Azerbaijani */ + {"azj", HB_TAG('A','Z','E',' ')}, /* North Azerbaijani */ {"ba", HB_TAG('B','S','H',' ')}, /* Bashkir */ {"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [family] */ - {"bal", HB_TAG('B','L','I',' ')}, /* Baluchi */ - {"bci", HB_TAG('B','A','U',' ')}, /* Baule */ + {"bal", HB_TAG('B','L','I',' ')}, /* Baluchi [macrolangauge] */ + {"ban", HB_TAG('B','A','N',' ')}, /* Balinese */ + {"bar", HB_TAG('B','A','R',' ')}, /* Bavarian */ + {"bbc", HB_TAG('B','B','C',' ')}, /* Batak Toba */ + {"bci", HB_TAG('B','A','U',' ')}, /* Baoulé */ + {"bcl", HB_TAG('B','I','K',' ')}, /* Central Bikol */ {"bcq", HB_TAG('B','C','H',' ')}, /* Bench */ - {"be", HB_TAG('B','E','L',' ')}, /* Belarussian */ + {"be", HB_TAG('B','E','L',' ')}, /* Belarusian */ {"bem", HB_TAG('B','E','M',' ')}, /* Bemba (Zambia) */ {"ber", HB_TAG('B','E','R',' ')}, /* Berber [family] */ {"bfq", HB_TAG('B','A','D',' ')}, /* Badaga */ {"bft", HB_TAG('B','L','T',' ')}, /* Balti */ {"bfy", HB_TAG('B','A','G',' ')}, /* Baghelkhandi */ {"bg", HB_TAG('B','G','R',' ')}, /* Bulgarian */ + {"bgc", HB_TAG('B','G','C',' ')}, /* Haryanvi */ + {"bgq", HB_TAG('B','G','Q',' ')}, /* Bagri */ {"bhb", HB_TAG('B','H','I',' ')}, /* Bhili */ + {"bhk", HB_TAG('B','I','K',' ')}, /* Albay Bicolano (retired code) */ {"bho", HB_TAG('B','H','O',' ')}, /* Bhojpuri */ - {"bik", HB_TAG('B','I','K',' ')}, /* Bikol */ + {"bi", HB_TAG('B','I','S',' ')}, /* Bislama */ + {"bik", HB_TAG('B','I','K',' ')}, /* Bikol [macrolanguage] */ {"bin", HB_TAG('E','D','O',' ')}, /* Bini */ + {"bjj", HB_TAG('B','J','J',' ')}, /* Kanauji */ {"bjt", HB_TAG('B','L','N',' ')}, /* Balanta-Ganja */ {"bla", HB_TAG('B','K','F',' ')}, /* Blackfoot */ {"ble", HB_TAG('B','L','N',' ')}, /* Balanta-Kentohe */ + {"blk", HB_TAG('B','L','K',' ')}, /* Pa'O/Pa'o Karen */ + {"bln", HB_TAG('B','I','K',' ')}, /* Southern Catanduanes Bikol */ {"bm", HB_TAG('B','M','B',' ')}, /* Bambara */ {"bn", HB_TAG('B','E','N',' ')}, /* Bengali */ {"bo", HB_TAG('T','I','B',' ')}, /* Tibetan */ + {"bpy", HB_TAG('B','P','Y',' ')}, /* Bishnupriya */ + {"bqi", HB_TAG('L','R','C',' ')}, /* Bakhtiari */ {"br", HB_TAG('B','R','E',' ')}, /* Breton */ {"bra", HB_TAG('B','R','I',' ')}, /* Braj Bhasha */ {"brh", HB_TAG('B','R','H',' ')}, /* Brahui */ + {"brx", HB_TAG('B','R','X',' ')}, /* Bodo (India) */ {"bs", HB_TAG('B','O','S',' ')}, /* Bosnian */ {"btb", HB_TAG('B','T','I',' ')}, /* Beti (Cameroon) */ + {"bto", HB_TAG('B','I','K',' ')}, /* Rinconada Bikol */ + {"bts", HB_TAG('B','T','S',' ')}, /* Batak Simalungun */ + {"bug", HB_TAG('B','U','G',' ')}, /* Buginese */ {"bxr", HB_TAG('R','B','U',' ')}, /* Russian Buriat */ {"byn", HB_TAG('B','I','L',' ')}, /* Bilen */ {"ca", HB_TAG('C','A','T',' ')}, /* Catalan */ + {"cbk", HB_TAG('C','B','K',' ')}, /* Chavacano */ {"ce", HB_TAG('C','H','E',' ')}, /* Chechen */ {"ceb", HB_TAG('C','E','B',' ')}, /* Cebuano */ + {"cgg", HB_TAG('C','G','G',' ')}, /* Chiga */ + {"ch", HB_TAG('C','H','A',' ')}, /* Chamorro */ + {"cho", HB_TAG('C','H','O',' ')}, /* Choctaw */ {"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */ {"chr", HB_TAG('C','H','R',' ')}, /* Cherokee */ + {"chy", HB_TAG('C','H','Y',' ')}, /* Cheyenne */ + {"ckb", HB_TAG('K','U','R',' ')}, /* Central Kurdish (Sorani) */ {"ckt", HB_TAG('C','H','K',' ')}, /* Chukchi */ {"cop", HB_TAG('C','O','P',' ')}, /* Coptic */ {"cr", HB_TAG('C','R','E',' ')}, /* Cree */ @@ -239,6 +274,9 @@ static const LangTag ot_languages[] = { {"crm", HB_TAG('M','C','R',' ')}, /* Moose Cree */ {"crx", HB_TAG('C','R','R',' ')}, /* Carrier */ {"cs", HB_TAG('C','S','Y',' ')}, /* Czech */ + {"csb", HB_TAG('C','S','B',' ')}, /* Kashubian */ + {"ctg", HB_TAG('C','T','G',' ')}, /* Chittagonian */ + {"cts", HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol */ {"cu", HB_TAG('C','S','L',' ')}, /* Church Slavic */ {"cv", HB_TAG('C','H','U',' ')}, /* Chuvash */ {"cwd", HB_TAG('D','C','R',' ')}, /* Woods Cree */ @@ -247,34 +285,42 @@ static const LangTag ot_languages[] = { {"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) */ {"dar", HB_TAG('D','A','R',' ')}, /* Dargwa */ {"de", HB_TAG('D','E','U',' ')}, /* German */ - {"din", HB_TAG('D','N','K',' ')}, /* Dinka */ - {"dje", HB_TAG('D','J','R',' ')}, /* Djerma */ + {"dgo", HB_TAG('D','G','O',' ')}, /* Dogri */ + {"dhd", HB_TAG('M','A','W',' ')}, /* Dhundari */ + {"din", HB_TAG('D','N','K',' ')}, /* Dinka [macrolanguage] */ + {"diq", HB_TAG('D','I','Q',' ')}, /* Dimli */ + {"dje", HB_TAG('D','J','R',' ')}, /* Zarma */ {"dng", HB_TAG('D','U','N',' ')}, /* Dungan */ - {"doi", HB_TAG('D','G','R',' ')}, /* Dogri */ + {"doi", HB_TAG('D','G','R',' ')}, /* Dogri [macrolanguage] */ {"dsb", HB_TAG('L','S','B',' ')}, /* Lower Sorbian */ - {"dv", HB_TAG('D','I','V',' ')}, /* Dhivehi */ + {"dv", HB_TAG('D','I','V',' ')}, /* Dhivehi/Divehi/Maldivian */ {"dyu", HB_TAG('J','U','L',' ')}, /* Jula */ {"dz", HB_TAG('D','Z','N',' ')}, /* Dzongkha */ {"ee", HB_TAG('E','W','E',' ')}, /* Ewe */ {"efi", HB_TAG('E','F','I',' ')}, /* Efik */ + {"ekk", HB_TAG('E','T','I',' ')}, /* Standard Estonian */ {"el", HB_TAG('E','L','L',' ')}, /* Modern Greek (1453-) */ + {"emk", HB_TAG('M','N','K',' ')}, /* Eastern Maninkakan */ {"en", HB_TAG('E','N','G',' ')}, /* English */ {"eo", HB_TAG('N','T','O',' ')}, /* Esperanto */ {"eot", HB_TAG('B','T','I',' ')}, /* Beti (Côte d'Ivoire) */ {"es", HB_TAG('E','S','P',' ')}, /* Spanish */ - {"et", HB_TAG('E','T','I',' ')}, /* Estonian */ + {"et", HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */ {"eu", HB_TAG('E','U','Q',' ')}, /* Basque */ {"eve", HB_TAG('E','V','N',' ')}, /* Even */ {"evn", HB_TAG('E','V','K',' ')}, /* Evenki */ - {"fa", HB_TAG('F','A','R',' ')}, /* Persian */ - {"ff", HB_TAG('F','U','L',' ')}, /* Fulah */ + {"fa", HB_TAG('F','A','R',' ')}, /* Persian [macrolanguage] */ + {"ff", HB_TAG('F','U','L',' ')}, /* Fulah [macrolanguage] */ {"fi", HB_TAG('F','I','N',' ')}, /* Finnish */ {"fil", HB_TAG('P','I','L',' ')}, /* Filipino */ {"fj", HB_TAG('F','J','I',' ')}, /* Fijian */ {"fo", HB_TAG('F','O','S',' ')}, /* Faroese */ {"fon", HB_TAG('F','O','N',' ')}, /* Fon */ {"fr", HB_TAG('F','R','A',' ')}, /* French */ + {"frc", HB_TAG('F','R','C',' ')}, /* Cajun French */ + {"frp", HB_TAG('F','R','P',' ')}, /* Arpitan/Francoprovençal */ {"fur", HB_TAG('F','R','L',' ')}, /* Friulian */ + {"fuv", HB_TAG('F','U','V',' ')}, /* Nigerian Fulfulde */ {"fy", HB_TAG('F','R','I',' ')}, /* Western Frisian */ {"ga", HB_TAG('I','R','I',' ')}, /* Irish */ {"gaa", HB_TAG('G','A','D',' ')}, /* Ga */ @@ -282,113 +328,167 @@ static const LangTag ot_languages[] = { {"gbm", HB_TAG('G','A','W',' ')}, /* Garhwali */ {"gd", HB_TAG('G','A','E',' ')}, /* Scottish Gaelic */ {"gez", HB_TAG('G','E','Z',' ')}, /* Ge'ez */ + {"ggo", HB_TAG('G','O','N',' ')}, /* Southern Gondi */ {"gl", HB_TAG('G','A','L',' ')}, /* Galician */ {"gld", HB_TAG('N','A','N',' ')}, /* Nanai */ - {"gn", HB_TAG('G','U','A',' ')}, /* Guarani */ - {"gon", HB_TAG('G','O','N',' ')}, /* Gondi */ + {"glk", HB_TAG('G','L','K',' ')}, /* Gilaki */ + {"gn", HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */ + {"gno", HB_TAG('G','O','N',' ')}, /* Northern Gondi */ + {"gog", HB_TAG('G','O','G',' ')}, /* Gogo */ + {"gon", HB_TAG('G','O','N',' ')}, /* Gondi [macrolanguage] */ {"grt", HB_TAG('G','R','O',' ')}, /* Garo */ {"gru", HB_TAG('S','O','G',' ')}, /* Sodo Gurage */ {"gu", HB_TAG('G','U','J',' ')}, /* Gujarati */ + {"guc", HB_TAG('G','U','C',' ')}, /* Wayuu */ {"guk", HB_TAG('G','M','Z',' ')}, /* Gumuz */ - {"gv", HB_TAG('M','N','X',' ')}, /* Manx Gaelic */ +/*{"guk", HB_TAG('G','U','K',' ')},*/ /* Gumuz (in SIL fonts) */ + {"guz", HB_TAG('G','U','Z',' ')}, /* Ekegusii/Gusii */ + {"gv", HB_TAG('M','N','X',' ')}, /* Manx */ {"ha", HB_TAG('H','A','U',' ')}, /* Hausa */ {"har", HB_TAG('H','R','I',' ')}, /* Harari */ - {"haw", HB_TAG('H','A','W',' ')}, /* Hawaiin */ + {"haw", HB_TAG('H','A','W',' ')}, /* Hawaiian */ + {"hay", HB_TAG('H','A','Y',' ')}, /* Haya */ + {"haz", HB_TAG('H','A','Z',' ')}, /* Hazaragi */ {"he", HB_TAG('I','W','R',' ')}, /* Hebrew */ + {"hz", HB_TAG('H','E','R',' ')}, /* Herero */ {"hi", HB_TAG('H','I','N',' ')}, /* Hindi */ {"hil", HB_TAG('H','I','L',' ')}, /* Hiligaynon */ {"hnd", HB_TAG('H','N','D',' ')}, /* [Southern] Hindko */ {"hne", HB_TAG('C','H','H',' ')}, /* Chattisgarhi */ {"hno", HB_TAG('H','N','D',' ')}, /* [Northern] Hindko */ + {"ho", HB_TAG('H','M','O',' ')}, /* Hiri Motu */ {"hoc", HB_TAG('H','O',' ',' ')}, /* Ho */ {"hoj", HB_TAG('H','A','R',' ')}, /* Harauti */ {"hr", HB_TAG('H','R','V',' ')}, /* Croatian */ {"hsb", HB_TAG('U','S','B',' ')}, /* Upper Sorbian */ - {"ht", HB_TAG('H','A','I',' ')}, /* Haitian */ + {"ht", HB_TAG('H','A','I',' ')}, /* Haitian/Haitian Creole */ {"hu", HB_TAG('H','U','N',' ')}, /* Hungarian */ {"hy", HB_TAG('H','Y','E',' ')}, /* Armenian */ + {"hz", HB_TAG('H','E','R',' ')}, /* Herero */ + {"ia", HB_TAG('I','N','A',' ')}, /* Interlingua (International Auxiliary Language Association) */ + {"ibb", HB_TAG('I','B','B',' ')}, /* Ibibio */ {"id", HB_TAG('I','N','D',' ')}, /* Indonesian */ + {"ie", HB_TAG('I','L','E',' ')}, /* Interlingue/Occidental */ {"ig", HB_TAG('I','B','O',' ')}, /* Igbo */ {"igb", HB_TAG('E','B','I',' ')}, /* Ebira */ + {"ijc", HB_TAG('I','J','O',' ')}, /* Izon */ {"ijo", HB_TAG('I','J','O',' ')}, /* Ijo [family] */ + {"ik", HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] */ {"ilo", HB_TAG('I','L','O',' ')}, /* Ilokano */ {"inh", HB_TAG('I','N','G',' ')}, /* Ingush */ + {"io", HB_TAG('I','D','O',' ')}, /* Ido */ {"is", HB_TAG('I','S','L',' ')}, /* Icelandic */ {"it", HB_TAG('I','T','A',' ')}, /* Italian */ - {"iu", HB_TAG('I','N','U',' ')}, /* Inuktitut */ + {"iu", HB_TAG('I','N','U',' ')}, /* Inuktitut [macrolanguage] */ {"ja", HB_TAG('J','A','N',' ')}, /* Japanese */ + {"jam", HB_TAG('J','A','M',' ')}, /* Jamaican Creole English */ + {"jbo", HB_TAG('J','B','O',' ')}, /* Lojban */ {"jv", HB_TAG('J','A','V',' ')}, /* Javanese */ {"ka", HB_TAG('K','A','T',' ')}, /* Georgian */ {"kaa", HB_TAG('K','R','K',' ')}, /* Karakalpak */ + {"kab", HB_TAG('K','A','B',' ')}, /* Kabyle */ {"kam", HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */ {"kar", HB_TAG('K','R','N',' ')}, /* Karen [family] */ {"kbd", HB_TAG('K','A','B',' ')}, /* Kabardian */ + {"kde", HB_TAG('K','D','E',' ')}, /* Makonde */ {"kdr", HB_TAG('K','R','M',' ')}, /* Karaim */ {"kdt", HB_TAG('K','U','Y',' ')}, /* Kuy */ {"kex", HB_TAG('K','K','N',' ')}, /* Kokni */ {"kfr", HB_TAG('K','A','C',' ')}, /* Kachchi */ {"kfy", HB_TAG('K','M','N',' ')}, /* Kumaoni */ + {"kg", HB_TAG('K','O','N',' ')}, /* Kongo [macrolanguage] */ {"kha", HB_TAG('K','S','I',' ')}, /* Khasi */ - {"khb", HB_TAG('X','B','D',' ')}, /* Tai Lue */ + {"khb", HB_TAG('X','B','D',' ')}, /* Lü */ + {"kht", HB_TAG('K','H','N',' ')}, /* Khamti (Microsoft fonts) */ +/*{"kht", HB_TAG('K','H','T',' ')},*/ /* Khamti (OpenType spec and SIL fonts) */ {"khw", HB_TAG('K','H','W',' ')}, /* Khowar */ - {"ki", HB_TAG('K','I','K',' ')}, /* Kikuyu */ + {"ki", HB_TAG('K','I','K',' ')}, /* Gikuyu/Kikuyu */ + {"kj", HB_TAG('K','U','A',' ')}, /* Kuanyama/Kwanyama */ {"kjh", HB_TAG('K','H','A',' ')}, /* Khakass */ + {"kjp", HB_TAG('K','J','P',' ')}, /* Pwo Eastern Karen */ {"kk", HB_TAG('K','A','Z',' ')}, /* Kazakh */ {"kl", HB_TAG('G','R','N',' ')}, /* Kalaallisut */ {"kln", HB_TAG('K','A','L',' ')}, /* Kalenjin */ {"km", HB_TAG('K','H','M',' ')}, /* Central Khmer */ - {"kmb", HB_TAG('M','B','N',' ')}, /* [North] Mbundu */ + {"kmb", HB_TAG('M','B','N',' ')}, /* Kimbundu */ {"kmw", HB_TAG('K','M','O',' ')}, /* Komo (Democratic Republic of Congo) */ {"kn", HB_TAG('K','A','N',' ')}, /* Kannada */ + {"knn", HB_TAG('K','O','K',' ')}, /* Konkani */ {"ko", HB_TAG('K','O','R',' ')}, /* Korean */ {"koi", HB_TAG('K','O','P',' ')}, /* Komi-Permyak */ - {"kok", HB_TAG('K','O','K',' ')}, /* Konkani */ - {"kpe", HB_TAG('K','P','L',' ')}, /* Kpelle */ + {"kok", HB_TAG('K','O','K',' ')}, /* Konkani [macrolanguage] */ + {"kpe", HB_TAG('K','P','L',' ')}, /* Kpelle [macrolanguage] */ {"kpv", HB_TAG('K','O','Z',' ')}, /* Komi-Zyrian */ {"kpy", HB_TAG('K','Y','K',' ')}, /* Koryak */ {"kqy", HB_TAG('K','R','T',' ')}, /* Koorete */ - {"kr", HB_TAG('K','N','R',' ')}, /* Kanuri */ + {"kr", HB_TAG('K','N','R',' ')}, /* Kanuri [macrolanguage] */ {"kri", HB_TAG('K','R','I',' ')}, /* Krio */ {"krl", HB_TAG('K','R','L',' ')}, /* Karelian */ {"kru", HB_TAG('K','U','U',' ')}, /* Kurukh */ {"ks", HB_TAG('K','S','H',' ')}, /* Kashmiri */ - {"ku", HB_TAG('K','U','R',' ')}, /* Kurdish */ + {"ksh", HB_TAG('K','S','H',' ')}, /* Kölsch */ +/*{"ksw", HB_TAG('K','R','N',' ')},*/ /* S'gaw Karen (Microsoft fonts?) */ + {"ksw", HB_TAG('K','S','W',' ')}, /* S'gaw Karen (OpenType spec and SIL fonts) */ + {"ku", HB_TAG('K','U','R',' ')}, /* Kurdish [macrolanguage] */ {"kum", HB_TAG('K','U','M',' ')}, /* Kumyk */ + {"kv", HB_TAG('K','O','M',' ')}, /* Komi [macrolanguage] */ {"kvd", HB_TAG('K','U','I',' ')}, /* Kui (Indonesia) */ + {"kw", HB_TAG('C','O','R',' ')}, /* Cornish */ {"kxc", HB_TAG('K','M','S',' ')}, /* Komso */ {"kxu", HB_TAG('K','U','I',' ')}, /* Kui (India) */ - {"ky", HB_TAG('K','I','R',' ')}, /* Kirghiz */ + {"ky", HB_TAG('K','I','R',' ')}, /* Kirghiz/Kyrgyz */ + {"kyu", HB_TAG('K','Y','U',' ')}, /* Western Kayah */ {"la", HB_TAG('L','A','T',' ')}, /* Latin */ {"lad", HB_TAG('J','U','D',' ')}, /* Ladino */ {"lb", HB_TAG('L','T','Z',' ')}, /* Luxembourgish */ {"lbe", HB_TAG('L','A','K',' ')}, /* Lak */ {"lbj", HB_TAG('L','D','K',' ')}, /* Ladakhi */ {"lez", HB_TAG('L','E','Z',' ')}, /* Lezgi */ - {"lg", HB_TAG('L','U','G',' ')}, /* Luganda */ + {"lg", HB_TAG('L','U','G',' ')}, /* Ganda */ + {"li", HB_TAG('L','I','M',' ')}, /* Limburgan/Limburger/Limburgish */ {"lif", HB_TAG('L','M','B',' ')}, /* Limbu */ + {"lij", HB_TAG('L','I','J',' ')}, /* Ligurian */ + {"lis", HB_TAG('L','I','S',' ')}, /* Lisu */ + {"ljp", HB_TAG('L','J','P',' ')}, /* Lampung Api */ + {"lki", HB_TAG('L','K','I',' ')}, /* Laki */ {"lld", HB_TAG('L','A','D',' ')}, /* Ladin */ {"lmn", HB_TAG('L','A','M',' ')}, /* Lambani */ + {"lmo", HB_TAG('L','M','O',' ')}, /* Lombard */ {"ln", HB_TAG('L','I','N',' ')}, /* Lingala */ {"lo", HB_TAG('L','A','O',' ')}, /* Lao */ + {"lrc", HB_TAG('L','R','C',' ')}, /* Northern Luri */ {"lt", HB_TAG('L','T','H',' ')}, /* Lithuanian */ {"lu", HB_TAG('L','U','B',' ')}, /* Luba-Katanga */ {"lua", HB_TAG('L','U','B',' ')}, /* Luba-Kasai */ {"luo", HB_TAG('L','U','O',' ')}, /* Luo (Kenya and Tanzania) */ {"lus", HB_TAG('M','I','Z',' ')}, /* Mizo */ - {"luy", HB_TAG('L','U','H',' ')}, /* Luhya [macrolanguage] */ + {"luy", HB_TAG('L','U','H',' ')}, /* Luyia/Oluluyia [macrolanguage] */ + {"luz", HB_TAG('L','R','C',' ')}, /* Southern Luri */ {"lv", HB_TAG('L','V','I',' ')}, /* Latvian */ {"lzz", HB_TAG('L','A','Z',' ')}, /* Laz */ + {"mad", HB_TAG('M','A','D',' ')}, /* Madurese */ + {"mag", HB_TAG('M','A','G',' ')}, /* Magahi */ {"mai", HB_TAG('M','T','H',' ')}, /* Maithili */ + {"mak", HB_TAG('M','K','R',' ')}, /* Makasar */ + {"man", HB_TAG('M','N','K',' ')}, /* Manding/Mandingo [macrolanguage] */ {"mdc", HB_TAG('M','L','E',' ')}, /* Male (Papua New Guinea) */ {"mdf", HB_TAG('M','O','K',' ')}, /* Moksha */ + {"mdr", HB_TAG('M','D','R',' ')}, /* Mandar */ {"mdy", HB_TAG('M','L','E',' ')}, /* Male (Ethiopia) */ {"men", HB_TAG('M','D','E',' ')}, /* Mende (Sierra Leone) */ - {"mg", HB_TAG('M','L','G',' ')}, /* Malagasy */ + {"mer", HB_TAG('M','E','R',' ')}, /* Meru */ + {"mfe", HB_TAG('M','F','E',' ')}, /* Morisyen */ + {"mg", HB_TAG('M','L','G',' ')}, /* Malagasy [macrolanguage] */ + {"mh", HB_TAG('M','A','H',' ')}, /* Marshallese */ {"mhr", HB_TAG('L','M','A',' ')}, /* Low Mari */ {"mi", HB_TAG('M','R','I',' ')}, /* Maori */ + {"min", HB_TAG('M','I','N',' ')}, /* Minangkabau */ {"mk", HB_TAG('M','K','D',' ')}, /* Macedonian */ + {"mku", HB_TAG('M','N','K',' ')}, /* Konyanka Maninka */ + {"mkw", HB_TAG('M','K','W',' ')}, /* Kituba (Congo) */ {"ml", HB_TAG('M','L','R',' ')}, /* Malayalam */ - {"mn", HB_TAG('M','N','G',' ')}, /* Mongolian */ + {"mlq", HB_TAG('M','N','K',' ')}, /* Western Maninkakan */ + {"mn", HB_TAG('M','N','G',' ')}, /* Mongolian [macrolanguage] */ {"mnc", HB_TAG('M','C','H',' ')}, /* Manchu */ {"mni", HB_TAG('M','N','I',' ')}, /* Manipuri */ {"mnk", HB_TAG('M','N','D',' ')}, /* Mandinka */ @@ -396,72 +496,119 @@ static const LangTag ot_languages[] = { {"mnw", HB_TAG('M','O','N',' ')}, /* Mon */ {"mo", HB_TAG('M','O','L',' ')}, /* Moldavian */ {"moh", HB_TAG('M','O','H',' ')}, /* Mohawk */ + {"mos", HB_TAG('M','O','S',' ')}, /* Mossi */ {"mpe", HB_TAG('M','A','J',' ')}, /* Majang */ {"mr", HB_TAG('M','A','R',' ')}, /* Marathi */ {"mrj", HB_TAG('H','M','A',' ')}, /* High Mari */ - {"ms", HB_TAG('M','L','Y',' ')}, /* Malay */ + {"ms", HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */ + {"msc", HB_TAG('M','N','K',' ')}, /* Sankaran Maninka */ {"mt", HB_TAG('M','T','S',' ')}, /* Maltese */ - {"mwr", HB_TAG('M','A','W',' ')}, /* Marwari */ + {"mtr", HB_TAG('M','A','W',' ')}, /* Mewari */ + {"mus", HB_TAG('M','U','S',' ')}, /* Creek */ + {"mve", HB_TAG('M','A','W',' ')}, /* Marwari (Pakistan) */ + {"mwk", HB_TAG('M','N','K',' ')}, /* Kita Maninkakan */ + {"mwl", HB_TAG('M','W','L',' ')}, /* Mirandese */ + {"mwr", HB_TAG('M','A','W',' ')}, /* Marwari [macrolanguage] */ + {"mww", HB_TAG('M','W','W',' ')}, /* Hmong Daw */ {"my", HB_TAG('B','R','M',' ')}, /* Burmese */ {"mym", HB_TAG('M','E','N',' ')}, /* Me'en */ + {"myq", HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) */ {"myv", HB_TAG('E','R','Z',' ')}, /* Erzya */ + {"mzn", HB_TAG('M','Z','N',' ')}, /* Mazanderani */ + {"na", HB_TAG('N','A','U',' ')}, /* Nauru */ {"nag", HB_TAG('N','A','G',' ')}, /* Naga-Assamese */ + {"nah", HB_TAG('N','A','H',' ')}, /* Nahuatl [family] */ + {"nap", HB_TAG('N','A','P',' ')}, /* Neapolitan */ {"nb", HB_TAG('N','O','R',' ')}, /* Norwegian Bokmål */ {"nco", HB_TAG('S','I','B',' ')}, /* Sibe */ {"nd", HB_TAG('N','D','B',' ')}, /* [North] Ndebele */ + {"ndc", HB_TAG('N','D','C',' ')}, /* Ndau */ + {"nds", HB_TAG('N','D','S',' ')}, /* Low German/Low Saxon */ {"ne", HB_TAG('N','E','P',' ')}, /* Nepali */ {"new", HB_TAG('N','E','W',' ')}, /* Newari */ {"ng", HB_TAG('N','D','G',' ')}, /* Ndonga */ + {"nga", HB_TAG('N','G','A',' ')}, /* Ngabaka */ {"ngl", HB_TAG('L','M','W',' ')}, /* Lomwe */ {"niu", HB_TAG('N','I','U',' ')}, /* Niuean */ {"niv", HB_TAG('G','I','L',' ')}, /* Gilyak */ {"nl", HB_TAG('N','L','D',' ')}, /* Dutch */ {"nn", HB_TAG('N','Y','N',' ')}, /* Norwegian Nynorsk */ - {"no", HB_TAG('N','O','R',' ')}, /* Norwegian (deprecated) */ - {"nod", HB_TAG('N','T','A',' ')}, /* Northern Tai */ + {"no", HB_TAG('N','O','R',' ')}, /* Norwegian [macrolanguage] */ + {"nod", HB_TAG('N','T','A',' ')}, /* Northern Thai */ + {"noe", HB_TAG('N','O','E',' ')}, /* Nimadi */ {"nog", HB_TAG('N','O','G',' ')}, /* Nogai */ + {"nov", HB_TAG('N','O','V',' ')}, /* Novial */ {"nqo", HB_TAG('N','K','O',' ')}, /* N'Ko */ {"nr", HB_TAG('N','D','B',' ')}, /* [South] Ndebele */ {"nsk", HB_TAG('N','A','S',' ')}, /* Naskapi */ {"nso", HB_TAG('S','O','T',' ')}, /* [Northern] Sotho */ - {"ny", HB_TAG('C','H','I',' ')}, /* Nyanja */ - {"nyn", HB_TAG('N','K','L',' ')}, /* Nkole */ + {"ny", HB_TAG('C','H','I',' ')}, /* Chewa/Chichwa/Nyanja */ + {"nym", HB_TAG('N','Y','M',' ')}, /* Nyamwezi */ + {"nyn", HB_TAG('N','K','L',' ')}, /* Nyankole */ {"oc", HB_TAG('O','C','I',' ')}, /* Occitan (post 1500) */ - {"oj", HB_TAG('O','J','B',' ')}, /* Ojibwa */ + {"oj", HB_TAG('O','J','B',' ')}, /* Ojibwa [macrolanguage] */ {"ojs", HB_TAG('O','C','R',' ')}, /* Oji-Cree */ - {"om", HB_TAG('O','R','O',' ')}, /* Oromo */ + {"om", HB_TAG('O','R','O',' ')}, /* Oromo [macrolanguage] */ {"or", HB_TAG('O','R','I',' ')}, /* Oriya */ {"os", HB_TAG('O','S','S',' ')}, /* Ossetian */ {"pa", HB_TAG('P','A','N',' ')}, /* Panjabi */ + {"pag", HB_TAG('P','A','G',' ')}, /* Pangasinan */ + {"pam", HB_TAG('P','A','M',' ')}, /* Kapampangan/Pampanga */ + {"pap", HB_TAG('P','A','P',' ')}, /* Papiamento */ + {"pcc", HB_TAG('P','C','C',' ')}, /* Bouyei */ + {"pcd", HB_TAG('P','C','D',' ')}, /* Picard */ {"pce", HB_TAG('P','L','G',' ')}, /* [Ruching] Palaung */ + {"pdc", HB_TAG('P','D','C',' ')}, /* Pennsylvania German */ + {"pes", HB_TAG('F','A','R',' ')}, /* Iranian Persian */ + {"phk", HB_TAG('P','H','K',' ')}, /* Phake */ {"pi", HB_TAG('P','A','L',' ')}, /* Pali */ + {"pih", HB_TAG('P','I','H',' ')}, /* Pitcairn-Norfolk */ {"pl", HB_TAG('P','L','K',' ')}, /* Polish */ {"pll", HB_TAG('P','L','G',' ')}, /* [Shwe] Palaung */ {"plp", HB_TAG('P','A','P',' ')}, /* Palpa */ - {"prs", HB_TAG('D','R','I',' ')}, /* Dari */ - {"ps", HB_TAG('P','A','S',' ')}, /* Pushto */ + {"pms", HB_TAG('P','M','S',' ')}, /* Piemontese */ + {"pnb", HB_TAG('P','N','B',' ')}, /* Western Panjabi */ + {"prs", HB_TAG('D','R','I',' ')}, /* Afghan Persian/Dari */ + {"ps", HB_TAG('P','A','S',' ')}, /* Pashto/Pushto [macrolanguage] */ {"pt", HB_TAG('P','T','G',' ')}, /* Portuguese */ - {"raj", HB_TAG('R','A','J',' ')}, /* Rajasthani */ - {"rbb", HB_TAG('P','L','G',' ')}, /* [Rumai] Palaung */ + {"pwo", HB_TAG('P','W','O',' ')}, /* Pwo Western Karen */ + {"qu", HB_TAG('Q','U','Z',' ')}, /* Quechua [macrolanguage] */ + {"quc", HB_TAG('Q','U','C',' ')}, /* K'iche'/Quiché */ + {"quz", HB_TAG('Q','U','Z',' ')}, /* Cusco Quechua */ + {"raj", HB_TAG('R','A','J',' ')}, /* Rajasthani [macrolanguage] */ + {"rbb", HB_TAG('P','L','G',' ')}, /* Rumai Palaung */ + {"rej", HB_TAG('R','E','J',' ')}, /* Rejang */ {"ria", HB_TAG('R','I','A',' ')}, /* Riang (India) */ {"ril", HB_TAG('R','I','A',' ')}, /* Riang (Myanmar) */ - {"rki", HB_TAG('A','R','K',' ')}, /* Arakanese */ - {"rm", HB_TAG('R','M','S',' ')}, /* Rhaeto-Romanic */ + {"rki", HB_TAG('A','R','K',' ')}, /* Rakhine */ + {"rm", HB_TAG('R','M','S',' ')}, /* Romansh */ + {"rmy", HB_TAG('R','M','Y',' ')}, /* Vlax Romani */ + {"rn", HB_TAG('R','U','N',' ')}, /* Rundi */ {"ro", HB_TAG('R','O','M',' ')}, /* Romanian */ - {"rom", HB_TAG('R','O','Y',' ')}, /* Romany */ + {"rom", HB_TAG('R','O','Y',' ')}, /* Romany [macrolanguage] */ {"ru", HB_TAG('R','U','S',' ')}, /* Russian */ {"rue", HB_TAG('R','S','Y',' ')}, /* Rusyn */ - {"rw", HB_TAG('R','U','A',' ')}, /* Ruanda */ + {"rup", HB_TAG('R','U','P',' ')}, /* Aromanian/Arumanian/Macedo-Romanian */ + {"rw", HB_TAG('R','U','A',' ')}, /* Kinyarwanda */ + {"rwr", HB_TAG('M','A','W',' ')}, /* Marwari (India) */ {"sa", HB_TAG('S','A','N',' ')}, /* Sanskrit */ {"sah", HB_TAG('Y','A','K',' ')}, /* Yakut */ + {"sas", HB_TAG('S','A','S',' ')}, /* Sasak */ {"sat", HB_TAG('S','A','T',' ')}, /* Santali */ {"sck", HB_TAG('S','A','D',' ')}, /* Sadri */ + {"sc", HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */ + {"scn", HB_TAG('S','C','N',' ')}, /* Sicilian */ + {"sco", HB_TAG('S','C','O',' ')}, /* Scots */ {"scs", HB_TAG('S','L','A',' ')}, /* [North] Slavey */ {"sd", HB_TAG('S','N','D',' ')}, /* Sindhi */ {"se", HB_TAG('N','S','M',' ')}, /* Northern Sami */ {"seh", HB_TAG('S','N','A',' ')}, /* Sena */ {"sel", HB_TAG('S','E','L',' ')}, /* Selkup */ {"sg", HB_TAG('S','G','O',' ')}, /* Sango */ + {"sga", HB_TAG('S','G','A',' ')}, /* Old Irish (to 900) */ + {"sgs", HB_TAG('S','G','S',' ')}, /* Samogitian */ + {"sgw", HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage */ +/*{"sgw", HB_TAG('S','G','W',' ')},*/ /* Sebat Bet Gurage (in SIL fonts) */ {"shn", HB_TAG('S','H','N',' ')}, /* Shan */ {"si", HB_TAG('S','N','H',' ')}, /* Sinhala */ {"sid", HB_TAG('S','I','D',' ')}, /* Sidamo */ @@ -474,60 +621,98 @@ static const LangTag ot_languages[] = { {"smj", HB_TAG('L','S','M',' ')}, /* Lule Sami */ {"smn", HB_TAG('I','S','M',' ')}, /* Inari Sami */ {"sms", HB_TAG('S','K','S',' ')}, /* Skolt Sami */ + {"sn", HB_TAG('S','N','A',' ')}, /* Shona */ {"snk", HB_TAG('S','N','K',' ')}, /* Soninke */ {"so", HB_TAG('S','M','L',' ')}, /* Somali */ - {"sq", HB_TAG('S','Q','I',' ')}, /* Albanian */ + {"sop", HB_TAG('S','O','P',' ')}, /* Songe */ + {"sq", HB_TAG('S','Q','I',' ')}, /* Albanian [macrolanguage] */ {"sr", HB_TAG('S','R','B',' ')}, /* Serbian */ {"srr", HB_TAG('S','R','R',' ')}, /* Serer */ - {"ss", HB_TAG('S','W','Z',' ')}, /* Swazi */ + {"ss", HB_TAG('S','W','Z',' ')}, /* Swati */ {"st", HB_TAG('S','O','T',' ')}, /* [Southern] Sotho */ + {"stq", HB_TAG('S','T','Q',' ')}, /* Saterfriesisch */ + {"stv", HB_TAG('S','I','G',' ')}, /* Silt'e */ + {"su", HB_TAG('S','U','N',' ')}, /* Sundanese */ + {"suk", HB_TAG('S','U','K',' ')}, /* Sukama */ {"suq", HB_TAG('S','U','R',' ')}, /* Suri */ {"sv", HB_TAG('S','V','E',' ')}, /* Swedish */ {"sva", HB_TAG('S','V','A',' ')}, /* Svan */ - {"sw", HB_TAG('S','W','K',' ')}, /* Swahili */ + {"sw", HB_TAG('S','W','K',' ')}, /* Swahili [macrolanguage] */ {"swb", HB_TAG('C','M','R',' ')}, /* Comorian */ - {"syr", HB_TAG('S','Y','R',' ')}, /* Syriac */ + {"swh", HB_TAG('S','W','K',' ')}, /* Kiswahili/Swahili */ + {"swv", HB_TAG('M','A','W',' ')}, /* Shekhawati */ + {"sxu", HB_TAG('S','X','U',' ')}, /* Upper Saxon */ + {"syl", HB_TAG('S','Y','L',' ')}, /* Sylheti */ + {"syr", HB_TAG('S','Y','R',' ')}, /* Syriac [macrolanguage] */ + {"szl", HB_TAG('S','Z','L',' ')}, /* Silesian */ {"ta", HB_TAG('T','A','M',' ')}, /* Tamil */ {"tab", HB_TAG('T','A','B',' ')}, /* Tabasaran */ {"tcy", HB_TAG('T','U','L',' ')}, /* Tulu */ + {"tdd", HB_TAG('T','D','D',' ')}, /* Tai Nüa */ {"te", HB_TAG('T','E','L',' ')}, /* Telugu */ {"tem", HB_TAG('T','M','N',' ')}, /* Temne */ + {"tet", HB_TAG('T','E','T',' ')}, /* Tetum */ {"tg", HB_TAG('T','A','J',' ')}, /* Tajik */ {"th", HB_TAG('T','H','A',' ')}, /* Thai */ {"ti", HB_TAG('T','G','Y',' ')}, /* Tigrinya */ {"tig", HB_TAG('T','G','R',' ')}, /* Tigre */ + {"tiv", HB_TAG('T','I','V',' ')}, /* Tiv */ {"tk", HB_TAG('T','K','M',' ')}, /* Turkmen */ + {"tl", HB_TAG('T','G','L',' ')}, /* Tagalog */ + {"tmh", HB_TAG('t','m','h',' ')}, /* Tamashek [macrolanguage] */ {"tn", HB_TAG('T','N','A',' ')}, /* Tswana */ {"to", HB_TAG('T','G','N',' ')}, /* Tonga (Tonga Islands) */ + {"tpi", HB_TAG('T','P','I',' ')}, /* Tok Pisin */ {"tr", HB_TAG('T','R','K',' ')}, /* Turkish */ {"tru", HB_TAG('T','U','A',' ')}, /* Turoyo Aramaic */ {"ts", HB_TAG('T','S','G',' ')}, /* Tsonga */ {"tt", HB_TAG('T','A','T',' ')}, /* Tatar */ + {"tum", HB_TAG('T','U','M',' ')}, /* Tumbuka */ {"tw", HB_TAG('T','W','I',' ')}, /* Twi */ {"ty", HB_TAG('T','H','T',' ')}, /* Tahitian */ {"tyv", HB_TAG('T','U','V',' ')}, /* Tuvin */ + {"tyz", HB_TAG('T','Y','Z',' ')}, /* Tày */ + {"tzm", HB_TAG('T','Z','M',' ')}, /* Central Atlas Tamazight */ {"udm", HB_TAG('U','D','M',' ')}, /* Udmurt */ {"ug", HB_TAG('U','Y','G',' ')}, /* Uighur */ {"uk", HB_TAG('U','K','R',' ')}, /* Ukrainian */ - {"umb", HB_TAG('M','B','N',' ')}, /* [South] Mbundu */ + {"umb", HB_TAG('U','M','B',' ')}, /* Umbundu */ {"unr", HB_TAG('M','U','N',' ')}, /* Mundari */ {"ur", HB_TAG('U','R','D',' ')}, /* Urdu */ - {"uz", HB_TAG('U','Z','B',' ')}, /* Uzbek */ + {"uz", HB_TAG('U','Z','B',' ')}, /* Uzbek [macrolanguage] */ + {"uzn", HB_TAG('U','Z','B',' ')}, /* Northern Uzbek */ + {"uzs", HB_TAG('U','Z','B',' ')}, /* Southern Uzbek */ {"ve", HB_TAG('V','E','N',' ')}, /* Venda */ + {"vec", HB_TAG('V','E','C',' ')}, /* Venetian */ + {"vls", HB_TAG('F','L','E',' ')}, /* Vlaams */ {"vi", HB_TAG('V','I','T',' ')}, /* Vietnamese */ - {"vmw", HB_TAG('M','A','K',' ')}, /* Makua */ + {"vmw", HB_TAG('M','A','K',' ')}, /* Makhuwa */ + {"vo", HB_TAG('V','O','L',' ')}, /* Volapük */ + {"vro", HB_TAG('V','R','O',' ')}, /* Võro */ + {"wa", HB_TAG('W','L','N',' ')}, /* Walloon */ + {"war", HB_TAG('W','A','R',' ')}, /* Waray (Philippines) */ {"wbm", HB_TAG('W','A',' ',' ')}, /* Wa */ {"wbr", HB_TAG('W','A','G',' ')}, /* Wagdi */ + {"wle", HB_TAG('S','I','G',' ')}, /* Wolane */ + {"wry", HB_TAG('M','A','W',' ')}, /* Merwari */ + {"wtm", HB_TAG('W','T','M',' ')}, /* Mewati */ {"wo", HB_TAG('W','L','F',' ')}, /* Wolof */ {"xal", HB_TAG('K','L','M',' ')}, /* Kalmyk */ {"xh", HB_TAG('X','H','S',' ')}, /* Xhosa */ + {"xog", HB_TAG('X','O','G',' ')}, /* Soga */ {"xom", HB_TAG('K','M','O',' ')}, /* Komo (Sudan) */ {"xsl", HB_TAG('S','S','L',' ')}, /* South Slavey */ - {"yi", HB_TAG('J','I','I',' ')}, /* Yiddish */ + {"xst", HB_TAG('S','I','G',' ')}, /* Silt'e (retired code) */ + {"xwo", HB_TAG('T','O','D',' ')}, /* Written Oirat (Todo) */ + {"yao", HB_TAG('Y','A','O',' ')}, /* Yao */ + {"yi", HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */ {"yo", HB_TAG('Y','B','A',' ')}, /* Yoruba */ {"yso", HB_TAG('N','I','S',' ')}, /* Nisi (China) */ + {"za", HB_TAG('Z','H','A',' ')}, /* Chuang/Zhuang [macrolanguage] */ + {"zea", HB_TAG('Z','E','A',' ')}, /* Zeeuws */ {"zne", HB_TAG('Z','N','D',' ')}, /* Zande */ - {"zu", HB_TAG('Z','U','L',' ')} /* Zulu */ + {"zu", HB_TAG('Z','U','L',' ')}, /* Zulu */ + {"zum", HB_TAG('L','R','C',' ')} /* Kumzari */ /* The corresponding languages IDs for the following IDs are unclear, * overlap, or are architecturally weird. Needs more research. */ @@ -536,13 +721,13 @@ static const LangTag ot_languages[] = { /*{"gsw?/gsw-FR?", HB_TAG('A','L','S',' ')},*/ /* Alsatian */ /*{"krc", HB_TAG('B','A','L',' ')},*/ /* Balkar */ /*{"??", HB_TAG('B','C','R',' ')},*/ /* Bible Cree */ -/*{"sgw?", HB_TAG('C','H','G',' ')},*/ /* Chaha Gurage */ +/*{"zh?", HB_TAG('C','H','N',' ')},*/ /* Chinese (seen in Microsoft fonts) */ /*{"acf/gcf?", HB_TAG('F','A','N',' ')},*/ /* French Antillean */ -/*{"vls/nl-be", HB_TAG('F','L','E',' ')},*/ /* Flemish */ /*{"enf?/yrk?", HB_TAG('F','N','E',' ')},*/ /* Forest Nenets */ /*{"fuf?", HB_TAG('F','T','A',' ')},*/ /* Futa */ /*{"ar-Syrc?", HB_TAG('G','A','R',' ')},*/ /* Garshuni */ /*{"cfm/rnl?", HB_TAG('H','A','L',' ')},*/ /* Halam */ +/*{"fonipa", HB_TAG('I','P','P','H')},*/ /* Phonetic transcription—IPA conventions */ /*{"ga-Latg?/Latg?", HB_TAG('I','R','T',' ')},*/ /* Irish Traditional */ /*{"krc", HB_TAG('K','A','R',' ')},*/ /* Karachay */ /*{"alw?/ktb?", HB_TAG('K','E','B',' ')},*/ /* Kebena */ @@ -559,8 +744,6 @@ static const LangTag ot_languages[] = { /*{"??", HB_TAG('L','C','R',' ')},*/ /* L-Cree */ /*{"??", HB_TAG('M','A','L',' ')},*/ /* Malayalam Traditional */ /*{"mnk?/mlq?/...", HB_TAG('M','L','N',' ')},*/ /* Malinke */ -/*{"man?/myq?/mku?/msc?/...", HB_TAG('M','N','K',' ')},*/ /* Maninka */ -/*{"??", HB_TAG('M','O','R',' ')},*/ /* Moroccan */ /*{"??", HB_TAG('N','C','R',' ')},*/ /* N-Cree */ /*{"??", HB_TAG('N','H','C',' ')},*/ /* Norway House Cree */ /*{"jpa?/sam?", HB_TAG('P','A','A',' ')},*/ /* Palestinian Aramaic */ @@ -569,14 +752,12 @@ static const LangTag ot_languages[] = { /*{"??", HB_TAG('R','C','R',' ')},*/ /* R-Cree */ /*{"chp?", HB_TAG('S','A','Y',' ')},*/ /* Sayisi */ /*{"xan?", HB_TAG('S','E','K',' ')},*/ /* Sekota */ -/*{"stv/wle?/xst?", HB_TAG('S','I','G',' ')},*/ /* Silte Gurage */ /*{"ngo?", HB_TAG('S','X','T',' ')},*/ /* Sutu */ /*{"??", HB_TAG('T','C','R',' ')},*/ /* TH-Cree */ /*{"tnz?/tog?/toi?", HB_TAG('T','N','G',' ')},*/ /* Tonga */ /*{"enh?/yrk?", HB_TAG('T','N','E',' ')},*/ /* Tundra Nenets */ -/*{"??", HB_TAG('T','O','D',' ')},*/ /* Todo */ /*{"??", HB_TAG('W','C','R',' ')},*/ /* West-Cree */ -/*{"??", HB_TAG('Y','C','R',' ')},*/ /* Y-Cree */ +/*{"cre?", HB_TAG('Y','C','R',' ')},*/ /* Y-Cree */ /*{"??", HB_TAG('Y','I','C',' ')},*/ /* Yi Classic */ /*{"ii?/Yiii?", HB_TAG('Y','I','M',' ')},*/ /* Yi Modern */ /*{"??", HB_TAG('Z','H','P',' ')},*/ /* Chinese Phonetic */ diff --git a/third_party/harfbuzz-ng/src/hb-ot.h b/third_party/harfbuzz-ng/src/hb-ot.h index 8073906..e9a280b 100644 --- a/third_party/harfbuzz-ng/src/hb-ot.h +++ b/third_party/harfbuzz-ng/src/hb-ot.h @@ -32,17 +32,10 @@ #include "hb-ot-layout.h" #include "hb-ot-tag.h" +#include "hb-ot-shape.h" HB_BEGIN_DECLS -/* TODO remove */ -void -hb_ot_shape_glyphs_closure (hb_font_t *font, - hb_buffer_t *buffer, - const hb_feature_t *features, - unsigned int num_features, - hb_set_t *glyphs); - HB_END_DECLS #undef HB_OT_H_IN diff --git a/third_party/harfbuzz-ng/src/hb-private.hh b/third_party/harfbuzz-ng/src/hb-private.hh index 4b72260..680b21e 100644 --- a/third_party/harfbuzz-ng/src/hb-private.hh +++ b/third_party/harfbuzz-ng/src/hb-private.hh @@ -808,6 +808,12 @@ hb_in_range (T u, T lo, T hi) } template <typename T> static inline bool +hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2) +{ + return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2); +} + +template <typename T> static inline bool hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) { return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3); diff --git a/third_party/harfbuzz-ng/src/hb-set-private.hh b/third_party/harfbuzz-ng/src/hb-set-private.hh index ca2a07b..705f554 100644 --- a/third_party/harfbuzz-ng/src/hb-set-private.hh +++ b/third_party/harfbuzz-ng/src/hb-set-private.hh @@ -28,7 +28,6 @@ #define HB_SET_PRIVATE_HH #include "hb-private.hh" -#include "hb-set.h" #include "hb-object-private.hh" diff --git a/third_party/harfbuzz-ng/src/hb-shape-plan-private.hh b/third_party/harfbuzz-ng/src/hb-shape-plan-private.hh index dd014e3..607da5e 100644 --- a/third_party/harfbuzz-ng/src/hb-shape-plan-private.hh +++ b/third_party/harfbuzz-ng/src/hb-shape-plan-private.hh @@ -28,7 +28,6 @@ #define HB_SHAPE_PLAN_PRIVATE_HH #include "hb-private.hh" -#include "hb-shape-plan.h" #include "hb-object-private.hh" #include "hb-shaper-private.hh" @@ -39,12 +38,15 @@ struct hb_shape_plan_t ASSERT_POD (); hb_bool_t default_shaper_list; - hb_face_t *face; + hb_face_t *face_unsafe; /* We don't carry a reference to face. */ hb_segment_properties_t props; hb_shape_func_t *shaper_func; const char *shaper_name; + hb_feature_t *user_features; + unsigned int num_user_features; + struct hb_shaper_data_t shaper_data; }; diff --git a/third_party/harfbuzz-ng/src/hb-shape-plan.cc b/third_party/harfbuzz-ng/src/hb-shape-plan.cc index b44a9e2..e354f29 100644 --- a/third_party/harfbuzz-ng/src/hb-shape-plan.cc +++ b/third_party/harfbuzz-ng/src/hb-shape-plan.cc @@ -46,7 +46,7 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan, #define HB_SHAPER_PLAN(shaper) \ HB_STMT_START { \ - if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face)) { \ + if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \ HB_SHAPER_DATA (shaper, shape_plan) = \ HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, user_features, num_user_features); \ shape_plan->shaper_func = _hb_##shaper##_shape; \ @@ -107,18 +107,27 @@ hb_shape_plan_create (hb_face_t *face, assert (props->direction != HB_DIRECTION_INVALID); hb_shape_plan_t *shape_plan; + hb_feature_t *features = NULL; if (unlikely (!face)) face = hb_face_get_empty (); if (unlikely (!props || hb_object_is_inert (face))) return hb_shape_plan_get_empty (); - if (!(shape_plan = hb_object_create<hb_shape_plan_t> ())) + if (num_user_features && !(features = (hb_feature_t *) malloc (num_user_features * sizeof (hb_feature_t)))) return hb_shape_plan_get_empty (); + if (!(shape_plan = hb_object_create<hb_shape_plan_t> ())) { + free (features); + return hb_shape_plan_get_empty (); + } hb_face_make_immutable (face); shape_plan->default_shaper_list = shaper_list == NULL; - shape_plan->face = hb_face_reference (face); + shape_plan->face_unsafe = face; shape_plan->props = *props; + shape_plan->num_user_features = num_user_features; + shape_plan->user_features = features; + if (num_user_features) + memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); hb_shape_plan_plan (shape_plan, user_features, num_user_features, shaper_list); @@ -147,6 +156,9 @@ hb_shape_plan_get_empty (void) NULL, /* shaper_func */ NULL, /* shaper_name */ + NULL, /* user_features */ + 0, /* num_user_featurs */ + { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, #include "hb-shaper-list.hh" @@ -190,7 +202,7 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT - hb_face_destroy (shape_plan->face); + free (shape_plan->user_features); free (shape_plan); } @@ -264,7 +276,7 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan, hb_object_is_inert (buffer))) return false; - assert (shape_plan->face == font->face); + assert (shape_plan->face_unsafe == font->face); assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props)); #define HB_SHAPER_EXECUTE(shaper) \ @@ -301,23 +313,55 @@ hb_shape_plan_hash (const hb_shape_plan_t *shape_plan) } #endif -/* TODO no user-feature caching for now. */ +/* User-feature caching is currently somewhat dumb: + * it only finds matches where the feature array is identical, + * not cases where the feature lists would be compatible for plan purposes + * but have different ranges, for example. + */ struct hb_shape_plan_proposal_t { const hb_segment_properties_t props; const char * const *shaper_list; + const hb_feature_t *user_features; + unsigned int num_user_features; hb_shape_func_t *shaper_func; }; +static inline hb_bool_t +hb_shape_plan_user_features_match (const hb_shape_plan_t *shape_plan, + const hb_shape_plan_proposal_t *proposal) +{ + if (proposal->num_user_features != shape_plan->num_user_features) return false; + for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++) + if (proposal->user_features[i].tag != shape_plan->user_features[i].tag || + proposal->user_features[i].value != shape_plan->user_features[i].value || + proposal->user_features[i].start != shape_plan->user_features[i].start || + proposal->user_features[i].end != shape_plan->user_features[i].end) return false; + return true; +} + static hb_bool_t hb_shape_plan_matches (const hb_shape_plan_t *shape_plan, const hb_shape_plan_proposal_t *proposal) { return hb_segment_properties_equal (&shape_plan->props, &proposal->props) && + hb_shape_plan_user_features_match (shape_plan, proposal) && ((shape_plan->default_shaper_list && proposal->shaper_list == NULL) || (shape_plan->shaper_func == proposal->shaper_func)); } +static inline hb_bool_t +hb_non_global_user_features_present (const hb_feature_t *user_features, + unsigned int num_user_features) +{ + while (num_user_features) + if (user_features->start != 0 || user_features->end != (unsigned int) -1) + return true; + else + num_user_features--, user_features++; + return false; +} + /** * hb_shape_plan_create_cached: * @face: @@ -339,12 +383,11 @@ hb_shape_plan_create_cached (hb_face_t *face, unsigned int num_user_features, const char * const *shaper_list) { - if (num_user_features) - return hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list); - hb_shape_plan_proposal_t proposal = { *props, shaper_list, + user_features, + num_user_features, NULL }; @@ -382,6 +425,11 @@ retry: hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list); + /* Don't add the plan to the cache if there were user features with non-global ranges */ + + if (hb_non_global_user_features_present (user_features, num_user_features)) + return shape_plan; + hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t)); if (unlikely (!node)) return shape_plan; @@ -395,9 +443,6 @@ retry: goto retry; } - /* Release our reference on face. */ - hb_face_destroy (face); - return hb_shape_plan_reference (shape_plan); } diff --git a/third_party/harfbuzz-ng/src/hb-shaper-list.hh b/third_party/harfbuzz-ng/src/hb-shaper-list.hh index b9c029e..da6d8e0 100644 --- a/third_party/harfbuzz-ng/src/hb-shaper-list.hh +++ b/third_party/harfbuzz-ng/src/hb-shaper-list.hh @@ -52,4 +52,6 @@ HB_SHAPER_IMPLEMENT (uniscribe) HB_SHAPER_IMPLEMENT (coretext) #endif +#ifdef HAVE_FALLBACK HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */ +#endif diff --git a/third_party/harfbuzz-ng/src/hb-tt-font.cc b/third_party/harfbuzz-ng/src/hb-tt-font.cc index c503a40..2233a4f 100644 --- a/third_party/harfbuzz-ng/src/hb-tt-font.cc +++ b/third_party/harfbuzz-ng/src/hb-tt-font.cc @@ -31,8 +31,6 @@ #include "hb-ot-hhea-table.hh" #include "hb-ot-hmtx-table.hh" -#include "hb-blob.h" - #include <string.h> diff --git a/third_party/harfbuzz-ng/src/hb-unicode-private.hh b/third_party/harfbuzz-ng/src/hb-unicode-private.hh index dd4d001..ba193e8 100644 --- a/third_party/harfbuzz-ng/src/hb-unicode-private.hh +++ b/third_party/harfbuzz-ng/src/hb-unicode-private.hh @@ -32,8 +32,6 @@ #define HB_UNICODE_PRIVATE_HH #include "hb-private.hh" - -#include "hb-unicode.h" #include "hb-object-private.hh" @@ -108,7 +106,11 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE modified_combining_class (hb_codepoint_t unicode) { /* XXX This hack belongs to the Myanmar shaper. */ - if (unicode == 0x1037) unicode = 0x103A; + if (unlikely (unicode == 0x1037)) unicode = 0x103A; + + /* XXX This hack belongs to the SEA shaper (for Tai Tham): + * Reorder SAKOT to ensure it comes after any tone marks. */ + if (unlikely (unicode == 0x1A60)) return 254; return _hb_modified_combining_class[combining_class (unicode)]; } @@ -132,10 +134,10 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE * 6.3 is also added manually. The new Unicode 6.3 bidi formatting * characters are encoded in a block that was Default_Ignorable already. * - * Note: While U+115F and U+1160 are Default_Ignorable, we do NOT want to - * hide them, as the way Uniscribe has implemented them is with regular - * spacing glyphs, and that's the way fonts are made to work. As such, - * we make exceptions for those two. + * Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable, + * we do NOT want to hide them, as the way Uniscribe has implemented them + * is with regular spacing glyphs, and that's the way fonts are made to work. + * As such, we make exceptions for those four. * * Gathered from: * http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:DI:]&abb=on&ucd=on&esc=on @@ -157,10 +159,10 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE * 200B..200F ;RIGHT-TO-LEFT MARK * 202A..202E ;RIGHT-TO-LEFT OVERRIDE * 2060..206F ;NOMINAL DIGIT SHAPES - * 3164 ;HANGUL FILLER + * #3164 ;HANGUL FILLER * FE00..FE0F ;VARIATION SELECTOR-16 * FEFF ;ZERO WIDTH NO-BREAK SPACE - * FFA0 ;HALFWIDTH HANGUL FILLER + * #FFA0 ;HALFWIDTH HANGUL FILLER * FFF0..FFF8 ;<unassigned-FFF8> * 1D173..1D17A ;MUSICAL SYMBOL END PHRASE * E0000..E0FFF ;<unassigned-E0FFF> @@ -182,9 +184,8 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200B, 0x200F, 0x202A, 0x202E, 0x2060, 0x206F); - case 0x31: return unlikely (ch == 0x3164); case 0xFE: return hb_in_range<hb_codepoint_t> (ch, 0xFE00, 0xFE0F) || ch == 0xFEFF; - case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0, 0xFFF8) || ch == 0xFFA0; + case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0, 0xFFF8); default: return false; } } diff --git a/third_party/harfbuzz-ng/src/hb-unicode.cc b/third_party/harfbuzz-ng/src/hb-unicode.cc index 145d528..5b44913 100644 --- a/third_party/harfbuzz-ng/src/hb-unicode.cc +++ b/third_party/harfbuzz-ng/src/hb-unicode.cc @@ -133,7 +133,7 @@ hb_unicode_funcs_get_default (void) #ifdef HAVE_GLIB HB_UNICODE_FUNCS_IMPLEMENT(glib) -#elif defined(HAVE_ICU) +#elif 0 && defined(HAVE_ICU) HB_UNICODE_FUNCS_IMPLEMENT(icu) #elif defined(HAVE_UCDN) HB_UNICODE_FUNCS_IMPLEMENT(ucdn) diff --git a/third_party/harfbuzz-ng/src/hb-uniscribe.cc b/third_party/harfbuzz-ng/src/hb-uniscribe.cc index fcb1aa6..6571448 100644 --- a/third_party/harfbuzz-ng/src/hb-uniscribe.cc +++ b/third_party/harfbuzz-ng/src/hb-uniscribe.cc @@ -709,7 +709,7 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, for (unsigned int i = 0; i < range_records.len; i++) { range_record_t *range = &range_records[i]; - range->props.potfRecords = feature_records.array + reinterpret_cast<unsigned int> (range->props.potfRecords); + range->props.potfRecords = feature_records.array + reinterpret_cast<uintptr_t> (range->props.potfRecords); } } else @@ -776,13 +776,14 @@ retry: } } - /* All the following types are sized in multiples of sizeof(int). */ - unsigned int glyphs_size = scratch_size / ((sizeof (WORD) + - sizeof (SCRIPT_GLYPHPROP) + - sizeof (int) + - sizeof (GOFFSET) + - sizeof (uint32_t)) - / sizeof (int)); + /* The -2 in the following is to compensate for possible + * alignment needed after the WORD array. sizeof(WORD) == 2. */ + unsigned int glyphs_size = (scratch_size * sizeof (int) - 2) + / (sizeof (WORD) + + sizeof (SCRIPT_GLYPHPROP) + + sizeof (int) + + sizeof (GOFFSET) + + sizeof (uint32_t)); ALLOCATE_ARRAY (WORD, glyphs, glyphs_size); ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size); |