Snap for 9728260 from 037d385269fdf902e814214e7515ed39bf2318cd to udc-release

Change-Id: Ib758b10a4ec3e984d49e20e1e2ab71ed04475cdb
diff --git a/.ci/build-win32.sh b/.ci/build-win32.sh
index a1ca53d..067e222 100755
--- a/.ci/build-win32.sh
+++ b/.ci/build-win32.sh
@@ -6,8 +6,9 @@
 	-Dtests=disabled \
 	-Dcairo=enabled \
 	-Dcairo:fontconfig=disabled \
+	-Dcairo:freetype=disabled \
 	-Dglib=enabled \
-	-Dfreetype=enabled \
+	-Dfreetype=disabled \
 	-Dgdi=enabled \
 	-Ddirectwrite=enabled \
 	-Dcairo=enabled \
diff --git a/.ci/build-win64.sh b/.ci/build-win64.sh
index 385d559..946d245 100644
--- a/.ci/build-win64.sh
+++ b/.ci/build-win64.sh
@@ -6,8 +6,9 @@
 	-Dtests=disabled \
 	-Dcairo=enabled \
 	-Dcairo:fontconfig=disabled \
+	-Dcairo:freetype=disabled \
 	-Dglib=enabled \
-	-Dfreetype=enabled \
+	-Dfreetype=disabled \
 	-Dgdi=enabled \
 	-Ddirectwrite=enabled \
 	-Dcairo=enabled \
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 9525c4a..b013b55 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -136,7 +136,7 @@
     steps:
       - checkout
       - run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build gtk-doc-tools python3 python3-pip git g++-mingw-w64-i686 zip
-      - run: pip3 install meson==0.56.0 --upgrade
+      - run: pip3 install meson==0.60.0
       - run: .ci/build-win32.sh
       - store_artifacts:
           path: harfbuzz-win32.zip
@@ -159,7 +159,7 @@
     steps:
       - checkout
       - run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build gtk-doc-tools python3 python3-pip git g++-mingw-w64-x86-64 zip
-      - run: pip3 install meson==0.56.0 --upgrade
+      - run: pip3 install meson==0.60.0
       - run: bash .ci/build-win64.sh
       - store_artifacts:
           path: harfbuzz-win64.zip
diff --git a/.github/workflows/arm-ci.yml b/.github/workflows/arm-ci.yml
new file mode 100644
index 0000000..3df1316
--- /dev/null
+++ b/.github/workflows/arm-ci.yml
@@ -0,0 +1,25 @@
+name: arm
+
+on:
+  push:
+    branches: [ main ]
+  pull_request:
+    branches: [ main ]
+
+permissions:
+  contents: read
+
+jobs:
+  arm-none-eabi:
+    runs-on: ubuntu-22.04
+    container:
+      image: devkitpro/devkitarm:latest
+    steps:
+      - uses: actions/checkout@v3
+      - name: Configure CMake
+        run: |
+          cmake -S . -B build \
+            -DCMAKE_TOOLCHAIN_FILE=${DEVKITPRO}/cmake/3DS.cmake
+      - name: Build
+        run: make CXX_FLAGS="-w -DHB_NO_MT"
+        working-directory: build
diff --git a/.github/workflows/configs-build.yml b/.github/workflows/configs-build.yml
index 9f4fd78..b81ce92 100644
--- a/.github/workflows/configs-build.yml
+++ b/.github/workflows/configs-build.yml
@@ -11,7 +11,7 @@
 
 jobs:
   build:
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
 
     steps:
     - uses: actions/checkout@v3
diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci.yml
index f67f5d3..3a95e9b 100644
--- a/.github/workflows/linux-ci.yml
+++ b/.github/workflows/linux-ci.yml
@@ -12,7 +12,7 @@
 
 jobs:
   build:
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
 
     steps:
     - uses: actions/checkout@v3
diff --git a/.github/workflows/macos-ci.yml b/.github/workflows/macos-ci.yml
index a6b6d3d..6a0b793 100644
--- a/.github/workflows/macos-ci.yml
+++ b/.github/workflows/macos-ci.yml
@@ -16,15 +16,9 @@
     steps:
     - uses: actions/checkout@v3
     - name: install dependencies
-      run: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config freetype glib glib-utils cairo icu4c graphite2 gobject-introspection gtk-doc ninja
-    - run: pip3 install fonttools meson==0.56.0 gcovr==5.0
+      run: HOMEBREW_NO_AUTO_UPDATE=1 brew install meson pkg-config freetype glib glib-utils cairo icu4c graphite2 gobject-introspection gtk-doc ninja
+    - run: pip3 install fonttools
     - name: run
-      run: PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig" meson build -Db_coverage=true -Dcoretext=enabled -Dgraphite=enabled -Dauto_features=enabled -Dchafa=disabled -Doptimization=2
+      run: PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig" meson build -Dcoretext=enabled -Dgraphite=enabled -Dauto_features=enabled -Dchafa=disabled -Doptimization=2
     - name: ci
       run: meson test --print-errorlogs -Cbuild
-
-    - name: cov
-      run: ninja -Cbuild coverage-xml
-    - uses: codecov/codecov-action@v3
-      with:
-        file: build/meson-logs/coverage.xml
diff --git a/.github/workflows/msvc-ci.yml b/.github/workflows/msvc-ci.yml
index 57aef04..79be9f6 100644
--- a/.github/workflows/msvc-ci.yml
+++ b/.github/workflows/msvc-ci.yml
@@ -14,6 +14,7 @@
     runs-on: ${{ matrix.os }}
 
     strategy:
+      fail-fast: false
       matrix:
         os: [windows-2019, windows-latest]
         include:
@@ -45,7 +46,7 @@
           $env:path = ($env:path.Split(';') | Where-Object { $_ -ne 'C:\Strawberry\perl\bin' }) -join ';'
 
           meson setup build `
-            --wrap-mode=default `
+            --wrap-mode=forcefallback `
             --buildtype=release `
             -Dglib=enabled `
             -Dfreetype=enabled `
diff --git a/.github/workflows/msys2-ci.yml b/.github/workflows/msys2-ci.yml
index 0704f4c..d5bddb4 100644
--- a/.github/workflows/msys2-ci.yml
+++ b/.github/workflows/msys2-ci.yml
@@ -14,6 +14,7 @@
     runs-on: windows-latest
 
     strategy:
+      fail-fast: false
       matrix:
         include:
           - MSYSTEM: MINGW32
@@ -22,6 +23,11 @@
             MSYS2_ARCH: x86_64
     name: ${{ matrix.MSYSTEM }}
 
+    env:
+      # XXX: For some reason enabling jit debugging "fixes" random python crashes
+      # see https://github.com/msys2/MINGW-packages/issues/11864
+      MSYS: "winjitdebug"
+
     defaults:
       run:
         shell: msys2 {0}
diff --git a/LICENSE b/LICENSE
index 2c60343..7e75ed0 100644
--- a/LICENSE
+++ b/LICENSE
@@ -935,6 +935,12 @@
 
 Licensed under the Apache License, Version 2.0
 
+-------------------------------------------------------------------
+
+Copyright 2011 Google Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0
+
 http://www.apache.org/licenses/LICENSE-2.0
 
 -------------------------------------------------------------------
@@ -4445,6 +4451,30 @@
 
 -------------------------------------------------------------------
 
+Copyright © 2022 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.
+
+-------------------------------------------------------------------
+
 Copyright ©1993–2016 by The Font Bureau, Inc. with Reserved Font Name “Zycon”
 
 https://opensource.org/licenses/OFL-1.1
diff --git a/NEWS b/NEWS
index 8d4389f..73dcef0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,65 @@
+Overview of changes leading to 6.0.0
+Friday, December 16, 2022
+====================================
+- A new API have been added to pre-process the face and speed up future
+  subsetting operations on that face. Provides up to a 95% reduction in
+  subsetting times when the same face is subset more than once.
+
+  For more details and benchmarks, see:
+  https://github.com/harfbuzz/harfbuzz/blob/main/docs/subset-preprocessing.md
+
+  (Garret Rieger, Behdad Esfahbod)
+
+- Shaping have been speedup by skipping entire lookups when the buffer contents
+  don't intersect with the lookup. Shows up to a 10% speedup in shaping some
+  fonts. (Behdad Esfahbod)
+
+- A new experimental feature, “Variable Composites” (enabled by passing
+  -Dexperimental_api=true to meson), is also featured in this release.
+  This technology enables drastic compression of fonts in the Chinese,
+  Japanese, Korean, and other writing systems, by reusing the OpenType Font
+  Variations technology for encoding “smart components” into the font.
+
+  The specification for these  extensions to the font format can be found in:
+  https://github.com/harfbuzz/boring-expansion-spec/blob/glyf1/glyf1.md
+
+  A test variable-font with ~7160 Hangul syllables derived from the
+  NotoSerifKR-VF font has been built, with existing OpenType technology, as
+  well as with the new Variable Composites (VarComposites) technology. The
+  VarComposites font is over 90% smaller than the OpenType version of the font!
+  Both fonts can be obtained from the “smarties” repository:
+  https://github.com/behdad/smarties/tree/3.0/fonts/hangul/serif
+
+  When building HarfBuzz with experimental features enabled, you can test
+  the “smarties” font with a sample character like this:
+
+  $ hb-view butchered-hangul-serif-smarties-variable.ttf -u AE01 --variations=wght=700
+
+  (Behdad Esfahbod)
+
+- The HarfBuzz subsetter can now drop axes by pinning them to specific values
+  (also referred to as instancing). There are a couple of restrictions
+  currently:
+
+  - Only works with TrueType (“glyf”) based fonts. “CFF2” fonts are not yet
+    supported.
+  - Only supports the case where all axes in a font are pinned.
+
+  (Garret Rieger, Qunxin Liu)
+
+- Miscellaneous fixes and improvements.
+
+  (Behdad Esfahbod, Christoph Reiter, David Corbett, Eli Schwartz, Garret
+   Rieger, Joel Auterson, Jordan Petridis, Khaled Hosny, Lorenz Wildberg,
+   Marco Rebhan, Martin Storsjö, Matthias Clasen, Qunxin Liu, Satadru Pramanik)
+
+
+- New API
++hb_subset_input_pin_axis_location()
++hb_subset_input_pin_axis_to_default()
++hb_subset_preprocess()
+
+
 Overview of changes leading to 5.3.1
 Wednesday, October 19, 2022
 ====================================
diff --git a/configure.ac b/configure.ac
index f2480c3..abe86ed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [5.3.1],
+        [6.0.0],
         [https://github.com/harfbuzz/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
diff --git a/docs/harfbuzz-docs.xml b/docs/harfbuzz-docs.xml
index 652a5e4..2d2827a 100644
--- a/docs/harfbuzz-docs.xml
+++ b/docs/harfbuzz-docs.xml
@@ -117,6 +117,7 @@
       <index id="api-index-full"><title>API Index</title><xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include></index>
       <index id="deprecated-api-index" role="deprecated"><title>Index of deprecated API</title><xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include></index>
 
+      <index id="api-index-6-0-0" role="6.0.0"><title>Index of new symbols in 6.0.0</title><xi:include href="xml/api-index-6.0.0.xml"><xi:fallback /></xi:include></index>
       <index id="api-index-5-3-0" role="5.3.0"><title>Index of new symbols in 5.3.0</title><xi:include href="xml/api-index-5.3.0.xml"><xi:fallback /></xi:include></index>
       <index id="api-index-5-0-0" role="5.0.0"><title>Index of new symbols in 5.0.0</title><xi:include href="xml/api-index-5.0.0.xml"><xi:fallback /></xi:include></index>
       <index id="api-index-4-4-0" role="4.4.0"><title>Index of new symbols in 4.4.0</title><xi:include href="xml/api-index-4.4.0.xml"><xi:fallback /></xi:include></index>
diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index 3a7aa35..a35d3aa 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -26,33 +26,33 @@
 hb_blob_create_from_file_or_fail
 hb_blob_create_sub_blob
 hb_blob_copy_writable_or_fail
+hb_blob_get_empty
+hb_blob_reference
 hb_blob_destroy
+hb_blob_set_user_data
+hb_blob_get_user_data
+hb_blob_make_immutable
+hb_blob_is_immutable
 hb_blob_get_data
 hb_blob_get_data_writable
-hb_blob_get_empty
 hb_blob_get_length
-hb_blob_get_user_data
-hb_blob_is_immutable
-hb_blob_make_immutable
-hb_blob_reference
-hb_blob_set_user_data
 hb_blob_t
 hb_memory_mode_t
 </SECTION>
 
 <SECTION>
 <FILE>hb-buffer</FILE>
-HB_SEGMENT_PROPERTIES_DEFAULT
-HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT
 hb_buffer_create
+hb_buffer_allocation_successful
 hb_buffer_create_similar
-hb_buffer_reference
 hb_buffer_get_empty
+hb_buffer_reference
 hb_buffer_destroy
+hb_buffer_set_user_data
+hb_buffer_get_user_data
 hb_buffer_reset
 hb_buffer_clear_contents
 hb_buffer_pre_allocate
-hb_buffer_allocation_successful
 hb_buffer_add
 hb_buffer_add_codepoints
 hb_buffer_add_utf32
@@ -79,15 +79,14 @@
 hb_buffer_guess_segment_properties
 hb_buffer_set_unicode_funcs
 hb_buffer_get_unicode_funcs
-hb_buffer_set_user_data
-hb_buffer_get_user_data
 hb_buffer_get_glyph_infos
+hb_glyph_info_get_glyph_flags
 hb_buffer_get_glyph_positions
 hb_buffer_has_positions
-hb_buffer_get_invisible_glyph
 hb_buffer_set_invisible_glyph
-hb_buffer_get_not_found_glyph
+hb_buffer_get_invisible_glyph
 hb_buffer_set_not_found_glyph
+hb_buffer_get_not_found_glyph
 hb_buffer_set_replacement_codepoint
 hb_buffer_get_replacement_codepoint
 hb_buffer_normalize_glyphs
@@ -106,9 +105,11 @@
 hb_segment_properties_hash
 hb_segment_properties_overlay
 hb_buffer_diff
+hb_buffer_message_func_t
 hb_buffer_set_message_func
+HB_SEGMENT_PROPERTIES_DEFAULT
+HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT
 hb_buffer_t
-hb_glyph_info_get_glyph_flags
 hb_glyph_info_t
 hb_glyph_flags_t
 hb_glyph_position_t
@@ -119,18 +120,25 @@
 hb_buffer_serialize_format_t
 hb_buffer_serialize_flags_t
 hb_buffer_diff_flags_t
-hb_buffer_message_func_t
 </SECTION>
 
 <SECTION>
 <FILE>hb-common</FILE>
+HB_TAG
+HB_UNTAG
 hb_tag_from_string
 hb_tag_to_string
 hb_direction_from_string
 hb_direction_to_string
+HB_DIRECTION_REVERSE
+HB_DIRECTION_IS_BACKWARD
+HB_DIRECTION_IS_FORWARD
+HB_DIRECTION_IS_HORIZONTAL
+HB_DIRECTION_IS_VALID
+HB_DIRECTION_IS_VERTICAL
 hb_script_from_iso15924_tag
-hb_script_from_string
 hb_script_to_iso15924_tag
+hb_script_from_string
 hb_script_get_horizontal_direction
 hb_language_from_string
 hb_language_to_string
@@ -152,20 +160,16 @@
 hb_tag_t
 hb_script_t
 hb_user_data_key_t
-HB_TAG
 HB_TAG_NONE
 HB_TAG_MAX
 HB_TAG_MAX_SIGNED
-HB_UNTAG
-HB_DIRECTION_REVERSE
-HB_DIRECTION_IS_BACKWARD
-HB_DIRECTION_IS_FORWARD
-HB_DIRECTION_IS_HORIZONTAL
-HB_DIRECTION_IS_VALID
-HB_DIRECTION_IS_VERTICAL
 HB_LANGUAGE_INVALID
 HB_FEATURE_GLOBAL_END
 HB_FEATURE_GLOBAL_START
+HB_HAS_CORETEXT
+HB_HAS_FREETYPE
+HB_HAS_GLIB
+HB_HAS_GRAPHITE
 <SUBSECTION Private>
 HB_BEGIN_DECLS
 HB_END_DECLS
@@ -179,7 +183,6 @@
 uint32_t
 uint64_t
 uint8_t
-<SUBSECTION Private>
 HB_EXTERN
 HB_DEPRECATED
 HB_DEPRECATED_FOR
@@ -187,12 +190,11 @@
 
 <SECTION>
 <FILE>hb-draw</FILE>
-hb_draw_funcs_t
 hb_draw_funcs_create
-hb_draw_funcs_destroy
 hb_draw_funcs_reference
-hb_draw_funcs_is_immutable
+hb_draw_funcs_destroy
 hb_draw_funcs_make_immutable
+hb_draw_funcs_is_immutable
 hb_draw_move_to_func_t
 hb_draw_funcs_set_move_to_func
 hb_draw_line_to_func_t
@@ -203,13 +205,14 @@
 hb_draw_funcs_set_cubic_to_func
 hb_draw_close_path_func_t
 hb_draw_funcs_set_close_path_func
-hb_draw_state_t
-HB_DRAW_STATE_DEFAULT
 hb_draw_move_to
 hb_draw_line_to
 hb_draw_quadratic_to
 hb_draw_cubic_to
 hb_draw_close_path
+HB_DRAW_STATE_DEFAULT
+hb_draw_funcs_t
+hb_draw_state_t
 </SECTION>
 
 <SECTION>
@@ -264,22 +267,22 @@
 hb_face_t
 hb_face_create
 hb_face_create_for_tables
-hb_face_destroy
 hb_face_get_empty
-hb_face_get_table_tags
-hb_face_get_glyph_count
-hb_face_get_index
-hb_face_get_upem
-hb_face_get_user_data
-hb_face_is_immutable
-hb_face_make_immutable
 hb_face_reference
+hb_face_destroy
+hb_face_set_user_data
+hb_face_get_user_data
+hb_face_make_immutable
+hb_face_is_immutable
+hb_face_get_table_tags
+hb_face_set_glyph_count
+hb_face_get_glyph_count
+hb_face_set_index
+hb_face_get_index
+hb_face_set_upem
+hb_face_get_upem
 hb_face_reference_blob
 hb_face_reference_table
-hb_face_set_glyph_count
-hb_face_set_index
-hb_face_set_upem
-hb_face_set_user_data
 hb_face_collect_unicodes
 hb_face_collect_variation_selectors
 hb_face_collect_variation_unicodes
@@ -293,113 +296,113 @@
 hb_font_add_glyph_origin_for_direction
 hb_font_create
 hb_font_create_sub_font
-hb_font_destroy
-hb_font_funcs_create
-hb_font_funcs_destroy
-hb_font_funcs_get_empty
-hb_font_funcs_get_user_data
-hb_font_funcs_is_immutable
-hb_font_funcs_make_immutable
-hb_font_funcs_reference
-hb_font_funcs_set_glyph_contour_point_func
-hb_font_funcs_set_glyph_extents_func
-hb_font_funcs_set_glyph_from_name_func
-hb_font_funcs_set_glyph_h_advance_func
-hb_font_funcs_set_glyph_h_advances_func
-hb_font_funcs_set_glyph_h_kerning_func
-hb_font_funcs_set_glyph_h_origin_func
-hb_font_funcs_set_glyph_name_func
-hb_font_funcs_set_glyph_shape_func
-hb_font_funcs_set_glyph_v_advance_func
-hb_font_funcs_set_glyph_v_advances_func
-hb_font_funcs_set_glyph_v_origin_func
-hb_font_funcs_set_nominal_glyph_func
-hb_font_funcs_set_nominal_glyphs_func
-hb_font_funcs_set_user_data
-hb_font_funcs_set_variation_glyph_func
-hb_font_funcs_t
 hb_font_get_empty
+hb_font_reference
+hb_font_destroy
+hb_font_set_user_data
+hb_font_get_user_data
+hb_font_make_immutable
+hb_font_is_immutable
+hb_font_set_face
 hb_font_get_face
 hb_font_get_glyph
 hb_font_get_glyph_advance_for_direction
-hb_font_get_glyph_advance_func_t
 hb_font_get_glyph_advances_for_direction
-hb_font_get_glyph_advances_func_t
 hb_font_get_glyph_contour_point
 hb_font_get_glyph_contour_point_for_origin
-hb_font_get_glyph_contour_point_func_t
 hb_font_get_glyph_extents
 hb_font_get_glyph_extents_for_origin
-hb_font_get_glyph_extents_func_t
 hb_font_get_glyph_from_name
-hb_font_get_glyph_from_name_func_t
 hb_font_get_glyph_h_advance
-hb_font_get_glyph_h_advance_func_t
-hb_font_get_glyph_h_advances
-hb_font_get_glyph_h_advances_func_t
-hb_font_get_glyph_h_kerning
-hb_font_get_glyph_h_kerning_func_t
-hb_font_get_glyph_h_origin
-hb_font_get_glyph_h_origin_func_t
-hb_font_get_glyph_kerning_for_direction
-hb_font_get_glyph_kerning_func_t
-hb_font_get_glyph_name
-hb_font_get_glyph_name_func_t
-hb_font_get_glyph_origin_for_direction
-hb_font_get_glyph_origin_func_t
-hb_font_get_glyph_shape
-hb_font_get_glyph_shape_func_t
 hb_font_get_glyph_v_advance
-hb_font_get_glyph_v_advance_func_t
+hb_font_get_glyph_h_advances
 hb_font_get_glyph_v_advances
-hb_font_get_glyph_v_advances_func_t
+hb_font_get_glyph_h_kerning
+hb_font_get_glyph_kerning_for_direction
+hb_font_get_glyph_h_origin
 hb_font_get_glyph_v_origin
-hb_font_get_glyph_v_origin_func_t
+hb_font_get_glyph_origin_for_direction
+hb_font_get_glyph_name
+hb_font_get_glyph_shape
 hb_font_get_nominal_glyph
-hb_font_get_nominal_glyph_func_t
 hb_font_get_nominal_glyphs
-hb_font_get_nominal_glyphs_func_t
-hb_font_get_parent
-hb_font_get_ppem
-hb_font_get_ptem
-hb_font_get_scale
-hb_font_get_synthetic_slant
-hb_font_get_user_data
 hb_font_get_variation_glyph
-hb_font_get_variation_glyph_func_t
+hb_font_set_parent
+hb_font_get_parent
+hb_font_set_ppem
+hb_font_get_ppem
+hb_font_set_ptem
+hb_font_get_ptem
+hb_font_set_scale
+hb_font_get_scale
+hb_font_set_synthetic_slant
+hb_font_get_synthetic_slant
+hb_font_set_variations
+hb_font_set_var_named_instance
+hb_font_set_var_coords_design
 hb_font_get_var_coords_design
+hb_font_set_var_coords_normalized
 hb_font_get_var_coords_normalized
 hb_font_glyph_from_string
 hb_font_glyph_to_string
-hb_font_is_immutable
-hb_font_make_immutable
 hb_font_get_serial
 hb_font_changed
-hb_font_reference
-hb_font_set_face
 hb_font_set_funcs
 hb_font_set_funcs_data
-hb_font_set_parent
-hb_font_set_ppem
-hb_font_set_ptem
-hb_font_set_scale
-hb_font_set_synthetic_slant
-hb_font_set_user_data
-hb_font_set_variations
-hb_font_set_var_coords_design
-hb_font_set_var_coords_normalized
-hb_font_set_var_named_instance
 hb_font_subtract_glyph_origin_for_direction
+hb_font_funcs_create
+hb_font_funcs_get_empty
+hb_font_funcs_reference
+hb_font_funcs_destroy
+hb_font_funcs_set_user_data
+hb_font_funcs_get_user_data
+hb_font_funcs_make_immutable
+hb_font_funcs_is_immutable
+hb_font_get_glyph_contour_point_func_t
+hb_font_funcs_set_glyph_contour_point_func
+hb_font_get_glyph_extents_func_t
+hb_font_funcs_set_glyph_extents_func
+hb_font_get_glyph_from_name_func_t
+hb_font_funcs_set_glyph_from_name_func
+hb_font_get_glyph_advance_func_t
+hb_font_get_glyph_h_advance_func_t
+hb_font_funcs_set_glyph_h_advance_func
+hb_font_get_glyph_v_advance_func_t
+hb_font_funcs_set_glyph_v_advance_func
+hb_font_get_glyph_advances_func_t
+hb_font_get_glyph_h_advances_func_t
+hb_font_funcs_set_glyph_h_advances_func
+hb_font_get_glyph_v_advances_func_t
+hb_font_funcs_set_glyph_v_advances_func
+hb_font_get_glyph_kerning_func_t
+hb_font_get_glyph_h_kerning_func_t
+hb_font_funcs_set_glyph_h_kerning_func
+hb_font_get_glyph_origin_func_t
+hb_font_get_glyph_h_origin_func_t
+hb_font_funcs_set_glyph_h_origin_func
+hb_font_get_glyph_v_origin_func_t
+hb_font_funcs_set_glyph_v_origin_func
+hb_font_get_glyph_name_func_t
+hb_font_funcs_set_glyph_name_func
+hb_font_get_glyph_shape_func_t
+hb_font_funcs_set_glyph_shape_func
+hb_font_get_nominal_glyph_func_t
+hb_font_funcs_set_nominal_glyph_func
+hb_font_get_nominal_glyphs_func_t
+hb_font_funcs_set_nominal_glyphs_func
+hb_font_get_variation_glyph_func_t
+hb_font_funcs_set_variation_glyph_func
+hb_font_funcs_t
 hb_font_t
 hb_reference_table_func_t
-hb_font_funcs_set_font_h_extents_func
-hb_font_funcs_set_font_v_extents_func
-hb_font_get_extents_for_direction
 hb_font_get_font_extents_func_t
 hb_font_get_font_h_extents_func_t
+hb_font_funcs_set_font_h_extents_func
 hb_font_get_font_v_extents_func_t
+hb_font_funcs_set_font_v_extents_func
 hb_font_get_h_extents
 hb_font_get_v_extents
+hb_font_get_extents_for_direction
 hb_font_extents_t
 hb_glyph_extents_t
 </SECTION>
@@ -450,30 +453,29 @@
 
 <SECTION>
 <FILE>hb-map</FILE>
-HB_MAP_VALUE_INVALID
-hb_map_allocation_successful
-hb_map_clear
-hb_map_copy
 hb_map_create
-hb_map_del
-hb_map_destroy
-hb_map_get
+hb_map_allocation_successful
+hb_map_copy
+hb_map_clear
 hb_map_get_empty
-hb_map_get_population
-hb_map_is_equal
-hb_map_get_user_data
-hb_map_has
-hb_map_hash
-hb_map_is_empty
 hb_map_reference
-hb_map_set
+hb_map_destroy
 hb_map_set_user_data
+hb_map_get_user_data
+hb_map_set
+hb_map_get
+hb_map_del
+hb_map_has
+hb_map_get_population
+hb_map_is_empty
+hb_map_is_equal
+hb_map_hash
+HB_MAP_VALUE_INVALID
 hb_map_t
 </SECTION>
 
 <SECTION>
 <FILE>hb-ot-color</FILE>
-hb_color_t
 HB_COLOR
 hb_color_get_alpha
 hb_color_get_blue
@@ -486,13 +488,14 @@
 hb_ot_color_has_palettes
 hb_ot_color_has_png
 hb_ot_color_has_svg
-hb_ot_color_layer_t
 hb_ot_color_palette_color_get_name_id
-hb_ot_color_palette_flags_t
 hb_ot_color_palette_get_colors
 hb_ot_color_palette_get_count
 hb_ot_color_palette_get_flags
 hb_ot_color_palette_get_name_id
+hb_color_t
+hb_ot_color_layer_t
+hb_ot_color_palette_flags_t
 </SECTION>
 
 <SECTION>
@@ -502,35 +505,21 @@
 
 <SECTION>
 <FILE>hb-ot-name</FILE>
-hb_ot_name_id_t
-HB_OT_NAME_ID_INVALID
-hb_ot_name_entry_t
 hb_ot_name_list_names
 hb_ot_name_get_utf16
 hb_ot_name_get_utf32
 hb_ot_name_get_utf8
+HB_OT_NAME_ID_INVALID
+hb_ot_name_id_t
+hb_ot_name_entry_t
 </SECTION>
 
 <SECTION>
 <FILE>hb-ot-layout</FILE>
-HB_OT_MAX_TAGS_PER_LANGUAGE
-HB_OT_MAX_TAGS_PER_SCRIPT
-HB_OT_TAG_DEFAULT_LANGUAGE
-HB_OT_TAG_DEFAULT_SCRIPT
 hb_ot_tag_to_language
 hb_ot_tag_to_script
 hb_ot_tags_from_script_and_language
 hb_ot_tags_to_script_and_language
-HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX
-HB_OT_LAYOUT_NO_FEATURE_INDEX
-HB_OT_LAYOUT_NO_SCRIPT_INDEX
-HB_OT_LAYOUT_NO_VARIATIONS_INDEX
-HB_OT_TAG_BASE
-HB_OT_TAG_GDEF
-HB_OT_TAG_GPOS
-HB_OT_TAG_GSUB
-HB_OT_TAG_JSTF
-hb_ot_layout_baseline_tag_t
 hb_ot_layout_collect_lookups
 hb_ot_layout_collect_features
 hb_ot_layout_feature_get_characters
@@ -545,7 +534,6 @@
 hb_ot_layout_get_glyphs_in_class
 hb_ot_layout_get_ligature_carets
 hb_ot_layout_get_size_params
-hb_ot_layout_glyph_class_t
 hb_ot_layout_has_glyph_classes
 hb_ot_layout_has_positioning
 hb_ot_layout_has_substitution
@@ -569,18 +557,25 @@
 hb_ot_layout_table_select_script
 hb_ot_shape_plan_collect_lookups
 hb_ot_layout_language_get_required_feature_index
+HB_OT_MAX_TAGS_PER_LANGUAGE
+HB_OT_MAX_TAGS_PER_SCRIPT
+HB_OT_TAG_DEFAULT_LANGUAGE
+HB_OT_TAG_DEFAULT_SCRIPT
+HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX
+HB_OT_LAYOUT_NO_FEATURE_INDEX
+HB_OT_LAYOUT_NO_SCRIPT_INDEX
+HB_OT_LAYOUT_NO_VARIATIONS_INDEX
+HB_OT_TAG_BASE
+HB_OT_TAG_GDEF
+HB_OT_TAG_GPOS
+HB_OT_TAG_GSUB
+HB_OT_TAG_JSTF
+hb_ot_layout_baseline_tag_t
+hb_ot_layout_glyph_class_t
 </SECTION>
 
 <SECTION>
 <FILE>hb-ot-math</FILE>
-HB_OT_TAG_MATH
-HB_OT_TAG_MATH_SCRIPT
-hb_ot_math_constant_t
-hb_ot_math_kern_t
-hb_ot_math_kern_entry_t
-hb_ot_math_glyph_variant_t
-hb_ot_math_glyph_part_flags_t
-hb_ot_math_glyph_part_t
 hb_ot_math_has_data
 hb_ot_math_get_constant
 hb_ot_math_get_glyph_italics_correction
@@ -591,23 +586,31 @@
 hb_ot_math_get_glyph_variants
 hb_ot_math_get_min_connector_overlap
 hb_ot_math_get_glyph_assembly
+HB_OT_TAG_MATH
+HB_OT_TAG_MATH_SCRIPT
+hb_ot_math_constant_t
+hb_ot_math_kern_t
+hb_ot_math_kern_entry_t
+hb_ot_math_glyph_variant_t
+hb_ot_math_glyph_part_flags_t
+hb_ot_math_glyph_part_t
 </SECTION>
 
 <SECTION>
 <FILE>hb-ot-meta</FILE>
-hb_ot_meta_tag_t
 hb_ot_meta_get_entry_tags
 hb_ot_meta_reference_entry
+hb_ot_meta_tag_t
 </SECTION>
 
 <SECTION>
 <FILE>hb-ot-metrics</FILE>
-hb_ot_metrics_tag_t
 hb_ot_metrics_get_position
 hb_ot_metrics_get_position_with_fallback
 hb_ot_metrics_get_variation
 hb_ot_metrics_get_x_variation
 hb_ot_metrics_get_y_variation
+hb_ot_metrics_tag_t
 </SECTION>
 
 <SECTION>
@@ -617,14 +620,7 @@
 
 <SECTION>
 <FILE>hb-ot-var</FILE>
-HB_OT_TAG_VAR_AXIS_ITALIC
-HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE
-HB_OT_TAG_VAR_AXIS_SLANT
-HB_OT_TAG_VAR_AXIS_WEIGHT
-HB_OT_TAG_VAR_AXIS_WIDTH
 hb_ot_var_has_data
-hb_ot_var_axis_flags_t
-hb_ot_var_axis_info_t
 hb_ot_var_find_axis_info
 hb_ot_var_get_axis_count
 hb_ot_var_get_axis_infos
@@ -634,31 +630,43 @@
 hb_ot_var_named_instance_get_design_coords
 hb_ot_var_normalize_variations
 hb_ot_var_normalize_coords
+HB_OT_TAG_VAR_AXIS_ITALIC
+HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE
+HB_OT_TAG_VAR_AXIS_SLANT
+HB_OT_TAG_VAR_AXIS_WEIGHT
+HB_OT_TAG_VAR_AXIS_WIDTH
+hb_ot_var_axis_flags_t
+hb_ot_var_axis_info_t
 </SECTION>
 
 <SECTION>
 <FILE>hb-set</FILE>
-HB_SET_VALUE_INVALID
+hb_set_create
+hb_set_allocation_successful
+hb_set_copy
+hb_set_get_empty
+hb_set_reference
+hb_set_destroy
+hb_set_set_user_data
+hb_set_get_user_data
+hb_set_clear
+hb_set_set
+hb_set_has
 hb_set_add
 hb_set_add_range
 hb_set_add_sorted_array
-hb_set_allocation_successful
-hb_set_copy
-hb_set_clear
-hb_set_create
 hb_set_del
 hb_set_del_range
-hb_set_destroy
-hb_set_get_empty
 hb_set_get_max
 hb_set_get_min
 hb_set_get_population
-hb_set_get_user_data
-hb_set_has
-hb_set_hash
-hb_set_intersect
-hb_set_invert
 hb_set_is_empty
+hb_set_hash
+hb_set_subtract
+hb_set_intersect
+hb_set_union
+hb_set_symmetric_difference
+hb_set_invert
 hb_set_is_equal
 hb_set_is_subset
 hb_set_next
@@ -666,13 +674,8 @@
 hb_set_next_many
 hb_set_previous
 hb_set_previous_range
-hb_set_reference
-hb_set_set
-hb_set_set_user_data
-hb_set_subtract
-hb_set_symmetric_difference
+HB_SET_VALUE_INVALID
 hb_set_t
-hb_set_union
 </SECTION>
 
 <SECTION>
@@ -688,50 +691,50 @@
 hb_shape_plan_create_cached
 hb_shape_plan_create2
 hb_shape_plan_create_cached2
-hb_shape_plan_destroy
-hb_shape_plan_execute
 hb_shape_plan_get_empty
-hb_shape_plan_get_shaper
-hb_shape_plan_get_user_data
 hb_shape_plan_reference
+hb_shape_plan_destroy
 hb_shape_plan_set_user_data
+hb_shape_plan_get_user_data
+hb_shape_plan_execute
+hb_shape_plan_get_shaper
 hb_shape_plan_t
 </SECTION>
 
 <SECTION>
 <FILE>hb-unicode</FILE>
-HB_UNICODE_MAX
-hb_unicode_combining_class
-hb_unicode_combining_class_func_t
-hb_unicode_combining_class_t
-hb_unicode_compose
-hb_unicode_compose_func_t
-hb_unicode_decompose
-hb_unicode_decompose_func_t
-hb_unicode_funcs_create
-hb_unicode_funcs_destroy
-hb_unicode_funcs_get_default
-hb_unicode_funcs_get_empty
-hb_unicode_funcs_get_parent
-hb_unicode_funcs_get_user_data
-hb_unicode_funcs_is_immutable
-hb_unicode_funcs_make_immutable
-hb_unicode_funcs_reference
-hb_unicode_funcs_set_combining_class_func
-hb_unicode_funcs_set_compose_func
-hb_unicode_funcs_set_decompose_func
-hb_unicode_funcs_set_general_category_func
-hb_unicode_funcs_set_mirroring_func
-hb_unicode_funcs_set_script_func
-hb_unicode_funcs_set_user_data
-hb_unicode_funcs_t
 hb_unicode_general_category
-hb_unicode_general_category_func_t
-hb_unicode_general_category_t
+hb_unicode_combining_class
 hb_unicode_mirroring
-hb_unicode_mirroring_func_t
 hb_unicode_script
+hb_unicode_compose
+hb_unicode_decompose
+hb_unicode_funcs_create
+hb_unicode_funcs_get_empty
+hb_unicode_funcs_reference
+hb_unicode_funcs_destroy
+hb_unicode_funcs_set_user_data
+hb_unicode_funcs_get_user_data
+hb_unicode_funcs_make_immutable
+hb_unicode_funcs_is_immutable
+hb_unicode_funcs_get_default
+hb_unicode_funcs_get_parent
+hb_unicode_general_category_func_t
+hb_unicode_funcs_set_general_category_func
+hb_unicode_combining_class_func_t
+hb_unicode_funcs_set_combining_class_func
+hb_unicode_mirroring_func_t
+hb_unicode_funcs_set_mirroring_func
 hb_unicode_script_func_t
+hb_unicode_funcs_set_script_func
+hb_unicode_compose_func_t
+hb_unicode_funcs_set_compose_func
+hb_unicode_decompose_func_t
+hb_unicode_funcs_set_decompose_func
+HB_UNICODE_MAX
+hb_unicode_combining_class_t
+hb_unicode_general_category_t
+hb_unicode_funcs_t
 </SECTION>
 
 <SECTION>
@@ -743,13 +746,13 @@
 <SECTION>
 <FILE>hb-version</FILE>
 HB_VERSION_ATLEAST
+hb_version
+hb_version_atleast
+hb_version_string
 HB_VERSION_MAJOR
 HB_VERSION_MICRO
 HB_VERSION_MINOR
 HB_VERSION_STRING
-hb_version
-hb_version_atleast
-hb_version_string
 </SECTION>
 
 <SECTION>
@@ -760,20 +763,18 @@
 
 <SECTION>
 <FILE>hb-subset</FILE>
-hb_subset_flags_t
-hb_subset_input_t
-hb_subset_sets_t
-hb_subset_plan_t
 hb_subset_input_create_or_fail
 hb_subset_input_reference
 hb_subset_input_destroy
 hb_subset_input_set_user_data
 hb_subset_input_get_user_data
-hb_subset_input_get_flags
 hb_subset_input_set_flags
+hb_subset_input_get_flags
 hb_subset_input_unicode_set
 hb_subset_input_glyph_set
 hb_subset_input_set
+hb_subset_input_pin_axis_location
+hb_subset_input_pin_axis_to_default
 hb_subset_or_fail
 hb_subset_plan_create_or_fail
 hb_subset_plan_reference
@@ -784,11 +785,14 @@
 hb_subset_plan_unicode_to_old_glyph_mapping
 hb_subset_plan_new_to_old_glyph_mapping
 hb_subset_plan_old_to_new_glyph_mapping
+hb_subset_preprocess
+hb_subset_flags_t
+hb_subset_input_t
+hb_subset_sets_t
+hb_subset_plan_t
 <SUBSECTION Private>
 hb_link_t
 hb_object_t
 hb_subset_repack_or_fail
-hb_subset_preprocess
-hb_subset_input_pin_axis_location
-hb_subset_input_pin_axis_to_default
+hb_subset_input_override_name_table
 </SECTION>
diff --git a/docs/subset-preprocessing.md b/docs/subset-preprocessing.md
new file mode 100644
index 0000000..637da28
--- /dev/null
+++ b/docs/subset-preprocessing.md
@@ -0,0 +1,228 @@
+# Introduction
+
+Subset preprocessing is a mechanism which can significantly speed up font subsetting operations.
+It works by prepopulating datastructures from the source font which can be used in later subsetting
+operations to more quickly produce the subset. Preprocessing is useful in cases where multiple subsets
+will be cut from the same source font.
+
+# Usage
+
+```c++
+hb_face_t* preprocessed = hb_subset_preprocess (source_face);
+
+...
+
+hb_face_t* subset = hb_subset_or_fail (preprocessed, subset_input);
+```
+
+# Additional Details
+
+*  A subset produced from a preprocessed face should be identical to a subset produced from only the
+   original face. The preprocessor does not change the functionality of the subsetter, just speeds
+   things up.
+
+*  The preprocessing operation may take longer than the time it takes to produce a subset from the
+   source font. Thus the main performance gains are made when a preprocessed face is reused for
+   multiple subsetting operations.
+
+*  Currently the largest performance gains are seen when using a preprocessed face for CFF subsetting.
+
+*  The preprocessed face may contain references to the memory backing the source face. If this memory
+   is fully owned by a harfbuzz hb_blob_t* then it will automatically be kept alive for the lifetime
+   of the preprocessed face. However, if this memory is not fully owned by a harfbuzz hb_blob_t* then
+   it is necessary to ensure that the memory is kept alive for the lifetime of the preprocessed face.
+
+
+# Performance Improvements
+
+Here is the performance difference of producing a subset with a preprocessed face vs producing
+a subset with the source face:
+
+Benchmark | Delta Time (%)
+----------|-----------------
+BM_subset/subset_glyphs/Roboto-Regular.ttf/10_median|-56%
+BM_subset/subset_glyphs/Roboto-Regular.ttf/64_median|-33%
+BM_subset/subset_glyphs/Roboto-Regular.ttf/512_median|-28%
+BM_subset/subset_glyphs/Roboto-Regular.ttf/1000_median|-11%
+BM_subset/subset_glyphs/Roboto-Regular.ttf/nohinting/10_median|-56%
+BM_subset/subset_glyphs/Roboto-Regular.ttf/nohinting/64_median|-33%
+BM_subset/subset_glyphs/Roboto-Regular.ttf/nohinting/512_median|-21%
+BM_subset/subset_glyphs/Roboto-Regular.ttf/nohinting/1000_median|-9%
+BM_subset/subset_glyphs/Amiri-Regular.ttf/10_median|-67%
+BM_subset/subset_glyphs/Amiri-Regular.ttf/64_median|-48%
+BM_subset/subset_glyphs/Amiri-Regular.ttf/512_median|-21%
+BM_subset/subset_glyphs/Amiri-Regular.ttf/4096_median|-9%
+BM_subset/subset_glyphs/Amiri-Regular.ttf/nohinting/10_median|-66%
+BM_subset/subset_glyphs/Amiri-Regular.ttf/nohinting/64_median|-50%
+BM_subset/subset_glyphs/Amiri-Regular.ttf/nohinting/512_median|-8%
+BM_subset/subset_glyphs/Amiri-Regular.ttf/nohinting/4096_median|-9%
+BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/10_median|-85%
+BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/64_median|-71%
+BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/512_median|-3%
+BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/1400_median|4%
+BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/nohinting/10_median|-84%
+BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/nohinting/64_median|-72%
+BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/nohinting/512_median|0%
+BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/nohinting/1400_median|0%
+BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/10_median|-30%
+BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/64_median|-24%
+BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/512_median|-3%
+BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/1000_median|-3%
+BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/nohinting/10_median|-30%
+BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/nohinting/64_median|-24%
+BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/nohinting/512_median|-3%
+BM_subset/subset_glyphs/NotoSansDevanagari-Regular.ttf/nohinting/1000_median|-5%
+BM_subset/subset_glyphs/Mplus1p-Regular.ttf/10_median|-96%
+BM_subset/subset_glyphs/Mplus1p-Regular.ttf/64_median|-90%
+BM_subset/subset_glyphs/Mplus1p-Regular.ttf/512_median|-74%
+BM_subset/subset_glyphs/Mplus1p-Regular.ttf/4096_median|-25%
+BM_subset/subset_glyphs/Mplus1p-Regular.ttf/10000_median|-23%
+BM_subset/subset_glyphs/Mplus1p-Regular.ttf/nohinting/10_median|-95%
+BM_subset/subset_glyphs/Mplus1p-Regular.ttf/nohinting/64_median|-90%
+BM_subset/subset_glyphs/Mplus1p-Regular.ttf/nohinting/512_median|-73%
+BM_subset/subset_glyphs/Mplus1p-Regular.ttf/nohinting/4096_median|-24%
+BM_subset/subset_glyphs/Mplus1p-Regular.ttf/nohinting/10000_median|-11%
+BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/10_median|-84%
+BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/64_median|-77%
+BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/512_median|-70%
+BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/4096_median|-80%
+BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/10000_median|-86%
+BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/nohinting/10_median|-84%
+BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/nohinting/64_median|-78%
+BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/nohinting/512_median|-71%
+BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/nohinting/4096_median|-86%
+BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/nohinting/10000_median|-88%
+BM_subset/subset_glyphs/SourceSansPro-Regular.otf/10_median|-59%
+BM_subset/subset_glyphs/SourceSansPro-Regular.otf/64_median|-55%
+BM_subset/subset_glyphs/SourceSansPro-Regular.otf/512_median|-67%
+BM_subset/subset_glyphs/SourceSansPro-Regular.otf/2000_median|-68%
+BM_subset/subset_glyphs/SourceSansPro-Regular.otf/nohinting/10_median|-60%
+BM_subset/subset_glyphs/SourceSansPro-Regular.otf/nohinting/64_median|-58%
+BM_subset/subset_glyphs/SourceSansPro-Regular.otf/nohinting/512_median|-72%
+BM_subset/subset_glyphs/SourceSansPro-Regular.otf/nohinting/2000_median|-71%
+BM_subset/subset_glyphs/AdobeVFPrototype.otf/10_median|-70%
+BM_subset/subset_glyphs/AdobeVFPrototype.otf/64_median|-64%
+BM_subset/subset_glyphs/AdobeVFPrototype.otf/300_median|-73%
+BM_subset/subset_glyphs/AdobeVFPrototype.otf/nohinting/10_median|-71%
+BM_subset/subset_glyphs/AdobeVFPrototype.otf/nohinting/64_median|-68%
+BM_subset/subset_glyphs/AdobeVFPrototype.otf/nohinting/300_median|-72%
+BM_subset/subset_glyphs/MPLUS1-Variable.ttf/10_median|-90%
+BM_subset/subset_glyphs/MPLUS1-Variable.ttf/64_median|-82%
+BM_subset/subset_glyphs/MPLUS1-Variable.ttf/512_median|-31%
+BM_subset/subset_glyphs/MPLUS1-Variable.ttf/4096_median|-9%
+BM_subset/subset_glyphs/MPLUS1-Variable.ttf/6000_median|-22%
+BM_subset/subset_glyphs/MPLUS1-Variable.ttf/nohinting/10_median|-88%
+BM_subset/subset_glyphs/MPLUS1-Variable.ttf/nohinting/64_median|-83%
+BM_subset/subset_glyphs/MPLUS1-Variable.ttf/nohinting/512_median|-31%
+BM_subset/subset_glyphs/MPLUS1-Variable.ttf/nohinting/4096_median|-16%
+BM_subset/subset_glyphs/MPLUS1-Variable.ttf/nohinting/6000_median|-18%
+BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/10_median|-44%
+BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/64_median|-18%
+BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/512_median|-2%
+BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/900_median|-6%
+BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/nohinting/10_median|-45%
+BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/nohinting/64_median|-17%
+BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/nohinting/512_median|-15%
+BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/nohinting/900_median|-3%
+BM_subset/subset_codepoints/Roboto-Regular.ttf/10_median|-20%
+BM_subset/subset_codepoints/Roboto-Regular.ttf/64_median|-16%
+BM_subset/subset_codepoints/Roboto-Regular.ttf/512_median|-12%
+BM_subset/subset_codepoints/Roboto-Regular.ttf/1000_median|-10%
+BM_subset/subset_codepoints/Roboto-Regular.ttf/nohinting/10_median|-24%
+BM_subset/subset_codepoints/Roboto-Regular.ttf/nohinting/64_median|-14%
+BM_subset/subset_codepoints/Roboto-Regular.ttf/nohinting/512_median|-15%
+BM_subset/subset_codepoints/Roboto-Regular.ttf/nohinting/1000_median|-9%
+BM_subset/subset_codepoints/Amiri-Regular.ttf/10_median|-51%
+BM_subset/subset_codepoints/Amiri-Regular.ttf/64_median|-37%
+BM_subset/subset_codepoints/Amiri-Regular.ttf/512_median|-12%
+BM_subset/subset_codepoints/Amiri-Regular.ttf/4096_median|-1%
+BM_subset/subset_codepoints/Amiri-Regular.ttf/nohinting/10_median|-49%
+BM_subset/subset_codepoints/Amiri-Regular.ttf/nohinting/64_median|-35%
+BM_subset/subset_codepoints/Amiri-Regular.ttf/nohinting/512_median|-6%
+BM_subset/subset_codepoints/Amiri-Regular.ttf/nohinting/4096_median|-1%
+BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/10_median|-82%
+BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/64_median|-9%
+BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/512_median|0%
+BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/1400_median|0%
+BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/nohinting/10_median|-82%
+BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/nohinting/64_median|-13%
+BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/nohinting/512_median|-3%
+BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/nohinting/1400_median|2%
+BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/10_median|-40%
+BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/64_median|-26%
+BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/512_median|-5%
+BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/1000_median|3%
+BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/nohinting/10_median|-43%
+BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/nohinting/64_median|-24%
+BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/nohinting/512_median|-2%
+BM_subset/subset_codepoints/NotoSansDevanagari-Regular.ttf/nohinting/1000_median|2%
+BM_subset/subset_codepoints/Mplus1p-Regular.ttf/10_median|-83%
+BM_subset/subset_codepoints/Mplus1p-Regular.ttf/64_median|-67%
+BM_subset/subset_codepoints/Mplus1p-Regular.ttf/512_median|-39%
+BM_subset/subset_codepoints/Mplus1p-Regular.ttf/4096_median|-20%
+BM_subset/subset_codepoints/Mplus1p-Regular.ttf/10000_median|-25%
+BM_subset/subset_codepoints/Mplus1p-Regular.ttf/nohinting/10_median|-83%
+BM_subset/subset_codepoints/Mplus1p-Regular.ttf/nohinting/64_median|-65%
+BM_subset/subset_codepoints/Mplus1p-Regular.ttf/nohinting/512_median|-42%
+BM_subset/subset_codepoints/Mplus1p-Regular.ttf/nohinting/4096_median|-34%
+BM_subset/subset_codepoints/Mplus1p-Regular.ttf/nohinting/10000_median|-21%
+BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/10_median|-69%
+BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/64_median|-69%
+BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/512_median|-70%
+BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/4096_median|-84%
+BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/10000_median|-83%
+BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/nohinting/10_median|-71%
+BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/nohinting/64_median|-68%
+BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/nohinting/512_median|-70%
+BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/nohinting/4096_median|-86%
+BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/nohinting/10000_median|-88%
+BM_subset/subset_codepoints/SourceSansPro-Regular.otf/10_median|-45%
+BM_subset/subset_codepoints/SourceSansPro-Regular.otf/64_median|-48%
+BM_subset/subset_codepoints/SourceSansPro-Regular.otf/512_median|-57%
+BM_subset/subset_codepoints/SourceSansPro-Regular.otf/2000_median|-66%
+BM_subset/subset_codepoints/SourceSansPro-Regular.otf/nohinting/10_median|-43%
+BM_subset/subset_codepoints/SourceSansPro-Regular.otf/nohinting/64_median|-50%
+BM_subset/subset_codepoints/SourceSansPro-Regular.otf/nohinting/512_median|-63%
+BM_subset/subset_codepoints/SourceSansPro-Regular.otf/nohinting/2000_median|-72%
+BM_subset/subset_codepoints/AdobeVFPrototype.otf/10_median|-69%
+BM_subset/subset_codepoints/AdobeVFPrototype.otf/64_median|-66%
+BM_subset/subset_codepoints/AdobeVFPrototype.otf/300_median|-74%
+BM_subset/subset_codepoints/AdobeVFPrototype.otf/nohinting/10_median|-70%
+BM_subset/subset_codepoints/AdobeVFPrototype.otf/nohinting/64_median|-71%
+BM_subset/subset_codepoints/AdobeVFPrototype.otf/nohinting/300_median|-75%
+BM_subset/subset_codepoints/MPLUS1-Variable.ttf/10_median|-66%
+BM_subset/subset_codepoints/MPLUS1-Variable.ttf/64_median|-46%
+BM_subset/subset_codepoints/MPLUS1-Variable.ttf/512_median|-15%
+BM_subset/subset_codepoints/MPLUS1-Variable.ttf/4096_median|-5%
+BM_subset/subset_codepoints/MPLUS1-Variable.ttf/6000_median|-16%
+BM_subset/subset_codepoints/MPLUS1-Variable.ttf/nohinting/10_median|-66%
+BM_subset/subset_codepoints/MPLUS1-Variable.ttf/nohinting/64_median|-45%
+BM_subset/subset_codepoints/MPLUS1-Variable.ttf/nohinting/512_median|-14%
+BM_subset/subset_codepoints/MPLUS1-Variable.ttf/nohinting/4096_median|-11%
+BM_subset/subset_codepoints/MPLUS1-Variable.ttf/nohinting/6000_median|-27%
+BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/10_median|-38%
+BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/64_median|-9%
+BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/512_median|-3%
+BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/900_median|-16%
+BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/nohinting/10_median|-39%
+BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/nohinting/64_median|-12%
+BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/nohinting/512_median|-4%
+BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/nohinting/900_median|-2%
+BM_subset/instance/MPLUS1-Variable.ttf/10_median|-68%
+BM_subset/instance/MPLUS1-Variable.ttf/64_median|-45%
+BM_subset/instance/MPLUS1-Variable.ttf/512_median|-18%
+BM_subset/instance/MPLUS1-Variable.ttf/4096_median|-2%
+BM_subset/instance/MPLUS1-Variable.ttf/6000_median|4%
+BM_subset/instance/MPLUS1-Variable.ttf/nohinting/10_median|-69%
+BM_subset/instance/MPLUS1-Variable.ttf/nohinting/64_median|-46%
+BM_subset/instance/MPLUS1-Variable.ttf/nohinting/512_median|-11%
+BM_subset/instance/MPLUS1-Variable.ttf/nohinting/4096_median|4%
+BM_subset/instance/MPLUS1-Variable.ttf/nohinting/6000_median|-5%
+BM_subset/instance/RobotoFlex-Variable.ttf/10_median|-34%
+BM_subset/instance/RobotoFlex-Variable.ttf/64_median|-12%
+BM_subset/instance/RobotoFlex-Variable.ttf/512_median|6%
+BM_subset/instance/RobotoFlex-Variable.ttf/900_median|-6%
+BM_subset/instance/RobotoFlex-Variable.ttf/nohinting/10_median|-33%
+BM_subset/instance/RobotoFlex-Variable.ttf/nohinting/64_median|-11%
+BM_subset/instance/RobotoFlex-Variable.ttf/nohinting/512_median|3%
+BM_subset/instance/RobotoFlex-Variable.ttf/nohinting/900_median|0%
diff --git a/generate_notice.py b/generate_notice.py
index 354dc3d..fab61cb 100644
--- a/generate_notice.py
+++ b/generate_notice.py
@@ -58,6 +58,7 @@
   ".codecov.yml",
   ".editorconfig",
   ".github/dependabot.yml",
+  ".github/workflows/arm-ci.yml",
   ".github/workflows/cifuzz.yml",
   ".github/workflows/configs-build.yml",
   ".github/workflows/coverity-scan.yml",
@@ -94,6 +95,7 @@
   "docs/meson.build",
   "docs/repacker.md",
   "docs/serializer.md",
+  "docs/subset-preprocessing.md",
   "docs/usermanual-buffers-language-script-and-direction.xml",
   "docs/usermanual-clusters.xml",
   "docs/usermanual-fonts-and-faces.xml",
@@ -175,6 +177,9 @@
   "src/OT/glyf/GlyphHeader.hh",
   "src/OT/glyf/SimpleGlyph.hh",
   "src/OT/glyf/SubsetGlyph.hh",
+  "src/OT/glyf/VarCompositeGlyph.hh",
+  "src/OT/glyf/composite-iter.hh",
+  "src/OT/glyf/coord-setter.hh",
   "src/OT/glyf/glyf-helpers.hh",
   "src/OT/glyf/glyf.hh",
   "src/OT/glyf/loca.hh",
@@ -231,6 +236,7 @@
   "subprojects/google-benchmark.wrap",
   "subprojects/packagefiles/ragel/meson.build",
   "subprojects/ragel.wrap",
+  "subprojects/zlib.wrap",
   "util/Makefile.am",
   "util/Makefile.sources",
   "util/meson.build",
diff --git a/meson.build b/meson.build
index b80679d..cc802f2 100644
--- a/meson.build
+++ b/meson.build
@@ -1,6 +1,6 @@
 project('harfbuzz', 'c', 'cpp',
   meson_version: '>= 0.55.0',
-  version: '5.3.1',
+  version: '6.0.0',
   default_options: [
     'cpp_rtti=false',       # Just to support msvc, we are passing -fno-exceptions also anyway
     'cpp_std=c++11',
@@ -83,20 +83,35 @@
 
 m_dep = cpp.find_library('m', required: false)
 
-
-# Try pkgconfig name
-freetype_dep = dependency('freetype2', required: false)
-if not freetype_dep.found()
-  # Try cmake name
-  freetype_dep = dependency('freetype', required: false)
-endif
-if not freetype_dep.found()
-  # Subproject fallback, `allow_fallback: true` means the fallback will be
-  # tried even if the freetype option is set to `auto`.
-  freetype_dep = dependency('freetype2',
+if meson.version().version_compare('>=0.60.0')
+  # pkg-config: freetype2, cmake: Freetype
+  freetype_dep = dependency('freetype2', 'Freetype',
                             required: get_option('freetype'),
                             default_options: ['harfbuzz=disabled'],
                             allow_fallback: true)
+else
+  # painful hack to handle multiple dependencies but also respect options
+  freetype_opt = get_option('freetype')
+  # we want to handle enabled manually after fallbacks, but also handle disabled normally
+  if freetype_opt.enabled()
+    freetype_opt = false
+  endif
+  # try pkg-config name
+  freetype_dep = dependency('freetype2', method: 'pkg-config', required: freetype_opt)
+  # when disabled, leave it not-found
+  if not freetype_dep.found() and not get_option('freetype').disabled()
+    # Try cmake name
+    freetype_dep = dependency('Freetype', method: 'cmake', required: false)
+    # Subproject fallback, `allow_fallback: true` means the fallback will be
+    # tried even if the freetype option is set to `auto`.
+    if not freetype_dep.found()
+      freetype_dep = dependency('freetype2',
+                                method: 'pkg-config',
+                                required: get_option('freetype'),
+                                default_options: ['harfbuzz=disabled'],
+                                allow_fallback: true)
+    endif
+  endif
 endif
 
 glib_dep = dependency('glib-2.0', required: get_option('glib'))
@@ -104,18 +119,36 @@
 graphite2_dep = dependency('graphite2', required: get_option('graphite2'))
 graphite_dep = dependency('graphite2', required: get_option('graphite'))
 
-# Try pkgconfig name
-icu_dep = dependency('icu-uc', required: false)
-if not icu_dep.found()
-  # Try cmake name
-  icu_dep = dependency('ICU',
-                       required: false,
-                       components: 'uc',
-                       method: 'cmake')
-endif
-if not icu_dep.found()
-  # Subproject fallback if icu option is enabled
-  icu_dep = dependency('icu-uc', required: get_option('icu'))
+if meson.version().version_compare('>=0.60.0')
+  # pkg-config: icu-uc, cmake: ICU but with components
+  icu_dep = dependency('icu-uc', 'ICU',
+                            components: 'uc',
+                            required: get_option('icu'),
+                            default_options: ['harfbuzz=disabled'],
+                            allow_fallback: true)
+else
+  # painful hack to handle multiple dependencies but also respect options
+  icu_opt = get_option('icu')
+  # we want to handle enabled manually after fallbacks, but also handle disabled normally
+  if icu_opt.enabled()
+    icu_opt = false
+  endif
+  # try pkg-config name
+  icu_dep = dependency('icu-uc', method: 'pkg-config', required: icu_opt)
+  # when disabled, leave it not-found
+  if not icu_dep.found() and not get_option('icu').disabled()
+    # Try cmake name
+    icu_dep = dependency('ICU', method: 'cmake', components: 'uc', required: false)
+    # Try again with subproject fallback. `allow_fallback: true` means the
+    # fallback will be tried even if the icu option is set to `auto`, but
+    # we cannot pass this option until Meson 0.59.0, because no wrap file
+    # is checked into git.
+    if not icu_dep.found()
+      icu_dep = dependency('icu-uc',
+                           method: 'pkg-config',
+                           required: get_option('icu'))
+    endif
+  endif
 endif
 
 if icu_dep.found() and icu_dep.type_name() == 'pkgconfig'
@@ -148,7 +181,8 @@
     # harfbuzz support disabled, so when cairo will lookup freetype2 dependency
     # it will be forced to use that one.
     cairo_dep = dependency('cairo', required: get_option('cairo'))
-    cairo_ft_dep = dependency('cairo-ft', required: get_option('cairo'))
+    cairo_ft_required = get_option('cairo').enabled() and get_option('freetype').enabled()
+    cairo_ft_dep = dependency('cairo-ft', required: cairo_ft_required)
   endif
 endif
 
diff --git a/perf/benchmark-shape.cc b/perf/benchmark-shape.cc
index 626a597..f44b3e5 100644
--- a/perf/benchmark-shape.cc
+++ b/perf/benchmark-shape.cc
@@ -27,10 +27,18 @@
    "perf/texts/fa-thelittleprince.txt",
    false},
 
+  {"perf/fonts/NotoNastaliqUrdu-Regular.ttf",
+   "perf/texts/fa-words.txt",
+   false},
+
   {"perf/fonts/Amiri-Regular.ttf",
    "perf/texts/fa-thelittleprince.txt",
    false},
 
+  {SUBSET_FONT_BASE_PATH "NotoSansDevanagari-Regular.ttf",
+   "perf/texts/hi-words.txt",
+   false},
+
   {"perf/fonts/Roboto-Regular.ttf",
    "perf/texts/en-thelittleprince.txt",
    false},
diff --git a/perf/benchmark-subset.cc b/perf/benchmark-subset.cc
index 0451c11..9b51b79 100644
--- a/perf/benchmark-subset.cc
+++ b/perf/benchmark-subset.cc
@@ -54,18 +54,19 @@
 struct test_input_t
 {
   const char *font_path;
-  const unsigned max_subset_size;
+  unsigned max_subset_size;
   const axis_location_t *instance_opts;
-  const unsigned num_instance_opts;
-} tests[] =
+  unsigned num_instance_opts;
+} default_tests[] =
 {
-  {SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf", 4000, nullptr, 0},
-  {SUBSET_FONT_BASE_PATH "Amiri-Regular.ttf", 4000, nullptr, 0},
-  {SUBSET_FONT_BASE_PATH "NotoNastaliqUrdu-Regular.ttf", 1000, nullptr, 0},
+  {SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf", 1000, nullptr, 0},
+  {SUBSET_FONT_BASE_PATH "Amiri-Regular.ttf", 4096, nullptr, 0},
+  {SUBSET_FONT_BASE_PATH "NotoNastaliqUrdu-Regular.ttf", 1400, nullptr, 0},
   {SUBSET_FONT_BASE_PATH "NotoSansDevanagari-Regular.ttf", 1000, nullptr, 0},
   {SUBSET_FONT_BASE_PATH "Mplus1p-Regular.ttf", 10000, nullptr, 0},
   {SUBSET_FONT_BASE_PATH "SourceHanSans-Regular_subset.otf", 10000, nullptr, 0},
   {SUBSET_FONT_BASE_PATH "SourceSansPro-Regular.otf", 2000, nullptr, 0},
+  {SUBSET_FONT_BASE_PATH "AdobeVFPrototype.otf", 300, nullptr, 0},
   {SUBSET_FONT_BASE_PATH "MPLUS1-Variable.ttf", 6000, _mplus_instance_opts, ARRAY_LEN (_mplus_instance_opts)},
   {SUBSET_FONT_BASE_PATH "RobotoFlex-Variable.ttf", 900, _roboto_flex_instance_opts, ARRAY_LEN (_roboto_flex_instance_opts)},
 #if 0
@@ -73,6 +74,10 @@
 #endif
 };
 
+static test_input_t *tests = default_tests;
+static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
+
+
 void AddCodepoints(const hb_set_t* codepoints_in_font,
                    unsigned subset_size,
                    hb_subset_input_t* input)
@@ -101,23 +106,25 @@
 // the subsetting operations.
 static hb_face_t* preprocess_face(hb_face_t* face)
 {
-  #ifdef HB_EXPERIMENTAL_API
   hb_face_t* new_face = hb_subset_preprocess(face);
   hb_face_destroy(face);
   return new_face;
-  #else
-  return face;
-  #endif
 }
 
 /* benchmark for subsetting a font */
 static void BM_subset (benchmark::State &state,
                        operation_t operation,
-                       const test_input_t &test_input)
+                       const test_input_t &test_input,
+                       bool hinting)
 {
   unsigned subset_size = state.range(0);
 
-  hb_face_t *face;
+  hb_face_t *face = nullptr;
+
+  static hb_face_t *cached_face;
+  static const char *cached_font_path;
+
+  if (!cached_font_path || strcmp (cached_font_path, test_input.font_path))
   {
     hb_blob_t *blob = hb_blob_create_from_file_or_fail (test_input.font_path);
     assert (blob);
@@ -125,11 +132,22 @@
     hb_blob_destroy (blob);
 
     face = preprocess_face (face);
+
+    if (cached_face)
+      hb_face_destroy (cached_face);
+
+    cached_face = hb_face_reference (face);
+    cached_font_path = test_input.font_path;
   }
+  else
+    face = hb_face_reference (cached_face);
 
   hb_subset_input_t* input = hb_subset_input_create_or_fail ();
   assert (input);
 
+  if (!hinting)
+    hb_subset_input_set_flags (input, HB_SUBSET_FLAGS_NO_HINTING);
+
   switch (operation)
   {
     case subset_codepoints:
@@ -149,7 +167,6 @@
     break;
 
     case instance:
-#ifdef HB_EXPERIMENTAL_API
     {
       hb_set_t* all_codepoints = hb_set_create ();
       hb_face_collect_unicodes (face, all_codepoints);
@@ -161,7 +178,6 @@
                                            test_input.instance_opts[i].axis_tag,
                                            test_input.instance_opts[i].axis_value);
     }
-#endif
     break;
   }
 
@@ -178,6 +194,7 @@
 
 static void test_subset (operation_t op,
                          const char *op_name,
+                         bool hinting,
                          benchmark::TimeUnit time_unit,
                          const test_input_t &test_input)
 {
@@ -186,36 +203,57 @@
 
   char name[1024] = "BM_subset/";
   strcat (name, op_name);
-  strcat (name, strrchr (test_input.font_path, '/'));
+  strcat (name, "/");
+  const char *p = strrchr (test_input.font_path, '/');
+  strcat (name, p ? p + 1 : test_input.font_path);
+  if (!hinting)
+    strcat (name, "/nohinting");
 
-  benchmark::RegisterBenchmark (name, BM_subset, op, test_input)
+  benchmark::RegisterBenchmark (name, BM_subset, op, test_input, hinting)
       ->Range(10, test_input.max_subset_size)
       ->Unit(time_unit);
 }
 
 static void test_operation (operation_t op,
                             const char *op_name,
+                            const test_input_t *tests,
+                            unsigned num_tests,
                             benchmark::TimeUnit time_unit)
 {
-  for (auto& test_input : tests)
+  for (unsigned i = 0; i < num_tests; i++)
   {
-      test_subset (op, op_name, time_unit, test_input);
+    auto& test_input = tests[i];
+    test_subset (op, op_name, true, time_unit, test_input);
+    test_subset (op, op_name, false, time_unit, test_input);
   }
 }
 
 int main(int argc, char** argv)
 {
-#define TEST_OPERATION(op, time_unit) test_operation (op, #op, time_unit)
+  benchmark::Initialize(&argc, argv);
+
+  if (argc > 1)
+  {
+    num_tests = (argc - 1) / 2;
+    tests = (test_input_t *) calloc (num_tests, sizeof (test_input_t));
+    for (unsigned i = 0; i < num_tests; i++)
+    {
+      tests[i].font_path = argv[1 + i * 2];
+      tests[i].max_subset_size = atoi (argv[2 + i * 2]);
+    }
+  }
+
+#define TEST_OPERATION(op, time_unit) test_operation (op, #op, tests, num_tests, time_unit)
 
   TEST_OPERATION (subset_glyphs, benchmark::kMillisecond);
   TEST_OPERATION (subset_codepoints, benchmark::kMillisecond);
-#ifdef HB_EXPERIMENTAL_API
   TEST_OPERATION (instance, benchmark::kMillisecond);
-#endif
 
 #undef TEST_OPERATION
 
-  benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
   benchmark::Shutdown();
+
+  if (tests != default_tests)
+    free (tests);
 }
diff --git a/perf/run.sh b/perf/run.sh
deleted file mode 100755
index c7dc6e0..0000000
--- a/perf/run.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-CXX=clang++
-FONT=fonts/NotoNastaliqUrdu-Regular.ttf
-TEXT=texts/fa-monologue.txt
-
-$CXX ../util/hb-shape.cc ../util/options.cc ../src/harfbuzz.cc \
-  -lm -fno-rtti -fno-exceptions -fno-omit-frame-pointer -DHB_NO_MT \
-  -I../src $FLAGS $SOURCES \
-  -DPACKAGE_NAME='""' -DPACKAGE_VERSION='""' \
-  -DHAVE_GLIB $(pkg-config --cflags --libs glib-2.0) \
-  -o hb-shape -g -O2 # -O3 \
-  #-march=native -mtune=native \
-  #-Rpass=loop-vectorize -Rpass-missed=loop-vectorize \
-  #-Rpass-analysis=loop-vectorize -fsave-optimization-record
-
-# -march=native: enable all vector instructions current CPU can offer
-# -Rpass*: https://llvm.org/docs/Vectorizers.html#diagnostics
-
-#sudo rm capture.syscap > /dev/null
-#sysprof-cli -c "./a.out $@"
-#sysprof capture.syscap
-
-perf stat ./hb-shape -o /dev/null $FONT --text-file $TEXT --num-iterations=100 --font-funcs=ot
-#perf record -g ./hb-shape -O '' -o /dev/null $FONT --text-file $TEXT --num-iterations=100 --font-funcs=ot
-#perf report -g
diff --git a/perf/texts/fa-words.txt b/perf/texts/fa-words.txt
new file mode 100644
index 0000000..4937544
--- /dev/null
+++ b/perf/texts/fa-words.txt
@@ -0,0 +1,10000 @@

+در
+به
+از
+ویکی‌پدیا
+که
+را
+این
+با
+است
+رده
+برای
+کاربر

+بحث
+تصویر
+میلادی
+ایران
+تاریخ
+نام
+پرونده
+آن
+یک
+ساعت
+صفحهٔ
+کنید
+پیوند
+مقاله
+صفحه
+شما
+اصلی
+عنوان
+یا
+تا
+سال
+هم
+من
+استفاده
+بر
+خود
+شده
+شد
+تغییرمسیر
+شهرستان
+کار
+راهنمای
+اگر
+تکثیر
+چه
+ویرایش
+حق
+مقاله‌های
+می
+فارسی
+نیست
+دیگر
+نوشتن
+پنج
+بود
+زبان
+سیارک
+امضا
+کمک
+شیوه‌نامه
+منابع
+ملی
+ثبت
+آثار
+پانویس
+۱۱
+میز
+خودآموز
+بخش
+دارد
+خرد
+انگلیسی
+او
+لطفاً
+نیز
+۱۵
+شماره
+پهنا
+بنیاد
+استان
+هر
+اثر
+می‌شود
+مورد
+کرد
+یادکرد
+امیدوارم
+راهنما
+کنیم
+خوش

+ویکی
+چیزی
+پس


+شهر
+پیش
+فهرست
+مرجع
+خط
+آمدید
+اطلاعات
+اینجا
+تاریخی
+زیر
+منبع
+جعبه
+جدید
+دوره
+بیشتر
+اینکه
+بهتر
+یکی
+شود
+دو
+سپتامبر
+راهنمایی
+پیوندهای

+حذف
+۲۰۰۰
+خوب

+نظر
+آزاد
+قرار
+خواهد
+تمرین
+باشد
+بله
+پیرامون
+سلام
+آموزش

+اصل
+۱۰
+نه
+صفحات
+۱۹
+۱۲
+۲۰۱۱،
+های
+پاس
+ولی
+توسط
+چگونه
+برگزیده
+بداریم
+فقط
+ویکی‌پروژه
+۲۰۰۱
+روی
+سریع
+اکتبر
+صورت
+دست
+قهوه‌خانه
+۱۴
+دانشگاه
+بنیادی
+اما
+بیاید
+ناشر
+داشتید،
+باید
+بروید
+الگو
+چهار
+اول
+مارس
+کتاب
+ایجاد
+بازدید
+توجه
+آنها
+پایه
+۲۰
+کشور
+ساختار
+سخ
+خوش‌آمدید
+مقالهٔ
+شده‌است
+سازمان
+فارسی‌نویسی
+بودن
+مرکزی
+باز
+آمریکا
+وب

+۱۶
+نویسنده
+کادر
+دسامبر
+صورتی
+۲۰۰۷
+۱۸
+۲۰۱۰،
+کند
+فنی
+تصمیم
+۱۳
+تهران
+وجود
+۱۷
+نشانی
+چطور
+چند
+کشف
+اوت
+دانشنامه‌ای
+فوتبال
+علمی
+۲۰۰۸،
+درج
+۲۰۰۲
+هستند
+بگیرید
+۲۱
+۲۰۱۱
+نوامبر
+مطالب
+آزمایش
+وی
+کاربران
+فیلم
+ها
+ماندن
+مقالات
+بپرسید
+حروف
+لذت
+جمعیت
+بحثم

+ببرید
+خوشتان

+مدک
+وابسته
+ویکی‌پدیانویس
+ویکی‌پدیانویسان

+۲۰۰۹،
+اسلام
+۲۲

+مسایل
+آوریل
+بنویسیم
+۱۹۹۹
+کاربری
+علامت
+واقع
+شوید
+اهمیت
+۲۳
+کلاس
+کردن
+ای
+آشنا
+باشید
+نگاهی
+کوچک
+نکنید
+وب‌گاه
+پروژه‌های
+کرده
+۲۸
+می‌توانید
+انتخاب

+مکنید
+بعد
+روز
+است،
+جستارهای
+شدن
+نوع
+نمونه‌های
+۲۴
+نفر
+دارید،
+بیندازید
+خودکار
+۲۰۰۶
+نوشته
+مطالعهٔ
+انبار
+عجله
+غفلت
+فهرست‌شده
+مشارکت
+اهل
+۲۵
+سوال
+محمد
+بوده
+۳۰
+بسیار
+بزرگ
+میراث
+میان
+زمان
+منابعی
+اثبات‌پذیری
+جلالی
+سیارک‌های
+دهستان
+مرکز
+انجام
+فوریه
+می‌کند
+۲۶
+نام‌های
+ما
+یعنی
+ایرانی
+ژوئن
+غیر
+پایان
+یونسکو
+حال
+پرحجم
+چپ
+می‌گویم
+داشته
+جمله
+پیام
+عمومی
+گردشگری
+قبل
+همین
+همچنین
+همان
+مالک
+سپاسگزارم
+سال‌های
+همه
+اندازه
+مربوط
+ویکی‌انبار
+قدر
+چون
+بیرون
+ویکی‌نویسی
+داده
+کسب
+دوم
+ویژه
+هیچ
+فرهنگ
+کسی
+بروید،
+تنها
+۲۰۰۳
+دارای
+ساخت
+افراد
+رتب
+تازه‌واردان،
+مه
+محلی
+بصب
+بین
+پتوپ
+مقاله‌ها
+نیازمند
+اسلامی
+۲۷
+بی
+مرگ
+علی
+۲۰۰۵
+متون
+مطلق
+سه
+می‌باشد
+نیاز
+شرکت
+۲۹
+۲۰۰۹
+باشگاه
+دلیل
+زندگی
+چاپ
+موجود
+۲۰۰۸
+نقل
+گروه
+۲۰۰۴
+انتهای
+دارند
+محتویات
+شاد
+موضوعات
+جستجوی
+۱۹۹۸
+مردم
+نشان
+موسیقی
+ویکی‌مدیا
+همراه
+ویکی‌گفتاورد
+تپه
+شورای
+دانشنامه
+ویکی‌واژه
+بدون
+مانند
+راه
+شهرهای
+فرهنگی
+سیاره
+ویکی‌نبشته
+ترجمه
+فراویکی
+حجم
+کنونی
+طبق
+ژانویهٔ
+بار
+اجرام
+روستای
+ویکی‌نَسک
+تغییر
+خوشامد
+سرعت
+۲۰۱۲،
+جنگ
+برابر
+محل
+سر
+سپس
+سیارک‌ها
+عربی
+بازیابی
+داشت
+بازی
+ماه
+می‌تواند
+رو
+کنید،
+ژانویه
+معرفی
+بنا
+مشترک
+چندین
+دوران
+ندارد
+جهان
+حقوق
+کنم
+بالا
+ضمن
+داد
+وبگاه
+البته
+آب
+قدیمی
+امکان
+جمهوری
+قسمت
+۰۹
+مفیدند
+پیدا
+وپ
+پروژه
+بن
+همکاری
+۰۸
+تغییرات
+كه
+منطقه
+معماری
+چم‌وخم
+معرفی‌شده
+کنند
+هزار
+عرض‌جغرافیایی
+طول‌جغرافیایی
+۰۷
+روی‌نقشه
+برخی
+آی‌پی
+آمار
+ویکی‌پدیای
+۲۰۱۰
+جای
+موضوع
+تمام
+گرفته
+شرقی
+فوریهٔ
+اخیر
+قمری
+متوسط
+دیگری
+غربی
+درگاه
+ربات
+راستی
+اولین
+۳۱
+باستانی
+امنیت
+چنین
+آلمان
+کم
+رسمی
+جهانی
+مطالعه
+بررسی
+ژوئیه
+فعالیت
+آغاز
+آذربایجان
+فکر
+اين
+الگوی
+تیم
+لطفا
+ژوئیهٔ
+صنایع
+درود
+نامه
+تلفن
+اقدام
+روستا
+ایشان
+می‌کنند
+فارس
+حتی
+تعداد
+دربارهٔ
+فعلی
+درست
+مدیران
+گفتگو
+حجت
+دستی
+ستاره
+بسیاری
+اند
+نقش
+کلیک
+بودند
+۰۶
+تولد
+کردم
+زادگان
+شاه
+متحده
+توضیح
+طول
+دوست
+ذکر
+رسیده
+مقاله‌ای
+قابل

+اضافه
+مسائل
+ایالات
+همهٔ
+اینترنتی
+نام‌گذاری
+سیاسی
+طور
+خیلی
+رضا
+روستاهای
+چپ‌چین
+تولید

+صفحه‌های

+برچسب
+خانه
+شکل
+دولت
+می‌توان
+شامل
+می‌نویسید
+یادتان
+موسسه
+جنوب
+نرود
+نشریه
+باشند
+۰۰
+آمد
+وارد

+فرانسه
+جوایز
+مجموعه
+قانون
+به‌عنوان
+متن

+۰۵
+جایزه
+خبری
+سید
+ویکی‌خبر
+گفته
+اساس
+سیاست‌های
+جنوبی
+سایت
+آری
+ممکن
+نمی
+بنویسید
+روسیه
+فیلم‌های
+مهٔ
+سوم
+تشکر
+جام
+۱۳۸۵
+حدود
+کامل
+عرض
+شمارهٔ
+قاجار
+ماني
+عکس
+اجازه
+تصحیح
+آرش
+علوم
+نظری
+جای‌های
+اشاره
+دانشنامهٔ
+گرفت
+کردند
+جان
+فرهنگی،
+مختلف
+بانی
+توضیحات
+ارتفاع
+موارد
+میلاد
+مثل
+مرمت
+ژورنال
+شعر
+محتوای
+بیش
+چرا
+شمال
+خواهر
+می‌کنم
+خم
+فصل
+شروع
+تشکیل
+چم
+سرشماری
+دهه
+مشکل
+ساخته
+زبان‌ها
+گونه‌های
+مدت
+مجموعه‌ای
+زیادی
+بهترین
+درباره
+موافق
+دیرینگی
+نتیجه
+هست
+آلبوم
+ادامه
+جهت
+خراسان
+شرح
+ایران‌شهر
+زیستی
+پیشرفته
+می‌دهد
+راهنماهای
+صفحه‌ی
+افغانستان
+هماهنگی
+قلعه
+اصفهان
+بالای
+جغرافیایی
+شخصی
+نسبت
+می‌شوند
+تصنيف
+مطرح
+عناوین
+بوده‌است
+۰۱
+۱۳۸۶
+زمین
+سازی
+حزب
+سی
+آن‌ها
+سرشناسی
+انقلاب
+مي
+واژه‌ها
+مهم
+سایر
+می‌آید،
+دکتر
+مساحت
+قطعنامه
+۰۴
+شدند
+مرد
+درگذشتگان
+پرونده‌های
+باعث
+نکاتی
+اعلام
+نامگذاری
+پروژه‌ای
+زبانه
+سیستم
+انتفاعی
+یادداشتی
+کتابچه
+پرسیدن
+۰۳
+چندرسانه‌ای
+قول‌ها
+هرکسی،
+ویکی‌گونه
+خوانندگانش
+کیلومتر
+سطح
+زمینه
+اهالی

+سؤال،
+حسین
+اصطلاح‌نامه
+موقت
+سندباد
+بود،
+تبدیل
+سبک
+بنویسیم؟
+روش
+میثم
+زمانی
+۱۳۸۷
+دسترسی
+کد
+انگلستان
+برنامه
+رنگ
+تحت
+هاروارد

+مدیر
+امیروبات
+جرم
+جلد
+وقتی
+گودال
+نگاره
+شمالی
+۰۲
+پاسخ
+آیا
+تر
+منتشر
+شوند
+انتشارات
+مخالف
+مسجد
+بایگانی
+هماهنگ‌کننده
+کپی
+متر
+مجلس
+۴۰
+دهید
+شاید
+آنجا
+گل
+کاربرهای
+ناسا
+دوستان
+جناب
+پیشنهاد
+ان
+دی
+یافت
+آسمانی
+۱۳۸۸
+هنوز
+نخستین
+مذهب
+نویسندگان
+زنده
+ایالت
+ماسه‌بازی
+احمد
+آنهاست
+کنار
+شبکه
+بازی‌های
+مشخص
+ژاپن
+نمود
+وقت
+کشورهای
+خواندن
+معروف
+اروپا
+اشتباه
+کرمان
+سن
+معرف
+پهلوی
+درجه
+سوی
+ام
+محیط
+بحثتان
+روزنامه
+گونه
+۱۹۹۷
+طرف
+کل
+داستان
+علت
+الگوهای
+آمریکایی
+تو
+آمده
+بین‌المللی
+داتک
+امیر
+انتشار
+قوانین
+شماره‌دار
+دادگان
+موفق
+رشته
+خاطر
+دارم
+خورشیدی
+حسن
+معنی

+زنان
+انتقال
+پی
+حکومت
+لازم
+به‌آفرید
+تپه‌های
+نام‌صفحه
+شابک
+زن
+قرن
+دهد
+عمل
+بازیگر
+تصاویر
+رئیس
+ممنون
+عزیز
+یاد
+گفت
+هفته
+دین
+رای
+وضعیت
+فرار
+درخواست
+سیاست
+سمت
+حالت
+پسر
+کوه
+پرچم
+طی
+ادبیات
+الله
+کلی
+کشف‌شده
+بازیابی‌شده
+غرب
+فرودگاه
+۱۳۹۰
+سپاس
+واژه
+توابع
+ابعاد
+کمربند
+دور
+مدرک
+مبدا
+مازندران
+کننده
+مدیریت
+دوستدار
+وجه
+مهدی
+نمایش
+هجری
+هنر
+ابتدا
+ده
+رسید
+اعضای
+انسان
+امام
+مثال
+دادن
+آخرین
+اسرائیل
+قول
+نمایید
+حضور
+رود
+خودتان
+زیاد
+جا
+توصیه
+مناطق
+عراق
+مطلب
+پرسش
+خان
+عضو
+حسام
+حداقل
+باستان
+ارائه
+۵۰
+مواد
+کمی
+خارج
+دما
+چین
+وزارت
+اوج
+خروج
+طبیعی
+پزشکی
+ستاره‌شناسی
+فراموش
+پایین
+کاری
+اکنون
+بعضی
+میانگین
+نشده
+هزاره
+نشر
+مهندسی
+شد،
+آباد
+خودم
+اسپانیا
+خاص
+دوران‌های
+۱۳۸۹
+جریان
+منظور
+طریق
+ترتیب
+بناهای
+بیان
+دارید
+روستایی
+سطحی
+شیخ
+نسخه
+حرکت
+بنده
+سده
+اجتماعی
+طراحی
+حرف
+خودروهای
+ویکی‌گزارش
+نو
+هند
+استاد
+به‌شما
+دوباره
+توان
+نظامی
+بلکه
+سری
+همسر
+هنری
+شیراز
+مفیدی
+جمع
+علم
+خانواده
+انتخابات
+آلمانی
+فاصله
+نیروی
+مرتبط
+نمونه
+پدیا
+فرمایید؛
+شناخته
+چگالی
+دیده
+معتبر
+مناسب
+قرآن
+میلیون
+واحد
+۴۵
+مهر
+تبریز
+هنگام
+گسترش
+طبقه‌بندی
+۱۹۹۶
+فلسفه
+کرمانشاه
+گردید
+گذشته
+دنیا
+زیرا
+قدرت
+مثلا
+ببینید
+لیگ
+دریافت
+انحراف
+نام‌رسمی
+می‌آید
+حمله
+گرانش
+توسعه
+افزایش
+چشم
+مکان
+عدد
+ابهام‌زدایی
+دانش
+موضوعی
+نزدیک
+شخص
+آنان
+دیگران
+بازیکنان
+آقای
+کاشف
+تلویزیونی
+زاده
+بسته
+جایی
+خدا
+حاضر
+شرق
+می‌شد
+حساب
+پدر
+داشتید
+نقض
+پیش‌شماره
+ایتالیا
+کاربرد
+سعی
+رفت
+برد
+‌بودن
+کاربردها
+تناوب
+۳۵
+معمولاً
+زبان‌های
+بهمن
+۳۲
+عباس
+حضیض
+پدیدآور
+انجمن
+فیزیک
+نگاه
+فعال
+نور
+نسخه‌ها
+ریاست
+هستم
+فلکی
+فرد
+مسیر
+اجازه‌نامه
+جامعه
+آلبدو
+مصر
+آنومالی
+کلمه
+نیم‌محور
+بریتانیا
+۱۹۹۵
+پر
+پاک

+۱۹۹۳
+بازیگران
+بخشی
+فرانسوی
+داخلی
+خبر
+سئوال
+محمود
+باشد،
+امروز
+کرده‌است
+ارتباط
+درصد

+تاریخچه
+ملل
+اصلاح
+معیارهای
+همچون

+طرح
+شده‌اند
+هدف
+عالی
+وقایع
+میدان
+محسوب
+حل
+باغ
+استان‌های
+خودش
+قطع
+ایران،
+۳۳
+۳۴
+اش
+دنبال
+شهری
+تعریف
+دانشکده
+انواع
+دار
+ورزشگاه
+نقشه
+کوتاه
+شمار

+مدرسه
+کمتر
+آرامگاه
+عصر
+عبارت
+بیست
+تن
+خرابکاری
+المپیک
+تیر
+می‌رود
+خیابان
+بازار
+نامزد
+میرزا
+داخل
+اندازه‌تصویر
+پایگاه
+رضوی
+سؤال
+۱۹۹۰
+الان
+گرامی
+نبود
+خوبی
+۳۷
+خارجی
+گیری
+آورد
+برچسب‌تصویر
+۴۸
+سیستان
+۱۹۹۴
+آزادی
+رشد
+نباید
+پرسشی
+۱۳۸۴
+حد
+۳۶
+ملیت
+رشدجمعیت
+تازه
+میانگین‌دما
+عدم
+نیروهای
+تراکم‌جمعیت
+سؤالی
+نام‌های‌قدیمی
+بنابراین
+ارتش
+شب
+داشتن
+علاوه
+ابن
+شمارروزهای‌یخبندان
+میانگین‌بارش‌سالانه
+پل
+تصویب
+میانه
+خرداد
+گیلان
+سنگ
+کنترل
+بهزاد
+کیفیت
+می‌‌نویسید
+۴۱
+درگذشت
+علیه
+گزارش
+شیعه
+خور
+۳۸
+جزیره
+ره‌آورد
+دسترس
+دستگاه
+نام‌محلی
+تگزاس
+جز
+همیشه
+۴۲
+اجرا
+کوشش
+پخش
+رد
+۴۶
+متحد
+اسفند
+وزیر
+خواننده
+بهبود
+اثبات
+سفید
+نظرخواهی
+شرایط
+جمله‌خوشامد
+ترکیه
+۴۴
+همدان
+قم
+۳۹
+می‌گیرد
+۴۳
+بلوچستان
+چیز
+دسته
+خوزستان
+گنو
+ترانه
+کدام
+خودرو
+۵۵
+۴۷
+باقی
+بندی
+۵۱
+بخوانید
+۱۹۹۲
+خواهند
+صد
+ناحیه
+۵۳
+کاهش
+۱۹۹۱
+میشود
+مذهبی
+۴۹
+ساختمان
+اولیه
+مقابل
+۵۲
+سبز
+وحید
+۵۷
+مشهور
+متوجه
+تهیه
+کافی
+آنچه
+ترک
+افزودن
+می‌شود،
+جدا
+۱۳۸۲
+چهارم
+تقسیم
+نژاد
+معنای
+کشاورزی
+صفوی
+براساس
+سیاه
+هایی
+آسیا
+تمامی
+تحقیق
+۱۹۶۰
+ساسانیان
+نوشتار
+رادیو
+۵۶
+۵۴
+اسم
+ارزش
+دهانه
+اقتصادی
+ابراهیم
+نخست
+فرزندان
+۵۹
+هاي
+شهرها
+دقیقه
+حالا
+دستور
+امور
+رابطه
+پارک
+جنبش
+دختر

+قالب
+بیماری
+نام‌های‌دیگر
+محوطه
+بازیکن
+کشته
+دارد،
+مشهد
+منتقل
+شهریور
+مرداد
+کیلومتری
+پرداخت
+۵۸
+تخصصی
+۲۰۱۲
+مرده
+دهیار
+صنعتی

+خدمت
+پشت
+فشار
+می‌کرد
+تلاش
+مدیاویکی
+تلویزیون
+میزان
+سال‌بنیاد
+قبلی
+انرژی
+بدست
+نظام
+حوزه
+پا
+بودم
+یزد

+هفت
+ازدواج
+است؟
+فضای
+نظریه
+اختلاف
+حمایت
+خواهم
+مجله
+رفته
+اجرای
+می‌گردد
+برتر
+متولد
+کره
+خاک
+برگزار
+سرزمین
+بدن
+کرده‌اید
+مسابقات
+اقتصاد
+ندارم
+بعدی
+قبول
+خلیج
+آخر
+کمیته
+فروردین
+مادر
+کارگردان
+می‌کنید
+سال‌ها
+کسانی
+مصرف
+جدول
+جشنواره
+آنرا
+دید
+فرزند
+عرب
+کاملا
+آمل
+پادشاه
+دیدگاه
+آذر
+اشکانیان
+سفر
+متفاوت
+وزن
+نیویورک
+داشتند
+بیشتری
+موزه
+یه
+می‌رسد
+خاصی
+دل
+دهستان‌های
+آنکه
+استقلال
+پنهان
+مجوز
+نوعی
+کردید
+لرستان
+جغرافیا
+ترکی
+محسن
+هوایی
+۱۹۸۱
+فروش
+مقام
+مقدار
+۱۶۱۵
+قزوین
+حالی
+عمر
+لزوم
+میل
+آبی
+دقت
+اصلا
+اطلاع
+رخ
+شکست
+اعمال
+اینترنت
+موتور
+دومین
+شهید
+تحقیقات
+تاسیس
+برخورد
+روم
+ماده
+محله
+لینک
+راست
+امروزه
+کرده‌اند
+بازگشت
+جواب
+پارس
+یونان
+رتبه

+شده،
+۱۳۸۱
+اساسی
+نقطه
+گردد
+موجب
+سخن
+تقویم
+نکته
+می‌دهند
+مستقل
+جامع
+اردیبهشت
+هستید
+سینما
+مدل
+کانادا
+گاه
+آورده
+حفظ
+ثابت

+احترام
+بوشهر
+مربع
+۱۹۸۸
+روابط
+سیمرغ
+درون
+زیرنویس
+کن
+نظرم
+ترکیب
+بهار
+بد
+پادشاهی
+دلار
+شیمی
+تعیین
+بابل
+نفت
+دولتی
+مدتی
+نظرات
+درستش
+کاتالوگ
+گاهشماری
+لحاظ
+ساده
+بخش‌های
+شوروی
+باب
+بی‌بی‌سی
+گرفتن
+دادم
+مثلاً
+گروه‌های
+ندارند
+کردستان
+حاصل
+شود،
+انسانی
+گرم
+روشن
+مسکن
+خون
+۱۳۸۰
+رسیدگی
+مفهوم
+خمینی
+گیاهان
+ساز
+آهنگ
+ترین
+هرمزگان
+۱۹۸۹
+صاحب
+کارهای
+اغلب
+عبدالله
+مشغول
+۱۰۰
+شناسی
+محمديان
+گفتم
+مختصات
+دهند
+یونانی
+رایانه‌ای
+یکم
+ستارگان
+کتاب‌های
+ایرانیان
+آوردن
+صنعت
+کند،
+صحبت
+فناوری
+نمی‌شود
+آینده
+واگردانی
+کتابخانه
+برجسته
+امر
+نقد
+مخصوص
+بزرگی
+آبان
+نتایج
+براي
+یافته
+لقب
+متاسفانه
+مالکیت
+مشاهده
+عرضه
+کارت
+گاهی
+شش
+دفاع
+مایکل
+اداره
+خبرگزاری
+دره
+مسئله
+صحیح
+ولایت
+گروهی
+رودخانه
+مقدس
+مراسم
+کشورها
+باد
+تاکنون
+خلاف
+علاقه
+ارومیه
+مرحله
+ورود
+۲۰۰۷،
+تکمیل
+موقعیت
+رویدادها
+تفاوت
+ایستگاه
+شیمیایی
+مگر
+ضد
+ژاپنی
+استاندارد
+دریای
+۱۹۸۰
+معاصر
+زندان
+غیرقابل
+عملیات
+دریایی
+خصوص
+برخوردار
+لندن
+شیوه
+آقا
+مشابه
+سخت
+خلاصه
+دفتر
+برنده
+سنت
+پاپ
+جلوگیری
+قدیم
+ورودی
+اسکار
+بطور
+چر
+بندر
+مرا
+راک
+نیشابور
+نیستند
+۱۵۱
+مشکلی
+آتش
+کشوری
+تابستانی
+امپراتوری
+بررسی‌های
+آن،
+اس
+میکنم
+پارسی
+تشخیص
+شاعر
+خدمات

+عهده
+نیمه
+مشکلات
+نیست،
+آشنایی
+بصورت
+تأسیس
+درمان
+ابزار
+آموزشی
+نوروز
+بروجرد
+تواند
+قتل
+تحصیل
+دیدم
+مدرس
+دانشگاه‌های
+جمهور
+محدود
+برج
+آبشار
+دانشجویان
+احتمال
+رفتار
+اعتماد
+اطراف
+هشدار
+همواره
+قطعنامه‌های
+محمدرضا
+پاریس
+ساله
+کالیفرنیا
+وسیله
+اصول
+درخت
+سالگی
+۱۹۷۷
+پیشه
+داریم
+شخصیت
+قصد
+نداشته
+می‌گوید
+جشن
+ویرایش‌های
+ادبی
+بهره
+سنتی
+فوق
+کنید؛
+تام

+بانک
+دهم
+استرالیا
+دقیق
+نامیده
+نفوس
+فراهم
+می‌توانند
+بدین
+اختیار
+چشمه
+دادند
+يا
+اردبیل
+پست
+خانوار
+قهرمانی
+منصور
+سرخ
+روسی
+۱۳۸۳
+شبیه
+بشر
+قرمز
+قطر
+سبب
+کشتی
+برده
+صدا
+یکسان
+شمسی
+مجدد
+اکثر
+جالب
+تک
+گلستان
+پنجم
+فراوان
+يك
+نرم‌افزار
+توهین
+اتحادیه
+عشق
+ظهیری
+گورستان
+بلژیک
+بکار
+رستم
+سرشناس
+‌ها
+هیئت
+علیا
+مقالاتی
+رباتیکی
+هنگامی
+لطف
+بختیاری
+روح
+ارجاع
+تقریبا
+۱۹۷۳

+سپاه
+‌های
+یکدیگر
+نموده
+رمان
+کرد،
+جنسی
+بزرگترین
+پیشرفت
+دعوت
+بقیه
+کلمات
+شهرت
+مرکزی،
+رایانه
+یمن
+تخت
+معادل
+صادق
+وسط
+خوانندگان
+تلفظ
+اتفاق
+امامزاده
+تحصیلات
+خانوادگی
+حقیقت
+خورشید
+نوری
+نقاط
+پایتخت
+بند
+گوگل
+مانده
+نزدیکی
+سعید
+امید
+نشود
+نر
+مسعود
+سلطان
+ادغام
+سفلی
+دریا
+لاتین
+اجماع
+خوانده
+سابق
+ریاضی
+درستی
+فضایی
+دلایل
+برندگان
+بعدها
+متعلق
+پیشین
+شدم
+هنرمند
+درس
+ذخیره
+کارگردانی
+نباشد
+دانقولا
+اون
+تابع
+مالی
+صدای
+بلند
+بارگذاری
+بخش‌ها
+اینگونه
+اواخر
+ریشه
+نشد
+کاخ
+ریز
+فرض
+قانونی
+برق
+جلوی
+کودکان
+نزد
+قاسم
+آهن
+زنجان
+نگارش
+شدت
+می‌گویند
+جایگزین
+جاده
+می‌کردند
+مفید
+زرشک
+لیست
+محور
+ویکیپدیا
+رایج
+مناسبت‌ها
+خلق
+مراکز
+ساری
+عامل
+نقاشی
+رسیدن
+کارشناسی
+۱۹۸۴

+زده
+رعایت
+انگلیس
+اطلاعاتی
+ورزشی
+مقایسه
+منبعی
+بازبینی
+حافظه
+حتما
+عربستان
+مستقیم
+گیرد
+الدین
+۱۹۸۲
+علیرضا
+تعدادی
+ورزش
+برادر
+گذاشته
+تهران،
+محصولات
+زندگینامه
+هوا
+۱۹۸۶
+۶۰
+کس
+پوشش
+حکم
+قهرمان
+خانه‌های
+حاج
+خواهش
+گردآفرید
+نوبل
+نرم
+رهبری
+خیر
+تجاری
+نوشت
+۱۹۸۵
+جوان
+واقعی
+نظیر
+سند
+سرانجام
+منجر
+اعداد
+فی
+واقعا
+نبرد
+مردان
+جغرافیای
+شدید
+روند
+ویرایشی
+دشت
+رده‌بندی
+پرحجم،
+گذاری
+افشار
+۱۹۷۸
+زدن
+سوئد
+خویش
+ماهی
+خالی
+درآمد
+آمریکای
+مسلمانان
+کجا
+می‌باشند
+طوری
+اید
+دکمهٔ
+احمدی
+درد
+۱۹۸۷
+شاعران
+گویا
+نداشت
+هـ
+سالهای
+ششم
+شیر
+دچار
+تاثیر
+زیست
+دینی
+سریال
+نماد
+راجع
+مطالعات
+مراجعه
+لحن
+خطر
+پرسپولیس
+حضرت
+مکتب
+دامنه
+بروید؛
+زیبا
+بافت
+مسلمان
+کامیار
+محافظت
+ناوبری
+نهایت
+کلیسای
+هشت
+تکرار
+پرورش
+توزیع
+معمولا
+وبلاگ
+طولانی
+تجربه
+ظاهر
+گسترده
+ممنوع
+پیروزی
+چهل
+گاز
+عکاسی
+کاملاً
+احساس
+همچنان
+تفسیر
+چک
+مترجم
+مشخصات
+اینها
+تایید
+۱۹۷۹
+توکیو
+ال
+سمنان
+۲۰۰
+رهبر
+بیت
+سومین
+خورده‌است
+پاکستان
+۹۰
+همانند
+فردی
+ملحق
+کامپیوتر
+سوریه
+پدرش
+اوایل
+پول
+سوره
+تقویم‌های
+آفریقا
+کتاب‌ها
+دنیای
+همانطور
+دودمان
+هدایت
+باره
+سلسله
+موسوی
+قضیه
+غیره
+صرف
+آید
+ايران
+پک
+طبقه
+حاکم
+داریوش
+گوناگون
+زهرا
+اسماعیل
+زمین‌لرزه
+اعتبار
+بعنوان
+مُروا
+توانست
+۱۳۷۹
+تدوین
+اهواز
+سبزوار
+جکسون
+نمایندگان
+مقاومت
+آی
+برداشت
+گشت
+قلم
+تنظیم
+نگاری
+هلند
+باور
+نهاد
+سینمای
+تمدن
+فرهنگستان
+کردی
+ویندوز
+سوئیس
+کانی
+نویسی
+ممتنع
+مانی
+پشتیبانی
+جو
+رده‌ها
+ساکن
+شهرک
+روزی
+صحنه
+اصطلاح
+تئاتر
+جستجو
+جلو
+فردا
+جیمز
+کی
+هرگز
+چیست؟
+حمل
+توصیف
+گیتار
+ری
+والدین
+۱۹۷۶
+حفاظت
+رشت
+سابقه
+کودک
+کنون
+فعالیت‌های
+عوض
+اعتراض
+نسل
+دریاچه
+مرز
+باشگاه‌های
+کهگیلویه
+میکند
+دادگاه
+تصویری
+خانم
+مخالفت
+نصب
+آل
+افرادی
+چاه
+نماینده
+نگه
+عملکرد
+جدیدی
+۱۹۷۰

+مهمترین
+آمده‌است
+محمدعلی
+بدهید
+اتحاد
+شرکت‌های
+موج
+رم
+کشیده
+تحلیل
+نظارت
+تابلوی
+شهرداری
+محصول
+متعدد
+نماید
+قوم
+مصطفی
+جزایر
+گرمی
+عقب
+صلح
+شعار
+ارسال
+جی
+نوشته‌های
+غلط
+۱۹۷۱
+سازنده
+نکرده
+مواردی
+جوانان
+حمام
+دورهٔ
+تبریک
+بگذارید
+دانشگاهی
+مس
+ماند
+خداوند
+مهاجرت
+ضبط
+ست
+احتمالا
+لبنان
+دوربین
+خودشان
+عبور
+ارشد
+بنام
+فرمان
+عبارتند
+مطابق
+خرم‌آباد
+بالاتر
+سد
+تقریباً
+اکبر
+دیدن
+موفقیت
+مدرن
+نگهداری
+۷۰
+عوامل
+پای
+جایگاه
+۸۰

+زادروز
+پرواز
+خلیفه
+هفتم
+ماشین
+هرچند
+هسته‌ای
+عناصر
+اسناد
+گنبد
+لا
+نهایی
+تدریس
+طلایی
+زابل
+چندان
+اروپایی
+ظاهری
+صفر
+اول،
+اشعار
+دبیرستان
+معلوم
+برنامه‌های
+نخواهد
+زد
+بیفزایید
+خصوصی
+وظیفه
+ادعا
+عزیزی
+عمده
+انتظار
+آن‌لاین
+قبلا
+مبارزه
+هستند،
+خسته
+فرصت
+رفتن
+مشارکت‌ها
+گرامی،
+سراسر
+۱۹۸۳
+پیروز
+گویش
+رفع
+جزو
+گفتاورد
+متال
+مکزیک
+۱۳۵۷
+امپراتور
+اطلس
+اسپانیایی
+پنجاه
+شاپا
+بیمارستان
+پیامبر
+بستک
+می‌کنیم
+اشکال
+تقسیمات
+الکتریکی
+درک
+سلطنت
+لباس
+دهنده
+نشست
+اعدام
+اقوام
+شاخه
+سلام،
+الگوریتم
+چپچین
+شان
+خواست
+مدال
+امارات
+جبهه
+باشم
+مطبوعات
+مستعار
+نیازی
+عادی
+چینی
+افتخار
+کهن
+نا
+مثبت
+شخصیت‌های
+خطوط
+ویلیام
+سلطنتی
+منطقی
+اطمینان
+جعفر
+سقوط
+روزهای
+گرفته‌است
+طبیعت
+باشیم
+رده‌های
+ترتیب‌پیش‌فرض
+شبه
+موافقم
+یهودیان
+تربیت
+دیوید
+معاون
+پرندگان
+ملت
+دیوان
+تی
+پلیس
+ملک
+نيز
+هنرمندان
+عین
+تماس
+حرفه‌ای
+آستانه
+بماند
+واکنش

+زحمت
+عمان
+حافظ
+نیم
+منفی
+آسیای
+تابستان
+جدی
+قابلیت
+ساختن
+آسیایی
+رجوع
+شهرستان‌های
+معین
+نیستم
+ناشی
+تهیه‌کننده
+داشته‌است
+دانشمندان
+صبح
+اعتقاد
+مبارک
+سورنا
+اساطیر
+اصلاً
+تذکر
+خطی
+کاربردی
+داشتم
+آدم
+کتابی
+مختلفی
+کاربرانی
+سرباز
+جذب
+متغیر
+وضع
+روزبه
+مجازی
+گذاشت
+بابت
+اعلانات
+مهمی
+فلان
+آماده
+مصاحبه
+باتجربه‌تر
+رقص
+کلاسیک
+گیاه
+سامانه
+مجبور
+نحوه
+نبوده
+نفوذ
+متری
+کانال
+حیات
+گفتمان
+جلسه
+ارادتمند
+درفش
+حومه
+تصور
+خاندان
+بهرام
+لحظه
+برزیل
+یهودی
+دهخدا
+ایتالیایی
+رسانه

+۱۹۷۵
+مسابقه
+خواستم
+کابل
+نی
+اوکراین
+موسی
+شما،
+بگیرد
+زرد
+هوای
+فلسطین
+اهداف
+است؛
+ولسوالی
+غار
+بنای
+نوشتارهای
+مربوطه
+اخبار
+بودند،
+مهم‌ترین
+سینمایی
+پیمان
+۸۸
+همزمان
+ها،
+احتمالاً
+آسمان
+شهرک‌های
+ابتدای
+ندهید
+بوجود
+آیدا
+جانوران
+سده‌های
+بازداشت
+هسته
+یادداشت
+ایلام
+نامی
+مجموع
+هنرهای
+می‌دانند
+ادعای
+سرویس
+بگویم
+ظهور
+هزینه
+کاویانی
+الگوها
+ضروری
+آرام
+حذفی
+اقیانوس
+یی
+امتیاز
+زمینی
+آدرس
+باشه
+امکانات
+بیشترین
+طراح
+نواحی
+مطالبی
+مقالات،
+بخاطر
+لی
+آفتاب
+بفرمایید
+دقیقا
+هشتم
+توانایی
+آیت‌الله
+مسیحیت
+تبلیغات
+محوطه‌های
+بارها
+ته
+سنچولی
+يک
+الف
+متصل
+ساسانی
+بویراحمد
+سروش
+نظرتان
+ربطی
+روایت
+بروز
+دیگه
+پژوهشی
+زبانی
+۱۳۷۸
+ثانیه
+برگزاری
+تبلیغ
+شاهنامه
+نزاکت
+قوی
+خواجه
+پوست
+پژوهش
+شروین
+سنی
+میباشد
+سرد
+بگویید
+شکایت
+بنی
+صدر
+مطلبی
+اسید
+کلید
+خسرو
+گذشت
+طلا
+شیرازی
+اي
+شناسایی
+تأثیر
+شیرین
+می‌کند،
+رأی
+فردوسی
+اگرچه
+چهارمین
+نمی‌کند
+زاپاس
+خشک
+جنگی
+برداری
+قادر
+بومی
+بنابر
+ديگر
+تقدیم
+حاشیه
+نگاره‌های
+۱۹۷۲
+اختصاص
+یونایتد
+بردن
+اندیشه
+حتماً
+بودجه
+داشت،
+افزوده
+۱۹۷۴
+بیرجند
+عضویت
+مستند
+بحثی
+الکترونیک
+امروزی
+بیرونی
+فتح
+معمول
+واژگان
+ادب
+نمی‌توان
+مرتضی
+اتصال
+مخالفان
+گویند
+ناقص
+سفارت
+۱۳۷۷
+المللی
+قسمتی
+چنان
+مدفن
+فضا
+گرچه
+ويکيپديا
+آمدن
+زیبایی
+نوشتم
+عهد
+رای‌گیری
+سرمایه
+نامعلوم
+ردیف
+تجارت
+نیک
+ایل
+یافتن
+اظهار
+گرد
+مایل
+اعراب
+قیمت
+چی
+مقدمه
+خرید
+عمق
+گمان
+هری
+معتقد
+داده‌است
+یوسف
+مردتنها
+بزرگ‌ترین
+فراوانی
+مرور
+جزء
+ناصر
+موشک
+رومانی
+دانست
+نادرست
+خود،
+فایل
+تلقی
+مشاهیر
+بوده‌اند
+آواز
+ضمنا
+بشود
+عثمانی
+مبنای
+قلب
+گوش
+جمعه
+آیت
+ویرایشات
+هاشمی
+دارند،
+استادان
+فرق
+همگی
+پرتغال
+ذهن
+پیر
+زیست‌شناسی
+پرنده
+بتواند
+ارمنستان
+اتریش
+اندکی
+آیین
+اتاق
+قطعه
+شناخت
+تغییری
+۱۹۶۸
+عبری
+معیار
+هفتاد
+روش‌های
+نکردن
+فاقد
+آیه
+دم
+عید
+مکانیک
+تک‌آهنگ
+نوبت
+دیوار
+گشتن
+درمانی
+مطمئن
+نصف‌النهار
+جنس
+تیره
+منظومه
+بایستی
+ریاضیات
+مهندس
+رییس
+بارگذار
+هواپیما
+میشه
+آرژانتین
+کلا
+کریم
+شاهد
+گر
+سنگی
+مسئول
+نشانه
+فیلمبرداری
+نوکیا
+جمشید
+تغییراتی
+کتب
+کرج
+استناد
+شریف
+ایرلند
+اف
+نسخهٔ
+چهره
+نوید
+کنگره
+منچستر
+رابرت
+نباشید
+پرویز
+مى
+نماز
+کمال
+گونه‌ای
+ژان
+دلیلی
+داری
+عالم
+اسب
+حمید
+قرارداد
+پیشینه
+قره
+خروجی
+کمونیست
+قاسمیان
+می‌گیرند
+شصت
+زمستان
+کلمبیا
+راهی
+محدوده
+نام‌ها
+میر
+لینوکس
+میلادی،
+بهداشت
+اگه
+سدهٔ
+۵۰۰
+بجای
+مغز
+پوستر
+حاوی
+لغت
+رسانی
+لوگو
+مسیح
+فرزاد
+فرمول
+مؤسسه
+مفصل
+پدید
+درام
+اردشیر
+آفریقای
+خرابکار
+تامین
+داره
+اتمی
+بزرگان
+محکوم
+نجات
+یادبودهای
+ریچارد
+رومی
+مدار
+تخریب
+بدانید
+درگیری
+بیستم
+افتاد
+محترم
+خودروها
+نوین
+مطابقت
+تاجیکستان
+نقش‌های
+افزار
+مراجع
+اتومبیل‌های
+عزیز،
+ضعیف
+امضاء
+بیگانه
+فرا
+اکثریت
+هرات
+می‌یابد
+پنجمین
+میکنند
+کنندگان
+فعلا
+۸۵
+نکات
+ارتباطات
+خواهید
+مجمع
+کنی
+یابد
+منطق
+دیدار
+دویست
+دوستانه
+آوری
+آلبوم‌های
+اتهام
+بینی
+مسیحی
+گری
+آنلاین
+ویژگی
+ادوارد
+امنیتی
+برایتان
+كرد
+دیگر،
+عام
+اصرار
+بودید
+تبلیغاتی
+حاجی
+هرچه
+۱۹۶۴
+انتقاد
+برسد
+شک
+توانید
+ویژگی‌های
+خوی
+۶۴
+زادگاه
+مساله
+فیزیکی
+هخامنشی
+غذایی
+نمی‌دانم
+سامسونگ
+گرفتند
+تاج
+موقع
+۱۹۶۹
+فاطمه
+سخنرانی
+سختی
+استدلال
+۱۳۷۶
+شهردار
+ار
+سلیمان
+متهم
+مذکور
+عملی
+چندی
+پدیای
+صادر
+منتظر

+ضرب
+تیم‌های
+تل
+حسینی
+گیر
+سراب
+تیرداد
+ویکی‌سازی
+تان
+مشروطه
+کوچکی
+مردمان
+ویکی‌پدیا،
+مجاز
+محاسبه
+بزنید
+جنگل
+مجموعه‌های
+واقعیت
+سان
+قومی
+صفحه‌ها
+قطب
+تالار
+خواب
+تاکید
+گاه‌شماری
+امین
+لذا
+آسیب
+هیات
+قد
+میلیارد
+کوچولو
+برقرار
+بالایی
+شیعیان
+قاضی
+برگرفته
+عنصر
+معانی
+ارتباطی
+شبکه‌های
+درود،
+۳۰۰
+مراحل
+لهستان
+معمولی
+نوار
+محس
+۸۹
+قبیل
+سیر
+دهیم
+شاخص
+عیسی
+ترور
+دمای
+تکامل
+کبیر
+درگیر
+سونی
+یاری
+۱۹۵۰
+آگاهی
+نیوز
+پیوست
+رچ
+خدای
+کودکی
+مرتب
+رژیم
+روبات
+ابتدایی
+میتوان
+هشتاد
+زادهٔ
+کشت
+بازسازی
+وسایل
+بتوان
+مجارستان
+پیاده
+میان‌ویکی
+فرمانده
+۸۷
+تهدید
+ویک
+محرم
+نهم
+احمدی‌نژاد
+۶۵
+خورد
+رسول
+تمیزکاری
+بندانگشتی
+گیاهی
+سیاست‌ها
+این‌که
+کلیه
+بهشت
+هندی
+مشکوک
+فکری
+عقیده
+اشغال
+نویس
+ستون
+خارجه
+۱۳۸۶،
+۸۶
+نمی‌گیرد
+کارخانه
+دانشجو
+پیوسته
+خاطرات
+پادشاهان
+۱۹۶۷
+غذا
+زرتشت
+سود
+خوشحال
+رساند
+آر
+فیلمی
+می‌پردازد
+تری
+لایه
+سپهرنوش
+ظاهرا
+مصدق
+کویت
+مال
+احداث
+کانون
+مد
+فرماندهی
+مرحوم
+مواجه
+۱۳۹۰،
+بايد
+افتاده
+دوم،
+گردیده
+کارل
+وگرنه
+ندارد،
+ترجمهٔ
+ساحل
+جم
+طرفی
+نگهدار
+شرط
+روان
+آبتین
+جوانبخت
+سازهای
+الکترونیکی
+پور
+نود
+جمعی
+راحتی
+حیوانات
+داروهای
+دستگیر
+بابک
+حداکثر
+دانش‌آموختگان
+حلقه
+راستای
+اراک
+نادر
+اثری
+زبانهای
+برندارید
+رشته‌های
+بستن
+برگردان
+آبشارها
+ریزی
+مراغه
+دروازه
+پذیرش
+نمایی
+مدیریتی
+منصفانه
+واژهٔ
+جانب
+متعددی
+رسد
+گوید
+شغل
+زاهدان
+نمای
+رواج
+واضح
+عده‌ای
+می‌مانند
+ایوان
+چوب
+نکند
+فلسفی
+معنا
+نمی‌تواند
+خورده
+سو
+باند
+ماهواره
+مرغ
+دشمن
+کوه‌های
+سرطان
+دبی
+پرداخته
+ایکس
+آشکار
+کاشان
+بغداد
+ببخشید
+ششمین
+منظورم
+جلب
+دیر
+مـهـران
+زند
+مناسبی
+خانگی
+تجزیه
+بالغ
+می‌داند
+علامه
+جولای
+برگ
+سیستم‌های
+سیستم‌عامل
+کاوه
+۷۵
+دراپر
+مدارس
+ظاهراً
+رنگی
+دهه‌ها
+چیست
+تظاهرات
+مربی
+سازمان‌های
+برپایه
+متشکرم
+دوازده
+ایراد
+گیتاشناسی
+می‌برد
+اسامی
+او،
+دارد؟
+بورکینافاسو
+تجهیزات
+شاهزاده
+دربار
+دانم
+زاویه
+قاره
+رهبران

+سرود
+ابهام
+۱۳۷۵
+ایمیل
+پیغام
+فرآیند
+دالبا

+پستی
+ظرفیت
+بشه
+سیتی
+هستیم
+پرتاب
+کمدی
+توی
+فجر
+این‌جا
+گرگان
+می‌دانم
+جواد
+شاتل
+خطاب
+الهی
+گرایش
+ملا
+دانشمند
+فیلتر
+نسبی
+شوم
+داستان‌های
+نمایشگاه
+تربت
+ممنونم
+آگوست
+پایدار
+مشارکت‌هایتان
+منطقه‌ای
+تنگ
+مقیاس
+شریک
+جزئی
+هویت
+بدهد
+نوشتهٔ
+بابا
+ادیان
+۱۹۶۵
+جورج
+هفتمین
+تصرف
+آهنگساز
+پاورقی
+دلیلتان
+حس
+کوچه
+رقابت
+نمایند
+رها
+مقامات
+منطقهٔ
+قلعه‌های
+فن
+مادرش
+متخصص
+تکنولوژی
+سالی
+کیفیتی
+زمین‌شناسی
+می‌دهم
+مک
+کشتار
+سنگین
+می‌نویسد
+نکردم
+ید
+پرو
+بدان
+باران
+دخالت
+درختان
+جوانی
+آنگاه
+حسب
+حرفه
+سندی
+چگونگی
+تبار
+توافق
+کتابهای
+اطلاق
+نامناسب
+مایکروسافت
+۱۹۶۶
+ارشاد
+فردوس
+صوتی
+روزگار
+نمودند
+سگ
+دارو
+خاورمیانه
+معلم
+گره
+ون
+سوخت
+مترو
+آموخت
+نشده‌است
+شماست
+هتل
+حدیث
+نداریم
+پیدایش
+۱۳۷۰
+میانی
+کنند،
+عقاید
+پیچیده

+قهوه
+فرشته
+نحوهٔ
+عجیب
+جداگانه
+هشتمین
+جزئیات
+همشهری
+مبنی
+کاتولیک
+اصفهانی
+حملات
+جاری
+پویان
+انگلیسی،
+برخلاف
+نيست
+اشخاص
+مجید
+سیمای
+کانی‌های
+تغذیه
+مربیگری
+برنامه‌نویسی
+‌پدیا
+فدراسیون
+اجرایی
+سیصد
+احمدآباد
+می‌خواهید
+جنگ‌های
+پیگیری
+حوادث
+اخیراً
+دیجیتال
+تکیه
+مریم
+الی
+۱۹۴۸
+كند
+عده
+اقدامات
+شعاع
+تخیلی
+ماه‌های
+۶۶
+آزمایشی
+شده‌است،
+واژه‌های
+دشتی
+موافقت
+قهرمانان
+جلال
+اچ‌دی
+الفبای
+نفس
+پایانی
+پانصد
+برایش
+ترجیح
+خواند
+سلول
+عصبی
+کوخرد
+آب‌انبار
+۶۲
+مفاهیم
+شنبه
+بالاخره
+دانسته
+هواپیمای
+نهمین
+ایالتی
+مو
+فارغ
+پلی
+دروغ
+اداری
+استقبال
+مسئولیت
+داده‌اند
+فدرال
+ترانه‌های
+نوازندگان
+چای
+دههٔ
+تراکم
+فهرست‌های
+مردی
+زمرہ
+گورستان‌های
+سوالات
+عباسی
+سردار
+محک
+ترکیبی
+رقم
+سعودی
+نرم‌افزارهای
+بازرگانی
+برلین
+نروژ
+مارتین
+فوت
+دیدنی
+کنفرانس
+فارسی،
+اهر
+نجف
+پذیرفته
+اینست
+ملکه
+سرخط
+كرده
+زنی
+قلمرو
+بخصوص
+امی
+بهائی
+نقاش
+کازرون
+تار
+گرفته،
+نظم
+۷۲
+خودداری
+شمس
+صفحه‌ای
+بیمار
+واقعه
+هادی
+۸۴
+خاتمی
+بارسلونا
+سرچشمه
+زنز
+برچسب‌های
+منتخب
+بحرین
+واشنگتن
+پاتر
+کرده‌ام
+شاهین
+زرین
+مارک
+توپ
+وقوع
+حدی
+آذری
+شاگردان
+معبد
+آرمان
+۱۹۶۲
+بیماری‌های
+بچه
+فعالان
+کوروش
+دارویی
+اوقات
+اوست
+می‌کنند،
+قضاوت
+ین
+دست‌اول
+فریدون
+تئوری
+نمی‌توانید
+دوستی
+حقیقی
+زندانی
+مقطع
+راستش
+۱۹۶۳
+شاپور
+۱۹۵۶
+آکادمی
+بازنویسی
+ارمنی
+۱۹۶۱
+مهران
+مردمی
+ندارید
+گذاشتن
+کوتاهی
+فقه
+تنکابن
+درجه‌بندی
+ژنرال
+مایع
+طرفداران
+مدارک
+بدلیل
+پیشنهادی
+باشند،
+ذرات
+دانشجویی
+نگارخانه
+نیت
+کیلوگرم
+سردشت
+ایده
+تسلیم
+برادران
+هزاران
+حادثه
+مرتضا
+خواستار
+نهضت
+نرسی
+آمیز
+استودیو
+قدمت
+مجموعهٔ
+مغناطیسی
+قطعات
+عمران
+توجهی
+فیلم‌ها
+كار
+۶۳
+رسم
+درب
+مبتنی
+امواج
+تمایل
+احزاب
+روحانی

+اردن
+۶۱
+عمارت
+می‌دانید
+گفتار
+دزفول
+داوری
+کا
+حقوقی
+زمستانی
+فولاد
+امریکا
+مزرعه
+بوده،
+رساله
+رامین
+جراحی
+محقق
+ابزارهای
+ویکی‌
+پزشک
+قبلاً
+ضلع
+سرور
+مجاهدین
+اخلاق
+گراف
+مانع
+مشارکت‌کنندگان
+قشلاق
+نوازنده
+پرده
+۱۹۵۳
+شیروان
+کاظم
+اریکسون
+طیف
+مسکو
+۱۹۳۰
+۶۸
+مقابله
+لوله
+علی‌آباد
+واقعاً
+معدنی
+طباطبایی
+شاهان
+تاريخ
+ودر
+ماهان
+یوشیمیتسو
+۱۹۴۵
+نمونه‌هایی
+البرز
+چهارمحال
+مالزی
+۱۹۵۸
+خودرویی
+بیاورید
+آبادی
+مخابرات
+می‌دهید
+رودبار
+جور
+یحیی
+كتاب
+وین
+می‌داد
+غلامرضا
+طایفه
+سطر
+خواهیم
+جانشین
+اقامت
+توده
+مشارکت‌های
+برود
+جویا
+می‌روند
+نتیجهٔ
+اختیاری
+اساتید
+آگاه
+ساوه
+قدس
+ناخالص
+چرخ
+پردازش
+خرم
+به‌
+کاربردهای
+فیلسوفان
+طب
+زمانه
+وحدت
+افغان
+منوچهر
+طرز
+بوسیله
+مدیری
+اخذ
+اصلاحات
+فرهاد
+۱۳۷۳
+بایرن
+تور
+۸۲
+بست
+راحت
+تقلید
+لهجه
+قرون
+افسانه
+۶۷
+منزل
+۰۰۰
+رکوردز
+تأثیرات
+افتتاح
+بزرگتر
+هندوستان
+نقره
+بهشتی
+پذیر
+عظیم
+سیم
+خواص
+اعتراضات
+سخنان
+رزیدنت
+مسجدهای
+هرگونه
+می‌آورد
+این‌ها
+دقیقاً
+بسکتبال
+صوت
+بوئین
+۱۲۰
+۱۵۰
+شور
+زودی
+توانند
+سربازان
+رویداد
+خب
+بنیان
+چلسی
+زیبای
+شورش
+خامنه‌ای
+برایم
+درخواستی
+روان‌شناسی
+جسم
+ممنوعیت
+اهورا
+چقدر
+ابوالحسن
+سالن
+صحت
+می‌خواهد
+۹۶۴
+نرخ
+اختلال
+رویدادهای
+خراب
+تونی
+دایره
+دبیر
+۸۱
+۱۳۶۸
+دانشگاه‌ها
+تقویت
+زلزله
+دهانه‌های
+کوهستانی
+محض
+۱۹۵۴
+نبودن
+بين
+کارکنان
+جملات
+خاکستری
+دادید
+فرایند
+دارا
+وفيات
+چهارصد
+خصوصیات
+چارلز
+گفتند
+ستاد
+۱۰۰۰
+پیتر
+انگلیسی‌زبان
+مجتمع
+وسعت
+می‌شدند
+۱۳۷۴
+نیروگاه
+گذار
+قوچان
+تحصیلی
+دهی
+میلان
+نمی‌کنم
+فرم
+پستانداران
+گردن
+۱۳۷۲
+۱۹۴۰
+جناح
+شوشتر
+پذیری
+لیبی
+اسلامی،
+بحث‌های
+سوء
+همسرش
+قفل
+اسکندر
+تحلیلی
+تحمل
+فعلاً
+۱۳۵۴
+میوه
+مصنوعی
+ارزیابی
+روزانه
+مدعی
+دانمارک
+فرستاده
+شناسه
+صبر
+شطرنج
+گفتید
+وسیع
+گام
+گوشت
+کرده،
+رصد
+کوهدشت
+اینطور
+نوجوانی
+ملت‌های
+محمدی
+۶۹
+لشکر
+بزرگراه
+۱۹۵۲
+پاینده
+۴۰۰
+جانبی
+ایول
+تجدید
+نیست؟
+حامد
+نشریات
+توماس
+مجازات
+قیام
+گپ
+سینا
+۷۸
+بس
+وظایف
+کوهستان
+اینجاست
+میدهد
+کارها
+سالها
+یادبود
+آبادان
+طبس
+خوردن
+روزه
+مسکونی
+اعظم
+دموکرات
+خشونت
+۸۳
+هوشنگ
+تخصص
+سیما
+منظر
+علمیه
+سالم
+پیکسل
+کمکی
+خواسته
+ایرج
+مدنی
+گفتن
+آذربایجانی
+ره
+اتمام
+آلاباما
+۱۹۲۰
+ابی
+بام
+فقیه
+کیلومترمربع
+عوارض
+۱۳۵۰
+ترس
+بازگردانی
+سعدی
+موثر
+کلیبر
+انقلابی
+وبسایت
+روانی
+موردی
+دختران
+روس
+بم
+پاک‌کن
+داشته‌اند
+یوتی‌سی
+صدها
+پانویس‌ها
+نفتی
+ورزقان
+کمبود
+نابود
+فرانک
+دان
+۷۶
+جرج
+جدایی
+کیهان
+نامش
+تبریزی
+کتیبه
+حکومتی
+قسمت‌های
+صرفا

+۷۱
+اندازی
+قدم
+منحصر
+عموم
+پهنای
+پدیده
+روغن
+رسانه‌های
+اطلاعات،
+سایت‌ها
+اکران
+سلامت
+بالاترین
+پیروی
+۱۹۵۱
+مصداق
+۷۳
+شکار
+مباحث
+پوویا

+فاصلهٔ
+فاز
+۷۷
+حالیکه
+شهریار
+۱۹۵۷
+درخشان
+آن‌جا
+تنهایی
+نکرد
+عدالت
+می‌نماید
+مقبره
+سانسور
+داده‌ها
+شاهرود
+تخمین
+نشست‌های
+۱۹۳۶
+جین
+روبرو
+پس‌زمینه
+نیرو
+اخلاقی
+داستانی
+سینه

+شاهنشاهی
+مولانا
+گاو
+استخوان
+گرگ
+دکتری
+اند،
+کشف‌های
+سنندج
+۷۴
+ساحلی
+برهان
+پیش‌نمایش
+کردم،
+دوره‌های
+۱۳۵۶
+آغازین
+سالانه
+بستگی
+تخم
+۹۹
+سیگنال
+ویکی‌پروژهٔ
+ناقض
+خودمان
+کرد؟
+ویرایشگران
+داوران
+برداشته
+۱۳۷۱
+یکمین
+ریزشگاه
+سوار
+سلاح
+شایسته
+سفیدپر
+غزه
+ترکیبات
+لاله
+اولی
+گذر
+جک
+ذیل
+دراز
+۹۵
+پان
+درصورت
+ایرانشهر
+عرصه
+پیروان
+پردازنده
+زایش
+مدینه
+انفجار
+کمپانی
+فرشتهٔ
+واحدهای
+حرارت
+بعداً
+۱۹۴۹
+همینطور
+استخراج
+ملاقات
+فرو
+پارامتر
+منتقدان
+آزمایشگاه
+نوشته‌شده
+اصطلاحات
+بتوانند
+مشتری
+متوقف
+اجباری
+مسلح
+سلجوقیان
+کندی
+اسکاتلند
+فیلسوف
+می‌سازد
+زود
+۷۹
+رجبی
+هفتصد
+تقی
+معدن
+مار
+فراز
+ایالت‌های
+ایمان
+ابراز
+ممسنی
+رادیویی
+سرکوب
+پیوندها
+۱۹۵۹
+توزیع‌کننده
+کشید
+بال
+۱۳۵۸
+۱۹۵۵
+شفاف
+کلام
+یکبار
+رصدخانه
+موسوم
+صلاح
+اخیرتان
+کالج
+واز
+شیکاگو
+جنبه
+۱۳۶۹
+عاشق
+کک
+خنثی
+امیرکبیر
+آنقدر
+زبان‌شناسی
+مشاور
+نمایشگر
+دا
+مِنْ
+آرزوی
+آئین
+می‌آیند
+شکلی
+۱۳۶۰
+سقف
+فرامرز
+بحث‌ها
+همت
+خیام
+تصادفی
+میتواند
+تجاوز
+روح‌الله
+روستاها
+هواپیمایی
+گلدن
+منظورتان
+کرمانی
+قله
+ضربه
+ساکنان
+اورشلیم
+مجدد،
+ویکی‌پ
+معتقدند
+۱۹۳۸
+محیطی
+جعفری
+خطا
+ویروس
+نگار

+سال‌ف
+ابراهیمی
+هشتصد
+نکنم
+ذوب
+رایت
+هاست
+متنی
+نان
+اضافی
+باله
+اصغر
+تایلند
+را،
+پیانو
+سکونت
+تالیف
+اختصاصی
+بهتری
+ترابری
+چو
+دیو
+زندگی‌نامه
+شیشه
+قلبی
+تحریک
+کیش
+ستاره‌ای
+اختراع
+برآورد
+سزار
+دهستانی
+مجسمه
+برطرف
+سپرده
+پارلمان
+رمز
+درسی
+سپاهان
+منصوب
+۱۹۴۱
+پروانه
+جمع‌بندی
+فعل
+کربن
+دژ
+تفکیک
+قفقاز

+همراهی
+عبدالحسین
+بسيار
+مواليد
+۲۵۰
+پیرو
+معاونت
+پیرانشهر
+۹۱
+معنوی
+کاروانسرای
+دفن
+سیزدهم
+ند
+اینقدر
+هخامنشیان
+دستگیری
+گل‌های
+می‌خواهم
+گیرند
+متفاوتی
+شیلی
+مراکش
+کنسرت
+بدهم
+تومان
+کهکشان
+اوضاع
+اندونزی
+چنانچه
+جایزهٔ
+بدهند
+کروبی
+سکه
+گرفته‌اند
+می‌شوم
+تضاد
+ملایر
+شیطان
+سهم
+اخطار
+حرم
+موافق،
+هیتلر
+واسطه
+ناظر
+نمودار
+بگوید
+تیمور
+قصر
+مکانی
+فرودگاه‌های
+۱۹۴۶
+جهاد
+مقداری
+داد،
+اندک
+دکترای
+فیلیپ
+۱۹۳۳
+کارگران
+آماری
+۹۸
+تست

+هستی
+میزبان
+تقاضای
+اوبلاست
+شیوه‌نامهٔ
+من،
+محتوا
+مربیان
+دیسک
+معتبری
+زدایی
+صعود
+حکمت
+مخفی
+زمینهٔ
+دهان
+گو
+رمضان
+ششصد
+هم‌اکنون
+شکسته
+‌است
+حرفی
+۹۶
+هواداران
+تبعید
+نشین
+توجیه
+مکه
+جاذبه‌های
+منافع
+بیفزایید،
+عرفان
+کشی
+آمریکایی‌های
+عقل
+وفات
+سیب
+پربارتر
+کنه
+تألیف
+بنیانگذار
+دموکراسی
+نهصد
+یادم
+سراسری
+تفکر
+لارستان
+برگزیدگی
+رباط
+لس
+حساس
+حبیب
+ویکی‌پدی
+فرود
+همکاران
+تشویق
+تحویل
+باقری
+داده‌های
+معرض
+گلوب
+کلیسا
+ویکی‌پد
+کف
+۱۳۶۷
+امضای
+بخواهیم
+خالد
+فلزی
+نظرخواهی‌ها
+آیات
+درگذشته
+شباهت
+هم‌چنین
+تعلق
+بگیرند
+گوناگونی
+نایب
+حساسیت
+کارگردانان
+مغول
+سازمانی
+دیا
+داغ
+خواهی
+فشرده
+ماجرای
+زندانیان
+تصاویری
+بیماران
+کهنه
+مکمل
+بخواهید
+رایگان
+رویه
+ماری
+فرمایید
+بلورین
+فورد
+درخواست‌های
+سازد
+پروتکل
+راس
+فرقه
+وفق
+نازی
+احتمالی
+طلب
+اقماری
+محدودیت
+همایون
+۱۱۰
+هیأت
+احسان
+ابرخس
+بخواهد
+له
+مهرداد
+می‌شوند،
+سکوت
+مهاجر
+صدور
+بازیگری
+آسان
+سراغ
+اولا
+محلول
+وان
+کوی
+الکساندر
+لیسانس
+خزر
+۹۲
+شکنجه
+امیررضا
+گرجستان
+بازرسی
+عکاس
+۱۳۶۲
+آسیاب
+گویی
+شود؟
+حیاط
+موجهی
+ارکستر
+ارباب
+نویسندهٔ
+یخ
+السلام
+نسب
+بوی
+۱۹۴۷
+نمي
+اعضا
+خانوادهٔ
+ویکیپدیای
+سحابی
+شاهی
+شیوهٔ
+زیارت
+تحقیقاتی
+فعالیتهای
+کاغذ
+تهرانی
+پروفسور
+بریتانیایی
+اخیرا
+ایرنا
+مادرید
+۱۳۵۵
+زمینه‌های
+ببینم
+۱۹۳۴
+می‌بینید،
+فیفا
+صالح
+متداول
+ربط
+سطوح
+ی‌پدیا
+خواهدشد
+بحران
+۱۹۳۹
+افکار
+پیراهن
+۱۹۳۲
+انتظامی
+بلافاصله
+ارایه
+کمیسیون
+راز
+محمدحسین
+آبیلا
+محبوب
+سایه
+جوامع
+داور
+۱۹۰۰
+زودتر
+ولز
+سوخته
+تأیید
+ابوالقاسم
+برادرش
+بمب
+امتحان
+آرتور
+فرستاد
+صص
+دانشجوی
+کارگر
+هوش
+اتفاقا
+غلامحسین
+قربانی
+می‌خورد
+احکام
+سرزمین‌های
+ضمناً
+فینال
+قبرستان
+ضعف
+نامهای
+گندم
+قواعد
+تند
+تایپ
+ماموریت
+موسیقی‌دانان
+گوشه
+دری
+مناسبت
+ارقام
+چاراویماق
+مبانی
+گذاشته‌اید
+ابر
+مدخل
+یو
+شناس
+اندازهٔ
+غالب
+قنات
+مبتلا
+ویکی‌فا
+نوزدهم
+مونیخ
+کابینه
+میرحسین
+باقر
+۱۹۳۵
+سامان
+هلندی
+موجودات
+فنلاند
+برعهده
+مدافع
+قطار
+تغییرات،
+فرمانروایی
+واگذار
+حکیم
+آهنگسازان
+شوند،
+تحول
+مرکب
+مقادیر
+اختیارات
+نوشتاری
+چندانی
+جان،
+هکتار
+رازی
+محله‌های
+آوردند
+صف
+مقاله،
+تدریج
+نیستید
+تسلط
+اسلام‌آباد
+آزمون
+ویرایشاتشان
+اصولا
+صفت
+۱۹۳۷
+می‌شد،
+سفیر
+تمرکز
+شهروند
+نمودن
+ویتنام
+نمایندگی
+گردش
+سران
+فر
+ایمنی
+خو
+مشارکت،
+پسرش
+می‌ماند
+متروی
+ختم
+علمای
+۱۳۶۴
+ران
+کودتای
+قهوه‌ای
+دایرة‌المعارف
+لنگه
+درونی
+سرا
+خاموش
+منصب
+ماد
+دومی
+کشور،
+سوادکوه
+خدایان
+بی‌طرف
+ماجرا
+دماوند
+بردسکن
+ویکی‌نویس
+ماهنامه
+یادگیری
+قابل‌
+هاشم
+همگان
+روانشناسی
+محمدآباد
+نگهبان
+آفرید
+گیرنده
+۱۳۵۲
+۱۳۸۹،
+ترکان
+هوی
+دندان
+خوش‌آمد
+گرفتم
+پایهٔ
+دانلود
+جفت
+فهم
+گوشزد
+متشکل
+رسمیت
+مقدماتی
+جویباری
+پيش
+کنیم،
+استانداردهای
+سرجعبه
+آنجایی
+خیریه
+بیش‌تر
+في
+دکمه
+ماندگار
+فیروزآباد
+بخار
+فیلیپین
+جلگه
+آرامش
+۹۳
+رونق
+پاسداران
+میتوانید
+کاووس
+۱۳۵۳
+۶۰۰
+مرو
+نیافتید،
+نداره
+نجفی
+الهام
+میکنید
+ناصرالدین
+قصه
+آمدند
+پراکنده
+خواهان
+روي
+مرودشت
+مسیحیان
+عبدالهی
+حسابی
+پاییز
+جانبدارانه
+کی‌پدیا
+حین
+پلی‌استیشن
+اعصاب
+می‌توانیم
+فرح
+نمک
+به‌طور
+۹۷
+۱۳۵۹
+گرافیک
+زمین‌لرزه‌های
+منتهی
+مستقر
+تقدیر
+۱۹۳۱
+می‌رفت
+افسانه‌ای
+برخط‌اند
+آبشارهای
+برخوردی
+عکسی
+خاور
+مورخ
+جمال
+باتجربه‌ترند
+به‌کار
+مطالبتان
+راه‌آهن
+نفع
+پاجعبه
+نسخه‌های
+بدی
+آکادمیک
+امتداد
+یوشیچی
+رضاشاه
+تأمین
+خواهشمندیم
+لو
+رئال
+خراسانی
+سردر
+آشپزی
+ایرانیکا
+شاگرد
+سرای
+یزدی
+نامزدهای
+وکیل
+نقشهٔ
+اکسیژن
+شفافیت
+یکی‌پدیا
+مقیم
+ویل
+یادآوری
+بلوری
+شعاعی
+قائم
+آلن
+استانبول
+بکنید
+عمیق
+تایمز
+سلماس
+بی‌طرفی
+بیل

+بویژه
+تک‌آهنگ‌های
+می‌باشد،
+جماهیر
+وحشی
+نمایشنامه
+روایات
+غنی
+کسروی
+بازتاب
+شاملو
+اروپای
+برنج
+بيشتر
+اخراج
+جمعیتی
+اخترسنجی
+شوش
+خوشنویسی
+تقاضا
+مکان‌های
+کریمی
+۱۹۲۹
+دفاعی
+برگشت
+کنید؟
+معمار
+خوش‌حال
+قوه
+۱۳۶۵
+اکسید
+لاهیجان
+آئیله
+عقاب
+پائین
+سوالی
+کنم،
+مان
+خواف
+انجیل
+محاکمه
+ور
+كنيد
+میخی
+مرزهای
+روشی
+بل
+آداب
+زرتشتی
+باشی
+جهرم
+آور
+شهادت
+رسیده‌است
+سادات
+زحمات
+بنویسم
+شریعتی
+بان
+مرتبه
+آثاری
+شه
+کابلی
+تویوهارا
+بیجار
+می‌زند
+نگران
+کر
+سیرجان
+اماکن
+ایلخانی
+ماست
+گزینه
+دوشنبه
+شواهد
+قاعده
+موازی
+شتاب
+۱۳۶۶
+حال،
+ویا
+می‌برند
+۱۹۲۴
+نت
+نجومی
+تعارض
+سادگی
+۱۳۰
+خلافت
+تأثیرپذیرفته
+طبری
+تعقیب
+کاشانی
+منع
+توضیحی
+دورود
+حبس
+بهایی
+محاسبات
+بگوییم
+تنوع
+معادله
+۱۳۵۱
+کوچکتر
+جوی
+دورنما
+شرایطی
+فرماندار
+هریوا
+پی‌گیری
+۱۹۲۸
+می‌نامند

+فومن
+الجزایر
+سیاست‌مداران
+۹۴
+مقدم
+طرفین
+چمن
+صفویه
+یر
+نابودی
+رفسنجانی
+معادن
+۱۳۴۷
+نیل
+سانتی
+دام
+نامه‌ای
+ات
+یافته‌است
+می‌دارد
+بقعه
+۸۰۰
+پرتو
+قید
+ظرف
+لری
+قدیمی‌ترین
+انسان‌ها
+برنامه‌ریزی
+وسطی
+مسلم
+چالوس
+پیشتر
+پوشیده
+فرزان
+میشوند
+منظم
+تلفن‌های
+خوشحالم
+تجمع
+رنج
+آباد،
+مختصر
+هماهنگ
+روشهای
+لفظ
+چوبی
+همين
+شادی
+وسیعی
+گور
+کردیم
+تندیس
+مواقع
+الیگودرز
+نسبتاً
+هٔ
+مخصوصا
+شی
+مشهورترین
+می‌خواستم
+انها
+نهنگ
+حرکات
+دنباله
+قانع
+۱۹۴۲
+داوود
+می‌کردم
+جاوا
+تعادل
+پزشکان
+نحوی
+مادی
+ردهٔ
+گذاشتم
+۱۳۶۳
+کمان
+بعدا
+شرمنده
+ویراستار
+ایام
+اسلواکی
+ناراحت
+متحرک
+تجربی
+خاصیت
+گیلانغرب
+کشتن
+مرزی
+پرچم‌ها
+ذهنی
+لر
+مساوی
+رستمی
+کرم
+ازبکستان
+رضایی
+احیا
+هنگ
+توانم
+شکر
+مند
+کمتری
+بردارید
+قبر
+فرعی
+ایم
+معارف
+پیوندی
+اطلاع‌رسانی
+بسازید
+کردند،
+کلیدی
+سيستم
+لغو
+بسیج
+سرنوشت
+شاخه‌های
+طرفدار
+سیاوش
+کشیدن
+پناه
+هشترود
+ورزشگاه‌های
+صفحه،
+عارف
+ابرکوه
+،خرد
+دراین
+بایر
+قلی
+دشوار
+بیزانس
+بهانه
+جالبی
+قبیله
+بیژن
+چنانکه
+می‌
+بیانیه
+آلفا
+کارگاه
+استوار
+کش
+پویا
+چیزهایی
+نمی‌کنند
+رهنمود
+وصل
+کریس
+پسوند
+مهاجم
+جامعه‌شناسی
+مجددا
+ایر
+احتیاج
+متأسفانه
+خودکشی
+۱۳۴۸
+مراتب
+یازدهم
+خام
+نوجوانان
+بدانم
+طنز
+چهره‌های
+شبانه
+دامغان
+مقصد
+وزیران
+لوح
+شهرام
+بده
+جلا
+دشتستان
+روزنامهٔ
+چهارشنبه
+دالاهو
+ضریب
+تکنیک
+سرخس
+ولي
+دکترا
+آنجلس
+خرس
+مجتبی
+نهاوند
+مسیه
+حسینیه
+كنند
+ملاک
+۳۶۰
+هندسه
+ابو
+کامپیوتری
+۱۳۴۵
+۱۰۱
+صندوق
+بلی
+آقایی
+قالی
+۱۹۲۵
+اشتغال
+اوستا
+خاش
+باتری
+قربان
+رمان‌های
+زير
+خالص
+زدم
+باشد؟
+توقف
+دوستانی
+اجتماع
+کوهی
+کلاه
+قائل
+فلز
+مطلوب
+گربه
+نگرانی
+زوج
+یار
+سرپل
+نوروزی
+۱۹۲۶
+الآن
+اختلالات
+بریتانیکا
+ايجاد
+آزار
+سا
+پروتئین
+بادی
+مجزا
+سانتیمتر
+اله
+پسران
+۱۳۴۶
+دروس
+کور
+مطلع
+نستعلیق
+خطرناک
+لوگوی
+دنده
+ویژه‌ای
+بهینه
+الکترون
+سقز
+عددی
+کاش
+جیرفت
+راسته
+بتوانم
+نسبتا
+یازده
+کمیل
+مانفی
+انتخابی
+نداشتن
+حرکتی
+کمترین
+مرورگر
+مقاله‌ی
+برنز
+انشای
+فراتر
+وسیلهٔ
+انزلی
+سوم،
+آشور
+اجزای
+روزنامه‌های
+نداشتند
+برتری
+توقیف
+گنجایش
+نویسندگی
+واشینگتن
+وَ
+عبد
+ماهیت
+ترکمن
+تابش
+برف
+اثرات
+نمایشی
+است‌
+حدس
+بین‌الملل
+۱۹۲۳
+راوی
+بامداد
+تنگه
+گذراند
+اتفاقی
+هالیوود
+گشته
+اسمیت
+باش
+آلی
+ترکمنستان
+سوسیالیستی
+مجلات
+۱۹۱۸
+بدنه
+قاهره
+خانهٔ
+بید
+ایرانی،
+۱۳۴۰
+پری
+اشتباهی
+نهاده
+وب‌سایت
+شهروندان
+همایش
+خوان
+نژادی
+عملیاتی
+افزود
+مخلوط
+رودسر
+الیزابت
+نمونه‌ای
+مغزی
+قضایی
+یان
+گالری
+بگو
+ملقب
+ایفا
+انیمیشن
+بخش‌هایی
+شکستگی
+سوپر
+کانی‌شناسی
+ویتامین
+می‌دادند
+پرجمعیت
+درسال
+۱۰۵
+ستاره‌های
+مدیا
+بندپی
+تردید
+كشور
+ماهیان
+پوزش
+انگار
+اسلام،
+ايشان
+سرپرستی
+تاکستان
+۱۹۲۷
+۱،
+پذیرفت
+نما
+مشتق
+باستان‌شناسی
+امامی
+اتم
+ندیدم
+نوشهر
+گزیدن
+۱۹۱۹
+حیوان
+بنظر
+کورش
+اواسط
+رفتند
+تبادل
+میلی
+استون
+دانستن
+آمریکا،
+حصار
+آینه
+گرایی
+قبایل
+کبیسه
+۱۹۴۳
+۱۹۱۲
+۱۹۱۷
+برقراری
+فيلم
+نداشتم
+سرده
+فعالیت‌ها
+بوستان
+خیال
+کارش
+کربلا
+کنم؟
+سیاست‌مدار
+معنایی
+آلودگی
+شماری
+کودتا
+پانزده
+المعارف
+کالبدشناسی
+عظیمی
+علائم
+کنسول
+نحو
+سوئدی
+گرفت،
+مازندرانی
+مثال،
+منسوب
+نشدم
+ویران
+درخشندگی
+بندرعباس
+ارگ
+سامانه‌های
+بیمه
+انجامید
+اردکان
+متمرکز
+سلولی
+مرسوم
+صادقی
+هيچ
+امثال
+ولتاژ
+مقررات
+رکورد
+بلخ
+نامزدی
+پردیس
+راه‌های
+‌ای
+مانده‌است
+هدیه
+خاکی
+کلاً
+كنم
+جویبار
+گرجی
+سنجش
+بو
+مثلث
+جمهوری‌های
+خاتمه
+رشتهٔ
+بوش
+حسین‌آباد
+۱۳۴۹
+جنگلی
+عزل
+مزار
+اختلافات
+زاکسن
+عشایر
+دشمنان
+کنگ
+یهودیت
+الگویی
+فرکانس
+تحریف
+پژوهش‌های
+شام
+لار
+می‌بینید
+مریخ
+علی‌اکبر
+عامه
+روزها
+زخمی
+عبارت‌اند
+ویکی‌های
+بری
+کارائیب
+رده‌فرد
+رحیم
+نگاشته
+القاب
+قاتل
+مکرر
+محمد،
+ابداع
+ویدئو
+اسطوره
+جامد
+ژنتیک
+مجاور
+سیاسی،
+رفسنجان
+بعید
+مرند
+روحانیون
+اریک
+قریب
+نثر
+تحریم
+موزیک
+برداشتن
+ارتفاعات
+اشکالی
+غذاهای
+شهاب
+بورس
+سال،
+نقشه‌های
+عروس
+نخل
+محلات
+آلبرت
+فا
+دشمنی
+۱۹۴۴
+يكي
+جایگزینی
+تفاصیل
+خدابنده
+اقلیت
+مشخصی
+محاصره
+زین
+افتخارات
+این،
+بي
+سواحل
+اندام
+فرماندهان
+دانند
+دوازدهم
+بجز
+آرا
+بهائیت
+۱۹۲۱
+کالا
+استقرار
+تلخ
+تکه
+جلوه
+امان
+نگونبانگونی
+فیلمنامه
+مترجمان
+کتاب،
+بستر
+تولیدی
+باغ‌های
+نباشند
+انصاری
+محمدتقی
+ان‌جی‌سی
+سلمان
+پهن
+گستره
+سودان
+پرهیز
+همون
+موسسات
+جاهای
+اشرف
+سواد
+مصوب
+دانه
+اينكه
+شعبه
+تشیع
+اپرا
+مجری
+موضع
+۱۴۰
+گلوله
+دارایی
+آوردم
+۱۸۰
+بلد
+سیروس
+گرمسار
+مهارت
+پیشاپیش
+ساختمانی
+باختر
+نامید
+ایفای
+باریک
+تعجب
+عقد
+فرمودید
+وطن
+گوی
+قبرس
+محبوبیت
+کوچ
+جدید،
+اخترشناسی
+کلمهٔ
+ایذه
+احوال
+پراکندگی
+ویرایش‌ها
+سانتا
+نپال
+چرخش
+فخرالدین
+دستگاه‌های
+پاراگراف
+می‌توانم
+پیکر
+بعد،
+جای‌ها
+یاران
+بیگ
+پنجره
+رامسر
+خواه
+انکار
+می‌کشد
+۱۹۲۲
+برعکس
+پاره
+اکشن
+لغات
+گردآوری
+سهراب
+نیز،
+عراقی
+پاسارگاد
+نوجوان
+مخفف
+هیچگاه
+کاندید
+بهروز
+بناب
+تهمت
+آفریقایی
+جسد
+پژوهشگران
+موسس
+بلاگ
+آبخواره
+مایه
+مجدداً
+لقب‌ها
+تلسکوپ
+استانی
+منتقد
+داراب
+دلخواه
+فرش
+بارگذاری‌شده
+صحرای
+نوک
+فارسي
+رسانه‌ها
+ماکو
+۱۳۶۱
+استفادهٔ
+دستیابی
+سرو
+بردار
+آلبوم‌ها
+مکعب
+تب
+می‌گرفت
+وی،
+قطعی
+اقبال
+پلاک
+برابری
+جوش
+التحصیل
+بردند
+شارل
+خشم
+سارا
+گناه
+حوصله
+بیافزایید
+اصیل
+خودمختار
+نمی‌دهد
+داند
+سراوان
+صور
+یعقوب
+شنیدن
+اشتراک
+دفع
+اد
+ه‍
+وستفالن
+بهائیان
+پناهگاه
+مسیرهای
+هست،
+مذاهب
+گران
+تابعیت
+یابی
+ولسوالی‌های
+اسرائیلی
+تاریکی
+تعطیل
+همکار
+زور
+خلیل
+شوخی
+سلول‌های
+تنش
+کرسی
+نصف
+می‌افتد
+بیات
+فضل
+نامشخص
+تعبیر
+۷۰۰
+شو
+سوسیالیسم
+اب
+پرچمک
+دموکراتیک
+تحولات
+بگیریم
+گسترده‌ای
+آریایی
+کیلو
+والی
+براون
+ناچار
+گنج
+بلندترین
+انگشت
+محتواهای
+۱۳۸۵،
+نه؟
+یهود
+وضوح
+بلوک
+بلور
+باکیفیت
+غير
+بدل
+نادیده
+لاریجان
+دلفین
+جاز
+حاکمان
+دوری
+آرای
+خاوری
+شناختی
+ماریا
+شیب
+نیوزیلند
+مشکین
+منتظری
+خریداری
+۱۱۵
+جانی
+به‌شمار
+تعلیم
+تأکید
+اندازه‌گیری
+یافتند
+مادری
+فون
+بادن
+کدهای
+بدنی
+لوئیس
+ادامهٔ
+مبلغ
+صلیب
+می‌بایست
+آریا
+۱۲۵
+بفرمائید
+قراردادی
+شر
+گفت‌وگو
+گرینویچ
+مولکولی
+نیو
+سايت
+۱۹۱۴
+جزیره‌های
+رسیدند
+فرمت
+قائم‌شهر
+تفرش
+نظریهٔ
+خواستید
+هافبک
+دائمی
+تنیس
+می‌دهد،
+ماتریس
+باخت
+سیا
+مغرب
+سل
+اسلحه
+ذهاب
+دهد،
+فرقی
+صرفاً
+وبلاگ‌ها
+نمیشود
+راضی
+آتن
+چراغ
+حالتی
+شلیک
+الیور
+اینکار
+برپا
+آهنگرکلا
+لویی
+نیما
+بجنورد
+نهادهای
+محروم
+نکا
+لب
+وحش
+اعتراضی
+ژن
+ويكي
+عثمان
+نیشابوری
+بلک
+کنندهٔ
+موتورهای
+رئیس‌جمهور
+حکایت
+حاکمیت
+نفره
+هرسین
+مالیات
+انجام‌دادنی‌ها
+خودت
+مناقشه
+کارهایی
+غذای
+نوردراین
+علل
+دیپلم
+دادگستری
+پیچ
+لیورپول
+سرپرست
+گلی
+تفت
+جنسیت
+امری
+صبا
+اسفراین
+ریخته
+برا
+ناپلئون
+دبستان
+ویدئویی
+خمیر
+انتخاباتی
+گفته‌است
+ورزشکاران
+عادت
+آرایه
+اعتراف
+استخدام
+آرامگاه‌های
+دوتایی
+ارنست
+عمدتا
+مجهز
+زدند
+۱۳۳۰
+۱۳۸
+۱۳۳۲
+آلبانی
+نشانه‌های
+باغین
+شعبان
+فارسی‌زبان
+نیمی
+سازگار
+زبانان
+پیست
+کارایی
+گرافیکی
+کوره
+اتیوپی
+ساوجبلاغ
+مشرق
+فِي
+سیزده
+۱۰۳
+مردم‌شناسی
+بلندی
+محمودآباد
+بتا
+۱۰۲
+مراد
+افتخاری
+سهام
+امیدان
+دلایلی
+غول
+۲،
+مازیار
+عمدتاً
+مملکت
+۱۳۴۲
+انگیزه
+فرنگی
+مینودشت
+بقایای
+ابوالفضل
+فاکس
+میگوید
+همچنين
+شعری
+لس‌آنجلس
+تائید
+تاریک
+تونس
+بستان‌آباد
+کارمندان
+اسحاق
+۱۶۰
+کارگری
+پتانسیل
+سحر
+۱۰۹
+نیازهای
+آرسنال
+افزون
+نظریات
+کوبا
+فهرستی
+آزادگان
+کارشناسان
+تزریق
+کاپیتان
+حدودی
+فیل
+والیبال
+ازای
+این‌گونه
+همانگونه
+نداده
+سردبیر
+تالش
+سام
+می‌گذرد
+آنتی
+مجلهٔ
+بازی‌ها
+رجال
+هم‌درازا
+دختری
+رفته‌است
+ابریشم
+فلوریدا
+بلغارستان
+مصری
+بلوار
+دليل
+راه‌اندازی
+۱۰۴
+شمشیر
+ندا
+صادرات
+دانیل
+هریس
+کله
+حوزهٔ
+نشسته
+بیاندازید
+۱۲۸
+وبه
+تازگی
+شورا
+سروده
+درمورد
+شدند،
+قطعا
+اراضی
+می‌گویید
+حامی
+خوراکی
+جایزه‌ها
+کویر
+مفهومی
+رودهای
+زمان،
+کمیاب
+مخاطب
+سوابق
+سلامتی
+علوی
+خواندم
+نهایتا
+هوشمند
+همیشگی
+همدیگر
+سازه
+ترویج
+مقر
+قشم
+تغيير
+دیروز
+مخالفم
+نجوم
+آرزو
+عموماً
+افقی
+گوشی‌های
+رباتیک
+کلاته
+لورنس
+وزیری
+پرداختند
+رجب
+جوزف
+سپری
+تایوان
+مقاله‌هایی
+بود؟
+بزند
+مرسی
+باختری
+صلاحیت
+نمی‌آید
+بهشهر
+جماعت
+خونی
+نوشته‌است
+ازنا
+مکانیکی
+فضاهای
+فرمانروایان
+رزمی
+همسایه
+همدانی
+۱۹۰۸
+۱۹۰۵
+هردو
+۱۱۴
+هرم
+شهرکرد
+۱۰۷
+آب‌های
+متقاعد
+شویم
+نبود،
+نویسان
+هم‌زمان
+شهر،
+صخره‌ای
+ارزشمند
+۱۳۲۰
+حذفش
+سامی
+ثانویه
+دن
+احساسات
+بوئینگ
+نام،
+شبکهٔ
+شمرده
+طوایف
+باری
+جبر
+اجازهٔ
+بزرگ،
+بهم
+۱۱۱
+جهان،
+مولوی
+تفریحی
+ماساچوست
+آنها،
+اجتماعی،
+طاق
+خوشامدید
+نیامده
+اچ
+ملاحظه
+کمبریج
+زی
+برش
+می‌گذارد
+شدگان
+بدو
+درحال
+چارچوب
+شده‌اند،
+قطبی
+لئون
+هیدروژن
+کاردانی
+درمیان
+نقاشان
+شنیده
+چنين
+آتشکده
+کوههای
+قروه
+هجوم
+سرهنگ
+عکس‌های
+تاجگذاری
+خرج
+۱۳۴۴
+جعلی
+آمیزش
+راهپیمایی
+سرشار
+فیروز
+دوک
+بهداشتی
+شکی
+ماهواره‌ای
+طاهره
+زیرصفحه
+تسخیر
+مخزن
+حیدر
+اتفاقات
+غزل
+زهج
+بولیوی
+کردها
+۱۹۰۱
+قند
+نخست‌وزیر
+بازهم
+عصب
+مهاباد
+پرس
+گازی
+ابزاری
+مبدل
+۱۳۵
+میشل
+مستقیما
+صدام
+محکم
+فلزات
+طنابداران
+پروژهٔ
+امّا
+صحرا
+۱۰۸
+جملهٔ
+شوهر
+هواپیماهای
+سعادت
+جعل
+صفحه‌کلید
+اوباما
+۱۹۰۶
+انب
+اپل
+مرخصی
+معیارها
+دانید
+دعا
+تلفات
+تضمین
+آرامی
+دائم
+شد؛
+چرخه
+شجره‌نامه
+آفرینش
+معادلات
+رسما
+مزبور
+بارش
+برکه
+نبی
+مصالح
+والتر
+سدیم
+بحثش
+پیشگیری
+پروین
+نشود،
+می‌گردند
+مسافر
+راین
+بتن
+خوشه
+طوسی
+جونز
+وابستگی
+اسیر
+خیابانی
+بت
+اینجانب
+ببینیم
+لیکن
+بگذاریم
+شراب
+انگیز
+برروی
+حاجی‌آباد
+پارسک
+اعزام
+اعطا
+فقر
+علي
+کارنامه
+حجاب
+اینک
+جمع‌آوری
+درهم
+خواهشمندم
+اینه
+گانه
+پارچه
+گردیده‌است
+مداوم
+آلوده
+حقایق
+جعبه‌دندهٔ
+بشری
+چهارده
+۱۳۰۰
+لیلا
+بدیهی
+مابین
+مثنوی
+ویدیویی
+محققان
+رابط
+تلمبه
+پرفروش‌ترین
+استیو
+ساختمان‌های
+وانتشار
+معترضان
+وحی
+برنامهٔ
+بگم
+عسل
+پرتغالی
+فصلنامه
+عجب
+رفتارهای
+وورتمبرگ
+امپراطوری
+برون
+شانزدهم
+مدل‌های
+آکسفورد
+فساد
+چیزها
+خبرنگار
+ذره
+کان
+کنیم؟
+دامداری
+هی
+عبدالکریم
+کوهرنگ
+آنتونیو
+ایرادی
+۱۱۶
+دریافتی
+هرمز
+آب،
+گـپ
+ویکی‌پدیایی‌ها
+۱۰۶
+غریب
+دلفان
+راسل
+۱۹۰۷
+گویم
+قزاقستان
+وحشت
+منشور
+انتقام
+مشروطیت
+کیفی
+بپردازد
+براى
+شركت
+تعصب
+ویلهلم
+خطای
+متقابل
+۲۰۱
+اشکانی
+می‌کرد،
+بروجردی
+طبقات
+طالبان
+سفارش
+فیلمهای
+آهنگ‌های
+کنستانتین
+پیوستن
+دیدگاه‌های
+چالش
+ستایش
+نقشی
+کهریز
+منطقه‌های
+خلبان
+تنگستان
+فروند
+حج
+خاتم
+۱۳۴۱
+گردند
+پایتون
+گفته‌اند
+دانسته‌اند
+دانشکدهٔ
+تکلیف
+بازرگان
+نتوانست
+بیوگرافی
+۱۵۰۰
+بنت
+مری
+نقص
+فانتزی
+پژوهشگر
+دویچه
+کنت
+قاجاریه
+دوام
+حیدریه
+جیمی
+پویانمایی
+قوای
+می‌آورند
+کامران
+متنوع
+استراتژی
+شمارش
+۱۹۰۴
+اعم
+داراي
+بهبهان
+الدوله
+تخلف
+فراری
+ایزد
+رأس
+انداخت
+چرداول
+پیش‌فرض
+رهنمودهای
+بافتا
+شناسان
+اردو
+آبیاری
+ترانه‌سرا
+روحی
+ادیب
+فلات
+ایست
+سلیقه
+ماجراهای
+باکو
+همارس
+تراکتورسازی
+گم
+رابطهٔ
+داشتند،
+رپ
+گز
+بگذارد
+۱۱۲
+مستندات
+زمین‌های
+سایت‌های
+مبحث
+مشکلاتی
+بوکان
+ابزارها
+جبران
+تقریبی
+زیان
+گلپایگان
+خوشنویسان
+۱۲۲
+بارز
+مَا
+بوک
+اشتباهات
+تانک
+می‌شده
+دهه‌های
+واژه‌نامه
+خشکی
+ایی
+اللَّهِ
+عفونت
+۱۲۳
+باده
+نام‌تصویر
+بیس
+كردن
+گچ
+زدهٔ
+طلای
+معکوس
+نبودند
+رضایت
+ثروت
+انار
+کشاورز
+کوانتومی
+اژدها
+سوراخ
+بیلبورد
+شاهین‌دژ
+بره
+اهدا
+زیرزمینی
+تکراری
+صربستان
+مراقبت
+تروریستی
+۱۹۱۱
+متمایز
+آملی
+برساند
+عن
+ابهر
+معتدل
+گفتگوی
+املش
+می‌بینم
+می‌آمد
+۱۹۱۳
+ناشناس
+وله
+جایش
+جنبش‌های
+توليد
+موزه‌های
+نمائید
+دهمین
+برند
+تاریخچهٔ
+می‌شده‌است
+پاسخی
+پشتی
+تشریح
+نمی‌شوند
+خویشاوندان
+انگشتدان
+دكتر
+ژانر
+فریاد
+اخلال
+تمشک
+سعد
+پارسا
+۹۰۰
+نامدار
+نظامیان
+قدری
+حمام‌های
+مستوفی
+گرما
+گرا
+یادگار
+عاشورا
+دفعه
+بیانی
+شنا
+استعفا
+رسانه‌ای
+انحلال
+بزرگداشت
+فایرفاکس
+بتوانید
+مؤلف
+حامیان
+ناحیهٔ
+مور
+۱۹۱۰
+حیاتی
+هرگاه
+آنا
+جاسوسی
+منتج
+جابجایی
+تولیدات
+هاى
+قدردانی
+۱۷۰
+راست۱
+لیلی
+عملاً
+میشد
+کشورهایی
+درجهٔ
+حامل
+ابوبکر
+خصوصا
+اختصار
+مجاورت
+پدیدآورنده
+آراء
+چپ۱
+گله
+یکپارچه
+عبارات
+جمینای
+جزیرهٔ
+اسرار
+خانواده‌های
+بلوز
+مونته‌نگرو
+بیابان
+به‌صورت
+دارید؟
+نقطهٔ
+ضرورت
+وي
+کارکرد
+هوانوردی
+محبت
+پارک‌های
+واژه‌ای
+امامزاده‌های
+هریک
+کوچکترین
+طاهر
+حوالی
+مطهری
+کنگاور
+شدهٔ
+شبکه‌ها
+شیوه‌های
+تیراندازی
+۱۱۸
+جست
+آژانس
+سایز
+بدن۱
+تکذیب
+نقدی
+متناسب
+دال
+بابی
+شانزده
+هرکدام
+ادعاهای
+العاده
+عنایت
+مزدیسنا
+انقراض
+مقدونیه
+۱۲۷
+ندیده
+رأی‌گیری
+دلو
+هندسی
+موبایل
+تورم
+رفتاری
+پیامدهای
+زید
+زادروزها
+حیدری
+بتوانیم
+فوری
+علایم
+نویسه
+غم
+خلال
+اریل
+کاشمر
+بز
+بردسیر
+۱۹۱۵
+حتا
+برخط
+خرمشهر
+همچین
+نفری
+سالگرد
+متخصصان
+شاهرخ
+صحن
+جنین
+جشن‌های
+یکشنبه
+تمیز
+ارامنه
+چپ۲
+جلسات
+مهمان
+کجای
+روال
+۱۳۴۳
+پینک
+سبک‌های
+هان
+بدن۲
+عمودی
+افسران
+شجریان
+نوسنگی
+الاسلام
+مساجد
+صاف
+مروارید
+جانور
+آنهایی
+راست۲
+اسکی
+ناشناخته
+اعتقادات
+یم
+انگور
+ويرايش
+گروههای
+ترانهٔ
+شد؟
+دقیقی
+استادیوم
+مختلف،
+عتیق
+توطئه
+بالا،
+مین
+همگانی
+تلفنی
+می‌دانست
+ود
+ميان
+تشکیلات
+روده
+مدیره
+ونزوئلا
+مخصوصاً
+مشتمل
+انتقادی
+تفنگ
+برایشان
+طالقان
+فرانسیس
+بازارهای
+پایین‌تر
+کاروان
+به‌جای
+الیاف
+خامنه
+خصوصاً
+ظهر
+سکس
+چهاردهم
+ایزو
+مسجدسلیمان
+الکل
+فلاندری
+محمدیان
+شکوه
+کرده‌اید،
+اسلامي
+سم
+کناره
+لوازم
+نمیدانم
+پیامی
+فارغ‌التحصیل
+باس
+کام
+بنویسد
+بازنشسته
+نصر
+کاشی
+شکارچی
+پست‌های
+ویلیامز
+دهکده
+اندر
+۱۵۴
+جهانگیر
+ملکان
+می‌توانست
+عبارتی
+مسئولان
+هلال
+مهندسان
+غارهای
+بیلی
+۱۹۱۶
+بنگلادش
+حملهٔ
+توانستند
+پارینه‌سنگی
+پولی
+خوشبختانه
+نموده‌است
+امینی
+نه،
+هما
+مشورت
+نامحدود
+آندره
+پلنگ
+مخدر
+مضمون
+برمی
+هم،
+لاس
+دهید،
+ویکتوریا
+موثق
+داود
+عذرخواهی
+یاهو
+رنگ‌های
+۱۱۷
+تناوبی
+نوشتید
+لااقل
+شتر
+مرکزیت
+امن
+ترسیم
+سیستم‌ها
+اتومبیل
+آفی
+جون
+خالق
+حرارتی
+رسوم
+موریس
+مارشال
+یورو
+بانو
+اولين
+منشورات
+غیبت
+نوشته‌اند
+قدرتمند
+شکم
+هایش
+انداز
+رویکرد
+علاقه‌مند
+خانواده‌ای
+دمشق
+دربند
+برو
+آرشیو
+۱۹۰۹
+رویش
+استخر
+آنالیز
+گچساران
+بکنم
+مولا
+متفرقه
+رحمت
+شاخ
+۱۳۱۰
+اتفاقاً
+اسمش
+سهامی
+دبلیو
+بخشهای
+سرتاسر
+ویکی‌ها
+خیالی
+نکنند
+تناسلی
+م‍انفی
+جديد
+۱۳۲۴
+کار،
+برندهٔ
+پیچیدگی
+گواهی
+زرتشتیان
+ناصری
+همانجا
+رغم
+گفتهٔ
+۱۱۳
+گرمسیری
+طلوع
+برترین
+درآورد
+به‌دست
+برقی
+سپاهیان
+ویژگی‌ها
+مر
+۱۲۴
+چهاردانگه
+جامعهٔ
+تحقق
+مجاری
+می‌گفتند
+فروپاشی
+چشمه‌های
+ساختاری
+مسافرت
+پیکان
+نرم‌افزاری
+جد
+روشنی
+معرفت
+تله
+می‌کنم،
+محرک
+مشتریان
+بیانگر
+سازمانهای
+چیزهای
+رقیب
+فرعون
+بیروت
+منعکس
+تابناک
+مشرف
+آورده‌است
+نمی‌توانم
+۱۱۹
+مولکول
+نعمت
+می‌رساند
+فرمانداری
+دستکاری
+۱۳۳۹
+مت
+اردبیلی
+مسدود
+بله،
+رانندگی
+۱۲۱
+سایپا
+استعداد
+پیامبران
+داماد
+واجب
+نسخ
+فاضل
+عرفانی
+بزرگ‌تر
+حق‌تکثیر
+شخصاً
+دگرگونی
+عكس
+انبوه
+آپولو
+فنون
+افلاطون
+حمزه
+میانجی‌گری
+نظرسنجی
+آنتونی
+اکوادور
+آن‌چه
+قذافی
+اسکن
+خاتون
+ناگهان
+گونه‌ها
+تونل
+به‌ویژه
+ناگهانی
+بدهیم
+دوشیزه
+آباده
+نمی‌توانند
+شلوغ
+ی،
+۱۳۳۵
+خلع
+فلوید
+ابومسلم
+بایت
+اعطای
+جاسک
+پوند
+پایداری
+تیتر
+واپسین
+استالین
+تعطیلات
+آستین
+مختلط
+تابلو
+خنده
+نویسه‌های
+ثمر
+۲۰۰۰،
+بازاریابی
+حسابداری
+تکلم
+رنگرزی
+نهبندان
+۱۳۳۶
+نیلوفر
+شرقی،
+بداند
+فسا
+آلیکانته
+دیلمی
+اجتناب
+نیر
+سطح‌بالای
+اينجا
+می‌زنند
+کیم
+لغتنامه
+عاشقانه
+فتحعلی
+اشیاء
+تعمیر
+فلانی
+استیون
+سازماندهی
+ویرجینیا
+راجر
+بگویند
+روزنامه‌نگاران
+هندو
+دیوانسالار
+ایستاده
+۱۳۳۷
+کرانه
+کلسیم
+هایدلبرگ
+کرواسی
+سرانه
+الملک
+سنگ‌های
+ژنتیکی
+نیکی
+هجرت
+مامور
+خنک
+نمایان
+بهرامی
+شبستر
+واسط
+آرایش
+مبهم
+بسی
+بریتانیای
+محدودهٔ
+بحث‍
+گاما
+ده‌ها
+نواختن
+فروشگاه
+خمین
+صنعاء،
+کنفدراسیون
+اموال
+هنرپیشه
+پارسیان
+متوسطه
+دامن
+۱۲۶
+لک
+شیشه‌ای
+ابراهیم،
+آمادگی
+هو
+زنجیره‌ای
+۱۳۲۸
+بازیهای
+سنقر
+بدر
+آورند
+مرجعیت
+آلت
+اسدآباد
+کارلوس
+سودمند
+نشانگر
+رسید،
+حوزه‌های
+دیار
+کنگو
+میهن
+کلانی
+۱۲۹
+افسر
+باکتری
+معماران
+۱۳۲
+سیدنی
+کفش
+ارادت
+می‌خواهند
+خر
+۳۵۰
+بدترین
+تاریخ،
+فلسطینی
+زاگرس
+بیاورد
+یانگ
+شخصا
+تشدید
+آدمی
+ماهی‌ها
+هیچکدام
+میناب
+بوسنی
+ایندیانا
+دنباله‌دار
+ملوان
+روزنامه‌نگار
+مؤثر
+دستورات
+رطوبت
+تعامل
+کلان
+عباس‌آباد
+کاملی
+احادیث
+مدرکی
+پاکسازی
+۱۳۷
+تفاوتی
+ورزشکار
+جنبه‌های
+غالباً
+بود؛
+چنگ
+مهاجران
+پله
+تراز
+آمد،
+وا

+کوثر
+وادی
+اتوبوس
+کاظمی
+خبرگان
+موس
+تکمیلی
+لهستانی
+درویش
+منم
+جعفرآباد
+نیا
+جاذبه
+گیلانی
+طلاق
+تروریسم
+به‌خاطر
+آيا
+گرفتار
+اشعه
+می‌پردازند
+شخصیتی
+آقایان
+رفتم
+جریمه
+مهره
+خاستگاه
+میان‌ویکی‌ها
+بالینی
+یزدگرد
+ببرد
+دوش
+چغازنبیل
+۳۰۰۰
+فوقانی
+۱۳۳۱
+گیلکی
+خط‌به‌خط
+کاترین
+بختیار
+کردید،
+گردان
+ادی
+طاها
+مدیترانه
+ارس
+حسن‌آباد
+پوشاک
+بابلسر
+رساندن
+کند؟
+بهش
+وست
+خوشامدگویی
+مهار
+میبد
+فلسفهٔ
+وند
+آش
+سیمین
+خوراک
+خوزه
+ساختند
+نياز
+عروسی
+میگردد
+جلفا
+بودیم
+بکند
+۱۳۸۸،
+روحانیان
+حماسه
+پایتخت‌های
+مبارزات
+احمد،
+ارث
+محمّد
+۱۳۳۳
+کوشک
+سنگ‌ها
+زشت
+دنا
+دستیار
+گرمایی
+ایشون
+نامهٔ
+تحمیل
+گوشی
+دوره‌ای
+ققنوس
+بدانند
+شن
+انداختن
+هفدهم
+غالبا
+اسدالله
+۱۳۴
+شدیدی
+ناپذیر
+۱۴۴
+گینه
+سرمربی
+نطنز
+کیبورد
+محفوظ
+آیند
+انفرادی
+آن‌که
+گمانم
+توانسته
+سال‌شهرشدن
+علم‌جو
+خرده
+درگز
+ایستگاه‌های
+بکشید
+پیش‌بینی
+حالات
+هرکس
+بزودی
+کایروس
+اوستایی
+صفات
+مارکسیست
+خشت
+جنب
+عذر
+ونیز
+آسانی
+کریستین
+صفویان
+اسدی
+۱۹۰۳
+تاخیر
+خیانت
+قوس
+قطره
+آثارش
+سیل
+اسکات
+مشاغل
+شم
+بخارا
+چاپی
+مکتوب
+دیدید
+انتها
+موزیکال
+كاربر
+منشأ
+سمی
+لَا
+پهلوان
+پوسته
+درختی
+مشابهی
+کنیا
+عاملی
+۱۳۹
+گویید
+۱۳۳
+تلاش‌های
+اهمیتی
+عازم
+اسمی
+پکن
+تصوف
+تکاب
+حاکی
+برت
+کنيد
+نوروزتان
+ببیند
+کبوتر
+سفرنامه
+۱۳۳۴
+تخلیه
+آق
+زنجیره
+انتقادات
+کوک
+همان‌طور
+غربی،
+جنجال
+فیزیولوژی
+سانتی‌متر
+بسط
+زخم
+۱۴۱
+ویکتور
+آران
+یك
+التهاب
+دسته‌بندی
+جنگنده
+ایفتا
+ژاک
+طاهری
+فیض
+بهتره
+ادعایی
+اسد
+بودنش
+پیک
+مسأله
+بانوان
+بنفش
+گشود
+باغی
+هیدوچ
+جسمی
+انگشتی
+یوهان
+لنز
+چراکه
+رهایی
+نگرفته
+مقصود
+جوراب۱
+آنهم
+قمی
+سکته
+کو
+سره
+زبانها
+برج‌های
+مکان‌ها
+نشدن
+چابهار
+پاراگوئه
+کتابها
+طولانی‌ترین
+اولویت
+مبارز
+استراحت
+مشت
+حرام
+فرمود
+نقلیه
+کمر
+پستان
+سرچ
+فعاليت
+ارتقاء
+شانس
+خودی
+فاتح
+مطالب،
+گوسفند
+میگویند
+غلام
+وصف
+دلم
+اظهارات
+انتگرال
+سوسیالیست
+گذارد
+ماموران
+بادام
+چال
+ساگه
+ایسنا
+معده
+ریشتر
+اعلان
+تک‌نفره
+بلو
+مناطقی
+شافعی
+می‌گفت
+می‌خواند
+ثانی
+هست؟
+منو
+لوث‌شدن
+جنایت
+برخاست
+بوده‌است،
+نمی‌باشد
+اشراف
+نداد
+مهربان
+الهیات
+همه‌ی
+زمين
+کینگ
+رول
+والتوزیع،
+مدرسهٔ
+ترافیک
+اتهامات
+وای
+بهنام
+شجاع
+سیار
+ترسناک
+ذات
+مختار
+عموما
+اینتر
+فرزندش
+داروشناسی
+ریسک
+۱۹۹
+نیجریه
+مظفر
+حشرات
+میدانید
+جبل
+آریزونا
+نارنجی
+کتابخانه‌های
+میدانم
+آرم
+بشمار
+اعتباری
+کره‌ای
+عکس‌ها
+پیکچرز
+تخته
+متمایل
+رفاه
+شهبازی
+میخائیل
+تطبیق
+نظریه‌های
+بلوغ
+عزیزم
+۱۳۹۱
+محاسباتی
+سنجی
+مکانیسم
+سریعتر
+آبشاری
+کالاهای
+اشک
+خانی
+سازگاری
+مارچ
+گرین
+قرص
+خوانندهٔ
+صفی
+نازک
+داروها
+۳،
+۱۳۶
+هماهنگ‌کنندهٔ
+لینکلن
+بانوی
+خودروی
+پل‌های
+۱۳۳۸
+دیوارهای
+ورامین
+۱۴۵
+اتخاذ
+کمیت
+دارم،
+مذاکرات
+حول
+برگزید
+کارشناس
+نامعتبر
+سفرهای
+رومیان
+ربات‌ها
+غیراینصورت
+انیمه
+به‌وسیله
+استعمال
+صریح
+سازه‌ها
+رامهرمز
+اندیس
+رازقنــدی
+تثبیت
+۱۰،
+تصوير
+گویش‌های
+کتک
+طالب
+حماس
+۱۳۲۹
+علیرغم
+۱۴۸
+حزبی
+استونی
+اوین
+غروب
+حریف
+استراتژیک
+شگفت
+مرگش
+جانسون
+پانزدهم
+موشک‌های
+گن‌آباد
+ارتقا
+باطل
+خورشیدی،
+آلفرد
+ساموئل
+بحرانی
+قندهار
+كردم
+ماکس
+گی
+میخواستم
+بچه‌های
+۱۳۲۵
+شرطی
+گشایش
+زندگي
+دایی
+یون
+فرانس
+تورات
+گزارشی
+۲۲۰
+فیلم،
+دهلی
+مسافران
+سنگر
+نخواهم
+موش
+ریشهٔ
+سخنگوی
+زنگ
+نینتندو
+دیوانه
+بمباران
+مسئولین
+استودیویی
+شدیدا
+تیلور
+۱۲۰۰
+قزوینی
+لاست
+مسلما
+ورق
+شهرزاد
+لطفی
+کلات
+بارداری
+دیواره
+باشگاهی
+شکستن
+تریلر
+ممتاز
+پرانتز
+یوتیوب
+بیهوده
+ابدی
+نباشد،
+کیوان
+طرح‌های
+بدم
+کاریکاتور
+بدتر
+داش
+می‌رسید
+میانجی
+بيش
+اختریان
+سربیشه
+روشنایی
+تبیان
+بکشد
+اراده
+چربی
+خرما
+سلطانی
+شيخ
+مقا
+مستخدم
+وب‌گاه‌ها،
+نشینی
+نرگس
+۱۷۵
+تویسرکان
+خاطره
+برکنار
+غیرقانونی
+ساواک
+نگاره‌ای
+سین
+شناسنامه
+بناها
+‌ها،
+غرق
+شعرهای
+مسلط
+سرش
+اه
+برکت
+جنگل‌های
+سلطه
+اقیانوسیه
+علما
+بنفشه
+یال
+هولوکاست
+دادستان
+حلی
+اجسام
+غواصی
+احاطه
+والا
+بیماریهای
+صدوق
+ریو
+دیویس
+ناهید
+دهها
+نتوانستم
+ایکس‌باکس
+ول
+منبع‌ها
+تاریخی،

+کثیر
+لیتوانی
+شده‌
+بپرسم
+قربانیان
+جانشینی
+سیریلیک
+بوستون
+یونانیان
+دوبار
+فرضیه
+امروز،
+دیده‌ام
+عزيز
+۱۴۲
+میگیرد
+شلوارک۱
+مِنَ
+ارسطو
+ومبلی
+بخواند
+۱۹۰
+صوفی
+صدق
+کارب
+گذاشتند
+هزینه‌های
+فردریک
+نوشته‌اید
+آو
+عمده‌ای
+م‍
+هیچگونه
+حسی
+اللَّهُ
+معدود
+مارکس
+سنگاپور
+رایانش
+عادل
+ریگان
+میرسد
+الگوریتم‌های
+ائتلاف
+فریدون‌کنار
+بازگا
+نگرش
+هرحال
+بدانیم
+کفایت
+فین
+۱۳۲۷
+باورهای
+بازگیر
+لردگان
+چرا؟
+تعویض
+سلجوقی
+جستار
+نخواهند
+می‌نمایند
+دهستان‌ها
+فرمانروای
+خودتون
+منتقدین
+کلاردشت
+اره
+لزومی
+مرتفع
+ویر
+سندرم
+نیاید
+آجر
+دانشکده‌های
+نمین
+مق
+تن‍
+اینچ
+فوتسال
+ساکنین
+‍ه‍
+فرانسه،
+صفحاتی
+۱۹۰۲
+طالقانی
+جعبهٔ
+غارت
+بزرگسالان
+لین
+۱۶۵
+قیاس
+افغانی
+نگذاشته‌اید
+ساید
+نادری
+امامان
+سنا
+سرگذشت
+رایش
+توجیهتان
+بروند
+سمفونی
+آهنگ‌ها
+توس
+تم
+پنسیلوانیا
+خرچنگ
+مغان
+سجاد
+پایینی
+تحریر
+لوث
+شانه
+طوفان
+اصولاً
+کبودرآهنگ
+تسمیه
+عامیانه
+بیشینه
+فضاپیمای
+بودایی
+۱۸۹۰
+اقلیم
+مثالی
+جشنواره‌های
+برایان
+میرود
+پین
+آم
+سرگرمی
+مزایای
+ریال
+رسماً
+ناحیه‌های
+تازه‌ای
+می‌دهیم
+هارد
+مقال
+فراهان
+دلیلش
+میلیمتر
+۱۸۰۰
+ماهنشان
+سالار
+جت
+مردگان
+فقیر
+۱۵۵
+راستا
+میکنیم
+جوری
+شلوارک۲
+پژوهشگاه
+نیستند،
+۱۴۶
+اینشتین
+یخچال
+روزمره
+ارم
+سنین
+تحسین
+سکه‌های
+۱۳۱
+فحاشی
+پاپ‌های
+عینی
+رسانده
+رز
+بودم،
+ارزشی
+ستان
+باراک
+اصلي
+الکتریک
+نامه‌های
+عطار
+علمي
+بخشید
+السلطنه
+يعني
+غلبه
+مستقیماً
+منش
+رستاق
+افراطی
+بگیرم
+سيد
+۱۴۷
+ندارند،
+الَّذِينَ
+نمونهٔ
+کریستال
+قایق
+نوادگان
+سالیانه
+می‌پذیرد
+احترامات
+شیری
+سیاهکل
+سرب
+نصرالله
+مانه
+گیم
+ببر
+آستان
+زیستگاه
+ای،
+داده‌ام
+لوئی
+شریعت
+آموز
+رتبهٔ
+کمک‌های
+نقدها
+حلقه‌ها
+ارتقای
+هال
+انسانها
+پشتو
+امیرحسین
+سین‌آباد
+رشید
+۱۴۳
+شیرینی
+مذاکره
+تعدیل
+کارمند
+اعضاء
+روانه
+بنر
+معروفترین
+خیابان‌های
+مشاوره
+اکثرا
+افت
+کنگان
+بگذارند
+دامنه‌های
+رحم
+بیدار
+تیپ
+تنفس
+افغانستان،
+میشیگان
+استعمار
+فرخ
+گذرگاه
+توالی
+تایم
+جمله‌ای
+ولادیمیر
+دستوری
+تساوی
+ساختارهای
+جانوری
+قسم
+۱۳۱۶
+هفده
+یقین
+صوفیان
+می‌نویسند
+رومرکز
+بک
+انگشته
+مولف
+نگفتم
+یورش
+ثبات
+بیایند
+بپرهیزید
+وبا
+اس‌جی‌اچ
+جن
+ورزش‌های
+لامرد
+سپیدان
+کبک
+عزت
+افشین
+کامرون
+فیلم‌شناسی
+پاول
+نکنیم
+درگیری‌های
+رخداد
+کیا
+عرف
+شازند
+یکصد
+استهبان
+می‌گیرد،
+نرسیده
+ویژهٔ
+ابتلا
+اینطوری
+گارد
+بزن
+مدتها
+وعده
+شرف
+پيدا
+نیدرزاکسن
+زواری‌جان
+اسدخانی
+هندواروپایی
+تصویرگر
+مختص
+استادی
+هیپ
+امشب
+احیای
+بنو
+امامت
+خونریزی
+سیگار
+کاسه
+غرض
+معتقدم
+ساختم
+صفح
+روایتی
+نمادهای
+متوالی
+خدایی
+نمود،
+عجم
+آبهای
+آمده‌اند
+نموده‌اید
+لاریجانی
+شیوع
+زمينه
+الا
+بیا
+آزمایشگاهی
+آنتن
+قرآنی
+بیستون
+فاجعه
+۱۵۸
+ریه
+انعکاس
+تقلب
+هجدهم
+طبرستان
+تناقض
+مدت‌ها
+علمی،
+تصنیف
+فروغ
+دایرةالمعارف
+آلمریا
+تاسیسات
+گونهٔ
+هیچکس
+ایدز
+آوا
+۱۴۹
+مديريت
+بیاد
+پایگاه‌های
+زیرصفحه‌های
+مقاوم
+گمشده
+نشدید
+نوزاد
+سیف
+دیفرانسیل
+موافقان
+بانه
+فونت
+صفا
+واتیکان
+اصالت
+کتابخانهٔ
+یگانه
+کیت
+ترجیحات
+کنوانسیون
+نانو
+۱۵۳
+آنزیم
+كردند
+تیمی
+۱۸۵
+هستید،
+حوض
+نویسنده،
+ورد
+حسنی
+پديا
+بویین
+مادها
+ناوگان
+بنگاه
+اردلان
+صومعه
+تورنتو
+کارولینای
+۵۰۰۰
+اشکالات
+مسائلی
+انداخته
+نماند
+دستمزد
+بخواهم
+سرقت
+میدانی
+ریتم
+خوبیدگی
+پوستی
+اندی
+الماس
+بزنم
+مقدونی
+هسن
+گروه‌ها
+بروجن
+تگ
+منشی
+ملکی
+تبعیض
+ببین
+افق
+خشن
+کورین
+دوی
+قوام
+ایلینوی
+بچه‌ها
+تکاملی
+دخترش
+برانگیز
+اصطلاحی
+مل
+یکان
+داراست
+عرب‌ها
+ناموفق
+کبد
+کوفی
+رودها
+پشته
+رسالت
+مرتکب
+معروف‌ترین
+نشوند
+نبودم
+بنیانگذاری
+لیبرال
+فرید
+حوضه
+ربع
+نوح
+سیاهه
+تای
+خستگی
+پدری
+برنامه‌ها
+فرستادن
+بیطرفی
+نواب
+نزول
+استیشن
+رادار
+پخش‌کننده
+سازند
+عضلات
+سعیدی
+کوین
+بنویسند
+برم
+بیایید
+حجازی
+شده؟
+تالیفات
+حسینعلی
+نیست؛
+مزاحم
+فروشی
+آموزان
+میکرد
+۲۴۰
+بحث،
+وارنر
+کوری
+واکنش‌های
+فستیوال
+قارچ
+لغت‌نامه
+تاجیک
+شرکتهای
+هروی
+ویژگیهای
+عکسهای
+چارلی
+باشيد
+داشتیم
+بومیان
+باقیمانده
+یافت،
+اشاره‌ای
+فصلی
+عبدی
+بزرگوار
+بیتی
+مُعجَم
+نازل
+امپراتوران
+مهمتر
+کانی‌ها
+۱۸۹۶
+محمدباقر
+شایع
+ادریس
+که‌
+دهندگان
+اعلامیه
+به‌نظر
+داروی
+لیک
+اتوماتیک
+مي‌شود
+فروغی
+برآورده
+بلا
+آدولف
+قشقایی
+تنفسی
+اردوگاه
+زنجانی
+تنه
+گزیده
+مریوان
+پورنو
+کامبوج
+تل‌های
+رمزنگاری
+دامپزشکی
+شاهنشاه
+قرقیزستان
+ارابه‌ران
+نمودم
+ضرر
+بازنگری
+دگرگون
+بررسي
+شده‌بود
+ناپدید
+متاسفم
+نسخه‌ای
+اشنویه
+پیاپی
+عبدالعزیز
+۱۶۸
+اسباب
+نسبیت
+کعبه
+مردم،
+ذوب‌آهن
+آنچنان
+ادرار
+رنسانس
+سوسیال
+دهخدا،
+تختی
+فاطمی
+ماشین‌های
+پاسکال
+مینا
+تابعی
+سایتی
+توانیم
+ترين
+توران
+ادارهٔ
+فهرست‌ها
+خوشی
+معینی
+یادآور
+مخالفین
+دود
+مدام
+انی
+تقاطع
+پتاسیم
+نساجی
+ارد
+اندیمشک
+داده،
+مخالفتی
+دونفره
+اندیشه‌های
+علیزاده
+آجری
+برسیم
+اقدامی
+فقهی
+اشکان
+همبستگی
+فرادیرینه‌سنگی
+گناوه
+کوفه
+۱۸۹۹
+اینصورت
+عبدالرحمن
+لبه
+بی‌پایان
+میدهند
+منشا
+مرحلهٔ
+بیطرف
+کردید؟
+مسخره
+مشخصه
+عضلانی
+اسارت
+عنوانی
+۱۵۲
+ندارم،
+برچسب‌ها
+اچ‌آی‌پی
+منصوری
+۲۱۰
+بینم
+مجنون
+تعاریف
+تعهد
+اقتباس
+جلیل
+می‌کنید؟
+رزن
+مسئلهٔ
+فرستنده
+گان
+قاب
+کمونیسم
+تناسب
+ندای
+توحید
+هواشناسی
+کرده‌اند،
+منتها
+روز،
+شوال
+لیزر
+پس‌از
+دزدان
+دارد؛
+جنگ‌افزار
+جایزه‌های
+واحدی
+تیموریان
+ذكر
+کنده
+ترش
+می‌خوانند
+ریش
+تمایز
+پیشبرد
+زندگانی
+دلتا
+پیش‌از
+نقده
+ایرلندی
+هنرستان
+قبال
+فرصتی
+دودویی
+عليه
+زیباترین
+شاعری
+سرما
+ایلی‌نوی
+شهبانو
+پنالتی
+بهاری
+افتد
+فیروزکوه
+فایده
+۱۶۳
+بروس
+نیسان
+نکردند
+نمیتوان
+۱۶۲
+روباه
+سقراط
+کشته‌شدگان
+اورانیوم
+عملا
+طراحان
+ماهیچه
+سرم
+اوهایو
+علاقمند
+نویسد
+الجزیره
+گذشته،
+مزارع
+گزینش
+جنگهای
+اطلاعی
+نوشته‌ها
+پارلمانی
+۱۱،
+جنابعالی
+اسفندیار
+امیدوار
+ک‌گ
+گازهای
+کبود
+زمین،
+تلگراف
+لئونیداس
+گرمای
+کتابخانه‌ها
+آشوری
+طعم
+راد
+زنانه
+عربی،
+جادو
+حمیدرضا
+جنگ،
+جابجا
+ماکیان
+بیابید
+شکاف
+گلزار
+متفقین
+متاخر
+سایتهای
+بایگانی‌ها
+بهره‌برداری
+جنایی
+کارون
+شهدای
+میامی
+پدیده‌های
+هستم،
+برکلی
+نایین
+ببینند
+استانداری
+۱۶۱
+پسری
+شوالیه
+کت
+شاخه‌ای
+مقاطع
+آنوقت
+اسکو
+۱۸۹۲
+نده
+رسانید
+۲۳۰
+تاسف
+هايي
+پلدختر
+تاجیکی
+جاجرم
+وضع‌کننده
+استر
+همنشین
+زحمتی
+کانادایی
+تبلیغات،
+زهک
+دولت‌های
+ترمودینامیک
+سوری
+خلفای
+درآن
+فراگیری
+ختنه
+امیرآباد
+تروث
+بوم
+زاد
+خنج
+بروم
+سومالی
+جیم
+دیجیتالی
+عفو
+سوشی
+اصفهان،
+بلاندی
+کوچک‌تر
+گمنام
+سکوی
+نزاع
+احتیاط
+گردید،
+بزنند
+علنی
+ویلا
+۱۳۲۶
+الهه
+هدر
+ظلم
+ناو
+می‌کردند،
+الحکمة،
+یاقوت
+حتي
+شرکت‌ها
+تعلیق
+خواستند
+کاروان‌سرا
+نکتهٔ
+رشته‌ای
+باهم
+بپردازند
+درجات
+وجودی
+بودا
+نیوتن
+منطبق
+نصرت
+ال‌جی
+سومی
+فلش
+۱۳۸۵جمعیت
+فریم
+دوما
+ساقه
+اسماعیلی
+دینامیک
+المقحفی،
+المُدُن
+فیلم‌هایی
+فیزیکدان
+محضر
+آخوند
+فراهانی
+صید
+بسا
+الیَمَنِیَة
+بنایی
+۱۷۳
+می‌گوییم
+درآمده
+مورخان
+یونیکس
+جاها
+وام
+کوتوله
+۱۷۶
+ژرفای
+موجودی
+مرادی
+بدنیا
+پمپ
+پرستاری
+می‌شوید
+مناره
+انقلاب،
+برجستهٔ
+جذاب
+نوشتارها
+نمیشه
+مایک
+امیری
+چناران
+ــ
+گردو
+تفویض
+دخیل
+۱۵۹
+بنیادین
+بدیع
+سالیان
+مواضع
+وَالقَبائِل
+۱۶۹
+می‌بیند
+درگذشتهٔ
+داشته،
+قنطورس
+۱۸۹۸
+تصمیم‌گیری
+مشمول
+رودان
+فراگیر
+آمده،
+نفهمیدم
+۱۸۸۹
+شده‌اید
+نفی
+افسردگی
+می‌دانستند
+آلات
+قوت
+دانه‌های
+محمدحسن
+عزيزی
+جامی
+نجم
+طرحی
+گاندی
+جنوبی،
+بصره
+اروگوئه
+شرکت‌ها،
+پورت
+خجسته
+زمانیکه
+ریشه‌های
+فمینیسم
+گاردین
+بایست
+وار
+دیوان‌سالار
+فوتبالیست
+۱۶۷
+آلمان،
+شعله
+آناتولی
+على
+شمالی،
+سیمون
+ظروف
+رستوران
+دایر
+می‌گذارند
+تفاهم
+آناتومی
+گذراندن
+شكل
+مرگ‌ها
+آهنگسازی
+لیتر
+دزدی
+فرموده
+معصوم
+اطاعت
+تارنمای
+فارس،
+پلان
+هانس
+فریدریش
+ملی،
+روحانیت
+اوّل
+نتيجه
+وادار
+صورت،
+۱۳۰۴
+ترتیبی
+مبارکه
+بنیان‌گذار
+۱۷۹
+ژوزف
+اردستان
+افزودم
+مطبوعاتی
+ارز
+جنجالی
+نوازندگی
+سوزان
+دارن
+افتادن
+هایشان
+تحقیقی
+سهند
+سپاسگذارم
+فیزیوتراپی
+محافظ
+ماشینی
+ربر
+یدالله
+میمون
+سیاستهای
+نگارهٔ
+چه؟
+صراحت
+رسته
+تجویز
+توفیق
+مغولستان
+کین
+وال
+ساکورا
+پیشروی
+متوفی
+تازی
+دیلم
+پل‌دختر
+می‌خواست
+صدیق
+نمی‌بینم
+ایلات
+درحالی
+غلات
+نوه
+هاله
+سیستمهای
+کتیبه‌های
+سیال
+منبر
+بیک
+۱۳۱۴
+۱۳۱۸
+حسين
+۱۷۱
+درشت
+سوق
+برنامه‌ای
+گهواره
+دست‌آوردهای
+تعبیه
+رادیوی
+ساسان
+درامز
+۱۲۹۹
+تجسمی
+سیمان
+گنجی
+کشش
+اسلوونی
+ویلسون
+داماش
+إِنَّ
+کارتوگرافی
+کاشت
+دستان
+لید
+نوازندهٔ
+نمی‌شد
+قران
+ایدئولوژی
+کامپکت
+ناغان
+قرائت
+کاراکتر
+خانه‌ها
+شفاهی
+فله‌ای
+شهرسازی
+اعتصاب
+۱۸۱
+ویدیو
+شايد
+ویرایشگر
+پردازد
+داده‌اید
+حاد
+اجتهاد
+مرطوب
+کلماتی
+مهریز
+حلال
+بیافزایید،
+۱۵۷
+همجنس‌گرایان
+لینکی
+تطابق
+باورند
+دالاس
+إِلَّا
+اصولی
+کپی‌رایت
+الفبا
+کیهانی
+تاب
+شرعی
+محتوی
+هانری
+می‌دهند،
+یوگسلاوی
+بگذارم
+تداوم
+گریز
+نشده‌اند
+شناخته‌شده
+انعطاف
+اندک،
+دعوا
+کری
+تبیین
+احساسی
+ساعات
+معاصر،
+پیشوند
+طبع
+میاندوآب
+اخترفیزیک
+مطمئنا
+پرسید
+انگل
+برکناری
+رولینگ
+حفاری
+زیارتگاه
+منتسب
+پیام‌های
+گسسته
+طريق
+باخ
+۱۳۲۳
+کلیساهای
+معصومه
+شهروز
+متناوب
+۱۸۹۵
+پن
+ابراهيم
+۱۳۱۳
+بطوریکه
+رابین
+آموخته
+میدان‌های
+تاریخ‌نگاران
+بکر
+میش
+پخته
+قلمداد
+رویا
+باشید،
+سیستانی
+قومیت
+جرمی
+لوس
+آفرین
+تلف
+خوارزمی
+محتوایی
+سول
+دبط
+جُستارهای
+می‌نمود
+روزنامه‌ها
+یت
+دگر
+بانکی
+سدان
+متغیرهای
+یابند
+بکارگیری
+انتاریو
+کوسه
+۱۶۴
+بلخی
+بیم
+خلخال
+حائری
+۱۸۹۳
+آورده‌اند
+نقطه‌ای
+علمجو
+استیل
+سلولهای
+گوگرد
+میتوانند
+گوارش
+سبزی
+۱۶۰۰
+جوراب۲
+زیرین
+ميشود
+پنبه
+آورد،
+حرفهای
+لنگرود
+فریمان
+سلاح‌های
+میانگین‌جریان
+غبار
+مردانه
+مؤسسهٔ
+اسراییل
+تک‌نواز
+۱۶۶
+لکی
+خبرنگاران
+پالایشگاه
+مصلحت
+۱۷۷
+مجروح
+پرستش
+دوگانه
+مدفون
+ولیعهد
+سرزمینی
+آق‌قلا
+اساسا
+بهر
+ملي
+كنار
+روستاي
+کلاس‌های
+سفره
+نرمال
+وری
+کیف
+۱۸۸۰
+۱۹۸
+زدید
+زراعت
+رهنمودها
+توضيح
+۱۷۲
+۱۹۲
+پدیدار
+وایت
+بمانند
+لرد
+دستم
+ایسلند
+لیقوان
+نیافتم
+باتشکر
+تئودور
+عبادت
+تبديل
+نکردید
+مسلحانه
+دیزنی
+رانش
+فرهنگ‌های
+مخاطبان
+دول
+کتابت
+سلیم
+ایرانی‌تبار
+غلظت
+شونده
+۱۲،
+اوراق
+سامانی
+اقتصادی،
+۲۵۰۰
+شخصیت‌ها
+فحش
+سربازی
+هشداردهنده
+ندرت
+۳۲۰
+می‌شه
+۱۸۹۷
+فروهر
+صلی
+سیوند
+انجمن‌های
+بعلاوه
+ترشح
+فرج
+جاي
+بخیر
+محراب
+کارتان
+هجده
+قریه
+ربیع‌الاول
+ضخامت
+بارندگی
+بح
+نسیم
+زهره
+جادویی
+تالاب
+جنون
+بروی
+۱۳،
+فیلد
+کریسمس
+میزبانی
+می‌کنید،
+آپلود
+برگزیدگان
+یش
+خانواده‌اش
+کریستوفر
+بیننده
+توکلی
+می‌سازند
+لنگ
+تداخل
+مقدمات
+۱۸۹۴
+الوند
+مع
+گناباد
+مزدا
+رکن
+عیلام
+ترقی
+منکر
+معامله
+اینچنین
+کول
+سازمان‌ها
+مأموریت
+موعود
+دولت‌آباد
+بلبل
+طولی
+می‌رسند
+اجاق‌کندی
+ديگري
+ندارد؟
+براین
+مصور
+اعتقادی
+فرخزاد
+درباره‌ی
+خداآفرین
+گفتاری
+خوانی
+پارامترهای
+تهاجم
+آیوی
+توضیحاتی
+بشرویه
+۹۷۸
+کیست
+نداشت،
+شهروندی
+برخي
+۱۵۶
+سمرقند
+نوا
+كمك
+لامپ
+عماد
+رام
+اينکه
+ضمیمه
+بنابراین،
+تصویربرداری
+سیبری
+یوفا
+کلر
+گوجه
+حیف
+سواری
+۱۳۱۲
+طارم
+۲۶۰
+اباد
+عنوان‌های
+مركز
+مقوله
+گوستاو
+مرعشی
+بحر
+تون
+انصار
+جداسازی
+تصفیه
+سازندگان
+ببنید
+محافل
+نقره‌ای
+تیرماه
+پیاز
+سرسبز
+انه
+چشمان
+تایباد
+اشیا
+طرد
+گوهر
+نکن
+هرزگوین
+اقلید
+خاص،
+ثالث
+علی‌رضا
+آنگونه
+مستمر
+عضوی
+هامبورگ
+پورتال
+تویوتا
+رامیان
+هخامنش
+اردل
+قاطع
+گنجینه
+روشنفکران
+تصادف
+۱۹۷
+جزیی
+مؤسس
+روبروی
+آلاسکا
+خوشه‌مهر
+آرد
+صالحی
+سونامی
+کشیش
+پروس
+انحصاری
+کاسته
+دوستانش
+گاوران
+دلالت
+۱۸۴
+اصحاب
+جزیره‌ها
+مهدوی
+آبیک
+افزايش
+مزیت
+جوابی
+صغیر
+منحنی
+رمین
+سانتیگراد
+دبیرکل
+غریب‌دوست
+بنزین
+اپیزود
+استانهای
+بهاءالله
+سپید
+کمونیستی
+سوگند
+شهباز
+اکتشاف
+استحکام
+مفاد
+بسازد
+اسکناس
+۱۴۰۰
+مبدأ
+بخورد
+مناظر
+زا
+پرستی
+تمبکا
+محرمانه
+سکنه
+زیتون
+رومانیایی
+جسارت
+عمومی،
+دات
+آهنی
+بینید
+مخابراتی
+نظرش
+مولداوی
+العظمی
+ولف
+ممکنه
+راننده
+اولاً
+وَمَا
+وسیله‌ای
+موی
+بادلو
+چرب
+مسافت
+مکس
+۱۷۸
+پودر
+عوام
+که،
+پنجم،
+گرگوری
+میسر
+مفصلی
+استبداد
+حیدرآباد
+آلیس
+فیروزه
+ریخت
+اینان
+کروی
+وقف
+شعارهای
+۱۹۶
+سملقان
+فروخته
+۱۷۴
+نبوده‌است
+دیکتاتوری
+میدهم
+ظریف
+معتبرترین
+سیاسر
+ایرادات
+اجماعی
+۱۹۳
+منحل
+زاید
+میخواهم
+صاحبان
+مهلت
+می‌پرداخت
+ماهه
+جری
+بازرس
+وَلَا
+گلشن
+برهنه
+نوشته‌ام
+می‌شود؟
+صخره
+عمو
+ابد
+بیداری
+۱۸۸۸
+۲۷۰
+بعلت
+پنیر
+حاتمی
+خانقاه
+رس
+شکسپیر
+معذرت
+پايان
+ساختگی
+آموختن
+فقدان
+پاسخگویی
+زانو
+كوه
+لزوما
+قمر
+شهریاری
+بيان
+واین
+صورتیکه
+بدنبال
+پاره‌ای
+ارمغان
+می‌شود؛
+شغلی
+دیگ
+عنبرآباد
+امریکایی
+پیشرو
+تجربیات
+علوم،
+پیری‌کندی
+ازجمله
+به‌نام
+صومای
+۳۳۰
+۲۶،
+اسطوره‌های
+منفجره
+دستتان
+رشته‌کوه
+۱۹۵
+برن
+بلده
+شیعی
+رحیمی
+رجایی
+کجور
+۱۵،
+تاون
+آموزگار
+آستارا
+هیل
+ترانه‌ها
+یوری
+کلاله
+محو
+خوانندگی
+زار
+عیب
+افسانه‌های
+پخت
+نامبرده
+پنجشنبه
+سور
+نروژی
+تکنیک‌های
+دریاچه‌های
+مالدیو
+سوسن
+کیسه
+کاوش
+دابودشت
+کردن،
+زندگان
+مقدمه‌ای
+موزهٔ
+۱۸۸
+برپایی
+داگلاس
+فضل‌الله
+زینب
+اللَّهَ
+صحرایی
+کرت
+اذیت
+نمی‌رسد
+آتشفشان
+۱۳۲۱
+بلاروس
+انگ
+ارگان
+بسامد
+نشوید
+بزرگای
+کلارک
+۲۱،
+بشدت
+نقوش
+خوشنویس
+الفبایی
+نخ
+رفیق
+ناراحتی
+رسی
+بخواهند
+طرفداری
+دردسر
+۴۵۰
+۱۸۳
+ایرباس
+پرت
+فرآیندهای
+گردشگران
+مخرب
+میگم
+کارتون
+نوژن
+سفری
+صندلی
+می‌کرده
+نزنید
+ج۱
+میخواهید
+گنگ
+می‌ریزد
+پشتکوه
+ویکی‌پدیاست
+دلاری
+ویکیفا
+خيلي
+بازگشایی
+چشمگیری
+نیتروژن
+بافی
+لانه
+بدید
+آشتیانی
+باشد؛
+محققین
+۲۴،
+یوتا
+طرفه
+توسعهٔ
+کشتی‌های
+۲۰۶
+جاستین
+شوشتری
+اسمیت‌سونیان
+طوطی
+عباسیان
+رده‌ای
+زرند
+می‌رود،
+ابتکار
+دهلران
+بستان
+برجای
+۳۸۰
+رمانتیک
+ترجمه‌های
+کاربرها
+بندری
+پرداختن
+منهتن
+پاتریک
+طناب
+چهارم،
+نتواند
+بور
+دانسته‌های
+روحیه
+میلاد،
+برزنجیر
+مرجان
+دهند،
+شهرستان‌ها
+سپرد
+داران
+استوارت
+دوچرخه
+طراحي
+۱۱۰۰
+خانه‌ای
+نوآوری
+نامنظم
+کامپیوترهای
+دیوانسالاری
+وفادار
+هرودوت
+امسال
+استثنا
+فرانکفورت
+مجالس
+خدمتتان
+کتابداری
+لاین
+پوران
+آنالوگ
+برادوست
+۲۰۸
+شادباش
+می‌شناسند
+بولکیمده
+می‌نویسم
+چالدران
+کهنوج
+تطبیقی
+۱۶،
+دیدگاهی
+منحرف
+شنوایی
+تیز
+تیغ
+موشکی
+پرشیانا
+امیل
+ایزدان
+سه‌گانه
+پنجه
+۱۸۹۱
+۱۳۲۲
+دين
+قبله
+جهنم
+خدماتی
+ببرند
+مأمور
+نیستیم
+کلمه‌ای
+اعتیاد
+فرانکلین
+معجزه
+ذهنم
+بازماندگان
+مصوبه
+کلینتون
+برسند
+معاهده
+نمیکنم
+چندگانه
+شهرستانی
+لاک
+موضوعاتی
+خوسف
+اسک
+خروس
+لتونی
+وات
+کرد؛
+رودکی
+خدمتم
+تاری
+مجلسی
+فهمید
+هفتگی
+کروز
+برگرداننده
+قیصر
+معروفی
+فكر
+نو،
+فضانورد
+فتح‌آباد
+هورمون
+الفاظ
+آمازون
+بیاوریم
+دستهٔ
+می‌کردید
+بینایی
+پافشاری
+بردم
+دیپلماتیک
+سنگینی

+نمره
+غیرآزاد
+فریب
+پذیرد
+حیطه
+اصلی،
+تربیتی
+محال
+ارجمند
+می‌یابند
+فلج
+اربر
+اینجا،
+آوای
+دودانگه
+چاه‌بهار
+همزه
+۲۳۸
+تمبر
+انوشیروان
+متن‌های
+پشتوانه
+عجب‌شیر
+قسمت‌ها
+آشوب
+بدرود
+نظرشان
+ه‌های
+روزتان
+استفان
+گیتاریست
+نشده،
+دینار
+چاره
+تیموری
+زهی
+مغولی
+۲۵۶
+هیوستون
+الموت
+۱۸۷۹
+راگبی
+لوکزامبورگ
+حیث
+عاج
+سخت‌افزار
+رمانی
+نگهبانی
+پتروشیمی
+چادر
+صلیبی
+کنکور
+کانسار
+بلوچ
+زاهدی
+هستید؟
+دوبله
+طیفی
+نشریه‌های
+زنبور
+حزب‌الله
+اخوان
+اجزاء
+ژنو
+دعای
+مزمن
+سخنی
+نهایتاً
+اندرو
+میشوم
+۱۸،
+دارمشترانگ
+می‌دارند
+سه‌شنبه
+حفره
+زرندیه
+ذخایر
+۱۳۱۹
+زنجیر
+سبکی
+قیمتی
+جنیفر
+۲۰،
+تعمید
+آبگرم
+حکمرانی
+پلاستیک
+بی‌نزاکتی
+تماشاگر
+لایحه
+بازه
+تحکیم
+موضعی
+جویی
+محافظة
+شاه،
+ما،
+۳۰،
+آمبرلا
+کلرادو
+هیجانی
+مجتهد
+گیاه‌شناسی
+اضطراب
+جنگ‌افزارهای
+۱۹،
+ادوار
+مسیری
+چمران
+پایه‌های
+گیتاشناسی،
+نمی‌کنید
+گیل
+متین
+آدلر
+۱۷،
+بعدش
+باکس
+یاس
+حکمیت
+کیلوبایت
+بریده
+هموار
+معقول
+کروم
+۱۸۸۶
+غزنوی
+نوش
+بازنشستگی
+گوینده
+یک‌نمونه
+هنر،
+میاد
+عظمت
+جهش
+جانبداری
+شبكه
+آسا
+استاندار
+۲۰۹
+فرانسیسکو
+بریتنی
+محدودیت‌های
+بشکه
+بنگرید
+تاثیرات
+آسفالت
+گیج
+کاروان‌سراهای
+فراموشی
+گلدار
+ترتیب،
+يافت
+همینجا
+بدخشان
+۲۵،
+تمدید
+زيادي
+هستش
+رضا۱۶۱۵
+بودی
+مهرماه
+اسکندریه
+لزوماً
+سیستمی
+هارون
+نگفته
+می‌دانیم
+سایوز
+آن‌را
+نوزده
+بمبئی
+فان
+میدانند
+۱۸۷
+دانستند
+اجاره
+فورت
+مراقب
+نفرت
+نوی
+۲۰۴
+تدریجی
+تهی
+نورآباد
+گزاره
+کلامی
+نتیجه‌ای
+پانک
+هاكل
+عفونی
+بسر
+پیشگامان
+بلاغ
+زئوس
+بريفين
+گزارش‌های
+نمایندهٔ
+سیالات
+۱۸۲
+فارسان
+جلدی
+فلک
+تحقیر
+فهمیدم
+ناتو
+سایرین
+شناور
+انستیتو
+نیکو
+مارکسیسم
+تبعیت
+تفریح
+زبان،
+گلوگاه
+بقیهٔ
+کمپین
+احراز
+بودن،
+محکومیت
+کماکان
+بستری
+تروریست
+سرواژهٔ
+دانمارکی
+آمستردام
+همی
+داوید
+کافیست
+دنی
+رون
+۶۰۰۰
+لابد
+کانتری
+سس
+کسری
+می‌فرمایید
+سیاستمدار
+حریم
+معنویت
+عسکری
+بخشیدن
+محصور
+مدافعان
+گرایش‌های
+واگن
+حجر
+سرداران
+مشهود
+یافتم
+تنسی
+نهر
+دارالفنون
+نمايش
+بسياري
+سابقهٔ
+یتیم
+توپولوژی
+۱۴،
+نگارشی
+جمعيت
+تنبیه
+کیو
+سقط
+شریفی
+کما
+میکروبیولوژی
+دیابت
+تاتنهام
+منقرض
+تاتی
+محمددین
+انگليسي
+فارسی‌سازی
+زمینهای
+شهدا
+۰۸،
+متکی
+کوه‌ها
+دزد
+کنایه
+مشایخ
+ارزان
+ماسه
+هرمان
+تنظیمات
+اونجا
+خار
+هیلاری
+چنار
+خزانه
+شکاری
+عجایب
+رنو
+قراردادن
+جابر
+سروستان
+مستطیل
+مجموعه‌ها
+بهمیی
+یکسال
+سرخرگ
+نادرشاه
+لیاقت
+دوستار
+وارده
+کاستیا
+لرزه
+اى
+بجا
+نم
+مغولان
+امارت
+کشاورزان
+طبی
+کجاست؟
+نبح
+نمایم
+للطباعة
+بکنند
+داستان‌ها
+آمیخته
+تاريخي
+اندازه‌ای
+پیکار
+مستعمره
+کوهپایه
+تصدیق
+۱۳۱۵
+فیلترینگ
+۰۹،
+آدینه
+توبه
+بصری
+بکنیم
+هوتک
+فیلم‌نامه
+پشتون
+زمره
+حبیبی
+اسکندری
+نیایش
+هائی
+رقابت‌های
+داوطلب
+ازش
+بنظرم
+دلیجان
+رضی
+مصاحب
+پرون
+بازگو
+آگهی
+قولی
+سیسیل
+انگلیسی‌ها
+مکاتب
+حبیب‌الله
+سانسکریت
+توکل‌آباد
+نموده‌اند
+حیوانی
+پروژه‌ها
+گیتی
+فالتز
+سنگسار
+بخت
+میلانی
+مارکوس
+نید
+شدیم
+۲۲۴
+مش
+فصول
+کتابش
+می‌خواهیم
+مشی
+آنی
+مادهٔ
+میکردند
+یکا
+طلبان
+عهدنامه
+الملل
+ارکان
+کاربریتان
+جلال‌الدین
+ایرونی
+یونس
+آبراهام
+فرشتگان
+فارسی‌زبانان
+۲۰۳
+۳۵،
+ناتمام
+موظف
+ایت
+می‌زنم
+ییلاق
+منی
+كم
+گریه
+بسازیم
+سیبک
+انجا
+موفق‌ترین
+۱۳۰۷
+ثروتمند
+گریخت
+زمان‌دار
+تروا
+ژرمنی
+برنارد
+تشكر
+ژنریک
+راهبردی
+گره‌های
+پارسی‌گوی
+بندهای
+مبادله
+اسفندیاری
+سرتیپ
+خوارزم
+کلاغ
+ياد
+ايراني
+نجف‌آباد
+سولفات
+كامل
+ناظری
+شهرستانهای
+أَنْ
+میگ
+پادگان
+مرتضوی
+زياد
+کلود
+مقاصد
+بهارستان
+دیکتاتور
+باستان،
+۳۱،
+اسکای
+الکلی
+میباشند
+پارتی
+بیاورند
+لایه‌های
+پرتقال
+آمیزی
+۴۰،
+۱۸۶
+رستاخیز
+خرگوش
+فیبر
+لیبرالیسم
+مخترع

+تعمیم
+برمی‌گردد
+تل‌آویو
+خورش
+مولد
+ستم
+باغات
+نژادهای
+ضربات
+آنست
+ارواح
+جوار
+اپرای
+تحتانی
+آنتوان
+زحمتش
+۱۸۸۲
+بازگشتی
+رفت،
+۱۸۹
+هوگو
+گیلاس
+۲۰۵
+دستاوردهای
+قضائیه
+۴۰۰۰
+مستقلی
+رعنا
+بخوان
+۵۶،
+سوزی
+تلاشی
+هرکسی
+میلی‌متر
+هفته‌نامه
+برومند
+کباب
+سرمایه‌گذاری
+پلاتین
+دنیس
+وگاس
+قرآن،
+نصرت‌آباد
+۲۲۵
+۱۹۱
+بافق
+ژاله
+آبریز
+صدد
+املاک
+مقاله‌
+بوانات
+پژو
+زمان‌ها
+کامیاران
+پگاه
+۲۰۲
+حرف‌های
+ترغیب
+حک
+مسطح
+دی‌وی‌دی
+جانبه
+سفیران
+غدد
+هستند؟
+مدرسه‌های
+۵۲،
+منبع‌دار
+چاله
+نائین
+مدير
+عکاسان
+آب‌خورده
+فیات
+خبرنامه
+مشهدی
+استرالیایی
+سیامک
+بگیر
+شایان
+درسته
+نامند
+ویرایشهای
+گل‌ها
+مایا
+گروه،
+آتشفشانی
+کرده‌است،
+نیمهٔ
+آزادشهر
+رانده
+علاقه‌ای
+ثریا
+متشکر
+ولت
+فرزانه
+صورت‌های
+دانشگاههای
+وز
+ویدئوی
+جنازه
+برتون
+جلوه‌های
+تغییرمسیرهای
+بیانیه‌ای
+دون
+نبوی
+یک‌بار
+رک
+حزب‌های
+مدارهای
+میگویم
+كنيم
+معلق
+تماشاگران
+نش
+نصیر
+۱۹۴
+رضاخان
+گردد،
+کنسول‌های
+قسمتهای
+شورشیان
+دقیق‌تر
+مداخله
+علاءالدین
+استنباط
+مصرفی
+باردار
+اهورامزدا
+ادبيات
+باهنر
+مقرر
+عزاداری
+كلمه
+خونین
+محدودی
+نمی‌دارد
+ذوق
+پرسش‌های
+بریم
+قشر
+۳۸،
+صالح‌آباد
+محسنی
+تخلص
+شکل‌های
+شوی
+رنگ‌ها
+توربین
+مگابایت
+فسفات
+واجد
+اهانت
+محفل
+برحسب
+گیگا
+گيرد
+۱۸۷۰
+صنفی
+تن‌تن
+برگردانده
+دایناسور
+لای
+می‌بینیم
+۰۴،
+فرمائید
+سیارات
+۵۱،
+تص
+سرودهای
+معترض
+ممكن
+متا
+می‌شویم
+ثلاث
+گفته‌های
+بی‌طرفانه
+هاپ
+نهان
+ادارات
+عجیبی
+جنایات
+دستورالعمل
+پارا
+نهادند
+ام،
+فتنه
+فواصل
+۱۸۵۰
+توریستی
+مرمر
+دیتابیس
+۴۲،
+کلیات
+۱۸۸۳
+لنین
+بلكه
+کاتوزیان
+میسیسیپی
+معاویه
+یوونتوس
+کشاورزی،
+هوافضا
+كوخرد
+فاریاب
+محيط
+نکنید،
+میترا
+رنگین
+آلپ
+آلومینیوم
+ملودی
+سیاستمداران
+گمر
+اسکان
+مختصری
+قشون
+جوادی
+رباتی
+۲۱۱
+جایز
+۲۷،
+محمودی
+كاربران
+یافته‌اند
+بگذریم
+محوری
+زمان‌های
+۲۲،
+انصراف
+میلا
+ساير
+۲۱۴
+تصریح
+۳۶،
+۲۸،
+آلباسته
+وظیفهٔ
+آذرشهر
+خدمه
+بارانی
+فیزیک‌دانان
+۱۸۸۴
+تماشای
+۱۳۱۱
+نويسنده
+علامرودشت
+افزاری
+گلشیری
+عملیات‌های
+داس
+ناخواسته
+هوتن
+واسه
+ثانیا
+لینه
+سنج
+اروپا،
+ایلیا
+بازمانده
+بشریت
+شناسی،
+۱۷۰۰
+کالیفرنیا،
+نکرده‌ام
+سیلیکات
+آزاده
+کامنت
+یونیکد
+آمدم
+احضار
+توده‌ای
+فرایندهای
+بیماری‌ها
+آخه
+تبلور
+۰۷،
+۲۰۷
+مونوبوک
+تصمیمات
+اختراعات
+جشنوارهٔ
+مشاهدات
+ریزشگاه‌ها
+۲۹،
+فیلادلفیا
+یزید
+سکولار
+خشایارشا
+سنتور
+محافظه
+کاپ
+نادرستی
+علی،
+محیط‌های
+منفرد
+اهتمام
+القاعده
+علاقهٔ
+لرزش
+عصبانی
+پسند
+لیل
+۲۲۶
+جدای
+جواهر
+ژولیوسی
+کوچک،
+شمیرانات
+بخوانند
+ربیع‌الثانی
+۵۰،
+۲۳۵
+توپخانه
+نیکلاس
+ویستا
+فردیناند
+۲۸۰
+تشییع
+نمیکند
+موسیقی،
+نیرومند
+۱۸۷۸
+غفاری
+بفتا
+هویدا
+صدیقی
+سلیمانی
+سياسي
+شهرضا
+جوانرود
+انتشاراتی
+شخصه
+۵۵،
+آسیاب‌های
+خوب،
+راههای
+والنشر
+حماسی
+عکسها
+۲۱۲
+۱۸۸۵
+تعریفی
+قاسمی
+مصادف
+مفرغ
+گشتاور
+۱۸۷۵
+شکل‌گیری
+طهماسب
+موجودیت
+ستاره‌ها
+آوردید
+سازه‌های
+۲۱۷
+ببریم
+ارسنجان
+بیدگل
+مگه
+عبادی
+فایل‌های
+۱۸۷۶
+تبریز،
+رهنما
+سپر
+قاره‌ای
+وو
+جعبه‌ای
+دانش‌نامه
+اجتماعي
+هیجان
+کارتر
+نرسید
+۳۳،
+کارم
+نمی‌شود،
+نسل‌کشی
+نمونه،
+صمد
+دریک
+میله
+پلاسما
+زاغ‌ده
+داروین
+۴۴،
+ویس
+قاچاق
+املای
+نامیدن
+گنجانده
+شادگان
+نی‌بید
+۲۲۲
+تسهیل
+هلن
+ناپدیدشدن
+خط‌ها
+ابلاغ
+شمع
+بازی،
+فندقاع
+جوهر
+پترزبورگ
+هخ
+سکو
+۴۱،
+یاسر
+۵۷،
+مستلزم
+آلبومی
+کلک
+ضخیم
+پاشا
+۲۳،
+۱۸۸۱
+دی‌ان‌ای
+حساب‌های
+غلامعلی
+خواندند
+معلمان
+همیلتون
+مداری
+مست
+تصویرها
+اندیشهٔ
+شدیداً
+دیواندره
+کنن
+بشوند
+نیامد
+مانگا
+۱۳۱۷
+چسب
+شجاعت
+مشتاق
+ایرا
+دانا
+بریتیش
+ویکی‌پدیاها
+مهم‌تر
+روبرت
+کافه
+ئی
+ارضی
+دست‌کم
+دندان‌پزشکی
+مهرآباد
+كننده
+رضوانشهر
+پراگ
+پال
+فرسایش
+درگاه‌ها
+راور
+میکروسکوپ
+فشارهای
+آرزومندم
+مصاحبه‌ای
+ویولن
+دریافت‌کنندگان
+نجیب
+سئول
diff --git a/perf/texts/hi-words.txt b/perf/texts/hi-words.txt
new file mode 100644
index 0000000..1dc18dc
--- /dev/null
+++ b/perf/texts/hi-words.txt
@@ -0,0 +1,10000 @@
+के
+में
+की
+है
+का
+और
+से
+को
+है।
+एक
+पर
+श्रेणी
+वार्ता
+भारत
+हैं
+भी
+यह
+शीर्षक
+पूर्व
+लिए
+गाँव
+ईसा
+उत्तराखण्ड
+किया
+ने
+इस
+संवत
+कि
+हिन्दी
+जो
+।
+जाता
+गया
+या
+जिले
+वर्ष
+जिला
+नहीं
+कर
+साँचा
+ही
+हैं।
+करने
+हो
+रूप
+था
+साथ
+द्वारा
+जन्म
+तहसील
+फ़िल्म
+होता
+तथा
+बाद
+विकिपीडिया
+आधार
+अन्य
+प्राचीन
+कुछ
+सदस्य
+अपने
+इसके
+प्रदेश
+तो
+एवं
+तक
+चित्र
+बाहरी
+राज्य
+जा
+प्रकार
+सरकार
+नाम
+दिया
+होती
+स्वागत
+कई
+वह
+बिहार
+करते
+सप्तर्षि
+जैसे
+थे
+समय
+अनुसार
+आदि
+वे
+सकते
+अधिक
+वाले
+किसी
+आधिकारिक
+सकता
+कड़ियाँ
+भारतीय
+उत्तर
+मण्डल
+हुए
+न
+जाती
+प्रखण्ड
+हुआ
+क्षेत्र
+लेख
+द
+बनी
+होने
+उसके
+करता
+इन
+अंग्रेज़ी
+संदर्भ
+थी
+था।
+शक
+कारण
+भाषा
+बहुत
+स्थित
+पहले
+उनके
+प्रसिद्ध
+सहायता
+जब
+दो
+अपनी
+कोई
+सबसे
+अलावा
+स्थान
+होते
+कम
+विश्व
+लिये
+ये
+जाने
+बारे
+लेकिन
+प्रयोग
+उन्होंने
+राष्ट्रीय
+वर्षों
+कहा
+पृष्ठ
+गए
+रहा
+आप
+देखें
+व
+एक्स्प्रेस
+तरह
+मे
+करना
+शामिल
+सभी
+प्रमुख
+आंध्र
+इसी
+अमेरिका
+प्राप्त
+करें
+अन्तर्गत
+इसे
+माना
+सितंबर
+उस
+५७
+इसका
+जानकारी
+नगर
+मुख्य
+हुई
+शिक्षा
+उन्हें
+संस्कृत
+कलियुग
+बीच
+गई
+विक्रमी
+रहे
+उपयोग
+मार्च
+पोर्टल
+काम
+वेबसाइट
+जनवरी
+कुमाऊँ
+उसे
+शहर
+जाते
+उनकी
+लोग
+जिसमें
+देश
+दी
+संघ
+थे।
+भाग
+लोगों
+जीवन
+१
+कार्य
+जी
+फिल्म
+विशेष
+बार
+ओर
+२
+इतिहास
+कभी
+दोनों
+अब
+निर्माण
+२००९
+पुरस्कार
+वाली
+शब्द
+पताका
+अधिकांश
+चिह्न
+विकास
+धर्म
+केवल
+लिया
+ए
+दक्षिण
+पुराने
+जुलाई
+यहाँ
+नया
+स्टेशन
+फिर
+लगभग
+संयुक्त
+अलग
+आन्ध्रप्रदेश
+गढ़वाल
+स्थल
+दिल्ली
+ई
+आरम्भ
+अपना
+जून
+विस्तृत
+यदि
+प्रान्त
+इसकी
+सूत्र
+शुरु
+मंदिर
+जालपृष्ठ
+जिसे
+घटनाएँ
+कृषि
+दौरान
+करती
+निधन
+दिन
+संगीत
+यहां
+तीन
+क्योंकि
+इसमें
+साहित्य
+ऑफ़
+मूल
+भूगोल
+॥
+पास
+पटना
+नए
+हालांकि
+सिंह
+प्रदर्शित
+प्रतिरूप
+अप्रैल
+बात
+विषय
+टेनिस
+२०१०
+प्रतियोगिता
+प्रचलित
+कहते
+विज्ञान
+विभिन्न
+अगस्त
+ऑफ
+पद्धति
+छत्तीसगढ़
+सन्
+जाना
+शुरू
+बना
+समूह
+अनेक
+थी।
+ता
+प्रामाणिक
+मध्य
+रही
+सूची
+संख्या
+व्यक्ति
+ऐसा
+गणना
+प्रति
+आज
+तब
+उनका
+क
+इलाहाबाद
+ऐसे
+मैं
+काल
+हम
+युद्ध
+गया।
+वाला
+श्री
+आदर्श
+स्थिति
+सी
+सकती
+दिसंबर
+प्रदान
+विक्रम
+विश्वविद्यालय
+रेलवे
+बड़े
+सामूहिक
+किया।
+किए
+राज्यक्षेत्र
+यातायात
+उन
+चार
+उपरोक्त
+दर्शाता
+बन
+अर्थ
+अलीगढ़
+दूसरे
+तौर
+गयी
+५८
+अन्तर
+उत्तरा
+राजा
+प्रभा
+क्या
+घटित
+मानकर
+विभाग
+कैलेंडर
+देने
+बनाने
+खेल
+प्रथम
+हिंदी
+इन्हें
+एकल
+उसकी
+एंड
+मसीह
+अथवा
+अमेरिकी
+जहां
+उदाहरण
+कलाकार
+निकाले
+आवश्यक
+७८
+महत्वपूर्ण
+पुरुष
+मई
+नदी
+जिसके
+प्रभाव
+आम
+जूलियन
+योगदान
+किये
+अधारित
+ले
+अधार
+इस्तेमाल
+सेवा
+३०७६
+जिसका
+३१०२
+पंचाग
+६६७६
+चर्चा
+भोजपुरी
+कैसे
+उर्दु
+कलेण्डर
+करके
+चाहिए
+स
+कला
+उपलब्ध
+जनसांख्यिकी
+साल
+काफी
+फर्रुखाबाद
+आगरा
+कंपनी
+३
+उच्च
+अक्तूबर
+आ
+मेरा
+स्तर
+नवंबर
+नीचे
+देता
+अध्ययन
+जारी
+कोड
+पहली
+प्रणाली
+अगर
+ओपन
+ध्यान
+उसका
+नामक
+बड़ी
+जल
+नैनीताल
+अक्सर
+अंग्रेजी
+सरकारी
+वर्तमान
+रंग
+जिससे
+मेल
+पुलिस
+रखा
+प्रत्येक
+हर
+बनाया
+ट्रेन
+सामान्य
+दुनिया
+भूमिका
+लिंक
+दे
+जबकि
+सन्देश
+शरीर
+पता
+भागलपुर
+विचार
+जहाँ
+लगा
+लेकर
+बड़ा
+वर्ग
+आगे
+छोटे
+तथ्य
+समाज
+पानी
+इससे
+उसने
+देशों
+महिला
+इसलिए
+देना
+पर्यटन
+एस
+परिणाम
+अल्मोड़ा
+सब
+स्थापना
+बाह्य
+स्थापित
+पौड़ी
+दल
+माध्यम
+आधारित
+पश्चिम
+प्रदर्शन
+सर्वश्रेष्ठ
+चीन
+शक्ति
+बाहर
+बी
+ऊपर
+बेगूसराय
+उत्पन्न
+हेतु
+डी
+आशीष
+अतिरिक्त
+समान
+वीं
+हिन्दू
+गये
+परिवर्तन
+आधुनिक
+लिखा
+कुमार
+देखा
+अंत
+मार्ग
+मानव
+रेल
+अक्टूबर
+आपको
+घर
+प्रश्न
+दूर
+कन्नौज
+भटनागर
+सामाजिक
+प्रकाशित
+अभिनेता
+देते
+कुल
+अभी
+जिस
+होना
+आई
+४
+पूरी
+संबंधित
+रहता
+ज्ञान
+ब्रिटिश
+कृपया
+हस्ताक्षर
+व्यक्तिगत
+बिना
+नई
+रोग
+१०
+दशक
+अधिकार
+परिवार
+शैली
+लेखक
+संस्करण
+जिनमें
+सेना
+संबंधी
+औरंगाबाद
+प्रक्रिया
+यात्रा
+२००८
+नये
+आवश्यकता
+ऐसी
+स्वयं
+होगा
+संबंध
+चिकित्सा
+मात्रा
+परियोजना
+प्रबंधक
+१५
+विकसित
+संदेशों
+होकर
+प्रकाश
+पहाड़ी
+पहला
+आकार
+सुधार
+जगह
+पन्ना
+सही
+मैथिली
+तैयार
+नवम्बर
+पिता
+मुक्त
+क्षेत्रों
+रचना
+१२
+२००७
+पूरा
+पी
+संस्थान
+५
+लोक
+१३
+चरित्र
+तुलना
+हुआ।
+लाल
+उत्पादन
+जनसंख्या
+रहते
+उसी
+इनके
+ा
+१४
+संदेश
+ज्यादा
+शताब्दी
+मृत्यु
+साधारण
+पाकिस्तान
+मास्टर्स
+दूसरी
+पुस्तक
+भगवान
+इनमें
+पूर्ण
+लाभ
+टीम
+बैंक
+अवधि
+भिन्न
+खिलाड़ी
+ली
+सदस्यों
+आने
+प्रयोक्ता
+कार्यक्रम
+सीमा
+समर्थन
+संस्कृति
+े
+अंतिम
+स्कूल
+बने
+विकि
+टी
+अ
+पाया
+नही
+र
+सदी
+फरवरी
+मुझे
+सन
+परिचय
+लेने
+मेरे
+पार्टी
+उत्तरी
+लिखने
+१८
+दिसम्बर
+राम
+भर
+विशिष्ट
+मी
+क्षमता
+प्रयास
+सहित
+पश्चिमी
+सिद्धांत
+दर्शन
+सभा
+किंतु
+वर्णन
+विधि
+श्रृंखला
+बजे
+संगठन
+गीत
+एम
+बेबल
+राजधानी
+प्रभावित
+पौडी
+ठीक
+सुझाव
+गति
+प्रबंधन
+व्यापार
+सामग्री
+ना
+एन
+दृष्टि
+दिया।
+पद
+ब्रजभाषा
+म
+सूचना
+शोध
+नामांकन
+अवधी
+लोकप्रिय
+आन्ध्र
+हाथ
+रहने
+विस्तार
+ऑस्ट्रेलिया
+वृद्धि
+फ़रवरी
+११
+जैसा
+आर
+कहानी
+व्यवस्था
+क्रिकेट
+बागेश्वर
+पृथ्वी
+चमोली
+गांव
+युग
+यौगिक
+कहीं
+पूर्वी
+२०
+सुरक्षा
+मुखपृष्ठ
+स्पष्ट
+१६
+मिलता
+देवी
+यही
+बुंदेली
+सामने
+प्रवेश
+यूरोप
+रखने
+दिए
+जॉन
+जिन्हें
+दूसरा
+पूरे
+स्थानीय
+आते
+नियंत्रण
+चीनी
+दिखाई
+प्रकाशन
+ऊर्जा
+प्राकृतिक
+की।
+जैन
+लगता
+बनाए
+अमरीकी
+कवि
+व्यापक
+दर
+वजह
+वहाँ
+परीक्षण
+लंदन
+प
+ी
+बदल
+जाए
+अदिलाबादु
+शासक
+खोज
+द्वितीय
+बस्तर
+मदद
+योजना
+ब्रिटेन
+प्रस्तुत
+जे
+धार्मिक
+आर्थिक
+सहायक
+लेखन
+शुरुआत
+मिल
+डॉ
+प्रौद्योगिकी
+शासन
+स्रोत
+रायगढ़
+वैज्ञानिक
+कमी
+आपके
+मिनट
+पत्र
+निर्वाचन
+रक्त
+ऑफिस
+गूगल
+संग्रह
+उद्योग
+राष्ट्र
+एशिया
+सांस्कृतिक
+पदार्थ
+इनका
+आपका
+मुंबई
+हिस्सा
+दृष्टिकोण
+उद्देश्य
+वी
+ह
+दूरी
+आता
+अनुवाद
+वो
+पीछे
+भूषण
+क्रिया
+स्वास्थ्य
+पैदा
+केंद्र
+२०११
+अच्छे
+पद्म
+शब्दों
+ऐतिहासिक
+गैर
+पिथोरागढ
+छोटी
+६
+सार्वजनिक
+कपूर
+प्रेम
+मुंगेर
+रहती
+चैनल
+समस्या
+कनाडा
+अंतर्गत
+देवनागरी
+राष्ट्रपति
+जिसने
+बैंड
+साम्राज्य
+कॉलेज
+मगही
+प्रयुक्त
+पुत्र
+अनुसंधान
+पहचान
+निर्मित
+किमी
+बंद
+प्रतिशत
+लगे
+अंतर्राष्ट्रीय
+ताकि
+भूमि
+मानक
+इंग्लैंड
+सके
+प्रारंभिक
+सन्दर्भ
+थीं
+अंगिका
+दिशा
+जर्मनी
+१९
+संकेत
+बच्चों
+द्वीप
+समाचार
+अफ्रीका
+घोषणा
+रह
+बंगाल
+भाषाओं
+घंटे
+हाल
+राजस्थान
+वहां
+आया
+उपन्यास
+कानून
+दिनों
+अभिनेत्री
+खिलाफ
+सदर
+अनुमति
+हवाई
+टीवी
+समाप्त
+मीडिया
+उपचार
+हमारे
+जनता
+नियम
+संक्षेप
+मन
+मिलियन
+चौपाल
+उपकरण
+राज
+भीतर
+चेन्नई
+२८
+कृष्ण
+क्लिक
+३०
+कविता
+कथा
+सूर्य
+प्रेस
+वीडियो
+स्वतंत्रता
+वन
+राजनीतिक
+आमतौर
+देती
+दृश्य
+न्यू
+योग्य
+लागू
+मिला
+बताया
+मैच
+जिसकी
+सा
+मीटर
+नेटवर्क
+रोचक
+भोजन
+हूँ
+मौजूद
+धीरे
+१७
+संभव
+माता
+नृत्य
+७
+महत्व
+परन्तु
+आशा
+डॉलर
+शायद
+आयोजित
+सम्मान
+युगल
+कांग्रेस
+सफल
+उर्दू
+उनमें
+वापस
+चाहिए।
+दें
+मनुष्य
+लाख
+महान
+निजी
+उल्लेख
+जैसी
+इनकी
+व्यवहार
+पन्ने
+नीति
+जाति
+एल
+पोस्टर
+विशाल
+बल्कि
+संचालित
+देखने
+विवाह
+अच्छा
+ख़ान
+२६
+इ
+कृष्णा
+वंश
+जापान
+केन्द्र
+मेरी
+तमिल
+देख
+विजेता
+वेब
+शिव
+सिर्फ
+न्यूयॉर्क
+भाई
+यूरोपीय
+राजीव
+प्रयोगस्थल
+उत्पाद
+मंच
+पांच
+०५
+पंजाब
+०४
+राजमार्ग
+मॉडल
+कंप्यूटर
+स्वीकार
+अंतर
+कार्बनिक
+सक्रिय
+परंतु
+लखीसराय
+किलोमीटर
+यमकेश्वर
+चला
+आलेख
+पड़ता
+उसमें
+ज्ञानसन्दूक
+आपने
+हमें
+मान
+इंजन
+तहत
+पत्रिका
+अवस्था
+९
+चम्पावत
+ं
+सहयोग
+मौलिक
+मामले
+अच्छी
+तिथि
+आरंभ
+स्वतंत्र
+बल
+बाजार
+८
+प्रारंभ
+मूल्य
+सरल
+वास्तव
+यू
+उससे
+तुम
+मैंने
+पुनः
+सागर
+पक्ष
+०६
+छोड़
+खाना
+अनुभव
+टू
+तरफ
+बस
+विजय
+महाराष्ट्र
+समुद्र
+उचित
+रेडियो
+चल
+हटाने
+खुद
+समीक्षाएँ
+जीव
+तेल
+दिल
+उम्र
+जर्मन
+ग्रंथ
+रूस
+संपर्क
+बौक्स
+रखें
+गंगा
+एल्बम
+राय
+पाठ
+हासिल
+निश्चित
+सीमित
+सात
+प्रांत
+गई।
+नेपाल
+दक्षिणी
+काव्य
+निर्णय
+छोटा
+२५
+डिजाइन
+रात
+हों
+लगाया
+वास्तविक
+पूछे
+ज्ञात
+प्रकृति
+कार
+गए।
+निर्वाचित
+तरीके
+त
+ज
+चुनाव
+किन्तु
+बढ़
+२१
+हो।
+जीत
+विपरीत
+दस
+वर्मन
+औसत
+इंडिया
+सम्मानित
+२२
+नाटक
+अधिनियम
+वस्तु
+संरचना
+मत
+सर्वाधिक
+लेखों
+विश्वास
+मास
+संकिपा
+वायु
+शीघ्र
+घटना
+निम्न
+विरोध
+सप्ताह
+स्वरूप
+प्रवेशद्वार
+सितम्बर
+गुरु
+सॉफ्टवेयर
+निर्धारित
+विद्युत
+रक्षा
+पूर्णिमा
+पड़ा
+बावजूद
+बेहतर
+वर्ल्ड
+चुका
+भारी
+मगध
+समुदाय
+क्यों
+ऑस्ट्रेलियाई
+जनगणना
+लीग
+अंक
+मिलती
+भागों
+बाल
+भेज
+कप
+कोरिया
+कर्नाटक
+मात्र
+हुई।
+अत्यंत
+तत्व
+महाभारत
+ओ
+अरब
+पूजा
+निर्माता
+रोमन
+विदेशी
+अल
+पर्वत
+पिछले
+इनसे
+पार्क
+स्थानों
+जिन
+धारा
+चुके
+मिली
+जाकर
+बदलने
+स्वामी
+सम्मेलन
+२३
+बनाये
+अल्मोडा
+शो
+जंक्शन
+मन्दिर
+गलत
+सफलता
+लिपि
+पाए
+योग
+निर्भर
+सिस्टम
+प्रसाद
+गांधी
+प्रचार
+फ्रांस
+वर्मा
+जिन्होंने
+रहें
+बौद्ध
+बच्चे
+आंदोलन
+एच
+तंत्र
+मोबाइल
+कोशिश
+अध्यक्ष
+गैस
+प्यार
+सारे
+ल
+लक्ष्य
+अवश्य
+लेते
+आसपास
+चरण
+पर्याप्त
+आयु
+शर्मा
+कार्बन
+सुरक्षित
+कोलकाता
+शीर्ष
+२७
+मै
+समिति
+धन
+विवरण
+सुविधा
+खान
+आती
+जिनके
+यद्यपि
+मामलों
+प्रशिक्षण
+सिटी
+कैंसर
+पात्र
+इतना
+रिपोर्ट
+नेतृत्व
+महिलाओं
+फल
+महीने
+सड़क
+देव
+मान्यता
+क्लब
+अनंतपुर
+क्रम
+य
+बजाय
+साँचे
+उप
+२४
+विश्लेषण
+आनन्द
+यूनानी
+चाहते
+राज्यों
+फाइनल
+अवार्ड
+जुड़े
+अत्यधिक
+तकनीक
+अज्ञात
+निकट
+सेंट
+चलता
+रेखा
+निर्देशक
+इंडियन
+मानते
+देवता
+जांच
+हे
+पत्नी
+इंटरनेट
+केरल
+जोखिम
+रिकॉर्ड
+बदलाव
+डिग्री
+प्रतीक
+जाएगा
+अतः
+पालन
+खंड
+विष्णु
+भौतिक
+जिनका
+अकादमी
+होगा।
+गुण
+वित्तीय
+क्षेत्रफल
+कर्नूलु
+करें।
+भाव
+तापमान
+०७
+अनुमान
+डे
+अमरीका
+रासायनिक
+च
+ग
+अभिनय
+पत्थर
+खाता
+किस
+गणराज्य
+टेस्ट
+चोर
+इत्यादि
+शुद्ध
+होगी
+भिकियासैण
+संघर्ष
+अंतरराष्ट्रीय
+लगातार
+माँ
+उल्लेखनीय
+रखते
+लक्षण
+जेम्स
+ग्रह
+प्राय
+वही
+औद्योगिक
+संक्षिप्त
+२००६
+विमान
+टिप्पणी
+नागरिक
+ध्वनि
+याद
+संचार
+बराबर
+प्रधान
+अमेरिकन
+पारंपरिक
+युक्त
+अत
+पुरी
+प्रतिक्रिया
+शाह
+चक्र
+अवसर
+हमेशा
+शारीरिक
+हंडिया
+आबादी
+तट
+लाइन
+विकल्प
+अंग
+लोकसभा
+खाद्य
+पर्यावरण
+संसार
+विवाद
+बनने
+करीब
+व्यक्तियों
+०
+वैदिक
+बिक्री
+ब
+निम्नलिखित
+कोशिका
+पार
+परमाणु
+भवन
+समझ
+नष्ट
+स्वर
+दुर्ग
+जितना
+प्रकट
+फॉर
+विमानक्षेत्र
+रख
+रुप
+शहरों
+तकनीकी
+लखनऊ
+मुद्रा
+हिस्से
+झील
+आयोजन
+इकाई
+मील
+समस्त
+संरक्षण
+अंदर
+संस्था
+परंपरा
+सतह
+कार्यों
+विद्यालय
+संसद
+अभियान
+सिद्ध
+मुख्यालय
+प्रस्ताव
+सीधे
+सर्वोच्च
+डालकर
+वाहन
+गुजरात
+उपयुक्त
+राशि
+बोली
+सक्षम
+अधिकतर
+नेशनल
+प्राथमिक
+मौत
+इसने
+गणित
+अली
+व्यवसाय
+हवा
+मिट्टी
+अगले
+फिल्मों
+चले
+डेविड
+मिलते
+बनाई
+महल
+आक्रमण
+रे
+राजनीति
+मंत्री
+गंभीर
+शाखा
+अम्ल
+हटा
+तटस्थ
+भविष्य
+ईश्वर
+आए
+वि
+दावा
+प्रसारण
+जीवित
+कड़ी
+रखें।
+लिमिटेड
+अन्दर
+क्रांति
+लिखे
+मैदान
+धातु
+एफ
+सम्बन्ध
+विलियम
+हृदय
+संभावना
+वातावरण
+न्यायालय
+लगाने
+सैन्य
+परिवहन
+परिषद
+चारों
+पवित्र
+योगदानकर्ताओ
+गुणवत्ता
+खगड़िया
+शेष
+करे
+ला
+युवा
+नियमित
+ऑन
+सर
+पसंद
+दबाव
+ईरान
+लागत
+०९
+०८
+२९
+अधिकारी
+उनसे
+कहना
+बोर्ड
+ग्रहण
+अशोक
+स्टार
+जान
+दिखाया
+ग्राम
+स्पेन
+नीतियाँ
+सभ्य
+०००
+समारोह
+संविधान
+इटली
+आठ
+संग्रहालय
+तर्क
+दूतावास
+पाने
+लिया।
+पाँच
+थलीसैंण
+लगी
+जन
+ताप
+परिणामस्वरूप
+लॉग
+लिखी
+रॉक
+कार्ड
+प्रेरित
+आगंतुकों
+फूल
+तेलगू
+लेता
+मिले
+रोगी
+आक्षेप
+जरूरत
+गठन
+व्यक्त
+भुगतान
+मौसम
+मीडियाविकि
+अन्तर्राष्ट्रीय
+पदार्थों
+पूर्वाग्रह
+रहे।
+शादी
+पुरा
+विषयों
+बिलियन
+ढंग
+आदेश
+लंबे
+काउंटी
+धन्यवाद
+मुस्लिम
+विरोधी
+वेल्स
+लिखें।
+पुरानी
+कांडा
+रानी
+विभाजित
+मिलकर
+तारा
+वैसे
+ईसाई
+पू
+शिकार
+ज्ञानसंदूक
+नेता
+शास्त्र
+कौन
+राजवंश
+ब्लैक
+अस्तित्व
+धारी
+प्र
+०३
+तेजी
+रायपुर
+संवाद
+किनारे
+टाइम्स
+भार
+सिर
+उत्तरप्रदेश
+छह
+आलोचना
+दिये
+गुप्त
+गेम
+नियंत्रित
+पुराण
+उद्यान
+डालें।
+हिंदू
+डीवीडी
+परीक्षा
+वालों
+घरेलू
+वस्तुओं
+व्याख्या
+पौराणिक
+अर्थात
+फूलपुर
+करोड़
+दिवस
+लघु
+जिसमे
+पिथौरागढ
+विज्ञापन
+पेश
+चर्च
+घोषित
+कंपनियों
+पशु
+पाएँ
+दर्द
+चलते
+समाधान
+माइकल
+सामना
+पूछें
+लड़ाई
+जोड़ें।
+संपादित
+जनरल
+विविध
+मिश्र
+आग
+भावना
+टिल्ड
+कैलंडर
+हत्या
+ग्रेगोरी
+प्रशासन
+रिलीज़
+खास
+मध्यम
+ज्यादातर
+अरबी
+रानीखेत
+देखते
+पाई
+आसानी
+अंश
+कश्मीर
+नवागंतुकों
+प्रभावी
+लिख
+किताब
+जीन
+इंडियाना
+चूंकि
+सत्य
+गंगोलीहाट
+नामांकित
+कोशिकाओं
+कार्यालय
+छात्र
+मस्तिष्क
+डेटा
+अनुनाद
+मंडल
+चुकी
+नारायण
+कर्म
+संपूर्ण
+प्रतिनिधित्व
+पहुंचती
+तेज
+अपेक्षा
+जाएगा।
+व्यंजन
+आत्मा
+वैश्विक
+मांग
+सेट
+इन्होंने
+सम्पूर्ण
+बदलें
+लग
+एशियाई
+रोड
+ऑनलाइन
+इस्लाम
+दास
+संत
+पक्षी
+बीबीसी
+व्यावसायिक
+सीज़न
+फुट
+जानते
+संक्रमण
+विचारों
+चाहता
+मतलब
+विरुद्ध
+रसायन
+निवेश
+वर्षा
+प्रमंडल
+संस्कार
+केन्द्रीय
+अंतरिक्ष
+ध्वज
+विशेषता
+बाकी
+थीं।
+यूनिवर्सिटी
+शंकर
+दैनिक
+आचार्य
+सं
+अनुरोध
+गायक
+मानसिक
+जमा
+हाउस
+मंत्रालय
+पहुंच
+जॉर्ज
+उपस्थित
+मार
+प्रधानमंत्री
+अंततः
+घनत्व
+थराली
+दूध
+सेवाओं
+वर्णित
+नियमों
+यूनाइटेड
+साथी
+विभाजन
+आपकी
+चौबटाखाल
+सम्मिलित
+प्रवाह
+गोल
+हुए।
+बिलासपुर
+कह
+जलवायु
+ब्राह्मण
+समर्पित
+निवास
+फोन
+प्रमाण
+पैमाने
+बिजली
+रोहित
+शांति
+अति
+उत्पत्ति
+तीसरे
+आनंद
+हमारी
+एकमात्र
+नुकसान
+मिलने
+पे
+सौ
+घटनाओं
+मां
+प्रायः
+भौतिकी
+कठिन
+माने
+घाटी
+अधीन
+स्थिर
+लेना
+उपयोगी
+रखना
+छूटती
+द्वार
+वेद
+चैम्पियनशिप
+बिंदु
+जुड़ा
+कल्पना
+आये
+संपादन
+तारे
+दें।
+परिभाषित
+उ
+सिद्धार्थ
+जापानी
+ऊंचाई
+भौगोलिक
+समुद्री
+आदमी
+उपकरणों
+स्त्री
+वाक्य
+निर्देश
+मशीन
+०२
+सत्र
+फुटबॉल
+घाट
+उपग्रह
+पंथ
+बहुधा
+हाइड्रोजन
+लंबी
+श
+सुंदर
+दौर
+रखता
+फ़ाइल
+मोहन
+देकर
+काला
+नंबर
+उपस्थिति
+दवा
+जीवनी
+आंतरिक
+परिवर्तित
+ज्ञानकोष
+वहीं
+आय
+समझा
+निगम
+वृक्ष
+पॉल
+बुद्ध
+बाज़ार
+मराठी
+रूसी
+जय
+ग्रैंड
+संचालन
+तत्वों
+व्यक्तित्व
+कीया
+३१
+कारणों
+बनाना
+अपराध
+फिल्में
+चक
+व्यास
+चाहे
+छोड़कर
+नमस्कार
+टेलीविजन
+डा
+वितरण
+एक्स
+पुराना
+रामायण
+बेरीनाग
+ग्रामीण
+सेंटर
+लाइसेंस
+मित्र
+छात्रों
+अध्याय
+शेयर
+अभाव
+मानना
+विद्वानों
+जनजातियां
+वैकल्पिक
+तुर्की
+जैव
+पश्चात
+नहीं।
+डिजिटल
+तारीख़
+समीक्षा
+हजार
+प्रिय
+इतनी
+अर्जुन
+शराब
+स्मृति
+जीता
+उच्चारण
+श्रीलंका
+बीजापुर
+निकल
+स्वीडन
+सत्ता
+संपत्ति
+गर्म
+बीमारी
+अर्थात्
+५०
+सम्राट
+व्रत
+मिश्रण
+वार्षिक
+प्रत्यक्ष
+अंकित
+रॉबर्ट
+समूहों
+आपूर्ति
+इंजीनियरिंग
+कैलिफोर्निया
+उनको
+गेंद
+इच्छा
+रन
+ऋषि
+समस्याओं
+आन्दोलन
+अपेक्षाकृत
+रोम
+चाहिये
+चलने
+गतिविधियों
+गाने
+विम्बलडन
+हैरी
+एण्ड
+इंच
+सेवाएं
+वेस्ट
+वें
+जाये
+पहुँच
+हूं
+श्रेष्ठ
+रहा।
+हार
+अस्पताल
+निरंतर
+नियुक्त
+तारों
+ख
+केंद्रीय
+वर्तनी
+धारण
+दान
+वाराणसी
+स्टूडियो
+रोगियों
+कुकर्म
+साधन
+जटिल
+अक्षर
+देंगे
+स्कोर
+उत्पादों
+प्रोटीन
+अनिवार्य
+२००१
+कायमगंज
+सौर
+सरगुजा
+साबित
+ऊँचाई
+लीला
+सैनिक
+स्टेडियम
+रायगढ
+पर्व
+जयपुर
+व्याकरण
+रावत
+इसलिये
+करेगा
+तीव्र
+प्रकाशक
+कृतियाँ
+प्रसार
+नोबेल
+सभ्यता
+परिसर
+अफ़्रीका
+राजनैतिक
+इलाज
+साहित्यिक
+सतपुली
+लिखित
+फ्रेंच
+देखे
+ऋण
+अकबर
+सोवियत
+हमला
+प्रोग्राम
+मिस्र
+डाला
+छत्तीसगढ
+आयोग
+पुरुषों
+रस
+सुनिश्चित
+पेरिस
+साहित्यकार
+परिभाषा
+डाटा
+अर्थव्यवस्था
+महाराज
+ओम
+सह
+पेज
+जिनकी
+वर्ण
+दर्ज
+भारती
+तभी
+तय
+एसोसिएशन
+अनुपात
+झारखंड
+जोड़ा
+पुन
+छत्तीसगढ़ी
+यानि
+लकड़ी
+त्वचा
+अधिकतम
+कोरबा
+देखकर
+डाल
+पुरालेख
+कोइल
+बढ़ती
+सफेद
+प्रतीत
+कानूनी
+चयन
+बनता
+हाथों
+जल्दी
+चार्ल्स
+ग्रन्थ
+रोक
+कारक
+खाने
+अभ्यास
+कैरियर
+वर्गीकरण
+सर्वेक्षण
+नारायणपुर
+मिश्रित
+ें
+तमिलनाडु
+प्राप्ति
+आकर्षित
+भेजा
+बनाकर
+संग्राम
+किले
+अड्डा
+कहलाता
+महसूस
+मार्क
+माल
+वजन
+फ़्रेंच
+ठोस
+उपयोगकर्ता
+चम्पा
+सलाह
+भेद
+काफ़ी
+लोगो
+खाते
+निर्देशन
+स्वर्ण
+बनाते
+नोकिया
+मूर्ति
+हद
+रोकने
+समाप्ति
+अकाउंट
+कार्यक्रमों
+ग्रीक
+संधि
+लंबाई
+निवासी
+दौरे
+चाहें
+क्षेत्रीय
+स्थायी
+किंग
+न्याय
+मोटर
+संभवतः
+बनाता
+पेड़
+तल
+पति
+वां
+कराया
+शुरूआत
+प्रारूप
+काले
+कांकेर
+रखे
+पौधों
+खेलों
+००
+काशी
+मस्जिद
+हरा
+आकर्षण
+नयी
+रखी
+मजबूत
+कडप
+आजकल
+टंकण
+साक्षात्कार
+तीसरी
+खेती
+महासागर
+लाया
+जोड़
+सामान्यतः
+सम्बंधित
+सुन्दर
+रचित
+जांजगीर
+पृष्ठों
+दीवार
+उन्होने
+विद्या
+लाने
+पड़ती
+संयोजन
+तीसरा
+पड़
+रोगों
+संसाधन
+भाषाएँ
+मानचित्र
+जमीन
+देहरादून
+मुगल
+कोर्ट
+कवर्धा
+धमतरी
+जशपुर
+पौधे
+कदम
+आकर
+बढ़ा
+अधिकारियों
+आरोप
+मिलाकर
+बढ़ाने
+प्रशासनिक
+हमले
+टाइम
+प्रेरणा
+उड़ान
+शक्तिशाली
+पीपी
+महासमुन्द
+विधानसभा
+फीट
+प्रगति
+स्नातक
+सूक्ष्म
+जवाब
+कम्प्यूटर
+अप
+छवि
+फ़िल्मों
+भ
+शुल्क
+विभूतियाँ
+कलाकारों
+संकट
+संभावित
+दिशानिर्देश
+जोर
+विधान
+आहार
+गोठ
+उपाधि
+राजनांदगांव
+जम्मू
+सतनाम
+कर्णप्रयाग
+थोड़ा
+बाबा
+साइट
+तथापि
+दन्तेवाड़ा
+यानी
+अमर
+मार्टिन
+तुरंत
+जिले।
+लाइव
+पुनःप्राप्त
+निर्धारण
+तत्कालीन
+कक्षा
+सारी
+प्रजातियों
+गये।
+करो
+मूल्यांकन
+द्वाराहाट
+राजशाही
+घई
+होगी।
+गैरसैण
+हॉल
+बिल
+ऐ
+रूपों
+मंगल
+जानी
+चित्रण
+नीतियां
+शिक्षण
+अवधारणा
+चेक
+किला
+तीनों
+मारे
+इमारत
+आवासीय
+किंगडम
+राजीवमास
+चुना
+आँकड़े
+फलस्वरूप
+करेंगे
+ज्योतिष
+यंत्र
+ग्राहक
+चित्रों
+नौ
+सल्ट
+उम्मीदवार
+कोश्याँकुटोली
+बीज
+उत्कृष्ट
+०१
+कम्पनी
+महात्मा
+खर्च
+केंद्रित
+सिन्हा
+हाई
+प्रबंधकों
+मुश्किल
+नर
+गाँधी
+बनाएं
+करनी
+हूँ।
+स्टेट
+प्
+दार्शनिक
+निकाल
+मनोरंजन
+पुस्तकालय
+सोचते
+जेल
+हिमालय
+पा
+जहाज
+तरल
+यूनिकोड
+सैन
+हास्य
+पैर
+दि
+दी।
+खराब
+ख़ुदा
+कृति
+पुष्टि
+हल्द्वानी
+असम
+अर्थशास्त्र
+सेवन
+ग्रंथों
+कड़ियां
+बदले
+पुस्तकों
+हेनरी
+रिचर्ड
+परम
+सके।
+पृ
+रहना
+हल
+सर्वप्रथम
+सामान
+काली
+चेतावनी
+मनोविज्ञान
+बॉक्स
+छोड़ने
+संगठनों
+तारामंडल
+हैदराबाद
+छिबरामऊ
+मुख्यतः
+टैग
+४०
+यहूदी
+विद्रोह
+दर्शकों
+ग्रुप
+जोशी
+डीडीहाट
+सेन
+गरुङ
+कीमत
+पीटर
+कृत्रिम
+विपणन
+प्राण
+आस
+बुनियादी
+वीर
+जल्द
+ऊपरी
+टिप्पणियाँ
+नज़र
+पहुंचा
+लेखकों
+ईंधन
+गुणों
+२००४
+स्ट्रीट
+बचपन
+लैटिन
+मलयालम
+हिमाचल
+सरस्वती
+स्वामित्व
+जंगल
+भनोली
+भक्ति
+श्रीकृष्ण
+नवीन
+मैन
+पीढ़ी
+शहरी
+लव
+अररिया
+अनुबंध
+विश्वभर
+स्मारक
+पुर्णीमा
+देवताओं
+पढ़ें
+प्रसारित
+परिस्थितियों
+रास्ते
+टाटा
+वा
+तरीका
+विषाणु
+अनुप्रयोग
+ईरानी
+यात्री
+संशोधन
+क्रमांक
+पंडित
+ते
+माह
+मुक्ति
+गहराई
+सुबह
+यहीं
+नाथ
+संबद्ध
+उत्तम
+प्रजाति
+मापन
+गद्य
+टीका
+वित्त
+विख्यात
+अवतार
+उपनिषद
+दीया
+मुहम्मद
+राजाओं
+फैसला
+परंपरागत
+जर्नल
+व्यापारिक
+होंगे
+एयर
+चौखुटिया
+मथुरा
+लगते
+उसको
+तनाव
+सिंगापुर
+उत्सव
+पुणे
+अभिव्यक्ति
+बढ़ावा
+इसको
+बच्चन
+द्रव
+अनुरूप
+एट
+मेट्रो
+उत्सर्जन
+एलबम
+हरियाणा
+चलती
+वाणिज्यिक
+डॉक्टर
+चली
+मानी
+लगा।
+लॉस
+सैनिकों
+सवाल
+२००५
+आरंभिक
+निदान
+अतरौली
+कराने
+मालिक
+देर
+तीर्थ
+विदेश
+यथा
+प्रबंध
+संपादक
+जैविक
+दोस्त
+मि
+अनुकूल
+संस्थापक
+इंटरनेशनल
+स्लैम
+सकारात्मक
+टाइप
+पुस्तकें
+रा
+मियामी
+लगे।
+ड
+घटक
+निदेशक
+इतने
+प्रतिनिधि
+मितुल
+अंग्रेजों
+दोनो
+बांग्लादेश
+वनस्पति
+बढ़ने
+बंदरगाह
+आसान
+सटीक
+मनाया
+भू
+समकालीन
+पाठक
+दोष
+औपचारिक
+डिस्क
+बेटी
+संदर्भित
+निभाई
+राव
+सूरज
+मगर
+चलचित्र
+मछली
+देखी
+जगत
+ज़्यादा
+सर्वर
+लम्बाई
+ग्रेट
+कर्मचारियों
+पंजाबी
+अगला
+शाही
+दर्जा
+चिकित्सक
+विकार
+फैला
+शुक्ल
+प्रजनन
+हां
+सदा
+अग्रणी
+नायक
+गृह
+धन्यवाद।
+जालस्थल
+आवाज
+बनाम
+कपकोट
+संघीय
+बिग
+गलती
+विविधता
+नो
+लगती
+पेट
+रिलीज
+विद्वान
+अन्तिम
+कॉपीराइट
+नमक
+अधिकारों
+प्रणालियों
+युकेश
+आर्ट
+रॉयल
+बालक
+पश्चात्
+हटाया
+पर्यटक
+आर्य
+प्रीमियर
+शब्दावली
+परत
+सिद्धांतों
+हमारा
+अकार्बनिक
+चोट
+कौशल
+प्रारम्भ
+विकेट
+गुना
+ब्रह्म
+आयरलैंड
+पेशेवर
+इस्पात
+ठाकुर
+अग्नि
+कोश
+रुचि
+उपनाम
+दत्त
+उम्मीद
+पशुओं
+श्रेय
+मुम्बई
+निकाला
+सिख
+पदक
+कवियों
+इसीलिए
+मार्शल
+बॉलीवुड
+खन्ना
+प्रवृत्ति
+यौन
+रचनाओं
+उड़ीसा
+तेलुगू
+आश्रम
+अस्पष्ट
+माइक्रोसॉफ्ट
+महत्त्वपूर्ण
+चयनित
+शास्त्रीय
+कर्मचारी
+जैक
+खो
+विशेषकर
+शब्दकोष
+स्क्रीन
+प्रतिमा
+बर्फ
+फारसी
+महाराजा
+ब्लू
+शून्य
+जरूरी
+आनेवालों
+दौरा
+प्रतिभा
+सच
+मौजूदा
+क्षति
+स्थलों
+खून
+फ़िल्में
+प्रशंसा
+होटल
+सेल
+सालों
+थ
+दुर्गा
+हाँ
+स्मिथ
+बुक
+नोट
+रचयिता
+शिखर
+नेहरू
+ब्रांड
+सुख
+समझने
+मुंह
+महाविद्यालय
+ईस्ट
+शृंखला
+बचाने
+आध्यात्मिक
+पुल
+त्याग
+आविष्कार
+हजारों
+कहता
+जाय
+प्रक्रियाओं
+विलय
+दूसरों
+जाए।
+२०००
+वापसी
+आकाश
+थॉमस
+इलेक्ट्रॉनिक
+कडियाँ
+संगीतकार
+परस्पर
+मुख्यमंत्री
+उपभोक्ता
+प्राणी
+होनी
+आउट
+स्व
+उपनिषदों
+वक्त
+कक्ष
+यांत्रिक
+आंशिक
+बांग्ला
+संकोच
+शनि
+ट
+हिन्द
+पट्टी
+लंबा
+कन्या
+जीवों
+नैतिक
+किशोर
+फ्रांसीसी
+वस्त्र
+शिकागो
+नदियों
+संस्थाओं
+ो
+गतिविधि
+कठोर
+सोने
+कंपनियां
+बेटे
+प्रतिरोध
+दवाओं
+न्यूनतम
+खैर
+गरीब
+मेला
+निकटतम
+स्थानांतरित
+लौट
+विटामिन
+जोड़ने
+ब्रायन
+यादव
+सहारा
+अफ्रीकी
+सिनेमा
+रचनात्मक
+नामों
+यज्ञ
+स्थितियों
+तृतीय
+हुये
+रिंग
+पोषण
+कहने
+उपाय
+विशेषज्ञ
+चार्ट
+क्लासिक
+मानवीय
+कार्रवाई
+एक्सप्रेस
+निर्देशित
+सम्बन्धित
+ग्राहकों
+चलाने
+अड्डे
+चेतना
+देखभाल
+रंगों
+विकी
+कल
+संबंधों
+सम्पर्क
+निष्कर्ष
+तंत्रिका
+वैज्ञानिकों
+टॉम
+प्रयत्न
+२००३
+पाठ्यक्रम
+चिंता
+३५
+श्रम
+बहन
+काल्पनिक
+डब्ल्यू
+कपड़े
+डबल्यू
+जातियों
+खाड़ी
+गीता
+हाथी
+डिज़ाइन
+एकीकृत
+कन्नड़
+खतरा
+प्रस्तावित
+खरीद
+अन्त
+कार्यरत
+ग्रीन
+विकिरण
+असफल
+हानि
+लोहाघाट
+कानपुर
+खिलाड़ियों
+छ
+सूचित
+अयोध्या
+स्टॉक
+चन्द्र
+गवर्नर
+लिंक्स
+फ़ारसी
+खनिज
+मंदिरों
+गिरावट
+पोखरी
+सारा
+आवाज़
+वायरस
+विलियम्स
+राधा
+सेंट्रल
+सहमत
+बातें
+रामनगर
+लिंग
+श्वेत
+लक्षणों
+दर्शनीय
+बाराकोट
+ऐंड
+सन्‌
+रास्ता
+वसा
+शती
+बदला
+उन्नत
+हिन्दुस्तान
+३६
+पृष्ठभूमि
+हार्ट
+सहज
+गिटार
+इतालवी
+पर्यटकों
+हरे
+खुले
+वर
+व्युत्पन्न
+जाँच
+धारणा
+मुख
+होली
+खड़े
+प्रतिष्ठित
+पड़ा।
+बचने
+निवासियों
+बरो
+लेती
+पीठ
+पाकिस्तानी
+रामचरितमानस
+आपस
+समझौते
+महीनों
+कर्ण
+हिस्ट्री
+सो
+पोस्ट
+पंक्ति
+बहु
+संशोधित
+कोलंबिया
+बचाव
+रिकॉर्डिंग
+थोड़ी
+चुने
+चौधरी
+अंकों
+शाम
+बातचीत
+ओलम्पिक
+गर्मी
+फ्लोरिडा
+गोली
+लाइफ
+लम्बी
+बम
+चावल
+बातों
+वर्गों
+आवास
+मिशन
+सफ़ेद
+४५
+दशा
+अपलोड
+मेडिकल
+जानने
+कार्यकारी
+सकतें
+समीप
+संयंत्र
+नि
+आवेदन
+मांस
+गहरा
+तरीकों
+छः
+कल्याण
+लगने
+हुसैन
+औ
+संजय
+जंगली
+केन
+सुपर
+सबूत
+साफ
+क्रमश
+लॉर्ड
+समझौता
+नाडु
+अदालत
+आगमन
+प्रथा
+डालने
+औषधि
+करवाया
+जिम्मेदार
+यान
+पन्नों
+महावीर
+सकें
+परम्परा
+मेक्सिको
+गोल्डन
+गईं
+टन
+एकदिवसीय
+आदि।
+ऑल
+१००
+प्रदूषण
+अणु
+चोपड़ा
+भा
+संरक्षित
+प्रभावशाली
+पुचः
+जुड़ी
+प्रोत्साहित
+तल्ला
+साधना
+न्यूटन
+लोकप्रियता
+भरा
+प्रार्थना
+बंगाली
+द्रव्यमान
+व्यावहारिक
+ट्रैक
+सावधान
+बैठक
+तुम्हारे
+पॉटर
+रथ
+प्रोग्रामिंग
+कही
+कमल
+मशहूर
+नजर
+धरती
+स्वाभाविक
+चेहरे
+सकता।
+शिशु
+कोण
+पॉप
+मन्त्र
+५१
+निवेदन
+अकेले
+आवृत्ति
+३२
+उठा
+कवर
+गरम
+शैक्षिक
+वास्तुकला
+पाते
+खूबसूरत
+एसिड
+होता।
+जायेगा
+पड़े
+सीजन
+नीला
+योग्यता
+वैध
+ग्लोबल
+पथ
+बीमा
+हिस्सों
+माप
+मैने
+बारह
+उल्लंघन
+जानवरों
+प्रवासी
+साहब
+एजेंसी
+हिट
+सुविधाओं
+सोच
+रवि
+गीतों
+पेन
+गुजराती
+अगली
+दर्शाया
+पतन
+चित्रित
+आकृति
+मैसूर
+बुद्धि
+मंत्र
+मनुष्यों
+पत्रकार
+पेय
+विद्यमान
+मादा
+बोलने
+मना
+बेस
+सहयोगी
+हराया
+समीकरण
+लिखते
+फसल
+संहिता
+लें
+तिलक
+प्रोफेसर
+सीधा
+आकर्षक
+संज्ञा
+मोटे
+वार
+खगोलीय
+क्रमशः
+समर्थक
+स्नान
+नकारात्मक
+नक्षत्र
+पहुंचने
+चित्रकार
+दुर्लभ
+सिद्धान्त
+भाँति
+छाया
+पूंजी
+आलोचक
+अपनाया
+बेहद
+खड़ा
+सका
+उदय
+भूल
+यमुना
+क्रेडिट
+साउथ
+नैदानिक
+हिल
+में।
+फ
+नील
+प्रयोगशाला
+५२
+शासकों
+मा
+हिसाब
+इन्हीं
+रॉय
+गाय
+घायल
+ऋतु
+तार
+लम्बे
+३८
+संपन्न
+क्रिस
+कृत
+उतना
+नामकरण
+स्वाद
+मनोवैज्ञानिक
+भय
+नौसेना
+हावड़ा
+४८
+श्याम
+कार्यवाही
+हस्तक्षेप
+दंड
+दुबई
+किस्म
+अभियांत्रिकी
+फ़िल्मफ़ेयर
+मोहम्मद
+उर्जा
+पारित
+गोरखपुर
+अस्थायी
+स्तंभ
+मुसलमानों
+असामान्य
+कैथोलिक
+वर्गीकृत
+पाप
+मनीष
+श्रेणियों
+भरे
+४६
+पढ़ने
+बिल्कुल
+खुला
+उद्यम
+मूलतः
+जोड़ी
+युनाइटेड
+दरबार
+मद्रास
+निकालने
+विरासत
+संगम
+निहित
+गिर
+कथन
+दाब
+आवश्यकताओं
+कहानियों
+ऑक्सफोर्ड
+आफ
+उन्हीं
+आधा
+मर
+सोसाइटी
+ब्लॉग
+मल्ला
+कालाढूगी
+आकलन
+अत्यन्त
+पकड़
+चाहिये।
+भरी
+भाषण
+आधे
+रत्न
+टूर
+नाना
+संस्थानों
+कालेज
+शल्य
+।।
+नौकरी
+जुड़ने
+गा
+मास्टर
+किरदार
+कुशल
+पक्षियों
+अधिग्रहण
+मजबूर
+खड़ी
+बताते
+अनिल
+महाद्वीप
+हथियार
+कलकत्ता
+प्लास्टिक
+पायलट
+स्वस्थ
+जिनसे
+रचनाएँ
+शिवाजी
+परिक्रमा
+२००२
+भोपाल
+पटकथा
+खत्म
+ड्राइव
+रूपांतरण
+भक्त
+४२
+अन्यथा
+उच्चतम
+बढ़ता
+असर
+रेड
+घरों
+व्हाइट
+आना
+खाली
+जॉनी
+राहुल
+कमजोर
+ब्राज़ील
+श्रीमती
+चाय
+रखकर
+ॐ
+एपिसोड
+मुसलमान
+जाया
+एडवर्ड
+पारी
+बांध
+विस्फोट
+उर्फ
+गुरू
+डच
+प्रमाणित
+समग्र
+मतदान
+कण
+पाटी
+प्रोटोकॉल
+विकिपीडीया
+हिंसा
+आजादी
+तस्वीर
+४७
+चुनौती
+क्रांतिकारी
+शेर
+न्यूजीलैंड
+ऑक्सीजन
+बनते
+निगरानी
+व्यवस्थित
+सर्विस
+आखिरी
+चिन्ह
+समृद्ध
+प्रयासों
+रेस
+पाता
+खतरे
+उन्हे
+पटेल
+बादशाह
+गर्भ
+हमने
+चरम
+मुखर्जी
+चलकर
+पाउंड
+जातक
+टिप्पणीसूची
+न्यायाधीश
+५५
+अनुच्छेद
+शास्त्री
+हि
+५३
+पेशकश
+बिट
+गणेश
+जीवाणु
+संकलन
+पीड़ित
+ख़ास
+बेस्ट
+निकलने
+लोहे
+ऑव
+स्वर्ग
+सोसायटी
+बेल
+भट्ट
+बढ़ते
+दुर्घटना
+त्यौहार
+संगणक
+विनोद
+हालाँकि
+न्यूज़
+गहरी
+पब्लिक
+४३
+तीव्रता
+पेटेंट
+तिब्बत
+पीने
+इस्लामी
+भीड़
+बहादुर
+ड्रामा
+सुल्तान
+हटाए
+अन्तरविकि
+साक्षरता
+विक्टोरिया
+सिनसिनाटी
+मठ
+प्रतिदिन
+सम्बन्धी
+निबंध
+बनाती
+नव
+विषय।
+तेलुगु
+वीकीपीडीया
+ऊतक
+असली
+संसाधनों
+जानवर
+डाक
+बाग
+डर
+स्रोतों
+प्रतिबंध
+सोमेश्वर
+कब्जा
+रहित
+अवशेष
+वरिष्ठ
+बेल्जियम
+देशी
+जीतने
+रणनीति
+हें
+ताल
+द्रव्य
+खेला
+राजस्व
+रीति
+गयी।
+सजा
+उपयोगकर्ताओं
+बोस
+आलोक
+आत्म
+फ़्रांस
+किसान
+गणितीय
+ज्वालामुखी
+अंगों
+ों
+बनती
+४९
+कायम
+खिताब
+तुलसी
+लक्ष्मी
+समानता
+वयस्क
+शिष्य
+संतुलन
+अचानक
+नदियाँ
+नीतियों
+नागरिकों
+जाल
+नामित
+नेताओं
+पात्रों
+सिविल
+कप्तान
+दुश्मन
+चमक
+अर्जित
+मौखिक
+स्वभाव
+आनुवंशिक
+कितने
+भागीदारी
+चोरी
+रोशन
+आलोचकों
+बोल
+गहरे
+गेट
+स्तरीय
+बता
+बहस
+जावा
+खासकर
+पड़ने
+दौड़
+३७
+निर्माताओं
+विशेषताओं
+माई
+काट
+५६
+सृष्टि
+फाउंडेशन
+संप्रदाय
+उपर
+प्रखंड
+एटा
+प्रकरण
+अक्षय
+स्कॉटलैंड
+राजकुमार
+इंग्लिश
+आइपी
+ध्रुव
+मैक
+अनुमानित
+मधुमेह
+गौतम
+चरणों
+कहे
+ि
+महादेवी
+निम्नांकित
+कथित
+परिणामों
+लिखना
+गाड़ी
+कॉम
+लड़की
+उद्धृत
+ब्लॉक
+३९
+टेलीविज़न
+एकता
+खेलने
+कारों
+सांसद
+चौथे
+सहमति
+बचा
+गाइड
+भले
+हा
+कां
+रिसर्च
+ज़मीन
+आयुर्वेद
+बॉब
+मुद्दों
+सोडियम
+तरंग
+चालक
+बाघ
+साइंस
+ग्लोब
+सकल
+मिलान
+बताता
+जिलों
+जिम
+पत्रिकाओं
+लगाना
+वाशिंगटन
+बैंकिंग
+प्राणियों
+ै
+ईमेल
+३३
+निर्दिष्ट
+पोर्ट
+पुर्तगाली
+चीज़
+बाबू
+अखिल
+उदयपुर
+चोटी
+शक्तियों
+मापदंड
+ण
+घातक
+माध्यमिक
+मारा
+जरिए
+इकाइयों
+५४
+लेजर
+विधियों
+खण्ड
+देखना
+कान
+प्रस्तुति
+३४
+अक्षांश
+कइ
+मानकों
+गुफा
+रखती
+सुरक्षीत
+होम
+करियर
+कारकों
+पत्रकारिता
+पृष्ठ।
+प्रचलन
+अनुक्रम
+इगलास
+जूनियर
+विनिमय
+अनुवादक
+विद्यार्थी
+निर्यात
+शब्दार्थ
+केन्द्रित
+सम्पादन
+बोध
+ब्रह्मा
+फ़ोन
+चाल
+ध
+अंडे
+हनुमान
+ज़
+बास्केटबॉल
+समापन
+राग
+छोर
+साहिब
+शांत
+यॉर्क
+अद्भुत
+राष्ट्रों
+सदन
+प्रसंग
+मोशन
+तकनीकों
+परामर्श
+पैसे
+एवम
+पं
+पृथक
+सरदार
+माया
+मारने
+लेबल
+टु
+निचले
+अतिथि
+महादेव
+परियोजनाओं
+दर्शक
+विकिपीडियन
+जगदीश
+विकिपरियोजना
+मुख्यत
+सीमाओं
+मुकाबले
+प्रताप
+यौगिकों
+बजट
+५९
+अहमद
+चलाया
+अहमदाबाद
+अनुपम
+पूर्ति
+पिक्चर
+स्कूलों
+अंग्रेज
+स्वीकृति
+बसा
+धरोहर
+आंकड़े
+बैटरी
+फूलों
+बेटा
+गर्मियों
+प्रबन्धक
+जोड़े
+महाकाव्य
+जन्मे
+गानों
+वनों
+लेन
+बाह
+एकत्रित
+नेपाली
+अमीर
+नीदरलैंड
+कहानियाँ
+मेयर
+ऑपरेशन
+एक्शन
+श्रेणियाँ
+४१
+चुंबकीय
+मृत
+मुद्दे
+हित
+तोड़
+करे।
+बर्मा
+कहलगाँव
+कहाँ
+बैंकों
+मेले
+ग्रहों
+परे
+ब्रज
+ऑस्टिन
+सूचीबद्ध
+जरिये
+दूरभाष
+कितना
+प्रभावों
+वध
+वर्णमाला
+कितनी
+सचिव
+पवन
+मैक्स
+पिछला
+सौंदर्य
+लो
+खबर
+वाह्य
+प्रचालन
+री
+प्रभाकर
+पहल
+प्रभाग
+अनुसरण
+पहलू
+धूम्रपान
+रिकार्ड
+प्रशांत
+अक्षरों
+कथानक
+पारिवारिक
+लाहौर
+भाषाओँ
+यात्रियों
+घास
+जनपद
+विचारधारा
+बिलकुल
+सीता
+प्रतिष्ठा
+निशान
+टॉप
+अवैध
+दूरसंचार
+लौह
+अतीत
+छत
+इंक
+पूर्णिया
+कोर
+एलन
+उद्योगों
+निष्क्रिय
+क्यूबा
+वेग
+स्टील
+टाउन
+यूनान
+साफ़
+अलंकार
+विफल
+कुत्ते
+सम
+करना।
+मलेशिया
+तैयारी
+भव्य
+ार
+पुत्री
+इमामगंज
+वकील
+४४
+संकेतों
+मूल्यों
+बाई
+भ्रम
+पाल
+ब्याज
+गहन
+अंतराल
+चौथी
+प्रतिस्पर्धा
+निश्चय
+कारोबार
+बच
+कोटि
+साझा
+खुल
+लन्दन
+सार
+राज्यपाल
+पराजित
+स्नातकोत्तर
+रात्रि
+शानदार
+हॉलीवुड
+नाटकों
+पीला
+ब्राजील
+ऊंची
+पाये
+जोशीमठ
+सदस्यता
+पैरों
+हॉट
+आँख
+शिक्षक
+घिरा
+फ़ाइलों
+कथाओं
+बिगाड़
+रुपये
+तू
+संदेह
+लेखा
+क्रिसमस
+भूकंप
+बुरी
+हवेली
+बीकानेर
+जोधपुर
+कहलाते
+करनेवाले
+दशकों
+प्रदेशों
+कमरे
+वुल्फ़
+जितनी
+खतरनाक
+गुगल
+मामला
+रक्तचाप
+डा०
+रविवार
+लीये
+स्थापत्य
+वाहनों
+छूट
+हों।
+प्रो
+जातीय
+फंड
+चौक
+सिक्किम
+मिस्टर
+टूर्नामेंट
+रहमान
+जड़
+बनवाया
+इलाके
+गठबंधन
+किरण
+गोपाल
+कागज
+शुभ
+मिस
+एयरलाइंस
+लाखों
+तत्काल
+अवार्ड्स
+मौका
+गोल्ड
+व्यापारी
+हरी
+सलाहकार
+मनु
+फ़र्रूख़ाबाद
+अपवाद
+मूवी
+जोन्स
+फ्रॉम
+शिकारी
+ऑडियो
+महेश
+गौरव
+ऊँचा
+कब
+सतत
+पहाड़
+अनिरुद्ध
+अध्ययनों
+इंदिरा
+उपर्युक्त
+एकत्र
+महर्षि
+भर्ती
+सोचा
+गुरुआ
+शुरुआती
+अभियान्त्रिकी
+जनवादी
+पड़ी
+आंख
+फ़्राँस
+गोवा
+जैंती
+ट्रस्ट
+सर्जरी
+संयोग
+गिरफ्तार
+रामपुर
+समाजवादी
+सृजन
+बपतिस्मा
+कोष
+आराम
+मैचों
+बसे
+पैदल
+तलाश
+थियेटर
+शुष्क
+विश्वयुद्ध
+प्रतिद्वंदी
+परिवर्तनों
+एकदम
+भ्रूण
+मासिक
+द्वीपसमूह
+माला
+फैल
+नरेन्द्र
+स्टोन
+उठाया
+सारणी
+प्रारम्भिक
+बेतालघाट
+बीस
+त्रुटि
+संगठित
+क्लास
+एड
+आयरिश
+हू
+ललिता
+आग्रह
+संतान
+प्रबल
+नहर
+डॉन
+प्रवाहित
+स्पेनिश
+बनावट
+भाषाएं
+करा
+प्रोत्साहन
+भ्रष्टाचार
+उष्णकटिबंधीय
+गाना
+उपरांत
+पोलैंड
+बनायी
+आएगा।
+पादरी
+फैशन
+बजाए
+टूट
+सोनी
+गले
+मलेरिया
+बंगलौर
+पढ़ाई
+क्रिस्टल
+चौड़ाई
+जोकि
+व्यय
+मिला।
+विवेक
+अब्दुल
+परिवारों
+बाधा
+भूत
+रंगीन
+राजेश
+नींव
+हाइड्रोकार्बन
+पीले
+राकेश
+बुलाया
+इंस्पेक्टर
+परिचित
+वेतन
+इलेक्ट्रिक
+तरी
+खोला
+पदों
+मेन
+स्तरों
+रोजगार
+डोमेन
+मानता
+सेकंड
+६०
+ईसवी
+सिरे
+नाइट
+गभाना
+यथार्थ
+लि
+कीट
+भावनाओं
+नरेश
+करार
+जानता
+कार्यकाल
+सिडनी
+रमेश
+परिमाण
+भरत
+कार्ल
+खोल
+म्यूज़िक
+पठार
+शाखाओं
+गुप्ता
+कार्लो
+तिरवा
+वर्षीय
+चक्रवर्ती
+दिव्य
+चंद्र
+पावर
+विथ
+पूरक
+मुफ्त
+ग्रस्त
+रोज़
+समुदायों
+शैक्षणिक
+नीले
+भिन्नता
+फ़
+देन
+जाएँ
+अनेकों
+काउंसिल
+प्रतिद्वंद्वी
+माइक
+चालू
+सम्भव
+क्रियाओं
+शहीद
+विश्वविद्यालयों
+चौथा
+सदैव
+सुधीर
+नागपुर
+दु
+नवाब
+स्पर्श
+कोट
+दलों
+लगाए
+इतिहासकार
+ओवर
+फ़तेहाबाद
+ऑस्ट्रिया
+हार्ड
+मुकदमा
+स्टीव
+चीज
+पायी
+बादल
+आकाशगंगा
+आवरण
+भेजने
+सुनील
+कुश्ती
+ईसापूर्व
+२००
+मुनि
+स्
+बृहस्पति
+प्रयोगों
+बयान
+खाँ
+शब्दकोश
+स्वचालित
+सिम्बल
+पसंदीदा
+उत्तराधिकारी
+संसदीय
+गायन
+क्षमा
+आतंकवाद
+पत्रों
+हरिद्वार
+लगाकर
+अतएव
+गार्डन
+बैठे
+मदन
+चौहान
+चन्द्रमा
+उठाने
+जायें
+अर्ध
+तारीख
+डाउनलोड
+अनु
+ओलंपिक
+श्रंखला
+दिखाने
+अमिताभ
+मौर्य
+मुताबिक
+प्रपात
+फोटो
+लक्ष्मण
+मालूम
+देगा
+अपील
+लेंस
+स्पेस
+बिन्दु
+द्वीपों
+स्विट्ज़रलैंड
+अर्जेंटीना
+पूछा
+वोट
+अकाल
+शत्रु
+कबीर
+आचरण
+सफलतापूर्वक
+एक्सचेंज
+उत्तराखंड
+शिकायत
+शंकराचार्य
+धारावाहिक
+दृश्यों
+१९९०
+तूफान
+सड़कों
+अपेक्षित
+बाढ़
+प्रोजेक्ट
+पहुँचने
+हूं।
+ग्रांड
+उन्नति
+कच्चे
+स्वीकृत
+बहती
+व्यायाम
+प्रयोजन
+एरिक
+ऑटो
+इंटरसिटी
+सरलता
+उपनगरीय
+अनाज
+धातुओं
+संकल्प
+तेरे
+धूप
+वंशज
+परिपथ
+घोड़े
+मोक्ष
+तालाब
+असमर्थ
+श्रद्धा
+विनाश
+सापेक्ष
+अद्वितीय
+सराय
+सुरेश
+जनजाति
+ट्यूब
+रहकर
+कैम्ब्रिज
+श्वसन
+सुविधाएं
+सूत्रों
+बंध
+जंगलों
+नेत्र
+डीएनए
+बिलबोर्ड
+आदिवासी
+दिखने
+गाया
+आर्थर
+नैशनल
+सिक्के
+वायुयान
+समक्ष
+समतल
+पिछली
+छोड़े।
+विधा
+सीखने
+कालीन
+बौद्धिक
+विधेयक
+सक्सेना
+खा
+यूनियन
+परमात्मा
+संस्करणों
+योद्धा
+पैटर्न
+स्त्रियों
+कर्तव्य
+जातियाँ
+वंशावली
+कमाई
+पैसा
+वसंत
+कहलाती
+एंजिल्स
+अपोलो
+सिंहासन
+इनपुट
+बस्ती
+दीवारों
+प्राधिकरण
+संभवत
+भालू
+केबल
+पुष्प
+सिंचाई
+मानने
+कॉल
+क्रॉस
+अभिगम
+उपलब्धि
+राजनीतिज्ञ
+नोट्स
+बे
+मेजर
+ग्वालियर
+प्रजातियां
+लॉ
+प्रसन्न
+यूएस
+रहेगा
+बुरा
+रोल
+नली
+उक्त
+राजकीय
+हल्के
+हंगरी
+पैलेस
+बनकर
+फेर
+पुरे
+घड़ी
+कविताओं
+स्वरुप
+सेनानी
+अवयव
+अनुप्रयोगों
+कृतियों
+ध्रुवीय
+विल
+इंडोनेशिया
+बहुमत
+टिकट
+कठिनाई
+शासनकाल
+कार्यान्वयन
+दायित्व
+जर्सी
+वितरित
+मूर
+टर्मिनस
+सुन
+जाएगी
+फोर्ड
+दीपक
+चित्रकला
+गरीबी
+सेमी
+तात्पर्य
+संलग्न
+आश्चर्य
+मेहरा
+१९९८
+भंडार
+परिषद्
+लाइब्रेरी
+बंधन
+इण्डिया
+कोयला
+महमूद
+सुना
+नंदीग्राम
+संतोष
+यूके
+जागरण
+बदलकर
+नींद
+बचे
+किसानों
+खुशी
+स्पोर्ट्स
+बलों
+भंग
+कहानियां
+सफाई
+रहस्य
+कणों
+किशन
+वृत्त
+अरुण
+मानस
+प्रेमी
+हमलों
+जीते
+नमूने
+त्वरित
+नम्बर
+शरण
+आतंकवादी
+रंगमंच
+टुकड़े
+निकलता
+ठंडा
+खेत
+गेम्स
+राजेन्द्र
+तालिका
+तटीय
+दिनेश
+भंडारण
+निकला
+मध्यकालीन
+५००
+पान
+चक्कर
+ब्राउन
+वाणी
+असाधारण
+यकृत
+बोलते
+रोटी
+झूठ
+पौधा
+वेदों
+संक्रमित
+जितने
+खूब
+नाभिकीय
+ज्यामिति
+रेटिंग
+जिम्मेदारी
+प्रेमचंद
+एजेंट
+निरीक्षण
+लुईस
+नित्य
+मेमोरी
+उतनी
+उसपर
+पड़ोसी
+तुम्हें
+वचन
+लोकतंत्र
+पार्श्व
+संवेदनशील
+उत्पादित
+सीरीज
+कॉर्पोरेट
+सूचकांक
+चैनलों
+अनंत
+नीतिया
+रिकॉर्ड्स
+ज़रूरत
+भावी
+होल
+विवादास्पद
+पिनकोड
+सरकारों
+पहलुओं
+जादू
+तपस्या
+विहार
+मोटी
+रुपए
+अपितु
+व्यंग्य
+सीधी
+सिर्फ़
+गुवाहाटी
+बेच
+नाटकीय
+शोर
+पुराणों
+मरीज
+वाजपेयी
+तिवारी
+रही।
+ब्रेक
+फैले
+विन्यास
+भाप
+थोड़े
+सर्वोत्तम
+शशि
+पार्वती
+रचनाकाल
+अदा
+गयीं
+पुर्णिया
+बॉन्ड
+बिन
+मोंटे
+नाक
+दीक्षित
+जिनमे
+अवलोकन
+नस्ल
+डेनमार्क
+वरुण
+विभक्त
+सैकड़ों
+अनुभूति
+पंजीकृत
+मतभेद
+कॉमेडी
+कलात्मक
+निकाय
+तरफ़
+आणि
+साथियों
+गुलाब
+झिल्ली
+सोना
+संश्लेषण
+इलाकों
+पण्डित
+आया।
+रेसिंग
+खपत
+टेलीफोन
+पड़ते
+दिलीप
+ई०
+एकादशी
+प्रतिबंधित
+फलों
+साइड
+उपासना
+खोटे
+प्रिक्स
+एचआईवी
+आमंत्रित
+फार्म
+इसपर
+रेंज
+१९९९
+प्रयाग
+मंगोल
+शासित
+रद्द
+अजय
+भाजपा
+आईएसबीएन
+सुमित
+एवम्
+रजिस्टर
+विकीस्रोत
+इंदौर
+बोइंग
+अमृतसर
+मकान
+पारिस्थितिकी
+मैड्रिड
+समन्वय
+अन्ना
+लोहा
+कम्युनिस्ट
+गण
+अवसरों
+ब्यूरो
+चूँकि
+खुली
+तन्त्र
+राजपूत
+समझते
+बिहारी
+वैष्णव
+चैंपियनशिप
+प्रतिकूल
+सिंड्रोम
+बंबई
+अमृतपुर
+ख्याति
+पुर्तगाल
+क्यूँ
+घ
+नारी
+अनुभाग
+मैरी
+गर्भाशय
+सर्व
+पूर्ववर्ती
+चतुर्थ
+इमारतों
+रेजिस्ट्रेशन
+प्रभु
+अस्वीकार
+साक्ष्य
+वॉ
+बढ़कर
+इनकार
+सांस
+प्रतिवर्ष
+भाषी
+बढा
+मूत्र
+अरारिया
+निकलती
+क्रिटिक्स
+धारक
+उपयोगिता
+त्योहार
+समेत
+प्रतिरक्षा
+बटन
+समर्थ
+दा
+नगरी
+तेज़
+भूतपूर्व
+देखता
+दमन
+अनुचित
+श्रीवास्तव
+हट
+प्रशंसकों
+भंडा
+तथ्यों
+दस्तावेज
+ऑपरेटिंग
+कोशिकाएं
+वाणिज्य
+पोषक
+धीमी
+वियतनाम
+स्कॉट
+रहीं
+घाव
+प्रावधान
+१९९२
+बैक
+श्रीराम
+मुकाबला
+स्टेट्स
+पादप
+गणतंत्र
+योजनाओं
+रोजर
+हार्मोन
+उत्पादक
+टेक्सास
+बेहतरीन
+फ़्रांसिसी
+राजस्थानी
+लगाते
+बीटा
+मान्य
+उद्धरण
+एज
+उद्घाटन
+पूर्वोत्तर
+हार्डी
+यहा
+शैलियों
+ऋग्वेद
+तमाम
+बेन
+सुभाष
+प्रशिक्षित
+दुबारा
+भीतरी
+प्रिंस
+हड्डी
+मल्ली
+बेचने
+महत्त्व
+आक्रामक
+कार्यकर्ता
+कटौती
+सोमवार
+गिर्द
+शुरूआती
+तिहाई
+खरीदने
+इट
+बिजनेस
+असंभव
+डिज़्नी
+जानकी
+ली।
+तें
+बने।
+खेले
+दादा
+पृथ्वीराज
+सांख्यिकी
+हुईं
+केविन
+बनारस
+रोशनी
+आरती
+पीछा
+स्थानांतरण
+रिश्ते
+बर्तन
+परिस्थिति
+बोले
+राष्ट्रीयता
+बलि
+इंजीनियर
+प्रमेय
+बुक्स
+उनपर
+छंद
+गुंजन
+टॉवर
+शाब्दिक
+स्वप्न
+सुधारने
+यूरो
+अवध
+तत्त्व
+निधि
+ललित
+भांति
+विमानों
+जलप्रपात
+चाहती
+आंकड़ों
+तेज़ी
+मैनेजमेंट
+मैट्रिक्स
+राजभाषा
+आयाम
+गुड
+पाली
+सनहौला
+पारस्परिक
+जंग
+पिक्चर्स
+इनको
+आस्था
+गुलाबी
+आजाद
+टेक
+ऊंचा
+एतमादपुर
+ब्लोक
+प्रतिनिधियों
+स्टेशनों
+हालत
+१९९१
+अटलांटिक
+ऊँचे
+वेबसाईट
+पत्ते
+आलू
+इन्द्र
+परिकल्पना
+सुनने
+गुलशन
+हज़ार
+कम्प्यूटिंग
+नियुक्ति
+पहुँचा
+विशेषताएं
+आयात
+खुदरा
+लैंड
+मग
+महा
+फ़िर
+अनुयायी
+काफलीगैर
+डाउन
+ओबामा
+कैद
+सूजन
+उपदेश
+विवेचन
+मोटा
+नारंगी
+धर्मों
+कुमारी
+बंदी
+ख़त्म
+अल्प
+कोटा
+चीजों
+पहाड़ियों
+८०
+सर्किट
+स्रोतहीन
+दुकान
+हंस
+सैद्धांतिक
+किरन
+देखें।
+तलवार
+सबके
+ब्रदर्स
+दोषी
+टेलर
+बॉल
+कटाई
+वाद
+पक्षों
+फ्रैंक
+नगरों
+वाहक
+विश्वसनीय
+समस्याएं
+पत्थरों
+कार्टून
+जि
+बीसवीं
+तिब्बती
+गो
+भेंट
+जगहों
+निष्पादन
+विक्रेता
+खगोल
+रोज
+कसम
+स्मरण
+क्रोध
+कॉमिक्स
+सूर्यवंशी
+पोप
+भेजे
+्य
+किरौली
+सख्त
+ग्रीष्मकालीन
+विल्सन
+सुदूर
+ढांचे
+जगन्नाथ
+ड्राइवर
+गांवों
+कश्मीरी
+स्वीडिश
+वशिष्ठ
+पीड़ा
+कहकर
+नैतिकता
+वस्तुत
+औषधीय
+मैट
+ज्योति
+नगला
+महापौर
+गठित
+प्रदाता
+श्
+आर्ट्स
+हटाना
+ऊष्मा
+सकने
+मरने
+ग्रीस
+मिश्रा
+हमसे
+आपसे
+क्वीन
+गिनती
+शिल्प
+मनोनीत
+एकड़
+रोकथाम
+हितों
+आशू
+अधिकृत
+इर्द
+सांता
+खुदाई
+स्टीफन
+विश्वकोश
+लायक
+विश्वनाथ
+गीतकार
+मुमताज़
+रूचि
+इराक
+लम्बा
+ग़ैर
+वॉशिंगटन
+आपसी
+भूमिगत
+भरपूर
+रावण
+वन्य
+सौरभ
+जुड़
+विद्युत्
+अद्यतन
+जीएसएम
+मैकमोहन
+सेतु
+दूरदर्शन
+संवैधानिक
+जीवाश्म
+डबल
+हानिकारक
+दर्पण
+पूजन
+विलयन
+िया
+लता
+उपहार
+क़ानून
+थिएटर
+परिचालन
+एकीकरण
+प्लेट
+हार्डवेयर
+समावेश
+संचिका
+अपशिष्ट
+मनमोहन
+फाइबर
+भारतीयों
+दुसरे
+आंखों
+संस्कृतियों
+यंग
+सदियों
+मत्स्य
+युक्ति
+फ्रांसिस्को
+बर्लिन
+लौटने
+मेहता
+क्षण
+पाश्चात्य
+गामा
+कैमरा
+ताजमहल
+सर्च
+बना।
+तल्ली
+साधनों
+पहचाना
+राजा।
+मेरठ
+जिसको
+मधु
+रिश्ता
+धूल
+गायब
+मोर
+सीरीज़
+इति
+सें
+सामुदायिक
+अनुदान
+ड्रम
+बडा
+कालिदास
+ब्रूस
+क्षय
+मातृवंश
+ट्रिपल
+प्रगतिशील
+गोस्वामी
+शनिवार
+हल्का
+हिन्दुओं
+फैली
+विष
+गर्भावस्था
+विस्तारित
+मिमी
+बा
+डेल्टा
+आँखों
+दीर्घ
+गंतव्य
+गणितज्ञ
+बिली
+बल्लेबाज
+क्लोराइड
+बालों
+मैनचेस्टर
+यु
+निर्णायक
+इंगित
+मयुर
+साप्ताहिक
+वैशाली
+पूर्णतया
+बच्चा
+अक्ष
+भविष्यवाणी
+भ्रमण
+हांगकांग
+ब्लेक
+रेस्तरां
+कृपा
+परेशान
+विकासशील
+मांसपेशियों
+गोविन्द
+प्राकृत
+कथाएँ
+गुलाम
+व्यस्त
+मार्गदर्शन
+कोंच
+कट
+प्रतिस्थापित
+वैभव
+पहने
+पाठकों
+बातकरें
+डॉग
+विकिमीडिया
+बेदी
+पोशाक
+चंद्रमा
+छिद्र
+इमारतें
+माउंट
+सिफारिश
+होगन
+उज्जैन
+समर्थित
+ब्रह्माण्ड
+रसूल
+श्लोक
+राहत
+आखिर
+एम्
+दाल
+पकड़ने
+मुँह
+उत्साह
+गर्दन
+तुलनात्मक
+काटने
+पाक
+महारानी
+ग्रंथि
+जरुर
+यूरोपियन
+आत्महत्या
+शर्त
+चुम्बकीय
+सम्प्रदाय
+नवीनतम
+हीरो
+मशीनों
+जयंती
+मिथुन
+उद्देश्यों
+सामयिक
+अकेला
+परिवेश
+मोड
+लवण
+चिली
+रखरखाव
+बोलचाल
+अभिलेख
+चाँद
+लें।
+सेनाओं
+अखबार
+दिखा
+रूपरेखा
+भास्कर
+समाधि
+विंडोज
+बनाया।
+भयंकर
+अमृत
+अरुणा
+ऊंचे
+खेर
+दोबारा
+बाध्य
+लगी।
+नागर
+उपन्यासों
+हीन्दी
+नाट्य
+जनक
+नमूना
+टीमों
+आउटपुट
+जोस
+कोरियाई
+मरम्मत
+डाक्टर
+सूरा
+कष्ट
+परीक्षणों
+बाएं
+भरने
+वेन
+केस
+महिलाएं
+लुप्त
+फ्रेम
+द्विवेदी
+असरानी
+शोषण
+नियमितता
+इंसान
+पद्य
+वायुमंडल
+पोल
+विलुप्त
+अपूर्ण
+बेचा
+लिनक्स
+कडी
+सतीश
+बहरहाल
+आयी
+हिन्दु
+मल
+बताने
+श्रीनगर
+लड़ने
+टोक्यो
+ऊँची
+पर्ल
+पितृवंश
+नी
+दीर्घा
+धार
+मंदी
+फ्री
+घंटा
+दोपहर
+इंस्टिट्यूट
+गुर्दे
+एचटीएमएल
+रजत
+अवकाश
+सीबीएस
+पाना
+होती।
+फेसबुक
+भगवानपुर
+पतली
+सीट
+मोड़
+मक्का
+स्पेक्ट्रम
+संरचनाओं
+इसमे
+बुध
+ब्लूज़
+अवसाद
+अफगानिस्तान
+पंजीकरण
+जरुरत
+अवरोध
+ब्राउज़र
+टाइगर
+विनिर्माण
+जालघर
+विज्ञापनों
+बॉट
+ग्यारह
+मुजफ्फरपुर
+गिनी
+परी
+मिलेगा
+कस्बे
+भाषाई
+बारी
+माँग
+गैलरी
+मिलन
+शुक्र
+आर्मेनिया
+इंस्टीट्यूट
+आत्मकथा
+सदस्योंको
+प्रतिपादन
+टर्मिनल
+रहेगा।
+पेड़ों
+मिली।
+कमीशन
+योनि
+फसलों
+गतिशील
+भी।
+संचरण
+प्रभुत्व
+उपक्रम
+समुचित
+दक्षता
+द्रविड़
+बन्द
+दिखता
+मध्यप्रदेश
+सारांश
+भीम
+अस्तित्वहीन
+हथियारों
+खुराक
+प्रकारों
+तेरा
+ताकत
+भगवान्
+लेक
+समकक्ष
+देशांतर
+ै।
+जोसेफ
+आज़ाद
+सामान्यत
+उपभोग
+भीष्म
+ऊतकों
+खिलाफ़
+लोकमान्य
+अन
+राजू
+अस्थि
+दरवाजे
+राजनेता
+आघात
+उपमहाद्वीप
+प्रख्यात
+टोनी
+टुल्सका
+विफलता
+स्टोरी
+बैठ
+बनना
+स्वतः
+भाषाविज्ञान
+दृढ़
+अर्थात्‌
+शी
+पचास
+प्रसिद्धि
+अपराधी
+डाली
+हरि
+डकोटा
+कोहली
+प्लेयर
+आश्रय
+नाग
+बिस्मिल
+छात्रवृति
+मिनेसोटा
+लाए
+सकें।
+चुनावों
+ब्रिज
+चिंतन
+बिगाड
+विमर्श
+पहुंचे
+होंगे।
+वैसा
+भूख
+दिखें
+नॉर्थ
+अवस्थित
+घेरे
+स्ट्रोक
+सर्बिया
+असल
+हिन्दुस्तानी
+घन
+वीज़ा
+महोत्सव
+घटकों
+बढ़ी
+करवा
+सुनकर
+रावल
+घट
+प्रायद्वीप
+स्वाधीनता
+विशेषज्ञों
+प्रबंधकोने
+कैलिन्डर
+धनरूआ
+डेली
+किलो
+जाट
+अधिकारिक
+माहौल
+सीटें
+पुरातत्व
+पीपल
+लीटर
+अनुकूलन
+गेंदबाज़ी
+शीह
+वायुसेना
+सूर्यगढा
+उन्होनें
+सिंध
+इधर
+टैंक
+पंच
+भूमध्य
+अफ़्रीकी
+डांस
+बलिया
+एड्स
+जनन
+जंतु
+समझना
+ग्रन्थों
+सैम
+गुरुत्वाकर्षण
+कोमल
+जायेंगे
+थाईलैंड
+टेलिविज़न
+दायर
+ज़िले
+त्रिपाठी
+प्राचीनतम
+विदेशों
+करी
+पढ़ा
+पर्वतीय
+नाइट्रोजन
+परशुराम
+स्वतन्त्रता
+चार्ज
+मेहनत
+फिलिप
+पेट्रोलियम
+नदियां
+पिंड
+उत्तरार्ध
+लेनदेन
+दीर्घकालिक
+आयतन
+मूलभूत
+टनकपुर
+डाटाबेस
+औरत
+नकल
+डि
+चैंपियन
+मोती
+होनेवाले
+दिमाग
+टेक्स्ट
+जीवनचरित
+मणिपुर
+फील्ड
+प्रक्षेपण
+निकले
+खड़गपुर
+करन
+९१
+प्रदर्शनी
+अनुष्ठान
+वक्र
+संबोधित
+शिविर
+वास्तविकता
+गोआ
+मेटल
+भगत
+सवार
+मजदूर
+शतक
+मानवता
+वॉन
+बढ़ाया
+दानव
+सदृश
+१९८९
+विभागों
+कमाल
+बचत
+मिर्च
+कॉफी
+बडे
+कीं
+फर्स्ट
+स्तन
+कोने
+संसारके
+१९७२
+डुमरिया
+क्
+आवागमन
+१९८०
+होम्स
+संकलित
+पत्तियों
+सूखे
+मुलाकात
+लास
+सनातन
+सामग्रियों
+कुत्तों
+रोबोट
+खैरागढ़
+कर्नल
+राखी
+आधारभूत
+पालीगंज
+स्पेशल
+संजीव
+अग्रवाल
+आस्ट्रेलिया
+आधी
+सूरत
+संक्रामक
+मुझसे
+मुग़ल
+वोल्टेज
+अणुओं
+ज़रा
+सील
+खनन
+समानांतर
+बोला
+ग्रे
+ष
+भागवत
+रंजीत
+मीनार
+पूर्णागिरी
+बीरबल
+गायत्री
+जबलपुर
+उजागर
+सशस्त्र
+कोच
+प्रश्नों
+बुंदेलखंड
+बडी
+बदलते
+पुर
+जीवविज्ञान
+राह
+प्रशंसक
+पर्यावरणीय
+लड़कियों
+स्टोर
+संगत
+प्रोफ़ेसर
+एलिस
+हिंद
+पूल
+भि
+९०
+भावनात्मक
+प्राथमिकता
+वाष्प
+ओल्ड
+आज्ञा
+औजार
+गैसों
+व्हिस्की
+रोका
+कहती
+जहाजों
+सशक्त
+दिवसीय
+उतार
+शान्ति
+वृक्षों
+प्रचुर
+प्रसव
+७०
+संरचनात्मक
+फीचर
+फॉक्स
+देरी
+पुरूष
+कीबोर्ड
+लाइट
+शिलालेख
+सपना
+व्युत्पत्ति
+कद
+सजीव
+लोकतांत्रिक
+स्राव
+विन्डोज़
+शॉट
+चिह्नित
+उधार
+जेट
+चे
+युधिष्ठिर
+माधव
+आसन
+संख्याओं
+शेख
+घूमने
+आक्सीजन
+राइट
+नियत
+इतिहासकारों
+एनरॉन
+रु
+पारम्परिक
+व्
+सर्वथा
+वाद्य
+आपदा
+दरभंगा
+जात
+१९७१
+लाभदायक
+म्यूजिक
+दावे
+वोल्डेमॉर्ट
+भारतवर्ष
+जोकर
+राणा
+कादर
+गढ़
+कनालीछीना
+मुकेश
+जाएं
+क्लार्क
+बॉबी
+सम्पन्न
+भूरे
+शोधकर्ताओं
+पूर्ववत
+अहिंसा
+बीमार
+जूते
+फाइल
+नारियल
+अमरीश
+अवतरण
+छेद
+शर्करा
+सेनापति
+एक्सेस
+वस्तुएं
+वादक
+दांत
+योगी
+चोल
+परिष्कृत
+श्रमिक
+नामांकरण
+सबको
+जिसपर
+इलेक्ट्रॉन
+महिमा
+क्षैतिज
+उत्तरदायी
+शूटिंग
+कारखाने
+आरक्षण
+आरेख
+किए।
+रो
+यों
+घटनाएं
+बाइबिल
+दम
+वार्ड
+ज़रूरी
+औचित्य
+एव
+१९७०
+तीस
+यूनिट
+खेलते
+डेटाबेस
+मामूली
+सफर
+अध्यक्षता
+आदर
+कॉर्पोरेशन
+चैतन्य
+िक
+निरपेक्ष
+निकोलस
+आसमान
+विश्राम
+वर्जीनिया
+अभिनीत
+आन
+संरक्षक
+दाता
+तेरी
+जॉनसन
+अल्कोहल
+दिस
+दर्शाते
+अन्वेषण
+लगाई
+जीने
+टीबी
+३००
+उदाहरणार्थ
+करण
+चंडीगढ़
+शरद
+कास्त्रो
+सहकारी
+छुट्टी
+स्थिरता
+जोड़ता
+कैल्शियम
+वुड्स
+ित
+सपने
+इत्यादि।
+प्रजा
+सेक्स
+शुक्रवार
+सर्दियों
+चीजें
+नाव
+फर्म
+हॉकी
+कहां
+विमानक्षेत्रों
+१९४७
+चढ़ाई
+परवर्ती
+क्षत्रिय
+ब्राह्मणों
+कराता
+नौबतपुर
+आयन
+आइ
+प्रवर्तन
+लिटिल
+स्वत
+नासा
+तंग
+रक्षक
+ग्रोवर
+शिवपुरी
+सीडी
+गौर
+बतौर
+कल्प
+साधु
+इकाइयाँ
+पढ़
+दीक्षा
+घंटों
+करेगी
+उदहारण
+लीवर
+सती
+बियर
+हार्वर्ड
+सहारे
+दक्ष
+१९९६
+अभिषेक
+तुम्हारी
+रेगिस्तान
+अभयारण्य
+चाचा
+प्रशासकीय
+टावर
+अनुकरण
+जें
+ऊन
+फायर
+जैसलमेर
+कविताएँ
+विक्रमादित्य
+लड़के
+न्यायिक
+आपराधिक
+निंदा
+सेठ
+गत
+दुर्योधन
+गगनचुम्बी
+हीरा
+१९९५
+वैन
+मिशेल
+मालुम
+जिमी
+रिपब्लिकन
+चटर्जी
+पेपर
+बोस्टन
+व्यापारियों
+शान
+सुप्रसिद्ध
+सचिन
+हु
+राजकुमारी
+निवारण
+विकृत
+त्रिपुरा
+लेबनान
+परेशानी
+१९९७
+देवलथल
+प्रत्यय
+मरीजों
+स्‍थान
+फतेहपुर
+ह्रदय
+अध्यापन
+लीड्स
+औरंगजेब
+वस्तुएँ
+निवेशकों
+सरोवर
+एंडी
+दिनांक
+कंट्री
+लीप
+गंध
+श्रेणियां
+आरक्षित
+मारुति
+प्रशासक
+ज़िन्दगी
+जन्मस्थान
+वॉल
+भाइयों
+सहकुंड
+शेयरों
+कवरेज
+धाम
+कर्ता
+वाल्मीकि
+संग
+सेल्सियस
+सलीम
+सूक्ष्मदर्शी
+यांत्रिकी
+इलाका
+रियल
+पंकज
+विशेषताएँ
+मकबरा
+प्रहार
+अजमेर
+अभिगमन
+केशव
+मयूर
+धनी
+ऑक्साइड
+अरुणाचल
+उपलब्धता
+नजदीकी
+इंजीनियरी
+डीन
+उपनिषद्
+जरूर
+प्रखण्ड।
+ब्रह्मांड
+शीत
+पहाड़ों
+एक्ट
+विण्डोज़
+छठी
+कश्यप
+वार्नर
+उ०व०
+बुश
+१९६०
+सन्त
+पारसी
+खोजने
+कुंजी
+रोमानिया
+इकट्ठा
+लय
+शस्त्र
+फलन
+तुलसीदास
+आदित्य
+जगदीशपुर
+नीम
+इयर
+सामान्यतया
+चार्ली
+जानेवाले
+एजेंसियों
+पाटिल
+सिगरेट
+बरकरार
+पाठ्य
+साहनी
+जोड़कर
+शैल
+पाचन
+लेट
+से।
+अनावश्यक
+गतिविधियाँ
+विषयक
+शर्तों
+असंख्य
+याहू
+विक्रय
+राष्ट्रमंडल
+ऑस्ट्रेलियन
+बलिदान
+उपेक्षा
+पाती
+गौरी
+संचित
+मार्केट
+सिकंदर
+सीरिया
+अभिक्रिया
+टक्कर
+दहन
+हैमिल्टन
+घोष
+समाजशास्त्र
+भाग्य
+चट्टानों
+साझेदारी
+पठन
+उत्तेजित
+अवशोषण
+चिकित्सकीय
+अपमान
+ओजोन
+स्तूप
+वयस्कों
+ट्यूमर
+रॉ
+इंटरफेस
+टेबल
+संज्ञानात्मक
+सच्चे
+कपड़ा
+वक़्त
+ऐल्बम
+मित्रों
+बीहता
+उदाहरणों
+ऑस्कर
+पृथक्
+घी
+अं
+सुई
+झलक
+विराम
+फोर्ट
+पुरस्कारों
+इज़
+एनबीसी
+रखा।
+सत्येन्द्र
+वर्णक्रम
+चांदी
+वेगास
+नें
+वषीश्ठ
+श्र
+बगैर
+पुनर्निर्माण
+आदान
+हिटलर
+क्षतिग्रस्त
+ज्यों
+प्रसंस्करण
+सुरंग
+शाकाहारी
+धनुष
+वैचारिक
+मधुर
+गायिका
+प्रोफाइल
+प्रतिरोधी
+उपज
+संवर्धन
+चेहरा
+बाँध
+कोर्स
+स्पेनी
+परिप्रेक्ष्य
+प्रतापगढ़
+महानगर
+सुनाई
+गद्दी
+वास्तु
+निर्देशांक
+आँखें
+व्यतीत
+उन्नीसवीं
+गिरने
+भावों
+सांख्यिकीय
+आशय
+भगवती
+साधारणतया
+भोज
+मुराद
+रवी
+प्लेस
+परंपराओं
+हिप
+डार्क
+चुन
+साजन
+परिदृश्य
+रज़ा
+ताइवान
+सवारी
+देखिये
+त्रिकोण
+कपड़ों
+पद्धतियों
+अपनाने
+स्त्रोत
+खिज़िरसराय
+समर
+जड़ी
+वेदव्यास
+१९६५
+चलन
+जिव्
+सौंप
+औपनिवेशिक
+चिकित्सीय
+ट्रेड
+स्वच्छ
+बुरे
+डैनियल
+मंगलवार
+पूर्वज
+उष्मा
+चिकित्सकों
+रूपांतरित
+जंतुओं
+नारद
+पैकेज
+नागरी
+पल
+बहुविकल्पी
+तथाकथित
+कार्यक्षेत्र
+पंख
+अवॉर्ड
+मसौढी
+तम्बाकू
+लहर
+बीमारियों
+निरूपण
+साइकिल
+थीम
+क्रान्तिकारी
+इंग्लैण्ड
+सर्वत्र
+जॉर्जिया
+शेट्टी
+छाप
+मलिक
+हैमबर्ग
+स्वदेशी
+सूचक
+१९६२
+धारचुला
+चर्चिल
+रिलायंस
+ईस
+ती
+संकर
+विजुअल
+उदार
+उद्गम
+पंचमी
+मंजूरी
+अनन्त
+प्रायोजित
+नेट
+मालवा
+लाई
+बगल
+धर्मेन्द्र
+नाश
+फीफा
+नगरपालिका
+टेप
+खुर्द
+मार्गों
+धमकी
+शिवलिंग
+प्रासंगिक
+धरहरा
+मारिया
+विवादित
+मेक्सिकन
+१९८६
+उपायों
+दरअसल
+सम्पादक
+वृत्तचित्र
+सिंगल
+लुई
+विद्यार्थियों
+मुद्दा
+फैसले
+आए।
+अलगाव
+मिशिगन
+धान
+भयानक
+पिट
+दिखाए
+ान
+चाप
+पहनने
+विशेषज्ञता
+पैट्रिक
+इनमे
+चर
+कुत्ता
+निर्वाण
+दण्ड
+नागरिकता
+दुकानों
+वर्चुअल
+लंका
+शॉन
+ब्लड
+जैक्सन
+जलीय
+अमास
+कड़ियों
+अनुसूचित
+रेत
+गारंटी
+दिशाओं
+स्टैनफोर्ड
+मूलत
+डेनियल
+परि
+सेवक
+अमृता
+शताब्दियों
+जायेगी
+दिलचस्पी
+नाईट
+मॉडलों
+हान
+स्वायत्त
+ज्वर
+जवाहरलाल
+आगामी
+कूद
+बुधवार
+राक्षस
+आयेगा।
+इंटर
+वांछित
+धमनी
+सुलभ
+बाण
+वाई
+पुरातात्विक
+गौड़
+सामवेद
+नाभिक
+अध्यापक
+समाजवाद
+उद्भव
+डैनी
+चक्रवात
+फैलाव
+एंटीबायोटिक
+चर्चित
+जितेन्द्र
+उपनिवेश
+लास्ट
+१९७५
+डाई
+गुणा
+सूट
+इलेक्ट्रॉनिक्स
+स्क्वायर
+डाले
+दुःख
+कुंड
+सांचे
+चंपारण
+प्रवास
+दुख
+अधिवेशन
+भरोसा
+तप
+महामारी
+सेब
+जेरी
+हसन
+ऑर्डर
+घोड़ा
+पासवर्ड
+खारिज
+ख़ुद
+इन्होने
+डेविस
+सरन
+प्लाज्मा
+खुलासा
+स्कॉटिश
+टोरंटो
+बेकर
+प्रतीक्षा
+कराते
+क्षमताओं
+पांडे
+हॉप
+कांच
+मणि
+ऐतरेय
+णी
+न्यूज
+संतुलित
+सीला
+विरूद्ध
+द्वितीयक
+ट्रक
+भेदभाव
+निराला
+नजदीक
+भाष्य
+आयेगा
+सहन
+उस्ताद
+नॉर्वे
+बैठा
+संस्कारों
+घने
+गोपनीयता
+स्तम्भ
+वैमानिक
+पंत
+भक्तों
+सम्भावना
+श्वास
+ओवेन
+जगत्
+फायदा
+तस्वीरें
+रुक
+निषेध
+नेटवर्किंग
+आयरन
+मॉडलिंग
+१९८४
+चंद
+शिमला
+कोल
+मनोज
+बैल
+झा
+केन्द्रों
+केप
+एकाधिक
+कुरुक्षेत्र
+डिएगो
+कराना
+फिल्मी
+ठहराया
+जिल्ला
+अमीरात
+ज़िला
+प्रतिस्थापन
+मूर्तियों
+कूट
+साहस
+बेबी
+हाइब्रिड
+पेशी
+तिरुपति
+सोलह
+इयान
+डिक्शनरी
+ताज
+बहुमूल्य
+सुगंधित
+पैनल
+वाटर
+नकली
+टैक्सी
+अस्त्र
+बुखार
+जानना
+उत्परिवर्तन
+निमित्त
+द्वारका
+फिलिप्स
+कांगो
+आइलैंड
+दाढ़ीकेश
+आक्साइड
+मिल्वौकी
+पर्वतों
+१९८५
+ढाल
+ईस्टर
+वर्षो
+उधर
+बिल्डिंग
+ज़ोर
+निर्भरता
+सिन्धु
+अनौपचारिक
+यम
+योर
+नवजात
+नियंत्रक
+अनुभवों
+विज्ञानी
+लगाये
+वर्णों
+स्वतन्त्र
+अलौकिक
+हीं
+बदलता
+डालते
+चौड़ी
+आशीर्वाद
+गोद
+उपाध्याय
+जिनको
+स्टर्लिंग
+क्यू
+सिपाही
+मासने
+अनुभवी
+अपभ्रंश
+सलमान
+दर्जे
+आईसीसी
+मेँ
+किलोग्राम
+इंजनों
+खुश
+किंग्स
+व्यर्थ
+प्राप्तकर्ता
+सल्तनत
+उत
+सीख
+१०००
+अवयवों
+जिक्र
+दीप
+ज्ञानपीठ
+कोयले
+्र
+संदिग्ध
+नम
+परमाणुओं
+मछलियों
+मार्टिना
+स्कैन
+मादक
+अधिवर्ष
+महान्
+लेखांकन
+आजीवन
+बेला
+बाली
+दाहिने
+उठ
+भूरा
+कोस्ट
+यंत्रों
+दलित
+पर्याय
+प्रस्थान
+रेखाओं
+ईस्वी
+पालतू
+गिरा
+बरौनी
+१९९४
+प्लग
+दोहरी
+एडम्स
+अजीत
+सावधानी
+थ्री
+आशंका
+सिल्वर
+न्यूयार्क
+रोमांस
+डॉट
+कॉपी
+बाप
+ईंट
+गर्भवती
+लाला
+घूर्णन
+जया
+यशवंतपुर
+पागल
+जागरूकता
+कंठ
+आईटी
+पत्तों
+समर्थकों
+टूल
+राउंड
+अन्‍य
+ग्रिड
+दंत
+हिंसक
+तार्किक
+विशुद्ध
+बैठने
+मुद्रण
+सकती।
+पहुंचाने
+कंधे
+परिश्रम
+खोलने
+वृत्तांत
+सिस्टम्स
+धरातल
+सांचा
+संवेदनशीलता
+जिंदगी
+पूर्णतः
+पुरस्कृत
+सराहना
+अन्न
+मीठा
+संतों
+डीसी
+एंड्रयू
+़
+बृहदारण्यक
+टुकड़ों
+रिजर्व
+खंडन
+उपभोक्ताओं
+टिम
+नागार्जुन
+श्रवण
+प्रविष्टियों
+कीटों
+रेसलिंग
+मैदानों
+अभिनव
+एनिमेटेड
+दीन
+बारिश
+मॉल
+डेथ
+क्रान्ति
+छोड़ा
+पुण्य
+प्रतियोगिताओं
+देह
+माइक्रोफोन
+मनाने
+किम
+हेल्थ
+अभिव्यक्त
+दस्तावेजों
+बेरी
+अपहरण
+टोपी
+बाजारों
+संग्रहित
+देखो
+बहने
+भली
+चतुर्वेदी
+विघटन
+रियासत
+भवनों
+जायेगा।
+छठे
+अपर्याप्त
+वस्तुतः
+कार्बोहाइड्रेट
+इंजेक्शन
+नायर
+विद्रोही
+बैटमैन
+गोल्फ
+प्रतिज्ञा
+जरा
+पीस
+बदलती
+खरीदा
+इंटरनैशनल
+झुकाव
+लाना
+उत्थान
+सुसज्जित
+अर्चना
+ओं
+लोड
+कमांडर
+१९८२
+विद्यालयों
+व्याप्त
+आतंक
+अनियमित
+विंग
+चंद्रशेखर
+जाहिर
+त्र
+काटकर
+गिल
+इवान
+एंटी
+जाता।
+प्रदीप
+वकालत
+परजीवी
+प्रणालियां
+अहम
+केले
+चन्द्रगुप्त
+इक्विटी
+दोस्तों
+विद्यापीठ
+समर्पण
+जिल
+तोड़ने
+फिलाडेल्फिया
+पंचायत
+चिड़ियाघर
+नर्मदा
+विनियमन
+परम्परागत
+लॉजिक
+बधाई
+टेक्नोलॉजी
+थाई
+मापने
+सोशल
+७५
+फॉण्ट
+चित्रकूट
+प्राइवेट
+मराठा
+तुम्हारा
+जमशेदपुर
+१९६१
+सावली
+भूमिकाओं
+चयापचय
+अभिन्न
+किन
+खंडों
+एलिजाबेथ
+ग्रहणाधिकार
+ताजा
+निक
+उदा
+प्रयोजनों
+पश्चात्‌
+लेखो
+गन
+नमस्ते
+जोनाथन
+गोविंद
+ऑटोमोबाइल
+गोलाकार
+गंभीरता
+फिनलैंड
+प्रबन्धन
+पूर्णविराम
+एलेक्स
+मनोहर
+सौदा
+स्टाइल
+२०१२
+पीट
+सामरिक
+रेड्डी
+दया
+प्रा
+वॉल्ट
+वादा
+दरों
+उपन्यासकार
+तरंगों
+स्पैनिश
+बरेली
+दोस्ती
+विकारों
+पंक्तियों
+दिखायी
+ड्रैगन
+चाँदी
+यश
+विकृति
+बेसिक
+कामयाब
+हल्की
+अंडा
+वास
+आर्मी
+कार्तिक
+श्रे
+ब्रह्मचारी
+अर्द्ध
+ग्रेड
+फिल्मांकन
+पूर्वानुमान
+साइटों
+मैत्री
+इज
+कलाओं
+मुद्रित
+मिलर
+सुंदरता
+युवाओं
+विंबलडन
+मीले
+पाणिनि
+सहारनपुर
+पिशाच
+केंडीबार
+मृ
+डिवीजन
+निकलकर
+निभाया
+मनी
+वक्ता
+सिग्नल
+कैलाश
+वाक्यांश
+तुर्क
+विशेषण
+निशाना
+अग्रसर
+रैंक
+१९५०
+खाद
+ङ
+सीटों
+कनेक्शन
+पेट्रोल
+तु
+ग्राफ
+रण
+कंट्रोल
+रत
+जुड़वां
+पूर्वक
+बर्बरता
+पेरू
+एहसास
+व्याख्यान
+गिल्ड
+न्यूज़ीलैंड
+कमान
+पुत्रों
+फ्रांसिस
+पुजारी
+भरतपुर
+कुवैत
+मापा
+खाई
+थकान
+रिक्त
+अनुमोदन
+लेडी
+बाएँ
+शोथ
+अभिप्राय
+युवक
+स्टेम
+नीलम
+पीरपैंती
+प्रतियां
+बहाव
+बहार
+उत्
+अरविन्द
+आराधना
+मंगोलिया
+ध्वन्यात्मक
+फ़ेडरर
+एयरपोर्ट
+बाबर
+टेरियर
+क्रमिक
+विषम
+१९९३
+चालित
+स्थाई
+शीतल
+सज़ा
+अनुपस्थिति
+बफ़ेलो
+होस्ट
+क्लान
+जाएंगे
+ऊर्ध्वाधर
+द्रौपदी
+सूप
+रुपया
+१९४८
+मीना
+शेक्सपियर
+बेकार
+टैगोर
+किताबें
+प्रविष्ट
+सौंपा
+चा
+हिंदुओं
+ऑब्जेक्ट
+अवशोषित
+सातवीं
+पिन
+अयस्क
+हाइकु
+संस्थाएं
+निकासी
+भीषण
+सल्फेट
+बीघा
+निपटने
+नाते
+बाला
+रिक
+समलैंगिक
+आपातकालीन
+उष्ण
+ईस्टवुड
+रचनाएं
+बरसात
+अमित
+यजुर्वेद
+प्रशा
+संपदा
+व्यंजनों
+रॉकेट
+चट्टान
+जार्ज
+यहूदियों
+विजयनगर
+अल्फा
+उत्तेजना
+प्रायोगिक
+अर्थों
+गेज
+दस्तावेज़
+मानकीकरण
+१९७७
+पैक
+टेरी
+उल्लिखित
+काच
+परास्त
+स्वीकार्य
+रचनाकार
+अलंकृत
+शपथ
+अंगूर
+अग्रिम
+वंचित
+कपास
+पाण्डवों
+दानापुर
+घोर
+कामना
+बह
+धोखा
+नं
+प्रतियोगी
+१९६७
+ज़्यादातर
+जला
+अनुशासन
+मसाला
+अंडरटेकर
+दूरस्थ
+सेठी
+उसमे
+दिलाने
+मुक्केबाजी
+संस्कृतनिष्ठ
+ग्रा
+कोकेन
+जेरिको
+ठंडे
+प्रोडक्शन
+गर्ल
+विराट
+गेंदबाजी
+पैन
+जज
+कराची
+महानगरीय
+स्टाफ
+मजदूरों
+एनीमेशन
+शाखाएँ
+वाइन
+१९५६
+एंव
+वीर्य
+सकते।
+तलाई
+परिपक्व
+डेल
+अवस्थाओं
+सर्प
+उन्मुख
+भूभाग
+युद्धों
+रूढ़िवादी
+नाथनगर
+नामके
+लॉस्ट
+कॉट
+नियामक
+वहन
+कलम
+सम्राट्
+परिपूर्ण
+इश्क
+ड्रीम
+कब्र
+मोम
+अल्बर्ट
+दूरबीन
+उदर
+कानूनों
+जवान
+इन्हे
+सौदे
+गान
+दामोदर
+बेलारूस
+श्रेण
+दिख
+दही
+विजयी
+घोल
+चालीस
+मध्ययुगीन
+पेंगुइन
+समायोजित
+मिनी
+पीसी
+फ़्रांसीसी
+सीईओ
+भजन
+आदत
+लिखकर
+१९६८
+परमेश्वर
+एरिया
+कमर
+रेशम
+मिसाइल
+जेन
+मोटर्स
+उग्र
+शैव
+डालता
+यूनिवर्सल
+पिनांग
+फ्लैश
+विजेताओं
+१९८८
+स्वरों
+बैंगनी
+स्विच
+फेफड़ों
+सच्चाई
+चरित
+निकटवर्ती
+इंद्र
+निवेशक
+सिकंदराबाद
+पूंछ
+समाहित
+चित्त
+फिट
+खुसरो
+सार्वभौमिक
+खाया
+स्थानिक
+चिट्ठा
+लग्गा
+समझे
+उपसर्ग
+भोग
+साइन
+क्रीम
+पाकर
+बोलियों
+सका।
+१९७३
+सिद्धि
+गुलज़ार
+आलोचनात्मक
+मिलाया
+शोभा
+ऐनी
+दायरे
+गईं।
+जाएगी।
+वाल्व
+वैली
+रामचंद्र
+संध्या
+क्रय
+सम्बद्ध
+जमाने
+सहस्रनामन
+ध्वस्त
+किरणों
+कै
+आएगा
+एस्टन
+सोचना
+अनुयायियों
+जवाहर
+मॅट
+निभाने
+का।
+क्रोएशिया
+कीर्ति
+कल्चर
+चालु
+ईथेन
+इरादा
+न्यास
+वृंदावन
+हिम
+गेट्स
+ज़ी
+वृद्धी
+परीचय
+डेबिट
+कार्निवल
+सकी
+नालंदा
+यो
+परेश
+कालांतर
+मुखिया
+डेड
+डब्लू
+सांख्य
+फ्रैंकफर्ट
+अजीब
+वृत्ति
+एफ़
+अबतक
+रूट
+हिस्सेदारी
+आवेश
+रू
+अंतरण
+वॉकर
+भवानी
+पत्ती
+धवन
+लाभकारी
+मैगज़ीन
+ओपेरा
+निकलते
+परिधि
+विलक्षण
+बताती
+शिक्षित
+१९५४
+विद
+लेफ्टिनेंट
+उल्लेखनीयता
+जोली
+रतन
+डालर
+उड़िया
+अनुपालन
+क्रिस्टोफर
+केदारनाथ
+डायोड
+तराई
+गुरारू
+प्रतिपादित
+धुरी
+प्रतिबिंबित
+अंग्रेज़
+स्टेज
+खलनायक
+सुप्रीम
+राष्ट्रवादी
+स्विस
+कैथरीन
+अपोल्लोन
+हिल्स
+प्रवर्तक
+रबर
+जोड़ों
+बॉम्बे
+विवादों
+वेस्टर्न
+मध्यवर्ती
+मालिश
+दीवाना
+गुरुवार
+दर्शाती
+गतिविधियां
+मुख्यधारा
+ऋषियों
+खिलाडी
+औसतन
+फ्रेडरिक
+पंचम
+सूखी
+चौड़ा
+विधियाँ
+१९८७
+बेंजामिन
+गली
+हफ्ते
+डीप
+नलिका
+पिंक
+आईपी
+साउंडट्रैक
+दिनकर
+एमटीवी
+अंकन
+क्रूज़
+कैफीन
+बल्लेबाजी
+देसाई
+ऑप्टिकल
+विद्वान्
+हेड
+लेंगे।
+शिवा
+बॉण्ड
+कुशलता
+क्वांटम
+अनिश्चित
+कन्नड
+विचित्र
+रग्बी
+रिव्यू
+प्रपत्र
+निष्पक्षता
+आर्कटिक
+समस्याएँ
+प्रयोगात्मक
+जुडना
+वाल
+ज़िम्बाब्वे
+तलाक
+व्योम
+बिक्रम
+अमीनो
+प्रतिस्पर्धी
+श्रीश
+विश्वव्यापी
+ग्राउंड
+पॉवर
+्ड
+बहुतायत
+मौसमी
+उतर
+तैनात
+चित्रकारी
+इंटरफ़ेस
+खगोलशास्त्र
+गुहा
+अपराधों
+पाउडर
+नॉन
+टिप्पणियां
+डू
+राजन
+मेघालय
+समृद्धि
+सीमेंट
+कथाकार
+गौराडीह
+कतिपय
+डगलस
+असमिया
+आदिम
+हज़ारों
+मीर
+हड़ताल
+ज्ञानसे
+पोर्टलैंड
+्रेणी
+संकाय
+दर्शाने
+अल्लाह
+बिल्ली
+श्रमिकों
+अल्पसंख्यक
+मेजबानी
+चाइना
+ह्रास
+फ़ाइलें
+गल्फ
+राख
+औषधियों
+१८५७
+आश्चर्यजनक
+हाउ
+खेतों
+विनंत्ती
+बढ़े
+ग्रीवा
+ऋषिकेश
+पुनपुन
+जटिलता
+राज्‍य
+लक्ष्यों
+डमी
+किताबों
+जोश
+लड़कों
+कॉमिक
+कैमरून
+पूर
+हमे
+१९८१
+स्पर्धा
+दिखाता
+कार्यकर्ताओं
+वरदान
+कराई
+अनुकूलित
+आचार
+गार्ड
+सुर
+मोर्चा
+१९७४
+प्रदत्त
+प्रेत
+डेवलपमेंट
+कार्यात्मक
+बालू
+पहचानने
+आश्रित
+रॉबिन
+आकस्मिक
+कस्बा
+मालिकों
+उपाध्यक्ष
+सिलिकॉन
+करेगा।
+दूत
+संग्रहण
+ड्रग
+गिरजाघर
+मोहब्बत
+घूम
+चैन
+आर्यों
+महासचिव
+फिलहाल
+मेजबान
+बसने
+१९८३
+पोत
+एप्पल
+रेणी
+मल्होत्रा
+चैप्लिन
+जीवाणुओं
+१९७६
+छाती
+ट्विटर
+सिकन्दर
+बोझ
+बैठकर
+ऐसें
+विस्फोटक
+अद्वैत
+जीवनकाल
+विचलन
+कैपिटल
+नाटककार
+उपवास
+बसें
+बांटा
+मदर
+डेस्कटॉप
+उन्मूलन
+देनी
+इच्छुक
+नेटस्केप
+बैरी
+ढाका
+ति
+तह
+एचटीएम
+खुफिया
+कामों
+आतंरिक
+सोनिया
+स्वम्
+ईमान
+सार्थक
+मेडिसिन
+काण्ड
+कॉमन्स
+अफ़ग़ानिस्तान
+शिशुओं
+शतरंज
+१२४
+गाजियाबाद
+सर्दी
+स्क्रिप्ट
+बैकअप
+छद्म
+केली
+मकर
+साधक
+मूर्तियां
+शिया
+सूरी
+छाल
+अब्राहम
+फूड
+ञ
+पालि
+मीमांसा
+मीरा
+मान्यताओं
+कैसा
+विनय
+जाय।
+लेम्बोर्गिनी
+इज़रायल
+जीनोम
+मैक्सिको
+एलिज़ाबेथ
+नॉट
+कंक्रीट
+बाधित
+यूनिक्स
+पाण्डव
+स्तनधारी
+सिवाय
+शारदा
+सत्याग्रह
+पूर्णत
+कठ
+बताई
+लीड
+उत्सर्जित
+सुधारों
+एंडरसन
+उत्कर्षराज
+कमला
+मैनेजर
+डीजल
+डेक
+शेखर
+साईट
+संयम
+बढ़ाकर
+तैत्तिरीय
+चमत्कार
+कवच
+तिल
+सप्रू
+४००
+सिंधु
+सब्जी
+पाइप
+मैथ्यू
+लेग
+वादी
+काय
+नेचर
+कागज़
+मंजिल
+बेल्ट
+प्रोफ़ाइल
+गाथा
+सीमांत
+कीमतों
+अंतर्निहित
+मुद्राओं
+जग
+ममता
+स्टीवन
+शास्त्रों
+फोरम
+लिए।
+विचारक
+प्रबंधकोंने
+हिंदुस्तान
+सिखों
+महत्ता
+गोदावरी
+खुदाबंदपुर
+दुबे
+सबका
+फिक्शन
+व्यवसायिक
+मरे
+चमड़े
+कालोनी
+सितारों
+दुरउपयोग
+आयुक्त
+नसीरुद्दीन
+दाँत
+सुलतानगंज
+राष्ट्रिय
+फतुहा
+संग्रामपुर
+सोर्स
+करेंगे।
+सहयोगियों
+क्लैप्टन
+बीजगणित
+प्रांतों
+आभासी
+दीवान
+मानो
+गौण
+लगाता
+डेनिस
+सुदृढ़
+एडम
+आभास
+सदस्योंके
+उठता
+ल्योन
+बंगला
+टुन
+लिट्टे
+नक्काशी
+बिंदुओं
+हेपेटाइटिस
+वामन
+जिलाधिकारी
+्व
+आठवीं
+फी
+जिन्ना
+क्वार्टर
+अनवर
+विंडोज़
+देखरेख
+ऑयल
+समजकर
+साहित्यकारों
+बालकाण्ड
+कौटिल्य
+जामनगर
+अंचल
+बिकने
+ज्ञानकोषकी
+अंगूठी
+खींच
+एफबीआई
+पेस्ट
+विडियो
+मिलना
+लाइनों
+भूटान
+ट्रेडमार्क
+तने
+बापकी
+अत्याचार
+मॉरिसन
+मलय
+उतने
+एंटीबॉडी
+मिठाई
+१९७९
+कोलेस्ट्रॉल
+ेणी
+संतुष्ट
+बेगम
+समझता
+पोलिश
+फ़ुटबॉल
+मीटाकर
+तारापुर
+धनबाद
+एयरलाइन
+लाकर
+अप्रत्यक्ष
+इंकार
+लौटे
+मानसून
+रॉबर्ट्स
+फोर्स
+चलाते
+प्रिंट
+ठ
+यूनेस्को
+धुन
+स्टॉप
+हर्ष
+ऊ
+सावित्री
+सलाम
+फेडरल
+जनित
+कु
+अन्तरिक्ष
+विक्टर
+इथियोपिया
+दुरुपयोग
+भारद्वाज
+नमः
+दांते
+शव
+सचमुच
+मुनिता
+चौथाई
+सालाना
+कब्जे
+ओड़िशा
+अंतत
+संगमरमर
+पारिस्थितिक
+आरम्भिक
+राघव
+मैसाचुसेट्स
+वीकीपीडीयांके
+पुनर्जागरण
+मिलक्त
+बमबारी
+अस्थिर
+प्रतीकों
+उच्चतर
+पतले
+अधिकांशतः
+चरित्रों
+सौन्दर्य
+पुरातन
+डिज्नी
+ड्यूक
+कार्यालयों
+कमज़ोर
+मेट
+शेफ़ील्ड
+आरएनए
+उत्प्रेरक
+सेक्शन
+संभोग
+बास
+वापिस
+राष्ट्रभाषा
+सस्ते
+मैदानी
+लग्न
+भोजपुर
+कुण्ड
+सघन
+फ़ॉर
+१९६४
+संस्मरण
+फॉर्म
+वैद्युत
+पाम
+परदे
+अचल
+ग़लती
+मंद
+बरियारपुर
+शुद्धता
+परवेज़
+बॉय
+जीभ
+रोलिंग
+बदलना
+स्टब
+भुवनेश्वर
+कोइ
+हस्तांतरण
+मुकदमे
+फैलने
+पैरिस
+प्रत्यारोपण
+अफ़्ग़ानिस्तान
+दयाल
+कवक
+मेमोरियल
+एयरबस
+इंटेल
+फिल्मफेयर
+बरोबर
+पहुँचे
+सावरकर
+कुरान
+माली
+दिखाते
+किनारों
+निचली
+कराती
+किस्मों
+रहेंगे
+रीढ़
+खजुराहो
+शियर्र
+घात
+स्वयंसेवक
+मेगावाट
+झरने
+बाढ
+ग्रीष्म
+हराकर
+ठंडी
+गेहूं
+ओबेरॉय
+फ्रेंकलिन
+केंद्रों
+शुक्राणु
+रूपये
+इकाइयां
+हटाकर
+प्रचारक
+रैंकिंग
+नीली
+क्लाउड
+निजामुद्दीन
+फर्क
+ग्लास
+उपजाऊ
+गैरी
+घुटने
+सत्यजित
+न्यून
+कमजोरी
+जोएल
+हरीश
+जन्मदिन
+क्योकि
+शिवराज
+ख़़ुदा
+सिक्कों
+पंचांग
+मिथिला
+१९३०
+पेशे
+राष्‍ट्रीय
+पहना
+कॅरियर
+प्रतिष्ठान
+मालदीव
+कलाम
+गेहूँ
+हुयी
+दुष्ट
+रांची
+टुकड़ा
+डाकू
+प्रक्रियाएं
+सहाय
+फ्रंट
+निकास
+लहसुन
+हेलन
+डाइऑक्साइड
+श्रद्धांजलि
+चिप
+रोमांटिक
+बॉडी
+शोक
+सितारा
+लेनी
+आयुर्विज्ञान
+फेम
+हरित
+हीमोग्लोबिन
+ब्रायंट
+गोला
+मानद
+कब्ज़ा
+व्यू
+प्रदर्शनों
+डेमोक्रेटिक
+फेंक
+आंत
+समुच्चय
+मातृभाषा
+महाराणा
+रिटर्न
+१९५७
+छपाई
+उपग्रहों
+गोले
+जीवंत
+रियो
+ैं
+दृढ़ता
+धीमा
+गज
+यादृच्छिक
+विपक्ष
+विमानन
+कथाएं
+चेष्टा
+गतिशीलता
+लालकुआँ
+१५०
+दिलचस्प
+बैक्टीरिया
+पवार
+ढांचा
+पंप
+नूतन
+आमन्त्रित
+पुस्तिका
+चौदह
+फोर
+सऊदी
+सरसों
+कैलिफ़ोर्निया
+नेल्सन
+रकम
+६५
+कहा।
+नायिका
+आभार
+अनजाने
+एस्टर
+एलेन
+प्रेरक
+जरुरी
+वाइल्ड
+विशेषाधिकार
+नरसिंह
+ब्रदर
+अधिकता
+बर्मी
+धाराओं
+सिंघल
+समीक्षकों
+राजदूत
+समारोहों
+ढेर
+सूखा
+अर्जेन्टीना
+प्लेटो
+१९६३
+१९६६
+स्थलाकृति
+इरादे
+कर्मों
+जानेवाली
+क्षीण
+मरुस्थल
+प्रांतीय
+स्काई
+ऍ
+विशिष्टता
+एमी
+अरबों
+इंसुलिन
+युवावस्था
+कैमरे
+नमूनों
+जावेद
+नक्शे
+सु
+१९६९
+संकुचन
+किय
+समीक्षाएं
+स्पिन
+हवाला
+कारावास
+शिक्षकों
+नाहीं
+सर्जन
+दाने
+उठाते
+वरन्
+६००
+उठाना
+भट्टाचार्य
+्ता
+डोनाल्ड
+संतृप्त
+हड्डियों
+मिलाने
+करनेवाला
+निकोबार
+दे।
+सॉसेज
+चेतन
+त्रिवेंद्रम
+ऐन
+करीबी
+मासको
+पहेली
+देशभर
+इमेज
+मोटाई
+सिगार
+ऑक्सीकरण
+मैनुअल
+सूअर
+चलना
+पड़े।
+पर।
+पराजय
+मंगेशकर
+नर्तकी
+यज्ञोपवीत
+देखिए
+द्योतक
+आतां
+मीठे
+भागने
+रूपी
+परिणत
+श्रृंगार
+शक्तिपीठ
+कुरु
+बीजिंग
+मुगलों
+घटा
+सच्चा
+वान
+पैकेट
+चौथान
+मॉर्गन
+सिवा
+इन्टरनेट
+वैधानिक
+मास्को
+भेड़
+रोहिणी
+मैरीलैंड
+भेजी
+मिर्ज़ा
+परिशिष्ट
+निर्माणाधीन
+असे
+रॉन
+डायरी
+द्
+संदूक
+नक्शा
+विराजमान
+विकल्पों
+प्रधानता
+लिपियों
+काउण्टी
+याचिका
+वरीयता
+विजू
+त्रुटियों
+निर्देशिका
+चूर्ण
+समूचे
+प्लस
+टाइपिंग
+लिखें
+दोहरे
+प्रथाओं
+निर्मल
+रस्सी
+बेखम
+ण्ड
+बजाया
+मुलायम
+हमीरपुर
+बंधक
+प्रतिरक्षी
+आपरेशन
+निसान
+नरम
+वॉल्यूम
+ख्याल
+क्रैमलिन
+इट्स
+थ्योरी
+शेयरधारकों
+सुमीत
+अंदरूनी
+लवी
+माधुरी
+खातों
+गाड़ियों
+सजावट
+निपटान
+खोलकर
+जन्मा
+पीएच
+अभिनेताओं
+चावला
+प्रेमिका
+स्विट्जरलैंड
+ब्राउजर
+मोदी
+शेरशाह
+नमी
+चालुक्य
+सूफी
+उचाई
+कोलम्बिया
+सू
+उठाकर
+ग़ज़ल
+क्षरण
+ग़लत
+खरीदारी
+दुल्हन
+शम्मी
+निष्ठा
+प्रविष्टि
+साम्यवादी
+रहेगी
+अनोखा
+स्तुति
+उपलब्धियों
+परियोजनाएं
+गद्यकार
+स्विफ्ट
+इंडीज
+लौकिक
+कोशों
+प्रिया
+शिष्यों
+निकली
+बाँटने
+टकराव
+मौजूदगी
+निरन्तर
+आकाशवाणी
+उल
+चीफ
+सुविधाजनक
+यादगार
+समाचारपत्र
+म्युज़िक
+सूचनाओं
+जमालपुर
+रोकता
+लक्षित
+दौलत
+स्पेंसर
+लालू
+पिच
+आसवन
+ज्वार
+पाषाण
+संयोजित
+अरे
+ईथरनेट
+मय
+आखिरकार
+एथेंस
+लड़का
+धूम
+निर्देशों
+आहे
+प्रयोगकर्ता
+झीलों
+ज्वाला
+नागालैंड
+आपत्ति
+कांस्य
+ख़राब
+करनेवाली
+विगत
+ार्ता
+फेडरेशन
+वैसी
+युनुस
+वस्त्रों
+श्रद्धालु
+अदृश्य
+सामर्थ्य
+६३
+हार्दिक
+मानदंड
+बौना
+सुनवाई
+शॉपिंग
+बराबरी
+सि
+पलायन
+लाइसेंसिंग
+अञ्चल
+जगदीप
+गोत्र
+देहांत
+कार्टर
+प्रतिबन्ध
+शैतान
+फांसी
+रीड
+बोतल
+गोविन्दा
+सामंजस्य
+फर्श
+फिल
+यूएसए
+गाते
+उपक्षेत्र
+एंग्लो
+तुमने
+बुगु
+निर्वाह
+बताए
+दूरदर्शी
+धोखाधड़ी
+संचालक
+तकरीबन
+आमिर
+स्टारबक्स
+जड़ें
+रूम
+टेल
+घोड़ों
+नरसंहार
+प्रीति
+अश्लील
+कलश
+कैलगरी
+८५
+घूमते
+प्रवक्ता
+वूल्वरिन
+अप्रत्याशित
+आंकड़ा
+ग्रीनहाउस
+फेस्टिवल
+अनूदित
+सर्वे
+चेन
+छवियों
+अधिकाधिक
+मिटा
+पिरामिड
+अग्र
+चाणक्य
+प्रक्षेपास्त्र
+१९७८
+विक
+टंडन
+मैनहटन
+कैच
+मौन
+टमाटर
+सांद्रता
+इस्तीफा
+करवाने
+समीक्षक
+फारस
+वज़न
+प्रवृत्तियों
+लुइस
+उत्तीर्ण
+राँची
+वनस्पतियों
+अल्फ़ा
+रीडर
+गेंदबाज
+नकद
+क्रिश्चियन
+राजेंद्र
+ऐल्कोहॉल
+कच्चा
+असोसिएशन
+लैंग्वेज
+मसाले
+ज़रूर
+मंडी
+सुमन
+सनी
+कर्मियों
+साइबेरिया
+कंपन
+आवर्त
+रुधिर
+गढ़ी
+चिकन
+स्नेह
+दत्ता
+धर्मग्रन्थ
+जौनपुर
+मुरादाबाद
+पर्वतमाला
+लौटा
+लाये
+गोपी
+दाएं
+पुनर्जीवित
+आगम
+प्रतिक्रियाओं
+हीरे
+तीर
+भ्रष्ट
+गर्भाधान
+परेड
+टेलीग्राफ
+ऐक्शन
+वीरता
+आर्क
+इफ़्तेख़ार
+टार्ज़न
+प्रतिलिपि
+डेढ़
+सम्पत्ति
+गर्व
+मदुगु
+माघ
+मूर्तियाँ
+छन्द
+कठिनाइयों
+अभियानों
+तया
+चांद
+कौषीतकि
+वास्तुकार
+पडता
+मज़बूत
+कार्यान्वित
+क्लाइंट
+पूरब
+साइमन
+क्षतिपूर्ति
+माध्यमों
+स्केल
+उत्तरदायित्व
+पतला
+पीटर्सबर्ग
+नौका
+पटल
+समझाने
+मिसौरी
+आण्विक
+एस्पिरिन
+म०ब०
+जोन
+कुक
+बाईं
+ध्येय
+ब्लेड
+कृत्य
+गार्सिया
+तीर्थंकर
+सम्मुख
+चाहीये
+मार्केटिंग
+रोमांचक
+सहानुभूति
+वायरलेस
+घृणा
+महाद्वीपीय
+उर्मिला
+बसंत
+दवाएं
+पकाने
+नन्दा
+अलवर
+निराशा
+छिपा
+तपेदिक
+आदिवासियों
+अनुवादित
+सातवें
+सिक्का
+संवत्
+सावन
+कार्पोरेशन
+उर्वरक
+राही
+ओलिवर
+पांचवें
+झीलें
+डेविल
+खां
+अन्तरराष्ट्रीय
+ब्राह्मी
+कांड
+जू
+गाँवों
+भैरव
+वीकली
+टुडे
+बेसिन
+बाघों
+निरूपित
+शाप
+मन्त्री
+कुंडली
+अथ
+राष्ट्रगान
+आणविक
+दांतों
+वैश्वीकरण
+कहें
+शैवाल
+सिलसिला
+कैरी
+१९५५
+काबुल
+मोटरसाइकिल
+विवश
+फ़ूड
+अरोड़ा
+गिरोह
+पते
+झरना
+अनुमोदित
+मांडूक्य
+कडियां
+मजाक
+जरी
+विकीपीडिया
+होत
+जमैका
+स्पष्टीकरण
+पाद
+जरूरतों
+एम्पायर
+हस्त
+संहिताओं
+लड्डू
+मध्यकाल
+वीकी
+देवगन
+चित्रआकार
+विदिशा
+कॉफ़ी
+सेंचुरी
+होते।
+मित्रता
+कठोरता
+वज़ीर
+रूपक
+अश्वेत
+राज्यसभा
+आभूषण
+चैम्पियन
+उपरान्त
+लार्ड
+नोबल
+प्रविष्टियां
+बस्तियों
+िए
+नानक
+बर्ड
+पड़ेगा
+लिंकन
+बहाल
+९६
+बंदूक
+रेट
+अयोध्याकाण्ड
+महाप्रभु
+ग्राहम
+नल
+डार्विन
+ग्रेटर
+कारखानों
+वाट
+सोचने
+हिम्मत
+बढाने
+लेबर
+गिना
+पूर्वजों
+बेचे
+हरिवंश
+श्वेताश्वतर
+माइक्रो
+सीनेट
+पु
+दिए।
+नकदी
+ब्रॉडबैंड
+फ्रेमवर्क
+दाग
+ँ
+ग्लूकोज
+आश्वासन
+दरगाह
+बीवी
+किस्में
+अभिकल्पना
+इन्दिरा
+रामकृष्ण
+शेन
+वार्
+पॉइंट
+झांसी
+चेल्सी
+वाइस
+महानतम
+विश्वसनीयता
+चूना
+डिस्प्ले
+प्रकोप
+सदाबहार
+लोहिया
+मीनाक्षी
+र्ता
+हावर्ड
+इस्लामिक
+कौशिक
+भुजा
+पहलवान
+जादुई
+अर्थशास्त्री
+मनमौजी
+शायर
+डिजाइनर
+समयावधि
+सपनों
+मर्यादा
+रेकी
+दरवाजा
+उत्त
+बारूद
+हे।
+कुर्सी
+जन्मजात
+लूट
+नियोजित
+नियोजन
+तेरह
+हिंगू
+मैडोना
+्म
+सोमनाथ
+पीपुल्स
+मुद्रास्फीति
+बजाने
+काँच
+तैराकी
+साबुन
+अभ्यारण्य
+बढ़ाते
+तन
+उ०प०
+महासभा
+अहंकार
+मांसपेशी
+निर्वात
+खतरों
+जाओ
+हैपलोग्रुप
+हैवीवेट
+आरोपों
+सितारे
+विनियमित
+सब्जियों
+शीतकालीन
+पार्टियों
+शिला
+रसवात्सल्य
+पश्च
+चॅक
+लड़ाकू
+तुझे
+रॉस
+क्लोरीन
+विषाक्तता
+मानों
+वाक्यों
+प्रतियों
+उल्टी
+हैरिस
+निकालना
+अक्षम
+सिंधी
+विशेषत
+आस्ट्रिया
+अवगत
+साधारणत
+मार्क्स
+चीता
+व्यवसायों
+डालना
+क्षितिज
+पालिका
+उल्टा
+कारखाना
+सैयद
+कमेटी
+भला
+फेयर
+फ्लू
+रामभद्राचार्य
+स्प्रिंगस्टीन
+पिस्टन
+संदर्भों
+जनसँख्या
+आनुवांशिक
+उषा
+ज़रिए
+सीमाएं
+घर्षण
+प्रौद्योगिकियों
+दिखती
+मतों
+लत
+बैले
+एक्यूपंक्चर
+फोटोग्राफर
+क्रिकेटर
+अनीता
+इण्डिक
+आधिपत्य
+सतही
+गुफाओं
+प्रतीकात्मक
+नशीली
+शुक्ला
+शेंगेन
+फास्ट
+बुल्गारिया
+महंगे
+सनम
+नज़रिया
+हेलो
+माथुर
+सेवाएँ
+रिपब्लिक
+सेंसर
+सर्कल
+बिज़नेस
+सेकेंड
+असत्यापित
+कैनेडी
+दुर्भाग्य
+विनायक
+कारगर
+प्रस्तावना
+अरस्तू
+बताये
+गृहयुद्ध
+तर
+शीट
+गिरफ्तारी
+वार्मिंग
+इसीलिये
+महासागरीय
+खनिजों
+पेरी
+जटिलताओं
+जीती
+लॉरेंस
+पूर्
+साठ
+सूडान
+एबीसी
+संस्थाएँ
+सिएटल
+आख्यान
+बोल्ट
+खानों
+यीशु
+परिलक्षित
+अभिमन्यु
+दैत्य
+पॉलिन
+निकाली
+राष्ट्रवाद
+खोजा
+साक्षी
+पारदर्शी
+७२
+जाएँगे।
+फुलवारीशरीफ़
+वैवाहिक
+जुलती
+सेंटीमीटर
+ईश
+नाभि
+रेशे
+संकीर्ण
+नेताजी
+टीके
+एड्रेस
+विश्‍व
+चार्टर
+बीना
+मधुबनी
+पियानो
+हेक्टेयर
+मंगलौर
+फलत
+सीने
+संभाल
+अलास्का
+स्पाइवेयर
+सुलोचना
+नीलगिरी
+तैसें
+उभरा
+राजकोट
+मिलीग्राम
+फाइलें
+हिब्रू
+बैग
+आटा
+होतीं
+शंख
+मजबूती
+सीना
+उनमे
+आज़मी
+अभिलेखों
+रोचेस्टर
+पुष्ट
+दाहिनी
+क़रीब
+कार्लोस
+जादूगर
+मैनें
+अवरुद्ध
+झ
+सस्ता
+लैंस
+टैक्स
+बैड
+इशारा
+पढ़ना
+विलायक
+ज्यामितीय
+एनी
+पत्तियाँ
+बहामास
+पढ़े
+कारें
+प्ले
+चश्मे
+प्रतिकृति
+झंडा
+उभरते
+स्टेनली
+डेव
+बेनोइट
+वीवरण
+निकालकर
+तदनुसार
+बुल
+अवशेषों
+कच्छ
+बताना
+एंटरटेनमेंट
+राज्यमंत्री
+मायने
+परख
+बराक
+मिले।
+ढाई
+प्रतिफल
+क्रियाएँ
+स्थूल
+बसु
+आकलनकर्ता
+गुट
+अथर्ववेद
+संस
+केट
+टीमें
+सैंडविच
+लेखिका
+कैबिनेट
+जुर्माना
+मारी
+मिटाने
+परवरदिगार
+अंदाज़
+मूल्यवान
+लिखता
+संचय
+साउंड
+युवराज
+विकिक्वेट
+स्कूली
+नशे
+प्रयोक्ताओं
+पापों
+पित्त
+बहल
+विकलांग
+डूब
+किंगफिशर
+कार्यक्षमता
+टेड
+वगैरह
+डाउनटाउन
+अपूर्व
+कलन
+थाली
+साढ़े
+पीली
+कृष्णन
+९९
+प्रोसेसर
+एमआईटी
+तंतु
+राजेन्द्रनाथ
+छीन
+स्टैंड
+मुरलीधरन
+कंप्यूटिंग
+सॉफ़्टवेयर
+चुप
+एसी
+प्रोटोटाइप
+चुनने
+राजी
+अंडर
+सुविधाएँ
+शरत
+हरेक
+मु
+विमानसेवा
+पड़ी।
+मूर्तिकला
+जुडी
+संविदा
+बाय
+बढ़ाता
+रुख
+लोकगीत
+समायोजन
+अमेरिकियों
+कैन
+जीप
+नक़ल
+तेथ
+श्रृंखलाओं
+ज़माने
+मशीनी
+एक्सरे
+आह्वान
+अलाउद्दीन
+प्रत्याशी
+बिन्दू
+रहस्यमय
+रेखाएँ
+पिया
+पत्रकारों
+प्रतिभूति
+उमर
+स्वच्छता
+घनश्याम
+विषाक्त
+दबाने
+अध
+जोड़ते
+वायुमंडलीय
+ठंड
+बर्फ़
+फीसदी
+लेआउट
+दरिया
+क्लबों
+छत्रपति
+असुरक्षित
+नागरकोविल
+कार्यो
+सौभाग्य
+परवाह
+महंगा
+युगांडा
+नवाचार
+रामचन्द्र
+जुलता
+निष्कासन
+गर्भगृह
+वेदांत
+निराश
+शोधकर्ता
+पड़ोस
+मौके
+असफलता
+गय
+जयसिंह
+हैदर
+संगीतकारों
+दीपावली
+मूसा
+समाजों
+मानवाधिकार
+जोड़ना
+ट्रम्प
+एंजाइम
+गांधीजी
+चुनी
+१९३१
+डिवाइस
+समझाया
+हजरत
+प्रमोद
+कुशीनगर
+बर्मन
+गोलार्ध
+मोह
+पढ़ते
+गवाह
+मर्सिडीज
+आमन्त्रण
+कतर
+एकाधिकार
+टायसन
+ऑपरेटर
+बलराम
+होंगी
+आये।
+नानी
+अलीगंज
+जहा
+विद्युतीय
+जड़ों
+अपराधियों
+द्वि
+जौ
+बंदर
+बढ़िया
+रेसलमेनिया
+इलेक्ट्रान
+फिलीपींस
+प्राप्‍त
+क्यूंकि
+विकलांगता
+जिल्हा
+सींग
+बछवारा
+हावी
+गाए
+एकेडमी
+वाइरस
+सवालों
+फोटोग्राफी
+हाइड्रोकार्बनों
+कोबेन
+स्वर्गीय
+यार
+कोशिकीय
+बखरी
+उतरने
+गैलापागोस
+विलास
+हंगल
+आज़ादी
+अंशों
+सिलेंडर
+केन्या
+अप्रयुक्त
+धर्मनिरपेक्ष
+प्रबंधको
+ताजिकिस्तान
+पुनर्गठन
+स्टडी
+समा
+ीर्षक
+दोषों
+आईएसओ
+कोला
+रेलमार्ग
+जहाज़
+बहाने
+थोक
+जानबूझकर
+बेकेट
+कमाने
+खाल
+छावनी
+डबल्स
+पहनते
+आल
+मनोरंजक
+फ्रैंकलिन
+भ्रमित
+सुज़ुकी
+वॉर्स
+वर्जित
+अनशन
+वुड
+अपवाह
+श्राफ
+एवेन्यू
+नाप
+पर्पल
+हुक्म
+भूगोलवेत्ता
+दबा
+उभर
+शंघाई
+पैकेजिंग
+नॉटिंघम
+वर्
+भूमिकाएं
+जनमत
+सीखा
+हलसी
+ग्रैमी
+सकेगा
+वार्त
+१९४०
+डैन
+कलंकीत
+कारन
+नहरें
+पडा
+२५०
+दर्रा
+ओड़िया
+कांफ्रेंस
+तिमाही
+फिल्टर
+ग्राफिक्स
+लाइक
+रोज़ेज़
+केक
+आंदोलनों
+ऑ
+७६
+गाँठ
+सेन्ट्रल
+करों
+पोजीशन
+ट्रांस
+अस्पतालों
+प्रचारित
+सपोर्ट
+समितियों
+एस्टेट
+संकुचित
+दिखते
+जलन
+उत्तराधिकार
+प्राध्यापक
+सूक्ष्मजैविकी
+मिर्जापुर
+रैखिक
+नैनोट्यूब
+वीजा
+गुजरती
+मालाबार
+निगमों
+पोरबंदर
+ट्वेंटी
+नवरातिलोवा
+्त
+७७
+जासूस
+अभूतपूर्व
+नवागन्तुकों
+वर्मनने
+मिसाल
+गरीबों
+फूट
+फ्रेंड्स
+फोकस
+शत
+तैसा
+गे
+एनिमेशन
+मेवाड़
+स्ट्रीम
+१९५८
+प्रमुखता
+पेशियों
+ऋ
+जलाशय
+चलाता
+क्ष
+हेमामालिनी
+बैंगलोर
+सुनते
+लैंगिक
+सुदर्शन
+रमन
+नाइट्राइट
+टिहरी
+कैदी
+कस्टम
+खरा
+चिप्स
+अनगिनत
+महाकवि
+आवश्यकताएं
+कमिश्नर
+रचा
+श्रेणीबद्ध
+रवाना
+बूटी
+वाँ
+खिलौना
+गर्ल्स
+कमांड
+चलाना
+संसद्
+तस्वीरों
+प्रतियोगिताएं
+शाखाएं
+निरूपा
+पावन
+रसायनों
+औषध
+वीणा
+साजिश
+बुजुर्ग
+एनालॉग
+मकबरे
+परीक्षित
+धोनी
+नबम्बर
+प्रबंधित
+सैल्मन
+आकारों
+सवाई
+माईस्पेस
+किण्वन
+आईबीएम
+प्लांट
+गुजर
+शर्ट
+ल०व०
+विकिसम्मेलन
+पंद्रहवीं
+मातृ
+ीय
+भिक्षु
+फ़ोटो
+अपडेट
+दोहरा
+क्रेन
+बाइबल
+पहुँचाने
+दाएँ
+निःशुल्क
+नाइट्रेट
+एरनाकुलम
+पहुंची
+सक्रियता
+लियोन
+मंडली
+लोकपाल
+निकायों
+आधुनिकता
+वसूली
+नारा
+राना
+गॉर्डन
+दांव
+चन्द्रशेखर
+हार्बर
+सलाद
+मंत्रिमंडल
+रसेल
+तब्दील
+आशिक
+विधायक
+बची
+१९४९
+जैकी
+पनीर
+वेशभूषा
+वेल्श
+पसन्द
+चुपके
+चि
+अतरी
+परतों
+मधुबाला
+सांप
+पहुंचता
+रोकना
+पकड़े
+१९२०
+पीतल
+नास्तिक
+नासिर
+किस्मत
+लाइनें
+प्रतिबिंब
+माफी
+मार्क्सवादी
+एथिलीन
+कोशीश
+जगद्गुरु
+जीना
+वाह
+प्रेसीडेंसी
+सीनियर
+पूर्णता
+फिजी
+अत्र
+होनेवाली
+बिड़ला
+रिवाज
+उपनगर
+ईथर
+बद्रीनाथ
+शीर
+ु
+रेखाचित्र
+महेन्द्र
+त्तराखण्ड
+सूत
+सीढ़ी
+भट्ठी
+भण्डार
+व्यवसायी
+सेवानिवृत्त
+गुणांक
+जामा
+शेखावत
+८००
+क्रूर
+घिरे
+फलक
+अम्बेडकर
+लगन
+बिन्दुओं
+मुकुट
+वेस्टमिंस्टर
+इमाम
+बर्नार्ड
+मृदा
+बायें
+शासकीय
+ख़िताब
+षड्यंत्र
+रेखीय
+स्पीयर्स
+जीमेल
+डिस्ट्रिक्ट
+अल्बानिया
+राशियों
+लीन
+गवाही
+जस्टिस
+स्पेलिंग
+बाँटा
+कुश
+मकसद
+अटल
+मेटा
+सर्पिल
+रास
+पंखों
+संवेदना
+हलचल
+संकल्पना
+३०००
+मक्खन
+जॉर्डन
+मिथ्या
+समीकरणों
+फेफड़े
+पैतृक
+प्लैटिनम
+एंथोनी
+वीनस
+बदली
+७००
+पीढ़ियों
+सूरीनाम
+स्ट्रॉस
+क्रियाशील
+विक्रेताओं
+मोल
+लड़ते
+रहो
+वक्तव्य
+उत्पादकता
+मॉनिटर
+पुरोहित
+मालवीय
+समझी
+रूपांतर
+पनामा
+प्रतिरोधक
+समस्तीपुर
+वेधशाला
+पीड़ितों
+देवदास
+अवधारणाओं
+फर्ग्यूसन
+ग्लेन
+चौड़े
+फाँसी
+आंत्र
+त्रि
+फेरारी
+पदार्थो
+शंकु
+दादी
+पुनरावर्तन
+विवरणों
+हलके
+दरार
+मीन
+गिरीश
+चुनें
+निभाता
+१९४५
+स्पीड
+यथार्थवादी
+तोप
+किट
+चिन
+पुकार
+मॉडर्न
+कड़े
+कावेरी
+आई।
+तूफ़ान
+द्योल
+पिकनिक
+बायर
+गिटारवादक
+एकांकी
+लगाव
+सस्ती
+खुदा
+बढ़ाना
+संयंत्रों
+निष्पक्ष
+अरविंद
+पकड़ा
+गिने
+शहद
+मिथक
+मून
+दीया।
+डेविडसन
+ग्राफिक
+प्रियस
+अनिष्पक्ष
+कराटे
+सुनहरा
+सचिवालय
+फ़ॉर्मैटिंग
+वाल्टर
+स्तंभों
+आटे
+स्मार्ट
+मेक
+घाटियों
+मेसन
+अनोखी
+सदाशिव
+प्रतिजन
+रुझान
+प्रवीण
+कपिल
+विधवा
+रुकावट
+टर्नर
+त्रिभुज
+मंत्रियों
+तत्पश्चात
+चूहे
+म्हणे
+कॉलेजों
+उत्कीर्ण
+र्षक
+घेर
+नेपोलियन
+सुलझाने
+विभिन्‍न
+आइस
+भित्ति
+गला
+वैधता
+लुकास
+उड़
+स्टैंडर्ड
+खिलौने
+युगों
+लिवरपूल
+लिप्यन्तरण
+खड़ीबोली
+पर्दे
+शत्रुघन
+अग्निहोत्री
+वर्चस्व
+बहिष्कार
+एडवेंचर
+यूटोपिया
+ऐसीटिलीन
+विचरण
+कल्पित
+मुख्‍य
+अपनाई
+गंधक
+ेश
+किशोरावस्था
+लेज़र
+कैम्प
+टाई
+तुरन्त
+अर्धचालक
+मॉरीशस
+साँस
+संगठनात्मक
+बहुवचन
+तले
+कभार
+पुकारा
+चाँदनी
+१९५९
+जिनपर
+नागराज
+मोनिका
+्तराखण्ड
+६४
+सुखद
+आवारा
+पानदारक
+एशियन
+चैत्र
+कैश
+हथेली
+नैनो
+झूठा
+विस्थापन
+प्रमाणीकरण
+इसराइल
+आठवें
+सागरीय
+प्रजापति
+किसने
+सभ्यताओं
+अर्ल
+स्वराज
+१९३६
+चन्द
+बसाया
+महानदी
+वर्ड
+रिसाव
+चम्मच
+प्रशिक्षक
+रघुनाथ
+एमिनेम
+सुधा
+पंद्रह
+काटा
+चादर
+जैम
+निकटता
+उमा
+भयभीत
+फ़ॉर्मूला
+शाहजहाँ
+इंजीनियरों
+वर्दी
+ूर्व
+आनुवंशिकी
+घेरा
+हाथियों
+रैली
+संलयन
+आवर्ती
+क्रियान्वित
+दशहरा
+वृद्ध
+विरोधियों
+बोवी
+भूविज्ञान
+पो
+होय
+ऋणात्मक
+लाते
+अण्डा
+सम्बंध
+बोट
+इटावा
+साहसिक
+आपातकाल
+टायर
+साइप्रस
+चूहों
+विधियां
+षक
+जोड़ती
+त्रिज्या
+मनाते
+बांड
+प्रतिबद्धता
+आइसलैंड
+उत्तेजक
+पैमाना
+बांद्रा
+गर्भपात
+पब्लिशिंग
+अन्यत्र
+बम्बई
+महीन
+पूंजीवाद
+क्रियान्वयन
+संगीतमय
+दैट
+दाखिला
+आवश्यकतानुसार
+मेनन
+स्प्रिंग
+ख़िलाफ़
+शक्तियां
+अंतरजाल
+यूक्रेन
+अस
+वर्जिन
+मानती
+सद्भावना
+आंद्रे
+वल्लभ
+इजरायल
+अध्यायों
+मजदूरी
+उत्तरोत्तर
+प्रभात
+श्रोताओं
+हलन्त
+हीरोज़
+कुँवर
+अलेक्जेंडर
+कराया।
+वोल्टता
+एवार्ड
+गोल्डेन
+पनडुब्बी
+स्टेरॉयड
+सचदेव
+ट्रू
+सिरों
+मारकर
+माउंटबेटन
+बार्नस्टार
+कोका
+मन्दिरों
+फ़िल्मी
+धाराएं
+सांप्रदायिक
+आत्मसमर्पण
+समांतर
+प्रीमियम
+विनोबा
+बहुराष्ट्रीय
+डैविल
+धागे
+दसवीं
+बार्कलेज
+बिरला
+प्रतिमान
+कक्षाओं
+हैना
+अमूर्त
+मंज़िल
+निरंतरता
+निपुण
+ढोल
+१९४२
+मनोरोग
+डेप
+यूनीवर्स
+डाला।
+क्षार
+शूट
+बेसबॉल
+बीएमडब्लू
+शौकिया
+प्रागैतिहासिक
+ारत
+मुझ
+गुफाएं
+वर्क
+अनन्य
+सुरुचि
+छा
+बग
+कर्क
+उठे
+हक
+प्रशस्ति
+कलाई
+जयप्रकाश
+महीना
+चिंतित
+दूषित
+नियोक्ता
+स्वदेश
+यत्र
+पूछताछ
+विस्थापित
+खोजों
+लाभान्वित
+कांट
+पहचाने
+बॉर्न
+प्रवृति
+रेजिमेंट
+थिंक
+ऐश
+स्थगित
+सीटी
+विशेषतः
+बुराई
+रुद्रप्रयाग
+सुषमा
+८४
+बनी।
+जनजातियों
+रेख
+अन्याय
+संवाददाता
+कच्ची
+बोलियाँ
+एडी
+पेंटिंग
+जिन्हे
+रति
+स्टार्च
+अबू
+पहुंचते
+अम्लीय
+सैर
+बीबी
+इंटरटेनमेंट
+वानस्पतिक
+बेशक
+श्लोकों
+आपात
+नन्द
+मेज
+तृतीयक
+टॉड
+प्रसिद्द
+रांगेय
+कैप्टन
+बीन
+चाह
+बनीं
+पोटेंशिअल
+असित
+सीरम
+कैदियों
+चुनरी
+ज्येष्ठ
+अगासी
+जस्ता
+थेरेपी
+मैथुन
+लोकल
+सूर
+यात्राओं
+गेंदों
+चढ़
+गाजीपुर
+भागीदार
+राहु
+सजाया
+उत्पीड़न
+ओमान
+बायीं
+तुर्कमेनिस्तान
+फेस
+धड़
+वन्यजीव
+चीज़ों
+अनमोल
+निभाते
+जैसें
+मुंशी
+सुपरमैन
+बहारी
+विकिस्रोत
+दुग्ध
+लगीं
+गुड्डी
+माउस
+आग़ा
+गोरखा
+कसौटी
+अल्फ्रेड
+पूज्य
+वोक्सवैगन
+ख़
+तना
+ट्रैफिक
+खंडित
+मो
+्षक
+नायडू
+शबाना
+आतंकवादियों
+जाली
+लिविंग
+पुनरावृत्ति
+एक्सप्लोरर
+फ़ोर्स
+श्रोता
+राजनयिक
+तुल्य
+डेज़
+फ्रेड
+परोसा
+ची
+फोर्ब्स
+कण्ठ
+बर
+कीन
+प्रतिभागियों
+सुरेन्द्र
+फाइलों
+निद्रा
+बंगलोर
+संभावनाओं
+बॉस्टन
+हार्ले
+प्रोसेसिंग
+नासिक
+वाइड
+एनर्जी
+पकवान
+दारा
+कम्पनियों
+थोडा
+नवादा
+सप्त
+शाहरुख़
+तांबे
+नग्न
+अंजाम
+तुग़लक़
+बचाया
+बैनर्जी
+बादलों
+संप्रेषण
+लैरी
+९८
+डायमंड
+शुभारंभ
+अपार
+देगा।
+खिड़की
+जश्न
+मैनपुरी
+विधाओं
+६६
+भ्रामक
+तंत्रों
+सीरिज़
+लहरों
+पुस्तकालयों
+विनाशकारी
+जैज़
+खतना
+बस्तियां
+उत्कर्ष
+कोशिकाएँ
+नेहरु
+मेड
+लिखा।
+धनात्मक
+चॉकलेट
+मनोरमा
+१९५२
+बार्सिलोना
+लावा
+फैजाबाद
+वाटर्स
+प्रात
+बढ
+विद्युत्‌
+मसलन
+मसूरी
+अचार
+सटीकता
+कीर्तिमान
+ब्रिगेड
+प्रकाशीय
+कं
+उत्साहित
+नौकर
+वारिस
+नामदेव
+हेमंत
+ईंटों
+इंटेलिजेंस
+सपाट
+गोबर
+पर्सनल
+कार्यप्रणाली
+असीम
+कॉलम
+झाँसी
+प्रबन्ध
+करिश्मा
+मिसिसिपी
+ब्रेकिंग
+निभा
+खाती
+दावों
+वोल्ट
+आप्रवासी
+धड़कन
+बिताया
+प्रशस्त
+बीटल
+महलों
+निलंबित
+एबरडीन
+लूथर
+बारबरा
+खण्डों
+यूज़र
+बर्बाद
+उन्नयन
+वेल्लोर
+राजबब्बर
+समन्वित
+लोप
+हल्दी
+बुद्धिमान
+किराए
+८८
+अनुसन्धान
+जेड
+बादाम
+पासपोर्ट
+खुलता
+माकपा
+प्रमाणन
+वृन्दावन
+सड़कें
+बम्बोर
+पोषित
+सिन्दूर
+अमोनिया
+श्रुति
+उठाए
+तकनीकें
+पदवी
+ऑर
+गड़बड़ी
+आमाशय
+नरक
+मुहैया
+गुजरने
+संग्रहीत
+जेसन
+सीक्रेट
+असिमोव
+कन्याकुमारी
+र्व
+झारखण्ड
+उत्तराख
+परिपक्वता
+८१
+कौरव
+ज्ञानकोश
+रंगोली
+गान्धी
+ध्वनियों
+कनाडाई
+छिपे
+म्हणोनि
+प्रणालियाँ
+विखंडन
+गुम्बद
+किक
+बख़्तियारपुर
+वश
+नैस्टर
+शा
+बर्गर
+फ़ल
+हुवा
+बिक
+अटलांटा
+रोधी
+बचना
+घा
+लुटेरे
+मेगाडेथ
+बीजों
+वियना
+चिन्तन
+अय्यर
+सोम
+चिन्हित
+रेफरी
+सहिष्णुता
+छोड़ना
+मसले
+उद्यमी
+जुलते
+स्लोवाकिया
+साख
+गोकुल
+दरबारी
+बढ़ाई
+देखा।
+खूबसूरती
+पैसेंजर
+फ्लाइट
+हवाओं
+पीढी
+नौगांव
+आगंतुक
+लिली
+उत्तरकाशी
+गुरुत्व
+सिखाया
+पियरे
+शीर्
+सिक्स
+डब्ल्यूडब्ल्यूएफ
+प्री
+दशमलव
+तेतिहा
+क़ानूनी
+धृतराष्ट्र
+हाजीपुर
+आर्यभट्ट
+प्रायोजक
+सन्दूक
+सांसारिक
+फलित
+नामका
+भट्टी
+पांव
+त्
+सम्पादित
+शोधन
+विश्‍वविद्यालय
+कंस
+पम्प
+चलाई
+करतीं
+ईपू
+मिज़ोरम
+हीन्दीवीकीपीडीयाके
+दायें
+अयोग्य
+मृग
+आनेवाले
+लीबिया
+लेसनर
+तुमको
+मेहमान
+मेलबोर्न
+स्‍थापना
+थर्ड
+इमेजिंग
+सम्मेलनों
+अमज़द
+लगेगा
+बेड़े
+इब्राहिम
+पक्का
+पलट
+मानदंडों
+त्रिनिदाद
+साम्राज्यवाद
+परीक्षक
+पड़ाव
+पहाडी
+जुड़ना
+विलोपन
+सिलसिले
+खींचने
+चलाए
+जानकर
+बेली
+विचारकों
+पितामह
+नॉर्मन
+डिपार्टमेंट
+स्वादिष्ट
+सुगंध
+पेस
+समता
+गोंडा
+लेस
+फैलाने
+सैनी
+पिज़्ज़ा
+रामधारी
+तांत्रिक
+साध्य
+जन्मभूमि
+संभालने
+आकृतियों
+अख्तर
+हेल
+तवी
+पांडवों
+मीलकर
+उत्खनन
+स्वैच्छिक
+दिल्‍ली
+श्रीलंकाई
+दोहराया
+मुखर
+टोयोटा
+रिपोर्टिंग
+निषिद्ध
+गंगोत्री
+डिक
+परमार
+बार्न
+फ़ैल
+इण्डोनेशिया
+अकादमिक
+ड्राफ्ट
+भूकम्प
+दिखलाई
+धर्मशास्त्र
+किये।
+क्राई
+बकरी
+पाया।
+न्यूर्क
+जौहर
+कामयाबी
+फौज
+सुव्यवस्थित
+डॉक्टरों
+बढ़त
+क्योटो
+दर्जन
+जुटाने
+कलर
+हिन
+ग्
+प्रेरण
+एथलेटिक्स
+कपाल
+जस्टिन
+पश्तो
+कुंभ
+थाइलैंड
+बांस
+ँव
+कनेक्टिकट
+जोरदार
+बेरोजगारी
+सुल्तानपुर
+बिस्तर
+खींचा
+प्रौढ़
+एल्बमों
+कड़ा
+मानकीकृत
+सामंत
+वृहत
+परबत्ता
+दुल्हिनबाजार
+सोल
+चना
+भोसले
+सप्ताहांत
+विशालकाय
+धोने
+भस्म
+रहनेवाले
+टेघरा
+अमीन
+फ़्रान्सीसी
+शल्यक्रिया
+ग्रांट
+१९२१
+सांकेतिक
+फार
+मदिरा
+पोर्शे
+परिधान
+यूरेनियम
+जिन्होने
+बलात्कार
+परीक्षाओं
+उत्तराखण
+ट्रेक
+जन्में
+पि
+पवित्रता
+इंतजार
+लाता
+वादन
+महत्‍वपूर्ण
+ब्
+अल्जीरिया
+सीखना
+नगण्य
+खत्री
+चतुर्भुज
+बाक़ी
+१९००
+टेन
+करोड़ों
+स्क्रीनिंग
+टूटने
+प्रजातियाँ
+आन्तरिक
+कहो
+अपघटन
+देशो
+ब्रेट
+पहुँचे।
+परिस्थितियां
+म्
+पुनर्निर्देशित
+नतीजा
+साइबर
+पैदावार
+स्याही
+नंदा
+सैटेलाइट
+न्यूट्रॉन
+रोनाल्ड
+देवेन
+चमकदार
+जिगर
+योजनाएं
+प्लेग
+अध्यात्म
+विदेशियों
+सच्ची
+चट्टोपाध्याय
+दार्शनिकों
+परिसंपत्ति
+ओक
+जाये।
+इलाक़े
+तुमसे
+बिखरे
+व्यवहारिक
+तराखण्ड
+मऊ
+प्लूटो
+दुखी
+ताम्र
+इल्म
+फैलता
+समतुल्य
+किरणें
+पेव्ड
+हुमायूँ
+सईद
+भाभी
+अंडमान
+चूक
+रणधीर
+इब्न
+बो
+बॉस
+उपराष्ट्रपति
+वू
+स्पीकर
+च्वाइस
+स्टुअर्ट
+प्रदाताओं
+कार्गो
+डेन्जोंगपा
+महज
+सीतापुर
+लगान
+पेंटल
+अनुसूची
+हस्तियों
+बहू
+कुलीन
+किनारा
+कुलकर्णी
+धनराशि
+छुटकारा
+बगीचे
+शिरा
+देखती
+हीन
+मद
+बीट
+वर्धित
+संभाला
+नीच
+बेंज
+जम
+जप
+गियर
+एफएम
+आरोपित
+सोन
+ठाकरे
+स्टीवर्ट
+पाण्डेय
+आयकर
+स्वार्थ
+जन्मतिथि
+विज्ञप्ति
+न्
+रीज़न
+म्हणौनि
+वत
+रणनीतिक
+शु
+अत्याधिक
+खालसा
+प्रान्तों
+कैलोरी
+१२०
+विनिर्देश
+अमावस्या
+गोलियों
+जिन्दगी
+अशुद्ध
+स्मिता
+वार्तालाप
+दाखिल
+काउबॉय
+एक्टर्स
+टेनेसी
+पराबैंगनी
+घूमती
+खुलने
+हिरण
+संचारित
+लैला
+लाभप्रद
+प्वाइंट
+नर्तक
+जासूसी
+मानवों
+शाहपुर
+गुड़िया
+अनुग्रह
+९५
+विश्लेषक
+जहांगीर
+ही।
+त्रिशूल
+मनीश
+स्पैरो
+कोंकणी
+सेक्टर
+रिवर
+यथासंभव
+साम्यवाद
+हडसन
+सेव
+चैंपियंस
+बसों
+किपलिंग
+लड़
+विकिपिडिया
+घनिष्ठ
+दीवारें
+टॉक
+क्रमपरिवर्तन
+म्यूजियम
+प्लान
+केसरी
+फैमिली
+लातिन
+आर्द्रता
+घाना
+अस्मिता
+बट
+छड़ी
+कात्यायन
+पुनर्जन्म
+ग्लूकोज़
+अज्ञेय
+फिटनेस
+प्रतिभाशाली
+कलाकृतियों
+हीलियम
+दोहा
+अंधेरे
+तापीय
+मल्टी
+टीकू
+आर्किटेक्चर
+किन्हीं
+सत्यापन
+बलूचिस्तान
+लारा
+फिशर
+रिहा
+देवा
+गॉड
+सुनाया
+वेश
+सबौर
+प्रशान्त
+चिंताओं
+तंजानिया
+जाएँ।
+संयोजी
+साँचों
+पूछ
+श्राद्ध
+मात
+टैंगो
+अमरनाथ
+जानकार
+कृषक
+पेले
+गुणसूत्र
+पहियों
+जिज्ञासा
+टिप्पणियों
+कहलाने
+मोनोक्रोम
+हीरालाल
+बारीक
+देंगे।
+चित
+छोड़ते
+क़ुरान
+यमन
+आदर्शों
+अपन
+संघटन
+विषयवस्तु
+आमदनी
+स्क्वैश
+दर्शनों
+सूरदास
+मातृभूमि
+फेंकने
+१९५३
+दोस्ताना
+लैण्ड
+योजन
+लॉर्ड्स
+अभि
+यूएफओ
+विध्वंस
+भूपति
+नदाल
+प्रतिभूतियों
+ट्री
+टॉमी
+संप्रदायों
+६२
+वैयक्तिक
+भेजता
+मल्टीमीडिया
+आयामी
+गुड़
+ट्रॉफी
+आविष्कारक
+हुईं।
+लॉयड
+चिह्नों
+बिशप
+साँप
+हेवी
+पर्यवेक्षण
+ाद
+चिन्ता
+आलम
+चौबीस
+तलसानिया
+ताड़
+दायित्वों
+गलतियाँ
+रिएक्टर
+चंद्रगुप्त
+सप्तम
+नाइजीरिया
+स्थ
+गुदा
+त्यों
+मिटटी
+कर्ज़
+बॉन
+६७
+तात्कालिक
+गार्डनर
+अनूठा
+ओड़िआ
+रीटा
+विश्लेषणात्मक
+देवरिया
+नेवर
+्दी
+चिकनी
+डेटिंग
+पोर्टेबल
+उगाया
+बालकों
+स्पोर्ट
+१९५१
+द्रोण
+आवंटित
+गांगुली
+नार्वे
+यन्त्र
+देशपांडे
+८२
+प्याज
+एसएमएस
+तूं
+संहार
+अलौली
+शकीरा
+छू
+देवकी
+गोल्डबर्ग
+मशीनें
+कर्ज
+चढ़ने
+हिमानी
+बतलाया
+बंगलुरु
+पढाई
+नेम
+फ़ैसला
+प्रीतम
+हिरासत
+मुबारक
+खा०प०
+डिप्लोमा
+कॉनकॉर्ड
+समझकर
+संदर्म
+एलर्जी
+नितांत
+उठने
+मेरिल
+गोपनीय
+सुगम
+क़ी
+ाखण्ड
+युग्म
+बढ़ना
+अबाउट
+वहा
+चला।
+वतन
+बाधाओं
+हुबली
+हीट
+फुल
+अनुपस्थित
+येल
+भावुक
+पित्ताशय
+टिन
+लड़ा
+रॉकी
+नोल्स
+वमन
+मारना
+ब्लाक
+बहोत
+कूपर
+करो।
+प्रमाणपत्र
+यूट्यूब
+सम्मलेन
+रनवे
+पूँजी
+मंडप
+पोटेशियम
+उत्तरांचल
+ठेठ
+ओडिशा
+पल्लव
+इन्दौर
+तर्ज़
+ः
+अनूप
+आओ
+कुख्यात
+बांसुरी
+अनुपयुक्त
+मगरमच्छ
+स्पा
+सेबी
+चाहा
+धमनियों
+बारें
+अश्व
+हस्तिनापुर
+ईसाइयों
+आइपॉड
+१०१
+इराकी
+रयान
+ाल
+हिमनद
+अमरावती
+गिरी
+पूछने
+प्रेषित
+घटाने
+डिस्कवरी
+पथरी
+रायबरेली
+नायनमार
+बढती
+मिलेगी
+किशोरों
+साड़ी
+शिवजी
+पुनर्वास
+सहरसा
+कैरोलिना
+आरण्यक
+असुर
+लौंग
+समाविष्ट
+ज़ोन
+फकीर
+बियोवुल्फ़
+राइस
+थेफ्ट
+लू
+ल०
+अज़ाब
+वेबदुनिया
+ल्यूकेमिया
+मार्गरेट
+संन्यास
+रनों
+सुनहरे
+सबने
+विरल
+पॉलिसी
+रश
+कैमरों
+एंजेल्स
+प्राणायाम
+सेलिब्रिटी
+कण्डारस्यूं
+शाश्वत
+जुलूस
+विश
+जेफ
+मतानुसार
+उत्पात
+मामा
+७३
+रहीं।
+क्लिंटन
+विकिया
+आइवी
+लिस्ट
+आबू
+गोमती
+पुरुषोत्तम
+उत्तराखण्
+हेराल्ड
+दांता
+पद्मश्री
+शर्तें
+कटिहार
+स्विंग
+उत्तरार्द्ध
+सिंगल्स
+केदार
+रघु
+वासना
+पहुँचकर
+न्यूकैसल
+मांगी
+अमल
+सल्फर
+छोड
+अंजना
+कंप्यूटरों
+ढ
+विलिस
+सीकर
+जुड़ता
+प्रसन्नता
+प्लेटफॉर्म
+गिरि
+उछाल
+करीना
+जहर
+मासके
+सम्पदा
+चौदहवीं
+ढाईज्यूली
+साओ
+कोचीन
+श्रावण
+अर्पित
+मासूम
+टीन
+स्पार्क
+कट्टर
+चढ़ा
+ट्रिब्यून
+होंडा
+कीये
+एंटोनियो
+लैस
+किससे
+एकजुट
+पतंग
+१९२७
+टीकाकरण
+मूक
+असरगंज
+सतहों
+नाल
+आयताकार
+चढ़ाव
+कार्यशील
+दक्षिणपूर्व
+माथे
+मर्फी
+गुजरता
+सफ़र
+स्लोवेनिया
+रिले
+कॉमन
+जमाव
+कुलभूषण
+्स
+क्रोम
+उजाला
+मूत्राशय
+इस्राइल
+नाड़ी
+ंवत
+परगना
+लैंडिंग
+रेलगाड़ी
+कलाँ
+उद्धार
+ज़रिये
+शॉर्ट
+टिक
+डिज़नी
+फिल्माया
+मरते
+निष्कर्षों
+उलट
+भीमसेन
+चक्रों
+मात्राओं
+प्रणाम
+सिम्बियन
+संस्थागत
+बिताने
+आंग्ल
+बिजनौर
+फायदे
+खेड़ा
+कार्यभार
diff --git a/src/Makefile.am b/src/Makefile.am
index 225444e..31399a6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -47,6 +47,9 @@
 HBDEPS   += $(GLIB_DEPS)
 HBSOURCES += $(HB_GLIB_sources)
 HBHEADERS += $(HB_GLIB_headers)
+HB_HAS_GLIB_DEF = define HB_HAS_GLIB 1
+else
+HB_HAS_GLIB_DEF = undef HB_HAS_GLIB
 endif
 
 if HAVE_FREETYPE
@@ -55,6 +58,9 @@
 HBDEPS   += $(FREETYPE_DEPS)
 HBSOURCES += $(HB_FT_sources)
 HBHEADERS += $(HB_FT_headers)
+HB_HAS_FREETYPE_DEF = define HB_HAS_FREETYPE 1
+else
+HB_HAS_FREETYPE_DEF = undef HB_HAS_FREETYPE
 endif
 
 if HAVE_GRAPHITE2
@@ -63,6 +69,9 @@
 HBDEPS   += $(GRAPHITE2_DEPS)
 HBSOURCES += $(HB_GRAPHITE2_sources)
 HBHEADERS += $(HB_GRAPHITE2_headers)
+HB_HAS_GRAPHITE_DEF = define HB_HAS_GRAPHITE 1
+else
+HB_HAS_GRAPHITE_DEF = undef HB_HAS_GRAPHITE
 endif
 
 if HAVE_UNISCRIBE
@@ -70,6 +79,9 @@
 HBNONPCLIBS += $(UNISCRIBE_LIBS)
 HBSOURCES += $(HB_UNISCRIBE_sources)
 HBHEADERS += $(HB_UNISCRIBE_headers)
+HB_HAS_UNISCRIBE_DEF = define HB_HAS_UNISCRIBE 1
+else
+HB_HAS_UNISCRIBE_DEF = undef HB_HAS_UNISCRIBE
 endif
 
 if HAVE_DIRECTWRITE
@@ -77,6 +89,9 @@
 HBNONPCLIBS += $(DIRECTWRITE_LIBS)
 HBSOURCES += $(HB_DIRECTWRITE_sources)
 HBHEADERS += $(HB_DIRECTWRITE_headers)
+HB_HAS_DIRECTWRITE_DEF = define HB_HAS_DIRECTWRITE 1
+else
+HB_HAS_DIRECTWRITE_DEF = undef HB_HAS_DIRECTWRITE
 endif
 
 if HAVE_GDI
@@ -84,6 +99,9 @@
 HBNONPCLIBS += $(GDI_LIBS)
 HBSOURCES += $(HB_GDI_sources)
 HBHEADERS += $(HB_GDI_headers)
+HB_HAS_GDI_DEF = define HB_HAS_GDI 1
+else
+HB_HAS_GDI_DEF = undef HB_HAS_GDI
 endif
 
 if HAVE_CORETEXT
@@ -91,6 +109,9 @@
 HBNONPCLIBS += $(CORETEXT_LIBS)
 HBSOURCES += $(HB_CORETEXT_sources)
 HBHEADERS += $(HB_CORETEXT_headers)
+HB_HAS_CORETEXT_DEF = define HB_HAS_CORETEXT 1
+else
+HB_HAS_CORETEXT_DEF = undef HB_HAS_CORETEXT
 endif
 
 
@@ -147,7 +168,7 @@
 pkgconfig_DATA = harfbuzz.pc
 cmakedir = $(libdir)/cmake/harfbuzz
 cmake_DATA = harfbuzz-config.cmake
-EXTRA_DIST += hb-version.h.in harfbuzz.pc.in harfbuzz-config.cmake.in
+EXTRA_DIST += hb-version.h.in hb-features.h.in harfbuzz.pc.in harfbuzz-config.cmake.in
 
 lib_LTLIBRARIES += libharfbuzz-subset.la
 libharfbuzz_subset_la_LINK = $(chosen_linker) $(libharfbuzz_subset_la_LDFLAGS)
@@ -178,6 +199,7 @@
 HBLIBS += $(ICU_LIBS)
 HBSOURCES += $(HB_ICU_sources)
 HBHEADERS += $(HB_ICU_headers)
+HB_HAS_ICU_DEF = define HB_HAS_ICU 1
 else
 lib_LTLIBRARIES += libharfbuzz-icu.la
 libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
@@ -187,6 +209,7 @@
 EXTRA_libharfbuzz_icu_la_DEPENDENCIES = $(harfbuzz_icu_def_dependency)
 pkginclude_HEADERS += $(HB_ICU_headers)
 pkgconfig_DATA += harfbuzz-icu.pc
+HB_HAS_ICU_DEF = undef HB_HAS_ICU
 endif
 endif
 EXTRA_DIST += harfbuzz-icu.pc.in
@@ -226,6 +249,25 @@
 	$(NULL)
 
 
+BUILT_SOURCES += \
+	hb-features.h
+DISTCLEANFILES += \
+	hb-features.h
+
+hb-features.h: hb-features.h.in $(top_builddir)/config.status
+	$(AM_V_GEN) $(SED) \
+		-e 's/mesondefine HB_HAS_FREETYPE/$(HB_HAS_FREETYPE_DEF)/' \
+		-e 's/mesondefine HB_HAS_GDI/$(HB_HAS_GDI_DEF)/' \
+		-e 's/mesondefine HB_HAS_GDI/$(HB_HAS_GDI_DEF)/' \
+		-e 's/mesondefine HB_HAS_GRAPHITE/$(HB_HAS_GRAPHITE_DEF)/' \
+		-e 's/mesondefine HB_HAS_GLIB/$(HB_HAS_GLIB_DEF)/' \
+		-e 's/mesondefine HB_HAS_UNISCRIBE/$(HB_HAS_UNISCRIBE_DEF)/' \
+		-e 's/mesondefine HB_HAS_DIRECTWRITE/$(HB_HAS_DIRECTWRITE_DEF)/' \
+		-e 's/mesondefine HB_HAS_CORETEXT/$(HB_HAS_CORETEXT_DEF)/' \
+		-e 's/mesondefine HB_HAS_ICU/$(HB_HAS_ICU_DEF)/' \
+		"$<" > "$@" || ($(RM) "$@"; false)
+
+
 %.pc: %.pc.in $(top_builddir)/config.status
 	$(AM_V_GEN) \
 	$(SED)	-e 's@%prefix%@$(prefix)@g' \
@@ -368,6 +410,7 @@
 	test-iter \
 	test-machinery \
 	test-map \
+	test-multimap \
 	test-number \
 	test-ot-tag \
 	test-priority-queue \
@@ -407,6 +450,10 @@
 test_map_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
 test_map_LDADD = $(COMPILED_TESTS_LDADD)
 
+test_multimap_SOURCES = test-multimap.cc hb-static.cc
+test_multimap_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_multimap_LDADD = $(COMPILED_TESTS_LDADD)
+
 test_number_SOURCES = test-number.cc hb-number.cc
 test_number_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
 test_number_LDADD = $(COMPILED_TESTS_LDADD)
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 6c891ea..6c4fc5d 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -52,6 +52,7 @@
 	hb-map.hh \
 	hb-meta.hh \
 	hb-ms-feature-ranges.hh \
+	hb-multimap.hh \
 	hb-mutex.hh \
 	hb-null.hh \
 	hb-number.cc \
@@ -95,7 +96,10 @@
 	OT/glyf/Glyph.hh \
 	OT/glyf/GlyphHeader.hh \
 	OT/glyf/SimpleGlyph.hh \
+	OT/glyf/coord-setter.hh \
+	OT/glyf/composite-iter.hh \
 	OT/glyf/CompositeGlyph.hh \
+	OT/glyf/VarCompositeGlyph.hh \
 	OT/glyf/SubsetGlyph.hh \
 	OT/Layout/types.hh \
 	OT/Layout/Common/Coverage.hh \
diff --git a/src/OT/Layout/Common/Coverage.hh b/src/OT/Layout/Common/Coverage.hh
index eef89a2..fbd7c64 100644
--- a/src/OT/Layout/Common/Coverage.hh
+++ b/src/OT/Layout/Common/Coverage.hh
@@ -49,7 +49,7 @@
   HBUINT16                      format;         /* Format identifier */
   CoverageFormat1_3<SmallTypes> format1;
   CoverageFormat2_4<SmallTypes> format2;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
   CoverageFormat1_3<MediumTypes>format3;
   CoverageFormat2_4<MediumTypes>format4;
 #endif
@@ -65,7 +65,7 @@
     {
     case 1: return_trace (u.format1.sanitize (c));
     case 2: return_trace (u.format2.sanitize (c));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 3: return_trace (u.format3.sanitize (c));
     case 4: return_trace (u.format4.sanitize (c));
 #endif
@@ -74,10 +74,8 @@
   }
 
   /* Has interface. */
-  static constexpr unsigned SENTINEL = NOT_COVERED;
-  typedef unsigned int value_t;
-  value_t operator [] (hb_codepoint_t k) const { return get (k); }
-  bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+  unsigned operator [] (hb_codepoint_t k) const { return get (k); }
+  bool has (hb_codepoint_t k) const { return (*this)[k] != NOT_COVERED; }
   /* Predicate. */
   bool operator () (hb_codepoint_t k) const { return has (k); }
 
@@ -87,7 +85,7 @@
     switch (u.format) {
     case 1: return u.format1.get_coverage (glyph_id);
     case 2: return u.format2.get_coverage (glyph_id);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 3: return u.format3.get_coverage (glyph_id);
     case 4: return u.format4.get_coverage (glyph_id);
 #endif
@@ -100,7 +98,7 @@
     switch (u.format) {
     case 1: return u.format1.get_population ();
     case 2: return u.format2.get_population ();
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 3: return u.format3.get_population ();
     case 4: return u.format4.get_population ();
 #endif
@@ -127,7 +125,7 @@
     }
     u.format = count <= num_ranges * 3 ? 1 : 2;
 
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     if (count && last > 0xFFFFu)
       u.format += 2;
 #endif
@@ -136,7 +134,7 @@
     {
     case 1: return_trace (u.format1.serialize (c, glyphs));
     case 2: return_trace (u.format2.serialize (c, glyphs));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 3: return_trace (u.format3.serialize (c, glyphs));
     case 4: return_trace (u.format4.serialize (c, glyphs));
 #endif
@@ -166,7 +164,7 @@
     {
     case 1: return u.format1.intersects (glyphs);
     case 2: return u.format2.intersects (glyphs);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 3: return u.format3.intersects (glyphs);
     case 4: return u.format4.intersects (glyphs);
 #endif
@@ -179,7 +177,7 @@
     {
     case 1: return u.format1.intersects_coverage (glyphs, index);
     case 2: return u.format2.intersects_coverage (glyphs, index);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 3: return u.format3.intersects_coverage (glyphs, index);
     case 4: return u.format4.intersects_coverage (glyphs, index);
 #endif
@@ -196,7 +194,7 @@
     {
     case 1: return u.format1.collect_coverage (glyphs);
     case 2: return u.format2.collect_coverage (glyphs);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 3: return u.format3.collect_coverage (glyphs);
     case 4: return u.format4.collect_coverage (glyphs);
 #endif
@@ -212,7 +210,7 @@
     {
     case 1: return u.format1.intersect_set (glyphs, intersect_glyphs);
     case 2: return u.format2.intersect_set (glyphs, intersect_glyphs);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 3: return u.format3.intersect_set (glyphs, intersect_glyphs);
     case 4: return u.format4.intersect_set (glyphs, intersect_glyphs);
 #endif
@@ -225,13 +223,13 @@
     static constexpr bool is_sorted_iterator = true;
     iter_t (const Coverage &c_ = Null (Coverage))
     {
-      memset (this, 0, sizeof (*this));
+      hb_memset (this, 0, sizeof (*this));
       format = c_.u.format;
       switch (format)
       {
       case 1: u.format1.init (c_.u.format1); return;
       case 2: u.format2.init (c_.u.format2); return;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
       case 3: u.format3.init (c_.u.format3); return;
       case 4: u.format4.init (c_.u.format4); return;
 #endif
@@ -244,7 +242,7 @@
       {
       case 1: return u.format1.__more__ ();
       case 2: return u.format2.__more__ ();
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
       case 3: return u.format3.__more__ ();
       case 4: return u.format4.__more__ ();
 #endif
@@ -257,7 +255,7 @@
       {
       case 1: u.format1.__next__ (); break;
       case 2: u.format2.__next__ (); break;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
       case 3: u.format3.__next__ (); break;
       case 4: u.format4.__next__ (); break;
 #endif
@@ -273,7 +271,7 @@
       {
       case 1: return u.format1.get_glyph ();
       case 2: return u.format2.get_glyph ();
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
       case 3: return u.format3.get_glyph ();
       case 4: return u.format4.get_glyph ();
 #endif
@@ -287,7 +285,7 @@
       {
       case 1: return u.format1 != o.u.format1;
       case 2: return u.format2 != o.u.format2;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
       case 3: return u.format3 != o.u.format3;
       case 4: return u.format4 != o.u.format4;
 #endif
@@ -302,7 +300,7 @@
       {
       case 1: it.u.format1 = u.format1.__end__ (); break;
       case 2: it.u.format2 = u.format2.__end__ (); break;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
       case 3: it.u.format3 = u.format3.__end__ (); break;
       case 4: it.u.format4 = u.format4.__end__ (); break;
 #endif
@@ -314,7 +312,7 @@
     private:
     unsigned int format;
     union {
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     CoverageFormat2_4<MediumTypes>::iter_t      format4; /* Put this one first since it's larger; helps shut up compiler. */
     CoverageFormat1_3<MediumTypes>::iter_t      format3;
 #endif
diff --git a/src/OT/Layout/Common/CoverageFormat1.hh b/src/OT/Layout/Common/CoverageFormat1.hh
index 82fd48d..5d68e3d 100644
--- a/src/OT/Layout/Common/CoverageFormat1.hh
+++ b/src/OT/Layout/Common/CoverageFormat1.hh
@@ -77,7 +77,14 @@
 
   bool intersects (const hb_set_t *glyphs) const
   {
-    /* TODO Speed up, using hb_set_next() and bsearch()? */
+    if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2)
+    {
+      for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+        if (get_coverage (g) != NOT_COVERED)
+	  return true;
+      return false;
+    }
+
     for (const auto& g : glyphArray.as_array ())
       if (glyphs->has (g))
         return true;
diff --git a/src/OT/Layout/Common/CoverageFormat2.hh b/src/OT/Layout/Common/CoverageFormat2.hh
index 974d094..d7fcc35 100644
--- a/src/OT/Layout/Common/CoverageFormat2.hh
+++ b/src/OT/Layout/Common/CoverageFormat2.hh
@@ -80,8 +80,6 @@
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (this))) return_trace (false);
 
-    /* TODO(iter) Write more efficiently? */
-
     unsigned num_ranges = 0;
     hb_codepoint_t last = (hb_codepoint_t) -2;
     for (auto g: glyphs)
@@ -115,26 +113,22 @@
 
   bool intersects (const hb_set_t *glyphs) const
   {
+    if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
+    {
+      for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+        if (get_coverage (g) != NOT_COVERED)
+	  return true;
+      return false;
+    }
+
     return hb_any (+ hb_iter (rangeRecord)
                    | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); }));
   }
   bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
   {
-    auto cmp = [] (const void *pk, const void *pr) -> int
-    {
-      unsigned index = * (const unsigned *) pk;
-      const RangeRecord<Types> &range = * (const RangeRecord<Types> *) pr;
-      if (index < range.value) return -1;
-      if (index > (unsigned int) range.value + (range.last - range.first)) return +1;
-      return 0;
-    };
-
-    auto arr = rangeRecord.as_array ();
-    unsigned idx;
-    if (hb_bsearch_impl (&idx, index,
-                         arr.arrayZ, arr.length, sizeof (arr[0]),
-                         (int (*)(const void *_key, const void *_item)) cmp))
-      return arr.arrayZ[idx].intersects (*glyphs);
+    auto *range = rangeRecord.as_array ().bsearch (index);
+    if (range)
+      return range->intersects (*glyphs);
     return false;
   }
 
@@ -142,9 +136,14 @@
 	    hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
   void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
   {
+    /* Break out of loop for overlapping, broken, tables,
+     * to avoid fuzzer timouts. */
+    hb_codepoint_t last = 0;
     for (const auto& range : rangeRecord)
     {
-      hb_codepoint_t last = range.last;
+      if (unlikely (range.first < last))
+        break;
+      last = range.last;
       for (hb_codepoint_t g = range.first - 1;
 	   glyphs.next (&g) && g <= last;)
 	intersect_glyphs << g;
diff --git a/src/OT/Layout/GPOS/MarkBasePos.hh b/src/OT/Layout/GPOS/MarkBasePos.hh
index c99b6b2..edf7099 100644
--- a/src/OT/Layout/GPOS/MarkBasePos.hh
+++ b/src/OT/Layout/GPOS/MarkBasePos.hh
@@ -13,7 +13,7 @@
   union {
   HBUINT16				format;         /* Format identifier */
   MarkBasePosFormat1_2<SmallTypes>	format1;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
   MarkBasePosFormat1_2<MediumTypes>	format2;
 #endif
   } u;
@@ -26,7 +26,7 @@
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
 #endif
     default:return_trace (c->default_return_value ());
diff --git a/src/OT/Layout/GPOS/MarkLigPos.hh b/src/OT/Layout/GPOS/MarkLigPos.hh
index 8a4de9f..09152fd 100644
--- a/src/OT/Layout/GPOS/MarkLigPos.hh
+++ b/src/OT/Layout/GPOS/MarkLigPos.hh
@@ -13,7 +13,7 @@
   union {
   HBUINT16				format;         /* Format identifier */
   MarkLigPosFormat1_2<SmallTypes>	format1;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
   MarkLigPosFormat1_2<MediumTypes>	format2;
 #endif
   } u;
@@ -26,7 +26,7 @@
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
 #endif
     default:return_trace (c->default_return_value ());
diff --git a/src/OT/Layout/GPOS/MarkMarkPos.hh b/src/OT/Layout/GPOS/MarkMarkPos.hh
index 74b5105..4118fc3 100644
--- a/src/OT/Layout/GPOS/MarkMarkPos.hh
+++ b/src/OT/Layout/GPOS/MarkMarkPos.hh
@@ -13,7 +13,7 @@
   union {
   HBUINT16				format;         /* Format identifier */
   MarkMarkPosFormat1_2<SmallTypes>	format1;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
   MarkMarkPosFormat1_2<MediumTypes>	format2;
 #endif
   } u;
@@ -26,7 +26,7 @@
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
 #endif
     default:return_trace (c->default_return_value ());
diff --git a/src/OT/Layout/GPOS/PairPos.hh b/src/OT/Layout/GPOS/PairPos.hh
index 72bfc43..9823768 100644
--- a/src/OT/Layout/GPOS/PairPos.hh
+++ b/src/OT/Layout/GPOS/PairPos.hh
@@ -15,7 +15,7 @@
   HBUINT16			format;         /* Format identifier */
   PairPosFormat1_3<SmallTypes>	format1;
   PairPosFormat2_4<SmallTypes>	format2;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
   PairPosFormat1_3<MediumTypes>	format3;
   PairPosFormat2_4<MediumTypes>	format4;
 #endif
@@ -30,7 +30,7 @@
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
     case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
     case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
 #endif
diff --git a/src/OT/Layout/GPOS/PairPosFormat1.hh b/src/OT/Layout/GPOS/PairPosFormat1.hh
index ddf7313..9c9b268 100644
--- a/src/OT/Layout/GPOS/PairPosFormat1.hh
+++ b/src/OT/Layout/GPOS/PairPosFormat1.hh
@@ -51,8 +51,21 @@
 
   bool intersects (const hb_set_t *glyphs) const
   {
+    auto &cov = this+coverage;
+
+    if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4)
+    {
+      for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+      {
+	unsigned i = cov.get_coverage (g);
+	if ((this+pairSet[i]).intersects (glyphs, valueFormat))
+	  return true;
+      }
+      return false;
+    }
+
     return
-    + hb_zip (this+coverage, pairSet)
+    + hb_zip (cov, pairSet)
     | hb_filter (*glyphs, hb_first)
     | hb_map (hb_second)
     | hb_map ([glyphs, this] (const typename Types::template OffsetTo<PairSet> &_)
@@ -171,12 +184,16 @@
     unsigned format1 = 0;
     unsigned format2 = 0;
     for (const auto & _ :
-             + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second))
+	  + hb_zip (this+coverage, pairSet)
+	  | hb_filter (glyphset, hb_first)
+	  | hb_map (hb_second)
+	)
     {
       const PairSet& set = (this + _);
       const PairValueRecord *record = &set.firstPairValueRecord;
 
-      for (unsigned i = 0; i < set.len; i++)
+      unsigned count = set.len;
+      for (unsigned i = 0; i < count; i++)
       {
         if (record->intersects (glyphset))
         {
@@ -185,6 +202,9 @@
         }
         record = &StructAtOffset<const PairValueRecord> (record, record_size);
       }
+
+      if (format1 == valueFormat[0] && format2 == valueFormat[1])
+        break;
     }
 
     return hb_pair (format1, format2);
diff --git a/src/OT/Layout/GPOS/PairPosFormat2.hh b/src/OT/Layout/GPOS/PairPosFormat2.hh
index 83b093b..9c87ac2 100644
--- a/src/OT/Layout/GPOS/PairPosFormat2.hh
+++ b/src/OT/Layout/GPOS/PairPosFormat2.hh
@@ -220,17 +220,25 @@
     if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
     {
       c->buffer->message (c->font,
-			  "kerning glyphs at %d,%d",
+			  "try kerning glyphs at %d,%d",
 			  c->buffer->idx, skippy_iter.idx);
     }
 
     applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
     applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
 
+    if (applied_first || applied_second)
+      if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+      {
+	c->buffer->message (c->font,
+			    "kerned glyphs at %d,%d",
+			    c->buffer->idx, skippy_iter.idx);
+      }
+
     if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
     {
       c->buffer->message (c->font,
-			  "kerned glyphs at %d,%d",
+			  "tried kerning glyphs at %d,%d",
 			  c->buffer->idx, skippy_iter.idx);
     }
 
@@ -241,10 +249,15 @@
     boring:
       buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
 
+    if (len2)
+    {
+      skippy_iter.idx++;
+      // https://github.com/harfbuzz/harfbuzz/issues/3824
+      // https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
+      buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
+    }
 
     buffer->idx = skippy_iter.idx;
-    if (len2)
-      buffer->idx++;
 
     return_trace (true);
   }
@@ -309,6 +322,7 @@
   {
     unsigned len1 = valueFormat1.get_len ();
     unsigned len2 = valueFormat2.get_len ();
+    unsigned record_size = len1 + len2;
 
     unsigned format1 = 0;
     unsigned format2 = 0;
@@ -317,10 +331,13 @@
     {
       for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
       {
-        unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+        unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_size;
         format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
         format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
       }
+
+      if (format1 == valueFormat1 && format2 == valueFormat2)
+        break;
     }
 
     return hb_pair (format1, format2);
diff --git a/src/OT/Layout/GPOS/PairSet.hh b/src/OT/Layout/GPOS/PairSet.hh
index aa48d93..a318f39 100644
--- a/src/OT/Layout/GPOS/PairSet.hh
+++ b/src/OT/Layout/GPOS/PairSet.hh
@@ -112,24 +112,38 @@
       if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
       {
 	c->buffer->message (c->font,
-			    "kerning glyphs at %d,%d",
+			    "try kerning glyphs at %d,%d",
 			    c->buffer->idx, pos);
       }
 
       bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
       bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
 
+      if (applied_first || applied_second)
+	if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+	{
+	  c->buffer->message (c->font,
+			      "kerned glyphs at %d,%d",
+			      c->buffer->idx, pos);
+	}
+
       if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
       {
 	c->buffer->message (c->font,
-			    "kerned glyphs at %d,%d",
+			    "tried kerning glyphs at %d,%d",
 			    c->buffer->idx, pos);
       }
 
       if (applied_first || applied_second)
         buffer->unsafe_to_break (buffer->idx, pos + 1);
+
       if (len2)
-        pos++;
+      {
+	pos++;
+      // https://github.com/harfbuzz/harfbuzz/issues/3824
+      // https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
+      buffer->unsafe_to_break (buffer->idx, pos + 1);
+      }
 
       buffer->idx = pos;
       return_trace (true);
diff --git a/src/OT/Layout/GSUB/AlternateSet.hh b/src/OT/Layout/GSUB/AlternateSet.hh
index 4a9e967..6c50c97 100644
--- a/src/OT/Layout/GSUB/AlternateSet.hh
+++ b/src/OT/Layout/GSUB/AlternateSet.hh
@@ -84,7 +84,7 @@
   {
     if (alternates.len && alternate_count)
     {
-      + alternates.sub_array (start_offset, alternate_count)
+      + alternates.as_array ().sub_array (start_offset, alternate_count)
       | hb_sink (hb_array (alternate_glyphs, *alternate_count))
       ;
     }
diff --git a/src/OT/Layout/GSUB/AlternateSubst.hh b/src/OT/Layout/GSUB/AlternateSubst.hh
index 3740617..9d7cd6f 100644
--- a/src/OT/Layout/GSUB/AlternateSubst.hh
+++ b/src/OT/Layout/GSUB/AlternateSubst.hh
@@ -14,7 +14,7 @@
   union {
   HBUINT16				format;         /* Format identifier */
   AlternateSubstFormat1_2<SmallTypes>	format1;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
   AlternateSubstFormat1_2<MediumTypes>	format2;
 #endif
   } u;
@@ -27,7 +27,7 @@
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
 #endif
     default:return_trace (c->default_return_value ());
diff --git a/src/OT/Layout/GSUB/Ligature.hh b/src/OT/Layout/GSUB/Ligature.hh
index 6caa80e..cdb35f5 100644
--- a/src/OT/Layout/GSUB/Ligature.hh
+++ b/src/OT/Layout/GSUB/Ligature.hh
@@ -118,7 +118,7 @@
 	match_positions[i] += delta;
 	if (i)
 	  *p++ = ',';
-	snprintf (p, sizeof(buf), "%u", match_positions[i]);
+	snprintf (p, sizeof(buf) - (p - buf), "%u", match_positions[i]);
 	p += strlen(p);
       }
 
diff --git a/src/OT/Layout/GSUB/LigatureSubst.hh b/src/OT/Layout/GSUB/LigatureSubst.hh
index 6370797..7ba19e8 100644
--- a/src/OT/Layout/GSUB/LigatureSubst.hh
+++ b/src/OT/Layout/GSUB/LigatureSubst.hh
@@ -14,7 +14,7 @@
   union {
   HBUINT16				format;         /* Format identifier */
   LigatureSubstFormat1_2<SmallTypes>	format1;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
   LigatureSubstFormat1_2<MediumTypes>	format2;
 #endif
   } u;
@@ -27,7 +27,7 @@
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
 #endif
     default:return_trace (c->default_return_value ());
diff --git a/src/OT/Layout/GSUB/MultipleSubst.hh b/src/OT/Layout/GSUB/MultipleSubst.hh
index 852ca3e..95710ed 100644
--- a/src/OT/Layout/GSUB/MultipleSubst.hh
+++ b/src/OT/Layout/GSUB/MultipleSubst.hh
@@ -14,7 +14,7 @@
   union {
   HBUINT16				format;         /* Format identifier */
   MultipleSubstFormat1_2<SmallTypes>	format1;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
   MultipleSubstFormat1_2<MediumTypes>	format2;
 #endif
   } u;
@@ -28,7 +28,7 @@
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
 #endif
     default:return_trace (c->default_return_value ());
diff --git a/src/OT/Layout/GSUB/Sequence.hh b/src/OT/Layout/GSUB/Sequence.hh
index abf1c64..e219007 100644
--- a/src/OT/Layout/GSUB/Sequence.hh
+++ b/src/OT/Layout/GSUB/Sequence.hh
@@ -117,7 +117,7 @@
       {
 	if (buf < p)
 	  *p++ = ',';
-	snprintf (p, sizeof(buf), "%u", i);
+	snprintf (p, sizeof(buf) - (p - buf), "%u", i);
 	p += strlen(p);
       }
 
diff --git a/src/OT/Layout/GSUB/SingleSubst.hh b/src/OT/Layout/GSUB/SingleSubst.hh
index 6942e69..7da8103 100644
--- a/src/OT/Layout/GSUB/SingleSubst.hh
+++ b/src/OT/Layout/GSUB/SingleSubst.hh
@@ -16,7 +16,7 @@
   HBUINT16				format;         /* Format identifier */
   SingleSubstFormat1_3<SmallTypes>	format1;
   SingleSubstFormat2_4<SmallTypes>	format2;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
   SingleSubstFormat1_3<MediumTypes>	format3;
   SingleSubstFormat2_4<MediumTypes>	format4;
 #endif
@@ -32,7 +32,7 @@
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
     case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
     case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
 #endif
@@ -55,7 +55,7 @@
       format = 1;
       hb_codepoint_t mask = 0xFFFFu;
 
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
        if (+ glyphs
 	   | hb_map_retains_sorting (hb_first)
 	   | hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; }))
@@ -78,7 +78,7 @@
                                                | hb_map_retains_sorting (hb_first),
                                                delta));
     case 2: return_trace (u.format2.serialize (c, glyphs));
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 3: return_trace (u.format3.serialize (c,
                                                + glyphs
                                                | hb_map_retains_sorting (hb_first),
diff --git a/src/OT/Layout/GSUB/SingleSubstFormat1.hh b/src/OT/Layout/GSUB/SingleSubstFormat1.hh
index 13665d7..1be21b9 100644
--- a/src/OT/Layout/GSUB/SingleSubstFormat1.hh
+++ b/src/OT/Layout/GSUB/SingleSubstFormat1.hh
@@ -57,7 +57,7 @@
     hb_codepoint_t max_before = intersection.get_max ();
     hb_codepoint_t min_after = (min_before + d) & mask;
     hb_codepoint_t max_after = (max_before + d) & mask;
-    if (pop >= max_before - min_before &&
+    if (intersection.get_population () == max_before - min_before + 1 &&
 	((min_before <= min_after && min_after <= max_before) ||
 	 (min_before <= max_after && max_after <= max_before)))
       return;
diff --git a/src/OT/Layout/GSUB/SingleSubstFormat2.hh b/src/OT/Layout/GSUB/SingleSubstFormat2.hh
index 5416299..01df714 100644
--- a/src/OT/Layout/GSUB/SingleSubstFormat2.hh
+++ b/src/OT/Layout/GSUB/SingleSubstFormat2.hh
@@ -36,8 +36,24 @@
 
   void closure (hb_closure_context_t *c) const
   {
-    + hb_zip (this+coverage, substitute)
-    | hb_filter (c->parent_active_glyphs (), hb_first)
+    auto &cov = this+coverage;
+    auto &glyph_set = c->parent_active_glyphs ();
+
+    if (substitute.len > glyph_set.get_population () * 4)
+    {
+      for (auto g : glyph_set)
+      {
+	unsigned i = cov.get_coverage (g);
+	if (i == NOT_COVERED || i >= substitute.len)
+	  continue;
+	c->output->add (substitute.arrayZ[i]);
+      }
+
+      return;
+    }
+
+    + hb_zip (cov, substitute)
+    | hb_filter (glyph_set, hb_first)
     | hb_map (hb_second)
     | hb_sink (c->output)
     ;
diff --git a/src/OT/glyf/CompositeGlyph.hh b/src/OT/glyf/CompositeGlyph.hh
index fc8e309..edf8cd8 100644
--- a/src/OT/glyf/CompositeGlyph.hh
+++ b/src/OT/glyf/CompositeGlyph.hh
@@ -3,6 +3,7 @@
 
 
 #include "../../hb-open-type.hh"
+#include "composite-iter.hh"
 
 
 namespace OT {
@@ -121,7 +122,7 @@
     if (flags & ARG_1_AND_2_ARE_WORDS)
     {
       // no overflow, copy and update value with deltas
-      memcpy (out, this, len);
+      hb_memcpy (out, this, len);
 
       const HBINT16 *px = reinterpret_cast<const HBINT16 *> (p);
       HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val);
@@ -135,7 +136,7 @@
       if (new_x <= 127 && new_x >= -128 &&
           new_y <= 127 && new_y >= -128)
       {
-        memcpy (out, this, len);
+        hb_memcpy (out, this, len);
         HBINT8 *o = reinterpret_cast<HBINT8 *> (out + len_before_val);
         o[0] = new_x;
         o[1] = new_y;
@@ -143,7 +144,7 @@
       else
       {
         // int8 overflows after deltas applied
-        memcpy (out, this, len_before_val);
+        hb_memcpy (out, this, len_before_val);
         
         //update flags
         CompositeGlyphRecord *o = reinterpret_cast<CompositeGlyphRecord *> (out);
@@ -152,14 +153,14 @@
 
         HBINT16 new_value;
         new_value = new_x;
-        memcpy (out, &new_value, HBINT16::static_size);
+        hb_memcpy (out, &new_value, HBINT16::static_size);
         out += HBINT16::static_size;
 
         new_value = new_y;
-        memcpy (out, &new_value, HBINT16::static_size);
+        hb_memcpy (out, &new_value, HBINT16::static_size);
         out += HBINT16::static_size;
 
-        memcpy (out, p+2, len - len_before_val - 2);
+        hb_memcpy (out, p+2, len - len_before_val - 2);
         len += 2;
       }
     }
@@ -252,55 +253,7 @@
   DEFINE_SIZE_MIN (4);
 };
 
-struct composite_iter_t : hb_iter_with_fallback_t<composite_iter_t, const CompositeGlyphRecord &>
-{
-  typedef const CompositeGlyphRecord *__item_t__;
-  composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
-      glyph (glyph_), current (nullptr), current_size (0)
-  {
-    set_current (current_);
-  }
-
-  composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
-
-  item_t __item__ () const { return *current; }
-  bool __more__ () const { return current; }
-  void __next__ ()
-  {
-    if (!current->has_more ()) { current = nullptr; return; }
-
-    set_current (&StructAtOffset<CompositeGlyphRecord> (current, current_size));
-  }
-  composite_iter_t __end__ () const { return composite_iter_t (); }
-  bool operator != (const composite_iter_t& o) const
-  { return current != o.current; }
-
-
-  void set_current (__item_t__ current_)
-  {
-    if (!glyph.check_range (current_, CompositeGlyphRecord::min_size))
-    {
-      current = nullptr;
-      current_size = 0;
-      return;
-    }
-    unsigned size = current_->get_size ();
-    if (!glyph.check_range (current_, size))
-    {
-      current = nullptr;
-      current_size = 0;
-      return;
-    }
-
-    current = current_;
-    current_size = size;
-  }
-
-  private:
-  hb_bytes_t glyph;
-  __item_t__ current;
-  unsigned current_size;
-};
+using composite_iter_t = composite_iter_tmpl<CompositeGlyphRecord>;
 
 struct CompositeGlyph
 {
@@ -382,7 +335,7 @@
       unsigned comp_len = component.get_size ();
       if (component.is_anchored ())
       {
-        memcpy (p, &component, comp_len);
+        hb_memcpy (p, &component, comp_len);
         p += comp_len;
       }
       else
@@ -398,7 +351,7 @@
     if (source_len > source_comp_len)
     {
       unsigned instr_len = source_len - source_comp_len;
-      memcpy (p, (const char *)c + source_comp_len, instr_len);
+      hb_memcpy (p, (const char *)c + source_comp_len, instr_len);
       p += instr_len;
     }
 
diff --git a/src/OT/glyf/Glyph.hh b/src/OT/glyf/Glyph.hh
index 0b25659..b7215b0 100644
--- a/src/OT/glyf/Glyph.hh
+++ b/src/OT/glyf/Glyph.hh
@@ -7,6 +7,8 @@
 #include "GlyphHeader.hh"
 #include "SimpleGlyph.hh"
 #include "CompositeGlyph.hh"
+#include "VarCompositeGlyph.hh"
+#include "coord-setter.hh"
 
 
 namespace OT {
@@ -16,6 +18,11 @@
 namespace glyf_impl {
 
 
+#ifndef HB_GLYF_MAX_POINTS
+#define HB_GLYF_MAX_POINTS 10000
+#endif
+
+
 enum phantom_point_index_t
 {
   PHANTOM_LEFT   = 0,
@@ -27,7 +34,7 @@
 
 struct Glyph
 {
-  enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
+  enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE, VAR_COMPOSITE };
 
   public:
   composite_iter_t get_composite_iterator () const
@@ -35,6 +42,11 @@
     if (type != COMPOSITE) return composite_iter_t ();
     return CompositeGlyph (*header, bytes).iter ();
   }
+  var_composite_iter_t get_var_composite_iterator () const
+  {
+    if (type != VAR_COMPOSITE) return var_composite_iter_t ();
+    return VarCompositeGlyph (*header, bytes).iter ();
+  }
 
   const hb_bytes_t trim_padding () const
   {
@@ -108,25 +120,25 @@
       if (unlikely (!glyph_header)) return false;
     }
 
-    int xMin = 0, xMax = 0;
-    int yMin = 0, yMax = 0;
+    float xMin = 0, xMax = 0;
+    float yMin = 0, yMax = 0;
     if (all_points.length > 4)
     {
-      xMin = xMax = roundf (all_points[0].x);
-      yMin = yMax = roundf (all_points[0].y);
+      xMin = xMax = all_points[0].x;
+      yMin = yMax = all_points[0].y;
     }
 
     for (unsigned i = 1; i < all_points.length - 4; i++)
     {
-      float rounded_x = roundf (all_points[i].x);
-      float rounded_y = roundf (all_points[i].y);
-      xMin = hb_min (xMin, rounded_x);
-      xMax = hb_max (xMax, rounded_x);
-      yMin = hb_min (yMin, rounded_y);
-      yMax = hb_max (yMax, rounded_y);
+      float x = all_points[i].x;
+      float y = all_points[i].y;
+      xMin = hb_min (xMin, x);
+      xMax = hb_max (xMax, x);
+      yMin = hb_min (yMin, y);
+      yMax = hb_max (yMax, y);
     }
 
-    update_mtx (plan, xMin, yMax, all_points);
+    update_mtx (plan, roundf (xMin), roundf (yMax), all_points);
 
     /*for empty glyphs: all_points only include phantom points.
      *just update metrics and then return */
@@ -134,10 +146,10 @@
       return true;
 
     glyph_header->numberOfContours = header->numberOfContours;
-    glyph_header->xMin = xMin;
-    glyph_header->yMin = yMin;
-    glyph_header->xMax = xMax;
-    glyph_header->yMax = yMax;
+    glyph_header->xMin = roundf (xMin);
+    glyph_header->yMin = roundf (yMin);
+    glyph_header->xMax = roundf (xMax);
+    glyph_header->yMax = roundf (yMax);
 
     dest_bytes = hb_bytes_t ((const char *)glyph_header, GlyphHeader::static_size);
     return true;
@@ -199,15 +211,24 @@
 		   bool shift_points_hori = true,
 		   bool use_my_metrics = true,
 		   bool phantom_only = false,
+		   hb_array_t<int> coords = hb_array_t<int> (),
 		   unsigned int depth = 0) const
   {
     if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
+
+    if (!coords)
+      coords = hb_array (font->coords, font->num_coords);
+
     contour_point_vector_t stack_points;
     bool inplace = type == SIMPLE && all_points.length == 0;
     /* Load into all_points if it's empty, as an optimization. */
     contour_point_vector_t &points = inplace ? all_points : stack_points;
 
     switch (type) {
+    case SIMPLE:
+      if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
+	return false;
+      break;
     case COMPOSITE:
     {
       /* pseudo component points for each component in composite glyph */
@@ -215,20 +236,25 @@
       if (unlikely (!points.resize (num_points))) return false;
       break;
     }
-    case SIMPLE:
-      if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
-	return false;
+#ifndef HB_NO_VAR_COMPOSITES
+    case VAR_COMPOSITE:
+    {
+      for (auto &item : get_var_composite_iterator ())
+        if (unlikely (!item.get_points (points))) return false;
+    }
+#endif
+    default:
       break;
     }
 
     /* Init phantom points */
     if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
-    hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
+    hb_array_t<contour_point_t> phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
     {
       int lsb = 0;
       int h_delta = glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ?
 		    (int) header->xMin - lsb : 0;
-      int tsb = 0;
+      HB_UNUSED int tsb = 0;
       int v_orig  = (int) header->yMax +
 #ifndef HB_NO_VERTICAL
 		    ((void) glyf_accelerator.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb)
@@ -257,7 +283,9 @@
     }
 
 #ifndef HB_NO_VAR
-    glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ());
+    glyf_accelerator.gvar->apply_deltas_to_points (gid,
+						   coords,
+						   points.as_array ());
 #endif
 
     // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
@@ -283,11 +311,24 @@
       for (auto &item : get_composite_iterator ())
       {
         comp_points.reset ();
+
 	if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
-				       .get_points (font, glyf_accelerator, comp_points,
-						    deltas, shift_points_hori, use_my_metrics, phantom_only, depth + 1)))
+				       .get_points (font,
+						    glyf_accelerator,
+						    comp_points,
+						    deltas,
+						    shift_points_hori,
+						    use_my_metrics,
+						    phantom_only,
+						    coords,
+						    depth + 1)))
 	  return false;
 
+	/* Copy phantom points from component if USE_MY_METRICS flag set */
+	if (use_my_metrics && item.is_use_my_metrics ())
+	  for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
+	    phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
+
 	/* Apply component transformation & translation */
 	item.transform_points (comp_points);
 
@@ -308,20 +349,63 @@
 	  }
 	}
 
-	/* Copy phantom points from component if USE_MY_METRICS flag set */
-	if (use_my_metrics && item.is_use_my_metrics ())
-	  for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
-	    phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
+	all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT));
 
-	all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
+	if (all_points.length > HB_GLYF_MAX_POINTS)
+	  return false;
 
 	comp_index++;
       }
 
       all_points.extend (phantoms);
     } break;
+#ifndef HB_NO_VAR_COMPOSITES
+    case VAR_COMPOSITE:
+    {
+      contour_point_vector_t comp_points;
+      hb_array_t<contour_point_t> points_left = points.as_array ();
+      for (auto &item : get_var_composite_iterator ())
+      {
+	hb_array_t<contour_point_t> record_points = points_left.sub_array (0, item.get_num_points ());
+
+        comp_points.reset ();
+
+	coord_setter_t coord_setter (coords);
+	item.set_variations (coord_setter, record_points);
+
+	if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
+				       .get_points (font,
+						    glyf_accelerator,
+						    comp_points,
+						    deltas,
+						    shift_points_hori,
+						    use_my_metrics,
+						    phantom_only,
+						    coord_setter.get_coords (),
+						    depth + 1)))
+	  return false;
+
+	/* Apply component transformation */
+	item.transform_points (record_points, comp_points);
+
+	/* Copy phantom points from component if USE_MY_METRICS flag set */
+	if (use_my_metrics && item.is_use_my_metrics ())
+	  for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
+	    phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
+
+	all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT));
+
+	if (all_points.length > HB_GLYF_MAX_POINTS)
+	  return false;
+
+	points_left += item.get_num_points ();
+      }
+      all_points.extend (phantoms);
+    } break;
+#endif
     default:
       all_points.extend (phantoms);
+      break;
     }
 
     if (depth == 0 && shift_points_hori) /* Apply at top level */
@@ -360,6 +444,7 @@
     int num_contours = header->numberOfContours;
     if (unlikely (num_contours == 0)) type = EMPTY;
     else if (num_contours > 0) type = SIMPLE;
+    else if (num_contours == -2) type = VAR_COMPOSITE;
     else type = COMPOSITE; /* negative numbers */
   }
 
diff --git a/src/OT/glyf/SimpleGlyph.hh b/src/OT/glyf/SimpleGlyph.hh
index d45f4eb..2b4aa99 100644
--- a/src/OT/glyf/SimpleGlyph.hh
+++ b/src/OT/glyf/SimpleGlyph.hh
@@ -132,8 +132,8 @@
 	if (unlikely (p + 1 > end)) return false;
 	unsigned int repeat_count = *p++;
 	unsigned stop = hb_min (i + repeat_count, count);
-	for (; i < stop;)
-	  points_.arrayZ[i++].flag = flag;
+	for (; i < stop; i++)
+	  points_.arrayZ[i].flag = flag;
       }
     }
     return true;
@@ -223,33 +223,34 @@
       if (value > 0) flag |= same_flag;
       else value = -value;
 
-      coords.push ((uint8_t)value);
+      coords.arrayZ[coords.length++] = (uint8_t) value;
     }
     else
     {
       int16_t val = value;
-      coords.push (val >> 8);
-      coords.push (val & 0xff);
+      coords.arrayZ[coords.length++] = val >> 8;
+      coords.arrayZ[coords.length++] = val & 0xff;
     }
   }
 
   static void encode_flag (uint8_t &flag,
                            uint8_t &repeat,
-                           uint8_t &lastflag,
+                           uint8_t lastflag,
                            hb_vector_t<uint8_t> &flags /* OUT */)
   {
     if (flag == lastflag && repeat != 255)
     {
-      repeat = repeat + 1;
+      repeat++;
       if (repeat == 1)
       {
-        flags.push(flag);
+        /* We know there's room. */
+        flags.arrayZ[flags.length++] = flag;
       }
       else
       {
         unsigned len = flags.length;
-        flags[len-2] = flag | FLAG_REPEAT;
-        flags[len-1] = repeat;
+        flags.arrayZ[len-2] = flag | FLAG_REPEAT;
+        flags.arrayZ[len-1] = repeat;
       }
     }
     else
@@ -257,7 +258,6 @@
       repeat = 0;
       flags.push (flag);
     }
-    lastflag = flag;
   }
 
   bool compile_bytes_with_deltas (const contour_point_vector_t &all_points,
@@ -269,7 +269,6 @@
       dest_bytes = hb_bytes_t ();
       return true;
     }
-    //convert absolute values to relative values
     unsigned num_points = all_points.length - 4;
 
     hb_vector_t<uint8_t> flags, x_coords, y_coords;
@@ -277,23 +276,23 @@
     if (unlikely (!x_coords.alloc (2*num_points))) return false;
     if (unlikely (!y_coords.alloc (2*num_points))) return false;
 
-    uint8_t lastflag = 0, repeat = 0;
-    int prev_x = 0.f, prev_y = 0.f;
-    
+    uint8_t lastflag = 255, repeat = 0;
+    int prev_x = 0, prev_y = 0;
+
     for (unsigned i = 0; i < num_points; i++)
     {
-      uint8_t flag = all_points[i].flag;
+      uint8_t flag = all_points.arrayZ[i].flag;
       flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE;
 
-      float cur_x = roundf (all_points[i].x);
-      float cur_y = roundf (all_points[i].y);
+      int cur_x = roundf (all_points.arrayZ[i].x);
+      int cur_y = roundf (all_points.arrayZ[i].y);
       encode_coord (cur_x - prev_x, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
       encode_coord (cur_y - prev_y, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
-      if (i == 0) lastflag = flag + 1; //make lastflag != flag for the first point
       encode_flag (flag, repeat, lastflag, flags);
 
       prev_x = cur_x;
       prev_y = cur_y;
+      lastflag = flag;
     }
 
     unsigned len_before_instrs = 2 * header.numberOfContours + 2;
@@ -303,29 +302,29 @@
     if (!no_hinting)
       total_len += len_instrs;
 
-    char *p = (char *) hb_calloc (total_len, sizeof (char));
+    char *p = (char *) hb_malloc (total_len);
     if (unlikely (!p)) return false;
 
     const char *src = bytes.arrayZ + GlyphHeader::static_size;
     char *cur = p;
-    memcpy (p, src, len_before_instrs);
+    hb_memcpy (p, src, len_before_instrs);
 
     cur += len_before_instrs;
     src += len_before_instrs;
 
     if (!no_hinting)
     {
-      memcpy (cur, src, len_instrs);
+      hb_memcpy (cur, src, len_instrs);
       cur += len_instrs;
     }
 
-    memcpy (cur, flags.arrayZ, flags.length);
+    hb_memcpy (cur, flags.arrayZ, flags.length);
     cur += flags.length;
 
-    memcpy (cur, x_coords.arrayZ, x_coords.length);
+    hb_memcpy (cur, x_coords.arrayZ, x_coords.length);
     cur += x_coords.length;
 
-    memcpy (cur, y_coords.arrayZ, y_coords.length);
+    hb_memcpy (cur, y_coords.arrayZ, y_coords.length);
 
     dest_bytes = hb_bytes_t (p, total_len);
     return true;
diff --git a/src/OT/glyf/SubsetGlyph.hh b/src/OT/glyf/SubsetGlyph.hh
index 88fc93c..1a0370c 100644
--- a/src/OT/glyf/SubsetGlyph.hh
+++ b/src/OT/glyf/SubsetGlyph.hh
@@ -21,10 +21,18 @@
 
   bool serialize (hb_serialize_context_t *c,
 		  bool use_short_loca,
-		  const hb_subset_plan_t *plan) const
+		  const hb_subset_plan_t *plan,
+		  hb_font_t *font)
   {
     TRACE_SERIALIZE (this);
 
+    if (font)
+    {
+      const OT::glyf_accelerator_t &glyf = *font->face->table.glyf;
+      if (!this->compile_bytes_with_deltas (plan, font, glyf))
+        return_trace (false);
+    }
+
     hb_bytes_t dest_glyph = dest_start.copy (c);
     dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
     unsigned int pad_length = use_short_loca ? padding () : 0;
diff --git a/src/OT/glyf/VarCompositeGlyph.hh b/src/OT/glyf/VarCompositeGlyph.hh
new file mode 100644
index 0000000..0f4c71c
--- /dev/null
+++ b/src/OT/glyf/VarCompositeGlyph.hh
@@ -0,0 +1,353 @@
+#ifndef OT_GLYF_VARCOMPOSITEGLYPH_HH
+#define OT_GLYF_VARCOMPOSITEGLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+#include "coord-setter.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct VarCompositeGlyphRecord
+{
+  protected:
+  enum var_composite_glyph_flag_t
+  {
+    USE_MY_METRICS		= 0x0001,
+    AXIS_INDICES_ARE_SHORT	= 0x0002,
+    UNIFORM_SCALE		= 0x0004,
+    HAVE_TRANSLATE_X		= 0x0008,
+    HAVE_TRANSLATE_Y		= 0x0010,
+    HAVE_ROTATION		= 0x0020,
+    HAVE_SCALE_X		= 0x0040,
+    HAVE_SCALE_Y		= 0x0080,
+    HAVE_SKEW_X			= 0x0100,
+    HAVE_SKEW_Y			= 0x0200,
+    HAVE_TCENTER_X		= 0x0400,
+    HAVE_TCENTER_Y		= 0x0800,
+    GID_IS_24			= 0x1000,
+    AXES_HAVE_VARIATION		= 0x2000,
+  };
+
+  public:
+
+  unsigned int get_size () const
+  {
+    unsigned int size = min_size;
+
+    unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 4 : 3;
+    size += numAxes * axis_width;
+
+    // gid
+    size += 2;
+    if (flags & GID_IS_24)		size += 1;
+
+    if (flags & HAVE_TRANSLATE_X)	size += 2;
+    if (flags & HAVE_TRANSLATE_Y)	size += 2;
+    if (flags & HAVE_ROTATION)		size += 2;
+    if (flags & HAVE_SCALE_X)		size += 2;
+    if (flags & HAVE_SCALE_Y)		size += 2;
+    if (flags & HAVE_SKEW_X)		size += 2;
+    if (flags & HAVE_SKEW_Y)		size += 2;
+    if (flags & HAVE_TCENTER_X)		size += 2;
+    if (flags & HAVE_TCENTER_Y)		size += 2;
+
+    return size;
+  }
+
+  bool has_more () const { return true; }
+
+  bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
+
+  hb_codepoint_t get_gid () const
+  {
+    if (flags & GID_IS_24)
+      return StructAfter<const HBGlyphID24> (numAxes);
+    else
+      return StructAfter<const HBGlyphID16> (numAxes);
+  }
+
+  unsigned get_numAxes () const
+  {
+    return numAxes;
+  }
+
+  unsigned get_num_points () const
+  {
+    unsigned num = 0;
+    if (flags & AXES_HAVE_VARIATION)			num += numAxes;
+    if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))	num++;
+    if (flags & HAVE_ROTATION)				num++;
+    if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y))		num++;
+    if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y))		num++;
+    if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y))	num++;
+    return num;
+  }
+
+  void transform_points (hb_array_t<contour_point_t> record_points,
+			 contour_point_vector_t &points) const
+  {
+    float matrix[4];
+    contour_point_t trans;
+
+    get_transformation_from_points (record_points, matrix, trans);
+
+    points.transform (matrix);
+    points.translate (trans);
+  }
+
+  static inline void transform (float (&matrix)[4], contour_point_t &trans,
+				float (other)[6])
+  {
+    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L268
+    float xx1 = other[0];
+    float xy1 = other[1];
+    float yx1 = other[2];
+    float yy1 = other[3];
+    float dx1 = other[4];
+    float dy1 = other[5];
+    float xx2 = matrix[0];
+    float xy2 = matrix[1];
+    float yx2 = matrix[2];
+    float yy2 = matrix[3];
+    float dx2 = trans.x;
+    float dy2 = trans.y;
+
+    matrix[0] = xx1*xx2 + xy1*yx2;
+    matrix[1] = xx1*xy2 + xy1*yy2;
+    matrix[2] = yx1*xx2 + yy1*yx2;
+    matrix[3] = yx1*xy2 + yy1*yy2;
+    trans.x = xx2*dx1 + yx2*dy1 + dx2;
+    trans.y = xy2*dx1 + yy2*dy1 + dy2;
+  }
+
+  static void translate (float (&matrix)[4], contour_point_t &trans,
+			 float translateX, float translateY)
+  {
+    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L213
+    float other[6] = {1.f, 0.f, 0.f, 1.f, translateX, translateY};
+    transform (matrix, trans, other);
+  }
+
+  static void scale (float (&matrix)[4], contour_point_t &trans,
+		     float scaleX, float scaleY)
+  {
+    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L224
+    float other[6] = {scaleX, 0.f, 0.f, scaleY, 0.f, 0.f};
+    transform (matrix, trans, other);
+  }
+
+  static void rotate (float (&matrix)[4], contour_point_t &trans,
+		      float rotation)
+  {
+    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
+    rotation = rotation * float (M_PI);
+    float c = cosf (rotation);
+    float s = sinf (rotation);
+    float other[6] = {c, s, -s, c, 0.f, 0.f};
+    transform (matrix, trans, other);
+  }
+
+  static void skew (float (&matrix)[4], contour_point_t &trans,
+		    float skewX, float skewY)
+  {
+    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
+    skewX = skewX * float (M_PI);
+    skewY = skewY * float (M_PI);
+    float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f};
+    transform (matrix, trans, other);
+  }
+
+  bool get_points (contour_point_vector_t &points) const
+  {
+    float translateX = 0.f;
+    float translateY = 0.f;
+    float rotation = 0.f;
+    float scaleX = 1.f * (1 << 12);
+    float scaleY = 1.f * (1 << 12);
+    float skewX = 0.f;
+    float skewY = 0.f;
+    float tCenterX = 0.f;
+    float tCenterY = 0.f;
+
+    if (unlikely (!points.resize (points.length + get_num_points ()))) return false;
+
+    unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
+    unsigned axes_size = numAxes * axis_width;
+
+    const F2DOT14 *q = (const F2DOT14 *) (axes_size +
+					  (flags & GID_IS_24 ? 3 : 2) +
+					  &StructAfter<const HBUINT8> (numAxes));
+
+    hb_array_t<contour_point_t> rec_points = points.as_array ().sub_array (points.length - get_num_points ());
+
+    unsigned count = numAxes;
+    if (flags & AXES_HAVE_VARIATION)
+    {
+      for (unsigned i = 0; i < count; i++)
+	rec_points[i].x = *q++;
+      rec_points += count;
+    }
+    else
+      q += count;
+
+    const HBUINT16 *p = (const HBUINT16 *) q;
+
+    if (flags & HAVE_TRANSLATE_X)	translateX = * (const FWORD *) p++;
+    if (flags & HAVE_TRANSLATE_Y)	translateY = * (const FWORD *) p++;
+    if (flags & HAVE_ROTATION)		rotation = * (const F2DOT14 *) p++;
+    if (flags & HAVE_SCALE_X)		scaleX = * (const F4DOT12 *) p++;
+    if (flags & HAVE_SCALE_Y)		scaleY = * (const F4DOT12 *) p++;
+    if (flags & HAVE_SKEW_X)		skewX = * (const F2DOT14 *) p++;
+    if (flags & HAVE_SKEW_Y)		skewY = * (const F2DOT14 *) p++;
+    if (flags & HAVE_TCENTER_X)		tCenterX = * (const FWORD *) p++;
+    if (flags & HAVE_TCENTER_Y)		tCenterY = * (const FWORD *) p++;
+
+    if ((flags & UNIFORM_SCALE) && !(flags & HAVE_SCALE_Y))
+      scaleY = scaleX;
+
+    if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))
+    {
+      rec_points[0].x = translateX;
+      rec_points[0].y = translateY;
+      rec_points++;
+    }
+    if (flags & HAVE_ROTATION)
+    {
+      rec_points[0].x = rotation;
+      rec_points++;
+    }
+    if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y))
+    {
+      rec_points[0].x = scaleX;
+      rec_points[0].y = scaleY;
+      rec_points++;
+    }
+    if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y))
+    {
+      rec_points[0].x = skewX;
+      rec_points[0].y = skewY;
+      rec_points++;
+    }
+    if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y))
+    {
+      rec_points[0].x = tCenterX;
+      rec_points[0].y = tCenterY;
+      rec_points++;
+    }
+    assert (!rec_points);
+
+    return true;
+  }
+
+  void get_transformation_from_points (hb_array_t<contour_point_t> rec_points,
+				       float (&matrix)[4], contour_point_t &trans) const
+  {
+    if (flags & AXES_HAVE_VARIATION)
+      rec_points += numAxes;
+
+    matrix[0] = matrix[3] = 1.f;
+    matrix[1] = matrix[2] = 0.f;
+    trans.init (0.f, 0.f);
+
+    float translateX = 0.f;
+    float translateY = 0.f;
+    float rotation = 0.f;
+    float scaleX = 1.f;
+    float scaleY = 1.f;
+    float skewX = 0.f;
+    float skewY = 0.f;
+    float tCenterX = 0.f;
+    float tCenterY = 0.f;
+
+    if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))
+    {
+      translateX = rec_points[0].x;
+      translateY = rec_points[0].y;
+      rec_points++;
+    }
+    if (flags & HAVE_ROTATION)
+    {
+      rotation = rec_points[0].x / (1 << 14);
+      rec_points++;
+    }
+    if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y))
+    {
+      scaleX = rec_points[0].x / (1 << 12);
+      scaleY = rec_points[0].y / (1 << 12);
+      rec_points++;
+    }
+    if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y))
+    {
+      skewX = rec_points[0].x / (1 << 14);
+      skewY = rec_points[0].y / (1 << 14);
+      rec_points++;
+    }
+    if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y))
+    {
+      tCenterX = rec_points[0].x;
+      tCenterY = rec_points[0].y;
+      rec_points++;
+    }
+    assert (!rec_points);
+
+    translate (matrix, trans, translateX + tCenterX, translateY + tCenterY);
+    rotate (matrix, trans, rotation);
+    scale (matrix, trans, scaleX, scaleY);
+    skew (matrix, trans, -skewX, skewY);
+    translate (matrix, trans, -tCenterX, -tCenterY);
+  }
+
+  void set_variations (coord_setter_t &setter,
+		       hb_array_t<contour_point_t> rec_points) const
+  {
+    bool have_variations = flags & AXES_HAVE_VARIATION;
+    unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
+
+    const HBUINT8  *p = (const HBUINT8 *)  (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24 ? 3 : 2));
+    const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24 ? 3 : 2));
+
+    const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + numAxes) : (HBUINT8 *) (q + numAxes)));
+
+    unsigned count = numAxes;
+    for (unsigned i = 0; i < count; i++)
+    {
+      unsigned axis_index = axis_width == 1 ? (unsigned) *p++ : (unsigned) *q++;
+
+      signed v = have_variations ? rec_points[i].x : *a++;
+
+      v += setter[axis_index];
+      v = hb_clamp (v, -(1<<14), (1<<14));
+      setter[axis_index] = v;
+    }
+  }
+
+  protected:
+  HBUINT16	flags;
+  HBUINT8	numAxes;
+  public:
+  DEFINE_SIZE_MIN (3);
+};
+
+using var_composite_iter_t = composite_iter_tmpl<VarCompositeGlyphRecord>;
+
+struct VarCompositeGlyph
+{
+  const GlyphHeader &header;
+  hb_bytes_t bytes;
+  VarCompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
+    header (header_), bytes (bytes_) {}
+
+  var_composite_iter_t iter () const
+  { return var_composite_iter_t (bytes, &StructAfter<VarCompositeGlyphRecord, GlyphHeader> (header)); }
+
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_VARCOMPOSITEGLYPH_HH */
diff --git a/src/OT/glyf/composite-iter.hh b/src/OT/glyf/composite-iter.hh
new file mode 100644
index 0000000..d05701f
--- /dev/null
+++ b/src/OT/glyf/composite-iter.hh
@@ -0,0 +1,68 @@
+#ifndef OT_GLYF_COMPOSITE_ITER_HH
+#define OT_GLYF_COMPOSITE_ITER_HH
+
+
+#include "../../hb.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+template <typename CompositeGlyphRecord>
+struct composite_iter_tmpl : hb_iter_with_fallback_t<composite_iter_tmpl<CompositeGlyphRecord>,
+						     const CompositeGlyphRecord &>
+{
+  typedef const CompositeGlyphRecord *__item_t__;
+  composite_iter_tmpl (hb_bytes_t glyph_, __item_t__ current_) :
+      glyph (glyph_), current (nullptr), current_size (0)
+  {
+    set_current (current_);
+  }
+
+  composite_iter_tmpl () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
+
+  const CompositeGlyphRecord & __item__ () const { return *current; }
+  bool __more__ () const { return current; }
+  void __next__ ()
+  {
+    if (!current->has_more ()) { current = nullptr; return; }
+
+    set_current (&StructAtOffset<CompositeGlyphRecord> (current, current_size));
+  }
+  composite_iter_tmpl __end__ () const { return composite_iter_tmpl (); }
+  bool operator != (const composite_iter_tmpl& o) const
+  { return current != o.current; }
+
+
+  void set_current (__item_t__ current_)
+  {
+    if (!glyph.check_range (current_, CompositeGlyphRecord::min_size))
+    {
+      current = nullptr;
+      current_size = 0;
+      return;
+    }
+    unsigned size = current_->get_size ();
+    if (!glyph.check_range (current_, size))
+    {
+      current = nullptr;
+      current_size = 0;
+      return;
+    }
+
+    current = current_;
+    current_size = size;
+  }
+
+  private:
+  hb_bytes_t glyph;
+  __item_t__ current;
+  unsigned current_size;
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+#endif /* OT_GLYF_COMPOSITE_ITER_HH */
diff --git a/src/OT/glyf/coord-setter.hh b/src/OT/glyf/coord-setter.hh
new file mode 100644
index 0000000..df64ed5
--- /dev/null
+++ b/src/OT/glyf/coord-setter.hh
@@ -0,0 +1,34 @@
+#ifndef OT_GLYF_COORD_SETTER_HH
+#define OT_GLYF_COORD_SETTER_HH
+
+
+#include "../../hb.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct coord_setter_t
+{
+  coord_setter_t (hb_array_t<int> coords) :
+    coords (coords) {}
+
+  int& operator [] (unsigned idx)
+  {
+    if (coords.length < idx + 1)
+      coords.resize (idx + 1);
+    return coords[idx];
+  }
+
+  hb_array_t<int> get_coords ()
+  { return coords.as_array (); }
+
+  hb_vector_t<int> coords;
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+#endif /* OT_GLYF_COORD_SETTER_HH */
diff --git a/src/OT/glyf/glyf.hh b/src/OT/glyf/glyf.hh
index 5fb32f6..e6e985c 100644
--- a/src/OT/glyf/glyf.hh
+++ b/src/OT/glyf/glyf.hh
@@ -42,11 +42,15 @@
   bool serialize (hb_serialize_context_t *c,
 		  Iterator it,
                   bool use_short_loca,
-		  const hb_subset_plan_t *plan)
+		  const hb_subset_plan_t *plan,
+		  hb_font_t *font)
   {
     TRACE_SERIALIZE (this);
+
     unsigned init_len = c->length ();
-    for (const auto &_ : it) _.serialize (c, use_short_loca, plan);
+    for (auto &_ : it)
+      if (unlikely (!_.serialize (c, use_short_loca, plan, font)))
+        return false;
 
     /* As a special case when all glyph in the font are empty, add a zero byte
      * to the table, so that OTS doesn’t reject it, and to make the table work
@@ -74,10 +78,11 @@
     hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
     _populate_subset_glyphs (c->plan, glyphs);
 
+    hb_font_t *font = nullptr;
     if (!c->plan->pinned_at_default)
     {
-      if (!_compile_subset_glyphs_with_deltas (c->plan, &glyphs))
-        return_trace (false);
+      font = _create_font_for_instancing (c->plan);
+      if (unlikely (!font)) return false;
     }
 
     auto padded_offsets =
@@ -85,11 +90,14 @@
     | hb_map (&glyf_impl::SubsetGlyph::padded_size)
     ;
 
-    unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
-    bool use_short_loca = max_offset < 0x1FFFF;
+    bool use_short_loca = false;
+    if (likely (!c->plan->force_long_loca))
+    {
+      unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
+      use_short_loca = max_offset < 0x1FFFF;
+    }
 
-
-    glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
+    glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan, font);
     if (!use_short_loca) {
       padded_offsets =
           + hb_iter (glyphs)
@@ -97,9 +105,12 @@
           ;
     }
 
-
-    if (!c->plan->pinned_at_default)
+    if (font)
+    {
       _free_compiled_subset_glyphs (&glyphs);
+      hb_font_destroy (font);
+    }
+
     if (unlikely (c->serializer->in_error ())) return_trace (false);
     return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan,
 									       padded_offsets,
@@ -110,9 +121,8 @@
   _populate_subset_glyphs (const hb_subset_plan_t   *plan,
 			   hb_vector_t<glyf_impl::SubsetGlyph> &glyphs /* OUT */) const;
 
-  bool
-  _compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
-                                      hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
+  hb_font_t *
+  _create_font_for_instancing (const hb_subset_plan_t *plan) const;
 
   void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> *glyphs) const
   {
@@ -394,7 +404,11 @@
                   plan->pinned_at_default)
       subset_glyph.source_glyph = glyf_impl::Glyph ();
     else
-      subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
+    {
+      /* If plan has an accelerator, the preprocessing step already trimmed glyphs.
+       * Don't trim them again! */
+      subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, !plan->accelerator);
+    }
 
     if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
       subset_glyph.drop_hints_bytes ();
@@ -403,17 +417,15 @@
   }
 }
 
-inline bool
-glyf::_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
-                                          hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const
+inline hb_font_t *
+glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
 {
-  OT::glyf_accelerator_t glyf (plan->source);
   hb_font_t *font = hb_font_create (plan->source);
-  if (unlikely (!font)) return false;
+  if (unlikely (font == hb_font_get_empty ())) return nullptr;
 
   hb_vector_t<hb_variation_t> vars;
   if (unlikely (!vars.alloc (plan->user_axes_location->get_population ())))
-    return false;
+    return nullptr;
 
   for (auto _ : *plan->user_axes_location)
   {
@@ -423,18 +435,10 @@
     vars.push (var);
   }
 
+#ifndef HB_NO_VAR
   hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ());
-  for (auto& subset_glyph : *glyphs)
-  {
-    if (!const_cast<glyf_impl::SubsetGlyph &> (subset_glyph).compile_bytes_with_deltas (plan, font, glyf))
-    {
-      hb_font_destroy (font);
-      return false;
-    }
-  }
-
-  hb_font_destroy (font);
-  return true;
+#endif
+  return font;
 }
 
 
diff --git a/src/check-symbols.py b/src/check-symbols.py
index 11ca28d..d0b8bd3 100755
--- a/src/check-symbols.py
+++ b/src/check-symbols.py
@@ -31,7 +31,7 @@
 		symprefix = '_' if suffix == 'dylib' else ''
 
 		EXPORTED_SYMBOLS = [s.split ()[2]
-				    for s in re.findall (r'^.+ [BCDGIRST] .+$', subprocess.check_output (nm.split() + [so]).decode ('utf-8'), re.MULTILINE)
+				    for s in re.findall (r'^.+ [BCDGIRSTu] .+$', subprocess.check_output (nm.split() + [so]).decode ('utf-8'), re.MULTILINE)
 				    if not re.match (r'.* %s(%s)\b' % (symprefix, IGNORED_SYMBOLS), s)]
 
 		# run again c++filt also if is available
diff --git a/src/gen-def.py b/src/gen-def.py
index e751f52..9b4efd4 100755
--- a/src/gen-def.py
+++ b/src/gen-def.py
@@ -20,9 +20,7 @@
 	# Move these to harfbuzz-sections.txt when got stable
 	experimental_symbols = \
 """hb_subset_repack_or_fail
-hb_subset_input_pin_axis_location
-hb_subset_input_pin_axis_to_default
-hb_subset_preprocess
+hb_subset_input_override_name_table
 """.splitlines ()
 	symbols = [x for x in symbols if x not in experimental_symbols]
 symbols = "\n".join (symbols)
diff --git a/src/gen-indic-table.py b/src/gen-indic-table.py
index 0ff3ef4..4ef9702 100755
--- a/src/gen-indic-table.py
+++ b/src/gen-indic-table.py
@@ -95,6 +95,7 @@
     'PLACEHOLDER',
     'DOTTEDCIRCLE',
     'RS',
+    'MPst',
     'Repha',
     'Ra',
     'CM',
@@ -168,8 +169,6 @@
   'Vowel'			: 'V',
   'Vowel_Dependent'		: 'M',
   'Vowel_Independent'		: 'V',
-  'Dotted_Circle'		: 'DOTTEDCIRCLE', # Ours, not Unicode's
-  'Ra'				: 'Ra', # Ours, not Unicode's
 }
 position_map = {
   'Not_Applicable'		: 'END',
@@ -240,6 +239,9 @@
   0x0953: 'SM',
   0x0954: 'SM',
 
+  # U+0A40 GURMUKHI VOWEL SIGN II may be preceded by U+0A02 GURMUKHI SIGN BINDI.
+  0x0A40: 'MPst',
+
   # The following act like consonants.
   0x0A72: 'C',
   0x0A73: 'C',
@@ -440,7 +442,7 @@
   indic_data[k] = (new_cat, pos, unicode_data[2][k])
 
 # We only expect position for certain types
-positioned_categories = ('CM', 'SM', 'RS', 'H', 'M')
+positioned_categories = ('CM', 'SM', 'RS', 'H', 'M', 'MPst')
 for k, (cat, pos, block) in indic_data.items():
   if cat not in positioned_categories:
     pos = 'END'
@@ -450,11 +452,12 @@
 
 # Keep in sync with CONSONANT_FLAGS in the shaper
 consonant_categories = ('C', 'CS', 'Ra','CM', 'V', 'PLACEHOLDER', 'DOTTEDCIRCLE')
+matra_categories = ('M', 'MPst')
 smvd_categories = ('SM', 'VD', 'A', 'Symbol')
 for k, (cat, pos, block) in indic_data.items():
   if cat in consonant_categories:
     pos = 'BASE_C'
-  elif cat == 'M':
+  elif cat in matra_categories:
     if block.startswith('Khmer') or block.startswith('Myanmar'):
       cat = position_to_category(pos)
     else:
@@ -634,7 +637,7 @@
 	end = (end-1)//8*8 + 7
 
 	if start != last + 1:
-		if start - last <= 1+16*3:
+		if start - last <= 1+16*2:
 			print_block (None, last+1, start-1, indic_data)
 		else:
 			if last >= 0:
@@ -691,6 +694,6 @@
 print ()
 print ("/* == End of generated table == */")
 
-# Maintain at least 30% occupancy in the table */
-if occupancy < 30:
+# Maintain at least 50% occupancy in the table */
+if occupancy < 50:
 	raise Exception ("Table too sparse, please investigate: ", occupancy)
diff --git a/src/gen-ucd-table.py b/src/gen-ucd-table.py
index f4c099f..d85ae4f 100755
--- a/src/gen-ucd-table.py
+++ b/src/gen-ucd-table.py
@@ -25,14 +25,28 @@
 
 logging.info('Preparing data tables...')
 
+
+# This is how the data is encoded:
+#
+# General_Category (gc), Canonical_Combining_Class (ccc),
+# and Script (sc) are encoded as integers.
+#
+# Mirroring character (bmg) is encoded as difference from
+# the original character.
+#
+# Composition & Decomposition (dm) are encoded elaborately,
+# as discussed below.
+
 gc = [u['gc'] for u in ucd]
 ccc = [int(u['ccc']) for u in ucd]
 bmg = [int(v, 16) - int(u) if v else 0 for u,v in enumerate(u['bmg'] for u in ucd)]
-#gc_ccc_non0 = set((cat,klass) for cat,klass in zip(gc,ccc) if klass)
-#gc_bmg_non0 = set((cat,mirr) for cat,mirr in zip(gc, bmg) if mirr)
-
 sc = [u['sc'] for u in ucd]
 
+
+# Prepare Compose / Decompose data
+#
+# This code is very dense.  See hb_ucd_compose() / hb_ucd_decompose() for the logic.
+
 dm = {i:tuple(int(v, 16) for v in u['dm'].split()) for i,u in enumerate(ucd)
       if u['dm'] != '#' and u['dt'] == 'can' and not (0xAC00 <= i < 0xAC00+11172)}
 ce = {i for i,u in enumerate(ucd) if u['Comp_Ex'] == 'Y'}
@@ -63,6 +77,9 @@
 dm_order.update(dm1_order)
 dm_order.update(dm2_order)
 
+
+# Prepare General_Category / Script mapping arrays
+
 gc_order = dict()
 for i,v in enumerate(('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu',
                       'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf',
@@ -83,10 +100,18 @@
     sc_order[i] = tag
     sc_array.append(name)
 
-DEFAULT = 3
-COMPACT = 5
-SLOPPY  = 9
 
+# Write out main data
+
+DEFAULT = 'DEFAULT'
+COMPACT = 'COMPACT'
+SLOPPY  = 'SLOPPY'
+
+compression_level = {
+    DEFAULT: 5,
+    COMPACT: 9,
+    SLOPPY:  9,
+}
 
 logging.info('Generating output...')
 print("/* == Start of generated table == */")
@@ -104,6 +129,9 @@
 print('#include "hb.hh"')
 print()
 
+
+# Write mapping data
+
 code = packTab.Code('_hb_ucd')
 sc_array, _ = code.addArray('hb_script_t', 'sc_map', sc_array)
 dm1_p0_array, _ = code.addArray('uint16_t', 'dm1_p0_map', dm1_p0_array)
@@ -120,18 +148,24 @@
     ('dm', dm, None, dm_order),
 ]
 
-for compression in (DEFAULT, COMPACT, SLOPPY):
+
+# Write main data
+
+for step in (DEFAULT, COMPACT, SLOPPY):
+    compression = compression_level[step]
     logging.info('  Compression=%d:' % compression)
     print()
-    if compression == DEFAULT:
+    if step == DEFAULT:
         print('#ifndef HB_OPTIMIZE_SIZE')
-    elif compression == COMPACT:
+    elif step == COMPACT:
         print('#elif !defined(HB_NO_UCD_UNASSIGNED)')
-    else:
+    elif step == SLOPPY:
         print('#else')
+    else:
+        assert False
     print()
 
-    if compression == SLOPPY:
+    if step == SLOPPY:
         for i in range(len(gc)):
             if (i % 128) and gc[i] == 'Cn':
                 gc[i] = gc[i - 1]
@@ -157,6 +191,7 @@
 
     print()
 
+
 print('#endif')
 print()
 
diff --git a/src/gen-use-table.py b/src/gen-use-table.py
index 0600a33..e8b76df 100755
--- a/src/gen-use-table.py
+++ b/src/gen-use-table.py
@@ -1,6 +1,9 @@
 #!/usr/bin/env python3
 # flake8: noqa: F821
 
+import logging
+logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
+
 """usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt
 
 Input files:
@@ -465,10 +468,29 @@
 
 import packTab
 data = {u:v[0] for u,v in use_data.items()}
-code = packTab.Code('hb_use')
-sol = packTab.pack_table(data, compression=5, default='O')
-sol.genCode(code, f'get_category')
-code.print_c(linkage='static inline')
+
+DEFAULT = 5
+COMPACT = 9
+for compression in (DEFAULT, COMPACT):
+
+    logging.info('  Compression=%d:' % compression)
+    print()
+    if compression == DEFAULT:
+        print('#ifndef HB_OPTIMIZE_SIZE')
+    elif compression == COMPACT:
+        print('#else')
+    else:
+        assert False
+    print()
+
+    code = packTab.Code('hb_use')
+    sol = packTab.pack_table(data, compression=compression, default='O')
+    logging.info('      FullCost=%d' % (sol.fullCost))
+    sol.genCode(code, f'get_category')
+    code.print_c(linkage='static inline')
+    print ()
+
+print('#endif')
 
 print ()
 for k in sorted(use_mapping.keys()):
diff --git a/src/graph/classdef-graph.hh b/src/graph/classdef-graph.hh
index 0bda76a..c2e24a7 100644
--- a/src/graph/classdef-graph.hh
+++ b/src/graph/classdef-graph.hh
@@ -112,7 +112,7 @@
     {
     case 1: return ((ClassDefFormat1*)this)->sanitize (vertex);
     case 2: return ((ClassDefFormat2*)this)->sanitize (vertex);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     // Not currently supported
     case 3:
     case 4:
diff --git a/src/graph/coverage-graph.hh b/src/graph/coverage-graph.hh
index 3c1022f..49d0936 100644
--- a/src/graph/coverage-graph.hh
+++ b/src/graph/coverage-graph.hh
@@ -136,7 +136,7 @@
     {
     case 1: return ((CoverageFormat1*)this)->sanitize (vertex);
     case 2: return ((CoverageFormat2*)this)->sanitize (vertex);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     // Not currently supported
     case 3:
     case 4:
diff --git a/src/graph/graph.hh b/src/graph/graph.hh
index 79c7e69..dc5b6a3 100644
--- a/src/graph/graph.hh
+++ b/src/graph/graph.hh
@@ -49,6 +49,50 @@
     unsigned end = 0;
     unsigned priority = 0;
 
+
+    bool link_positions_valid (unsigned num_objects, bool removed_nil)
+    {
+      hb_set_t assigned_bytes;
+      for (const auto& l : obj.real_links)
+      {
+        if (l.objidx >= num_objects
+            || (removed_nil && !l.objidx))
+        {
+          DEBUG_MSG (SUBSET_REPACK, nullptr,
+                     "Invalid graph. Invalid object index.");
+          return false;
+        }
+
+        unsigned start = l.position;
+        unsigned end = start + l.width - 1;
+
+        if (unlikely (l.width < 2 || l.width > 4))
+        {
+          DEBUG_MSG (SUBSET_REPACK, nullptr,
+                     "Invalid graph. Invalid link width.");
+          return false;
+        }
+
+        if (unlikely (end >= table_size ()))
+        {
+          DEBUG_MSG (SUBSET_REPACK, nullptr,
+                     "Invalid graph. Link position is out of bounds.");
+          return false;
+        }
+
+        if (unlikely (assigned_bytes.intersects (start, end)))
+        {
+          DEBUG_MSG (SUBSET_REPACK, nullptr,
+                     "Invalid graph. Found offsets whose positions overlap.");
+          return false;
+        }
+
+        assigned_bytes.add_range (start, end);
+      }
+
+      return !assigned_bytes.in_error ();
+    }
+
     void normalize ()
     {
       obj.real_links.qsort ();
@@ -132,7 +176,7 @@
       for (unsigned i = 0; i < parents.length; i++)
       {
         if (parents[i] != parent_index) continue;
-        parents.remove (i);
+        parents.remove_unordered (i);
         break;
       }
     }
@@ -148,7 +192,7 @@
         if ((obj.head + link.position) != offset)
           continue;
 
-        obj.real_links.remove (i);
+        obj.real_links.remove_unordered (i);
         return;
       }
     }
@@ -286,8 +330,6 @@
     vertices_scratch_.alloc (objects.length);
     for (unsigned i = 0; i < objects.length; i++)
     {
-      // TODO(grieger): check all links point to valid objects.
-
       // If this graph came from a serialization buffer object 0 is the
       // nil object. We don't need it for our purposes here so drop it.
       if (i == 0 && !objects[i])
@@ -299,6 +341,9 @@
       vertex_t* v = vertices_.push ();
       if (check_success (!vertices_.in_error ()))
         v->obj = *objects[i];
+
+      check_success (v->link_positions_valid (objects.length, removed_nil));
+
       if (!removed_nil) continue;
       // Fix indices to account for removed nil object.
       for (auto& l : v->obj.all_links_writer ()) {
@@ -418,6 +463,13 @@
       hb_swap (sorted_graph[new_id], vertices_[next_id]);
       const vertex_t& next = sorted_graph[new_id];
 
+      if (unlikely (!check_success(new_id >= 0))) {
+        // We are out of ids. Which means we've visited a node more than once.
+        // This graph contains a cycle which is not allowed.
+        DEBUG_MSG (SUBSET_REPACK, nullptr, "Invalid graph. Contains cycle.");
+        return;
+      }
+
       id_map[next_id] = new_id--;
 
       for (const auto& link : next.obj.all_links ()) {
@@ -580,7 +632,7 @@
 
     while (roots)
     {
-      unsigned next = HB_SET_VALUE_INVALID;
+      uint32_t next = HB_SET_VALUE_INVALID;
       if (unlikely (!check_success (!roots.in_error ()))) break;
       if (!roots.next (&next)) break;
 
@@ -661,8 +713,8 @@
 
     auto new_subgraph =
         + subgraph.keys ()
-        | hb_map([&] (unsigned node_idx) {
-          const unsigned *v;
+        | hb_map([&] (uint32_t node_idx) {
+          const uint32_t *v;
           if (index_map.has (node_idx, &v)) return *v;
           return node_idx;
         })
@@ -672,10 +724,10 @@
     remap_obj_indices (index_map, parents.iter (), true);
 
     // Update roots set with new indices as needed.
-    unsigned next = HB_SET_VALUE_INVALID;
+    uint32_t next = HB_SET_VALUE_INVALID;
     while (roots.next (&next))
     {
-      const unsigned *v;
+      const uint32_t *v;
       if (index_map.has (next, &v))
       {
         roots.del (next);
@@ -690,7 +742,7 @@
   {
     for (const auto& link : vertices_[node_idx].obj.all_links ())
     {
-      const unsigned *v;
+      const uint32_t *v;
       if (subgraph.has (link.objidx, &v))
       {
         subgraph.set (link.objidx, *v + 1);
@@ -941,6 +993,72 @@
     return made_change;
   }
 
+  bool is_fully_connected ()
+  {
+    update_parents();
+
+    if (root().parents)
+      // Root cannot have parents.
+      return false;
+
+    for (unsigned i = 0; i < root_idx (); i++)
+    {
+      if (!vertices_[i].parents)
+        return false;
+    }
+    return true;
+  }
+
+#if 0
+  /*
+   * Saves the current graph to a packed binary format which the repacker fuzzer takes
+   * as a seed.
+   */
+  void save_fuzzer_seed (hb_tag_t tag) const
+  {
+    FILE* f = fopen ("./repacker_fuzzer_seed", "w");
+    fwrite ((void*) &tag, sizeof (tag), 1, f);
+
+    uint16_t num_objects = vertices_.length;
+    fwrite ((void*) &num_objects, sizeof (num_objects), 1, f);
+
+    for (const auto& v : vertices_)
+    {
+      uint16_t blob_size = v.table_size ();
+      fwrite ((void*) &blob_size, sizeof (blob_size), 1, f);
+      fwrite ((const void*) v.obj.head, blob_size, 1, f);
+    }
+
+    uint16_t link_count = 0;
+    for (const auto& v : vertices_)
+      link_count += v.obj.real_links.length;
+
+    fwrite ((void*) &link_count, sizeof (link_count), 1, f);
+
+    typedef struct
+    {
+      uint16_t parent;
+      uint16_t child;
+      uint16_t position;
+      uint8_t width;
+    } link_t;
+
+    for (unsigned i = 0; i < vertices_.length; i++)
+    {
+      for (const auto& l : vertices_[i].obj.real_links)
+      {
+        link_t link {
+          (uint16_t) i, (uint16_t) l.objidx,
+          (uint16_t) l.position, (uint8_t) l.width
+        };
+        fwrite ((void*) &link, sizeof (link), 1, f);
+      }
+    }
+
+    fclose (f);
+  }
+#endif
+
   void print_orphaned_nodes ()
   {
     if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
@@ -949,6 +1067,10 @@
     parents_invalid = true;
     update_parents();
 
+    if (root().parents) {
+      DEBUG_MSG (SUBSET_REPACK, nullptr, "Root node has incoming edges.");
+    }
+
     for (unsigned i = 0; i < root_idx (); i++)
     {
       const auto& v = vertices_[i];
@@ -1065,6 +1187,11 @@
       }
     }
 
+    for (unsigned i = 0; i < vertices_.length; i++)
+      // parents arrays must be accurate or downstream operations like cycle detection
+      // and sorting won't work correctly.
+      check_success (!vertices_[i].parents.in_error ());
+
     parents_invalid = false;
   }
 
@@ -1183,7 +1310,7 @@
     {
       for (auto& link : vertices_[i].obj.all_links_writer ())
       {
-        const unsigned *v;
+        const uint32_t *v;
         if (!id_map.has (link.objidx, &v)) continue;
         if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
 
diff --git a/src/graph/gsubgpos-graph.hh b/src/graph/gsubgpos-graph.hh
index e8d5bef..c170638 100644
--- a/src/graph/gsubgpos-graph.hh
+++ b/src/graph/gsubgpos-graph.hh
@@ -201,7 +201,7 @@
                       + new_subtable_count * OT::Offset16::static_size;
     char* buffer = (char*) hb_calloc (1, new_size);
     c.add_buffer (buffer);
-    memcpy (buffer, v.obj.head, v.table_size());
+    hb_memcpy (buffer, v.obj.head, v.table_size());
 
     v.obj.head = buffer;
     v.obj.tail = buffer + new_size;
@@ -355,7 +355,7 @@
   {
     switch (u.version.major) {
     case 1: return u.version1.get_lookup_list_offset ();
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 2: return u.version2.get_lookup_list_offset ();
 #endif
     default: return 0;
@@ -374,7 +374,7 @@
   {
     switch (u.version.major) {
       case 1: find_lookups<SmallTypes> (graph, lookups); break;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
       case 2: find_lookups<MediumTypes> (graph, lookups); break;
 #endif
     }
diff --git a/src/graph/markbasepos-graph.hh b/src/graph/markbasepos-graph.hh
index e42a604..84ef5f7 100644
--- a/src/graph/markbasepos-graph.hh
+++ b/src/graph/markbasepos-graph.hh
@@ -112,7 +112,7 @@
       auto& child = c.graph.vertices_[child_idx];
       child.remove_parent (this_index);
 
-      o.real_links.remove (i);
+      o.real_links.remove_unordered (i);
       num_links--;
       i--;
     }
@@ -372,7 +372,7 @@
     if (!mark_coverage) return false;
     hb_set_t marks = sc.marks_for (0, count);
     auto new_coverage =
-        + hb_zip (hb_range (), mark_coverage.table->iter ())
+        + hb_enumerate (mark_coverage.table->iter ())
         | hb_filter (marks, hb_first)
         | hb_map_retains_sorting (hb_second)
         ;
@@ -431,7 +431,7 @@
     if (!mark_coverage) return false;
     hb_set_t marks = sc.marks_for (start, end);
     auto new_coverage =
-        + hb_zip (hb_range (), mark_coverage.table->iter ())
+        + hb_enumerate (mark_coverage.table->iter ())
         | hb_filter (marks, hb_first)
         | hb_map_retains_sorting (hb_second)
         ;
@@ -477,7 +477,7 @@
     switch (u.format) {
     case 1:
       return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 2: HB_FALLTHROUGH;
       // Don't split 24bit PairPos's.
 #endif
@@ -494,7 +494,7 @@
     switch (u.format) {
     case 1:
       return ((MarkBasePosFormat1*)(&u.format1))->sanitize (vertex);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 2: HB_FALLTHROUGH;
 #endif
     default:
diff --git a/src/graph/pairpos-graph.hh b/src/graph/pairpos-graph.hh
index 8040778..1c13eb2 100644
--- a/src/graph/pairpos-graph.hh
+++ b/src/graph/pairpos-graph.hh
@@ -434,7 +434,7 @@
 
     char* start_addr = ((char*)&values[0]) + start * split_context.class1_record_size;
     unsigned num_records = end - start;
-    memcpy (&pair_pos_prime->values[0],
+    hb_memcpy (&pair_pos_prime->values[0],
             start_addr,
             num_records * split_context.class1_record_size);
 
@@ -611,7 +611,7 @@
       return ((PairPosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
     case 2:
       return ((PairPosFormat2*)(&u.format2))->split_subtables (c, parent_index, this_index);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 3: HB_FALLTHROUGH;
     case 4: HB_FALLTHROUGH;
       // Don't split 24bit PairPos's.
@@ -631,7 +631,7 @@
       return ((PairPosFormat1*)(&u.format1))->sanitize (vertex);
     case 2:
       return ((PairPosFormat2*)(&u.format2))->sanitize (vertex);
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
     case 3: HB_FALLTHROUGH;
     case 4: HB_FALLTHROUGH;
 #endif
diff --git a/src/graph/serialize.hh b/src/graph/serialize.hh
index ecc6cc5..d03a61b 100644
--- a/src/graph/serialize.hh
+++ b/src/graph/serialize.hh
@@ -33,6 +33,23 @@
 {
   unsigned parent;
   unsigned child;
+
+  bool operator != (const overflow_record_t o) const
+  { return !(*this == o); }
+
+  inline bool operator == (const overflow_record_t& o) const
+  {
+    return parent == o.parent &&
+        child == o.child;
+  }
+
+  inline uint32_t hash () const
+  {
+    uint32_t current = 0;
+    current = current * 31 + hb_hash (parent);
+    current = current * 31 + hb_hash (child);
+    return current;
+  }
 };
 
 inline
@@ -94,6 +111,7 @@
   if (overflows) overflows->resize (0);
   graph.update_positions ();
 
+  hb_hashmap_t<overflow_record_t*, bool> record_set;
   const auto& vertices = graph.vertices_;
   for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--)
   {
@@ -109,7 +127,10 @@
       overflow_record_t r;
       r.parent = parent_idx;
       r.child = link.objidx;
+      if (record_set.has(&r)) continue; // don't keep duplicate overflows.
+
       overflows->push (r);
+      record_set.set(&r, true);
     }
   }
 
@@ -223,7 +244,7 @@
       return nullptr;
     }
 
-    memcpy (start, vertices[i].obj.head, size);
+    hb_memcpy (start, vertices[i].obj.head, size);
 
     // Only real links needs to be serialized.
     for (const auto& link : vertices[i].obj.real_links)
diff --git a/src/harfbuzz-config.cmake.in b/src/harfbuzz-config.cmake.in
index 304410d..0de082c 100644
--- a/src/harfbuzz-config.cmake.in
+++ b/src/harfbuzz-config.cmake.in
@@ -1,29 +1,5 @@
-# Set these variables so that the `${prefix}/lib` expands to something we can
-# remove.
-set(_harfbuzz_remove_string "REMOVE_ME")
-set(exec_prefix "${_harfbuzz_remove_string}")
-set(prefix "${_harfbuzz_remove_string}")
-
-# Compute the installation prefix by stripping components from our current
-# location.
-get_filename_component(_harfbuzz_prefix "${CMAKE_CURRENT_LIST_DIR}" DIRECTORY)
-get_filename_component(_harfbuzz_prefix "${_harfbuzz_prefix}" DIRECTORY)
 set(_harfbuzz_libdir "@libdir@")
-string(REPLACE "${_harfbuzz_remove_string}/" "" _harfbuzz_libdir "${_harfbuzz_libdir}")
-set(_harfbuzz_libdir_iter "${_harfbuzz_libdir}")
-while (_harfbuzz_libdir_iter)
-  set(_harfbuzz_libdir_prev_iter "${_harfbuzz_libdir_iter}")
-  get_filename_component(_harfbuzz_libdir_iter "${_harfbuzz_libdir_iter}" DIRECTORY)
-  if (_harfbuzz_libdir_prev_iter STREQUAL _harfbuzz_libdir_iter)
-    break()
-  endif ()
-  get_filename_component(_harfbuzz_prefix "${_harfbuzz_prefix}" DIRECTORY)
-endwhile ()
-unset(_harfbuzz_libdir_iter)
-
-# Get the include subdir.
 set(_harfbuzz_includedir "@includedir@")
-string(REPLACE "${_harfbuzz_remove_string}/" "" _harfbuzz_includedir "${_harfbuzz_includedir}")
 
 # Extract version information from libtool.
 set(_harfbuzz_version_info "@HB_LIBTOOL_VERSION_INFO@")
@@ -48,29 +24,29 @@
 # Add the libraries.
 add_library(harfbuzz::harfbuzz SHARED IMPORTED)
 set_target_properties(harfbuzz::harfbuzz PROPERTIES
-  INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
-  IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz${_harfbuzz_lib_suffix}")
+  INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
+  IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz${_harfbuzz_lib_suffix}")
 
 add_library(harfbuzz::icu SHARED IMPORTED)
 set_target_properties(harfbuzz::icu PROPERTIES
-  INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
+  INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
   INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
-  IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-icu${_harfbuzz_lib_suffix}")
+  IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-icu${_harfbuzz_lib_suffix}")
 
 add_library(harfbuzz::subset SHARED IMPORTED)
 set_target_properties(harfbuzz::subset PROPERTIES
-  INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
+  INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
   INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
-  IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-subset${_harfbuzz_lib_suffix}")
+  IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-subset${_harfbuzz_lib_suffix}")
 
 # Only add the gobject library if it was built.
 set(_harfbuzz_have_gobject "@have_gobject@")
 if (_harfbuzz_have_gobject)
   add_library(harfbuzz::gobject SHARED IMPORTED)
   set_target_properties(harfbuzz::gobject PROPERTIES
-    INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
+    INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
     INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
-    IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-gobject${_harfbuzz_lib_suffix}")
+    IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-gobject${_harfbuzz_lib_suffix}")
 endif ()
 
 # Clean out variables we used in our scope.
@@ -80,7 +56,3 @@
 unset(_harfbuzz_age)
 unset(_harfbuzz_includedir)
 unset(_harfbuzz_libdir)
-unset(_harfbuzz_prefix)
-unset(exec_prefix)
-unset(prefix)
-unset(_harfbuzz_remove_string)
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index aa4ad4c..8b9190d 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -131,14 +131,14 @@
 	  hb_glyph_info_t *info = buffer->info;
 	  hb_glyph_info_t buf[4];
 
-	  memcpy (buf, info + start, l * sizeof (buf[0]));
-	  memcpy (buf + 2, info + end - r, r * sizeof (buf[0]));
+	  hb_memcpy (buf, info + start, l * sizeof (buf[0]));
+	  hb_memcpy (buf + 2, info + end - r, r * sizeof (buf[0]));
 
 	  if (l != r)
 	    memmove (info + start + r, info + start + l, (end - start - l - r) * sizeof (buf[0]));
 
-	  memcpy (info + start, buf + 2, r * sizeof (buf[0]));
-	  memcpy (info + end - l, buf, l * sizeof (buf[0]));
+	  hb_memcpy (info + start, buf + 2, r * sizeof (buf[0]));
+	  hb_memcpy (info + end - l, buf, l * sizeof (buf[0]));
 	  if (reverse_l)
 	  {
 	    buf[0] = info[end - 1];
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
index d60126f..78427b0 100644
--- a/src/hb-aat-layout.cc
+++ b/src/hb-aat-layout.cc
@@ -289,7 +289,7 @@
 void
 hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
 {
-  hb_ot_layout_delete_glyphs_inplace (buffer, is_deleted_glyph);
+  buffer->delete_glyphs_inplace (is_deleted_glyph);
 }
 
 /**
diff --git a/src/hb-aat-map.hh b/src/hb-aat-map.hh
index c914f58..d0ee7d6 100644
--- a/src/hb-aat-map.hh
+++ b/src/hb-aat-map.hh
@@ -38,7 +38,7 @@
 
   void init ()
   {
-    memset (this, 0, sizeof (*this));
+    hb_memset (this, 0, sizeof (*this));
     chain_flags.init ();
   }
   void fini () { chain_flags.fini (); }
diff --git a/src/hb-algs.hh b/src/hb-algs.hh
index cc37c07..d85a4af 100644
--- a/src/hb-algs.hh
+++ b/src/hb-algs.hh
@@ -236,17 +236,6 @@
   template <typename T> constexpr auto
   impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
 
-  template <typename T> constexpr uint32_t
-  impl (const hb::shared_ptr<T>& v, hb_priority<1>) const
-  {
-    return v.get () ? v.get ()->hash () : 0;
-  }
-  template <typename T> constexpr uint32_t
-  impl (const hb::unique_ptr<T>& v, hb_priority<1>) const
-  {
-    return v.get () ? v.get ()->hash () : 0;
-  }
-
   template <typename T> constexpr auto
   impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
 
@@ -495,6 +484,17 @@
 }
 HB_FUNCOBJ (hb_equal);
 
+struct
+{
+  template <typename T> void
+  operator () (T& a, T& b) const
+  {
+    using std::swap; // allow ADL
+    swap (a, b);
+  }
+}
+HB_FUNCOBJ (hb_swap);
+
 
 template <typename T1, typename T2>
 struct hb_pair_t
@@ -507,7 +507,7 @@
 	    hb_enable_if (std::is_default_constructible<U1>::value &&
 			  std::is_default_constructible<U2>::value)>
   hb_pair_t () : first (), second () {}
-  hb_pair_t (T1 a, T2 b) : first (a), second (b) {}
+  hb_pair_t (T1 a, T2 b) : first (std::forward<T1> (a)), second (std::forward<T2> (b)) {}
 
   template <typename Q1, typename Q2,
 	    hb_enable_if (hb_is_convertible (T1, Q1) &&
@@ -524,6 +524,25 @@
   bool operator > (const pair_t& o) const { return first > o.first || (first == o.first && second > o.second); }
   bool operator <= (const pair_t& o) const { return !(*this > o); }
 
+  static int cmp (const void *pa, const void *pb)
+  {
+    pair_t *a = (pair_t *) pa;
+    pair_t *b = (pair_t *) pb;
+
+    if (a->first < b->first) return -1;
+    if (a->first > b->first) return +1;
+    if (a->second < b->second) return -1;
+    if (a->second > b->second) return +1;
+    return 0;
+  }
+
+  friend void swap (hb_pair_t& a, hb_pair_t& b)
+  {
+    hb_swap (a.first, b.first);
+    hb_swap (a.second, b.second);
+  }
+
+
   T1 first;
   T2 second;
 };
@@ -570,17 +589,6 @@
 }
 HB_FUNCOBJ (hb_clamp);
 
-struct
-{
-  template <typename T> void
-  operator () (T& a, T& b) const
-  {
-    using std::swap; // allow ADL
-    swap (a, b);
-  }
-}
-HB_FUNCOBJ (hb_swap);
-
 /*
  * Bithacks.
  */
@@ -849,19 +857,14 @@
   return (T)(u - lo) <= (T)(hi - lo);
 }
 template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
+hb_in_ranges (T u, T lo1, T hi1)
 {
-  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
+  return hb_in_range (u, lo1, hi1);
 }
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
+template <typename T, typename ...Ts> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, Ts... ds)
 {
-  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
-}
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3, T lo4, T hi4)
-{
-  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3) || hb_in_range (u, lo4, hi4);
+  return hb_in_range<T> (u, lo1, hi1) || hb_in_ranges<T> (u, ds...);
 }
 
 
@@ -869,10 +872,18 @@
  * Overflow checking.
  */
 
-/* Consider __builtin_mul_overflow use here also */
 static inline bool
-hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
+hb_unsigned_mul_overflows (unsigned int count, unsigned int size, unsigned *result = nullptr)
 {
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+  unsigned stack_result;
+  if (!result)
+    result = &stack_result;
+  return __builtin_mul_overflow (count, size, result);
+#endif
+
+  if (result)
+    *result = count * size;
   return (size > 0) && (count >= ((unsigned int) -1) / size);
 }
 
@@ -1164,9 +1175,12 @@
 }
 
 
-template <typename T, typename T2, typename T3> static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2)
+template <typename T, typename T2, typename T3 = int> static inline void
+hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2 = nullptr)
 {
+  static_assert (hb_is_trivially_copy_assignable (T), "");
+  static_assert (hb_is_trivially_copy_assignable (T3), "");
+
   for (unsigned int i = 1; i < len; i++)
   {
     unsigned int j = i;
@@ -1189,12 +1203,6 @@
   }
 }
 
-template <typename T> static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
-{
-  hb_stable_sort (array, len, compar, (int *) nullptr);
-}
-
 static inline hb_bool_t
 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
 {
@@ -1322,47 +1330,4 @@
 HB_FUNCOBJ (hb_dec);
 
 
-/* Compiler-assisted vectorization. */
-
-/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
- * basically a fixed-size bitset. */
-template <typename elt_t, unsigned int byte_size>
-struct hb_vector_size_t
-{
-  elt_t& operator [] (unsigned int i) { return v[i]; }
-  const elt_t& operator [] (unsigned int i) const { return v[i]; }
-
-  void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
-
-  template <typename Op>
-  hb_vector_size_t process (const Op& op) const
-  {
-    hb_vector_size_t r;
-    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
-      r.v[i] = op (v[i]);
-    return r;
-  }
-  template <typename Op>
-  hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const
-  {
-    hb_vector_size_t r;
-    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
-      r.v[i] = op (v[i], o.v[i]);
-    return r;
-  }
-  hb_vector_size_t operator | (const hb_vector_size_t &o) const
-  { return process (hb_bitwise_or, o); }
-  hb_vector_size_t operator & (const hb_vector_size_t &o) const
-  { return process (hb_bitwise_and, o); }
-  hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
-  { return process (hb_bitwise_xor, o); }
-  hb_vector_size_t operator ~ () const
-  { return process (hb_bitwise_neg); }
-
-  private:
-  static_assert (0 == byte_size % sizeof (elt_t), "");
-  elt_t v[byte_size / sizeof (elt_t)];
-};
-
-
 #endif /* HB_ALGS_HH */
diff --git a/src/hb-array.hh b/src/hb-array.hh
index 5884007..17562bc 100644
--- a/src/hb-array.hh
+++ b/src/hb-array.hh
@@ -100,10 +100,18 @@
   /* Ouch. The operator== compares the contents of the array.  For range-based for loops,
    * it's best if we can just compare arrayZ, though comparing contents is still fast,
    * but also would require that Type has operator==.  As such, we optimize this operator
-   * for range-based for loop and just compare arrayZ and length. */
+   * for range-based for loop and just compare arrayZ and length.
+   *
+   * The above comment is outdated now because we implemented separate begin/end to
+   * objects that were using hb_array_t for range-based loop before. */
   bool operator != (const hb_array_t& o) const
   { return this->arrayZ != o.arrayZ || this->length != o.length; }
 
+  /* Faster range-based for loop without bounds-check. */
+  Type *begin () const { return arrayZ; }
+  Type *end () const { return arrayZ + length; }
+
+
   /* Extra operators.
    */
   Type * operator & () const { return arrayZ; }
@@ -112,11 +120,11 @@
 
   HB_INTERNAL bool operator == (const hb_array_t &o) const;
 
-  uint32_t hash () const {
+  uint32_t hash () const
+  {
     uint32_t current = 0;
-    for (unsigned int i = 0; i < this->length; i++) {
-      current = current * 31 + hb_hash (this->arrayZ[i]);
-    }
+    for (auto &v : *this)
+      current = current * 31 + hb_hash (v);
     return current;
   }
 
@@ -184,23 +192,18 @@
 
   hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*))
   {
+    //static_assert (hb_enable_if (hb_is_trivially_copy_assignable(Type)), "");
     if (likely (length))
       hb_qsort (arrayZ, length, this->get_item_size (), cmp_);
     return hb_sorted_array_t<Type> (*this);
   }
   hb_sorted_array_t<Type> qsort ()
   {
+    //static_assert (hb_enable_if (hb_is_trivially_copy_assignable(Type)), "");
     if (likely (length))
       hb_qsort (arrayZ, length, this->get_item_size (), Type::cmp);
     return hb_sorted_array_t<Type> (*this);
   }
-  void qsort (unsigned int start, unsigned int end)
-  {
-    end = hb_min (end, length);
-    assert (start <= end);
-    if (likely (start < end))
-      hb_qsort (arrayZ + start, end - start, this->get_item_size (), Type::cmp);
-  }
 
   /*
    * Other methods.
@@ -262,17 +265,31 @@
   void fini ()
   { hb_free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
 
-  template <typename hb_serialize_context_t>
+  template <typename hb_serialize_context_t,
+	    typename U = Type,
+	    hb_enable_if (!(sizeof (U) < sizeof (long long) && hb_is_trivially_copy_assignable(hb_decay<Type>)))>
   hb_array_t copy (hb_serialize_context_t *c) const
   {
     TRACE_SERIALIZE (this);
     auto* out = c->start_embed (arrayZ);
-    if (unlikely (!c->extend_size (out, get_size ()))) return_trace (hb_array_t ());
+    if (unlikely (!c->extend_size (out, get_size (), false))) return_trace (hb_array_t ());
     for (unsigned i = 0; i < length; i++)
       out[i] = arrayZ[i]; /* TODO: add version that calls c->copy() */
     return_trace (hb_array_t (out, length));
   }
 
+  template <typename hb_serialize_context_t,
+	    typename U = Type,
+	    hb_enable_if (sizeof (U) < sizeof (long long) && hb_is_trivially_copy_assignable(hb_decay<Type>))>
+  hb_array_t copy (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    auto* out = c->start_embed (arrayZ);
+    if (unlikely (!c->extend_size (out, get_size (), false))) return_trace (hb_array_t ());
+    hb_memcpy (out, arrayZ, get_size ());
+    return_trace (hb_array_t (out, length));
+  }
+
   template <typename hb_sanitize_context_t>
   bool sanitize (hb_sanitize_context_t *c) const
   { return c->check_array (arrayZ, length); }
@@ -295,8 +312,8 @@
 
 template <typename Type>
 struct hb_sorted_array_t :
-	hb_iter_t<hb_sorted_array_t<Type>, Type&>,
-	hb_array_t<Type>
+	hb_array_t<Type>,
+	hb_iter_t<hb_sorted_array_t<Type>, Type&>
 {
   typedef hb_iter_t<hb_sorted_array_t, Type&> iter_base_t;
   HB_ITER_USING (iter_base_t);
@@ -316,8 +333,8 @@
   template <typename U,
 	    hb_enable_if (hb_is_cr_convertible(U, Type))>
   constexpr hb_sorted_array_t (const hb_array_t<U> &o) :
-    hb_iter_t<hb_sorted_array_t, Type&> (),
-    hb_array_t<Type> (o) {}
+    hb_array_t<Type> (o),
+    hb_iter_t<hb_sorted_array_t, Type&> () {}
   template <typename U,
 	    hb_enable_if (hb_is_cr_convertible(U, Type))>
   hb_sorted_array_t& operator = (const hb_array_t<U> &o)
@@ -329,6 +346,11 @@
   bool operator != (const hb_sorted_array_t& o) const
   { return this->arrayZ != o.arrayZ || this->length != o.length; }
 
+  /* Faster range-based for loop without bounds-check. */
+  Type *begin () const { return this->arrayZ; }
+  Type *end () const { return this->arrayZ + this->length; }
+
+
   hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
   { return hb_sorted_array_t (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
   hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
@@ -421,18 +443,42 @@
   return 0 == hb_memcmp (arrayZ, o.arrayZ, length);
 }
 
+
+/* Specialize hash() for byte arrays. */
+
 template <>
-inline uint32_t hb_array_t<const char>::hash () const {
+inline uint32_t hb_array_t<const char>::hash () const
+{
   uint32_t current = 0;
-  for (unsigned int i = 0; i < this->length; i++)
-    current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u);
+  unsigned i = 0;
+
+#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
+    ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__))
+  struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
+  for (; i + 4 <= this->length; i += 4)
+    current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v);
+#endif
+
+  for (; i < this->length; i++)
+    current = current * 31 + hb_hash (this->arrayZ[i]);
   return current;
 }
+
 template <>
-inline uint32_t hb_array_t<const unsigned char>::hash () const {
+inline uint32_t hb_array_t<const unsigned char>::hash () const
+{
   uint32_t current = 0;
-  for (unsigned int i = 0; i < this->length; i++)
-    current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u);
+  unsigned i = 0;
+
+#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
+    ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__))
+  struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
+  for (; i + 4 <= this->length; i += 4)
+    current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v);
+#endif
+
+  for (; i < this->length; i++)
+    current = current * 31 + hb_hash (this->arrayZ[i]);
   return current;
 }
 
diff --git a/src/hb-bit-page.hh b/src/hb-bit-page.hh
index 95ae1b7..1198705 100644
--- a/src/hb-bit-page.hh
+++ b/src/hb-bit-page.hh
@@ -30,6 +30,53 @@
 
 #include "hb.hh"
 
+
+/* Compiler-assisted vectorization. */
+
+/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
+ * basically a fixed-size bitset. */
+template <typename elt_t, unsigned int byte_size>
+struct hb_vector_size_t
+{
+  elt_t& operator [] (unsigned int i) { return v[i]; }
+  const elt_t& operator [] (unsigned int i) const { return v[i]; }
+
+  void clear (unsigned char v = 0) { hb_memset (this, v, sizeof (*this)); }
+
+  template <typename Op>
+  hb_vector_size_t process (const Op& op) const
+  {
+    hb_vector_size_t r;
+    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+      r.v[i] = op (v[i]);
+    return r;
+  }
+  template <typename Op>
+  hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const
+  {
+    hb_vector_size_t r;
+    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+      r.v[i] = op (v[i], o.v[i]);
+    return r;
+  }
+  hb_vector_size_t operator | (const hb_vector_size_t &o) const
+  { return process (hb_bitwise_or, o); }
+  hb_vector_size_t operator & (const hb_vector_size_t &o) const
+  { return process (hb_bitwise_and, o); }
+  hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
+  { return process (hb_bitwise_xor, o); }
+  hb_vector_size_t operator ~ () const
+  { return process (hb_bitwise_neg); }
+
+  hb_array_t<const elt_t> iter () const
+  { return hb_array (v); }
+
+  private:
+  static_assert (0 == byte_size % sizeof (elt_t), "");
+  elt_t v[byte_size / sizeof (elt_t)];
+};
+
+
 struct hb_bit_page_t
 {
   void init0 () { v.clear (); }
@@ -40,17 +87,17 @@
 
   bool is_empty () const
   {
-    for (unsigned i = 0; i < len (); i++)
-      if (v[i])
-	return false;
-    return true;
+    return
+    + hb_iter (v)
+    | hb_none
+    ;
   }
   uint32_t hash () const
   {
-    uint32_t h = 0;
-    for (unsigned i = 0; i < len (); i++)
-      h = h * 31 + hb_hash (v[i]);
-    return h;
+    return
+    + hb_iter (v)
+    | hb_reduce ([] (uint32_t h, const elt_t &_) { return h * 31 + hb_hash (_); }, (uint32_t) 0u)
+    ;
   }
 
   void add (hb_codepoint_t g) { elt (g) |= mask (g); }
@@ -69,7 +116,7 @@
       *la |= ~(mask (a) - 1);
       la++;
 
-      memset (la, 0xff, (char *) lb - (char *) la);
+      hb_memset (la, 0xff, (char *) lb - (char *) la);
 
       *lb |= ((mask (b) << 1) - 1);
     }
@@ -85,7 +132,7 @@
       *la &= mask (a) - 1;
       la++;
 
-      memset (la, 0, (char *) lb - (char *) la);
+      hb_memset (la, 0, (char *) lb - (char *) la);
 
       *lb &= ~((mask (b) << 1) - 1);
     }
@@ -101,13 +148,13 @@
 		      hb_codepoint_t *p,
 		      unsigned int    size) const
   {
-    unsigned int start_v = start_value >> ELT_BITS_LOG_2;
+    unsigned int start_v = start_value / ELT_BITS;
     unsigned int start_bit = start_value & ELT_MASK;
     unsigned int count = 0;
     for (unsigned i = start_v; i < len () && count < size; i++)
     {
       elt_t bits = v[i];
-      uint32_t v_base = base | (i << ELT_BITS_LOG_2);
+      uint32_t v_base = base | (i * ELT_BITS);
       for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++)
       {
 	if ((elt_t(1) << j) & bits) {
@@ -132,13 +179,13 @@
 			       unsigned int    size,
 			       hb_codepoint_t *next_value) const
   {
-    unsigned int start_v = start_value >> ELT_BITS_LOG_2;
+    unsigned int start_v = start_value / ELT_BITS;
     unsigned int start_bit = start_value & ELT_MASK;
     unsigned int count = 0;
     for (unsigned i = start_v; i < len () && count < size; i++)
     {
       elt_t bits = v[i];
-      uint32_t v_offset = i << ELT_BITS_LOG_2;
+      uint32_t v_offset = i * ELT_BITS;
       for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++)
       {
 	if ((elt_t(1) << j) & bits)
@@ -161,7 +208,10 @@
 
   bool is_equal (const hb_bit_page_t &other) const
   {
-    return 0 == hb_memcmp (&v, &other.v, sizeof (v));
+    for (unsigned i = 0; i < len (); i++)
+      if (v[i] != other.v[i])
+	return false;
+    return true;
   }
   bool is_subset (const hb_bit_page_t &larger_page) const
   {
@@ -173,10 +223,10 @@
 
   unsigned int get_population () const
   {
-    unsigned int pop = 0;
-    for (unsigned int i = 0; i < len (); i++)
-      pop += hb_popcount (v[i]);
-    return pop;
+    return
+    + hb_iter (v)
+    | hb_reduce ([] (unsigned pop, const elt_t &_) { return pop + hb_popcount (_); }, 0u)
+    ;
   }
 
   bool next (hb_codepoint_t *codepoint) const
@@ -262,8 +312,6 @@
   typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
 
   static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8;
-  static constexpr unsigned ELT_BITS_LOG_2 = 6;
-  static_assert (1 << ELT_BITS_LOG_2 == ELT_BITS, "");
   static constexpr unsigned ELT_MASK = ELT_BITS - 1;
 
   static constexpr unsigned BITS = sizeof (vector_t) * 8;
diff --git a/src/hb-bit-set-invertible.hh b/src/hb-bit-set-invertible.hh
index 27fb073..ff8aecc 100644
--- a/src/hb-bit-set-invertible.hh
+++ b/src/hb-bit-set-invertible.hh
@@ -123,10 +123,8 @@
   bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; }
 
   /* Has interface. */
-  static constexpr bool SENTINEL = false;
-  typedef bool value_t;
-  value_t operator [] (hb_codepoint_t k) const { return get (k); }
-  bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+  bool operator [] (hb_codepoint_t k) const { return get (k); }
+  bool has (hb_codepoint_t k) const { return (*this)[k]; }
   /* Predicate. */
   bool operator () (hb_codepoint_t k) const { return has (k); }
 
diff --git a/src/hb-bit-set.hh b/src/hb-bit-set.hh
index a63887e..8de6e03 100644
--- a/src/hb-bit-set.hh
+++ b/src/hb-bit-set.hh
@@ -85,10 +85,10 @@
   void err () { if (successful) successful = false; } /* TODO Remove */
   bool in_error () const { return !successful; }
 
-  bool resize (unsigned int count)
+  bool resize (unsigned int count, bool clear = true)
   {
     if (unlikely (!successful)) return false;
-    if (unlikely (!pages.resize (count) || !page_map.resize (count)))
+    if (unlikely (!pages.resize (count, clear) || !page_map.resize (count, clear)))
     {
       pages.resize (page_map.length);
       successful = false;
@@ -330,10 +330,8 @@
   }
 
   /* Has interface. */
-  static constexpr bool SENTINEL = false;
-  typedef bool value_t;
-  value_t operator [] (hb_codepoint_t k) const { return get (k); }
-  bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+  bool operator [] (hb_codepoint_t k) const { return get (k); }
+  bool has (hb_codepoint_t k) const { return (*this)[k]; }
   /* Predicate. */
   bool operator () (hb_codepoint_t k) const { return has (k); }
 
@@ -352,7 +350,7 @@
   {
     if (unlikely (!successful)) return;
     unsigned int count = other.pages.length;
-    if (unlikely (!resize (count)))
+    if (unlikely (!resize (count, false)))
       return;
     population = other.population;
 
@@ -391,7 +389,7 @@
   bool is_subset (const hb_bit_set_t &larger_set) const
   {
     if (has_population () && larger_set.has_population () &&
-	population != larger_set.population)
+	population > larger_set.population)
       return false;
 
     uint32_t spi = 0;
@@ -540,21 +538,21 @@
     b = nb;
     for (; a && b; )
     {
-      if (page_map[a - 1].major == other.page_map[b - 1].major)
+      if (page_map.arrayZ[a - 1].major == other.page_map.arrayZ[b - 1].major)
       {
 	a--;
 	b--;
 	count--;
-	page_map[count] = page_map[a];
+	page_map.arrayZ[count] = page_map.arrayZ[a];
 	page_at (count).v = op (page_at (a).v, other.page_at (b).v);
       }
-      else if (page_map[a - 1].major > other.page_map[b - 1].major)
+      else if (page_map.arrayZ[a - 1].major > other.page_map.arrayZ[b - 1].major)
       {
 	a--;
 	if (passthru_left)
 	{
 	  count--;
-	  page_map[count] = page_map[a];
+	  page_map.arrayZ[count] = page_map.arrayZ[a];
 	}
       }
       else
@@ -563,8 +561,8 @@
 	if (passthru_right)
 	{
 	  count--;
-	  page_map[count].major = other.page_map[b].major;
-	  page_map[count].index = next_page++;
+	  page_map.arrayZ[count].major = other.page_map.arrayZ[b].major;
+	  page_map.arrayZ[count].index = next_page++;
 	  page_at (count).v = other.page_at (b).v;
 	}
       }
@@ -574,15 +572,15 @@
       {
 	a--;
 	count--;
-	page_map[count] = page_map [a];
+	page_map.arrayZ[count] = page_map.arrayZ[a];
       }
     if (passthru_right)
       while (b)
       {
 	b--;
 	count--;
-	page_map[count].major = other.page_map[b].major;
-	page_map[count].index = next_page++;
+	page_map.arrayZ[count].major = other.page_map.arrayZ[b].major;
+	page_map.arrayZ[count].index = next_page++;
 	page_at (count).v = other.page_at (b).v;
       }
     assert (!count);
@@ -605,8 +603,6 @@
 
   bool next (hb_codepoint_t *codepoint) const
   {
-    // TODO: this should be merged with prev() as both implementations
-    //       are very similar.
     if (unlikely (*codepoint == INVALID)) {
       *codepoint = get_min ();
       return *codepoint != INVALID;
@@ -640,7 +636,7 @@
 
     for (; i < page_map.length; i++)
     {
-      const page_map_t &current = page_map.arrayZ[i];
+      const page_map_t &current = page_map_array[i];
       hb_codepoint_t m = pages_array[current.index].get_min ();
       if (m != INVALID)
       {
@@ -663,21 +659,21 @@
     page_map_t map = {get_major (*codepoint), 0};
     unsigned int i;
     page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST);
-    if (i < page_map.length && page_map[i].major == map.major)
+    if (i < page_map.length && page_map.arrayZ[i].major == map.major)
     {
-      if (pages[page_map[i].index].previous (codepoint))
+      if (pages[page_map.arrayZ[i].index].previous (codepoint))
       {
-	*codepoint += page_map[i].major * page_t::PAGE_BITS;
+	*codepoint += page_map.arrayZ[i].major * page_t::PAGE_BITS;
 	return true;
       }
     }
     i--;
     for (; (int) i >= 0; i--)
     {
-      hb_codepoint_t m = pages[page_map[i].index].get_max ();
+      hb_codepoint_t m = pages.arrayZ[page_map.arrayZ[i].index].get_max ();
       if (m != INVALID)
       {
-	*codepoint = page_map[i].major * page_t::PAGE_BITS + m;
+	*codepoint = page_map.arrayZ[i].major * page_t::PAGE_BITS + m;
 	return true;
       }
     }
@@ -905,7 +901,7 @@
     {
       auto &cached_page = page_map.arrayZ[i];
       if (cached_page.major == major)
-	return &pages[cached_page.index];
+	return &pages.arrayZ[cached_page.index];
     }
 
     page_map_t map = {major, pages.length};
@@ -917,15 +913,15 @@
       if (unlikely (!resize (pages.length + 1)))
 	return nullptr;
 
-      pages[map.index].init0 ();
-      memmove (page_map + i + 1,
-	       page_map + i,
+      pages.arrayZ[map.index].init0 ();
+      memmove (page_map.arrayZ + i + 1,
+	       page_map.arrayZ + i,
 	       (page_map.length - 1 - i) * page_map.item_size);
       page_map[i] = map;
     }
 
     last_page_lookup = i;
-    return &pages[page_map[i].index];
+    return &pages.arrayZ[page_map.arrayZ[i].index];
   }
   const page_t *page_for (hb_codepoint_t g) const
   {
@@ -939,7 +935,7 @@
     {
       auto &cached_page = page_map.arrayZ[i];
       if (cached_page.major == major)
-	return &pages[cached_page.index];
+	return &pages.arrayZ[cached_page.index];
     }
 
     page_map_t key = {major};
@@ -947,10 +943,18 @@
       return nullptr;
 
     last_page_lookup = i;
-    return &pages[page_map[i].index];
+    return &pages.arrayZ[page_map[i].index];
   }
-  page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
-  const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
+  page_t &page_at (unsigned int i)
+  {
+    assert (i < page_map.length);
+    return pages.arrayZ[page_map.arrayZ[i].index];
+  }
+  const page_t &page_at (unsigned int i) const
+  {
+    assert (i < page_map.length);
+    return pages.arrayZ[page_map.arrayZ[i].index];
+  }
   unsigned int get_major (hb_codepoint_t g) const { return g >> page_t::PAGE_BITS_LOG_2; }
   unsigned int page_remainder (hb_codepoint_t g) const { return g & page_t::PAGE_BITMASK; }
   hb_codepoint_t major_start (unsigned int major) const { return major << page_t::PAGE_BITS_LOG_2; }
diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index 9bc12ea..f0fda1f 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -495,7 +495,7 @@
 
   DEBUG_MSG_FUNC (BLOB, this, "dupped successfully -> %p\n", this->data);
 
-  memcpy (new_data, this->data, this->length);
+  hb_memcpy (new_data, this->data, this->length);
   this->destroy_user_data ();
   this->mode = HB_MEMORY_MODE_WRITABLE;
   this->data = new_data;
diff --git a/src/hb-buffer-deserialize-json.hh b/src/hb-buffer-deserialize-json.hh
index 8709585..993bb1f 100644
--- a/src/hb-buffer-deserialize-json.hh
+++ b/src/hb-buffer-deserialize-json.hh
@@ -32,7 +32,7 @@
 #include "hb.hh"
 
 
-#line 36 "hb-buffer-deserialize-json.hh"
+#line 33 "hb-buffer-deserialize-json.hh"
 static const unsigned char _deserialize_json_trans_keys[] = {
 	0u, 0u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 
 	48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 
@@ -557,12 +557,12 @@
   hb_glyph_info_t info = {0};
   hb_glyph_position_t pos = {0};
   
-#line 561 "hb-buffer-deserialize-json.hh"
+#line 554 "hb-buffer-deserialize-json.hh"
 	{
 	cs = deserialize_json_start;
 	}
 
-#line 566 "hb-buffer-deserialize-json.hh"
+#line 557 "hb-buffer-deserialize-json.hh"
 	{
 	int _slen;
 	int _trans;
@@ -590,8 +590,8 @@
 	case 1:
 #line 38 "hb-buffer-deserialize-json.rl"
 	{
-	memset (&info, 0, sizeof (info));
-	memset (&pos , 0, sizeof (pos ));
+	hb_memset (&info, 0, sizeof (info));
+	hb_memset (&pos , 0, sizeof (pos ));
 }
 	break;
 	case 5:
@@ -774,7 +774,7 @@
 	*end_ptr = p;
 }
 	break;
-#line 778 "hb-buffer-deserialize-json.hh"
+#line 735 "hb-buffer-deserialize-json.hh"
 	}
 
 _again:
diff --git a/src/hb-buffer-deserialize-json.rl b/src/hb-buffer-deserialize-json.rl
index d5e3c13..d6fbfe8 100644
--- a/src/hb-buffer-deserialize-json.rl
+++ b/src/hb-buffer-deserialize-json.rl
@@ -36,8 +36,8 @@
 write data;
 
 action clear_item {
-	memset (&info, 0, sizeof (info));
-	memset (&pos , 0, sizeof (pos ));
+	hb_memset (&info, 0, sizeof (info));
+	hb_memset (&pos , 0, sizeof (pos ));
 }
 
 action add_item {
diff --git a/src/hb-buffer-deserialize-text.hh b/src/hb-buffer-deserialize-text.hh
index 9062610..6b9b428 100644
--- a/src/hb-buffer-deserialize-text.hh
+++ b/src/hb-buffer-deserialize-text.hh
@@ -32,32 +32,30 @@
 #include "hb.hh"
 
 
-#line 36 "hb-buffer-deserialize-text.hh"
+#line 33 "hb-buffer-deserialize-text.hh"
 static const unsigned char _deserialize_text_trans_keys[] = {
-	0u, 0u, 9u, 91u, 85u, 85u, 43u, 43u, 48u, 102u, 9u, 85u, 48u, 57u, 45u, 57u, 
-	48u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 
-	44u, 57u, 43u, 124u, 45u, 57u, 48u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u, 
+	0u, 0u, 9u, 91u, 85u, 85u, 43u, 43u, 48u, 102u, 9u, 85u, 48u, 57u, 48u, 57u, 
+	45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 
+	45u, 57u, 48u, 57u, 44u, 57u, 43u, 124u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u, 
 	9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 
 	9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 
-	9u, 124u, 9u, 124u, 9u, 124u, 0
+	0
 };
 
 static const char _deserialize_text_key_spans[] = {
-	0, 83, 1, 1, 55, 77, 10, 13, 
-	10, 10, 10, 13, 10, 1, 13, 10, 
-	14, 82, 13, 10, 116, 116, 0, 77, 
+	0, 83, 1, 1, 55, 77, 10, 10, 
+	13, 10, 13, 10, 10, 13, 10, 1, 
+	13, 10, 14, 82, 116, 116, 0, 77, 
 	116, 116, 116, 116, 116, 116, 116, 116, 
-	116, 116, 116, 116, 116, 116, 116, 116, 
-	116, 116, 116
+	116, 116, 116, 116, 116, 116, 116, 116
 };
 
 static const short _deserialize_text_index_offsets[] = {
 	0, 0, 84, 86, 88, 144, 222, 233, 
-	247, 258, 269, 280, 294, 305, 307, 321, 
-	332, 347, 430, 444, 455, 572, 689, 690, 
+	244, 258, 269, 283, 294, 305, 319, 330, 
+	332, 346, 357, 372, 455, 572, 689, 690, 
 	768, 885, 1002, 1119, 1236, 1353, 1470, 1587, 
-	1704, 1821, 1938, 2055, 2172, 2289, 2406, 2523, 
-	2640, 2757, 2874
+	1704, 1821, 1938, 2055, 2172, 2289, 2406, 2523
 };
 
 static const char _deserialize_text_indicies[] = {
@@ -90,34 +88,34 @@
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 4, 1, 8, 
 	9, 9, 9, 9, 9, 9, 9, 9, 
-	9, 1, 10, 1, 1, 11, 12, 12, 
-	12, 12, 12, 12, 12, 12, 12, 1, 
+	9, 1, 10, 11, 11, 11, 11, 11, 
+	11, 11, 11, 11, 1, 12, 1, 1, 
 	13, 14, 14, 14, 14, 14, 14, 14, 
 	14, 14, 1, 15, 16, 16, 16, 16, 
-	16, 16, 16, 16, 16, 1, 17, 18, 
-	18, 18, 18, 18, 18, 18, 18, 18, 
-	1, 19, 1, 1, 20, 21, 21, 21, 
+	16, 16, 16, 16, 16, 1, 17, 1, 
+	1, 18, 19, 19, 19, 19, 19, 19, 
+	19, 19, 19, 1, 20, 21, 21, 21, 
 	21, 21, 21, 21, 21, 21, 1, 22, 
 	23, 23, 23, 23, 23, 23, 23, 23, 
-	23, 1, 24, 1, 25, 1, 1, 26, 
-	27, 27, 27, 27, 27, 27, 27, 27, 
-	27, 1, 28, 29, 29, 29, 29, 29, 
-	29, 29, 29, 29, 1, 24, 1, 1, 
-	1, 23, 23, 23, 23, 23, 23, 23, 
-	23, 23, 23, 1, 30, 30, 1, 1, 
+	23, 1, 24, 1, 1, 25, 26, 26, 
+	26, 26, 26, 26, 26, 26, 26, 1, 
+	27, 28, 28, 28, 28, 28, 28, 28, 
+	28, 28, 1, 29, 1, 30, 1, 1, 
+	31, 32, 32, 32, 32, 32, 32, 32, 
+	32, 32, 1, 33, 34, 34, 34, 34, 
+	34, 34, 34, 34, 34, 1, 29, 1, 
+	1, 1, 28, 28, 28, 28, 28, 28, 
+	28, 28, 28, 28, 1, 35, 35, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 30, 1, 
-	1, 30, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 35, 
+	1, 1, 35, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 30, 30, 1, 
+	1, 1, 1, 1, 1, 1, 35, 35, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 30, 1, 31, 
-	1, 1, 32, 33, 33, 33, 33, 33, 
-	33, 33, 33, 33, 1, 34, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 1, 
+	1, 1, 1, 1, 1, 1, 35, 1, 
 	36, 36, 36, 36, 36, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 36, 
@@ -201,53 +199,24 @@
 	48, 48, 48, 48, 48, 48, 48, 48, 
 	48, 48, 48, 48, 48, 48, 48, 48, 
 	48, 48, 48, 48, 48, 48, 56, 48, 
-	57, 57, 57, 57, 57, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 57, 
-	30, 30, 58, 30, 30, 30, 30, 30, 
-	30, 30, 59, 1, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 60, 30, 30, 61, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 62, 63, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 64, 30, 57, 57, 57, 
-	57, 57, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 57, 30, 30, 58, 
-	30, 30, 30, 30, 30, 30, 30, 59, 
-	1, 30, 30, 30, 65, 66, 66, 66, 
-	66, 66, 66, 66, 66, 66, 30, 30, 
-	30, 60, 30, 30, 61, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	62, 63, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	64, 30, 67, 67, 67, 67, 67, 1, 
+	57, 57, 57, 57, 57, 35, 35, 35, 
+	35, 35, 35, 35, 35, 35, 35, 35, 
+	35, 35, 35, 35, 35, 35, 35, 57, 
+	35, 35, 58, 35, 35, 35, 35, 35, 
+	35, 35, 59, 1, 35, 35, 35, 35, 
+	35, 35, 35, 35, 35, 35, 35, 35, 
+	35, 35, 35, 35, 60, 35, 35, 61, 
+	35, 35, 35, 35, 35, 35, 35, 35, 
+	35, 35, 35, 35, 35, 35, 35, 35, 
+	35, 35, 35, 35, 35, 35, 35, 35, 
+	35, 35, 35, 62, 63, 35, 35, 35, 
+	35, 35, 35, 35, 35, 35, 35, 35, 
+	35, 35, 35, 35, 35, 35, 35, 35, 
+	35, 35, 35, 35, 35, 35, 35, 35, 
+	35, 35, 35, 64, 35, 65, 65, 65, 
+	65, 65, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 67, 1, 1, 68, 1, 1, 1, 
-	1, 1, 1, 1, 1, 69, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 70, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 71, 1, 72, 
-	72, 72, 72, 72, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 72, 1, 
+	1, 1, 1, 1, 65, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
@@ -255,228 +224,210 @@
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 42, 1, 1, 1, 1, 
+	1, 66, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 73, 1, 74, 74, 74, 74, 
-	74, 48, 48, 48, 48, 48, 48, 48, 
+	67, 1, 68, 68, 68, 68, 68, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 68, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 42, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 69, 1, 70, 
+	70, 70, 70, 70, 48, 48, 48, 48, 
 	48, 48, 48, 48, 48, 48, 48, 48, 
-	48, 48, 48, 74, 48, 48, 50, 48, 
-	48, 48, 48, 48, 48, 48, 51, 1, 
+	48, 48, 48, 48, 48, 48, 70, 48, 
+	48, 50, 48, 48, 48, 48, 48, 48, 
+	48, 51, 1, 48, 48, 48, 48, 48, 
+	48, 48, 48, 48, 48, 48, 48, 48, 
+	48, 48, 48, 52, 48, 48, 53, 48, 
 	48, 48, 48, 48, 48, 48, 48, 48, 
 	48, 48, 48, 48, 48, 48, 48, 48, 
-	52, 48, 48, 53, 48, 48, 48, 48, 
+	48, 48, 48, 48, 48, 48, 48, 48, 
+	48, 48, 54, 55, 48, 48, 48, 48, 
 	48, 48, 48, 48, 48, 48, 48, 48, 
 	48, 48, 48, 48, 48, 48, 48, 48, 
-	48, 48, 48, 48, 48, 48, 48, 54, 
-	55, 48, 48, 48, 48, 48, 48, 48, 
 	48, 48, 48, 48, 48, 48, 48, 48, 
-	48, 48, 48, 48, 48, 48, 48, 48, 
-	48, 48, 48, 48, 48, 48, 48, 56, 
-	48, 75, 75, 75, 75, 75, 1, 1, 
+	48, 48, 56, 48, 71, 71, 71, 71, 
+	71, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	75, 1, 1, 76, 1, 1, 1, 1, 
-	1, 1, 1, 77, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	78, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 45, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 79, 1, 80, 80, 
-	80, 80, 80, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 80, 1, 1, 
+	1, 1, 1, 71, 1, 1, 72, 1, 
+	1, 1, 1, 1, 1, 1, 1, 73, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
+	74, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 75, 
+	1, 76, 76, 76, 76, 76, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	76, 1, 1, 77, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 78, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 79, 1, 76, 76, 
+	76, 76, 76, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 76, 1, 1, 
+	77, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 21, 21, 21, 
+	21, 21, 21, 21, 21, 21, 21, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 78, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 79, 1, 71, 71, 71, 71, 71, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 71, 1, 1, 72, 1, 1, 
+	1, 1, 1, 1, 1, 1, 73, 1, 
+	1, 1, 16, 16, 16, 16, 16, 16, 
+	16, 16, 16, 16, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 74, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 75, 1, 
+	80, 80, 80, 80, 80, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 80, 
 	1, 1, 81, 1, 1, 1, 1, 1, 
+	1, 1, 82, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 83, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 82, 1, 80, 80, 80, 80, 80, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 80, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 83, 83, 83, 83, 83, 83, 
-	83, 83, 83, 83, 1, 1, 1, 1, 
+	1, 1, 1, 1, 45, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 81, 
+	1, 1, 1, 84, 1, 85, 85, 85, 
+	85, 85, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 82, 1, 
-	84, 84, 84, 84, 84, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 84, 
-	1, 1, 85, 1, 1, 1, 1, 1, 
-	1, 1, 86, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 85, 1, 1, 86, 
+	1, 1, 1, 1, 1, 1, 1, 87, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 88, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	89, 1, 85, 85, 85, 85, 85, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 85, 1, 1, 86, 1, 1, 1, 
 	1, 1, 1, 1, 87, 1, 1, 1, 
+	1, 34, 34, 34, 34, 34, 34, 34, 
+	34, 34, 34, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 88, 1, 84, 84, 84, 
-	84, 84, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 88, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 84, 1, 1, 85, 
-	1, 1, 1, 1, 1, 1, 1, 86, 
-	1, 1, 1, 1, 29, 29, 29, 29, 
-	29, 29, 29, 29, 29, 29, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 89, 1, 80, 
+	80, 80, 80, 80, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 80, 1, 
+	1, 81, 1, 1, 1, 1, 1, 1, 
+	1, 82, 1, 1, 1, 1, 90, 90, 
+	90, 90, 90, 90, 90, 90, 90, 90, 
+	1, 1, 1, 1, 1, 1, 83, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 45, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 84, 1, 65, 65, 65, 65, 
+	65, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 65, 1, 1, 1, 1, 
+	1, 1, 1, 1, 1, 1, 1, 1, 
+	1, 1, 1, 91, 91, 91, 91, 91, 
+	91, 91, 91, 91, 91, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 87, 1, 1, 1, 1, 1, 1, 
+	66, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	88, 1, 75, 75, 75, 75, 75, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 75, 1, 1, 76, 1, 1, 1, 
-	1, 1, 1, 1, 77, 1, 1, 1, 
-	1, 89, 89, 89, 89, 89, 89, 89, 
-	89, 89, 89, 1, 1, 1, 1, 1, 
-	1, 78, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 45, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 79, 1, 90, 
-	90, 90, 90, 90, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 90, 1, 
-	1, 91, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 92, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 93, 1, 90, 90, 90, 90, 
-	90, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 90, 1, 1, 91, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	92, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 93, 
-	1, 67, 67, 67, 67, 67, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	67, 1, 1, 68, 1, 1, 1, 1, 
-	1, 1, 1, 1, 69, 1, 1, 1, 
-	14, 14, 14, 14, 14, 14, 14, 14, 
-	14, 14, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 70, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 71, 1, 94, 94, 
-	94, 94, 94, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 94, 30, 30, 
-	58, 30, 30, 30, 30, 30, 30, 30, 
-	59, 1, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 60, 30, 30, 61, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 62, 95, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 96, 30, 94, 94, 94, 94, 94, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 94, 30, 30, 58, 30, 30, 
-	30, 30, 30, 30, 30, 59, 1, 30, 
-	30, 30, 97, 97, 97, 97, 97, 97, 
-	97, 97, 97, 97, 30, 30, 30, 60, 
-	30, 30, 61, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 62, 95, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 30, 30, 
-	30, 30, 30, 30, 30, 30, 96, 30, 
-	0
+	1, 1, 1, 1, 1, 1, 1, 67, 
+	1, 0
 };
 
 static const char _deserialize_text_trans_targs[] = {
 	1, 0, 2, 26, 3, 4, 20, 5, 
-	24, 25, 8, 29, 40, 29, 40, 32, 
-	37, 33, 34, 12, 13, 16, 13, 16, 
-	14, 15, 35, 36, 35, 36, 27, 19, 
-	38, 39, 38, 39, 21, 20, 6, 22, 
+	24, 25, 28, 39, 9, 31, 34, 31, 
+	34, 11, 32, 33, 32, 33, 35, 38, 
+	14, 15, 18, 15, 18, 16, 17, 36, 
+	37, 36, 37, 27, 21, 20, 6, 22, 
 	23, 21, 22, 23, 21, 22, 23, 25, 
-	27, 27, 28, 7, 9, 11, 17, 22, 
-	31, 27, 28, 7, 9, 11, 17, 22, 
-	31, 41, 42, 30, 10, 18, 22, 31, 
-	30, 31, 31, 30, 10, 7, 11, 31, 
-	30, 22, 31, 34, 30, 10, 7, 22, 
-	31, 37, 30, 10, 22, 31, 27, 22, 
-	31, 42
+	27, 27, 7, 8, 12, 13, 19, 22, 
+	30, 27, 7, 8, 12, 13, 19, 22, 
+	30, 29, 22, 30, 29, 30, 30, 29, 
+	7, 10, 22, 30, 29, 7, 22, 30, 
+	29, 7, 8, 13, 30, 29, 7, 8, 
+	22, 30, 38, 39
 };
 
 static const char _deserialize_text_trans_actions[] = {
 	0, 0, 0, 0, 1, 0, 2, 0, 
-	2, 2, 3, 4, 4, 5, 5, 4, 
-	4, 4, 4, 3, 3, 3, 0, 0, 
-	6, 3, 4, 4, 5, 5, 5, 3, 
-	4, 4, 5, 5, 7, 8, 9, 7, 
+	2, 2, 3, 3, 4, 3, 3, 5, 
+	5, 4, 3, 3, 5, 5, 3, 3, 
+	4, 4, 4, 0, 0, 6, 4, 3, 
+	3, 5, 5, 5, 7, 8, 9, 7, 
 	7, 0, 0, 0, 10, 10, 10, 8, 
-	12, 13, 14, 15, 15, 15, 16, 11, 
-	11, 18, 19, 20, 20, 20, 0, 17, 
-	17, 4, 4, 21, 22, 22, 21, 21, 
-	0, 0, 13, 10, 23, 23, 23, 10, 
-	24, 24, 24, 5, 25, 26, 26, 25, 
-	25, 5, 27, 28, 27, 27, 30, 29, 
-	29, 5
+	12, 13, 14, 14, 14, 14, 15, 11, 
+	11, 17, 18, 18, 18, 18, 0, 16, 
+	16, 19, 19, 19, 0, 0, 13, 20, 
+	21, 21, 20, 20, 22, 23, 22, 22, 
+	10, 24, 24, 24, 10, 25, 26, 26, 
+	25, 25, 5, 5
 };
 
 static const char _deserialize_text_eof_actions[] = {
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 7, 0, 0, 0, 
-	10, 10, 11, 17, 17, 21, 0, 11, 
-	10, 24, 24, 25, 25, 10, 27, 27, 
-	21, 29, 29
+	10, 10, 11, 16, 19, 0, 11, 20, 
+	22, 22, 20, 10, 25, 25, 10, 19
 };
 
 static const int deserialize_text_start = 1;
@@ -509,12 +460,12 @@
   hb_glyph_info_t info = {0};
   hb_glyph_position_t pos = {0};
   
-#line 513 "hb-buffer-deserialize-text.hh"
+#line 457 "hb-buffer-deserialize-text.hh"
 	{
 	cs = deserialize_text_start;
 	}
 
-#line 518 "hb-buffer-deserialize-text.hh"
+#line 460 "hb-buffer-deserialize-text.hh"
 	{
 	int _slen;
 	int _trans;
@@ -542,11 +493,11 @@
 	case 1:
 #line 38 "hb-buffer-deserialize-text.rl"
 	{
-	memset (&info, 0, sizeof (info));
-	memset (&pos , 0, sizeof (pos ));
+	hb_memset (&info, 0, sizeof (info));
+	hb_memset (&pos , 0, sizeof (pos ));
 }
 	break;
-	case 3:
+	case 4:
 #line 51 "hb-buffer-deserialize-text.rl"
 	{
 	tok = p;
@@ -560,7 +511,7 @@
 #line 56 "hb-buffer-deserialize-text.rl"
 	{ if (unlikely (!buffer->ensure_unicode ())) return false; }
 	break;
-	case 20:
+	case 18:
 #line 58 "hb-buffer-deserialize-text.rl"
 	{
 	/* TODO Unescape delimiters. */
@@ -574,7 +525,7 @@
 #line 66 "hb-buffer-deserialize-text.rl"
 	{if (!parse_hex (tok, p, &info.codepoint )) return false; }
 	break;
-	case 23:
+	case 24:
 #line 68 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
 	break;
@@ -586,26 +537,26 @@
 #line 70 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
 	break;
-	case 22:
+	case 21:
 #line 71 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
 	break;
-	case 28:
+	case 23:
 #line 72 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
 	break;
-	case 16:
+	case 15:
 #line 38 "hb-buffer-deserialize-text.rl"
 	{
-	memset (&info, 0, sizeof (info));
-	memset (&pos , 0, sizeof (pos ));
+	hb_memset (&info, 0, sizeof (info));
+	hb_memset (&pos , 0, sizeof (pos ));
 }
 #line 51 "hb-buffer-deserialize-text.rl"
 	{
 	tok = p;
 }
 	break;
-	case 4:
+	case 3:
 #line 51 "hb-buffer-deserialize-text.rl"
 	{
 	tok = p;
@@ -621,7 +572,7 @@
 #line 56 "hb-buffer-deserialize-text.rl"
 	{ if (unlikely (!buffer->ensure_unicode ())) return false; }
 	break;
-	case 17:
+	case 16:
 #line 58 "hb-buffer-deserialize-text.rl"
 	{
 	/* TODO Unescape delimiters. */
@@ -639,18 +590,6 @@
 	*end_ptr = p;
 }
 	break;
-	case 19:
-#line 58 "hb-buffer-deserialize-text.rl"
-	{
-	/* TODO Unescape delimiters. */
-	if (!hb_font_glyph_from_string (font,
-					tok, p - tok,
-					&info.codepoint))
-	  return false;
-}
-#line 55 "hb-buffer-deserialize-text.rl"
-	{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
-	break;
 	case 7:
 #line 66 "hb-buffer-deserialize-text.rl"
 	{if (!parse_hex (tok, p, &info.codepoint )) return false; }
@@ -687,7 +626,7 @@
 	*end_ptr = p;
 }
 	break;
-	case 21:
+	case 20:
 #line 71 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
 #line 43 "hb-buffer-deserialize-text.rl"
@@ -699,7 +638,7 @@
 	*end_ptr = p;
 }
 	break;
-	case 27:
+	case 22:
 #line 72 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
 #line 43 "hb-buffer-deserialize-text.rl"
@@ -711,7 +650,7 @@
 	*end_ptr = p;
 }
 	break;
-	case 24:
+	case 19:
 #line 73 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_uint (tok, p, &info.mask    )) return false; }
 #line 43 "hb-buffer-deserialize-text.rl"
@@ -726,8 +665,8 @@
 	case 12:
 #line 38 "hb-buffer-deserialize-text.rl"
 	{
-	memset (&info, 0, sizeof (info));
-	memset (&pos , 0, sizeof (pos ));
+	hb_memset (&info, 0, sizeof (info));
+	hb_memset (&pos , 0, sizeof (pos ));
 }
 #line 51 "hb-buffer-deserialize-text.rl"
 	{
@@ -736,11 +675,11 @@
 #line 55 "hb-buffer-deserialize-text.rl"
 	{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
 	break;
-	case 15:
+	case 14:
 #line 38 "hb-buffer-deserialize-text.rl"
 	{
-	memset (&info, 0, sizeof (info));
-	memset (&pos , 0, sizeof (pos ));
+	hb_memset (&info, 0, sizeof (info));
+	hb_memset (&pos , 0, sizeof (pos ));
 }
 #line 51 "hb-buffer-deserialize-text.rl"
 	{
@@ -755,7 +694,7 @@
 	  return false;
 }
 	break;
-	case 18:
+	case 17:
 #line 58 "hb-buffer-deserialize-text.rl"
 	{
 	/* TODO Unescape delimiters. */
@@ -775,31 +714,11 @@
 	*end_ptr = p;
 }
 	break;
-	case 29:
-#line 58 "hb-buffer-deserialize-text.rl"
-	{
-	/* TODO Unescape delimiters. */
-	if (!hb_font_glyph_from_string (font,
-					tok, p - tok,
-					&info.codepoint))
-	  return false;
-}
-#line 73 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_uint (tok, p, &info.mask    )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
-	{
-	buffer->add_info (info);
-	if (unlikely (!buffer->successful))
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
 	case 11:
 #line 38 "hb-buffer-deserialize-text.rl"
 	{
-	memset (&info, 0, sizeof (info));
-	memset (&pos , 0, sizeof (pos ));
+	hb_memset (&info, 0, sizeof (info));
+	hb_memset (&pos , 0, sizeof (pos ));
 }
 #line 51 "hb-buffer-deserialize-text.rl"
 	{
@@ -822,54 +741,11 @@
 	*end_ptr = p;
 }
 	break;
-	case 14:
-#line 38 "hb-buffer-deserialize-text.rl"
-	{
-	memset (&info, 0, sizeof (info));
-	memset (&pos , 0, sizeof (pos ));
-}
-#line 51 "hb-buffer-deserialize-text.rl"
-	{
-	tok = p;
-}
-#line 58 "hb-buffer-deserialize-text.rl"
-	{
-	/* TODO Unescape delimiters. */
-	if (!hb_font_glyph_from_string (font,
-					tok, p - tok,
-					&info.codepoint))
-	  return false;
-}
-#line 55 "hb-buffer-deserialize-text.rl"
-	{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
-	break;
-	case 30:
-#line 58 "hb-buffer-deserialize-text.rl"
-	{
-	/* TODO Unescape delimiters. */
-	if (!hb_font_glyph_from_string (font,
-					tok, p - tok,
-					&info.codepoint))
-	  return false;
-}
-#line 73 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_uint (tok, p, &info.mask    )) return false; }
-#line 55 "hb-buffer-deserialize-text.rl"
-	{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
-	{
-	buffer->add_info (info);
-	if (unlikely (!buffer->successful))
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
 	case 13:
 #line 38 "hb-buffer-deserialize-text.rl"
 	{
-	memset (&info, 0, sizeof (info));
-	memset (&pos , 0, sizeof (pos ));
+	hb_memset (&info, 0, sizeof (info));
+	hb_memset (&pos , 0, sizeof (pos ));
 }
 #line 51 "hb-buffer-deserialize-text.rl"
 	{
@@ -894,7 +770,7 @@
 	*end_ptr = p;
 }
 	break;
-#line 898 "hb-buffer-deserialize-text.hh"
+#line 715 "hb-buffer-deserialize-text.hh"
 	}
 
 _again:
@@ -906,7 +782,7 @@
 	if ( p == eof )
 	{
 	switch ( _deserialize_text_eof_actions[cs] ) {
-	case 17:
+	case 16:
 #line 58 "hb-buffer-deserialize-text.rl"
 	{
 	/* TODO Unescape delimiters. */
@@ -960,7 +836,7 @@
 	*end_ptr = p;
 }
 	break;
-	case 21:
+	case 20:
 #line 71 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
 #line 43 "hb-buffer-deserialize-text.rl"
@@ -972,7 +848,7 @@
 	*end_ptr = p;
 }
 	break;
-	case 27:
+	case 22:
 #line 72 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
 #line 43 "hb-buffer-deserialize-text.rl"
@@ -984,27 +860,7 @@
 	*end_ptr = p;
 }
 	break;
-	case 24:
-#line 73 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_uint (tok, p, &info.mask    )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
-	{
-	buffer->add_info (info);
-	if (unlikely (!buffer->successful))
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 29:
-#line 58 "hb-buffer-deserialize-text.rl"
-	{
-	/* TODO Unescape delimiters. */
-	if (!hb_font_glyph_from_string (font,
-					tok, p - tok,
-					&info.codepoint))
-	  return false;
-}
+	case 19:
 #line 73 "hb-buffer-deserialize-text.rl"
 	{ if (!parse_uint (tok, p, &info.mask    )) return false; }
 #line 43 "hb-buffer-deserialize-text.rl"
@@ -1019,8 +875,8 @@
 	case 11:
 #line 38 "hb-buffer-deserialize-text.rl"
 	{
-	memset (&info, 0, sizeof (info));
-	memset (&pos , 0, sizeof (pos ));
+	hb_memset (&info, 0, sizeof (info));
+	hb_memset (&pos , 0, sizeof (pos ));
 }
 #line 51 "hb-buffer-deserialize-text.rl"
 	{
@@ -1043,7 +899,7 @@
 	*end_ptr = p;
 }
 	break;
-#line 1047 "hb-buffer-deserialize-text.hh"
+#line 825 "hb-buffer-deserialize-text.hh"
 	}
 	}
 
diff --git a/src/hb-buffer-deserialize-text.rl b/src/hb-buffer-deserialize-text.rl
index 0f33eb8..f82d5ab 100644
--- a/src/hb-buffer-deserialize-text.rl
+++ b/src/hb-buffer-deserialize-text.rl
@@ -36,8 +36,8 @@
 write data;
 
 action clear_item {
-	memset (&info, 0, sizeof (info));
-	memset (&pos , 0, sizeof (pos ));
+	hb_memset (&info, 0, sizeof (info));
+	hb_memset (&pos , 0, sizeof (pos ));
 }
 
 action add_item {
@@ -76,7 +76,7 @@
 num	= '-'? unum;
 
 glyph_id = unum;
-glyph_name = ([^\\\]=@+,|] | '\\' [\\\]=@+,|]) *;
+glyph_name = ([^\\\]=@+,#|] | '\\' [\\\]=@+,|]) *;
 
 glyph	= (glyph_id | glyph_name) >tok %parse_glyph;
 cluster	= '=' (unum >tok %parse_cluster);
diff --git a/src/hb-buffer-serialize.cc b/src/hb-buffer-serialize.cc
index d1e1775..a458f23 100644
--- a/src/hb-buffer-serialize.cc
+++ b/src/hb-buffer-serialize.cc
@@ -183,7 +183,7 @@
     unsigned int l = p - b;
     if (buf_size > l)
     {
-      memcpy (buf, b, l);
+      hb_memcpy (buf, b, l);
       buf += l;
       buf_size -= l;
       *buf_consumed += l;
@@ -241,7 +241,7 @@
     unsigned int l = p - b;
     if (buf_size > l)
     {
-      memcpy (buf, b, l);
+      hb_memcpy (buf, b, l);
       buf += l;
       buf_size -= l;
       *buf_consumed += l;
@@ -329,7 +329,7 @@
     unsigned int l = p - b;
     if (buf_size > l)
     {
-      memcpy (buf, b, l);
+      hb_memcpy (buf, b, l);
       buf += l;
       buf_size -= l;
       *buf_consumed += l;
@@ -381,7 +381,7 @@
     unsigned int l = p - b;
     if (buf_size > l)
     {
-      memcpy (buf, b, l);
+      hb_memcpy (buf, b, l);
       buf += l;
       buf_size -= l;
       *buf_consumed += l;
diff --git a/src/hb-buffer-verify.cc b/src/hb-buffer-verify.cc
index 5453e1c..1cd52b3 100644
--- a/src/hb-buffer-verify.cc
+++ b/src/hb-buffer-verify.cc
@@ -186,7 +186,7 @@
 
   bool ret = true;
   hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
-  if (diff)
+  if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
   {
     buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed.");
     ret = false;
@@ -313,7 +313,6 @@
 
   bool ret = true;
   hb_buffer_diff_flags_t diff;
-
   /*
    * Shape the two fragment streams.
    */
@@ -382,7 +381,7 @@
    * Diff results.
    */
   diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
-  if (diff)
+  if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
   {
     buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed.");
     ret = false;
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 57a5ae0..4b6c2d9 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -172,12 +172,13 @@
   while (size >= new_allocated)
     new_allocated += (new_allocated >> 1) + 32;
 
-  static_assert ((sizeof (info[0]) == sizeof (pos[0])), "");
-  if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]))))
+  unsigned new_bytes;
+  if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]), &new_bytes)))
     goto done;
 
-  new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_allocated * sizeof (pos[0]));
-  new_info = (hb_glyph_info_t *) hb_realloc (info, new_allocated * sizeof (info[0]));
+  static_assert (sizeof (info[0]) == sizeof (pos[0]), "");
+  new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_bytes);
+  new_info = (hb_glyph_info_t *) hb_realloc (info, new_bytes);
 
 done:
   if (unlikely (!new_pos || !new_info))
@@ -208,7 +209,7 @@
     assert (have_output);
 
     out_info = (hb_glyph_info_t *) pos;
-    memcpy (out_info, info, out_len * sizeof (out_info[0]));
+    hb_memcpy (out_info, info, out_len * sizeof (out_info[0]));
   }
 
   return true;
@@ -229,7 +230,7 @@
      * Ideally, we should at least set Default_Ignorable bits on
      * these, as well as consistent cluster values.  But the former
      * is layering violation... */
-    memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
+    hb_memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
   }
   len += count;
   idx += count;
@@ -298,8 +299,8 @@
   out_len = 0;
   out_info = info;
 
-  memset (context, 0, sizeof context);
-  memset (context_len, 0, sizeof context_len);
+  hb_memset (context, 0, sizeof context);
+  hb_memset (context_len, 0, sizeof context_len);
 
   deallocate_var_all ();
   serial = 0;
@@ -313,15 +314,14 @@
   serial = 0;
   shaping_failed = false;
   scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
-  if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR)))
+  unsigned mul;
+  if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR, &mul)))
   {
-    max_len = hb_max (len * HB_BUFFER_MAX_LEN_FACTOR,
-		      (unsigned) HB_BUFFER_MAX_LEN_MIN);
+    max_len = hb_max (mul, (unsigned) HB_BUFFER_MAX_LEN_MIN);
   }
-  if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR)))
+  if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR, &mul)))
   {
-    max_ops = hb_max (len * HB_BUFFER_MAX_OPS_FACTOR,
-		      (unsigned) HB_BUFFER_MAX_OPS_MIN);
+    max_ops = hb_max (mul, (unsigned) HB_BUFFER_MAX_OPS_MIN);
   }
 }
 void
@@ -345,7 +345,7 @@
 
   glyph = &info[len];
 
-  memset (glyph, 0, sizeof (*glyph));
+  hb_memset (glyph, 0, sizeof (*glyph));
   glyph->codepoint = codepoint;
   glyph->mask = 0;
   glyph->cluster = cluster;
@@ -606,6 +606,53 @@
 }
 
 void
+hb_buffer_t::delete_glyphs_inplace (bool (*filter) (const hb_glyph_info_t *info))
+{
+  /* Merge clusters and delete filtered glyphs.
+   * NOTE! We can't use out-buffer as we have positioning data. */
+  unsigned int j = 0;
+  unsigned int count = len;
+  for (unsigned int i = 0; i < count; i++)
+  {
+    if (filter (&info[i]))
+    {
+      /* Merge clusters.
+       * Same logic as delete_glyph(), but for in-place removal. */
+
+      unsigned int cluster = info[i].cluster;
+      if (i + 1 < count && cluster == info[i + 1].cluster)
+	continue; /* Cluster survives; do nothing. */
+
+      if (j)
+      {
+	/* Merge cluster backward. */
+	if (cluster < info[j - 1].cluster)
+	{
+	  unsigned int mask = info[i].mask;
+	  unsigned int old_cluster = info[j - 1].cluster;
+	  for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
+	    set_cluster (info[k - 1], cluster, mask);
+	}
+	continue;
+      }
+
+      if (i + 1 < count)
+	merge_clusters (i, i + 2); /* Merge cluster forward. */
+
+      continue;
+    }
+
+    if (j != i)
+    {
+      info[j] = info[i];
+      pos[j] = pos[i];
+    }
+    j++;
+  }
+  len = j;
+}
+
+void
 hb_buffer_t::guess_segment_properties ()
 {
   assert_unicode ();
@@ -933,7 +980,6 @@
 void
 hb_buffer_set_direction (hb_buffer_t    *buffer,
 			 hb_direction_t  direction)
-
 {
   if (unlikely (hb_object_is_immutable (buffer)))
     return;
@@ -1385,9 +1431,9 @@
 
   /* Wipe the new space */
   if (length > buffer->len) {
-    memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
+    hb_memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
     if (buffer->have_positions)
-      memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
+      hb_memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
   }
 
   buffer->len = length;
@@ -1795,7 +1841,9 @@
  * marks at stat of run.
  *
  * This function does not check the validity of @text, it is up to the caller
- * to ensure it contains a valid Unicode code points.
+ * to ensure it contains a valid Unicode scalar values.  In contrast,
+ * hb_buffer_add_utf32() can be used that takes similar input but performs
+ * sanity-check on the input.
  *
  * Since: 0.9.31
  **/
@@ -1858,9 +1906,9 @@
 
   hb_segment_properties_overlay (&buffer->props, &source->props);
 
-  memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
+  hb_memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
   if (buffer->have_positions)
-    memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
+    hb_memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
 
   if (source->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE)
   {
@@ -2048,7 +2096,7 @@
       result |= HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH;
     if (buf_info->cluster != ref_info->cluster)
       result |= HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH;
-    if ((buf_info->mask & ~ref_info->mask & HB_GLYPH_FLAG_DEFINED))
+    if ((buf_info->mask ^ ref_info->mask) & HB_GLYPH_FLAG_DEFINED)
       result |= HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH;
     if (contains && ref_info->codepoint == dottedcircle_glyph)
       result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT;
@@ -2103,6 +2151,13 @@
 			    hb_buffer_message_func_t func,
 			    void *user_data, hb_destroy_func_t destroy)
 {
+  if (unlikely (hb_object_is_immutable (buffer)))
+  {
+    if (destroy)
+      destroy (user_data);
+    return;
+  }
+
   if (buffer->message_destroy)
     buffer->message_destroy (buffer->message_data);
 
diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh
index 26c3f0f..bb1efe9 100644
--- a/src/hb-buffer.hh
+++ b/src/hb-buffer.hh
@@ -32,6 +32,7 @@
 
 #include "hb.hh"
 #include "hb-unicode.hh"
+#include "hb-set-digest.hh"
 
 
 #ifndef HB_BUFFER_MAX_LEN_FACTOR
@@ -207,6 +208,14 @@
   hb_glyph_info_t &prev ()      { return out_info[out_len ? out_len - 1 : 0]; }
   hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
 
+  hb_set_digest_t digest () const
+  {
+    hb_set_digest_t d;
+    d.init ();
+    d.add_array (&info[0].codepoint, len, sizeof (info[0]));
+    return d;
+  }
+
   HB_INTERNAL void similar (const hb_buffer_t &src);
   HB_INTERNAL void reset ();
   HB_INTERNAL void clear ();
@@ -402,6 +411,8 @@
   HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
   /* Merge clusters for deleting current glyph, and skip it. */
   HB_INTERNAL void delete_glyph ();
+  HB_INTERNAL void delete_glyphs_inplace (bool (*filter) (const hb_glyph_info_t *info));
+
 
 
   /* Adds glyph flags in mask to infos with clusters between start and end.
diff --git a/src/hb-cache.hh b/src/hb-cache.hh
index 897f313..f8c8108 100644
--- a/src/hb-cache.hh
+++ b/src/hb-cache.hh
@@ -46,7 +46,7 @@
 					  >::type;
 
   static_assert ((key_bits >= cache_bits), "");
-  static_assert ((key_bits + value_bits - cache_bits <= 8 * sizeof (item_t)), "");
+  static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), "");
 
   void init () { clear (); }
   void fini () {}
diff --git a/src/hb-cff-interp-common.hh b/src/hb-cff-interp-common.hh
index 5c2cb06..49805a8 100644
--- a/src/hb-cff-interp-common.hh
+++ b/src/hb-cff-interp-common.hh
@@ -284,65 +284,56 @@
 /* A byte string associated with the current offset and an error condition */
 struct byte_str_ref_t
 {
-  byte_str_ref_t () { init (); }
-
-  void init ()
-  {
-    str = hb_ubytes_t ();
-    offset = 0;
-    error = false;
-  }
-
-  void fini () {}
+  byte_str_ref_t ()
+    : str () {}
 
   byte_str_ref_t (const hb_ubytes_t &str_, unsigned int offset_ = 0)
-    : str (str_), offset (offset_), error (false) {}
+    : str (str_) { set_offset (offset_); }
 
   void reset (const hb_ubytes_t &str_, unsigned int offset_ = 0)
   {
     str = str_;
-    offset = offset_;
-    error = false;
+    set_offset (offset_);
   }
 
   const unsigned char& operator [] (int i) {
-    if (unlikely ((unsigned int) (offset + i) >= str.length))
+    if (unlikely ((unsigned int) (get_offset () + i) >= str.length))
     {
       set_error ();
       return Null (unsigned char);
     }
-    return str[offset + i];
+    return str.arrayZ[get_offset () + i];
   }
 
+  unsigned char head_unchecked () const { return str.arrayZ[get_offset ()]; }
+
   /* Conversion to hb_ubytes_t */
-  operator hb_ubytes_t () const { return str.sub_array (offset, str.length - offset); }
+  operator hb_ubytes_t () const { return str.sub_array (get_offset ()); }
 
   hb_ubytes_t sub_array (unsigned int offset_, unsigned int len_) const
   { return str.sub_array (offset_, len_); }
 
   bool avail (unsigned int count=1) const
-  { return (!in_error () && offset + count <= str.length); }
+  { return get_offset () + count <= str.length; }
   void inc (unsigned int count=1)
   {
-    if (likely (!in_error () && (offset <= str.length) && (offset + count <= str.length)))
-    {
-      offset += count;
-    }
-    else
-    {
-      offset = str.length;
-      set_error ();
-    }
+    /* Automatically puts us in error if count is out-of-range. */
+    set_offset (get_offset () + count);
   }
 
-  void set_error ()      { error = true; }
-  bool in_error () const { return error; }
+  /* We (ab)use ubytes backwards_length as a cursor (called offset),
+   * as well as to store error condition. */
 
-  hb_ubytes_t       str;
-  unsigned int  offset; /* beginning of the sub-string within str */
+  unsigned get_offset () const { return str.backwards_length; }
+  void set_offset (unsigned offset) { str.backwards_length = offset; }
+
+  void set_error ()      { str.backwards_length = str.length + 1; }
+  bool in_error () const { return str.backwards_length > str.length; }
+
+  unsigned total_size () const { return str.length; }
 
   protected:
-  bool	  error;
+  hb_ubytes_t       str;
 };
 
 using byte_str_array_t = hb_vector_t<hb_ubytes_t>;
@@ -491,8 +482,15 @@
 /* an operator prefixed by its operands in a byte string */
 struct op_str_t
 {
-  hb_ubytes_t str;
+  /* This used to have a hb_ubytes_t. Using a pointer and length
+   * in a particular order, saves 8 bytes in this struct and more
+   * in our parsed_cs_op_t subclass. */
+
+  const unsigned char *ptr = nullptr;
+
   op_code_t  op;
+
+  uint8_t length = 0;
 };
 
 /* base of OP_SERIALIZER */
@@ -503,9 +501,11 @@
   {
     TRACE_SERIALIZE (this);
 
-    HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
+    unsigned char *d = c->allocate_size<unsigned char> (opstr.length);
     if (unlikely (!d)) return_trace (false);
-    memcpy (d, &opstr.str[0], opstr.str.length);
+    /* Faster than hb_memcpy for small strings. */
+    for (unsigned i = 0; i < opstr.length; i++)
+      d[i] = opstr.ptr[i];
     return_trace (true);
   }
 };
@@ -529,16 +529,20 @@
   {
     VAL *val = values.push ();
     val->op = op;
-    val->str = str_ref.str.sub_array (opStart, str_ref.offset - opStart);
-    opStart = str_ref.offset;
+    auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
+    val->ptr = arr.arrayZ;
+    val->length = arr.length;
+    opStart = str_ref.get_offset ();
   }
 
   void add_op (op_code_t op, const byte_str_ref_t& str_ref, const VAL &v)
   {
     VAL *val = values.push (v);
     val->op = op;
-    val->str = str_ref.sub_array ( opStart, str_ref.offset - opStart);
-    opStart = str_ref.offset;
+    auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
+    val->ptr = arr.arrayZ;
+    val->length = arr.length;
+    opStart = str_ref.get_offset ();
   }
 
   bool has_op (op_code_t op) const
@@ -549,8 +553,7 @@
   }
 
   unsigned get_count () const { return values.length; }
-  const VAL &get_value (unsigned int i)   const { return values[i]; }
-  const VAL &operator [] (unsigned int i) const { return get_value (i); }
+  const VAL &operator [] (unsigned int i) const { return values[i]; }
 
   unsigned int       opStart;
   hb_vector_t<VAL>   values;
@@ -565,23 +568,23 @@
     str_ref.reset (str_);
   }
   bool in_error () const
-  { return error || str_ref.in_error () || argStack.in_error (); }
+  { return str_ref.in_error () || argStack.in_error (); }
 
-  void set_error () { error = true; }
+  void set_error () { str_ref.set_error (); }
 
   op_code_t fetch_op ()
   {
     op_code_t  op = OpCode_Invalid;
     if (unlikely (!str_ref.avail ()))
       return OpCode_Invalid;
-    op = (op_code_t)(unsigned char)str_ref[0];
+    op = (op_code_t) str_ref.head_unchecked ();
+    str_ref.inc ();
     if (op == OpCode_escape) {
       if (unlikely (!str_ref.avail ()))
 	return OpCode_Invalid;
-      op = Make_OpCode_ESC(str_ref[1]);
+      op = Make_OpCode_ESC (str_ref.head_unchecked ());
       str_ref.inc ();
     }
-    str_ref.inc ();
     return op;
   }
 
@@ -596,8 +599,6 @@
 		str_ref;
   arg_stack_t<ARG>
 		argStack;
-  protected:
-  bool		error = false;
 };
 
 using num_interp_env_t =  interp_env_t<>;
diff --git a/src/hb-cff2-interp-cs.hh b/src/hb-cff2-interp-cs.hh
index d0b9e7b..00c2580 100644
--- a/src/hb-cff2-interp-cs.hh
+++ b/src/hb-cff2-interp-cs.hh
@@ -40,13 +40,15 @@
   void set_real (double v) { reset_blends (); number_t::set_real (v); }
 
   void set_blends (unsigned int numValues_, unsigned int valueIndex_,
-		   unsigned int numBlends, hb_array_t<const blend_arg_t> blends_)
+		   hb_array_t<const blend_arg_t> blends_)
   {
     numValues = numValues_;
     valueIndex = valueIndex_;
-    deltas.resize (numBlends);
+    unsigned numBlends = blends_.length;
+    if (unlikely (!deltas.resize (numBlends)))
+      return;
     for (unsigned int i = 0; i < numBlends; i++)
-      deltas[i] = blends_[i];
+      deltas.arrayZ[i] = blends_.arrayZ[i];
   }
 
   bool blending () const { return deltas.length > 0; }
@@ -61,7 +63,6 @@
   hb_vector_t<number_t> deltas;
 };
 
-typedef interp_env_t<blend_arg_t> BlendInterpEnv;
 typedef biased_subrs_t<CFF2Subrs>   cff2_biased_subrs_t;
 
 template <typename ELEM>
@@ -154,8 +155,9 @@
     {
       if (likely (scalars.length == deltas.length))
       {
-	for (unsigned int i = 0; i < scalars.length; i++)
-	  v += (double) scalars[i] * deltas[i].to_real ();
+        unsigned count = scalars.length;
+	for (unsigned i = 0; i < count; i++)
+	  v += (double) scalars.arrayZ[i] * deltas.arrayZ[i].to_real ();
       }
     }
     return v;
@@ -220,7 +222,7 @@
 				 const hb_array_t<const ELEM> blends,
 				 unsigned n, unsigned i)
   {
-    arg.set_blends (n, i, blends.length, blends);
+    arg.set_blends (n, i, blends);
   }
   template <typename T = ELEM,
 	    hb_enable_if (!hb_is_same (T, blend_arg_t))>
diff --git a/src/hb-common.cc b/src/hb-common.cc
index bbb6cd5..e9f9cfe 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -285,7 +285,7 @@
     lang = (hb_language_t) hb_malloc(len);
     if (likely (lang))
     {
-      memcpy((unsigned char *) lang, s, len);
+      hb_memcpy((unsigned char *) lang, s, len);
       for (unsigned char *p = (unsigned char *) lang; *p; p++)
 	*p = canon_map[*p];
     }
@@ -379,7 +379,7 @@
     /* NUL-terminate it. */
     char strbuf[64];
     len = hb_min (len, (int) sizeof (strbuf) - 1);
-    memcpy (strbuf, str, len);
+    hb_memcpy (strbuf, str, len);
     strbuf[len] = '\0';
     item = lang_find_or_insert (strbuf);
   }
@@ -976,7 +976,7 @@
   }
 
   if (feature)
-    memset (feature, 0, sizeof (*feature));
+    hb_memset (feature, 0, sizeof (*feature));
   return false;
 }
 
@@ -1025,7 +1025,7 @@
   }
   assert (len < ARRAY_LENGTH (s));
   len = hb_min (len, size - 1);
-  memcpy (buf, s, len);
+  hb_memcpy (buf, s, len);
   buf[len] = '\0';
 }
 
@@ -1088,7 +1088,7 @@
   }
 
   if (variation)
-    memset (variation, 0, sizeof (*variation));
+    hb_memset (variation, 0, sizeof (*variation));
   return false;
 }
 
@@ -1136,7 +1136,7 @@
 /**
  * hb_variation_to_string:
  * @variation: an #hb_variation_t to convert
- * @buf: (array length=size) (out): output string
+ * @buf: (array length=size) (out caller-allocates): output string
  * @size: the allocated size of @buf
  *
  * Converts an #hb_variation_t into a `NULL`-terminated string in the format
@@ -1166,7 +1166,7 @@
 
   assert (len < ARRAY_LENGTH (s));
   len = hb_min (len, size - 1);
-  memcpy (buf, s, len);
+  hb_memcpy (buf, s, len);
   buf[len] = '\0';
 }
 
diff --git a/src/hb-config.hh b/src/hb-config.hh
index d56617f..98b1e9d 100644
--- a/src/hb-config.hh
+++ b/src/hb-config.hh
@@ -35,8 +35,9 @@
 #include "config.h"
 #endif
 
-#ifndef HB_BORING_EXPANSION
-#define HB_NO_BORING_EXPANSION
+#ifndef HB_EXPERIMENTAL_API
+#define HB_NO_BEYOND_64K
+#define HB_NO_VAR_COMPOSITES
 #endif
 
 #ifdef HB_TINY
@@ -84,6 +85,7 @@
 #define HB_NO_OT_SHAPE_FRACTIONS
 #define HB_NO_STYLE
 #define HB_NO_SUBSET_LAYOUT
+#define HB_NO_VERTICAL
 #define HB_NO_VAR
 #endif
 
@@ -104,7 +106,7 @@
 
 #ifdef HB_NO_BORING_EXPANSION
 #define HB_NO_BEYOND_64K
-#define HB_NO_VARIATIONS2
+#define HB_NO_AVAR2
 #endif
 
 #ifdef HB_DISABLE_DEPRECATED
@@ -113,6 +115,11 @@
 #define HB_IF_NOT_DEPRECATED(x) x
 #endif
 
+#ifdef HB_NO_SHAPER
+#define HB_NO_OT_SHAPE
+#define HB_NO_AAT_SHAPE
+#endif
+
 #ifdef HB_NO_AAT
 #define HB_NO_OT_NAME_LANGUAGE_AAT
 #define HB_NO_AAT_SHAPE
@@ -159,6 +166,7 @@
 #define HB_NO_OT_SHAPER_HEBREW_FALLBACK
 #define HB_NO_OT_SHAPER_THAI_FALLBACK
 #define HB_NO_OT_SHAPER_VOWEL_CONSTRAINTS
+#define HB_NO_OT_SHAPER_MYANMAR_ZAWGYI
 #endif
 
 #ifdef NDEBUG
diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc
index 99b33c0..4267e0e 100644
--- a/src/hb-coretext.cc
+++ b/src/hb-coretext.cc
@@ -347,10 +347,13 @@
       hb_ot_var_axis_info_t info;
       unsigned int c = 1;
       hb_ot_var_get_axis_infos (font->face, i, &c, &info);
-      CFDictionarySetValue (variations,
-	CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag),
-	CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &font->design_coords[i])
-      );
+      float v = hb_clamp (font->design_coords[i], info.min_value, info.max_value);
+
+      CFNumberRef tag_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag);
+      CFNumberRef value_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &v);
+      CFDictionarySetValue (variations, tag_number, value_number);
+      CFRelease (tag_number);
+      CFRelease (value_number);
     }
 
     CFDictionaryRef attributes =
@@ -648,7 +651,7 @@
       } else {
 	active_feature_t *feature = active_features.lsearch (event->feature);
 	if (feature)
-	  active_features.remove (feature - active_features.arrayZ);
+	  active_features.remove_ordered (feature - active_features.arrayZ);
       }
     }
   }
diff --git a/src/hb-draw.cc b/src/hb-draw.cc
index 46797e6..72c203f 100644
--- a/src/hb-draw.cc
+++ b/src/hb-draw.cc
@@ -80,6 +80,56 @@
 			void *user_data HB_UNUSED) {}
 
 
+static bool
+_hb_draw_funcs_set_preamble (hb_draw_funcs_t    *dfuncs,
+			     bool                func_is_null,
+			     void              **user_data,
+			     hb_destroy_func_t  *destroy)
+{
+  if (hb_object_is_immutable (dfuncs))
+  {
+    if (*destroy)
+      (*destroy) (*user_data);
+    return false;
+  }
+
+  if (func_is_null)
+  {
+    if (*destroy)
+      (*destroy) (*user_data);
+    *destroy = nullptr;
+    *user_data = nullptr;
+  }
+
+  return true;
+}
+
+static bool
+_hb_draw_funcs_set_middle (hb_draw_funcs_t   *dfuncs,
+			   void              *user_data,
+			   hb_destroy_func_t  destroy)
+{
+  if (user_data && !dfuncs->user_data)
+  {
+    dfuncs->user_data = (decltype (dfuncs->user_data)) hb_calloc (1, sizeof (*dfuncs->user_data));
+    if (unlikely (!dfuncs->user_data))
+      goto fail;
+  }
+  if (destroy && !dfuncs->destroy)
+  {
+    dfuncs->destroy = (decltype (dfuncs->destroy)) hb_calloc (1, sizeof (*dfuncs->destroy));
+    if (unlikely (!dfuncs->destroy))
+      goto fail;
+  }
+
+  return true;
+
+fail:
+  if (destroy)
+    (destroy) (user_data);
+  return false;
+}
+
 #define HB_DRAW_FUNC_IMPLEMENT(name)						\
 										\
 void										\
@@ -88,43 +138,24 @@
 				 void			 *user_data,		\
 				 hb_destroy_func_t	  destroy)		\
 {										\
-  if (hb_object_is_immutable (dfuncs))						\
-    return;									\
+  if (!_hb_draw_funcs_set_preamble (dfuncs, !func, &user_data, &destroy))\
+      return;                                                            \
 										\
   if (dfuncs->destroy && dfuncs->destroy->name)					\
     dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name); \
 									 \
-  if (user_data && !dfuncs->user_data)                                   \
-  {                                                                      \
-    dfuncs->user_data = (decltype (dfuncs->user_data)) hb_calloc (1, sizeof (*dfuncs->user_data)); \
-    if (unlikely (!dfuncs->user_data))                                   \
-      goto fail;                                                         \
-  }                                                                      \
-  if (destroy && !dfuncs->destroy)                                       \
-  {                                                                      \
-    dfuncs->destroy = (decltype (dfuncs->destroy)) hb_calloc (1, sizeof (*dfuncs->destroy)); \
-    if (unlikely (!dfuncs->destroy))                                     \
-      goto fail;                                                         \
-  }                                                                      \
+  if (!_hb_draw_funcs_set_middle (dfuncs, user_data, destroy))           \
+      return;                                                            \
 									\
-  if (func) {								\
+  if (func)								\
     dfuncs->func.name = func;						\
-    if (dfuncs->user_data)						\
-      dfuncs->user_data->name = user_data;				\
-    if (dfuncs->destroy)						\
-      dfuncs->destroy->name = destroy;					\
-  } else {								\
+  else									\
     dfuncs->func.name = hb_draw_##name##_nil;				\
-    if (dfuncs->user_data)						\
-      dfuncs->user_data->name = nullptr;				\
-    if (dfuncs->destroy)						\
-      dfuncs->destroy->name = nullptr;					\
-  }									\
-  return;                                                                \
-                                                                         \
-fail:                                                                    \
-  if (destroy)                                                           \
-    destroy (user_data);                                                 \
+									\
+  if (dfuncs->user_data)						\
+    dfuncs->user_data->name = user_data;				\
+  if (dfuncs->destroy)							\
+    dfuncs->destroy->name = destroy;					\
 }
 
 HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
diff --git a/src/hb-face.cc b/src/hb-face.cc
index e7deb31..8b4b635 100644
--- a/src/hb-face.cc
+++ b/src/hb-face.cc
@@ -288,6 +288,7 @@
 {
   if (!hb_object_destroy (face)) return;
 
+#ifndef HB_NO_SHAPER
   for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
   {
     hb_face_t::plan_node_t *next = node->next;
@@ -295,6 +296,7 @@
     hb_free (node);
     node = next;
   }
+#endif
 
   face->data.fini ();
   face->table.fini ();
@@ -636,7 +638,7 @@
 struct face_table_info_t
 {
   hb_blob_t* data;
-  unsigned order;
+  signed order;
 };
 
 struct hb_face_builder_data_t
@@ -784,16 +786,16 @@
 hb_bool_t
 hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
 {
-  if (tag == HB_MAP_VALUE_INVALID)
+  if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
     return false;
 
-  if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
+  if (tag == HB_MAP_VALUE_INVALID)
     return false;
 
   hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
 
   hb_blob_t* previous = data->tables.get (tag).data;
-  if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), 0}))
+  if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), -1}))
   {
     hb_blob_destroy (blob);
     return false;
@@ -819,13 +821,16 @@
 hb_face_builder_sort_tables (hb_face_t *face,
                              const hb_tag_t  *tags)
 {
+  if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
+    return;
+
   hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
 
   // Sort all unspecified tables after any specified tables.
   for (auto& info : data->tables.values_ref())
-    info.order = -1;
+    info.order = (unsigned) -1;
 
-  unsigned order = 0;
+  signed order = 0;
   for (const hb_tag_t* tag = tags;
        *tag;
        tag++)
diff --git a/src/hb-face.hh b/src/hb-face.hh
index 12e10d0..1bf0606 100644
--- a/src/hb-face.hh
+++ b/src/hb-face.hh
@@ -65,7 +65,9 @@
     hb_shape_plan_t *shape_plan;
     plan_node_t *next;
   };
+#ifndef HB_NO_SHAPER
   hb_atomic_ptr_t<plan_node_t> shape_plans;
+#endif
 
   hb_blob_t *reference_table (hb_tag_t tag) const
   {
diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc
index f8524ec..c54ad87 100644
--- a/src/hb-fallback-shape.cc
+++ b/src/hb-fallback-shape.cc
@@ -75,16 +75,6 @@
 		    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.
-   */
-
   hb_codepoint_t space;
   bool has_space = (bool) font->get_nominal_glyph (' ', &space);
 
diff --git a/src/hb-features.h.in b/src/hb-features.h.in
new file mode 100644
index 0000000..30ebf65
--- /dev/null
+++ b/src/hb-features.h.in
@@ -0,0 +1,96 @@
+/*
+ * Copyright © 2022 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.
+ */
+
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
+#error "Include <hb.h> instead."
+#endif
+
+#ifndef HB_FEATURES_H
+#define HB_FEATURES_H
+
+#include "hb-common.h"
+
+HB_BEGIN_DECLS
+
+
+/**
+ * HB_HAS_FREETYPE:
+ *
+ * Defined if Harfbuzz has been built with Freetype support.
+ */
+#mesondefine HB_HAS_FREETYPE
+
+/**
+ * HB_HAS_GDI:
+ *
+ * Defined if Harfbuzz has been built with GDI support.
+ */
+#mesondefine HB_HAS_GDI
+
+/**
+ * HB_HAS_GRAPHITE:
+ *
+ * Defined if Harfbuzz has been built with Graphite support.
+ */
+#mesondefine HB_HAS_GRAPHITE
+
+/**
+ * HB_HAS_GLIB:
+ *
+ * Defined if Harfbuzz has been built with GLib support.
+ */
+#mesondefine HB_HAS_GLIB
+
+/**
+ * HB_HAS_UNISCRIBE:
+ *
+ * Defined if Harfbuzz has been built with Uniscribe support.
+ */
+#mesondefine HB_HAS_UNISCRIBE
+
+/**
+ * HB_HAS_DIRECTWRITE:
+ *
+ * Defined if Harfbuzz has been built with DirectWrite support.
+ */
+#mesondefine HB_HAS_DIRECTWRITE
+
+/**
+ * HB_HAS_CORETEXT:
+ *
+ * Defined if Harfbuzz has been built with CoreText support.
+ */
+#mesondefine HB_HAS_CORETEXT
+
+/**
+ * HB_HAS_ICU:
+ *
+ * Defined if Harfbuzz has been built with ICU support.
+ */
+#mesondefine HB_HAS_ICU
+
+
+HB_END_DECLS
+
+#endif /* HB_FEATURES_H */
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 856bbdd..0ce3e26 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -71,7 +71,7 @@
 				hb_font_extents_t *extents,
 				void              *user_data HB_UNUSED)
 {
-  memset (extents, 0, sizeof (*extents));
+  hb_memset (extents, 0, sizeof (*extents));
   return false;
 }
 
@@ -96,7 +96,7 @@
 				hb_font_extents_t *extents,
 				void              *user_data HB_UNUSED)
 {
-  memset (extents, 0, sizeof (*extents));
+  hb_memset (extents, 0, sizeof (*extents));
   return false;
 }
 
@@ -409,7 +409,7 @@
 			       hb_glyph_extents_t *extents,
 			       void               *user_data HB_UNUSED)
 {
-  memset (extents, 0, sizeof (*extents));
+  hb_memset (extents, 0, sizeof (*extents));
   return false;
 }
 
@@ -518,6 +518,7 @@
   void		  *draw_data;
   float		   x_scale;
   float		   y_scale;
+  float		   slant;
 } hb_font_get_glyph_shape_default_adaptor_t;
 
 static void
@@ -530,9 +531,10 @@
   hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
   float x_scale = adaptor->x_scale;
   float y_scale = adaptor->y_scale;
+  float slant   = adaptor->slant;
 
   adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st,
-				     x_scale * to_x, y_scale * to_y);
+				     x_scale * to_x + slant * to_y, y_scale * to_y);
 }
 
 static void
@@ -544,12 +546,13 @@
   hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
   float x_scale = adaptor->x_scale;
   float y_scale = adaptor->y_scale;
+  float slant   = adaptor->slant;
 
-  st->current_x *= x_scale;
-  st->current_y *= y_scale;
+  st->current_x = st->current_x * x_scale + st->current_y * slant;
+  st->current_y = st->current_y * y_scale;
 
   adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st,
-				     x_scale * to_x, y_scale * to_y);
+				     x_scale * to_x + slant * to_y, y_scale * to_y);
 }
 
 static void
@@ -562,13 +565,14 @@
   hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
   float x_scale = adaptor->x_scale;
   float y_scale = adaptor->y_scale;
+  float slant   = adaptor->slant;
 
-  st->current_x *= x_scale;
-  st->current_y *= y_scale;
+  st->current_x = st->current_x * x_scale + st->current_y * slant;
+  st->current_y = st->current_y * y_scale;
 
   adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st,
-					  x_scale * control_x, y_scale * control_y,
-					  x_scale * to_x, y_scale * to_y);
+					  x_scale * control_x + slant * control_y, y_scale * control_y,
+					  x_scale * to_x + slant * to_y, y_scale * to_y);
 }
 
 static void
@@ -582,14 +586,15 @@
   hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
   float x_scale = adaptor->x_scale;
   float y_scale = adaptor->y_scale;
+  float slant   = adaptor->slant;
 
-  st->current_x *= x_scale;
-  st->current_y *= y_scale;
+  st->current_x = st->current_x * x_scale + st->current_y * slant;
+  st->current_y = st->current_y * y_scale;
 
   adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st,
-				      x_scale * control1_x, y_scale * control1_y,
-				      x_scale * control2_x, y_scale * control2_y,
-				      x_scale * to_x, y_scale * to_y);
+				      x_scale * control1_x + slant * control1_y, y_scale * control1_y,
+				      x_scale * control2_x + slant * control2_y, y_scale * control2_y,
+				      x_scale * to_x + slant * to_y, y_scale * to_y);
 }
 
 static void
@@ -623,8 +628,10 @@
   hb_font_get_glyph_shape_default_adaptor_t adaptor = {
     draw_funcs,
     draw_data,
-    (float) font->x_scale / (float) font->parent->x_scale,
-    (float) font->y_scale / (float) font->parent->y_scale
+    font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f,
+    font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f,
+    font->parent->y_scale ? (font->slant - font->parent->slant) *
+			    (float) font->x_scale / (float) font->parent->y_scale : 0.f
   };
 
   font->parent->get_glyph_shape (glyph,
@@ -822,6 +829,56 @@
 }
 
 
+static bool
+_hb_font_funcs_set_preamble (hb_font_funcs_t    *ffuncs,
+			     bool                func_is_null,
+			     void              **user_data,
+			     hb_destroy_func_t  *destroy)
+{
+  if (hb_object_is_immutable (ffuncs))
+  {
+    if (*destroy)
+      (*destroy) (*user_data);
+    return false;
+  }
+
+  if (func_is_null)
+  {
+    if (*destroy)
+      (*destroy) (*user_data);
+    *destroy = nullptr;
+    *user_data = nullptr;
+  }
+
+  return true;
+}
+
+static bool
+_hb_font_funcs_set_middle (hb_font_funcs_t   *ffuncs,
+			   void              *user_data,
+			   hb_destroy_func_t  destroy)
+{
+  if (user_data && !ffuncs->user_data)
+  {
+    ffuncs->user_data = (decltype (ffuncs->user_data)) hb_calloc (1, sizeof (*ffuncs->user_data));
+    if (unlikely (!ffuncs->user_data))
+      goto fail;
+  }
+  if (destroy && !ffuncs->destroy)
+  {
+    ffuncs->destroy = (decltype (ffuncs->destroy)) hb_calloc (1, sizeof (*ffuncs->destroy));
+    if (unlikely (!ffuncs->destroy))
+      goto fail;
+  }
+
+  return true;
+
+fail:
+  if (destroy)
+    (destroy) (user_data);
+  return false;
+}
+
 #define HB_FONT_FUNC_IMPLEMENT(name) \
 									 \
 void                                                                     \
@@ -830,51 +887,24 @@
 				 void                        *user_data, \
 				 hb_destroy_func_t            destroy)   \
 {                                                                        \
-  if (hb_object_is_immutable (ffuncs))                                   \
-    goto fail;                                                           \
-                                                                         \
-  if (!func)                                                             \
-  {                                                                      \
-    if (destroy)                                                         \
-      destroy (user_data);                                               \
-    destroy = nullptr;                                                   \
-    user_data = nullptr;                                                 \
-  }                                                                      \
+  if (!_hb_font_funcs_set_preamble (ffuncs, !func, &user_data, &destroy))\
+      return;                                                            \
 									 \
   if (ffuncs->destroy && ffuncs->destroy->name)                          \
     ffuncs->destroy->name (!ffuncs->user_data ? nullptr : ffuncs->user_data->name); \
                                                                          \
-  if (user_data && !ffuncs->user_data)                                   \
-  {                                                                      \
-    ffuncs->user_data = (decltype (ffuncs->user_data)) hb_calloc (1, sizeof (*ffuncs->user_data)); \
-    if (unlikely (!ffuncs->user_data))                                   \
-      goto fail;                                                         \
-  }                                                                      \
-  if (destroy && !ffuncs->destroy)                                       \
-  {                                                                      \
-    ffuncs->destroy = (decltype (ffuncs->destroy)) hb_calloc (1, sizeof (*ffuncs->destroy)); \
-    if (unlikely (!ffuncs->destroy))                                     \
-      goto fail;                                                         \
-  }                                                                      \
+  if (!_hb_font_funcs_set_middle (ffuncs, user_data, destroy))           \
+      return;                                                            \
 									 \
-  if (func) {                                                            \
+  if (func)                                                              \
     ffuncs->get.f.name = func;                                           \
-    if (ffuncs->user_data)                                               \
-      ffuncs->user_data->name = user_data;                               \
-    if (ffuncs->destroy)                                                 \
-      ffuncs->destroy->name = destroy;                                   \
-  } else {                                                               \
+  else                                                                   \
     ffuncs->get.f.name = hb_font_get_##name##_default;                   \
-    if (ffuncs->user_data)                                               \
-      ffuncs->user_data->name = nullptr;                                 \
-    if (ffuncs->destroy)						 \
-      ffuncs->destroy->name = nullptr;                                   \
-  }                                                                      \
-  return;                                                                \
-                                                                         \
-fail:                                                                    \
-  if (destroy)                                                           \
-    destroy (user_data);                                                 \
+									 \
+  if (ffuncs->user_data)                                                 \
+    ffuncs->user_data->name = user_data;                                 \
+  if (ffuncs->destroy)                                                   \
+    ffuncs->destroy->name = destroy;                                     \
 }
 
 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
@@ -1323,7 +1353,7 @@
  * @draw_data: User data to pass to draw callbacks
  *
  * Fetches the glyph shape that corresponds to a glyph in the specified @font.
- * The shape is returned by way of calls to the callsbacks of the @dfuncs
+ * The shape is returned by way of calls to the callbacks of the @dfuncs
  * objects, with @draw_data passed to them.
  *
  * Since: 4.0.0
@@ -1780,8 +1810,8 @@
     float *design_coords = (float *) hb_calloc (num_coords, sizeof (parent->design_coords[0]));
     if (likely (coords && design_coords))
     {
-      memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0]));
-      memcpy (design_coords, parent->design_coords, num_coords * sizeof (parent->design_coords[0]));
+      hb_memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0]));
+      hb_memcpy (design_coords, parent->design_coords, num_coords * sizeof (parent->design_coords[0]));
       _hb_font_adopt_var_coords (font, coords, design_coords, num_coords);
     }
     else
@@ -2443,7 +2473,7 @@
   }
 
   if (coords_length)
-    memcpy (design_coords, coords, coords_length * sizeof (font->design_coords[0]));
+    hb_memcpy (design_coords, coords, coords_length * sizeof (font->design_coords[0]));
 
   hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
   _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
@@ -2519,8 +2549,8 @@
 
   if (coords_length)
   {
-    memcpy (copy, coords, coords_length * sizeof (coords[0]));
-    memcpy (unmapped, coords, coords_length * sizeof (coords[0]));
+    hb_memcpy (copy, coords, coords_length * sizeof (coords[0]));
+    hb_memcpy (unmapped, coords, coords_length * sizeof (coords[0]));
   }
 
   /* Best effort design coords simulation */
diff --git a/src/hb-font.hh b/src/hb-font.hh
index bb402e2..6942d99 100644
--- a/src/hb-font.hh
+++ b/src/hb-font.hh
@@ -206,14 +206,14 @@
 
   hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
   {
-    memset (extents, 0, sizeof (*extents));
+    hb_memset (extents, 0, sizeof (*extents));
     return klass->get.f.font_h_extents (this, user_data,
 					extents,
 					!klass->user_data ? nullptr : klass->user_data->font_h_extents);
   }
   hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
   {
-    memset (extents, 0, sizeof (*extents));
+    hb_memset (extents, 0, sizeof (*extents));
     return klass->get.f.font_v_extents (this, user_data,
 					extents,
 					!klass->user_data ? nullptr : klass->user_data->font_v_extents);
@@ -342,7 +342,7 @@
   hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
 			       hb_glyph_extents_t *extents)
   {
-    memset (extents, 0, sizeof (*extents));
+    hb_memset (extents, 0, sizeof (*extents));
     return klass->get.f.glyph_extents (this, user_data,
 				       glyph,
 				       extents,
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index bcc1dd0..3892ded 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -89,7 +89,7 @@
   bool unref; /* Whether to destroy ft_face when done. */
   bool transform; /* Whether to apply FT_Face's transform. */
 
-  mutable hb_mutex_t lock;
+  mutable hb_mutex_t lock; /* Protects members below. */
   FT_Face ft_face;
   mutable unsigned cached_serial;
   mutable hb_ft_advance_cache_t advance_cache;
@@ -732,16 +732,18 @@
 
 static int
 _hb_ft_move_to (const FT_Vector *to,
-		hb_draw_session_t *drawing)
+		void *arg)
 {
+  hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
   drawing->move_to (to->x, to->y);
   return FT_Err_Ok;
 }
 
 static int
 _hb_ft_line_to (const FT_Vector *to,
-		hb_draw_session_t *drawing)
+		void *arg)
 {
+  hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
   drawing->line_to (to->x, to->y);
   return FT_Err_Ok;
 }
@@ -749,8 +751,9 @@
 static int
 _hb_ft_conic_to (const FT_Vector *control,
 		 const FT_Vector *to,
-		 hb_draw_session_t *drawing)
+		 void *arg)
 {
+  hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
   drawing->quadratic_to (control->x, control->y,
 			 to->x, to->y);
   return FT_Err_Ok;
@@ -760,8 +763,9 @@
 _hb_ft_cubic_to (const FT_Vector *control1,
 		 const FT_Vector *control2,
 		 const FT_Vector *to,
-		 hb_draw_session_t *drawing)
+		 void *arg)
 {
+  hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
   drawing->cubic_to (control1->x, control1->y,
 		     control2->x, control2->y,
 		     to->x, to->y);
@@ -787,10 +791,10 @@
     return;
 
   const FT_Outline_Funcs outline_funcs = {
-    (FT_Outline_MoveToFunc) _hb_ft_move_to,
-    (FT_Outline_LineToFunc) _hb_ft_line_to,
-    (FT_Outline_ConicToFunc) _hb_ft_conic_to,
-    (FT_Outline_CubicToFunc) _hb_ft_cubic_to,
+    _hb_ft_move_to,
+    _hb_ft_line_to,
+    _hb_ft_conic_to,
+    _hb_ft_cubic_to,
     0, /* shift */
     0, /* delta */
   };
@@ -975,8 +979,9 @@
 }
 
 static void
-hb_ft_face_finalize (FT_Face ft_face)
+hb_ft_face_finalize (void *arg)
 {
+  FT_Face ft_face = (FT_Face) arg;
   hb_face_destroy ((hb_face_t *) ft_face->generic.data);
 }
 
@@ -1008,7 +1013,7 @@
       ft_face->generic.finalizer (ft_face);
 
     ft_face->generic.data = hb_ft_face_create (ft_face, nullptr);
-    ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize;
+    ft_face->generic.finalizer = hb_ft_face_finalize;
   }
 
   return hb_face_reference ((hb_face_t *) ft_face->generic.data);
@@ -1217,8 +1222,9 @@
 }
 
 static void
-_release_blob (FT_Face ft_face)
+_release_blob (void *arg)
 {
+  FT_Face ft_face = (FT_Face) arg;
   hb_blob_destroy ((hb_blob_t *) ft_face->generic.data);
 }
 
@@ -1271,7 +1277,7 @@
 
 
   ft_face->generic.data = blob;
-  ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
+  ft_face->generic.finalizer = _release_blob;
 
   _hb_ft_font_set_funcs (font, ft_face, true);
   hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING);
diff --git a/src/hb-glib.cc b/src/hb-glib.cc
index 8ddc7eb..1da8169 100644
--- a/src/hb-glib.cc
+++ b/src/hb-glib.cc
@@ -129,32 +129,9 @@
 {
 #if GLIB_CHECK_VERSION(2,29,12)
   return g_unichar_compose (a, b, ab);
+#else
+  return false;
 #endif
-
-  /* We don't ifdef-out the fallback code such that compiler always
-   * sees it and makes sure it's compilable. */
-
-  gchar utf8[12];
-  gchar *normalized;
-  int len;
-  hb_bool_t ret;
-
-  len = g_unichar_to_utf8 (a, utf8);
-  len += g_unichar_to_utf8 (b, utf8 + len);
-  normalized = g_utf8_normalize (utf8, len, G_NORMALIZE_NFC);
-  len = g_utf8_strlen (normalized, -1);
-  if (unlikely (!len))
-    return false;
-
-  if (len == 1) {
-    *ab = g_utf8_get_char (normalized);
-    ret = true;
-  } else {
-    ret = false;
-  }
-
-  g_free (normalized);
-  return ret;
 }
 
 static hb_bool_t
@@ -166,55 +143,9 @@
 {
 #if GLIB_CHECK_VERSION(2,29,12)
   return g_unichar_decompose (ab, a, b);
+#else
+  return false;
 #endif
-
-  /* We don't ifdef-out the fallback code such that compiler always
-   * sees it and makes sure it's compilable. */
-
-  gchar utf8[6];
-  gchar *normalized;
-  int len;
-  hb_bool_t ret;
-
-  len = g_unichar_to_utf8 (ab, utf8);
-  normalized = g_utf8_normalize (utf8, len, G_NORMALIZE_NFD);
-  len = g_utf8_strlen (normalized, -1);
-  if (unlikely (!len))
-    return false;
-
-  if (len == 1) {
-    *a = g_utf8_get_char (normalized);
-    *b = 0;
-    ret = *a != ab;
-  } else if (len == 2) {
-    *a = g_utf8_get_char (normalized);
-    *b = g_utf8_get_char (g_utf8_next_char (normalized));
-    /* Here's the ugly part: if ab decomposes to a single character and
-     * that character decomposes again, we have to detect that and undo
-     * the second part :-(. */
-    gchar *recomposed = g_utf8_normalize (normalized, -1, G_NORMALIZE_NFC);
-    hb_codepoint_t c = g_utf8_get_char (recomposed);
-    if (c != ab && c != *a) {
-      *a = c;
-      *b = 0;
-    }
-    g_free (recomposed);
-    ret = true;
-  } else {
-    /* If decomposed to more than two characters, take the last one,
-     * and recompose the rest to get the first component. */
-    gchar *end = g_utf8_offset_to_pointer (normalized, len - 1);
-    gchar *recomposed;
-    *b = g_utf8_get_char (end);
-    recomposed = g_utf8_normalize (normalized, end - normalized, G_NORMALIZE_NFC);
-    /* We expect that recomposed has exactly one character now. */
-    *a = g_utf8_get_char (recomposed);
-    g_free (recomposed);
-    ret = true;
-  }
-
-  g_free (normalized);
-  return ret;
 }
 
 
diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc
index 4d0e687..9e068f8 100644
--- a/src/hb-graphite2.cc
+++ b/src/hb-graphite2.cc
@@ -318,7 +318,7 @@
 
 #undef ALLOCATE_ARRAY
 
-  memset (clusters, 0, sizeof (clusters[0]) * buffer->len);
+  hb_memset (clusters, 0, sizeof (clusters[0]) * buffer->len);
 
   hb_codepoint_t *pg = gids;
   clusters[0].cluster = buffer->info[0].cluster;
diff --git a/src/hb-iter.hh b/src/hb-iter.hh
index 1a3ab43..b57f37b 100644
--- a/src/hb-iter.hh
+++ b/src/hb-iter.hh
@@ -73,8 +73,10 @@
   /* Operators. */
   iter_t iter () const { return *thiz(); }
   iter_t operator + () const { return *thiz(); }
-  iter_t begin () const { return *thiz(); }
-  iter_t end () const { return thiz()->__end__ (); }
+  iter_t _begin () const { return *thiz(); }
+  iter_t begin () const { return _begin (); }
+  iter_t _end () const { return thiz()->__end__ (); }
+  iter_t end () const { return _end (); }
   explicit operator bool () const { return thiz()->__more__ (); }
   unsigned len () const { return thiz()->__len__ (); }
   /* The following can only be enabled if item_t is reference type.  Otherwise
@@ -118,7 +120,9 @@
 
 #define HB_ITER_USING(Name) \
   using item_t = typename Name::item_t; \
+  using Name::_begin; \
   using Name::begin; \
+  using Name::_end; \
   using Name::end; \
   using Name::get_item_size; \
   using Name::is_iterator; \
@@ -377,7 +381,7 @@
   void __forward__ (unsigned n) { it += n; }
   void __prev__ () { --it; }
   void __rewind__ (unsigned n) { it -= n; }
-  hb_map_iter_t __end__ () const { return hb_map_iter_t (it.end (), f); }
+  hb_map_iter_t __end__ () const { return hb_map_iter_t (it._end (), f); }
   bool operator != (const hb_map_iter_t& o) const
   { return it != o.it; }
 
@@ -440,7 +444,7 @@
   bool __more__ () const { return bool (it); }
   void __next__ () { do ++it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); }
   void __prev__ () { do --it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); }
-  hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it.end (), p, f); }
+  hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it._end (), p, f); }
   bool operator != (const hb_filter_iter_t& o) const
   { return it != o.it; }
 
@@ -553,7 +557,7 @@
   void __forward__ (unsigned n) { a += n; b += n; }
   void __prev__ () { --a; --b; }
   void __rewind__ (unsigned n) { a -= n; b -= n; }
-  hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a.end (), b.end ()); }
+  hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a._end (), b._end ()); }
   /* Note, we should stop if ANY of the iters reaches end.  As such two compare
    * unequal if both items are unequal, NOT if either is unequal. */
   bool operator != (const hb_zip_iter_t& o) const
@@ -637,7 +641,7 @@
     }
   }
 
-  hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a.end (), b.end ()); }
+  hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a._end (), b._end ()); }
   bool operator != (const hb_concat_iter_t& o) const
   {
     return a != o.a
diff --git a/src/hb-machinery.hh b/src/hb-machinery.hh
index 2571f22..b555739 100644
--- a/src/hb-machinery.hh
+++ b/src/hb-machinery.hh
@@ -136,6 +136,13 @@
 
 /*
  * Lazy loaders.
+ *
+ * The lazy-loaders are thread-safe pointer-like objects that create their
+ * instead on-demand.  They also support access to a "data" object that is
+ * necessary for creating their instance.  The data object, if specified,
+ * is accessed via pointer math, located at a location before the position
+ * of the loader itself.  This avoids having to store a pointer to data
+ * for every lazy-loader.  Multiple lazy-loaders can access the same data.
  */
 
 template <typename Data, unsigned int WheresData>
@@ -228,7 +235,8 @@
 
   bool cmpexch (Stored *current, Stored *value) const
   {
-    /* This *must* be called when there are no other threads accessing. */
+    /* This function can only be safely called directly if no
+     * other thread is accessing. */
     return this->instance.cmpexch (current, value);
   }
 
@@ -261,7 +269,7 @@
     hb_free (p);
   }
 
-//  private:
+  private:
   /* Must only have one pointer. */
   hb_atomic_ptr_t<Stored *> instance;
 };
@@ -283,7 +291,7 @@
   {
     auto c = hb_sanitize_context_t ();
     if (core)
-      c.set_num_glyphs (0); // So we don't recurse ad infinitum...
+      c.set_num_glyphs (0); // So we don't recurse ad infinitum, or doesn't need num_glyphs
     return c.reference_table<T> (face);
   }
   static void destroy (hb_blob_t *p) { hb_blob_destroy (p); }
diff --git a/src/hb-map.hh b/src/hb-map.hh
index 8302e3f..bfb1b3f 100644
--- a/src/hb-map.hh
+++ b/src/hb-map.hh
@@ -43,9 +43,9 @@
   hb_hashmap_t ()  { init (); }
   ~hb_hashmap_t () { fini (); }
 
-  hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (population); hb_copy (o, *this); }
+  hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (o.population); hb_copy (o, *this); }
   hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); }
-  hb_hashmap_t& operator= (const hb_hashmap_t& o)  { resize (population); hb_copy (o, *this); return *this; }
+  hb_hashmap_t& operator= (const hb_hashmap_t& o)  { reset (); resize (o.population); hb_copy (o, *this); return *this; }
   hb_hashmap_t& operator= (hb_hashmap_t&& o)  { hb_swap (*this, o); return *this; }
 
   hb_hashmap_t (std::initializer_list<hb_pair_t<K, V>> lst) : hb_hashmap_t ()
@@ -71,6 +71,11 @@
     uint32_t is_tombstone_ : 1;
     V value;
 
+    item_t () : key (),
+		hash (0),
+		is_used_ (false), is_tombstone_ (false),
+		value () {}
+
     bool is_used () const { return is_used_; }
     void set_used (bool is_used) { is_used_ = is_used; }
     bool is_tombstone () const { return is_tombstone_; }
@@ -88,17 +93,8 @@
       return minus_1;
     };
 
-    void clear ()
-    {
-      new (std::addressof (key)) K ();
-      new (std::addressof (value)) V ();
-      hash = 0;
-      is_used_ = false;
-      is_tombstone_ = false;
-    }
-
-    bool operator == (const K &o) { return hb_deref (key) == hb_deref (o); }
-    bool operator == (const item_t &o) { return *this == o.key; }
+    bool operator == (const K &o) const { return hb_deref (key) == hb_deref (o); }
+    bool operator == (const item_t &o) const { return *this == o.key; }
     hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
     hb_pair_t<const K &, const V &> get_pair_ref() const { return hb_pair_t<const K &, const V &> (key, value); }
 
@@ -107,8 +103,8 @@
   };
 
   hb_object_header_t header;
-  bool successful; /* Allocations successful */
-  unsigned int population; /* Not including tombstones. */
+  unsigned int successful : 1; /* Allocations successful */
+  unsigned int population : 31; /* Not including tombstones. */
   unsigned int occupancy; /* Including tombstones. */
   unsigned int mask;
   unsigned int prime;
@@ -118,7 +114,10 @@
   {
     if (unlikely (!a.successful || !b.successful))
       return;
-    hb_swap (a.population, b.population);
+    unsigned tmp = a.population;
+    a.population = b.population;
+    b.population = tmp;
+    //hb_swap (a.population, b.population);
     hb_swap (a.occupancy, b.occupancy);
     hb_swap (a.mask, b.mask);
     hb_swap (a.prime, b.prime);
@@ -160,7 +159,9 @@
   {
     if (unlikely (!successful)) return false;
 
-    unsigned int power = hb_bit_storage (hb_max (population, new_population) * 2 + 8);
+    if (new_population != 0 && (new_population + new_population / 2) < mask) return true;
+
+    unsigned int power = hb_bit_storage (hb_max ((unsigned) population, new_population) * 2 + 8);
     unsigned int new_size = 1u << power;
     item_t *new_items = (item_t *) hb_malloc ((size_t) new_size * sizeof (item_t));
     if (unlikely (!new_items))
@@ -169,9 +170,9 @@
       return false;
     }
     for (auto &_ : hb_iter (new_items, new_size))
-      _.clear ();
+      new (&_) item_t ();
 
-    unsigned int old_size = mask + 1;
+    unsigned int old_size = size ();
     item_t *old_items = items;
 
     /* Switch to new, empty, array. */
@@ -181,47 +182,82 @@
     items = new_items;
 
     /* Insert back old items. */
-    if (old_items)
-      for (unsigned int i = 0; i < old_size; i++)
+    for (unsigned int i = 0; i < old_size; i++)
+    {
+      if (old_items[i].is_real ())
       {
-	if (old_items[i].is_real ())
-	{
-	  set_with_hash (old_items[i].key,
-			 old_items[i].hash,
-			 std::move (old_items[i].value));
-	}
-	old_items[i].~item_t ();
+	set_with_hash (std::move (old_items[i].key),
+		       old_items[i].hash,
+		       std::move (old_items[i].value));
       }
+      old_items[i].~item_t ();
+    }
 
     hb_free (old_items);
 
     return true;
   }
 
-  template <typename VV>
-  bool set (K key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); }
-
-  const V& get (K key) const
+  template <typename KK, typename VV>
+  bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool is_delete=false)
   {
-    if (unlikely (!items)) return item_t::default_value ();
-    unsigned int i = bucket_for (key);
-    return items[i].is_real () && items[i] == key ? items[i].value : item_t::default_value ();
+    if (unlikely (!successful)) return false;
+    if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
+    item_t &item = item_for_hash (key, hash);
+
+    if (is_delete && !(item == key))
+      return true; /* Trying to delete non-existent key. */
+
+    if (item.is_used ())
+    {
+      occupancy--;
+      if (!item.is_tombstone ())
+	population--;
+    }
+
+    item.key = std::forward<KK> (key);
+    item.value = std::forward<VV> (value);
+    item.hash = hash;
+    item.set_used (true);
+    item.set_tombstone (is_delete);
+
+    occupancy++;
+    if (!is_delete)
+      population++;
+
+    return true;
   }
 
-  void del (K key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); }
+  template <typename VV>
+  bool set (const K &key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); }
+  template <typename VV>
+  bool set (K &&key, VV&& value) { return set_with_hash (std::move (key), hb_hash (key), std::forward<VV> (value)); }
+
+  const V& get_with_hash (const K &key, uint32_t hash) const
+  {
+    if (unlikely (!items)) return item_t::default_value ();
+    auto &item = item_for_hash (key, hash);
+    return item.is_real () && item == key ? item.value : item_t::default_value ();
+  }
+  const V& get (const K &key) const
+  {
+    if (unlikely (!items)) return item_t::default_value ();
+    return get_with_hash (key, hb_hash (key));
+  }
+
+  void del (const K &key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); }
 
   /* Has interface. */
-  typedef const V& value_t;
-  value_t operator [] (K k) const { return get (k); }
+  const V& operator [] (K k) const { return get (k); }
   template <typename VV=V>
   bool has (K key, VV **vp = nullptr) const
   {
     if (unlikely (!items))
       return false;
-    unsigned int i = bucket_for (key);
-    if (items[i].is_real () && items[i] == key)
+    auto &item = item_for_hash (key, hb_hash (key));
+    if (item.is_real () && item == key)
     {
-      if (vp) *vp = &items[i].value;
+      if (vp) *vp = std::addressof (item.value);
       return true;
     }
     else
@@ -230,13 +266,18 @@
   /* Projection. */
   V operator () (K k) const { return get (k); }
 
+  unsigned size () const { return mask ? mask + 1 : 0; }
+
   void clear ()
   {
     if (unlikely (!successful)) return;
 
-    if (items)
-      for (auto &_ : hb_iter (items, mask + 1))
-	_.clear ();
+    for (auto &_ : hb_iter (items, size ()))
+    {
+      /* Reconstruct items. */
+      _.~item_t ();
+      new (&_) item_t ();
+    }
 
     population = occupancy = 0;
   }
@@ -246,11 +287,10 @@
 
   uint32_t hash () const
   {
-    uint32_t h = 0;
-    for (const auto &item : + hb_array (items, mask ? mask + 1 : 0)
-			    | hb_filter (&item_t::is_real))
-      h ^= item.total_hash ();
-    return h;
+    return
+    + iter_items ()
+    | hb_reduce ([] (uint32_t h, const item_t &_) { return h ^ _.total_hash (); }, (uint32_t) 0u)
+    ;
   }
 
   bool is_equal (const hb_hashmap_t &other) const
@@ -258,7 +298,7 @@
     if (population != other.population) return false;
 
     for (auto pair : iter ())
-      if (get (pair.first) != pair.second)
+      if (other.get (pair.first) != pair.second)
         return false;
 
     return true;
@@ -271,87 +311,54 @@
   /*
    * Iterator
    */
-  auto iter () const HB_AUTO_RETURN
+
+  auto iter_items () const HB_AUTO_RETURN
   (
-    + hb_array (items, mask ? mask + 1 : 0)
+    + hb_iter (items, size ())
     | hb_filter (&item_t::is_real)
-    | hb_map (&item_t::get_pair)
   )
   auto iter_ref () const HB_AUTO_RETURN
   (
-    + hb_array (items, mask ? mask + 1 : 0)
-    | hb_filter (&item_t::is_real)
+    + iter_items ()
     | hb_map (&item_t::get_pair_ref)
   )
-  auto keys () const HB_AUTO_RETURN
+  auto iter () const HB_AUTO_RETURN
   (
-    + hb_array (items, mask ? mask + 1 : 0)
-    | hb_filter (&item_t::is_real)
-    | hb_map (&item_t::key)
-    | hb_map (hb_ridentity)
+    + iter_items ()
+    | hb_map (&item_t::get_pair)
   )
   auto keys_ref () const HB_AUTO_RETURN
   (
-    + hb_array (items, mask ? mask + 1 : 0)
-    | hb_filter (&item_t::is_real)
+    + iter_items ()
     | hb_map (&item_t::key)
   )
-  auto values () const HB_AUTO_RETURN
+  auto keys () const HB_AUTO_RETURN
   (
-    + hb_array (items, mask ? mask + 1 : 0)
-    | hb_filter (&item_t::is_real)
-    | hb_map (&item_t::value)
+    + keys_ref ()
     | hb_map (hb_ridentity)
   )
   auto values_ref () const HB_AUTO_RETURN
   (
-    + hb_array (items, mask ? mask + 1 : 0)
-    | hb_filter (&item_t::is_real)
+    + iter_items ()
     | hb_map (&item_t::value)
   )
+  auto values () const HB_AUTO_RETURN
+  (
+    + values_ref ()
+    | hb_map (hb_ridentity)
+  )
 
   /* Sink interface. */
   hb_hashmap_t& operator << (const hb_pair_t<K, V>& v)
   { set (v.first, v.second); return *this; }
+  hb_hashmap_t& operator << (const hb_pair_t<K, V&&>& v)
+  { set (v.first, std::move (v.second)); return *this; }
+  hb_hashmap_t& operator << (const hb_pair_t<K&&, V>& v)
+  { set (std::move (v.first), v.second); return *this; }
+  hb_hashmap_t& operator << (const hb_pair_t<K&&, V&&>& v)
+  { set (std::move (v.first), std::move (v.second)); return *this; }
 
-  protected:
-
-  template <typename VV>
-  bool set_with_hash (K key, uint32_t hash, VV&& value, bool is_delete=false)
-  {
-    if (unlikely (!successful)) return false;
-    if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
-    unsigned int i = bucket_for_hash (key, hash);
-
-    if (is_delete && items[i].key != key)
-      return true; /* Trying to delete non-existent key. */
-
-    if (items[i].is_used ())
-    {
-      occupancy--;
-      if (!items[i].is_tombstone ())
-	population--;
-    }
-
-    items[i].key = key;
-    items[i].value = std::forward<VV> (value);
-    items[i].hash = hash;
-    items[i].set_used (true);
-    items[i].set_tombstone (is_delete);
-
-    occupancy++;
-    if (!is_delete)
-      population++;
-
-    return true;
-  }
-
-  unsigned int bucket_for (const K &key) const
-  {
-    return bucket_for_hash (key, hb_hash (key));
-  }
-
-  unsigned int bucket_for_hash (const K &key, uint32_t hash) const
+  item_t& item_for_hash (const K &key, uint32_t hash) const
   {
     hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
     unsigned int i = hash % prime;
@@ -360,12 +367,12 @@
     while (items[i].is_used ())
     {
       if (items[i].hash == hash && items[i] == key)
-	return i;
+	return items[i];
       if (tombstone == (unsigned) -1 && items[i].is_tombstone ())
 	tombstone = i;
       i = (i + ++step) & mask;
     }
-    return tombstone == (unsigned) -1 ? i : tombstone;
+    return items[tombstone == (unsigned) -1 ? i : tombstone];
   }
 
   static unsigned int prime_for (unsigned int shift)
diff --git a/src/hb-meta.hh b/src/hb-meta.hh
index 52a6791..31aa7fa 100644
--- a/src/hb-meta.hh
+++ b/src/hb-meta.hh
@@ -112,8 +112,7 @@
 template <typename T> using hb_add_pointer = decltype (_hb_try_add_pointer<T> (hb_prioritize));
 
 
-/* TODO Add feature-parity to std::decay. */
-template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>;
+template <typename T> using hb_decay = typename std::decay<T>::type;
 
 #define hb_is_convertible(From,To) std::is_convertible<From, To>::value
 
diff --git a/src/hb-ms-feature-ranges.hh b/src/hb-ms-feature-ranges.hh
index d40fdea..46a20c9 100644
--- a/src/hb-ms-feature-ranges.hh
+++ b/src/hb-ms-feature-ranges.hh
@@ -166,7 +166,7 @@
     {
       auto *feature = active_features.lsearch (event->feature);
       if (feature)
-        active_features.remove (feature - active_features.arrayZ);
+        active_features.remove_ordered (feature - active_features.arrayZ);
     }
   }
 
diff --git a/src/hb-multimap.hh b/src/hb-multimap.hh
new file mode 100644
index 0000000..f0f9591
--- /dev/null
+++ b/src/hb-multimap.hh
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2022  Behdad Esfahbod
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_MULTIMAP_HH
+#define HB_MULTIMAP_HH
+
+#include "hb.hh"
+#include "hb-map.hh"
+#include "hb-vector.hh"
+
+
+/*
+ * hb_multimap_t
+ */
+
+struct hb_multimap_t
+{
+  void add (hb_codepoint_t k, hb_codepoint_t v)
+  {
+    hb_codepoint_t *i;
+    if (multiples_indices.has (k, &i))
+    {
+      multiples_values[*i].push (v);
+      return;
+    }
+
+    hb_codepoint_t *old_v;
+    if (singulars.has (k, &old_v))
+    {
+      hb_codepoint_t old = *old_v;
+      singulars.del (k);
+
+      multiples_indices.set (k, multiples_values.length);
+      auto *vec = multiples_values.push ();
+
+      vec->push (old);
+      vec->push (v);
+
+      return;
+    }
+
+    singulars.set (k, v);
+  }
+
+  hb_array_t<const hb_codepoint_t> get (hb_codepoint_t k) const
+  {
+    hb_codepoint_t *v;
+    if (singulars.has (k, &v))
+      return hb_array (v, 1);
+
+    hb_codepoint_t *i;
+    if (multiples_indices.has (k, &i))
+      return multiples_values[*i].as_array ();
+
+    return hb_array_t<hb_codepoint_t> ();
+  }
+
+  bool in_error () const
+  {
+    return singulars.in_error () || multiples_indices.in_error () || multiples_values.in_error ();
+  }
+
+  protected:
+  hb_map_t singulars;
+  hb_map_t multiples_indices;
+  hb_vector_t<hb_vector_t<hb_codepoint_t>> multiples_values;
+};
+
+
+
+#endif /* HB_MULTIMAP_HH */
diff --git a/src/hb-mutex.hh b/src/hb-mutex.hh
index 6914b22..053f9dd 100644
--- a/src/hb-mutex.hh
+++ b/src/hb-mutex.hh
@@ -108,10 +108,11 @@
 
 struct hb_lock_t
 {
-  hb_lock_t (hb_mutex_t &mutex_) : mutex (mutex_) { mutex.lock (); }
-  ~hb_lock_t () { mutex.unlock (); }
+  hb_lock_t (hb_mutex_t &mutex_) : mutex (&mutex_) { mutex->lock (); }
+  hb_lock_t (hb_mutex_t *mutex_) : mutex (mutex_) { if (mutex) mutex->lock (); }
+  ~hb_lock_t () { if (mutex) mutex->unlock (); }
   private:
-  hb_mutex_t &mutex;
+  hb_mutex_t *mutex;
 };
 
 
diff --git a/src/hb-number-parser.hh b/src/hb-number-parser.hh
index 1a9dbba..ec68c3a 100644
--- a/src/hb-number-parser.hh
+++ b/src/hb-number-parser.hh
@@ -31,7 +31,7 @@
 #include "hb.hh"
 
 
-#line 35 "hb-number-parser.hh"
+#line 32 "hb-number-parser.hh"
 static const unsigned char _double_parser_trans_keys[] = {
 	0u, 0u, 43u, 57u, 46u, 57u, 48u, 57u, 43u, 57u, 48u, 57u, 48u, 101u, 48u, 57u, 
 	46u, 101u, 0
@@ -135,12 +135,12 @@
 
   int cs;
   
-#line 139 "hb-number-parser.hh"
+#line 132 "hb-number-parser.hh"
 	{
 	cs = double_parser_start;
 	}
 
-#line 144 "hb-number-parser.hh"
+#line 135 "hb-number-parser.hh"
 	{
 	int _slen;
 	int _trans;
@@ -198,7 +198,7 @@
 	  exp_overflow = true;
 }
 	break;
-#line 202 "hb-number-parser.hh"
+#line 187 "hb-number-parser.hh"
 	}
 
 _again:
diff --git a/src/hb-object.hh b/src/hb-object.hh
index 9876c29..a23c25f 100644
--- a/src/hb-object.hh
+++ b/src/hb-object.hh
@@ -80,7 +80,7 @@
     if (item)
     {
       item_t old = *item;
-      *item = items[items.length - 1];
+      *item = std::move (items.tail ());
       items.pop ();
       l.unlock ();
       old.fini ();
@@ -123,7 +123,7 @@
     l.lock ();
     while (items.length)
     {
-      item_t old = items[items.length - 1];
+      item_t old = items.tail ();
       items.pop ();
       l.unlock ();
       old.fini ();
diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh
index 6eee582..13570a4 100644
--- a/src/hb-open-file.hh
+++ b/src/hb-open-file.hh
@@ -90,7 +90,7 @@
   {
     if (table_count)
     {
-      + tables.sub_array (start_offset, table_count)
+      + tables.as_array ().sub_array (start_offset, table_count)
       | hb_map (&TableRecord::tag)
       | hb_sink (hb_array (table_tags, *table_count))
       ;
@@ -158,7 +158,7 @@
         return_trace (false);
 
       if (likely (len))
-	memcpy (start, blob->data, len);
+	hb_memcpy (start, blob->data, len);
 
       /* 4-byte alignment. */
       c->align (4);
diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
index e66f451..2907991 100644
--- a/src/hb-open-type.hh
+++ b/src/hb-open-type.hh
@@ -148,7 +148,7 @@
   static_assert (Type::static_size * 8 > fraction_bits, "");
 
   HBFixed& operator = (typename Type::type i ) { Type::operator= (i); return *this; }
-  float to_float () const  { return ((int32_t) Type::v) / shift; }
+  float to_float (float offset = 0) const  { return ((int32_t) Type::v + offset) / shift; }
   void set_float (float f) { Type::v = roundf (f * shift); }
   public:
   DEFINE_SIZE_STATIC (Type::static_size);
@@ -157,6 +157,9 @@
 /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
 using F2DOT14 = HBFixed<HBINT16, 14>;
 
+/* 16-bit signed fixed number with the low 12 bits of fraction (4.12). */
+using F4DOT12 = HBFixed<HBINT16, 12>;
+
 /* 32-bit signed fixed-point number (16.16). */
 using F16DOT16 = HBFixed<HBINT32, 16>;
 
@@ -209,6 +212,12 @@
 
 struct VarIdx : HBUINT32 {
   static constexpr unsigned NO_VARIATION = 0xFFFFFFFFu;
+  static_assert (NO_VARIATION == HB_OT_LAYOUT_NO_VARIATIONS_INDEX, "");
+  static uint32_t add (uint32_t i, unsigned short v)
+  {
+    if (i == NO_VARIATION) return i;
+    return i + v;
+  }
   VarIdx& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; }
 };
 DECLARE_NULL_NAMESPACE_BYTES (OT, VarIdx);
@@ -493,10 +502,10 @@
   void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
   { as_array (len).qsort (start, end); }
 
-  bool serialize (hb_serialize_context_t *c, unsigned int items_len)
+  bool serialize (hb_serialize_context_t *c, unsigned int items_len, bool clear = true)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend (this, items_len))) return_trace (false);
+    if (unlikely (!c->extend_size (this, get_size (items_len), clear))) return_trace (false);
     return_trace (true);
   }
   template <typename Iterator,
@@ -504,8 +513,8 @@
   bool serialize (hb_serialize_context_t *c, Iterator items)
   {
     TRACE_SERIALIZE (this);
-    unsigned count = items.len ();
-    if (unlikely (!serialize (c, count))) return_trace (false);
+    unsigned count = hb_len (items);
+    if (unlikely (!serialize (c, count, false))) return_trace (false);
     /* TODO Umm. Just exhaust the iterator instead?  Being extra
      * cautious right now.. */
     for (unsigned i = 0; i < count; i++, ++items)
@@ -646,14 +655,9 @@
   operator   iter_t () const { return   iter (); }
   operator writer_t ()       { return writer (); }
 
-  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
-  { return as_array ().sub_array (start_offset, count); }
-  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
-  { return as_array ().sub_array (start_offset, count); }
-  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
-  { return as_array ().sub_array (start_offset, count); }
-  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
-  { return as_array ().sub_array (start_offset, count); }
+  /* Faster range-based for loop. */
+  const Type *begin () const { return arrayZ; }
+  const Type *end () const { return arrayZ + len; }
 
   template <typename T>
   Type &lsearch (const T &x, Type &not_found = Crap (Type))
@@ -667,15 +671,15 @@
 	      unsigned int to_store = (unsigned int) -1) const
   { return as_array ().lfind (x, i, not_found, to_store); }
 
-  void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
-  { as_array ().qsort (start, end); }
+  void qsort ()
+  { as_array ().qsort (); }
 
-  HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len)
+  HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len, bool clear = true)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (this))) return_trace (false);
     c->check_assign (len, items_len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
-    if (unlikely (!c->extend (this))) return_trace (false);
+    if (unlikely (!c->extend_size (this, get_size (), clear))) return_trace (false);
     return_trace (true);
   }
   template <typename Iterator,
@@ -683,8 +687,8 @@
   HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items)
   {
     TRACE_SERIALIZE (this);
-    unsigned count = items.len ();
-    if (unlikely (!serialize (c, count))) return_trace (false);
+    unsigned count = hb_len (items);
+    if (unlikely (!serialize (c, count, false))) return_trace (false);
     /* TODO Umm. Just exhaust the iterator instead?  Being extra
      * cautious right now.. */
     for (unsigned i = 0; i < count; i++, ++items)
@@ -828,21 +832,25 @@
   operator   iter_t () const { return   iter (); }
   operator writer_t ()       { return writer (); }
 
-  bool serialize (hb_serialize_context_t *c, unsigned int items_len)
+  /* Faster range-based for loop. */
+  const Type *begin () const { return arrayZ; }
+  const Type *end () const { return arrayZ + get_length (); }
+
+  HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned int items_len, bool clear = true)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (this))) return_trace (false);
     c->check_assign (lenP1, items_len + 1, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
-    if (unlikely (!c->extend (this))) return_trace (false);
+    if (unlikely (!c->extend_size (this, get_size (), clear))) return_trace (false);
     return_trace (true);
   }
   template <typename Iterator,
 	    hb_requires (hb_is_source_of (Iterator, Type))>
-  bool serialize (hb_serialize_context_t *c, Iterator items)
+  HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items)
   {
     TRACE_SERIALIZE (this);
-    unsigned count = items.len ();
-    if (unlikely (!serialize (c, count))) return_trace (false);
+    unsigned count = hb_len (items);
+    if (unlikely (!serialize (c, count, false))) return_trace (false);
     /* TODO Umm. Just exhaust the iterator instead?  Being extra
      * cautious right now.. */
     for (unsigned i = 0; i < count; i++, ++items)
@@ -944,14 +952,9 @@
   operator   iter_t () const { return   iter (); }
   operator writer_t ()       { return writer (); }
 
-  hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
-  { return as_array ().sub_array (start_offset, count); }
-  hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
-  { return as_array ().sub_array (start_offset, count); }
-  hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
-  { return as_array ().sub_array (start_offset, count); }
-  hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
-  { return as_array ().sub_array (start_offset, count); }
+  /* Faster range-based for loop. */
+  const Type *begin () const { return this->arrayZ; }
+  const Type *end () const { return this->arrayZ + this->len; }
 
   bool serialize (hb_serialize_context_t *c, unsigned int items_len)
   {
diff --git a/src/hb-ot-cff-common.hh b/src/hb-ot-cff-common.hh
index ae3b83a..f22824f 100644
--- a/src/hb-ot-cff-common.hh
+++ b/src/hb-ot-cff-common.hh
@@ -66,95 +66,25 @@
   {
     TRACE_SERIALIZE (this);
     unsigned int size = get_size ();
-    CFFIndex *out = c->allocate_size<CFFIndex> (size);
+    CFFIndex *out = c->allocate_size<CFFIndex> (size, false);
     if (likely (out))
-      memcpy (out, this, size);
+      hb_memcpy (out, this, size);
     return_trace (out);
   }
 
+  template <typename Iterable,
+	    hb_requires (hb_is_iterable (Iterable))>
   bool serialize (hb_serialize_context_t *c,
-		  unsigned int offSize_,
-		  const byte_str_array_t &byteArray)
+		  const Iterable &iterable)
   {
     TRACE_SERIALIZE (this);
-
-    if (byteArray.length == 0)
-    {
-      COUNT *dest = c->allocate_min<COUNT> ();
-      if (unlikely (!dest)) return_trace (false);
-      *dest = 0;
-      return_trace (true);
-    }
-
-    /* serialize CFFIndex header */
-    if (unlikely (!c->extend_min (this))) return_trace (false);
-    this->count = byteArray.length;
-    this->offSize = offSize_;
-    if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
-      return_trace (false);
-
-    /* serialize indices */
-    unsigned int  offset = 1;
-    unsigned int  i = 0;
-    for (; i < byteArray.length; i++)
-    {
-      set_offset_at (i, offset);
-      offset += byteArray[i].get_size ();
-    }
-    set_offset_at (i, offset);
-
-    /* serialize data */
-    for (unsigned int i = 0; i < byteArray.length; i++)
-    {
-      const hb_ubytes_t &bs = byteArray[i];
-      unsigned char *dest = c->allocate_size<unsigned char> (bs.length);
-      if (unlikely (!dest)) return_trace (false);
-      memcpy (dest, &bs[0], bs.length);
-    }
-
-    return_trace (true);
-  }
-
-  bool serialize (hb_serialize_context_t *c,
-		  unsigned int offSize_,
-		  const str_buff_vec_t &buffArray)
-  {
-    byte_str_array_t  byteArray;
-    byteArray.init ();
-    byteArray.resize (buffArray.length);
-    for (unsigned int i = 0; i < byteArray.length; i++)
-      byteArray[i] = hb_ubytes_t (buffArray[i].arrayZ, buffArray[i].length);
-    bool result = this->serialize (c, offSize_, byteArray);
-    byteArray.fini ();
-    return result;
-  }
-
-  template <typename Iterator,
-	    hb_requires (hb_is_iterator (Iterator))>
-  bool serialize (hb_serialize_context_t *c,
-		  Iterator it)
-  {
-    TRACE_SERIALIZE (this);
-    serialize_header(c, + it | hb_map ([] (const hb_ubytes_t &_) { return _.length; }));
+    auto it = hb_iter (iterable);
+    serialize_header(c, + it | hb_map (hb_iter) | hb_map (hb_len));
     for (const auto &_ : +it)
-      _.copy (c);
+      hb_iter (_).copy (c);
     return_trace (true);
   }
 
-  bool serialize (hb_serialize_context_t *c,
-		  const byte_str_array_t &byteArray)
-  { return serialize (c, + hb_iter (byteArray)); }
-
-  bool serialize (hb_serialize_context_t *c,
-		  const str_buff_vec_t &buffArray)
-  {
-    auto it =
-    + hb_iter (buffArray)
-    | hb_map ([] (const str_buff_t &_) { return hb_ubytes_t (_.arrayZ, _.length); })
-    ;
-    return serialize (c, it);
-  }
-
   template <typename Iterator,
 	    hb_requires (hb_is_iterator (Iterator))>
   bool serialize_header (hb_serialize_context_t *c,
@@ -171,7 +101,7 @@
     if (!this->count) return_trace (true);
     if (unlikely (!c->extend (this->offSize))) return_trace (false);
     this->offSize = off_size;
-    if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1))))
+    if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1), false)))
       return_trace (false);
 
     /* serialize indices */
@@ -179,14 +109,27 @@
     unsigned int i = 0;
     for (unsigned _ : +it)
     {
-      CFFIndex<COUNT>::set_offset_at (i++, offset);
+      set_offset_at (i++, offset);
       offset += _;
     }
-    CFFIndex<COUNT>::set_offset_at (i, offset);
+    set_offset_at (i, offset);
 
     return_trace (true);
   }
 
+  template <typename Iterable,
+	    hb_requires (hb_is_iterable (Iterable))>
+  static unsigned total_size (const Iterable &iterable)
+  {
+    auto it = + hb_iter (iterable) | hb_map (hb_iter) | hb_map (hb_len);
+    if (!it) return 0;
+
+    unsigned total = + it | hb_reduce (hb_add, 0);
+    unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
+
+    return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total;
+  }
+
   void set_offset_at (unsigned int index, unsigned int offset)
   {
     assert (index <= count);
@@ -207,10 +150,14 @@
 
     unsigned int size = offSize;
     const HBUINT8 *p = offsets + size * index;
-    unsigned int offset = 0;
-    for (; size; size--)
-      offset = (offset << 8) + *p++;
-    return offset;
+    switch (size)
+    {
+      case 1: return * (HBUINT8  *) p;
+      case 2: return * (HBUINT16 *) p;
+      case 3: return * (HBUINT24 *) p;
+      case 4: return * (HBUINT32 *) p;
+      default: return 0;
+    }
   }
 
   unsigned int length_at (unsigned int index) const
@@ -229,6 +176,7 @@
   hb_ubytes_t operator [] (unsigned int index) const
   {
     if (unlikely (index >= count)) return hb_ubytes_t ();
+    _hb_compiler_memory_r_barrier ();
     unsigned length = length_at (index);
     if (unlikely (!length)) return hb_ubytes_t ();
     return hb_ubytes_t (data_base () + offset_at (index) - 1, length);
@@ -280,7 +228,7 @@
     if (unlikely (!c->extend_min (this))) return_trace (false);
     this->count = dataArrayLen;
     this->offSize = offSize_;
-    if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
+    if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1), false)))
       return_trace (false);
 
     /* serialize indices */
@@ -288,10 +236,10 @@
     unsigned int  i = 0;
     for (; i < dataArrayLen; i++)
     {
-      CFFIndex<COUNT>::set_offset_at (i, offset);
+      this->set_offset_at (i, offset);
       offset += dataSizeArray[i];
     }
-    CFFIndex<COUNT>::set_offset_at (i, offset);
+    this->set_offset_at (i, offset);
 
     /* serialize data */
     for (unsigned int i = 0; i < dataArrayLen; i++)
@@ -324,13 +272,12 @@
   template <typename T, typename V>
   static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, V value, op_code_t intOp)
   {
-    // XXX: not sure why but LLVM fails to compile the following 'unlikely' macro invocation
-    if (/*unlikely*/ (!serialize_int<T, V> (c, intOp, value)))
+    if (unlikely ((!serialize_int<T, V> (c, intOp, value))))
       return false;
 
     TRACE_SERIALIZE (this);
     /* serialize the opcode */
-    HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op));
+    HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op), false);
     if (unlikely (!p)) return_trace (false);
     if (Is_OpCode_ESC (op))
     {
@@ -415,9 +362,8 @@
     TRACE_SANITIZE (this);
     if (unlikely (!(c->check_struct (this))))
       return_trace (false);
-    for (unsigned int i = 0; i < c->get_num_glyphs (); i++)
-      if (unlikely (!fds[i].sanitize (c)))
-	return_trace (false);
+    if (unlikely (!c->check_array (fds, c->get_num_glyphs ())))
+      return_trace (false);
 
     return_trace (true);
   }
@@ -471,14 +417,20 @@
     return_trace (true);
   }
 
+  static int _cmp_range (const void *_key, const void *_item)
+  {
+    hb_codepoint_t glyph = * (hb_codepoint_t *) _key;
+    FDSelect3_4_Range<GID_TYPE, FD_TYPE> *range = (FDSelect3_4_Range<GID_TYPE, FD_TYPE> *) _item;
+
+    if (glyph < range[0].first) return -1;
+    if (glyph < range[1].first) return 0;
+    return +1;
+  }
+
   hb_codepoint_t get_fd (hb_codepoint_t glyph) const
   {
-    unsigned int i;
-    for (i = 1; i < nRanges (); i++)
-      if (glyph < ranges[i].first)
-	break;
-
-    return (hb_codepoint_t) ranges[i - 1].fd;
+    auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range);
+    return range ? range->fd : ranges[nRanges () - 1].fd;
   }
 
   GID_TYPE        &nRanges ()       { return ranges.len; }
@@ -501,9 +453,9 @@
   {
     TRACE_SERIALIZE (this);
     unsigned int size = src.get_size (num_glyphs);
-    FDSelect *dest = c->allocate_size<FDSelect> (size);
+    FDSelect *dest = c->allocate_size<FDSelect> (size, false);
     if (unlikely (!dest)) return_trace (false);
-    memcpy (dest, &src, size);
+    hb_memcpy (dest, &src, size);
     return_trace (true);
   }
 
diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh
index 17b0296..bb856c9 100644
--- a/src/hb-ot-cff1-table.hh
+++ b/src/hb-ot-cff1-table.hh
@@ -175,7 +175,7 @@
     unsigned int size = src.get_size ();
     Encoding *dest = c->allocate_size<Encoding> (size);
     if (unlikely (!dest)) return_trace (false);
-    memcpy (dest, &src, size);
+    hb_memcpy (dest, &src, size);
     return_trace (true);
   }
 
@@ -471,7 +471,7 @@
     unsigned int size = src.get_size (num_glyphs);
     Charset *dest = c->allocate_size<Charset> (size);
     if (unlikely (!dest)) return_trace (false);
-    memcpy (dest, &src, size);
+    hb_memcpy (dest, &src, size);
     return_trace (true);
   }
 
@@ -617,7 +617,6 @@
     }
 
     byte_str_array_t bytesArray;
-    bytesArray.init ();
     if (!bytesArray.resize (sidmap.get_population ()))
       return_trace (false);
     for (unsigned int i = 0; i < strings.count; i++)
@@ -628,7 +627,6 @@
     }
 
     bool result = CFF1Index::serialize (c, bytesArray);
-    bytesArray.fini ();
     return_trace (result);
   }
 };
@@ -813,7 +811,7 @@
 	break;
 
       default:
-	env.last_offset = env.str_ref.offset;
+	env.last_offset = env.str_ref.get_offset ();
 	top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
 	/* Record this operand below if stack is empty, otherwise done */
 	if (!env.argStack.is_empty ()) return;
@@ -1295,10 +1293,10 @@
     }
 
     protected:
-    hb_blob_t	           *blob = nullptr;
     hb_sanitize_context_t   sc;
 
     public:
+    hb_blob_t               *blob = nullptr;
     const Encoding	    *encoding = nullptr;
     const Charset	    *charset = nullptr;
     const CFF1NameIndex     *nameIndex = nullptr;
diff --git a/src/hb-ot-cff2-table.hh b/src/hb-ot-cff2-table.hh
index 746160d..9081930 100644
--- a/src/hb-ot-cff2-table.hh
+++ b/src/hb-ot-cff2-table.hh
@@ -56,7 +56,7 @@
     unsigned int size = src.get_size (num_glyphs);
     CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size);
     if (unlikely (!dest)) return_trace (false);
-    memcpy (dest, &src, size);
+    hb_memcpy (dest, &src, size);
     return_trace (true);
   }
 
@@ -124,7 +124,7 @@
     unsigned int size_ = varStore->get_size ();
     CFF2VariationStore *dest = c->allocate_size<CFF2VariationStore> (size_);
     if (unlikely (!dest)) return_trace (false);
-    memcpy (dest, varStore, size_);
+    hb_memcpy (dest, varStore, size_);
     return_trace (true);
   }
 
@@ -483,13 +483,18 @@
       blob = nullptr;
     }
 
+    hb_map_t *create_glyph_to_sid_map () const
+    {
+      return nullptr;
+    }
+
     bool is_valid () const { return blob; }
 
     protected:
-    hb_blob_t			*blob = nullptr;
     hb_sanitize_context_t	sc;
 
     public:
+    hb_blob_t			*blob = nullptr;
     cff2_top_dict_values_t	topDict;
     const CFF2Subrs		*globalSubrs = nullptr;
     const CFF2VariationStore	*varStore = nullptr;
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index 09c9fe9..523196f 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -909,7 +909,7 @@
       hb_codepoint_t first = arrayZ[i].startUnicodeValue;
       hb_codepoint_t last = hb_min ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
 				    (hb_codepoint_t) HB_UNICODE_MAX);
-      out->add_range (first, hb_min (last, 0x10FFFFu));
+      out->add_range (first, last);
     }
   }
 
@@ -925,37 +925,75 @@
     if (unlikely (!c->copy<HBUINT32> (len))) return nullptr;
     unsigned init_len = c->length ();
 
-    hb_codepoint_t lastCode = HB_MAP_VALUE_INVALID;
-    int count = -1;
-
-    for (const UnicodeValueRange& _ : as_array ())
+    if (this->len > unicodes->get_population () * hb_bit_storage ((unsigned) this->len))
     {
-      for (const unsigned addcnt : hb_range ((unsigned) _.additionalCount + 1))
-      {
-	unsigned curEntry = (unsigned) _.startUnicodeValue + addcnt;
-	if (!unicodes->has (curEntry)) continue;
-	count += 1;
-	if (lastCode == HB_MAP_VALUE_INVALID)
-	  lastCode = curEntry;
-	else if (lastCode + count != curEntry)
-	{
-	  UnicodeValueRange rec;
-	  rec.startUnicodeValue = lastCode;
-	  rec.additionalCount = count - 1;
-	  c->copy<UnicodeValueRange> (rec);
+      hb_codepoint_t start = HB_SET_VALUE_INVALID;
+      hb_codepoint_t end = HB_SET_VALUE_INVALID;
 
-	  lastCode = curEntry;
-	  count = 0;
+      for (hb_codepoint_t u = HB_SET_VALUE_INVALID;
+	   unicodes->next (&u);)
+      {
+        if (!as_array ().bsearch (u))
+	  continue;
+	if (start == HB_SET_VALUE_INVALID)
+	{
+	  start = u;
+	  end = start - 1;
+	}
+	if (end + 1 != u || end - start == 255)
+        {
+	  UnicodeValueRange rec;
+	  rec.startUnicodeValue = start;
+	  rec.additionalCount = end - start;
+	  c->copy<UnicodeValueRange> (rec);
+	  start = u;
+	}
+	end = u;
+      }
+      if (start != HB_SET_VALUE_INVALID)
+      {
+	UnicodeValueRange rec;
+	rec.startUnicodeValue = start;
+	rec.additionalCount = end - start;
+	c->copy<UnicodeValueRange> (rec);
+      }
+
+    }
+    else
+    {
+      hb_codepoint_t lastCode = HB_SET_VALUE_INVALID;
+      int count = -1;
+
+      for (const UnicodeValueRange& _ : *this)
+      {
+	hb_codepoint_t curEntry = (hb_codepoint_t) (_.startUnicodeValue - 1);
+	hb_codepoint_t end = curEntry + _.additionalCount + 2;
+
+	for (; unicodes->next (&curEntry) && curEntry < end;)
+	{
+	  count += 1;
+	  if (lastCode == HB_SET_VALUE_INVALID)
+	    lastCode = curEntry;
+	  else if (lastCode + count != curEntry)
+	  {
+	    UnicodeValueRange rec;
+	    rec.startUnicodeValue = lastCode;
+	    rec.additionalCount = count - 1;
+	    c->copy<UnicodeValueRange> (rec);
+
+	    lastCode = curEntry;
+	    count = 0;
+	  }
 	}
       }
-    }
 
-    if (lastCode != HB_MAP_VALUE_INVALID)
-    {
-      UnicodeValueRange rec;
-      rec.startUnicodeValue = lastCode;
-      rec.additionalCount = count;
-      c->copy<UnicodeValueRange> (rec);
+      if (lastCode != HB_MAP_VALUE_INVALID)
+      {
+	UnicodeValueRange rec;
+	rec.startUnicodeValue = lastCode;
+	rec.additionalCount = count;
+	c->copy<UnicodeValueRange> (rec);
+      }
     }
 
     if (c->length () - init_len == 0)
@@ -1474,32 +1512,80 @@
   DEFINE_SIZE_STATIC (8);
 };
 
+struct cmap;
+
 struct SubtableUnicodesCache {
 
  private:
-  const void* base;
-  hb_hashmap_t<intptr_t, hb::unique_ptr<hb_set_t>> cached_unicodes;
+  hb_blob_ptr_t<cmap> base_blob;
+  const char* base;
+  hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> cached_unicodes;
 
  public:
-  SubtableUnicodesCache(const void* cmap_base)
-      : base(cmap_base), cached_unicodes() {}
 
-  hb_set_t* set_for (const EncodingRecord* record)
+  static SubtableUnicodesCache* create (hb_blob_ptr_t<cmap> source_table)
   {
-    if (!cached_unicodes.has ((intptr_t) record))
+    SubtableUnicodesCache* cache =
+        (SubtableUnicodesCache*) hb_malloc (sizeof(SubtableUnicodesCache));
+    new (cache) SubtableUnicodesCache (source_table);
+    return cache;
+  }
+
+  static void destroy (void* value) {
+    if (!value) return;
+
+    SubtableUnicodesCache* cache = (SubtableUnicodesCache*) value;
+    cache->~SubtableUnicodesCache ();
+    hb_free (cache);
+  }
+
+  SubtableUnicodesCache(const void* cmap_base)
+      : base_blob(),
+        base ((const char*) cmap_base),
+        cached_unicodes ()
+  {}
+
+  SubtableUnicodesCache(hb_blob_ptr_t<cmap> base_blob_)
+      : base_blob(base_blob_),
+        base ((const char *) base_blob.get()),
+        cached_unicodes ()
+  {}
+
+  ~SubtableUnicodesCache()
+  {
+    base_blob.destroy ();
+  }
+
+  bool same_base(const void* other) const
+  {
+    return other == (const void*) base;
+  }
+
+  const hb_set_t* set_for (const EncodingRecord* record,
+                           SubtableUnicodesCache& mutable_cache) const
+  {
+    if (cached_unicodes.has ((unsigned) ((const char *) record - base)))
+      return cached_unicodes.get ((unsigned) ((const char *) record - base));
+
+    return mutable_cache.set_for (record);
+  }
+
+  const hb_set_t* set_for (const EncodingRecord* record)
+  {
+    if (!cached_unicodes.has ((unsigned) ((const char *) record - base)))
     {
       hb_set_t *s = hb_set_create ();
       if (unlikely (s->in_error ()))
 	return hb_set_get_empty ();
-	
+
       (base+record->subtable).collect_unicodes (s);
 
-      if (unlikely (!cached_unicodes.set ((intptr_t) record, hb::unique_ptr<hb_set_t> {s})))
+      if (unlikely (!cached_unicodes.set ((unsigned) ((const char *) record - base), hb::unique_ptr<hb_set_t> {s})))
         return hb_set_get_empty ();
 
       return s;
     }
-    return cached_unicodes.get ((intptr_t) record);
+    return cached_unicodes.get ((unsigned) ((const char *) record - base));
   }
 
 };
@@ -1523,13 +1609,30 @@
 {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
 
+
+  static SubtableUnicodesCache* create_filled_cache(hb_blob_ptr_t<cmap> source_table) {
+    const cmap* cmap = source_table.get();
+    auto it =
+    + hb_iter (cmap->encodingRecord)
+    | hb_filter ([&](const EncodingRecord& _) {
+      return cmap::filter_encoding_records_for_subset (cmap, _);
+    })
+    ;
+
+    SubtableUnicodesCache* cache = SubtableUnicodesCache::create(source_table);
+    for (const EncodingRecord& _ : it)
+      cache->set_for(&_); // populate the cache for this encoding record.
+
+    return cache;
+  }
+
   template<typename Iterator, typename EncodingRecIter,
 	   hb_requires (hb_is_iterator (EncodingRecIter))>
   bool serialize (hb_serialize_context_t *c,
 		  Iterator it,
 		  EncodingRecIter encodingrec_iter,
 		  const void *base,
-		  const hb_subset_plan_t *plan,
+		  hb_subset_plan_t *plan,
                   bool drop_format_4 = false)
   {
     if (unlikely (!c->extend_min ((*this))))  return false;
@@ -1538,7 +1641,14 @@
     unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0;
     auto snap = c->snapshot ();
 
-    SubtableUnicodesCache unicodes_cache (base);
+    SubtableUnicodesCache local_unicodes_cache (base);
+    const SubtableUnicodesCache* unicodes_cache = &local_unicodes_cache;
+
+    if (plan->accelerator &&
+        plan->accelerator->cmap_cache &&
+        plan->accelerator->cmap_cache->same_base (base))
+      unicodes_cache = plan->accelerator->cmap_cache;
+
     for (const EncodingRecord& _ : encodingrec_iter)
     {
       if (c->in_error ())
@@ -1547,7 +1657,7 @@
       unsigned format = (base+_.subtable).u.format;
       if (format != 4 && format != 12 && format != 14) continue;
 
-      hb_set_t* unicodes_set = unicodes_cache.set_for (&_);
+      const hb_set_t* unicodes_set = unicodes_cache->set_for (&_, local_unicodes_cache);
 
       if (!drop_format_4 && format == 4)
       {
@@ -1566,7 +1676,13 @@
 
       else if (format == 12)
       {
-        if (_can_drop (_, *unicodes_set, base, unicodes_cache, + it | hb_map (hb_first), encodingrec_iter)) continue;
+        if (_can_drop (_,
+                       *unicodes_set,
+                       base,
+                       *unicodes_cache,
+                       local_unicodes_cache,
+                       + it | hb_map (hb_first), encodingrec_iter))
+          continue;
         c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 12u, base, plan, &format12objidx);
       }
       else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
@@ -1585,7 +1701,8 @@
   bool _can_drop (const EncodingRecord& cmap12,
                   const hb_set_t& cmap12_unicodes,
                   const void* base,
-                  SubtableUnicodesCache& unicodes_cache,
+                  const SubtableUnicodesCache& unicodes_cache,
+                  SubtableUnicodesCache& local_unicodes_cache,
                   Iterator subset_unicodes,
                   EncodingRecordIterator encoding_records)
   {
@@ -1616,7 +1733,7 @@
           || (base+_.subtable).get_language() != target_language)
         continue;
 
-      hb_set_t* sibling_unicodes = unicodes_cache.set_for (&_);
+      const hb_set_t* sibling_unicodes = unicodes_cache.set_for (&_, local_unicodes_cache);
 
       auto cmap12 = + subset_unicodes | hb_filter (cmap12_unicodes);
       auto sibling = + subset_unicodes | hb_filter (*sibling_unicodes);
@@ -1653,17 +1770,9 @@
 
     auto encodingrec_iter =
     + hb_iter (encodingRecord)
-    | hb_filter ([&] (const EncodingRecord& _)
-		{
-		  if ((_.platformID == 0 && _.encodingID == 3) ||
-		      (_.platformID == 0 && _.encodingID == 4) ||
-		      (_.platformID == 3 && _.encodingID == 1) ||
-		      (_.platformID == 3 && _.encodingID == 10) ||
-		      (this + _.subtable).u.format == 14)
-		    return true;
-
-		  return false;
-		})
+    | hb_filter ([&](const EncodingRecord& _) {
+      return cmap::filter_encoding_records_for_subset (this, _);
+    })
     ;
 
     if (unlikely (!encodingrec_iter.len ())) return_trace (false);
@@ -1692,7 +1801,11 @@
 		 { return (_.second != HB_MAP_VALUE_INVALID); })
     ;
 
-    return_trace (cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan));
+    return_trace (cmap_prime->serialize (c->serializer,
+                                         it,
+                                         encodingrec_iter,
+                                         this,
+                                         c->plan));
   }
 
   const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
@@ -1928,6 +2041,19 @@
 		  encodingRecord.sanitize (c, this));
   }
 
+ private:
+
+  static bool filter_encoding_records_for_subset(const cmap* cmap,
+                                                 const EncodingRecord& _)
+  {
+    return
+        (_.platformID == 0 && _.encodingID == 3) ||
+        (_.platformID == 0 && _.encodingID == 4) ||
+        (_.platformID == 3 && _.encodingID == 1) ||
+        (_.platformID == 3 && _.encodingID == 10) ||
+        (cmap + _.subtable).u.format == 14;
+  }
+
   protected:
   HBUINT16	version;	/* Table version number (0). */
   SortedArray16Of<EncodingRecord>
diff --git a/src/hb-ot-color-cbdt-table.hh b/src/hb-ot-color-cbdt-table.hh
index 23fa56c..3246894 100644
--- a/src/hb-ot-color-cbdt-table.hh
+++ b/src/hb-ot-color-cbdt-table.hh
@@ -67,7 +67,7 @@
 {
   unsigned int new_len = cbdt_prime->length + length;
   if (unlikely (!cbdt_prime->alloc (new_len))) return false;
-  memcpy (cbdt_prime->arrayZ + cbdt_prime->length, data, length);
+  hb_memcpy (cbdt_prime->arrayZ + cbdt_prime->length, data, length);
   cbdt_prime->length = new_len;
   return true;
 }
@@ -468,13 +468,13 @@
     if (unlikely (!c->serializer->check_success (records->resize (records->length + 1))))
       return_trace (false);
 
-    (*records)[records->length - 1].firstGlyphIndex = 1;
-    (*records)[records->length - 1].lastGlyphIndex = 0;
+    records->tail ().firstGlyphIndex = 1;
+    records->tail ().lastGlyphIndex = 0;
     bitmap_size_context->size += IndexSubtableRecord::min_size;
 
     c->serializer->push ();
 
-    if (unlikely (!add_new_subtable (c, bitmap_size_context, &((*records)[records->length - 1]), lookup, base, start)))
+    if (unlikely (!add_new_subtable (c, bitmap_size_context, &(records->tail ()), lookup, base, start)))
     {
       c->serializer->pop_discard ();
       c->serializer->revert (snap);
diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh
index 908bf55..1af9d30 100644
--- a/src/hb-ot-color-colr-table.hh
+++ b/src/hb-ot-color-colr-table.hh
@@ -39,11 +39,7 @@
 #define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
 
 #ifndef HB_COLRV1_MAX_NESTING_LEVEL
-#define HB_COLRV1_MAX_NESTING_LEVEL	100
-#endif
-
-#ifndef COLRV1_ENABLE_SUBSETTING
-#define COLRV1_ENABLE_SUBSETTING 1
+#define HB_COLRV1_MAX_NESTING_LEVEL	16
 #endif
 
 namespace OT {
@@ -188,6 +184,7 @@
 
   protected:
   T      value;
+  public:
   VarIdx varIdxBase;
   public:
   DEFINE_SIZE_STATIC (4 + T::static_size);
@@ -196,6 +193,8 @@
 template <typename T>
 struct NoVariable
 {
+  static constexpr uint32_t varIdxBase = VarIdx::NO_VARIATION;
+
   NoVariable<T>* copy (hb_serialize_context_t *c) const
   {
     TRACE_SERIALIZE (this);
@@ -888,6 +887,11 @@
   DEFINE_SIZE_STATIC (8);
 };
 
+struct ClipBoxData
+{
+  int xMin, yMin, xMax, yMax;
+};
+
 struct ClipBoxFormat1
 {
   bool sanitize (hb_sanitize_context_t *c) const
@@ -896,6 +900,14 @@
     return_trace (c->check_struct (this));
   }
 
+  void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer HB_UNUSED) const
+  {
+    clip_box.xMin = xMin;
+    clip_box.yMin = yMin;
+    clip_box.xMax = xMax;
+    clip_box.yMax = yMax;
+  }
+
   public:
   HBUINT8	format; /* format = 1(noVar) or 2(Var)*/
   FWORD		xMin;
@@ -906,7 +918,20 @@
   DEFINE_SIZE_STATIC (1 + 4 * FWORD::static_size);
 };
 
-struct ClipBoxFormat2 : Variable<ClipBoxFormat1> {};
+struct ClipBoxFormat2 : Variable<ClipBoxFormat1>
+{
+  void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer) const
+  {
+    value.get_clip_box(clip_box, instancer);
+    if (instancer)
+    {
+      clip_box.xMin += _hb_roundf (instancer (varIdxBase, 0));
+      clip_box.yMin += _hb_roundf (instancer (varIdxBase, 1));
+      clip_box.xMax += _hb_roundf (instancer (varIdxBase, 2));
+      clip_box.yMax += _hb_roundf (instancer (varIdxBase, 3));
+    }
+  }
+};
 
 struct ClipBox
 {
@@ -932,6 +957,28 @@
     }
   }
 
+  bool get_extents (hb_glyph_extents_t *extents,
+                    const VarStoreInstancer &instancer) const
+  {
+    ClipBoxData clip_box;
+    switch (u.format) {
+    case 1:
+      u.format1.get_clip_box (clip_box, instancer);
+      break;
+    case 2:
+      u.format2.get_clip_box (clip_box, instancer);
+      break;
+    default:
+      return false;
+    }
+
+    extents->x_bearing = clip_box.xMin;
+    extents->y_bearing = clip_box.yMax;
+    extents->width = clip_box.xMax - clip_box.xMin;
+    extents->height = clip_box.yMin - clip_box.yMax;
+    return true;
+  }
+
   protected:
   union {
   HBUINT8		format;         /* Format identifier */
@@ -942,6 +989,9 @@
 
 struct ClipRecord
 {
+  int cmp (hb_codepoint_t g) const
+  { return g < startGlyphID ? -1 : g <= endGlyphID ? 0 : +1; }
+
   ClipRecord* copy (hb_serialize_context_t *c, const void *base) const
   {
     TRACE_SERIALIZE (this);
@@ -957,6 +1007,13 @@
     return_trace (c->check_struct (this) && clipBox.sanitize (c, base));
   }
 
+  bool get_extents (hb_glyph_extents_t *extents,
+		    const void *base,
+		    const VarStoreInstancer &instancer) const
+  {
+    return (base+clipBox).get_extents (extents, instancer);
+  }
+
   public:
   HBUINT16		startGlyphID;  // first gid clip applies to
   HBUINT16		endGlyphID;    // last gid clip applies to, inclusive
@@ -964,6 +1021,7 @@
   public:
   DEFINE_SIZE_STATIC (7);
 };
+DECLARE_NULL_NAMESPACE_BYTES (OT, ClipRecord);
 
 struct ClipList
 {
@@ -1052,11 +1110,26 @@
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
+    // TODO Make a formatted struct!
     return_trace (c->check_struct (this) && clips.sanitize (c, this));
   }
 
+  bool
+  get_extents (hb_codepoint_t gid,
+	       hb_glyph_extents_t *extents,
+	       const VarStoreInstancer &instancer) const
+  {
+    auto *rec = clips.as_array ().bsearch (gid);
+    if (rec)
+    {
+      rec->get_extents (extents, this, instancer);
+      return true;
+    }
+    return false;
+  }
+
   HBUINT8			format;  // Set to 1.
-  Array32Of<ClipRecord>		clips;  // Clip records, sorted by startGlyphID
+  SortedArray32Of<ClipRecord>	clips;  // Clip records, sorted by startGlyphID
   public:
   DEFINE_SIZE_ARRAY_SIZED (5, clips);
 };
@@ -1359,7 +1432,7 @@
                   (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
                   (this+layersZ).sanitize (c, numLayers) &&
                   (version == 0 ||
-		   (COLRV1_ENABLE_SUBSETTING && version == 1 &&
+		   (version == 1 &&
 		    baseGlyphList.sanitize (c, this) &&
 		    layerList.sanitize (c, this) &&
 		    clipList.sanitize (c, this) &&
@@ -1516,6 +1589,30 @@
     return_trace (true);
   }
 
+  bool
+  get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+  {
+    if (version != 1)
+      return false;
+
+    VarStoreInstancer instancer (this+varStore,
+				 this+varIdxMap,
+				 hb_array (font->coords, font->num_coords));
+
+    if ((this+clipList).get_extents (glyph,
+				     extents,
+				     instancer))
+    {
+      extents->x_bearing = font->em_scale_x (extents->x_bearing);
+      extents->y_bearing = font->em_scale_x (extents->y_bearing);
+      extents->width = font->em_scale_x (extents->width);
+      extents->height = font->em_scale_x (extents->height);
+      return true;
+    }
+
+    return false;
+  }
+
   protected:
   HBUINT16	version;	/* Table version number (starts at 0). */
   HBUINT16	numBaseGlyphs;	/* Number of Base Glyph Records. */
diff --git a/src/hb-ot-face-table-list.hh b/src/hb-ot-face-table-list.hh
index c05034b..c9da36c 100644
--- a/src/hb-ot-face-table-list.hh
+++ b/src/hb-ot-face-table-list.hh
@@ -56,9 +56,9 @@
 #if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT)
 HB_OT_ACCELERATOR (OT, cmap)
 #endif
-HB_OT_TABLE (OT, hhea)
+HB_OT_CORE_TABLE (OT, hhea)
 HB_OT_ACCELERATOR (OT, hmtx)
-HB_OT_TABLE (OT, OS2)
+HB_OT_CORE_TABLE (OT, OS2)
 #if !defined(HB_NO_OT_FONT_GLYPH_NAMES) || !defined(HB_NO_METRICS) || !defined(HB_NO_STYLE)
 HB_OT_ACCELERATOR (OT, post)
 #endif
@@ -66,7 +66,7 @@
 HB_OT_ACCELERATOR (OT, name)
 #endif
 #ifndef HB_NO_STYLE
-HB_OT_TABLE (OT, STAT)
+HB_OT_CORE_TABLE (OT, STAT)
 #endif
 #ifndef HB_NO_META
 HB_OT_ACCELERATOR (OT, meta)
@@ -74,9 +74,9 @@
 
 /* Vertical layout. */
 #ifndef HB_NO_VERTICAL
-HB_OT_TABLE (OT, vhea)
+HB_OT_CORE_TABLE (OT, vhea)
 HB_OT_ACCELERATOR (OT, vmtx)
-HB_OT_TABLE (OT, VORG)
+HB_OT_CORE_TABLE (OT, VORG)
 #endif
 
 /* TrueType outlines. */
@@ -91,15 +91,15 @@
 
 /* OpenType variations. */
 #ifndef HB_NO_VAR
-HB_OT_TABLE (OT, fvar)
-HB_OT_TABLE (OT, avar)
+HB_OT_CORE_TABLE (OT, fvar)
+HB_OT_CORE_TABLE (OT, avar)
 HB_OT_ACCELERATOR (OT, gvar)
-HB_OT_TABLE (OT, MVAR)
+HB_OT_CORE_TABLE (OT, MVAR)
 #endif
 
 /* Legacy kern. */
 #ifndef HB_NO_OT_KERN
-HB_OT_TABLE (OT, kern)
+HB_OT_CORE_TABLE (OT, kern)
 #endif
 
 /* OpenType shaping. */
@@ -107,12 +107,12 @@
 HB_OT_ACCELERATOR (OT, GDEF)
 HB_OT_ACCELERATOR (OT, GSUB)
 HB_OT_ACCELERATOR (OT, GPOS)
-//HB_OT_TABLE (OT, JSTF)
+//HB_OT_CORE_TABLE (OT, JSTF)
 #endif
 
 /* OpenType baseline. */
 #ifndef HB_NO_BASE
-HB_OT_TABLE (OT, BASE)
+HB_OT_CORE_TABLE (OT, BASE)
 #endif
 
 /* AAT shaping. */
@@ -129,8 +129,8 @@
 
 /* OpenType color fonts. */
 #ifndef HB_NO_COLOR
-HB_OT_TABLE (OT, COLR)
-HB_OT_TABLE (OT, CPAL)
+HB_OT_CORE_TABLE (OT, COLR)
+HB_OT_CORE_TABLE (OT, CPAL)
 HB_OT_ACCELERATOR (OT, CBDT)
 HB_OT_ACCELERATOR (OT, sbix)
 HB_OT_ACCELERATOR (OT, SVG)
@@ -138,7 +138,7 @@
 
 /* OpenType math. */
 #ifndef HB_NO_MATH
-HB_OT_TABLE (OT, MATH)
+HB_OT_CORE_TABLE (OT, MATH)
 #endif
 
 
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 825b308..8405103 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -45,6 +45,7 @@
 #include "hb-ot-vorg-table.hh"
 #include "hb-ot-color-cbdt-table.hh"
 #include "hb-ot-color-sbix-table.hh"
+#include "hb-ot-color-colr-table.hh"
 
 
 /**
@@ -350,13 +351,15 @@
   if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
   if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
 #endif
+#if !defined(HB_NO_COLOR)
+  if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
+#endif
   if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
 #ifndef HB_NO_OT_FONT_CFF
   if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
   if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
 #endif
 
-  // TODO Hook up side-bearings variations.
   return false;
 }
 
diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh
index 579abf0..0f424f5 100644
--- a/src/hb-ot-layout-common.hh
+++ b/src/hb-ot-layout-common.hh
@@ -478,7 +478,7 @@
   {
     if (_count)
     {
-      + this->sub_array (start_offset, _count)
+      + this->as_array ().sub_array (start_offset, _count)
       | hb_sink (hb_array (_indexes, *_count))
       ;
     }
@@ -658,7 +658,7 @@
   {
     if (char_count)
     {
-      + characters.sub_array (start_offset, char_count)
+      + characters.as_array ().sub_array (start_offset, char_count)
       | hb_sink (hb_array (chars, *char_count))
       ;
     }
@@ -932,7 +932,7 @@
   {
     if (record_count)
     {
-      + this->sub_array (start_offset, record_count)
+      + this->as_array ().sub_array (start_offset, record_count)
       | hb_map (&Record<Type>::tag)
       | hb_sink (hb_array (record_tags, *record_count))
       ;
@@ -980,18 +980,16 @@
     auto *out = c->serializer->start_embed (*this);
     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
 
-    unsigned count = this->len;
-
-    + hb_zip (*this, hb_range (count))
-    | hb_filter (l->feature_index_map, hb_second)
-    | hb_apply ([l, out, this] (const hb_pair_t<const Record<Feature>&, unsigned>& _)
+    + hb_enumerate (*this)
+    | hb_filter (l->feature_index_map, hb_first)
+    | hb_apply ([l, out, this] (const hb_pair_t<unsigned, const Record<Feature>&>& _)
                 {
                   const Feature *f_sub = nullptr;
                   const Feature **f = nullptr;
-                  if (l->feature_substitutes_map->has (_.second, &f))
+                  if (l->feature_substitutes_map->has (_.first, &f))
                     f_sub = *f;
 
-                  subset_record_array (l, out, this, f_sub) (_.first);
+                  subset_record_array (l, out, this, f_sub) (_.second);
                 })
     ;
 
@@ -1079,7 +1077,7 @@
     auto *out = c->serializer->start_embed (*this);
     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
 
-    const unsigned *v;
+    const uint32_t *v;
     out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu;
 
     if (!l->visitFeatureIndex (featureIndex.len))
@@ -1147,7 +1145,6 @@
 	return;
     }
 
-    unsigned langsys_count = get_lang_sys_count ();
     if (has_default_lang_sys ())
     {
       //only collect features from non-redundant langsys
@@ -1156,24 +1153,24 @@
         d.collect_features (c);
       }
 
-      for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
+      for (auto _ : + hb_enumerate (langSys))
       {
-        const LangSys& l = this+_.first.offset;
+        const LangSys& l = this+_.second.offset;
         if (!c->visitLangsys (l.get_feature_count ())) continue;
         if (l.compare (d, c->duplicate_feature_map)) continue;
 
         l.collect_features (c);
-        c->script_langsys_map->get (script_index)->add (_.second);
+        c->script_langsys_map->get (script_index)->add (_.first);
       }
     }
     else
     {
-      for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
+      for (auto _ : + hb_enumerate (langSys))
       {
-        const LangSys& l = this+_.first.offset;
+        const LangSys& l = this+_.second.offset;
         if (!c->visitLangsys (l.get_feature_count ())) continue;
         l.collect_features (c);
-        c->script_langsys_map->get (script_index)->add (_.second);
+        c->script_langsys_map->get (script_index)->add (_.first);
       }
     }
   }
@@ -1211,10 +1208,9 @@
     const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index);
     if (active_langsys)
     {
-      unsigned count = langSys.len;
-      + hb_zip (langSys, hb_range (count))
-      | hb_filter (active_langsys, hb_second)
-      | hb_map (hb_first)
+      + hb_enumerate (langSys)
+      | hb_filter (active_langsys, hb_first)
+      | hb_map (hb_second)
       | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
       | hb_apply (subset_record_array (l, &(out->langSys), this))
       ;
@@ -1250,12 +1246,11 @@
     auto *out = c->serializer->start_embed (*this);
     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
 
-    unsigned count = this->len;
-    for (auto _ : + hb_zip (*this, hb_range (count)))
+    for (auto _ : + hb_enumerate (*this))
     {
       auto snap = c->serializer->snapshot ();
-      l->cur_script_index = _.second;
-      bool ret = _.first.subset (l, this);
+      l->cur_script_index = _.first;
+      bool ret = _.second.subset (l, this);
       if (!ret) c->serializer->revert (snap);
       else out->len++;
     }
@@ -1388,7 +1383,13 @@
       outMarkFilteringSet = markFilteringSet;
     }
 
-    return_trace (out->subTable.len);
+    // Always keep the lookup even if it's empty. The rest of layout subsetting depends on lookup
+    // indices being consistent with those computed during planning. So if an empty lookup is
+    // discarded during the subset phase it will invalidate all subsequent lookup indices.
+    // Generally we shouldn't end up with an empty lookup as we pre-prune them during the planning
+    // phase, but it can happen in rare cases such as when during closure subtable is considered
+    // degenerate (see: https://github.com/harfbuzz/harfbuzz/issues/3853)
+    return true;
   }
 
   template <typename TSubTable>
@@ -1454,10 +1455,9 @@
     auto *out = c->serializer->start_embed (this);
     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
 
-    unsigned count = this->len;
-    + hb_zip (*this, hb_range (count))
-    | hb_filter (l->lookup_index_map, hb_second)
-    | hb_map (hb_first)
+    + hb_enumerate (*this)
+    | hb_filter (l->lookup_index_map, hb_first)
+    | hb_map (hb_second)
     | hb_apply (subset_offset_array (c, *out, this))
     ;
     return_trace (true);
@@ -1491,7 +1491,7 @@
     klass_map->set (0, 0);
 
   unsigned idx = klass_map->has (0) ? 1 : 0;
-  for (const unsigned k: klasses.iter ())
+  for (const unsigned k: klasses)
   {
     if (klass_map->has (k)) continue;
     klass_map->set (k, idx);
@@ -1524,6 +1524,11 @@
     return classValue[(unsigned int) (glyph_id - startGlyph)];
   }
 
+  unsigned get_population () const
+  {
+    return classValue.len;
+  }
+
   template<typename Iterator,
 	   hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
   bool serialize (hb_serialize_context_t *c,
@@ -1548,7 +1553,7 @@
 
     startGlyph = glyph_min;
     if (unlikely (!classValue.serialize (c, glyph_count))) return_trace (false);
-    for (const hb_pair_t<hb_codepoint_t, unsigned> gid_klass_pair : + it)
+    for (const hb_pair_t<hb_codepoint_t, uint32_t> gid_klass_pair : + it)
     {
       unsigned idx = gid_klass_pair.first - glyph_min;
       classValue[idx] = gid_klass_pair.second;
@@ -1639,11 +1644,10 @@
 
   bool intersects (const hb_set_t *glyphs) const
   {
-    /* TODO Speed up, using hb_set_next()? */
     hb_codepoint_t start = startGlyph;
     hb_codepoint_t end = startGlyph + classValue.len;
     for (hb_codepoint_t iter = startGlyph - 1;
-	 hb_set_next (glyphs, &iter) && iter < end;)
+	 glyphs->next (&iter) && iter < end;)
       if (classValue[iter - start]) return true;
     return false;
   }
@@ -1654,10 +1658,10 @@
     {
       /* Match if there's any glyph that is not listed! */
       hb_codepoint_t g = HB_SET_VALUE_INVALID;
-      if (!hb_set_next (glyphs, &g)) return false;
+      if (!glyphs->next (&g)) return false;
       if (g < startGlyph) return true;
       g = startGlyph + count - 1;
-      if (hb_set_next (glyphs, &g)) return true;
+      if (glyphs->next (&g)) return true;
       /* Fall through. */
     }
     /* TODO Speed up, using set overlap first? */
@@ -1675,12 +1679,12 @@
     if (klass == 0)
     {
       unsigned start_glyph = startGlyph;
-      for (unsigned g = HB_SET_VALUE_INVALID;
-	   hb_set_next (glyphs, &g) && g < start_glyph;)
+      for (uint32_t g = HB_SET_VALUE_INVALID;
+	   glyphs->next (&g) && g < start_glyph;)
 	intersect_glyphs->add (g);
 
-      for (unsigned g = startGlyph + count - 1;
-	   hb_set_next (glyphs, &g);)
+      for (uint32_t g = startGlyph + count - 1;
+	   glyphs-> next (&g);)
 	intersect_glyphs->add (g);
 
       return;
@@ -1696,7 +1700,7 @@
     unsigned start_glyph = startGlyph;
     unsigned end_glyph = start_glyph + count;
     for (unsigned g = startGlyph - 1;
-	 hb_set_next (glyphs, &g) && g < end_glyph;)
+	 glyphs->next (&g) && g < end_glyph;)
       if (classValue.arrayZ[g - start_glyph] == klass)
         intersect_glyphs->add (g);
 #endif
@@ -1739,6 +1743,14 @@
     return rangeRecord.bsearch (glyph_id).value;
   }
 
+  unsigned get_population () const
+  {
+    typename Types::large_int ret = 0;
+    for (const auto &r : rangeRecord)
+      ret += r.get_population ();
+    return ret > UINT_MAX ? UINT_MAX : (unsigned) ret;
+  }
+
   template<typename Iterator,
 	   hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
   bool serialize (hb_serialize_context_t *c,
@@ -1802,28 +1814,45 @@
   {
     TRACE_SUBSET (this);
     const hb_map_t &glyph_map = *c->plan->glyph_map_gsub;
+    const hb_set_t &glyph_set = *c->plan->glyphset_gsub ();
 
     hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
     hb_set_t orig_klasses;
 
-    unsigned num_source_glyphs = c->plan->source->get_num_glyphs ();
-    unsigned count = rangeRecord.len;
-    for (unsigned i = 0; i < count; i++)
+    if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2
+	< get_population ())
     {
-      unsigned klass = rangeRecord[i].value;
-      if (!klass) continue;
-      hb_codepoint_t start = rangeRecord[i].first;
-      hb_codepoint_t end   = hb_min (rangeRecord[i].last + 1, num_source_glyphs);
-      for (hb_codepoint_t g = start; g < end; g++)
+      for (hb_codepoint_t g : glyph_set)
       {
-        hb_codepoint_t new_gid = glyph_map[g];
+	unsigned klass = get_class (g);
+	if (!klass) continue;
+	hb_codepoint_t new_gid = glyph_map[g];
 	if (new_gid == HB_MAP_VALUE_INVALID) continue;
-        if (glyph_filter && !glyph_filter->has (g)) continue;
-
+	if (glyph_filter && !glyph_filter->has (g)) continue;
 	glyph_and_klass.push (hb_pair (new_gid, klass));
 	orig_klasses.add (klass);
       }
     }
+    else
+    {
+      unsigned num_source_glyphs = c->plan->source->get_num_glyphs ();
+      for (auto &range : rangeRecord)
+      {
+	unsigned klass = range.value;
+	if (!klass) continue;
+	hb_codepoint_t start = range.first;
+	hb_codepoint_t end   = hb_min (range.last + 1, num_source_glyphs);
+	for (hb_codepoint_t g = start; g < end; g++)
+	{
+	  hb_codepoint_t new_gid = glyph_map[g];
+	  if (new_gid == HB_MAP_VALUE_INVALID) continue;
+	  if (glyph_filter && !glyph_filter->has (g)) continue;
+
+	  glyph_and_klass.push (hb_pair (new_gid, klass));
+	  orig_klasses.add (klass);
+	}
+      }
+    }
 
     const hb_set_t& glyphset = *c->plan->glyphset_gsub ();
     unsigned glyph_count = glyph_filter
@@ -1850,10 +1879,9 @@
   template <typename set_t>
   bool collect_coverage (set_t *glyphs) const
   {
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (rangeRecord[i].value)
-	if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
+    for (auto &range : rangeRecord)
+      if (range.value)
+	if (unlikely (!range.collect_coverage (glyphs)))
 	  return false;
     return true;
   }
@@ -1861,11 +1889,10 @@
   template <typename set_t>
   bool collect_class (set_t *glyphs, unsigned int klass) const
   {
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
+    for (auto &range : rangeRecord)
     {
-      if (rangeRecord[i].value == klass)
-	if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
+      if (range.value == klass)
+	if (unlikely (!range.collect_coverage (glyphs)))
 	  return false;
     }
     return true;
@@ -1873,32 +1900,32 @@
 
   bool intersects (const hb_set_t *glyphs) const
   {
-    /* TODO Speed up, using hb_set_next() and bsearch()? */
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
+    if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
     {
-      const auto& range = rangeRecord[i];
-      if (range.intersects (*glyphs) && range.value)
-	return true;
+      for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+        if (get_class (g))
+	  return true;
+      return false;
     }
-    return false;
+
+    return hb_any (+ hb_iter (rangeRecord)
+                   | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs) && range.value; }));
   }
   bool intersects_class (const hb_set_t *glyphs, uint16_t klass) const
   {
-    unsigned int count = rangeRecord.len;
     if (klass == 0)
     {
       /* Match if there's any glyph that is not listed! */
       hb_codepoint_t g = HB_SET_VALUE_INVALID;
-      for (unsigned int i = 0; i < count; i++)
+      for (auto &range : rangeRecord)
       {
-	if (!hb_set_next (glyphs, &g))
+	if (!glyphs->next (&g))
 	  break;
-	if (g < rangeRecord[i].first)
+	if (g < range.first)
 	  return true;
-	g = rangeRecord[i].last;
+	g = range.last;
       }
-      if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
+      if (g != HB_SET_VALUE_INVALID && glyphs->next (&g))
 	return true;
       /* Fall through. */
     }
@@ -1910,49 +1937,49 @@
 
   void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const
   {
-    unsigned count = rangeRecord.len;
     if (klass == 0)
     {
       hb_codepoint_t g = HB_SET_VALUE_INVALID;
-      for (unsigned int i = 0; i < count; i++)
+      for (auto &range : rangeRecord)
       {
-	if (!hb_set_next (glyphs, &g))
+	if (!glyphs->next (&g))
 	  goto done;
-	while (g < rangeRecord[i].first)
+	while (g < range.first)
 	{
 	  intersect_glyphs->add (g);
-	  if (!hb_set_next (glyphs, &g))
+	  if (!glyphs->next (&g))
 	    goto done;
         }
-        g = rangeRecord[i].last;
+        g = range.last;
       }
-      while (hb_set_next (glyphs, &g))
+      while (glyphs->next (&g))
 	intersect_glyphs->add (g);
       done:
 
       return;
     }
 
-#if 0
-    /* The following implementation is faster asymptotically, but slower
-     * in practice. */
-    if ((count >> 3) > glyphs->get_population ())
+    unsigned count = rangeRecord.len;
+    if (count > glyphs->get_population () * hb_bit_storage (count) * 8)
     {
       for (hb_codepoint_t g = HB_SET_VALUE_INVALID;
-	   hb_set_next (glyphs, &g);)
-        if (rangeRecord.as_array ().bfind (g))
+	   glyphs->next (&g);)
+      {
+        unsigned i;
+        if (rangeRecord.as_array ().bfind (g, &i) &&
+	    rangeRecord.arrayZ[i].value == klass)
 	  intersect_glyphs->add (g);
+      }
       return;
     }
-#endif
 
-    for (unsigned int i = 0; i < count; i++)
+    for (auto &range : rangeRecord)
     {
-      if (rangeRecord[i].value != klass) continue;
+      if (range.value != klass) continue;
 
-      unsigned end = rangeRecord[i].last + 1;
-      for (hb_codepoint_t g = rangeRecord[i].first - 1;
-	   hb_set_next (glyphs, &g) && g < end;)
+      unsigned end = range.last + 1;
+      for (hb_codepoint_t g = range.first - 1;
+	   glyphs->next (&g) && g < end;)
 	intersect_glyphs->add (g);
     }
   }
@@ -1961,25 +1988,24 @@
   {
     if (glyphs->is_empty ()) return;
 
-    unsigned count = rangeRecord.len;
     hb_codepoint_t g = HB_SET_VALUE_INVALID;
-    for (unsigned int i = 0; i < count; i++)
+    for (auto &range : rangeRecord)
     {
-      if (!hb_set_next (glyphs, &g))
+      if (!glyphs->next (&g))
         break;
-      if (g < rangeRecord[i].first)
+      if (g < range.first)
       {
         intersect_classes->add (0);
         break;
       }
-      g = rangeRecord[i].last;
+      g = range.last;
     }
-    if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
+    if (g != HB_SET_VALUE_INVALID && glyphs->next (&g))
       intersect_classes->add (0);
 
-    for (const auto& record : rangeRecord.iter ())
-      if (record.intersects (*glyphs))
-        intersect_classes->add (record.value);
+    for (const auto& range : rangeRecord)
+      if (range.intersects (*glyphs))
+        intersect_classes->add (range.value);
   }
 
   protected:
@@ -1994,10 +2020,8 @@
 struct ClassDef
 {
   /* Has interface. */
-  static constexpr unsigned SENTINEL = 0;
-  typedef unsigned int value_t;
-  value_t operator [] (hb_codepoint_t k) const { return get (k); }
-  bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+  unsigned operator [] (hb_codepoint_t k) const { return get (k); }
+  bool has (hb_codepoint_t k) const { return (*this)[k]; }
   /* Projection. */
   hb_codepoint_t operator () (hb_codepoint_t k) const { return get (k); }
 
@@ -2015,6 +2039,19 @@
     }
   }
 
+  unsigned get_population () const
+  {
+    switch (u.format) {
+    case 1: return u.format1.get_population ();
+    case 2: return u.format2.get_population ();
+#ifndef HB_NO_BEYOND_64K
+    case 3: return u.format3.get_population ();
+    case 4: return u.format4.get_population ();
+#endif
+    default:return NOT_COVERED;
+    }
+  }
+
   template<typename Iterator,
 	   hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
   bool serialize (hb_serialize_context_t *c, Iterator it_with_class_zero)
@@ -2332,7 +2369,7 @@
     {
       unsigned int backward = region_map.backward (r);
       if (backward >= region_count) return_trace (false);
-      memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * backward], VarRegionAxis::static_size * axisCount);
+      hb_memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * backward], VarRegionAxis::static_size * axisCount);
     }
 
     return_trace (true);
@@ -2442,21 +2479,26 @@
     unsigned ri_count = src->regionIndices.len;
     enum delta_size_t { kZero=0, kNonWord, kWord };
     hb_vector_t<delta_size_t> delta_sz;
-    hb_vector_t<unsigned int> ri_map;	/* maps old index to new index */
+    hb_vector_t<unsigned int> ri_map;	/* maps new index to old index */
     delta_sz.resize (ri_count);
     ri_map.resize (ri_count);
     unsigned int new_word_count = 0;
     unsigned int r;
 
+    const HBUINT8 *src_delta_bytes = src->get_delta_bytes ();
+    unsigned src_row_size = src->get_row_size ();
+    unsigned src_word_count = src->wordCount ();
+    bool     src_long_words = src->longWords ();
+
     bool has_long = false;
-    if (src->longWords ())
+    if (src_long_words)
     {
-      for (r = 0; r < ri_count; r++)
+      for (r = 0; r < src_word_count; r++)
       {
 	for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
 	{
 	  unsigned int old = inner_map.backward (i);
-	  int32_t delta = src->get_item_delta (old, r);
+	  int32_t delta = src->get_item_delta_fast (old, r, src_delta_bytes, src_row_size);
 	  if (delta < -65536 || 65535 < delta)
 	  {
 	    has_long = true;
@@ -2470,11 +2512,13 @@
     signed max_threshold = has_long ? +65535 : +127;
     for (r = 0; r < ri_count; r++)
     {
+      bool short_circuit = src_long_words == has_long && src_word_count <= r;
+
       delta_sz[r] = kZero;
       for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
       {
 	unsigned int old = inner_map.backward (i);
-	int32_t delta = src->get_item_delta (old, r);
+	int32_t delta = src->get_item_delta_fast (old, r, src_delta_bytes, src_row_size);
 	if (delta < min_threshold || max_threshold < delta)
 	{
 	  delta_sz[r] = kWord;
@@ -2482,7 +2526,11 @@
 	  break;
 	}
 	else if (delta != 0)
+	{
 	  delta_sz[r] = kNonWord;
+	  if (short_circuit)
+	    break;
+	}
       }
     }
 
@@ -2492,7 +2540,8 @@
     for (r = 0; r < ri_count; r++)
       if (delta_sz[r])
       {
-	ri_map[r] = (delta_sz[r] == kWord)? word_index++ : non_word_index++;
+	unsigned new_r = (delta_sz[r] == kWord)? word_index++ : non_word_index++;
+	ri_map[new_r] = r;
 	new_ri_count++;
       }
 
@@ -2502,14 +2551,20 @@
 
     if (unlikely (!c->extend (this))) return_trace (false);
 
-    for (r = 0; r < ri_count; r++)
-      if (delta_sz[r]) regionIndices[ri_map[r]] = region_map[src->regionIndices[r]];
+    for (r = 0; r < new_ri_count; r++)
+      regionIndices[r] = region_map[src->regionIndices[ri_map[r]]];
 
-    for (unsigned int i = 0; i < itemCount; i++)
+    HBUINT8 *delta_bytes = get_delta_bytes ();
+    unsigned row_size = get_row_size ();
+    unsigned count = itemCount;
+    for (unsigned int i = 0; i < count; i++)
     {
-      unsigned int	old = inner_map.backward (i);
-      for (unsigned int r = 0; r < ri_count; r++)
-	if (delta_sz[r]) set_item_delta (i, ri_map[r], src->get_item_delta (old, r));
+      unsigned int old = inner_map.backward (i);
+      for (unsigned int r = 0; r < new_ri_count; r++)
+	set_item_delta_fast (i, r,
+			     src->get_item_delta_fast (old, ri_map[r],
+						       src_delta_bytes, src_row_size),
+			     delta_bytes, row_size);
     }
 
     return_trace (true);
@@ -2517,12 +2572,15 @@
 
   void collect_region_refs (hb_set_t &region_indices, const hb_inc_bimap_t &inner_map) const
   {
+    const HBUINT8 *delta_bytes = get_delta_bytes ();
+    unsigned row_size = get_row_size ();
+
     for (unsigned int r = 0; r < regionIndices.len; r++)
     {
-      unsigned int region = regionIndices[r];
+      unsigned int region = regionIndices.arrayZ[r];
       if (region_indices.has (region)) continue;
       for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
-	if (get_item_delta (inner_map.backward (i), r) != 0)
+	if (get_item_delta_fast (inner_map.backward (i), r, delta_bytes, row_size) != 0)
 	{
 	  region_indices.add (region);
 	  break;
@@ -2537,10 +2595,12 @@
   HBUINT8 *get_delta_bytes ()
   { return &StructAfter<HBUINT8> (regionIndices); }
 
-  int32_t get_item_delta (unsigned int item, unsigned int region) const
+  int32_t get_item_delta_fast (unsigned int item, unsigned int region,
+			       const HBUINT8 *delta_bytes, unsigned row_size) const
   {
-    if ( item >= itemCount || unlikely (region >= regionIndices.len)) return 0;
-    const HBINT8 *p = (const HBINT8 *) get_delta_bytes () + item * get_row_size ();
+    if (unlikely (item >= itemCount || region >= regionIndices.len)) return 0;
+
+    const HBINT8 *p = (const HBINT8 *) delta_bytes + item * row_size;
     unsigned word_count = wordCount ();
     bool is_long = longWords ();
     if (is_long)
@@ -2558,10 +2618,17 @@
 	return (p + HBINT16::static_size * word_count)[region - word_count];
     }
   }
-
-  void set_item_delta (unsigned int item, unsigned int region, int32_t delta)
+  int32_t get_item_delta (unsigned int item, unsigned int region) const
   {
-    HBINT8 *p = (HBINT8 *)get_delta_bytes () + item * get_row_size ();
+     return get_item_delta_fast (item, region,
+				 get_delta_bytes (),
+				 get_row_size ());
+  }
+
+  void set_item_delta_fast (unsigned int item, unsigned int region, int32_t delta,
+			    HBUINT8 *delta_bytes, unsigned row_size)
+  {
+    HBINT8 *p = (HBINT8 *) delta_bytes + item * row_size;
     unsigned word_count = wordCount ();
     bool is_long = longWords ();
     if (is_long)
@@ -2579,6 +2646,12 @@
 	(p + HBINT16::static_size * word_count)[region - word_count] = delta;
     }
   }
+  void set_item_delta (unsigned int item, unsigned int region, int32_t delta)
+  {
+    set_item_delta_fast (item, region, delta,
+			 get_delta_bytes (),
+			 get_row_size ());
+  }
 
   bool longWords () const { return wordSizeCount & 0x8000u /* LONG_WORDS */; }
   unsigned wordCount () const { return wordSizeCount & 0x7FFFu /* WORD_DELTA_COUNT_MASK */; }
@@ -2642,6 +2715,14 @@
     unsigned int inner = index & 0xFFFF;
     return get_delta (outer, inner, coords, coord_count, cache);
   }
+  float get_delta (unsigned int index,
+		   hb_array_t<int> coords,
+		   VarRegionList::cache_t *cache = nullptr) const
+  {
+    return get_delta (index,
+		      coords.arrayZ, coords.length,
+		      cache);
+  }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -2948,7 +3029,7 @@
 
     // all conditions met
     if (num_kept_cond == 0) return DROP_COND_WITH_VAR;
- 
+
     //check if condition_set is unique with variations
     if (c->conditionset_map->has (p))
       //duplicate found, drop the entire record
@@ -3420,17 +3501,16 @@
   {
     TRACE_SERIALIZE (this);
     if (!layout_variation_idx_delta_map) return_trace (nullptr);
-    auto snap = c->snapshot ();
+
+    hb_pair_t<unsigned, int> *v;
+    if (!layout_variation_idx_delta_map->has (varIdx, &v))
+      return_trace (nullptr);
+
+    c->start_zerocopy (this->static_size);
     auto *out = c->embed (this);
     if (unlikely (!out)) return_trace (nullptr);
 
-    /* TODO Just get() and bail if NO_VARIATION. Needs to setup the map to return that. */
-    if (!layout_variation_idx_delta_map->has (varIdx))
-    {
-      c->revert (snap);
-      return_trace (nullptr);
-    }
-    unsigned new_idx = hb_first (layout_variation_idx_delta_map->get (varIdx));
+    unsigned new_idx = hb_first (*v);
     out->varIdx = new_idx;
     return_trace (out);
   }
diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh
index 22925fd..a84edef 100644
--- a/src/hb-ot-layout-gdef-table.hh
+++ b/src/hb-ot-layout-gdef-table.hh
@@ -73,7 +73,7 @@
 
     if (point_count)
     {
-      + points.sub_array (start_offset, point_count)
+      + points.as_array ().sub_array (start_offset, point_count)
       | hb_sink (hb_array (point_array, *point_count))
       ;
     }
@@ -322,7 +322,7 @@
   {
     if (caret_count)
     {
-      + carets.sub_array (start_offset, caret_count)
+      + carets.as_array ().sub_array (start_offset, caret_count)
       | hb_map (hb_add (this))
       | hb_map ([&] (const CaretValue &value) { return value.get_caret_value (font, direction, glyph_id, var_store); })
       | hb_sink (hb_array (caret_array, *caret_count))
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
index d1d9425..04ccefd 100644
--- a/src/hb-ot-layout-gsubgpos.hh
+++ b/src/hb-ot-layout-gsubgpos.hh
@@ -100,8 +100,8 @@
 
   bool is_lookup_done (unsigned int lookup_index)
   {
-    if (done_lookups_glyph_count->in_error () ||
-        done_lookups_glyph_set->in_error ())
+    if (unlikely (done_lookups_glyph_count->in_error () ||
+		  done_lookups_glyph_set->in_error ()))
       return true;
 
     /* Have we visited this lookup with the current set of glyphs? */
@@ -535,7 +535,12 @@
     bool next (unsigned *unsafe_to = nullptr)
     {
       assert (num_items > 0);
-      while (idx + num_items < end)
+      /* The alternate condition below is faster at string boundaries,
+       * but produces subpar "unsafe-to-concat" values. */
+      signed stop = (signed) end - (signed) num_items;
+      if (c->buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT)
+        stop = (signed) end - 1;
+      while ((signed) idx < stop)
       {
 	idx++;
 	hb_glyph_info_t &info = c->buffer->info[idx];
@@ -568,7 +573,12 @@
     bool prev (unsigned *unsafe_from = nullptr)
     {
       assert (num_items > 0);
-      while (idx > num_items - 1)
+      /* The alternate condition below is faster at string boundaries,
+       * but produces subpar "unsafe-to-concat" values. */
+      unsigned stop = num_items - 1;
+      if (c->buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT)
+        stop = 1 - 1;
+      while (idx > stop)
       {
 	idx--;
 	hb_glyph_info_t &info = c->buffer->out_info[idx];
@@ -672,6 +682,7 @@
   const GDEF &gdef;
   const VariationStore &var_store;
   VariationStore::cache_t *var_store_cache;
+  hb_set_digest_t digest;
 
   hb_direction_t direction;
   hb_mask_t lookup_mask = 1;
@@ -707,6 +718,7 @@
 					 nullptr
 #endif
 					),
+			digest (buffer_->digest ()),
 			direction (buffer_->props.direction),
 			has_glyph_classes (gdef.has_glyph_classes ())
   { init_iters (); }
@@ -781,8 +793,10 @@
   void _set_glyph_class (hb_codepoint_t glyph_index,
 			  unsigned int class_guess = 0,
 			  bool ligature = false,
-			  bool component = false) const
+			  bool component = false)
   {
+    digest.add (glyph_index);
+
     if (new_syllables != (unsigned) -1)
       buffer->cur().syllable() = new_syllables;
 
@@ -815,24 +829,24 @@
       _hb_glyph_info_set_glyph_props (&buffer->cur(), props);
   }
 
-  void replace_glyph (hb_codepoint_t glyph_index) const
+  void replace_glyph (hb_codepoint_t glyph_index)
   {
     _set_glyph_class (glyph_index);
     (void) buffer->replace_glyph (glyph_index);
   }
-  void replace_glyph_inplace (hb_codepoint_t glyph_index) const
+  void replace_glyph_inplace (hb_codepoint_t glyph_index)
   {
     _set_glyph_class (glyph_index);
     buffer->cur().codepoint = glyph_index;
   }
   void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
-				    unsigned int class_guess) const
+				    unsigned int class_guess)
   {
     _set_glyph_class (glyph_index, class_guess, true);
     (void) buffer->replace_glyph (glyph_index);
   }
   void output_glyph_for_component (hb_codepoint_t glyph_index,
-				   unsigned int class_guess) const
+				   unsigned int class_guess)
   {
     _set_glyph_class (glyph_index, class_guess, false, true);
     (void) buffer->output_glyph (glyph_index);
@@ -844,7 +858,7 @@
        hb_dispatch_context_t<hb_accelerate_subtables_context_t>
 {
   template <typename Type>
-  static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
+  static inline bool apply_to (const void *obj, hb_ot_apply_context_t *c)
   {
     const Type *typed_obj = (const Type *) obj;
     return typed_obj->apply (c);
@@ -852,30 +866,30 @@
 
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
   template <typename T>
-  static inline auto apply_cached_ (const T *obj, OT::hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (bool, obj->apply (c, true) )
+  static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (bool, obj->apply (c, true) )
   template <typename T>
-  static inline auto apply_cached_ (const T *obj, OT::hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (bool, obj->apply (c) )
+  static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (bool, obj->apply (c) )
   template <typename Type>
-  static inline bool apply_cached_to (const void *obj, OT::hb_ot_apply_context_t *c)
+  static inline bool apply_cached_to (const void *obj, hb_ot_apply_context_t *c)
   {
     const Type *typed_obj = (const Type *) obj;
     return apply_cached_ (typed_obj, c, hb_prioritize);
   }
 
   template <typename T>
-  static inline auto cache_func_ (const T *obj, OT::hb_ot_apply_context_t *c, bool enter, hb_priority<1>) HB_RETURN (bool, obj->cache_func (c, enter) )
+  static inline auto cache_func_ (const T *obj, hb_ot_apply_context_t *c, bool enter, hb_priority<1>) HB_RETURN (bool, obj->cache_func (c, enter) )
   template <typename T>
-  static inline bool cache_func_ (const T *obj, OT::hb_ot_apply_context_t *c, bool enter, hb_priority<0>) { return false; }
+  static inline bool cache_func_ (const T *obj, hb_ot_apply_context_t *c, bool enter, hb_priority<0>) { return false; }
   template <typename Type>
-  static inline bool cache_func_to (const void *obj, OT::hb_ot_apply_context_t *c, bool enter)
+  static inline bool cache_func_to (const void *obj, hb_ot_apply_context_t *c, bool enter)
   {
     const Type *typed_obj = (const Type *) obj;
     return cache_func_ (typed_obj, c, enter, hb_prioritize);
   }
 #endif
 
-  typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
-  typedef bool (*hb_cache_func_t) (const void *obj, OT::hb_ot_apply_context_t *c, bool enter);
+  typedef bool (*hb_apply_func_t) (const void *obj, hb_ot_apply_context_t *c);
+  typedef bool (*hb_cache_func_t) (const void *obj, hb_ot_apply_context_t *c, bool enter);
 
   struct hb_applicable_t
   {
@@ -901,20 +915,20 @@
       obj_.get_coverage ().collect_coverage (&digest);
     }
 
-    bool apply (OT::hb_ot_apply_context_t *c) const
+    bool apply (hb_ot_apply_context_t *c) const
     {
       return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c);
     }
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
-    bool apply_cached (OT::hb_ot_apply_context_t *c) const
+    bool apply_cached (hb_ot_apply_context_t *c) const
     {
       return digest.may_have (c->buffer->cur().codepoint) &&  apply_cached_func (obj, c);
     }
-    bool cache_enter (OT::hb_ot_apply_context_t *c) const
+    bool cache_enter (hb_ot_apply_context_t *c) const
     {
       return cache_func (obj, c, true);
     }
-    void cache_leave (OT::hb_ot_apply_context_t *c) const
+    void cache_leave (hb_ot_apply_context_t *c) const
     {
       cache_func (obj, c, false);
     }
@@ -988,8 +1002,8 @@
 };
 
 
-typedef bool (*intersects_func_t) (const hb_set_t *glyphs, unsigned value, const void *data);
-typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs);
+typedef bool (*intersects_func_t) (const hb_set_t *glyphs, unsigned value, const void *data, void *cache);
+typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache);
 typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, unsigned value, const void *data);
 typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
 
@@ -1012,16 +1026,25 @@
 };
 
 
-static inline bool intersects_glyph (const hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED)
+static inline bool intersects_glyph (const hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED, void *cache HB_UNUSED)
 {
   return glyphs->has (value);
 }
-static inline bool intersects_class (const hb_set_t *glyphs, unsigned value, const void *data)
+static inline bool intersects_class (const hb_set_t *glyphs, unsigned value, const void *data, void *cache)
 {
   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  return class_def.intersects_class (glyphs, value);
+  hb_map_t *map = (hb_map_t *) cache;
+
+  hb_codepoint_t *cached_v;
+  if (map->has (value, &cached_v))
+    return *cached_v;
+
+  bool v = class_def.intersects_class (glyphs, value);
+  map->set (value, v);
+
+  return v;
 }
-static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, const void *data)
+static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, const void *data, void *cache HB_UNUSED)
 {
   Offset16To<Coverage> coverage;
   coverage = value;
@@ -1029,17 +1052,36 @@
 }
 
 
-static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs)
+static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs, HB_UNUSED void *cache)
 {
   unsigned g = reinterpret_cast<const HBUINT16 *>(data)[value];
   intersected_glyphs->add (g);
 }
-static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs)
+
+using intersected_class_cache_t = hb_hashmap_t<unsigned, hb_set_t>;
+
+static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache)
 {
   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  class_def.intersected_class_glyphs (glyphs, value, intersected_glyphs);
+
+  intersected_class_cache_t *map = (intersected_class_cache_t *) cache;
+
+  hb_set_t *cached_v;
+  if (map->has (value, &cached_v))
+  {
+    intersected_glyphs->union_ (*cached_v);
+    return;
+  }
+
+  hb_set_t v;
+  class_def.intersected_class_glyphs (glyphs, value, &v);
+
+  intersected_glyphs->union_ (v);
+
+  map->set (value, std::move (v));
 }
-static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs)
+
+static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, HB_UNUSED void *cache)
 {
   Offset16To<Coverage> coverage;
   coverage = value;
@@ -1052,10 +1094,11 @@
 				       unsigned int count,
 				       const HBUINT values[],
 				       intersects_func_t intersects_func,
-				       const void *intersects_data)
+				       const void *intersects_data,
+				       void *cache)
 {
   for (const auto &_ : + hb_iter (values, count))
-    if (!intersects_func (glyphs, _, intersects_data)) return false;
+    if (!intersects_func (glyphs, _, intersects_data, cache)) return false;
   return true;
 }
 
@@ -1492,7 +1535,8 @@
 					     unsigned value,
 					     ContextFormat context_format,
 					     const void *data,
-					     intersected_glyphs_func_t intersected_glyphs_func)
+					     intersected_glyphs_func_t intersected_glyphs_func,
+					     void *cache)
 {
   hb_set_t *covered_seq_indicies = hb_set_create ();
   for (unsigned int i = 0; i < lookupCount; i++)
@@ -1513,7 +1557,7 @@
           pos_glyphs.add (value);
           break;
         case ContextFormat::ClassBasedContext:
-          intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs);
+          intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs, cache);
           break;
         case ContextFormat::CoverageBasedContext:
           pos_glyphs.set (c->parent_active_glyphs ());
@@ -1530,7 +1574,7 @@
           input_value = input[seqIndex - 1];
         }
 
-        intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs);
+        intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs, cache);
       }
     }
 
@@ -1710,6 +1754,8 @@
   ContextClosureFuncs funcs;
   ContextFormat context_format;
   const void *intersects_data;
+  void *intersects_cache;
+  void *intersected_glyphs_cache;
 };
 
 struct ContextCollectGlyphsLookupContext
@@ -1732,7 +1778,9 @@
 {
   return array_is_subset_of (glyphs,
 			     inputCount ? inputCount - 1 : 0, input,
-			     lookup_context.funcs.intersects, lookup_context.intersects_data);
+			     lookup_context.funcs.intersects,
+			     lookup_context.intersects_data,
+			     lookup_context.intersects_cache);
 }
 
 template <typename HBUINT>
@@ -1753,7 +1801,8 @@
 				     value,
 				     lookup_context.context_format,
 				     lookup_context.intersects_data,
-				     lookup_context.funcs.intersected_glyphs);
+				     lookup_context.funcs.intersected_glyphs,
+				     lookup_context.intersected_glyphs_cache);
 }
 
 template <typename HBUINT>
@@ -1777,7 +1826,7 @@
 					       const HBUINT input[], /* Array of input values--start with second glyph */
 					       unsigned int lookupCount HB_UNUSED,
 					       const LookupRecord lookupRecord[] HB_UNUSED,
-					       ContextApplyLookupContext &lookup_context)
+					       const ContextApplyLookupContext &lookup_context)
 {
   return would_match_input (c,
 			    inputCount, input,
@@ -1790,7 +1839,7 @@
 					 const HBUINT input[], /* Array of input values--start with second glyph */
 					 unsigned int lookupCount,
 					 const LookupRecord lookupRecord[],
-					 ContextApplyLookupContext &lookup_context)
+					 const ContextApplyLookupContext &lookup_context)
 {
   unsigned match_end = 0;
   unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
@@ -1858,7 +1907,7 @@
   }
 
   bool would_apply (hb_would_apply_context_t *c,
-		    ContextApplyLookupContext &lookup_context) const
+		    const ContextApplyLookupContext &lookup_context) const
   {
     const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
 					   (inputZ.as_array (inputCount ? inputCount - 1 : 0));
@@ -1869,7 +1918,7 @@
   }
 
   bool apply (hb_ot_apply_context_t *c,
-	      ContextApplyLookupContext &lookup_context) const
+	      const ContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
     const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
@@ -1989,7 +2038,7 @@
   }
 
   bool would_apply (hb_would_apply_context_t *c,
-		    ContextApplyLookupContext &lookup_context) const
+		    const ContextApplyLookupContext &lookup_context) const
   {
     return
     + hb_iter (rule)
@@ -2000,7 +2049,7 @@
   }
 
   bool apply (hb_ot_apply_context_t *c,
-	      ContextApplyLookupContext &lookup_context) const
+	      const ContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
     return_trace (
@@ -2108,7 +2157,7 @@
   void closure_lookups (hb_closure_lookups_context_t *c) const
   {
     struct ContextClosureLookupContext lookup_context = {
-      {intersects_glyph, intersected_glyph},
+      {intersects_glyph, nullptr},
       ContextFormat::SimpleContext,
       nullptr
     };
@@ -2220,10 +2269,12 @@
 
     const ClassDef &class_def = this+classDef;
 
+    hb_map_t cache;
     struct ContextClosureLookupContext lookup_context = {
-      {intersects_class, intersected_class_glyphs},
+      {intersects_class, nullptr},
       ContextFormat::ClassBasedContext,
-      &class_def
+      &class_def,
+      &cache
     };
 
     hb_set_t retained_coverage_glyphs;
@@ -2259,10 +2310,14 @@
 
     const ClassDef &class_def = this+classDef;
 
+    hb_map_t cache;
+    intersected_class_cache_t intersected_cache;
     struct ContextClosureLookupContext lookup_context = {
       {intersects_class, intersected_class_glyphs},
       ContextFormat::ClassBasedContext,
-      &class_def
+      &class_def,
+      &cache,
+      &intersected_cache
     };
 
     + hb_enumerate (ruleSet)
@@ -2286,10 +2341,12 @@
 
     const ClassDef &class_def = this+classDef;
 
+    hb_map_t cache;
     struct ContextClosureLookupContext lookup_context = {
-      {intersects_class, intersected_class_glyphs},
+      {intersects_class, nullptr},
       ContextFormat::ClassBasedContext,
-      &class_def
+      &class_def,
+      &cache
     };
 
     + hb_iter (ruleSet)
@@ -2407,6 +2464,7 @@
     const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
     bool ret = true;
     int non_zero_index = -1, index = 0;
+    auto snapshot = c->serializer->snapshot();
     for (const auto& _ : + hb_enumerate (ruleSet)
 			 | hb_filter (klass_map, hb_first))
     {
@@ -2418,8 +2476,10 @@
       }
 
       if (coverage_glyph_classes.has (_.first) &&
-	  o->serialize_subset (c, _.second, this, lookup_map, &klass_map))
+	  o->serialize_subset (c, _.second, this, lookup_map, &klass_map)) {
 	non_zero_index = index;
+        snapshot = c->serializer->snapshot();
+      }
 
       index++;
     }
@@ -2433,6 +2493,7 @@
       out->ruleSet.pop ();
       index--;
     }
+    c->serializer->revert (snapshot);
 
     return_trace (bool (out->ruleSet));
   }
@@ -2469,7 +2530,7 @@
       return false;
 
     struct ContextClosureLookupContext lookup_context = {
-      {intersects_coverage, intersected_coverage_glyphs},
+      {intersects_coverage, nullptr},
       ContextFormat::CoverageBasedContext,
       this
     };
@@ -2655,6 +2716,8 @@
   ContextClosureFuncs funcs;
   ContextFormat context_format;
   const void *intersects_data[3];
+  void *intersects_cache[3];
+  void *intersected_glyphs_cache;
 };
 
 struct ChainContextCollectGlyphsLookupContext
@@ -2681,13 +2744,19 @@
 {
   return array_is_subset_of (glyphs,
 			     backtrackCount, backtrack,
-			     lookup_context.funcs.intersects, lookup_context.intersects_data[0])
+			     lookup_context.funcs.intersects,
+			     lookup_context.intersects_data[0],
+			     lookup_context.intersects_cache[0])
       && array_is_subset_of (glyphs,
 			     inputCount ? inputCount - 1 : 0, input,
-			     lookup_context.funcs.intersects, lookup_context.intersects_data[1])
+			     lookup_context.funcs.intersects,
+			     lookup_context.intersects_data[1],
+			     lookup_context.intersects_cache[1])
       && array_is_subset_of (glyphs,
 			     lookaheadCount, lookahead,
-			     lookup_context.funcs.intersects, lookup_context.intersects_data[2]);
+			     lookup_context.funcs.intersects,
+			     lookup_context.intersects_data[2],
+			     lookup_context.intersects_cache[2]);
 }
 
 template <typename HBUINT>
@@ -2714,7 +2783,8 @@
 		     value,
 		     lookup_context.context_format,
 		     lookup_context.intersects_data[1],
-		     lookup_context.funcs.intersected_glyphs);
+		     lookup_context.funcs.intersected_glyphs,
+		     lookup_context.intersected_glyphs_cache);
 }
 
 template <typename HBUINT>
@@ -2752,7 +2822,7 @@
 						     const HBUINT lookahead[] HB_UNUSED,
 						     unsigned int lookupCount HB_UNUSED,
 						     const LookupRecord lookupRecord[] HB_UNUSED,
-						     ChainContextApplyLookupContext &lookup_context)
+						     const ChainContextApplyLookupContext &lookup_context)
 {
   return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
       && would_match_input (c,
@@ -2770,7 +2840,7 @@
 					       const HBUINT lookahead[],
 					       unsigned int lookupCount,
 					       const LookupRecord lookupRecord[],
-					       ChainContextApplyLookupContext &lookup_context)
+					       const ChainContextApplyLookupContext &lookup_context)
 {
   unsigned end_index = c->buffer->idx;
   unsigned match_end = 0;
@@ -2864,7 +2934,7 @@
   }
 
   bool would_apply (hb_would_apply_context_t *c,
-		    ChainContextApplyLookupContext &lookup_context) const
+		    const ChainContextApplyLookupContext &lookup_context) const
   {
     const auto &input = StructAfter<decltype (inputX)> (backtrack);
     const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
@@ -2876,7 +2946,8 @@
 					     lookup.arrayZ, lookup_context);
   }
 
-  bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  bool apply (hb_ot_apply_context_t *c,
+	      const ChainContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
     const auto &input = StructAfter<decltype (inputX)> (backtrack);
@@ -3042,7 +3113,8 @@
     ;
   }
 
-  bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  bool would_apply (hb_would_apply_context_t *c,
+		    const ChainContextApplyLookupContext &lookup_context) const
   {
     return
     + hb_iter (rule)
@@ -3052,7 +3124,8 @@
     ;
   }
 
-  bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  bool apply (hb_ot_apply_context_t *c,
+	      const ChainContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
     return_trace (
@@ -3166,7 +3239,7 @@
   void closure_lookups (hb_closure_lookups_context_t *c) const
   {
     struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_glyph, intersected_glyph},
+      {intersects_glyph, nullptr},
       ContextFormat::SimpleContext,
       {nullptr, nullptr, nullptr}
     };
@@ -3278,12 +3351,14 @@
     const ClassDef &input_class_def = this+inputClassDef;
     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
 
+    hb_map_t caches[3] = {};
     struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_class, intersected_class_glyphs},
+      {intersects_class, nullptr},
       ContextFormat::ClassBasedContext,
       {&backtrack_class_def,
        &input_class_def,
-       &lookahead_class_def}
+       &lookahead_class_def},
+      {&caches[0], &caches[1], &caches[2]}
     };
 
     hb_set_t retained_coverage_glyphs;
@@ -3321,12 +3396,16 @@
     const ClassDef &input_class_def = this+inputClassDef;
     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
 
+    hb_map_t caches[3] = {};
+    intersected_class_cache_t intersected_cache;
     struct ChainContextClosureLookupContext lookup_context = {
       {intersects_class, intersected_class_glyphs},
       ContextFormat::ClassBasedContext,
       {&backtrack_class_def,
        &input_class_def,
-       &lookahead_class_def}
+       &lookahead_class_def},
+      {&caches[0], &caches[1], &caches[2]},
+      &intersected_cache
     };
 
     + hb_enumerate (ruleSet)
@@ -3352,12 +3431,14 @@
     const ClassDef &input_class_def = this+inputClassDef;
     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
 
+    hb_map_t caches[3] = {};
     struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_class, intersected_class_glyphs},
+      {intersects_class, nullptr},
       ContextFormat::ClassBasedContext,
       {&backtrack_class_def,
        &input_class_def,
-       &lookahead_class_def}
+       &lookahead_class_def},
+      {&caches[0], &caches[1], &caches[2]}
     };
 
     + hb_iter (ruleSet)
@@ -3587,7 +3668,7 @@
 
     const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
     struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_coverage, intersected_coverage_glyphs},
+      {intersects_coverage, nullptr},
       ContextFormat::CoverageBasedContext,
       {this, this, this}
     };
@@ -3938,13 +4019,14 @@
   template <typename TLookup>
   void init (const TLookup &lookup)
   {
-    digest.init ();
-    lookup.collect_coverage (&digest);
-
     subtables.init ();
-    OT::hb_accelerate_subtables_context_t c_accelerate_subtables (subtables);
+    hb_accelerate_subtables_context_t c_accelerate_subtables (subtables);
     lookup.dispatch (&c_accelerate_subtables);
 
+    digest.init ();
+    for (auto& subtable : hb_iter (subtables))
+      digest.add (subtable.digest);
+
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
     cache_user_idx = c_accelerate_subtables.cache_user_idx;
     for (unsigned i = 0; i < subtables.length; i++)
@@ -3962,21 +4044,25 @@
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
     if (use_cache)
     {
-      for (unsigned int i = 0; i < subtables.length; i++)
-        if (subtables[i].apply_cached (c))
-	  return true;
+      return
+      + hb_iter (subtables)
+      | hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply_cached (c); })
+      | hb_any
+      ;
     }
     else
 #endif
     {
-      for (unsigned int i = 0; i < subtables.length; i++)
-        if (subtables[i].apply (c))
-	  return true;
+      return
+      + hb_iter (subtables)
+      | hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply (c); })
+      | hb_any
+      ;
     }
     return false;
   }
 
-  bool cache_enter (OT::hb_ot_apply_context_t *c) const
+  bool cache_enter (hb_ot_apply_context_t *c) const
   {
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
     return cache_user_idx != (unsigned) -1 &&
@@ -3985,7 +4071,7 @@
     return false;
 #endif
   }
-  void cache_leave (OT::hb_ot_apply_context_t *c) const
+  void cache_leave (hb_ot_apply_context_t *c) const
   {
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
     subtables[cache_user_idx].cache_leave (c);
@@ -3993,8 +4079,8 @@
   }
 
 
-  private:
   hb_set_digest_t digest;
+  private:
   hb_accelerate_subtables_context_t::array_t subtables;
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
   unsigned cache_user_idx = (unsigned) -1;
@@ -4255,11 +4341,11 @@
 			hb_set_t       *lookup_indexes /* IN/OUT */) const
   {
     hb_set_t visited_lookups, inactive_lookups;
-    OT::hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups);
+    hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups);
 
     c.set_recurse_func (TLookup::template dispatch_recurse_func<hb_closure_lookups_context_t>);
 
-    for (unsigned lookup_index : + hb_iter (lookup_indexes))
+    for (unsigned lookup_index : *lookup_indexes)
       reinterpret_cast<const TLookup &> (get_lookup (lookup_index)).closure_lookups (&c, lookup_index);
 
     hb_set_union (lookup_indexes, &visited_lookups);
@@ -4301,7 +4387,7 @@
     }
 #endif
 
-    for (unsigned i : feature_indices->iter())
+    for (unsigned i : hb_iter (feature_indices))
     {
       hb_tag_t tag =  get_feature_tag (i);
       if (tag == HB_TAG ('p', 'r', 'e', 'f'))
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index dbb3007..e8091ec 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1465,56 +1465,6 @@
   _hb_ot_layout_set_glyph_props (font, buffer);
 }
 
-void
-hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
-				    bool (*filter) (const hb_glyph_info_t *info))
-{
-  /* Merge clusters and delete filtered glyphs.
-   * NOTE! We can't use out-buffer as we have positioning data. */
-  unsigned int j = 0;
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  hb_glyph_position_t *pos = buffer->pos;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    if (filter (&info[i]))
-    {
-      /* Merge clusters.
-       * Same logic as buffer->delete_glyph(), but for in-place removal. */
-
-      unsigned int cluster = info[i].cluster;
-      if (i + 1 < count && cluster == info[i + 1].cluster)
-	continue; /* Cluster survives; do nothing. */
-
-      if (j)
-      {
-	/* Merge cluster backward. */
-	if (cluster < info[j - 1].cluster)
-	{
-	  unsigned int mask = info[i].mask;
-	  unsigned int old_cluster = info[j - 1].cluster;
-	  for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
-	    buffer->set_cluster (info[k - 1], cluster, mask);
-	}
-	continue;
-      }
-
-      if (i + 1 < count)
-	buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
-
-      continue;
-    }
-
-    if (j != i)
-    {
-      info[j] = info[i];
-      pos[j] = pos[i];
-    }
-    j++;
-  }
-  buffer->len = j;
-}
-
 /**
  * hb_ot_layout_lookup_substitute_closure:
  * @face: #hb_face_t to work upon
@@ -1867,7 +1817,7 @@
   while (buffer->idx < buffer->len && buffer->successful)
   {
     bool applied = false;
-    if (accel.may_have (buffer->cur().codepoint) &&
+    if (accel.digest.may_have (buffer->cur().codepoint) &&
 	(buffer->cur().mask & c->lookup_mask) &&
 	c->check_glyph_property (&buffer->cur(), c->lookup_props))
      {
@@ -1894,7 +1844,7 @@
   hb_buffer_t *buffer = c->buffer;
   do
   {
-    if (accel.may_have (buffer->cur().codepoint) &&
+    if (accel.digest.may_have (buffer->cur().codepoint) &&
 	(buffer->cur().mask & c->lookup_mask) &&
 	c->check_glyph_property (&buffer->cur(), c->lookup_props))
      ret |= accel.apply (c, false);
@@ -1908,15 +1858,16 @@
 }
 
 template <typename Proxy>
-static inline void
+static inline bool
 apply_string (OT::hb_ot_apply_context_t *c,
 	      const typename Proxy::Lookup &lookup,
 	      const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
+  bool ret = false;
   hb_buffer_t *buffer = c->buffer;
 
   if (unlikely (!buffer->len || !c->lookup_mask))
-    return;
+    return ret;
 
   c->set_lookup_props (lookup.get_props ());
 
@@ -1927,7 +1878,7 @@
       buffer->clear_output ();
 
     buffer->idx = 0;
-    apply_forward (c, accel);
+    ret = apply_forward (c, accel);
 
     if (!Proxy::always_inplace)
       buffer->sync ();
@@ -1937,8 +1888,10 @@
     /* in-place backward substitution/positioning */
     assert (!buffer->have_output);
     buffer->idx = buffer->len - 1;
-    apply_backward (c, accel);
+    ret = apply_backward (c, accel);
   }
+
+  return ret;
 }
 
 template <typename Proxy>
@@ -1957,23 +1910,42 @@
     const stage_map_t *stage = &stages[table_index][stage_index];
     for (; i < stage->last_lookup; i++)
     {
-      unsigned int lookup_index = lookups[table_index][i].index;
-      if (!buffer->message (font, "start lookup %d", lookup_index)) continue;
-      c.set_lookup_index (lookup_index);
-      c.set_lookup_mask (lookups[table_index][i].mask);
-      c.set_auto_zwj (lookups[table_index][i].auto_zwj);
-      c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
-      c.set_random (lookups[table_index][i].random);
-      c.set_per_syllable (lookups[table_index][i].per_syllable);
+      auto &lookup = lookups[table_index][i];
 
-      apply_string<Proxy> (&c,
-			   proxy.table.get_lookup (lookup_index),
-			   proxy.accels[lookup_index]);
-      (void) buffer->message (font, "end lookup %d", lookup_index);
+      unsigned int lookup_index = lookup.index;
+      if (!buffer->message (font, "start lookup %d feature '%c%c%c%c'", lookup_index, HB_UNTAG (lookup.feature_tag))) continue;
+
+      /* c.digest is a digest of all the current glyphs in the buffer
+       * (plus some past glyphs).
+       *
+       * Only try applying the lookup if there is any overlap. */
+      if (proxy.accels[lookup_index].digest.may_have (c.digest))
+      {
+	c.set_lookup_index (lookup_index);
+	c.set_lookup_mask (lookup.mask);
+	c.set_auto_zwj (lookup.auto_zwj);
+	c.set_auto_zwnj (lookup.auto_zwnj);
+	c.set_random (lookup.random);
+	c.set_per_syllable (lookup.per_syllable);
+
+	apply_string<Proxy> (&c,
+			     proxy.table.get_lookup (lookup_index),
+			     proxy.accels[lookup_index]);
+      }
+      else
+	(void) buffer->message (font, "skipped lookup %d feature '%c%c%c%c' because no glyph matches", lookup_index, HB_UNTAG (lookup.feature_tag));
+
+      (void) buffer->message (font, "end lookup %d feature '%c%c%c%c'", lookup_index, HB_UNTAG (lookup.feature_tag));
     }
 
     if (stage->pause_func)
-      stage->pause_func (plan, font, buffer);
+    {
+      if (stage->pause_func (plan, font, buffer))
+      {
+	/* Refresh working buffer digest since buffer changed. */
+	c.digest = buffer->digest ();
+      }
+    }
   }
 }
 
diff --git a/src/hb-ot-layout.hh b/src/hb-ot-layout.hh
index de06610..9505d5f 100644
--- a/src/hb-ot-layout.hh
+++ b/src/hb-ot-layout.hh
@@ -102,10 +102,6 @@
 hb_ot_layout_substitute_start (hb_font_t    *font,
 			       hb_buffer_t  *buffer);
 
-HB_INTERNAL void
-hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
-				    bool (*filter) (const hb_glyph_info_t *info));
-
 namespace OT {
   struct hb_ot_apply_context_t;
   struct hb_ot_layout_lookup_accelerator_t;
@@ -552,7 +548,7 @@
   info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
 }
 
-static inline void
+static inline bool
 _hb_clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
 			      hb_font_t *font HB_UNUSED,
 			      hb_buffer_t *buffer)
@@ -561,6 +557,7 @@
   unsigned int count = buffer->len;
   for (unsigned int i = 0; i < count; i++)
     _hb_glyph_info_clear_substituted (&info[i]);
+  return false;
 }
 
 
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 39215b3..8882dba 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -45,7 +45,7 @@
 hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
 					  const hb_segment_properties_t &props_)
 {
-  memset (this, 0, sizeof (*this));
+  hb_memset (this, 0, sizeof (*this));
 
   feature_infos.init ();
   for (unsigned int table_index = 0; table_index < 2; table_index++)
@@ -133,7 +133,8 @@
 				  bool          auto_zwnj,
 				  bool          auto_zwj,
 				  bool          random,
-				  bool          per_syllable)
+				  bool          per_syllable,
+				  hb_tag_t      feature_tag)
 {
   unsigned int lookup_indices[32];
   unsigned int offset, len;
@@ -162,6 +163,7 @@
       lookup->auto_zwj = auto_zwj;
       lookup->random = random;
       lookup->per_syllable = per_syllable;
+      lookup->feature_tag = feature_tag;
     }
 
     offset += len;
@@ -212,24 +214,26 @@
   if (feature_infos.length)
   {
     feature_infos.qsort ();
+    auto *f = feature_infos.arrayZ;
     unsigned int j = 0;
-    for (unsigned int i = 1; i < feature_infos.length; i++)
-      if (feature_infos[i].tag != feature_infos[j].tag)
-	feature_infos[++j] = feature_infos[i];
+    unsigned count = feature_infos.length;
+    for (unsigned int i = 1; i < count; i++)
+      if (f[i].tag != f[j].tag)
+	f[++j] = f[i];
       else {
-	if (feature_infos[i].flags & F_GLOBAL) {
-	  feature_infos[j].flags |= F_GLOBAL;
-	  feature_infos[j].max_value = feature_infos[i].max_value;
-	  feature_infos[j].default_value = feature_infos[i].default_value;
+	if (f[i].flags & F_GLOBAL) {
+	  f[j].flags |= F_GLOBAL;
+	  f[j].max_value = f[i].max_value;
+	  f[j].default_value = f[i].default_value;
 	} else {
-	  if (feature_infos[j].flags & F_GLOBAL)
-	    feature_infos[j].flags ^= F_GLOBAL;
-	  feature_infos[j].max_value = hb_max (feature_infos[j].max_value, feature_infos[i].max_value);
+	  if (f[j].flags & F_GLOBAL)
+	    f[j].flags ^= F_GLOBAL;
+	  f[j].max_value = hb_max (f[j].max_value, f[i].max_value);
 	  /* Inherit default_value from j */
 	}
-	feature_infos[j].flags |= (feature_infos[i].flags & F_HAS_FALLBACK);
-	feature_infos[j].stage[0] = hb_min (feature_infos[j].stage[0], feature_infos[i].stage[0]);
-	feature_infos[j].stage[1] = hb_min (feature_infos[j].stage[1], feature_infos[i].stage[1]);
+	f[j].flags |= (f[i].flags & F_HAS_FALLBACK);
+	f[j].stage[0] = hb_min (f[j].stage[0], f[i].stage[0]);
+	f[j].stage[1] = hb_min (f[j].stage[1], f[i].stage[1]);
       }
     feature_infos.shrink (j + 1);
   }
@@ -239,7 +243,8 @@
   static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
   unsigned int next_bit = hb_popcount (HB_GLYPH_FLAG_DEFINED) + 1;
 
-  for (unsigned int i = 0; i < feature_infos.length; i++)
+  unsigned count = feature_infos.length;
+  for (unsigned int i = 0; i < count; i++)
   {
     const feature_info_t *info = &feature_infos[i];
 
@@ -308,7 +313,7 @@
     map->_1_mask = (1u << map->shift) & map->mask;
     map->needs_fallback = !found;
   }
-  feature_infos.shrink (0); /* Done with these */
+  //feature_infos.shrink (0); /* Done with these */
 
 
   add_gsub_pause (nullptr);
@@ -317,6 +322,7 @@
   for (unsigned int table_index = 0; table_index < 2; table_index++)
   {
     /* Collect lookup indices for features */
+    auto &lookups = m.lookups[table_index];
 
     unsigned int stage_index = 0;
     unsigned int last_num_lookups = 0;
@@ -329,36 +335,39 @@
 		     key.variations_index[table_index],
 		     global_bit_mask);
 
-      for (unsigned i = 0; i < m.features.length; i++)
-	if (m.features[i].stage[table_index] == stage)
-	  add_lookups (m, table_index,
-		       m.features[i].index[table_index],
-		       key.variations_index[table_index],
-		       m.features[i].mask,
-		       m.features[i].auto_zwnj,
-		       m.features[i].auto_zwj,
-		       m.features[i].random,
-		       m.features[i].per_syllable);
-
-      /* Sort lookups and merge duplicates */
-      if (last_num_lookups < m.lookups[table_index].length)
+      for (auto &feature : m.features)
       {
-	m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].length);
-
-	unsigned int j = last_num_lookups;
-	for (unsigned int i = j + 1; i < m.lookups[table_index].length; i++)
-	  if (m.lookups[table_index][i].index != m.lookups[table_index][j].index)
-	    m.lookups[table_index][++j] = m.lookups[table_index][i];
-	  else
-	  {
-	    m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask;
-	    m.lookups[table_index][j].auto_zwnj &= m.lookups[table_index][i].auto_zwnj;
-	    m.lookups[table_index][j].auto_zwj &= m.lookups[table_index][i].auto_zwj;
-	  }
-	m.lookups[table_index].shrink (j + 1);
+	if (feature.stage[table_index] == stage)
+	  add_lookups (m, table_index,
+		       feature.index[table_index],
+		       key.variations_index[table_index],
+		       feature.mask,
+		       feature.auto_zwnj,
+		       feature.auto_zwj,
+		       feature.random,
+		       feature.per_syllable,
+		       feature.tag);
       }
 
-      last_num_lookups = m.lookups[table_index].length;
+      /* Sort lookups and merge duplicates */
+      if (last_num_lookups < lookups.length)
+      {
+	lookups.as_array ().sub_array (last_num_lookups, lookups.length - last_num_lookups).qsort ();
+
+	unsigned int j = last_num_lookups;
+	for (unsigned int i = j + 1; i < lookups.length; i++)
+	  if (lookups.arrayZ[i].index != lookups.arrayZ[j].index)
+	    lookups.arrayZ[++j] = lookups.arrayZ[i];
+	  else
+	  {
+	    lookups.arrayZ[j].mask |= lookups.arrayZ[i].mask;
+	    lookups.arrayZ[j].auto_zwnj &= lookups.arrayZ[i].auto_zwnj;
+	    lookups.arrayZ[j].auto_zwj &= lookups.arrayZ[i].auto_zwj;
+	  }
+	lookups.shrink (j + 1);
+      }
+
+      last_num_lookups = lookups.length;
 
       if (stage_index < stages[table_index].length && stages[table_index][stage_index].index == stage) {
 	hb_ot_map_t::stage_map_t *stage_map = m.stages[table_index].push ();
diff --git a/src/hb-ot-map.hh b/src/hb-ot-map.hh
index a7b5eec..efc8cae 100644
--- a/src/hb-ot-map.hh
+++ b/src/hb-ot-map.hh
@@ -69,6 +69,7 @@
     unsigned short random : 1;
     unsigned short per_syllable : 1;
     hb_mask_t mask;
+    hb_tag_t feature_tag;
 
     HB_INTERNAL static int cmp (const void *pa, const void *pb)
     {
@@ -78,7 +79,9 @@
     }
   };
 
-  typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
+  /* Pause functions return true if new glyph indices might have been
+   * added to the buffer.  This is used to update buffer digest. */
+  typedef bool (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
 
   struct stage_map_t {
     unsigned int last_lookup; /* Cumulative */
@@ -87,13 +90,13 @@
 
   void init ()
   {
-    memset (this, 0, sizeof (*this));
+    hb_memset (this, 0, sizeof (*this));
 
-    features.init ();
+    features.init0 ();
     for (unsigned int table_index = 0; table_index < 2; table_index++)
     {
-      lookups[table_index].init ();
-      stages[table_index].init ();
+      lookups[table_index].init0 ();
+      stages[table_index].init0 ();
     }
   }
   void fini ()
@@ -239,7 +242,8 @@
 				bool          auto_zwnj = true,
 				bool          auto_zwj = true,
 				bool          random = false,
-				bool          per_syllable = false);
+				bool          per_syllable = false,
+				hb_tag_t      feature_tag = HB_TAG(' ',' ',' ',' '));
 
   struct feature_info_t {
     hb_tag_t tag;
diff --git a/src/hb-ot-math-table.hh b/src/hb-ot-math-table.hh
index d834d94..9395337 100644
--- a/src/hb-ot-math-table.hh
+++ b/src/hb-ot-math-table.hh
@@ -77,11 +77,11 @@
 
     HBINT16 *p = c->allocate_size<HBINT16> (HBINT16::static_size * 2);
     if (unlikely (!p)) return_trace (nullptr);
-    memcpy (p, percentScaleDown, HBINT16::static_size * 2);
+    hb_memcpy (p, percentScaleDown, HBINT16::static_size * 2);
 
     HBUINT16 *m = c->allocate_size<HBUINT16> (HBUINT16::static_size * 2);
     if (unlikely (!m)) return_trace (nullptr);
-    memcpy (m, minHeight, HBUINT16::static_size * 2);
+    hb_memcpy (m, minHeight, HBUINT16::static_size * 2);
 
     unsigned count = ARRAY_LENGTH (mathValueRecords);
     for (unsigned i = 0; i < count; i++)
@@ -786,7 +786,7 @@
     if (parts_count)
     {
       int64_t mult = font->dir_mult (direction);
-      for (auto _ : hb_zip (partRecords.sub_array (start_offset, parts_count),
+      for (auto _ : hb_zip (partRecords.as_array ().sub_array (start_offset, parts_count),
 			    hb_array (parts, *parts_count)))
 	_.first.extract (_.second, mult, font);
     }
@@ -855,7 +855,7 @@
     if (variants_count)
     {
       int64_t mult = font->dir_mult (direction);
-      for (auto _ : hb_zip (mathGlyphVariantRecord.sub_array (start_offset, variants_count),
+      for (auto _ : hb_zip (mathGlyphVariantRecord.as_array ().sub_array (start_offset, variants_count),
 			    hb_array (variants, *variants_count)))
 	_.second = {_.first.variantGlyph, font->em_mult (_.first.advanceMeasurement, mult)};
     }
diff --git a/src/hb-ot-meta-table.hh b/src/hb-ot-meta-table.hh
index 93e64c5..e1b68bc 100644
--- a/src/hb-ot-meta-table.hh
+++ b/src/hb-ot-meta-table.hh
@@ -84,7 +84,7 @@
     {
       if (count)
       {
-	+ table->dataMaps.sub_array (start_offset, count)
+	+ table->dataMaps.as_array ().sub_array (start_offset, count)
 	| hb_map (&DataMap::get_tag)
 	| hb_map ([](hb_tag_t tag) { return (hb_ot_meta_tag_t) tag; })
 	| hb_sink (hb_array (entries, *count))
diff --git a/src/hb-ot-name-table.hh b/src/hb-ot-name-table.hh
index 1f2131f..6f4461c 100644
--- a/src/hb-ot-name-table.hh
+++ b/src/hb-ot-name-table.hh
@@ -30,10 +30,55 @@
 #include "hb-open-type.hh"
 #include "hb-ot-name-language.hh"
 #include "hb-aat-layout.hh"
+#include "hb-utf.hh"
 
 
 namespace OT {
 
+template <typename in_utf_t, typename out_utf_t>
+inline unsigned int
+hb_ot_name_convert_utf (hb_bytes_t                       bytes,
+			unsigned int                    *text_size /* IN/OUT */,
+			typename out_utf_t::codepoint_t *text /* OUT */)
+{
+  unsigned int src_len = bytes.length / sizeof (typename in_utf_t::codepoint_t);
+  const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes.arrayZ;
+  const typename in_utf_t::codepoint_t *src_end = src + src_len;
+
+  typename out_utf_t::codepoint_t *dst = text;
+
+  hb_codepoint_t unicode;
+  const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+
+  if (text_size && *text_size)
+  {
+    (*text_size)--; /* Save room for NUL-termination. */
+    const typename out_utf_t::codepoint_t *dst_end = text + *text_size;
+
+    while (src < src_end && dst < dst_end)
+    {
+      const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement);
+      typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode);
+      if (dst_next == dst)
+	break; /* Out-of-room. */
+
+      dst = dst_next;
+      src = src_next;
+    }
+
+    *text_size = dst - text;
+    *dst = 0; /* NUL-terminate. */
+  }
+
+  /* Accumulate length of rest. */
+  unsigned int dst_len = dst - text;
+  while (src < src_end)
+  {
+    src = in_utf_t::next (src, src_end, &unicode, replacement);
+    dst_len += out_utf_t::encode_len (unicode);
+  }
+  return dst_len;
+}
 
 #define entry_score var.u16[0]
 #define entry_index var.u16[1]
@@ -97,12 +142,68 @@
     return UNSUPPORTED;
   }
 
-  NameRecord* copy (hb_serialize_context_t *c, const void *base) const
+  NameRecord* copy (hb_serialize_context_t *c, const void *base
+#ifdef HB_EXPERIMENTAL_API
+                    , const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides
+#endif
+		    ) const
   {
     TRACE_SERIALIZE (this);
+    HB_UNUSED auto snap = c->snapshot ();
     auto *out = c->embed (this);
     if (unlikely (!out)) return_trace (nullptr);
-    out->offset.serialize_copy (c, offset, base, 0, hb_serialize_context_t::Tail, length);
+#ifdef HB_EXPERIMENTAL_API
+    hb_ot_name_record_ids_t record_ids (platformID, encodingID, languageID, nameID);
+    hb_bytes_t* name_bytes;
+
+    if (name_table_overrides->has (record_ids, &name_bytes)) {
+      hb_bytes_t encoded_bytes = *name_bytes;
+      char *name_str_utf16_be = nullptr;
+
+      if (platformID != 1)
+      {
+        unsigned text_size = hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, nullptr, nullptr);
+  
+        text_size++; // needs to consider NULL terminator for use in hb_ot_name_convert_utf()
+        unsigned byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
+        name_str_utf16_be = (char *) hb_calloc (byte_len, 1);
+        if (!name_str_utf16_be)
+        {
+          c->revert (snap);
+          return_trace (nullptr);
+        }
+        hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, &text_size,
+                                                          (hb_utf16_be_t::codepoint_t *) name_str_utf16_be);
+  
+        unsigned encoded_byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
+        if (!encoded_byte_len || !c->check_assign (out->length, encoded_byte_len, HB_SERIALIZE_ERROR_INT_OVERFLOW)) {
+          c->revert (snap);
+          hb_free (name_str_utf16_be);
+          return_trace (nullptr);
+        }
+  
+        encoded_bytes = hb_bytes_t (name_str_utf16_be, encoded_byte_len);
+      }
+      else
+      {
+        // mac platform, copy the UTF-8 string(all ascii characters) as is
+        if (!c->check_assign (out->length, encoded_bytes.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) {
+          c->revert (snap);
+          return_trace (nullptr);
+        }
+      }
+
+      out->offset = 0;
+      c->push ();
+      encoded_bytes.copy (c);
+      c->add_link (out->offset, c->pop_pack (), hb_serialize_context_t::Tail, 0);
+      hb_free (name_str_utf16_be);
+    }
+    else
+#endif
+    {
+      out->offset.serialize_copy (c, offset, base, 0, hb_serialize_context_t::Tail, length);
+    }
     return_trace (out);
   }
 
@@ -216,29 +317,61 @@
 	    hb_requires (hb_is_source_of (Iterator, const NameRecord &))>
   bool serialize (hb_serialize_context_t *c,
 		  Iterator it,
-		  const void *src_string_pool)
+		  const void *src_string_pool
+#ifdef HB_EXPERIMENTAL_API
+                  , const hb_vector_t<hb_ot_name_record_ids_t>& insert_name_records
+		  , const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides
+#endif
+		  )
   {
     TRACE_SERIALIZE (this);
 
     if (unlikely (!c->extend_min ((*this))))  return_trace (false);
 
+    unsigned total_count = it.len ()
+#ifdef HB_EXPERIMENTAL_API
+        + insert_name_records.length
+#endif
+        ;
     this->format = 0;
-    this->count = it.len ();
+    if (!c->check_assign (this->count, total_count, HB_SERIALIZE_ERROR_INT_OVERFLOW))
+      return false;
 
-    NameRecord *name_records = (NameRecord *) hb_calloc (it.len (), NameRecord::static_size);
+    NameRecord *name_records = (NameRecord *) hb_calloc (total_count, NameRecord::static_size);
     if (unlikely (!name_records)) return_trace (false);
 
-    hb_array_t<NameRecord> records (name_records, it.len ());
+    hb_array_t<NameRecord> records (name_records, total_count);
 
     for (const NameRecord& record : it)
     {
-      memcpy (name_records, &record, NameRecord::static_size);
+      hb_memcpy (name_records, &record, NameRecord::static_size);
       name_records++;
     }
 
+#ifdef HB_EXPERIMENTAL_API
+    for (unsigned i = 0; i < insert_name_records.length; i++)
+    {
+      const hb_ot_name_record_ids_t& ids = insert_name_records[i];
+      NameRecord record;
+      record.platformID = ids.platform_id;
+      record.encodingID = ids.encoding_id;
+      record.languageID = ids.language_id;
+      record.nameID = ids.name_id;
+      record.length = 0; // handled in NameRecord copy()
+      record.offset = 0;
+      memcpy (name_records, &record, NameRecord::static_size);
+      name_records++;
+    }
+#endif
+
     records.qsort ();
 
-    c->copy_all (records, src_string_pool);
+    c->copy_all (records,
+		 src_string_pool
+#ifdef HB_EXPERIMENTAL_API
+		 , name_table_overrides
+#endif
+		 );
     hb_free (records.arrayZ);
 
 
@@ -256,6 +389,11 @@
     name *name_prime = c->serializer->start_embed<name> ();
     if (unlikely (!name_prime)) return_trace (false);
 
+#ifdef HB_EXPERIMENTAL_API
+    const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides =
+        c->plan->name_table_overrides;
+#endif
+    
     auto it =
     + nameRecordZ.as_array (count)
     | hb_filter (c->plan->name_ids, &NameRecord::nameID)
@@ -265,10 +403,48 @@
           (c->plan->flags & HB_SUBSET_FLAGS_NAME_LEGACY)
           || namerecord.isUnicode ();
     })
+#ifdef HB_EXPERIMENTAL_API
+    | hb_filter ([&] (const NameRecord& namerecord) {
+      if (name_table_overrides->is_empty ())
+        return true;
+      hb_ot_name_record_ids_t rec_ids (namerecord.platformID,
+                                       namerecord.encodingID,
+                                       namerecord.languageID,
+                                       namerecord.nameID);
+
+      hb_bytes_t *p;
+      if (name_table_overrides->has (rec_ids, &p) &&
+          (*p).length == 0)
+        return false;
+      return true;
+    })
+#endif
     ;
 
-    name_prime->serialize (c->serializer, it, std::addressof (this + stringOffset));
-    return_trace (name_prime->count);
+#ifdef HB_EXPERIMENTAL_API
+    hb_vector_t<hb_ot_name_record_ids_t> insert_name_records;
+    if (!name_table_overrides->is_empty ())
+    {
+      if (unlikely (!insert_name_records.alloc (name_table_overrides->get_population ())))
+        return_trace (false);
+      for (const auto& record_ids : name_table_overrides->keys ())
+      {
+        if (name_table_overrides->get (record_ids).length == 0)
+          continue;
+        if (has_name_record_with_ids (record_ids))
+          continue;
+        insert_name_records.push (record_ids);
+      }
+    }
+#endif
+
+    return (name_prime->serialize (c->serializer, it,
+                                   std::addressof (this + stringOffset)
+#ifdef HB_EXPERIMENTAL_API
+                                   , insert_name_records
+                                   , name_table_overrides
+#endif
+                                   ));
   }
 
   bool sanitize_records (hb_sanitize_context_t *c) const
@@ -378,6 +554,23 @@
     hb_vector_t<hb_ot_name_entry_t> names;
   };
 
+  private:
+  // sometimes NameRecords are not sorted in the font file, so use linear search
+  // here
+  bool has_name_record_with_ids (const hb_ot_name_record_ids_t& record_ids) const
+  {
+    for (const auto& record : nameRecordZ.as_array (count))
+    {
+      if (record.platformID == record_ids.platform_id &&
+          record.encodingID == record_ids.encoding_id &&
+          record.languageID == record_ids.language_id &&
+          record.nameID == record_ids.name_id)
+        return true;
+    }
+    return false;
+  }
+
+  public:
   /* We only implement format 0 for now. */
   HBUINT16	format;		/* Format selector (=0/1). */
   HBUINT16	count;		/* Number of name records. */
diff --git a/src/hb-ot-name.cc b/src/hb-ot-name.cc
index c35ac5b..6adf1e8 100644
--- a/src/hb-ot-name.cc
+++ b/src/hb-ot-name.cc
@@ -64,52 +64,6 @@
   return (const hb_ot_name_entry_t *) name.names;
 }
 
-
-template <typename in_utf_t, typename out_utf_t>
-static inline unsigned int
-hb_ot_name_convert_utf (hb_bytes_t                       bytes,
-			unsigned int                    *text_size /* IN/OUT */,
-			typename out_utf_t::codepoint_t *text /* OUT */)
-{
-  unsigned int src_len = bytes.length / sizeof (typename in_utf_t::codepoint_t);
-  const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes.arrayZ;
-  const typename in_utf_t::codepoint_t *src_end = src + src_len;
-
-  typename out_utf_t::codepoint_t *dst = text;
-
-  hb_codepoint_t unicode;
-  const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
-
-  if (text_size && *text_size)
-  {
-    (*text_size)--; /* Same room for NUL-termination. */
-    const typename out_utf_t::codepoint_t *dst_end = text + *text_size;
-
-    while (src < src_end && dst < dst_end)
-    {
-      const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement);
-      typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode);
-      if (dst_next == dst)
-	break; /* Out-of-room. */
-
-      dst = dst_next;
-      src = src_next;
-    }
-
-    *text_size = dst - text;
-    *dst = 0; /* NUL-terminate. */
-  }
-
-  /* Accumulate length of rest. */
-  unsigned int dst_len = dst - text;
-  while (src < src_end)
-  {
-    src = in_utf_t::next (src, src_end, &unicode, replacement);
-    dst_len += out_utf_t::encode_len (unicode);
-  }
-  return dst_len;
-}
-
 template <typename utf_t>
 static inline unsigned int
 hb_ot_name_get_utf (hb_face_t       *face,
@@ -130,10 +84,10 @@
     hb_bytes_t bytes = name.get_name (idx);
 
     if (width == 2) /* UTF16-BE */
-      return hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (bytes, text_size, text);
+      return OT::hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (bytes, text_size, text);
 
     if (width == 1) /* ASCII */
-      return hb_ot_name_convert_utf<hb_ascii_t, utf_t> (bytes, text_size, text);
+      return OT::hb_ot_name_convert_utf<hb_ascii_t, utf_t> (bytes, text_size, text);
   }
 
   if (text_size)
@@ -227,5 +181,4 @@
   return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text);
 }
 
-
 #endif
diff --git a/src/hb-ot-os2-table.hh b/src/hb-ot-os2-table.hh
index c6e8fad..5b017d5 100644
--- a/src/hb-ot-os2-table.hh
+++ b/src/hb-ot-os2-table.hh
@@ -212,17 +212,6 @@
     TRACE_SUBSET (this);
     OS2 *os2_prime = c->serializer->embed (this);
     if (unlikely (!os2_prime)) return_trace (false);
-    if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES)
-      return_trace (true);
-
-    /* when --gids option is not used, no need to do collect_mapping that is
-       * iterating all codepoints in each subtable, which is not efficient */
-    uint16_t min_cp, max_cp;
-    find_min_and_max_codepoint (c->plan->unicodes, &min_cp, &max_cp);
-    os2_prime->usFirstCharIndex = min_cp;
-    os2_prime->usLastCharIndex = max_cp;
-
-    _update_unicode_ranges (c->plan->unicodes, os2_prime->ulUnicodeRange);
 
     if (c->plan->user_axes_location->has (HB_TAG ('w','g','h','t')) &&
         !c->plan->pinned_at_default)
@@ -244,6 +233,18 @@
         return_trace (false);
     }
 
+    if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES)
+      return_trace (true);
+
+    /* when --gids option is not used, no need to do collect_mapping that is
+       * iterating all codepoints in each subtable, which is not efficient */
+    uint16_t min_cp, max_cp;
+    find_min_and_max_codepoint (c->plan->unicodes, &min_cp, &max_cp);
+    os2_prime->usFirstCharIndex = min_cp;
+    os2_prime->usLastCharIndex = max_cp;
+
+    _update_unicode_ranges (c->plan->unicodes, os2_prime->ulUnicodeRange);
+
     return_trace (true);
   }
 
diff --git a/src/hb-ot-post-table-v2subset.hh b/src/hb-ot-post-table-v2subset.hh
index 4d427e5..951e639 100644
--- a/src/hb-ot-post-table-v2subset.hh
+++ b/src/hb-ot-post-table-v2subset.hh
@@ -78,14 +78,14 @@
 
   post::accelerator_t _post (c->plan->source);
 
-  hb_hashmap_t<hb_bytes_t, unsigned, true> glyph_name_to_new_index;
+  hb_hashmap_t<hb_bytes_t, uint32_t, true> glyph_name_to_new_index;
   for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
   {
     hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
     unsigned old_index = glyphNameIndex[old_gid];
 
     unsigned new_index;
-    const unsigned *new_index2;
+    const uint32_t *new_index2;
     if (old_index <= 257) new_index = old_index;
     else if (old_new_index_map.has (old_index, &new_index2))
     {
diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh
index 59c1de3..a04b803 100644
--- a/src/hb-ot-post-table.hh
+++ b/src/hb-ot-post-table.hh
@@ -84,7 +84,7 @@
     post *post_prime = c->allocate_min<post> ();
     if (unlikely (!post_prime))  return_trace (false);
 
-    memcpy (post_prime, this, post::min_size);
+    hb_memcpy (post_prime, this, post::min_size);
     if (!glyph_names)
       return_trace (c->check_assign (post_prime->version.major, 3,
                                      HB_SERIALIZE_ERROR_INT_OVERFLOW)); // Version 3 does not have any glyph names.
diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc
index 7db0b25..897377a 100644
--- a/src/hb-ot-shape-normalize.cc
+++ b/src/hb-ot-shape-normalize.cc
@@ -341,7 +341,7 @@
     {
       unsigned int end;
       for (end = buffer->idx + 1; end < count; end++)
-	if (unlikely (_hb_glyph_info_is_unicode_mark (&buffer->info[end])))
+	if (_hb_glyph_info_is_unicode_mark (&buffer->info[end]))
 	  break;
 
       if (end < count)
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 249b5a8..bbdfc21 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -91,9 +91,11 @@
   script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
   script_fallback_mark_positioning = shaper->fallback_position;
 
+#ifndef HB_NO_AAT_SHAPE
   /* https://github.com/harfbuzz/harfbuzz/issues/1528 */
   if (apply_morx && shaper != &_hb_ot_shaper_default)
     shaper = &_hb_ot_shaper_dumber;
+#endif
 }
 
 void
@@ -864,7 +866,7 @@
     }
   }
   else
-    hb_ot_layout_delete_glyphs_inplace (buffer, _hb_glyph_info_is_default_ignorable);
+    buffer->delete_glyphs_inplace (_hb_glyph_info_is_default_ignorable);
 }
 
 
diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh
index cd6f15c..ace2860 100644
--- a/src/hb-ot-shape.hh
+++ b/src/hb-ot-shape.hh
@@ -51,7 +51,7 @@
 
   bool equal (const hb_ot_shape_plan_key_t *other)
   {
-    return 0 == memcmp (this, other, sizeof (*this));
+    return 0 == hb_memcmp (this, other, sizeof (*this));
   }
 };
 
diff --git a/src/hb-ot-shaper-arabic.cc b/src/hb-ot-shaper-arabic.cc
index ed2748b..2332ae3 100644
--- a/src/hb-ot-shaper-arabic.cc
+++ b/src/hb-ot-shaper-arabic.cc
@@ -161,22 +161,23 @@
 };
 
 
-static void
+static bool
 arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
 		       hb_font_t *font,
 		       hb_buffer_t *buffer);
 
-static void
+static bool
 record_stch (const hb_ot_shape_plan_t *plan,
 	     hb_font_t *font,
 	     hb_buffer_t *buffer);
 
-static void
+static bool
 deallocate_buffer_var (const hb_ot_shape_plan_t *plan,
 		       hb_font_t *font,
 		       hb_buffer_t *buffer)
 {
   HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
+  return false;
 }
 
 static void
@@ -412,19 +413,19 @@
   setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script);
 }
 
-static void
+static bool
 arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
 		       hb_font_t *font,
 		       hb_buffer_t *buffer)
 {
 #ifdef HB_NO_OT_SHAPER_ARABIC_FALLBACK
-  return;
+  return false;
 #endif
 
   const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
 
   if (!arabic_plan->do_fallback)
-    return;
+    return false;
 
 retry:
   arabic_fallback_plan_t *fallback_plan = arabic_plan->fallback_plan;
@@ -440,6 +441,7 @@
   }
 
   arabic_fallback_plan_shape (fallback_plan, font, buffer);
+  return true;
 }
 
 /*
@@ -450,14 +452,14 @@
  * marks can use it as well.
  */
 
-static void
+static bool
 record_stch (const hb_ot_shape_plan_t *plan,
 	     hb_font_t *font HB_UNUSED,
 	     hb_buffer_t *buffer)
 {
   const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
   if (!arabic_plan->has_stch)
-    return;
+    return false;
 
   /* 'stch' feature was just applied.  Look for anything that multiplied,
    * and record it for stch treatment later.  Note that rtlm, frac, etc
@@ -473,6 +475,7 @@
       info[i].arabic_shaping_action() = comp % 2 ? STCH_REPEATING : STCH_FIXED;
       buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH;
     }
+  return false;
 }
 
 static void
diff --git a/src/hb-ot-shaper-default.cc b/src/hb-ot-shaper-default.cc
index 2f6f499..f0404a4 100644
--- a/src/hb-ot-shaper-default.cc
+++ b/src/hb-ot-shaper-default.cc
@@ -49,6 +49,7 @@
   true, /* fallback_position */
 };
 
+#ifndef HB_NO_AAT_SHAPE
 /* Same as default but no mark advance zeroing / fallback positioning.
  * Dumbest shaper ever, basically. */
 const hb_ot_shaper_t _hb_ot_shaper_dumber =
@@ -68,6 +69,7 @@
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
 };
+#endif
 
 
 #endif
diff --git a/src/hb-ot-shaper-indic-machine.hh b/src/hb-ot-shaper-indic-machine.hh
index d52b13f..d6c67b8 100644
--- a/src/hb-ot-shaper-indic-machine.hh
+++ b/src/hb-ot-shaper-indic-machine.hh
@@ -53,7 +53,7 @@
 };
 
 
-#line 57 "hb-ot-shaper-indic-machine.hh"
+#line 54 "hb-ot-shaper-indic-machine.hh"
 #define indic_syllable_machine_ex_A 9u
 #define indic_syllable_machine_ex_C 1u
 #define indic_syllable_machine_ex_CM 16u
@@ -61,6 +61,7 @@
 #define indic_syllable_machine_ex_DOTTEDCIRCLE 11u
 #define indic_syllable_machine_ex_H 4u
 #define indic_syllable_machine_ex_M 7u
+#define indic_syllable_machine_ex_MPst 13u
 #define indic_syllable_machine_ex_N 3u
 #define indic_syllable_machine_ex_PLACEHOLDER 10u
 #define indic_syllable_machine_ex_RS 12u
@@ -75,268 +76,302 @@
 #define indic_syllable_machine_ex_ZWNJ 5u
 
 
-#line 79 "hb-ot-shaper-indic-machine.hh"
+#line 75 "hb-ot-shaper-indic-machine.hh"
 static const unsigned char _indic_syllable_machine_trans_keys[] = {
-	8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 4u, 12u, 4u, 8u, 8u, 8u, 
-	5u, 7u, 5u, 8u, 4u, 8u, 4u, 12u, 4u, 12u, 4u, 12u, 8u, 8u, 5u, 7u, 
-	5u, 8u, 4u, 8u, 4u, 8u, 4u, 12u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 
-	4u, 8u, 5u, 8u, 8u, 8u, 1u, 18u, 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 
-	5u, 9u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u, 1u, 15u, 1u, 15u, 3u, 9u, 
-	4u, 9u, 5u, 9u, 4u, 9u, 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 
-	3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 
-	5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u, 1u, 15u, 3u, 9u, 4u, 9u, 5u, 9u, 
-	4u, 9u, 5u, 9u, 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 4u, 8u, 
-	3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 
-	5u, 9u, 1u, 15u, 1u, 15u, 3u, 9u, 4u, 9u, 5u, 9u, 3u, 16u, 4u, 9u, 
-	5u, 9u, 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 4u, 12u, 4u, 8u, 3u, 16u, 
-	3u, 16u, 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 
-	1u, 15u, 1u, 15u, 3u, 9u, 4u, 9u, 5u, 9u, 3u, 16u, 4u, 9u, 5u, 9u, 
-	5u, 9u, 3u, 9u, 5u, 9u, 1u, 16u, 3u, 16u, 1u, 16u, 4u, 12u, 5u, 9u, 
-	9u, 9u, 5u, 9u, 1u, 15u, 3u, 9u, 5u, 9u, 5u, 9u, 9u, 9u, 5u, 9u, 
-	1u, 15u, 0
+	8u, 8u, 4u, 13u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 
+	8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 
+	8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u, 
+	5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 5u, 13u, 8u, 8u, 1u, 18u, 
+	3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 5u, 9u, 5u, 9u, 9u, 9u, 5u, 9u, 
+	1u, 15u, 1u, 15u, 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 4u, 13u, 
+	5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 3u, 16u, 3u, 16u, 4u, 16u, 
+	1u, 15u, 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 
+	1u, 15u, 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 4u, 13u, 5u, 9u, 
+	5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 4u, 13u, 3u, 16u, 3u, 16u, 
+	4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u, 
+	1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 3u, 16u, 4u, 13u, 5u, 9u, 
+	5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 4u, 13u, 4u, 13u, 3u, 16u, 3u, 16u, 
+	4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u, 
+	1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 3u, 16u, 4u, 13u, 5u, 9u, 
+	5u, 9u, 3u, 9u, 5u, 9u, 1u, 16u, 3u, 16u, 1u, 16u, 4u, 13u, 5u, 13u, 
+	5u, 13u, 9u, 9u, 5u, 9u, 1u, 15u, 3u, 9u, 5u, 9u, 5u, 9u, 9u, 9u, 
+	5u, 9u, 1u, 15u, 0
 };
 
 static const char _indic_syllable_machine_key_spans[] = {
-	1, 5, 3, 4, 5, 9, 5, 1, 
-	3, 4, 5, 9, 9, 9, 1, 3, 
-	4, 5, 5, 9, 1, 3, 4, 5, 
-	5, 4, 1, 18, 14, 14, 13, 15, 
-	5, 5, 1, 5, 15, 15, 15, 7, 
-	6, 5, 6, 5, 7, 5, 14, 14, 
-	14, 14, 13, 15, 14, 14, 13, 15, 
-	5, 1, 5, 15, 15, 7, 6, 5, 
-	6, 5, 5, 7, 5, 14, 14, 5, 
-	14, 14, 13, 15, 14, 15, 5, 1, 
-	5, 15, 15, 7, 6, 5, 14, 6, 
-	5, 5, 7, 5, 14, 9, 5, 14, 
-	14, 13, 15, 14, 15, 5, 1, 5, 
-	15, 15, 7, 6, 5, 14, 6, 5, 
-	5, 7, 5, 16, 14, 16, 9, 5, 
-	1, 5, 15, 7, 5, 5, 1, 5, 
-	15
+	1, 10, 9, 9, 1, 10, 10, 10, 
+	1, 9, 9, 1, 10, 10, 10, 10, 
+	1, 9, 9, 1, 10, 10, 10, 1, 
+	9, 9, 1, 10, 10, 9, 1, 18, 
+	14, 14, 13, 15, 5, 5, 1, 5, 
+	15, 15, 15, 11, 10, 9, 9, 10, 
+	5, 7, 5, 14, 14, 14, 14, 13, 
+	15, 14, 14, 13, 15, 5, 1, 5, 
+	15, 15, 11, 10, 9, 9, 10, 5, 
+	5, 7, 5, 14, 14, 10, 14, 14, 
+	13, 15, 14, 15, 5, 1, 5, 15, 
+	15, 11, 10, 9, 9, 14, 10, 5, 
+	5, 7, 5, 14, 10, 10, 14, 14, 
+	13, 15, 14, 15, 5, 1, 5, 15, 
+	15, 11, 10, 9, 9, 14, 10, 5, 
+	5, 7, 5, 16, 14, 16, 10, 9, 
+	9, 1, 5, 15, 7, 5, 5, 1, 
+	5, 15
 };
 
 static const short _indic_syllable_machine_index_offsets[] = {
-	0, 2, 8, 12, 17, 23, 33, 39, 
-	41, 45, 50, 56, 66, 76, 86, 88, 
-	92, 97, 103, 109, 119, 121, 125, 130, 
-	136, 142, 147, 149, 168, 183, 198, 212, 
-	228, 234, 240, 242, 248, 264, 280, 296, 
-	304, 311, 317, 324, 330, 338, 344, 359, 
-	374, 389, 404, 418, 434, 449, 464, 478, 
-	494, 500, 502, 508, 524, 540, 548, 555, 
-	561, 568, 574, 580, 588, 594, 609, 624, 
-	630, 645, 660, 674, 690, 705, 721, 727, 
-	729, 735, 751, 767, 775, 782, 788, 803, 
-	810, 816, 822, 830, 836, 851, 861, 867, 
-	882, 897, 911, 927, 942, 958, 964, 966, 
-	972, 988, 1004, 1012, 1019, 1025, 1040, 1047, 
-	1053, 1059, 1067, 1073, 1090, 1105, 1122, 1132, 
-	1138, 1140, 1146, 1162, 1170, 1176, 1182, 1184, 
-	1190
+	0, 2, 13, 23, 33, 35, 46, 57, 
+	68, 70, 80, 90, 92, 103, 114, 125, 
+	136, 138, 148, 158, 160, 171, 182, 193, 
+	195, 205, 215, 217, 228, 239, 249, 251, 
+	270, 285, 300, 314, 330, 336, 342, 344, 
+	350, 366, 382, 398, 410, 421, 431, 441, 
+	452, 458, 466, 472, 487, 502, 517, 532, 
+	546, 562, 577, 592, 606, 622, 628, 630, 
+	636, 652, 668, 680, 691, 701, 711, 722, 
+	728, 734, 742, 748, 763, 778, 789, 804, 
+	819, 833, 849, 864, 880, 886, 888, 894, 
+	910, 926, 938, 949, 959, 969, 984, 995, 
+	1001, 1007, 1015, 1021, 1036, 1047, 1058, 1073, 
+	1088, 1102, 1118, 1133, 1149, 1155, 1157, 1163, 
+	1179, 1195, 1207, 1218, 1228, 1238, 1253, 1264, 
+	1270, 1276, 1284, 1290, 1307, 1322, 1339, 1350, 
+	1360, 1370, 1372, 1378, 1394, 1402, 1408, 1414, 
+	1416, 1422
 };
 
 static const unsigned char _indic_syllable_machine_indicies[] = {
-	1, 0, 2, 3, 3, 4, 1, 0, 
-	3, 3, 4, 0, 3, 3, 4, 1, 
-	0, 5, 3, 3, 4, 1, 0, 2, 
-	3, 3, 4, 1, 0, 0, 0, 6, 
-	0, 8, 9, 9, 10, 11, 7, 11, 
-	7, 9, 9, 10, 7, 9, 9, 10, 
-	11, 7, 12, 9, 9, 10, 11, 7, 
-	8, 9, 9, 10, 11, 7, 7, 7, 
-	13, 7, 8, 9, 9, 10, 11, 7, 
-	7, 7, 14, 7, 16, 17, 17, 18, 
-	19, 15, 15, 15, 20, 15, 19, 15, 
-	17, 17, 18, 21, 17, 17, 18, 19, 
-	15, 16, 17, 17, 18, 19, 15, 22, 
-	17, 17, 18, 19, 15, 24, 25, 25, 
-	26, 27, 23, 23, 23, 28, 23, 27, 
-	23, 25, 25, 26, 23, 25, 25, 26, 
-	27, 23, 24, 25, 25, 26, 27, 23, 
-	29, 25, 25, 26, 27, 23, 17, 17, 
-	18, 1, 0, 31, 30, 33, 34, 35, 
-	36, 37, 38, 18, 19, 39, 40, 40, 
-	20, 32, 41, 42, 43, 44, 45, 32, 
-	47, 48, 49, 50, 4, 1, 51, 46, 
-	46, 6, 46, 46, 46, 52, 46, 53, 
-	48, 54, 54, 4, 1, 51, 46, 46, 
-	46, 46, 46, 46, 52, 46, 48, 54, 
-	54, 4, 1, 51, 46, 46, 46, 46, 
-	46, 46, 52, 46, 33, 46, 46, 46, 
-	55, 56, 46, 1, 51, 46, 46, 46, 
-	46, 46, 33, 46, 57, 57, 46, 1, 
-	51, 46, 51, 46, 46, 58, 51, 46, 
-	51, 46, 51, 46, 46, 46, 51, 46, 
-	33, 46, 59, 46, 57, 57, 46, 1, 
-	51, 46, 46, 46, 46, 46, 33, 46, 
-	33, 46, 46, 46, 57, 57, 46, 1, 
-	51, 46, 46, 46, 46, 46, 33, 46, 
-	33, 46, 46, 46, 57, 56, 46, 1, 
-	51, 46, 46, 46, 46, 46, 33, 46, 
-	60, 61, 62, 62, 4, 1, 51, 46, 
-	61, 62, 62, 4, 1, 51, 46, 62, 
-	62, 4, 1, 51, 46, 63, 64, 64, 
-	4, 1, 51, 46, 55, 65, 46, 1, 
-	51, 46, 55, 46, 57, 57, 46, 1, 
-	51, 46, 57, 65, 46, 1, 51, 46, 
-	47, 48, 54, 54, 4, 1, 51, 46, 
-	46, 46, 46, 46, 46, 52, 46, 47, 
-	48, 49, 54, 4, 1, 51, 46, 46, 
-	6, 46, 46, 46, 52, 46, 67, 68, 
-	69, 70, 10, 11, 71, 66, 66, 14, 
-	66, 66, 66, 72, 66, 73, 68, 74, 
-	70, 10, 11, 71, 66, 66, 66, 66, 
-	66, 66, 72, 66, 68, 74, 70, 10, 
-	11, 71, 66, 66, 66, 66, 66, 66, 
-	72, 66, 75, 66, 66, 66, 76, 77, 
-	66, 11, 71, 66, 66, 66, 66, 66, 
-	75, 66, 78, 68, 79, 80, 10, 11, 
-	71, 66, 66, 13, 66, 66, 66, 72, 
-	66, 81, 68, 74, 74, 10, 11, 71, 
-	66, 66, 66, 66, 66, 66, 72, 66, 
-	68, 74, 74, 10, 11, 71, 66, 66, 
-	66, 66, 66, 66, 72, 66, 75, 66, 
-	66, 66, 82, 77, 66, 11, 71, 66, 
-	66, 66, 66, 66, 75, 66, 71, 66, 
-	66, 83, 71, 66, 71, 66, 71, 66, 
-	66, 66, 71, 66, 75, 66, 84, 66, 
-	82, 82, 66, 11, 71, 66, 66, 66, 
-	66, 66, 75, 66, 75, 66, 66, 66, 
-	82, 82, 66, 11, 71, 66, 66, 66, 
-	66, 66, 75, 66, 85, 86, 87, 87, 
-	10, 11, 71, 66, 86, 87, 87, 10, 
-	11, 71, 66, 87, 87, 10, 11, 71, 
-	66, 88, 89, 89, 10, 11, 71, 66, 
-	76, 90, 66, 11, 71, 66, 82, 82, 
-	66, 11, 71, 66, 76, 66, 82, 82, 
-	66, 11, 71, 66, 82, 90, 66, 11, 
-	71, 66, 78, 68, 74, 74, 10, 11, 
-	71, 66, 66, 66, 66, 66, 66, 72, 
-	66, 78, 68, 79, 74, 10, 11, 71, 
-	66, 66, 13, 66, 66, 66, 72, 66, 
-	8, 9, 9, 10, 11, 66, 67, 68, 
-	74, 70, 10, 11, 71, 66, 66, 66, 
-	66, 66, 66, 72, 66, 92, 36, 93, 
-	93, 18, 19, 39, 91, 91, 91, 91, 
-	91, 91, 43, 91, 36, 93, 93, 18, 
-	19, 39, 91, 91, 91, 91, 91, 91, 
-	43, 91, 94, 91, 91, 91, 95, 96, 
-	91, 19, 39, 91, 91, 91, 91, 91, 
-	94, 91, 35, 36, 97, 98, 18, 19, 
-	39, 91, 91, 20, 91, 91, 91, 43, 
-	91, 94, 91, 91, 91, 99, 96, 91, 
-	19, 39, 91, 91, 91, 91, 91, 94, 
-	91, 39, 91, 91, 100, 39, 91, 39, 
-	91, 39, 91, 91, 91, 39, 91, 94, 
-	91, 101, 91, 99, 99, 91, 19, 39, 
-	91, 91, 91, 91, 91, 94, 91, 94, 
-	91, 91, 91, 99, 99, 91, 19, 39, 
-	91, 91, 91, 91, 91, 94, 91, 102, 
-	103, 104, 104, 18, 19, 39, 91, 103, 
-	104, 104, 18, 19, 39, 91, 104, 104, 
-	18, 19, 39, 91, 35, 36, 93, 93, 
-	18, 19, 39, 91, 91, 91, 91, 91, 
-	91, 43, 91, 105, 106, 106, 18, 19, 
-	39, 91, 95, 107, 91, 19, 39, 91, 
-	99, 99, 91, 19, 39, 91, 95, 91, 
-	99, 99, 91, 19, 39, 91, 99, 107, 
-	91, 19, 39, 91, 35, 36, 97, 93, 
-	18, 19, 39, 91, 91, 20, 91, 91, 
-	91, 43, 91, 16, 17, 17, 18, 19, 
-	108, 108, 108, 20, 108, 16, 17, 17, 
-	18, 19, 108, 110, 111, 112, 113, 26, 
-	27, 114, 109, 109, 28, 109, 109, 109, 
-	115, 109, 116, 111, 113, 113, 26, 27, 
-	114, 109, 109, 109, 109, 109, 109, 115, 
-	109, 111, 113, 113, 26, 27, 114, 109, 
-	109, 109, 109, 109, 109, 115, 109, 117, 
-	109, 109, 109, 118, 119, 109, 27, 114, 
-	109, 109, 109, 109, 109, 117, 109, 110, 
-	111, 112, 40, 26, 27, 114, 109, 109, 
-	28, 109, 109, 109, 115, 109, 117, 109, 
-	109, 109, 120, 119, 109, 27, 114, 109, 
-	109, 109, 109, 109, 117, 109, 114, 109, 
-	109, 121, 114, 109, 114, 109, 114, 109, 
-	109, 109, 114, 109, 117, 109, 122, 109, 
-	120, 120, 109, 27, 114, 109, 109, 109, 
-	109, 109, 117, 109, 117, 109, 109, 109, 
-	120, 120, 109, 27, 114, 109, 109, 109, 
-	109, 109, 117, 109, 123, 124, 125, 125, 
-	26, 27, 114, 109, 124, 125, 125, 26, 
-	27, 114, 109, 125, 125, 26, 27, 114, 
-	109, 110, 111, 113, 113, 26, 27, 114, 
-	109, 109, 109, 109, 109, 109, 115, 109, 
-	126, 127, 127, 26, 27, 114, 109, 118, 
-	128, 109, 27, 114, 109, 120, 120, 109, 
-	27, 114, 109, 118, 109, 120, 120, 109, 
-	27, 114, 109, 120, 128, 109, 27, 114, 
-	109, 33, 34, 35, 36, 97, 93, 18, 
-	19, 39, 40, 40, 20, 91, 91, 33, 
-	43, 91, 47, 129, 49, 50, 4, 1, 
-	51, 46, 46, 6, 46, 46, 46, 52, 
-	46, 33, 34, 35, 36, 130, 131, 18, 
-	132, 133, 46, 40, 20, 46, 46, 33, 
-	43, 46, 16, 134, 134, 18, 132, 51, 
-	46, 46, 20, 46, 133, 46, 46, 135, 
-	133, 46, 133, 46, 133, 46, 46, 46, 
-	133, 46, 33, 46, 59, 16, 134, 134, 
-	18, 132, 51, 46, 46, 46, 46, 46, 
-	33, 46, 137, 136, 138, 138, 136, 31, 
-	139, 136, 138, 138, 136, 31, 139, 136, 
-	139, 136, 136, 140, 139, 136, 139, 136, 
-	139, 136, 136, 136, 139, 136, 33, 108, 
-	108, 108, 108, 108, 108, 108, 108, 40, 
-	108, 108, 108, 108, 33, 108, 0
+	1, 0, 2, 3, 3, 4, 5, 0, 
+	0, 0, 0, 4, 0, 3, 3, 4, 
+	6, 0, 0, 0, 0, 4, 0, 3, 
+	3, 4, 5, 0, 0, 0, 0, 4, 
+	0, 4, 0, 7, 3, 3, 4, 5, 
+	0, 0, 0, 0, 4, 0, 2, 3, 
+	3, 4, 5, 0, 0, 0, 8, 4, 
+	0, 10, 11, 11, 12, 13, 9, 9, 
+	9, 9, 12, 9, 14, 9, 11, 11, 
+	12, 15, 9, 9, 9, 9, 12, 9, 
+	11, 11, 12, 13, 9, 9, 9, 9, 
+	12, 9, 12, 9, 16, 11, 11, 12, 
+	13, 9, 9, 9, 9, 12, 9, 10, 
+	11, 11, 12, 13, 9, 9, 9, 17, 
+	12, 9, 10, 11, 11, 12, 13, 9, 
+	9, 9, 18, 12, 9, 20, 21, 21, 
+	22, 23, 19, 19, 19, 24, 22, 19, 
+	25, 19, 21, 21, 22, 27, 26, 26, 
+	26, 26, 22, 26, 21, 21, 22, 23, 
+	19, 19, 19, 19, 22, 19, 22, 26, 
+	20, 21, 21, 22, 23, 19, 19, 19, 
+	19, 22, 19, 28, 21, 21, 22, 23, 
+	19, 19, 19, 19, 22, 19, 30, 31, 
+	31, 32, 33, 29, 29, 29, 34, 32, 
+	29, 35, 29, 31, 31, 32, 36, 29, 
+	29, 29, 29, 32, 29, 31, 31, 32, 
+	33, 29, 29, 29, 29, 32, 29, 32, 
+	29, 30, 31, 31, 32, 33, 29, 29, 
+	29, 29, 32, 29, 37, 31, 31, 32, 
+	33, 29, 29, 29, 29, 32, 29, 21, 
+	21, 22, 38, 0, 0, 0, 0, 22, 
+	0, 40, 39, 42, 43, 44, 45, 46, 
+	47, 22, 23, 48, 49, 49, 24, 22, 
+	50, 51, 52, 53, 54, 41, 56, 57, 
+	58, 59, 4, 5, 60, 55, 55, 8, 
+	4, 55, 55, 61, 55, 62, 57, 63, 
+	63, 4, 5, 60, 55, 55, 55, 4, 
+	55, 55, 61, 55, 57, 63, 63, 4, 
+	5, 60, 55, 55, 55, 4, 55, 55, 
+	61, 55, 42, 55, 55, 55, 64, 65, 
+	55, 1, 60, 55, 55, 55, 55, 55, 
+	42, 55, 66, 66, 55, 1, 60, 55, 
+	60, 55, 55, 67, 60, 55, 60, 55, 
+	60, 55, 55, 55, 60, 55, 42, 55, 
+	68, 55, 66, 66, 55, 1, 60, 55, 
+	55, 55, 55, 55, 42, 55, 42, 55, 
+	55, 55, 66, 66, 55, 1, 60, 55, 
+	55, 55, 55, 55, 42, 55, 42, 55, 
+	55, 55, 66, 65, 55, 1, 60, 55, 
+	55, 55, 55, 55, 42, 55, 69, 70, 
+	71, 71, 4, 5, 60, 55, 55, 55, 
+	4, 55, 70, 71, 71, 4, 5, 60, 
+	55, 55, 55, 4, 55, 71, 71, 4, 
+	5, 60, 55, 55, 55, 4, 55, 60, 
+	55, 55, 67, 60, 55, 55, 55, 4, 
+	55, 72, 73, 73, 4, 5, 60, 55, 
+	55, 55, 4, 55, 64, 74, 55, 1, 
+	60, 55, 64, 55, 66, 66, 55, 1, 
+	60, 55, 66, 74, 55, 1, 60, 55, 
+	56, 57, 63, 63, 4, 5, 60, 55, 
+	55, 55, 4, 55, 55, 61, 55, 56, 
+	57, 58, 63, 4, 5, 60, 55, 55, 
+	8, 4, 55, 55, 61, 55, 76, 77, 
+	78, 79, 12, 13, 80, 75, 75, 18, 
+	12, 75, 75, 81, 75, 82, 77, 83, 
+	79, 12, 13, 80, 75, 75, 75, 12, 
+	75, 75, 81, 75, 77, 83, 79, 12, 
+	13, 80, 75, 75, 75, 12, 75, 75, 
+	81, 75, 84, 75, 75, 75, 85, 86, 
+	75, 14, 80, 75, 75, 75, 75, 75, 
+	84, 75, 87, 77, 88, 89, 12, 13, 
+	80, 75, 75, 17, 12, 75, 75, 81, 
+	75, 90, 77, 83, 83, 12, 13, 80, 
+	75, 75, 75, 12, 75, 75, 81, 75, 
+	77, 83, 83, 12, 13, 80, 75, 75, 
+	75, 12, 75, 75, 81, 75, 84, 75, 
+	75, 75, 91, 86, 75, 14, 80, 75, 
+	75, 75, 75, 75, 84, 75, 80, 75, 
+	75, 92, 80, 75, 80, 75, 80, 75, 
+	75, 75, 80, 75, 84, 75, 93, 75, 
+	91, 91, 75, 14, 80, 75, 75, 75, 
+	75, 75, 84, 75, 84, 75, 75, 75, 
+	91, 91, 75, 14, 80, 75, 75, 75, 
+	75, 75, 84, 75, 94, 95, 96, 96, 
+	12, 13, 80, 75, 75, 75, 12, 75, 
+	95, 96, 96, 12, 13, 80, 75, 75, 
+	75, 12, 75, 96, 96, 12, 13, 80, 
+	75, 75, 75, 12, 75, 80, 75, 75, 
+	92, 80, 75, 75, 75, 12, 75, 97, 
+	98, 98, 12, 13, 80, 75, 75, 75, 
+	12, 75, 85, 99, 75, 14, 80, 75, 
+	91, 91, 75, 14, 80, 75, 85, 75, 
+	91, 91, 75, 14, 80, 75, 91, 99, 
+	75, 14, 80, 75, 87, 77, 83, 83, 
+	12, 13, 80, 75, 75, 75, 12, 75, 
+	75, 81, 75, 87, 77, 88, 83, 12, 
+	13, 80, 75, 75, 17, 12, 75, 75, 
+	81, 75, 10, 11, 11, 12, 13, 75, 
+	75, 75, 75, 12, 75, 76, 77, 83, 
+	79, 12, 13, 80, 75, 75, 75, 12, 
+	75, 75, 81, 75, 101, 45, 102, 102, 
+	22, 23, 48, 100, 100, 100, 22, 100, 
+	100, 52, 100, 45, 102, 102, 22, 23, 
+	48, 100, 100, 100, 22, 100, 100, 52, 
+	100, 103, 100, 100, 100, 104, 105, 100, 
+	25, 48, 100, 100, 100, 100, 100, 103, 
+	100, 44, 45, 106, 107, 22, 23, 48, 
+	100, 100, 24, 22, 100, 100, 52, 100, 
+	103, 100, 100, 100, 108, 105, 100, 25, 
+	48, 100, 100, 100, 100, 100, 103, 100, 
+	48, 100, 100, 109, 48, 100, 48, 100, 
+	48, 100, 100, 100, 48, 100, 103, 100, 
+	110, 100, 108, 108, 100, 25, 48, 100, 
+	100, 100, 100, 100, 103, 100, 103, 100, 
+	100, 100, 108, 108, 100, 25, 48, 100, 
+	100, 100, 100, 100, 103, 100, 111, 112, 
+	113, 113, 22, 23, 48, 100, 100, 100, 
+	22, 100, 112, 113, 113, 22, 23, 48, 
+	100, 100, 100, 22, 100, 113, 113, 22, 
+	23, 48, 100, 100, 100, 22, 100, 48, 
+	100, 100, 109, 48, 100, 100, 100, 22, 
+	100, 44, 45, 102, 102, 22, 23, 48, 
+	100, 100, 100, 22, 100, 100, 52, 100, 
+	114, 115, 115, 22, 23, 48, 100, 100, 
+	100, 22, 100, 104, 116, 100, 25, 48, 
+	100, 108, 108, 100, 25, 48, 100, 104, 
+	100, 108, 108, 100, 25, 48, 100, 108, 
+	116, 100, 25, 48, 100, 44, 45, 106, 
+	102, 22, 23, 48, 100, 100, 24, 22, 
+	100, 100, 52, 100, 20, 21, 21, 22, 
+	23, 117, 117, 117, 24, 22, 117, 20, 
+	21, 21, 22, 23, 117, 117, 117, 117, 
+	22, 117, 119, 120, 121, 122, 32, 33, 
+	123, 118, 118, 34, 32, 118, 118, 124, 
+	118, 125, 120, 122, 122, 32, 33, 123, 
+	118, 118, 118, 32, 118, 118, 124, 118, 
+	120, 122, 122, 32, 33, 123, 118, 118, 
+	118, 32, 118, 118, 124, 118, 126, 118, 
+	118, 118, 127, 128, 118, 35, 123, 118, 
+	118, 118, 118, 118, 126, 118, 119, 120, 
+	121, 49, 32, 33, 123, 118, 118, 34, 
+	32, 118, 118, 124, 118, 126, 118, 118, 
+	118, 129, 128, 118, 35, 123, 118, 118, 
+	118, 118, 118, 126, 118, 123, 118, 118, 
+	130, 123, 118, 123, 118, 123, 118, 118, 
+	118, 123, 118, 126, 118, 131, 118, 129, 
+	129, 118, 35, 123, 118, 118, 118, 118, 
+	118, 126, 118, 126, 118, 118, 118, 129, 
+	129, 118, 35, 123, 118, 118, 118, 118, 
+	118, 126, 118, 132, 133, 134, 134, 32, 
+	33, 123, 118, 118, 118, 32, 118, 133, 
+	134, 134, 32, 33, 123, 118, 118, 118, 
+	32, 118, 134, 134, 32, 33, 123, 118, 
+	118, 118, 32, 118, 123, 118, 118, 130, 
+	123, 118, 118, 118, 32, 118, 119, 120, 
+	122, 122, 32, 33, 123, 118, 118, 118, 
+	32, 118, 118, 124, 118, 135, 136, 136, 
+	32, 33, 123, 118, 118, 118, 32, 118, 
+	127, 137, 118, 35, 123, 118, 129, 129, 
+	118, 35, 123, 118, 127, 118, 129, 129, 
+	118, 35, 123, 118, 129, 137, 118, 35, 
+	123, 118, 42, 43, 44, 45, 106, 102, 
+	22, 23, 48, 49, 49, 24, 22, 100, 
+	42, 52, 100, 56, 138, 58, 59, 4, 
+	5, 60, 55, 55, 8, 4, 55, 55, 
+	61, 55, 42, 43, 44, 45, 139, 140, 
+	22, 141, 142, 55, 49, 24, 22, 55, 
+	42, 52, 55, 20, 143, 143, 22, 141, 
+	60, 55, 55, 24, 22, 55, 60, 55, 
+	55, 67, 60, 55, 55, 55, 22, 55, 
+	142, 55, 55, 144, 142, 55, 55, 55, 
+	22, 55, 142, 55, 142, 55, 55, 55, 
+	142, 55, 42, 55, 68, 20, 143, 143, 
+	22, 141, 60, 55, 55, 55, 22, 55, 
+	42, 55, 146, 145, 147, 147, 145, 40, 
+	148, 145, 147, 147, 145, 40, 148, 145, 
+	148, 145, 145, 149, 148, 145, 148, 145, 
+	148, 145, 145, 145, 148, 145, 42, 117, 
+	117, 117, 117, 117, 117, 117, 117, 49, 
+	117, 117, 117, 117, 42, 117, 0
 };
 
 static const unsigned char _indic_syllable_machine_trans_targs[] = {
-	27, 33, 38, 2, 39, 45, 46, 27, 
-	55, 8, 61, 56, 68, 69, 72, 27, 
-	77, 15, 83, 78, 86, 27, 91, 27, 
-	100, 21, 106, 101, 109, 114, 27, 125, 
-	27, 28, 48, 73, 75, 93, 94, 79, 
-	95, 115, 116, 87, 123, 128, 27, 29, 
-	31, 5, 47, 34, 42, 30, 1, 32, 
-	36, 0, 35, 37, 40, 41, 3, 43, 
-	4, 44, 27, 49, 51, 12, 71, 57, 
-	64, 50, 6, 52, 66, 59, 53, 11, 
-	70, 54, 7, 58, 60, 62, 63, 9, 
-	65, 10, 67, 27, 74, 17, 76, 89, 
-	81, 13, 92, 14, 80, 82, 84, 85, 
-	16, 88, 18, 90, 27, 27, 96, 98, 
-	19, 23, 102, 110, 97, 99, 112, 104, 
-	20, 103, 105, 107, 108, 22, 111, 24, 
-	113, 117, 118, 122, 119, 120, 25, 121, 
-	27, 124, 26, 126, 127
+	31, 37, 42, 2, 43, 46, 4, 50, 
+	51, 31, 60, 9, 66, 69, 61, 11, 
+	74, 75, 78, 31, 83, 17, 89, 92, 
+	93, 84, 31, 19, 98, 31, 107, 24, 
+	113, 116, 117, 108, 26, 122, 127, 31, 
+	134, 31, 32, 53, 79, 81, 100, 101, 
+	85, 102, 123, 124, 94, 132, 137, 31, 
+	33, 35, 6, 52, 38, 47, 34, 1, 
+	36, 40, 0, 39, 41, 44, 45, 3, 
+	48, 5, 49, 31, 54, 56, 14, 77, 
+	62, 70, 55, 7, 57, 72, 64, 58, 
+	13, 76, 59, 8, 63, 65, 67, 68, 
+	10, 71, 12, 73, 31, 80, 20, 82, 
+	96, 87, 15, 99, 16, 86, 88, 90, 
+	91, 18, 95, 21, 97, 31, 31, 103, 
+	105, 22, 27, 109, 118, 104, 106, 120, 
+	111, 23, 110, 112, 114, 115, 25, 119, 
+	28, 121, 125, 126, 131, 128, 129, 29, 
+	130, 31, 133, 30, 135, 136
 };
 
 static const char _indic_syllable_machine_trans_actions[] = {
-	1, 0, 2, 0, 2, 2, 2, 3, 
-	2, 0, 2, 0, 2, 2, 2, 4, 
-	2, 0, 5, 0, 5, 6, 2, 7, 
-	2, 0, 2, 0, 2, 2, 8, 0, 
-	11, 2, 2, 5, 0, 12, 12, 0, 
-	2, 5, 2, 5, 2, 0, 13, 2, 
-	0, 0, 2, 0, 2, 2, 0, 2, 
-	2, 0, 0, 2, 2, 2, 0, 0, 
-	0, 2, 14, 2, 0, 0, 2, 0, 
-	2, 2, 0, 2, 2, 2, 2, 0, 
+	1, 0, 2, 0, 2, 0, 0, 2, 
+	2, 3, 2, 0, 2, 0, 0, 0, 
+	2, 2, 2, 4, 2, 0, 5, 0, 
+	5, 0, 6, 0, 2, 7, 2, 0, 
+	2, 0, 2, 0, 0, 2, 0, 8, 
+	0, 11, 2, 2, 5, 0, 12, 12, 
+	0, 2, 5, 2, 5, 2, 0, 13, 
+	2, 0, 0, 2, 0, 2, 2, 0, 
 	2, 2, 0, 0, 2, 2, 2, 0, 
-	0, 0, 2, 15, 5, 0, 5, 2, 
-	2, 0, 5, 0, 0, 2, 5, 5, 
-	0, 0, 0, 2, 16, 17, 2, 0, 
-	0, 0, 0, 2, 2, 2, 2, 2, 
-	0, 0, 2, 2, 2, 0, 0, 0, 
-	2, 0, 18, 18, 0, 0, 0, 0, 
-	19, 2, 0, 0, 0
+	0, 0, 2, 14, 2, 0, 0, 2, 
+	0, 2, 2, 0, 2, 2, 2, 2, 
+	0, 2, 2, 0, 0, 2, 2, 2, 
+	0, 0, 0, 2, 15, 5, 0, 5, 
+	2, 2, 0, 5, 0, 0, 2, 5, 
+	5, 0, 0, 0, 2, 16, 17, 2, 
+	0, 0, 0, 0, 2, 2, 2, 2, 
+	2, 0, 0, 2, 2, 2, 0, 0, 
+	0, 2, 0, 18, 18, 0, 0, 0, 
+	0, 19, 2, 0, 0, 0
 };
 
 static const char _indic_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, 9, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 9, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
@@ -349,14 +384,15 @@
 	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, 
+	0, 0
 };
 
 static const char _indic_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, 10, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 10, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
@@ -369,41 +405,43 @@
 	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, 
+	0, 0
 };
 
 static const short _indic_syllable_machine_eof_trans[] = {
-	1, 1, 1, 1, 1, 1, 8, 8, 
-	8, 8, 8, 8, 8, 16, 16, 22, 
-	16, 16, 16, 24, 24, 24, 24, 24, 
-	24, 1, 31, 0, 47, 47, 47, 47, 
-	47, 47, 47, 47, 47, 47, 47, 47, 
-	47, 47, 47, 47, 47, 47, 47, 47, 
-	67, 67, 67, 67, 67, 67, 67, 67, 
-	67, 67, 67, 67, 67, 67, 67, 67, 
-	67, 67, 67, 67, 67, 67, 67, 67, 
-	67, 92, 92, 92, 92, 92, 92, 92, 
-	92, 92, 92, 92, 92, 92, 92, 92, 
-	92, 92, 92, 92, 92, 109, 109, 110, 
-	110, 110, 110, 110, 110, 110, 110, 110, 
-	110, 110, 110, 110, 110, 110, 110, 110, 
-	110, 110, 110, 92, 47, 47, 47, 47, 
-	47, 47, 47, 137, 137, 137, 137, 137, 
-	109
+	1, 1, 1, 1, 1, 1, 1, 10, 
+	10, 10, 10, 10, 10, 10, 10, 20, 
+	20, 27, 20, 27, 20, 20, 30, 30, 
+	30, 30, 30, 30, 30, 1, 40, 0, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 76, 76, 76, 
+	76, 76, 76, 76, 76, 76, 76, 76, 
+	76, 76, 76, 76, 76, 76, 76, 76, 
+	76, 76, 76, 76, 76, 76, 76, 101, 
+	101, 101, 101, 101, 101, 101, 101, 101, 
+	101, 101, 101, 101, 101, 101, 101, 101, 
+	101, 101, 101, 101, 118, 118, 119, 119, 
+	119, 119, 119, 119, 119, 119, 119, 119, 
+	119, 119, 119, 119, 119, 119, 119, 119, 
+	119, 119, 119, 101, 56, 56, 56, 56, 
+	56, 56, 56, 56, 146, 146, 146, 146, 
+	146, 118
 };
 
-static const int indic_syllable_machine_start = 27;
-static const int indic_syllable_machine_first_final = 27;
+static const int indic_syllable_machine_start = 31;
+static const int indic_syllable_machine_first_final = 31;
 static const int indic_syllable_machine_error = -1;
 
-static const int indic_syllable_machine_en_main = 27;
+static const int indic_syllable_machine_en_main = 31;
 
 
 #line 58 "hb-ot-shaper-indic-machine.rl"
 
 
 
-#line 117 "hb-ot-shaper-indic-machine.rl"
+#line 118 "hb-ot-shaper-indic-machine.rl"
 
 
 #define found_syllable(syllable_type) \
@@ -412,7 +450,7 @@
     for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     syllable_serial++; \
-    if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+    if (syllable_serial == 16) syllable_serial = 1; \
   } HB_STMT_END
 
 inline void
@@ -422,7 +460,7 @@
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 426 "hb-ot-shaper-indic-machine.hh"
+#line 453 "hb-ot-shaper-indic-machine.hh"
 	{
 	cs = indic_syllable_machine_start;
 	ts = 0;
@@ -430,7 +468,7 @@
 	act = 0;
 	}
 
-#line 137 "hb-ot-shaper-indic-machine.rl"
+#line 138 "hb-ot-shaper-indic-machine.rl"
 
 
   p = 0;
@@ -438,7 +476,7 @@
 
   unsigned int syllable_serial = 1;
   
-#line 442 "hb-ot-shaper-indic-machine.hh"
+#line 465 "hb-ot-shaper-indic-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -452,7 +490,7 @@
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 456 "hb-ot-shaper-indic-machine.hh"
+#line 477 "hb-ot-shaper-indic-machine.hh"
 	}
 
 	_keys = _indic_syllable_machine_trans_keys + (cs<<1);
@@ -475,51 +513,51 @@
 	{te = p+1;}
 	break;
 	case 11:
-#line 113 "hb-ot-shaper-indic-machine.rl"
+#line 114 "hb-ot-shaper-indic-machine.rl"
 	{te = p+1;{ found_syllable (indic_non_indic_cluster); }}
 	break;
 	case 13:
-#line 108 "hb-ot-shaper-indic-machine.rl"
+#line 109 "hb-ot-shaper-indic-machine.rl"
 	{te = p;p--;{ found_syllable (indic_consonant_syllable); }}
 	break;
 	case 14:
-#line 109 "hb-ot-shaper-indic-machine.rl"
+#line 110 "hb-ot-shaper-indic-machine.rl"
 	{te = p;p--;{ found_syllable (indic_vowel_syllable); }}
 	break;
 	case 17:
-#line 110 "hb-ot-shaper-indic-machine.rl"
+#line 111 "hb-ot-shaper-indic-machine.rl"
 	{te = p;p--;{ found_syllable (indic_standalone_cluster); }}
 	break;
 	case 19:
-#line 111 "hb-ot-shaper-indic-machine.rl"
+#line 112 "hb-ot-shaper-indic-machine.rl"
 	{te = p;p--;{ found_syllable (indic_symbol_cluster); }}
 	break;
 	case 15:
-#line 112 "hb-ot-shaper-indic-machine.rl"
+#line 113 "hb-ot-shaper-indic-machine.rl"
 	{te = p;p--;{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
 	break;
 	case 16:
-#line 113 "hb-ot-shaper-indic-machine.rl"
+#line 114 "hb-ot-shaper-indic-machine.rl"
 	{te = p;p--;{ found_syllable (indic_non_indic_cluster); }}
 	break;
 	case 1:
-#line 108 "hb-ot-shaper-indic-machine.rl"
+#line 109 "hb-ot-shaper-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (indic_consonant_syllable); }}
 	break;
 	case 3:
-#line 109 "hb-ot-shaper-indic-machine.rl"
+#line 110 "hb-ot-shaper-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (indic_vowel_syllable); }}
 	break;
 	case 7:
-#line 110 "hb-ot-shaper-indic-machine.rl"
+#line 111 "hb-ot-shaper-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (indic_standalone_cluster); }}
 	break;
 	case 8:
-#line 111 "hb-ot-shaper-indic-machine.rl"
+#line 112 "hb-ot-shaper-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (indic_symbol_cluster); }}
 	break;
 	case 4:
-#line 112 "hb-ot-shaper-indic-machine.rl"
+#line 113 "hb-ot-shaper-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
 	break;
 	case 6:
@@ -540,19 +578,19 @@
 	case 18:
 #line 1 "NONE"
 	{te = p+1;}
-#line 108 "hb-ot-shaper-indic-machine.rl"
+#line 109 "hb-ot-shaper-indic-machine.rl"
 	{act = 1;}
 	break;
 	case 5:
 #line 1 "NONE"
 	{te = p+1;}
-#line 112 "hb-ot-shaper-indic-machine.rl"
+#line 113 "hb-ot-shaper-indic-machine.rl"
 	{act = 5;}
 	break;
 	case 12:
 #line 1 "NONE"
 	{te = p+1;}
-#line 113 "hb-ot-shaper-indic-machine.rl"
+#line 114 "hb-ot-shaper-indic-machine.rl"
 	{act = 6;}
 	break;
 #line 559 "hb-ot-shaper-indic-machine.hh"
@@ -564,7 +602,7 @@
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 568 "hb-ot-shaper-indic-machine.hh"
+#line 566 "hb-ot-shaper-indic-machine.hh"
 	}
 
 	if ( ++p != pe )
@@ -580,7 +618,7 @@
 
 	}
 
-#line 145 "hb-ot-shaper-indic-machine.rl"
+#line 146 "hb-ot-shaper-indic-machine.rl"
 
 }
 
diff --git a/src/hb-ot-shaper-indic-machine.rl b/src/hb-ot-shaper-indic-machine.rl
index 3274a77..4684188 100644
--- a/src/hb-ot-shaper-indic-machine.rl
+++ b/src/hb-ot-shaper-indic-machine.rl
@@ -74,6 +74,7 @@
 export PLACEHOLDER = 10;
 export DOTTEDCIRCLE = 11;
 export RS    = 12;
+export MPst  = 13;
 export Repha = 14;
 export Ra    = 15;
 export CM    = 16;
@@ -88,7 +89,7 @@
 
 cn = c.ZWJ?.n?;
 symbol = Symbol.N?;
-matra_group = z*.M.N?.H?;
+matra_group = z*.(M | SM? MPst).N?.H?;
 syllable_tail = (z?.SM.SM?.ZWNJ?)? (A | VD)*;
 halant_group = (z?.H.(ZWJ.N?)?);
 final_halant_group = halant_group | H.ZWNJ;
@@ -122,7 +123,7 @@
     for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     syllable_serial++; \
-    if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+    if (syllable_serial == 16) syllable_serial = 1; \
   } HB_STMT_END
 
 inline void
diff --git a/src/hb-ot-shaper-indic-table.cc b/src/hb-ot-shaper-indic-table.cc
index bf6a275..d9fb051 100644
--- a/src/hb-ot-shaper-indic-table.cc
+++ b/src/hb-ot-shaper-indic-table.cc
@@ -42,6 +42,7 @@
 #define OT_PLACEHOLDER I_Cat(PLACEHOLDER)
 #define OT_DOTTEDCIRCLE I_Cat(DOTTEDCIRCLE)
 #define OT_RS I_Cat(RS)
+#define OT_MPst I_Cat(MPst)
 #define OT_Repha I_Cat(Repha)
 #define OT_Ra I_Cat(Ra)
 #define OT_CM I_Cat(CM)
@@ -80,9 +81,10 @@
 #define _OT_CS   OT_CS           /*   2 chars; CS */
 #define _OT_DC   OT_DOTTEDCIRCLE /*   1 chars; DOTTEDCIRCLE */
 #define _OT_H    OT_H            /*  11 chars; H */
-#define _OT_M    OT_M            /* 143 chars; M */
+#define _OT_M    OT_M            /* 142 chars; M */
 #define _OT_MH   OT_MH           /*   1 chars; MH */
 #define _OT_ML   OT_ML           /*   1 chars; ML */
+#define _OT_MP   OT_MPst         /*   1 chars; MPst */
 #define _OT_MR   OT_MR           /*   1 chars; MR */
 #define _OT_MW   OT_MW           /*   2 chars; MW */
 #define _OT_MY   OT_MY           /*   3 chars; MY */
@@ -200,7 +202,7 @@
   /* 0A28 */  _(C,C),  _(X,X),  _(C,C),  _(C,C),  _(C,C),  _(C,C),  _(C,C),  _(C,C),
   /* 0A30 */  _(R,C),  _(X,X),  _(C,C),  _(C,C),  _(X,X),  _(C,C),  _(C,C),  _(X,X),
   /* 0A38 */  _(C,C),  _(C,C),  _(X,X),  _(X,X),  _(N,X),  _(X,X), _(M,AP), _(M,LM),
-  /* 0A40 */ _(M,AP), _(M,AP), _(M,AP),  _(X,X),  _(X,X),  _(X,X),  _(X,X), _(M,AP),
+  /* 0A40 */_(MP,AP), _(M,AP), _(M,AP),  _(X,X),  _(X,X),  _(X,X),  _(X,X), _(M,AP),
   /* 0A48 */ _(M,AP),  _(X,X),  _(X,X), _(M,AP), _(M,AP),  _(H,B),  _(X,X),  _(X,X),
   /* 0A50 */  _(X,X),  _(M,B),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
   /* 0A58 */  _(X,X),  _(C,C),  _(C,C),  _(C,C),  _(C,C),  _(X,X),  _(C,C),  _(X,X),
@@ -451,15 +453,12 @@
   /* Grantha */
 
   /* 11300 */  _(X,X),_(SM,SM),_(SM,SM),_(SM,SM),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
-  /* 11308 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
-  /* 11310 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
-  /* 11318 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
-  /* 11320 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
-  /* 11328 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
-  /* 11330 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
+
+#define indic_offset_0x11338u 1720
+
   /* 11338 */  _(X,X),  _(X,X),  _(X,X),  _(N,X),  _(N,X),  _(X,X),  _(X,X),  _(X,X),
 
-}; /* Table items: 1776; occupancy: 69% */
+}; /* Table items: 1728; occupancy: 71% */
 
 uint16_t
 hb_indic_get_categories (hb_codepoint_t u)
@@ -497,7 +496,8 @@
       break;
 
     case 0x11u:
-      if (hb_in_range<hb_codepoint_t> (u, 0x11300u, 0x1133Fu)) return indic_table[u - 0x11300u + indic_offset_0x11300u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x11300u, 0x11307u)) return indic_table[u - 0x11300u + indic_offset_0x11300u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x11338u, 0x1133Fu)) return indic_table[u - 0x11338u + indic_offset_0x11338u];
       break;
 
     default:
@@ -519,6 +519,7 @@
 #undef _OT_M
 #undef _OT_MH
 #undef _OT_ML
+#undef _OT_MP
 #undef _OT_MR
 #undef _OT_MW
 #undef _OT_MY
diff --git a/src/hb-ot-shaper-indic.cc b/src/hb-ot-shaper-indic.cc
index 55509c1..7652210 100644
--- a/src/hb-ot-shaper-indic.cc
+++ b/src/hb-ot-shaper-indic.cc
@@ -223,15 +223,15 @@
   INDIC_BASIC_FEATURES = INDIC_INIT, /* Don't forget to update this! */
 };
 
-static void
+static bool
 setup_syllables_indic (const hb_ot_shape_plan_t *plan,
 		       hb_font_t *font,
 		       hb_buffer_t *buffer);
-static void
+static bool
 initial_reordering_indic (const hb_ot_shape_plan_t *plan,
 			  hb_font_t *font,
 			  hb_buffer_t *buffer);
-static void
+static bool
 final_reordering_indic (const hb_ot_shape_plan_t *plan,
 			hb_font_t *font,
 			hb_buffer_t *buffer);
@@ -413,7 +413,7 @@
     set_indic_properties (info[i]);
 }
 
-static void
+static bool
 setup_syllables_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
 		       hb_font_t *font HB_UNUSED,
 		       hb_buffer_t *buffer)
@@ -422,6 +422,7 @@
   find_syllables_indic (buffer);
   foreach_syllable (buffer, start, end)
     buffer->unsafe_to_break (start, end);
+  return false;
 }
 
 static int
@@ -714,6 +715,9 @@
 	    }
 	}
       } else if (info[i].indic_position() != POS_SMVD) {
+	if (info[i].indic_category() == I_Cat(MPst) &&
+	    i > start && info[i - 1].indic_category() == I_Cat(SM))
+	  info[i - 1].indic_position() = info[i].indic_position();
 	last_pos = (indic_position_t) info[i].indic_position();
       }
     }
@@ -729,7 +733,7 @@
 	  if (info[j].indic_position() < POS_SMVD)
 	    info[j].indic_position() = info[i].indic_position();
 	last = i;
-      } else if (info[i].indic_category() == I_Cat(M))
+      } else if (FLAG_UNSAFE (info[i].indic_category()) & (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst))))
 	last = i;
   }
 
@@ -742,14 +746,40 @@
 
     /* Sit tight, rock 'n roll! */
     hb_stable_sort (info + start, end - start, compare_indic_order);
-    /* Find base again */
+
+    /* Find base again; also flip left-matra sequence. */
+    unsigned first_left_matra = end;
+    unsigned last_left_matra = end;
     base = end;
     for (unsigned int i = start; i < end; i++)
+    {
       if (info[i].indic_position() == POS_BASE_C)
       {
 	base = i;
 	break;
       }
+      else if (info[i].indic_position() == POS_PRE_M)
+      {
+        if (first_left_matra == end)
+	  first_left_matra = i;
+	last_left_matra = i;
+      }
+    }
+    /* https://github.com/harfbuzz/harfbuzz/issues/3863 */
+    if (first_left_matra < last_left_matra)
+    {
+      /* No need to merge clusters, handled later. */
+      buffer->reverse_range (first_left_matra, last_left_matra + 1);
+      /* Reverse back nuktas, etc. */
+      unsigned i = first_left_matra;
+      for (unsigned j = i; j <= last_left_matra; j++)
+	if (FLAG_UNSAFE (info[j].indic_category()) & (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst))))
+	{
+	  buffer->reverse_range (i, j + 1);
+	  i = j + 1;
+	}
+    }
+
     /* Things are out-of-control for post base positions, they may shuffle
      * around like crazy.  In old-spec mode, we move halants around, so in
      * that case merge all clusters after base.  Otherwise, check the sort
@@ -955,25 +985,29 @@
   }
 }
 
-static void
+static bool
 initial_reordering_indic (const hb_ot_shape_plan_t *plan,
 			  hb_font_t *font,
 			  hb_buffer_t *buffer)
 {
+  bool ret = false;
   if (!buffer->message (font, "start reordering indic initial"))
-    return;
+    return ret;
 
   update_consonant_positions_indic (plan, font, buffer);
-  hb_syllabic_insert_dotted_circles (font, buffer,
-				     indic_broken_cluster,
-				     I_Cat(DOTTEDCIRCLE),
-				     I_Cat(Repha),
-				     POS_END);
+  if (hb_syllabic_insert_dotted_circles (font, buffer,
+					 indic_broken_cluster,
+					 I_Cat(DOTTEDCIRCLE),
+					 I_Cat(Repha),
+					 POS_END))
+    ret = true;
 
   foreach_syllable (buffer, start, end)
     initial_reordering_syllable_indic (plan, font->face, buffer, start, end);
 
   (void) buffer->message (font, "end reordering indic initial");
+
+  return ret;
 }
 
 static void
@@ -1116,7 +1150,7 @@
     {
     search:
       while (new_pos > start &&
-	     !(is_one_of (info[new_pos], (FLAG (I_Cat(M)) | FLAG (I_Cat(H))))))
+	     !(is_one_of (info[new_pos], (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst)) | FLAG (I_Cat(H))))))
 	new_pos--;
 
       /* If we found no Halant we are done.
@@ -1316,7 +1350,8 @@
 	  unlikely (is_halant (info[new_reph_pos])))
       {
 	for (unsigned int i = base + 1; i < new_reph_pos; i++)
-	  if (info[i].indic_category() == I_Cat(M)) {
+	  if (FLAG_UNSAFE (info[i].indic_category()) & (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst))))
+	  {
 	    /* Ok, got it. */
 	    new_reph_pos--;
 	  }
@@ -1376,7 +1411,7 @@
 	  if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL)
 	  {
 	    while (new_pos > start &&
-		   !(is_one_of (info[new_pos - 1], FLAG(I_Cat(M)) | FLAG (I_Cat(H)))))
+		   !(is_one_of (info[new_pos - 1], FLAG (I_Cat(M)) | FLAG (I_Cat(MPst)) | FLAG (I_Cat(H)))))
 	      new_pos--;
 	  }
 
@@ -1439,13 +1474,13 @@
 }
 
 
-static void
+static bool
 final_reordering_indic (const hb_ot_shape_plan_t *plan,
 			hb_font_t *font HB_UNUSED,
 			hb_buffer_t *buffer)
 {
   unsigned int count = buffer->len;
-  if (unlikely (!count)) return;
+  if (unlikely (!count)) return false;
 
   if (buffer->message (font, "start reordering indic final")) {
     foreach_syllable (buffer, start, end)
@@ -1455,6 +1490,8 @@
 
   HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
   HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);
+
+  return false;
 }
 
 
diff --git a/src/hb-ot-shaper-khmer-machine.hh b/src/hb-ot-shaper-khmer-machine.hh
index e18bd75..fd91ee0 100644
--- a/src/hb-ot-shaper-khmer-machine.hh
+++ b/src/hb-ot-shaper-khmer-machine.hh
@@ -48,7 +48,7 @@
 };
 
 
-#line 52 "hb-ot-shaper-khmer-machine.hh"
+#line 49 "hb-ot-shaper-khmer-machine.hh"
 #define khmer_syllable_machine_ex_C 1u
 #define khmer_syllable_machine_ex_DOTTEDCIRCLE 11u
 #define khmer_syllable_machine_ex_H 4u
@@ -66,7 +66,7 @@
 #define khmer_syllable_machine_ex_ZWNJ 5u
 
 
-#line 70 "hb-ot-shaper-khmer-machine.hh"
+#line 65 "hb-ot-shaper-khmer-machine.hh"
 static const unsigned char _khmer_syllable_machine_trans_keys[] = {
 	5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 
 	5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u, 
@@ -284,7 +284,7 @@
     for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     syllable_serial++; \
-    if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+    if (syllable_serial == 16) syllable_serial = 1; \
   } HB_STMT_END
 
 inline void
@@ -294,7 +294,7 @@
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 298 "hb-ot-shaper-khmer-machine.hh"
+#line 287 "hb-ot-shaper-khmer-machine.hh"
 	{
 	cs = khmer_syllable_machine_start;
 	ts = 0;
@@ -310,7 +310,7 @@
 
   unsigned int syllable_serial = 1;
   
-#line 314 "hb-ot-shaper-khmer-machine.hh"
+#line 299 "hb-ot-shaper-khmer-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -324,7 +324,7 @@
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 328 "hb-ot-shaper-khmer-machine.hh"
+#line 311 "hb-ot-shaper-khmer-machine.hh"
 	}
 
 	_keys = _khmer_syllable_machine_trans_keys + (cs<<1);
@@ -394,7 +394,7 @@
 #line 98 "hb-ot-shaper-khmer-machine.rl"
 	{act = 3;}
 	break;
-#line 398 "hb-ot-shaper-khmer-machine.hh"
+#line 368 "hb-ot-shaper-khmer-machine.hh"
 	}
 
 _again:
@@ -403,7 +403,7 @@
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 407 "hb-ot-shaper-khmer-machine.hh"
+#line 375 "hb-ot-shaper-khmer-machine.hh"
 	}
 
 	if ( ++p != pe )
diff --git a/src/hb-ot-shaper-khmer-machine.rl b/src/hb-ot-shaper-khmer-machine.rl
index f180471..d5d429d 100644
--- a/src/hb-ot-shaper-khmer-machine.rl
+++ b/src/hb-ot-shaper-khmer-machine.rl
@@ -107,7 +107,7 @@
     for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     syllable_serial++; \
-    if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+    if (syllable_serial == 16) syllable_serial = 1; \
   } HB_STMT_END
 
 inline void
diff --git a/src/hb-ot-shaper-khmer.cc b/src/hb-ot-shaper-khmer.cc
index d979558..019a285 100644
--- a/src/hb-ot-shaper-khmer.cc
+++ b/src/hb-ot-shaper-khmer.cc
@@ -89,11 +89,11 @@
   info.khmer_category() = (khmer_category_t) (type & 0xFFu);
 }
 
-static void
+static bool
 setup_syllables_khmer (const hb_ot_shape_plan_t *plan,
 		       hb_font_t *font,
 		       hb_buffer_t *buffer);
-static void
+static bool
 reorder_khmer (const hb_ot_shape_plan_t *plan,
 	       hb_font_t *font,
 	       hb_buffer_t *buffer);
@@ -192,7 +192,7 @@
     set_khmer_properties (info[i]);
 }
 
-static void
+static bool
 setup_syllables_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
 		       hb_font_t *font HB_UNUSED,
 		       hb_buffer_t *buffer)
@@ -201,6 +201,7 @@
   find_syllables_khmer (buffer);
   foreach_syllable (buffer, start, end)
     buffer->unsafe_to_break (start, end);
+  return false;
 }
 
 
@@ -303,23 +304,27 @@
   }
 }
 
-static void
+static bool
 reorder_khmer (const hb_ot_shape_plan_t *plan,
 	       hb_font_t *font,
 	       hb_buffer_t *buffer)
 {
+  bool ret = false;
   if (buffer->message (font, "start reordering khmer"))
   {
-    hb_syllabic_insert_dotted_circles (font, buffer,
-				       khmer_broken_cluster,
-				       K_Cat(DOTTEDCIRCLE),
-				       (unsigned) -1);
+    if (hb_syllabic_insert_dotted_circles (font, buffer,
+					   khmer_broken_cluster,
+					   K_Cat(DOTTEDCIRCLE),
+					   (unsigned) -1))
+      ret = true;
 
     foreach_syllable (buffer, start, end)
       reorder_syllable_khmer (plan, font->face, buffer, start, end);
     (void) buffer->message (font, "end reordering khmer");
   }
   HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category);
+
+  return ret;
 }
 
 
diff --git a/src/hb-ot-shaper-myanmar-machine.hh b/src/hb-ot-shaper-myanmar-machine.hh
index b109708..87cded4 100644
--- a/src/hb-ot-shaper-myanmar-machine.hh
+++ b/src/hb-ot-shaper-myanmar-machine.hh
@@ -50,7 +50,7 @@
 };
 
 
-#line 54 "hb-ot-shaper-myanmar-machine.hh"
+#line 51 "hb-ot-shaper-myanmar-machine.hh"
 #define myanmar_syllable_machine_ex_A 9u
 #define myanmar_syllable_machine_ex_As 32u
 #define myanmar_syllable_machine_ex_C 1u
@@ -77,7 +77,7 @@
 #define myanmar_syllable_machine_ex_ZWNJ 5u
 
 
-#line 81 "hb-ot-shaper-myanmar-machine.hh"
+#line 76 "hb-ot-shaper-myanmar-machine.hh"
 static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
 	1u, 41u, 3u, 41u, 5u, 39u, 5u, 8u, 3u, 41u, 3u, 39u, 3u, 39u, 5u, 39u, 
 	5u, 39u, 3u, 39u, 3u, 39u, 3u, 41u, 5u, 39u, 1u, 15u, 3u, 39u, 3u, 39u, 
@@ -433,7 +433,7 @@
     for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     syllable_serial++; \
-    if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+    if (syllable_serial == 16) syllable_serial = 1; \
   } HB_STMT_END
 
 inline void
@@ -443,7 +443,7 @@
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 447 "hb-ot-shaper-myanmar-machine.hh"
+#line 436 "hb-ot-shaper-myanmar-machine.hh"
 	{
 	cs = myanmar_syllable_machine_start;
 	ts = 0;
@@ -459,7 +459,7 @@
 
   unsigned int syllable_serial = 1;
   
-#line 463 "hb-ot-shaper-myanmar-machine.hh"
+#line 448 "hb-ot-shaper-myanmar-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -473,7 +473,7 @@
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 477 "hb-ot-shaper-myanmar-machine.hh"
+#line 460 "hb-ot-shaper-myanmar-machine.hh"
 	}
 
 	_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@@ -519,7 +519,7 @@
 #line 113 "hb-ot-shaper-myanmar-machine.rl"
 	{te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
 	break;
-#line 523 "hb-ot-shaper-myanmar-machine.hh"
+#line 498 "hb-ot-shaper-myanmar-machine.hh"
 	}
 
 _again:
@@ -528,7 +528,7 @@
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 532 "hb-ot-shaper-myanmar-machine.hh"
+#line 505 "hb-ot-shaper-myanmar-machine.hh"
 	}
 
 	if ( ++p != pe )
diff --git a/src/hb-ot-shaper-myanmar-machine.rl b/src/hb-ot-shaper-myanmar-machine.rl
index 2cb6e4e..db6a44c 100644
--- a/src/hb-ot-shaper-myanmar-machine.rl
+++ b/src/hb-ot-shaper-myanmar-machine.rl
@@ -122,7 +122,7 @@
     for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     syllable_serial++; \
-    if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+    if (syllable_serial == 16) syllable_serial = 1; \
   } HB_STMT_END
 
 inline void
diff --git a/src/hb-ot-shaper-myanmar.cc b/src/hb-ot-shaper-myanmar.cc
index 78bd8de..1b2a085 100644
--- a/src/hb-ot-shaper-myanmar.cc
+++ b/src/hb-ot-shaper-myanmar.cc
@@ -98,11 +98,11 @@
 }
 
 
-static void
+static bool
 setup_syllables_myanmar (const hb_ot_shape_plan_t *plan,
 			 hb_font_t *font,
 			 hb_buffer_t *buffer);
-static void
+static bool
 reorder_myanmar (const hb_ot_shape_plan_t *plan,
 		 hb_font_t *font,
 		 hb_buffer_t *buffer);
@@ -150,7 +150,7 @@
     set_myanmar_properties (info[i]);
 }
 
-static void
+static bool
 setup_syllables_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
 			 hb_font_t *font HB_UNUSED,
 			 hb_buffer_t *buffer)
@@ -159,6 +159,7 @@
   find_syllables_myanmar (buffer);
   foreach_syllable (buffer, start, end)
     buffer->unsafe_to_break (start, end);
+  return false;
 }
 
 static int
@@ -270,6 +271,33 @@
 
   /* Sit tight, rock 'n roll! */
   buffer->sort (start, end, compare_myanmar_order);
+
+  /* Flip left-matra sequence. */
+  unsigned first_left_matra = end;
+  unsigned last_left_matra = end;
+  for (unsigned int i = start; i < end; i++)
+  {
+    if (info[i].myanmar_position() == POS_PRE_M)
+    {
+      if (first_left_matra == end)
+	first_left_matra = i;
+      last_left_matra = i;
+    }
+  }
+  /* https://github.com/harfbuzz/harfbuzz/issues/3863 */
+  if (first_left_matra < last_left_matra)
+  {
+    /* No need to merge clusters, done already? */
+    buffer->reverse_range (first_left_matra, last_left_matra + 1);
+    /* Reverse back VS, etc. */
+    unsigned i = first_left_matra;
+    for (unsigned j = i; j <= last_left_matra; j++)
+      if (info[j].myanmar_category() == M_Cat(VPre))
+      {
+	buffer->reverse_range (i, j + 1);
+	i = j + 1;
+      }
+  }
 }
 
 static void
@@ -291,16 +319,18 @@
   }
 }
 
-static void
+static bool
 reorder_myanmar (const hb_ot_shape_plan_t *plan,
 		 hb_font_t *font,
 		 hb_buffer_t *buffer)
 {
+  bool ret = false;
   if (buffer->message (font, "start reordering myanmar"))
   {
-    hb_syllabic_insert_dotted_circles (font, buffer,
-				       myanmar_broken_cluster,
-				       M_Cat(DOTTEDCIRCLE));
+    if (hb_syllabic_insert_dotted_circles (font, buffer,
+					   myanmar_broken_cluster,
+					   M_Cat(DOTTEDCIRCLE)))
+      ret = true;
 
     foreach_syllable (buffer, start, end)
       reorder_syllable_myanmar (plan, font->face, buffer, start, end);
@@ -309,6 +339,8 @@
 
   HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category);
   HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position);
+
+  return ret;
 }
 
 
@@ -331,6 +363,7 @@
 };
 
 
+#ifndef HB_NO_OT_SHAPER_MYANMAR_ZAWGYI
 /* Ugly Zawgyi encoding.
  * Disable all auto processing.
  * https://github.com/harfbuzz/harfbuzz/issues/1162 */
@@ -351,6 +384,7 @@
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
 };
+#endif
 
 
 #endif
diff --git a/src/hb-ot-shaper-syllabic.cc b/src/hb-ot-shaper-syllabic.cc
index a8e0d8e..89226ae 100644
--- a/src/hb-ot-shaper-syllabic.cc
+++ b/src/hb-ot-shaper-syllabic.cc
@@ -29,7 +29,7 @@
 #include "hb-ot-shaper-syllabic.hh"
 
 
-void
+bool
 hb_syllabic_insert_dotted_circles (hb_font_t *font,
 				   hb_buffer_t *buffer,
 				   unsigned int broken_syllable_type,
@@ -38,13 +38,13 @@
 				   int dottedcircle_position)
 {
   if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
-    return;
+    return false;
   if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE)))
-    return;
+    return false;
 
   hb_codepoint_t dottedcircle_glyph;
   if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
-    return;
+    return false;
 
   hb_glyph_info_t dottedcircle = {0};
   dottedcircle.codepoint = 0x25CCu;
@@ -84,14 +84,16 @@
       (void) buffer->next_glyph ();
   }
   buffer->sync ();
+  return true;
 }
 
-HB_INTERNAL void
+HB_INTERNAL bool
 hb_syllabic_clear_var (const hb_ot_shape_plan_t *plan,
 		       hb_font_t *font,
 		       hb_buffer_t *buffer)
 {
   HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
+  return false;
 }
 
 
diff --git a/src/hb-ot-shaper-syllabic.hh b/src/hb-ot-shaper-syllabic.hh
index e8a15bb..f240ad1 100644
--- a/src/hb-ot-shaper-syllabic.hh
+++ b/src/hb-ot-shaper-syllabic.hh
@@ -30,7 +30,7 @@
 #include "hb-ot-shaper.hh"
 
 
-HB_INTERNAL void
+HB_INTERNAL bool
 hb_syllabic_insert_dotted_circles (hb_font_t *font,
 				   hb_buffer_t *buffer,
 				   unsigned int broken_syllable_type,
@@ -38,7 +38,7 @@
 				   int repha_category = -1,
 				   int dottedcircle_position = -1);
 
-HB_INTERNAL void
+HB_INTERNAL bool
 hb_syllabic_clear_var (const hb_ot_shape_plan_t *plan,
 		       hb_font_t *font,
 		       hb_buffer_t *buffer);
diff --git a/src/hb-ot-shaper-thai.cc b/src/hb-ot-shaper-thai.cc
index 15349b1..6cd67cd 100644
--- a/src/hb-ot-shaper-thai.cc
+++ b/src/hb-ot-shaper-thai.cc
@@ -98,9 +98,9 @@
 thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font)
 {
   struct thai_pua_mapping_t {
-    hb_codepoint_t u;
-    hb_codepoint_t win_pua;
-    hb_codepoint_t mac_pua;
+    uint16_t u;
+    uint16_t win_pua;
+    uint16_t mac_pua;
   } const *pua_mappings = nullptr;
   static const thai_pua_mapping_t SD_mappings[] = {
     {0x0E48u, 0xF70Au, 0xF88Bu}, /* MAI EK */
diff --git a/src/hb-ot-shaper-use-machine.hh b/src/hb-ot-shaper-use-machine.hh
index 41e8a34..f2fbdb7 100644
--- a/src/hb-ot-shaper-use-machine.hh
+++ b/src/hb-ot-shaper-use-machine.hh
@@ -53,7 +53,7 @@
 };
 
 
-#line 57 "hb-ot-shaper-use-machine.hh"
+#line 54 "hb-ot-shaper-use-machine.hh"
 #define use_syllable_machine_ex_B 1u
 #define use_syllable_machine_ex_CGJ 6u
 #define use_syllable_machine_ex_CMAbv 31u
@@ -97,7 +97,7 @@
 #define use_syllable_machine_ex_ZWNJ 14u
 
 
-#line 101 "hb-ot-shaper-use-machine.hh"
+#line 96 "hb-ot-shaper-use-machine.hh"
 static const unsigned char _use_syllable_machine_trans_keys[] = {
 	0u, 53u, 11u, 53u, 11u, 53u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u, 
 	14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u, 
@@ -839,7 +839,7 @@
     for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     syllable_serial++; \
-    if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+    if (syllable_serial == 16) syllable_serial = 1; \
   } HB_STMT_END
 
 
@@ -929,7 +929,7 @@
   unsigned int act HB_UNUSED;
   int cs;
   
-#line 933 "hb-ot-shaper-use-machine.hh"
+#line 922 "hb-ot-shaper-use-machine.hh"
 	{
 	cs = use_syllable_machine_start;
 	ts = 0;
@@ -942,7 +942,7 @@
 
   unsigned int syllable_serial = 1;
   
-#line 946 "hb-ot-shaper-use-machine.hh"
+#line 931 "hb-ot-shaper-use-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -956,7 +956,7 @@
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 960 "hb-ot-shaper-use-machine.hh"
+#line 943 "hb-ot-shaper-use-machine.hh"
 	}
 
 	_keys = _use_syllable_machine_trans_keys + (cs<<1);
@@ -1046,7 +1046,7 @@
 #line 178 "hb-ot-shaper-use-machine.rl"
 	{te = p;p--;{ found_syllable (use_non_cluster); }}
 	break;
-#line 1050 "hb-ot-shaper-use-machine.hh"
+#line 1014 "hb-ot-shaper-use-machine.hh"
 	}
 
 _again:
@@ -1055,7 +1055,7 @@
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 1059 "hb-ot-shaper-use-machine.hh"
+#line 1021 "hb-ot-shaper-use-machine.hh"
 	}
 
 	if ( ++p != pe )
diff --git a/src/hb-ot-shaper-use-machine.rl b/src/hb-ot-shaper-use-machine.rl
index 9f22057..8ace1f0 100644
--- a/src/hb-ot-shaper-use-machine.rl
+++ b/src/hb-ot-shaper-use-machine.rl
@@ -187,7 +187,7 @@
     for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     syllable_serial++; \
-    if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+    if (syllable_serial == 16) syllable_serial = 1; \
   } HB_STMT_END
 
 
diff --git a/src/hb-ot-shaper-use-table.hh b/src/hb-ot-shaper-use-table.hh
index 9833fb5..6b6b552 100644
--- a/src/hb-ot-shaper-use-table.hh
+++ b/src/hb-ot-shaper-use-table.hh
@@ -91,6 +91,9 @@
 #define VMPre	USE(VMPre)
 #pragma GCC diagnostic pop
 
+
+#ifndef HB_OPTIMIZE_SIZE
+
 static const uint8_t
 hb_use_u8[3141] =
 {
@@ -357,6 +360,273 @@
   return u<921600u?hb_use_u8[2777+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
 }
 
+
+#else
+
+static const uint8_t
+hb_use_u8[3413] =
+{
+     16,   50,   51,   51,   51,   52,   51,   83,  118,  131,   51,   57,   58,  179,  195,   61,
+     51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+     51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+     51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+     51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+     51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+     51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+     14,    0,    1,    1,    2,    1,    1,    3,    4,    5,    6,    7,    8,    9,   10,    1,
+     11,   12,    1,    1,    1,    1,    1,    1,   13,   14,   15,   16,   17,   18,   19,    1,
+      1,   20,    1,    1,    1,    1,   21,    1,    1,    1,    1,    1,    1,    1,   22,    1,
+      1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+      1,    1,    1,    1,    1,    1,    1,    1,    1,   23,   24,   25,   26,    1,    1,    1,
+      1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   27,
+     28,    1,    1,    1,    1,    1,   29,    1,    1,    1,    1,   30,   31,    1,   32,   33,
+     34,   35,   36,   37,   38,   39,   40,   41,   42,   43,   44,   45,    1,   46,   47,   48,
+     49,   50,   50,   50,   50,   51,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+      1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   52,   53,    1,    1,    1,
+     54,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   50,   55,    1,    1,
+      1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   56,    1,    1,
+      1,    1,   57,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+      1,    1,   58,   59,    1,   60,    1,    1,    1,    1,   61,    1,    1,    1,    1,    1,
+      1,   62,   63,   62,   62,   62,   62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+     62,    0,    1,    0,    0,    0,    2,    3,    0,    0,    0,    0,    0,    0,    0,    0,
+      0,    0,    0,    4,    0,    0,    0,    0,    0,    0,    0,    5,    0,    0,    0,    0,
+      0,    0,    0,    0,    0,    0,    0,    6,    7,    0,    0,    8,    0,    0,    0,    0,
+      0,    9,   10,   11,   12,   13,   14,   15,   16,   17,   18,   19,   20,   21,   22,   23,
+     24,   25,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35,   36,   37,   38,   39,
+     40,   41,   42,   43,   36,   44,   45,   46,   47,   48,   49,   50,   51,   52,   53,   54,
+      0,   55,   56,   57,   58,   59,    0,    0,    0,   60,   61,   62,   63,   55,   64,   65,
+     66,   67,   55,   55,   68,   69,   70,    0,    0,   71,   72,   73,   74,   55,   75,   76,
+      0,   77,   55,   78,   79,   80,    0,    0,    0,   81,   82,   83,   84,   85,   86,   55,
+     87,   55,   88,   89,    0,    0,    0,   90,   91,    0,    0,    0,    0,    0,    0,    0,
+     92,   93,   94,    0,   95,   96,    0,    0,   97,    0,    0,    0,    0,    0,    0,   98,
+      0,    0,   99,   55,  100,    0,    0,    0,    0,  101,  102,   55,  103,  104,  105,  106,
+    107,   55,  108,  109,    0,  110,  111,  112,  113,   55,  114,  115,  116,   55,  117,  118,
+    119,    0,    0,    0,    0,    0,    0,   55,  120,  121,    0,    0,    0,    0,    0,    0,
+    122,    0,    0,    0,    0,    0,    0,    0,  123,    0,    0,    0,  124,  125,  126,    0,
+      0,  127,  128,  129,    0,    0,    0,   50,  130,    0,    0,    0,    0,  131,  132,    0,
+      0,   55,  133,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   55,  134,    0,
+      0,    0,   99,  135,   99,  136,  137,  138,    0,  139,  140,  141,  142,  143,  144,  145,
+      0,  146,  147,  148,  149,  143,  150,  151,  152,  153,  154,  155,    0,  156,  157,  158,
+    159,  160,  161,  162,  163,    0,    0,    0,    0,   55,  164,  165,  166,  167,  168,  169,
+      0,    0,    0,    0,    0,   55,  170,  171,    0,   55,  172,  173,    0,   55,  174,   66,
+      0,  175,  176,  177,    0,    0,    0,    0,    0,   55,  178,    0,    0,    0,    0,    0,
+      0,  179,  180,  181,    0,    0,  182,  183,  184,  185,  186,  187,   55,  188,    0,    0,
+      0,  189,  190,  191,  192,  193,  194,    0,    0,  195,  196,  197,  198,  199,   66,    0,
+      0,    0,    0,    0,    0,    0,    0,    0,  200,  201,  202,  203,    0,    0,    0,    0,
+      0,   55,   55,   55,   55,   55,   55,   55,   55,   55,  204,  205,    0,    0,    0,    0,
+      0,    0,    0,    0,    0,    0,    0,   66,    0,   55,  206,    0,    0,    0,    0,    0,
+      0,   55,   55,  207,  208,  209,    0,    0,  210,   55,   55,   55,   55,   55,   55,  211,
+      0,   55,   55,   55,  212,  213,    0,    0,    0,    0,    0,    0,  214,    0,    0,    0,
+      0,   55,  215,  216,    0,    0,    0,    0,    0,    0,    0,    0,    0,   99,  217,   55,
+    218,    0,    0,    0,    0,    0,    0,   99,  219,   55,   55,  220,    0,    0,    0,    0,
+      0,  221,  221,  221,  221,  221,  221,  221,  221,  222,  222,  222,  222,  222,  222,  222,
+    223,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,
+      0,    2,    2,    2,    2,    2,    0,    0,    0,    3,    0,    0,    0,    0,    0,    4,
+      0,    0,    5,    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,    0,    0,    0,
+      0,    0,    0,    0,    0,    0,    0,    0,    6,    7,    0,    0,    0,    0,    0,    0,
+      0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+      2,    2,    2,    2,    2,    2,    8,    9,    9,    9,    9,    0,    0,    0,    7,   10,
+      0,    2,    2,    2,    2,   11,   12,    0,    0,    9,   13,    2,    2,    2,    2,    2,
+      2,    2,    2,    2,    2,    2,   14,   15,   16,   17,   18,   19,   20,   14,   21,   22,
+     23,   10,   24,   25,   18,    2,    2,    2,    2,    2,   18,    0,    2,    2,    2,    2,
+      2,    0,    2,    2,    2,    2,    2,    2,    2,   26,   27,   28,    2,    2,    2,    7,
+     28,    7,   28,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    7,    2,    2,
+      2,    7,    7,    0,    2,    2,    0,   15,   16,   17,   18,   29,   30,   31,   30,   32,
+      0,    0,    0,    0,   33,    0,    0,    2,   28,    2,    0,    0,    0,    0,    0,    7,
+     34,   10,   13,   28,    2,    2,    7,    0,   28,    7,    2,   28,    7,    2,    0,   35,
+     16,   17,   29,    0,   25,   36,   25,   37,    0,   38,    0,    0,    0,   28,    2,    7,
+      7,    0,    0,    0,    2,    2,    2,    2,    2,   39,   40,   41,    0,    0,    0,    0,
+      0,   10,   13,   28,    2,    2,    2,    2,   28,    2,   28,    2,    2,    2,    2,    2,
+      2,    7,    2,   28,    2,    2,    0,   15,   16,   17,   18,   19,   25,   20,   33,   22,
+      0,    0,    0,    0,    0,   28,   39,   39,   42,   10,   27,   28,    2,    2,    2,    7,
+     28,    7,    2,   28,    2,    2,    0,   15,   43,    0,    0,   25,   20,    0,    0,    2,
+     28,   28,    0,    0,    0,    0,    0,    0,    0,    0,   44,   28,    2,    2,    7,    0,
+      2,    7,    2,    2,    0,   28,    7,    7,    2,    0,   28,    7,    0,    2,    7,    0,
+      2,    2,    2,    2,    2,    2,    0,    0,   21,   14,   45,    0,   46,   31,   46,   32,
+      0,    0,    0,    0,   33,    0,    0,    0,    0,   13,   27,   47,    2,    2,    2,    7,
+      2,    7,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    0,   15,
+     20,   14,   21,   45,   20,   36,   20,   37,    0,    0,    0,   25,   29,    2,    7,    0,
+      0,    8,   27,   28,    2,    2,    2,    7,    2,    2,    2,   28,    2,    2,    0,   15,
+     43,    0,    0,   33,   45,    0,    0,    0,    7,   48,   49,    0,    0,    0,    0,    0,
+      0,    9,   27,    2,    2,    2,    2,    7,    2,    2,    2,    2,    2,    2,   50,   51,
+     21,   21,   17,   29,   46,   31,   46,   32,   52,    0,    0,    0,   33,    0,    0,    0,
+     28,   10,   27,   28,    2,    2,    2,    2,    2,    2,    2,    2,    7,    0,    2,    2,
+      2,    2,   28,    2,    2,    2,    2,   28,    0,    2,    2,    2,    7,    0,   53,    0,
+     33,   21,   20,   29,   29,   16,   46,   46,   23,    0,   21,    0,    0,    0,    0,    0,
+      0,    2,    0,    2,    7,    0,    0,    0,    0,    0,    0,    0,    0,   18,    0,    0,
+      0,    2,    2,   54,   54,   55,    0,    0,   16,    2,    2,    2,    2,   28,    2,    2,
+      2,    2,    2,    2,    2,    2,    2,    7,    0,   56,   19,   57,   20,   20,   18,   18,
+     44,   19,    9,   29,    9,    2,    2,   58,   59,   59,   59,   59,   59,   60,   59,   59,
+     59,   59,   59,   59,   59,   59,   59,   59,   59,   59,   59,   59,   59,   59,   59,   61,
+      0,    0,    0,    0,   62,    0,    0,    0,    0,    2,    2,    2,    2,    2,   63,   43,
+     57,   64,   20,   20,   65,   66,   67,   68,   69,    2,    2,    2,    2,    2,    1,    0,
+      3,    2,    2,    2,   21,   18,    2,    2,   70,   69,   71,   72,   63,   71,   27,   27,
+      2,   50,   20,   51,    2,    2,    2,    2,    2,    2,   73,   74,   75,   27,   27,   76,
+     77,    2,    2,    2,    2,    2,   27,   43,    0,    2,   57,   78,    0,    0,    0,    0,
+     28,    2,   57,   45,    0,    0,    0,    0,    0,    2,   57,    0,    0,    0,    0,    0,
+      0,    2,    2,    2,    2,    2,    2,    7,    2,    7,   57,    0,    0,    0,    0,    0,
+      0,    2,    2,   79,   43,   20,   57,   18,   46,   46,   46,   46,   13,   80,   81,   82,
+     83,   84,   85,    0,    0,    0,    0,   86,    0,    7,    0,    0,   28,    0,   87,   79,
+     88,    2,    2,    2,    2,    7,    0,    0,    0,   40,   40,   89,   90,    2,    2,    2,
+      2,    2,    2,    2,    2,   11,    7,    0,    0,   91,    2,    2,    2,    2,    2,    2,
+      2,    2,    2,    2,    2,    2,    2,    2,    7,   20,   78,   43,   20,   92,   59,    0,
+      0,   93,   94,   93,   93,   95,   96,    0,    0,    2,    2,    2,    2,    2,    2,    2,
+      0,    2,    2,    7,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    2,    0,
+      0,    2,    2,    2,    2,   27,    0,    0,    0,    2,    2,    2,    2,    2,    7,    0,
+      0,    2,    2,    2,   50,   97,   43,    0,    0,    2,    2,   98,   99,  100,  101,   59,
+     61,  102,   14,   43,   20,   57,   19,   78,   46,   46,   74,    9,    9,    9,  103,   44,
+     38,    9,  104,   72,    2,    2,    2,    2,    2,    2,    2,  105,   20,   18,   18,   20,
+     46,   46,   20,  106,    2,    2,    2,    7,    0,    0,    0,    0,    0,    0,  107,  108,
+    109,  109,  109,    0,    0,    0,    0,    0,    0,  104,   72,    2,    2,    2,    2,    2,
+      2,   58,   59,   57,   23,   20,  110,   59,    2,    2,    2,    2,  105,   20,   21,   43,
+     43,  100,   12,    0,    0,    0,    0,    0,    0,    2,    2,   59,   16,   46,   21,  111,
+    100,  100,  100,  112,  113,    0,    0,    0,    0,    2,    2,    2,    2,    2,    0,   28,
+      2,    9,   44,  114,  114,  114,    9,  114,  114,   13,  114,  114,  114,   24,    0,   38,
+      0,    0,    0,  115,   49,    9,    3,    0,    0,    0,    0,    0,    0,    0,  116,    0,
+      0,    0,    0,    0,    0,    0,    4,  117,  118,   40,   40,    3,    0,    0,    0,    0,
+      0,    0,    0,    0,    0,    0,  118,  118,  119,  118,  118,  118,  118,  118,  118,  118,
+    118,    0,    0,  120,    0,    0,    0,    0,    0,    0,    5,  120,    0,    0,    0,    0,
+      0,   44,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    7,
+      0,    2,    2,    2,    2,    0,    0,    0,   28,    0,    0,    0,    0,    0,    0,    0,
+    121,    2,   51,    2,  106,    2,    8,    2,    2,    2,   63,   17,   14,    0,    0,   29,
+      0,    2,    2,    0,    0,    0,    0,    0,    0,   27,    2,    2,    2,    2,    2,    2,
+      2,    2,    2,  122,   21,   21,   21,   21,   21,   21,   21,  123,    0,    0,    0,    0,
+      0,    9,    9,    9,    9,    9,    9,    9,    9,    9,    2,    0,    0,    0,    0,    0,
+     50,    2,    2,    2,   20,   20,  124,  114,    0,    2,    2,    2,  125,   18,   57,   18,
+    111,  100,  126,    0,    0,    0,    0,    0,    0,    9,  127,    2,    2,    2,    2,    2,
+      2,    2,  128,   21,   20,   18,   46,  129,  130,  131,    0,    0,    0,    0,    0,    0,
+      0,    2,    2,   50,   28,    2,    2,    2,    2,    2,    2,    2,    2,    8,   20,   57,
+     97,   74,  132,  133,  134,    0,    0,    0,    0,    2,  135,    2,    2,    2,    2,  136,
+      0,   28,    2,   40,    3,    0,   77,   13,    2,   51,   20,  137,   50,   51,    2,    2,
+    103,    8,    7,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,  138,   19,
+     23,    0,    0,  139,  140,    0,    0,    0,    0,    2,   63,   43,   21,   78,   45,  141,
+      0,   79,   79,   79,   79,   79,   79,   79,   79,    0,    0,    0,    0,    0,    0,    0,
+      4,  118,  118,  118,  118,  119,    0,    0,    0,    2,    2,    2,    2,    2,    7,    2,
+      2,    2,    7,    2,   28,    2,    2,    2,    2,    2,   28,    2,    2,    2,   28,    7,
+      0,  125,   18,   25,   29,    0,    0,  142,  143,    2,    2,   28,    2,   28,    2,    2,
+      2,    2,    2,    2,    0,   12,   35,    0,  144,    2,    2,   11,   35,    0,   28,    2,
+      2,    2,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   28,    2,    2,
+      7,    2,    2,    9,   39,    0,    0,    0,    0,    2,    2,    2,    2,    2,   25,   36,
+      0,    2,    2,    2,  114,  114,  114,  114,  114,  145,    2,    7,    0,    0,    0,    0,
+      0,    2,   12,   12,    0,    0,    0,    0,    0,    7,    2,    2,    7,    2,    2,    2,
+      2,   28,    2,    7,    0,   28,    2,    0,    0,  146,  147,  148,    2,    2,    2,    2,
+      2,    2,    2,    2,    2,   20,   20,   18,   18,   18,   20,   20,  131,    0,    0,    0,
+      0,    0,  149,  149,  149,  149,  149,  149,  149,  149,  149,  149,    2,    2,    2,    2,
+      2,   51,   50,   51,    0,    0,    0,    0,  150,    9,   72,    2,    2,    2,    2,    2,
+      2,   16,   17,   19,   14,   22,   35,    0,    0,    0,   29,    0,    0,    0,    0,    0,
+      0,    9,   47,    2,    2,    2,    2,    2,    2,    2,    2,    2,  125,   18,   20,  151,
+     20,   19,  152,  153,    2,    2,    2,    2,    2,    0,    0,   63,  154,    0,    0,    0,
+      0,    2,   11,    0,    0,    0,    0,    0,    0,    2,   63,   23,   18,   18,   18,   20,
+     20,  106,  155,    0,    0,   54,  156,   29,  157,   28,    2,    2,    2,    2,    2,    2,
+      2,    2,    2,    2,    2,    2,    2,   21,   17,   20,   20,  158,   42,    0,    0,    0,
+     47,  125,    0,    0,    0,    0,    0,    0,    0,    2,    2,    2,    7,    7,    2,    2,
+     28,    2,    2,    2,    2,    2,    2,    2,   28,    2,    2,    2,    2,    2,    2,    2,
+      8,   16,   17,   19,   20,  159,   29,    0,    0,    9,    9,   28,    2,    2,    2,    7,
+     28,    7,    2,   28,    2,    2,   56,   15,   21,   14,   21,   45,   30,   31,   30,   32,
+      0,    0,    0,    0,   33,    0,    0,    0,    2,    2,   21,    0,    9,    9,    9,   44,
+      0,    9,    9,   44,    0,    0,    0,    0,    0,    2,    2,   63,   23,   18,   18,   18,
+     20,   21,  123,   13,   15,    0,    0,    0,    0,    2,    2,    2,    2,    2,    0,    0,
+    160,  161,    0,    0,    0,    0,    0,    0,    0,   16,   17,   18,   18,   64,   97,   23,
+    157,    9,  162,    7,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    2,    2,
+     63,   23,   18,   18,    0,   46,   46,    9,  163,   35,    0,    0,    0,    0,    0,    0,
+      0,    0,    0,    0,    0,    2,    2,   18,    0,   21,   17,   18,   18,   19,   14,   80,
+    163,   36,    0,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    8,  164,
+     23,   18,   20,   20,  162,    7,    0,    0,    0,    2,    2,    2,    2,    2,    7,   41,
+    133,   21,   20,   18,   74,   19,   20,    0,    0,    2,    2,    2,    7,    0,    0,    0,
+      0,    2,    2,    2,    2,    2,    2,   16,   17,   18,   19,   20,  103,  163,   35,    0,
+      0,    2,    2,    2,    7,   28,    0,    2,    2,    2,    2,   28,    7,    2,    2,    2,
+      2,   21,   21,   16,   30,   31,   10,  165,  166,  167,  168,    0,    0,    0,    0,    0,
+      0,    2,    2,    2,    2,    0,    2,    2,    2,   63,   23,   18,   18,    0,   20,   21,
+     27,  106,    0,   31,    0,    0,    0,    0,    0,   50,   18,   20,   20,   20,  137,    2,
+      2,    2,  169,  170,    9,   13,  171,   70,  172,    0,    0,    1,  144,    0,    0,    0,
+      0,   50,   18,   20,   14,   17,   18,    2,    2,    2,    2,  155,  155,  155,  173,  173,
+    173,  173,  173,  173,   13,  174,    0,   28,    0,   20,   18,   18,   29,   20,   20,    9,
+    163,    0,   59,   59,   59,   59,   59,   59,   59,   64,   19,   80,   44,    0,    0,    0,
+      0,    2,    2,    2,    7,    2,   28,    2,    2,   50,   20,   20,   29,    0,   36,   20,
+     25,    9,  156,  175,  171,    0,    0,    0,    0,    2,    2,    2,   28,    7,    2,    2,
+      2,    2,    2,    2,    2,    2,   21,   21,   45,   20,   33,   80,   66,    0,    0,    0,
+      0,    2,  176,   64,   45,    0,    0,    0,    0,    9,  177,    2,    2,    2,    2,    2,
+      2,    2,    2,   21,   20,   18,   29,    0,   46,   14,  140,    0,    0,    0,    0,    0,
+      0,  178,  178,  178,  106,  179,  178,    0,    0,  145,    2,    2,  180,  114,  114,  114,
+    114,  114,  114,  114,    0,    0,    0,    0,    0,    9,    9,    9,   44,    0,    0,    0,
+      0,    2,    2,    2,    2,    2,    7,    0,   56,  181,   18,   18,   18,   18,   18,   18,
+     18,   18,   18,   18,   18,   18,   18,   18,   18,   18,   18,   18,   18,    0,    0,    0,
+     38,  114,   24,    0,    0,    0,    0,    0,    0,    0,    0,    7,    0,    0,    0,    0,
+      0,    2,    2,    2,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    0,   56,
+     35,    0,    4,  118,  118,  118,  119,    0,    0,    9,    9,    9,   47,    2,    2,    2,
+      0,    2,    2,    2,    2,    2,    0,    0,    2,    2,    2,    2,    2,    2,    2,    2,
+     44,    2,    2,    2,    2,    2,    2,    9,    9,    2,    2,    2,    2,    2,    2,   20,
+     20,    2,    2,   42,   42,   42,   90,    0,    0,    O,    O,    O,   GB,    B,    B,   GB,
+      O,    O,   WJ,FMPst,FMPst,    O,  CGJ,    B,    O,    B,VMAbv,VMAbv,VMAbv,    O,VMAbv,    B,
+  CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw,    B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw,
+   VAbv, VAbv, VAbv, VPst, VPst, VPst,    H, VPre, VPst,VMBlw,    O,    O, VAbv,   GB,VMAbv,VMPst,
+  VMPst,    O,    B, VBlw,    O,    O, VPre, VPre,    O, VPre,    H,    O, VPst,FMAbv,    O,CMBlw,
+      O, VAbv,    O, VAbv,    H,    O,VMBlw,VMAbv,CMAbv,   GB,   GB,    O, MBlw,CMAbv,CMAbv, VPst,
+   VAbv,VMAbv,    O, VPst,    O, VPre, VPre,VMAbv,    B,    O,   CS,   CS,VMPst,    B, VAbv, VAbv,
+      B,    R,    O,  HVM,    O,    O,FMBlw,    O,CMAbv,    O,CMBlw, VAbv, VBlw,    B,  SUB,  SUB,
+    SUB,    O,  SUB,  SUB,    O,FMBlw,    O,    B, VPst, VBlw, VPre,VMAbv,VMBlw,VMPst,   IS, VAbv,
+   MPst, MPre, MBlw, MBlw,    B, MBlw, MBlw, VPst,VMPst,VMPst,    B, MBlw, VPst, VPre, VAbv, VAbv,
+  VMPst,VMPst,VMBlw,    B,VMPst, VBlw, VPst,  CGJ,  CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,
+  VMAbv,FMAbv, VAbv,   IS,FMAbv,    B,FMAbv,    B,  CGJ,   WJ,  CGJ,   GB,CMAbv,CMAbv,    B,   GB,
+      B, VAbv,  SUB, FPst, FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv, VPre,    B, MPre, MBlw,
+    SUB, FAbv, FAbv, MAbv,  SUB,   Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst,    H,    B,    O,
+  SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst,   IS, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv,
+     CS,    O,FMAbv, ZWNJ,  CGJ,   WJ,   WJ,   WJ,    O,FMPst,    O,    O,    H, MPst, VPst,    H,
+  VMAbv, VAbv,VMBlw,    B, VBlw, FPst, VPst, FAbv,VMPst,    B,CMAbv, VAbv, MBlw, MPst, MBlw,    H,
+      O, VBlw, MPst, MPre, MAbv, MBlw,    O,    B, FAbv, FAbv, FPst, VBlw,    B,    B, VPre,    O,
+  VMPst,   IS,    O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv,    O,   IS,VMBlw,    B,VMPst,VMAbv,VMPst,
+     CS,   CS,    B,    N,    N,    O,   HN, VPre, VBlw, VAbv,   IS,CMAbv,    O, VPst,    B,    R,
+      R,CMBlw, VAbv, VPre,VMAbv,VMAbv,    H, VAbv,CMBlw,FMAbv,    B,   CS,   CS,    H,CMBlw,VMPst,
+      H,VMPst, VAbv,VMAbv, VPst,   IS,    R, MPst,    R, MPst,CMBlw,    B,FMBlw, VBlw,VMAbv,    R,
+   MBlw, MBlw,   GB, FBlw, FBlw,CMAbv,   IS, VBlw,   IS,   GB, VAbv,    R,VMPst,    H,    H,    B,
+      H,    B,VMBlw,    O, VBlw,
+};
+static const uint16_t
+hb_use_u16[448] =
+{
+    0,  0,  1,  2,  3,  4,  0,  5,  6,  0,  7,  0,  8,  9, 10, 11,
+    9, 12, 13,  9,  9, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+   17, 25, 26, 20, 21, 27, 28, 29, 30, 31, 32, 33, 21, 34, 35,  0,
+   17, 36, 37, 20, 21, 38, 23, 39, 17, 40, 41, 42, 43, 44, 45, 46,
+   30,  0, 47, 48, 21, 49, 50, 51, 17,  0, 52, 48, 21, 53, 50, 54,
+   17, 55, 56, 48,  9, 57, 58, 59, 60, 61,  9, 62, 63, 64, 30, 65,
+   66, 67,  9, 68, 69,  9, 70, 71, 72, 73, 74, 75, 76,  0,  9,  9,
+   77, 78, 79, 80, 81, 82, 83, 84,  9, 85,  9, 86,  9, 87, 88, 89,
+    9, 90, 91, 92,  2,  0, 93,  0,  9, 94, 95,  9, 96,  0, 97, 98,
+   99,100, 30,  9,101,102,103,  9,104,105,  9,106,  9,107,108,109,
+    2,  2,110,  9,  9,111,112,  2,113,114,115,  9,116,  9,117,118,
+  119,120,121,  0,  0,122,123,124,  0,125,126,127,128,  0,129,130,
+  131,  0,  0,132,133,  0,  0,  9,134,135,136,  9,137,  0,  9,138,
+  139,  9,  9,140,141,  2,142,143,144,  9,145,146,147,  9,  9,148,
+  149,  2,150, 98,151,152,153,  2,  9,154,  9,155,156,  0,157,158,
+  159,  2,160,  0,  0,161,  0,162,  0,163,163,164, 33,165,166,167,
+    9,168, 94,  0,169,  0,  9,170,171,  0,172,  2,173,170,174,175,
+  176,  0,  0,177,178,  0,179,  9,  9,180,181,182,183,184,185,  9,
+    9,186,187,  0,188,  9,189,190,191,  9,  9,192,  9,193,194,105,
+  195,102,  9, 33,196,197,198,  0,199,200, 94,  9,  9,201,202,  2,
+  203, 20, 21,204,205,206,207,208,  9,209,210,211,212,  0,195,  9,
+    9,213,214,  2,215,216,217,218,  9,219,220,  2,221,222,  9,223,
+  224,103,225,  0,226,227,228,229,  9,230,231,  2,232,  9,  9,233,
+  234,  0,235,  9,  9,236,237,238,239,240, 21,  9,215,241,  7,  9,
+   70, 18,  9,242, 73,243,244,  9,  9,245,246,  2,247,  9,248,249,
+    9,250,251, 48,  9,252,253,  2,  9,254,255,256,  9,257,258,259,
+  260,260,261,262,263,  0,  9,264,105, 70, 94,265,  0,266, 70,267,
+  268,  0,269,  0,270,  2,271,  2,272,  2,129,129,160,160,160,129,
+};
+
+static inline unsigned
+hb_use_b4 (const uint8_t* a, unsigned i)
+{
+  return (a[i>>1]>>((i&1u)<<2))&15u;
+}
+static inline uint_fast8_t
+hb_use_get_category (unsigned u)
+{
+  return u<921600u?hb_use_u8[3049+(((hb_use_u8[865+(((hb_use_u16[((hb_use_u8[353+(((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>1>>3>>4))<<4)+((u>>1>>3>>1>>3)&15u))])<<3)+((u>>1>>3>>1)&7u))])<<1)+((u>>1>>3)&1u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
+}
+
+#endif
+
 #undef B
 #undef CGJ
 #undef CS
diff --git a/src/hb-ot-shaper-use.cc b/src/hb-ot-shaper-use.cc
index c40ec52..342aba1 100644
--- a/src/hb-ot-shaper-use.cc
+++ b/src/hb-ot-shaper-use.cc
@@ -89,19 +89,19 @@
   HB_TAG('p','s','t','s'),
 };
 
-static void
+static bool
 setup_syllables_use (const hb_ot_shape_plan_t *plan,
 		     hb_font_t *font,
 		     hb_buffer_t *buffer);
-static void
+static bool
 record_rphf_use (const hb_ot_shape_plan_t *plan,
 		 hb_font_t *font,
 		 hb_buffer_t *buffer);
-static void
+static bool
 record_pref_use (const hb_ot_shape_plan_t *plan,
 		 hb_font_t *font,
 		 hb_buffer_t *buffer);
-static void
+static bool
 reorder_use (const hb_ot_shape_plan_t *plan,
 	     hb_font_t *font,
 	     hb_buffer_t *buffer);
@@ -293,7 +293,7 @@
   }
 }
 
-static void
+static bool
 setup_syllables_use (const hb_ot_shape_plan_t *plan,
 		     hb_font_t *font HB_UNUSED,
 		     hb_buffer_t *buffer)
@@ -304,9 +304,10 @@
     buffer->unsafe_to_break (start, end);
   setup_rphf_mask (plan, buffer);
   setup_topographical_masks (plan, buffer);
+  return false;
 }
 
-static void
+static bool
 record_rphf_use (const hb_ot_shape_plan_t *plan,
 		 hb_font_t *font HB_UNUSED,
 		 hb_buffer_t *buffer)
@@ -314,7 +315,7 @@
   const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
 
   hb_mask_t mask = use_plan->rphf_mask;
-  if (!mask) return;
+  if (!mask) return false;
   hb_glyph_info_t *info = buffer->info;
 
   foreach_syllable (buffer, start, end)
@@ -327,9 +328,10 @@
 	break;
       }
   }
+  return false;
 }
 
-static void
+static bool
 record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
 		 hb_font_t *font HB_UNUSED,
 		 hb_buffer_t *buffer)
@@ -346,6 +348,7 @@
 	break;
       }
   }
+  return false;
 }
 
 static inline bool
@@ -438,17 +441,19 @@
   }
 }
 
-static void
+static bool
 reorder_use (const hb_ot_shape_plan_t *plan,
 	     hb_font_t *font,
 	     hb_buffer_t *buffer)
 {
+  bool ret = false;
   if (buffer->message (font, "start reordering USE"))
   {
-    hb_syllabic_insert_dotted_circles (font, buffer,
-				       use_broken_cluster,
-				       USE(B),
-				       USE(R));
+    if (hb_syllabic_insert_dotted_circles (font, buffer,
+					   use_broken_cluster,
+					   USE(B),
+					   USE(R)))
+      ret = true;
 
     foreach_syllable (buffer, start, end)
       reorder_syllable_use (buffer, start, end);
@@ -457,6 +462,8 @@
   }
 
   HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
+
+  return ret;
 }
 
 
diff --git a/src/hb-ot-shaper.hh b/src/hb-ot-shaper.hh
index b2d1acb..0207b2b 100644
--- a/src/hb-ot-shaper.hh
+++ b/src/hb-ot-shaper.hh
@@ -262,11 +262,13 @@
 	return &_hb_ot_shaper_myanmar;
 
 
+#ifndef HB_NO_OT_SHAPER_MYANMAR_ZAWGYI
 #define HB_SCRIPT_MYANMAR_ZAWGYI	((hb_script_t) HB_TAG ('Q','a','a','g'))
     case HB_SCRIPT_MYANMAR_ZAWGYI:
     /* https://github.com/harfbuzz/harfbuzz/issues/1162 */
 
       return &_hb_ot_shaper_myanmar_zawgyi;
+#endif
 
 
     /* Unicode-2.0 additions */
diff --git a/src/hb-ot-stat-table.hh b/src/hb-ot-stat-table.hh
index af6d550..59bb2da 100644
--- a/src/hb-ot-stat-table.hh
+++ b/src/hb-ot-stat-table.hh
@@ -320,7 +320,7 @@
     unsigned total_size = min_size + axisCount * AxisValueRecord::static_size;
     auto *out = c->serializer->allocate_size<AxisValueFormat4> (total_size);
     if (unlikely (!out)) return_trace (false);
-    memcpy (out, this, total_size);
+    hb_memcpy (out, this, total_size);
     return_trace (true);
   }
 
diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc
index 1b18270..f6ba3b0 100644
--- a/src/hb-ot-tag.cc
+++ b/src/hb-ot-tag.cc
@@ -577,7 +577,7 @@
       else
       {
 	int shift;
-	memcpy (buf, lang_str, len);
+	hb_memcpy (buf, lang_str, len);
 	if (lang_str[0] != 'x' || lang_str[1] != '-') {
 	  buf[len++] = '-';
 	  buf[len++] = 'x';
diff --git a/src/hb-ot-var-avar-table.hh b/src/hb-ot-var-avar-table.hh
index f60bc4a..cc5c5c0 100644
--- a/src/hb-ot-var-avar-table.hh
+++ b/src/hb-ot-var-avar-table.hh
@@ -143,7 +143,7 @@
     TRACE_SANITIZE (this);
     if (!(version.sanitize (c) &&
 	  (version.major == 1
-#ifndef HB_NO_VARIATIONS2
+#ifndef HB_NO_AVAR2
 	   || version.major == 2
 #endif
 	   ) &&
@@ -159,7 +159,7 @@
       map = &StructAfter<SegmentMaps> (*map);
     }
 
-#ifndef HB_NO_VARIATIONS2
+#ifndef HB_NO_AVAR2
     if (version.major < 2)
       return_trace (true);
 
@@ -182,7 +182,7 @@
       map = &StructAfter<SegmentMaps> (*map);
     }
 
-#ifndef HB_NO_VARIATIONS2
+#ifndef HB_NO_AVAR2
     if (version.major < 2)
       return;
 
diff --git a/src/hb-ot-var-common.hh b/src/hb-ot-var-common.hh
index 1d29e3e..4997c2e 100644
--- a/src/hb-ot-var-common.hh
+++ b/src/hb-ot-var-common.hh
@@ -47,7 +47,7 @@
     HBUINT8 *p = c->allocate_size<HBUINT8> (total_size);
     if (unlikely (!p)) return_trace (nullptr);
 
-    memcpy (p, this, HBUINT8::static_size * total_size);
+    hb_memcpy (p, this, HBUINT8::static_size * total_size);
     return_trace (out);
   }
 
@@ -219,6 +219,25 @@
   DEFINE_SIZE_UNION (1, format);
 };
 
+
+struct VarStoreInstancer
+{
+  VarStoreInstancer (const VariationStore &varStore,
+		     const DeltaSetIndexMap &varIdxMap,
+		     hb_array_t<int> coords) :
+    varStore (varStore), varIdxMap (varIdxMap), coords (coords) {}
+
+  operator bool () const { return bool (coords); }
+
+  float operator() (uint32_t varIdx, unsigned short offset = 0) const
+  { return varStore.get_delta (varIdxMap.map (VarIdx::add (varIdx, offset)), coords); }
+
+  const VariationStore &varStore;
+  const DeltaSetIndexMap &varIdxMap;
+  hb_array_t<int> coords;
+};
+
+
 } /* namespace OT */
 
 
diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh
index af23862..c1d57a0 100644
--- a/src/hb-ot-var-fvar-table.hh
+++ b/src/hb-ot-var-fvar-table.hh
@@ -59,7 +59,7 @@
     const hb_hashmap_t<hb_tag_t, float> *axes_location = c->plan->user_axes_location;
     for (unsigned i = 0 ; i < axis_count; i++)
     {
-      unsigned *axis_tag;
+      uint32_t *axis_tag;
       // only keep instances whose coordinates == pinned axis location
       if (!c->plan->axes_old_index_tag_map->has (i, &axis_tag)) continue;
 
@@ -337,13 +337,13 @@
     {
       const InstanceRecord *instance = get_instance (i);
 
-      if (hb_any (+ hb_zip (instance->get_coordinates (axisCount), hb_range ((unsigned)axisCount))
-                  | hb_filter (pinned_axes, hb_second)
-                  | hb_map ([&] (const hb_pair_t<const F16DOT16&, unsigned>& _)
+      if (hb_any (+ hb_enumerate (instance->get_coordinates (axisCount))
+                  | hb_filter (pinned_axes, hb_first)
+                  | hb_map ([&] (const hb_pair_t<unsigned, const F16DOT16&>& _)
                             {
-                              hb_tag_t axis_tag = pinned_axes.get (_.second);
+                              hb_tag_t axis_tag = pinned_axes.get (_.first);
                               float location = user_axes_location->get (axis_tag);
-                              if (fabs ((double)location - (double)_.first.to_float ()) > 0.001) return true;
+                              if (fabs ((double)location - (double)_.second.to_float ()) > 0.001) return true;
                               return false;
                             })
                   ))
diff --git a/src/hb-ot-var-gvar-table.hh b/src/hb-ot-var-gvar-table.hh
index bf1039d..e02063c 100644
--- a/src/hb-ot-var-gvar-table.hh
+++ b/src/hb-ot-var-gvar-table.hh
@@ -56,12 +56,11 @@
   void extend (const hb_array_t<contour_point_t> &a)
   {
     unsigned int old_len = length;
-    if (unlikely (!resize (old_len + a.length)))
+    if (unlikely (!resize (old_len + a.length, false)))
       return;
     auto arrayZ = this->arrayZ + old_len;
     unsigned count = a.length;
-    for (unsigned int i = 0; i < count; i++)
-      arrayZ[i] = a.arrayZ[i];
+    hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0]));
   }
 
   void transform (const float (&matrix)[4])
@@ -231,8 +230,8 @@
     {
       return (index < var_data->tupleVarCount.get_count ()) &&
 	     var_data_bytes.check_range (current_tuple, TupleVariationHeader::min_size) &&
-	     var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (), current_tuple->get_size (axis_count))) &&
-	     current_tuple->get_size (axis_count);
+	     var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (),
+								current_tuple->get_size (axis_count)));
     }
 
     bool move_to_next ()
@@ -281,42 +280,42 @@
 
     if (unlikely (p + 1 > end)) return false;
 
-    uint16_t count = *p++;
+    unsigned count = *p++;
     if (count & POINTS_ARE_WORDS)
     {
       if (unlikely (p + 1 > end)) return false;
       count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++;
     }
-    if (unlikely (!points.resize (count))) return false;
+    if (unlikely (!points.resize (count, false))) return false;
 
-    unsigned int n = 0;
-    uint16_t i = 0;
+    unsigned n = 0;
+    unsigned i = 0;
     while (i < count)
     {
       if (unlikely (p + 1 > end)) return false;
-      uint16_t j;
-      uint8_t control = *p++;
-      uint16_t run_count = (control & POINT_RUN_COUNT_MASK) + 1;
+      unsigned control = *p++;
+      unsigned run_count = (control & POINT_RUN_COUNT_MASK) + 1;
+      if (unlikely (i + run_count > count)) return false;
+      unsigned j;
       if (control & POINTS_ARE_WORDS)
       {
-	for (j = 0; j < run_count && i < count; j++, i++)
+	if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
+	for (j = 0; j < run_count; j++, i++)
 	{
-	  if (unlikely (p + HBUINT16::static_size > end)) return false;
 	  n += *(const HBUINT16 *)p;
-	  points[i] = n;
+	  points.arrayZ[i] = n;
 	  p += HBUINT16::static_size;
 	}
       }
       else
       {
-	for (j = 0; j < run_count && i < count; j++, i++)
+	if (unlikely (p + run_count > end)) return false;
+	for (j = 0; j < run_count; j++, i++)
 	{
-	  if (unlikely (p + 1 > end)) return false;
 	  n += *p++;
-	  points[i] = n;
+	  points.arrayZ[i] = n;
 	}
       }
-      if (j < run_count) return false;
     }
     return true;
   }
@@ -332,32 +331,37 @@
       DELTA_RUN_COUNT_MASK = 0x3F
     };
 
-    unsigned int i = 0;
-    unsigned int count = deltas.length;
+    unsigned i = 0;
+    unsigned count = deltas.length;
     while (i < count)
     {
       if (unlikely (p + 1 > end)) return false;
-      uint8_t control = *p++;
-      unsigned int run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
-      unsigned int j;
+      unsigned control = *p++;
+      unsigned run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
+      if (unlikely (i + run_count > count)) return false;
+      unsigned j;
       if (control & DELTAS_ARE_ZERO)
-	for (j = 0; j < run_count && i < count; j++, i++)
-	  deltas[i] = 0;
+      {
+	for (j = 0; j < run_count; j++, i++)
+	  deltas.arrayZ[i] = 0;
+      }
       else if (control & DELTAS_ARE_WORDS)
-	for (j = 0; j < run_count && i < count; j++, i++)
+      {
+	if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
+	for (j = 0; j < run_count; j++, i++)
 	{
-	  if (unlikely (p + HBUINT16::static_size > end)) return false;
-	  deltas[i] = *(const HBINT16 *) p;
+	  deltas.arrayZ[i] = * (const HBINT16 *) p;
 	  p += HBUINT16::static_size;
 	}
+      }
       else
-	for (j = 0; j < run_count && i < count; j++, i++)
+      {
+	if (unlikely (p + run_count > end)) return false;
+	for (j = 0; j < run_count; j++, i++)
 	{
-	  if (unlikely (p + 1 > end)) return false;
-	  deltas[i] = *(const HBINT8 *) p++;
+	  deltas.arrayZ[i] = * (const HBINT8 *) p++;
 	}
-      if (j < run_count)
-	return false;
+      }
     }
     return true;
   }
@@ -450,7 +454,7 @@
       F2DOT14 *tuples = c->serializer->allocate_size<F2DOT14> (shared_tuple_size);
       if (!tuples) return_trace (false);
       out->sharedTuples = (char *) tuples - (char *) out;
-      memcpy (tuples, this+sharedTuples, shared_tuple_size);
+      hb_memcpy (tuples, this+sharedTuples, shared_tuple_size);
     }
 
     char *subset_data = c->serializer->allocate_size<char> (subset_data_size);
@@ -473,7 +477,7 @@
 	((HBUINT16 *) subset_offsets)[gid] = glyph_offset / 2;
 
       if (var_data_bytes.length > 0)
-	memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length);
+	hb_memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length);
       subset_data += var_data_bytes.length;
       glyph_offset += var_data_bytes.length;
     }
@@ -501,6 +505,7 @@
   unsigned get_offset (unsigned i) const
   {
     if (unlikely (i > glyphCount)) return 0;
+    _hb_compiler_memory_r_barrier ();
     return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2;
   }
 
@@ -521,11 +526,11 @@
 			      unsigned int target, unsigned int prev, unsigned int next,
 			      float contour_point_t::*m)
     {
-      float target_val = points[target].*m;
-      float prev_val = points[prev].*m;
-      float next_val = points[next].*m;
-      float prev_delta =  deltas[prev].*m;
-      float next_delta =  deltas[next].*m;
+      float target_val = points.arrayZ[target].*m;
+      float prev_val = points.arrayZ[prev].*m;
+      float next_val = points.arrayZ[next].*m;
+      float prev_delta =  deltas.arrayZ[prev].*m;
+      float next_delta =  deltas.arrayZ[next].*m;
 
       if (prev_val == next_val)
 	return (prev_delta == next_delta) ? prev_delta : 0.f;
@@ -543,10 +548,11 @@
     { return (i >= end) ? start : (i + 1); }
 
     public:
-    bool apply_deltas_to_points (hb_codepoint_t glyph, hb_font_t *font,
+    bool apply_deltas_to_points (hb_codepoint_t glyph,
+				 hb_array_t<int> coords,
 				 const hb_array_t<contour_point_t> points) const
     {
-      if (!font->num_coords) return true;
+      if (!coords) return true;
 
       if (unlikely (glyph >= table->glyphCount)) return true;
 
@@ -559,20 +565,20 @@
 	return true; /* so isn't applied at all */
 
       /* Save original points for inferred delta calculation */
-      contour_point_vector_t orig_points;
-      if (unlikely (!orig_points.resize (points.length))) return false;
-      for (unsigned int i = 0; i < orig_points.length; i++)
-	orig_points.arrayZ[i] = points.arrayZ[i];
+      contour_point_vector_t orig_points_vec;
+      orig_points_vec.extend (points);
+      if (unlikely (orig_points_vec.in_error ())) return false;
+      auto orig_points = orig_points_vec.as_array ();
 
-      contour_point_vector_t deltas; /* flag is used to indicate referenced point */
-      if (unlikely (!deltas.resize (points.length))) return false;
+      contour_point_vector_t deltas_vec; /* flag is used to indicate referenced point */
+      if (unlikely (!deltas_vec.resize (points.length, false))) return false;
+      auto deltas = deltas_vec.as_array ();
 
       hb_vector_t<unsigned> end_points;
       for (unsigned i = 0; i < points.length; ++i)
-	if (points[i].is_end_point)
+	if (points.arrayZ[i].is_end_point)
 	  end_points.push (i);
 
-      auto coords = hb_array (font->coords, font->num_coords);
       unsigned num_coords = table->axisCount;
       hb_array_t<const F2DOT14> shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount);
 
@@ -598,70 +604,89 @@
 
 	bool apply_to_all = (indices.length == 0);
 	unsigned int num_deltas = apply_to_all ? points.length : indices.length;
-	if (unlikely (!x_deltas.resize (num_deltas))) return false;
+	if (unlikely (!x_deltas.resize (num_deltas, false))) return false;
 	if (unlikely (!GlyphVariationData::unpack_deltas (p, x_deltas, end))) return false;
-	if (unlikely (!y_deltas.resize (num_deltas))) return false;
+	if (unlikely (!y_deltas.resize (num_deltas, false))) return false;
 	if (unlikely (!GlyphVariationData::unpack_deltas (p, y_deltas, end))) return false;
 
-	for (unsigned int i = 0; i < deltas.length; i++)
-	  deltas[i].init ();
-	for (unsigned int i = 0; i < num_deltas; i++)
-	{
-	  unsigned int pt_index = apply_to_all ? i : indices[i];
-	  if (unlikely (pt_index >= deltas.length)) continue;
-	  deltas.arrayZ[pt_index].flag = 1;	/* this point is referenced, i.e., explicit deltas specified */
-	  deltas.arrayZ[pt_index].x += x_deltas.arrayZ[i] * scalar;
-	  deltas.arrayZ[pt_index].y += y_deltas.arrayZ[i] * scalar;
-	}
+	hb_memset (deltas.arrayZ, 0, deltas.get_size ());
+
+	unsigned ref_points = 0;
+	if (scalar != 1.0f)
+	  for (unsigned int i = 0; i < num_deltas; i++)
+	  {
+	    unsigned int pt_index = apply_to_all ? i : indices[i];
+	    if (unlikely (pt_index >= deltas.length)) continue;
+	    auto &delta = deltas.arrayZ[pt_index];
+	    ref_points += !delta.flag;
+	    delta.flag = 1;	/* this point is referenced, i.e., explicit deltas specified */
+	    delta.x += x_deltas.arrayZ[i] * scalar;
+	    delta.y += y_deltas.arrayZ[i] * scalar;
+	  }
+	else
+	  for (unsigned int i = 0; i < num_deltas; i++)
+	  {
+	    unsigned int pt_index = apply_to_all ? i : indices[i];
+	    if (unlikely (pt_index >= deltas.length)) continue;
+	    auto &delta = deltas.arrayZ[pt_index];
+	    ref_points += !delta.flag;
+	    delta.flag = 1;	/* this point is referenced, i.e., explicit deltas specified */
+	    delta.x += x_deltas.arrayZ[i];
+	    delta.y += y_deltas.arrayZ[i];
+	  }
 
 	/* infer deltas for unreferenced points */
-	unsigned start_point = 0;
-	for (unsigned c = 0; c < end_points.length; c++)
+	if (ref_points && ref_points < orig_points.length)
 	{
-	  unsigned end_point = end_points[c];
-
-	  /* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */
-	  unsigned unref_count = 0;
-	  for (unsigned i = start_point; i <= end_point; i++)
-	    if (!deltas[i].flag) unref_count++;
-
-	  unsigned j = start_point;
-	  if (unref_count == 0 || unref_count > end_point - start_point)
-	    goto no_more_gaps;
-
-	  for (;;)
+	  unsigned start_point = 0;
+	  for (unsigned c = 0; c < end_points.length; c++)
 	  {
-	    /* Locate the next gap of unreferenced points between two referenced points prev and next.
-	     * Note that a gap may wrap around at left (start_point) and/or at right (end_point).
-	     */
-	    unsigned int prev, next, i;
+	    unsigned end_point = end_points.arrayZ[c];
+
+	    /* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */
+	    unsigned unref_count = 0;
+	    for (unsigned i = start_point; i < end_point + 1; i++)
+	      unref_count += deltas.arrayZ[i].flag;
+	    unref_count = (end_point - start_point + 1) - unref_count;
+
+	    unsigned j = start_point;
+	    if (unref_count == 0 || unref_count > end_point - start_point)
+	      goto no_more_gaps;
+
 	    for (;;)
 	    {
-	      i = j;
-	      j = next_index (i, start_point, end_point);
-	      if (deltas[i].flag && !deltas[j].flag) break;
+	      /* Locate the next gap of unreferenced points between two referenced points prev and next.
+	       * Note that a gap may wrap around at left (start_point) and/or at right (end_point).
+	       */
+	      unsigned int prev, next, i;
+	      for (;;)
+	      {
+		i = j;
+		j = next_index (i, start_point, end_point);
+		if (deltas.arrayZ[i].flag && !deltas.arrayZ[j].flag) break;
+	      }
+	      prev = j = i;
+	      for (;;)
+	      {
+		i = j;
+		j = next_index (i, start_point, end_point);
+		if (!deltas.arrayZ[i].flag && deltas.arrayZ[j].flag) break;
+	      }
+	      next = j;
+	      /* Infer deltas for all unref points in the gap between prev and next */
+	      i = prev;
+	      for (;;)
+	      {
+		i = next_index (i, start_point, end_point);
+		if (i == next) break;
+		deltas.arrayZ[i].x = infer_delta (orig_points, deltas, i, prev, next, &contour_point_t::x);
+		deltas.arrayZ[i].y = infer_delta (orig_points, deltas, i, prev, next, &contour_point_t::y);
+		if (--unref_count == 0) goto no_more_gaps;
+	      }
 	    }
-	    prev = j = i;
-	    for (;;)
-	    {
-	      i = j;
-	      j = next_index (i, start_point, end_point);
-	      if (!deltas[i].flag && deltas[j].flag) break;
-	    }
-	    next = j;
-	    /* Infer deltas for all unref points in the gap between prev and next */
-	    i = prev;
-	    for (;;)
-	    {
-	      i = next_index (i, start_point, end_point);
-	      if (i == next) break;
-	      deltas[i].x = infer_delta (orig_points.as_array (), deltas.as_array (), i, prev, next, &contour_point_t::x);
-	      deltas[i].y = infer_delta (orig_points.as_array (), deltas.as_array (), i, prev, next, &contour_point_t::y);
-	      if (--unref_count == 0) goto no_more_gaps;
-	    }
+	  no_more_gaps:
+	    start_point = end_point + 1;
 	  }
-	no_more_gaps:
-	  start_point = end_point + 1;
 	}
 
 	/* apply specified / inferred deltas to points */
diff --git a/src/hb-pool.hh b/src/hb-pool.hh
index dcf8f66..e4bb64f 100644
--- a/src/hb-pool.hh
+++ b/src/hb-pool.hh
@@ -35,15 +35,13 @@
 struct hb_pool_t
 {
   hb_pool_t () : next (nullptr) {}
-  ~hb_pool_t () { fini (); }
-
-  void fini ()
+  ~hb_pool_t ()
   {
     next = nullptr;
 
-    for (chunk_t *_ : chunks) hb_free (_);
-
-    chunks.fini ();
+    + hb_iter (chunks)
+    | hb_apply (hb_free)
+    ;
   }
 
   T* alloc ()
@@ -60,7 +58,7 @@
     T* obj = next;
     next = * ((T**) next);
 
-    memset (obj, 0, sizeof (T));
+    hb_memset (obj, 0, sizeof (T));
 
     return obj;
   }
diff --git a/src/hb-priority-queue.hh b/src/hb-priority-queue.hh
index ffb86e3..ac76b7d 100644
--- a/src/hb-priority-queue.hh
+++ b/src/hb-priority-queue.hh
@@ -63,7 +63,9 @@
 
     heap.arrayZ[0] = heap.arrayZ[heap.length - 1];
     heap.shrink (heap.length - 1);
-    bubble_down (0);
+
+    if (!is_empty ())
+      bubble_down (0);
 
     return result;
   }
@@ -100,7 +102,7 @@
 
   void bubble_down (unsigned index)
   {
-    assert (index <= heap.length);
+    assert (index < heap.length);
 
     unsigned left = left_child (index);
     unsigned right = right_child (index);
@@ -112,7 +114,7 @@
 
     bool has_right = right < heap.length;
     if (heap.arrayZ[index].first <= heap.arrayZ[left].first
-        && (!has_right || heap[index].first <= heap.arrayZ[right].first))
+        && (!has_right || heap.arrayZ[index].first <= heap.arrayZ[right].first))
       return;
 
     if (!has_right || heap.arrayZ[left].first < heap.arrayZ[right].first)
@@ -128,7 +130,7 @@
 
   void bubble_up (unsigned index)
   {
-    assert (index <= heap.length);
+    assert (index < heap.length);
 
     if (index == 0) return;
 
@@ -142,8 +144,8 @@
 
   void swap (unsigned a, unsigned b)
   {
-    assert (a <= heap.length);
-    assert (b <= heap.length);
+    assert (a < heap.length);
+    assert (b < heap.length);
     hb_swap (heap.arrayZ[a], heap.arrayZ[b]);
   }
 };
diff --git a/src/hb-repacker.hh b/src/hb-repacker.hh
index c97ce6c..7a3143c 100644
--- a/src/hb-repacker.hh
+++ b/src/hb-repacker.hh
@@ -209,7 +209,7 @@
     // Only move at most half of the roots in a space at a time.
     unsigned extra = roots_to_isolate.get_population () - maximum_to_move;
     while (extra--) {
-      unsigned root = HB_SET_VALUE_INVALID;
+      uint32_t root = HB_SET_VALUE_INVALID;
       roots_to_isolate.previous (&root);
       roots_to_isolate.del (root);
     }
@@ -283,6 +283,11 @@
                             graph_t& sorted_graph /* IN/OUT */)
 {
   sorted_graph.sort_shortest_distance ();
+  if (sorted_graph.in_error ())
+  {
+    DEBUG_MSG (SUBSET_REPACK, nullptr, "Sorted graph in error state after initial sort.");
+    return false;
+  }
 
   bool will_overflow = graph::will_overflow (sorted_graph);
   if (!will_overflow)
@@ -376,6 +381,26 @@
                       unsigned max_rounds = 20,
                       bool recalculate_extensions = false) {
   graph_t sorted_graph (packed);
+  if (sorted_graph.in_error ())
+  {
+    // Invalid graph definition.
+    return nullptr;
+  }
+
+  if (!sorted_graph.is_fully_connected ())
+  {
+    sorted_graph.print_orphaned_nodes ();
+    return nullptr;
+  }
+
+  if (sorted_graph.in_error ())
+  {
+    // Allocations failed somewhere
+    DEBUG_MSG (SUBSET_REPACK, nullptr,
+               "Graph is in error, likely due to a memory allocation error.");
+    return nullptr;
+  }
+
   if (!hb_resolve_graph_overflows (table_tag, max_rounds, recalculate_extensions, sorted_graph))
     return nullptr;
 
diff --git a/src/hb-sanitize.hh b/src/hb-sanitize.hh
index 65c2772..bd3250e 100644
--- a/src/hb-sanitize.hh
+++ b/src/hb-sanitize.hh
@@ -198,10 +198,11 @@
   void start_processing ()
   {
     reset_object ();
-    if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR)))
+    unsigned m;
+    if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR, &m)))
       this->max_ops = HB_SANITIZE_MAX_OPS_MAX;
     else
-      this->max_ops = hb_clamp ((unsigned) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
+      this->max_ops = hb_clamp (m,
 				(unsigned) HB_SANITIZE_MAX_OPS_MIN,
 				(unsigned) HB_SANITIZE_MAX_OPS_MAX);
     this->edit_count = 0;
@@ -252,8 +253,9 @@
 		    unsigned int a,
 		    unsigned int b) const
   {
-    return !hb_unsigned_mul_overflows (a, b) &&
-	   this->check_range (base, a * b);
+    unsigned m;
+    return !hb_unsigned_mul_overflows (a, b, &m) &&
+	   this->check_range (base, m);
   }
 
   template <typename T>
@@ -262,8 +264,9 @@
 		    unsigned int b,
 		    unsigned int c) const
   {
-    return !hb_unsigned_mul_overflows (a, b) &&
-	   this->check_range (base, a * b, c);
+    unsigned m;
+    return !hb_unsigned_mul_overflows (a, b, &m) &&
+	   this->check_range (base, m, c);
   }
 
   template <typename T>
diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh
index f47cde5..d557328 100644
--- a/src/hb-serialize.hh
+++ b/src/hb-serialize.hh
@@ -194,7 +194,6 @@
       current = current->next;
       _->fini ();
     }
-    object_pool.fini ();
   }
 
   bool in_error () const { return bool (errors); }
@@ -224,6 +223,7 @@
     this->errors = HB_SERIALIZE_ERROR_NONE;
     this->head = this->start;
     this->tail = this->end;
+    this->zerocopy = nullptr;
     this->debug_depth = 0;
 
     fini ();
@@ -326,7 +326,8 @@
     if (unlikely (in_error() && !only_overflow ())) return;
 
     current = current->next;
-    revert (obj->head, obj->tail);
+    revert (zerocopy ? zerocopy : obj->head, obj->tail);
+    zerocopy = nullptr;
     obj->fini ();
     object_pool.release (obj);
   }
@@ -344,8 +345,11 @@
     current = current->next;
     obj->tail = head;
     obj->next = nullptr;
+    assert (obj->head <= obj->tail);
     unsigned len = obj->tail - obj->head;
-    head = obj->head; /* Rewind head. */
+    head = zerocopy ? zerocopy : obj->head; /* Rewind head. */
+    bool was_zerocopy = zerocopy;
+    zerocopy = nullptr;
 
     if (!len)
     {
@@ -355,9 +359,11 @@
     }
 
     objidx_t objidx;
+    uint32_t hash = 0;
     if (share)
     {
-      objidx = packed_map.get (obj);
+      hash = hb_hash (obj);
+      objidx = packed_map.get_with_hash (obj, hash);
       if (objidx)
       {
         merge_virtual_links (obj, objidx);
@@ -367,7 +373,10 @@
     }
 
     tail -= len;
-    memmove (tail, obj->head, len);
+    if (was_zerocopy)
+      assert (tail == obj->head);
+    else
+      memmove (tail, obj->head, len);
 
     obj->head = tail;
     obj->tail = tail + len;
@@ -385,7 +394,7 @@
 
     objidx = packed.length - 1;
 
-    if (share) packed_map.set (obj, objidx);
+    if (share) packed_map.set_with_hash (obj, hash, objidx);
     propagate_error (packed_map);
 
     return objidx;
@@ -569,8 +578,26 @@
     return !bool ((errors = (errors | err_type)));
   }
 
+  bool start_zerocopy (size_t size)
+  {
+    if (unlikely (in_error ())) return false;
+
+    if (unlikely (size > INT_MAX || this->tail - this->head < ptrdiff_t (size)))
+    {
+      err (HB_SERIALIZE_ERROR_OUT_OF_ROOM);
+      return false;
+    }
+
+    assert (!this->zerocopy);
+    this->zerocopy = this->head;
+
+    assert (this->current->head == this->head);
+    this->current->head = this->current->tail = this->head = this->tail - size;
+    return true;
+  }
+
   template <typename Type>
-  Type *allocate_size (size_t size)
+  Type *allocate_size (size_t size, bool clear = true)
   {
     if (unlikely (in_error ())) return nullptr;
 
@@ -579,7 +606,8 @@
       err (HB_SERIALIZE_ERROR_OUT_OF_ROOM);
       return nullptr;
     }
-    hb_memset (this->head, 0, size);
+    if (clear)
+      hb_memset (this->head, 0, size);
     char *ret = this->head;
     this->head += size;
     return reinterpret_cast<Type *> (ret);
@@ -593,9 +621,9 @@
   Type *embed (const Type *obj)
   {
     unsigned int size = obj->get_size ();
-    Type *ret = this->allocate_size<Type> (size);
+    Type *ret = this->allocate_size<Type> (size, false);
     if (unlikely (!ret)) return nullptr;
-    memcpy (ret, obj, size);
+    hb_memcpy (ret, obj, size);
     return ret;
   }
   template <typename Type>
@@ -616,7 +644,7 @@
   }
 
   /* Like embed, but active: calls obj.operator=() or obj.copy() to transfer data
-   * instead of memcpy(). */
+   * instead of hb_memcpy(). */
   template <typename Type, typename ...Ts>
   Type *copy (const Type &src, Ts&&... ds)
   { return _copy (src, hb_prioritize, std::forward<Ts> (ds)...); }
@@ -634,7 +662,7 @@
   hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; }
 
   template <typename Type>
-  Type *extend_size (Type *obj, size_t size)
+  Type *extend_size (Type *obj, size_t size, bool clear = true)
   {
     if (unlikely (in_error ())) return nullptr;
 
@@ -642,12 +670,12 @@
     assert ((char *) obj <= this->head);
     assert ((size_t) (this->head - (char *) obj) <= size);
     if (unlikely (((char *) obj + size < (char *) obj) ||
-		  !this->allocate_size<Type> (((char *) obj) + size - this->head))) return nullptr;
+		  !this->allocate_size<Type> (((char *) obj) + size - this->head, clear))) return nullptr;
     return reinterpret_cast<Type *> (obj);
   }
   template <typename Type>
-  Type *extend_size (Type &obj, size_t size)
-  { return extend_size (std::addressof (obj), size); }
+  Type *extend_size (Type &obj, size_t size, bool clear = true)
+  { return extend_size (std::addressof (obj), size, clear); }
 
   template <typename Type>
   Type *extend_min (Type *obj) { return extend_size (obj, obj->min_size); }
@@ -676,8 +704,8 @@
     char *p = (char *) hb_malloc (len);
     if (unlikely (!p)) return hb_bytes_t ();
 
-    memcpy (p, this->start, this->head - this->start);
-    memcpy (p + (this->head - this->start), this->tail, this->end - this->tail);
+    hb_memcpy (p, this->start, this->head - this->start);
+    hb_memcpy (p + (this->head - this->start), this->tail, this->end - this->tail);
     return hb_bytes_t (p, len);
   }
   template <typename Type>
@@ -704,7 +732,7 @@
   }
 
   public:
-  char *start, *head, *tail, *end;
+  char *start, *head, *tail, *end, *zerocopy;
   unsigned int debug_depth;
   hb_serialize_error_t errors;
 
diff --git a/src/hb-set-digest.hh b/src/hb-set-digest.hh
index fab3621..e840911 100644
--- a/src/hb-set-digest.hh
+++ b/src/hb-set-digest.hh
@@ -28,6 +28,7 @@
 #define HB_SET_DIGEST_HH
 
 #include "hb.hh"
+#include "hb-machinery.hh"
 
 /*
  * The set-digests here implement various "filters" that support
@@ -75,6 +76,8 @@
 
   void init () { mask = 0; }
 
+  void add (const hb_set_digest_bits_pattern_t &o) { mask |= o.mask; }
+
   void add (hb_codepoint_t g) { mask |= mask_for (g); }
 
   bool add_range (hb_codepoint_t a, hb_codepoint_t b)
@@ -95,7 +98,7 @@
     for (unsigned int i = 0; i < count; i++)
     {
       add (*array);
-      array = (const T *) (stride + (const char *) array);
+      array = &StructAtOffsetUnaligned<T> ((const void *) array, stride);
     }
   }
   template <typename T>
@@ -103,16 +106,15 @@
   template <typename T>
   bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
   {
-    for (unsigned int i = 0; i < count; i++)
-    {
-      add (*array);
-      array = (const T *) (stride + (const char *) array);
-    }
+    add_array (array, count, stride);
     return true;
   }
   template <typename T>
   bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
 
+  bool may_have (const hb_set_digest_bits_pattern_t &o) const
+  { return mask & o.mask; }
+
   bool may_have (hb_codepoint_t g) const
   { return mask & mask_for (g); }
 
@@ -132,6 +134,12 @@
     tail.init ();
   }
 
+  void add (const hb_set_digest_combiner_t &o)
+  {
+    head.add (o.head);
+    tail.add (o.tail);
+  }
+
   void add (hb_codepoint_t g)
   {
     head.add (g);
@@ -140,9 +148,8 @@
 
   bool add_range (hb_codepoint_t a, hb_codepoint_t b)
   {
-    head.add_range (a, b);
-    tail.add_range (a, b);
-    return true;
+    return head.add_range (a, b) &&
+	   tail.add_range (a, b);
   }
   template <typename T>
   void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
@@ -155,13 +162,17 @@
   template <typename T>
   bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
   {
-    head.add_sorted_array (array, count, stride);
-    tail.add_sorted_array (array, count, stride);
-    return true;
+    return head.add_sorted_array (array, count, stride) &&
+	   tail.add_sorted_array (array, count, stride);
   }
   template <typename T>
   bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
 
+  bool may_have (const hb_set_digest_combiner_t &o) const
+  {
+    return head.may_have (o.head) && tail.may_have (o.tail);
+  }
+
   bool may_have (hb_codepoint_t g) const
   {
     return head.may_have (g) && tail.may_have (g);
diff --git a/src/hb-set.hh b/src/hb-set.hh
index 5d5576c..f958a08 100644
--- a/src/hb-set.hh
+++ b/src/hb-set.hh
@@ -105,10 +105,8 @@
   bool get (hb_codepoint_t g) const { return s.get (g); }
 
   /* Has interface. */
-  static constexpr bool SENTINEL = false;
-  typedef bool value_t;
-  value_t operator [] (hb_codepoint_t k) const { return get (k); }
-  bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+  bool operator [] (hb_codepoint_t k) const { return get (k); }
+  bool has (hb_codepoint_t k) const { return (*this)[k]; }
 
   /* Predicate. */
   bool operator () (hb_codepoint_t k) const { return has (k); }
diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index 9e513c0..cabcbd4 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -31,6 +31,8 @@
 #include "hb-buffer.hh"
 
 
+#ifndef HB_NO_SHAPER
+
 /**
  * SECTION:hb-shape-plan
  * @title: hb-shape-plan
@@ -74,7 +76,7 @@
   this->user_features = copy ? features : user_features;
   if (copy && num_user_features)
   {
-    memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
+    hb_memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
     /* Make start/end uniform to easier catch bugs. */
     for (unsigned int i = 0; i < num_user_features; i++)
     {
@@ -574,3 +576,6 @@
 
   return hb_shape_plan_reference (shape_plan);
 }
+
+
+#endif
diff --git a/src/hb-shape.cc b/src/hb-shape.cc
index 547d0af..7b5bf2c 100644
--- a/src/hb-shape.cc
+++ b/src/hb-shape.cc
@@ -35,6 +35,8 @@
 #include "hb-machinery.hh"
 
 
+#ifndef HB_NO_SHAPER
+
 /**
  * SECTION:hb-shape
  * @title: hb-shape
@@ -192,3 +194,6 @@
 {
   hb_shape_full (font, buffer, features, num_features, nullptr);
 }
+
+
+#endif
diff --git a/src/hb-shaper.cc b/src/hb-shaper.cc
index a900ac6..c4885cd 100644
--- a/src/hb-shaper.cc
+++ b/src/hb-shaper.cc
@@ -53,7 +53,7 @@
     if (unlikely (!shapers))
       return nullptr;
 
-    memcpy (shapers, _hb_all_shapers, sizeof (_hb_all_shapers));
+    hb_memcpy (shapers, _hb_all_shapers, sizeof (_hb_all_shapers));
 
      /* Reorder shaper list to prefer requested shapers. */
     unsigned int i = 0;
diff --git a/src/hb-static.cc b/src/hb-static.cc
index 5d4c7cd..eac5075 100644
--- a/src/hb-static.cc
+++ b/src/hb-static.cc
@@ -33,6 +33,7 @@
 #include "hb-aat-layout-feat-table.hh"
 #include "hb-ot-layout-common.hh"
 #include "hb-ot-cmap-table.hh"
+#include "hb-ot-color-colr-table.hh"
 #include "hb-ot-glyf-table.hh"
 #include "hb-ot-head-table.hh"
 #include "hb-ot-maxp-table.hh"
@@ -47,6 +48,7 @@
 DEFINE_NULL_NAMESPACE_BYTES (OT, VarIdx) =  {0xFF,0xFF,0xFF,0xFF};
 DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
 DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x01};
+DEFINE_NULL_NAMESPACE_BYTES (OT, ClipRecord) = {0x01};
 DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00};
 DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF};
 DEFINE_NULL_NAMESPACE_BYTES (AAT, Lookup) = {0xFF,0xFF};
diff --git a/src/hb-subset-accelerator.hh b/src/hb-subset-accelerator.hh
index 34bd053..63ae6d7 100644
--- a/src/hb-subset-accelerator.hh
+++ b/src/hb-subset-accelerator.hh
@@ -31,21 +31,34 @@
 #include "hb.hh"
 
 #include "hb-map.hh"
+#include "hb-multimap.hh"
 #include "hb-set.hh"
 
+extern HB_INTERNAL hb_user_data_key_t _hb_subset_accelerator_user_data_key;
+
+namespace CFF {
+struct cff_subset_accelerator_t;
+}
+
+namespace OT {
+struct SubtableUnicodesCache;
+};
+
 struct hb_subset_accelerator_t
 {
   static hb_user_data_key_t* user_data_key()
   {
-    static hb_user_data_key_t key;
-    return &key;
+    return &_hb_subset_accelerator_user_data_key;
   }
 
   static hb_subset_accelerator_t* create(const hb_map_t& unicode_to_gid_,
-                                         const hb_set_t& unicodes_) {
+					 const hb_multimap_t gid_to_unicodes_,
+					 const hb_set_t& unicodes_,
+					 bool has_seac_) {
     hb_subset_accelerator_t* accel =
         (hb_subset_accelerator_t*) hb_malloc (sizeof(hb_subset_accelerator_t));
-    new (accel) hb_subset_accelerator_t (unicode_to_gid_, unicodes_);
+    new (accel) hb_subset_accelerator_t (unicode_to_gid_, gid_to_unicodes_, unicodes_);
+    accel->has_seac = has_seac_;
     return accel;
   }
 
@@ -53,22 +66,54 @@
     if (!value) return;
 
     hb_subset_accelerator_t* accel = (hb_subset_accelerator_t*) value;
+
+    if (accel->cff_accelerator && accel->destroy_cff_accelerator)
+      accel->destroy_cff_accelerator ((void*) accel->cff_accelerator);
+
+    if (accel->cmap_cache && accel->destroy_cmap_cache)
+      accel->destroy_cmap_cache ((void*) accel->cmap_cache);
+
     accel->~hb_subset_accelerator_t ();
     hb_free (accel);
   }
 
-  hb_subset_accelerator_t(const hb_map_t& unicode_to_gid_,
+  hb_subset_accelerator_t (const hb_map_t& unicode_to_gid_,
+			   const hb_multimap_t& gid_to_unicodes_,
                           const hb_set_t& unicodes_)
-      : unicode_to_gid(unicode_to_gid_), unicodes(unicodes_) {}
+      : unicode_to_gid(unicode_to_gid_), gid_to_unicodes (gid_to_unicodes_), unicodes(unicodes_),
+        cmap_cache(nullptr), destroy_cmap_cache(nullptr),
+        has_seac(false), cff_accelerator(nullptr), destroy_cff_accelerator(nullptr)
+  { sanitized_table_cache_lock.init (); }
+
+  ~hb_subset_accelerator_t ()
+  { sanitized_table_cache_lock.fini (); }
+
+  // Generic
+
+  mutable hb_mutex_t sanitized_table_cache_lock;
+  mutable hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>> sanitized_table_cache;
 
   const hb_map_t unicode_to_gid;
+  const hb_multimap_t gid_to_unicodes;
   const hb_set_t unicodes;
+
+  // cmap
+  const OT::SubtableUnicodesCache* cmap_cache;
+  hb_destroy_func_t destroy_cmap_cache;
+
+  // CFF
+  bool has_seac;
+  const CFF::cff_subset_accelerator_t* cff_accelerator;
+  hb_destroy_func_t destroy_cff_accelerator;
+
   // TODO(garretrieger): cumulative glyf checksum map
-  // TODO(garretrieger): sanitized table cache.
 
   bool in_error () const
   {
-    return unicode_to_gid.in_error() || unicodes.in_error ();
+    return unicode_to_gid.in_error () ||
+	   gid_to_unicodes.in_error () ||
+	   unicodes.in_error () ||
+	   sanitized_table_cache.in_error ();
   }
 };
 
diff --git a/src/hb-subset-cff-common.cc b/src/hb-subset-cff-common.cc
index 711b223..6e1b6f7 100644
--- a/src/hb-subset-cff-common.cc
+++ b/src/hb-subset-cff-common.cc
@@ -66,8 +66,7 @@
 
   {
     /* use hb_set to determine the subset of font dicts */
-    hb_set_t *set = hb_set_create ();
-    if (unlikely (set == &Null (hb_set_t))) return false;
+    hb_set_t set;
     hb_codepoint_t prev_fd = CFF_UNDEF_CODE;
     for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++)
     {
@@ -79,7 +78,7 @@
 	glyph = i;
       }
       fd = src.get_fd (glyph);
-      set->add (fd);
+      set.add (fd);
 
       if (fd != prev_fd)
       {
@@ -90,12 +89,11 @@
       }
     }
 
-    subset_fd_count = set->get_population ();
+    subset_fd_count = set.get_population ();
     if (subset_fd_count == fdCount)
     {
       /* all font dicts belong to the subset. no need to subset FDSelect & FDArray */
       fdmap.identity (fdCount);
-      hb_set_destroy (set);
     }
     else
     {
@@ -103,9 +101,8 @@
       fdmap.reset ();
 
       hb_codepoint_t fd = CFF_UNDEF_CODE;
-      while (set->next (&fd))
+      while (set.next (&fd))
 	fdmap.add (fd);
-      hb_set_destroy (set);
       if (unlikely (fdmap.get_population () != subset_fd_count))
 	return false;
     }
diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh
index bb9f27e..8bbc017 100644
--- a/src/hb-subset-cff-common.hh
+++ b/src/hb-subset-cff-common.hh
@@ -38,15 +38,16 @@
 struct str_encoder_t
 {
   str_encoder_t (str_buff_t &buff_)
-    : buff (buff_), error (false) {}
+    : buff (buff_) {}
 
   void reset () { buff.reset (); }
 
   void encode_byte (unsigned char b)
   {
-    buff.push (b);
-    if (unlikely (buff.in_error ()))
-      set_error ();
+    if (likely ((signed) buff.length < buff.allocated))
+      buff.arrayZ[buff.length++] = b;
+    else
+      buff.push (b);
   }
 
   void encode_int (int v)
@@ -108,27 +109,18 @@
       encode_byte (op);
   }
 
-  void copy_str (const hb_ubytes_t &str)
+  void copy_str (const unsigned char *str, unsigned length)
   {
-    unsigned int  offset = buff.length;
-    /* Manually resize buffer since faster. */
-    if ((signed) (buff.length + str.length) <= buff.allocated)
-      buff.length += str.length;
-    else if (unlikely (!buff.resize (offset + str.length)))
-    {
-      set_error ();
-      return;
-    }
-    memcpy (buff.arrayZ + offset, &str[0], str.length);
+    assert ((signed) (buff.length + length) <= buff.allocated);
+    hb_memcpy (buff.arrayZ + buff.length, str, length);
+    buff.length += length;
   }
 
-  bool is_error () const { return error; }
+  bool in_error () const { return buff.in_error (); }
 
   protected:
-  void set_error () { error = true; }
 
   str_buff_t &buff;
-  bool    error;
 };
 
 struct cff_sub_table_info_t {
@@ -187,9 +179,12 @@
     }
     else
     {
-      HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
+      unsigned char *d = c->allocate_size<unsigned char> (opstr.length);
       if (unlikely (!d)) return_trace (false);
-      memcpy (d, &opstr.str[0], opstr.str.length);
+      /* Faster than hb_memcpy for small strings. */
+      for (unsigned i = 0; i < opstr.length; i++)
+	d[i] = opstr.ptr[i];
+      //hb_memcpy (d, opstr.ptr, opstr.length);
     }
     return_trace (true);
   }
@@ -239,11 +234,10 @@
 
   bool flatten (str_buff_vec_t &flat_charstrings)
   {
-    if (!flat_charstrings.resize (plan->num_output_glyphs ()))
+    unsigned count = plan->num_output_glyphs ();
+    if (!flat_charstrings.resize (count))
       return false;
-    for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
-      flat_charstrings[i].init ();
-    for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
+    for (unsigned int i = 0; i < count; i++)
     {
       hb_codepoint_t  glyph;
       if (!plan->old_gid_for_new_gid (i, &glyph))
@@ -259,7 +253,7 @@
       ENV env (str, acc, fd);
       cs_interpreter_t<ENV, OPSET, flatten_param_t> interp (env);
       flatten_param_t  param = {
-        flat_charstrings[i],
+        flat_charstrings.arrayZ[i],
         (bool) (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
       };
       if (unlikely (!interp.interpret (param)))
@@ -274,11 +268,9 @@
 
 struct subr_closures_t
 {
-  subr_closures_t (unsigned int fd_count) : valid (false), global_closure (), local_closures ()
+  subr_closures_t (unsigned int fd_count) : global_closure (), local_closures ()
   {
-    valid = true;
-    if (!local_closures.resize (fd_count))
-      valid = false;
+    local_closures.resize (fd_count);
   }
 
   void reset ()
@@ -288,47 +280,38 @@
       local_closures[i].clear();
   }
 
-  bool is_valid () const { return valid; }
-  bool  valid;
+  bool in_error () const { return local_closures.in_error (); }
   hb_set_t  global_closure;
   hb_vector_t<hb_set_t> local_closures;
 };
 
 struct parsed_cs_op_t : op_str_t
 {
-  void init (unsigned int subr_num_ = 0)
-  {
-    subr_num = subr_num_;
-    drop_flag = false;
-    keep_flag = false;
-    skip_flag = false;
-  }
+  parsed_cs_op_t (unsigned int subr_num_ = 0) :
+    subr_num (subr_num_) {}
 
-  bool for_drop () const { return drop_flag; }
-  void set_drop ()       { if (!for_keep ()) drop_flag = true; }
+  bool is_hinting () const { return hinting_flag; }
+  void set_hinting ()       { hinting_flag = true; }
 
-  bool for_keep () const { return keep_flag; }
-  void set_keep ()       { keep_flag = true; }
-
-  bool for_skip () const { return skip_flag; }
-  void set_skip ()       { skip_flag = true; }
-
-  unsigned int  subr_num;
+  /* The layout of this struct is designed to fit within the
+   * padding of op_str_t! */
 
   protected:
-  bool	  drop_flag;
-  bool	  keep_flag;
-  bool	  skip_flag;
+  bool	  hinting_flag = false;
+
+  public:
+  uint16_t subr_num;
 };
 
 struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
 {
-  void init ()
+  parsed_cs_str_t () :
+    parsed (false),
+    hint_dropped (false),
+    has_prefix_ (false),
+    has_calls_ (false)
   {
     SUPER::init ();
-    parsed = false;
-    hint_dropped = false;
-    has_prefix_ = false;
   }
 
   void add_op (op_code_t op, const byte_str_ref_t& str_ref)
@@ -341,13 +324,12 @@
   {
     if (!is_parsed ())
     {
-      unsigned int parsed_len = get_count ();
-      if (likely (parsed_len > 0))
-	values[parsed_len-1].set_skip ();
+      has_calls_ = true;
 
-      parsed_cs_op_t val;
-      val.init (subr_num);
-      SUPER::add_op (op, str_ref, val);
+      /* Pop the subroutine number. */
+      values.pop ();
+
+      SUPER::add_op (op, str_ref, {subr_num});
     }
   }
 
@@ -377,11 +359,14 @@
   op_code_t prefix_op () const         { return prefix_op_; }
   const number_t &prefix_num () const { return prefix_num_; }
 
+  bool has_calls () const          { return has_calls_; }
+
   protected:
-  bool    parsed;
-  bool    hint_dropped;
-  bool    vsindex_dropped;
-  bool    has_prefix_;
+  bool    parsed : 1;
+  bool    hint_dropped : 1;
+  bool    vsindex_dropped : 1;
+  bool    has_prefix_ : 1;
+  bool    has_calls_ : 1;
   op_code_t	prefix_op_;
   number_t	prefix_num_;
 
@@ -395,6 +380,59 @@
   typedef hb_vector_t<parsed_cs_str_t> SUPER;
 };
 
+struct cff_subset_accelerator_t
+{
+  static cff_subset_accelerator_t* create (
+      hb_blob_t* original_blob,
+      const parsed_cs_str_vec_t& parsed_charstrings,
+      const parsed_cs_str_vec_t& parsed_global_subrs,
+      const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs) {
+    cff_subset_accelerator_t* accel =
+        (cff_subset_accelerator_t*) hb_malloc (sizeof(cff_subset_accelerator_t));
+    new (accel) cff_subset_accelerator_t (original_blob,
+                                          parsed_charstrings,
+                                          parsed_global_subrs,
+                                          parsed_local_subrs);
+    return accel;
+  }
+
+  static void destroy (void* value) {
+    if (!value) return;
+
+    cff_subset_accelerator_t* accel = (cff_subset_accelerator_t*) value;
+    accel->~cff_subset_accelerator_t ();
+    hb_free (accel);
+  }
+
+  cff_subset_accelerator_t(
+      hb_blob_t* original_blob_,
+      const parsed_cs_str_vec_t& parsed_charstrings_,
+      const parsed_cs_str_vec_t& parsed_global_subrs_,
+      const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs_)
+  {
+    parsed_charstrings = parsed_charstrings_;
+    parsed_global_subrs = parsed_global_subrs_;
+    parsed_local_subrs = parsed_local_subrs_;
+
+    // the parsed charstrings point to memory in the original CFF table so we must hold a reference
+    // to it to keep the memory valid.
+    original_blob = hb_blob_reference (original_blob_);
+  }
+
+  ~cff_subset_accelerator_t() {
+    hb_blob_destroy (original_blob);
+    hb_map_destroy (glyph_to_sid_map.get_relaxed ());
+  }
+
+  parsed_cs_str_vec_t parsed_charstrings;
+  parsed_cs_str_vec_t parsed_global_subrs;
+  hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs;
+  mutable hb_atomic_ptr_t<hb_map_t> glyph_to_sid_map = nullptr;
+
+ private:
+  hb_blob_t* original_blob;
+};
+
 struct subr_subset_param_t
 {
   subr_subset_param_t (parsed_cs_str_t *parsed_charstring_,
@@ -446,7 +484,11 @@
     if (unlikely (calling && !parsed_str->is_parsed () && (parsed_str->values.length > 0)))
       env.set_error ();
     else
+    {
+      if (!parsed_str->is_parsed ())
+        parsed_str->alloc (env.str_ref.total_size () / 2);
       current_parsed_str = parsed_str;
+    }
   }
 
   parsed_cs_str_t	*current_parsed_str;
@@ -506,7 +548,7 @@
   {
     global_remap.create (&closures.global_closure);
     for (unsigned int i = 0; i < local_remaps.length; i++)
-      local_remaps[i].create (&closures.local_closures[i]);
+      local_remaps.arrayZ[i].create (&closures.local_closures[i]);
   }
 
   subr_remap_t	       global_remap;
@@ -517,7 +559,8 @@
 struct subr_subsetter_t
 {
   subr_subsetter_t (ACC &acc_, const hb_subset_plan_t *plan_)
-      : acc (acc_), plan (plan_), closures(acc_.fdCount), remaps(acc_.fdCount)
+      : acc (acc_), plan (plan_), closures(acc_.fdCount),
+        remaps(acc_.fdCount)
   {}
 
   /* Subroutine subsetting with --no-desubroutinize runs in phases:
@@ -536,55 +579,96 @@
    */
   bool subset (void)
   {
-    parsed_charstrings.resize (plan->num_output_glyphs ());
-    parsed_global_subrs.resize (acc.globalSubrs->count);
+    unsigned fd_count = acc.fdCount;
+    const cff_subset_accelerator_t* cff_accelerator = nullptr;
+    if (plan->accelerator && plan->accelerator->cff_accelerator) {
+      cff_accelerator = plan->accelerator->cff_accelerator;
+      fd_count = cff_accelerator->parsed_local_subrs.length;
+    }
+
+    if (cff_accelerator) {
+      // If we are not dropping hinting then charstrings are not modified so we can
+      // just use a reference to the cached copies.
+      cached_charstrings.resize (plan->num_output_glyphs ());
+      parsed_global_subrs = &cff_accelerator->parsed_global_subrs;
+      parsed_local_subrs = &cff_accelerator->parsed_local_subrs;
+    } else {
+      parsed_charstrings.resize (plan->num_output_glyphs ());
+      parsed_global_subrs_storage.resize (acc.globalSubrs->count);
+
+      if (unlikely (!parsed_local_subrs_storage.resize (fd_count))) return false;
+
+      for (unsigned int i = 0; i < acc.fdCount; i++)
+      {
+        unsigned count = acc.privateDicts[i].localSubrs->count;
+        parsed_local_subrs_storage[i].resize (count);
+        if (unlikely (parsed_local_subrs_storage[i].in_error ())) return false;
+      }
+
+      parsed_global_subrs = &parsed_global_subrs_storage;
+      parsed_local_subrs = &parsed_local_subrs_storage;
+    }
 
     if (unlikely (remaps.in_error()
+                  || cached_charstrings.in_error ()
                   || parsed_charstrings.in_error ()
-                  || parsed_global_subrs.in_error ())) {
+                  || parsed_global_subrs->in_error ()
+                  || closures.in_error ())) {
       return false;
     }
 
-    if (unlikely (!parsed_local_subrs.resize (acc.fdCount))) return false;
-
-    for (unsigned int i = 0; i < acc.fdCount; i++)
-    {
-      parsed_local_subrs[i].resize (acc.privateDicts[i].localSubrs->count);
-      if (unlikely (parsed_local_subrs[i].in_error ())) return false;
-    }
-    if (unlikely (!closures.valid))
-      return false;
-
     /* phase 1 & 2 */
     for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
     {
       hb_codepoint_t  glyph;
       if (!plan->old_gid_for_new_gid (i, &glyph))
-	continue;
+        continue;
+
       const hb_ubytes_t str = (*acc.charStrings)[glyph];
       unsigned int fd = acc.fdSelect->get_fd (glyph);
       if (unlikely (fd >= acc.fdCount))
-	return false;
+        return false;
+
+      if (cff_accelerator)
+      {
+        // parsed string already exists in accelerator, copy it and move
+        // on.
+        if (cached_charstrings)
+          cached_charstrings[i] = &cff_accelerator->parsed_charstrings[glyph];
+        else
+          parsed_charstrings[i] = cff_accelerator->parsed_charstrings[glyph];
+
+        continue;
+      }
 
       ENV env (str, acc, fd);
       cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp (env);
 
-      parsed_charstrings[i].alloc (str.length);
+      parsed_charstrings[i].alloc (str.length / 2);
       subr_subset_param_t  param (&parsed_charstrings[i],
-				  &parsed_global_subrs,
-				  &parsed_local_subrs[fd],
-				  &closures.global_closure,
-				  &closures.local_closures[fd],
-				  plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+                                  &parsed_global_subrs_storage,
+                                  &parsed_local_subrs_storage[fd],
+                                  &closures.global_closure,
+                                  &closures.local_closures[fd],
+                                  plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
 
       if (unlikely (!interp.interpret (param)))
-	return false;
+        return false;
 
       /* complete parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
       SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]);
     }
 
-    if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+    // Since parsed strings were loaded from accelerator, we still need
+    // to compute the subroutine closures which would have normally happened during
+    // parsing.
+    if (cff_accelerator &&
+        !closure_subroutines(*parsed_global_subrs,
+                             *parsed_local_subrs))
+      return false;
+
+    if ((plan->flags & HB_SUBSET_FLAGS_NO_HINTING && !cff_accelerator) ||
+	plan->inprogress_accelerator)
     {
       /* mark hint ops and arguments for drop */
       for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
@@ -596,8 +680,8 @@
 	if (unlikely (fd >= acc.fdCount))
 	  return false;
 	subr_subset_param_t  param (&parsed_charstrings[i],
-				    &parsed_global_subrs,
-				    &parsed_local_subrs[fd],
+				    &parsed_global_subrs_storage,
+				    &parsed_local_subrs_storage[fd],
 				    &closures.global_closure,
 				    &closures.local_closures[fd],
 				    plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
@@ -612,27 +696,14 @@
       }
 
       /* after dropping hints recreate closures of actually used subrs */
-      closures.reset ();
-      for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
-      {
-	hb_codepoint_t  glyph;
-	if (!plan->old_gid_for_new_gid (i, &glyph))
-	  continue;
-	unsigned int fd = acc.fdSelect->get_fd (glyph);
-	if (unlikely (fd >= acc.fdCount))
-	  return false;
-	subr_subset_param_t  param (&parsed_charstrings[i],
-				    &parsed_global_subrs,
-				    &parsed_local_subrs[fd],
-				    &closures.global_closure,
-				    &closures.local_closures[fd],
-				    plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
-	collect_subr_refs_in_str (parsed_charstrings[i], param);
-      }
+      if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING &&
+	  !cff_accelerator &&
+	  !closure_subroutines(*parsed_global_subrs, *parsed_local_subrs)) return false;
     }
 
     remaps.create (closures);
 
+    populate_subset_accelerator ();
     return true;
   }
 
@@ -646,13 +717,13 @@
       if (!plan->old_gid_for_new_gid (i, &glyph))
       {
 	/* add an endchar only charstring for a missing glyph if CFF1 */
-	if (endchar_op != OpCode_Invalid) buffArray[i].push (endchar_op);
+	if (endchar_op != OpCode_Invalid) buffArray.arrayZ[i].push (endchar_op);
 	continue;
       }
       unsigned int  fd = acc.fdSelect->get_fd (glyph);
       if (unlikely (fd >= acc.fdCount))
 	return false;
-      if (unlikely (!encode_str (parsed_charstrings[i], fd, buffArray[i])))
+      if (unlikely (!encode_str (get_parsed_charstring (i), fd, buffArray.arrayZ[i])))
 	return false;
     }
     return true;
@@ -664,26 +735,25 @@
 
     if (unlikely (!buffArray.resize (count)))
       return false;
-    for (unsigned int old_num = 0; old_num < subrs.length; old_num++)
+    for (unsigned int new_num = 0; new_num < count; new_num++)
     {
-      hb_codepoint_t new_num = remap[old_num];
-      if (new_num != CFF_UNDEF_CODE)
-      {
-	if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num])))
-	  return false;
-      }
+      hb_codepoint_t old_num = remap.backward (new_num);
+      assert (old_num != CFF_UNDEF_CODE);
+
+      if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num])))
+	return false;
     }
     return true;
   }
 
   bool encode_globalsubrs (str_buff_vec_t &buffArray)
   {
-    return encode_subrs (parsed_global_subrs, remaps.global_remap, 0, buffArray);
+    return encode_subrs (*parsed_global_subrs, remaps.global_remap, 0, buffArray);
   }
 
   bool encode_localsubrs (unsigned int fd, str_buff_vec_t &buffArray) const
   {
-    return encode_subrs (parsed_local_subrs[fd], remaps.local_remaps[fd], fd, buffArray);
+    return encode_subrs ((*parsed_local_subrs)[fd], remaps.local_remaps[fd], fd, buffArray);
   }
 
   protected:
@@ -712,7 +782,7 @@
      * then this entire subroutine must be a hint. drop its call. */
     if (drop.ends_in_hint)
     {
-      str.values[pos].set_drop ();
+      str.values[pos].set_hinting ();
       /* if this subr call is at the end of the parent subr, propagate the flag
        * otherwise reset the flag */
       if (!str.at_end (pos))
@@ -720,7 +790,7 @@
     }
     else if (drop.all_dropped)
     {
-      str.values[pos].set_drop ();
+      str.values[pos].set_hinting ();
     }
 
     return has_hint;
@@ -731,20 +801,22 @@
   {
     bool  seen_hint = false;
 
-    for (unsigned int pos = 0; pos < str.values.length; pos++)
+    unsigned count = str.values.length;
+    auto *values = str.values.arrayZ;
+    for (unsigned int pos = 0; pos < count; pos++)
     {
       bool  has_hint = false;
-      switch (str.values[pos].op)
+      switch (values[pos].op)
       {
 	case OpCode_callsubr:
 	  has_hint = drop_hints_in_subr (str, pos,
-					*param.parsed_local_subrs, str.values[pos].subr_num,
+					*param.parsed_local_subrs, values[pos].subr_num,
 					param, drop);
 	  break;
 
 	case OpCode_callgsubr:
 	  has_hint = drop_hints_in_subr (str, pos,
-					*param.parsed_global_subrs, str.values[pos].subr_num,
+					*param.parsed_global_subrs, values[pos].subr_num,
 					param, drop);
 	  break;
 
@@ -758,7 +830,7 @@
 	case OpCode_cntrmask:
 	  if (drop.seen_moveto)
 	  {
-	    str.values[pos].set_drop ();
+	    values[pos].set_hinting ();
 	    break;
 	  }
 	  HB_FALLTHROUGH;
@@ -768,13 +840,13 @@
 	case OpCode_hstem:
 	case OpCode_vstem:
 	  has_hint = true;
-	  str.values[pos].set_drop ();
+	  values[pos].set_hinting ();
 	  if (str.at_end (pos))
 	    drop.ends_in_hint = true;
 	  break;
 
 	case OpCode_dotsection:
-	  str.values[pos].set_drop ();
+	  values[pos].set_hinting ();
 	  break;
 
 	default:
@@ -785,10 +857,10 @@
       {
 	for (int i = pos - 1; i >= 0; i--)
 	{
-	  parsed_cs_op_t  &csop = str.values[(unsigned)i];
-	  if (csop.for_drop ())
+	  parsed_cs_op_t  &csop = values[(unsigned)i];
+	  if (csop.is_hinting ())
 	    break;
-	  csop.set_drop ();
+	  csop.set_hinting ();
 	  if (csop.op == OpCode_vsindexcs)
 	    drop.vsindex_dropped = true;
 	}
@@ -801,12 +873,12 @@
      * only (usually one) hintmask operator, then calls to this subr can be dropped.
      */
     drop.all_dropped = true;
-    for (unsigned int pos = 0; pos < str.values.length; pos++)
+    for (unsigned int pos = 0; pos < count; pos++)
     {
-      parsed_cs_op_t  &csop = str.values[pos];
+      parsed_cs_op_t  &csop = values[pos];
       if (csop.op == OpCode_return)
 	break;
-      if (!csop.for_drop ())
+      if (!csop.is_hinting ())
       {
 	drop.all_dropped = false;
 	break;
@@ -816,32 +888,62 @@
     return seen_hint;
   }
 
-  void collect_subr_refs_in_subr (parsed_cs_str_t &str, unsigned int pos,
-				  unsigned int subr_num, parsed_cs_str_vec_t &subrs,
+  bool closure_subroutines (const parsed_cs_str_vec_t& global_subrs,
+                            const hb_vector_t<parsed_cs_str_vec_t>& local_subrs)
+  {
+    closures.reset ();
+    for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
+    {
+      hb_codepoint_t  glyph;
+      if (!plan->old_gid_for_new_gid (i, &glyph))
+        continue;
+      unsigned int fd = acc.fdSelect->get_fd (glyph);
+      if (unlikely (fd >= acc.fdCount))
+        return false;
+
+      // Note: const cast is safe here because the collect_subr_refs_in_str only performs a
+      //       closure and does not modify any of the charstrings.
+      subr_subset_param_t  param (const_cast<parsed_cs_str_t*> (&get_parsed_charstring (i)),
+                                  const_cast<parsed_cs_str_vec_t*> (&global_subrs),
+                                  const_cast<parsed_cs_str_vec_t*> (&local_subrs[fd]),
+                                  &closures.global_closure,
+                                  &closures.local_closures[fd],
+                                  plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+      collect_subr_refs_in_str (get_parsed_charstring (i), param);
+    }
+
+    return true;
+  }
+
+  void collect_subr_refs_in_subr (unsigned int subr_num, parsed_cs_str_vec_t &subrs,
 				  hb_set_t *closure,
 				  const subr_subset_param_t &param)
   {
+    if (closure->has (subr_num))
+      return;
     closure->add (subr_num);
     collect_subr_refs_in_str (subrs[subr_num], param);
   }
 
-  void collect_subr_refs_in_str (parsed_cs_str_t &str, const subr_subset_param_t &param)
+  void collect_subr_refs_in_str (const parsed_cs_str_t &str,
+                                 const subr_subset_param_t &param)
   {
-    for (unsigned int pos = 0; pos < str.values.length; pos++)
+    if (!str.has_calls ())
+      return;
+
+    for (auto &opstr : str.values)
     {
-      if (!str.values[pos].for_drop ())
+      if (!param.drop_hints || !opstr.is_hinting ())
       {
-	switch (str.values[pos].op)
+	switch (opstr.op)
 	{
 	  case OpCode_callsubr:
-	    collect_subr_refs_in_subr (str, pos,
-				       str.values[pos].subr_num, *param.parsed_local_subrs,
+	    collect_subr_refs_in_subr (opstr.subr_num, *param.parsed_local_subrs,
 				       param.local_closure, param);
 	    break;
 
 	  case OpCode_callgsubr:
-	    collect_subr_refs_in_subr (str, pos,
-				       str.values[pos].subr_num, *param.parsed_global_subrs,
+	    collect_subr_refs_in_subr (opstr.subr_num, *param.parsed_global_subrs,
 				       param.global_closure, param);
 	    break;
 
@@ -853,42 +955,113 @@
 
   bool encode_str (const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff) const
   {
-    unsigned count = str.get_count ();
     str_encoder_t  encoder (buff);
     encoder.reset ();
-    buff.alloc (count * 3);
+    bool hinting = !(plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
     /* if a prefix (CFF1 width or CFF2 vsindex) has been removed along with hints,
      * re-insert it at the beginning of charstreing */
-    if (str.has_prefix () && str.is_hint_dropped ())
+    if (str.has_prefix () && !hinting && str.is_hint_dropped ())
     {
       encoder.encode_num (str.prefix_num ());
       if (str.prefix_op () != OpCode_Invalid)
 	encoder.encode_op (str.prefix_op ());
     }
-    for (unsigned int i = 0; i < count; i++)
+
+    unsigned size = 0;
+    for (auto &opstr : str.values)
     {
-      const parsed_cs_op_t  &opstr = str.values[i];
-      if (!opstr.for_drop () && !opstr.for_skip ())
+      size += opstr.length;
+      if (opstr.op == OpCode_callsubr || opstr.op == OpCode_callgsubr)
+        size += 3;
+    }
+    if (!buff.alloc (buff.length + size))
+      return false;
+
+    for (auto &opstr : str.values)
+    {
+      if (hinting || !opstr.is_hinting ())
       {
 	switch (opstr.op)
 	{
 	  case OpCode_callsubr:
 	    encoder.encode_int (remaps.local_remaps[fd].biased_num (opstr.subr_num));
-	    encoder.encode_op (OpCode_callsubr);
+	    encoder.copy_str (opstr.ptr, opstr.length);
 	    break;
 
 	  case OpCode_callgsubr:
 	    encoder.encode_int (remaps.global_remap.biased_num (opstr.subr_num));
-	    encoder.encode_op (OpCode_callgsubr);
+	    encoder.copy_str (opstr.ptr, opstr.length);
 	    break;
 
 	  default:
-	    encoder.copy_str (opstr.str);
+	    encoder.copy_str (opstr.ptr, opstr.length);
 	    break;
 	}
       }
     }
-    return !encoder.is_error ();
+    return !encoder.in_error ();
+  }
+
+  void compact_parsed_strings () const
+  {
+    for (auto &cs : parsed_charstrings)
+      compact_string (cs);
+    for (auto &cs : parsed_global_subrs_storage)
+      compact_string (cs);
+    for (auto &vec : parsed_local_subrs_storage)
+      for (auto &cs : vec)
+	compact_string (cs);
+  }
+
+  static void compact_string (parsed_cs_str_t &str)
+  {
+    unsigned count = str.values.length;
+    if (unlikely (!count)) return;
+    auto &opstr = str.values.arrayZ;
+    unsigned j = 0;
+    for (unsigned i = 1; i < count; i++)
+    {
+      /* See if we can combine op j and op i. */
+      bool combine =
+        (opstr[j].op != OpCode_callsubr && opstr[j].op != OpCode_callgsubr) &&
+        (opstr[i].op != OpCode_callsubr && opstr[i].op != OpCode_callgsubr) &&
+        (opstr[j].is_hinting () == opstr[i].is_hinting ()) &&
+        (opstr[j].ptr + opstr[j].length == opstr[i].ptr) &&
+        (opstr[j].length + opstr[i].length <= 255);
+
+      if (combine)
+      {
+	opstr[j].length += opstr[i].length;
+	opstr[j].op = OpCode_Invalid;
+      }
+      else
+      {
+	opstr[++j] = opstr[i];
+      }
+    }
+    str.values.shrink (j + 1);
+  }
+
+  void populate_subset_accelerator () const
+  {
+    if (!plan->inprogress_accelerator) return;
+
+    compact_parsed_strings ();
+
+    plan->inprogress_accelerator->cff_accelerator =
+        cff_subset_accelerator_t::create(acc.blob,
+                                         parsed_charstrings,
+                                         parsed_global_subrs_storage,
+                                         parsed_local_subrs_storage);
+    plan->inprogress_accelerator->destroy_cff_accelerator =
+        cff_subset_accelerator_t::destroy;
+
+  }
+
+  const parsed_cs_str_t& get_parsed_charstring (unsigned i) const
+  {
+    if (cached_charstrings) return *(cached_charstrings[i]);
+    return parsed_charstrings[i];
   }
 
   protected:
@@ -897,13 +1070,17 @@
 
   subr_closures_t		closures;
 
-  parsed_cs_str_vec_t		parsed_charstrings;
-  parsed_cs_str_vec_t		parsed_global_subrs;
-  hb_vector_t<parsed_cs_str_vec_t>  parsed_local_subrs;
+  hb_vector_t<const parsed_cs_str_t*>     cached_charstrings;
+  const parsed_cs_str_vec_t*              parsed_global_subrs;
+  const hb_vector_t<parsed_cs_str_vec_t>* parsed_local_subrs;
 
   subr_remaps_t			remaps;
 
   private:
+
+  parsed_cs_str_vec_t		parsed_charstrings;
+  parsed_cs_str_vec_t		parsed_global_subrs_storage;
+  hb_vector_t<parsed_cs_str_vec_t>  parsed_local_subrs_storage;
   typedef typename SUBRS::count_type subr_count_type;
 };
 
diff --git a/src/hb-subset-cff1.cc b/src/hb-subset-cff1.cc
index 52bb13d..538f28f 100644
--- a/src/hb-subset-cff1.cc
+++ b/src/hb-subset-cff1.cc
@@ -167,9 +167,10 @@
 	   * for supplement, the original byte string is copied along with the op code */
 	  op_str_t supp_op;
 	  supp_op.op = op;
-	  if ( unlikely (!(opstr.str.length >= opstr.last_arg_offset + 3)))
+	  if ( unlikely (!(opstr.length >= opstr.last_arg_offset + 3)))
 	    return_trace (false);
-	  supp_op.str = hb_ubytes_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset);
+	  supp_op.ptr = opstr.ptr + opstr.last_arg_offset;
+	  supp_op.length = opstr.length - opstr.last_arg_offset;
 	  return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::registry]) &&
 			UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) &&
 			copy_opstr (c, supp_op));
@@ -442,8 +443,17 @@
       return;
     }
 
-    bool use_glyph_to_sid_map = plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.;
-    hb_map_t *glyph_to_sid_map = use_glyph_to_sid_map ? acc.create_glyph_to_sid_map () : nullptr;
+    hb_map_t *glyph_to_sid_map = (plan->accelerator && plan->accelerator->cff_accelerator) ?
+				  plan->accelerator->cff_accelerator->glyph_to_sid_map :
+				  nullptr;
+    bool created_map = false;
+    if (!glyph_to_sid_map &&
+	((plan->accelerator && plan->accelerator->cff_accelerator) ||
+	 plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.))
+    {
+      created_map = true;
+      glyph_to_sid_map = acc.create_glyph_to_sid_map ();
+    }
 
     unsigned int glyph;
     for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++)
@@ -467,8 +477,12 @@
       last_sid = sid;
     }
 
-    if (glyph_to_sid_map)
-      hb_map_destroy (glyph_to_sid_map);
+    if (created_map)
+    {
+      if (!(plan->accelerator && plan->accelerator->cff_accelerator) ||
+	  !plan->accelerator->cff_accelerator->glyph_to_sid_map.cmpexch (nullptr, glyph_to_sid_map))
+	hb_map_destroy (glyph_to_sid_map);
+    }
 
     bool two_byte = subset_charset_ranges.complete (glyph);
 
@@ -728,11 +742,17 @@
 
   /* CharStrings */
   {
+    c->push<CFF1CharStrings> ();
+
+    unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings);
+    if (unlikely (!c->start_zerocopy (total_size)))
+       return false;
+
     CFF1CharStrings  *cs = c->start_embed<CFF1CharStrings> ();
     if (unlikely (!cs)) return false;
-    c->push ();
+
     if (likely (cs->serialize (c, plan.subset_charstrings)))
-      plan.info.char_strings_link = c->pop_pack ();
+      plan.info.char_strings_link = c->pop_pack (false);
     else
     {
       c->pop_discard ();
@@ -815,7 +835,7 @@
     CFF1Subrs *dest = c->start_embed <CFF1Subrs> ();
     if (unlikely (!dest)) return false;
     if (likely (dest->serialize (c, plan.subset_globalsubrs)))
-      c->pop_pack ();
+      c->pop_pack (false);
     else
     {
       c->pop_discard ();
diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc
index 08e820e..60946b0 100644
--- a/src/hb-subset-cff2.cc
+++ b/src/hb-subset-cff2.cc
@@ -334,7 +334,7 @@
 	if (unlikely (!dest)) return false;
 	c->push ();
 	if (likely (dest->serialize (c, plan.subset_localsubrs[i])))
-	  subrs_link = c->pop_pack ();
+	  subrs_link = c->pop_pack (false);
 	else
 	{
 	  c->pop_discard ();
@@ -361,11 +361,17 @@
 
   /* CharStrings */
   {
+    c->push ();
+
+    unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings);
+    if (unlikely (!c->start_zerocopy (total_size)))
+       return false;
+
     CFF2CharStrings  *cs = c->start_embed<CFF2CharStrings> ();
     if (unlikely (!cs)) return false;
-    c->push ();
+
     if (likely (cs->serialize (c, plan.subset_charstrings)))
-      plan.info.char_strings_link = c->pop_pack ();
+      plan.info.char_strings_link = c->pop_pack (false);
     else
     {
       c->pop_discard ();
@@ -377,9 +383,10 @@
   if (acc.fdSelect != &Null (CFF2FDSelect))
   {
     c->push ();
-    if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *(const FDSelect *)acc.fdSelect, 					      plan.orig_fdcount,
-					    plan.subset_fdselect_format, plan.subset_fdselect_size,
-					    plan.subset_fdselect_ranges)))
+    if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *(const FDSelect *)acc.fdSelect,
+					   plan.orig_fdcount,
+					   plan.subset_fdselect_format, plan.subset_fdselect_size,
+					   plan.subset_fdselect_ranges)))
       plan.info.fd_select.link = c->pop_pack ();
     else
     {
@@ -401,7 +408,7 @@
 	      hb_iter (private_dict_infos))
     ;
     if (unlikely (!fda->serialize (c, it, fontSzr))) return false;
-    plan.info.fd_array_link = c->pop_pack ();
+    plan.info.fd_array_link = c->pop_pack (false);
   }
 
   /* variation store */
@@ -410,7 +417,7 @@
     c->push ();
     CFF2VariationStore *dest = c->start_embed<CFF2VariationStore> ();
     if (unlikely (!dest || !dest->serialize (c, acc.varStore))) return false;
-    plan.info.var_store_link = c->pop_pack ();
+    plan.info.var_store_link = c->pop_pack (false);
   }
 
   OT::cff2 *cff2 = c->allocate_min<OT::cff2> ();
diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc
index fd25010..42434ae 100644
--- a/src/hb-subset-input.cc
+++ b/src/hb-subset-input.cc
@@ -26,7 +26,7 @@
 
 #include "hb-subset.hh"
 #include "hb-set.hh"
-
+#include "hb-utf.hh"
 /**
  * hb_subset_input_create_or_fail:
  *
@@ -49,8 +49,15 @@
     set = hb_set_create ();
 
   input->axes_location = hb_hashmap_create<hb_tag_t, float> ();
+#ifdef HB_EXPERIMENTAL_API
+  input->name_table_overrides = hb_hashmap_create<hb_ot_name_record_ids_t, hb_bytes_t> ();
+#endif
 
-  if (!input->axes_location || input->in_error ())
+  if (!input->axes_location ||
+#ifdef HB_EXPERIMENTAL_API
+      !input->name_table_overrides ||
+#endif
+      input->in_error ())
   {
     hb_subset_input_destroy (input);
     return nullptr;
@@ -248,6 +255,15 @@
 
   hb_hashmap_destroy (input->axes_location);
 
+#ifdef HB_EXPERIMENTAL_API
+  if (input->name_table_overrides)
+  {
+    for (auto _ : *input->name_table_overrides)
+      _.second.fini ();
+  }
+  hb_hashmap_destroy (input->name_table_overrides);
+#endif
+
   hb_free (input);
 }
 
@@ -379,7 +395,6 @@
   return hb_object_get_user_data (input, key);
 }
 
-#ifdef HB_EXPERIMENTAL_API
 #ifndef HB_NO_VAR
 /**
  * hb_subset_input_pin_axis_to_default: (skip)
@@ -388,9 +403,12 @@
  *
  * Pin an axis to its default location in the given subset input object.
  *
+ * Currently only works for fonts with 'glyf' tables. CFF and CFF2 is not
+ * yet supported. Additionally all axes in a font must be pinned.
+ *
  * Return value: `true` if success, `false` otherwise
  *
- * Since: EXPERIMENTAL
+ * Since: 6.0.0
  **/
 HB_EXTERN hb_bool_t
 hb_subset_input_pin_axis_to_default (hb_subset_input_t  *input,
@@ -412,9 +430,12 @@
  *
  * Pin an axis to a fixed location in the given subset input object.
  *
+ * Currently only works for fonts with 'glyf' tables. CFF and CFF2 is not
+ * yet supported. Additionally all axes in a font must be pinned.
+ *
  * Return value: `true` if success, `false` otherwise
  *
- * Since: EXPERIMENTAL
+ * Since: 6.0.0
  **/
 HB_EXTERN hb_bool_t
 hb_subset_input_pin_axis_location (hb_subset_input_t  *input,
@@ -430,28 +451,41 @@
   return input->axes_location->set (axis_tag, val);
 }
 #endif
-#endif
 
-#ifdef HB_EXPERIMENTAL_API
 /**
- * hb_subset_preprocess
- * @input: a #hb_face_t object.
+ * hb_subset_preprocess:
+ * @source: a #hb_face_t object.
  *
  * Preprocesses the face and attaches data that will be needed by the
  * subsetter. Future subsetting operations can then use the precomputed data
  * to speed up the subsetting operation.
  *
- * Since: EXPERIMENTAL
+ * See [subset-preprocessing](https://github.com/harfbuzz/harfbuzz/blob/main/docs/subset-preprocessing.md)
+ * for more information.
+ *
+ * Note: the preprocessed face may contain sub-blobs that reference the memory
+ * backing the source #hb_face_t. Therefore in the case that this memory is not
+ * owned by the source face you will need to ensure that memory lives
+ * as long as the returned #hb_face_t.
+ *
+ * Returns: a new #hb_face_t.
+ *
+ * Since: 6.0.0
  **/
 
 HB_EXTERN hb_face_t *
 hb_subset_preprocess (hb_face_t *source)
 {
   hb_subset_input_t* input = hb_subset_input_create_or_fail ();
+  if (!input)
+    return source;
 
   hb_set_clear (hb_subset_input_set(input, HB_SUBSET_SETS_UNICODE));
   hb_set_invert (hb_subset_input_set(input, HB_SUBSET_SETS_UNICODE));
 
+  hb_set_clear (hb_subset_input_set(input, HB_SUBSET_SETS_GLYPH_INDEX));
+  hb_set_invert (hb_subset_input_set(input, HB_SUBSET_SETS_GLYPH_INDEX));
+
   hb_set_clear (hb_subset_input_set(input,
                                     HB_SUBSET_SETS_LAYOUT_FEATURE_TAG));
   hb_set_invert (hb_subset_input_set(input,
@@ -467,15 +501,100 @@
   hb_set_invert (hb_subset_input_set(input,
                                      HB_SUBSET_SETS_NAME_ID));
 
+  hb_set_clear (hb_subset_input_set(input,
+                                    HB_SUBSET_SETS_NAME_LANG_ID));
+  hb_set_invert (hb_subset_input_set(input,
+                                     HB_SUBSET_SETS_NAME_LANG_ID));
+
   hb_subset_input_set_flags(input,
                             HB_SUBSET_FLAGS_NOTDEF_OUTLINE |
                             HB_SUBSET_FLAGS_GLYPH_NAMES |
-                            HB_SUBSET_FLAGS_RETAIN_GIDS);
+                            HB_SUBSET_FLAGS_RETAIN_GIDS |
+                            HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES);
   input->attach_accelerator_data = true;
 
+  // Always use long loca in the preprocessed version. This allows
+  // us to store the glyph bytes unpadded which allows the future subset
+  // operation to run faster by skipping the trim padding step.
+  input->force_long_loca = true;
+
   hb_face_t* new_source = hb_subset_or_fail (source, input);
   hb_subset_input_destroy (input);
 
+  if (!new_source) {
+    DEBUG_MSG (SUBSET, nullptr, "Preprocessing failed due to subset failure.");
+    return source;
+  }
+
   return new_source;
 }
+
+#ifdef HB_EXPERIMENTAL_API
+/**
+ * hb_subset_input_override_name_table:
+ * @input: a #hb_subset_input_t object.
+ * @name_id: name_id of a nameRecord
+ * @platform_id: platform ID of a nameRecord
+ * @encoding_id: encoding ID of a nameRecord
+ * @language_id: language ID of a nameRecord
+ * @name_str: pointer to name string new value or null to indicate should remove
+ * @str_len: the size of @name_str, or -1 if it is `NULL`-terminated
+ *
+ * Override the name string of the NameRecord identified by name_id,
+ * platform_id, encoding_id and language_id. If a record with that name_id
+ * doesn't exist, create it and insert to the name table.
+ *
+ * Note: for mac platform, we only support name_str with all ascii characters,
+ * name_str with non-ascii characters will be ignored.
+ *
+ * Since: EXPERIMENTAL
+ **/
+HB_EXTERN hb_bool_t
+hb_subset_input_override_name_table (hb_subset_input_t  *input,
+                                     hb_ot_name_id_t     name_id,
+                                     unsigned            platform_id,
+                                     unsigned            encoding_id,
+                                     unsigned            language_id,
+                                     const char         *name_str,
+                                     int                 str_len /* -1 means nul-terminated */)
+{
+  if (!name_str)
+  {
+    str_len = 0;
+  }
+  else if (str_len == -1)
+  {
+      str_len = strlen (name_str);
+  }
+
+  hb_bytes_t name_bytes (nullptr, 0);
+  if (str_len)
+  {
+    if (platform_id == 1)
+    {
+      const uint8_t *src = reinterpret_cast<const uint8_t*> (name_str);
+      const uint8_t *src_end = src + str_len;
+
+      hb_codepoint_t unicode;
+      const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+      while (src < src_end)
+      {
+        src = hb_utf8_t::next (src, src_end, &unicode, replacement);
+        if (unicode >= 0x0080u)
+        {
+          printf ("Non-ascii character detected, ignored...This API supports acsii characters only for mac platform\n");
+          return false;
+        }
+      }
+    }
+    char *override_name = (char *) hb_malloc (str_len);
+    if (unlikely (!override_name)) return false;
+
+    hb_memcpy (override_name, name_str, str_len);
+    name_bytes = hb_bytes_t (override_name, str_len);
+  }
+  input->name_table_overrides->set (hb_ot_name_record_ids_t (platform_id, encoding_id, language_id, name_id), name_bytes);
+  return true;
+}
+
 #endif
diff --git a/src/hb-subset-input.hh b/src/hb-subset-input.hh
index dabb491..ecd47b7 100644
--- a/src/hb-subset-input.hh
+++ b/src/hb-subset-input.hh
@@ -36,6 +36,48 @@
 
 #include "hb-font.hh"
 
+struct hb_ot_name_record_ids_t
+{
+  hb_ot_name_record_ids_t () = default;
+  hb_ot_name_record_ids_t (unsigned platform_id_,
+                           unsigned encoding_id_,
+                           unsigned language_id_,
+                           unsigned name_id_)
+      :platform_id (platform_id_),
+      encoding_id (encoding_id_),
+      language_id (language_id_),
+      name_id (name_id_) {}
+
+  bool operator != (const hb_ot_name_record_ids_t o) const
+  { return !(*this == o); }
+
+  inline bool operator == (const hb_ot_name_record_ids_t& o) const
+  {
+    return platform_id == o.platform_id &&
+           encoding_id == o.encoding_id &&
+           language_id == o.language_id &&
+           name_id == o.name_id;
+  }
+
+  inline uint32_t hash () const
+  {
+    uint32_t current = 0;
+    current = current * 31 + hb_hash (platform_id);
+    current = current * 31 + hb_hash (encoding_id);
+    current = current * 31 + hb_hash (language_id);
+    current = current * 31 + hb_hash (name_id);
+    return current;
+  }
+
+  unsigned platform_id;
+  unsigned encoding_id;
+  unsigned language_id;
+  unsigned name_id;
+};
+
+typedef struct hb_ot_name_record_ids_t hb_ot_name_record_ids_t;
+
+
 HB_MARK_AS_FLAG_T (hb_subset_flags_t);
 
 struct hb_subset_input_t
@@ -60,7 +102,14 @@
 
   unsigned flags;
   bool attach_accelerator_data = false;
+
+  // If set loca format will always be the long version.
+  bool force_long_loca = false;
+
   hb_hashmap_t<hb_tag_t, float> *axes_location;
+#ifdef HB_EXPERIMENTAL_API
+  hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides;
+#endif
 
   inline unsigned num_sets () const
   {
@@ -80,7 +129,11 @@
         return true;
     }
 
-    return axes_location->in_error ();
+    return axes_location->in_error ()
+#ifdef HB_EXPERIMENTAL_API
+	|| name_table_overrides->in_error ()
+#endif
+	;
   }
 };
 
diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index 9cf7c9e..71bc908 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -27,6 +27,7 @@
 #include "hb-subset-plan.hh"
 #include "hb-subset-accelerator.hh"
 #include "hb-map.hh"
+#include "hb-multimap.hh"
 #include "hb-set.hh"
 
 #include "hb-ot-cmap-table.hh"
@@ -47,7 +48,7 @@
 
 typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map;
 #ifndef HB_NO_SUBSET_CFF
-static inline void
+static inline bool
 _add_cff_seac_components (const OT::cff1::accelerator_t &cff,
 			  hb_codepoint_t gid,
 			  hb_set_t *gids_to_retain)
@@ -57,7 +58,9 @@
   {
     gids_to_retain->add (base_gid);
     gids_to_retain->add (accent_gid);
+    return true;
   }
+  return false;
 }
 #endif
 
@@ -82,10 +85,8 @@
 _remap_indexes (const hb_set_t *indexes,
 		hb_map_t       *mapping /* OUT */)
 {
-  unsigned count = indexes->get_population ();
-
-  for (auto _ : + hb_zip (indexes->iter (), hb_range (count)))
-    mapping->set (_.first, _.second);
+  for (auto _ : + hb_enumerate (indexes->iter ()))
+    mapping->set (_.second, _.first);
 
 }
 
@@ -344,7 +345,9 @@
     vars.push (var);
   }
 
+#ifndef HB_NO_VAR
   hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ());
+#endif
   return font;
 }
 
@@ -521,14 +524,44 @@
       cmap_unicodes = &plan->accelerator->unicodes;
     }
 
-    for (hb_codepoint_t cp : *cmap_unicodes)
+    if (plan->accelerator &&
+	unicodes->get_population () < cmap_unicodes->get_population () &&
+	glyphs->get_population () < cmap_unicodes->get_population ())
     {
-      hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
-      if (!unicodes->has (cp) && !glyphs->has (gid))
-        continue;
+      auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes;
+      for (hb_codepoint_t gid : *glyphs)
+      {
+        auto unicodes = gid_to_unicodes.get (gid);
 
-      plan->codepoint_to_glyph->set (cp, gid);
-      plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+	for (hb_codepoint_t cp : unicodes)
+	{
+	  plan->codepoint_to_glyph->set (cp, gid);
+	  plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+	}
+      }
+      for (hb_codepoint_t cp : *unicodes)
+      {
+	/* Don't double-add entry. */
+	if (plan->codepoint_to_glyph->has (cp))
+	  continue;
+
+	hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
+	plan->codepoint_to_glyph->set (cp, gid);
+	plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+      }
+      plan->unicode_to_new_gid_list.qsort ();
+    }
+    else
+    {
+      for (hb_codepoint_t cp : *cmap_unicodes)
+      {
+	hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
+	if (!unicodes->has (cp) && !glyphs->has (gid))
+	  continue;
+
+	plan->codepoint_to_glyph->set (cp, gid);
+	plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+      }
     }
 
     /* Add gids which where requested, but not mapped in cmap */
@@ -639,9 +672,15 @@
   else
     plan->_glyphset->union_ (cur_glyphset);
 #ifndef HB_NO_SUBSET_CFF
-  if (cff.is_valid ())
-    for (hb_codepoint_t gid : cur_glyphset)
-      _add_cff_seac_components (cff, gid, plan->_glyphset);
+  if (!plan->accelerator || plan->accelerator->has_seac)
+  {
+    bool has_seac = false;
+    if (cff.is_valid ())
+      for (hb_codepoint_t gid : cur_glyphset)
+	if (_add_cff_seac_components (cff, gid, plan->_glyphset))
+	  has_seac = true;
+    plan->has_seac = has_seac;
+  }
 #endif
 
   _remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ());
@@ -848,9 +887,28 @@
   plan->check_success (plan->vmtx_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
   plan->check_success (plan->hmtx_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
 
+#ifdef HB_EXPERIMENTAL_API
+  plan->check_success (plan->name_table_overrides = hb_hashmap_create<hb_ot_name_record_ids_t, hb_bytes_t> ());
+  if (plan->name_table_overrides && input->name_table_overrides)
+  {
+    for (auto _ : *input->name_table_overrides)
+    {
+      hb_bytes_t name_bytes = _.second;
+      unsigned len = name_bytes.length;
+      char *name_str = (char *) hb_malloc (len);
+      if (unlikely (!plan->check_success (name_str)))
+        break;
+
+      hb_memcpy (name_str, name_bytes.arrayZ, len);
+      plan->name_table_overrides->set (_.first, hb_bytes_t (name_str, len));
+    }
+  }
+#endif
+
   void* accel = hb_face_get_user_data(face, hb_subset_accelerator_t::user_data_key());
 
   plan->attach_accelerator_data = input->attach_accelerator_data;
+  plan->force_long_loca = input->force_long_loca;
   if (accel)
     plan->accelerator = (hb_subset_accelerator_t*) accel;
 
@@ -893,6 +951,28 @@
     hb_subset_plan_destroy (plan);
     return nullptr;
   }
+
+
+  if (plan->attach_accelerator_data)
+  {
+    hb_multimap_t gid_to_unicodes;
+
+    hb_map_t &unicode_to_gid = *plan->codepoint_to_glyph;
+
+    for (auto unicode : *plan->unicodes)
+    {
+      auto gid = unicode_to_gid[unicode];
+      gid_to_unicodes.add (gid, unicode);
+    }
+
+    plan->inprogress_accelerator =
+      hb_subset_accelerator_t::create (*plan->codepoint_to_glyph,
+				       gid_to_unicodes,
+                                       *plan->unicodes,
+				       plan->has_seac);
+  }
+
+
   return plan;
 }
 
diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh
index 15fabba..1b2aee7 100644
--- a/src/hb-subset-plan.hh
+++ b/src/hb-subset-plan.hh
@@ -87,6 +87,18 @@
     hb_hashmap_destroy (vmtx_map);
     hb_hashmap_destroy (layout_variation_idx_delta_map);
 
+#ifdef HB_EXPERIMENTAL_API
+    if (name_table_overrides)
+    {
+      for (auto _ : *name_table_overrides)
+        _.second.fini ();
+    }
+    hb_hashmap_destroy (name_table_overrides);
+#endif
+
+    if (inprogress_accelerator)
+      hb_subset_accelerator_t::destroy ((void*) inprogress_accelerator);
+
     if (user_axes_location)
     {
       hb_object_destroy (user_axes_location);
@@ -99,10 +111,11 @@
   bool successful;
   unsigned flags;
   bool attach_accelerator_data = false;
+  bool force_long_loca = false;
 
   // For each cp that we'd like to retain maps to the corresponding gid.
   hb_set_t *unicodes;
-  hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> unicode_to_new_gid_list;
+  hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> unicode_to_new_gid_list;
 
   // name_ids we would like to retain
   hb_set_t *name_ids;
@@ -185,31 +198,41 @@
   hb_map_t *axes_old_index_tag_map;
   bool all_axes_pinned;
   bool pinned_at_default;
+  bool has_seac;
 
   //hmtx metrics map: new gid->(advance, lsb)
   hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *hmtx_map;
   //vmtx metrics map: new gid->(advance, lsb)
   hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *vmtx_map;
 
+#ifdef HB_EXPERIMENTAL_API
+  // name table overrides map: hb_ot_name_record_ids_t-> name string new value or
+  // None to indicate should remove
+  hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides;
+#endif
+
   const hb_subset_accelerator_t* accelerator;
+  hb_subset_accelerator_t* inprogress_accelerator;
 
  public:
 
   template<typename T>
   hb_blob_ptr_t<T> source_table()
   {
-    if (sanitized_table_cache
-        && !sanitized_table_cache->in_error ()
-        && sanitized_table_cache->has (T::tableTag)) {
-      return hb_blob_reference (sanitized_table_cache->get (T::tableTag).get ());
+    hb_lock_t (accelerator ? &accelerator->sanitized_table_cache_lock : nullptr);
+
+    auto *cache = accelerator ? &accelerator->sanitized_table_cache : sanitized_table_cache;
+    if (cache
+        && !cache->in_error ()
+        && cache->has (+T::tableTag)) {
+      return hb_blob_reference (cache->get (+T::tableTag).get ());
     }
 
     hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (source)};
     hb_blob_t* ret = hb_blob_reference (table_blob.get ());
 
-    if (likely (sanitized_table_cache))
-      sanitized_table_cache->set (T::tableTag,
-                                  std::move (table_blob));
+    if (likely (cache))
+      cache->set (+T::tableTag, std::move (table_blob));
 
     return ret;
   }
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 6026aa6..186b12d 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -82,6 +82,10 @@
  * retain glyph ids option and configure the subset to pass through the layout tables untouched.
  */
 
+
+hb_user_data_key_t _hb_subset_accelerator_user_data_key = {};
+
+
 /*
  * The list of tables in the open type spec. Used to check for tables that may need handling
  * if we are unable to list the tables in a face.
@@ -409,20 +413,14 @@
 
 static bool
 _dependencies_satisfied (hb_subset_plan_t *plan, hb_tag_t tag,
-                         hb_set_t &visited_set, hb_set_t &revisit_set)
+                         const hb_set_t &subsetted_tags,
+                         const hb_set_t &pending_subset_tags)
 {
   switch (tag)
   {
   case HB_OT_TAG_hmtx:
   case HB_OT_TAG_vmtx:
-    if (!plan->pinned_at_default &&
-        !visited_set.has (HB_OT_TAG_glyf))
-    {
-      revisit_set.add (tag);
-      return false;
-    }
-    return true;
-
+    return plan->pinned_at_default || !pending_subset_tags.has (HB_OT_TAG_glyf);
   default:
     return true;
   }
@@ -495,12 +493,14 @@
   }
 }
 
-static void _attach_accelerator_data (const hb_subset_plan_t* plan,
+static void _attach_accelerator_data (hb_subset_plan_t* plan,
                                       hb_face_t* face /* IN/OUT */)
 {
-  hb_subset_accelerator_t* accel =
-      hb_subset_accelerator_t::create (*plan->codepoint_to_glyph,
-                                       *plan->unicodes);
+  if (!plan->inprogress_accelerator) return;
+
+  // Transfer the accelerator from the plan to us.
+  hb_subset_accelerator_t* accel = plan->inprogress_accelerator;
+  plan->inprogress_accelerator = nullptr;
 
   if (accel->in_error ())
   {
@@ -508,6 +508,11 @@
     return;
   }
 
+  // Populate caches that need access to the final tables.
+  hb_blob_ptr_t<OT::cmap> cmap_ptr (hb_sanitize_context_t ().reference_table<OT::cmap> (face));
+  accel->cmap_cache = OT::cmap::create_filled_cache (cmap_ptr);
+  accel->destroy_cmap_cache = OT::SubtableUnicodesCache::destroy;
+
   if (!hb_face_set_user_data(face,
                              hb_subset_accelerator_t::user_data_key(),
                              accel,
@@ -561,41 +566,63 @@
     return nullptr;
   }
 
-  hb_set_t tags_set, revisit_set;
-  bool success = true;
   hb_tag_t table_tags[32];
   unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
-  hb_vector_t<char> buf;
-  buf.alloc (4096 - 16);
 
+  hb_set_t subsetted_tags, pending_subset_tags;
   while (((void) _get_table_tags (plan, offset, &num_tables, table_tags), num_tables))
   {
     for (unsigned i = 0; i < num_tables; ++i)
     {
       hb_tag_t tag = table_tags[i];
-      if (_should_drop_table (plan, tag) && !tags_set.has (tag)) continue;
-      if (!_dependencies_satisfied (plan, tag, tags_set, revisit_set)) continue;
-      tags_set.add (tag);
+      if (_should_drop_table (plan, tag)) continue;
+      pending_subset_tags.add (tag);
+    }
+
+    offset += num_tables;
+  }
+
+  hb_vector_t<char> buf;
+  buf.alloc (4096 - 16);
+
+
+  bool success = true;
+
+  while (!pending_subset_tags.is_empty ())
+  {
+    if (subsetted_tags.in_error ()
+        || pending_subset_tags.in_error ()) {
+      success = false;
+      goto end;
+    }
+
+    bool made_changes = false;
+    for (hb_tag_t tag : pending_subset_tags)
+    {
+      if (!_dependencies_satisfied (plan, tag,
+                                    subsetted_tags,
+                                    pending_subset_tags))
+      {
+        // delayed subsetting for some tables since they might have dependency on other tables
+        // in some cases: e.g: during instantiating glyf tables, hmetrics/vmetrics are updated
+        // and saved in subset plan, hmtx/vmtx subsetting need to use these updated metrics values
+        continue;
+      }
+
+      pending_subset_tags.del (tag);
+      subsetted_tags.add (tag);
+      made_changes = true;
+
       success = _subset_table (plan, buf, tag);
       if (unlikely (!success)) goto end;
     }
 
-    /*delayed subsetting for some tables since they might have dependency on other tables in some cases:
-    e.g: during instantiating glyf tables, hmetrics/vmetrics are updated and saved in subset plan,
-    hmtx/vmtx subsetting need to use these updated metrics values*/
-    while (!revisit_set.is_empty ())
+    if (!made_changes)
     {
-      hb_set_t revisit_temp;
-      for (hb_tag_t tag : revisit_set)
-      {
-        if (!_dependencies_satisfied (plan, tag, tags_set, revisit_temp)) continue;
-        tags_set.add (tag);
-        success = _subset_table (plan, buf, tag);
-        if (unlikely (!success)) goto end;
-      }
-      revisit_set = revisit_temp;
+      DEBUG_MSG (SUBSET, nullptr, "Table dependencies unable to be satisfied. Subset failed.");
+      success = false;
+      goto end;
     }
-    offset += num_tables;
   }
 
   if (success && plan->attach_accelerator_data) {
diff --git a/src/hb-subset.h b/src/hb-subset.h
index 6a2c5f6..b83264e 100644
--- a/src/hb-subset.h
+++ b/src/hb-subset.h
@@ -28,6 +28,7 @@
 #define HB_SUBSET_H
 
 #include "hb.h"
+#include "hb-ot.h"
 
 HB_BEGIN_DECLS
 
@@ -164,8 +165,6 @@
 hb_subset_input_set_flags (hb_subset_input_t *input,
 			   unsigned value);
 
-#ifdef HB_EXPERIMENTAL_API
-#ifndef HB_NO_VAR
 HB_EXTERN hb_bool_t
 hb_subset_input_pin_axis_to_default (hb_subset_input_t  *input,
 				     hb_face_t          *face,
@@ -176,16 +175,22 @@
 				   hb_face_t          *face,
 				   hb_tag_t            axis_tag,
 				   float               axis_value);
-#endif
-#endif
 
 #ifdef HB_EXPERIMENTAL_API
+HB_EXTERN hb_bool_t
+hb_subset_input_override_name_table (hb_subset_input_t  *input,
+				     hb_ot_name_id_t     name_id,
+				     unsigned            platform_id,
+				     unsigned            encoding_id,
+				     unsigned            language_id,
+				     const char         *name_str,
+				     int                 str_len);
+
+#endif
 
 HB_EXTERN hb_face_t *
 hb_subset_preprocess (hb_face_t *source);
 
-#endif
-
 HB_EXTERN hb_face_t *
 hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input);
 
diff --git a/src/hb-ucd-table.hh b/src/hb-ucd-table.hh
index a372a4a..f7d76ee 100644
--- a/src/hb-ucd-table.hh
+++ b/src/hb-ucd-table.hh
@@ -1069,1791 +1069,6 @@
 #ifndef HB_OPTIMIZE_SIZE
 
 static const uint8_t
-_hb_ucd_u8[18260] =
-{
-    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,
-    7,  7,  7,  7,  9, 10,  7,  7,  7,  7, 11, 12, 13, 13, 13, 14,
-   15, 16, 17, 18, 19, 20, 21, 22, 23, 22, 22, 22, 22, 24,  7,  7,
-   25, 26, 22, 22, 22, 27, 28, 29, 22, 30, 31, 32, 33, 34, 35, 36,
-    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-    7,  7,  7,  7, 37,  7, 38, 39,  7, 40,  7,  7,  7, 41, 22, 42,
-    7,  7, 43,  7, 44, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   45, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 46,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 47,
-    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
-   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-   32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43,
-   44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
-   60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73,
-   69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83,
-   84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34,
-   91, 34, 34, 34, 34, 34, 34, 34, 34, 92, 34, 34, 93, 94, 95, 96,
-   97, 98, 99,100,101,102,103,104, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,105,
-  106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
-  107,107, 34, 34,108,109,110,111, 34, 34,112,113,114,115,116,117,
-  118,119,120,121,122,123,124,125,126,127,128,129, 34, 34,130,131,
-  132,133,134,135,136,137,138,139,140,141,142,122,143,144,145,146,
-  147,148,149,150,151,152,153,122,154,155,122,156,157,158,159,122,
-  160,161,162,163,164,165,166,122,167,168,169,170,122,171,172,173,
-   34, 34, 34, 34, 34, 34, 34,174,175, 34,176,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,177,
-   34, 34, 34, 34, 34, 34, 34, 34,178,122,122,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,
-  122,122,122,122,122,122,122,122, 34, 34, 34, 34,179,122,122,122,
-   34, 34, 34, 34,180,181,182,183,122,122,122,122,184,185,186,187,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,188,
-   34, 34, 34, 34, 34, 34, 34, 34, 34,189,190,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,191,
-   34, 34,192, 34, 34,193,122,122,122,122,122,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,194,195,122,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,196,197,
-   69,198,199,200,201,202,203,122,204,205,206,207,208,209,210,211,
-   69, 69, 69, 69,212,213,122,122,122,122,122,122,122,122,214,122,
-  215,216,217,122,122,218,122,122,122,219,122,122,122,122,122,220,
-   34,221,222,122,122,122,122,122,223,224,225,122,226,227,122,122,
-  228,229,230,231,232,122, 69,233, 69, 69, 69, 69, 69,234,235,236,
-  237,238, 69, 69,239,240, 69,241,122,122,122,122,122,122,122,122,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,242, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,243, 34,
-  244, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,245, 34, 34,
-   34, 34, 34, 34, 34, 34, 34,246,122,122,122,122,122,122,122,122,
-   34, 34, 34, 34,247,122,122,122,122,122,122,122,122,122,122,122,
-   34, 34, 34, 34, 34, 34,248, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34,249,122,122,122,122,122,122,122,122,
-  250,122,251,252,122,122,122,122,122,122,122,122,122,122,122,122,
-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,253,
-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,254,
-    0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  2,  4,  5,  6,  2,
-    7,  7,  7,  7,  7,  2,  8,  9, 10, 11, 11, 11, 11, 11, 11, 11,
-   11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
-   16, 16, 16, 16, 16, 17, 18, 19,  1, 20, 20, 21, 22, 23, 24, 25,
-   26, 27, 15,  2, 28, 29, 27, 30, 11, 11, 11, 11, 11, 11, 11, 11,
-   11, 11, 11, 31, 11, 11, 11, 32, 16, 16, 16, 16, 16, 16, 16, 16,
-   16, 16, 16, 33, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32,
-   32, 32, 32, 32, 34, 34, 34, 34, 34, 34, 34, 34, 16, 32, 32, 32,
-   32, 32, 32, 32, 11, 34, 34, 16, 34, 32, 32, 11, 34, 11, 16, 11,
-   11, 34, 32, 11, 32, 16, 11, 34, 32, 32, 32, 11, 34, 16, 32, 11,
-   34, 11, 34, 34, 32, 35, 32, 16, 36, 36, 37, 34, 38, 37, 34, 34,
-   34, 34, 34, 34, 34, 34, 16, 32, 34, 38, 32, 11, 32, 32, 32, 32,
-   32, 32, 16, 16, 16, 11, 34, 32, 34, 34, 11, 32, 32, 32, 32, 32,
-   16, 16, 39, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 40,
-   40, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41,
-   40, 40, 42, 41, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41,
-   43, 43, 43, 43, 43, 43, 43, 43, 32, 32, 42, 32, 44, 45, 16, 10,
-   44, 44, 41, 46, 11, 47, 47, 11, 34, 11, 11, 11, 11, 11, 11, 11,
-   11, 48, 11, 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 34,
-   16, 11, 32, 16, 32, 32, 32, 32, 16, 16, 32, 49, 34, 32, 34, 11,
-   32, 50, 43, 43, 51, 32, 32, 32, 11, 34, 34, 34, 34, 34, 34, 16,
-   48, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 47, 52,  2,  2,  2,
-   16, 16, 16, 16, 53, 54, 55, 56, 57, 43, 43, 43, 43, 43, 43, 43,
-   43, 43, 43, 43, 43, 43, 43, 58, 59, 60, 43, 59, 44, 44, 44, 44,
-   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 62,
-   36, 63, 64, 44, 44, 44, 44, 44, 65, 65, 65,  8,  9, 66,  2, 67,
-   43, 43, 43, 43, 43, 60, 68,  2, 69, 36, 36, 36, 36, 70, 43, 43,
-    7,  7,  7,  7,  7,  2,  2, 36, 71, 36, 36, 36, 36, 36, 36, 36,
-   36, 36, 72, 43, 43, 43, 73, 50, 43, 43, 74, 75, 76, 43, 43, 36,
-    7,  7,  7,  7,  7, 36, 77, 78,  2,  2,  2,  2,  2,  2,  2, 79,
-   70, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 80, 62, 36,
-   36, 36, 36, 43, 43, 43, 43, 43, 71, 44, 44, 44, 44, 44, 44, 44,
-    7,  7,  7,  7,  7, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43,
-   43, 43, 40, 21,  2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43,
-   43, 43, 75, 43, 75, 43, 43, 44,  2,  2,  2,  2,  2,  2,  2, 64,
-   36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44,
-   36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 44, 43, 43, 43, 43,
-   36, 36, 36, 36, 83, 43, 43, 43, 43, 84, 43, 43, 43, 43, 43, 43,
-   43, 85, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 85, 71, 86,
-   87, 43, 43, 43, 85, 86, 87, 86, 70, 43, 43, 43, 36, 36, 36, 36,
-   36, 43,  2,  7,  7,  7,  7,  7, 88, 36, 36, 36, 36, 36, 36, 36,
-   70, 86, 62, 36, 36, 36, 61, 62, 61, 62, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 61, 36, 36, 36, 61, 61, 44, 36, 36, 44, 71, 86,
-   87, 43, 80, 89, 90, 89, 87, 61, 44, 44, 44, 89, 44, 44, 36, 62,
-   36, 43, 44,  7,  7,  7,  7,  7, 36, 20, 27, 27, 27, 56, 63, 80,
-   57, 85, 62, 36, 36, 61, 44, 62, 61, 36, 62, 61, 36, 44, 80, 86,
-   87, 80, 44, 57, 80, 57, 43, 44, 57, 44, 44, 44, 62, 36, 61, 61,
-   44, 44, 44,  7,  7,  7,  7,  7, 43, 36, 70, 64, 44, 44, 44, 44,
-   57, 85, 62, 36, 36, 36, 36, 62, 36, 62, 36, 36, 36, 36, 36, 36,
-   61, 36, 62, 36, 36, 44, 71, 86, 87, 43, 43, 57, 85, 89, 87, 44,
-   61, 44, 44, 44, 44, 44, 44, 44, 66, 44, 44, 44, 62, 43, 43, 43,
-   57, 86, 62, 36, 36, 36, 61, 62, 61, 36, 62, 36, 36, 44, 71, 87,
-   87, 43, 80, 89, 90, 89, 87, 44, 44, 44, 57, 85, 44, 44, 36, 62,
-   78, 27, 27, 27, 44, 44, 44, 44, 44, 71, 62, 36, 36, 61, 44, 36,
-   61, 36, 36, 44, 62, 61, 61, 36, 44, 62, 61, 44, 36, 61, 44, 36,
-   36, 36, 36, 36, 36, 44, 44, 86, 85, 90, 44, 86, 90, 86, 87, 44,
-   61, 44, 44, 89, 44, 44, 44, 44, 27, 91, 67, 67, 56, 92, 44, 44,
-   85, 86, 71, 36, 36, 36, 61, 36, 61, 36, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 36, 44, 71, 43, 85, 86, 90, 43, 80, 43, 43, 44,
-   44, 44, 57, 80, 36, 61, 62, 44, 44, 44, 44, 93, 27, 27, 27, 91,
-   70, 86, 72, 36, 36, 36, 61, 36, 36, 36, 62, 36, 36, 44, 71, 87,
-   86, 86, 90, 85, 90, 86, 43, 44, 44, 44, 89, 90, 44, 44, 62, 61,
-   62, 94, 44, 44, 44, 44, 44, 44, 43, 86, 36, 36, 36, 36, 61, 36,
-   36, 36, 36, 36, 36, 70, 71, 86, 87, 43, 80, 86, 90, 86, 87, 77,
-   44, 44, 36, 94, 27, 27, 27, 95, 27, 27, 27, 27, 91, 36, 36, 36,
-   57, 86, 62, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 36, 36, 36,
-   36, 62, 36, 36, 36, 36, 62, 44, 36, 36, 36, 61, 44, 80, 44, 89,
-   86, 43, 80, 80, 86, 86, 86, 86, 44, 86, 64, 44, 44, 44, 44, 44,
-   62, 36, 36, 36, 36, 36, 36, 36, 70, 36, 43, 43, 43, 80, 44, 96,
-   36, 36, 36, 75, 43, 43, 43, 60,  7,  7,  7,  7,  7,  2, 44, 44,
-   44, 44, 44, 44, 44, 44, 44, 44, 62, 61, 61, 36, 36, 61, 36, 36,
-   36, 36, 62, 62, 36, 36, 36, 36, 70, 36, 43, 43, 43, 43, 71, 44,
-   36, 36, 61, 81, 43, 43, 43, 80,  7,  7,  7,  7,  7, 44, 36, 36,
-   77, 67,  2,  2,  2,  2,  2,  2,  2, 97, 97, 67, 43, 67, 67, 67,
-    7,  7,  7,  7,  7, 27, 27, 27, 27, 27, 50, 50, 50,  4,  4, 86,
-   36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44,
-   57, 43, 43, 43, 43, 43, 43, 85, 43, 43, 60, 43, 36, 36, 70, 43,
-   43, 43, 43, 43, 57, 43, 43, 43, 43, 43, 43, 43, 43, 43, 80, 67,
-   67, 67, 67, 76, 67, 67, 92, 67,  2,  2, 97, 67, 21, 64, 44, 44,
-   36, 36, 36, 36, 36, 94, 87, 43, 85, 43, 43, 43, 87, 85, 87, 71,
-    7,  7,  7,  7,  7,  2,  2,  2, 36, 36, 36, 86, 43, 36, 36, 43,
-   71, 86, 98, 94, 86, 86, 86, 36, 70, 43, 71, 36, 36, 36, 36, 36,
-   36, 85, 87, 85, 86, 86, 87, 94,  7,  7,  7,  7,  7, 86, 87, 67,
-   11, 11, 11, 48, 44, 44, 48, 44, 16, 16, 16, 16, 16, 53, 45, 16,
-   36, 36, 36, 36, 61, 36, 36, 44, 36, 36, 36, 61, 61, 36, 36, 44,
-   61, 36, 36, 44, 36, 36, 36, 61, 61, 36, 36, 44, 36, 36, 36, 36,
-   36, 36, 36, 61, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 57, 43,
-    2,  2,  2,  2, 99, 27, 27, 27, 27, 27, 27, 27, 27, 27,100, 44,
-   67, 67, 67, 67, 67, 44, 44, 44, 11, 11, 11, 44, 16, 16, 16, 44,
-  101, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 77, 72,
-  102, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,103,104, 44,
-   36, 36, 36, 36, 36, 63,  2,105,106, 36, 36, 36, 61, 44, 44, 44,
-   36, 43, 85, 44, 44, 44, 44, 62, 36, 43,107, 64, 44, 44, 44, 44,
-   36, 43, 44, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 61, 36,
-   61, 43, 44, 44, 44, 44, 44, 44, 36, 36, 43, 87, 43, 43, 43, 86,
-   86, 86, 86, 85, 87, 43, 43, 43, 43, 43,  2, 88,  2, 66, 70, 44,
-    7,  7,  7,  7,  7, 44, 44, 44, 27, 27, 27, 27, 27, 44, 44, 44,
-    2,  2,  2,108,  2, 59, 43, 84, 36, 83, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 61, 44, 44, 44, 36, 36, 70, 71, 36, 36, 36, 36,
-   36, 36, 36, 36, 70, 61, 44, 44, 36, 36, 36, 44, 44, 44, 44, 44,
-   36, 36, 36, 36, 36, 36, 36, 61, 43, 85, 86, 87, 85, 86, 44, 44,
-   86, 85, 86, 86, 87, 43, 44, 44, 92, 44,  2,  7,  7,  7,  7,  7,
-   36, 36, 36, 36, 36, 36, 36, 44, 36, 36, 61, 44, 44, 44, 44, 44,
-   36, 36, 36, 36, 36, 36, 44, 44, 36, 36, 36, 36, 36, 44, 44, 44,
-    7,  7,  7,  7,  7,100, 44, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-   36, 36, 36, 70, 85, 87, 44,  2, 36, 36, 94, 85, 43, 43, 43, 80,
-   85, 85, 87, 43, 43, 43, 85, 86, 86, 87, 43, 43, 43, 43, 80, 57,
-    2,  2,  2, 88,  2,  2,  2, 44, 43, 43, 43, 43, 43, 43, 43,109,
-   43, 43, 43, 43, 43, 43, 43, 80, 43, 43, 98, 36, 36, 36, 36, 36,
-   36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 44,
-   97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 64,
-   43, 98, 36, 36, 36, 36, 36, 36, 94, 43, 43, 86, 43, 87, 43, 36,
-   36, 36, 36, 85, 43, 86, 87, 87, 43, 86, 44, 44, 44, 44,  2,  2,
-   36, 36, 86, 86, 86, 86, 43, 43, 43, 43, 86, 43, 44, 93,  2,  2,
-    7,  7,  7,  7,  7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40,  2,
-   16, 16, 16, 16,110, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
-    2,  2,  2,  2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43,
-   85, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 94, 43, 61, 44, 44,
-   16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16,
-   16, 16, 16, 16, 45, 16, 16, 16, 16, 16, 16, 16, 16,111, 40, 40,
-   32, 32, 32, 16, 16, 16, 16, 32, 16, 16, 16, 16, 11, 11, 11, 11,
-   16, 16, 16, 44, 11, 11, 11, 44, 16, 16, 16, 16, 48, 48, 48, 48,
-   16, 16, 16, 16, 16, 16, 16, 44, 16, 16, 16, 16,112,112,112,112,
-   16, 16,110, 16, 11, 11,113,114, 41, 16,110, 16, 11, 11,113, 41,
-   16, 16, 44, 16, 11, 11,115, 41, 16, 16, 16, 16, 11, 11,116, 41,
-   44, 16,110, 16, 11, 11,113,117,118,118,118,118,118,119, 65, 65,
-  120,120,120,  2,121,122,121,122,  2,  2,  2,  2,123, 65, 65,124,
-    2,  2,  2,  2,125,126,  2,127,128,  2,129,130,  2,  2,  2,  2,
-    2,  9,128,  2,  2,  2,  2,131, 65, 65,132, 65, 65, 65, 65, 65,
-  133, 44, 27, 27, 27,  8,129,134, 27, 27, 27, 27, 27,  8,129,104,
-   40, 40, 40, 40, 40, 40, 81, 44, 20, 20, 20, 20, 20, 20, 20, 20,
-  135, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43,136, 51,
-  109, 51,109, 43, 43, 43, 43, 43, 80, 44, 44, 44, 44, 44, 44, 44,
-   67,137, 67,138, 67, 34, 11, 16, 11, 32,138, 67, 49, 11, 11, 67,
-   67, 67,137,137,137, 11, 11,139, 11, 11, 35, 36, 39, 67, 16, 11,
-    8,  8, 49, 16, 16, 26, 67,140, 27, 27, 27, 27, 27, 27, 27, 27,
-  105,105,105,105,105,105,105,105,105,141,142,105,143, 67, 44, 44,
-    8,  8,144, 67, 67,  8, 67, 67,144, 26, 67,144, 67, 67, 67,144,
-   67, 67, 67, 67, 67, 67, 67,  8, 67,144,144, 67, 67, 67, 67, 67,
-   67, 67,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-   67, 67, 67, 67,  4,  4, 67, 67,  8, 67, 67, 67,145,146, 67, 67,
-   67, 67, 67, 67, 67, 67,144, 67, 67, 67, 67, 67, 67, 26,  8,  8,
-    8,  8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,
-    8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44,
-   67, 67, 67, 67, 67, 92, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67,
-   67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67,
-   26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,  8,  8,
-   67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67,  4,  4,  4,  4,
-    4,  4,  4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67,
-    8,  8,129,147,  8,  8,  8,  8,  8,  8,  8,  4,  4,  4,  4,  4,
-    8,129,148,148,148,148,148,148,148,148,148,148,147,  8,  8,  8,
-    8,  8,  8,  8,  4,  4,  8,  8,  8,  8,  8,  8,  8,  8,  4,  8,
-    8,  8,144, 26,  8,  8,144, 67, 67, 67, 44, 67, 67, 67, 67, 67,
-   67, 67, 67, 55, 67, 67, 67, 67, 32, 11, 32, 34, 34, 34, 34, 11,
-   32, 32, 34, 16, 16, 16, 40, 11, 32, 32,140, 67, 67,138, 34,149,
-   43, 32, 44, 44, 93,  2, 99,  2, 16, 16, 16,150, 44, 44,150, 44,
-   36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57,
-   36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61,
-    2,121,121,  2,125,126,121,  2,  2,  2,  2,  6,  2,108,121,  2,
-  121,  4,  4,  4,  4,  2,  2, 88,  2,  2,  2,  2,  2,120,  2,  2,
-  108,151,  2,  2,  2,  2,  2,  2, 67,  2,152,148,148,148,153, 44,
-   67, 67, 67, 67, 67, 55, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44,
-   67, 67, 67, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 44, 44,
-    1,  2,154,155,  4,  4,  4,  4,  4, 67,  4,  4,  4,  4,156,157,
-  158,105,105,105,105, 43, 43, 86,159, 40, 40, 67,105,160, 63, 67,
-   36, 36, 36, 61, 57,161,162, 69, 36, 36, 36, 36, 36, 63, 40, 69,
-   44, 44, 62, 36, 36, 36, 36, 36, 67, 27, 27, 67, 67, 67, 67, 67,
-   67, 67, 67, 67, 67, 67, 67, 92, 27, 27, 27, 27, 27, 67, 67, 67,
-   67, 67, 67, 67, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27,
-   36, 36, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,164,  2,
-    7,  7,  7,  7,  7, 36, 44, 44, 32, 32, 32, 32, 32, 32, 32, 70,
-   51,165, 43, 43, 43, 43, 43, 88, 32, 32, 32, 32, 32, 32, 40, 43,
-   36, 36, 36,105,105,105,105,105, 43,  2,  2,  2, 44, 44, 44, 44,
-   41, 41, 41,162, 40, 40, 40, 40, 41, 32, 32, 32, 32, 32, 32, 32,
-   16, 32, 32, 32, 32, 32, 32, 32, 45, 16, 16, 16, 34, 34, 34, 32,
-   32, 32, 32, 32, 42,166, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32,
-   32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32,
-   32, 32, 11, 11, 34,110, 44, 44, 32,150,150, 32, 32, 44, 44, 44,
-   44, 40,167, 35, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36,
-   36, 94, 87, 85, 67, 67, 80, 44, 27, 27, 27, 67,168, 44, 44, 44,
-   36, 36,  2,  2, 44, 44, 44, 44, 86, 36, 36, 36, 36, 36, 36, 36,
-   36, 36, 86, 86, 86, 86, 86, 86, 86, 86, 43, 44, 44, 44, 44,  2,
-   43, 36, 36, 36,  2, 72, 72, 70, 36, 36, 36, 43, 43, 43, 43,  2,
-   36, 36, 36, 70, 43, 43, 43, 43, 43, 86, 44, 44, 44, 44, 44, 93,
-   36, 70, 86, 43, 43, 86, 43, 86,107,  2,  2,  2,  2,  2,  2, 52,
-    7,  7,  7,  7,  7, 44, 44,  2, 36, 36, 70, 69, 36, 36, 36, 36,
-    7,  7,  7,  7,  7, 36, 36, 61, 36, 36, 36, 36, 70, 43, 43, 85,
-   87, 85, 87, 80, 44, 44, 44, 44, 36, 70, 36, 36, 36, 36, 85, 44,
-    7,  7,  7,  7,  7, 44,  2,  2, 69, 36, 36, 77, 67, 94, 85, 36,
-   71, 43, 71, 70, 71, 36, 36, 43, 70, 61, 44, 44, 44, 44, 44, 44,
-   44, 44, 44, 44, 44, 62, 83,  2, 36, 36, 36, 36, 36, 94, 43, 86,
-    2, 83,169, 80, 44, 44, 44, 44, 62, 36, 36, 61, 62, 36, 36, 61,
-   62, 36, 36, 61, 44, 44, 44, 44, 16, 16, 16, 16, 16,114, 40, 40,
-   16, 16, 16, 16,111, 41, 44, 44, 36, 94, 87, 86, 85,107, 87, 44,
-   36, 36, 44, 44, 44, 44, 44, 44, 36, 36, 36, 61, 44, 62, 36, 36,
-  170,170,170,170,170,170,170,170,171,171,171,171,171,171,171,171,
-   16, 16, 16,110, 44, 44, 44, 44, 44,150, 16, 16, 44, 44, 62, 71,
-   36, 36, 36, 36,172, 36, 36, 36, 36, 36, 36, 61, 36, 36, 61, 61,
-   36, 62, 61, 36, 36, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41,
-   41,117, 44, 44, 44, 44, 44, 44, 44, 62, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 36, 36, 36,148, 44, 36, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 44, 44, 44, 55, 36, 36, 36, 36, 36, 36,168, 67,
-    2,  2,  2,152,130, 44, 44, 44,  6,173,174,148,148,148,148,148,
-  148,148,130,152,130,  2,127,175,  2, 64,  2,  2,156,148,148,130,
-    2,176,  8,177, 66,  2, 44, 44, 36, 36, 61, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 36, 36, 61, 79, 93,  2,  3,  2,  4,  5,  6,  2,
-   16, 16, 16, 16, 16, 17, 18,129,130,  4,  2, 36, 36, 36, 36, 36,
-   69, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 40,
-   44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 61, 44,
-   20,178, 56,135, 26,  8,144, 92, 44, 44, 44, 44, 79, 65, 67, 44,
-   36, 36, 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 61, 36, 62,
-    2, 64, 44,179, 27, 27, 27, 27, 27, 27, 44, 55, 67, 67, 67, 67,
-  105,105,143, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 27, 67, 92,
-   67, 67, 67, 67, 67, 67, 92, 44, 92, 44, 44, 44, 44, 44, 44, 44,
-   67, 67, 67, 67, 67, 67, 50, 44,180, 27, 27, 27, 27, 27, 27, 27,
-   27, 27, 27, 27, 27, 27, 44, 44, 27, 27, 44, 44, 44, 44, 62, 36,
-  155, 36, 36, 36, 36,181, 44, 44, 36, 36, 36, 43, 43, 80, 44, 44,
-   36, 36, 36, 36, 36, 36, 36, 93, 36, 36, 44, 44, 36, 36, 36, 36,
-  182,105,105, 44, 44, 44, 44, 44, 11, 11, 11, 11, 16, 16, 16, 16,
-   11, 11, 44, 44, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 44, 44,
-   36, 36, 36, 36, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44, 44, 93,
-   11, 11, 11, 11, 11, 47, 11, 11, 11, 47, 11,150, 16, 16, 16, 16,
-   16,150, 16, 16, 16, 16, 16, 16, 16,150, 16, 16, 16,150,110, 44,
-   40, 40, 40, 52, 40, 40, 40, 40, 81, 40, 40, 40, 40, 81, 44, 44,
-   36, 36, 36, 44, 61, 36, 36, 36, 36, 36, 36, 62, 61, 44, 61, 62,
-   36, 36, 36, 93, 27, 27, 27, 27, 36, 36, 36, 77,163, 27, 27, 27,
-   44, 44, 44,179, 27, 27, 27, 27, 36, 61, 36, 44, 44,179, 27, 27,
-   36, 36, 36, 27, 27, 27, 44, 93, 36, 36, 36, 36, 36, 44, 44, 93,
-   36, 36, 36, 36, 44, 44, 27, 36, 44, 27, 27, 27, 27, 27, 27, 27,
-   70, 43, 57, 80, 44, 44, 43, 43, 36, 36, 62, 36, 62, 36, 36, 36,
-   36, 36, 36, 44, 43, 80, 44, 57, 27, 27, 27, 27,100, 44, 44, 44,
-    2,  2,  2,  2, 64, 44, 44, 44, 36, 36, 36, 36, 36, 36,183, 30,
-   36, 36, 36, 36, 36, 36,183, 27, 36, 36, 36, 36, 78, 36, 36, 36,
-   36, 36, 70, 80, 44,179, 27, 27,  2,  2,  2, 64, 44, 44, 44, 44,
-   36, 36, 36, 44, 93,  2,  2,  2, 36, 36, 36, 44, 27, 27, 27, 27,
-   36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 93,  2, 64, 44,
-   44, 44, 44, 44,179, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44,
-   16,110, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44,
-   27, 27, 27, 27, 27, 27, 27,100, 36, 36, 36, 36, 36, 57,184, 44,
-   36, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 57, 43,
-   27, 27, 27, 95, 44, 44, 44, 44,180, 27, 30,  2,  2, 44, 44, 44,
-   36, 43, 43,  2,  2, 44, 44, 44, 36, 36,183, 27, 27, 27, 44, 44,
-   87, 98, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43,
-   43, 43, 43, 60,  2,  2,  2, 44, 27, 27, 27,  7,  7,  7,  7,  7,
-   71, 70, 71, 44, 44, 44, 44, 57, 86, 87, 43, 85, 87, 60,185,  2,
-    2, 80, 44, 44, 44, 44, 79, 44, 43, 71, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 70, 43, 43, 87, 43, 43, 43, 80,  7,  7,  7,  7,  7,
-    2,  2, 94, 98, 44, 44, 44, 44, 36, 70,  2, 61, 44, 44, 44, 44,
-   36, 94, 86, 43, 43, 43, 43, 85, 98, 36, 63,  2, 59, 43, 60, 87,
-    7,  7,  7,  7,  7, 63, 63,  2,179, 27, 27, 27, 27, 27, 27, 27,
-   27, 27,100, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 86, 87,
-   43, 86, 85, 43,  2,  2,  2, 71, 70, 44, 44, 44, 44, 44, 44, 44,
-   36, 36, 36, 61, 61, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 62,
-   36, 36, 36, 36, 63, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 70,
-   86, 87, 43, 43, 43, 80, 44, 44, 43, 86, 62, 36, 36, 36, 61, 62,
-   61, 36, 62, 36, 36, 57, 71, 86, 85, 86, 90, 89, 90, 89, 86, 44,
-   61, 44, 44, 89, 44, 44, 62, 36, 36, 86, 44, 43, 43, 43, 80, 44,
-   43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 94, 86, 43, 43, 43, 43,
-   86, 43, 85, 71, 36, 63,  2,  2,  7,  7,  7,  7,  7,  2, 93, 71,
-   86, 87, 43, 43, 85, 85, 86, 87, 85, 43, 36, 72, 44, 44, 44, 44,
-   36, 36, 36, 36, 36, 36, 36, 94, 86, 43, 43, 44, 86, 86, 43, 87,
-   60,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 43, 44,
-   86, 87, 43, 43, 43, 85, 87, 87, 60,  2, 61, 44, 44, 44, 44, 44,
-    2,  2,  2,  2,  2,  2, 64, 44, 36, 36, 36, 36, 36, 70, 87, 86,
-   43, 43, 43, 87, 63, 44, 44, 44, 86, 43, 43, 87, 43, 43, 44, 44,
-    7,  7,  7,  7,  7, 27,  2, 97, 43, 43, 43, 43, 87, 60, 44, 44,
-   27,100, 44, 44, 44, 44, 44, 62, 36, 36, 36, 61, 62, 44, 36, 36,
-   36, 36, 62, 61, 36, 36, 36, 36, 86, 86, 86, 89, 90, 57, 85, 71,
-   98, 87,  2, 64, 44, 44, 44, 44, 36, 36, 36, 36, 44, 36, 36, 36,
-   94, 86, 43, 43, 44, 43, 86, 86, 71, 72, 90, 44, 44, 44, 44, 44,
-   70, 43, 43, 43, 43, 71, 36, 36, 36, 70, 43, 43, 85, 70, 43, 60,
-    2,  2,  2, 59, 44, 44, 44, 44, 70, 43, 43, 85, 87, 43, 36, 36,
-   36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 85, 43,  2, 72,  2,
-    2, 64, 44, 44, 44, 44, 44, 44,  2,  2,  2,  2,  2, 44, 44, 44,
-   43, 43, 43, 80, 43, 43, 43, 87, 63,  2,  2, 44, 44, 44, 44, 44,
-    2, 36, 36, 36, 36, 36, 36, 36, 44, 43, 43, 43, 43, 43, 43, 43,
-   43, 43, 43, 43, 89, 43, 43, 43, 85, 43, 87, 80, 44, 44, 44, 44,
-   36, 36, 36, 61, 36, 62, 36, 36, 70, 43, 43, 80, 44, 80, 43, 57,
-   43, 43, 43, 70, 44, 44, 44, 44, 36, 36, 36, 62, 61, 36, 36, 36,
-   36, 36, 36, 36, 36, 86, 86, 90, 43, 89, 87, 87, 61, 44, 44, 44,
-   36, 70, 85,107, 64, 44, 44, 44, 43, 94, 36, 36, 36, 36, 36, 36,
-   36, 36, 86, 43, 43, 80, 44, 86, 85, 60,  2,  2,  2,  2,  2,  2,
-   27, 27, 91, 67, 67, 67, 56, 20,168, 67, 67, 67, 67, 67, 67, 67,
-   67, 44, 44, 44, 44, 44, 44, 93,105,105,105,105,105,105,105,181,
-    2,  2, 64, 44, 44, 44, 44, 44, 63, 64, 44, 44, 44, 44, 44, 44,
-   65, 65, 65, 65, 65, 65, 65, 65, 71, 36, 36, 70, 43, 43, 43, 43,
-   43, 43, 43, 44, 44, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44,
-   43, 43, 43, 60,  2,  2, 67, 67, 40, 40, 97, 44, 44, 44, 44, 44,
-    7,  7,  7,  7,  7,179, 27, 27, 27, 62, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 44, 44, 62, 36, 27, 27, 27, 30,  2, 64, 44, 44,
-   36, 36, 36, 36, 36, 61, 44, 57, 94, 86, 86, 86, 86, 86, 86, 86,
-   86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 44, 44, 57,
-   43, 74, 40, 40, 40, 40, 40, 40, 40, 88, 80, 44, 44, 44, 44, 44,
-   86, 44, 44, 44, 44, 44, 44, 44, 40, 40, 52, 40, 40, 40, 52, 81,
-   36, 61, 44, 44, 44, 44, 44, 44, 44, 61, 44, 44, 44, 44, 44, 44,
-   36, 61, 62, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44,
-   36, 36, 36, 36, 36, 44, 50, 60, 65, 65, 44, 44, 44, 44, 44, 44,
-   43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 80, 44, 44, 44, 44,
-   67, 67, 67, 92, 55, 67, 67, 67, 67, 67,186, 87, 43, 67,186, 86,
-   86,187, 65, 65, 65, 84, 43, 43, 43, 76, 50, 43, 43, 43, 67, 67,
-   67, 67, 67, 67, 67, 43, 43, 67, 67, 43, 76, 44, 44, 44, 44, 44,
-   27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16,
-   16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
-   16, 16,110, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
-   16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11,
-   11, 11, 11, 16, 16,150,150, 16, 16, 16,150, 16, 16, 16, 16, 16,
-   16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16,
-   16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11,
-   47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
-   11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11,
-   31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16,
-   16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16,
-   16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16,
-   16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11,
-   11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16,
-   11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44,  7,
-    7,  7,  7,  7,  7,  7,  7,  7, 43, 43, 43, 76, 67, 50, 43, 43,
-   43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67,
-   67, 67, 76, 21,  2,  2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43,
-   16, 16, 16, 16, 16, 39, 16, 16, 16, 16, 16, 16, 16, 16, 16,110,
-   44, 44,150, 16, 16,110, 44, 44, 43, 43, 43, 80, 43, 43, 43, 43,
-   43, 43, 43, 43, 80, 57, 43, 43, 43, 57, 80, 43, 43, 80, 44, 44,
-   40, 40, 40, 40, 40, 40, 40, 44, 44, 44, 44, 44, 44, 44, 44, 57,
-   43, 43, 43, 74, 40, 40, 40, 44,  7,  7,  7,  7,  7, 44, 44, 77,
-   36, 36, 36, 36, 36, 36, 36, 80, 36, 36, 36, 36, 36, 36, 43, 43,
-    7,  7,  7,  7,  7, 44, 44, 96, 36, 36, 36, 36, 36, 83, 43, 43,
-   36, 36, 36, 61, 36, 36, 62, 61, 36, 36, 61,179, 27, 27, 27, 27,
-   16, 16, 43, 43, 43, 74, 44, 44, 27, 27, 27, 27, 27, 27,163, 27,
-  188, 27,100, 44, 44, 44, 44, 44, 27, 27, 27, 27, 27, 27, 27,163,
-   27, 27, 27, 27, 27, 27, 27, 44, 36, 36, 62, 36, 36, 36, 36, 36,
-   62, 61, 61, 62, 62, 36, 36, 36, 36, 61, 36, 36, 62, 62, 44, 44,
-   44, 61, 44, 62, 62, 62, 62, 36, 62, 61, 61, 62, 62, 62, 62, 62,
-   62, 61, 61, 62, 36, 61, 36, 36, 36, 61, 36, 36, 62, 36, 61, 61,
-   36, 36, 36, 36, 36, 62, 36, 36, 62, 36, 62, 36, 36, 62, 36, 36,
-    8, 44, 44, 44, 44, 44, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67,
-   27, 27, 27, 27, 27, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 44,
-   44, 44, 44, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, 44, 44,
-   67, 67, 67, 67, 92, 44, 44, 44, 67, 44, 44, 44, 44, 44, 44, 44,
-   67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 67, 67,
-   67, 67, 67, 92, 44, 55, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44,
-   67, 67, 67, 67, 67, 67, 67, 55, 67, 67, 67, 44, 44, 44, 44, 67,
-   67, 92, 67, 67, 67, 67, 67, 67, 79, 44, 44, 44, 44, 44, 44, 44,
-  171,171,171,171,171,171,171, 44,171,171,171,171,171,171,171,  0,
-    0,  0, 29, 21, 21, 21, 23, 21, 22, 18, 21, 25, 21, 17, 13, 13,
-   25, 25, 25, 21, 21,  9,  9,  9,  9, 22, 21, 18, 24, 16, 24,  5,
-    5,  5,  5, 22, 25, 18, 25,  0, 23, 23, 26, 21, 24, 26,  7, 20,
-   25,  1, 26, 24, 26, 25, 15, 15, 24, 15,  7, 19, 15, 21,  9, 25,
-    9,  5,  5, 25,  5,  9,  5,  7,  7,  7,  9,  8,  8,  5,  7,  5,
-    6,  6, 24, 24,  6, 24, 12, 12,  2,  2,  6,  5,  9, 21,  9,  2,
-    2,  9, 25,  9, 26, 12, 11, 11,  2,  6,  5, 21, 17,  2,  2, 26,
-   26, 23,  2, 12, 17, 12, 21, 12, 12, 21,  7,  2,  2,  7,  7, 21,
-   21,  2,  1,  1, 21, 23, 26, 26,  1, 21,  6,  7,  7, 12, 12,  7,
-   21,  7, 12,  1, 12,  6,  6, 12, 12, 26,  7, 26, 26,  7,  2,  1,
-   12,  2,  6,  2, 24,  7,  7,  6,  1, 12, 12, 10, 10, 10, 10, 12,
-   21,  6,  2, 10, 10,  2, 15, 26, 26,  2,  2, 21,  7, 10, 15,  7,
-    2, 23, 21, 26, 10,  7, 21, 15, 15,  2, 17,  7, 29,  7,  7, 22,
-   18,  2, 14, 14, 14,  7, 10, 21, 17, 21, 11, 12,  5,  2,  5,  6,
-    8,  8,  8, 24,  5, 24,  2, 24,  9, 24, 24,  2, 29, 29, 29,  1,
-   17, 17, 20, 19, 22, 20, 27, 28,  1, 29, 21, 20, 19, 21, 21, 16,
-   16, 21, 25, 22, 18, 21, 21, 29,  1,  2, 15,  6, 18,  6, 23,  2,
-   12, 11,  9, 26, 26,  9, 26,  5,  5, 26, 14,  9,  5, 14, 14, 15,
-   25, 26, 26, 22, 18, 26, 18, 25, 18, 22,  5, 12,  2,  5, 22, 21,
-   21, 22, 18, 17, 26,  6,  7, 14, 17, 22, 18, 18, 26, 14, 17,  6,
-   14,  6, 12, 24, 24,  6, 26, 15,  6, 21, 11, 21, 24,  9,  6,  9,
-   23, 26,  6, 10,  4,  4,  3,  3,  7, 25, 17, 16, 16, 22, 16, 16,
-   25, 17, 25,  2, 25, 24,  2, 15, 12, 15, 14,  2, 21, 14,  7, 15,
-   12, 17, 21,  1, 26, 10, 10,  1, 23, 15,  0,  1,  2,  3,  4,  5,
-    6,  7,  8,  9,  0, 10, 11, 12, 13,  0, 14,  0,  0,  0,  0,  0,
-   15,  0, 16,  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,  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, 17, 18, 19,
-    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,  0,  0,  0,  0,  0,  0, 20,  0, 21, 22, 23,  0,  0,  0, 24,
-   25, 26, 27, 28, 29, 30, 31, 32, 33, 34,  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,  0,  0,  0,  0, 35,
-    0, 36,  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,  0,  0,  0,  0,  0, 37,  0,  0,  0,  0,  0,  0,  0,
-    0,  0, 38, 39,  0,  0,  0,  0,  0,  0, 40, 41, 42,  0, 43,  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,  1,  2,  3,  4,  0,  0,  0,  0,
-    0,  0,  0,  0,  5,  0,  0,  0,  0,  0,  0,  0,  6,  7,  8,  0,
-    9,  0, 10, 11,  0,  0, 12, 13, 14, 15, 16,  0,  0,  0,  0, 17,
-   18, 19, 20,  0, 21,  0, 22, 23,  0, 24, 25,  0,  0, 24, 26, 27,
-    0, 24, 26,  0,  0, 24, 26,  0,  0, 24, 26,  0,  0,  0, 26,  0,
-    0, 24, 28,  0,  0, 24, 26,  0,  0, 29, 26,  0,  0,  0, 30,  0,
-    0, 31, 32,  0,  0, 33, 34,  0, 35, 36,  0, 37, 38,  0, 39,  0,
-    0, 40,  0,  0, 41,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 42,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0, 43, 44,  0,  0,  0,  0, 45,  0,
-    0,  0,  0,  0,  0, 46,  0,  0,  0, 47,  0,  0,  0,  0,  0,  0,
-   48,  0,  0, 49,  0, 50, 51,  0,  0, 52, 53, 54,  0, 55,  0, 56,
-    0, 57,  0,  0,  0,  0, 58, 59,  0,  0,  0,  0,  0,  0, 60, 61,
-    0,  0,  0,  0,  0,  0, 62, 63,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0, 64,  0,  0,  0, 65,  0,  0,  0, 66,
-    0, 67,  0,  0, 68,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0, 69, 70,  0,  0, 71,  0,  0,  0,  0,  0,  0,  0,  0,
-   72, 73,  0,  0,  0,  0, 53, 74,  0, 75, 76,  0,  0, 77, 78,  0,
-    0,  0,  0,  0,  0, 79, 80, 81,  0,  0,  0,  0,  0,  0,  0, 26,
-    0,  0,  0,  0,  0,  0,  0,  0, 82,  0,  0,  0,  0,  0,  0,  0,
-    0, 83,  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, 84,
-    0,  0,  0,  0,  0,  0,  0, 85,  0,  0,  0, 86,  0,  0,  0,  0,
-   87, 88,  0,  0,  0,  0,  0, 89,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0, 90,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0, 91,  0, 92,  0,  0, 93,  0, 94,  0,  0,  0,
-    0,  0, 72, 95,  0, 96,  0,  0, 97, 98,  0, 77,  0,  0, 99,  0,
-    0,100,  0,  0,  0,  0,  0,101,  0,102, 26,103,  0,  0,  0,  0,
-    0,  0,104,  0,  0,  0,105,  0,  0,  0,  0,  0,  0, 65,106,  0,
-    0, 65,  0,  0,  0,107,  0,  0,  0,108,  0,  0,  0,  0,  0,  0,
-    0, 96,  0,  0,  0,  0,  0,  0,  0,109,110,  0,  0,  0,  0, 78,
-    0, 44,111,  0,112,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0, 65,  0,  0,  0,  0,  0,  0,  0,  0,113,  0,114,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,115,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,116,  0,117,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,118,
-    0,  0,  0,  0,119,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,120,121,122,  0,  0,
-    0,  0,123,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-  124,125,  0,  0,126,  0,  0,  0,  0,117,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,127,  0,128,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,129,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,130,  0,  0,  0,131,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  3,  4,
-    5,  6,  7,  4,  4,  8,  9, 10,  1, 11, 12, 13, 14, 15, 16, 17,
-   18,  1,  1,  1,  0,  0,  0,  0, 19,  1,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0, 20, 21, 22,  1, 23,  4, 21, 24, 25, 26, 27, 28,
-   29, 30,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1, 31,  0,
-    0,  0, 32, 33, 34, 35,  1, 36,  0,  0,  0,  0, 37,  0,  0,  0,
-    0,  0,  0,  0,  0, 38,  1, 39, 14, 39, 40, 41,  0,  0,  0,  0,
-    0,  0,  0,  0, 42,  0,  0,  0,  0,  0,  0,  0, 43, 36, 44, 45,
-   21, 45, 46,  0,  0,  0,  0,  0,  0,  0, 19,  1, 21,  0,  0, 47,
-    0,  0,  0,  0,  0, 38, 48,  1,  1, 49, 49, 50,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0, 51,  0,  0,  0,  0,  0,  0,  0, 52,  1,
-    0,  0, 38, 14,  4,  1,  1,  1, 53, 21, 43, 52, 54, 21, 35,  1,
-    0,  0,  0,  0,  0,  0,  0, 55,  0,  0,  0, 56, 57, 58,  0,  0,
-    0,  0,  0, 56,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 59,
-    0,  0,  0, 56,  0, 60,  0,  0,  0,  0,  0,  0,  0,  0, 61, 62,
-    0,  0, 63,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 64,  0,
-    0,  0, 65,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 66,  0,
-    0,  0, 67,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 68,  0,
-    0,  0,  0,  0,  0, 69, 70,  0,  0,  0,  0,  0, 71, 72, 73, 74,
-   75, 76,  0,  0,  0,  0,  0,  0,  0, 77,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0, 78, 79,  0,  0,  0,  0, 47,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0, 49,  0,  0,  0,  0,  0, 80,  0,  0,
-    0,  0,  0,  0,  0, 62,  0,  0,  0,  0,  0,  0, 63,  0,  0, 81,
-    0,  0, 82,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 83,  0,
-    0,  0,  0,  0,  0, 19, 84,  0, 62,  0,  0,  0,  0, 49,  1, 85,
-    0,  0,  0,  0,  1, 52, 15, 86, 36, 10, 21, 87,  0,  0,  0,  0,
-    0,  0,  0,  0,  0, 55,  0,  0,  0, 62,  0,  0,  0,  0,  0,  0,
-    0,  0, 19, 10,  1,  0,  0,  0,  0,  0, 88,  0,  0,  0,  0,  0,
-    0, 89,  0,  0, 88,  0,  0,  0,  0,  0,  0,  0,  0, 78,  0,  0,
-    0,  0,  0,  0, 87,  9, 12,  4, 90,  8, 91, 47,  0, 58, 50,  0,
-   21,  1, 21, 92, 93,  1,  1,  1,  1,  1,  1,  1,  1, 94, 95, 96,
-    0,  0,  0,  0, 97,  1, 98, 58, 81, 99,100,  4, 58,  0,  0,  0,
-    0,  0,  0, 19, 50,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 61,
-    1,  1,  1,  1,  1,  1,  1,  1,  0,  0,101,102,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,103,  0,  0,  0,  0, 19,  0,  1,  1, 50,
-    0,  0,  0,  0,  0,  0,  0, 38,  0,  0,  0,  0, 50,  0,  0,  0,
-    0, 63,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0,  0,
-    1,  1,  1,  1, 50,  0,  0,  0,  0,  0,104, 68,  0,  0,  0,  0,
-    0,  0,  0,  0, 61,  0,  0,  0,  0,  0,  0,  0, 78,  0,  0,  0,
-   62,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,106, 58, 38,
-   81,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 63,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,107,  1, 14,  4, 12,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0, 47, 84,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0, 38, 87,  0,  0,  0,  0,108,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,109, 61,  0,110,  0,  0,  0,  0,  0,  0,
-    0,  1,  0,  0,  0,  0,  0,  0,  0,  0, 19, 58,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0, 51,  0,111, 14, 52, 84,  0,  0,  0,
-  112, 41,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0, 61,
-    0,  0,  0,  0,  0,  0,113,  0, 87,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0, 61, 62,  0,  0, 62,  0, 89,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,113,  0,  0,  0,  0,114,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0, 78, 55,  0, 38,  1, 58,  1, 58,  0,  0,
-   63, 89,  0,  0,  0,  0,  0, 59,115,  0,  0,  0,  0,  0,  0,  0,
-   55,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,115,  0,  0,
-    0,  0, 61,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 79,
-   78,  0,  0,  0,  0,  0,  0,  0,  0, 61,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0, 56,  0, 89, 80,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0, 61,  0,  0, 79,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  8, 91,  0,  0,  0,  0,  0,  0,  1, 87,  0,  0,
-    0,  0,  0,  0,116,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,117,
-    0,118,119,120,121,  0,104,  4,122, 49, 23,  0,  0,  0,  0,  0,
-    0,  0, 38, 50,  0,  0,  0,  0, 38, 58,  0,  0,  0,  0,  0,  0,
-    1, 87,  1,  1,  1,  1, 39,  1, 48,105, 87,  0,  0,  0,  0,  0,
-    0,  0,  0, 19,  0,  0,  0,  0,  0,  0,  0, 59,  0,  0,  0,  0,
-    0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,123,  0,  0,  0,  0,
-    0,  0,  0,  0,  4,122,  0,  0,  0,  1,124,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,230,230,230,230,230,232,220,220,220,220,232,216,
-  220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220,
-    1,  1,  1,  1,  1,220,220,220,220,230,230,230,230,240,230,220,
-  220,220,230,230,230,220,220,  0,230,230,230,220,220,220,220,230,
-  232,220,220,230,233,234,234,233,234,234,233,230,  0,  0,  0,230,
-    0,220,230,230,230,230,220,230,230,230,222,220,230,230,220,220,
-  230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20,
-   21, 22,  0, 23,  0, 24, 25,  0,230,220,  0, 18, 30, 31, 32,  0,
-    0,  0,  0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230,
-  220,230,230,220, 35,  0,  0,  0,  0,  0,230,230,230,  0,  0,230,
-  230,  0,220,230,230,220,  0,  0,  0, 36,  0,  0,230,220,230,230,
-  220,220,230,220,220,230,220,230,220,230,230,  0,  0,220,  0,  0,
-  230,230,  0,230,  0,230,230,230,230,230,  0,  0,  0,220,220,220,
-  230,220,220,220,230,230,  0,220, 27, 28, 29,230,  7,  0,  0,  0,
-    0,  9,  0,  0,  0,230,220,230,230,  0,  0,  0,  0,  0,230,  0,
-    0, 84, 91,  0,  0,  0,  0,  9,  9,  0,  0,  0,  0,  0,  9,  0,
-  103,103,  9,  0,107,107,107,107,118,118,  9,  0,122,122,122,122,
-  220,220,  0,  0,  0,220,  0,220,  0,216,  0,  0,  0,129,130,  0,
-  132,  0,  0,  0,  0,  0,130,130,130,130,  0,  0,130,  0,230,230,
-    9,  0,230,230,  0,  0,220,  0,  0,  0,  0,  7,  0,  9,  9,  0,
-    9,  9,  0,  0,  0,230,  0,  0,  0,228,  0,  0,  0,222,230,220,
-  220,  0,  0,  0,230,  0,  0,220,230,220,  0,220,230,230,230,  0,
-    0,  0,  9,  9,  0,  0,  7,  0,230,  0,  1,  1,  1,  0,  0,  0,
-  230,234,214,220,202,230,230,230,230,230,232,228,228,220,218,230,
-  233,220,230,220,230,230,  1,  1,  1,  1,  1,230,  0,  1,  1,230,
-  220,230,  1,  1,  0,  0,218,228,232,222,224,224,  0,  8,  8,  0,
-    0,  0,  0,220,230,  0,230,230,220,  0,  0,230,  0,  0, 26,  0,
-    0,220,  0,230,230,  1,220,  0,  0,230,220,  0,  0,  0,220,220,
-    0,  0,230,220,  0,  9,  7,  0,  0,  7,  9,  0,  0,  0,  9,  7,
-    6,  6,  0,  0,  0,  0,  1,  0,  0,216,216,  1,  1,  1,  0,  0,
-    0,226,216,216,216,216,216,  0,220,220,220,  0,232,232,220,230,
-  230,230,  7,  0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19,
-   17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17,
-   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-   17, 17, 17,237,  0,  1,  2,  2,  0,  3,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  4,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    5,  0,  0,  0,  0,  6,  7,  8,  9,  0,  0,  0, 10, 11, 12, 13,
-   14, 15, 16, 17, 18, 19,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,
-    0,  0, 21, 22,  0,  0,  0,  0, 23, 24, 25, 26,  0, 27,  0, 28,
-   29, 30, 31, 32,  0,  0,  0,  0,  0,  0,  0, 33, 34, 35, 36,  0,
-    0,  0,  0,  0, 37,  0,  0,  0,  0,  0,  0,  0,  0,  0, 38, 39,
-    0,  0,  0,  0,  1,  2, 40, 41,  0,  1,  2,  2,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  2,  0,  0,  0,  0,
-    0,  0,  3,  4,  0,  0,  5,  0,  0,  0,  6,  0,  0,  0,  0,  0,
-    0,  0,  7,  1,  0,  0,  0,  0,  0,  0,  8,  9,  0,  0,  0,  0,
-    0,  0, 10,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0, 10,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0, 11, 12,
-    0, 13,  0, 14, 15, 16,  0,  0,  0,  0,  0,  1, 17, 18,  0, 19,
-    7,  1,  0,  0,  0, 20, 20,  7, 20, 20, 20, 20, 20, 20, 20,  8,
-   21,  0, 22,  0,  7, 23, 24,  0, 20, 20, 25,  0,  0,  0, 26, 27,
-    1,  7, 20, 20, 20, 20, 20,  1, 28, 29, 30, 31,  0,  0, 20,  0,
-    0,  0,  0,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0, 20, 20,
-   20,  1,  0,  0,  8, 21, 32,  4,  0, 10,  0, 33,  7, 20, 20, 20,
-    0,  0,  0,  0,  8, 34, 34, 35, 36, 34, 37,  0, 38,  1, 20, 20,
-    0,  0, 39,  0,  1,  1,  0,  8, 21,  1, 20,  0,  0,  0,  1,  0,
-    0, 40,  1,  1,  0,  0,  8, 21,  0,  1,  0,  1,  0,  1,  0,  0,
-    0,  0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21,  7, 20, 41,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 21,  0, 42, 43, 44,  0, 45,
-    0,  8, 21,  0,  0,  0,  0,  0,  0,  0,  0, 46,  7,  1, 10,  1,
-    0,  0,  0,  1, 20, 20,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0, 26, 34,  9,  0,  0, 20, 20,  1, 20, 20,  0,  0,  0,  0,  0,
-    0,  0, 26, 21,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  3, 47, 48,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,
-    4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-    9, 10, 11, 11, 11, 11, 12, 13, 13, 13, 13, 14, 15, 16, 17, 18,
-   19, 20, 21, 13, 22, 13, 13, 13, 13, 23, 24, 24, 25, 26, 13, 13,
-   13, 27, 28, 29, 13, 30, 31, 32, 33, 34, 35, 36,  7,  7,  7,  7,
-    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-   37,  7, 38, 39,  7, 40,  7,  7,  7, 41, 13, 42,  7,  7, 43,  7,
-   44, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 45,  0,  0,  1,
-    2,  2,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
-   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-   32, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42,
-   43, 44, 45, 46, 47, 48, 49, 50, 51, 52,  2,  2, 53, 54, 55, 56,
-   57, 58, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 61, 61,
-   59, 59, 59, 59, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
-   74, 75, 76, 77, 78, 59, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 79, 70, 70, 70, 70, 80, 80,
-   80, 80, 80, 80, 80, 80, 80, 81, 82, 82, 83, 84, 85, 86, 87, 88,
-   89, 90, 91, 92, 93, 94, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 95, 96, 96,
-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-   70, 70, 97, 98, 99,100,101,101,102,103,104,105,106,107,108,109,
-  110,111, 96,112,113,114,115,116,117,118,119,119,120,121,122,123,
-  124,125,126,127,128,129,130,131,132, 96,133,134,135,136,137,138,
-  139,140,141,142,143, 96,144,145, 96,146,147,148,149, 96,150,151,
-  152,153,154,155,156, 96,157,158,159,160, 96,161,162,163,164,164,
-  164,164,164,164,164,165,166,164,167, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,168,169,169,
-  169,169,169,169,169,169,170, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96, 96,171,171,171,171,172, 96, 96, 96,173,173,
-  173,173,174,175,176,177, 96, 96, 96, 96,178,179,180,181,182,182,
-  182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
-  182,182,182,182,182,182,182,182,182,182,182,182,182,183,182,182,
-  182,182,182,182,184,184,184,185,186, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,187,188,189,
-  190,191,191,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96, 96,193,194, 96, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,195,196, 59,197,
-  198,199,200,201,202, 96,203,204,205, 59, 59,206, 59,207,208,208,
-  208,208,208,209, 96, 96, 96, 96, 96, 96, 96, 96,210, 96,211,212,
-  213, 96, 96,214, 96, 96, 96,215, 96, 96, 96, 96, 96,216,217,218,
-  219, 96, 96, 96, 96, 96,220,221,222, 96,223,224, 96, 96,225,226,
-   59,227,228, 96, 59, 59, 59, 59, 59, 59, 59,229,230,231,232,233,
-   59, 59,234,235, 59,236, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,237, 70, 70, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,238, 70,239, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,240, 70, 70, 70, 70,
-   70, 70, 70, 70, 70,241, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
-   70, 70,242, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
-   70, 70, 70, 70,243, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 70, 70, 70, 70,244, 96, 96, 96, 96, 96, 96, 96, 96,245, 96,
-  246,247,  0,  1,  2,  2,  0,  1,  2,  2,  2,  3,  4,  5,  0,  0,
-    0,  0,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-   19, 19, 19, 19, 19, 19, 19, 19, 19,  0,  0,  0,  0,  0,  0,  0,
-   19,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19, 19, 19,  0, 19,  0,
-    0,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19,  0,  0,  0,  0,  0,
-   26, 26,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  9,  9,
-    9,  9,  0,  9,  9,  9,  2,  2,  9,  9,  9,  9,  0,  9,  2,  2,
-    2,  2,  9,  0,  9,  0,  9,  9,  9,  2,  9,  2,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  2,  9,  9,  9,  9,  9,  9,  9,
-   55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,  6,  6,
-    6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  1,  1,  6,  2,  4,
-    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
-    4,  4,  4,  4,  4,  2,  4,  4,  4,  2,  2,  4,  4,  4,  2, 14,
-   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  2,  2,
-    2,  2,  2,  2,  2,  2, 14, 14, 14,  2,  2,  2,  2, 14, 14, 14,
-   14, 14, 14,  2,  2,  2,  3,  3,  3,  3,  3,  0,  3,  3,  3,  3,
-    3,  3,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-    3,  0,  3,  3,  3,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-    3,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  3,  3,  1,  3,
-    3,  3,  3,  3,  3,  3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-   37, 37, 37, 37,  2, 37, 37, 37, 37,  2,  2, 37, 37, 37, 38, 38,
-   38, 38, 38, 38, 38, 38, 38, 38,  2,  2,  2,  2,  2,  2, 64, 64,
-   64, 64, 64, 64, 64, 64, 64, 64, 64,  2,  2, 64, 64, 64, 90, 90,
-   90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,  2,  2, 90, 90,
-   90, 90, 90, 90, 90,  2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
-   95, 95,  2,  2, 95,  2, 37, 37, 37,  2,  2,  2,  2,  2,  3,  3,
-    3,  3,  3,  3,  3,  2,  3,  3,  2,  2,  2,  2,  2,  2,  3,  3,
-    0,  3,  3,  3,  3,  3,  7,  7,  7,  7,  7,  7,  7,  7,  7,  1,
-    1,  1,  1,  7,  7,  7,  7,  7,  7,  7,  0,  0,  7,  7,  5,  5,
-    5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  5,  5,  2,
-    2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,
-    5,  5,  5,  5,  5,  5,  5,  2,  5,  2,  2,  2,  5,  5,  5,  5,
-    2,  2,  5,  5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  2,  2,  2,
-    2,  2,  2,  2,  2,  5,  2,  2,  2,  2,  5,  5,  2,  5,  5,  5,
-    5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2, 11,
-   11, 11,  2, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2, 11, 11,  2,
-    2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,
-   11, 11, 11, 11, 11, 11, 11,  2, 11, 11,  2, 11, 11,  2, 11, 11,
-    2,  2, 11,  2, 11, 11, 11,  2,  2, 11, 11, 11,  2,  2,  2, 11,
-    2,  2,  2,  2,  2,  2,  2, 11, 11, 11, 11,  2, 11,  2,  2,  2,
-    2,  2,  2,  2, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,  2, 10,
-   10, 10,  2, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,
-    2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2,
-   10, 10, 10, 10, 10, 10, 10,  2, 10, 10,  2, 10, 10, 10, 10, 10,
-    2,  2, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,  2,  2, 10,  2,
-    2,  2,  2,  2,  2,  2, 10, 10, 10, 10,  2,  2, 10, 10, 10, 10,
-    2,  2,  2,  2,  2,  2,  2, 10, 10, 10, 10, 10, 10, 10,  2, 21,
-   21, 21,  2, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2, 21, 21,  2,
-    2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,
-   21, 21, 21, 21, 21, 21, 21,  2, 21, 21,  2, 21, 21, 21, 21, 21,
-    2,  2, 21, 21, 21, 21, 21,  2,  2, 21, 21, 21,  2,  2,  2,  2,
-    2,  2,  2, 21, 21, 21,  2,  2,  2,  2, 21, 21,  2, 21, 21, 21,
-   21, 21,  2,  2, 21, 21,  2,  2, 22, 22,  2, 22, 22, 22, 22, 22,
-   22,  2,  2,  2, 22, 22, 22,  2, 22, 22, 22, 22,  2,  2,  2, 22,
-   22,  2, 22,  2, 22, 22,  2,  2,  2, 22, 22,  2,  2,  2, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22,  2,  2,  2,  2, 22, 22, 22,  2,
-    2,  2,  2,  2,  2, 22,  2,  2,  2,  2,  2,  2, 22, 22, 22, 22,
-   22,  2,  2,  2,  2,  2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-   23, 23, 23,  2, 23, 23, 23,  2, 23, 23, 23, 23, 23, 23, 23, 23,
-    2,  2, 23, 23, 23, 23, 23,  2, 23, 23, 23, 23,  2,  2,  2,  2,
-    2,  2,  2, 23, 23,  2, 23, 23, 23,  2,  2, 23,  2,  2, 23, 23,
-   23, 23,  2,  2, 23, 23,  2,  2,  2,  2,  2,  2,  2, 23, 16, 16,
-   16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16,  2,
-   16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16, 16,
-    2,  2, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16,  2,  2,  2,  2,
-    2,  2,  2, 16, 16,  2, 16, 16, 16, 16,  2,  2, 16, 16,  2, 16,
-   16, 16,  2,  2,  2,  2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
-   20, 20, 20,  2, 20, 20, 20,  2, 20, 20, 20, 20, 20, 20,  2,  2,
-    2,  2, 20, 20, 20, 20, 20, 20, 20, 20,  2,  2, 20, 20,  2, 36,
-   36, 36,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 36,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36, 36,
-    2, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,  2,
-   36,  2,  2,  2,  2, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,
-    2,  2,  2,  2, 36, 36,  2,  2, 36, 36, 36,  2,  2,  2,  2, 24,
-   24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-   24,  2,  2,  2,  2,  0, 24, 24, 24, 24,  2,  2,  2,  2,  2, 18,
-   18,  2, 18,  2, 18, 18, 18, 18, 18,  2, 18, 18, 18, 18, 18, 18,
-   18, 18, 18, 18, 18, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18, 18,
-   18, 18, 18, 18,  2,  2, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18,
-   18, 18, 18, 18, 18,  2, 18, 18,  2,  2, 18, 18, 18, 18, 25, 25,
-   25, 25, 25, 25, 25, 25,  2, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-   25, 25, 25,  2,  2,  2, 25, 25, 25, 25, 25,  2, 25, 25, 25, 25,
-   25, 25, 25,  0,  0,  0,  0, 25, 25,  2,  2,  2,  2,  2, 33, 33,
-   33, 33, 33, 33, 33, 33,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-    8,  8,  8,  8,  2,  8,  2,  2,  2,  2,  2,  8,  2,  2,  8,  8,
-    8,  0,  8,  8,  8,  8, 12, 12, 12, 12, 12, 12, 12, 12, 30, 30,
-   30, 30, 30, 30, 30, 30, 30,  2, 30, 30, 30, 30,  2,  2, 30, 30,
-   30, 30, 30, 30, 30,  2, 30, 30, 30,  2,  2, 30, 30, 30, 30, 30,
-   30, 30, 30,  2,  2,  2, 30, 30,  2,  2,  2,  2,  2,  2, 29, 29,
-   29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,  2,  2, 28, 28,
-   28, 28, 28, 28, 28, 28, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34,  2,  2,  2, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-   35,  0,  0,  0, 35, 35, 35,  2,  2,  2,  2,  2,  2,  2, 45, 45,
-   45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,  2,  2,  2,  2,
-    2,  2,  2,  2,  2, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
-   44, 44, 44,  0,  0,  2, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
-   43, 43,  2,  2,  2,  2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
-   46, 46, 46,  2, 46, 46, 46,  2, 46, 46,  2,  2,  2,  2, 31, 31,
-   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,  2,  2, 31, 31,
-    2,  2,  2,  2,  2,  2, 32, 32,  0,  0, 32,  0, 32, 32, 32, 32,
-   32, 32, 32, 32, 32, 32, 32, 32,  2,  2,  2,  2,  2,  2, 32,  2,
-    2,  2,  2,  2,  2,  2, 32, 32, 32,  2,  2,  2,  2,  2, 28, 28,
-   28, 28, 28, 28,  2,  2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
-   48, 48, 48, 48, 48,  2, 48, 48, 48, 48,  2,  2,  2,  2, 48,  2,
-    2,  2, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-   52, 52, 52, 52,  2,  2, 52, 52, 52, 52, 52,  2,  2,  2, 58, 58,
-   58, 58, 58, 58, 58, 58, 58, 58, 58, 58,  2,  2,  2,  2, 58, 58,
-    2,  2,  2,  2,  2,  2, 58, 58, 58,  2,  2,  2, 58, 58, 54, 54,
-   54, 54, 54, 54, 54, 54, 54, 54, 54, 54,  2,  2, 54, 54, 91, 91,
-   91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,  2, 91, 91,
-   91, 91, 91,  2,  2, 91, 91, 91,  2,  2,  2,  2,  2,  2, 91, 91,
-   91, 91, 91, 91,  2,  2,  1,  1,  1,  1,  1,  1,  1,  2, 62, 62,
-   62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,  2,  2,  2, 62, 62,
-   62, 62, 62, 62, 62,  2, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93,
-   93, 93, 93, 93, 93, 93, 93, 93, 93, 93,  2,  2,  2,  2,  2,  2,
-    2,  2, 93, 93, 93, 93, 70, 70, 70, 70, 70, 70, 70, 70,  2,  2,
-    2, 70, 70, 70, 70, 70, 70, 70,  2,  2,  2, 70, 70, 70, 73, 73,
-   73, 73, 73, 73, 73, 73,  6,  2,  2,  2,  2,  2,  2,  2,  8,  8,
-    8,  2,  2,  8,  8,  8,  1,  1,  1,  0,  1,  1,  1,  1,  1,  0,
-    1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,
-    0,  0,  1,  0,  0,  0,  1,  1,  0,  2,  2,  2,  2,  2, 19, 19,
-   19, 19, 19, 19,  9,  9,  9,  9,  9,  6, 19, 19, 19, 19, 19, 19,
-   19, 19, 19,  9,  9,  9,  9,  9, 19, 19, 19, 19,  9,  9,  9,  9,
-    9, 19, 19, 19, 19, 19,  6, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-   19, 19, 19, 19, 19,  9,  9,  9,  9,  9,  9,  9,  2,  2,  2,  9,
-    2,  9,  2,  9,  2,  9,  9,  9,  9,  9,  9,  2,  9,  9,  9,  9,
-    9,  9,  2,  2,  9,  9,  9,  9,  9,  9,  2,  9,  9,  9,  2,  2,
-    9,  9,  9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  2,  0,  0,
-    0,  0,  1,  1,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0, 19,
-    2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,  0,  0,
-    0,  0,  0,  0,  0,  2, 19, 19, 19, 19, 19,  2,  2,  2,  0,  2,
-    2,  2,  2,  2,  2,  2,  1,  2,  2,  2,  2,  2,  2,  2,  0,  0,
-    0,  0,  0,  0,  9,  0,  0,  0, 19, 19,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0, 19,  0, 19,  0,  0,  0,  2,  2,  2,  2,  0,  0,
-    0,  2,  2,  2,  2,  2, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,
-    0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0, 56, 56,
-   56, 56, 56, 56, 56, 56, 55, 55, 55, 55,  2,  2,  2,  2,  2, 55,
-   55, 55, 55, 55, 55, 55, 61, 61, 61, 61, 61, 61, 61, 61,  2,  2,
-    2,  2,  2,  2,  2, 61, 61,  2,  2,  2,  2,  2,  2,  2,  0,  0,
-    0,  0,  0,  0,  2,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-    2, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2, 13, 13,
-   13, 13, 13, 13,  2,  2,  0,  0,  0,  0,  2,  2,  2,  2,  0,  0,
-    0,  0,  0, 13,  0, 13,  0, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-    1,  1,  1,  1, 12, 12, 13, 13, 13, 13,  0,  0,  0,  0,  2, 15,
-   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-   15, 15, 15, 15, 15,  2,  2,  1,  1,  0,  0, 15, 15, 15,  0, 17,
-   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-   17,  0,  0, 17, 17, 17,  2,  2,  2,  2,  2, 26, 26, 26, 26, 26,
-   26, 26, 26, 26, 26, 26,  2, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-   12, 12, 12, 12, 12,  2, 12, 12, 12, 12, 12, 12, 12,  0, 17, 17,
-   17, 17, 17, 17, 17,  0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
-   39, 39, 39,  2,  2,  2, 39, 39, 39, 39, 39, 39, 39,  2, 86, 86,
-   86, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
-   77, 77,  2,  2,  2,  2, 79, 79, 79, 79, 79, 79, 79, 79,  0,  0,
-   19, 19, 19, 19, 19, 19,  0,  0,  0, 19, 19, 19, 19, 19, 19, 19,
-   19,  2,  2,  2,  2,  2, 19, 19,  2, 19,  2, 19, 19, 19, 19, 19,
-    2,  2,  2,  2,  2,  2,  2,  2, 19, 19, 19, 19, 19, 19, 60, 60,
-   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,  2,  2,  2,  0,  0,
-    2,  2,  2,  2,  2,  2, 65, 65, 65, 65, 65, 65, 65, 65, 75, 75,
-   75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,  2,  2,  2,  2,
-    2,  2,  2,  2, 75, 75, 75, 75,  2,  2,  2,  2,  2,  2, 69, 69,
-   69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,  0, 69, 74, 74,
-   74, 74, 74, 74, 74, 74, 74, 74, 74, 74,  2,  2,  2,  2,  2,  2,
-    2,  2,  2,  2,  2, 74, 12, 12, 12, 12, 12,  2,  2,  2, 84, 84,
-   84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,  2,  0, 84, 84,
-    2,  2,  2,  2, 84, 84, 33, 33, 33, 33, 33, 33, 33,  2, 68, 68,
-   68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,  2, 68, 68,
-   68, 68, 68, 68,  2,  2, 68, 68,  2,  2, 68, 68, 68, 68, 92, 92,
-   92, 92, 92, 92, 92, 92, 92, 92, 92,  2,  2,  2,  2,  2,  2,  2,
-    2, 92, 92, 92, 92, 92, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
-   87, 87, 87, 87, 87,  2,  2, 30, 30, 30, 30, 30, 30,  2, 19, 19,
-   19,  0, 19, 19, 19, 19, 19, 19, 19, 19, 19,  9, 19, 19, 19, 19,
-    0,  0,  2,  2,  2,  2, 87, 87, 87, 87, 87, 87,  2,  2, 87, 87,
-    2,  2,  2,  2,  2,  2, 12, 12, 12, 12,  2,  2,  2,  2,  2,  2,
-    2, 12, 12, 12, 12, 12, 13, 13,  2,  2,  2,  2,  2,  2, 19, 19,
-   19, 19, 19, 19, 19,  2,  2,  2,  2,  4,  4,  4,  4,  4,  2,  2,
-    2,  2,  2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  2, 14, 14,
-   14, 14, 14,  2, 14,  2, 14, 14,  2, 14, 14,  2, 14, 14,  3,  3,
-    3,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,
-    3,  3,  3,  3,  0,  0,  2,  2,  3,  3,  3,  3,  3,  3,  2,  2,
-    2,  2,  2,  2,  2,  3,  1,  1,  1,  1,  1,  1,  6,  6,  0,  0,
-    0,  2,  0,  0,  0,  0,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,
-    3,  3,  3,  2,  2,  0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0, 17, 17, 17, 17, 17, 17, 17, 17,  0,  0,  2,  2,
-   12, 12, 12, 12, 12, 12,  2,  2, 12, 12, 12,  2,  2,  2,  2,  0,
-    0,  0,  0,  0,  2,  2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
-   49, 49,  2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,  2, 49, 49,
-   49,  2, 49, 49,  2, 49, 49, 49, 49, 49, 49, 49,  2,  2, 49, 49,
-   49,  2,  2,  2,  2,  2,  0,  0,  0,  2,  2,  2,  2,  0,  0,  0,
-    0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  2,  2,  2,  9,  2,
-    2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  1,  2,  2, 71, 71,
-   71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,  2,  2,  2, 67, 67,
-   67, 67, 67, 67, 67, 67, 67,  2,  2,  2,  2,  2,  2,  2,  1,  0,
-    0,  0,  0,  0,  0,  0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
-   42, 42,  2,  2,  2,  2,  2,  2,  2,  2,  2, 42, 42, 42, 41, 41,
-   41, 41, 41, 41, 41, 41, 41, 41, 41,  2,  2,  2,  2,  2,118,118,
-  118,118,118,118,118,118,118,118,118,  2,  2,  2,  2,  2, 53, 53,
-   53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,  2, 53, 59, 59,
-   59, 59, 59, 59, 59, 59, 59, 59, 59, 59,  2,  2,  2,  2, 59, 59,
-   59, 59, 59, 59,  2,  2, 40, 40, 40, 40, 40, 40, 40, 40, 51, 51,
-   51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
-   50, 50, 50, 50,  2,  2, 50, 50,  2,  2,  2,  2,  2,  2,135,135,
-  135,135,135,135,135,135,135,135,135,135,  2,  2,  2,  2,106,106,
-  106,106,106,106,106,106,104,104,104,104,104,104,104,104,104,104,
-  104,104,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,104,161,161,
-  161,161,161,161,161,161,161,161,161,  2,161,161,161,161,161,161,
-  161,  2,161,161,  2,161,161,161,  2,161,161,161,161,161,161,161,
-    2,161,161,  2,  2,  2,110,110,110,110,110,110,110,110,110,110,
-  110,110,110,110,110,  2,110,110,110,110,110,110,  2,  2, 19, 19,
-   19, 19, 19, 19,  2, 19, 19,  2, 19, 19, 19, 19, 19, 19, 47, 47,
-   47, 47, 47, 47,  2,  2, 47,  2, 47, 47, 47, 47, 47, 47, 47, 47,
-   47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,  2, 47, 47,  2,
-    2,  2, 47,  2,  2, 47, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
-   81, 81, 81, 81,  2, 81,120,120,120,120,120,120,120,120,116,116,
-  116,116,116,116,116,116,116,116,116,116,116,116,116,  2,  2,  2,
-    2,  2,  2,  2,  2,116,128,128,128,128,128,128,128,128,128,128,
-  128,  2,128,128,  2,  2,  2,  2,  2,128,128,128,128,128, 66, 66,
-   66, 66, 66, 66, 66, 66, 66, 66, 66, 66,  2,  2,  2, 66, 72, 72,
-   72, 72, 72, 72, 72, 72, 72, 72,  2,  2,  2,  2,  2, 72, 98, 98,
-   98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97,  2,  2,
-    2,  2, 97, 97, 97, 97,  2,  2, 97, 97, 97, 97, 97, 97, 57, 57,
-   57, 57,  2, 57, 57,  2,  2,  2,  2,  2, 57, 57, 57, 57, 57, 57,
-   57, 57,  2, 57, 57, 57,  2, 57, 57, 57, 57, 57, 57, 57, 57, 57,
-   57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,  2,  2, 57, 57,
-   57,  2,  2,  2,  2, 57, 57,  2,  2,  2,  2,  2,  2,  2, 88, 88,
-   88, 88, 88, 88, 88, 88,117,117,117,117,117,117,117,117,112,112,
-  112,112,112,112,112,112,112,112,112,112,112,112,112,  2,  2,  2,
-    2,112,112,112,112,112, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
-   78, 78, 78, 78,  2,  2,  2, 78, 78, 78, 78, 78, 78, 78, 83, 83,
-   83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,  2,  2, 82, 82,
-   82, 82, 82, 82, 82, 82, 82, 82, 82,  2,  2,  2,  2,  2,122,122,
-  122,122,122,122,122,122,122,122,  2,  2,  2,  2,  2,  2,  2,122,
-  122,122,122,  2,  2,  2,  2,122,122,122,122,122,122,122, 89, 89,
-   89, 89, 89, 89, 89, 89, 89,  2,  2,  2,  2,  2,  2,  2,130,130,
-  130,130,130,130,130,130,130,130,130,  2,  2,  2,  2,  2,  2,  2,
-  130,130,130,130,130,130,144,144,144,144,144,144,144,144,144,144,
-    2,  2,  2,  2,  2,  2,156,156,156,156,156,156,156,156,156,156,
-    2,156,156,156,  2,  2,156,156,  2,  2,  2,  2,  2,  2,  2,  2,
-    2,  2,  2,  3,  3,  3,147,147,147,147,147,147,147,147,148,148,
-  148,148,148,148,148,148,148,148,  2,  2,  2,  2,  2,  2,158,158,
-  158,158,158,158,158,158,158,158,  2,  2,  2,  2,  2,  2,153,153,
-  153,153,153,153,153,153,153,153,153,153,  2,  2,  2,  2,149,149,
-  149,149,149,149,149,149,149,149,149,149,149,149,149,  2, 94, 94,
-   94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2,
-   94, 94, 94, 94, 94, 94,  2,  2,  2,  2,  2,  2,  2, 94, 85, 85,
-   85, 85, 85, 85, 85, 85, 85, 85, 85,  2,  2,  2,  2,  2,  2,  2,
-    2,  2,  2, 85,  2,  2,101,101,101,101,101,101,101,101,101,  2,
-    2,  2,  2,  2,  2,  2,101,101,  2,  2,  2,  2,  2,  2, 96, 96,
-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,  2, 96, 96,111,111,
-  111,111,111,111,111,111,111,111,111,111,111,111,111,  2,100,100,
-  100,100,100,100,100,100,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-   36, 36, 36,  2,  2,  2,108,108,108,108,108,108,108,108,108,108,
-    2,108,108,108,108,108,108,108,  2,  2,  2,  2,  2,  2,129,129,
-  129,129,129,129,129,  2,129,  2,129,129,129,129,  2,129,129,129,
-  129,129,129,129,129,129,129,129,129,129,129,129,  2,129,129,129,
-    2,  2,  2,  2,  2,  2,109,109,109,109,109,109,109,109,109,109,
-  109,  2,  2,  2,  2,  2,109,109,  2,  2,  2,  2,  2,  2,107,107,
-  107,107,  2,107,107,107,107,107,107,107,107,  2,  2,107,107,  2,
-    2,107,107,107,107,107,107,107,107,107,107,107,107,107,107,  2,
-  107,107,107,107,107,107,107,  2,107,107,  2,107,107,107,107,107,
-    2,  1,107,107,107,107,107,  2,  2,107,107,107,  2,  2,107,  2,
-    2,  2,  2,  2,  2,107,  2,  2,  2,  2,  2,107,107,107,107,107,
-  107,107,  2,  2,107,107,107,107,107,107,107,  2,  2,  2,137,137,
-  137,137,137,137,137,137,137,137,137,137,  2,137,137,137,137,137,
-    2,  2,  2,  2,  2,  2,124,124,124,124,124,124,124,124,124,124,
-    2,  2,  2,  2,  2,  2,123,123,123,123,123,123,123,123,123,123,
-  123,123,123,123,  2,  2,114,114,114,114,114,114,114,114,114,114,
-  114,114,114,  2,  2,  2,114,114,  2,  2,  2,  2,  2,  2, 32, 32,
-   32, 32, 32,  2,  2,  2,102,102,102,102,102,102,102,102,102,102,
-    2,  2,  2,  2,  2,  2,126,126,126,126,126,126,126,126,126,126,
-  126,  2,  2,126,126,126,126,126,126,126,  2,  2,  2,  2,126,126,
-  126,126,126,126,126,  2,142,142,142,142,142,142,142,142,142,142,
-  142,142,  2,  2,  2,  2,125,125,125,125,125,125,125,125,125,125,
-  125,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,125,154,154,
-  154,154,154,154,154,  2,  2,154,  2,  2,154,154,154,154,154,154,
-  154,154,  2,154,154,  2,154,154,154,154,154,154,154,154,154,154,
-  154,154,154,154,  2,154,154,  2,  2,154,154,154,154,154,154,154,
-    2,  2,  2,  2,  2,  2,150,150,150,150,150,150,150,150,  2,  2,
-  150,150,150,150,150,150,150,150,150,150,150,  2,  2,  2,141,141,
-  141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140,
-  140,  2,  2,  2,  2,  2,121,121,121,121,121,121,121,121,121,  2,
-    2,  2,  2,  2,  2,  2,  7,  7,  2,  2,  2,  2,  2,  2,133,133,
-  133,133,133,133,133,133,133,  2,133,133,133,133,133,133,133,133,
-  133,133,133,133,133,  2,133,133,133,133,133,133,  2,  2,133,133,
-  133,133,133,  2,  2,  2,134,134,134,134,134,134,134,134,  2,  2,
-  134,134,134,134,134,134,  2,134,134,134,134,134,134,134,134,134,
-  134,134,134,134,134,  2,138,138,138,138,138,138,138,  2,138,138,
-    2,138,138,138,138,138,138,138,138,138,138,138,138,138,  2,  2,
-  138,  2,138,138,  2,138,138,138,  2,  2,  2,  2,  2,  2,143,143,
-  143,143,143,143,  2,143,143,  2,143,143,143,143,143,143,143,143,
-  143,143,143,143,143,143,143,143,143,143,143,143,143,  2,143,143,
-    2,143,143,143,143,143,143,  2,  2,  2,  2,  2,  2,  2,143,143,
-    2,  2,  2,  2,  2,  2,145,145,145,145,145,145,145,145,145,  2,
-    2,  2,  2,  2,  2,  2,163,163,163,163,163,163,163,163,163,  2,
-  163,163,163,163,163,163,163,163,163,  2,  2,  2,163,163,163,163,
-    2,  2,  2,  2,  2,  2, 86,  2,  2,  2,  2,  2,  2,  2, 22, 22,
-    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 22, 63, 63,
-   63, 63, 63, 63, 63, 63, 63, 63,  2,  2,  2,  2,  2,  2, 63, 63,
-   63, 63, 63, 63, 63,  2, 63, 63, 63, 63, 63,  2,  2,  2, 63, 63,
-   63, 63,  2,  2,  2,  2,157,157,157,157,157,157,157,157,157,157,
-  157,  2,  2,  2,  2,  2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
-   80, 80, 80, 80,  2,  2,127,127,127,127,127,127,127,127,127,127,
-  127,127,127,127,127,  2, 79,  2,  2,  2,  2,  2,  2,  2,115,115,
-  115,115,115,115,115,115,115,115,115,115,115,115,115,  2,115,115,
-    2,  2,  2,  2,115,115,159,159,159,159,159,159,159,159,159,159,
-  159,159,159,159,159,  2,159,159,  2,  2,  2,  2,  2,  2,103,103,
-  103,103,103,103,103,103,103,103,103,103,103,103,  2,  2,119,119,
-  119,119,119,119,119,119,119,119,119,119,119,119,  2,  2,119,119,
-    2,119,119,119,119,119,  2,  2,  2,  2,  2,119,119,119,146,146,
-  146,146,146,146,146,146,146,146,146,  2,  2,  2,  2,  2, 99, 99,
-   99, 99, 99, 99, 99, 99, 99, 99, 99,  2,  2,  2,  2, 99,  2,  2,
-    2,  2,  2,  2,  2, 99,136,139, 13, 13,155,  2,  2,  2,136,136,
-  136,136,136,136,136,136,155,155,155,155,155,155,155,155,155,155,
-  155,155,155,155,  2,  2,136,  2,  2,  2,  2,  2,  2,  2, 17, 17,
-   17, 17,  2, 17, 17, 17, 17, 17, 17, 17,  2, 17, 17,  2, 17, 15,
-   15, 15, 15, 15, 15, 15, 17, 17, 17,  2,  2,  2,  2,  2,  2,  2,
-   15,  2,  2,  2,  2,  2, 15, 15, 15,  2,  2, 17,  2,  2,  2,  2,
-    2,  2, 17, 17, 17, 17,139,139,139,139,139,139,139,139,139,139,
-  139,139,  2,  2,  2,  2,105,105,105,105,105,105,105,105,105,105,
-  105,  2,  2,  2,  2,  2,105,105,105,105,105,  2,  2,  2,105,  2,
-    2,  2,  2,  2,  2,  2,105,105,  2,  2,105,105,105,105,  1,  1,
-    1,  1,  1,  1,  2,  2,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,
-    1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,
-    1,  1,  1,  1,  0,  0,  2,  2,  0,  2,  2,  0,  0,  2,  2,  0,
-    0,  0,  0,  2,  0,  0,  0,  0,  2,  0,  2,  0,  0,  0,  0,  0,
-    0,  0,  2,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,  0,
-    2,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  2,  0,  2,  2,  2,
-    0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,131,131,
-  131,131,131,131,131,131,131,131,131,131,  2,  2,  2,  2,  2,  2,
-    2,131,131,131,131,131,  2,131,131,131,131,131,131,131,  2,  2,
-    2,  2,  2, 19, 19, 19, 56, 56, 56, 56, 56, 56, 56,  2, 56,  2,
-    2, 56, 56, 56, 56, 56, 56, 56,  2, 56, 56,  2, 56, 56, 56, 56,
-   56,  2,  2,  2,  2,  2,  6,  6,  6,  6,  6,  6,  2,  2,  2,  2,
-    2,  2,  2,  2,  2,  6,151,151,151,151,151,151,151,151,151,151,
-  151,151,151,  2,  2,  2,151,151,151,151,151,151,  2,  2,151,151,
-    2,  2,  2,  2,151,151,160,160,160,160,160,160,160,160,160,160,
-  160,160,160,160,160,  2,152,152,152,152,152,152,152,152,152,152,
-    2,  2,  2,  2,  2,152,164,164,164,164,164,164,164,164,164,164,
-    2,  2,  2,  2,  2,  2, 30, 30, 30, 30,  2, 30, 30,  2,113,113,
-  113,113,113,113,113,113,113,113,113,113,113,  2,  2,113,113,113,
-  113,113,113,113,113,  2,132,132,132,132,132,132,132,132,132,132,
-  132,132,  2,  2,  2,  2,132,132,  2,  2,  2,  2,132,132,  3,  3,
-    3,  3,  2,  3,  3,  3,  2,  3,  3,  2,  3,  2,  2,  3,  2,  3,
-    3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,  2,  3,
-    2,  3,  2,  2,  2,  2,  2,  2,  3,  2,  2,  2,  2,  3,  2,  3,
-    2,  3,  2,  3,  3,  3,  2,  3,  2,  3,  2,  3,  2,  3,  2,  3,
-    3,  3,  3,  2,  3,  2,  3,  3,  2,  3,  3,  3,  3,  3,  3,  3,
-    3,  3,  2,  2,  2,  2,  2,  3,  3,  3,  2,  3,  3,  3,  2,  2,
-    2,  2,  2,  2,  0,  0, 15,  0,  0,  2,  2,  2,  2,  2,  2,  2,
-    2,  2,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0, 13,  2,
-    2,  2,  2,  2,  2,  2, 13, 13, 13,  2,  2,  2,  2,  2,  2,  0,
-    2,  2,  2,  2,  2,  2,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
-    9,  9,  9, 10,  9, 11, 12, 13,  9,  9,  9, 14,  9,  9, 15,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9, 16, 17,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 18, 19,
-   20,  9, 21,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 22,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9, 23, 24,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12,  0,  0, 13, 14,
-   15, 16, 17, 18, 19, 20, 21, 22,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0, 23,  0,  0, 24, 25, 26, 27, 28,
-   29, 30,  0,  0, 31, 32,  0, 33,  0, 34,  0, 35,  0,  0,  0,  0,
-   36, 37, 38, 39,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0, 40,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-   41, 42,  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,  0,  0,  0, 43, 44,  0, 45,  0,  0,  0,  0,  0,  0,
-   46, 47,  0,  0,  0,  0,  0, 48,  0, 49,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0, 50, 51,  0,  0,  0, 52,  0,  0,
-   53,  0,  0,  0,  0,  0,  0,  0, 54,  0,  0,  0,  0,  0,  0,  0,
-   55,  0,  0,  0,  0,  0,  0,  0, 56,  0,  0,  0,  0,  0,  0,  0,
-    0, 57,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0, 58, 59, 60, 61, 62, 63, 64, 65,
-    0,  0,  0,  0,  0,  0, 66,  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,  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,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0, 67, 68,  0, 69, 70,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
-   83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
-   99,100,101,102,103,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,104,  0,  0,  0,  0,  0,  0,105,106,  0,
-  107,  0,  0,  0,108,  0,109,  0,110,  0,111,112,113,  0,114,  0,
-    0,  0,115,  0,  0,  0,116,  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,117,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,118,119,120,121,  0,122,123,124,
-  125,126,  0,127,  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,128,129,130,131,132,133,134,135,136,137,138,139,
-  140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,
-  156,157,  0,  0,  0,158,159,160,161,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,162,163,  0,
-    0,  0,  0,  0,  0,  0,164,  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,165,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,166,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,167,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,168,  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,169,170,  0,  0,  0,  0,171,
-  172,  0,  0,  0,173,174,175,176,177,178,179,180,181,182,183,184,
-  185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,
-  201,202,203,204,205,206,  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,
-    1,  2,  3,  4,
-};
-static const uint16_t
-_hb_ucd_u16[9320] =
-{
-     0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
-    13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
-    13,  13,  13,  24,  25,  11,  11,  11,  11,  26,  11,  27,  28,  29,  30,  31,
-    32,  32,  32,  32,  32,  32,  32,  33,  34,  35,  36,  11,  37,  38,  13,  39,
-     9,   9,   9,  11,  11,  11,  13,  13,  40,  13,  13,  13,  41,  13,  13,  13,
-    13,  13,  13,  42,   9,  43,  11,  11,  44,  45,  32,  46,  47,  48,  49,  50,
-    51,  52,  48,  48,  53,  32,  54,  55,  48,  48,  48,  48,  48,  56,  57,  58,
-    59,  60,  48,  32,  61,  48,  48,  48,  48,  48,  62,  63,  64,  48,  65,  66,
-    48,  67,  68,  69,  48,  70,  71,  48,  72,  73,  48,  48,  74,  32,  75,  32,
-    76,  48,  48,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
-    90,  83,  84,  91,  92,  93,  94,  95,  96,  97,  84,  98,  99, 100,  88, 101,
-   102,  83,  84, 103, 104, 105,  88, 106, 107, 108, 109, 110, 111, 112,  94, 113,
-   114, 115,  84, 116, 117, 118,  88, 119, 120, 115,  84, 121, 122, 123,  88, 124,
-   125, 115,  48, 126, 127, 128,  88, 129, 130, 131,  48, 132, 133, 134,  94, 135,
-   136,  48,  48, 137, 138, 139, 140, 140, 141,  48, 142, 143, 144, 145, 140, 140,
-   146, 147, 148, 149, 150,  48, 151, 152, 153, 154,  32, 155, 156, 157, 140, 140,
-    48,  48, 158, 159, 160, 161, 162, 163, 164, 165,   9,   9, 166,  11,  11, 167,
-    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 168, 169,  48,  48,
-   168,  48,  48, 170, 171, 172,  48,  48,  48, 171,  48,  48,  48, 173, 174, 175,
-    48, 176,   9,   9,   9,   9,   9, 177, 178,  48,  48,  48,  48,  48,  48,  48,
-    48,  48,  48,  48,  48,  48, 179,  48, 180, 181,  48,  48,  48,  48, 182, 183,
-    48, 184,  48, 185,  48, 186, 187, 188,  48,  48,  48, 189, 190, 191, 192, 193,
-   194, 192,  48,  48, 195,  48,  48, 196, 197,  48, 198,  48,  48,  48,  48, 199,
-    48, 200, 201, 202, 203,  48, 204, 205,  48,  48, 206,  48, 207, 208, 209, 209,
-    48, 210,  48,  48,  48, 211, 212, 213, 192, 192, 214, 215, 216, 140, 140, 140,
-   217,  48,  48, 218, 219, 160, 220, 221, 222,  48, 223,  64,  48,  48, 224, 225,
-    48,  48, 226, 227, 228,  64,  48, 229, 230,   9,   9, 231, 232, 233, 234, 235,
-    11,  11, 236,  27,  27,  27, 237, 238,  11, 239,  27,  27,  32,  32,  32,  32,
-    13,  13,  13,  13,  13,  13,  13,  13,  13, 240,  13,  13,  13,  13,  13,  13,
-   241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250,
-   251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265,
-   266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278,
-   279, 279, 279, 279, 279, 279, 279, 279, 280, 209, 281, 209, 209, 209, 209, 282,
-   209, 283, 279, 284, 209, 285, 286, 209, 209, 209, 287, 140, 288, 140, 271, 271,
-   271, 289, 209, 209, 209, 209, 290, 271, 209, 209, 209, 209, 209, 209, 209, 209,
-   209, 209, 209, 291, 292, 209, 209, 293, 209, 209, 209, 209, 209, 209, 294, 209,
-   209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279,
-   300, 301, 279, 279, 279, 302, 279, 303, 209, 209, 209, 279, 304, 209, 209, 305,
-   209, 306, 209, 209, 209, 209, 209, 209,   9,   9,   9,  11,  11,  11, 307, 308,
-    13,  13,  13,  13,  13,  13, 309, 310,  11,  11, 311,  48,  48,  48, 312, 313,
-    48, 314, 315, 315, 315, 315,  32,  32, 316, 317, 318, 319, 320, 321, 140, 140,
-   209, 322, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 324, 140, 325,
-   326, 327, 328, 329, 136,  48,  48,  48,  48, 330, 178,  48,  48,  48,  48, 331,
-   332,  48,  48, 136,  48,  48,  48,  48, 200, 333,  48,  48, 209, 209, 323,  48,
-   209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209,
-    48,  48,  48,  48, 209, 209, 209, 209,  48, 338,  48,  48,  48,  48,  48,  48,
-   151, 209, 209, 209, 287,  48,  48, 229, 339,  48, 340, 140,  13,  13, 341, 342,
-    13, 343,  48,  48,  48,  48, 344, 345,  31, 346, 347, 348,  13,  13,  13, 349,
-   350, 351, 352, 353, 354, 355, 140, 356, 357,  48, 358, 359,  48,  48,  48, 360,
-   361,  48,  48, 362, 363, 192,  32, 364,  64,  48, 365,  48, 366, 367,  48, 151,
-    76,  48,  48, 368, 369, 370, 371, 372,  48,  48, 373, 374, 375, 376,  48, 377,
-    48,  48,  48, 378, 379, 380, 381, 382, 383, 384, 315,  11,  11, 385, 386,  11,
-    11,  11,  11,  11,  48,  48, 387, 192,  48,  48, 388,  48, 389,  48,  48, 206,
-   390, 390, 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391,
-    48,  48,  48,  48,  48,  48, 204,  48,  48,  48,  48,  48,  48, 207, 140, 140,
-   392, 393, 394, 395, 396,  48,  48,  48,  48,  48,  48, 397, 398, 399,  48,  48,
-    48,  48,  48, 400, 209,  48,  48,  48,  48, 401,  48,  48, 402, 140, 140, 403,
-    32, 404,  32, 405, 406, 407, 408, 409,  48,  48,  48,  48,  48,  48,  48, 410,
-   411,   2,   3,   4,   5, 412, 413, 414,  48, 415,  48, 200, 416, 417, 418, 419,
-   420,  48, 172, 421, 204, 204, 140, 140,  48,  48,  48,  48,  48,  48,  48,  71,
-   422, 271, 271, 423, 272, 272, 272, 424, 425, 426, 427, 140, 140, 209, 209, 428,
-   140, 140, 140, 140, 140, 140, 140, 140,  48, 151,  48,  48,  48, 100, 429, 430,
-    48,  48, 431,  48, 432,  48,  48, 433,  48, 434,  48,  48, 435, 436, 140, 140,
-     9,   9, 437,  11,  11,  48,  48,  48,  48, 204, 192,   9,   9, 438,  11, 439,
-    48,  48, 440,  48,  48,  48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140,
-    48,  48,  48, 314,  48, 199, 440, 140, 446,  27,  27, 447, 140, 140, 140, 140,
-   448,  48,  48, 449,  48, 450,  48, 451,  48, 200, 452, 140, 140, 140,  48, 453,
-    48, 454,  48, 455, 140, 140, 140, 140,  48,  48,  48, 456, 271, 457, 271, 271,
-   458, 459,  48, 460, 461, 462,  48, 463,  48, 464, 140, 140, 465,  48, 466, 467,
-    48,  48,  48, 468,  48, 469,  48, 470,  48, 471, 472, 140, 140, 140, 140, 140,
-    48,  48,  48,  48, 196, 140, 140, 140,   9,   9,   9, 473,  11,  11,  11, 474,
-    48,  48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 476,
-    48,  48, 477, 478, 140, 140, 140, 479,  48, 464, 480,  48,  62, 481, 140,  48,
-   482, 140, 140,  48, 483, 140,  48, 314, 484,  48,  48, 485, 486, 457, 487, 488,
-   222,  48,  48, 489, 490,  48, 196, 192, 491,  48, 492, 493, 494,  48,  48, 495,
-   222,  48,  48, 496, 497, 498, 499, 500,  48,  97, 501, 502, 503, 140, 140, 140,
-   504, 505, 506,  48,  48, 507, 508, 192, 509,  83,  84, 510, 511, 512, 513, 514,
-    48,  48,  48, 515, 516, 517, 478, 140,  48,  48,  48, 518, 519, 192, 140, 140,
-    48,  48, 520, 521, 522, 523, 140, 140,  48,  48,  48, 524, 525, 192, 526, 140,
-    48,  48, 527, 528, 192, 140, 140, 140,  48, 173, 529, 530, 314, 140, 140, 140,
-    48,  48, 501, 531, 140, 140, 140, 140, 140, 140,   9,   9,  11,  11, 148, 532,
-   533, 534,  48, 535, 536, 192, 140, 140, 140, 140, 537,  48,  48, 538, 539, 140,
-   540,  48,  48, 541, 542, 543,  48,  48, 544, 545, 546,  48,  48,  48,  48, 196,
-   547, 140, 140, 140, 140, 140, 140, 140,  84,  48, 520, 548, 549, 148, 175, 550,
-    48, 551, 552, 553, 140, 140, 140, 140, 554,  48,  48, 555, 556, 192, 557,  48,
-   558, 559, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 560,
-   561, 115,  48, 562, 563, 192, 140, 140, 140, 140, 140, 100, 271, 564, 565, 566,
-    48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 567, 568,
-    48,  48,  48,  48, 388, 140, 140, 140, 140,  48,  48,  48,  48,  48,  48, 569,
-    48,  48,  48, 570, 571, 572, 140, 140,  48,  48,  48,  48, 314, 140, 140, 140,
-    48,  48,  48, 196,  48, 200, 370,  48,  48,  48,  48, 200, 192,  48, 204, 573,
-    48,  48,  48, 574, 575, 576, 577, 578,  48, 140, 140, 140, 140, 140, 140, 140,
-   140, 140, 140, 140,   9,   9,  11,  11, 271, 579, 140, 140, 140, 140, 140, 140,
-    48,  48,  48,  48, 580, 581, 582, 582, 583, 584, 140, 140, 140, 140, 585, 586,
-    48,  48,  48,  48,  48,  48,  48, 440,  48,  48,  48,  48,  48, 199, 140, 140,
-   196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 587,
-    48,  48, 588, 589, 140, 590, 591,  48,  48,  48,  48,  48,  48,  48,  48, 206,
-    48,  48,  48,  48,  48,  48,  71, 151, 196, 592, 593, 140, 140, 140, 140, 140,
-    32,  32, 594,  32, 595, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
-   209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 596, 209, 209, 209, 597, 598,
-   599, 209, 600, 209, 209, 209, 288, 140, 209, 209, 209, 209, 601, 140, 140, 140,
-   140, 140, 140, 140, 271, 602, 271, 602, 209, 209, 209, 209, 209, 287, 271, 461,
-     9, 603,  11, 604, 605, 606, 241,   9, 607, 608, 609, 610, 611,   9, 603,  11,
-   612, 613,  11, 614, 615, 616, 617,   9, 618,  11,   9, 603,  11, 604, 605,  11,
-   241,   9, 607, 617,   9, 618,  11,   9, 603,  11, 619,   9, 620, 621, 622, 623,
-    11, 624,   9, 625, 626, 627, 628,  11, 629,   9, 630,  11, 631, 632, 632, 632,
-    32,  32,  32, 633,  32,  32, 634, 635, 636, 637,  45, 140, 140, 140, 140, 140,
-   638, 639, 640, 140, 140, 140, 140, 140, 641, 642, 643,  27,  27,  27, 644, 140,
-   645, 140, 140, 140, 140, 140, 140, 140,  48,  48, 151, 646, 647, 140, 140, 140,
-   140,  48, 648, 140,  48,  48, 649, 650, 140, 140, 140, 140, 140,  48, 651, 192,
-   140, 140, 140, 140, 140, 140, 652, 200,  48,  48,  48,  48, 653, 595, 140, 140,
-     9,   9, 607,  11, 654, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 499,
-   271, 271, 655, 656, 140, 140, 140, 140, 499, 271, 657, 658, 140, 140, 140, 140,
-   659,  48, 660, 661, 662, 663, 664, 665, 666, 206, 667, 206, 140, 140, 140, 668,
-   209, 209, 325, 209, 209, 209, 209, 209, 209, 323, 334, 669, 669, 669, 209, 324,
-   670, 209, 209, 209, 209, 209, 209, 209, 209, 209, 671, 140, 140, 140, 672, 209,
-   673, 209, 209, 325, 674, 675, 324, 140, 209, 209, 209, 209, 209, 209, 209, 676,
-   209, 209, 209, 209, 209, 677, 426, 426, 209, 209, 209, 209, 209, 209, 209, 678,
-   209, 209, 209, 209, 209, 176, 325, 427, 325, 209, 209, 209, 679, 176, 209, 209,
-   679, 209, 671, 675, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 671, 426,
-   674, 209, 209, 680, 681, 325, 674, 674, 209, 682, 209, 209, 288, 140, 140, 192,
-    48,  48,  48,  48,  48,  48, 140, 140,  48,  48,  48, 207,  48,  48,  48,  48,
-    48, 204,  48,  48,  48,  48,  48,  48,  48,  48, 478,  48,  48,  48,  48,  48,
-    48,  48,  48,  48,  48,  48, 100, 140,  48, 204, 140, 140, 140, 140, 140, 140,
-    48,  48,  48,  48,  71,  48,  48,  48,  48,  48,  48, 140, 140, 140, 140, 140,
-   683, 140, 570, 570, 570, 570, 570, 570,  32,  32,  32,  32,  32,  32,  32,  32,
-    32,  32,  32,  32,  32,  32,  32, 140, 391, 391, 391, 391, 391, 391, 391, 684,
-   391, 391, 391, 391, 391, 391, 391, 685,   0,   0,   0,   0,   0,   0,   0,   0,
-     1,   2,   2,   3,   1,   2,   2,   3,   0,   0,   0,   0,   0,   4,   0,   4,
-     2,   2,   5,   2,   2,   2,   5,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-     2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   6,
-     0,   0,   0,   0,   7,   8,   0,   0,   9,   9,   9,   9,   9,   9,   9,   9,
-     9,   9,   9,   9,   9,   9,  10,  11,  12,  13,  14,  14,  15,  14,  14,  14,
-    14,  14,  14,  14,  16,  17,  14,  14,  18,  18,  18,  18,  18,  18,  18,  18,
-    18,  18,  18,  18,  18,  18,  18,  18,  19,  18,  18,  18,  18,  18,  18,  18,
-    18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  20,  21,
-    21,  21,  22,  20,  21,  21,  21,  21,  21,  23,  24,  25,  25,  25,  25,  25,
-    25,  26,  25,  25,  25,  27,  28,  26,  29,  30,  31,  32,  31,  31,  31,  31,
-    33,  34,  35,  31,  31,  31,  36,  31,  31,  31,  31,  31,  31,  31,  31,  31,
-    31,  31,  31,  29,  31,  31,  31,  31,  37,  38,  37,  37,  37,  37,  37,  37,
-    37,  39,  31,  31,  31,  31,  31,  31,  40,  40,  40,  40,  40,  40,  41,  26,
-    42,  42,  42,  42,  42,  42,  42,  43,  44,  44,  44,  44,  44,  45,  44,  46,
-    47,  47,  47,  48,  37,  49,  31,  31,  31,  50,  51,  31,  31,  31,  31,  31,
-    31,  31,  31,  31,  52,  31,  31,  31,  53,  53,  53,  53,  53,  53,  53,  53,
-    53,  53,  54,  53,  55,  53,  53,  53,  56,  57,  58,  59,  59,  60,  61,  62,
-    57,  63,  64,  65,  66,  59,  59,  67,  68,  69,  70,  71,  71,  72,  73,  74,
-    69,  75,  76,  77,  78,  71,  79,  26,  80,  81,  82,  83,  83,  84,  85,  86,
-    81,  87,  88,  26,  89,  83,  90,  91,  92,  93,  94,  95,  95,  96,  97,  98,
-    93,  99, 100, 101, 102,  95,  95,  26, 103, 104, 105, 106, 107, 104, 108, 109,
-   104, 105, 110,  26, 111, 108, 108, 112, 113, 114, 115, 113, 113, 115, 113, 116,
-   114, 117, 118, 119, 120, 113, 121, 113, 122, 123, 124, 122, 122, 124, 125, 126,
-   123, 127, 128, 128, 129, 122, 130,  26, 131, 132, 133, 131, 131, 131, 131, 131,
-   132, 133, 134, 131, 135, 131, 131, 131, 136, 137, 138, 139, 137, 137, 140, 141,
-   138, 142, 143, 137, 144, 137, 145,  26, 146, 147, 147, 147, 147, 147, 147, 148,
-   147, 147, 147, 149,  26,  26,  26,  26, 150, 151, 152, 152, 153, 152, 152, 154,
-   155, 156, 152, 157,  26,  26,  26,  26, 158, 158, 158, 158, 158, 158, 158, 158,
-   158, 159, 158, 158, 158, 160, 159, 158, 158, 158, 158, 159, 158, 158, 158, 161,
-   158, 161, 162, 163,  26,  26,  26,  26, 164, 164, 164, 164, 164, 164, 164, 164,
-   164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 165, 165, 165, 165,
-   166, 167, 165, 165, 165, 165, 165, 168, 169, 169, 169, 169, 169, 169, 169, 169,
-   169, 169, 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 170, 170, 170,
-   170, 171, 172, 171, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 171, 172,
-   171, 170, 172, 170, 170, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 170,
-   170, 170, 170, 173, 170, 170, 170, 174, 170, 170, 170, 175, 176, 176, 176, 176,
-   176, 176, 176, 176, 176, 176, 177, 177, 178, 178, 178, 178, 178, 178, 178, 178,
-   178, 178, 178, 178, 178, 178, 178, 178, 179, 179, 179, 180, 181, 181, 181, 181,
-   181, 181, 181, 181, 181, 182, 181, 183, 184, 184, 185, 186, 187, 187, 188,  26,
-   189, 189, 190,  26, 191, 192, 193,  26, 194, 194, 194, 194, 194, 194, 194, 194,
-   194, 194, 194, 195, 194, 196, 194, 196, 197, 198, 198, 199, 198, 198, 198, 198,
-   198, 198, 198, 198, 198, 198, 198, 200, 198, 198, 198, 198, 198, 201, 178, 178,
-   178, 178, 178, 178, 178, 178, 202,  26, 203, 203, 203, 204, 203, 205, 203, 205,
-   206, 203, 207, 207, 207, 208, 209,  26, 210, 210, 210, 210, 210, 211, 210, 210,
-   210, 212, 210, 213, 194, 194, 194, 194, 214, 214, 214, 215, 216, 216, 216, 216,
-   216, 216, 216, 217, 216, 216, 216, 218, 216, 219, 216, 219, 216, 220,   9,   9,
-     9, 221,  26,  26,  26,  26,  26,  26, 222, 222, 222, 222, 222, 222, 222, 222,
-   222, 223, 222, 222, 222, 222, 222, 224, 225, 225, 225, 225, 225, 225, 225, 225,
-   226, 226, 226, 226, 226, 226, 227, 228, 229, 229, 229, 229, 229, 229, 229, 230,
-   229, 231, 232, 232, 232, 232, 232, 232,  18, 233, 165, 165, 165, 165, 165, 234,
-   225,  26, 235,   9, 236, 237, 238, 239,   2,   2,   2,   2, 240, 241,   2,   2,
-     2,   2,   2, 242, 243, 244,   2, 245,   2,   2,   2,   2,   2,   2,   2, 246,
-     9,   9,   9,   9,   9,   9,   9,   9,  14,  14, 247, 247,  14,  14,  14,  14,
-   247, 247,  14, 248,  14,  14,  14, 247,  14,  14,  14,  14,  14,  14, 249,  14,
-   249,  14, 250, 251,  14,  14, 252, 253,   0, 254,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0, 255,   0, 256, 257,   0, 258,   2, 259,   0,   0,   0,   0,
-   260,  26,   9,   9,   9,   9, 261,  26,   0,   0,   0,   0, 262, 263,   4,   0,
-     0, 264,   0,   0,   2,   2,   2,   2,   2, 265,   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,   0, 258,  26,  26,  26,
-     0, 266,  26,  26,   0,   0,   0,   0, 267, 267, 267, 267, 267, 267, 267, 267,
-   267, 267, 267, 267, 267, 267, 267, 267,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0, 268,   0,   0,   0, 269,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0, 270, 270, 270, 270, 270, 270, 270, 270,
-   270, 270, 270, 270,   2,   2,   2,   2,  17,  17,  17,  17,  17,  17,  17,  17,
-    17,  17,  17,  17,  17,  17, 271, 272, 165, 165, 165, 165, 166, 167, 273, 273,
-   273, 273, 273, 273, 273, 274, 275, 274, 170, 170, 172,  26, 172, 172, 172, 172,
-   172, 172, 172, 172,  18,  18,  18,  18,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0, 276,  26,  26,  26,  26, 277, 277, 277, 278, 277, 277, 277, 277,
-   277, 277, 277, 277, 277, 277, 279,  26, 277, 277, 277, 277, 277, 277, 277, 277,
-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
-   277, 277, 280,  26,  26,  26,   0, 281, 282,   0,   0,   0, 283, 284,   0, 285,
-   286, 287, 287, 287, 287, 287, 287, 287, 287, 287, 288, 289, 290, 291, 291, 291,
-   291, 291, 291, 291, 291, 291, 291, 292, 293, 294, 294, 294, 294, 294, 295, 169,
-   169, 169, 169, 169, 169, 169, 169, 169, 169, 296,   0,   0, 294, 294, 294, 294,
-     0,   0,   0,   0, 281,  26, 291, 291, 169, 169, 169, 296,   0,   0,   0,   0,
-     0,   0,   0,   0, 169, 169, 169, 297,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0, 291, 291, 291, 291, 291, 298, 291, 291, 291, 291, 291, 291, 291, 291,
-   291, 291, 291,   0,   0,   0,   0,   0, 277, 277, 277, 277, 277, 277, 277, 277,
-     0,   0,   0,   0,   0,   0,   0,   0, 299, 299, 299, 299, 299, 299, 299, 299,
-   299, 299, 299, 299, 299, 299, 299, 299, 299, 300, 299, 299, 299, 299, 299, 299,
-   301,  26, 302, 302, 302, 302, 302, 302, 303, 303, 303, 303, 303, 303, 303, 303,
-   303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 304,  26,  26,
-    18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18, 305, 305, 305, 305,
-   305, 305, 305, 305, 305, 305, 305,  26,   0,   0,   0,   0, 306,   2,   2,   2,
-     2,   2,   2,   2,   2,   2,   2,   2,   2, 307,   2,   2,   2,   2,   2,   2,
-     2, 308, 309, 310,  26,  26, 311,   2, 312, 312, 312, 312, 312, 313,   0, 314,
-   315, 315, 315, 315, 315, 315, 315,  26, 316, 316, 316, 316, 316, 316, 316, 316,
-   317, 318, 316, 319,  53,  53,  53,  53, 320, 320, 320, 320, 320, 321, 322, 322,
-   322, 322, 323, 324, 169, 169, 169, 325, 326, 326, 326, 326, 326, 326, 326, 326,
-   326, 327, 326, 328, 164, 164, 164, 329, 330, 330, 330, 330, 330, 330, 331,  26,
-   330, 332, 330, 333, 164, 164, 164, 164, 334, 334, 334, 334, 334, 334, 334, 334,
-   335,  26,  26, 336, 337, 337, 338,  26, 339, 339, 339,  26, 172, 172,   2,   2,
-     2,   2,   2, 340, 341, 342, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
-   337, 337, 337, 337, 337, 343, 337, 344, 169, 169, 169, 169, 345,  26, 169, 169,
-   296, 346, 169, 169, 169, 169, 169, 345,  26,  26,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26, 277, 277, 277, 277, 277, 277, 277, 277,
-   277, 277, 277, 277, 277, 280, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
-   277, 277, 277, 347,  26,  26,  26,  26, 348,  26, 349, 350,  25,  25, 351, 352,
-   353,  25,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,
-   354,  26, 355,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,
-    31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31, 356,
-    31,  31,  31,  31,  31,  31,  31,  31,  31,  31, 357,  31,  31,  31,  31,  31,
-    31, 358,  26,  26,  26,  26,  31,  31,   9,   9,   0, 314,   9, 359,   0,   0,
-     0,   0, 360,   0, 258, 281, 361,  31,  31,  31,  31,  31,  31,  31,  31,  31,
-    31,  31,  31,  31,  31,  31,  31, 362, 363,   0,   0,   0,   1,   2,   2,   3,
-     1,   2,   2,   3, 364, 291, 290, 291, 291, 291, 291, 365, 169, 169, 169, 296,
-   366, 366, 366, 367, 258, 258,  26, 368, 369, 370, 369, 369, 371, 369, 369, 372,
-   369, 373, 369, 373,  26,  26,  26,  26, 369, 369, 369, 369, 369, 369, 369, 369,
-   369, 369, 369, 369, 369, 369, 369, 374, 375,   0,   0,   0,   0,   0, 376,   0,
-    14,  14,  14,  14,  14,  14,  14,  14,  14, 253,   0, 377, 378,  26,  26,  26,
-    26,  26,   0,   0,   0,   0,   0, 379, 380, 380, 380, 381, 382, 382, 382, 382,
-   382, 382, 383,  26, 384,   0,   0, 281, 385, 385, 385, 385, 386, 387, 388, 388,
-   388, 389, 390, 390, 390, 390, 390, 391, 392, 392, 392, 393, 394, 394, 394, 394,
-   395, 394, 396,  26,  26,  26,  26,  26, 397, 397, 397, 397, 397, 397, 397, 397,
-   397, 397, 398, 398, 398, 398, 398, 398, 399, 399, 399, 400, 399, 401, 402, 402,
-   402, 402, 403, 402, 402, 402, 402, 403, 404, 404, 404, 404, 404,  26, 405, 405,
-   405, 405, 405, 405, 406, 407, 408, 409, 408, 409, 410, 408, 411, 408, 411, 412,
-    26,  26,  26,  26,  26,  26,  26,  26, 413, 413, 413, 413, 413, 413, 413, 413,
-   413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 414,  26,
-   413, 413, 415,  26, 413,  26,  26,  26, 416,   2,   2,   2,   2,   2, 417, 308,
-    26,  26,  26,  26,  26,  26,  26,  26, 418, 419, 420, 420, 420, 420, 421, 422,
-   423, 423, 424, 423, 425, 425, 425, 425, 426, 426, 426, 427, 428, 426,  26,  26,
-    26,  26,  26,  26, 429, 429, 430, 431, 432, 432, 432, 433, 434, 434, 434, 435,
-    26,  26,  26,  26,  26,  26,  26,  26, 436, 436, 436, 436, 437, 437, 437, 438,
-   437, 437, 439, 437, 437, 437, 437, 437, 440, 441, 442, 443, 444, 444, 445, 446,
-   444, 447, 444, 447, 448, 448, 448, 448, 449, 449, 449, 449,  26,  26,  26,  26,
-   450, 450, 450, 450, 451, 452, 451,  26, 453, 453, 453, 453, 453, 453, 454, 455,
-   456, 456, 457, 456, 458, 458, 459, 458, 460, 460, 461, 462,  26, 463,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26, 464, 464, 464, 464, 464, 464, 464, 464,
-   464, 465,  26,  26,  26,  26,  26,  26, 466, 466, 466, 466, 466, 466, 467,  26,
-   466, 466, 466, 466, 466, 466, 467, 468, 469, 469, 469, 469, 469,  26, 469, 470,
-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26,  31,  31,  31,  50, 471, 471, 471, 471, 471, 472, 473,  26,
-    26,  26,  26,  26,  26,  26,  26, 474, 475, 475, 475, 475, 475,  26, 476, 476,
-   476, 476, 476, 477,  26,  26, 478, 478, 478, 479,  26,  26,  26,  26, 480, 480,
-   480, 481,  26,  26, 482, 482, 483,  26, 484, 484, 484, 484, 484, 484, 484, 484,
-   484, 485, 486, 484, 484, 484, 485, 487, 488, 488, 488, 488, 488, 488, 488, 488,
-   489, 490, 491, 491, 491, 492, 491, 493, 494, 494, 494, 494, 494, 494, 495, 494,
-   494,  26, 496, 496, 496, 496, 497,  26, 498, 498, 498, 498, 498, 498, 498, 498,
-   498, 498, 498, 498, 499, 137, 500,  26, 501, 501, 502, 501, 501, 501, 501, 501,
-   503,  26,  26,  26,  26,  26,  26,  26, 504, 505, 506, 507, 506, 508, 509, 509,
-   509, 509, 509, 509, 509, 510, 509, 511, 512, 513, 514, 515, 515, 516, 517, 518,
-   513, 519, 520, 521, 522, 523, 523,  26, 524, 524, 524, 524, 524, 524, 524, 524,
-   524, 524, 524, 525, 526,  26,  26,  26, 527, 527, 527, 527, 527, 527, 527, 527,
-   527,  26, 527, 528,  26,  26,  26,  26, 529, 529, 529, 529, 529, 529, 530, 529,
-   529, 529, 529, 530,  26,  26,  26,  26, 531, 531, 531, 531, 531, 531, 531, 531,
-   532,  26, 531, 533, 198, 534,  26,  26, 535, 535, 535, 535, 535, 535, 535, 536,
-   535, 536,  26,  26,  26,  26,  26,  26, 537, 537, 537, 538, 537, 539, 537, 537,
-   540,  26,  26,  26,  26,  26,  26,  26, 541, 541, 541, 541, 541, 541, 541, 542,
-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 543, 543, 543, 543,
-   543, 543, 543, 543, 543, 543, 544, 545, 546, 547, 548, 549, 549, 549, 550, 551,
-   546,  26, 549, 552,  26,  26,  26,  26,  26,  26,  26,  26, 553, 554, 553, 553,
-   553, 553, 553, 554, 555,  26,  26,  26, 556, 556, 556, 556, 556, 556, 556, 556,
-   556,  26, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 558,  26, 178, 178,
-   559, 559, 559, 559, 559, 559, 559, 560,  53, 561,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26, 562, 563, 562, 562, 562, 562, 564, 562,
-   565,  26, 562, 562, 562, 566, 567, 567, 567, 567, 568, 567, 567, 569, 570,  26,
-    26,  26,  26,  26,  26,  26,  26,  26, 571, 572, 573, 573, 573, 573, 571, 574,
-   573,  26, 573, 575, 576, 577, 578, 578, 578, 579, 580, 581, 578, 582,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26, 583, 583, 583, 584, 585, 585, 586, 585, 585, 585, 585, 587,
-   585, 585, 585, 588,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 589,  26,
-   108, 108, 108, 108, 108, 108, 590, 591, 592, 592, 592, 592, 592, 592, 592, 592,
-   592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 593,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26, 592, 592, 592, 592, 592, 592, 592, 592,
-   592, 592, 592, 592, 592, 594, 595,  26, 592, 592, 592, 592, 592, 592, 592, 592,
-   596,  26,  26,  26,  26,  26,  26,  26,  26,  26, 597, 597, 597, 597, 597, 597,
-   597, 597, 597, 597, 597, 597, 598,  26, 599, 599, 599, 599, 599, 599, 599, 599,
-   599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599,
-   599, 599, 600,  26,  26,  26,  26,  26, 601, 601, 601, 601, 601, 601, 601, 601,
-   601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601,
-   602,  26,  26,  26,  26,  26,  26,  26, 305, 305, 305, 305, 305, 305, 305, 305,
-   305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 603,
-   604, 604, 604, 605, 604, 606, 607, 607, 607, 607, 607, 607, 607, 607, 607, 608,
-   607, 609, 610, 610, 610, 611, 611,  26, 612, 612, 612, 612, 612, 612, 612, 612,
-   613,  26, 612, 614, 614, 612, 612, 615, 612, 612,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-   616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 617,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26, 618, 618, 618, 618, 618, 618, 618, 618,
-   618, 619, 618, 618, 618, 618, 618, 618, 618, 620, 618, 618,  26,  26,  26,  26,
-    26,  26,  26,  26, 621,  26, 347,  26, 622, 622, 622, 622, 622, 622, 622, 622,
-   622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622,
-   622, 622, 622, 622, 622, 622, 622,  26, 623, 623, 623, 623, 623, 623, 623, 623,
-   623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623,
-   623, 623, 624,  26,  26,  26,  26,  26, 622, 625,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26, 626, 627, 628, 287, 287, 287, 287, 287, 287, 287,
-   287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
-   287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 629,  26, 630,  26,
-    26,  26, 631,  26, 632,  26, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633,
-   633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633,
-   633, 633, 633, 633, 633, 633, 633, 634, 635, 635, 635, 635, 635, 635, 635, 635,
-   635, 635, 635, 635, 635, 636, 635, 637, 635, 638, 635, 639, 281,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26,   9,   9,   9,   9,   9, 640,   9,   9,
-   221,  26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   281,  26,  26,  26,  26,  26,  26,  26,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0, 276,  26,   0,   0,   0,   0, 258, 363,   0,   0,
-     0,   0,   0,   0, 641, 642,   0, 643, 644, 645,   0,   0,   0, 646,   0,   0,
-     0,   0,   0,   0,   0, 266,  26,  26,  14,  14,  14,  14,  14,  14,  14,  14,
-   247,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-     0,   0, 281,  26,   0,   0, 281,  26,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0, 258,  26,   0,   0,   0, 260,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0, 255,   0,   0,   0,   0,   0,   0,   0,   0, 255, 647, 648,   0, 649,
-   650,   0,   0,   0,   0,   0,   0,   0, 269, 651, 255, 255,   0,   0,   0, 652,
-   653, 654, 655,   0,   0,   0,   0,   0,   0,   0,   0,   0, 276,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0, 268,   0,   0,   0,   0,   0,   0, 656, 656, 656, 656, 656, 656, 656, 656,
-   656, 656, 656, 656, 656, 656, 656, 656, 656, 657,  26, 658, 659, 656,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26,   2,   2,   2, 348, 660, 308,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26, 661, 270, 270, 662, 663, 664,  18,  18,
-    18,  18,  18,  18,  18, 665,  26,  26,  26, 666,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26, 667, 667, 667, 667, 667, 668, 667, 669,
-   667, 670,  26,  26,  26,  26,  26,  26,  26,  26, 671, 671, 671, 672,  26,  26,
-   673, 673, 673, 673, 673, 673, 673, 674,  26,  26,  26,  26,  26,  26,  26,  26,
-    26,  26, 675, 675, 675, 675, 675, 676,  26,  26,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26, 172, 677, 170, 172, 678, 678, 678, 678, 678, 678, 678, 678,
-   678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678,
-   679, 678, 680,  26,  26,  26,  26,  26, 681, 681, 681, 681, 681, 681, 681, 681,
-   681, 682, 681, 683,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26, 363,   0,   0,   0,   0,   0,   0,   0, 377,  26,
-    26,  26,  26,  26,  26,  26,  26,  26, 363,   0,   0,   0,   0,   0,   0, 276,
-    26,  26,  26,  26,  26,  26,  26,  26, 684,  31,  31,  31, 685, 686, 687, 688,
-   689, 690, 685, 691, 685, 687, 687, 692,  31, 693,  31, 694, 695, 693,  31, 694,
-    26,  26,  26,  26,  26,  26,  51,  26,   0,   0,   0,   0,   0, 281,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 281,  26,   0, 258, 363,   0,
-   363,   0, 363,   0,   0,   0, 276,  26,   0,   0,   0,   0,   0, 276,  26,  26,
-    26,  26,  26,  26, 696,   0,   0,   0, 697,  26,   0,   0,   0,   0,   0, 281,
-     0, 260, 314,  26, 276,  26,  26,  26,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0, 698,   0, 377,   0, 377,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0, 258, 699,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0, 314,   0, 281, 260,  26,   0, 281,   0,   0,   0,   0,   0,   0,
-     0,  26,   0, 314,   0,   0,   0,   0,   0,  26,   0,   0,   0, 276, 314,  26,
-    26,  26,  26,  26,  26,  26,  26,  26,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0, 281,  26,   0, 276,   0, 377,   0, 260,   0,   0,   0,   0,   0, 269,
-   276, 696,   0, 281,   0, 260,   0, 260,   0,   0, 360,   0,   0,   0,   0,   0,
-     0, 266,  26,  26,  26,  26,   0, 314, 277, 277, 277, 277, 277, 277, 277, 277,
-   277, 277, 277, 277,  26,  26,  26,  26, 277, 277, 277, 277, 277, 277, 277, 347,
-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 280, 277, 277, 277, 277,
-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 347,  26, 277, 277,
-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
-   277, 277, 277, 277, 700,  26,  26,  26, 277, 277, 277, 280,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26, 277, 277, 277, 277, 277, 277, 277, 277,
-   277, 701, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26, 702,  26,  26,  26,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   9,   9,   9,   9,   9,   9,   9,   9,
-     9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,
-     9,   9,   9,   9,   9,   9,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0, 939, 940, 941, 942, 946, 948,   0, 962,
-   969, 970, 971, 976,1001,1002,1003,1008,   0,1033,1040,1041,1042,1043,1047,   0,
-     0,1080,1081,1082,1086,1110,   0,   0,1124,1125,1126,1127,1131,1133,   0,1147,
-  1154,1155,1156,1161,1187,1188,1189,1193,   0,1219,1226,1227,1228,1229,1233,   0,
-     0,1267,1268,1269,1273,1298,   0,1303, 943,1128, 944,1129, 954,1139, 958,1143,
-   959,1144, 960,1145, 961,1146, 964,1149,   0,   0, 973,1158, 974,1159, 975,1160,
-   983,1168, 978,1163, 988,1173, 990,1175, 991,1176, 993,1178, 994,1179,   0,   0,
-  1004,1190,1005,1191,1006,1192,1014,1199,1007,   0,   0,   0,1016,1201,1020,1206,
-     0,1022,1208,1025,1211,1023,1209,   0,   0,   0,   0,1032,1218,1037,1223,1035,
-  1221,   0,   0,   0,1044,1230,1045,1231,1049,1235,   0,   0,1058,1244,1064,1250,
-  1060,1246,1066,1252,1067,1253,1072,1258,1069,1255,1077,1264,1074,1261,   0,   0,
-  1083,1270,1084,1271,1085,1272,1088,1275,1089,1276,1096,1283,1103,1290,1111,1299,
-  1115,1118,1307,1120,1309,1121,1310,   0,1053,1239,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,1093,1280,   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, 949,1134,1010,1195,1050,1236,1090,1277,1341,1368,1340,
-  1367,1342,1369,1339,1366,   0,1320,1347,1418,1419,1323,1350,   0,   0, 992,1177,
-  1018,1204,1055,1241,1416,1417,1415,1424,1202,   0,   0,   0, 987,1172,   0,   0,
-  1031,1217,1321,1348,1322,1349,1338,1365, 950,1135, 951,1136, 979,1164, 980,1165,
-  1011,1196,1012,1197,1051,1237,1052,1238,1061,1247,1062,1248,1091,1278,1092,1279,
-  1071,1257,1076,1263,   0,   0, 997,1182,   0,   0,   0,   0,   0,   0, 945,1130,
-   982,1167,1337,1364,1335,1362,1046,1232,1422,1423,1113,1301,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   8,   9,   0,  10,1425,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   7,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,1314,1427,   5,
-  1434,1438,1443,   0,1450,   0,1455,1461,1514,   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,1446,1458,1468,1476,1480,1486,1517,   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,1489,1503,1494,1500,1508,   0,   0,   0,   0,1520,1521,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,1526,1528,   0,1525,   0,   0,   0,1522,
-     0,   0,   0,   0,1536,1532,1539,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,1534,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,1556,   0,   0,   0,   0,   0,   0,1548,1550,   0,1547,   0,   0,   0,1567,
-     0,   0,   0,   0,1558,1554,1561,   0,   0,   0,   0,   0,   0,   0,1568,1569,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,1529,1551,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,1523,1545,1524,1546,   0,   0,1527,1549,
-     0,   0,1570,1571,1530,1552,1531,1553,   0,   0,1533,1555,1535,1557,1537,1559,
-     0,   0,1572,1573,1544,1566,1538,1560,1540,1562,1541,1563,1542,1564,   0,   0,
-  1543,1565,   0,   0,   0,   0,   0,   0,   0,   0,1606,1607,1609,1608,1610,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,1613,   0,1611,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1612,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,1620,   0,   0,   0,   0,   0,   0,   0,1623,   0,   0,1624,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  1614,1615,1616,1617,1618,1619,1621,1622,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,1628,1629,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,1625,1626,   0,1627,   0,   0,   0,1634,   0,   0,1635,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,1630,1631,1632,   0,   0,1633,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  1639,   0,   0,1638,1640,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,1636,1637,   0,   0,   0,   0,   0,   0,1641,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,1642,1644,1643,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  1645,   0,   0,   0,   0,   0,   0,   0,1646,   0,   0,   0,   0,   0,   0,1648,
-  1649,   0,1647,1650,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,1651,1653,1652,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,1654,   0,1655,1657,1656,   0,   0,   0,   0,1659,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,1660,   0,   0,   0,   0,1661,   0,   0,   0,   0,1662,
-     0,   0,   0,   0,1663,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,1658,   0,   0,   0,   0,   0,   0,   0,   0,   0,1664,   0,1665,1673,   0,
-  1674,   0,   0,   0,   0,   0,   0,   0,   0,1666,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1668,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,1669,   0,   0,   0,   0,1670,   0,   0,   0,   0,1671,
-     0,   0,   0,   0,1672,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,1667,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1675,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1676,   0,
-  1677,   0,1678,   0,1679,   0,1680,   0,   0,   0,1681,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,1682,   0,1683,   0,   0,1684,1685,   0,1686,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0, 953,1138, 955,1140, 956,1141, 957,1142,
-  1324,1351, 963,1148, 965,1150, 968,1153, 966,1151, 967,1152,1378,1380,1379,1381,
-   984,1169, 985,1170,1420,1421, 986,1171, 989,1174, 995,1180, 998,1183, 996,1181,
-   999,1184,1000,1185,1015,1200,1329,1356,1017,1203,1019,1205,1021,1207,1024,1210,
-  1687,1688,1027,1213,1026,1212,1028,1214,1029,1215,1030,1216,1034,1220,1036,1222,
-  1039,1225,1038,1224,1334,1361,1336,1363,1382,1384,1383,1385,1056,1242,1057,1243,
-  1059,1245,1063,1249,1689,1690,1065,1251,1068,1254,1070,1256,1386,1387,1388,1389,
-  1691,1692,1073,1259,1075,1262,1079,1266,1078,1265,1095,1282,1098,1285,1097,1284,
-  1390,1391,1392,1393,1099,1286,1100,1287,1101,1288,1102,1289,1105,1292,1104,1291,
-  1106,1294,1107,1295,1108,1296,1114,1302,1119,1308,1122,1311,1123,1312,1186,1260,
-  1293,1305,   0,1394,   0,   0,   0,   0, 952,1137, 947,1132,1317,1344,1316,1343,
-  1319,1346,1318,1345,1693,1695,1371,1375,1370,1374,1373,1377,1372,1376,1694,1696,
-   981,1166, 977,1162, 972,1157,1326,1353,1325,1352,1328,1355,1327,1354,1697,1698,
-  1009,1194,1013,1198,1054,1240,1048,1234,1331,1358,1330,1357,1333,1360,1332,1359,
-  1699,1700,1396,1401,1395,1400,1398,1403,1397,1402,1399,1404,1094,1281,1087,1274,
-  1406,1411,1405,1410,1408,1413,1407,1412,1409,1414,1109,1297,1117,1306,1116,1304,
-  1112,1300,   0,   0,   0,   0,   0,   0,1471,1472,1701,1705,1702,1706,1703,1707,
-  1430,1431,1715,1719,1716,1720,1717,1721,1477,1478,1729,1731,1730,1732,   0,   0,
-  1435,1436,1733,1735,1734,1736,   0,   0,1481,1482,1737,1741,1738,1742,1739,1743,
-  1439,1440,1751,1755,1752,1756,1753,1757,1490,1491,1765,1768,1766,1769,1767,1770,
-  1447,1448,1771,1774,1772,1775,1773,1776,1495,1496,1777,1779,1778,1780,   0,   0,
-  1451,1452,1781,1783,1782,1784,   0,   0,1504,1505,1785,1788,1786,1789,1787,1790,
-     0,1459,   0,1791,   0,1792,   0,1793,1509,1510,1794,1798,1795,1799,1796,1800,
-  1462,1463,1808,1812,1809,1813,1810,1814,1467,  21,1475,  22,1479,  23,1485,  24,
-  1493,  27,1499,  28,1507,  29,   0,   0,1704,1708,1709,1710,1711,1712,1713,1714,
-  1718,1722,1723,1724,1725,1726,1727,1728,1740,1744,1745,1746,1747,1748,1749,1750,
-  1754,1758,1759,1760,1761,1762,1763,1764,1797,1801,1802,1803,1804,1805,1806,1807,
-  1811,1815,1816,1817,1818,1819,1820,1821,1470,1469,1822,1474,1465,   0,1473,1825,
-  1429,1428,1426,  12,1432,   0,  26,   0,   0,1315,1823,1484,1466,   0,1483,1829,
-  1433,  13,1437,  14,1441,1826,1827,1828,1488,1487,1513,  19,   0,   0,1492,1515,
-  1445,1444,1442,  15,   0,1831,1832,1833,1502,1501,1516,  25,1497,1498,1506,1518,
-  1457,1456,1454,  17,1453,1313,  11,   3,   0,   0,1824,1512,1519,   0,1511,1830,
-  1449,  16,1460,  18,1464,   4,   0,   0,  30,  31,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  20,   0,
-     0,   0,   2,   6,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,1834,1835,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1836,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,1837,1839,1838,   0,   0,   0,   0,1840,   0,   0,   0,
-     0,1841,   0,   0,1842,   0,   0,   0,   0,   0,   0,   0,1843,   0,1844,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,1845,   0,   0,1846,   0,   0,1847,
-     0,1848,   0,   0,   0,   0,   0,   0, 937,   0,1850,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,1849, 936, 938,1851,1852,   0,   0,1853,1854,   0,   0,
-  1855,1856,   0,   0,   0,   0,   0,   0,1857,1858,   0,   0,1861,1862,   0,   0,
-  1863,1864,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,1867,1868,1869,1870,1859,1860,1865,1866,   0,   0,   0,   0,
-     0,   0,1871,1872,1873,1874,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,  32,  33,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,1875,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,1877,   0,1878,   0,1879,   0,1880,   0,1881,   0,1882,   0,
-  1883,   0,1884,   0,1885,   0,1886,   0,1887,   0,1888,   0,   0,1889,   0,1890,
-     0,1891,   0,   0,   0,   0,   0,   0,1892,1893,   0,1894,1895,   0,1896,1897,
-     0,1898,1899,   0,1900,1901,   0,   0,   0,   0,   0,   0,1876,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1902,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,1904,   0,1905,   0,1906,   0,1907,   0,1908,   0,1909,   0,
-  1910,   0,1911,   0,1912,   0,1913,   0,1914,   0,1915,   0,   0,1916,   0,1917,
-     0,1918,   0,   0,   0,   0,   0,   0,1919,1920,   0,1921,1922,   0,1923,1924,
-     0,1925,1926,   0,1927,1928,   0,   0,   0,   0,   0,   0,1903,   0,   0,1929,
-  1930,1931,1932,   0,   0,   0,1933,   0, 710, 385, 724, 715, 455, 103, 186, 825,
-   825, 242, 751, 205, 241, 336, 524, 601, 663, 676, 688, 738, 411, 434, 474, 500,
-   649, 746, 799, 108, 180, 416, 482, 662, 810, 275, 462, 658, 692, 344, 618, 679,
-   293, 388, 440, 492, 740, 116, 146, 168, 368, 414, 481, 527, 606, 660, 665, 722,
-   781, 803, 809, 538, 553, 588, 642, 758, 811, 701, 233, 299, 573, 612, 487, 540,
-   714, 779, 232, 267, 412, 445, 457, 585, 594, 766, 167, 613, 149, 148, 560, 589,
-   648, 768, 708, 345, 411, 704, 105, 259, 313, 496, 518, 174, 542, 120, 307, 101,
-   430, 372, 584, 183, 228, 529, 650, 697, 424, 732, 428, 349, 632, 355, 517, 110,
-   135, 147, 403, 580, 624, 700, 750, 170, 193, 245, 297, 374, 463, 543, 763, 801,
-   812, 815, 162, 384, 420, 730, 287, 330, 337, 366, 459, 476, 509, 558, 591, 610,
-   726, 652, 734, 759, 154, 163, 198, 473, 683, 697, 292, 311, 353, 423, 572, 494,
-   113, 217, 259, 280, 314, 499, 506, 603, 608, 752, 778, 782, 788, 117, 557, 748,
-   774, 320, 109, 126, 260, 265, 373, 411, 479, 523, 655, 737, 823, 380, 765, 161,
-   395, 398, 438, 451, 502, 516, 537, 583, 791, 136, 340, 769, 122, 273, 446, 727,
-   305, 322, 400, 496, 771, 155, 190, 269, 377, 391, 406, 432, 501, 519, 599, 684,
-   687, 749, 776, 175, 452, 191, 480, 510, 659, 772, 805, 813, 397, 444, 619, 566,
-   568, 575, 491, 471, 707, 111, 636, 156, 153, 288, 346, 578, 256, 435, 383, 729,
-   680, 767, 694, 295, 128, 210,   0,   0, 227,   0, 379,   0,   0, 150, 493, 525,
-   544, 551, 552, 556, 783, 576, 604,   0, 661,   0, 703,   0,   0, 735, 743,   0,
-     0,   0, 793, 794, 795, 808, 741, 773, 118, 127, 130, 166, 169, 177, 207, 213,
-   215, 226, 229, 268, 270, 317, 327, 329, 335, 369, 375, 381, 404, 441, 448, 458,
-   477, 484, 503, 539, 545, 547, 546, 548, 549, 550, 554, 555, 561, 564, 569, 591,
-   593, 595, 598, 607, 620, 625, 625, 651, 690, 695, 705, 706, 716, 717, 733, 735,
-   777, 786, 790, 315, 869, 623,   0,   0, 102, 145, 134, 115, 129, 138, 165, 171,
-   207, 202, 206, 212, 227, 231, 240, 243, 250, 254, 294, 296, 303, 308, 319, 325,
-   321, 329, 326, 335, 341, 357, 360, 362, 370, 379, 388, 389, 393, 421, 424, 438,
-   456, 454, 458, 465, 477, 535, 485, 490, 493, 507, 512, 514, 521, 522, 525, 526,
-   528, 533, 532, 541, 565, 569, 574, 586, 591, 597, 607, 637, 647, 674, 691, 693,
-   695, 698, 703, 699, 705, 704, 702, 706, 709, 717, 728, 736, 747, 754, 770, 777,
-   783, 784, 786, 787, 790, 802, 825, 848, 847, 857,  55,  65,  66, 883, 892, 916,
-   822, 824,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,1586,   0,1605,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,1602,1603,1934,1935,1574,1575,1576,1577,1579,1580,1581,1583,1584,   0,
-  1585,1587,1588,1589,1591,   0,1592,   0,1593,1594,   0,1595,1596,   0,1598,1599,
-  1600,1601,1604,1582,1578,1590,1597,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,1936,   0,1937,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,1938,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1939,1940,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,1941,1942,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,1944,1943,   0,1945,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,1946,1947,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  1948,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1949,1950,1951,1952,1953,1954,1955,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,1956,1957,1958,1960,1959,1961,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0, 106, 104, 107, 826, 114, 118, 119, 121,
-   123, 124, 127, 125,  34, 830, 130, 131, 132, 137, 827,  35, 133, 139, 829, 142,
-   143, 112, 144, 145, 924, 151, 152,  37, 157, 158, 159, 160,  38, 165, 166, 169,
-   171, 172, 173, 174, 176, 177, 178, 179, 181, 182, 182, 182, 833, 468, 184, 185,
-   834, 187, 188, 189, 196, 192, 194, 195, 197, 199, 200, 201, 203, 204, 204, 206,
-   208, 209, 211, 218, 213, 219, 214, 216, 153, 234, 221, 222, 223, 220, 225, 224,
-   230, 835, 235, 236, 237, 238, 239, 244, 836, 837, 247, 248, 249, 246, 251,  39,
-    40, 253, 255, 255, 838, 257, 258, 259, 261, 839, 262, 263, 301, 264,  41, 266,
-   270, 272, 271, 841, 274, 842, 277, 276, 278, 281, 282,  42, 283, 284, 285, 286,
-    43, 843,  44, 289, 290, 291, 293, 934, 298, 845, 845, 621, 300, 300,  45, 852,
-   894, 302, 304,  46, 306, 309, 310, 312, 316,  48,  47, 317, 846, 318, 323, 324,
-   325, 324, 328, 329, 333, 331, 332, 334, 335, 336, 338, 339, 342, 343, 347, 351,
-   849, 350, 348, 352, 354, 359, 850, 361, 358, 356,  49, 363, 365, 367, 364,  50,
-   369, 371, 851, 376, 386, 378,  53, 381,  52,  51, 140, 141, 387, 382, 614,  78,
-   388, 389, 390, 394, 392, 856,  54, 399, 396, 402, 404, 858, 405, 401, 407,  55,
-   408, 409, 410, 413, 859, 415,  56, 417, 860, 418,  57, 419, 422, 424, 425, 861,
-   840, 862, 426, 863, 429, 431, 427, 433, 437, 441, 438, 439, 442, 443, 864, 436,
-   449, 450,  58, 454, 453, 865, 447, 460, 866, 867, 461, 466, 465, 464,  59, 467,
-   470, 469, 472, 828, 475, 868, 478, 870, 483, 485, 486, 871, 488, 489, 872, 873,
-   495, 497,  60, 498,  61,  61, 504, 505, 507, 508, 511,  62, 513, 874, 515, 875,
-   518, 844, 520, 876, 877, 878,  63,  64, 528, 880, 879, 881, 882, 530, 531, 531,
-   533,  66, 534,  67,  68, 884, 536, 538, 541,  69, 885, 549, 886, 887, 556, 559,
-    70, 561, 562, 563, 888, 889, 889, 567,  71, 890, 570, 571,  72, 891, 577,  73,
-   581, 579, 582, 893, 587,  74, 590, 592, 596,  75, 895, 896,  76, 897, 600, 898,
-   602, 605, 607, 899, 900, 609, 901, 611, 853,  77, 615, 616,  79, 617, 252, 902,
-   903, 854, 855, 621, 622, 731,  80, 627, 626, 628, 164, 629, 630, 631, 633, 904,
-   632, 634, 639, 640, 635, 641, 646, 651, 638, 643, 644, 645, 905, 907, 906,  81,
-   653, 654, 656, 911, 657, 908,  82,  83, 909, 910,  84, 664, 665, 666, 667, 669,
-   668, 671, 670, 674, 672, 673, 675,  85, 677, 678,  86, 681, 682, 912, 685, 686,
-    87, 689,  36, 913, 914,  88,  89, 696, 702, 709, 711, 915, 712, 713, 718, 719,
-   917, 831, 721, 720, 723, 832, 725, 728, 918, 919, 739, 742, 744, 920, 745, 753,
-   756, 757, 755, 760, 761, 921, 762,  90, 764, 922,  91, 775, 279, 780, 923, 925,
-    92,  93, 785, 926,  94, 927, 787, 787, 789, 928, 792,  95, 796, 797, 798, 800,
-    96, 929, 802, 804, 806,  97,  98, 807, 930,  99, 931, 932, 933, 814, 100, 816,
-   817, 818, 819, 820, 821, 935,   0,   0,
-};
-static const int16_t
-_hb_ucd_i16[196] =
-{
-      0,    0,    0,    0,    1,   -1,    0,    0,    2,    0,   -2,    0,    0,    0,    0,    2,
-      0,   -2,    0,    0,    0,    0,    0,   16,    0,    0,    0,  -16,    0,    0,    1,   -1,
-      0,    0,    0,    1,   -1,    0,    0,    0,    0,    1,   -1,    0,    3,    3,    3,   -3,
-     -3,   -3,    0,    0,    0, 2016,    0,    0,    0,    0,    0, 2527, 1923, 1914, 1918,    0,
-   2250,    0,    0,    0,    0,    0,    0,  138,    0,    7,    0,    0,   -7,    0,    0,    0,
-      1,   -1,    1,   -1,   -1,    1,   -1,    0, 1824,    0,    0,    0,    0,    0, 2104,    0,
-   2108, 2106,    0, 2106, 1316,    0,    0,    0,    0,    1,   -1,    1,   -1, -138,    0,    0,
-      1,   -1,    8,    8,    8,    0,    7,    7,    0,    0,   -8,   -8,   -8,   -7,   -7,    0,
-      1,   -1,    0,    2,-1316,    1,   -1,    0,   -1,    1,   -1,    1,   -1,    3,    1,   -1,
-     -3,    1,   -1,    1,   -1,    0,    0,-1914,-1918,    0,    0,-1923,-1824,    0,    0,    0,
-      0,-2016,    0,    0,    1,   -1,    0,    1,    0,    0,-2104,    0,    0,    0,    0,-2106,
-  -2108,-2106,    0,    0,    1,   -1,-2250,    0,    0,    0,-2527,    0,    0,   -2,    0,    1,
-     -1,    0,    1,   -1,
-};
-
-static inline uint_fast8_t
-_hb_ucd_gc (unsigned u)
-{
-  return u<1114110u?_hb_ucd_u8[6800+(((_hb_ucd_u8[1312+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
-}
-static inline uint_fast8_t
-_hb_ucd_ccc (unsigned u)
-{
-  return u<125259u?_hb_ucd_u8[9184+(((_hb_ucd_u8[8128+(((_hb_ucd_u8[7424+(((_hb_ucd_u8[7178+(u>>2>>3>>4)])<<4)+((u>>2>>3)&15u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u))]:0;
-}
-static inline unsigned
-_hb_ucd_b4 (const uint8_t* a, unsigned i)
-{
-  return (a[i>>1]>>((i&1u)<<2))&15u;
-}
-static inline int_fast16_t
-_hb_ucd_bmg (unsigned u)
-{
-  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9932+(((_hb_ucd_u8[9812+(((_hb_ucd_b4(9684+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
-}
-static inline uint_fast8_t
-_hb_ucd_sc (unsigned u)
-{
-  return u<918000u?_hb_ucd_u8[11454+(((_hb_ucd_u16[2040+(((_hb_ucd_u8[10718+(((_hb_ucd_u8[10268+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2;
-}
-static inline uint_fast16_t
-_hb_ucd_dm (unsigned u)
-{
-  return u<195102u?_hb_ucd_u16[6008+(((_hb_ucd_u8[17460+(((_hb_ucd_u8[17078+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
-}
-
-
-#elif !defined(HB_NO_UCD_UNASSIGNED)
-
-static const uint8_t
 _hb_ucd_u8[17868] =
 {
     0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,
@@ -4611,6 +2826,1609 @@
 }
 
 
+#elif !defined(HB_NO_UCD_UNASSIGNED)
+
+static const uint8_t
+_hb_ucd_u8[14744] =
+{
+    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  9, 10,  7,  7,  7,  7, 11, 12, 13, 13, 13, 14,
+   15, 16, 17, 18, 19, 20, 21, 22, 23, 22, 22, 22, 22, 24,  7,  7,
+   25, 26, 22, 22, 22, 27, 28, 29, 22, 30, 31, 32, 33, 34, 35, 36,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7, 37,  7, 38, 39,  7, 40,  7,  7,  7, 41, 22, 42,
+    7,  7, 43,  7, 44, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   45, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 46,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 47,
+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+   32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43,
+   44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+   60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73,
+   69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83,
+   84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34,
+   91, 34, 34, 34, 34, 34, 34, 34, 34, 92, 34, 34, 93, 94, 95, 96,
+   97, 98, 99,100,101,102,103,104, 34, 34, 34, 34, 34, 34, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,105,
+  106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
+  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
+  107,107, 34, 34,108,109,110,111, 34, 34,112,113,114,115,116,117,
+  118,119,120,121,122,123,124,125,126,127,128,129, 34, 34,130,131,
+  132,133,134,135,136,137,138,139,140,141,142,122,143,144,145,146,
+  147,148,149,150,151,152,153,122,154,155,122,156,157,158,159,122,
+  160,161,162,163,164,165,166,122,167,168,169,170,122,171,172,173,
+   34, 34, 34, 34, 34, 34, 34,174,175, 34,176,122,122,122,122,122,
+  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,177,
+   34, 34, 34, 34, 34, 34, 34, 34,178,122,122,122,122,122,122,122,
+  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,
+  122,122,122,122,122,122,122,122, 34, 34, 34, 34,179,122,122,122,
+   34, 34, 34, 34,180,181,182,183,122,122,122,122,184,185,186,187,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,188,
+   34, 34, 34, 34, 34, 34, 34, 34, 34,189,190,122,122,122,122,122,
+  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,191,
+   34, 34,192, 34, 34,193,122,122,122,122,122,122,122,122,122,122,
+  122,122,122,122,122,122,122,122,194,195,122,122,122,122,122,122,
+  122,122,122,122,122,122,122,122,122,122,122,122,122,122,196,197,
+   69,198,199,200,201,202,203,122,204,205,206,207,208,209,210,211,
+   69, 69, 69, 69,212,213,122,122,122,122,122,122,122,122,214,122,
+  215,216,217,122,122,218,122,122,122,219,122,122,122,122,122,220,
+   34,221,222,122,122,122,122,122,223,224,225,122,226,227,122,122,
+  228,229,230,231,232,122, 69,233, 69, 69, 69, 69, 69,234,235,236,
+  237,238, 69, 69,239,240, 69,241,122,122,122,122,122,122,122,122,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,242, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,243, 34,
+  244, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,245, 34, 34,
+   34, 34, 34, 34, 34, 34, 34,246,122,122,122,122,122,122,122,122,
+   34, 34, 34, 34,247,122,122,122,122,122,122,122,122,122,122,122,
+   34, 34, 34, 34, 34, 34,248, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+   34, 34, 34, 34, 34, 34, 34,249,122,122,122,122,122,122,122,122,
+  250,122,251,252,122,122,122,122,122,122,122,122,122,122,122,122,
+  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,253,
+  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,254,
+    0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  2,  4,  5,  6,  2,
+    7,  7,  7,  7,  7,  2,  8,  9, 10, 11, 11, 11, 11, 11, 11, 11,
+   11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 17, 18, 19,  1, 20, 20, 21, 22, 23, 24, 25,
+   26, 27, 15,  2, 28, 29, 27, 30, 11, 11, 11, 11, 11, 11, 11, 11,
+   11, 11, 11, 31, 11, 11, 11, 32, 16, 16, 16, 16, 16, 16, 16, 16,
+   16, 16, 16, 33, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32,
+   32, 32, 32, 32, 34, 34, 34, 34, 34, 34, 34, 34, 16, 32, 32, 32,
+   32, 32, 32, 32, 11, 34, 34, 16, 34, 32, 32, 11, 34, 11, 16, 11,
+   11, 34, 32, 11, 32, 16, 11, 34, 32, 32, 32, 11, 34, 16, 32, 11,
+   34, 11, 34, 34, 32, 35, 32, 16, 36, 36, 37, 34, 38, 37, 34, 34,
+   34, 34, 34, 34, 34, 34, 16, 32, 34, 38, 32, 11, 32, 32, 32, 32,
+   32, 32, 16, 16, 16, 11, 34, 32, 34, 34, 11, 32, 32, 32, 32, 32,
+   16, 16, 39, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 40,
+   40, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41,
+   40, 40, 42, 41, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41,
+   43, 43, 43, 43, 43, 43, 43, 43, 32, 32, 42, 32, 44, 45, 16, 10,
+   44, 44, 41, 46, 11, 47, 47, 11, 34, 11, 11, 11, 11, 11, 11, 11,
+   11, 48, 11, 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 34,
+   16, 11, 32, 16, 32, 32, 32, 32, 16, 16, 32, 49, 34, 32, 34, 11,
+   32, 50, 43, 43, 51, 32, 32, 32, 11, 34, 34, 34, 34, 34, 34, 16,
+   48, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 47, 52,  2,  2,  2,
+   16, 16, 16, 16, 53, 54, 55, 56, 57, 43, 43, 43, 43, 43, 43, 43,
+   43, 43, 43, 43, 43, 43, 43, 58, 59, 60, 43, 59, 44, 44, 44, 44,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 62,
+   36, 63, 64, 44, 44, 44, 44, 44, 65, 65, 65,  8,  9, 66,  2, 67,
+   43, 43, 43, 43, 43, 60, 68,  2, 69, 36, 36, 36, 36, 70, 43, 43,
+    7,  7,  7,  7,  7,  2,  2, 36, 71, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 72, 43, 43, 43, 73, 50, 43, 43, 74, 75, 76, 43, 43, 36,
+    7,  7,  7,  7,  7, 36, 77, 78,  2,  2,  2,  2,  2,  2,  2, 79,
+   70, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 80, 62, 36,
+   36, 36, 36, 43, 43, 43, 43, 43, 71, 44, 44, 44, 44, 44, 44, 44,
+    7,  7,  7,  7,  7, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43,
+   43, 43, 40, 21,  2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43,
+   43, 43, 75, 43, 75, 43, 43, 44,  2,  2,  2,  2,  2,  2,  2, 64,
+   36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44,
+   36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 44, 43, 43, 43, 43,
+   36, 36, 36, 36, 83, 43, 43, 43, 43, 84, 43, 43, 43, 43, 43, 43,
+   43, 85, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 85, 71, 86,
+   87, 43, 43, 43, 85, 86, 87, 86, 70, 43, 43, 43, 36, 36, 36, 36,
+   36, 43,  2,  7,  7,  7,  7,  7, 88, 36, 36, 36, 36, 36, 36, 36,
+   70, 86, 62, 36, 36, 36, 61, 62, 61, 62, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 61, 36, 36, 36, 61, 61, 44, 36, 36, 44, 71, 86,
+   87, 43, 80, 89, 90, 89, 87, 61, 44, 44, 44, 89, 44, 44, 36, 62,
+   36, 43, 44,  7,  7,  7,  7,  7, 36, 20, 27, 27, 27, 56, 63, 80,
+   57, 85, 62, 36, 36, 61, 44, 62, 61, 36, 62, 61, 36, 44, 80, 86,
+   87, 80, 44, 57, 80, 57, 43, 44, 57, 44, 44, 44, 62, 36, 61, 61,
+   44, 44, 44,  7,  7,  7,  7,  7, 43, 36, 70, 64, 44, 44, 44, 44,
+   57, 85, 62, 36, 36, 36, 36, 62, 36, 62, 36, 36, 36, 36, 36, 36,
+   61, 36, 62, 36, 36, 44, 71, 86, 87, 43, 43, 57, 85, 89, 87, 44,
+   61, 44, 44, 44, 44, 44, 44, 44, 66, 44, 44, 44, 62, 43, 43, 43,
+   57, 86, 62, 36, 36, 36, 61, 62, 61, 36, 62, 36, 36, 44, 71, 87,
+   87, 43, 80, 89, 90, 89, 87, 44, 44, 44, 57, 85, 44, 44, 36, 62,
+   78, 27, 27, 27, 44, 44, 44, 44, 44, 71, 62, 36, 36, 61, 44, 36,
+   61, 36, 36, 44, 62, 61, 61, 36, 44, 62, 61, 44, 36, 61, 44, 36,
+   36, 36, 36, 36, 36, 44, 44, 86, 85, 90, 44, 86, 90, 86, 87, 44,
+   61, 44, 44, 89, 44, 44, 44, 44, 27, 91, 67, 67, 56, 92, 44, 44,
+   85, 86, 71, 36, 36, 36, 61, 36, 61, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 44, 71, 43, 85, 86, 90, 43, 80, 43, 43, 44,
+   44, 44, 57, 80, 36, 61, 62, 44, 44, 44, 44, 93, 27, 27, 27, 91,
+   70, 86, 72, 36, 36, 36, 61, 36, 36, 36, 62, 36, 36, 44, 71, 87,
+   86, 86, 90, 85, 90, 86, 43, 44, 44, 44, 89, 90, 44, 44, 62, 61,
+   62, 94, 44, 44, 44, 44, 44, 44, 43, 86, 36, 36, 36, 36, 61, 36,
+   36, 36, 36, 36, 36, 70, 71, 86, 87, 43, 80, 86, 90, 86, 87, 77,
+   44, 44, 36, 94, 27, 27, 27, 95, 27, 27, 27, 27, 91, 36, 36, 36,
+   57, 86, 62, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 36, 36, 36,
+   36, 62, 36, 36, 36, 36, 62, 44, 36, 36, 36, 61, 44, 80, 44, 89,
+   86, 43, 80, 80, 86, 86, 86, 86, 44, 86, 64, 44, 44, 44, 44, 44,
+   62, 36, 36, 36, 36, 36, 36, 36, 70, 36, 43, 43, 43, 80, 44, 96,
+   36, 36, 36, 75, 43, 43, 43, 60,  7,  7,  7,  7,  7,  2, 44, 44,
+   44, 44, 44, 44, 44, 44, 44, 44, 62, 61, 61, 36, 36, 61, 36, 36,
+   36, 36, 62, 62, 36, 36, 36, 36, 70, 36, 43, 43, 43, 43, 71, 44,
+   36, 36, 61, 81, 43, 43, 43, 80,  7,  7,  7,  7,  7, 44, 36, 36,
+   77, 67,  2,  2,  2,  2,  2,  2,  2, 97, 97, 67, 43, 67, 67, 67,
+    7,  7,  7,  7,  7, 27, 27, 27, 27, 27, 50, 50, 50,  4,  4, 86,
+   36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44,
+   57, 43, 43, 43, 43, 43, 43, 85, 43, 43, 60, 43, 36, 36, 70, 43,
+   43, 43, 43, 43, 57, 43, 43, 43, 43, 43, 43, 43, 43, 43, 80, 67,
+   67, 67, 67, 76, 67, 67, 92, 67,  2,  2, 97, 67, 21, 64, 44, 44,
+   36, 36, 36, 36, 36, 94, 87, 43, 85, 43, 43, 43, 87, 85, 87, 71,
+    7,  7,  7,  7,  7,  2,  2,  2, 36, 36, 36, 86, 43, 36, 36, 43,
+   71, 86, 98, 94, 86, 86, 86, 36, 70, 43, 71, 36, 36, 36, 36, 36,
+   36, 85, 87, 85, 86, 86, 87, 94,  7,  7,  7,  7,  7, 86, 87, 67,
+   11, 11, 11, 48, 44, 44, 48, 44, 16, 16, 16, 16, 16, 53, 45, 16,
+   36, 36, 36, 36, 61, 36, 36, 44, 36, 36, 36, 61, 61, 36, 36, 44,
+   61, 36, 36, 44, 36, 36, 36, 61, 61, 36, 36, 44, 36, 36, 36, 36,
+   36, 36, 36, 61, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 57, 43,
+    2,  2,  2,  2, 99, 27, 27, 27, 27, 27, 27, 27, 27, 27,100, 44,
+   67, 67, 67, 67, 67, 44, 44, 44, 11, 11, 11, 44, 16, 16, 16, 44,
+  101, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 77, 72,
+  102, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,103,104, 44,
+   36, 36, 36, 36, 36, 63,  2,105,106, 36, 36, 36, 61, 44, 44, 44,
+   36, 43, 85, 44, 44, 44, 44, 62, 36, 43,107, 64, 44, 44, 44, 44,
+   36, 43, 44, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 61, 36,
+   61, 43, 44, 44, 44, 44, 44, 44, 36, 36, 43, 87, 43, 43, 43, 86,
+   86, 86, 86, 85, 87, 43, 43, 43, 43, 43,  2, 88,  2, 66, 70, 44,
+    7,  7,  7,  7,  7, 44, 44, 44, 27, 27, 27, 27, 27, 44, 44, 44,
+    2,  2,  2,108,  2, 59, 43, 84, 36, 83, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 61, 44, 44, 44, 36, 36, 70, 71, 36, 36, 36, 36,
+   36, 36, 36, 36, 70, 61, 44, 44, 36, 36, 36, 44, 44, 44, 44, 44,
+   36, 36, 36, 36, 36, 36, 36, 61, 43, 85, 86, 87, 85, 86, 44, 44,
+   86, 85, 86, 86, 87, 43, 44, 44, 92, 44,  2,  7,  7,  7,  7,  7,
+   36, 36, 36, 36, 36, 36, 36, 44, 36, 36, 61, 44, 44, 44, 44, 44,
+   36, 36, 36, 36, 36, 36, 44, 44, 36, 36, 36, 36, 36, 44, 44, 44,
+    7,  7,  7,  7,  7,100, 44, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+   36, 36, 36, 70, 85, 87, 44,  2, 36, 36, 94, 85, 43, 43, 43, 80,
+   85, 85, 87, 43, 43, 43, 85, 86, 86, 87, 43, 43, 43, 43, 80, 57,
+    2,  2,  2, 88,  2,  2,  2, 44, 43, 43, 43, 43, 43, 43, 43,109,
+   43, 43, 43, 43, 43, 43, 43, 80, 43, 43, 98, 36, 36, 36, 36, 36,
+   36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 44,
+   97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 64,
+   43, 98, 36, 36, 36, 36, 36, 36, 94, 43, 43, 86, 43, 87, 43, 36,
+   36, 36, 36, 85, 43, 86, 87, 87, 43, 86, 44, 44, 44, 44,  2,  2,
+   36, 36, 86, 86, 86, 86, 43, 43, 43, 43, 86, 43, 44, 93,  2,  2,
+    7,  7,  7,  7,  7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40,  2,
+   16, 16, 16, 16,110, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
+    2,  2,  2,  2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43,
+   85, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 94, 43, 61, 44, 44,
+   16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16,
+   16, 16, 16, 16, 45, 16, 16, 16, 16, 16, 16, 16, 16,111, 40, 40,
+   32, 32, 32, 16, 16, 16, 16, 32, 16, 16, 16, 16, 11, 11, 11, 11,
+   16, 16, 16, 44, 11, 11, 11, 44, 16, 16, 16, 16, 48, 48, 48, 48,
+   16, 16, 16, 16, 16, 16, 16, 44, 16, 16, 16, 16,112,112,112,112,
+   16, 16,110, 16, 11, 11,113,114, 41, 16,110, 16, 11, 11,113, 41,
+   16, 16, 44, 16, 11, 11,115, 41, 16, 16, 16, 16, 11, 11,116, 41,
+   44, 16,110, 16, 11, 11,113,117,118,118,118,118,118,119, 65, 65,
+  120,120,120,  2,121,122,121,122,  2,  2,  2,  2,123, 65, 65,124,
+    2,  2,  2,  2,125,126,  2,127,128,  2,129,130,  2,  2,  2,  2,
+    2,  9,128,  2,  2,  2,  2,131, 65, 65,132, 65, 65, 65, 65, 65,
+  133, 44, 27, 27, 27,  8,129,134, 27, 27, 27, 27, 27,  8,129,104,
+   40, 40, 40, 40, 40, 40, 81, 44, 20, 20, 20, 20, 20, 20, 20, 20,
+  135, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43,136, 51,
+  109, 51,109, 43, 43, 43, 43, 43, 80, 44, 44, 44, 44, 44, 44, 44,
+   67,137, 67,138, 67, 34, 11, 16, 11, 32,138, 67, 49, 11, 11, 67,
+   67, 67,137,137,137, 11, 11,139, 11, 11, 35, 36, 39, 67, 16, 11,
+    8,  8, 49, 16, 16, 26, 67,140, 27, 27, 27, 27, 27, 27, 27, 27,
+  105,105,105,105,105,105,105,105,105,141,142,105,143, 67, 44, 44,
+    8,  8,144, 67, 67,  8, 67, 67,144, 26, 67,144, 67, 67, 67,144,
+   67, 67, 67, 67, 67, 67, 67,  8, 67,144,144, 67, 67, 67, 67, 67,
+   67, 67,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+   67, 67, 67, 67,  4,  4, 67, 67,  8, 67, 67, 67,145,146, 67, 67,
+   67, 67, 67, 67, 67, 67,144, 67, 67, 67, 67, 67, 67, 26,  8,  8,
+    8,  8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,
+    8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44,
+   67, 67, 67, 67, 67, 92, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67,
+   67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67,
+   26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,  8,  8,
+   67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67,  4,  4,  4,  4,
+    4,  4,  4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67,
+    8,  8,129,147,  8,  8,  8,  8,  8,  8,  8,  4,  4,  4,  4,  4,
+    8,129,148,148,148,148,148,148,148,148,148,148,147,  8,  8,  8,
+    8,  8,  8,  8,  4,  4,  8,  8,  8,  8,  8,  8,  8,  8,  4,  8,
+    8,  8,144, 26,  8,  8,144, 67, 67, 67, 44, 67, 67, 67, 67, 67,
+   67, 67, 67, 55, 67, 67, 67, 67, 32, 11, 32, 34, 34, 34, 34, 11,
+   32, 32, 34, 16, 16, 16, 40, 11, 32, 32,140, 67, 67,138, 34,149,
+   43, 32, 44, 44, 93,  2, 99,  2, 16, 16, 16,150, 44, 44,150, 44,
+   36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57,
+   36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61,
+    2,121,121,  2,125,126,121,  2,  2,  2,  2,  6,  2,108,121,  2,
+  121,  4,  4,  4,  4,  2,  2, 88,  2,  2,  2,  2,  2,120,  2,  2,
+  108,151,  2,  2,  2,  2,  2,  2, 67,  2,152,148,148,148,153, 44,
+   67, 67, 67, 67, 67, 55, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44,
+   67, 67, 67, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 44, 44,
+    1,  2,154,155,  4,  4,  4,  4,  4, 67,  4,  4,  4,  4,156,157,
+  158,105,105,105,105, 43, 43, 86,159, 40, 40, 67,105,160, 63, 67,
+   36, 36, 36, 61, 57,161,162, 69, 36, 36, 36, 36, 36, 63, 40, 69,
+   44, 44, 62, 36, 36, 36, 36, 36, 67, 27, 27, 67, 67, 67, 67, 67,
+   67, 67, 67, 67, 67, 67, 67, 92, 27, 27, 27, 27, 27, 67, 67, 67,
+   67, 67, 67, 67, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27,
+   36, 36, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,164,  2,
+    7,  7,  7,  7,  7, 36, 44, 44, 32, 32, 32, 32, 32, 32, 32, 70,
+   51,165, 43, 43, 43, 43, 43, 88, 32, 32, 32, 32, 32, 32, 40, 43,
+   36, 36, 36,105,105,105,105,105, 43,  2,  2,  2, 44, 44, 44, 44,
+   41, 41, 41,162, 40, 40, 40, 40, 41, 32, 32, 32, 32, 32, 32, 32,
+   16, 32, 32, 32, 32, 32, 32, 32, 45, 16, 16, 16, 34, 34, 34, 32,
+   32, 32, 32, 32, 42,166, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32,
+   32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32,
+   32, 32, 11, 11, 34,110, 44, 44, 32,150,150, 32, 32, 44, 44, 44,
+   44, 40,167, 35, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36,
+   36, 94, 87, 85, 67, 67, 80, 44, 27, 27, 27, 67,168, 44, 44, 44,
+   36, 36,  2,  2, 44, 44, 44, 44, 86, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 86, 86, 86, 86, 86, 86, 86, 86, 43, 44, 44, 44, 44,  2,
+   43, 36, 36, 36,  2, 72, 72, 70, 36, 36, 36, 43, 43, 43, 43,  2,
+   36, 36, 36, 70, 43, 43, 43, 43, 43, 86, 44, 44, 44, 44, 44, 93,
+   36, 70, 86, 43, 43, 86, 43, 86,107,  2,  2,  2,  2,  2,  2, 52,
+    7,  7,  7,  7,  7, 44, 44,  2, 36, 36, 70, 69, 36, 36, 36, 36,
+    7,  7,  7,  7,  7, 36, 36, 61, 36, 36, 36, 36, 70, 43, 43, 85,
+   87, 85, 87, 80, 44, 44, 44, 44, 36, 70, 36, 36, 36, 36, 85, 44,
+    7,  7,  7,  7,  7, 44,  2,  2, 69, 36, 36, 77, 67, 94, 85, 36,
+   71, 43, 71, 70, 71, 36, 36, 43, 70, 61, 44, 44, 44, 44, 44, 44,
+   44, 44, 44, 44, 44, 62, 83,  2, 36, 36, 36, 36, 36, 94, 43, 86,
+    2, 83,169, 80, 44, 44, 44, 44, 62, 36, 36, 61, 62, 36, 36, 61,
+   62, 36, 36, 61, 44, 44, 44, 44, 16, 16, 16, 16, 16,114, 40, 40,
+   16, 16, 16, 16,111, 41, 44, 44, 36, 94, 87, 86, 85,107, 87, 44,
+   36, 36, 44, 44, 44, 44, 44, 44, 36, 36, 36, 61, 44, 62, 36, 36,
+  170,170,170,170,170,170,170,170,171,171,171,171,171,171,171,171,
+   16, 16, 16,110, 44, 44, 44, 44, 44,150, 16, 16, 44, 44, 62, 71,
+   36, 36, 36, 36,172, 36, 36, 36, 36, 36, 36, 61, 36, 36, 61, 61,
+   36, 62, 61, 36, 36, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41,
+   41,117, 44, 44, 44, 44, 44, 44, 44, 62, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36,148, 44, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 44, 44, 44, 55, 36, 36, 36, 36, 36, 36,168, 67,
+    2,  2,  2,152,130, 44, 44, 44,  6,173,174,148,148,148,148,148,
+  148,148,130,152,130,  2,127,175,  2, 64,  2,  2,156,148,148,130,
+    2,176,  8,177, 66,  2, 44, 44, 36, 36, 61, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 61, 79, 93,  2,  3,  2,  4,  5,  6,  2,
+   16, 16, 16, 16, 16, 17, 18,129,130,  4,  2, 36, 36, 36, 36, 36,
+   69, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 40,
+   44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 61, 44,
+   20,178, 56,135, 26,  8,144, 92, 44, 44, 44, 44, 79, 65, 67, 44,
+   36, 36, 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 61, 36, 62,
+    2, 64, 44,179, 27, 27, 27, 27, 27, 27, 44, 55, 67, 67, 67, 67,
+  105,105,143, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 27, 67, 92,
+   67, 67, 67, 67, 67, 67, 92, 44, 92, 44, 44, 44, 44, 44, 44, 44,
+   67, 67, 67, 67, 67, 67, 50, 44,180, 27, 27, 27, 27, 27, 27, 27,
+   27, 27, 27, 27, 27, 27, 44, 44, 27, 27, 44, 44, 44, 44, 62, 36,
+  155, 36, 36, 36, 36,181, 44, 44, 36, 36, 36, 43, 43, 80, 44, 44,
+   36, 36, 36, 36, 36, 36, 36, 93, 36, 36, 44, 44, 36, 36, 36, 36,
+  182,105,105, 44, 44, 44, 44, 44, 11, 11, 11, 11, 16, 16, 16, 16,
+   11, 11, 44, 44, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 44, 44,
+   36, 36, 36, 36, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44, 44, 93,
+   11, 11, 11, 11, 11, 47, 11, 11, 11, 47, 11,150, 16, 16, 16, 16,
+   16,150, 16, 16, 16, 16, 16, 16, 16,150, 16, 16, 16,150,110, 44,
+   40, 40, 40, 52, 40, 40, 40, 40, 81, 40, 40, 40, 40, 81, 44, 44,
+   36, 36, 36, 44, 61, 36, 36, 36, 36, 36, 36, 62, 61, 44, 61, 62,
+   36, 36, 36, 93, 27, 27, 27, 27, 36, 36, 36, 77,163, 27, 27, 27,
+   44, 44, 44,179, 27, 27, 27, 27, 36, 61, 36, 44, 44,179, 27, 27,
+   36, 36, 36, 27, 27, 27, 44, 93, 36, 36, 36, 36, 36, 44, 44, 93,
+   36, 36, 36, 36, 44, 44, 27, 36, 44, 27, 27, 27, 27, 27, 27, 27,
+   70, 43, 57, 80, 44, 44, 43, 43, 36, 36, 62, 36, 62, 36, 36, 36,
+   36, 36, 36, 44, 43, 80, 44, 57, 27, 27, 27, 27,100, 44, 44, 44,
+    2,  2,  2,  2, 64, 44, 44, 44, 36, 36, 36, 36, 36, 36,183, 30,
+   36, 36, 36, 36, 36, 36,183, 27, 36, 36, 36, 36, 78, 36, 36, 36,
+   36, 36, 70, 80, 44,179, 27, 27,  2,  2,  2, 64, 44, 44, 44, 44,
+   36, 36, 36, 44, 93,  2,  2,  2, 36, 36, 36, 44, 27, 27, 27, 27,
+   36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 93,  2, 64, 44,
+   44, 44, 44, 44,179, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44,
+   16,110, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44,
+   27, 27, 27, 27, 27, 27, 27,100, 36, 36, 36, 36, 36, 57,184, 44,
+   36, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 57, 43,
+   27, 27, 27, 95, 44, 44, 44, 44,180, 27, 30,  2,  2, 44, 44, 44,
+   36, 43, 43,  2,  2, 44, 44, 44, 36, 36,183, 27, 27, 27, 44, 44,
+   87, 98, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43,
+   43, 43, 43, 60,  2,  2,  2, 44, 27, 27, 27,  7,  7,  7,  7,  7,
+   71, 70, 71, 44, 44, 44, 44, 57, 86, 87, 43, 85, 87, 60,185,  2,
+    2, 80, 44, 44, 44, 44, 79, 44, 43, 71, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 70, 43, 43, 87, 43, 43, 43, 80,  7,  7,  7,  7,  7,
+    2,  2, 94, 98, 44, 44, 44, 44, 36, 70,  2, 61, 44, 44, 44, 44,
+   36, 94, 86, 43, 43, 43, 43, 85, 98, 36, 63,  2, 59, 43, 60, 87,
+    7,  7,  7,  7,  7, 63, 63,  2,179, 27, 27, 27, 27, 27, 27, 27,
+   27, 27,100, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 86, 87,
+   43, 86, 85, 43,  2,  2,  2, 71, 70, 44, 44, 44, 44, 44, 44, 44,
+   36, 36, 36, 61, 61, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 62,
+   36, 36, 36, 36, 63, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 70,
+   86, 87, 43, 43, 43, 80, 44, 44, 43, 86, 62, 36, 36, 36, 61, 62,
+   61, 36, 62, 36, 36, 57, 71, 86, 85, 86, 90, 89, 90, 89, 86, 44,
+   61, 44, 44, 89, 44, 44, 62, 36, 36, 86, 44, 43, 43, 43, 80, 44,
+   43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 94, 86, 43, 43, 43, 43,
+   86, 43, 85, 71, 36, 63,  2,  2,  7,  7,  7,  7,  7,  2, 93, 71,
+   86, 87, 43, 43, 85, 85, 86, 87, 85, 43, 36, 72, 44, 44, 44, 44,
+   36, 36, 36, 36, 36, 36, 36, 94, 86, 43, 43, 44, 86, 86, 43, 87,
+   60,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 43, 44,
+   86, 87, 43, 43, 43, 85, 87, 87, 60,  2, 61, 44, 44, 44, 44, 44,
+    2,  2,  2,  2,  2,  2, 64, 44, 36, 36, 36, 36, 36, 70, 87, 86,
+   43, 43, 43, 87, 63, 44, 44, 44, 86, 43, 43, 87, 43, 43, 44, 44,
+    7,  7,  7,  7,  7, 27,  2, 97, 43, 43, 43, 43, 87, 60, 44, 44,
+   27,100, 44, 44, 44, 44, 44, 62, 36, 36, 36, 61, 62, 44, 36, 36,
+   36, 36, 62, 61, 36, 36, 36, 36, 86, 86, 86, 89, 90, 57, 85, 71,
+   98, 87,  2, 64, 44, 44, 44, 44, 36, 36, 36, 36, 44, 36, 36, 36,
+   94, 86, 43, 43, 44, 43, 86, 86, 71, 72, 90, 44, 44, 44, 44, 44,
+   70, 43, 43, 43, 43, 71, 36, 36, 36, 70, 43, 43, 85, 70, 43, 60,
+    2,  2,  2, 59, 44, 44, 44, 44, 70, 43, 43, 85, 87, 43, 36, 36,
+   36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 85, 43,  2, 72,  2,
+    2, 64, 44, 44, 44, 44, 44, 44,  2,  2,  2,  2,  2, 44, 44, 44,
+   43, 43, 43, 80, 43, 43, 43, 87, 63,  2,  2, 44, 44, 44, 44, 44,
+    2, 36, 36, 36, 36, 36, 36, 36, 44, 43, 43, 43, 43, 43, 43, 43,
+   43, 43, 43, 43, 89, 43, 43, 43, 85, 43, 87, 80, 44, 44, 44, 44,
+   36, 36, 36, 61, 36, 62, 36, 36, 70, 43, 43, 80, 44, 80, 43, 57,
+   43, 43, 43, 70, 44, 44, 44, 44, 36, 36, 36, 62, 61, 36, 36, 36,
+   36, 36, 36, 36, 36, 86, 86, 90, 43, 89, 87, 87, 61, 44, 44, 44,
+   36, 70, 85,107, 64, 44, 44, 44, 43, 94, 36, 36, 36, 36, 36, 36,
+   36, 36, 86, 43, 43, 80, 44, 86, 85, 60,  2,  2,  2,  2,  2,  2,
+   27, 27, 91, 67, 67, 67, 56, 20,168, 67, 67, 67, 67, 67, 67, 67,
+   67, 44, 44, 44, 44, 44, 44, 93,105,105,105,105,105,105,105,181,
+    2,  2, 64, 44, 44, 44, 44, 44, 63, 64, 44, 44, 44, 44, 44, 44,
+   65, 65, 65, 65, 65, 65, 65, 65, 71, 36, 36, 70, 43, 43, 43, 43,
+   43, 43, 43, 44, 44, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44,
+   43, 43, 43, 60,  2,  2, 67, 67, 40, 40, 97, 44, 44, 44, 44, 44,
+    7,  7,  7,  7,  7,179, 27, 27, 27, 62, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 44, 44, 62, 36, 27, 27, 27, 30,  2, 64, 44, 44,
+   36, 36, 36, 36, 36, 61, 44, 57, 94, 86, 86, 86, 86, 86, 86, 86,
+   86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 44, 44, 57,
+   43, 74, 40, 40, 40, 40, 40, 40, 40, 88, 80, 44, 44, 44, 44, 44,
+   86, 44, 44, 44, 44, 44, 44, 44, 40, 40, 52, 40, 40, 40, 52, 81,
+   36, 61, 44, 44, 44, 44, 44, 44, 44, 61, 44, 44, 44, 44, 44, 44,
+   36, 61, 62, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44,
+   36, 36, 36, 36, 36, 44, 50, 60, 65, 65, 44, 44, 44, 44, 44, 44,
+   43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 80, 44, 44, 44, 44,
+   67, 67, 67, 92, 55, 67, 67, 67, 67, 67,186, 87, 43, 67,186, 86,
+   86,187, 65, 65, 65, 84, 43, 43, 43, 76, 50, 43, 43, 43, 67, 67,
+   67, 67, 67, 67, 67, 43, 43, 67, 67, 43, 76, 44, 44, 44, 44, 44,
+   27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16,
+   16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
+   16, 16,110, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11,
+   11, 11, 11, 16, 16,150,150, 16, 16, 16,150, 16, 16, 16, 16, 16,
+   16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16,
+   16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11,
+   47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
+   11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11,
+   31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16,
+   16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16,
+   16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11,
+   11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16,
+   11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44,  7,
+    7,  7,  7,  7,  7,  7,  7,  7, 43, 43, 43, 76, 67, 50, 43, 43,
+   43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67,
+   67, 67, 76, 21,  2,  2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43,
+   16, 16, 16, 16, 16, 39, 16, 16, 16, 16, 16, 16, 16, 16, 16,110,
+   44, 44,150, 16, 16,110, 44, 44, 43, 43, 43, 80, 43, 43, 43, 43,
+   43, 43, 43, 43, 80, 57, 43, 43, 43, 57, 80, 43, 43, 80, 44, 44,
+   40, 40, 40, 40, 40, 40, 40, 44, 44, 44, 44, 44, 44, 44, 44, 57,
+   43, 43, 43, 74, 40, 40, 40, 44,  7,  7,  7,  7,  7, 44, 44, 77,
+   36, 36, 36, 36, 36, 36, 36, 80, 36, 36, 36, 36, 36, 36, 43, 43,
+    7,  7,  7,  7,  7, 44, 44, 96, 36, 36, 36, 36, 36, 83, 43, 43,
+   36, 36, 36, 61, 36, 36, 62, 61, 36, 36, 61,179, 27, 27, 27, 27,
+   16, 16, 43, 43, 43, 74, 44, 44, 27, 27, 27, 27, 27, 27,163, 27,
+  188, 27,100, 44, 44, 44, 44, 44, 27, 27, 27, 27, 27, 27, 27,163,
+   27, 27, 27, 27, 27, 27, 27, 44, 36, 36, 62, 36, 36, 36, 36, 36,
+   62, 61, 61, 62, 62, 36, 36, 36, 36, 61, 36, 36, 62, 62, 44, 44,
+   44, 61, 44, 62, 62, 62, 62, 36, 62, 61, 61, 62, 62, 62, 62, 62,
+   62, 61, 61, 62, 36, 61, 36, 36, 36, 61, 36, 36, 62, 36, 61, 61,
+   36, 36, 36, 36, 36, 62, 36, 36, 62, 36, 62, 36, 36, 62, 36, 36,
+    8, 44, 44, 44, 44, 44, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67,
+   27, 27, 27, 27, 27, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 44,
+   44, 44, 44, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, 44, 44,
+   67, 67, 67, 67, 92, 44, 44, 44, 67, 44, 44, 44, 44, 44, 44, 44,
+   67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 67, 67,
+   67, 67, 67, 92, 44, 55, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44,
+   67, 67, 67, 67, 67, 67, 67, 55, 67, 67, 67, 44, 44, 44, 44, 67,
+   67, 92, 67, 67, 67, 67, 67, 67, 79, 44, 44, 44, 44, 44, 44, 44,
+  171,171,171,171,171,171,171, 44,171,171,171,171,171,171,171,  0,
+    0,  0, 29, 21, 21, 21, 23, 21, 22, 18, 21, 25, 21, 17, 13, 13,
+   25, 25, 25, 21, 21,  9,  9,  9,  9, 22, 21, 18, 24, 16, 24,  5,
+    5,  5,  5, 22, 25, 18, 25,  0, 23, 23, 26, 21, 24, 26,  7, 20,
+   25,  1, 26, 24, 26, 25, 15, 15, 24, 15,  7, 19, 15, 21,  9, 25,
+    9,  5,  5, 25,  5,  9,  5,  7,  7,  7,  9,  8,  8,  5,  7,  5,
+    6,  6, 24, 24,  6, 24, 12, 12,  2,  2,  6,  5,  9, 21,  9,  2,
+    2,  9, 25,  9, 26, 12, 11, 11,  2,  6,  5, 21, 17,  2,  2, 26,
+   26, 23,  2, 12, 17, 12, 21, 12, 12, 21,  7,  2,  2,  7,  7, 21,
+   21,  2,  1,  1, 21, 23, 26, 26,  1, 21,  6,  7,  7, 12, 12,  7,
+   21,  7, 12,  1, 12,  6,  6, 12, 12, 26,  7, 26, 26,  7,  2,  1,
+   12,  2,  6,  2, 24,  7,  7,  6,  1, 12, 12, 10, 10, 10, 10, 12,
+   21,  6,  2, 10, 10,  2, 15, 26, 26,  2,  2, 21,  7, 10, 15,  7,
+    2, 23, 21, 26, 10,  7, 21, 15, 15,  2, 17,  7, 29,  7,  7, 22,
+   18,  2, 14, 14, 14,  7, 10, 21, 17, 21, 11, 12,  5,  2,  5,  6,
+    8,  8,  8, 24,  5, 24,  2, 24,  9, 24, 24,  2, 29, 29, 29,  1,
+   17, 17, 20, 19, 22, 20, 27, 28,  1, 29, 21, 20, 19, 21, 21, 16,
+   16, 21, 25, 22, 18, 21, 21, 29,  1,  2, 15,  6, 18,  6, 23,  2,
+   12, 11,  9, 26, 26,  9, 26,  5,  5, 26, 14,  9,  5, 14, 14, 15,
+   25, 26, 26, 22, 18, 26, 18, 25, 18, 22,  5, 12,  2,  5, 22, 21,
+   21, 22, 18, 17, 26,  6,  7, 14, 17, 22, 18, 18, 26, 14, 17,  6,
+   14,  6, 12, 24, 24,  6, 26, 15,  6, 21, 11, 21, 24,  9,  6,  9,
+   23, 26,  6, 10,  4,  4,  3,  3,  7, 25, 17, 16, 16, 22, 16, 16,
+   25, 17, 25,  2, 25, 24,  2, 15, 12, 15, 14,  2, 21, 14,  7, 15,
+   12, 17, 21,  1, 26, 10, 10,  1, 23, 15,  0,  1,  2,  3,  4,  5,
+    6,  7,  8,  9,  0, 10, 11, 12, 13,  0, 14,  0,  0,  0,  0,  0,
+   15,  0, 16,  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,  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, 17, 18, 19,
+    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,  0,  0,  0,  0,  0,  0, 20,  0, 21, 22, 23,  0,  0,  0, 24,
+   25, 26, 27, 28, 29, 30, 31, 32, 33, 34,  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,  0,  0,  0,  0, 35,
+    0, 36,  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,  0,  0,  0,  0,  0, 37,  0,  0,  0,  0,  0,  0,  0,
+    0,  0, 38, 39,  0,  0,  0,  0,  0,  0, 40, 41, 42,  0, 43,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  0,  0,
+    0,  0,  3,  0,  0,  0,  4,  5,  6,  7,  0,  8,  9, 10,  0, 11,
+   12, 13, 14, 15, 16, 17, 16, 18, 16, 19, 16, 19, 16, 19,  0, 19,
+   16, 20, 16, 19, 21, 19,  0, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+   31,  0, 32,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 33,  0,  0,
+    0,  0,  0,  0, 34,  0,  0, 35,  0,  0, 36,  0, 37,  0,  0,  0,
+   38, 39, 40, 41, 42, 43, 44, 45, 46,  0,  0, 47,  0,  0,  0, 48,
+    0,  0,  0, 49,  0,  0,  0,  0,  0,  0,  0, 50,  0, 51,  0, 52,
+   53,  0, 54,  0,  0,  0,  0,  0,  0, 55, 56, 57,  0,  0,  0,  0,
+   58,  0,  0, 59, 60, 61, 62, 63,  0,  0, 64, 65,  0,  0,  0, 66,
+    0,  0,  0,  0, 67,  0,  0,  0, 68,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 69,  0,  0,  0, 70,  0, 71,  0,  0,
+   72,  0,  0, 73,  0,  0,  0,  0,  0,  0,  0,  0, 74,  0,  0,  0,
+    0,  0, 75, 76,  0, 77, 78,  0,  0, 79, 80,  0, 81, 62,  0, 82,
+   83,  0,  0, 84, 85, 86,  0,  0,  0, 87,  0, 88,  0,  0, 51, 89,
+   51,  0, 90,  0, 91,  0,  0,  0, 80,  0,  0,  0, 92, 93,  0, 94,
+   95, 96, 97,  0,  0,  0,  0,  0, 51,  0,  0,  0,  0, 98, 99,  0,
+    0,  0,  0,  0,  0,100,  0,  0,  0,  0,  0,101,102,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,103,  0,  0,104,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,105,106,  0,  0,107,  0,  0,  0,  0,  0,  0,
+  108,  0,109,  0,102,  0,  0,  0,  0,  0,110,111,  0,  0,  0,  0,
+    0,  0,  0,112,  0,  0,  0,  0,  0,  0,  0,113,  0,114,  0,  0,
+    0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  0,  8,  0,  0,  0,
+    0,  9, 10, 11, 12,  0,  0,  0,  0, 13,  0,  0, 14, 15,  0, 16,
+    0, 17, 18,  0,  0, 19,  0, 20, 21,  0,  0,  0,  0,  0, 22, 23,
+    0, 24, 25,  0,  0, 26,  0,  0,  0, 27,  0,  0, 28, 29, 30, 31,
+    0,  0,  0, 32, 33, 34,  0,  0, 33,  0,  0, 35, 33,  0,  0,  0,
+   33, 36,  0,  0,  0,  0,  0, 37, 38,  0,  0,  0,  0,  0,  0, 39,
+   40,  0,  0,  0,  0,  0,  0, 41, 42,  0,  0,  0,  0, 43,  0, 44,
+    0,  0,  0, 45, 46,  0,  0,  0, 47,  0,  0,  0,  0,  0,  0, 48,
+   49,  0,  0,  0,  0, 50,  0,  0,  0, 51,  0, 52,  0, 53,  0,  0,
+    0,  0, 54,  0,  0,  0,  0, 55,  0, 56,  0,  0,  0,  0, 57, 58,
+    0,  0,  0, 59, 60,  0,  0,  0,  0,  0,  0, 61, 52,  0, 62, 63,
+    0,  0, 64,  0,  0,  0, 65, 66,  0,  0,  0, 67,  0, 68, 69, 70,
+   71, 72,  1, 73,  0, 74, 75, 76,  0,  0, 77, 78,  0,  0,  0, 79,
+    0,  0,  1,  1,  0,  0, 80,  0,  0, 81,  0,  0,  0,  0, 77, 82,
+    0, 83,  0,  0,  0,  0,  0, 78, 84,  0, 85,  0, 52,  0,  1, 78,
+    0,  0, 86,  0,  0, 87,  0,  0,  0,  0,  0, 88, 57,  0,  0,  0,
+    0,  0,  0, 89, 90,  0,  0, 84,  0,  0, 33,  0,  0, 91,  0,  0,
+    0,  0, 92,  0,  0,  0,  0, 49,  0,  0, 93,  0,  0,  0,  0, 94,
+   95,  0,  0, 96,  0,  0, 97,  0,  0,  0, 98,  0,  0,  0, 99,  0,
+    0,  0,  0,100,101, 93,  0,  0,102,  0,  0,  0, 84,  0,  0,103,
+    0,  0,  0,104,105,  0,  0,106,107,  0,  0,  0,  0,  0,  0,108,
+    0,  0,109,  0,  0,  0,  0,110, 33,  0,111,112,113, 35,  0,  0,
+  114,  0,  0,  0,115,  0,  0,  0,  0,  0,  0,116,  0,  0,117,  0,
+    0,  0,  0,118, 88,  0,  0,  0,  0,  0, 57,  0,  0,  0,  0, 52,
+  119,  0,  0,  0,  0,120,  0,  0,121,  0,  0,  0,  0,119,  0,  0,
+  122,  0,  0,  0,  0,  0,  0,123,  0,  0,  0,124,  0,  0,  0,125,
+    0,126,  0,  0,  0,  0,127,128,129,  0,130,  0,131,  0,  0,  0,
+  132,133,134,  0, 77,  0,  0,  0,  0,  0, 35,  0,  0,  0,135,  0,
+    0,  0,136,  0,  0,137,  0,  0,138,  0,  0,  0,  0,  0,  0,  0,
+    1,  1,  1,  1,  1,  2,  3,  4,  5,  6,  7,  4,  4,  8,  9, 10,
+    1, 11, 12, 13, 14, 15, 16, 17, 18,  1,  1,  1, 19,  1,  0,  0,
+   20, 21, 22,  1, 23,  4, 21, 24, 25, 26, 27, 28, 29, 30,  0,  0,
+    1,  1, 31,  0,  0,  0, 32, 33, 34, 35,  1, 36, 37,  0,  0,  0,
+    0, 38,  1, 39, 14, 39, 40, 41, 42,  0,  0,  0, 43, 36, 44, 45,
+   21, 45, 46,  0,  0,  0, 19,  1, 21,  0,  0, 47,  0, 38, 48,  1,
+    1, 49, 49, 50,  0,  0, 51,  0,  0,  0, 52,  1,  0,  0, 38, 14,
+    4,  1,  1,  1, 53, 21, 43, 52, 54, 21, 35,  1,  0,  0,  0, 55,
+    0,  0,  0, 56, 57, 58,  0,  0,  0,  0,  0, 59,  0, 60,  0,  0,
+    0,  0, 61, 62,  0,  0, 63,  0,  0,  0, 64,  0,  0,  0, 65,  0,
+    0,  0, 66,  0,  0,  0, 67,  0,  0,  0, 68,  0,  0, 69, 70,  0,
+   71, 72, 73, 74, 75, 76,  0,  0,  0, 77,  0,  0,  0, 78, 79,  0,
+    0,  0,  0, 47,  0,  0,  0, 49,  0, 80,  0,  0,  0, 62,  0,  0,
+   63,  0,  0, 81,  0,  0, 82,  0,  0,  0, 83,  0,  0, 19, 84,  0,
+   62,  0,  0,  0,  0, 49,  1, 85,  1, 52, 15, 86, 36, 10, 21, 87,
+    0, 55,  0,  0,  0,  0, 19, 10,  1,  0,  0,  0,  0,  0, 88,  0,
+    0, 89,  0,  0, 88,  0,  0,  0,  0, 78,  0,  0, 87,  9, 12,  4,
+   90,  8, 91, 47,  0, 58, 50,  0, 21,  1, 21, 92, 93,  1,  1,  1,
+    1, 94, 95, 96, 97,  1, 98, 58, 81, 99,100,  4, 58,  0,  0,  0,
+    0,  0,  0, 19, 50,  0,  0,  0,  0,  0,  0, 61,  0,  0,101,102,
+    0,  0,103,  0,  0,  1,  1, 50,  0,  0,  0, 38,  0, 63,  0,  0,
+    0,  0,  0, 62,  0,  0,104, 68, 61,  0,  0,  0, 78,  0,  0,  0,
+  105,106, 58, 38, 81,  0,  0,  0,  0,  0,  0,107,  1, 14,  4, 12,
+   84,  0,  0,  0,  0, 38, 87,  0,  0,  0,  0,108,  0,  0,109, 61,
+    0,110,  0,  0,  0,  1,  0,  0,  0,  0, 19, 58,  0,  0,  0, 51,
+    0,111, 14, 52,112, 41,  0,  0, 62,  0,  0, 61,  0,  0,113,  0,
+   87,  0,  0,  0, 61, 62,  0,  0, 62,  0, 89,  0,  0,113,  0,  0,
+    0,  0,114,  0,  0,  0, 78, 55,  0, 38,  1, 58,  1, 58,  0,  0,
+   63, 89,  0,  0,115,  0,  0,  0, 55,  0,  0,  0,  0,115,  0,  0,
+    0,  0, 61,  0,  0,  0,  0, 79,  0, 61,  0,  0,  0,  0, 56,  0,
+   89, 80,  0,  0, 79,  0,  0,  0,  8, 91,  0,  0,  1, 87,  0,  0,
+  116,  0,  0,  0,  0,  0,  0,117,  0,118,119,120,121,  0,104,  4,
+  122, 49, 23,  0,  0,  0, 38, 50, 38, 58,  0,  0,  1, 87,  1,  1,
+    1,  1, 39,  1, 48,105, 87,  0,  0,  0,  0,  1,  0,  0,  0,123,
+    4,122,  0,  0,  0,  1,124,  0,  0,  0,  0,  0,230,230,230,230,
+  230,232,220,220,220,220,232,216,220,220,220,220,220,202,202,220,
+  220,220,220,202,202,220,220,220,  1,  1,  1,  1,  1,220,220,220,
+  220,230,230,230,230,240,230,220,220,220,230,230,230,220,220,  0,
+  230,230,230,220,220,220,220,230,232,220,220,230,233,234,234,233,
+  234,234,233,230,  0,  0,  0,230,  0,220,230,230,230,230,220,230,
+  230,230,222,220,230,230,220,220,230,222,228,230, 10, 11, 12, 13,
+   14, 15, 16, 17, 18, 19, 19, 20, 21, 22,  0, 23,  0, 24, 25,  0,
+  230,220,  0, 18, 30, 31, 32,  0,  0,  0,  0, 27, 28, 29, 30, 31,
+   32, 33, 34,230,230,220,220,230,220,230,230,220, 35,  0,  0,  0,
+    0,  0,230,230,230,  0,  0,230,230,  0,220,230,230,220,  0,  0,
+    0, 36,  0,  0,230,220,230,230,220,220,230,220,220,230,220,230,
+  220,230,230,  0,  0,220,  0,  0,230,230,  0,230,  0,230,230,230,
+  230,230,  0,  0,  0,220,220,220,230,220,220,220,230,230,  0,220,
+   27, 28, 29,230,  7,  0,  0,  0,  0,  9,  0,  0,  0,230,220,230,
+  230,  0,  0,  0,  0,  0,230,  0,  0, 84, 91,  0,  0,  0,  0,  9,
+    9,  0,  0,  0,  0,  0,  9,  0,103,103,  9,  0,107,107,107,107,
+  118,118,  9,  0,122,122,122,122,220,220,  0,  0,  0,220,  0,220,
+    0,216,  0,  0,  0,129,130,  0,132,  0,  0,  0,  0,  0,130,130,
+  130,130,  0,  0,130,  0,230,230,  9,  0,230,230,  0,  0,220,  0,
+    0,  0,  0,  7,  0,  9,  9,  0,  9,  9,  0,  0,  0,230,  0,  0,
+    0,228,  0,  0,  0,222,230,220,220,  0,  0,  0,230,  0,  0,220,
+  230,220,  0,220,230,230,230,  0,  0,  0,  9,  9,  0,  0,  7,  0,
+  230,  0,  1,  1,  1,  0,  0,  0,230,234,214,220,202,230,230,230,
+  230,230,232,228,228,220,218,230,233,220,230,220,230,230,  1,  1,
+    1,  1,  1,230,  0,  1,  1,230,220,230,  1,  1,  0,  0,218,228,
+  232,222,224,224,  0,  8,  8,  0,  0,  0,  0,220,230,  0,230,230,
+  220,  0,  0,230,  0,  0, 26,  0,  0,220,  0,230,230,  1,220,  0,
+    0,230,220,  0,  0,  0,220,220,  0,  0,230,220,  0,  9,  7,  0,
+    0,  7,  9,  0,  0,  0,  9,  7,  6,  6,  0,  0,  0,  0,  1,  0,
+    0,216,216,  1,  1,  1,  0,  0,  0,226,216,216,216,216,216,  0,
+  220,220,220,  0,232,232,220,230,230,230,  7,  0, 16, 17, 17, 33,
+   17, 49, 17, 17, 84, 97,135,145, 26, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,177,  0,  1,  2,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+    4,  3,  3,  3,  3,  3,  5,  3,  3,  3,  3,  3,  6,  7,  8,  3,
+    3,  3,  3,  3,  9, 10, 11, 12, 13,  3,  3,  3,  3,  3,  3,  3,
+    3, 14,  3, 15,  3,  3,  3,  3,  3,  3, 16, 17, 18, 19, 20, 21,
+    3,  3,  3, 22, 23, 24,  3,  3,  3,  3,  3,  3, 25,  3,  3,  3,
+    3,  3,  3,  3,  3, 26,  3,  3, 27, 28,  0,  1,  0,  0,  0,  0,
+    0,  1,  0,  2,  0,  0,  0,  3,  0,  0,  0,  3,  0,  0,  0,  0,
+    0,  4,  0,  5,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  6,  0,  0,  0,  7,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  8,  9,  0,  0,  0,  0,  0,  0,  9,  0,  9,  0,  0,
+    0,  0,  0,  0,  0, 10, 11, 12, 13,  0,  0, 14, 15, 16,  6,  0,
+   17, 18, 19, 19, 19, 20, 21, 22, 23, 24, 19, 25,  0, 26, 27, 19,
+   19, 28, 29, 30,  0, 31,  0,  0,  0,  8,  0,  0,  0,  0,  0,  0,
+    0, 19, 28,  0, 32, 33,  9, 34, 35, 19,  0,  0, 36, 37, 38, 39,
+   40, 19,  0, 41, 42, 43, 44, 31,  0,  1, 45, 42,  0,  0,  0,  0,
+    0, 32, 14, 14,  0,  0,  0,  0, 14,  0,  0, 46, 47, 47, 47, 47,
+   48, 49, 47, 47, 47, 47, 50, 51, 52, 53, 43, 21,  0,  0,  0,  0,
+    0,  0,  0, 54,  6, 55,  0, 14, 19,  1,  0,  0,  0,  0, 56, 57,
+    0,  0,  0,  0,  0, 19, 58, 31,  0,  0,  0,  0,  0,  0,  0, 59,
+   14,  0,  0,  0,  0,  1,  0,  2,  0,  0,  0,  3,  0,  0,  0, 60,
+   61,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  2,  3,
+    0,  4,  5,  0,  0,  6,  0,  0,  0,  7,  0,  0,  0,  1,  1,  0,
+    0,  8,  9,  0,  8,  9,  0,  0,  0,  0,  8,  9, 10, 11, 12,  0,
+    0,  0, 13,  0,  0,  0,  0, 14, 15, 16, 17,  0,  0,  0,  1,  0,
+    0, 18, 19,  0,  0,  0, 20,  0,  0,  0,  1,  1,  1,  1,  0,  1,
+    1,  1,  1,  1,  1,  1,  0,  8, 21,  9,  0,  0, 22,  0,  0,  0,
+    0,  1,  0, 23, 24, 25,  0,  0, 26,  0,  0,  0,  8, 21, 27,  0,
+    1,  0,  0,  1,  1,  1,  1,  0,  1, 28, 29, 30,  0, 31, 32, 20,
+    1,  1,  0,  0,  0,  8, 21,  9,  1,  4,  5,  0,  0,  0, 33,  9,
+    0,  1,  1,  1,  0,  8, 21, 21, 21, 21, 34,  1, 35, 21, 21, 21,
+    9, 36,  0,  0, 37, 38,  1,  0, 39,  0,  0,  0,  1,  0,  1,  0,
+    0,  0,  0,  8, 21,  9,  1,  0,  0,  0, 40,  0,  8, 21, 21, 21,
+   21, 21, 21, 21, 21,  9,  0,  1,  1,  1,  1,  8, 21, 21, 21,  9,
+    0,  0,  0, 41,  0, 42, 43,  0,  0,  0,  1, 44,  0,  0,  0, 45,
+    8,  9,  1,  0,  0,  0,  8, 21, 21, 21,  9,  0,  1,  0,  1,  1,
+    8, 21, 21,  9,  0,  4,  5,  8,  9,  1,  0,  0,  0,  1,  2,  3,
+    4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    9, 10, 11, 11, 11, 11, 12, 13, 13, 13, 13, 14, 15, 16, 17, 18,
+   19, 20, 21, 13, 22, 13, 13, 13, 13, 23, 24, 24, 25, 26, 13, 13,
+   13, 27, 28, 29, 13, 30, 31, 32, 33, 34, 35, 36,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+   37,  7, 38, 39,  7, 40,  7,  7,  7, 41, 13, 42,  7,  7, 43,  7,
+   44, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 45,  0,  0,  1,
+    2,  2,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+   32, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42,
+   43, 44, 45, 46, 47, 48, 49, 50, 51, 52,  2,  2, 53, 54, 55, 56,
+   57, 58, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 61, 61,
+   59, 59, 59, 59, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+   74, 75, 76, 77, 78, 59, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+   70, 70, 70, 70, 70, 70, 70, 70, 70, 79, 70, 70, 70, 70, 80, 80,
+   80, 80, 80, 80, 80, 80, 80, 81, 82, 82, 83, 84, 85, 86, 87, 88,
+   89, 90, 91, 92, 93, 94, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 95, 96, 96,
+   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+   70, 70, 97, 98, 99,100,101,101,102,103,104,105,106,107,108,109,
+  110,111, 96,112,113,114,115,116,117,118,119,119,120,121,122,123,
+  124,125,126,127,128,129,130,131,132, 96,133,134,135,136,137,138,
+  139,140,141,142,143, 96,144,145, 96,146,147,148,149, 96,150,151,
+  152,153,154,155,156, 96,157,158,159,160, 96,161,162,163,164,164,
+  164,164,164,164,164,165,166,164,167, 96, 96, 96, 96, 96, 96, 96,
+   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,168,169,169,
+  169,169,169,169,169,169,170, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+   96, 96, 96, 96, 96, 96,171,171,171,171,172, 96, 96, 96,173,173,
+  173,173,174,175,176,177, 96, 96, 96, 96,178,179,180,181,182,182,
+  182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
+  182,182,182,182,182,182,182,182,182,182,182,182,182,183,182,182,
+  182,182,182,182,184,184,184,185,186, 96, 96, 96, 96, 96, 96, 96,
+   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,187,188,189,
+  190,191,191,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+   96, 96, 96, 96, 96, 96,193,194, 96, 96, 96, 96, 96, 96, 96, 96,
+   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,195,196, 59,197,
+  198,199,200,201,202, 96,203,204,205, 59, 59,206, 59,207,208,208,
+  208,208,208,209, 96, 96, 96, 96, 96, 96, 96, 96,210, 96,211,212,
+  213, 96, 96,214, 96, 96, 96,215, 96, 96, 96, 96, 96,216,217,218,
+  219, 96, 96, 96, 96, 96,220,221,222, 96,223,224, 96, 96,225,226,
+   59,227,228, 96, 59, 59, 59, 59, 59, 59, 59,229,230,231,232,233,
+   59, 59,234,235, 59,236, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,237, 70, 70, 70, 70,
+   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,238, 70,239, 70,
+   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,240, 70, 70, 70, 70,
+   70, 70, 70, 70, 70,241, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+   70, 70,242, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+   70, 70, 70, 70,243, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+   70, 70, 70, 70, 70,244, 96, 96, 96, 96, 96, 96, 96, 96,245, 96,
+  246,247,  0,  1,  2,  2,  0,  1,  2,  2,  2,  3,  4,  5,  0,  0,
+    0,  0,  0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,  0,  0,  0,
+   19,  0, 19,  0,  0,  0,  0,  0, 26, 26,  1,  1,  1,  1,  9,  9,
+    9,  9,  0,  9,  9,  9,  2,  2,  9,  9,  9,  9,  0,  9,  2,  2,
+    2,  2,  9,  0,  9,  0,  9,  9,  9,  2,  9,  2,  9,  9,  9,  9,
+    2,  9,  9,  9, 55, 55, 55, 55, 55, 55,  6,  6,  6,  6,  6,  1,
+    1,  6,  2,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14,  2,  2,  2,  2, 14, 14,  2,
+    2,  2,  3,  3,  3,  3,  3,  0,  3,  3,  0,  3,  3,  3,  3,  3,
+    3,  0,  3,  3,  3,  1,  1,  1,  3,  3,  1,  3,  3,  3, 37, 37,
+   37, 37, 37, 37,  2, 37, 37, 37, 37,  2,  2, 37, 37, 37, 38, 38,
+   38, 38, 38, 38,  2,  2, 64, 64, 64, 64, 64, 64, 64,  2,  2, 64,
+   64, 64, 90, 90, 90, 90, 90, 90,  2,  2, 90, 90, 90,  2, 95, 95,
+   95, 95,  2,  2, 95,  2,  3,  3,  3,  2,  3,  3,  2,  2,  3,  3,
+    0,  3,  7,  7,  7,  7,  7,  1,  1,  1,  1,  7,  7,  7,  0,  0,
+    7,  7,  5,  5,  5,  5,  2,  5,  5,  5,  5,  2,  2,  5,  5,  2,
+    5,  5,  5,  2,  5,  2,  2,  2,  5,  5,  5,  5,  2,  2,  5,  5,
+    5,  2,  2,  2,  2,  5,  5,  5,  2,  5,  2, 11, 11, 11, 11, 11,
+   11,  2,  2,  2,  2, 11, 11,  2,  2, 11, 11, 11, 11, 11, 11,  2,
+   11, 11,  2, 11, 11,  2, 11, 11,  2,  2,  2, 11,  2,  2, 11,  2,
+   11,  2,  2,  2, 11, 11,  2, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    2, 10, 10,  2, 10, 10, 10, 10,  2,  2, 10,  2,  2,  2,  2,  2,
+   10, 10,  2, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2, 21, 21,  2,
+   21, 21, 21, 21,  2,  2, 21, 21,  2, 21,  2,  2, 21, 21,  2,  2,
+   22, 22,  2, 22, 22, 22, 22, 22, 22,  2, 22,  2, 22, 22, 22, 22,
+    2,  2,  2, 22, 22,  2,  2,  2,  2, 22, 22,  2,  2,  2, 22, 22,
+   22, 22, 23, 23, 23, 23, 23,  2, 23, 23, 23, 23,  2,  2,  2, 23,
+   23,  2, 23, 23, 23,  2,  2, 23,  2,  2,  2,  2, 23, 23,  2,  2,
+    2, 23, 16, 16, 16, 16, 16,  2, 16, 16,  2, 16, 16, 16, 16, 16,
+    2,  2,  2, 16, 16,  2,  2,  2, 16, 16, 20, 20, 20, 20, 20,  2,
+   20, 20,  2,  2, 20, 20,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36,  2,  2,  2, 36, 36, 36, 36,  2, 36,  2, 36,  2,  2,  2,  2,
+   36,  2,  2,  2,  2, 36, 36,  2, 36,  2, 36,  2,  2,  2,  2, 24,
+   24, 24, 24, 24, 24, 24, 24, 24, 24,  2,  2,  2,  2,  0,  2, 18,
+   18,  2, 18,  2, 18, 18, 18, 18, 18,  2, 18, 18, 18, 18,  2, 18,
+    2, 18, 18, 18,  2,  2, 18,  2, 18,  2, 25, 25, 25, 25,  2, 25,
+   25, 25, 25,  2,  2,  2, 25,  2, 25, 25, 25,  0,  0,  0,  0, 25,
+   25,  2, 33, 33, 33, 33,  8,  8,  8,  8,  8,  8,  2,  8,  2,  8,
+    2,  2,  8,  8,  8,  0, 12, 12, 12, 12, 30, 30, 30, 30, 30,  2,
+   30, 30, 30, 30,  2,  2, 30, 30, 30,  2,  2, 30, 30, 30, 30,  2,
+    2,  2, 29, 29, 29, 29, 29, 29,  2,  2, 28, 28, 28, 28, 34, 34,
+   34, 34, 34,  2,  2,  2, 35, 35, 35, 35, 35, 35, 35,  0,  0,  0,
+   35, 35, 35,  2,  2,  2, 45, 45, 45, 45, 45, 45,  2,  2,  2,  2,
+    2, 45, 44, 44, 44, 44, 44,  0,  0,  2, 43, 43, 43, 43, 46, 46,
+   46, 46, 46,  2, 46, 46, 31, 31, 31, 31, 31, 31,  2,  2, 32, 32,
+    0,  0, 32,  0, 32, 32, 32, 32, 32, 32, 32, 32,  2,  2, 32,  2,
+    2,  2, 32, 32, 32,  2, 28, 28,  2,  2, 48, 48, 48, 48, 48, 48,
+   48,  2, 48,  2,  2,  2, 52, 52, 52, 52, 52, 52,  2,  2, 52,  2,
+    2,  2, 58, 58, 58, 58, 58, 58,  2,  2, 58, 58, 58,  2,  2,  2,
+   58, 58, 54, 54, 54, 54,  2,  2, 54, 54, 91, 91, 91, 91, 91, 91,
+   91,  2, 91,  2,  2, 91, 91, 91,  2,  2,  1,  1,  1,  2, 62, 62,
+   62, 62, 62,  2,  2,  2, 62, 62, 62,  2, 76, 76, 76, 76, 93, 93,
+   93, 93, 70, 70, 70, 70,  2,  2,  2, 70, 70, 70,  2,  2,  2, 70,
+   70, 70, 73, 73, 73, 73,  6,  2,  2,  2,  8,  8,  8,  2,  2,  8,
+    8,  8,  1,  1,  1,  0,  1,  0,  1,  1,  1,  0,  0,  0,  0,  1,
+    0,  0,  1,  1,  0,  2, 19, 19,  9,  9,  9,  9,  9,  6, 19,  9,
+    9,  9,  9,  9, 19, 19,  9,  9,  9, 19,  6, 19, 19, 19, 19, 19,
+   19,  9,  9,  9,  2,  2,  2,  9,  2,  9,  2,  9,  9,  9,  1,  1,
+    0,  0,  0,  2,  0,  0,  0, 19,  2,  2,  0,  0,  0, 19,  0,  0,
+    0,  2, 19,  2,  2,  2,  0,  2,  2,  2,  1,  2,  2,  2,  0,  0,
+    9,  0,  0,  0, 19, 19, 27, 27, 27, 27,  2,  2,  0,  0,  0,  0,
+    2,  0, 56, 56, 56, 56,  2, 55, 55, 55, 61, 61, 61, 61,  2,  2,
+    2, 61, 61,  2,  2,  2,  0,  0,  2,  2, 13, 13, 13, 13, 13, 13,
+    2, 13, 13, 13,  2,  2,  0, 13,  0, 13,  0, 13, 13, 13, 13, 13,
+    1,  1,  1,  1, 12, 12,  2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15,  2,  2,  1,  1,  0,  0, 15, 15, 15,  0, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17,  0,  2, 26, 26, 26, 26, 26, 26, 26,  2, 12,
+   12, 12, 12, 12, 12,  2, 12, 12, 12,  0, 39, 39, 39, 39, 39,  2,
+    2,  2, 39, 39, 39,  2, 86, 86, 86, 86, 77, 77, 77, 77, 79, 79,
+   79, 79, 19, 19, 19,  2, 19, 19,  2, 19,  2, 19, 19, 19, 19, 19,
+    2,  2,  2,  2, 19, 19, 60, 60, 60, 60, 60,  2,  2,  2, 65, 65,
+   65, 65, 75, 75, 75, 75, 75, 75,  2,  2,  2,  2, 75, 75, 69, 69,
+   69, 69, 69, 69,  0, 69, 74, 74, 74, 74,  2,  2,  2, 74, 12,  2,
+    2,  2, 84, 84, 84, 84, 84, 84,  2,  0, 84, 84,  2,  2,  2,  2,
+   84, 84, 33, 33, 33,  2, 68, 68, 68, 68, 68, 68, 68,  2, 68, 68,
+    2,  2, 92, 92, 92, 92, 92, 92, 92,  2,  2,  2,  2, 92, 87, 87,
+   87, 87, 87, 87, 87,  2, 19,  9, 19, 19, 19, 19,  0,  0, 87, 87,
+    2,  2,  2,  2,  2, 12,  2,  2,  2,  4, 14,  2, 14,  2, 14, 14,
+    2, 14, 14,  2, 14, 14,  2,  2,  2,  3,  3,  3,  0,  0,  2,  2,
+    3,  3,  1,  1,  6,  6,  3,  2,  3,  3,  3,  2,  2,  0,  2,  0,
+    0,  0,  0,  0, 17, 17, 17, 17,  0,  0,  2,  2, 12, 12, 49, 49,
+   49, 49,  2, 49, 49, 49, 49, 49, 49,  2, 49, 49,  2, 49, 49, 49,
+    2,  2,  9,  2,  2,  2,  0,  1,  2,  2, 71, 71, 71, 71, 71,  2,
+    2,  2, 67, 67, 67, 67, 67,  2,  2,  2, 42, 42, 42, 42,  2, 42,
+   42, 42, 41, 41, 41, 41, 41, 41, 41,  2,118,118,118,118,118,118,
+  118,  2, 53, 53, 53, 53, 53, 53,  2, 53, 59, 59, 59, 59, 59, 59,
+    2,  2, 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50,
+    2,  2,135,135,135,135,106,106,106,106,104,104,104,104,  2,  2,
+    2,104,161,161,161,161,161,161,161,  2,161,161,  2,161,161,  2,
+    2,  2,110,110,110,110,110,110,110,  2,110,110,  2,  2, 19,  2,
+   19, 19, 47, 47, 47, 47, 47, 47,  2,  2, 47,  2, 47, 47, 47, 47,
+    2, 47, 47,  2,  2,  2, 47,  2,  2, 47, 81, 81, 81, 81, 81, 81,
+    2, 81,120,120,120,120,116,116,116,116,116,116,116,  2,  2,  2,
+    2,116,128,128,128,128,128,128,128,  2,128,128,  2,  2,  2,  2,
+    2,128, 66, 66, 66, 66,  2,  2,  2, 66, 72, 72, 72, 72, 72, 72,
+    2,  2,  2,  2,  2, 72, 98, 98, 98, 98, 97, 97, 97, 97,  2,  2,
+   97, 97, 57, 57, 57, 57,  2, 57, 57,  2,  2, 57, 57, 57, 57, 57,
+    2,  2, 57, 57, 57,  2,  2,  2,  2, 57, 57,  2,  2,  2, 88, 88,
+   88, 88,117,117,117,117,112,112,112,112,112,112,112,  2,  2,  2,
+    2,112, 78, 78, 78, 78, 78, 78,  2,  2,  2, 78, 78, 78, 83, 83,
+   83, 83, 83, 83,  2,  2, 82, 82, 82, 82, 82, 82, 82,  2,122,122,
+  122,122,122,122,  2,  2,  2,122,122,122,122,  2,  2,  2, 89, 89,
+   89, 89, 89,  2,  2,  2,130,130,130,130,130,130,130,  2,  2,  2,
+  130,130,144,144,144,144,144,144,  2,  2,156,156,156,156,156,156,
+    2,156,156,156,  2,  2,  2,  3,  3,  3,147,147,147,147,148,148,
+  148,148,148,148,  2,  2,158,158,158,158,158,158,  2,  2,153,153,
+  153,153,149,149,149,149,149,149,149,  2, 94, 94, 94, 94, 94, 94,
+    2,  2,  2,  2, 94, 94,  2,  2,  2, 94, 85, 85, 85, 85, 85, 85,
+   85,  2,  2, 85,  2,  2,101,101,101,101,101,  2,  2,  2,101,101,
+    2,  2, 96, 96, 96, 96, 96,  2, 96, 96,111,111,111,111,111,111,
+  111,  2,100,100,100,100,108,108,108,108,108,108,  2,108,108,108,
+    2,  2,129,129,129,129,129,129,129,  2,129,  2,129,129,129,129,
+    2,129,129,129,  2,  2,109,109,109,109,109,109,109,  2,109,109,
+    2,  2,107,107,107,107,  2,107,107,107,107,  2,  2,107,107,  2,
+  107,107,107,107,  2,  1,107,107,  2,  2,107,  2,  2,  2,  2,  2,
+    2,107,  2,  2,107,107,137,137,137,137,  2,137,137,137,137,137,
+    2,  2,124,124,124,124,124,124,  2,  2,123,123,123,123,123,123,
+    2,  2,114,114,114,114,114,  2,  2,  2,114,114,  2,  2,102,102,
+  102,102,102,102,  2,  2,126,126,126,126,126,126,126,  2,  2,126,
+  126,126,142,142,142,142,125,125,125,125,125,125,125,  2,  2,  2,
+    2,125,154,154,154,154,154,154,154,  2,  2,154,  2,  2,  2,154,
+  154,  2,154,154,  2,154,154,  2,  2,154,154,154,  2,  2,150,150,
+  150,150,  2,  2,150,150,150,  2,  2,  2,141,141,141,141,140,140,
+  140,140,140,140,140,  2,121,121,121,121,121,  2,  2,  2,  7,  7,
+    2,  2,133,133,133,133,133,  2,133,133,133,133,133,  2,133,133,
+    2,  2,133,  2,  2,  2,134,134,134,134,  2,  2,134,134,  2,134,
+  134,134,134,134,134,  2,138,138,138,138,138,138,138,  2,138,138,
+    2,138,  2,  2,138,  2,138,138,  2,  2,143,143,143,143,143,143,
+    2,143,143,  2,143,143,143,143,143,  2,143,  2,  2,  2,143,143,
+    2,  2,145,145,145,145,145,  2,  2,  2,163,163,163,163,163,  2,
+  163,163,163,163,163,  2,  2,  2,163,163,163,163,  2,  2, 86,  2,
+    2,  2, 63, 63, 63, 63, 63, 63,  2,  2, 63, 63, 63,  2, 63,  2,
+    2,  2,157,157,157,157,157,157,157,  2, 80, 80, 80, 80, 80, 80,
+    2,  2,127,127,127,127,127,127,127,  2, 79,  2,  2,  2,115,115,
+  115,115,115,115,115,  2,115,115,  2,  2,  2,  2,115,115,159,159,
+  159,159,159,159,159,  2,159,159,  2,  2,103,103,103,103,103,103,
+    2,  2,119,119,119,119,119,119,  2,  2,119,119,  2,119,  2,119,
+  119,119,146,146,146,146,146,146,146,  2, 99, 99, 99, 99, 99, 99,
+   99,  2,  2,  2,  2, 99,136,139, 13, 13,155,  2,  2,  2,136,136,
+  136,136,155,155,155,155,155,155,  2,  2,136,  2,  2,  2,  2, 17,
+   17, 17,  2, 17, 17,  2, 17, 15, 15, 15, 17, 17, 17,  2,  2,  2,
+   15,  2,  2, 17,  2,  2,139,139,139,139,105,105,105,105,105,105,
+  105,  2,105,  2,  2,  2,105,105,  2,  2,  1,  1,  2,  2,  0,  0,
+    0,  1,  0,  1,  1,  1,  0,  0,  1,  1,  2,  2,  0,  2,  2,  0,
+    0,  2,  0,  2,  0,  2,131,131,131,131,  2,  2,  2,131,  2,131,
+  131,131, 56, 56, 56,  2, 56,  2,  2, 56, 56, 56,  2, 56, 56,  2,
+   56, 56,  6,  6,  2,  2,  2,  2,  2,  6,151,151,151,151,151,  2,
+    2,  2,151,151,  2,  2,  2,  2,151,151,160,160,160,160,160,160,
+  160,  2,152,152,152,152,152,152,  2,  2,  2,  2,  2,152,164,164,
+  164,164,164,164,  2,  2,  2, 30, 30,  2,113,113,113,113,113,  2,
+    2,113,113,113,113,  2,132,132,132,132,132,132,  2,  2,  2,  2,
+  132,132,  2,  3,  3,  2,  3,  2,  2,  3,  2,  3,  2,  3,  2,  2,
+    3,  2,  3,  2,  3,  2,  3,  3,  2,  3, 15,  0,  0,  2, 13,  2,
+    2,  2, 13, 13, 13,  2,  2,  0,  2,  2,  0,  1,  2,  3,  4,  5,
+    6,  7,  8,  9,  9,  9,  9, 10,  9, 11, 12, 13,  9,  9,  9, 14,
+    9,  9, 15,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9, 16, 17,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9, 18, 19, 20,  9, 21,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9, 22,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9, 23, 24,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12,
+    0,  0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0,  0, 24,
+   25, 26, 27, 28, 29, 30,  0,  0, 31, 32,  0, 33,  0, 34,  0, 35,
+    0,  0,  0,  0, 36, 37, 38, 39,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 40,  0,  0,  0,  0,  0,
+    0,  0,  0,  0, 41, 42,  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,  0,  0,  0, 43, 44,  0, 45,  0,  0,
+    0,  0,  0,  0, 46, 47,  0,  0,  0,  0,  0, 48,  0, 49,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 50, 51,  0,  0,
+    0, 52,  0,  0, 53,  0,  0,  0,  0,  0,  0,  0, 54,  0,  0,  0,
+    0,  0,  0,  0, 55,  0,  0,  0,  0,  0,  0,  0, 56,  0,  0,  0,
+    0,  0,  0,  0,  0, 57,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 58, 59, 60, 61,
+   62, 63, 64, 65,  0,  0,  0,  0,  0,  0, 66,  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,  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,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 67, 68,  0, 69, 70,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 71, 72, 73, 74, 75, 76, 77, 78,
+   79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+   95, 96, 97, 98, 99,100,101,102,103,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,104,  0,  0,  0,  0,  0,
+    0,105,106,  0,107,  0,  0,  0,108,  0,109,  0,110,  0,111,112,
+  113,  0,114,  0,  0,  0,115,  0,  0,  0,116,  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,117,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,118,119,120,121,
+    0,122,123,124,125,126,  0,127,  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,128,129,130,131,132,133,134,135,
+  136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,
+  152,153,154,155,156,157,  0,  0,  0,158,159,160,161,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,162,163,  0,  0,  0,  0,  0,  0,  0,164,  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,165,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,166,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,167,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,168,  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,169,170,  0,
+    0,  0,  0,171,172,  0,  0,  0,173,174,175,176,177,178,179,180,
+  181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,
+  197,198,199,200,201,202,203,204,205,206,  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,  1,  2,  3,  4,
+};
+static const uint16_t
+_hb_ucd_u16[10040] =
+{
+     0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
+    13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
+    13,  13,  13,  24,  25,  11,  11,  11,  11,  26,  11,  27,  28,  29,  30,  31,
+    32,  32,  32,  32,  32,  32,  32,  33,  34,  35,  36,  11,  37,  38,  13,  39,
+     9,   9,   9,  11,  11,  11,  13,  13,  40,  13,  13,  13,  41,  13,  13,  13,
+    13,  13,  13,  42,   9,  43,  11,  11,  44,  45,  32,  46,  47,  48,  49,  50,
+    51,  52,  48,  48,  53,  32,  54,  55,  48,  48,  48,  48,  48,  56,  57,  58,
+    59,  60,  48,  32,  61,  48,  48,  48,  48,  48,  62,  63,  64,  48,  65,  66,
+    48,  67,  68,  69,  48,  70,  71,  48,  72,  73,  48,  48,  74,  32,  75,  32,
+    76,  48,  48,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
+    90,  83,  84,  91,  92,  93,  94,  95,  96,  97,  84,  98,  99, 100,  88, 101,
+   102,  83,  84, 103, 104, 105,  88, 106, 107, 108, 109, 110, 111, 112,  94, 113,
+   114, 115,  84, 116, 117, 118,  88, 119, 120, 115,  84, 121, 122, 123,  88, 124,
+   125, 115,  48, 126, 127, 128,  88, 129, 130, 131,  48, 132, 133, 134,  94, 135,
+   136,  48,  48, 137, 138, 139, 140, 140, 141,  48, 142, 143, 144, 145, 140, 140,
+   146, 147, 148, 149, 150,  48, 151, 152, 153, 154,  32, 155, 156, 157, 140, 140,
+    48,  48, 158, 159, 160, 161, 162, 163, 164, 165,   9,   9, 166,  11,  11, 167,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 168, 169,  48,  48,
+   168,  48,  48, 170, 171, 172,  48,  48,  48, 171,  48,  48,  48, 173, 174, 175,
+    48, 176,   9,   9,   9,   9,   9, 177, 178,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48, 179,  48, 180, 181,  48,  48,  48,  48, 182, 183,
+    48, 184,  48, 185,  48, 186, 187, 188,  48,  48,  48, 189, 190, 191, 192, 193,
+   194, 192,  48,  48, 195,  48,  48, 196, 197,  48, 198,  48,  48,  48,  48, 199,
+    48, 200, 201, 202, 203,  48, 204, 205,  48,  48, 206,  48, 207, 208, 209, 209,
+    48, 210,  48,  48,  48, 211, 212, 213, 192, 192, 214, 215, 216, 140, 140, 140,
+   217,  48,  48, 218, 219, 160, 220, 221, 222,  48, 223,  64,  48,  48, 224, 225,
+    48,  48, 226, 227, 228,  64,  48, 229, 230,   9,   9, 231, 232, 233, 234, 235,
+    11,  11, 236,  27,  27,  27, 237, 238,  11, 239,  27,  27,  32,  32,  32,  32,
+    13,  13,  13,  13,  13,  13,  13,  13,  13, 240,  13,  13,  13,  13,  13,  13,
+   241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250,
+   251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265,
+   266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278,
+   279, 279, 279, 279, 279, 279, 279, 279, 280, 209, 281, 209, 209, 209, 209, 282,
+   209, 283, 279, 284, 209, 285, 286, 209, 209, 209, 287, 140, 288, 140, 271, 271,
+   271, 289, 209, 209, 209, 209, 290, 271, 209, 209, 209, 209, 209, 209, 209, 209,
+   209, 209, 209, 291, 292, 209, 209, 293, 209, 209, 209, 209, 209, 209, 294, 209,
+   209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279,
+   300, 301, 279, 279, 279, 302, 279, 303, 209, 209, 209, 279, 304, 209, 209, 305,
+   209, 306, 209, 209, 209, 209, 209, 209,   9,   9,   9,  11,  11,  11, 307, 308,
+    13,  13,  13,  13,  13,  13, 309, 310,  11,  11, 311,  48,  48,  48, 312, 313,
+    48, 314, 315, 315, 315, 315,  32,  32, 316, 317, 318, 319, 320, 321, 140, 140,
+   209, 322, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 324, 140, 325,
+   326, 327, 328, 329, 136,  48,  48,  48,  48, 330, 178,  48,  48,  48,  48, 331,
+   332,  48,  48, 136,  48,  48,  48,  48, 200, 333,  48,  48, 209, 209, 323,  48,
+   209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209,
+    48,  48,  48,  48, 209, 209, 209, 209,  48, 338,  48,  48,  48,  48,  48,  48,
+   151, 209, 209, 209, 287,  48,  48, 229, 339,  48, 340, 140,  13,  13, 341, 342,
+    13, 343,  48,  48,  48,  48, 344, 345,  31, 346, 347, 348,  13,  13,  13, 349,
+   350, 351, 352, 353, 354, 355, 140, 356, 357,  48, 358, 359,  48,  48,  48, 360,
+   361,  48,  48, 362, 363, 192,  32, 364,  64,  48, 365,  48, 366, 367,  48, 151,
+    76,  48,  48, 368, 369, 370, 371, 372,  48,  48, 373, 374, 375, 376,  48, 377,
+    48,  48,  48, 378, 379, 380, 381, 382, 383, 384, 315,  11,  11, 385, 386,  11,
+    11,  11,  11,  11,  48,  48, 387, 192,  48,  48, 388,  48, 389,  48,  48, 206,
+   390, 390, 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391,
+    48,  48,  48,  48,  48,  48, 204,  48,  48,  48,  48,  48,  48, 207, 140, 140,
+   392, 393, 394, 395, 396,  48,  48,  48,  48,  48,  48, 397, 398, 399,  48,  48,
+    48,  48,  48, 400, 209,  48,  48,  48,  48, 401,  48,  48, 402, 140, 140, 403,
+    32, 404,  32, 405, 406, 407, 408, 409,  48,  48,  48,  48,  48,  48,  48, 410,
+   411,   2,   3,   4,   5, 412, 413, 414,  48, 415,  48, 200, 416, 417, 418, 419,
+   420,  48, 172, 421, 204, 204, 140, 140,  48,  48,  48,  48,  48,  48,  48,  71,
+   422, 271, 271, 423, 272, 272, 272, 424, 425, 426, 427, 140, 140, 209, 209, 428,
+   140, 140, 140, 140, 140, 140, 140, 140,  48, 151,  48,  48,  48, 100, 429, 430,
+    48,  48, 431,  48, 432,  48,  48, 433,  48, 434,  48,  48, 435, 436, 140, 140,
+     9,   9, 437,  11,  11,  48,  48,  48,  48, 204, 192,   9,   9, 438,  11, 439,
+    48,  48, 440,  48,  48,  48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140,
+    48,  48,  48, 314,  48, 199, 440, 140, 446,  27,  27, 447, 140, 140, 140, 140,
+   448,  48,  48, 449,  48, 450,  48, 451,  48, 200, 452, 140, 140, 140,  48, 453,
+    48, 454,  48, 455, 140, 140, 140, 140,  48,  48,  48, 456, 271, 457, 271, 271,
+   458, 459,  48, 460, 461, 462,  48, 463,  48, 464, 140, 140, 465,  48, 466, 467,
+    48,  48,  48, 468,  48, 469,  48, 470,  48, 471, 472, 140, 140, 140, 140, 140,
+    48,  48,  48,  48, 196, 140, 140, 140,   9,   9,   9, 473,  11,  11,  11, 474,
+    48,  48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 476,
+    48,  48, 477, 478, 140, 140, 140, 479,  48, 464, 480,  48,  62, 481, 140,  48,
+   482, 140, 140,  48, 483, 140,  48, 314, 484,  48,  48, 485, 486, 457, 487, 488,
+   222,  48,  48, 489, 490,  48, 196, 192, 491,  48, 492, 493, 494,  48,  48, 495,
+   222,  48,  48, 496, 497, 498, 499, 500,  48,  97, 501, 502, 503, 140, 140, 140,
+   504, 505, 506,  48,  48, 507, 508, 192, 509,  83,  84, 510, 511, 512, 513, 514,
+    48,  48,  48, 515, 516, 517, 478, 140,  48,  48,  48, 518, 519, 192, 140, 140,
+    48,  48, 520, 521, 522, 523, 140, 140,  48,  48,  48, 524, 525, 192, 526, 140,
+    48,  48, 527, 528, 192, 140, 140, 140,  48, 173, 529, 530, 314, 140, 140, 140,
+    48,  48, 501, 531, 140, 140, 140, 140, 140, 140,   9,   9,  11,  11, 148, 532,
+   533, 534,  48, 535, 536, 192, 140, 140, 140, 140, 537,  48,  48, 538, 539, 140,
+   540,  48,  48, 541, 542, 543,  48,  48, 544, 545, 546,  48,  48,  48,  48, 196,
+   547, 140, 140, 140, 140, 140, 140, 140,  84,  48, 520, 548, 549, 148, 175, 550,
+    48, 551, 552, 553, 140, 140, 140, 140, 554,  48,  48, 555, 556, 192, 557,  48,
+   558, 559, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 560,
+   561, 115,  48, 562, 563, 192, 140, 140, 140, 140, 140, 100, 271, 564, 565, 566,
+    48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 567, 568,
+    48,  48,  48,  48, 388, 140, 140, 140, 140,  48,  48,  48,  48,  48,  48, 569,
+    48,  48,  48, 570, 571, 572, 140, 140,  48,  48,  48,  48, 314, 140, 140, 140,
+    48,  48,  48, 196,  48, 200, 370,  48,  48,  48,  48, 200, 192,  48, 204, 573,
+    48,  48,  48, 574, 575, 576, 577, 578,  48, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140,   9,   9,  11,  11, 271, 579, 140, 140, 140, 140, 140, 140,
+    48,  48,  48,  48, 580, 581, 582, 582, 583, 584, 140, 140, 140, 140, 585, 586,
+    48,  48,  48,  48,  48,  48,  48, 440,  48,  48,  48,  48,  48, 199, 140, 140,
+   196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 587,
+    48,  48, 588, 589, 140, 590, 591,  48,  48,  48,  48,  48,  48,  48,  48, 206,
+    48,  48,  48,  48,  48,  48,  71, 151, 196, 592, 593, 140, 140, 140, 140, 140,
+    32,  32, 594,  32, 595, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
+   209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 596, 209, 209, 209, 597, 598,
+   599, 209, 600, 209, 209, 209, 288, 140, 209, 209, 209, 209, 601, 140, 140, 140,
+   140, 140, 140, 140, 271, 602, 271, 602, 209, 209, 209, 209, 209, 287, 271, 461,
+     9, 603,  11, 604, 605, 606, 241,   9, 607, 608, 609, 610, 611,   9, 603,  11,
+   612, 613,  11, 614, 615, 616, 617,   9, 618,  11,   9, 603,  11, 604, 605,  11,
+   241,   9, 607, 617,   9, 618,  11,   9, 603,  11, 619,   9, 620, 621, 622, 623,
+    11, 624,   9, 625, 626, 627, 628,  11, 629,   9, 630,  11, 631, 632, 632, 632,
+    32,  32,  32, 633,  32,  32, 634, 635, 636, 637,  45, 140, 140, 140, 140, 140,
+   638, 639, 640, 140, 140, 140, 140, 140, 641, 642, 643,  27,  27,  27, 644, 140,
+   645, 140, 140, 140, 140, 140, 140, 140,  48,  48, 151, 646, 647, 140, 140, 140,
+   140,  48, 648, 140,  48,  48, 649, 650, 140, 140, 140, 140, 140,  48, 651, 192,
+   140, 140, 140, 140, 140, 140, 652, 200,  48,  48,  48,  48, 653, 595, 140, 140,
+     9,   9, 607,  11, 654, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 499,
+   271, 271, 655, 656, 140, 140, 140, 140, 499, 271, 657, 658, 140, 140, 140, 140,
+   659,  48, 660, 661, 662, 663, 664, 665, 666, 206, 667, 206, 140, 140, 140, 668,
+   209, 209, 325, 209, 209, 209, 209, 209, 209, 323, 334, 669, 669, 669, 209, 324,
+   670, 209, 209, 209, 209, 209, 209, 209, 209, 209, 671, 140, 140, 140, 672, 209,
+   673, 209, 209, 325, 674, 675, 324, 140, 209, 209, 209, 209, 209, 209, 209, 676,
+   209, 209, 209, 209, 209, 677, 426, 426, 209, 209, 209, 209, 209, 209, 209, 678,
+   209, 209, 209, 209, 209, 176, 325, 427, 325, 209, 209, 209, 679, 176, 209, 209,
+   679, 209, 671, 675, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 671, 426,
+   674, 209, 209, 680, 681, 325, 674, 674, 209, 682, 209, 209, 288, 140, 140, 192,
+    48,  48,  48,  48,  48,  48, 140, 140,  48,  48,  48, 207,  48,  48,  48,  48,
+    48, 204,  48,  48,  48,  48,  48,  48,  48,  48, 478,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48, 100, 140,  48, 204, 140, 140, 140, 140, 140, 140,
+    48,  48,  48,  48,  71,  48,  48,  48,  48,  48,  48, 140, 140, 140, 140, 140,
+   683, 140, 570, 570, 570, 570, 570, 570,  32,  32,  32,  32,  32,  32,  32,  32,
+    32,  32,  32,  32,  32,  32,  32, 140, 391, 391, 391, 391, 391, 391, 391, 684,
+   391, 391, 391, 391, 391, 391, 391, 685,   0,   0,   0,   0,   1,   2,   1,   2,
+     0,   0,   3,   3,   4,   5,   4,   5,   4,   4,   4,   4,   4,   4,   4,   4,
+     4,   4,   4,   6,   0,   0,   7,   0,   8,   8,   8,   8,   8,   8,   8,   9,
+    10,  11,  12,  11,  11,  11,  13,  11,  14,  14,  14,  14,  14,  14,  14,  14,
+    15,  14,  14,  14,  14,  14,  14,  14,  14,  14,  14,  16,  17,  18,  17,  17,
+    19,  20,  21,  21,  22,  21,  23,  24,  25,  26,  27,  27,  28,  29,  27,  30,
+    27,  27,  27,  27,  27,  31,  27,  27,  32,  33,  33,  33,  34,  27,  27,  27,
+    35,  35,  35,  36,  37,  37,  37,  38,  39,  39,  40,  41,  42,  43,  44,  27,
+    45,  46,  27,  27,  27,  27,  47,  27,  48,  48,  48,  48,  48,  49,  50,  48,
+    51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,
+    67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,
+    83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
+    99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 109, 110, 111, 112, 109,
+   113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 122, 123, 122, 124, 125, 125,
+   126, 127, 128, 129, 130, 131, 125, 125, 132, 132, 132, 132, 133, 132, 134, 135,
+   132, 133, 132, 136, 136, 137, 125, 125, 138, 138, 138, 138, 138, 138, 138, 138,
+   138, 138, 139, 139, 140, 139, 139, 141, 142, 142, 142, 142, 142, 142, 142, 142,
+   143, 143, 143, 143, 144, 145, 143, 143, 144, 143, 143, 146, 147, 148, 143, 143,
+   143, 147, 143, 143, 143, 149, 143, 150, 143, 151, 152, 152, 152, 152, 152, 153,
+   154, 154, 154, 154, 154, 154, 154, 154, 155, 156, 157, 157, 157, 157, 158, 159,
+   160, 161, 162, 163, 164, 165, 166, 167, 168, 168, 168, 168, 168, 169, 170, 170,
+   171, 172, 173, 173, 173, 173, 173, 174, 173, 173, 175, 154, 154, 154, 154, 176,
+   177, 178, 179, 179, 180, 181, 182, 183, 184, 184, 185, 184, 186, 187, 168, 168,
+   188, 189, 190, 190, 190, 191, 190, 192, 193, 193, 194,   8, 195, 125, 125, 125,
+   196, 196, 196, 196, 197, 196, 196, 198, 199, 199, 199, 199, 200, 200, 200, 201,
+   202, 202, 202, 203, 204, 205, 205, 205, 206, 139, 139, 207, 208, 209, 210, 211,
+     4,   4, 212,   4,   4, 213, 214, 215,   4,   4,   4, 216,   8,   8,   8,   8,
+    11, 217,  11,  11, 217, 218,  11, 219,  11,  11,  11, 220, 220, 221,  11, 222,
+   223,   0,   0,   0,   0,   0, 224, 225, 226, 227,   0,   0, 228,   8,   8, 229,
+     0,   0, 230, 231, 232,   0,   4,   4, 233,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 234, 125, 235, 125,   0,   0,
+   236, 236, 236, 236, 236, 236, 236, 236,   0,   0,   0,   0,   0,   0,   0, 237,
+     0, 238,   0,   0,   0,   0,   0,   0, 239, 239, 239, 239, 239, 239,   4,   4,
+   240, 240, 240, 240, 240, 240, 240, 241, 139, 139, 140, 242, 242, 242, 243, 244,
+   143, 245, 246, 246, 246, 246,  14,  14,   0,   0,   0,   0,   0, 247, 125, 125,
+   248, 249, 248, 248, 248, 248, 248, 250, 248, 248, 248, 248, 248, 248, 248, 248,
+   248, 248, 248, 248, 248, 251, 125, 252, 253,   0, 254, 255, 256, 257, 257, 257,
+   257, 258, 259, 260, 260, 260, 260, 261, 262, 263, 263, 264, 142, 142, 142, 142,
+   265,   0, 263, 263,   0,   0, 266, 260, 142, 265,   0,   0,   0,   0, 142, 267,
+     0,   0,   0,   0,   0, 260, 260, 268, 260, 260, 260, 260, 260, 269,   0,   0,
+   248, 248, 248, 248,   0,   0,   0,   0, 270, 270, 270, 270, 270, 270, 270, 270,
+   271, 270, 270, 270, 272, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274,
+   274, 274, 275, 125,  14,  14,  14,  14,  14,  14, 276, 276, 276, 276, 276, 277,
+     0,   0, 278,   4,   4,   4,   4,   4, 279,   4,   4,   4, 280, 281, 125, 282,
+   283, 283, 284, 285, 286, 286, 286, 287, 288, 288, 288, 288, 289, 290,  48,  48,
+   291, 291, 292, 293, 293, 294, 142, 295, 296, 296, 296, 296, 297, 298, 138, 299,
+   300, 300, 300, 301, 302, 303, 138, 138, 304, 304, 304, 304, 305, 306, 307, 308,
+   309, 310, 246,   4,   4, 311, 312, 152, 152, 152, 152, 152, 307, 307, 313, 314,
+   142, 142, 315, 142, 316, 142, 142, 317, 125, 125, 125, 125, 125, 125, 125, 125,
+   248, 248, 248, 248, 248, 248, 318, 248, 248, 248, 248, 248, 248, 319, 125, 125,
+   320, 321,  21, 322, 323,  27,  27,  27,  27,  27,  27,  27, 324, 325,  27,  27,
+    27,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27, 326,  27,  27,  27,  27,
+    27, 327,  27,  27, 328, 125, 125,  27,   8, 285, 329,   0,   0, 330, 331, 332,
+    27,  27,  27,  27,  27,  27,  27, 333, 334,   0,   1,   2,   1,   2, 335, 259,
+   260, 336, 142, 265, 337, 338, 339, 340, 341, 342, 343, 344, 345, 345, 125, 125,
+   342, 342, 342, 342, 342, 342, 342, 346, 347,   0,   0, 348,  11,  11,  11,  11,
+   349, 350, 351, 125, 125,   0,   0, 352, 353, 354, 355, 355, 355, 356, 357, 252,
+   358, 358, 359, 360, 361, 362, 362, 363, 364, 365, 366, 366, 367, 368, 125, 125,
+   369, 369, 369, 369, 369, 370, 370, 370, 371, 372, 373, 374, 374, 375, 374, 376,
+   377, 377, 378, 379, 379, 379, 380, 381, 381, 382, 383, 384, 125, 125, 125, 125,
+   385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 386, 385, 387, 388, 125,
+   389,   4,   4, 390, 125, 125, 125, 125, 391, 392, 392, 393, 394, 395, 396, 396,
+   397, 398, 399, 125, 125, 125, 400, 401, 402, 403, 404, 405, 125, 125, 125, 125,
+   406, 406, 407, 408, 407, 409, 407, 407, 410, 411, 412, 413, 414, 414, 415, 415,
+   416, 416, 125, 125, 417, 417, 418, 419, 420, 420, 420, 421, 422, 423, 424, 425,
+   426, 427, 428, 125, 125, 125, 125, 125, 429, 429, 429, 429, 430, 125, 125, 125,
+   431, 431, 431, 432, 431, 431, 431, 433, 434, 434, 435, 436, 125, 125, 125, 125,
+   125, 125, 125, 125, 125, 125,  27,  45, 437, 437, 438, 439, 125, 125, 125, 440,
+   441, 441, 442, 443, 443, 444, 125, 445, 446, 125, 125, 447, 448, 125, 449, 450,
+   451, 451, 451, 451, 452, 453, 451, 454, 455, 455, 455, 455, 456, 457, 458, 459,
+   460, 460, 460, 461, 462, 463, 463, 464, 465, 465, 465, 465, 465, 465, 466, 467,
+   468, 469, 468, 468, 470, 125, 125, 125, 471, 472, 473, 474, 474, 474, 475, 476,
+   477, 478, 479, 480, 481, 482, 483, 484, 485, 485, 485, 485, 485, 486, 487, 125,
+   488, 488, 488, 488, 489, 490, 125, 125, 491, 491, 491, 492, 491, 493, 125, 125,
+   494, 494, 494, 494, 495, 496, 497, 125, 498, 498, 498, 499, 499, 125, 125, 125,
+   500, 501, 502, 500, 503, 125, 125, 125, 504, 504, 504, 505, 125, 125, 125, 125,
+   125, 125, 506, 506, 506, 506, 506, 507, 508, 509, 510, 511, 512, 513, 125, 125,
+   125, 125, 514, 515, 515, 514, 516, 125, 517, 517, 517, 517, 518, 519, 519, 519,
+   519, 519, 520, 154, 521, 521, 521, 522, 523, 125, 125, 125, 125, 125, 125, 125,
+   524, 525, 525, 526, 527, 525, 528, 529, 529, 530, 531, 532, 125, 125, 125, 125,
+   533, 534, 534, 535, 536, 537, 538, 539, 540, 541, 542, 125, 125, 125, 125, 125,
+   125, 125, 125, 125, 125, 125, 543, 544, 545, 546, 545, 547, 545, 548, 125, 125,
+   125, 125, 125, 549, 550, 550, 550, 551, 552, 552, 552, 552, 552, 552, 552, 552,
+   552, 553, 125, 125, 125, 125, 125, 125, 552, 552, 552, 552, 552, 552, 554, 555,
+   552, 552, 552, 552, 556, 125, 125, 125, 125, 557, 557, 557, 557, 557, 557, 558,
+   559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 560, 125, 125,
+   561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 562, 125, 125, 125,
+   276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 563, 564, 565, 566, 567,
+   567, 567, 567, 568, 569, 570, 571, 572, 573, 573, 573, 573, 574, 575, 576, 577,
+   573, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 578, 578, 578, 578,
+   578, 579, 125, 125, 125, 125, 125, 125, 580, 580, 580, 580, 581, 580, 580, 580,
+   582, 580, 125, 125, 125, 125, 583, 584, 585, 585, 585, 585, 585, 585, 585, 585,
+   585, 585, 585, 585, 585, 585, 585, 586, 587, 587, 587, 587, 587, 587, 587, 587,
+   587, 587, 587, 587, 587, 588, 125, 125, 589, 125, 125, 125, 125, 125, 125, 125,
+   125, 125, 125, 125, 125, 125, 125, 590, 591, 257, 257, 257, 257, 257, 257, 257,
+   257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 592, 593, 125, 594, 595, 596,
+   596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 597,
+   598, 598, 598, 598, 598, 598, 599, 600, 601, 602, 266, 125, 125, 125, 125, 125,
+     8,   8, 603,   8, 604,   0,   0,   0,   0,   0,   0,   0, 266, 125, 125, 125,
+     0,   0,   0,   0,   0,   0,   0, 605,   0,   0, 606,   0,   0,   0, 607, 608,
+   609,   0, 610,   0,   0,   0, 235, 125,  11,  11,  11,  11, 611, 125, 125, 125,
+   125, 125, 125, 125,   0, 266,   0, 266,   0,   0,   0,   0,   0, 234,   0, 612,
+     0,   0,   0,   0,   0, 224,   0,   0,   0, 613, 614, 615, 616,   0,   0,   0,
+   617, 618,   0, 619, 620, 621,   0,   0,   0,   0, 622,   0,   0,   0,   0,   0,
+     0,   0,   0,   0, 623,   0,   0,   0, 624, 624, 624, 624, 624, 624, 624, 624,
+   625, 626, 627, 125, 125, 125, 125, 125,   4, 628, 629, 125, 125, 125, 125, 125,
+   630, 631, 632,  14,  14,  14, 633, 125, 634, 125, 125, 125, 125, 125, 125, 125,
+   635, 635, 636, 637, 638, 125, 125, 125, 125, 639, 640, 125, 641, 641, 641, 642,
+   125, 125, 125, 125, 125, 643, 643, 644, 125, 125, 125, 125, 125, 125, 645, 646,
+   647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 648, 649, 125, 125,
+   650, 650, 650, 650, 651, 652, 125, 125, 125, 125, 125, 125, 125, 125, 125, 334,
+     0,   0,   0, 653, 125, 125, 125, 125, 334,   0,   0, 247, 125, 125, 125, 125,
+   654,  27, 655, 656, 657, 658, 659, 660, 661, 662, 663, 662, 125, 125, 125, 664,
+     0,   0, 252,   0,   0,   0,   0,   0,   0, 266, 226, 334, 334, 334,   0, 605,
+     0,   0, 247, 125, 125, 125, 665,   0, 666,   0,   0, 252, 612, 667, 605, 125,
+     0,   0,   0,   0,   0, 668, 350, 350,   0,   0,   0,   0,   0,   0,   0, 669,
+     0,   0,   0,   0,   0, 285, 252, 228, 252,   0,   0,   0, 670, 285,   0,   0,
+   670,   0, 247, 667, 125, 125, 125, 125,   0,   0,   0,   0,   0, 266, 247, 350,
+   612,   0,   0, 671, 672, 252, 612, 612,   0, 330,   0,   0, 235, 125, 125, 285,
+   248, 248, 248, 248, 248, 248, 125, 125, 248, 248, 248, 319, 248, 248, 248, 248,
+   248, 318, 248, 248, 248, 248, 248, 248, 248, 248, 584, 248, 248, 248, 248, 248,
+   248, 248, 248, 248, 248, 248, 673, 125, 248, 318, 125, 125, 125, 125, 125, 125,
+   248, 248, 248, 248, 674, 248, 248, 248, 248, 248, 248, 125, 125, 125, 125, 125,
+   675, 125,   0,   0,   0,   0,   0,   0,   8,   8,   8,   8,   8,   8,   8,   8,
+     8,   8,   8,   8,   8,   8,   8,   0,   0,   0,   0,   0,   1,   2,   2,   2,
+     2,   2,   3,   0,   0,   0,   4,   0,   2,   2,   2,   2,   2,   3,   2,   2,
+     2,   2,   5,   0,   2,   5,   6,   0,   7,   7,   7,   7,   8,   9,  10,  11,
+    12,  13,  14,  15,   8,   8,   8,   8,  16,   8,   8,   8,  17,  18,  18,  18,
+    19,  19,  19,  19,  19,  20,  19,  19,  21,  22,  22,  22,  22,  22,  22,  22,
+    22,  23,  21,  22,  22,  22,  23,  21,  24,  25,  25,  25,  25,  25,  25,  25,
+    25,  25,  12,  12,  25,  25,  26,  27,  25,  28,  12,  12,  29,  30,  29,  31,
+    29,  29,  32,  32,  29,  29,  29,  29,  31,  29,  33,   7,   7,  34,  29,  29,
+    35,  29,  29,  29,  29,  29,  29,  30,  36,  36,  36,  37,  36,  36,  36,  36,
+    36,  36,  38,  39,  40,  40,  40,  40,  41,  12,  12,  12,  42,  42,  42,  42,
+    42,  42,  43,  44,  45,  45,  45,  45,  45,  45,  45,  46,  45,  45,  45,  47,
+    48,  48,  48,  48,  48,  48,  48,  49,  36,  36,  38,  12,  29,  29,  29,  50,
+    51,  12,  29,  29,  52,  29,  29,  29,  53,  53,  53,  53,  54,  55,  53,  53,
+    53,  56,  53,  53,  57,  58,  57,  59,  59,  57,  57,  57,  57,  57,  60,  57,
+    61,  62,  63,  57,  57,  59,  59,  64,  12,  65,  12,  66,  57,  62,  57,  57,
+    57,  57,  57,  64,  67,  67,  68,  69,  70,  71,  71,  71,  71,  71,  72,  71,
+    72,  73,  74,  72,  68,  69,  70,  74,  75,  12,  67,  76,  12,  77,  71,  71,
+    71,  68,  12,  12,  78,  78,  79,  80,  80,  79,  79,  79,  79,  79,  81,  79,
+    81,  78,  82,  79,  79,  80,  80,  82,  83,  12,  12,  12,  79,  84,  79,  79,
+    82,  12,  78,  79,  85,  85,  86,  87,  87,  86,  86,  86,  86,  86,  88,  86,
+    88,  85,  89,  86,  86,  87,  87,  89,  12,  85,  12,  90,  86,  91,  86,  86,
+    86,  86,  12,  12,  92,  93,  94,  92,  95,  96,  97,  95,  98,  99,  94,  92,
+   100, 100,  96,  92,  94,  92,  95,  96,  99,  98,  12,  12,  12,  92, 100, 100,
+   100, 100,  94,  12, 101, 101, 101, 102, 102, 101, 101, 101, 101, 101, 102, 101,
+   101, 101, 103, 101, 101, 102, 102, 103,  12, 104, 105, 106, 101, 107, 101, 101,
+    12, 108, 101, 101, 109, 109, 109, 110, 110, 109, 109, 109, 109, 109, 110, 109,
+   109, 111, 112, 109, 109, 110, 110, 112,  12, 113,  12, 113, 109, 114, 109, 109,
+   111,  12,  12,  12, 115, 115, 115, 116, 116, 115, 115, 115, 115, 115, 115, 115,
+   115, 116, 116, 115,  12, 115, 115, 115, 115, 117, 115, 115, 118, 118, 119, 119,
+   119, 120, 121, 119, 119, 119, 119, 119, 122, 119, 119, 123, 119, 120, 124, 125,
+   119, 126, 119, 119,  12, 121, 119, 119, 121, 127,  12,  12, 128, 129, 129, 129,
+   129, 129, 129, 129, 129, 129, 130, 131, 129, 129, 129,  12,  12,  12,  12,  12,
+   132, 133, 134, 135, 135, 135, 135, 135, 135, 136, 135, 135, 135, 135, 135, 137,
+   135, 138, 135, 134, 135, 135, 137, 135, 139, 139, 139, 139, 139, 139, 140, 139,
+   139, 139, 139, 141, 140, 139, 139, 139, 139, 139, 139, 142, 139, 143, 144,  12,
+   145, 145, 145, 145, 146, 146, 146, 146, 146, 147,  12, 148, 146, 146, 149, 146,
+   150, 150, 150, 150, 151, 151, 151, 151, 151, 151, 152, 153, 151, 154, 152, 153,
+   152, 153, 151, 154, 152, 153, 151, 151, 151, 154, 151, 151, 151, 151, 154, 155,
+   151, 151, 151, 156, 151, 151, 153,  12, 157, 157, 157, 157, 157, 158, 157, 158,
+   159, 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, 161, 162, 162, 162, 162,
+   162, 162, 163, 164, 162, 162, 165,  12, 166, 166, 166, 166, 166, 167,  12, 168,
+   169, 169, 169, 169, 169, 170,  12,  12, 171, 171, 171, 171, 171,  12,  12,  12,
+   172, 172, 172, 173, 173,  12,  12,  12, 174, 174, 174, 174, 174, 174, 174, 175,
+   174, 174, 175,  12, 176, 177, 178, 178, 178, 178, 179,  12, 178, 178, 178, 178,
+   178, 178, 180,  12, 178, 178, 181,  12, 159, 182,  12,  12, 183, 183, 183, 183,
+   183, 183, 183, 184, 183, 183, 183,  12, 185, 183, 183, 183, 186, 186, 186, 186,
+   186, 186, 186, 187, 186, 188,  12,  12, 189, 189, 189, 189, 189, 189, 189,  12,
+   189, 189, 190,  12, 189, 189, 191, 192, 193, 193, 193, 193, 193, 193, 193, 194,
+   195, 195, 195, 195, 195, 195, 195, 196, 195, 195, 195, 197, 195, 195, 198,  12,
+   195, 195, 195, 198,   7,   7,   7, 199, 200, 200, 200, 200, 200, 200, 200, 201,
+   200, 200, 200, 202, 203, 203, 203, 203, 204, 204, 204, 204, 204,  12,  12, 204,
+   205, 205, 205, 205, 205, 205, 206, 205, 205, 205, 207, 208, 209, 209, 209, 209,
+    19,  19, 210,  12, 146, 146, 211, 212, 203, 203,  12,  12, 213,   7,   7,   7,
+   214,   7, 215, 216,   0, 215, 217,  12,   2, 218, 219,   2,   2,   2,   2, 220,
+   221, 218, 222,   2,   2,   2, 223,   2,   2,   2,   2, 224,   8, 225,   8, 225,
+     8,   8, 226, 226,   8,   8,   8, 225,   8,  15,   8,   8,   8,  10,   8, 227,
+    10,  15,   8,  14,   0,   0,   0, 228,   0, 229,   0,   0, 230,   0,   0, 231,
+     0,   0,   0, 232,   2,   2,   2, 233, 234,  12,  12,  12, 235,  12,  12,  12,
+     0, 236, 237,   0,   4,   0,   0,   0,   0,   0,   0,   4,   2,   2,   5,  12,
+     0, 232,  12,  12,   0,   0, 232,  12, 238, 238, 238, 238,   0, 239,   0,   0,
+     0, 240,   0,   0, 241, 241, 241, 241,  18,  18,  18,  18,  18,  12, 242,  18,
+   243, 243, 243, 243, 243, 243,  12, 244, 245,  12,  12, 244, 151, 154,  12,  12,
+   151, 154, 151, 154,   0,   0,   0, 246, 247, 247, 247, 247, 247, 247, 248, 247,
+   247,  12,  12,  12, 247, 249,  12,  12,   0,   0,   0,  12,   0, 250,   0,   0,
+   251, 247, 252, 253,   0,   0, 247,   0, 254, 255, 255, 255, 255, 255, 255, 255,
+   255, 256, 257, 258, 259, 260, 260, 260, 260, 260, 260, 260, 260, 260, 261, 259,
+    12, 262, 263, 263, 263, 263, 263, 263, 264, 150, 150, 150, 150, 150, 150, 265,
+     0,  12,  12,  12, 150, 150, 150, 266, 260, 260, 260, 261, 260, 260,   0,   0,
+   267, 267, 267, 267, 267, 267, 267, 268, 267, 269,  12,  12, 270, 270, 270, 270,
+   271, 271, 271, 271, 271, 271, 271,  12, 272, 272, 272, 272, 272, 272,  12,  12,
+   237,   2,   2,   2,   2,   2, 231,   2,   2,   2, 273,  12, 274, 275, 276,  12,
+   277,   2,   2,   2, 278, 278, 278, 278, 278, 278, 278, 279,   0,   0, 246,  12,
+   280, 280, 280, 280, 280, 280,  12,  12, 281, 281, 281, 281, 281, 282,  12, 283,
+   281, 281, 282,  12, 284, 284, 284, 284, 284, 284, 284, 285, 286, 286, 286, 286,
+   286,  12,  12, 287, 150, 150, 150, 288, 289, 289, 289, 289, 289, 289, 289, 290,
+   289, 289, 291, 292, 145, 145, 145, 293, 294, 294, 294, 294, 294, 295,  12,  12,
+   294, 294, 294, 296, 294, 294, 296, 294, 297, 297, 297, 297, 298,  12,  12,  12,
+    12,  12, 299, 297, 300, 300, 300, 300, 300, 301,  12,  12, 155, 154, 155, 154,
+   155, 154,  12,  12,   2,   2,   3,   2,   2, 302, 303,  12, 300, 300, 300, 304,
+   300, 300, 304,  12, 150,  12,  12,  12, 150, 265, 305, 150, 150, 150, 150,  12,
+   247, 247, 247, 249, 247, 247, 249,  12,   2, 273,  12,  12, 306,  22,  12,  24,
+    25,  26,  25, 307, 308, 309,  25,  25,  50,  12,  12,  12, 310,  29,  29,  29,
+    29,  29,  29, 311, 312,  29,  29,  29,  29,  29,  12, 310,   7,   7,   7, 313,
+   232,   0,   0,   0,   0, 232,   0,  12,  29, 314,  29,  29,  29,  29,  29, 315,
+   316,   0,   0,   0,   0, 317, 260, 260, 260, 260, 260, 318, 319, 150, 319, 150,
+   319, 150, 319, 288,   0, 232,   0, 232,  12,  12, 316, 246, 320, 320, 320, 321,
+   320, 320, 320, 320, 320, 322, 320, 320, 320, 320, 322, 323, 320, 320, 320, 324,
+   320, 320, 322,  12, 232, 131,   0,   0,   0, 131,   0,   0,   8,   8,   8,  14,
+     0,   0,   0, 234, 325,  12,  12,  12,   0,   0,   0, 326, 327, 327, 327, 327,
+   327, 327, 327, 328, 329, 329, 329, 329, 330,  12,  12,  12, 215,   0,   0,   0,
+   331, 331, 331, 331, 331,  12,  12, 332, 333, 333, 333, 333, 333, 333, 334,  12,
+   335, 335, 335, 335, 335, 335, 336,  12, 337, 337, 337, 337, 337, 337, 337, 338,
+   339, 339, 339, 339, 339,  12, 339, 339, 339, 340,  12,  12, 341, 341, 341, 341,
+   342, 342, 342, 342, 343, 343, 343, 343, 343, 343, 343, 344, 343, 343, 344,  12,
+   345, 345, 345, 345, 345,  12, 345, 345, 345, 345, 345,  12, 346, 346, 346, 346,
+   346, 346,  12,  12, 347, 347, 347, 347, 347,  12,  12, 348, 349, 349, 350, 349,
+   350, 351, 349, 349, 351, 349, 349, 349, 351, 349, 351, 352, 353, 353, 353, 353,
+   353, 354,  12,  12, 353, 355,  12,  12, 353, 353,  12,  12,   2, 274,   2,   2,
+   356,   2, 273,  12, 357, 358, 359, 357, 357, 357, 357, 357, 357, 360, 361, 362,
+   363, 363, 363, 363, 363, 364, 363, 363, 365, 365, 365, 365, 366, 366, 366, 366,
+   366, 366, 366, 367,  12, 368, 366, 366, 369, 369, 369, 369, 370, 371, 372, 369,
+   373, 373, 373, 373, 373, 373, 373, 374, 375, 375, 375, 375, 375, 375, 376, 377,
+   378, 378, 378, 378, 379, 379, 379, 379, 379, 379,  12, 379, 380, 379, 379, 379,
+   381, 382,  12, 381, 381, 383, 383, 381, 381, 381, 381, 381, 381, 384, 385, 386,
+   381, 381, 387,  12, 388, 388, 388, 388, 389, 389, 389, 389, 390, 390, 390, 390,
+   390, 391, 392, 390, 390, 391,  12,  12, 393, 393, 393, 393, 393, 394, 395, 393,
+   396, 396, 396, 396, 396, 397, 396, 396, 398, 398, 398, 398, 399,  12, 398, 398,
+   400, 400, 400, 400, 401,  12, 402, 403,  12,  12, 402, 400, 404, 404, 404, 404,
+   404, 404, 405,  12, 406, 406, 406, 406, 407,  12,  12,  12, 407,  12, 408, 406,
+   409, 409, 409, 409, 409, 409,  12,  12, 409, 409, 410,  12, 411, 411, 411, 411,
+   411, 411, 412, 413, 413,  12,  12,  12,  12,  12,  12, 414, 415, 415, 415, 415,
+   415, 415,  12,  12, 416, 416, 416, 416, 416, 416, 417,  12, 418, 418, 418, 418,
+   418, 418, 419,  12, 420, 420, 420, 420, 420, 420, 420,  12, 421, 421, 421, 421,
+   421, 422,  12,  12, 423, 423, 423, 423, 423, 423, 423, 424, 425, 423, 423, 423,
+   423, 424,  12, 426, 427, 427, 427, 427, 428,  12,  12, 429, 430, 430, 430, 430,
+   430, 430, 431,  12, 430, 430, 432,  12, 433, 433, 433, 433, 433, 434, 433, 433,
+   433, 433,  12,  12, 435, 435, 435, 435, 435, 436,  12,  12, 437, 437, 437, 437,
+   118, 119, 119, 119, 119, 127,  12,  12, 438, 438, 438, 438, 439, 438, 438, 438,
+   440,  12,  12,  12, 441, 442, 443, 444, 441, 441, 441, 444, 441, 441, 445,  12,
+   446, 446, 446, 446, 446, 446, 447,  12, 446, 446, 448,  12, 449, 450, 449, 451,
+   451, 449, 449, 449, 449, 449, 452, 449, 452, 450, 453, 449, 449, 451, 451, 454,
+   455, 456,  12, 450, 449, 457, 449, 455, 449, 455,  12,  12, 458, 458, 458, 458,
+   458, 458, 458, 459, 460,  12,  12,  12, 461, 461, 461, 461, 461, 461,  12,  12,
+   461, 461, 462,  12, 463, 463, 463, 463, 463, 464, 463, 463, 463, 463, 463, 464,
+   465, 465, 465, 465, 465, 466,  12,  12, 465, 465, 467,  12, 178, 178, 178, 180,
+   468, 468, 468, 468, 468, 468, 469,  12, 470, 470, 470, 470, 470, 470, 471, 472,
+   470, 470, 470,  12, 470, 471,  12,  12, 473, 473, 473, 473, 473, 473, 473,  12,
+   474, 474, 474, 474, 475,  12,  12, 476, 477, 478, 479, 477, 477, 480, 477, 477,
+   477, 477, 477, 477, 477, 481, 482, 477, 477, 478,  12,  12, 477, 477, 483,  12,
+   484, 484, 485, 484, 484, 484, 484, 484, 484, 486,  12,  12, 487, 487, 487, 487,
+   487, 487,  12,  12, 488, 488, 488, 488, 489,  12,  12,  12, 490, 490, 490, 490,
+   490, 490, 491,  12,  53,  53, 492,  12, 493, 493, 494, 493, 493, 493, 493, 493,
+   493, 495, 493, 493, 493, 496,  12,  12, 493, 493, 493, 497, 498, 498, 498, 498,
+   499, 498, 498, 498, 498, 498, 500, 498, 498, 501,  12,  12, 502, 503, 504, 502,
+   502, 502, 502, 502, 502, 503, 505, 504, 502, 502,  12,  12, 502, 502, 506,  12,
+   507, 508, 509, 507, 507, 507, 507, 507, 507, 507, 507, 510, 508, 507, 511,  12,
+   507, 507, 512,  12, 513, 513, 513, 513, 513, 513, 514,  12, 515, 515, 515, 515,
+   516, 515, 515, 515, 515, 515, 517, 518, 515, 515, 519,  12, 520,  12,  12,  12,
+   100, 100, 100, 100,  96,  12,  12,  98, 521, 521, 521, 521, 521, 521, 522,  12,
+   521, 521, 521, 523, 521, 524,  12,  12, 521,  12,  12,  12, 525, 525, 525, 525,
+   526,  12,  12,  12, 527, 527, 527, 527, 527, 528,  12,  12, 529, 529, 529, 529,
+   529, 530,  12,  12, 272, 272, 531,  12, 532, 532, 532, 532, 532, 532, 532, 533,
+   532, 532, 534, 535, 536, 536, 536, 536, 536, 536, 536, 537, 536, 536, 538,  12,
+   539, 539, 539, 539, 539, 539, 539, 540, 539, 540,  12,  12, 541, 541, 541, 541,
+   541, 542,  12,  12, 541, 541, 543, 541, 543, 541, 541, 541, 541, 541,  12, 544,
+   545, 545, 545, 545, 545, 545, 546,  12, 547, 547, 547, 547, 547, 547, 548, 549,
+   547, 547,  12, 549, 550, 551,  12,  12, 249,  12,  12,  12, 552, 552, 552, 552,
+   552, 552,  12,  12, 553, 553, 553, 553, 553, 554,  12,  12, 552, 552, 555,  12,
+   260, 556, 260, 557, 558, 255, 255, 255, 559,  12,  12,  12, 560,  12,  12,  12,
+   256, 561,  12,  12,  12, 260,  12,  12, 562, 562, 562, 562, 562, 562, 562,  12,
+   563, 563, 563, 563, 563, 563, 564,  12, 563, 563, 563, 565, 563, 563, 565,  12,
+   563, 563, 566, 563,   7,   7,   7, 567,   7, 199,  12,  12,   0, 246,  12,  12,
+     0, 232, 316,   0,   0, 568, 228,   0,   0,   0, 568,   7, 213, 569,   7,   0,
+     0,   0, 570, 228,   8, 225,  12,  12,   0,   0, 234,  12,   0,   0,   0, 229,
+   571, 572, 316, 229,   0,   0, 240, 316,   0, 316,   0,   0,   0, 240, 232, 316,
+     0, 229,   0, 229,   0,   0, 240, 232,   0, 573, 239,   0, 229,   0,   0,   0,
+     0, 246,   0,   0,   0,   0,   0, 239, 574, 574, 574, 574, 574, 574, 574,  12,
+    12,  12, 575, 574, 576, 574, 574, 574,   2,   2,   2, 273,  12, 275, 273,  12,
+   241, 577, 241, 241, 241, 241, 578, 241, 579, 580, 577,  12,  19,  19,  19, 581,
+    12,  12,  12, 582, 583, 583, 583, 583, 583, 583, 583, 584, 583, 583, 583, 585,
+   583, 583, 585, 586, 587, 587, 587, 587, 587, 587, 587, 588, 589, 589, 589, 589,
+   589, 589, 590, 591, 592, 592, 592, 592, 592, 592, 593,  12, 151, 154, 151, 594,
+   151, 151, 151, 154, 595, 595, 595, 595, 595, 596, 595, 595, 595, 597,  12,  12,
+   598, 598, 598, 598, 598, 598, 598,  12, 598, 598, 599, 600,   0, 234,  12,  12,
+    29, 414,  29,  29, 601, 602, 414,  29,  50,  29, 603,  12, 604, 310, 603, 414,
+   601, 602, 603, 603, 601, 602,  50,  29,  50,  29, 414, 605,  29,  29, 606,  29,
+    29,  29,  29,  12, 414, 414, 606,  29,  51,  12,  12,  12,  12, 239,   0,   0,
+   607,  12,  12,  12, 246,  12,  12,  12,   0,   0,  12,   0,   0, 232, 131,   0,
+     0,   0,  12,  12,   0,   0,   0, 240,   0, 246,  12, 239, 608,  12,  12,  12,
+   247, 247, 609,  12, 610,  12,  12,  12,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0, 939, 940, 941, 942, 946, 948,   0, 962,
+   969, 970, 971, 976,1001,1002,1003,1008,   0,1033,1040,1041,1042,1043,1047,   0,
+     0,1080,1081,1082,1086,1110,   0,   0,1124,1125,1126,1127,1131,1133,   0,1147,
+  1154,1155,1156,1161,1187,1188,1189,1193,   0,1219,1226,1227,1228,1229,1233,   0,
+     0,1267,1268,1269,1273,1298,   0,1303, 943,1128, 944,1129, 954,1139, 958,1143,
+   959,1144, 960,1145, 961,1146, 964,1149,   0,   0, 973,1158, 974,1159, 975,1160,
+   983,1168, 978,1163, 988,1173, 990,1175, 991,1176, 993,1178, 994,1179,   0,   0,
+  1004,1190,1005,1191,1006,1192,1014,1199,1007,   0,   0,   0,1016,1201,1020,1206,
+     0,1022,1208,1025,1211,1023,1209,   0,   0,   0,   0,1032,1218,1037,1223,1035,
+  1221,   0,   0,   0,1044,1230,1045,1231,1049,1235,   0,   0,1058,1244,1064,1250,
+  1060,1246,1066,1252,1067,1253,1072,1258,1069,1255,1077,1264,1074,1261,   0,   0,
+  1083,1270,1084,1271,1085,1272,1088,1275,1089,1276,1096,1283,1103,1290,1111,1299,
+  1115,1118,1307,1120,1309,1121,1310,   0,1053,1239,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,1093,1280,   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, 949,1134,1010,1195,1050,1236,1090,1277,1341,1368,1340,
+  1367,1342,1369,1339,1366,   0,1320,1347,1418,1419,1323,1350,   0,   0, 992,1177,
+  1018,1204,1055,1241,1416,1417,1415,1424,1202,   0,   0,   0, 987,1172,   0,   0,
+  1031,1217,1321,1348,1322,1349,1338,1365, 950,1135, 951,1136, 979,1164, 980,1165,
+  1011,1196,1012,1197,1051,1237,1052,1238,1061,1247,1062,1248,1091,1278,1092,1279,
+  1071,1257,1076,1263,   0,   0, 997,1182,   0,   0,   0,   0,   0,   0, 945,1130,
+   982,1167,1337,1364,1335,1362,1046,1232,1422,1423,1113,1301,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   8,   9,   0,  10,1425,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   7,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,1314,1427,   5,
+  1434,1438,1443,   0,1450,   0,1455,1461,1514,   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,1446,1458,1468,1476,1480,1486,1517,   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,1489,1503,1494,1500,1508,   0,   0,   0,   0,1520,1521,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,1526,1528,   0,1525,   0,   0,   0,1522,
+     0,   0,   0,   0,1536,1532,1539,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1534,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1556,   0,   0,   0,   0,   0,   0,1548,1550,   0,1547,   0,   0,   0,1567,
+     0,   0,   0,   0,1558,1554,1561,   0,   0,   0,   0,   0,   0,   0,1568,1569,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1529,1551,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,1523,1545,1524,1546,   0,   0,1527,1549,
+     0,   0,1570,1571,1530,1552,1531,1553,   0,   0,1533,1555,1535,1557,1537,1559,
+     0,   0,1572,1573,1544,1566,1538,1560,1540,1562,1541,1563,1542,1564,   0,   0,
+  1543,1565,   0,   0,   0,   0,   0,   0,   0,   0,1606,1607,1609,1608,1610,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,1613,   0,1611,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1612,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1620,   0,   0,   0,   0,   0,   0,   0,1623,   0,   0,1624,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1614,1615,1616,1617,1618,1619,1621,1622,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1628,1629,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1625,1626,   0,1627,   0,   0,   0,1634,   0,   0,1635,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1630,1631,1632,   0,   0,1633,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1639,   0,   0,1638,1640,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1636,1637,   0,   0,   0,   0,   0,   0,1641,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,1642,1644,1643,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1645,   0,   0,   0,   0,   0,   0,   0,1646,   0,   0,   0,   0,   0,   0,1648,
+  1649,   0,1647,1650,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,1651,1653,1652,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,1654,   0,1655,1657,1656,   0,   0,   0,   0,1659,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,1660,   0,   0,   0,   0,1661,   0,   0,   0,   0,1662,
+     0,   0,   0,   0,1663,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1658,   0,   0,   0,   0,   0,   0,   0,   0,   0,1664,   0,1665,1673,   0,
+  1674,   0,   0,   0,   0,   0,   0,   0,   0,1666,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1668,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,1669,   0,   0,   0,   0,1670,   0,   0,   0,   0,1671,
+     0,   0,   0,   0,1672,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1667,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1675,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1676,   0,
+  1677,   0,1678,   0,1679,   0,1680,   0,   0,   0,1681,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1682,   0,1683,   0,   0,1684,1685,   0,1686,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0, 953,1138, 955,1140, 956,1141, 957,1142,
+  1324,1351, 963,1148, 965,1150, 968,1153, 966,1151, 967,1152,1378,1380,1379,1381,
+   984,1169, 985,1170,1420,1421, 986,1171, 989,1174, 995,1180, 998,1183, 996,1181,
+   999,1184,1000,1185,1015,1200,1329,1356,1017,1203,1019,1205,1021,1207,1024,1210,
+  1687,1688,1027,1213,1026,1212,1028,1214,1029,1215,1030,1216,1034,1220,1036,1222,
+  1039,1225,1038,1224,1334,1361,1336,1363,1382,1384,1383,1385,1056,1242,1057,1243,
+  1059,1245,1063,1249,1689,1690,1065,1251,1068,1254,1070,1256,1386,1387,1388,1389,
+  1691,1692,1073,1259,1075,1262,1079,1266,1078,1265,1095,1282,1098,1285,1097,1284,
+  1390,1391,1392,1393,1099,1286,1100,1287,1101,1288,1102,1289,1105,1292,1104,1291,
+  1106,1294,1107,1295,1108,1296,1114,1302,1119,1308,1122,1311,1123,1312,1186,1260,
+  1293,1305,   0,1394,   0,   0,   0,   0, 952,1137, 947,1132,1317,1344,1316,1343,
+  1319,1346,1318,1345,1693,1695,1371,1375,1370,1374,1373,1377,1372,1376,1694,1696,
+   981,1166, 977,1162, 972,1157,1326,1353,1325,1352,1328,1355,1327,1354,1697,1698,
+  1009,1194,1013,1198,1054,1240,1048,1234,1331,1358,1330,1357,1333,1360,1332,1359,
+  1699,1700,1396,1401,1395,1400,1398,1403,1397,1402,1399,1404,1094,1281,1087,1274,
+  1406,1411,1405,1410,1408,1413,1407,1412,1409,1414,1109,1297,1117,1306,1116,1304,
+  1112,1300,   0,   0,   0,   0,   0,   0,1471,1472,1701,1705,1702,1706,1703,1707,
+  1430,1431,1715,1719,1716,1720,1717,1721,1477,1478,1729,1731,1730,1732,   0,   0,
+  1435,1436,1733,1735,1734,1736,   0,   0,1481,1482,1737,1741,1738,1742,1739,1743,
+  1439,1440,1751,1755,1752,1756,1753,1757,1490,1491,1765,1768,1766,1769,1767,1770,
+  1447,1448,1771,1774,1772,1775,1773,1776,1495,1496,1777,1779,1778,1780,   0,   0,
+  1451,1452,1781,1783,1782,1784,   0,   0,1504,1505,1785,1788,1786,1789,1787,1790,
+     0,1459,   0,1791,   0,1792,   0,1793,1509,1510,1794,1798,1795,1799,1796,1800,
+  1462,1463,1808,1812,1809,1813,1810,1814,1467,  21,1475,  22,1479,  23,1485,  24,
+  1493,  27,1499,  28,1507,  29,   0,   0,1704,1708,1709,1710,1711,1712,1713,1714,
+  1718,1722,1723,1724,1725,1726,1727,1728,1740,1744,1745,1746,1747,1748,1749,1750,
+  1754,1758,1759,1760,1761,1762,1763,1764,1797,1801,1802,1803,1804,1805,1806,1807,
+  1811,1815,1816,1817,1818,1819,1820,1821,1470,1469,1822,1474,1465,   0,1473,1825,
+  1429,1428,1426,  12,1432,   0,  26,   0,   0,1315,1823,1484,1466,   0,1483,1829,
+  1433,  13,1437,  14,1441,1826,1827,1828,1488,1487,1513,  19,   0,   0,1492,1515,
+  1445,1444,1442,  15,   0,1831,1832,1833,1502,1501,1516,  25,1497,1498,1506,1518,
+  1457,1456,1454,  17,1453,1313,  11,   3,   0,   0,1824,1512,1519,   0,1511,1830,
+  1449,  16,1460,  18,1464,   4,   0,   0,  30,  31,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  20,   0,
+     0,   0,   2,   6,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,1834,1835,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,1836,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,1837,1839,1838,   0,   0,   0,   0,1840,   0,   0,   0,
+     0,1841,   0,   0,1842,   0,   0,   0,   0,   0,   0,   0,1843,   0,1844,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1845,   0,   0,1846,   0,   0,1847,
+     0,1848,   0,   0,   0,   0,   0,   0, 937,   0,1850,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,1849, 936, 938,1851,1852,   0,   0,1853,1854,   0,   0,
+  1855,1856,   0,   0,   0,   0,   0,   0,1857,1858,   0,   0,1861,1862,   0,   0,
+  1863,1864,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1867,1868,1869,1870,1859,1860,1865,1866,   0,   0,   0,   0,
+     0,   0,1871,1872,1873,1874,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,  32,  33,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1875,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1877,   0,1878,   0,1879,   0,1880,   0,1881,   0,1882,   0,
+  1883,   0,1884,   0,1885,   0,1886,   0,1887,   0,1888,   0,   0,1889,   0,1890,
+     0,1891,   0,   0,   0,   0,   0,   0,1892,1893,   0,1894,1895,   0,1896,1897,
+     0,1898,1899,   0,1900,1901,   0,   0,   0,   0,   0,   0,1876,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,1902,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1904,   0,1905,   0,1906,   0,1907,   0,1908,   0,1909,   0,
+  1910,   0,1911,   0,1912,   0,1913,   0,1914,   0,1915,   0,   0,1916,   0,1917,
+     0,1918,   0,   0,   0,   0,   0,   0,1919,1920,   0,1921,1922,   0,1923,1924,
+     0,1925,1926,   0,1927,1928,   0,   0,   0,   0,   0,   0,1903,   0,   0,1929,
+  1930,1931,1932,   0,   0,   0,1933,   0, 710, 385, 724, 715, 455, 103, 186, 825,
+   825, 242, 751, 205, 241, 336, 524, 601, 663, 676, 688, 738, 411, 434, 474, 500,
+   649, 746, 799, 108, 180, 416, 482, 662, 810, 275, 462, 658, 692, 344, 618, 679,
+   293, 388, 440, 492, 740, 116, 146, 168, 368, 414, 481, 527, 606, 660, 665, 722,
+   781, 803, 809, 538, 553, 588, 642, 758, 811, 701, 233, 299, 573, 612, 487, 540,
+   714, 779, 232, 267, 412, 445, 457, 585, 594, 766, 167, 613, 149, 148, 560, 589,
+   648, 768, 708, 345, 411, 704, 105, 259, 313, 496, 518, 174, 542, 120, 307, 101,
+   430, 372, 584, 183, 228, 529, 650, 697, 424, 732, 428, 349, 632, 355, 517, 110,
+   135, 147, 403, 580, 624, 700, 750, 170, 193, 245, 297, 374, 463, 543, 763, 801,
+   812, 815, 162, 384, 420, 730, 287, 330, 337, 366, 459, 476, 509, 558, 591, 610,
+   726, 652, 734, 759, 154, 163, 198, 473, 683, 697, 292, 311, 353, 423, 572, 494,
+   113, 217, 259, 280, 314, 499, 506, 603, 608, 752, 778, 782, 788, 117, 557, 748,
+   774, 320, 109, 126, 260, 265, 373, 411, 479, 523, 655, 737, 823, 380, 765, 161,
+   395, 398, 438, 451, 502, 516, 537, 583, 791, 136, 340, 769, 122, 273, 446, 727,
+   305, 322, 400, 496, 771, 155, 190, 269, 377, 391, 406, 432, 501, 519, 599, 684,
+   687, 749, 776, 175, 452, 191, 480, 510, 659, 772, 805, 813, 397, 444, 619, 566,
+   568, 575, 491, 471, 707, 111, 636, 156, 153, 288, 346, 578, 256, 435, 383, 729,
+   680, 767, 694, 295, 128, 210,   0,   0, 227,   0, 379,   0,   0, 150, 493, 525,
+   544, 551, 552, 556, 783, 576, 604,   0, 661,   0, 703,   0,   0, 735, 743,   0,
+     0,   0, 793, 794, 795, 808, 741, 773, 118, 127, 130, 166, 169, 177, 207, 213,
+   215, 226, 229, 268, 270, 317, 327, 329, 335, 369, 375, 381, 404, 441, 448, 458,
+   477, 484, 503, 539, 545, 547, 546, 548, 549, 550, 554, 555, 561, 564, 569, 591,
+   593, 595, 598, 607, 620, 625, 625, 651, 690, 695, 705, 706, 716, 717, 733, 735,
+   777, 786, 790, 315, 869, 623,   0,   0, 102, 145, 134, 115, 129, 138, 165, 171,
+   207, 202, 206, 212, 227, 231, 240, 243, 250, 254, 294, 296, 303, 308, 319, 325,
+   321, 329, 326, 335, 341, 357, 360, 362, 370, 379, 388, 389, 393, 421, 424, 438,
+   456, 454, 458, 465, 477, 535, 485, 490, 493, 507, 512, 514, 521, 522, 525, 526,
+   528, 533, 532, 541, 565, 569, 574, 586, 591, 597, 607, 637, 647, 674, 691, 693,
+   695, 698, 703, 699, 705, 704, 702, 706, 709, 717, 728, 736, 747, 754, 770, 777,
+   783, 784, 786, 787, 790, 802, 825, 848, 847, 857,  55,  65,  66, 883, 892, 916,
+   822, 824,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,1586,   0,1605,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,1602,1603,1934,1935,1574,1575,1576,1577,1579,1580,1581,1583,1584,   0,
+  1585,1587,1588,1589,1591,   0,1592,   0,1593,1594,   0,1595,1596,   0,1598,1599,
+  1600,1601,1604,1582,1578,1590,1597,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,1936,   0,1937,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1938,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,1939,1940,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1941,1942,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1944,1943,   0,1945,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,1946,1947,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1948,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,1949,1950,1951,1952,1953,1954,1955,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1956,1957,1958,1960,1959,1961,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0, 106, 104, 107, 826, 114, 118, 119, 121,
+   123, 124, 127, 125,  34, 830, 130, 131, 132, 137, 827,  35, 133, 139, 829, 142,
+   143, 112, 144, 145, 924, 151, 152,  37, 157, 158, 159, 160,  38, 165, 166, 169,
+   171, 172, 173, 174, 176, 177, 178, 179, 181, 182, 182, 182, 833, 468, 184, 185,
+   834, 187, 188, 189, 196, 192, 194, 195, 197, 199, 200, 201, 203, 204, 204, 206,
+   208, 209, 211, 218, 213, 219, 214, 216, 153, 234, 221, 222, 223, 220, 225, 224,
+   230, 835, 235, 236, 237, 238, 239, 244, 836, 837, 247, 248, 249, 246, 251,  39,
+    40, 253, 255, 255, 838, 257, 258, 259, 261, 839, 262, 263, 301, 264,  41, 266,
+   270, 272, 271, 841, 274, 842, 277, 276, 278, 281, 282,  42, 283, 284, 285, 286,
+    43, 843,  44, 289, 290, 291, 293, 934, 298, 845, 845, 621, 300, 300,  45, 852,
+   894, 302, 304,  46, 306, 309, 310, 312, 316,  48,  47, 317, 846, 318, 323, 324,
+   325, 324, 328, 329, 333, 331, 332, 334, 335, 336, 338, 339, 342, 343, 347, 351,
+   849, 350, 348, 352, 354, 359, 850, 361, 358, 356,  49, 363, 365, 367, 364,  50,
+   369, 371, 851, 376, 386, 378,  53, 381,  52,  51, 140, 141, 387, 382, 614,  78,
+   388, 389, 390, 394, 392, 856,  54, 399, 396, 402, 404, 858, 405, 401, 407,  55,
+   408, 409, 410, 413, 859, 415,  56, 417, 860, 418,  57, 419, 422, 424, 425, 861,
+   840, 862, 426, 863, 429, 431, 427, 433, 437, 441, 438, 439, 442, 443, 864, 436,
+   449, 450,  58, 454, 453, 865, 447, 460, 866, 867, 461, 466, 465, 464,  59, 467,
+   470, 469, 472, 828, 475, 868, 478, 870, 483, 485, 486, 871, 488, 489, 872, 873,
+   495, 497,  60, 498,  61,  61, 504, 505, 507, 508, 511,  62, 513, 874, 515, 875,
+   518, 844, 520, 876, 877, 878,  63,  64, 528, 880, 879, 881, 882, 530, 531, 531,
+   533,  66, 534,  67,  68, 884, 536, 538, 541,  69, 885, 549, 886, 887, 556, 559,
+    70, 561, 562, 563, 888, 889, 889, 567,  71, 890, 570, 571,  72, 891, 577,  73,
+   581, 579, 582, 893, 587,  74, 590, 592, 596,  75, 895, 896,  76, 897, 600, 898,
+   602, 605, 607, 899, 900, 609, 901, 611, 853,  77, 615, 616,  79, 617, 252, 902,
+   903, 854, 855, 621, 622, 731,  80, 627, 626, 628, 164, 629, 630, 631, 633, 904,
+   632, 634, 639, 640, 635, 641, 646, 651, 638, 643, 644, 645, 905, 907, 906,  81,
+   653, 654, 656, 911, 657, 908,  82,  83, 909, 910,  84, 664, 665, 666, 667, 669,
+   668, 671, 670, 674, 672, 673, 675,  85, 677, 678,  86, 681, 682, 912, 685, 686,
+    87, 689,  36, 913, 914,  88,  89, 696, 702, 709, 711, 915, 712, 713, 718, 719,
+   917, 831, 721, 720, 723, 832, 725, 728, 918, 919, 739, 742, 744, 920, 745, 753,
+   756, 757, 755, 760, 761, 921, 762,  90, 764, 922,  91, 775, 279, 780, 923, 925,
+    92,  93, 785, 926,  94, 927, 787, 787, 789, 928, 792,  95, 796, 797, 798, 800,
+    96, 929, 802, 804, 806,  97,  98, 807, 930,  99, 931, 932, 933, 814, 100, 816,
+   817, 818, 819, 820, 821, 935,   0,   0,
+};
+static const int16_t
+_hb_ucd_i16[92] =
+{
+      0,    0,    1,   -1,    2,    0,   -2,    0,    0,    2,    0,   -2,    0,   16,    0,  -16,
+      0,    1,   -1,    0,    3,    3,    3,   -3,   -3,   -3,    0, 2016,    0, 2527, 1923, 1914,
+   1918,    0, 2250,    0,    0,  138,    0,    7,   -7,    0,   -1,    1, 1824,    0, 2104,    0,
+   2108, 2106,    0, 2106, 1316,    0,   -1, -138,    8,    8,    8,    0,    7,    7,   -8,   -8,
+     -8,   -7,-1316,    1,   -1,    3,   -3,    1,    0,-1914,-1918,    0,    0,-1923,-1824,    0,
+      0,-2016,-2104,    0,    0,-2106,-2108,-2106,-2250,    0,-2527,    0,
+};
+
+static inline uint_fast8_t
+_hb_ucd_gc (unsigned u)
+{
+  return u<1114110u?_hb_ucd_u8[6800+(((_hb_ucd_u8[1312+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
+}
+static inline uint_fast8_t
+_hb_ucd_ccc (unsigned u)
+{
+  return u<125259u?_hb_ucd_u8[8792+(((_hb_ucd_u8[8236+(((_hb_ucd_u8[7776+(((_hb_ucd_u8[7424+(((_hb_ucd_u8[7178+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
+}
+static inline unsigned
+_hb_ucd_b4 (const uint8_t* a, unsigned i)
+{
+  return (a[i>>1]>>((i&1u)<<2))&15u;
+}
+static inline int_fast16_t
+_hb_ucd_bmg (unsigned u)
+{
+  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9684+(((_hb_ucd_u8[9452+(((_hb_ucd_u8[9356+(((_hb_ucd_b4(9292+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
+}
+static inline uint_fast8_t
+_hb_ucd_sc (unsigned u)
+{
+  return u<918000u?_hb_ucd_u8[11118+(((_hb_ucd_u16[4024+(((_hb_ucd_u16[2040+(((_hb_ucd_u8[10382+(((_hb_ucd_u8[9932+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
+}
+static inline uint_fast16_t
+_hb_ucd_dm (unsigned u)
+{
+  return u<195102u?_hb_ucd_u16[6728+(((_hb_ucd_u8[13944+(((_hb_ucd_u8[13562+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+}
+
+
 #else
 
 static const uint8_t
diff --git a/src/hb-ucd.cc b/src/hb-ucd.cc
index baea224..4c8b1ee 100644
--- a/src/hb-ucd.cc
+++ b/src/hb-ucd.cc
@@ -129,12 +129,16 @@
 		hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab,
 		void *user_data HB_UNUSED)
 {
+  // Hangul is handled algorithmically.
   if (_hb_ucd_compose_hangul (a, b, ab)) return true;
 
   hb_codepoint_t u = 0;
 
   if ((a & 0xFFFFF800u) == 0x0000u && (b & 0xFFFFFF80) == 0x0300u)
   {
+    /* If "a" is small enough and "b" is in the U+0300 range,
+     * the composition data is encoded in a 32bit array sorted
+     * by "a,b" pair. */
     uint32_t k = HB_CODEPOINT_ENCODE3_11_7_14 (a, b, 0);
     const uint32_t *v = hb_bsearch (k,
 				    _hb_ucd_dm2_u32_map,
@@ -146,6 +150,8 @@
   }
   else
   {
+    /* Otherwise it is stored in a 64bit array sorted by
+     * "a,b" pair. */
     uint64_t k = HB_CODEPOINT_ENCODE3 (a, b, 0);
     const uint64_t *v = hb_bsearch (k,
 				    _hb_ucd_dm2_u64_map,
@@ -170,15 +176,22 @@
 
   unsigned i = _hb_ucd_dm (ab);
 
+  /* If no data, there's no decomposition. */
   if (likely (!i)) return false;
   i--;
 
+  /* Check if it's a single-character decomposition. */
   if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map))
   {
+    /* Single-character decompositions currently are only in plane 0 or plane 2. */
     if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map))
+    {
+      /* Plane 0. */
       *a = _hb_ucd_dm1_p0_map[i];
+    }
     else
     {
+      /* Plane 2. */
       i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map);
       *a = 0x20000 | _hb_ucd_dm1_p2_map[i];
     }
@@ -187,8 +200,10 @@
   }
   i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map);
 
+  /* Otherwise they are encoded either in a 32bit array or a 64bit array. */
   if (i < ARRAY_LENGTH (_hb_ucd_dm2_u32_map))
   {
+    /* 32bit array. */
     uint32_t v = _hb_ucd_dm2_u32_map[i];
     *a = HB_CODEPOINT_DECODE3_11_7_14_1 (v);
     *b = HB_CODEPOINT_DECODE3_11_7_14_2 (v);
@@ -196,6 +211,7 @@
   }
   i -= ARRAY_LENGTH (_hb_ucd_dm2_u32_map);
 
+  /* 64bit array. */
   uint64_t v = _hb_ucd_dm2_u64_map[i];
   *a = HB_CODEPOINT_DECODE3_1 (v);
   *b = HB_CODEPOINT_DECODE3_2 (v);
diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc
index c1795dc..9a6471e 100644
--- a/src/hb-unicode.cc
+++ b/src/hb-unicode.cc
@@ -377,20 +377,30 @@
 				    hb_destroy_func_t		    destroy)	\
 {										\
   if (hb_object_is_immutable (ufuncs))						\
-    return;									\
+    goto fail;									\
+										\
+  if (!func)									\
+  {										\
+    if (destroy)								\
+      destroy (user_data);							\
+    destroy = nullptr;								\
+    user_data = ufuncs->parent->user_data.name;					\
+  }										\
 										\
   if (ufuncs->destroy.name)							\
     ufuncs->destroy.name (ufuncs->user_data.name);				\
 										\
-  if (func) {									\
+  if (func)									\
     ufuncs->func.name = func;							\
-    ufuncs->user_data.name = user_data;						\
-    ufuncs->destroy.name = destroy;						\
-  } else {									\
+  else										\
     ufuncs->func.name = ufuncs->parent->func.name;				\
-    ufuncs->user_data.name = ufuncs->parent->user_data.name;			\
-    ufuncs->destroy.name = nullptr;						\
-  }										\
+  ufuncs->user_data.name = user_data;						\
+  ufuncs->destroy.name = destroy;						\
+  return;									\
+										\
+fail:										\
+  if (destroy)									\
+    destroy (user_data);							\
 }
 
 HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc
index 50f71ce..9648e02 100644
--- a/src/hb-uniscribe.cc
+++ b/src/hb-uniscribe.cc
@@ -355,7 +355,7 @@
     return nullptr;
   }
 
-  memcpy(new_sfnt_data, orig_sfnt_data, length);
+  hb_memcpy(new_sfnt_data, orig_sfnt_data, length);
 
   OT::name &name = StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
   name.format = 0;
@@ -478,11 +478,11 @@
 		   hb_font_t *font,
 		   unsigned int font_size)
 {
-  memset (lf, 0, sizeof (*lf));
+  hb_memset (lf, 0, sizeof (*lf));
   lf->lfHeight = - (int) font_size;
   lf->lfCharSet = DEFAULT_CHARSET;
 
-  memcpy (lf->lfFaceName, font->face->data.uniscribe->face_name, sizeof (lf->lfFaceName));
+  hb_memcpy (lf->lfFaceName, font->face->data.uniscribe->face_name, sizeof (lf->lfFaceName));
 
   return true;
 }
diff --git a/src/hb-vector.hh b/src/hb-vector.hh
index a6d9f6b..9b52f5c 100644
--- a/src/hb-vector.hh
+++ b/src/hb-vector.hh
@@ -35,7 +35,7 @@
 
 template <typename Type,
 	  bool sorted=false>
-struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty_t>::type
+struct hb_vector_t
 {
   typedef Type item_t;
   static constexpr unsigned item_size = hb_static_size (Type);
@@ -53,9 +53,10 @@
 	    hb_requires (hb_is_iterable (Iterable))>
   hb_vector_t (const Iterable &o) : hb_vector_t ()
   {
-    if (hb_iter (o).is_random_access_iterator)
-      alloc (hb_len (hb_iter (o)));
-    hb_copy (o, *this);
+    auto iter = hb_iter (o);
+    if (iter.is_random_access_iterator)
+      alloc (hb_len (iter));
+    hb_copy (iter, *this);
   }
   hb_vector_t (const hb_vector_t &o) : hb_vector_t ()
   {
@@ -83,6 +84,9 @@
     allocated = length = 0;
     arrayZ = nullptr;
   }
+  void init0 ()
+  {
+  }
 
   void fini ()
   {
@@ -94,7 +98,11 @@
   void reset ()
   {
     if (unlikely (in_error ()))
-      allocated = length; // Big hack!
+      /* Big Hack! We don't know the true allocated size before
+       * an allocation failure happened. But we know it was at
+       * least as big as length. Restore it to that and continue
+       * as if error did not happen. */
+      allocated = length;
     resize (0);
   }
 
@@ -122,7 +130,7 @@
   }
 
   hb_bytes_t as_bytes () const
-  { return hb_bytes_t ((const char *) arrayZ, length * item_size); }
+  { return hb_bytes_t ((const char *) arrayZ, get_size ()); }
 
   bool operator == (const hb_vector_t &o) const { return as_array () == o.as_array (); }
   bool operator != (const hb_vector_t &o) const { return !(*this == o); }
@@ -164,14 +172,10 @@
   operator   iter_t () const { return   iter (); }
   operator writer_t ()       { return writer (); }
 
-  c_array_t sub_array (unsigned int start_offset, unsigned int count) const
-  { return as_array ().sub_array (start_offset, count); }
-  c_array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
-  { return as_array ().sub_array (start_offset, count); }
-  array_t sub_array (unsigned int start_offset, unsigned int count)
-  { return as_array ().sub_array (start_offset, count); }
-  array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
-  { return as_array ().sub_array (start_offset, count); }
+  /* Faster range-based for loop. */
+  Type *begin () const { return arrayZ; }
+  Type *end () const { return arrayZ + length; }
+
 
   hb_sorted_array_t<Type> as_sorted_array ()
   { return hb_sorted_array (arrayZ, length); }
@@ -240,12 +244,11 @@
     if (likely (new_array))
     {
       for (unsigned i = 0; i < length; i++)
+      {
 	new (std::addressof (new_array[i])) Type ();
-      for (unsigned i = 0; i < (unsigned) length; i++)
 	new_array[i] = std::move (arrayZ[i]);
-      unsigned old_length = length;
-      shrink_vector (0);
-      length = old_length;
+	arrayZ[i].~Type ();
+      }
       hb_free (arrayZ);
     }
     return new_array;
@@ -277,7 +280,14 @@
   copy_vector (const hb_vector_t &other)
   {
     length = other.length;
-    hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size);
+#ifndef HB_OPTIMIZE_SIZE
+    if (sizeof (T) >= sizeof (long long))
+      /* This runs faster because of alignment. */
+      for (unsigned i = 0; i < length; i++)
+	arrayZ[i] = other.arrayZ[i];
+    else
+#endif
+       hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size);
   }
   template <typename T = Type,
 	    hb_enable_if (!hb_is_trivially_copyable (T) &&
@@ -309,15 +319,6 @@
     }
   }
 
-  template <typename T = Type,
-	    hb_enable_if (hb_is_trivially_destructible(T))>
-  void
-  shrink_vector (unsigned size)
-  {
-    length = size;
-  }
-  template <typename T = Type,
-	    hb_enable_if (!hb_is_trivially_destructible(T))>
   void
   shrink_vector (unsigned size)
   {
@@ -328,17 +329,6 @@
     }
   }
 
-  template <typename T = Type,
-	    hb_enable_if (hb_is_trivially_copy_assignable(T))>
-  void
-  shift_down_vector (unsigned i)
-  {
-    memmove (static_cast<void *> (&arrayZ[i - 1]),
-	     static_cast<void *> (&arrayZ[i]),
-	     (length - i) * sizeof (Type));
-  }
-  template <typename T = Type,
-	    hb_enable_if (!hb_is_trivially_copy_assignable(T))>
   void
   shift_down_vector (unsigned i)
   {
@@ -381,16 +371,22 @@
     return true;
   }
 
-  bool resize (int size_)
+  bool resize (int size_, bool initialize = true)
   {
     unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
     if (!alloc (size))
       return false;
 
     if (size > length)
-      grow_vector (size);
+    {
+      if (initialize)
+	grow_vector (size);
+    }
     else if (size < length)
-      shrink_vector (size);
+    {
+      if (initialize)
+	shrink_vector (size);
+    }
 
     length = size;
     return true;
@@ -399,13 +395,13 @@
   Type pop ()
   {
     if (!length) return Null (Type);
-    Type v = arrayZ[length - 1];
+    Type v {std::move (arrayZ[length - 1])};
     arrayZ[length - 1].~Type ();
     length--;
     return v;
   }
 
-  void remove (unsigned int i)
+  void remove_ordered (unsigned int i)
   {
     if (unlikely (i >= length))
       return;
@@ -414,6 +410,18 @@
     length--;
   }
 
+  template <bool Sorted = sorted,
+	    hb_enable_if (!Sorted)>
+  void remove_unordered (unsigned int i)
+  {
+    if (unlikely (i >= length))
+      return;
+    if (i != length - 1)
+      arrayZ[i] = std::move (arrayZ[length - 1]);
+    arrayZ[length - 1].~Type ();
+    length--;
+  }
+
   void shrink (int size_)
   {
     unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
@@ -425,10 +433,8 @@
 
 
   /* Sorting API. */
-  void qsort (int (*cmp)(const void*, const void*))
+  void qsort (int (*cmp)(const void*, const void*) = Type::cmp)
   { as_array ().qsort (cmp); }
-  void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
-  { as_array ().qsort (start, end); }
 
   /* Unsorted search API. */
   template <typename T>
diff --git a/src/hb-version.h b/src/hb-version.h
index 8d6ec66..1070262 100644
--- a/src/hb-version.h
+++ b/src/hb-version.h
@@ -41,26 +41,26 @@
  *
  * The major component of the library version available at compile-time.
  */
-#define HB_VERSION_MAJOR 5
+#define HB_VERSION_MAJOR 6
 /**
  * HB_VERSION_MINOR:
  *
  * The minor component of the library version available at compile-time.
  */
-#define HB_VERSION_MINOR 3
+#define HB_VERSION_MINOR 0
 /**
  * HB_VERSION_MICRO:
  *
  * The micro component of the library version available at compile-time.
  */
-#define HB_VERSION_MICRO 1
+#define HB_VERSION_MICRO 0
 
 /**
  * HB_VERSION_STRING:
  *
  * A string literal containing the library version available at compile-time.
  */
-#define HB_VERSION_STRING "5.3.1"
+#define HB_VERSION_STRING "6.0.0"
 
 /**
  * HB_VERSION_ATLEAST:
diff --git a/src/hb.hh b/src/hb.hh
index 8ec638a..410d090 100644
--- a/src/hb.hh
+++ b/src/hb.hh
@@ -126,6 +126,7 @@
 /* Ignored intentionally. */
 #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
 #pragma GCC diagnostic ignored "-Wclass-memaccess"
+#pragma GCC diagnostic ignored "-Wcast-function-type-strict" // https://github.com/harfbuzz/harfbuzz/pull/3859#issuecomment-1295409126
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
 #pragma GCC diagnostic ignored "-Wformat-zero-length"
 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
diff --git a/src/main.cc b/src/main.cc
index 99e1528..bb18ebe 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -58,7 +58,8 @@
     const char *data = hb_blob_get_data (blob, &length);
 
     char output_path[255];
-    sprintf (output_path, "out/svg-%u-%u.svg%s",
+    snprintf (output_path, sizeof output_path,
+	     "out/svg-%u-%u.svg%s",
 	     glyph_id,
 	     face_index,
 	     // append "z" if the content is gzipped, https://stackoverflow.com/a/6059405
@@ -112,7 +113,7 @@
 	const char *data = hb_blob_get_data (blob, &length);
 
 	char output_path[255];
-	sprintf (output_path, "out/png-%u-%u-%u.png", glyph_id, strike, face_index);
+	snprintf (output_path, sizeof output_path, "out/png-%u-%u-%u.png", glyph_id, strike, face_index);
 
 	FILE *f = fopen (output_path, "wb");
 	fwrite (data, 1, length, f);
@@ -224,7 +225,7 @@
 	}
 
 	char output_path[255];
-	sprintf (output_path, "out/colr-%u-%u-%u.svg", gid, palette, face_index);
+	snprintf (output_path, sizeof output_path, "out/colr-%u-%u-%u.svg", gid, palette, face_index);
 	FILE *f = fopen (output_path, "wb");
 	fprintf (f, "<svg xmlns=\"http://www.w3.org/2000/svg\""
 		    " viewBox=\"%d %d %d %d\">\n",
@@ -274,7 +275,7 @@
     }
 
     char output_path[255];
-    sprintf (output_path, "out/%u-%u.svg", face_index, gid);
+    snprintf (output_path, sizeof output_path, "out/%u-%u.svg", face_index, gid);
     FILE *f = fopen (output_path, "wb");
     fprintf (f, "<svg xmlns=\"http://www.w3.org/2000/svg\""
 		" viewBox=\"%d %d %d %d\"><path d=\"",
diff --git a/src/meson.build b/src/meson.build
index ba3470f..5d01d98 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -56,6 +56,7 @@
   'hb-map.hh',
   'hb-meta.hh',
   'hb-ms-feature-ranges.hh',
+  'hb-multimap.hh',
   'hb-mutex.hh',
   'hb-null.hh',
   'hb-number.cc',
@@ -414,33 +415,40 @@
 
 libharfbuzz_link_language = 'c'
 
+hb_features = configuration_data()
+
 if conf.get('HAVE_FREETYPE', 0) == 1
   hb_sources += hb_ft_sources
   hb_headers += hb_ft_headers
   harfbuzz_deps += [freetype_dep]
+  hb_features.set('HB_HAS_FREETYPE', 1)
 endif
 
 if conf.get('HAVE_GDI', 0) == 1
   hb_sources += hb_gdi_sources
   hb_headers += hb_gdi_headers
   harfbuzz_deps += gdi_uniscribe_deps
+  hb_features.set('HB_HAS_GDI', 1)
 endif
 
 if conf.get('HAVE_GRAPHITE2', 0) == 1
   hb_sources += hb_graphite2_sources
   hb_headers += hb_graphite2_headers
   harfbuzz_deps += [graphite2_dep, graphite_dep]
+  hb_features.set('HB_HAS_GRAPHITE', 1)
 endif
 
 if conf.get('HAVE_GLIB', 0) == 1
   hb_sources += hb_glib_sources
   hb_headers += hb_glib_headers
   harfbuzz_deps += [glib_dep]
+  hb_features.set('HB_HAS_GLIB', 1)
 endif
 
 if conf.get('HAVE_UNISCRIBE', 0) == 1
   hb_sources += hb_uniscribe_sources
   hb_headers += hb_uniscribe_headers
+  hb_features.set('HB_HAS_UNISCRIBE', 1)
 endif
 
 if conf.get('HAVE_DIRECTWRITE', 0) == 1
@@ -448,12 +456,14 @@
   hb_headers += hb_directwrite_headers
   # hb-directwrite needs a C++ linker
   libharfbuzz_link_language = 'cpp'
+  hb_features.set('HB_HAS_DIRECTWRITE', 1)
 endif
 
 if conf.get('HAVE_CORETEXT', 0) == 1
   hb_sources += hb_coretext_sources
   hb_headers += hb_coretext_headers
   harfbuzz_deps += coretext_deps
+  hb_features.set('HB_HAS_CORETEXT', 1)
 endif
 
 have_icu = conf.get('HAVE_ICU', 0) == 1
@@ -463,8 +473,17 @@
   hb_sources += hb_icu_sources
   hb_headers += hb_icu_headers
   harfbuzz_deps += [icu_dep]
+  hb_features.set('HB_HAS_ICU', 1)
 endif
 
+hb_features_h = configure_file(input: 'hb-features.h.in',
+                               output: 'hb-features.h',
+                               configuration: hb_features,
+                               install: true,
+                               install_dir: get_option('includedir') / meson.project_name())
+
+# Base and default-included sources and headers
+
 # harfbuzz
 gen_def = find_program('gen-def.py')
 
@@ -580,6 +599,7 @@
     'test-iter': ['test-iter.cc', 'hb-static.cc'],
     'test-machinery': ['test-machinery.cc', 'hb-static.cc'],
     'test-map': ['test-map.cc', 'hb-static.cc'],
+    'test-multimap': ['test-multimap.cc', 'hb-static.cc'],
     'test-number': ['test-number.cc', 'hb-number.cc'],
     'test-ot-tag': ['hb-ot-tag.cc'],
     'test-priority-queue': ['test-priority-queue.cc', 'hb-static.cc'],
@@ -657,8 +677,8 @@
 have_gobject = conf.get('HAVE_GOBJECT', 0) == 1
 
 cmake_config = configuration_data()
-cmake_config.set('libdir', '${prefix}/@0@'.format(get_option('libdir')))
-cmake_config.set('includedir', '${prefix}/@0@'.format(get_option('includedir')))
+cmake_config.set('libdir', get_option('prefix') / get_option('libdir'))
+cmake_config.set('includedir', get_option('prefix') / get_option('includedir'))
 cmake_config.set('HB_LIBTOOL_VERSION_INFO', hb_libtool_version_info)
 cmake_config.set('have_gobject', '@0@'.format(have_gobject))
 configure_file(input: 'harfbuzz-config.cmake.in',
diff --git a/src/sample.py b/src/sample.py
index fd85048..5d04e80 100755
--- a/src/sample.py
+++ b/src/sample.py
@@ -2,6 +2,8 @@
 
 import sys
 import array
+import gi
+gi.require_version('HarfBuzz', '0.0')
 from gi.repository import HarfBuzz as hb
 from gi.repository import GLib
 
diff --git a/src/test-array.cc b/src/test-array.cc
index 6c88813..28cd023 100644
--- a/src/test-array.cc
+++ b/src/test-array.cc
@@ -70,6 +70,9 @@
 int
 main (int argc, char **argv)
 {
+  /* The following fails on MSVC. */
+  // assert (sizeof (hb_array_t<int>) == sizeof (hb_sorted_array_t<int>));
+
   test_reverse ();
   test_reverse_range ();
   test_reverse_invalid ();
diff --git a/src/test-buffer-serialize.cc b/src/test-buffer-serialize.cc
index bbebcbe..8a88792 100644
--- a/src/test-buffer-serialize.cc
+++ b/src/test-buffer-serialize.cc
@@ -43,10 +43,8 @@
 
 #ifndef HB_NO_BUFFER_SERIALIZE
 
-  if (argc != 2) {
-    fprintf (stderr, "usage: %s font-file\n", argv[0]);
-    exit (1);
-  }
+  if (argc < 2)
+    argv[1] = (char *) "/dev/null";
 
   hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
   assert (blob);
@@ -58,7 +56,7 @@
   hb_font_t *font = hb_font_create (face);
   hb_face_destroy (face);
   hb_font_set_scale (font, upem, upem);
-  hb_ot_font_set_funcs (font);
+  //hb_ot_font_set_funcs (font);
 #ifdef HAVE_FREETYPE
   //hb_ft_font_set_funcs (font);
 #endif
diff --git a/src/test-iter.cc b/src/test-iter.cc
index c37d1e7..bb966d4 100644
--- a/src/test-iter.cc
+++ b/src/test-iter.cc
@@ -319,13 +319,36 @@
   ;
   /* The result should be something like 0->10, 1->11, ..., 9->19 */
   assert (hb_map_get (result, 9) == 19);
+  hb_map_destroy (result);
+
+  /* Like above, but passing hb_set_t instead of hb_set_t * */
+  temp1 = 10;
+  temp2 = 0;
+  result =
+  + hb_iter (src)
+  | hb_map ([&] (int i) -> hb_set_t
+	    {
+	      hb_set_t set;
+	      for (unsigned int i = 0; i < temp1; ++i)
+		hb_set_add (&set, i);
+	      temp1++;
+	      return set;
+	    })
+  | hb_reduce ([&] (hb_map_t *acc, hb_set_t value) -> hb_map_t *
+	       {
+		 hb_map_set (acc, temp2++, hb_set_get_population (&value));
+		 return acc;
+	       }, hb_map_create ())
+  ;
+  /* The result should be something like 0->10, 1->11, ..., 9->19 */
+  assert (hb_map_get (result, 9) == 19);
+  hb_map_destroy (result);
 
   unsigned int temp3 = 0;
   + hb_iter(src)
   | hb_map([&] (int i) { return ++temp3; })
   | hb_reduce([&] (float acc, int value) { return acc + value; }, 0)
   ;
-  hb_map_destroy (result);
 
   + hb_iter (src)
   | hb_drain
diff --git a/src/test-map.cc b/src/test-map.cc
index 357a8b0..da77a2f 100644
--- a/src/test-map.cc
+++ b/src/test-map.cc
@@ -179,20 +179,43 @@
 
     hb_hashmap_t<vector_t, vector_t> m1;
 
-    m1.set (vector_t (), vector_t ());
     m1.set (vector_t (), vector_t {1});
     m1.set (vector_t {1}, vector_t {2});
 
+    m1 << hb_pair_t<vector_t, vector_t> {vector_t {2}, vector_t ()};
+
     assert (m1.get (vector_t ()) == vector_t {1});
     assert (m1.get (vector_t {1}) == vector_t {2});
   }
 
+  /* Test moving values */
+  {
+    using vector_t = hb_vector_t<unsigned>;
+
+    hb_hashmap_t<vector_t, vector_t> m1;
+    vector_t v {3};
+    assert (v.length == 1);
+    m1 << hb_pair_t<vector_t, vector_t> {vector_t {3}, v};
+    assert (v.length == 1);
+    m1 << hb_pair_t<vector_t, vector_t&&> {vector_t {4}, std::move (v)};
+    assert (v.length == 0);
+    m1 << hb_pair_t<vector_t&&, vector_t> {vector_t {4}, vector_t {5}};
+    m1 << hb_pair_t<vector_t&&, vector_t&&> {vector_t {4}, vector_t {5}};
+
+    hb_hashmap_t<vector_t, vector_t> m2;
+    vector_t v2 {3};
+    m2.set (vector_t {4}, v2);
+    assert (v2.length == 1);
+    m2.set (vector_t {5}, std::move (v2));
+    assert (v2.length == 0);
+  }
+
   /* Test hb::shared_ptr. */
-  hb_hash (hb::shared_ptr<hb_set_t> ());
   {
     hb_hashmap_t<hb::shared_ptr<hb_set_t>, hb::shared_ptr<hb_set_t>> m;
 
-    m.get (hb::shared_ptr<hb_set_t> ());
+    m.set (hb::shared_ptr<hb_set_t> (hb_set_get_empty ()),
+	   hb::shared_ptr<hb_set_t> (hb_set_get_empty ()));
     m.get (hb::shared_ptr<hb_set_t> (hb_set_get_empty ()));
     m.iter ();
     m.keys ();
@@ -202,12 +225,14 @@
     m.values_ref ();
   }
   /* Test hb::unique_ptr. */
-  hb_hash (hb::unique_ptr<hb_set_t> ());
   {
     hb_hashmap_t<hb::unique_ptr<hb_set_t>, hb::unique_ptr<hb_set_t>> m;
 
-    m.get (hb::unique_ptr<hb_set_t> ());
+    m.set (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()),
+           hb::unique_ptr<hb_set_t> (hb_set_get_empty ()));
     m.get (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()));
+    hb::unique_ptr<hb_set_t> *v;
+    m.has (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()), &v);
     m.iter_ref ();
     m.keys_ref ();
     m.values_ref ();
@@ -234,11 +259,48 @@
     hb::shared_ptr<hb_map_t> p1 {m1};
     hb::shared_ptr<hb_map_t> p2 {m2};
     m.set (p1,1);
-    
+
     assert (m.has (p2));
 
     m1->set (2,4);
     assert (!m.has (p2));
   }
+  /* Test value type with hb_bytes_t. */
+  {
+    hb_hashmap_t<int, hb_bytes_t> m;
+    char c_str[] = "Test";
+    hb_bytes_t bytes (c_str);
+
+    m.set (1, bytes);
+    assert (m.has (1));
+  }
+  /* Test operators. */
+  {
+    hb_map_t m1, m2, m3;
+    m1.set (1, 2);
+    m1.set (2, 4);
+    m2.set (1, 2);
+    m2.set (2, 4);
+    m3.set (1, 3);
+    m3.set (3, 5);
+
+    assert (m1 == m2);
+    assert (m1 != m3);
+    assert (!(m2 == m3));
+
+    m2 = m3;
+    assert (m2.has (1));
+    assert (!m2.has (2));
+    assert (m2.has (3));
+
+    assert (m3.has (3));
+  }
+  /* Test reset. */
+  {
+    hb_hashmap_t<int, hb_set_t> m;
+    m.set (1, hb_set_t {1, 2, 3});
+    m.reset ();
+  }
+
   return 0;
 }
diff --git a/src/test-multimap.cc b/src/test-multimap.cc
new file mode 100644
index 0000000..8cd8f52
--- /dev/null
+++ b/src/test-multimap.cc
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2022  Behdad Esfahbod
+ *
+ *  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.
+ */
+
+#include "hb.hh"
+#include "hb-multimap.hh"
+
+int
+main (int argc, char **argv)
+{
+  hb_multimap_t m;
+
+  assert (m.get (10).length == 0);
+
+  m.add (10, 11);
+  assert (m.get (10).length == 1);
+
+  m.add (10, 12);
+  assert (m.get (10).length == 2);
+
+  m.add (10, 13);
+  assert (m.get (10).length == 3);
+  assert (m.get (10)[0] == 11);
+  assert (m.get (10)[1] == 12);
+  assert (m.get (10)[2] == 13);
+
+  assert (m.get (11).length == 0);
+  m.add (11, 14);
+  assert (m.get (10).length == 3);
+  assert (m.get (11).length == 1);
+  assert (m.get (12).length == 0);
+  assert (m.get (10)[0] == 11);
+  assert (m.get (10)[1] == 12);
+  assert (m.get (10)[2] == 13);
+  assert (m.get (11)[0] == 14);
+  assert (m.get (12)[0] == 0); // Array fallback value
+
+  return 0;
+}
diff --git a/src/test-repacker.cc b/src/test-repacker.cc
index cd8789f..94ff084 100644
--- a/src/test-repacker.cc
+++ b/src/test-repacker.cc
@@ -35,7 +35,7 @@
                     hb_serialize_context_t* c)
 {
   char* obj = c->allocate_size<char> (len);
-  memcpy (obj, value, len);
+  hb_memcpy (obj, value, len);
 }
 
 static void start_object(const char* tag,
@@ -1476,6 +1476,7 @@
 
   graph_t graph (c.object_graph ());
   graph.sort_shortest_distance ();
+  assert (!graph.in_error ());
 
   assert(strncmp (graph.object (4).head, "abc", 3) == 0);
   assert(graph.object (4).real_links.length == 3);
diff --git a/src/test-set.cc b/src/test-set.cc
index 983a159..e760c98 100644
--- a/src/test-set.cc
+++ b/src/test-set.cc
@@ -34,6 +34,7 @@
     hb_set_t v1 {1, 2};
     hb_set_t v2 {v1};
     assert (v1.get_population () == 2);
+    assert (hb_len (hb_iter (v1)) == 2);
     assert (v2.get_population () == 2);
   }
 
@@ -51,6 +52,7 @@
     hb_set_t s {1, 2};
     hb_set_t v (std::move (s));
     assert (s.get_population () == 0);
+    assert (hb_len (hb_iter (s)) == 0);
     assert (v.get_population () == 2);
   }
 
@@ -86,11 +88,14 @@
     hb_set_t s;
 
     s.add (18);
-    s.add (12);
+    s << 12;
+
+    /* Sink a range. */
+    s << hb_pair_t<hb_codepoint_t, hb_codepoint_t> {1, 3};
 
     hb_set_t v (hb_iter (s));
 
-    assert (v.get_population () == 2);
+    assert (v.get_population () == 5);
   }
 
   /* Test initializing from initializer list and swapping. */
diff --git a/src/test-vector.cc b/src/test-vector.cc
index 37bec30..65e51c6 100644
--- a/src/test-vector.cc
+++ b/src/test-vector.cc
@@ -26,12 +26,14 @@
 #include "hb.hh"
 #include "hb-vector.hh"
 #include "hb-set.hh"
+#include "hb-map.hh"
 #include <string>
 
 
 int
 main (int argc, char **argv)
 {
+  assert (sizeof (hb_vector_t<int>) == sizeof (hb_sorted_vector_t<int>));
 
   /* Test copy constructor. */
   {
@@ -160,7 +162,24 @@
 
     v2 = v;
 
-    v2.remove (50);
+    v2.remove_ordered (50);
+    v2.remove_unordered (50);
+  }
+
+  {
+    hb_vector_t<hb_set_t> v;
+    hb_set_t s {1, 5, 7};
+    v.push (s);
+    v << s;
+    assert (s.get_population () == 3);
+    v << std::move (s);
+    assert (s.get_population () == 0);
+  }
+
+  {
+    hb_vector_t<hb_map_t> v;
+    hb_map_t m;
+    v.push (m);
   }
 
   return 0;
diff --git a/subprojects/freetype2.wrap b/subprojects/freetype2.wrap
index 43ab8fa..1ff89ec 100644
--- a/subprojects/freetype2.wrap
+++ b/subprojects/freetype2.wrap
@@ -1,7 +1,9 @@
-[wrap-git]
-directory=freetype
-url=https://gitlab.freedesktop.org/freetype/freetype.git
-revision=VER-2-11-0
+[wrap-file]
+directory = freetype-2.12.1
+source_url = https://download.savannah.gnu.org/releases/freetype/freetype-2.12.1.tar.xz
+source_filename = freetype-2.12.1.tar.xz
+source_hash = 4766f20157cc4cf0cd292f80bf917f92d1c439b243ac3018debf6b9140c41a7f
+wrapdb_version = 2.12.1-2
 
 [provide]
 freetype2 = freetype_dep
diff --git a/subprojects/glib.wrap b/subprojects/glib.wrap
index 9143090..a865af4 100644
--- a/subprojects/glib.wrap
+++ b/subprojects/glib.wrap
@@ -1,10 +1,11 @@
-[wrap-git]
-directory=glib
-url=https://gitlab.gnome.org/GNOME/glib.git
-depth=1
[email protected]:GNOME/glib.git
-revision=2.58.1
+[wrap-file]
+directory = glib-2.74.1
+source_url = https://download.gnome.org/sources/glib/2.74/glib-2.74.1.tar.xz
+source_fallback_url = https://ftp.acc.umu.se/pub/gnome/sources/glib/2.74/glib-2.74.1.tar.xz
+source_filename = glib-2.74.1.tar.xz
+source_hash = 0ab981618d1db47845e56417b0d7c123f81a3427b2b9c93f5a46ff5bbb964964
+wrapdb_version = 2.74.1-1
 
 [provide]
-glib-2.0 = libglib_dep
-gobject-2.0 = libgobject_dep
+dependency_names = gthread-2.0, gobject-2.0, gmodule-no-export-2.0, gmodule-export-2.0, gmodule-2.0, glib-2.0, gio-2.0, gio-windows-2.0, gio-unix-2.0
+program_names = glib-genmarshal, glib-mkenums, glib-compile-schemas, glib-compile-resources, gio-querymodules, gdbus-codegen
diff --git a/subprojects/google-benchmark.wrap b/subprojects/google-benchmark.wrap
index 268ddf9..6205cd7 100644
--- a/subprojects/google-benchmark.wrap
+++ b/subprojects/google-benchmark.wrap
@@ -1,11 +1,12 @@
 [wrap-file]
-directory = benchmark-1.6.0
-source_url = https://github.com/google/benchmark/archive/refs/tags/v1.6.0.tar.gz
-source_filename = benchmark-1.6.0.tar.gz
-source_hash = 1f71c72ce08d2c1310011ea6436b31e39ccab8c2db94186d26657d41747c85d6
-patch_filename = google-benchmark_1.6.0-1_patch.zip
-patch_url = https://wrapdb.mesonbuild.com/v2/google-benchmark_1.6.0-1/get_patch
-patch_hash = f2feff0641a5ebf6b893a4f49ea0bff566ba866ee993c5c3aef62ff40cdc6b14
+directory = benchmark-1.7.1
+source_url = https://github.com/google/benchmark/archive/refs/tags/v1.7.1.tar.gz
+source_filename = benchmark-1.7.1.tar.gz
+source_hash = 6430e4092653380d9dc4ccb45a1e2dc9259d581f4866dc0759713126056bc1d7
+patch_filename = google-benchmark_1.7.1-1_patch.zip
+patch_url = https://wrapdb.mesonbuild.com/v2/google-benchmark_1.7.1-1/get_patch
+patch_hash = 9c6694328ac971cd781aa67c45c64291c087f118e23b75946f52670caacf49b7
+wrapdb_version = 1.7.1-1
 
 [provide]
 benchmark = google_benchmark_dep
diff --git a/subprojects/zlib.wrap b/subprojects/zlib.wrap
new file mode 100644
index 0000000..23af071
--- /dev/null
+++ b/subprojects/zlib.wrap
@@ -0,0 +1,12 @@
+[wrap-file]
+directory = zlib-1.2.13
+source_url = http://zlib.net/fossils/zlib-1.2.13.tar.gz
+source_filename = zlib-1.2.13.tar.gz
+source_hash = b3a24de97a8fdbc835b9833169501030b8977031bcb54b3b3ac13740f846ab30
+patch_filename = zlib_1.2.13-2_patch.zip
+patch_url = https://wrapdb.mesonbuild.com/v2/zlib_1.2.13-2/get_patch
+patch_hash = a7abea3ad65dc2c291ad5fbbf5355d0585a7f7b8c935d4a74335b8fe18684506
+wrapdb_version = 1.2.13-2
+
+[provide]
+zlib = zlib_dep
diff --git a/test/api/fonts/nameID.override.expected.ttf b/test/api/fonts/nameID.override.expected.ttf
new file mode 100644
index 0000000..d17ea83
--- /dev/null
+++ b/test/api/fonts/nameID.override.expected.ttf
Binary files differ
diff --git a/test/api/test-subset-nameids.c b/test/api/test-subset-nameids.c
index b58a86c..e51b470 100644
--- a/test/api/test-subset-nameids.c
+++ b/test/api/test-subset-nameids.c
@@ -67,6 +67,44 @@
   hb_face_destroy (face_expected);
 }
 
+#ifdef HB_EXPERIMENTAL_API
+static void
+test_subset_name_overrides (void)
+{
+  hb_face_t *face_origin = hb_test_open_font_file ("fonts/nameID.origin.ttf");
+  hb_face_t *face_expected = hb_test_open_font_file ("fonts/nameID.override.expected.ttf");
+
+  char str1[] = "Roboto Test";
+  char str1_3[] = "Roboto Test unicode platform";
+  char str2[] = "Bold";
+  char str6[] = "Roboto-Bold";
+  char str12[] = "Non ascii test Ü";
+  char str16[] = "Roboto-test-inserting";
+ 
+  hb_set_t *name_ids = hb_set_create();
+  hb_face_t *face_subset;
+  hb_set_add_range (name_ids, 0, 15);
+
+  hb_subset_input_t *subset_input = hb_subset_test_create_input_from_nameids (name_ids);
+  hb_subset_input_override_name_table (subset_input, 1, 1, 0, 0, str1, -1);
+  hb_subset_input_override_name_table (subset_input, 1, 3, 1, 0x409, str1_3, -1);
+  hb_subset_input_override_name_table (subset_input, 2, 1, 0, 0, str2, 4);
+  hb_subset_input_override_name_table (subset_input, 6, 1, 0, 0, str6, -1);
+  hb_subset_input_override_name_table (subset_input, 12, 1, 0, 0, str12, -1);
+  hb_subset_input_override_name_table (subset_input, 14, 1, 0, 0, NULL, -1);
+  hb_subset_input_override_name_table (subset_input, 16, 1, 0, 0, str16, -1);
+
+  face_subset = hb_subset_test_create_subset (face_origin, subset_input);
+  hb_set_destroy (name_ids);
+
+  hb_subset_test_check (face_expected, face_subset, HB_TAG ('n','a','m','e'));
+
+  hb_face_destroy (face_subset);
+  hb_face_destroy (face_origin);
+  hb_face_destroy (face_expected);
+}
+#endif
+
 int
 main (int argc, char **argv)
 {
@@ -74,6 +112,9 @@
 
   hb_test_add (test_subset_nameids);
   hb_test_add (test_subset_nameids_with_dup_strs);
+#ifdef HB_EXPERIMENTAL_API
+  hb_test_add (test_subset_name_overrides);
+#endif
 
   return hb_test_run();
 }
diff --git a/test/api/test-unicode.c b/test/api/test-unicode.c
index 4ec718b..857308b 100644
--- a/test/api/test-unicode.c
+++ b/test/api/test-unicode.c
@@ -754,9 +754,9 @@
     /* Since uf is immutable now, the following setter should do nothing. */
     p->func_setter (uf, (get_func_t) a_is_for_arabic_get_script, &data[1], free_up);
 
-    g_assert (data[0].freed && !data[1].freed);
+    g_assert (data[0].freed && data[1].freed);
     hb_unicode_funcs_destroy (uf);
-    g_assert (data[0].freed && !data[1].freed);
+    g_assert (data[0].freed && data[1].freed);
   }
 }
 
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-6635625931735040 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-6635625931735040
new file mode 100644
index 0000000..333ebaa
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-6635625931735040
Binary files differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5845846876356608 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5845846876356608
new file mode 100644
index 0000000..faf2e85
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5845846876356608
Binary files differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6164014466203648 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6164014466203648
new file mode 100644
index 0000000..3a15ab2
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6164014466203648
Binary files differ
diff --git a/test/fuzzing/graphs/clusterfuzz-testcase-minimized-hb-repacker-fuzzer-5390364397928448 b/test/fuzzing/graphs/clusterfuzz-testcase-minimized-hb-repacker-fuzzer-5390364397928448
new file mode 100644
index 0000000..54ee816
--- /dev/null
+++ b/test/fuzzing/graphs/clusterfuzz-testcase-minimized-hb-repacker-fuzzer-5390364397928448
Binary files differ
diff --git a/test/fuzzing/graphs/clusterfuzz-testcase-minimized-hb-repacker-fuzzer-6014493291577344 b/test/fuzzing/graphs/clusterfuzz-testcase-minimized-hb-repacker-fuzzer-6014493291577344
new file mode 100644
index 0000000..a29d1e2
--- /dev/null
+++ b/test/fuzzing/graphs/clusterfuzz-testcase-minimized-hb-repacker-fuzzer-6014493291577344
Binary files differ
diff --git a/test/fuzzing/graphs/clusterfuzz-testcase-minimized-hb-repacker-fuzzer-6714085985353728 b/test/fuzzing/graphs/clusterfuzz-testcase-minimized-hb-repacker-fuzzer-6714085985353728
new file mode 100644
index 0000000..aeee90b
--- /dev/null
+++ b/test/fuzzing/graphs/clusterfuzz-testcase-minimized-hb-repacker-fuzzer-6714085985353728
Binary files differ
diff --git a/test/fuzzing/graphs/crash-3bf72494aa4c9f8cbbcbf887fdc2a2858c87feb4 b/test/fuzzing/graphs/crash-3bf72494aa4c9f8cbbcbf887fdc2a2858c87feb4
new file mode 100644
index 0000000..ff8da7b
--- /dev/null
+++ b/test/fuzzing/graphs/crash-3bf72494aa4c9f8cbbcbf887fdc2a2858c87feb4
Binary files differ
diff --git a/test/fuzzing/graphs/crash-442bfac994a3d9929cf06262ae9fb00f6ee1f774 b/test/fuzzing/graphs/crash-442bfac994a3d9929cf06262ae9fb00f6ee1f774
new file mode 100644
index 0000000..0160ce5
--- /dev/null
+++ b/test/fuzzing/graphs/crash-442bfac994a3d9929cf06262ae9fb00f6ee1f774
Binary files differ
diff --git a/test/fuzzing/graphs/leak-a77f29b25edb873729f3ab120148fdb213cfa527 b/test/fuzzing/graphs/leak-a77f29b25edb873729f3ab120148fdb213cfa527
new file mode 100644
index 0000000..58b4075
--- /dev/null
+++ b/test/fuzzing/graphs/leak-a77f29b25edb873729f3ab120148fdb213cfa527
Binary files differ
diff --git a/test/fuzzing/graphs/noto_nastaliq_urdu b/test/fuzzing/graphs/noto_nastaliq_urdu
new file mode 100644
index 0000000..2e3cab8
--- /dev/null
+++ b/test/fuzzing/graphs/noto_nastaliq_urdu
Binary files differ
diff --git a/test/fuzzing/hb-repacker-fuzzer.cc b/test/fuzzing/hb-repacker-fuzzer.cc
new file mode 100644
index 0000000..0b06fd2
--- /dev/null
+++ b/test/fuzzing/hb-repacker-fuzzer.cc
@@ -0,0 +1,145 @@
+#include "hb-fuzzer.hh"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "hb-subset-repacker.h"
+
+typedef struct
+{
+  uint16_t parent;
+  uint16_t child;
+  uint16_t position;
+  uint8_t width;
+} link_t;
+
+/* The fuzzer seed contains a serialized representation of a object graph which forms
+ * the input graph to the repacker call. The binary format is:
+ *
+ * table tag: 4 bytes
+ * number of objects: 2 bytes
+ * objects[number of objects]:
+ *   blob size: 2 bytes
+ *   blob: blob size bytes
+ * num of real links: 2 bytes
+ * links[number of real links]: link_t struct
+ *
+ * TODO(garretrieger): add optional virtual links
+ */
+
+template <typename T>
+bool read(const uint8_t** data, size_t* size, T* out)
+{
+  if (*size < sizeof (T)) return false;
+
+  memcpy(out, *data, sizeof (T));
+
+  *data += sizeof (T);
+  *size -= sizeof (T);
+
+  return true;
+}
+
+void cleanup (hb_object_t* objects, uint16_t num_objects)
+{
+  for (uint32_t i = 0; i < num_objects; i++)
+  {
+    free (objects[i].head);
+    free (objects[i].real_links);
+  }
+}
+
+void add_links_to_objects (hb_object_t* objects, uint16_t num_objects,
+                           link_t* links, uint16_t num_links)
+{
+  unsigned* link_count = (unsigned*) calloc (num_objects, sizeof (unsigned));
+
+  for (uint32_t i = 0; i < num_links; i++)
+  {
+    uint16_t parent_idx = links[i].parent;
+    link_count[parent_idx]++;
+  }
+
+  for (uint32_t i = 0; i < num_objects; i++)
+  {
+    objects[i].num_real_links = link_count[i];
+    objects[i].real_links = (hb_link_t*) calloc (link_count[i], sizeof (hb_link_t));
+    objects[i].num_virtual_links = 0;
+    objects[i].virtual_links = nullptr;
+  }
+
+  for (uint32_t i = 0; i < num_links; i++)
+  {
+    uint16_t parent_idx = links[i].parent;
+    uint16_t child_idx = links[i].child + 1; // All indices are shifted by 1 by the null object.
+    hb_link_t* link = &(objects[parent_idx].real_links[link_count[parent_idx] - 1]);
+
+    link->width = links[i].width;
+    link->position = links[i].position;
+    link->objidx = child_idx;
+    link_count[parent_idx]--;
+  }
+
+  free (link_count);
+}
+
+extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
+{
+  // TODO(garretrieger): move graph validity checks into repacker graph creation.
+  alloc_state = _fuzzing_alloc_state (data, size);
+
+  uint16_t num_objects = 0;
+  hb_object_t* objects = nullptr;
+
+  uint16_t num_real_links = 0;
+  link_t* links = nullptr;
+
+  hb_tag_t table_tag;
+  if (!read<hb_tag_t> (&data, &size, &table_tag)) goto end;
+  if (!read<uint16_t> (&data, &size, &num_objects)) goto end;
+
+  objects = (hb_object_t*) calloc (num_objects, sizeof (hb_object_t));
+  for (uint32_t i = 0; i < num_objects; i++)
+  {
+    uint16_t blob_size;
+    if (!read<uint16_t> (&data, &size, &blob_size)) goto end;
+    if (size < blob_size) goto end;
+
+    char* copy = (char*) calloc (1, blob_size);
+    memcpy (copy, data, blob_size);
+    objects[i].head = (char*) copy;
+    objects[i].tail = (char*) (copy + blob_size);
+
+    size -= blob_size;
+    data += blob_size;
+  }
+
+  if (!read<uint16_t> (&data, &size, &num_real_links)) goto end;
+  links = (link_t*) calloc (num_real_links, sizeof (link_t));
+  for (uint32_t i = 0; i < num_real_links; i++)
+  {
+    if (!read<link_t> (&data, &size, &links[i])) goto end;
+
+    if (links[i].parent >= num_objects)
+      goto end;
+  }
+
+  add_links_to_objects (objects, num_objects,
+                        links, num_real_links);
+
+  hb_blob_destroy (hb_subset_repack_or_fail (table_tag,
+                                             objects,
+                                             num_objects));
+
+end:
+  if (objects)
+  {
+    cleanup (objects, num_objects);
+    free (objects);
+  }
+  free (links);
+
+  return 0;
+}
diff --git a/test/fuzzing/meson.build b/test/fuzzing/meson.build
index 3aba9eb..d38ca8f 100644
--- a/test/fuzzing/meson.build
+++ b/test/fuzzing/meson.build
@@ -5,6 +5,10 @@
   'hb-draw-fuzzer.cc',
 ]
 
+if get_option('experimental_api')
+  tests += 'hb-repacker-fuzzer.cc'
+endif
+
 foreach file_name : tests
   test_name = file_name.split('.')[0]
 
@@ -19,6 +23,10 @@
     extra_cpp_args += '-DHB_IS_IN_FUZZER'
   endif
 
+  if get_option('experimental_api')
+    extra_cpp_args += '-DHB_EXPERIMENTAL_API'
+  endif
+
   exe = executable(test_name, sources,
     cpp_args: cpp_args + extra_cpp_args,
     include_directories: [incconfig, incsrc],
@@ -55,6 +63,20 @@
   suite: ['fuzzing', 'slow'],
 )
 
+if get_option('experimental_api')
+  test('repacker_fuzzer', find_program('run-repacker-fuzzer-tests.py'),
+    args: [
+      hb_repacker_fuzzer_exe,
+    ],
+    # as the tests are ran concurrently let's raise acceptable time here
+    # ideally better to break and let meson handles them in parallel
+    timeout: 300,
+    workdir: meson.current_build_dir() / '..' / '..',
+    env: env,
+    suite: ['fuzzing', 'slow'],
+  )
+endif
+
 test('draw_fuzzer', find_program('run-draw-fuzzer-tests.py'),
   args: [
     hb_draw_fuzzer_exe,
diff --git a/test/fuzzing/run-repacker-fuzzer-tests.py b/test/fuzzing/run-repacker-fuzzer-tests.py
new file mode 100644
index 0000000..85a23e1
--- /dev/null
+++ b/test/fuzzing/run-repacker-fuzzer-tests.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python3
+
+import sys, os, subprocess, tempfile, shutil
+
+
+def cmd (command):
+	# https://stackoverflow.com/a/4408409 as we might have huge output sometimes
+	with tempfile.TemporaryFile () as tempf:
+		p = subprocess.Popen (command, stderr=tempf)
+
+		try:
+			p.wait ()
+			tempf.seek (0)
+			text = tempf.read ()
+
+			#TODO: Detect debug mode with a better way
+			is_debug_mode = b"SANITIZE" in text
+
+			return ("" if is_debug_mode else text.decode ("utf-8").strip ()), p.returncode
+		except subprocess.TimeoutExpired:
+			return 'error: timeout, ' + ' '.join (command), 1
+
+
+srcdir = os.getenv ("srcdir", ".")
+EXEEXT = os.getenv ("EXEEXT", "")
+top_builddir = os.getenv ("top_builddir", ".")
+hb_repacker_fuzzer = os.path.join (top_builddir, "hb-repacker-fuzzer" + EXEEXT)
+
+if not os.path.exists (hb_repacker_fuzzer):
+        if len (sys.argv) < 2 or not os.path.exists (sys.argv[1]):
+                sys.exit ("""Failed to find hb-repacker-fuzzer binary automatically,
+please provide it as the first argument to the tool""")
+
+        hb_repacker_fuzzer = sys.argv[1]
+
+print ('hb_repacker_fuzzer:', hb_repacker_fuzzer)
+fails = 0
+
+valgrind = None
+if os.getenv ('RUN_VALGRIND', ''):
+	valgrind = shutil.which ('valgrind')
+	if valgrind is None:
+		sys.exit ("""Valgrind requested but not found.""")
+
+def run_dir (parent_path):
+	global fails
+	for file in os.listdir (parent_path):
+		path = os.path.join(parent_path, file)
+		print ("running repacker fuzzer against %s" % path)
+		if valgrind:
+			text, returncode = cmd ([valgrind, '--leak-check=full', '--error-exitcode=1', hb_repacker_fuzzer, path])
+		else:
+			text, returncode = cmd ([hb_repacker_fuzzer, path])
+			if 'error' in text:
+				returncode = 1
+
+		if (not valgrind or returncode) and text.strip ():
+			print (text)
+
+		if returncode != 0:
+			print ("failed for %s" % path)
+			fails = fails + 1
+
+
+run_dir (os.path.join (srcdir, "graphs"))
+
+if fails:
+	sys.exit ("%d repacker fuzzer related tests failed." % fails)
diff --git a/test/shape/data/in-house/fonts/5f73fff1ffc07b5a99a90c0909609f2b09fef274.ttf b/test/shape/data/in-house/fonts/5f73fff1ffc07b5a99a90c0909609f2b09fef274.ttf
new file mode 100644
index 0000000..f94d2aa
--- /dev/null
+++ b/test/shape/data/in-house/fonts/5f73fff1ffc07b5a99a90c0909609f2b09fef274.ttf
Binary files differ
diff --git a/test/shape/data/in-house/fonts/9d8c53cb64b8747abdd2b70755cce2ee0eb42ef7.ttf b/test/shape/data/in-house/fonts/9d8c53cb64b8747abdd2b70755cce2ee0eb42ef7.ttf
new file mode 100644
index 0000000..9c9f942
--- /dev/null
+++ b/test/shape/data/in-house/fonts/9d8c53cb64b8747abdd2b70755cce2ee0eb42ef7.ttf
Binary files differ
diff --git a/test/shape/data/in-house/fonts/a232bb734d4c6c898a44506547d19768f0eba6a6.ttf b/test/shape/data/in-house/fonts/a232bb734d4c6c898a44506547d19768f0eba6a6.ttf
new file mode 100644
index 0000000..e0325bb
--- /dev/null
+++ b/test/shape/data/in-house/fonts/a232bb734d4c6c898a44506547d19768f0eba6a6.ttf
Binary files differ
diff --git a/test/shape/data/in-house/tests/indic-special-cases.tests b/test/shape/data/in-house/tests/indic-special-cases.tests
index 016f894..d563dec 100644
--- a/test/shape/data/in-house/tests/indic-special-cases.tests
+++ b/test/shape/data/in-house/tests/indic-special-cases.tests
@@ -2,3 +2,7 @@
 ../fonts/3cae6bfe5b57c07ba81ddbd54c02fe4f3a1e3bf6.ttf;;U+0CB0,U+200D,U+0CCD,U+0C95;[gid2=0+1334|gid6=0+358]
 ../fonts/3cae6bfe5b57c07ba81ddbd54c02fe4f3a1e3bf6.ttf;;U+0CB0,U+0CCD,U+200D,U+0C95;[gid2=0+1334|gid6=0+358]
 ../fonts/e716f6bd00a108d186b7e9f47b4515565f784f36.ttf;;U+0C1A,U+0C3F,U+0C32,U+0C4D,U+0C15,U+0C42,U+0C30,U+0C4D;[civoweltelu=0+766|latelu=2+709|uuvowelsigntelu=2+661|kasubscripttelu=2+483|rahalanttelu=6+593]
+../fonts/9d8c53cb64b8747abdd2b70755cce2ee0eb42ef7.ttf;;U+0915,U+093F,U+094E,U+093C;[uni094E=0+273|uni093C=0+0|ivowelsign03deva=0+259|uni0915=0+762]
+../fonts/9d8c53cb64b8747abdd2b70755cce2ee0eb42ef7.ttf;;U+0915,U+093F,U+093C,U+094E;[uni094E=0+273|ivowelsign00deva=0+259|uni093C=0+0|uni0915=0+762]
+../fonts/5f73fff1ffc07b5a99a90c0909609f2b09fef274.ttf;;U+0A15,U+0A40,U+0A02;[uni0A15=0+505|uni0A40=0+427|uni0A02=0+0]
+../fonts/5f73fff1ffc07b5a99a90c0909609f2b09fef274.ttf;;U+0A15,U+0A02,U+0A40;[uni0A15=0+505|uni0A02=0+0|uni0A40=0+427]
diff --git a/test/shape/data/in-house/tests/myanmar-misc.tests b/test/shape/data/in-house/tests/myanmar-misc.tests
index 5273863..8ba0be4 100644
--- a/test/shape/data/in-house/tests/myanmar-misc.tests
+++ b/test/shape/data/in-house/tests/myanmar-misc.tests
@@ -1 +1,2 @@
 ../fonts/065b01e54f35f0d849fd43bd5b936212739a50cb.ttf;;U+101A,U+1035;[ya_e_above=0+1000]
+../fonts/a232bb734d4c6c898a44506547d19768f0eba6a6.ttf;;U+1000,U+1031,U+1084;[e_shn=0+592|_e=0+618|ka=0+1124]
diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am
index 8ee6923..e6d2325 100644
--- a/test/subset/data/Makefile.am
+++ b/test/subset/data/Makefile.am
@@ -7,6 +7,7 @@
 
 EXTRA_DIST += \
 	$(TESTS) \
+	$(DISABLED_TESTS) \
 	expected/32bit_var_store \
 	expected/basics \
 	expected/full-font \
@@ -55,6 +56,10 @@
 	expected/math \
 	expected/math_coverage_offset \
 	expected/post \
+	expected/full_instance \
+	expected/instance_feature_variations \
+	expected/instantiate_glyf \
+	expected/pin_all_at_default \
 	fonts \
 	profiles \
 	$(NULL)
diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources
index 798db64..845a77e 100644
--- a/test/subset/data/Makefile.sources
+++ b/test/subset/data/Makefile.sources
@@ -47,6 +47,10 @@
 	tests/math.tests \
 	tests/math_coverage_offset.tests \
 	tests/post.tests \
+	tests/full_instance.tests \
+	tests/instance_feature_variations.tests \
+	tests/instantiate_glyf.tests \
+	tests/pin_all_at_default.tests \
 	$(NULL)
 
 # TODO: re-enable once colrv1 subsetting is stabilized.
@@ -57,5 +61,6 @@
 XFAIL_TESTS = \
 	$(NULL)
 
+# Disabled because instancing is only available w/ experimental API on.
 DISABLED_TESTS = \
 	$(NULL)
diff --git a/test/subset/data/expected/full_instance/Roboto-Variable.no-prune-unicode-ranges.retain-all-codepoint.wght=150,wdth=80.ttf b/test/subset/data/expected/full_instance/Roboto-Variable.no-prune-unicode-ranges.retain-all-codepoint.wght=150,wdth=80.ttf
new file mode 100644
index 0000000..ca2aeef
--- /dev/null
+++ b/test/subset/data/expected/full_instance/Roboto-Variable.no-prune-unicode-ranges.retain-all-codepoint.wght=150,wdth=80.ttf
Binary files differ
diff --git a/test/subset/data/expected/full_instance/Roboto-Variable.no-prune-unicode-ranges.retain-all-codepoint.wght=300,wdth=90.ttf b/test/subset/data/expected/full_instance/Roboto-Variable.no-prune-unicode-ranges.retain-all-codepoint.wght=300,wdth=90.ttf
new file mode 100644
index 0000000..04be94e
--- /dev/null
+++ b/test/subset/data/expected/full_instance/Roboto-Variable.no-prune-unicode-ranges.retain-all-codepoint.wght=300,wdth=90.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test-retain-gids.41,42,43.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test-retain-gids.41,42,43.otf
index 70dd0fd..5ae5d5b 100644
--- a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test-retain-gids.41,42,43.otf
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test-retain-gids.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test-retain-gids.41,42.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test-retain-gids.41,42.otf
index f9349f6..cfe6648 100644
--- a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test-retain-gids.41,42.otf
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test-retain-gids.41,42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test-retain-gids.retain-all-codepoint.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test-retain-gids.retain-all-codepoint.otf
index 07e6ad5..0e98d1a 100644
--- a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test-retain-gids.retain-all-codepoint.otf
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test-retain-gids.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test.41,42,43.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test.41,42,43.otf
index 070f9ec..6530ab6 100644
--- a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test.41,42,43.otf
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test.41,42.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test.41,42.otf
index 60fd45c..cac1abb 100644
--- a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test.41,42.otf
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test.41,42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test.retain-all-codepoint.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test.retain-all-codepoint.otf
index 07e6ad5..0e98d1a 100644
--- a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test.retain-all-codepoint.otf
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.layout-test.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gdef-attachlist/IndicTestJalandhar-Regular.default.retain-all-codepoint.ttf b/test/subset/data/expected/layout.gdef-attachlist/IndicTestJalandhar-Regular.default.retain-all-codepoint.ttf
index ab0c1d1..c64ef97 100644
--- a/test/subset/data/expected/layout.gdef-attachlist/IndicTestJalandhar-Regular.default.retain-all-codepoint.ttf
+++ b/test/subset/data/expected/layout.gdef-attachlist/IndicTestJalandhar-Regular.default.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout.gdef-attachlist/IndicTestJalandhar-Regular.drop-hints.retain-all-codepoint.ttf b/test/subset/data/expected/layout.gdef-attachlist/IndicTestJalandhar-Regular.drop-hints.retain-all-codepoint.ttf
index 2306381..b4a2677 100644
--- a/test/subset/data/expected/layout.gdef-attachlist/IndicTestJalandhar-Regular.drop-hints.retain-all-codepoint.ttf
+++ b/test/subset/data/expected/layout.gdef-attachlist/IndicTestJalandhar-Regular.drop-hints.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout.gdef-attachlist/IndicTestJalandhar-Regular.keep-gdef.retain-all-codepoint.ttf b/test/subset/data/expected/layout.gdef-attachlist/IndicTestJalandhar-Regular.keep-gdef.retain-all-codepoint.ttf
index ab0c1d1..c64ef97 100644
--- a/test/subset/data/expected/layout.gdef-attachlist/IndicTestJalandhar-Regular.keep-gdef.retain-all-codepoint.ttf
+++ b/test/subset/data/expected/layout.gdef-attachlist/IndicTestJalandhar-Regular.keep-gdef.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test-retain-gids.41,42,43.otf b/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test-retain-gids.41,42,43.otf
index 1d3f3cd..f6b78bc 100644
--- a/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test-retain-gids.41,42,43.otf
+++ b/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test-retain-gids.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test-retain-gids.41,42.otf b/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test-retain-gids.41,42.otf
index 5a0d0c4..6f2e7ef 100644
--- a/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test-retain-gids.41,42.otf
+++ b/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test-retain-gids.41,42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test-retain-gids.retain-all-codepoint.otf b/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test-retain-gids.retain-all-codepoint.otf
index b3d6ae9..ff0595a 100644
--- a/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test-retain-gids.retain-all-codepoint.otf
+++ b/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test-retain-gids.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test.41,42,43.otf b/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test.41,42,43.otf
index 0a693c6..8086051 100644
--- a/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test.41,42,43.otf
+++ b/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test.41,42.otf b/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test.41,42.otf
index 128c1d4..0a26e0f 100644
--- a/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test.41,42.otf
+++ b/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test.41,42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test.retain-all-codepoint.otf b/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test.retain-all-codepoint.otf
index b3d6ae9..ff0595a 100644
--- a/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test.retain-all-codepoint.otf
+++ b/test/subset/data/expected/layout.gsub5/gsub_context2_multiple_subrules_f2.layout-test.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.627,644,62D,628.ttf b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.627,644,62D,628.ttf
index cbfad3d..e402e57 100644
--- a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.627,644,62D,628.ttf
+++ b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.627,644,62D,628.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.633,6D2.ttf b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.633,6D2.ttf
index f4938d8..5683d04 100644
--- a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.633,6D2.ttf
+++ b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.633,6D2.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.63A,64A,631.ttf b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.63A,64A,631.ttf
index 6ac7bcd..e19feda 100644
--- a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.63A,64A,631.ttf
+++ b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.63A,64A,631.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.retain-all-codepoint.ttf b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.retain-all-codepoint.ttf
index ba99d30..ea153c9 100644
--- a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.retain-all-codepoint.ttf
+++ b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.default.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.627,644,62D,628.ttf b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.627,644,62D,628.ttf
index 81ee9e8..fb9746e 100644
--- a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.627,644,62D,628.ttf
+++ b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.627,644,62D,628.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.633,6D2.ttf b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.633,6D2.ttf
index 3f5367a..81319fd 100644
--- a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.633,6D2.ttf
+++ b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.633,6D2.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.63A,64A,631.ttf b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.63A,64A,631.ttf
index 2610a64..b9aa70b 100644
--- a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.63A,64A,631.ttf
+++ b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.63A,64A,631.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.retain-all-codepoint.ttf b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.retain-all-codepoint.ttf
index e41720c..4458d5f 100644
--- a/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.retain-all-codepoint.ttf
+++ b/test/subset/data/expected/layout.notonastaliqurdu/NotoNastaliqUrdu-Regular.retain-gids.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/tests/full_instance.tests b/test/subset/data/tests/full_instance.tests
index 1b08673..f99e5eb 100644
--- a/test/subset/data/tests/full_instance.tests
+++ b/test/subset/data/tests/full_instance.tests
@@ -3,6 +3,7 @@
 
 PROFILES:
 default.txt
+no-prune-unicode-ranges.txt
 
 SUBSETS:
 *
diff --git a/test/subset/generate-expected-outputs.py b/test/subset/generate-expected-outputs.py
index 48b2f913..2b7a87f 100755
--- a/test/subset/generate-expected-outputs.py
+++ b/test/subset/generate-expected-outputs.py
@@ -45,6 +45,7 @@
 	args = ["fonttools", "subset", input_path]
 	args.extend(["--drop-tables+=DSIG",
 		     "--drop-tables-=sbix",
+		     "--no-harfbuzz-repacker", # disable harfbuzz repacker so we aren't comparing to ourself.
 		     "--unicodes=%s" % unicodes,
 		     "--output-file=%s" % fonttools_path])
 	args.extend(profile_flags)
diff --git a/test/subset/meson.build b/test/subset/meson.build
index 319d8bb..77a2029 100644
--- a/test/subset/meson.build
+++ b/test/subset/meson.build
@@ -40,8 +40,8 @@
   'colr_glyphs',
   'math',
   'math_coverage_offset',
-# TODO: re-enable once colrv1 subsetting is stabilized.
-# 'colrv1.notoemoji',
+  # TODO: re-enable once colrv1 subsetting is stabilized.
+  # 'colrv1.notoemoji',
   'colrv1',
   'colr_with_components',
   'cbdt',
@@ -49,11 +49,10 @@
   'glyph_names',
   'post',
   '32bit_var_store',
-# instacing tests, enable when --instance is not experimental
-# 'pin_all_at_default',
-# 'instantiate_glyf',
-# 'full_instance',
-# 'instance_feature_variations',
+  'pin_all_at_default',
+  'instantiate_glyf',
+  'full_instance',
+  'instance_feature_variations',
 ]
 
 repack_tests = [
@@ -65,7 +64,6 @@
   'space_splitting',
 ]
 
-
 run_test = find_program('run-tests.py')
 
 foreach t : tests
diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py
index 6a2146d..db3c042 100755
--- a/test/subset/run-tests.py
+++ b/test/subset/run-tests.py
@@ -47,14 +47,16 @@
 	print ('  expected_file	    %s' % os.path.abspath (expected_file))
 	return 1
 
-def run_test (test, should_check_ots):
+def run_test (test, should_check_ots, preprocess):
 	out_file = os.path.join (tempfile.mkdtemp (), test.get_font_name () + '-subset' + test.get_font_extension ())
 	cli_args = ["--font-file=" + test.font_path,
 		    "--output-file=" + out_file,
 		    "--unicodes=%s" % test.unicodes (),
-		    "--preprocess-face",
 		    "--drop-tables+=DSIG",
 		    "--drop-tables-=sbix"]
+	if preprocess:
+		cli_args.extend(["--preprocess-face",])
+
 	cli_args.extend (test.get_profile_flags ())
 	if test.get_instance_flags ():
 		cli_args.extend (["--instance=%s" % ','.join(test.get_instance_flags ())])
@@ -142,7 +144,10 @@
 		print ("Running tests in " + path)
 		test_suite = SubsetTestSuite (path, f.read ())
 		for test in test_suite.tests ():
-			fails += run_test (test, has_ots)
+			# Tests are run with and without preprocessing, results should be the
+			# same between them.
+			fails += run_test (test, has_ots, False)
+			fails += run_test (test, has_ots, True)
 
 if fails != 0:
 	sys.exit ("%d test(s) failed." % fails)
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index f2606c7..bd4dea2 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -34,11 +34,7 @@
 
 static hb_face_t* preprocess_face(hb_face_t* face)
 {
-  #ifdef HB_EXPERIMENTAL_API
   return hb_subset_preprocess (face);
-  #else
-  return hb_face_reference(face);
-  #endif
 }
 
 /*
@@ -120,7 +116,7 @@
     for (unsigned i = 0; i < num_iterations; i++)
     {
       hb_face_destroy (new_face);
-      new_face = hb_subset_or_fail (face, input);
+      new_face = hb_subset_or_fail (orig_face, input);
     }
 
     bool success = new_face;
@@ -664,7 +660,6 @@
   return true;
 }
 
-#ifdef HB_EXPERIMENTAL_API
 #ifndef HB_NO_VAR
 static gboolean
 parse_instance (const char *name,
@@ -729,7 +724,6 @@
   return true;
 }
 #endif
-#endif
 
 template <GOptionArgFunc line_parser, bool allow_comments=true>
 static gboolean
@@ -840,7 +834,7 @@
 
   GOptionEntry glyphset_entries[] =
   {
-    {"gids",		0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_gids,
+    {"gids",		'g', 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_gids,
      "Specify glyph IDs or ranges to include in the subset.\n"
      "                                                       "
      "Use --gids-=... to subtract codepoints from the current set.", "list of glyph indices/ranges or *"},
@@ -854,13 +848,13 @@
 
     {"glyphs-file",	0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_file_for<parse_glyphs>,	"Specify file to read glyph names from", "filename"},
 
-    {"text",		0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text,			"Specify text to include in the subset. Use --text-=... to subtract codepoints from the current set.", "string"},
+    {"text",		't', 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text,			"Specify text to include in the subset. Use --text-=... to subtract codepoints from the current set.", "string"},
     {"text-",		0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text,			"Specify text to remove from the subset", "string"},
     {"text+",		0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text,			"Specify text to include in the subset", "string"},
 
 
     {"text-file",	0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_file_for<parse_text, false>,"Specify file to read text from", "filename"},
-    {"unicodes",	0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes,
+    {"unicodes",	'u', 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes,
      "Specify Unicode codepoints or ranges to include in the subset. Use * to include all codepoints.\n"
      "                                                       "
      "--unicodes-=... can be used to subtract codepoints from the current set.\n"
@@ -901,7 +895,6 @@
     {"drop-tables",	0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_drop_tables,	"Drop the specified tables. Use --drop-tables-=... to subtract from the current set.", "list of string table tags or *"},
     {"drop-tables+",	0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, (gpointer) &parse_drop_tables,	"Drop the specified tables.", "list of string table tags or *"},
     {"drop-tables-",	0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, (gpointer) &parse_drop_tables,	"Drop the specified tables.", "list of string table tags or *"},
-#ifdef HB_EXPERIMENTAL_API
 #ifndef HB_NO_VAR
     {"instance",	0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_instance,
      "(Partially|Fully) Instantiate a variable font. A location consists of the tag of a variation axis, followed by '=', followed by a\n"
@@ -911,7 +904,6 @@
      "Note: currently only fully instancing to the default location is supported\n",
      "list of comma separated axis-locations"},
 #endif
-#endif
     {nullptr}
   };
   add_group (other_entries,
diff --git a/util/helper-cairo.hh b/util/helper-cairo.hh
index 6df92e5..a8463de 100644
--- a/util/helper-cairo.hh
+++ b/util/helper-cairo.hh
@@ -29,7 +29,9 @@
 
 #include "view-options.hh"
 #include "output-options.hh"
-#include "helper-cairo-ft.hh"
+#ifdef HAVE_CAIRO_FT
+#  include "helper-cairo-ft.hh"
+#endif
 #include "helper-cairo-user.hh"
 
 #include <cairo.h>
@@ -71,21 +73,35 @@
 {
   const char *env = getenv ("HB_DRAW");
   if (!env)
+#if 1
+    /* Following branch disabled because we prefer our
+     * OpenType extensions working, ie going through hb-draw,
+     * over avoiding the obscure cairo bug. */
+    return true;
+#else
+    /* Older cairo had a bug in rendering COLRv0 fonts in
+     * right-to-left direction. */
     return cairo_version () >= CAIRO_VERSION_ENCODE (1, 17, 5);
+#endif
+
   return atoi (env);
 }
 
 static inline cairo_scaled_font_t *
 helper_cairo_create_scaled_font (const font_options_t *font_opts)
 {
-  bool use_hb_draw = helper_cairo_use_hb_draw (font_opts);
   hb_font_t *font = hb_font_reference (font_opts->font);
 
+#ifdef HAVE_CAIRO_FT
+  bool use_hb_draw = helper_cairo_use_hb_draw (font_opts);
   cairo_font_face_t *cairo_face;
   if (use_hb_draw)
     cairo_face = helper_cairo_create_user_font_face (font_opts);
   else
     cairo_face = helper_cairo_create_ft_font_face (font_opts);
+#else
+  cairo_font_face_t *cairo_face = helper_cairo_create_user_font_face (font_opts);
+#endif
 
   cairo_matrix_t ctm, font_matrix;
   cairo_font_options_t *font_options;
@@ -94,8 +110,10 @@
   cairo_matrix_init_scale (&font_matrix,
 			   font_opts->font_size_x,
 			   font_opts->font_size_y);
-  if (use_hb_draw)
+#ifdef HAVE_CAIRO_FT
+  if (!use_hb_draw)
     font_matrix.xy = -font_opts->slant * font_opts->font_size_x;
+#endif
 
   font_options = cairo_font_options_create ();
   cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
@@ -122,10 +140,14 @@
 static inline bool
 helper_cairo_scaled_font_has_color (cairo_scaled_font_t *scaled_font)
 {
+#ifdef HAVE_CAIRO_FT
   if (helper_cairo_user_font_face_has_data (cairo_scaled_font_get_font_face (scaled_font)))
     return helper_cairo_user_scaled_font_has_color (scaled_font);
   else
     return helper_cairo_ft_scaled_font_has_color (scaled_font);
+#else
+  return helper_cairo_user_scaled_font_has_color (scaled_font);
+#endif
 }
 
 
diff --git a/util/meson.build b/util/meson.build
index fdab620..1367405 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -17,8 +17,7 @@
 util_deps = [freetype_dep, cairo_dep, cairo_ft_dep, glib_dep]
 
 if conf.get('HAVE_GLIB', 0) == 1
-  if conf.get('HAVE_FREETYPE', 0) == 1 and conf.get('HAVE_CAIRO_FT', 0) == 1
-
+  if conf.get('HAVE_CAIRO', 0) == 1
     hb_view = executable('hb-view', hb_view_sources,
       cpp_args: cpp_args,
       include_directories: [incconfig, incsrc],
diff --git a/util/shape-consumer.hh b/util/shape-consumer.hh
index 2115189..8ee4bd6 100644
--- a/util/shape-consumer.hh
+++ b/util/shape-consumer.hh
@@ -61,11 +61,11 @@
 
     for (unsigned int n = num_iterations; n; n--)
     {
-      const char *error = nullptr;
-
       populate_buffer (buffer, text, text_len, app.text_before, app.text_after);
       if (n == 1)
 	output.consume_text (buffer, text, text_len, utf8_clusters);
+
+      const char *error = nullptr;
       if (!shape (app.font, buffer, &error))
       {
 	failed = true;