diff --git a/DEPS b/DEPS
index 19a977e..d5f338f6 100644
--- a/DEPS
+++ b/DEPS
@@ -79,11 +79,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'cb88470d82d646972a7e83d04bb19444d87dd840',
+  'skia_revision': 'ec77963bf32eda185cb422d2166f60da094feade',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '3d6608cea0c1fb98a5c1474972cc80728d9dbbc8',
+  'v8_revision': '8ac76771ab2ea77b926c344b31a12d33131daeaf',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -91,11 +91,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'e3dc5dd0cb164d73725af27f2b2624657f1281d9',
+  'angle_revision': 'aa5d883e02151601b3797643d5a6baa45b15feb1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
-  'buildtools_revision': '2888931260f2a32bc583f005bd807a561b2fa6af',
+  'buildtools_revision': '3748a2a90871fc25b0455790fa5a6699553f5197',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -103,7 +103,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'c49f39dff730a71b0198521f5ec0e2142c0c0d26',
+  'pdfium_revision': 'b3a5240832fce3f0b706c16070a1e69c2c1edb86',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -133,6 +133,10 @@
   # and whatever else without interference from each other.
   'freetype_revision': '713d68ee9f47cc8df56e47fa2f54b191bb8c3186',
   # Three lines of non-changing comments so that
+  # the commit queue can handle CLs rolling HarfBuzz
+  # and whatever else without interference from each other.
+  'harfbuzz_revision': '957e7756634a4fdf1654041e20e883cf964ecac9',
+  # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
   'catapult_revision': '734f737c6b57655a718a178426fb09532ff6f0e9',
@@ -316,7 +320,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '5978d7dd749e58fb74f8f253066c54898b34ebc2',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'b84994071091a2287443fa0d893a9450c926e48c',
       'condition': 'checkout_linux',
   },
 
@@ -341,7 +345,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '544b744621b7c60097788c38594ea44973d0c8eb',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0b89935ad6fee0109212969cbaccdce822a7632c',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -382,6 +386,9 @@
   'src/third_party/freetype/src':
     Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + Var('freetype_revision'),
 
+  'src/third_party/harfbuzz-ng/src':
+    Var('chromium_git') + '/external/github.com/harfbuzz/harfbuzz.git' + '@' + Var('harfbuzz_revision'),
+
   # Chrome OS touchpad gestures library.
   'src/third_party/gestures/gestures': {
       'url': Var('chromium_git') + '/chromiumos/platform/gestures.git' + '@' + '74f55100df966280d305d5d5ada824605f875839',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index b877faa..117881c0 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -2633,11 +2633,13 @@
   results.extend(input_api.RunTests(
     input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
 
-  if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
-    results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
-        input_api, output_api,
-        input_api.PresubmitLocalPath(),
-        whitelist=[r'^PRESUBMIT_test\.py$']))
+  for f in input_api.AffectedFiles():
+    path, name = input_api.os_path.split(f.LocalPath())
+    if name == 'PRESUBMIT.py':
+      full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
+      results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
+          input_api, output_api, full_path,
+          whitelist=[r'^PRESUBMIT_test\.py$']))
   return results
 
 
diff --git a/ash/public/interfaces/accessibility_controller.mojom b/ash/public/interfaces/accessibility_controller.mojom
index ea2fd2c..279bcc4 100644
--- a/ash/public/interfaces/accessibility_controller.mojom
+++ b/ash/public/interfaces/accessibility_controller.mojom
@@ -4,7 +4,7 @@
 
 module ash.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "ui/accessibility/ax_enums.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
@@ -71,7 +71,7 @@
 
   // Initiates play of shutdown sound and returns sound duration. This method
   // exists because the browser owns all media playback.
-  PlayShutdownSound() => (mojo.common.mojom.TimeDelta sound_duration);
+  PlayShutdownSound() => (mojo_base.mojom.TimeDelta sound_duration);
 
   // Forwards an accessibility gesture from the touch exploration controller to
   // ChromeVox.
diff --git a/ash/public/interfaces/process_creation_time_recorder.mojom b/ash/public/interfaces/process_creation_time_recorder.mojom
index 3f9e23b..9e13caf3 100644
--- a/ash/public/interfaces/process_creation_time_recorder.mojom
+++ b/ash/public/interfaces/process_creation_time_recorder.mojom
@@ -4,9 +4,9 @@
 
 module ash.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 interface ProcessCreationTimeRecorder {
   // Sets the time the main process was created at, used for logging metrics.
-  SetMainProcessCreationTime(mojo.common.mojom.TimeTicks start_time);
+  SetMainProcessCreationTime(mojo_base.mojom.TimeTicks start_time);
 };
diff --git a/ash/public/interfaces/session_controller.mojom b/ash/public/interfaces/session_controller.mojom
index 7e5e90e..bedc54f 100644
--- a/ash/public/interfaces/session_controller.mojom
+++ b/ash/public/interfaces/session_controller.mojom
@@ -6,7 +6,7 @@
 
 import "ash/public/interfaces/user_info.mojom";
 import "components/signin/public/interfaces/account_id.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 // Matches session_manager::SessionState.
 enum SessionState {
@@ -158,8 +158,8 @@
   // NOTE: Chrome enforces the limit, not ash. Ash could enforce it if local
   // state prefs and user activity monitoring were available under mustash.
   // http://crbug.com/729808
-  SetSessionLengthLimit(mojo.common.mojom.TimeDelta length_limit,
-                        mojo.common.mojom.TimeTicks start_time);
+  SetSessionLengthLimit(mojo_base.mojom.TimeDelta length_limit,
+                        mojo_base.mojom.TimeTicks start_time);
 
   // Returns whether it's ok to switch the active multiprofile user. May affect
   // or be affected by system state such as window overview mode and screen
diff --git a/ash/public/interfaces/time_to_first_present_recorder_test_api.mojom b/ash/public/interfaces/time_to_first_present_recorder_test_api.mojom
index bd694a8..a4f0c02 100644
--- a/ash/public/interfaces/time_to_first_present_recorder_test_api.mojom
+++ b/ash/public/interfaces/time_to_first_present_recorder_test_api.mojom
@@ -4,11 +4,11 @@
 
 module ash.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 // Used to test internal state of TimeToFirstPresentRecorder.
 interface TimeToFirstPresentRecorderTestApi {
   // Returns the time between process creation and the first pixels shown on
   // screen.
-  GetProcessCreationToFirstPresentTime() => (mojo.common.mojom.TimeDelta delta);
+  GetProcessCreationToFirstPresentTime() => (mojo_base.mojom.TimeDelta delta);
 };
diff --git a/ash/public/interfaces/vpn_list.mojom b/ash/public/interfaces/vpn_list.mojom
index 3c030fe..f190c7f 100644
--- a/ash/public/interfaces/vpn_list.mojom
+++ b/ash/public/interfaces/vpn_list.mojom
@@ -4,7 +4,7 @@
 
 module ash.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 // Describes a third-party VPN provided by an extension (e.g. Cisco AnyConnect).
 struct ThirdPartyVpnProvider {
@@ -22,7 +22,7 @@
   // Unique app id for launching the app. e.g. pbmkokpdlpfmapoiccpblbmjjhhabjaa
   string app_id;
   // Last launch time of the Arc VPN provider.
-  mojo.common.mojom.Time last_launch_time;
+  mojo_base.mojom.Time last_launch_time;
 };
 
 // Manages the VPN provider list in ash. Allows extension-backed VPN providers
diff --git a/ash/public/interfaces/wallpaper.mojom b/ash/public/interfaces/wallpaper.mojom
index bc2c524..3605f4b 100644
--- a/ash/public/interfaces/wallpaper.mojom
+++ b/ash/public/interfaces/wallpaper.mojom
@@ -6,9 +6,9 @@
 
 import "ash/public/interfaces/user_info.mojom";
 import "components/signin/public/interfaces/account_id.mojom";
-import "mojo/common/time.mojom";
 import "mojo/public/mojom/base/file_path.mojom";
-import "skia/public/interfaces/bitmap.mojom";
+import "mojo/public/mojom/base/time.mojom";
+import "ui/gfx/image/mojo/image.mojom";
 import "url/mojom/url.mojom";
 
 // These values match wallpaper::WallpaperLayout.
@@ -73,7 +73,7 @@
                      string wallpaper_files_id,
                      string file_name,
                      WallpaperLayout layout,
-                     skia.mojom.Bitmap image,
+                     gfx.mojom.ImageSkia image,
                      bool preview_mode);
 
   // Sets wallpaper from the wallpaper picker selection, i.e., the wallpaper
@@ -87,7 +87,7 @@
   //                 the user wallpaper info until |ConfirmPreviewWallpaper| is
   //                 called.
   SetOnlineWallpaper(WallpaperUserInfo user_info,
-                     skia.mojom.Bitmap image,
+                     gfx.mojom.ImageSkia image,
                      string url,
                      WallpaperLayout layout,
                      bool preview_mode);
@@ -128,6 +128,29 @@
   // clears the device policy controlled wallpaper if applicable.
   SetDeviceWallpaperPolicyEnforced(bool enforced);
 
+  // Sets wallpaper from a third-party app (as opposed to the Chrome OS
+  // wallpaper picker).
+  // |user_info|: The user's information related to wallpaper.
+  // |wallpaper_files_id|: The file id for user_info.account_id.
+  // |file_name|: The name of the wallpaper file.
+  // |layout|: The layout of the wallpaper, used for wallpaper resizing.
+  // |image|: The wallpaper image.
+  // |allowed|: If the wallpaper is allowed to be shown on screen. It's false if
+  //            1) the user is not permitted to change wallpaper, or
+  //            2) updating the on-screen wallpaper is not allowed at the
+  //               given moment.
+  // |image_id|: A unique id assigned to the image. Clients may be interested in
+  //             observing all wallpaper changes and acting differently based on
+  //             if the wallpaper change is due to their own request. In order
+  //             to do so, they should compare this value with the one that's
+  //             returned by |OnWallpaperChanged|.
+  SetThirdPartyWallpaper(WallpaperUserInfo user_info,
+                         string wallpaper_files_id,
+                         string file_name,
+                         WallpaperLayout layout,
+                         gfx.mojom.ImageSkia image)
+                         => (bool allowed, uint32 image_id);
+
   // Confirms the wallpaper being previewed to be set as the actual user
   // wallpaper. Must be called in preview mode.
   ConfirmPreviewWallpaper();
@@ -170,7 +193,7 @@
 
   // Sets wallpaper animation duration. Passing an empty value disables the
   // animation.
-  SetAnimationDuration(mojo.common.mojom.TimeDelta animation_duration);
+  SetAnimationDuration(mojo_base.mojom.TimeDelta animation_duration);
 
   // Opens the wallpaper picker if the active user is not controlled by policy
   // and it's allowed to change wallpaper per the user type and the login state.
@@ -180,6 +203,9 @@
   // state. Observers are automatically removed as their connections are closed.
   AddObserver(associated WallpaperObserver observer);
 
+  // Returns the wallpaper image currently being shown.
+  GetWallpaperImage() => (gfx.mojom.ImageSkia image);
+
   // Runs to get wallpaper prominent colors.
   GetWallpaperColors() => (array<uint32> prominent_colors);
 
@@ -211,9 +237,14 @@
 
 // Used to listen for wallpaper state changed.
 interface WallpaperObserver {
-  // Called when the colors extracted from the current wallpaper change. May
-  // be called as a side effect of changing the wallpaper on the
-  // WallpaperController, e.g. WallpaperController::SetWallpaperImage().
-  // Colors are ordered and are referenced in wallpaper::ColorProfileType.
+  // Invoked when the wallpaper is changed. |image_id| is the unique id assigned
+  // to the current wallpaper image. It should only be used to compare against
+  // the value returned by a setting wallpaper request earlier
+  // (e.g. SetThirdPartyWallpaper). This value is unique to each |ImageSkia|
+  // object and is different for two objects with the same pixels.
+  OnWallpaperChanged(uint32 image_id);
+
+  // Called when the colors extracted from the current wallpaper change. Colors
+  // are ordered and are referenced in wallpaper::ColorProfileType.
   OnWallpaperColorsChanged(array<uint32> prominent_colors);
 };
diff --git a/ash/system/tray/tray_constants.h b/ash/system/tray/tray_constants.h
index 47fa447..08ea3fa 100644
--- a/ash/system/tray/tray_constants.h
+++ b/ash/system/tray/tray_constants.h
@@ -127,6 +127,9 @@
 
 // The colors used when --enable-features=SystemTrayUnified flag is enabled.
 constexpr SkColor kUnifiedMenuBackgroundColor = SkColorSetRGB(0x20, 0x21, 0x24);
+constexpr SkColor kUnifiedMenuBackgroundColorWithBlur =
+    SkColorSetA(kUnifiedMenuBackgroundColor, 0xB3);
+constexpr float kUnifiedMenuBackgroundBlur = 30.f;
 constexpr SkColor kUnifiedMenuTextColor = SkColorSetRGB(0xf1, 0xf2, 0xf3);
 constexpr SkColor kUnifiedMenuIconColor = SkColorSetRGB(0xf1, 0xf2, 0xf3);
 constexpr SkColor kUnifiedMenuSecondaryTextColor =
diff --git a/ash/system/unified/feature_pod_button.cc b/ash/system/unified/feature_pod_button.cc
index e257b45..02be619 100644
--- a/ash/system/unified/feature_pod_button.cc
+++ b/ash/system/unified/feature_pod_button.cc
@@ -27,6 +27,7 @@
   label->SetMultiLine(true);
   label->SizeToFit(kUnifiedFeaturePodSize.width());
   label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+  label->SetSubpixelRenderingEnabled(false);
 }
 
 }  // namespace
diff --git a/ash/system/unified/sign_out_button.cc b/ash/system/unified/sign_out_button.cc
index 70f251d..59be0e7 100644
--- a/ash/system/unified/sign_out_button.cc
+++ b/ash/system/unified/sign_out_button.cc
@@ -30,6 +30,7 @@
   SetEnabledTextColors(kUnifiedMenuTextColor);
   SetHorizontalAlignment(gfx::ALIGN_CENTER);
   SetBorder(views::CreateEmptyBorder(gfx::Insets()));
+  label()->SetSubpixelRenderingEnabled(false);
   TrayPopupUtils::ConfigureTrayPopupButton(this);
 }
 
diff --git a/ash/system/unified/unified_system_info_view.cc b/ash/system/unified/unified_system_info_view.cc
index 8276fd7..b5047a5 100644
--- a/ash/system/unified/unified_system_info_view.cc
+++ b/ash/system/unified/unified_system_info_view.cc
@@ -66,6 +66,7 @@
   AddChildView(label_);
 
   label_->SetAutoColorReadabilityEnabled(false);
+  label_->SetSubpixelRenderingEnabled(false);
   label_->SetEnabledColor(kUnifiedMenuTextColor);
   Update();
 
@@ -174,6 +175,7 @@
 
 void BatteryView::ConfigureLabel(views::Label* label) {
   label->SetAutoColorReadabilityEnabled(false);
+  label->SetSubpixelRenderingEnabled(false);
   label->SetEnabledColor(kUnifiedMenuSecondaryTextColor);
 }
 
@@ -207,6 +209,7 @@
 
   auto* label = new views::Label;
   label->SetAutoColorReadabilityEnabled(false);
+  label->SetSubpixelRenderingEnabled(false);
   label->SetEnabledColor(kUnifiedMenuSecondaryTextColor);
   label->SetText(
       l10n_util::GetStringUTF16(IDS_ASH_ENTERPRISE_DEVICE_MANAGED_SHORT));
diff --git a/ash/system/unified/unified_system_tray_bubble.cc b/ash/system/unified/unified_system_tray_bubble.cc
index 6165fc8..b317c6d 100644
--- a/ash/system/unified/unified_system_tray_bubble.cc
+++ b/ash/system/unified/unified_system_tray_bubble.cc
@@ -9,6 +9,7 @@
 #include "ash/system/unified/unified_system_tray.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "ash/system/unified/unified_system_tray_view.h"
+#include "ui/app_list/app_list_features.h"
 
 namespace ash {
 
@@ -29,13 +30,19 @@
   bubble_view->AddChildView(controller_->CreateView());
   bubble_view->set_anchor_view_insets(
       tray->shelf()->GetSystemTrayAnchor()->GetBubbleAnchorInsets());
-  bubble_view->set_color(kUnifiedMenuBackgroundColor);
+  bubble_view->set_color(SK_ColorTRANSPARENT);
+  bubble_view->layer()->SetFillsBoundsOpaquely(false);
 
   bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(bubble_view);
   bubble_widget_->AddObserver(this);
 
   TrayBackgroundView::InitializeBubbleAnimations(bubble_widget_);
   bubble_view->InitializeAndShowBubble();
+  if (app_list::features::IsBackgroundBlurEnabled()) {
+    // ClientView's layer (See TrayBubbleView::InitializeAndShowBubble())
+    bubble_view->layer()->parent()->SetBackgroundBlur(
+        kUnifiedMenuBackgroundBlur);
+  }
 
   bubble_widget_->widget_delegate()->set_can_activate(true);
   bubble_widget_->Activate();
diff --git a/ash/system/unified/unified_system_tray_view.cc b/ash/system/unified/unified_system_tray_view.cc
index 5ba7c591..cd30a38 100644
--- a/ash/system/unified/unified_system_tray_view.cc
+++ b/ash/system/unified/unified_system_tray_view.cc
@@ -4,10 +4,13 @@
 
 #include "ash/system/unified/unified_system_tray_view.h"
 
+#include "ash/system/tray/tray_constants.h"
 #include "ash/system/unified/feature_pod_button.h"
 #include "ash/system/unified/feature_pods_container_view.h"
 #include "ash/system/unified/top_shortcuts_view.h"
 #include "ash/system/unified/unified_system_info_view.h"
+#include "ui/app_list/app_list_features.h"
+#include "ui/views/background.h"
 #include "ui/views/layout/box_layout.h"
 
 namespace ash {
@@ -22,6 +25,13 @@
   SetLayoutManager(
       std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical));
 
+  SetBackground(
+      views::CreateSolidBackground(app_list::features::IsBackgroundBlurEnabled()
+                                       ? kUnifiedMenuBackgroundColorWithBlur
+                                       : kUnifiedMenuBackgroundColor));
+  SetPaintToLayer();
+  layer()->SetFillsBoundsOpaquely(false);
+
   AddChildView(new TopShortcutsView(controller_));
   AddChildView(feature_pods_container_);
   AddChildView(system_info_view_);
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc
index 84cfe41..fb86de49 100644
--- a/ash/wallpaper/wallpaper_controller.cc
+++ b/ash/wallpaper/wallpaper_controller.cc
@@ -771,6 +771,9 @@
 
   for (auto& observer : observers_)
     observer.OnWallpaperDataChanged();
+  mojo_observers_.ForAllPtrs([this](mojom::WallpaperObserver* observer) {
+    observer->OnWallpaperChanged(current_wallpaper_->original_image_id());
+  });
 
   wallpaper_mode_ = WALLPAPER_IMAGE;
   InstallDesktopControllerForAllWindows();
@@ -1032,29 +1035,6 @@
   return SetUserWallpaperInfo(account_id, info, is_ephemeral);
 }
 
-void WallpaperController::SetArcWallpaper(
-    const AccountId& account_id,
-    const user_manager::UserType user_type,
-    const std::string& wallpaper_files_id,
-    const std::string& file_name,
-    const gfx::ImageSkia& image,
-    wallpaper::WallpaperLayout layout,
-    bool is_ephemeral,
-    bool show_wallpaper) {
-  if (!CanSetUserWallpaper(account_id, is_ephemeral))
-    return;
-
-  ash::mojom::WallpaperUserInfoPtr user_info =
-      ash::mojom::WallpaperUserInfo::New();
-  user_info->account_id = account_id;
-  user_info->type = user_type;
-  user_info->is_ephemeral = is_ephemeral;
-  // |has_gaia_account| is unused.
-  user_info->has_gaia_account = true;
-  SaveAndSetWallpaper(std::move(user_info), wallpaper_files_id, file_name,
-                      wallpaper::CUSTOMIZED, layout, show_wallpaper, image);
-}
-
 bool WallpaperController::GetWallpaperFromCache(const AccountId& account_id,
                                                 gfx::ImageSkia* image) {
   CustomWallpaperMap::const_iterator it = wallpaper_cache_map_.find(account_id);
@@ -1109,37 +1089,34 @@
     const std::string& wallpaper_files_id,
     const std::string& file_name,
     wallpaper::WallpaperLayout layout,
-    const SkBitmap& image,
+    const gfx::ImageSkia& image,
     bool preview_mode) {
   DCHECK(Shell::Get()->session_controller()->IsActiveUserSessionStarted());
   if (!CanSetUserWallpaper(user_info->account_id, user_info->is_ephemeral))
     return;
 
-  const gfx::ImageSkia custom_wallpaper =
-      gfx::ImageSkia::CreateFrom1xBitmap(image);
   const bool is_active_user = IsActiveUser(user_info->account_id);
   if (preview_mode) {
     DCHECK(is_active_user);
-    confirm_preview_wallpaper_callback_ =
-        base::BindOnce(&WallpaperController::SaveAndSetWallpaper,
-                       weak_factory_.GetWeakPtr(), std::move(user_info),
-                       wallpaper_files_id, file_name, wallpaper::CUSTOMIZED,
-                       layout, false /*show_wallpaper=*/, custom_wallpaper);
+    confirm_preview_wallpaper_callback_ = base::BindOnce(
+        &WallpaperController::SaveAndSetWallpaper, weak_factory_.GetWeakPtr(),
+        std::move(user_info), wallpaper_files_id, file_name,
+        wallpaper::CUSTOMIZED, layout, false /*show_wallpaper=*/, image);
     ShowWallpaperImage(
-        custom_wallpaper,
+        image,
         wallpaper::WallpaperInfo{std::string(), layout, wallpaper::CUSTOMIZED,
                                  base::Time::Now().LocalMidnight()},
         true /*preview_mode=*/);
   } else {
     SaveAndSetWallpaper(std::move(user_info), wallpaper_files_id, file_name,
                         wallpaper::CUSTOMIZED, layout,
-                        is_active_user /*show_wallpaper=*/, custom_wallpaper);
+                        is_active_user /*show_wallpaper=*/, image);
   }
 }
 
 void WallpaperController::SetOnlineWallpaper(
     mojom::WallpaperUserInfoPtr user_info,
-    const SkBitmap& image,
+    const gfx::ImageSkia& image,
     const std::string& url,
     wallpaper::WallpaperLayout layout,
     bool preview_mode) {
@@ -1147,22 +1124,20 @@
   if (!CanSetUserWallpaper(user_info->account_id, user_info->is_ephemeral))
     return;
 
-  const gfx::ImageSkia online_wallpaper =
-      gfx::ImageSkia::CreateFrom1xBitmap(image);
   const bool is_active_user = IsActiveUser(user_info->account_id);
   if (preview_mode) {
     DCHECK(is_active_user);
     confirm_preview_wallpaper_callback_ =
         base::BindOnce(&WallpaperController::SetOnlineWallpaperImpl,
-                       weak_factory_.GetWeakPtr(), online_wallpaper, url,
-                       layout, std::move(user_info), false /*show_wallpaper=*/);
+                       weak_factory_.GetWeakPtr(), image, url, layout,
+                       std::move(user_info), false /*show_wallpaper=*/);
     ShowWallpaperImage(
-        online_wallpaper,
+        image,
         wallpaper::WallpaperInfo{std::string(), layout, wallpaper::ONLINE,
                                  base::Time::Now().LocalMidnight()},
         true /*preview_mode=*/);
   } else {
-    SetOnlineWallpaperImpl(online_wallpaper, url, layout, std::move(user_info),
+    SetOnlineWallpaperImpl(image, url, layout, std::move(user_info),
                            is_active_user /*show_wallpaper=*/);
   }
 }
@@ -1245,6 +1220,27 @@
   }
 }
 
+void WallpaperController::SetThirdPartyWallpaper(
+    mojom::WallpaperUserInfoPtr user_info,
+    const std::string& wallpaper_files_id,
+    const std::string& file_name,
+    wallpaper::WallpaperLayout layout,
+    const gfx::ImageSkia& image,
+    SetThirdPartyWallpaperCallback callback) {
+  const uint32_t image_id = wallpaper::WallpaperResizer::GetImageId(image);
+  bool allowed_to_set_wallpaper =
+      CanSetUserWallpaper(user_info->account_id, user_info->is_ephemeral);
+  bool allowed_to_show_wallpaper = IsActiveUser(user_info->account_id);
+  std::move(callback).Run(allowed_to_set_wallpaper && allowed_to_show_wallpaper,
+                          image_id);
+
+  if (allowed_to_set_wallpaper) {
+    SaveAndSetWallpaper(std::move(user_info), wallpaper_files_id, file_name,
+                        wallpaper::CUSTOMIZED, layout,
+                        allowed_to_show_wallpaper, image);
+  }
+}
+
 void WallpaperController::ConfirmPreviewWallpaper() {
   DCHECK(confirm_preview_wallpaper_callback_);
   std::move(confirm_preview_wallpaper_callback_).Run();
@@ -1425,6 +1421,11 @@
   mojo_observers_.AddPtr(std::move(observer_ptr));
 }
 
+void WallpaperController::GetWallpaperImage(
+    GetWallpaperImageCallback callback) {
+  std::move(callback).Run(GetWallpaper());
+}
+
 void WallpaperController::GetWallpaperColors(
     GetWallpaperColorsCallback callback) {
   std::move(callback).Run(prominent_colors_);
diff --git a/ash/wallpaper/wallpaper_controller.h b/ash/wallpaper/wallpaper_controller.h
index 685f376..f622d7a 100644
--- a/ash/wallpaper/wallpaper_controller.h
+++ b/ash/wallpaper/wallpaper_controller.h
@@ -324,20 +324,6 @@
   bool InitializeUserWallpaperInfo(const AccountId& account_id,
                                    bool is_ephemeral);
 
-  // TODO(crbug.com/776464): This method is a temporary workaround during the
-  // refactoring. It should be combined with |SetCustomWallpaper|.
-  // The same with |SetCustomWallpaper|, except that |image| wasn't once
-  // converted to |SkBitmap|, so that the image id is preserved.
-  // ArcWallpaperService needs this to track the wallpaper change.
-  void SetArcWallpaper(const AccountId& account_id,
-                       const user_manager::UserType user_type,
-                       const std::string& wallpaper_files_id,
-                       const std::string& file_name,
-                       const gfx::ImageSkia& image,
-                       wallpaper::WallpaperLayout layout,
-                       bool is_ephemeral,
-                       bool show_wallpaper);
-
   // Gets encoded wallpaper from cache. Returns true if success.
   bool GetWallpaperFromCache(const AccountId& account_id,
                              gfx::ImageSkia* image);
@@ -359,10 +345,10 @@
                           const std::string& wallpaper_files_id,
                           const std::string& file_name,
                           wallpaper::WallpaperLayout layout,
-                          const SkBitmap& image,
+                          const gfx::ImageSkia& image,
                           bool preview_mode) override;
   void SetOnlineWallpaper(mojom::WallpaperUserInfoPtr user_info,
-                          const SkBitmap& image,
+                          const gfx::ImageSkia& image,
                           const std::string& url,
                           wallpaper::WallpaperLayout layout,
                           bool preview_mode) override;
@@ -376,6 +362,12 @@
                           const std::string& wallpaper_files_id,
                           const std::string& data) override;
   void SetDeviceWallpaperPolicyEnforced(bool enforced) override;
+  void SetThirdPartyWallpaper(mojom::WallpaperUserInfoPtr user_info,
+                              const std::string& wallpaper_files_id,
+                              const std::string& file_name,
+                              wallpaper::WallpaperLayout layout,
+                              const gfx::ImageSkia& image,
+                              SetThirdPartyWallpaperCallback callback) override;
   void ConfirmPreviewWallpaper() override;
   void CancelPreviewWallpaper() override;
   void UpdateCustomWallpaperLayout(mojom::WallpaperUserInfoPtr user_info,
@@ -389,6 +381,7 @@
   void SetAnimationDuration(base::TimeDelta animation_duration) override;
   void OpenWallpaperPickerIfAllowed() override;
   void AddObserver(mojom::WallpaperObserverAssociatedPtrInfo observer) override;
+  void GetWallpaperImage(GetWallpaperImageCallback callback) override;
   void GetWallpaperColors(GetWallpaperColorsCallback callback) override;
   void IsActiveUserWallpaperControlledByPolicy(
       IsActiveUserWallpaperControlledByPolicyCallback callback) override;
diff --git a/ash/wallpaper/wallpaper_controller_observer.h b/ash/wallpaper/wallpaper_controller_observer.h
index abb05b9..3c46598 100644
--- a/ash/wallpaper/wallpaper_controller_observer.h
+++ b/ash/wallpaper/wallpaper_controller_observer.h
@@ -12,6 +12,7 @@
 class ASH_EXPORT WallpaperControllerObserver {
  public:
   // Invoked when the wallpaper data is changed.
+  // TODO(wzang): Remove this.
   virtual void OnWallpaperDataChanged() = 0;
 
   // Invoked when the colors extracted from the current wallpaper change.
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index cde46137..2b1ce3a 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -25,6 +25,7 @@
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/task_scheduler/task_scheduler.h"
+#include "base/test/bind_test_util.h"
 #include "chromeos/chromeos_switches.h"
 #include "components/prefs/testing_pref_service.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
@@ -210,6 +211,8 @@
   ~TestWallpaperObserver() override = default;
 
   // mojom::WallpaperObserver:
+  void OnWallpaperChanged(uint32_t image_id) override {}
+
   void OnWallpaperColorsChanged(
       const std::vector<SkColor>& prominent_colors) override {
     ++wallpaper_colors_changed_count_;
@@ -855,7 +858,7 @@
   // successfully and wallpaper info is updated.
   controller_->SetCustomWallpaper(InitializeUser(account_id_1),
                                   wallpaper_files_id_1, file_name_1, layout,
-                                  *image.bitmap(), false /*preview_mode=*/);
+                                  image, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
@@ -876,7 +879,7 @@
   image = CreateImage(640, 480, custom_wallpaper_color);
   controller_->SetCustomWallpaper(InitializeUser(account_id_1),
                                   wallpaper_files_id_1, file_name_1, layout,
-                                  *image.bitmap(), false /*preview_mode=*/);
+                                  image, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
@@ -901,8 +904,8 @@
 
   // Set an online wallpaper for |user_1|. Verify the wallpaper is set
   // successfully and wallpaper info is updated.
-  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), *image.bitmap(),
-                                  url, layout, false /*preview_mode=*/);
+  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), image, url,
+                                  layout, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
@@ -920,8 +923,8 @@
   SimulateUserLogin(user_2);
   const SkColor online_wallpaper_color = SK_ColorCYAN;
   image = CreateImage(640, 480, online_wallpaper_color);
-  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), *image.bitmap(),
-                                  url, layout, false /*preview_mode=*/);
+  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), image, url,
+                                  layout, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
@@ -1004,6 +1007,111 @@
   EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
 }
 
+TEST_F(WallpaperControllerTest, SetThirdPartyWallpaper) {
+  SetBypassDecode();
+  SimulateUserLogin(user_1);
+
+  // Verify the user starts with no wallpaper info.
+  wallpaper::WallpaperInfo wallpaper_info;
+  EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
+                                                 false /*is_ephemeral=*/));
+
+  // Set a third-party wallpaper for |user_1|.
+  const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
+  gfx::ImageSkia third_party_wallpaper = CreateImage(640, 480, kWallpaperColor);
+  bool allowed_to_update_wallpaper = false;
+  std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
+  controller_->SetThirdPartyWallpaper(
+      InitializeUser(account_id_1), wallpaper_files_id_1, file_name_1, layout,
+      third_party_wallpaper,
+      base::BindLambdaForTesting([&allowed_to_update_wallpaper, &run_loop](
+                                     bool allowed, uint32_t image_id) {
+        allowed_to_update_wallpaper = allowed;
+        run_loop->Quit();
+      }));
+  run_loop->Run();
+  // Verify the wallpaper is shown.
+  EXPECT_EQ(1, GetWallpaperCount());
+  // Verify the callback function gets the correct value.
+  EXPECT_TRUE(allowed_to_update_wallpaper);
+  // Verify the user wallpaper info is updated.
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
+                                                false /*is_ephemeral=*/));
+  wallpaper::WallpaperInfo expected_wallpaper_info(
+      base::FilePath(wallpaper_files_id_1).Append(file_name_1).value(), layout,
+      wallpaper::CUSTOMIZED, base::Time::Now().LocalMidnight());
+  EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
+
+  // Switch active user to |user_2|, but set another third-party wallpaper for
+  // |user_1|.
+  allowed_to_update_wallpaper = true;
+  SimulateUserLogin(user_2);
+  run_loop.reset(new base::RunLoop());
+  controller_->SetThirdPartyWallpaper(
+      InitializeUser(account_id_1), wallpaper_files_id_2, file_name_2, layout,
+      third_party_wallpaper,
+      base::BindLambdaForTesting([&allowed_to_update_wallpaper, &run_loop](
+                                     bool allowed, uint32_t image_id) {
+        allowed_to_update_wallpaper = allowed;
+        run_loop->Quit();
+      }));
+  run_loop->Run();
+  // Verify the wallpaper is not shown because |user_1| is not the active user.
+  EXPECT_EQ(0, GetWallpaperCount());
+  // Verify the callback function gets the correct value.
+  EXPECT_FALSE(allowed_to_update_wallpaper);
+  // Verify the wallpaper info for |user_1| is updated, because setting
+  // wallpaper is still allowed for non-active users.
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
+                                                false /*is_ephemeral=*/));
+  wallpaper::WallpaperInfo expected_wallpaper_info_2(
+      base::FilePath(wallpaper_files_id_2).Append(file_name_2).value(), layout,
+      wallpaper::CUSTOMIZED, base::Time::Now().LocalMidnight());
+  EXPECT_EQ(wallpaper_info, expected_wallpaper_info_2);
+
+  // Set a policy wallpaper for |user_2|. Verify that |user_2| becomes policy
+  // controlled.
+  controller_->SetPolicyWallpaper(InitializeUser(account_id_2),
+                                  wallpaper_files_id_2,
+                                  std::string() /*data=*/);
+  RunAllTasksUntilIdle();
+  EXPECT_TRUE(
+      controller_->IsPolicyControlled(account_id_2, false /*is_ephemeral=*/));
+  EXPECT_TRUE(IsActiveUserWallpaperControlledByPolicy());
+
+  // Set a third-party wallpaper for |user_2|.
+  allowed_to_update_wallpaper = true;
+  run_loop.reset(new base::RunLoop());
+  controller_->SetThirdPartyWallpaper(
+      InitializeUser(account_id_2), wallpaper_files_id_1, file_name_1, layout,
+      third_party_wallpaper,
+      base::BindLambdaForTesting([&allowed_to_update_wallpaper, &run_loop](
+                                     bool allowed, uint32_t image_id) {
+        allowed_to_update_wallpaper = allowed;
+        run_loop->Quit();
+      }));
+  run_loop->Run();
+  // Verify the wallpaper is not shown because third-party wallpaper cannot be
+  // set for policy controlled users.
+  EXPECT_EQ(0, GetWallpaperCount());
+  // Verify the callback gets the correct value.
+  EXPECT_FALSE(allowed_to_update_wallpaper);
+  // Verify |user_2| is still policy controlled and has the policy wallpaper
+  // info.
+  EXPECT_TRUE(
+      controller_->IsPolicyControlled(account_id_2, false /*is_ephemeral=*/));
+  EXPECT_TRUE(IsActiveUserWallpaperControlledByPolicy());
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_2, &wallpaper_info,
+                                                false /*is_ephemeral=*/));
+  wallpaper::WallpaperInfo policy_wallpaper_info(
+      base::FilePath(wallpaper_files_id_2)
+          .Append("policy-controlled.jpeg")
+          .value(),
+      wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::POLICY,
+      base::Time::Now().LocalMidnight());
+  EXPECT_EQ(wallpaper_info, policy_wallpaper_info);
+}
+
 TEST_F(WallpaperControllerTest, SetDefaultWallpaperForRegularAccount) {
   CreateDefaultWallpapers();
   SimulateUserLogin(user_1);
@@ -1177,7 +1285,7 @@
   // |account_id|'s wallpaper info is not updated.
   controller_->SetCustomWallpaper(
       InitializeUser(account_id_1), wallpaper_files_id_1, file_name_1,
-      WALLPAPER_LAYOUT_CENTER, *image.bitmap(), false /*preview_mode=*/);
+      WALLPAPER_LAYOUT_CENTER, image, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
   wallpaper::WallpaperInfo wallpaper_info;
@@ -1186,7 +1294,7 @@
 
   // Verify that |SetOnlineWallpaper| doesn't set wallpaper in kiosk mode, and
   // |account_id|'s wallpaper info is not updated.
-  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), *image.bitmap(),
+  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), image,
                                   "dummy_url", WALLPAPER_LAYOUT_CENTER,
                                   false /*preview_mode=*/);
   RunAllTasksUntilIdle();
@@ -1222,7 +1330,7 @@
   // enforced, and the user wallpaper info is not updated.
   controller_->SetCustomWallpaper(
       InitializeUser(account_id_1), wallpaper_files_id_1, file_name_1,
-      WALLPAPER_LAYOUT_CENTER, *image.bitmap(), false /*preview_mode=*/);
+      WALLPAPER_LAYOUT_CENTER, image, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
   wallpaper::WallpaperInfo wallpaper_info;
@@ -1238,7 +1346,7 @@
 
   // Verify that |SetOnlineWallpaper| doesn't set wallpaper when policy is
   // enforced, and the user wallpaper info is not updated.
-  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), *image.bitmap(),
+  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), image,
                                   "dummy_url", WALLPAPER_LAYOUT_CENTER,
                                   false /*preview_mode=*/);
   RunAllTasksUntilIdle();
@@ -1272,7 +1380,7 @@
 
   // Verify |SetOnlineWallpaper| updates wallpaper cache for |user1|.
   controller_->SetOnlineWallpaper(
-      InitializeUser(account_id_1), *image.bitmap(), "dummy_file_location",
+      InitializeUser(account_id_1), image, "dummy_file_location",
       WALLPAPER_LAYOUT_CENTER, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_TRUE(
@@ -1298,7 +1406,7 @@
   // Verify |SetCustomWallpaper| updates wallpaper cache for |user1|.
   controller_->SetCustomWallpaper(
       InitializeUser(account_id_1), wallpaper_files_id_1, file_name_1,
-      WALLPAPER_LAYOUT_CENTER, *image.bitmap(), false /*preview_mode=*/);
+      WALLPAPER_LAYOUT_CENTER, image, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_TRUE(
       controller_->GetWallpaperFromCache(account_id_1, &cached_wallpaper));
@@ -1423,7 +1531,7 @@
   // and the wallpaper info is updated.
   controller_->SetCustomWallpaper(InitializeUser(account_id_1),
                                   wallpaper_files_id_1, file_name_1, layout,
-                                  *image.bitmap(), false /*preview_mode=*/);
+                                  image, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_EQ(controller_->GetWallpaperLayout(), layout);
@@ -1452,8 +1560,8 @@
   // wallpaper info is updated.
   const std::string url = "dummy_url";
   image = CreateImage(640, 480, kWallpaperColor);
-  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), *image.bitmap(),
-                                  url, layout, false /*preview_mode=*/);
+  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), image, url,
+                                  layout, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::ONLINE);
@@ -1786,9 +1894,9 @@
   const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
   gfx::ImageSkia custom_wallpaper = CreateImage(640, 480, kWallpaperColor);
   EXPECT_NE(kWallpaperColor, GetWallpaperColor());
-  controller_->SetCustomWallpaper(
-      InitializeUser(account_id_1), wallpaper_files_id_1, file_name_1, layout,
-      *custom_wallpaper.bitmap(), true /*preview_mode=*/);
+  controller_->SetCustomWallpaper(InitializeUser(account_id_1),
+                                  wallpaper_files_id_1, file_name_1, layout,
+                                  custom_wallpaper, true /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
@@ -1821,7 +1929,7 @@
       CreateImage(640, 480, online_wallpaper_color);
   EXPECT_NE(online_wallpaper_color, GetWallpaperColor());
   controller_->SetOnlineWallpaper(InitializeUser(account_id_1),
-                                  *online_wallpaper.bitmap(), url, layout,
+                                  online_wallpaper, url, layout,
                                   true /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
@@ -1867,9 +1975,9 @@
   const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
   gfx::ImageSkia custom_wallpaper = CreateImage(640, 480, kWallpaperColor);
   EXPECT_NE(kWallpaperColor, GetWallpaperColor());
-  controller_->SetCustomWallpaper(
-      InitializeUser(account_id_1), wallpaper_files_id_1, file_name_1, layout,
-      *custom_wallpaper.bitmap(), true /*preview_mode=*/);
+  controller_->SetCustomWallpaper(InitializeUser(account_id_1),
+                                  wallpaper_files_id_1, file_name_1, layout,
+                                  custom_wallpaper, true /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
@@ -1896,7 +2004,7 @@
       CreateImage(640, 480, online_wallpaper_color);
   EXPECT_NE(online_wallpaper_color, GetWallpaperColor());
   controller_->SetOnlineWallpaper(InitializeUser(account_id_1),
-                                  *online_wallpaper.bitmap(), url, layout,
+                                  online_wallpaper, url, layout,
                                   true /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
@@ -1937,9 +2045,9 @@
   const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
   gfx::ImageSkia custom_wallpaper = CreateImage(640, 480, kWallpaperColor);
   EXPECT_NE(kWallpaperColor, GetWallpaperColor());
-  controller_->SetCustomWallpaper(
-      InitializeUser(account_id_1), wallpaper_files_id_1, file_name_1, layout,
-      *custom_wallpaper.bitmap(), true /*preview_mode=*/);
+  controller_->SetCustomWallpaper(InitializeUser(account_id_1),
+                                  wallpaper_files_id_1, file_name_1, layout,
+                                  custom_wallpaper, true /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
@@ -1958,7 +2066,7 @@
   ClearWallpaperCount();
   controller_->SetCustomWallpaper(
       InitializeUser(account_id_1), wallpaper_files_id_2, file_name_2, layout,
-      *synced_custom_wallpaper.bitmap(), false /*preview_mode=*/);
+      synced_custom_wallpaper, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
@@ -1989,8 +2097,8 @@
   gfx::ImageSkia online_wallpaper = CreateImage(640, 480, kWallpaperColor);
   EXPECT_NE(kWallpaperColor, GetWallpaperColor());
   controller_->SetOnlineWallpaper(InitializeUser(account_id_1),
-                                  *online_wallpaper.bitmap(), preview_url,
-                                  layout, true /*preview_mode=*/);
+                                  online_wallpaper, preview_url, layout,
+                                  true /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
@@ -2007,8 +2115,8 @@
       CreateImage(640, 480, synced_online_wallpaper_color);
   ClearWallpaperCount();
   controller_->SetOnlineWallpaper(InitializeUser(account_id_1),
-                                  *synced_online_wallpaper.bitmap(), synced_url,
-                                  layout, false /*preview_mode=*/);
+                                  synced_online_wallpaper, synced_url, layout,
+                                  false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
diff --git a/build/android/gyp/compile_resources.py b/build/android/gyp/compile_resources.py
new file mode 100755
index 0000000..377d1143
--- /dev/null
+++ b/build/android/gyp/compile_resources.py
@@ -0,0 +1,561 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Compile Android resources into an intermediate APK.
+
+This can also generate an R.txt, and an .srcjar file containing the proper
+final R.java class for all resource packages the APK depends on.
+
+This will crunch images with aapt2.
+"""
+
+import argparse
+import collections
+import multiprocessing.pool
+import os
+import re
+import shutil
+import subprocess
+import sys
+import zipfile
+from xml.etree import ElementTree
+
+
+from util import build_utils
+from util import resource_utils
+
+_SOURCE_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(
+    __file__))))
+# Import jinja2 from third_party/jinja2
+sys.path.insert(1, os.path.join(_SOURCE_ROOT, 'third_party'))
+from jinja2 import Template # pylint: disable=F0401
+
+# A variation of this lists also exists in:
+# //base/android/java/src/org/chromium/base/LocaleUtils.java
+_CHROME_TO_ANDROID_LOCALE_MAP = {
+    'en-GB': 'en-rGB',
+    'en-US': 'en-rUS',
+    'es-419': 'es-rUS',
+    'fil': 'tl',
+    'he': 'iw',
+    'id': 'in',
+    'pt-PT': 'pt-rPT',
+    'pt-BR': 'pt-rBR',
+    'yi': 'ji',
+    'zh-CN': 'zh-rCN',
+    'zh-TW': 'zh-rTW',
+}
+
+# Pngs that we shouldn't convert to webp. Please add rationale when updating.
+_PNG_WEBP_BLACKLIST_PATTERN = re.compile('|'.join([
+    # Crashes on Galaxy S5 running L (https://crbug.com/807059).
+    r'.*star_gray\.png',
+    # Android requires pngs for 9-patch images.
+    r'.*\.9\.png',
+    # Daydream (*.dd) requires pngs for icon files.
+    r'.*\.dd\.png']))
+
+
+def _ParseArgs(args):
+  """Parses command line options.
+
+  Returns:
+    An options object as from argparse.ArgumentParser.parse_args()
+  """
+  parser, input_opts, output_opts = resource_utils.ResourceArgsParser()
+
+  input_opts.add_argument('--android-manifest', required=True,
+                          help='AndroidManifest.xml path')
+
+  input_opts.add_argument(
+      '--shared-resources',
+      action='store_true',
+      help='Make all resources in R.java non-final and allow the resource IDs '
+           'to be reset to a different package index when the apk is loaded by '
+           'another application at runtime.')
+
+  input_opts.add_argument(
+      '--shared-resources-whitelist',
+      help='An R.txt file acting as a whitelist for resources that should be '
+           'non-final and have their package ID changed at runtime in R.java. '
+           'Implies and overrides --shared-resources.')
+
+  input_opts.add_argument('--support-zh-hk', action='store_true',
+                          help='Use zh-rTW resources for zh-rHK.')
+
+  input_opts.add_argument('--debuggable',
+                          action='store_true',
+                          help='Whether to add android:debuggable="true"')
+
+  input_opts.add_argument('--version-code', help='Version code for apk.')
+  input_opts.add_argument('--version-name', help='Version name for apk.')
+
+  input_opts.add_argument(
+      '--no-compress',
+      help='disables compression for the given comma-separated list of '
+           'extensions')
+
+  input_opts.add_argument(
+      '--locale-whitelist',
+      default='[]',
+      help='GN list of languages to include. All other language configs will '
+          'be stripped out. List may include a combination of Android locales '
+          'or Chrome locales.')
+
+  input_opts.add_argument('--exclude-xxxhdpi', action='store_true',
+                          help='Do not include xxxhdpi drawables.')
+
+  input_opts.add_argument(
+      '--xxxhdpi-whitelist',
+      default='[]',
+      help='GN list of globs that say which xxxhdpi images to include even '
+           'when --exclude-xxxhdpi is set.')
+
+  input_opts.add_argument('--png-to-webp', action='store_true',
+                          help='Convert png files to webp format.')
+
+  input_opts.add_argument('--webp-binary', default='',
+                          help='Path to the cwebp binary.')
+
+  input_opts.add_argument('--no-xml-namespaces',
+                          action='store_true',
+                          help='Whether to strip xml namespaces from processed '
+                               'xml resources')
+
+  output_opts.add_argument('--apk-path', required=True,
+                           help='Path to output (partial) apk.')
+
+  output_opts.add_argument('--srcjar-out',
+                           help='Path to srcjar to contain generated R.java.')
+
+  output_opts.add_argument('--r-text-out',
+                           help='Path to store the generated R.txt file.')
+
+  output_opts.add_argument('--proguard-file',
+                           help='Path to proguard.txt generated file')
+
+  output_opts.add_argument(
+      '--proguard-file-main-dex',
+      help='Path to proguard.txt generated file for main dex')
+
+  options = parser.parse_args(args)
+
+  resource_utils.HandleCommonOptions(options)
+
+  options.locale_whitelist = build_utils.ParseGnList(options.locale_whitelist)
+  options.xxxhdpi_whitelist = build_utils.ParseGnList(options.xxxhdpi_whitelist)
+
+  return options
+
+
+def _SortZip(original_path, sorted_path):
+  """Generate new zip archive by sorting all files in the original by name."""
+  with zipfile.ZipFile(sorted_path, 'w') as sorted_zip, \
+      zipfile.ZipFile(original_path, 'r') as original_zip:
+    for info in sorted(original_zip.infolist(), key=lambda i: i.filename):
+      sorted_zip.writestr(info, original_zip.read(info))
+
+
+def _DuplicateZhResources(resource_dirs):
+  """Duplicate Taiwanese resources into Hong-Kong specific directory."""
+  for resource_dir in resource_dirs:
+    # We use zh-TW resources for zh-HK (if we have zh-TW resources).
+    for path in build_utils.IterFiles(resource_dir):
+      if 'zh-rTW' in path:
+        hk_path = path.replace('zh-rTW', 'zh-rHK')
+        build_utils.MakeDirectory(os.path.dirname(hk_path))
+        shutil.copyfile(path, hk_path)
+
+
+def _ToAaptLocales(locale_whitelist, support_zh_hk):
+  """Converts the list of Chrome locales to aapt config locales."""
+  ret = set()
+  for locale in locale_whitelist:
+    locale = _CHROME_TO_ANDROID_LOCALE_MAP.get(locale, locale)
+    if locale is None or ('-' in locale and '-r' not in locale):
+      raise Exception('_CHROME_TO_ANDROID_LOCALE_MAP needs updating.'
+                      ' Found: %s' % locale)
+    ret.add(locale)
+    # Always keep non-regional fall-backs.
+    language = locale.split('-')[0]
+    ret.add(language)
+
+  # We don't actually support zh-HK in Chrome on Android, but we mimic the
+  # native side behavior where we use zh-TW resources when the locale is set to
+  # zh-HK. See https://crbug.com/780847.
+  if support_zh_hk:
+    assert not any('HK' in l for l in locale_whitelist), (
+        'Remove special logic if zh-HK is now supported (crbug.com/780847).')
+    ret.add('zh-rHK')
+  return sorted(ret)
+
+
+def _MoveImagesToNonMdpiFolders(res_root):
+  """Move images from drawable-*-mdpi-* folders to drawable-* folders.
+
+  Why? http://crbug.com/289843
+  """
+  for src_dir_name in os.listdir(res_root):
+    src_components = src_dir_name.split('-')
+    if src_components[0] != 'drawable' or 'mdpi' not in src_components:
+      continue
+    src_dir = os.path.join(res_root, src_dir_name)
+    if not os.path.isdir(src_dir):
+      continue
+    dst_components = [c for c in src_components if c != 'mdpi']
+    assert dst_components != src_components
+    dst_dir_name = '-'.join(dst_components)
+    dst_dir = os.path.join(res_root, dst_dir_name)
+    build_utils.MakeDirectory(dst_dir)
+    for src_file_name in os.listdir(src_dir):
+      if not os.path.splitext(src_file_name)[1] in ('.png', '.webp'):
+        continue
+      src_file = os.path.join(src_dir, src_file_name)
+      dst_file = os.path.join(dst_dir, src_file_name)
+      assert not os.path.lexists(dst_file)
+      shutil.move(src_file, dst_file)
+
+
+def _CreateLinkApkArgs(options):
+  """Create command-line arguments list to invoke 'aapt2 link'.
+
+  Args:
+    options: The command-line options tuple.
+  Returns:
+    A list of strings corresponding to the command-line invokation for
+    the command, matching the arguments from |options|.
+  """
+  link_command = [
+    options.aapt_path + '2',
+    'link',
+    '--version-code', options.version_code,
+    '--version-name', options.version_name,
+    '--auto-add-overlay',
+    '--no-version-vectors',
+    '-I', options.android_sdk_jar,
+    '-o', options.apk_path,
+  ]
+
+  if options.proguard_file:
+    link_command += ['--proguard', options.proguard_file]
+  if options.proguard_file_main_dex:
+    link_command += ['--proguard-main-dex', options.proguard_file_main_dex]
+
+  if options.no_compress:
+    for ext in options.no_compress.split(','):
+      link_command += ['-0', ext]
+
+  if options.shared_resources:
+    link_command.append('--shared-lib')
+
+  if options.locale_whitelist:
+    aapt_locales = _ToAaptLocales(
+        options.locale_whitelist, options.support_zh_hk)
+    link_command += ['-c', ','.join(aapt_locales)]
+
+  if options.no_xml_namespaces:
+    link_command.append('--no-xml-namespaces')
+
+  return link_command
+
+
+def _ExtractVersionFromSdk(aapt_path, sdk_path):
+  """Extract version code and name from Android SDK .jar file.
+
+  Args:
+    aapt_path: Path to 'aapt' build tool.
+    sdk_path: Path to SDK-specific android.jar file.
+  Returns:
+    A (version_code, version_name) pair of strings.
+  """
+  output = subprocess.check_output([aapt_path, 'dump', 'badging', sdk_path])
+  version_code = re.search(r"versionCode='(.*?)'", output).group(1)
+  version_name = re.search(r"versionName='(.*?)'", output).group(1)
+  return version_code, version_name,
+
+
+def _FixManifest(options, temp_dir):
+  """Fix the APK's AndroidManifest.xml.
+
+  This adds any missing namespaces for 'android' and 'tools', and
+  sets certains elements like 'platformBuildVersionCode' or
+  'android:debuggable' depending on the content of |options|.
+
+  Args:
+    options: The command-line arguments tuple.
+    temp_dir: A temporary directory where the fixed manifest will be written to.
+  Returns:
+    Path to the fixed manifest within |temp_dir|.
+  """
+  debug_manifest_path = os.path.join(temp_dir, 'AndroidManifest.xml')
+  _ANDROID_NAMESPACE = 'http://schemas.android.com/apk/res/android'
+  _TOOLS_NAMESPACE = 'http://schemas.android.com/tools'
+  ElementTree.register_namespace('android', _ANDROID_NAMESPACE)
+  ElementTree.register_namespace('tools', _TOOLS_NAMESPACE)
+  original_manifest = ElementTree.parse(options.android_manifest)
+
+  version_code, version_name = _ExtractVersionFromSdk(
+      options.aapt_path, options.android_sdk_jar)
+
+  # ElementTree.find does not work if the required tag is the root.
+  if original_manifest.getroot().tag == 'manifest':
+    manifest_node = original_manifest.getroot()
+  else:
+    manifest_node = original_manifest.find('manifest')
+
+  manifest_node.set('platformBuildVersionCode', version_code)
+  manifest_node.set('platformBuildVersionName', version_name)
+
+  if options.debuggable:
+    app_node = original_manifest.find('application')
+    app_node.set('{%s}%s' % (_ANDROID_NAMESPACE, 'debuggable'), 'true')
+
+  with open(debug_manifest_path, 'w') as debug_manifest:
+    debug_manifest.write(ElementTree.tostring(
+        original_manifest.getroot(), encoding='UTF-8'))
+
+  return debug_manifest_path
+
+
+def _ResourceNameFromPath(path):
+  return os.path.splitext(os.path.basename(path))[0]
+
+
+def _CreateKeepPredicate(resource_dirs, exclude_xxxhdpi, xxxhdpi_whitelist):
+  """Return a predicate lambda to determine which resource files to keep."""
+  if not exclude_xxxhdpi:
+    # Do not extract dotfiles (e.g. ".gitkeep"). aapt ignores them anyways.
+    return lambda path: os.path.basename(path)[0] != '.'
+
+  # Returns False only for xxxhdpi non-mipmap, non-whitelisted drawables.
+  naive_predicate = lambda path: (
+      not re.search(r'[/-]xxxhdpi[/-]', path) or
+      re.search(r'[/-]mipmap[/-]', path) or
+      build_utils.MatchesGlob(path, xxxhdpi_whitelist))
+
+  # Build a set of all non-xxxhdpi drawables to ensure that we never exclude any
+  # xxxhdpi drawable that does not exist in other densities.
+  non_xxxhdpi_drawables = set()
+  for resource_dir in resource_dirs:
+    for path in build_utils.IterFiles(resource_dir):
+      if re.search(r'[/-]drawable[/-]', path) and naive_predicate(path):
+        non_xxxhdpi_drawables.add(_ResourceNameFromPath(path))
+
+  return lambda path: (naive_predicate(path) or
+                       _ResourceNameFromPath(path) not in non_xxxhdpi_drawables)
+
+
+def _ConvertToWebP(webp_binary, png_files):
+  pool = multiprocessing.pool.ThreadPool(10)
+  def convert_image(png_path):
+    root = os.path.splitext(png_path)[0]
+    webp_path = root + '.webp'
+    args = [webp_binary, png_path, '-mt', '-quiet', '-m', '6', '-q', '100',
+        '-lossless', '-o', webp_path]
+    subprocess.check_call(args)
+    os.remove(png_path)
+
+  pool.map(convert_image, [f for f in png_files
+                           if not _PNG_WEBP_BLACKLIST_PATTERN.match(f)])
+  pool.close()
+  pool.join()
+
+
+def _CompileDeps(aapt_path, dep_subdirs, temp_dir):
+  partials_dir = os.path.join(temp_dir, 'partials')
+  build_utils.MakeDirectory(partials_dir)
+  partial_compile_command = [
+      aapt_path + '2',
+      'compile',
+      # TODO(wnwen): Turn this on once aapt2 forces 9-patch to be crunched.
+      # '--no-crunch',
+  ]
+  pool = multiprocessing.pool.ThreadPool(10)
+  def compile_partial(directory):
+    dirname = os.path.basename(directory)
+    partial_path = os.path.join(partials_dir, dirname + '.zip')
+    compile_command = (partial_compile_command +
+                       ['--dir', directory, '-o', partial_path])
+    build_utils.CheckOutput(compile_command)
+
+    # Sorting the files in the partial ensures deterministic output from the
+    # aapt2 link step which uses order of files in the partial.
+    sorted_partial_path = os.path.join(partials_dir, dirname + '.sorted.zip')
+    _SortZip(partial_path, sorted_partial_path)
+
+    return sorted_partial_path
+
+  partials = pool.map(compile_partial, dep_subdirs)
+  pool.close()
+  pool.join()
+  return partials
+
+
+def _PackageApk(options, dep_subdirs, temp_dir, gen_dir, r_txt_path):
+  """Compile resources with aapt2 and generate intermediate .ap_ file.
+
+  Args:
+    options: The command-line options tuple. E.g. the generated apk
+      will be written to |options.apk_path|.
+    dep_subdirs: The list of directories where dependency resource zips
+      were extracted (its content will be altered by this function).
+    temp_dir: A temporary directory.
+    gen_dir: Another temp directory where some intermediate files are
+      generated.
+    r_txt_path: The path where the R.txt file will written to.
+  """
+  _DuplicateZhResources(dep_subdirs)
+
+  keep_predicate = _CreateKeepPredicate(
+      dep_subdirs, options.exclude_xxxhdpi, options.xxxhdpi_whitelist)
+  png_paths = []
+  for directory in dep_subdirs:
+    for f in build_utils.IterFiles(directory):
+      if not keep_predicate(f):
+        os.remove(f)
+      elif f.endswith('.png'):
+        png_paths.append(f)
+  if png_paths and options.png_to_webp:
+    _ConvertToWebP(options.webp_binary, png_paths)
+  for directory in dep_subdirs:
+    _MoveImagesToNonMdpiFolders(directory)
+
+  link_command = _CreateLinkApkArgs(options)
+  link_command += ['--output-text-symbols', r_txt_path]
+  # TODO(digit): Is this below actually required for R.txt generation?
+  link_command += ['--java', gen_dir]
+
+  fixed_manifest = _FixManifest(options, temp_dir)
+  link_command += ['--manifest', fixed_manifest]
+
+  partials = _CompileDeps(options.aapt_path, dep_subdirs, temp_dir)
+  for partial in partials:
+    link_command += ['-R', partial]
+
+  # Creates a .zip with AndroidManifest.xml, resources.arsc, res/*
+  # Also creates R.txt
+  build_utils.CheckOutput(
+      link_command, print_stdout=False, print_stderr=False)
+
+
+def _WriteFinalRTxtFile(options, aapt_r_txt_path):
+  """Determine final R.txt and return its location.
+
+  This handles --r-text-in and --r-text-out options at the same time.
+
+  Args:
+    options: The command-line options tuple.
+    aapt_r_txt_path: The path to the R.txt generated by aapt.
+  Returns:
+    Path to the final R.txt file.
+  """
+  if options.r_text_in:
+    r_txt_file = options.r_text_in
+  else:
+    # When an empty res/ directory is passed, aapt does not write an R.txt.
+    r_txt_file = aapt_r_txt_path
+    if not os.path.exists(r_txt_file):
+      build_utils.Touch(r_txt_file)
+
+  if options.r_text_out:
+    shutil.copyfile(r_txt_file, options.r_text_out)
+
+  return r_txt_file
+
+
+def _OnStaleMd5(options):
+  with resource_utils.BuildContext() as build:
+    dep_subdirs = resource_utils.ExtractDeps(options.dependencies_res_zips,
+                                             build.deps_dir)
+
+    _PackageApk(options, dep_subdirs, build.temp_dir, build.gen_dir,
+                build.r_txt_path)
+
+    r_txt_path = _WriteFinalRTxtFile(options, build.r_txt_path)
+
+    package = resource_utils.ExtractPackageFromManifest(
+        options.android_manifest)
+
+    # If --shared-resources-whitelist is used, the all resources listed in
+    # the corresponding R.txt file will be non-final, and an onResourcesLoaded()
+    # will be generated to adjust them at runtime.
+    #
+    # Otherwise, if --shared-resources is used, the all resources will be
+    # non-final, and an onResourcesLoaded() method will be generated too.
+    #
+    # Otherwise, all resources will be final, and no method will be generated.
+    #
+    rjava_build_options = resource_utils.RJavaBuildOptions()
+    if options.shared_resources_whitelist:
+      rjava_build_options.ExportSomeResources(
+          options.shared_resources_whitelist)
+      rjava_build_options.GenerateOnResourcesLoaded()
+    elif options.shared_resources:
+      rjava_build_options.ExportAllResources()
+      rjava_build_options.GenerateOnResourcesLoaded()
+
+    resource_utils.CreateRJavaFiles(
+        build.srcjar_dir, package, r_txt_path,
+        options.extra_res_packages,
+        options.extra_r_text_files,
+        rjava_build_options)
+
+    if options.srcjar_out:
+      build_utils.ZipDir(options.srcjar_out, build.srcjar_dir)
+
+
+def main(args):
+  args = build_utils.ExpandFileArgs(args)
+  options = _ParseArgs(args)
+
+  # Order of these must match order specified in GN so that the correct one
+  # appears first in the depfile.
+  possible_output_paths = [
+    options.apk_path,
+    options.r_text_out,
+    options.srcjar_out,
+    options.proguard_file,
+    options.proguard_file_main_dex,
+  ]
+  output_paths = [x for x in possible_output_paths if x]
+
+  # List python deps in input_strings rather than input_paths since the contents
+  # of them does not change what gets written to the depsfile.
+  input_strings = options.extra_res_packages + [
+    options.shared_resources,
+    options.exclude_xxxhdpi,
+    options.xxxhdpi_whitelist,
+    str(options.debuggable),
+    str(options.png_to_webp),
+    str(options.support_zh_hk),
+    str(options.no_xml_namespaces),
+  ]
+
+  input_strings.extend(_CreateLinkApkArgs(options))
+
+  possible_input_paths = [
+    options.aapt_path,
+    options.android_manifest,
+    options.android_sdk_jar,
+    options.shared_resources_whitelist,
+  ]
+  input_paths = [x for x in possible_input_paths if x]
+  input_paths.extend(options.dependencies_res_zips)
+  input_paths.extend(options.extra_r_text_files)
+
+  if options.webp_binary:
+    input_paths.append(options.webp_binary)
+
+  build_utils.CallAndWriteDepfileIfStale(
+      lambda: _OnStaleMd5(options),
+      options,
+      input_paths=input_paths,
+      input_strings=input_strings,
+      output_paths=output_paths)
+
+
+if __name__ == '__main__':
+  main(sys.argv[1:])
diff --git a/build/android/gyp/prepare_resources.py b/build/android/gyp/prepare_resources.py
new file mode 100755
index 0000000..fee7932
--- /dev/null
+++ b/build/android/gyp/prepare_resources.py
@@ -0,0 +1,285 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Process Android resource directories to generate .resources.zip, R.txt and
+.srcjar files."""
+
+import argparse
+import collections
+import os
+import re
+import shutil
+import sys
+
+import generate_v14_compatible_resources
+
+from util import build_utils
+from util import resource_utils
+
+
+def _ParseArgs(args):
+  """Parses command line options.
+
+  Returns:
+    An options object as from argparse.ArgumentParser.parse_args()
+  """
+  parser, input_opts, output_opts = resource_utils.ResourceArgsParser()
+
+  input_opts.add_argument('--resource-dirs',
+                        default='[]',
+                        help='A list of input directories containing resources '
+                             'for this target.')
+
+  input_opts.add_argument(
+      '--shared-resources',
+      action='store_true',
+      help='Make resources shareable by generating an onResourcesLoaded() '
+           'method in the R.java source file.')
+
+  input_opts.add_argument('--custom-package',
+                          help='Optional Java package for main R.java.')
+
+  input_opts.add_argument(
+      '--android-manifest',
+      help='Optional AndroidManifest.xml path. Only used to extract a package '
+           'name for R.java if a --custom-package is not provided.')
+
+  output_opts.add_argument(
+      '--resource-zip-out',
+      help='Path to a zip archive containing all resources from '
+           '--resource-dirs, merged into a single directory tree. This will '
+           'also include auto-generated v14-compatible resources unless '
+           '--v14-skip is used.')
+
+  output_opts.add_argument('--srcjar-out',
+                    help='Path to .srcjar to contain the generated R.java.')
+
+  output_opts.add_argument('--r-text-out',
+                    help='Path to store the generated R.txt file.')
+
+  input_opts.add_argument(
+      '--v14-skip',
+      action="store_true",
+      help='Do not generate nor verify v14 resources.')
+
+  options = parser.parse_args(args)
+
+  resource_utils.HandleCommonOptions(options)
+
+  options.resource_dirs = build_utils.ParseGnList(options.resource_dirs)
+
+  return options
+
+
+def _GenerateGlobs(pattern):
+  # This function processes the aapt ignore assets pattern into a list of globs
+  # to be used to exclude files on the python side. It removes the '!', which is
+  # used by aapt to mean 'not chatty' so it does not output if the file is
+  # ignored (we dont output anyways, so it is not required). This function does
+  # not handle the <dir> and <file> prefixes used by aapt and are assumed not to
+  # be included in the pattern string.
+  return pattern.replace('!', '').split(':')
+
+
+def _ZipResources(resource_dirs, zip_path, ignore_pattern):
+  # Python zipfile does not provide a way to replace a file (it just writes
+  # another file with the same name). So, first collect all the files to put
+  # in the zip (with proper overriding), and then zip them.
+  # ignore_pattern is a string of ':' delimited list of globs used to ignore
+  # files that should not be part of the final resource zip.
+  files_to_zip = dict()
+  globs = _GenerateGlobs(ignore_pattern)
+  for d in resource_dirs:
+    for root, _, files in os.walk(d):
+      for f in files:
+        archive_path = f
+        parent_dir = os.path.relpath(root, d)
+        if parent_dir != '.':
+          archive_path = os.path.join(parent_dir, f)
+        path = os.path.join(root, f)
+        if build_utils.MatchesGlob(archive_path, globs):
+          continue
+        files_to_zip[archive_path] = path
+  build_utils.DoZip(files_to_zip.iteritems(), zip_path)
+
+
+def _GenerateRTxt(options, dep_subdirs, gen_dir):
+  """Generate R.txt file.
+
+  Args:
+    options: The command-line options tuple.
+    dep_subdirs: List of directories containing extracted dependency resources.
+    gen_dir: Locates where the aapt-generated files will go. In particular
+      the output file is always generated as |{gen_dir}/R.txt|.
+  """
+  # NOTE: This uses aapt rather than aapt2 because 'aapt2 compile' does not
+  # support the --output-text-symbols option yet (https://crbug.com/820460).
+  package_command = [options.aapt_path,
+                     'package',
+                     '-m',
+                     '-M', resource_utils.EMPTY_ANDROID_MANIFEST_PATH,
+                     '--no-crunch',
+                     '--auto-add-overlay',
+                     '--no-version-vectors',
+                     '-I', options.android_sdk_jar,
+                     '--output-text-symbols', gen_dir,
+                     '-J', gen_dir,  # Required for R.txt generation.
+                     '--ignore-assets', build_utils.AAPT_IGNORE_PATTERN]
+
+  # Adding all dependencies as sources is necessary for @type/foo references
+  # to symbols within dependencies to resolve. However, it has the side-effect
+  # that all Java symbols from dependencies are copied into the new R.java.
+  # E.g.: It enables an arguably incorrect usage of
+  # "mypackage.R.id.lib_symbol" where "libpackage.R.id.lib_symbol" would be
+  # more correct. This is just how Android works.
+  for d in dep_subdirs:
+    package_command += ['-S', d]
+
+  for d in options.resource_dirs:
+    package_command += ['-S', d]
+
+  # Only creates an R.txt
+  build_utils.CheckOutput(
+      package_command, print_stdout=False, print_stderr=False)
+
+
+def _GenerateResourcesZip(output_resource_zip, input_resource_dirs,
+                          v14_skip, temp_dir):
+  """Generate a .resources.zip file fron a list of input resource dirs.
+
+  Args:
+    output_resource_zip: Path to the output .resources.zip file.
+    input_resource_dirs: A list of input resource directories.
+    v14_skip: If False, then v14-compatible resource will also be
+      generated in |{temp_dir}/v14| and added to the final zip.
+    temp_dir: Path to temporary directory.
+  """
+  if not v14_skip:
+    # Generate v14-compatible resources in temp_dir.
+    v14_dir = os.path.join(temp_dir, 'v14')
+    build_utils.MakeDirectory(v14_dir)
+
+    for resource_dir in input_resource_dirs:
+      generate_v14_compatible_resources.GenerateV14Resources(
+          resource_dir,
+          v14_dir)
+
+    input_resource_dirs.append(v14_dir)
+
+  _ZipResources(input_resource_dirs, output_resource_zip,
+                  build_utils.AAPT_IGNORE_PATTERN)
+
+
+def _OnStaleMd5(options):
+  with resource_utils.BuildContext() as build:
+    if options.r_text_in:
+      r_txt_path = options.r_text_in
+    else:
+      # Extract dependencies to resolve @foo/type references into
+      # dependent packages.
+      dep_subdirs = resource_utils.ExtractDeps(options.dependencies_res_zips,
+                                               build.deps_dir)
+
+      _GenerateRTxt(options, dep_subdirs, build.gen_dir)
+      r_txt_path = build.r_txt_path
+
+      # 'aapt' doesn't generate any R.txt file if res/ was empty.
+      if not os.path.exists(r_txt_path):
+        build_utils.Touch(r_txt_path)
+
+    if options.r_text_out:
+      shutil.copyfile(r_txt_path, options.r_text_out)
+
+    if options.srcjar_out:
+      package = options.custom_package
+      if not package and options.android_manifest:
+        package = resource_utils.ExtractPackageFromManifest(
+            options.android_manifest)
+
+      # Don't create a .java file for the current resource target when no
+      # package name was provided (either by manifest or build rules).
+      if package:
+        # All resource IDs should be non-final here, but the
+        # onResourcesLoaded() method should only be generated if
+        # --shared-resources is used.
+        rjava_build_options = resource_utils.RJavaBuildOptions()
+        rjava_build_options.ExportAllResources()
+        rjava_build_options.ExportAllStyleables()
+        if options.shared_resources:
+          rjava_build_options.GenerateOnResourcesLoaded()
+
+        resource_utils.CreateRJavaFiles(
+            build.srcjar_dir, package, r_txt_path,
+            options.extra_res_packages,
+            options.extra_r_text_files,
+            rjava_build_options)
+
+      build_utils.ZipDir(options.srcjar_out, build.srcjar_dir)
+
+    if options.resource_zip_out:
+      _GenerateResourcesZip(options.resource_zip_out, options.resource_dirs,
+                            options.v14_skip, build.temp_dir)
+
+
+def main(args):
+  args = build_utils.ExpandFileArgs(args)
+  options = _ParseArgs(args)
+
+  # Order of these must match order specified in GN so that the correct one
+  # appears first in the depfile.
+  possible_output_paths = [
+    options.resource_zip_out,
+    options.r_text_out,
+    options.srcjar_out,
+  ]
+  output_paths = [x for x in possible_output_paths if x]
+
+  # List python deps in input_strings rather than input_paths since the contents
+  # of them does not change what gets written to the depsfile.
+  input_strings = options.extra_res_packages + [
+    options.custom_package,
+    options.shared_resources,
+    options.v14_skip,
+  ]
+
+  possible_input_paths = [
+    options.aapt_path,
+    options.android_manifest,
+    options.android_sdk_jar,
+  ]
+  input_paths = [x for x in possible_input_paths if x]
+  input_paths.extend(options.dependencies_res_zips)
+  input_paths.extend(options.extra_r_text_files)
+
+  # Resource files aren't explicitly listed in GN. Listing them in the depfile
+  # ensures the target will be marked stale when resource files are removed.
+  depfile_deps = []
+  resource_names = []
+  for resource_dir in options.resource_dirs:
+    for resource_file in build_utils.FindInDirectory(resource_dir, '*'):
+      # Don't list the empty .keep file in depfile. Since it doesn't end up
+      # included in the .zip, it can lead to -w 'dupbuild=err' ninja errors
+      # if ever moved.
+      if not resource_file.endswith(os.path.join('empty', '.keep')):
+        input_paths.append(resource_file)
+        depfile_deps.append(resource_file)
+      resource_names.append(os.path.relpath(resource_file, resource_dir))
+
+  # Resource filenames matter to the output, so add them to strings as well.
+  # This matters if a file is renamed but not changed (http://crbug.com/597126).
+  input_strings.extend(sorted(resource_names))
+
+  build_utils.CallAndWriteDepfileIfStale(
+      lambda: _OnStaleMd5(options),
+      options,
+      input_paths=input_paths,
+      input_strings=input_strings,
+      output_paths=output_paths,
+      depfile_deps=depfile_deps)
+
+
+if __name__ == '__main__':
+  main(sys.argv[1:])
diff --git a/build/android/gyp/process_resources.py b/build/android/gyp/process_resources.py
deleted file mode 100755
index a038a60..0000000
--- a/build/android/gyp/process_resources.py
+++ /dev/null
@@ -1,884 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Process Android resources to generate R.java, and prepare for packaging.
-
-This will crunch images with aapt2 and generate v14 compatible resources
-(see generate_v14_compatible_resources.py).
-"""
-
-import codecs
-import collections
-import multiprocessing.pool
-import optparse
-import os
-import re
-import shutil
-import subprocess
-import sys
-import zipfile
-from xml.etree import ElementTree
-
-
-import generate_v14_compatible_resources
-
-from util import build_utils
-
-_SOURCE_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(
-    __file__))))
-# Import jinja2 from third_party/jinja2
-sys.path.insert(1, os.path.join(_SOURCE_ROOT, 'third_party'))
-from jinja2 import Template # pylint: disable=F0401
-
-
-_EMPTY_ANDROID_MANIFEST_PATH = os.path.join(
-    _SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml')
-
-
-# Represents a line from a R.txt file.
-TextSymbolsEntry = collections.namedtuple('RTextEntry',
-    ('java_type', 'resource_type', 'name', 'value'))
-
-
-# A variation of this lists also exists in:
-# //base/android/java/src/org/chromium/base/LocaleUtils.java
-_CHROME_TO_ANDROID_LOCALE_MAP = {
-    'en-GB': 'en-rGB',
-    'en-US': 'en-rUS',
-    'es-419': 'es-rUS',
-    'fil': 'tl',
-    'he': 'iw',
-    'id': 'in',
-    'pt-PT': 'pt-rPT',
-    'pt-BR': 'pt-rBR',
-    'yi': 'ji',
-    'zh-CN': 'zh-rCN',
-    'zh-TW': 'zh-rTW',
-}
-
-# Pngs that we shouldn't convert to webp. Please add rationale when updating.
-_PNG_WEBP_BLACKLIST_PATTERN = re.compile('|'.join([
-    # Crashes on Galaxy S5 running L (https://crbug.com/807059).
-    r'.*star_gray\.png',
-    # Android requires pngs for 9-patch images.
-    r'.*\.9\.png',
-    # Daydream (*.dd) requires pngs for icon files.
-    r'.*\.dd\.png']))
-
-
-class _ResourceWhitelist(object):
-  def __init__(self, entries=None):
-    self._entries = None
-    if entries:
-      self._entries = set(self._Key(x) for x in entries)
-
-  def __contains__(self, entry):
-    return self._entries is None or self._Key(entry) in self._entries
-
-  @staticmethod
-  def _Key(entry):
-    # Whitelists should only care about the name of the resource rather than the
-    # resource ID (since the whitelist is from another compilation unit, the
-    # resource IDs may not match).
-    return (entry.java_type, entry.resource_type, entry.name)
-
-
-def _ParseArgs(args):
-  """Parses command line options.
-
-  Returns:
-    An options object as from optparse.OptionsParser.parse_args()
-  """
-  parser = optparse.OptionParser()
-  build_utils.AddDepfileOption(parser)
-
-  parser.add_option('--android-sdk-jar',
-                    help='the path to android jar file.')
-  parser.add_option('--aapt-path',
-                    help='path to the Android aapt tool')
-  parser.add_option('--non-constant-id', action='store_true')
-
-  parser.add_option('--android-manifest', help='AndroidManifest.xml path')
-  parser.add_option('--custom-package', help='Java package for R.java')
-  parser.add_option(
-      '--shared-resources',
-      action='store_true',
-      help='Make a resource package that can be loaded by a different'
-      'application at runtime to access the package\'s resources.')
-  parser.add_option(
-      '--app-as-shared-lib',
-      action='store_true',
-      help='Make a resource package that can be loaded as shared library.')
-  parser.add_option(
-      '--shared-resources-whitelist',
-      help='An R.txt file acting as a whitelist for resources that should be '
-      'non-final and have their package ID changed at runtime in R.java. If no '
-      'whitelist is provided, then everything is whitelisted.')
-
-  parser.add_option('--resource-dirs',
-                    default='[]',
-                    help='Directories containing resources of this target.')
-  parser.add_option('--dependencies-res-zips',
-                    help='Resources from dependents.')
-
-  parser.add_option('--resource-zip-out',
-                    help='Path for output zipped resources.')
-
-  parser.add_option('--srcjar-out',
-                    help='Path to srcjar to contain generated R.java.')
-  parser.add_option('--r-text-out',
-                    help='Path to store the generated R.txt file.')
-  parser.add_option('--r-text-in',
-                    help='Path to pre-existing R.txt for these resources. '
-                    'Resource names from it will be used to generate R.java '
-                    'instead of aapt-generated R.txt.')
-
-  parser.add_option('--proguard-file',
-                    help='Path to proguard.txt generated file')
-  parser.add_option('--proguard-file-main-dex',
-                    help='Path to proguard.txt generated file for main dex')
-
-  parser.add_option(
-      '--v14-skip',
-      action="store_true",
-      help='Do not generate nor verify v14 resources')
-
-  parser.add_option(
-      '--extra-res-packages',
-      help='Additional package names to generate R.java files for')
-  parser.add_option(
-      '--extra-r-text-files',
-      help='For each additional package, the R.txt file should contain a '
-      'list of resources to be included in the R.java file in the format '
-      'generated by aapt')
-
-  parser.add_option('--support-zh-hk', action='store_true',
-                    help='Use zh-rTW resources for zh-rHK.')
-
-  parser.add_option('--stamp', help='File to touch on success')
-
-  parser.add_option('--debuggable',
-                    action='store_true',
-                    help='Whether to add android:debuggable="true"')
-  parser.add_option('--version-code', help='Version code for apk.')
-  parser.add_option('--version-name', help='Version name for apk.')
-  parser.add_option('--no-compress', help='disables compression for the '
-                    'given comma separated list of extensions')
-  parser.add_option('--locale-whitelist',
-                    default='[]',
-                    help='GN list of languages to include. All other language '
-                         'configs will be stripped out. List may include '
-                         'a combination of Android locales or Chrome locales.')
-  parser.add_option('--apk-path',
-                    help='Path to output (partial) apk.')
-  parser.add_option('--exclude-xxxhdpi', action='store_true',
-                    help='Do not include xxxhdpi drawables.')
-  parser.add_option('--xxxhdpi-whitelist',
-                    default='[]',
-                    help='GN list of globs that say which xxxhdpi images to '
-                         'include even when --exclude-xxxhdpi is set.')
-  parser.add_option('--png-to-webp', action='store_true',
-                    help='Convert png files to webp format.')
-  parser.add_option('--webp-binary', default='',
-                    help='Path to the cwebp binary.')
-  parser.add_option('--no-xml-namespaces',
-                    action='store_true',
-                    help='Whether to strip xml namespaces from processed xml '
-                    'resources')
-
-  options, positional_args = parser.parse_args(args)
-
-  if positional_args:
-    parser.error('No positional arguments should be given.')
-
-  # Check that required options have been provided.
-  required_options = (
-      'android_sdk_jar',
-      'aapt_path',
-      'dependencies_res_zips',
-      )
-  build_utils.CheckOptions(options, parser, required=required_options)
-
-  options.resource_dirs = build_utils.ParseGnList(options.resource_dirs)
-  options.dependencies_res_zips = (
-      build_utils.ParseGnList(options.dependencies_res_zips))
-
-  options.locale_whitelist = build_utils.ParseGnList(options.locale_whitelist)
-  options.xxxhdpi_whitelist = build_utils.ParseGnList(options.xxxhdpi_whitelist)
-
-  # Don't use [] as default value since some script explicitly pass "".
-  if options.extra_res_packages:
-    options.extra_res_packages = (
-        build_utils.ParseGnList(options.extra_res_packages))
-  else:
-    options.extra_res_packages = []
-
-  if options.extra_r_text_files:
-    options.extra_r_text_files = (
-        build_utils.ParseGnList(options.extra_r_text_files))
-  else:
-    options.extra_r_text_files = []
-
-  return options
-
-
-def _CreateRJavaFiles(srcjar_dir, main_r_txt_file, packages, r_txt_files,
-      shared_resources, non_constant_id, whitelist_r_txt_file, is_apk):
-  assert len(packages) == len(r_txt_files), 'Need one R.txt file per package'
-
-  # Map of (resource_type, name) -> Entry.
-  # Contains the correct values for resources.
-  all_resources = {}
-  for entry in _ParseTextSymbolsFile(main_r_txt_file):
-    entry = entry._replace(value=_FixPackageIds(entry.value))
-    all_resources[(entry.resource_type, entry.name)] = entry
-
-  if whitelist_r_txt_file:
-    whitelisted_resources = _ResourceWhitelist(
-        _ParseTextSymbolsFile(whitelist_r_txt_file))
-  else:
-    whitelisted_resources = _ResourceWhitelist()
-
-  # Map of package_name->resource_type->entry
-  resources_by_package = (
-      collections.defaultdict(lambda: collections.defaultdict(list)))
-  # Build the R.java files using each package's R.txt file, but replacing
-  # each entry's placeholder value with correct values from all_resources.
-  for package, r_txt_file in zip(packages, r_txt_files):
-    if package in resources_by_package:
-      raise Exception(('Package name "%s" appeared twice. All '
-                       'android_resources() targets must use unique package '
-                       'names, or no package name at all.') % package)
-    resources_by_type = resources_by_package[package]
-    # The sub-R.txt files have the wrong values at this point. Read them to
-    # figure out which entries belong to them, but use the values from the
-    # main R.txt file.
-    for entry in _ParseTextSymbolsFile(r_txt_file):
-      entry = all_resources.get((entry.resource_type, entry.name))
-      # For most cases missing entry here is an error. It means that some
-      # library claims to have or depend on a resource that isn't included into
-      # the APK. There is one notable exception: Google Play Services (GMS).
-      # GMS is shipped as a bunch of AARs. One of them - basement - contains
-      # R.txt with ids of all resources, but most of the resources are in the
-      # other AARs. However, all other AARs reference their resources via
-      # basement's R.java so the latter must contain all ids that are in its
-      # R.txt. Most targets depend on only a subset of GMS AARs so some
-      # resources are missing, which is okay because the code that references
-      # them is missing too. We can't get an id for a resource that isn't here
-      # so the only solution is to skip the resource entry entirely.
-      #
-      # We can verify that all entries referenced in the code were generated
-      # correctly by running Proguard on the APK: it will report missing
-      # fields.
-      if entry:
-        resources_by_type[entry.resource_type].append(entry)
-
-  for package, resources_by_type in resources_by_package.iteritems():
-    package_r_java_dir = os.path.join(srcjar_dir, *package.split('.'))
-    build_utils.MakeDirectory(package_r_java_dir)
-    package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
-    java_file_contents = _CreateRJavaFile(package, resources_by_type,
-        shared_resources, non_constant_id, whitelisted_resources, is_apk)
-    with open(package_r_java_path, 'w') as f:
-      f.write(java_file_contents)
-
-
-def _ParseTextSymbolsFile(path):
-  """Given an R.txt file, returns a list of TextSymbolsEntry."""
-  ret = []
-  with open(path) as f:
-    for line in f:
-      m = re.match(r'(int(?:\[\])?) (\w+) (\w+) (.+)$', line)
-      if not m:
-        raise Exception('Unexpected line in R.txt: %s' % line)
-      java_type, resource_type, name, value = m.groups()
-      ret.append(TextSymbolsEntry(java_type, resource_type, name, value))
-  return ret
-
-
-def _FixPackageIds(resource_value):
-  # Resource IDs for resources belonging to regular APKs have their first byte
-  # as 0x7f (package id). However with webview, since it is not a regular apk
-  # but used as a shared library, aapt is passed the --shared-resources flag
-  # which changes some of the package ids to 0x02 and 0x00.  This function just
-  # normalises all package ids to 0x7f, which the generated code in R.java
-  # changes to the correct package id at runtime.
-  # resource_value is a string with either, a single value '0x12345678', or an
-  # array of values like '{ 0xfedcba98, 0x01234567, 0x56789abc }'
-  return re.sub(r'0x(?!01)\d\d', r'0x7f', resource_value)
-
-
-def _CreateRJavaFile(package, resources_by_type, shared_resources,
-                     non_constant_id, whitelisted_resources, is_apk):
-  """Generates the contents of a R.java file."""
-  final_resources_by_type = collections.defaultdict(list)
-  non_final_resources_by_type = collections.defaultdict(list)
-  if shared_resources or non_constant_id:
-    for res_type, resources in resources_by_type.iteritems():
-      for entry in resources:
-        # Entries in stylable that are not int[] are not actually resource ids
-        # but constants. If we are creating an apk there is no reason for them
-        # to be non-final. However for libraries, they may be clobbered later on
-        # and thus should remain non-final. This is regardless of the
-        # whitelisting rules (since they are not actually resources).
-        if entry.resource_type == 'styleable' and entry.java_type != 'int[]':
-          if is_apk:
-            final_resources_by_type[res_type].append(entry)
-          else:
-            non_final_resources_by_type[res_type].append(entry)
-        elif entry in whitelisted_resources:
-          non_final_resources_by_type[res_type].append(entry)
-        else:
-          final_resources_by_type[res_type].append(entry)
-  else:
-    final_resources_by_type = resources_by_type
-
-  # Keep these assignments all on one line to make diffing against regular
-  # aapt-generated files easier.
-  create_id = ('{{ e.resource_type }}.{{ e.name }} ^= packageIdTransform;')
-  # Here we diverge from what aapt does. Because we have so many
-  # resources, the onResourcesLoaded method was exceeding the 64KB limit that
-  # Java imposes. For this reason we split onResourcesLoaded into different
-  # methods for each resource type.
-  template = Template("""/* AUTO-GENERATED FILE.  DO NOT MODIFY. */
-
-package {{ package }};
-
-public final class R {
-    private static boolean sResourcesDidLoad;
-    {% for resource_type in resource_types %}
-    public static final class {{ resource_type }} {
-        {% for e in final_resources[resource_type] %}
-        public static final {{ e.java_type }} {{ e.name }} = {{ e.value }};
-        {% endfor %}
-        {% for e in non_final_resources[resource_type] %}
-        public static {{ e.java_type }} {{ e.name }} = {{ e.value }};
-        {% endfor %}
-    }
-    {% endfor %}
-    {% if shared_resources %}
-    public static void transfromArray(int[] array, int packageIdTransform) {
-        for (int i=0; i < array.length; i++) {
-            if ((array[i] >>> 24) == 0x7f) {
-                array[i] ^= packageIdTransform;
-            }
-        }
-    }
-    public static void onResourcesLoaded(int packageId) {
-        assert !sResourcesDidLoad;
-        sResourcesDidLoad = true;
-        int packageIdTransform = (packageId ^ 0x7f) << 24;
-        {% for resource_type in resource_types %}
-        onResourcesLoaded{{ resource_type|title }}(packageIdTransform);
-        {% for e in non_final_resources[resource_type] %}
-        {% if e.java_type == 'int[]' %}
-        transfromArray({{ e.resource_type }}.{{ e.name }}, packageIdTransform);
-        {% endif %}
-        {% endfor %}
-        {% endfor %}
-    }
-    {% for res_type in resource_types %}
-    private static void onResourcesLoaded{{ res_type|title }} (
-            int packageIdTransform) {
-        {% for e in non_final_resources[res_type] %}
-        {% if res_type != 'styleable' and e.java_type != 'int[]' %}
-        """ + create_id + """
-        {% endif %}
-        {% endfor %}
-    }
-    {% endfor %}
-    {% endif %}
-}
-""", trim_blocks=True, lstrip_blocks=True)
-
-  return template.render(package=package,
-                         resource_types=sorted(resources_by_type),
-                         shared_resources=shared_resources,
-                         final_resources=final_resources_by_type,
-                         non_final_resources=non_final_resources_by_type)
-
-
-def _GenerateGlobs(pattern):
-  # This function processes the aapt ignore assets pattern into a list of globs
-  # to be used to exclude files on the python side. It removes the '!', which is
-  # used by aapt to mean 'not chatty' so it does not output if the file is
-  # ignored (we dont output anyways, so it is not required). This function does
-  # not handle the <dir> and <file> prefixes used by aapt and are assumed not to
-  # be included in the pattern string.
-  return pattern.replace('!', '').split(':')
-
-
-def _ZipResources(resource_dirs, zip_path, ignore_pattern):
-  # Python zipfile does not provide a way to replace a file (it just writes
-  # another file with the same name). So, first collect all the files to put
-  # in the zip (with proper overriding), and then zip them.
-  # ignore_pattern is a string of ':' delimited list of globs used to ignore
-  # files that should not be part of the final resource zip.
-  files_to_zip = dict()
-  globs = _GenerateGlobs(ignore_pattern)
-  for d in resource_dirs:
-    for root, _, files in os.walk(d):
-      for f in files:
-        archive_path = f
-        parent_dir = os.path.relpath(root, d)
-        if parent_dir != '.':
-          archive_path = os.path.join(parent_dir, f)
-        path = os.path.join(root, f)
-        if build_utils.MatchesGlob(archive_path, globs):
-          continue
-        files_to_zip[archive_path] = path
-  build_utils.DoZip(files_to_zip.iteritems(), zip_path)
-
-def _SortZip(original_path, sorted_path):
-  with zipfile.ZipFile(sorted_path, 'w') as sorted_zip, \
-      zipfile.ZipFile(original_path, 'r') as original_zip:
-    for info in sorted(original_zip.infolist(), key=lambda i: i.filename):
-      sorted_zip.writestr(info, original_zip.read(info))
-
-
-
-def _DuplicateZhResources(resource_dirs):
-  for resource_dir in resource_dirs:
-    # We use zh-TW resources for zh-HK (if we have zh-TW resources).
-    for path in build_utils.IterFiles(resource_dir):
-      if 'zh-rTW' in path:
-        hk_path = path.replace('zh-rTW', 'zh-rHK')
-        build_utils.MakeDirectory(os.path.dirname(hk_path))
-        shutil.copyfile(path, hk_path)
-
-def _ExtractPackageFromManifest(manifest_path):
-  doc = ElementTree.parse(manifest_path)
-  return doc.getroot().get('package')
-
-
-def _ToAaptLocales(locale_whitelist, support_zh_hk):
-  """Converts the list of Chrome locales to aapt config locales."""
-  ret = set()
-  for locale in locale_whitelist:
-    locale = _CHROME_TO_ANDROID_LOCALE_MAP.get(locale, locale)
-    if locale is None or ('-' in locale and '-r' not in locale):
-      raise Exception('_CHROME_TO_ANDROID_LOCALE_MAP needs updating.'
-                      ' Found: %s' % locale)
-    ret.add(locale)
-    # Always keep non-regional fall-backs.
-    language = locale.split('-')[0]
-    ret.add(language)
-
-  # We don't actually support zh-HK in Chrome on Android, but we mimic the
-  # native side behavior where we use zh-TW resources when the locale is set to
-  # zh-HK. See https://crbug.com/780847.
-  if support_zh_hk:
-    assert not any('HK' in l for l in locale_whitelist), (
-        'Remove special logic if zh-HK is now supported (crbug.com/780847).')
-    ret.add('zh-rHK')
-  return sorted(ret)
-
-
-def _MoveImagesToNonMdpiFolders(res_root):
-  """Move images from drawable-*-mdpi-* folders to drawable-* folders.
-
-  Why? http://crbug.com/289843
-  """
-  for src_dir_name in os.listdir(res_root):
-    src_components = src_dir_name.split('-')
-    if src_components[0] != 'drawable' or 'mdpi' not in src_components:
-      continue
-    src_dir = os.path.join(res_root, src_dir_name)
-    if not os.path.isdir(src_dir):
-      continue
-    dst_components = [c for c in src_components if c != 'mdpi']
-    assert dst_components != src_components
-    dst_dir_name = '-'.join(dst_components)
-    dst_dir = os.path.join(res_root, dst_dir_name)
-    build_utils.MakeDirectory(dst_dir)
-    for src_file_name in os.listdir(src_dir):
-      if not os.path.splitext(src_file_name)[1] in ('.png', '.webp'):
-        continue
-      src_file = os.path.join(src_dir, src_file_name)
-      dst_file = os.path.join(dst_dir, src_file_name)
-      assert not os.path.lexists(dst_file)
-      shutil.move(src_file, dst_file)
-
-
-def _CreateLinkApkArgs(options):
-  link_command = [
-    options.aapt_path + '2',
-    'link',
-    '--version-code', options.version_code,
-    '--version-name', options.version_name,
-    '--auto-add-overlay',
-    '--no-version-vectors',
-    '-I', options.android_sdk_jar,
-    '-o', options.apk_path,
-  ]
-
-  if options.proguard_file:
-    link_command += ['--proguard', options.proguard_file]
-  if options.proguard_file_main_dex:
-    link_command += ['--proguard-main-dex', options.proguard_file_main_dex]
-
-  if options.no_compress:
-    for ext in options.no_compress.split(','):
-      link_command += ['-0', ext]
-
-  if options.shared_resources:
-    link_command.append('--shared-lib')
-
-  if options.locale_whitelist:
-    aapt_locales = _ToAaptLocales(
-        options.locale_whitelist, options.support_zh_hk)
-    link_command += ['-c', ','.join(aapt_locales)]
-
-  if options.no_xml_namespaces:
-    link_command.append('--no-xml-namespaces')
-
-  return link_command
-
-
-def _ExtractVersionFromSdk(aapt_path, sdk_path):
-  output = subprocess.check_output([aapt_path, 'dump', 'badging', sdk_path])
-  version_code = re.search(r"versionCode='(.*?)'", output).group(1)
-  version_name = re.search(r"versionName='(.*?)'", output).group(1)
-  return version_code, version_name,
-
-
-def _FixManifest(options, temp_dir):
-  debug_manifest_path = os.path.join(temp_dir, 'AndroidManifest.xml')
-  _ANDROID_NAMESPACE = 'http://schemas.android.com/apk/res/android'
-  _TOOLS_NAMESPACE = 'http://schemas.android.com/tools'
-  ElementTree.register_namespace('android', _ANDROID_NAMESPACE)
-  ElementTree.register_namespace('tools', _TOOLS_NAMESPACE)
-  original_manifest = ElementTree.parse(options.android_manifest)
-
-  version_code, version_name = _ExtractVersionFromSdk(
-      options.aapt_path, options.android_sdk_jar)
-
-  # ElementTree.find does not work if the required tag is the root.
-  if original_manifest.getroot().tag == 'manifest':
-    manifest_node = original_manifest.getroot()
-  else:
-    manifest_node = original_manifest.find('manifest')
-
-  manifest_node.set('platformBuildVersionCode', version_code)
-  manifest_node.set('platformBuildVersionName', version_name)
-
-  if options.debuggable:
-    app_node = original_manifest.find('application')
-    app_node.set('{%s}%s' % (_ANDROID_NAMESPACE, 'debuggable'), 'true')
-
-  with open(debug_manifest_path, 'w') as debug_manifest:
-    debug_manifest.write(ElementTree.tostring(
-        original_manifest.getroot(), encoding='UTF-8'))
-
-  return debug_manifest_path
-
-
-def _ResourceNameFromPath(path):
-  return os.path.splitext(os.path.basename(path))[0]
-
-
-def _CreateKeepPredicate(resource_dirs, exclude_xxxhdpi, xxxhdpi_whitelist):
-  if not exclude_xxxhdpi:
-    # Do not extract dotfiles (e.g. ".gitkeep"). aapt ignores them anyways.
-    return lambda path: os.path.basename(path)[0] != '.'
-
-  # Returns False only for xxxhdpi non-mipmap, non-whitelisted drawables.
-  naive_predicate = lambda path: (
-      not re.search(r'[/-]xxxhdpi[/-]', path) or
-      re.search(r'[/-]mipmap[/-]', path) or
-      build_utils.MatchesGlob(path, xxxhdpi_whitelist))
-
-  # Build a set of all non-xxxhdpi drawables to ensure that we never exclude any
-  # xxxhdpi drawable that does not exist in other densities.
-  non_xxxhdpi_drawables = set()
-  for resource_dir in resource_dirs:
-    for path in build_utils.IterFiles(resource_dir):
-      if re.search(r'[/-]drawable[/-]', path) and naive_predicate(path):
-        non_xxxhdpi_drawables.add(_ResourceNameFromPath(path))
-
-  return lambda path: (naive_predicate(path) or
-                       _ResourceNameFromPath(path) not in non_xxxhdpi_drawables)
-
-
-def _ConvertToWebP(webp_binary, png_files):
-  pool = multiprocessing.pool.ThreadPool(10)
-  def convert_image(png_path):
-    root = os.path.splitext(png_path)[0]
-    webp_path = root + '.webp'
-    args = [webp_binary, png_path, '-mt', '-quiet', '-m', '6', '-q', '100',
-        '-lossless', '-o', webp_path]
-    subprocess.check_call(args)
-    os.remove(png_path)
-
-  pool.map(convert_image, [f for f in png_files
-                           if not _PNG_WEBP_BLACKLIST_PATTERN.match(f)])
-  pool.close()
-  pool.join()
-
-
-def _CompileDeps(aapt_path, dep_subdirs, temp_dir):
-  partials_dir = os.path.join(temp_dir, 'partials')
-  build_utils.MakeDirectory(partials_dir)
-  partial_compile_command = [
-      aapt_path + '2',
-      'compile',
-      # TODO(wnwen): Turn this on once aapt2 forces 9-patch to be crunched.
-      # '--no-crunch',
-  ]
-  pool = multiprocessing.pool.ThreadPool(10)
-  def compile_partial(directory):
-    dirname = os.path.basename(directory)
-    partial_path = os.path.join(partials_dir, dirname + '.zip')
-    compile_command = (partial_compile_command +
-                       ['--dir', directory, '-o', partial_path])
-    build_utils.CheckOutput(compile_command)
-
-    # Sorting the files in the partial ensures deterministic output from the
-    # aapt2 link step which uses order of files in the partial.
-    sorted_partial_path = os.path.join(partials_dir, dirname + '.sorted.zip')
-    _SortZip(partial_path, sorted_partial_path)
-
-    return sorted_partial_path
-
-  partials = pool.map(compile_partial, dep_subdirs)
-  pool.close()
-  pool.join()
-  return partials
-
-
-def _PackageApk(options, dep_subdirs, temp_dir, gen_dir, r_txt_path):
-  _DuplicateZhResources(dep_subdirs)
-
-  keep_predicate = _CreateKeepPredicate(
-      dep_subdirs, options.exclude_xxxhdpi, options.xxxhdpi_whitelist)
-  png_paths = []
-  for directory in dep_subdirs:
-    for f in build_utils.IterFiles(directory):
-      if not keep_predicate(f):
-        os.remove(f)
-      elif f.endswith('.png'):
-        png_paths.append(f)
-  if png_paths and options.png_to_webp:
-    _ConvertToWebP(options.webp_binary, png_paths)
-  for directory in dep_subdirs:
-    _MoveImagesToNonMdpiFolders(directory)
-
-  link_command = _CreateLinkApkArgs(options)
-  link_command += ['--output-text-symbols', r_txt_path]
-  link_command += ['--java', gen_dir]
-
-  fixed_manifest = _FixManifest(options, temp_dir)
-  link_command += ['--manifest', fixed_manifest]
-
-  partials = _CompileDeps(options.aapt_path, dep_subdirs, temp_dir)
-  for partial in partials:
-    link_command += ['-R', partial]
-
-  # Creates a .zip with AndroidManifest.xml, resources.arsc, res/*
-  # Also creates R.txt
-  build_utils.CheckOutput(
-      link_command, print_stdout=False, print_stderr=False)
-
-
-# _PackageLibrary uses aapt rather than aapt2 because aapt2 compile does not
-# support outputting an R.txt file.
-def _PackageLibrary(options, dep_subdirs, temp_dir, gen_dir):
-  v14_dir = os.path.join(temp_dir, 'v14')
-  build_utils.MakeDirectory(v14_dir)
-
-  # Generate R.java. This R.java contains non-final constants and is used only
-  # while compiling the library jar (e.g. chromium_content.jar). When building
-  # an apk, a new R.java file with the correct resource -> ID mappings will be
-  # generated by merging the resources from all libraries and the main apk
-  # project.
-  package_command = [options.aapt_path,
-                     'package',
-                     '-m',
-                     '-M', _EMPTY_ANDROID_MANIFEST_PATH,
-                     '--no-crunch',
-                     '--auto-add-overlay',
-                     '--no-version-vectors',
-                     '-I', options.android_sdk_jar,
-                     '--output-text-symbols', gen_dir,
-                     '-J', gen_dir,  # Required for R.txt generation.
-                     '--ignore-assets', build_utils.AAPT_IGNORE_PATTERN]
-
-  # Adding all dependencies as sources is necessary for @type/foo references
-  # to symbols within dependencies to resolve. However, it has the side-effect
-  # that all Java symbols from dependencies are copied into the new R.java.
-  # E.g.: It enables an arguably incorrect usage of
-  # "mypackage.R.id.lib_symbol" where "libpackage.R.id.lib_symbol" would be
-  # more correct. This is just how Android works.
-  for d in dep_subdirs:
-    package_command += ['-S', d]
-
-  input_resource_dirs = options.resource_dirs
-
-  for d in input_resource_dirs:
-    package_command += ['-S', d]
-
-  if not options.v14_skip:
-    for resource_dir in input_resource_dirs:
-      generate_v14_compatible_resources.GenerateV14Resources(
-          resource_dir,
-          v14_dir)
-
-  # This is the list of directories with resources to put in the final .zip
-  zip_resource_dirs = input_resource_dirs + [v14_dir]
-
-  if options.resource_zip_out:
-    _ZipResources(zip_resource_dirs, options.resource_zip_out,
-                  build_utils.AAPT_IGNORE_PATTERN)
-
-  # Only creates an R.txt
-  build_utils.CheckOutput(
-      package_command, print_stdout=False, print_stderr=False)
-
-
-def _CreateRTxtAndSrcJar(options, r_txt_path, srcjar_dir):
-  # When an empty res/ directory is passed, aapt does not write an R.txt.
-  if not os.path.exists(r_txt_path):
-    build_utils.Touch(r_txt_path)
-
-  if options.r_text_in:
-    r_txt_path = options.r_text_in
-
-  packages = list(options.extra_res_packages)
-  r_txt_files = list(options.extra_r_text_files)
-
-  cur_package = options.custom_package
-  if not options.custom_package and options.android_manifest:
-    cur_package = _ExtractPackageFromManifest(options.android_manifest)
-
-  # Don't create a .java file for the current resource target when:
-  # - no package name was provided (either by manifest or build rules),
-  # - there was already a dependent android_resources() with the same
-  #   package (occurs mostly when an apk target and resources target share
-  #   an AndroidManifest.xml)
-  if cur_package and cur_package not in packages:
-    packages.append(cur_package)
-    r_txt_files.append(r_txt_path)
-
-  if packages:
-    shared_resources = options.shared_resources or options.app_as_shared_lib
-    _CreateRJavaFiles(srcjar_dir, r_txt_path, packages, r_txt_files,
-        shared_resources, options.non_constant_id,
-        options.shared_resources_whitelist, bool(options.apk_path))
-
-  if options.srcjar_out:
-    build_utils.ZipDir(options.srcjar_out, srcjar_dir)
-
-  if options.r_text_out:
-    shutil.copyfile(r_txt_path, options.r_text_out)
-
-
-def _ExtractDeps(dep_zips, deps_dir):
-  dep_subdirs = []
-  for z in dep_zips:
-    subdir = os.path.join(deps_dir, os.path.basename(z))
-    if os.path.exists(subdir):
-      raise Exception('Resource zip name conflict: ' + os.path.basename(z))
-    build_utils.ExtractAll(z, path=subdir)
-    dep_subdirs.append(subdir)
-  return dep_subdirs
-
-
-def _OnStaleMd5(options):
-  with build_utils.TempDir() as temp_dir:
-    deps_dir = os.path.join(temp_dir, 'deps')
-    build_utils.MakeDirectory(deps_dir)
-    gen_dir = os.path.join(temp_dir, 'gen')
-    build_utils.MakeDirectory(gen_dir)
-    r_txt_path = os.path.join(gen_dir, 'R.txt')
-    srcjar_dir = os.path.join(temp_dir, 'java')
-
-    dep_subdirs = _ExtractDeps(options.dependencies_res_zips, deps_dir)
-
-    if options.apk_path:
-      _PackageApk(options, dep_subdirs, temp_dir, gen_dir, r_txt_path)
-    else:
-      _PackageLibrary(options, dep_subdirs, temp_dir, gen_dir)
-
-    _CreateRTxtAndSrcJar(options, r_txt_path, srcjar_dir)
-
-
-def main(args):
-  args = build_utils.ExpandFileArgs(args)
-  options = _ParseArgs(args)
-
-  # Order of these must match order specified in GN so that the correct one
-  # appears first in the depfile.
-  possible_output_paths = [
-    options.apk_path,
-    options.resource_zip_out,
-    options.r_text_out,
-    options.srcjar_out,
-    options.proguard_file,
-    options.proguard_file_main_dex,
-  ]
-  output_paths = [x for x in possible_output_paths if x]
-
-  # List python deps in input_strings rather than input_paths since the contents
-  # of them does not change what gets written to the depsfile.
-  input_strings = options.extra_res_packages + [
-    options.app_as_shared_lib,
-    options.custom_package,
-    options.non_constant_id,
-    options.shared_resources,
-    options.v14_skip,
-    options.exclude_xxxhdpi,
-    options.xxxhdpi_whitelist,
-    str(options.debuggable),
-    str(options.png_to_webp),
-    str(options.support_zh_hk),
-    str(options.no_xml_namespaces),
-  ]
-
-  if options.apk_path:
-    input_strings.extend(_CreateLinkApkArgs(options))
-
-  possible_input_paths = [
-    options.aapt_path,
-    options.android_manifest,
-    options.android_sdk_jar,
-    options.shared_resources_whitelist,
-  ]
-  input_paths = [x for x in possible_input_paths if x]
-  input_paths.extend(options.dependencies_res_zips)
-  input_paths.extend(options.extra_r_text_files)
-
-  if options.webp_binary:
-    input_paths.append(options.webp_binary)
-
-  # Resource files aren't explicitly listed in GN. Listing them in the depfile
-  # ensures the target will be marked stale when resource files are removed.
-  depfile_deps = []
-  resource_names = []
-  for resource_dir in options.resource_dirs:
-    for resource_file in build_utils.FindInDirectory(resource_dir, '*'):
-      # Don't list the empty .keep file in depfile. Since it doesn't end up
-      # included in the .zip, it can lead to -w 'dupbuild=err' ninja errors
-      # if ever moved.
-      if not resource_file.endswith(os.path.join('empty', '.keep')):
-        input_paths.append(resource_file)
-        depfile_deps.append(resource_file)
-      resource_names.append(os.path.relpath(resource_file, resource_dir))
-
-  # Resource filenames matter to the output, so add them to strings as well.
-  # This matters if a file is renamed but not changed (http://crbug.com/597126).
-  input_strings.extend(sorted(resource_names))
-
-  build_utils.CallAndWriteDepfileIfStale(
-      lambda: _OnStaleMd5(options),
-      options,
-      input_paths=input_paths,
-      input_strings=input_strings,
-      output_paths=output_paths,
-      depfile_deps=depfile_deps)
-
-
-if __name__ == '__main__':
-  main(sys.argv[1:])
diff --git a/build/android/gyp/util/resource_utils.py b/build/android/gyp/util/resource_utils.py
new file mode 100644
index 0000000..1c0b7c5
--- /dev/null
+++ b/build/android/gyp/util/resource_utils.py
@@ -0,0 +1,453 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import collections
+import contextlib
+import os
+import re
+import shutil
+import sys
+import tempfile
+from xml.etree import ElementTree
+
+import util.build_utils as build_utils
+
+_SOURCE_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(
+    os.path.dirname(__file__)))))
+# Import jinja2 from third_party/jinja2
+sys.path.insert(1, os.path.join(_SOURCE_ROOT, 'third_party'))
+from jinja2 import Template # pylint: disable=F0401
+
+
+EMPTY_ANDROID_MANIFEST_PATH = os.path.join(
+    _SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml')
+
+
+# Represents a line from a R.txt file.
+_TextSymbolEntry = collections.namedtuple('RTextEntry',
+    ('java_type', 'resource_type', 'name', 'value'))
+
+
+def _ParseTextSymbolsFile(path, fix_package_ids=False):
+  """Given an R.txt file, returns a list of _TextSymbolEntry.
+
+  Args:
+    path: Input file path.
+    fix_package_ids: if True, all packaged IDs read from the file
+      will be fixed to 0x7f.
+  Returns:
+    A list of _TextSymbolEntry instances.
+  Raises:
+    Exception: An unexpected line was detected in the input.
+  """
+  ret = []
+  with open(path) as f:
+    for line in f:
+      m = re.match(r'(int(?:\[\])?) (\w+) (\w+) (.+)$', line)
+      if not m:
+        raise Exception('Unexpected line in R.txt: %s' % line)
+      java_type, resource_type, name, value = m.groups()
+      if fix_package_ids:
+        value = _FixPackageIds(value)
+      ret.append(_TextSymbolEntry(java_type, resource_type, name, value))
+  return ret
+
+
+def _FixPackageIds(resource_value):
+  # Resource IDs for resources belonging to regular APKs have their first byte
+  # as 0x7f (package id). However with webview, since it is not a regular apk
+  # but used as a shared library, aapt is passed the --shared-resources flag
+  # which changes some of the package ids to 0x02 and 0x00.  This function just
+  # normalises all package ids to 0x7f, which the generated code in R.java
+  # changes to the correct package id at runtime.
+  # resource_value is a string with either, a single value '0x12345678', or an
+  # array of values like '{ 0xfedcba98, 0x01234567, 0x56789abc }'
+  return re.sub(r'0x(?!01)\d\d', r'0x7f', resource_value)
+
+
+def _GetRTxtResourceNames(r_txt_path):
+  """Parse an R.txt file and extract the set of resource names from it."""
+  result = set()
+  for entry in _ParseTextSymbolsFile(r_txt_path):
+    result.add(entry.name)
+  return result
+
+
+class RJavaBuildOptions:
+  """A class used to model the various ways to build an R.java file.
+
+  This is used to control which resource ID variables will be final or
+  non-final, and whether an onResourcesLoaded() method will be generated
+  to adjust the non-final ones, when the corresponding library is loaded
+  at runtime.
+
+  Note that by default, all resources are final, and there is no
+  method generated, which corresponds to calling ExportNoResources().
+  """
+  def __init__(self):
+    self.has_constant_ids = True
+    self.resources_whitelist = None
+    self.has_on_resources_loaded = False
+    self.export_const_styleable = False
+
+  def ExportNoResources(self):
+    """Make all resource IDs final, and don't generate a method."""
+    self.has_constant_ids = True
+    self.resources_whitelist = None
+    self.has_on_resources_loaded = False
+    self.export_const_styleable = False
+
+  def ExportAllResources(self):
+    """Make all resource IDs non-final in the R.java file."""
+    self.has_constant_ids = False
+    self.resources_whitelist = None
+
+  def ExportSomeResources(self, r_txt_file_path):
+    """Only select specific resource IDs to be non-final.
+
+    Args:
+      r_txt_file_path: The path to an R.txt file. All resources named
+        int it will be non-final in the generated R.java file, all others
+        will be final.
+    """
+    self.has_constant_ids = True
+    self.resources_whitelist = _GetRTxtResourceNames(r_txt_file_path)
+
+  def ExportAllStyleables(self):
+    """Make all styleable constants non-final, even non-resources ones.
+
+    Resources that are styleable but not of int[] type are not actually
+    resource IDs but constants. By default they are always final. Call this
+    method to make them non-final anyway in the final R.java file.
+    """
+    self.export_const_styleable = True
+
+  def GenerateOnResourcesLoaded(self):
+    """Generate an onResourcesLoaded() method.
+
+    This Java method will be called at runtime by the framework when
+    the corresponding library (which includes the R.java source file)
+    will be loaded at runtime. This corresponds to the --shared-resources
+    or --app-as-shared-lib flags of 'aapt package'.
+    """
+    self.has_on_resources_loaded = True
+
+  def _IsResourceFinal(self, entry):
+    """Determines whether a resource should be final or not.
+
+  Args:
+    entry: A _TextSymbolEntry instance.
+  Returns:
+    True iff the corresponding entry should be final.
+  """
+    if entry.resource_type == 'styleable' and entry.java_type != 'int[]':
+      # A styleable constant may be exported as non-final after all.
+      return not self.export_const_styleable
+    elif not self.has_constant_ids:
+      # Every resource is non-final
+      return False
+    elif not self.resources_whitelist:
+      # No whitelist means all IDs are non-final.
+      return True
+    else:
+      # Otherwise, only those in the
+      return entry.name not in self.resources_whitelist
+
+
+def CreateRJavaFiles(srcjar_dir, package, main_r_txt_file,
+                     extra_res_packages, extra_r_txt_files,
+                     rjava_build_options):
+  """Create all R.java files for a set of packages and R.txt files.
+
+  Args:
+    srcjar_dir: The top-level output directory for the generated files.
+    package: Top-level package name.
+    main_r_txt_file: The main R.txt file containing the valid values
+      of _all_ resource IDs.
+    extra_res_packages: A list of extra package names.
+    extra_r_txt_files: A list of extra R.txt files. One per item in
+      |extra_res_packages|. Note that all resource IDs in them will be ignored,
+      |and replaced by the values extracted from |main_r_txt_file|.
+    rjava_build_options: An RJavaBuildOptions instance that controls how
+      exactly the R.java file is generated.
+  Raises:
+    Exception if a package name appears several times in |extra_res_packages|
+  """
+  assert len(extra_res_packages) == len(extra_r_txt_files), \
+         'Need one R.txt file per package'
+
+  packages = list(extra_res_packages)
+  r_txt_files = list(extra_r_txt_files)
+
+  if package not in packages:
+    # Sometimes, an apk target and a resources target share the same
+    # AndroidManifest.xml and thus |package| will already be in |packages|.
+    packages.append(package)
+    r_txt_files.append(main_r_txt_file)
+
+  # Map of (resource_type, name) -> Entry.
+  # Contains the correct values for resources.
+  all_resources = {}
+  for entry in _ParseTextSymbolsFile(main_r_txt_file, fix_package_ids=True):
+    all_resources[(entry.resource_type, entry.name)] = entry
+
+  # Map of package_name->resource_type->entry
+  resources_by_package = (
+      collections.defaultdict(lambda: collections.defaultdict(list)))
+  # Build the R.java files using each package's R.txt file, but replacing
+  # each entry's placeholder value with correct values from all_resources.
+  for package, r_txt_file in zip(packages, r_txt_files):
+    if package in resources_by_package:
+      raise Exception(('Package name "%s" appeared twice. All '
+                       'android_resources() targets must use unique package '
+                       'names, or no package name at all.') % package)
+    resources_by_type = resources_by_package[package]
+    # The sub-R.txt files have the wrong values at this point. Read them to
+    # figure out which entries belong to them, but use the values from the
+    # main R.txt file.
+    for entry in _ParseTextSymbolsFile(r_txt_file):
+      entry = all_resources.get((entry.resource_type, entry.name))
+      # For most cases missing entry here is an error. It means that some
+      # library claims to have or depend on a resource that isn't included into
+      # the APK. There is one notable exception: Google Play Services (GMS).
+      # GMS is shipped as a bunch of AARs. One of them - basement - contains
+      # R.txt with ids of all resources, but most of the resources are in the
+      # other AARs. However, all other AARs reference their resources via
+      # basement's R.java so the latter must contain all ids that are in its
+      # R.txt. Most targets depend on only a subset of GMS AARs so some
+      # resources are missing, which is okay because the code that references
+      # them is missing too. We can't get an id for a resource that isn't here
+      # so the only solution is to skip the resource entry entirely.
+      #
+      # We can verify that all entries referenced in the code were generated
+      # correctly by running Proguard on the APK: it will report missing
+      # fields.
+      if entry:
+        resources_by_type[entry.resource_type].append(entry)
+
+  for package, resources_by_type in resources_by_package.iteritems():
+    _CreateRJavaSourceFile(srcjar_dir, package, resources_by_type,
+                           rjava_build_options)
+
+
+def _CreateRJavaSourceFile(srcjar_dir, package, resources_by_type,
+                           rjava_build_options):
+  """Generates an R.java source file."""
+  package_r_java_dir = os.path.join(srcjar_dir, *package.split('.'))
+  build_utils.MakeDirectory(package_r_java_dir)
+  package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
+  java_file_contents = _RenderRJavaSource(package, resources_by_type,
+                                          rjava_build_options)
+  with open(package_r_java_path, 'w') as f:
+    f.write(java_file_contents)
+
+
+def _RenderRJavaSource(package, resources_by_type, rjava_build_options):
+  """Render an R.java source file. See _CreateRJaveSourceFile for args info."""
+  final_resources_by_type = collections.defaultdict(list)
+  non_final_resources_by_type = collections.defaultdict(list)
+  for res_type, resources in resources_by_type.iteritems():
+    for entry in resources:
+      # Entries in stylable that are not int[] are not actually resource ids
+      # but constants.
+      if rjava_build_options._IsResourceFinal(entry):
+        final_resources_by_type[res_type].append(entry)
+      else:
+        non_final_resources_by_type[res_type].append(entry)
+
+  # Keep these assignments all on one line to make diffing against regular
+  # aapt-generated files easier.
+  create_id = ('{{ e.resource_type }}.{{ e.name }} ^= packageIdTransform;')
+  # Here we diverge from what aapt does. Because we have so many
+  # resources, the onResourcesLoaded method was exceeding the 64KB limit that
+  # Java imposes. For this reason we split onResourcesLoaded into different
+  # methods for each resource type.
+  template = Template("""/* AUTO-GENERATED FILE.  DO NOT MODIFY. */
+
+package {{ package }};
+
+public final class R {
+    private static boolean sResourcesDidLoad;
+    {% for resource_type in resource_types %}
+    public static final class {{ resource_type }} {
+        {% for e in final_resources[resource_type] %}
+        public static final {{ e.java_type }} {{ e.name }} = {{ e.value }};
+        {% endfor %}
+        {% for e in non_final_resources[resource_type] %}
+        public static {{ e.java_type }} {{ e.name }} = {{ e.value }};
+        {% endfor %}
+    }
+    {% endfor %}
+    {% if has_on_resources_loaded %}
+    public static void transfromArray(int[] array, int packageIdTransform) {
+        for (int i=0; i < array.length; i++) {
+            if ((array[i] >>> 24) == 0x7f) {
+                array[i] ^= packageIdTransform;
+            }
+        }
+    }
+    public static void onResourcesLoaded(int packageId) {
+        assert !sResourcesDidLoad;
+        sResourcesDidLoad = true;
+        int packageIdTransform = (packageId ^ 0x7f) << 24;
+        {% for resource_type in resource_types %}
+        onResourcesLoaded{{ resource_type|title }}(packageIdTransform);
+        {% for e in non_final_resources[resource_type] %}
+        {% if e.java_type == 'int[]' %}
+        transfromArray({{ e.resource_type }}.{{ e.name }}, packageIdTransform);
+        {% endif %}
+        {% endfor %}
+        {% endfor %}
+    }
+    {% for res_type in resource_types %}
+    private static void onResourcesLoaded{{ res_type|title }} (
+            int packageIdTransform) {
+        {% for e in non_final_resources[res_type] %}
+        {% if res_type != 'styleable' and e.java_type != 'int[]' %}
+        """ + create_id + """
+        {% endif %}
+        {% endfor %}
+    }
+    {% endfor %}
+    {% endif %}
+}
+""", trim_blocks=True, lstrip_blocks=True)
+
+  return template.render(
+      package=package,
+      resource_types=sorted(resources_by_type),
+      has_on_resources_loaded=rjava_build_options.has_on_resources_loaded,
+      final_resources=final_resources_by_type,
+      non_final_resources=non_final_resources_by_type)
+
+
+def ExtractPackageFromManifest(manifest_path):
+  """Extract package name from Android manifest file."""
+  doc = ElementTree.parse(manifest_path)
+  return doc.getroot().get('package')
+
+
+def ExtractDeps(dep_zips, deps_dir):
+  """Extract a list of resource dependency zip files.
+
+  Args:
+     dep_zips: A list of zip file paths, each one will be extracted to
+       a subdirectory of |deps_dir|, named after the zip file (e.g.
+       '/some/path/foo.zip' -> '{deps_dir}/foo/').
+    deps_dir: Top-level extraction directory.
+  Returns:
+    The list of all sub-directory paths, relative to |deps_dir|.
+  Raises:
+    Exception: If a sub-directory already exists with the same name before
+      extraction.
+  """
+  dep_subdirs = []
+  for z in dep_zips:
+    subdir = os.path.join(deps_dir, os.path.basename(z))
+    if os.path.exists(subdir):
+      raise Exception('Resource zip name conflict: ' + os.path.basename(z))
+    build_utils.ExtractAll(z, path=subdir)
+    dep_subdirs.append(subdir)
+  return dep_subdirs
+
+
+class _ResourceBuildContext(object):
+  """A temporary directory for packaging and compiling Android resources."""
+  def __init__(self):
+    """Initialized the context."""
+    # The top-level temporary directory.
+    self.temp_dir = tempfile.mkdtemp()
+    # A location to store resources extracted form dependency zip files.
+    self.deps_dir = os.path.join(self.temp_dir, 'deps')
+    os.mkdir(self.deps_dir)
+    # A location to place aapt-generated files.
+    self.gen_dir = os.path.join(self.temp_dir, 'gen')
+    os.mkdir(self.gen_dir)
+    # Location of the generated R.txt file.
+    self.r_txt_path = os.path.join(self.gen_dir, 'R.txt')
+    # A location to place generated R.java files.
+    self.srcjar_dir = os.path.join(self.temp_dir, 'java')
+    os.mkdir(self.srcjar_dir)
+
+  def Close(self):
+    """Close the context and destroy all temporary files."""
+    shutil.rmtree(self.temp_dir)
+
+
+@contextlib.contextmanager
+def BuildContext():
+  """Generator for a _ResourceBuildContext instance."""
+  try:
+    context = _ResourceBuildContext()
+    yield context
+  finally:
+    context.Close()
+
+
+def ResourceArgsParser():
+  """Create an argparse.ArgumentParser instance with common argument groups.
+
+  Returns:
+    A tuple of (parser, in_group, out_group) corresponding to the parser
+    instance, and the input and output argument groups for it, respectively.
+  """
+  parser = argparse.ArgumentParser(description=__doc__)
+
+  input_opts = parser.add_argument_group('Input options')
+  output_opts = parser.add_argument_group('Output options')
+
+  build_utils.AddDepfileOption(output_opts)
+
+  input_opts.add_argument('--android-sdk-jar', required=True,
+                        help='Path to the android.jar file.')
+
+  input_opts.add_argument('--aapt-path', required=True,
+                         help='Path to the Android aapt tool')
+
+  input_opts.add_argument('--dependencies-res-zips', required=True,
+                    help='Resources zip archives from dependents. Required to '
+                         'resolve @type/foo references into dependent '
+                         'libraries.')
+
+  input_opts.add_argument(
+      '--r-text-in',
+       help='Path to pre-existing R.txt. Its resource IDs override those found '
+            'in the aapt-generated R.txt when generating R.java.')
+
+  input_opts.add_argument(
+      '--extra-res-packages',
+      help='Additional package names to generate R.java files for.')
+
+  input_opts.add_argument(
+      '--extra-r-text-files',
+      help='For each additional package, the R.txt file should contain a '
+           'list of resources to be included in the R.java file in the format '
+           'generated by aapt.')
+
+  return (parser, input_opts, output_opts)
+
+
+def HandleCommonOptions(options):
+  """Handle common command-line options after parsing.
+
+  Args:
+    options: the result of parse_args() on the parser returned by
+        ResourceArgsParser(). This function updates a few common fields.
+  """
+  options.dependencies_res_zips = (
+      build_utils.ParseGnList(options.dependencies_res_zips))
+
+  # Don't use [] as default value since some script explicitly pass "".
+  if options.extra_res_packages:
+    options.extra_res_packages = (
+        build_utils.ParseGnList(options.extra_res_packages))
+  else:
+    options.extra_res_packages = []
+
+  if options.extra_r_text_files:
+    options.extra_r_text_files = (
+        build_utils.ParseGnList(options.extra_r_text_files))
+  else:
+    options.extra_r_text_files = []
diff --git a/build/android/main_dex_classes.flags b/build/android/main_dex_classes.flags
index a293257..2f709a6c 100644
--- a/build/android/main_dex_classes.flags
+++ b/build/android/main_dex_classes.flags
@@ -44,22 +44,18 @@
 -keep @**.RunWith class * {}
 
 # The following are based on $SDK_BUILD_TOOLS/mainDexClasses.rules
-# Ours differ in that it omits -keeps for application / instrumentation /
-# backupagents (these are added by aapt's main dex list rules output).
-# The keeps in this file are not only redundant, but the explicit -keep
-# of Application.attachBaseContext() is overly broad and adds ~20k methods to
-# chrome_public_apk at the time of this change.
+# Ours differ in that:
+# 1. It omits -keeps for application / instrumentation / backupagents (these are
+#    redundant since they are added by aapt's main dex list rules output).
+# 2. Omits keep for Application.attachBaseContext(), which is overly broad.
+# 3. Omits keep for all annotations, which is also overly broad (and pulls in
+#    any class that has an @IntDef).
 
 ######## START mainDexClasses.rules ########
 
-# We need to keep all annotation classes because proguard does not trace annotation attribute
-# it just filter the annotation attributes according to annotation classes it already kept.
--keep public class * extends java.lang.annotation.Annotation {
- *;
-}
-# Keep old fashion tests in the main dex or they'll be silently ignored by InstrumentationTestRunner↵
+# Keep old fashion tests in the main dex or they'll be silently ignored by InstrumentationTestRunner
 -keep public class * extends android.test.InstrumentationTestCase {
- <init>();
+  <init>();
 }
 
 ######## END mainDexClasses.rules ########
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 81c502bd..452afa4 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -1449,22 +1449,65 @@
     }
   }
 
-  template("process_resources") {
-    _process_resources_target_name = target_name
+  # This template is used to parse a set of resource directories and
+  # create the R.txt, .srcjar and .resources.zip for it.
+  #
+  # Input variables:
+  #   deps: Specifies the input dependencies for this target.
+  #
+  #   build_config: Path to the .build_config file corresponding to the target.
+  #
+  #   resource_dirs:
+  #     List of directories containing Android resources, layout should be
+  #     similar to what aapt -S <dir> expects.
+  #
+  #   generated_resource_dirs: (optional)
+  #     List of directories containing generated resources.
+  #
+  #   generated_resource_files: (optional)
+  #     If generated_resources_dirs is not empty, must list all the files
+  #     within these directories (the directory must appear at the start of
+  #     the file path).
+  #
+  #   custom_package: (optional)
+  #     Package name for the generated R.java source file. Optional if
+  #     android_manifest is not provided.
+  #
+  #   android_manifest: (optional)
+  #     If custom_package is not provided, path to an AndroidManifest.xml file
+  #     that is only used to extract a package name out of it.
+  #
+  #   r_text_in_path: (optional)
+  #     Path to an input R.txt file to use to generate the R.java file.
+  #     The default is to use 'aapt' to generate the file from the content
+  #     of the resource directories.
+  #
+  #   alternative_android_sdk_jar: Alternative android.jar to use.
+  #     TODO(digit): Not sure this is needed here.
+  #
+  #   shared_resources: (optional)
+  #     If true, generate an R.java file that uses non-final resource ID
+  #     variables and an onResourcesLoaded() method.
+  #
+  #   v14_skip: (optional)
+  #     If true, skip generation of v14 compatible resources.
+  #     (see generate_v14_compatible_resources.py for details).
+  #
+  # Output variables:
+  #   zip_path: (optional)
+  #     Path to a .resources.zip that will simply contain all the
+  #     input resources, collected in a single archive.
+  #
+  #   r_text_out_path: (optional): Path for the generated R.txt file.
+  #
+  #   srcjar_path: (optional) Path to a generated .srcjar containing the
+  #                           generated R.java source file.
+  #
+  template("prepare_resources") {
     if (defined(invoker.srcjar_path)) {
       _srcjar_path = invoker.srcjar_path
     }
-    if (defined(invoker.output)) {
-      _packaged_resources_path = invoker.output
-    }
-    if (defined(invoker.post_process_script)) {
-      _process_resources_target_name = "${target_name}__intermediate"
-      _packaged_resources_path =
-          get_path_info(_packaged_resources_path, "dir") + "/" +
-          get_path_info(_packaged_resources_path, "name") + ".intermediate.ap_"
-      _srcjar_path = "${_srcjar_path}.intermediate.srcjar"
-    }
-    action(_process_resources_target_name) {
+    action(target_name) {
       set_sources_assignment_filter([])
       forward_variables_from(invoker,
                              [
@@ -1472,9 +1515,9 @@
                                "testonly",
                                "visibility",
                              ])
-      script = "//build/android/gyp/process_resources.py"
+      script = "//build/android/gyp/prepare_resources.py"
 
-      depfile = "$target_gen_dir/${invoker.target_name}_1.d"
+      depfile = "$target_gen_dir/${invoker.target_name}.d"
       outputs = []
       _all_resource_dirs = []
       sources = []
@@ -1507,7 +1550,6 @@
       }
 
       inputs = [
-        android_default_aapt_path,
         invoker.build_config,
         _android_aapt_path,
         _android_sdk_jar,
@@ -1541,44 +1583,6 @@
         args += [ "--resource-dirs=$_rebased_all_resource_dirs" ]
       }
 
-      if (defined(invoker.shared_resources_whitelist)) {
-        inputs += [ invoker.shared_resources_whitelist ]
-        args += [
-          "--shared-resources-whitelist",
-          rebase_path(invoker.shared_resources_whitelist, root_build_dir),
-        ]
-      }
-
-      if (defined(invoker.no_xml_namespaces) && invoker.no_xml_namespaces) {
-        args += [ "--no-xml-namespaces" ]
-      }
-
-      if (defined(invoker.version_code)) {
-        args += [
-          "--version-code",
-          invoker.version_code,
-        ]
-      }
-      if (defined(invoker.version_name)) {
-        args += [
-          "--version-name",
-          invoker.version_name,
-        ]
-      }
-      if (defined(_packaged_resources_path)) {
-        outputs += [ _packaged_resources_path ]
-        args += [
-          "--apk-path",
-          rebase_path(_packaged_resources_path, root_build_dir),
-        ]
-      }
-
-      # Useful to have android:debuggable in the manifest even for Release
-      # builds. Just omit it for officai
-      if (debuggable_apks) {
-        args += [ "--debuggable" ]
-      }
-
       if (defined(invoker.zip_path)) {
         outputs += [ invoker.zip_path ]
         args += [
@@ -1612,9 +1616,203 @@
         ]
       }
 
-      if (!defined(invoker.generate_constant_ids) ||
-          !invoker.generate_constant_ids) {
-        args += [ "--non-constant-id" ]
+      if (defined(invoker.custom_package)) {
+        args += [
+          "--custom-package",
+          invoker.custom_package,
+        ]
+      }
+
+      if (defined(invoker.shared_resources) && invoker.shared_resources) {
+        args += [ "--shared-resources" ]
+      }
+
+      if (defined(invoker.v14_skip) && invoker.v14_skip) {
+        args += [ "--v14-skip" ]
+      }
+    }
+  }
+
+  # A template that is used to compile all resources needed by a binary
+  # (e.g. an android_apk or a junit_binary) into an intermediate .ar_
+  # archive. It can also generate an associated .srcjar that contains the
+  # final R.java sources for all resource packages the binary depends on.
+  #
+  # Input variables:
+  #   deps: Specifies the input dependencies for this target.
+  #
+  #   build_config: Path to the .build_config file corresponding to the target.
+  #
+  #   android_manifest: Path to root manifest for the binary.
+  #
+  #   version_code: (optional)
+  #
+  #   version_name: (optional)
+  #
+  #   alternative_android_sdk_jar: Alternative system android.jar to use.
+  #
+  #   shared_resources: (optional)
+  #     If true, make all variables in each generated R.java file non-final,
+  #     and provide an onResourcesLoaded() method that can be used to reset
+  #     their package index at load time. Useful when the APK corresponds to
+  #     a library that is loaded at runtime, like system_webview_apk or
+  #     monochrome_apk.
+  #
+  #   shared_resources_whitelist: (optional)
+  #     Path to an R.txt file. If provided, acts similar to shared_resources
+  #     except that it restricts the list of non-final resource variables
+  #     to the list from the input R.txt file. Overrides shared_resources
+  #     when both are specified.
+  #
+  #   support_zh_hk: (optional)
+  #     If true, support zh-HK in Chrome on Android by using the resources
+  #     from zh-TW. See https://crbug.com/780847.
+  #
+  #   aapt_locale_whitelist: (optional)
+  #     Restrict compiled locale-dependent resources to a specific whitelist.
+  #     NOTE: This is a list of Chromium locale names, not Android ones.
+  #
+  #   exclude_xxxhdpi: (optional)
+  #
+  #   xxxhdpi_whitelist: (optional)
+  #
+  #   no_xml_namespaces: (optional)
+  #
+  #   png_to_webp: (optional)
+  #     If true, convert all PNG resources (except 9-patch files) to WebP.
+  #
+  #   post_process_script: (optional)
+  #
+  #
+  # Output variables:
+  #   output:  Path to a zip file containing the compiled resources.
+  #
+  #   r_text_out_path: (optional):
+  #       Path for the corresponding generated R.txt file.
+  #
+  #   srcjar_path: (optional)
+  #       Path to a generated .srcjar containing the generated R.java sources
+  #       for all dependent resource libraries.
+  #
+  #   proguard_file: (optional)
+  #       Path to proguard configuration file for this apk target.
+  #
+  #   proguard_file_main_dex: (optional)
+  #
+  #
+  template("compile_resources") {
+    _compile_resources_target_name = target_name
+    _compiled_resources_path = invoker.output
+
+    if (defined(invoker.srcjar_path)) {
+      _srcjar_path = invoker.srcjar_path
+    }
+    if (defined(invoker.post_process_script)) {
+      _compile_resources_target_name = "${target_name}__intermediate"
+      _compiled_resources_path =
+          get_path_info(_compiled_resources_path, "dir") + "/" +
+          get_path_info(_compiled_resources_path, "name") + ".intermediate.ap_"
+      _srcjar_path = "${_srcjar_path}.intermediate.srcjar"
+    }
+
+    action(_compile_resources_target_name) {
+      set_sources_assignment_filter([])
+      forward_variables_from(invoker,
+                             [
+                               "deps",
+                               "testonly",
+                               "visibility",
+                             ])
+      script = "//build/android/gyp/compile_resources.py"
+
+      depfile = "$target_gen_dir/${invoker.target_name}_1.d"
+      outputs = []
+
+      _android_aapt_path = android_default_aapt_path
+
+      _android_sdk_jar = android_sdk_jar
+      if (defined(invoker.alternative_android_sdk_jar)) {
+        _android_sdk_jar = invoker.alternative_android_sdk_jar
+      }
+
+      inputs = [
+        invoker.build_config,
+        _android_aapt_path,
+        _android_sdk_jar,
+      ]
+
+      _rebased_build_config = rebase_path(invoker.build_config, root_build_dir)
+
+      args = [
+        "--depfile",
+        rebase_path(depfile, root_build_dir),
+        "--android-sdk-jar",
+        rebase_path(_android_sdk_jar, root_build_dir),
+        "--aapt-path",
+        rebase_path(_android_aapt_path, root_build_dir),
+        "--dependencies-res-zips=@FileArg($_rebased_build_config:resources:dependency_zips)",
+        "--extra-res-packages=@FileArg($_rebased_build_config:resources:extra_package_names)",
+        "--extra-r-text-files=@FileArg($_rebased_build_config:resources:extra_r_text_files)",
+      ]
+
+      inputs += [ invoker.android_manifest ]
+      args += [
+        "--android-manifest",
+        rebase_path(invoker.android_manifest, root_build_dir),
+      ]
+
+      if (defined(invoker.shared_resources_whitelist)) {
+        inputs += [ invoker.shared_resources_whitelist ]
+        args += [
+          "--shared-resources-whitelist",
+          rebase_path(invoker.shared_resources_whitelist, root_build_dir),
+        ]
+      }
+
+      if (defined(invoker.no_xml_namespaces) && invoker.no_xml_namespaces) {
+        args += [ "--no-xml-namespaces" ]
+      }
+
+      if (defined(invoker.version_code)) {
+        args += [
+          "--version-code",
+          invoker.version_code,
+        ]
+      }
+      if (defined(invoker.version_name)) {
+        args += [
+          "--version-name",
+          invoker.version_name,
+        ]
+      }
+      if (defined(_compiled_resources_path)) {
+        outputs += [ _compiled_resources_path ]
+        args += [
+          "--apk-path",
+          rebase_path(_compiled_resources_path, root_build_dir),
+        ]
+      }
+
+      # Useful to have android:debuggable in the manifest even for Release
+      # builds. Just omit it for officai
+      if (debuggable_apks) {
+        args += [ "--debuggable" ]
+      }
+
+      if (defined(invoker.r_text_out_path)) {
+        outputs += [ invoker.r_text_out_path ]
+        args += [
+          "--r-text-out",
+          rebase_path(invoker.r_text_out_path, root_build_dir),
+        ]
+      }
+
+      if (defined(_srcjar_path)) {
+        outputs += [ _srcjar_path ]
+        args += [
+          "--srcjar-out",
+          rebase_path(_srcjar_path, root_build_dir),
+        ]
       }
 
       if (defined(invoker.custom_package)) {
@@ -1624,18 +1822,10 @@
         ]
       }
 
-      if (defined(invoker.v14_skip) && invoker.v14_skip) {
-        args += [ "--v14-skip" ]
-      }
-
       if (defined(invoker.shared_resources) && invoker.shared_resources) {
         args += [ "--shared-resources" ]
       }
 
-      if (defined(invoker.app_as_shared_lib) && invoker.app_as_shared_lib) {
-        args += [ "--app-as-shared-lib" ]
-      }
-
       if (defined(invoker.proguard_file)) {
         outputs += [ invoker.proguard_file ]
         args += [
@@ -1690,7 +1880,7 @@
           "--depfile",
           rebase_path(depfile, root_build_dir),
           "--apk-path",
-          rebase_path(_packaged_resources_path, root_build_dir),
+          rebase_path(_compiled_resources_path, root_build_dir),
           "--output",
           rebase_path(invoker.output, root_build_dir),
           "--srcjar-in",
@@ -1708,14 +1898,14 @@
         }
         inputs = [
           _srcjar_path,
-          _packaged_resources_path,
+          _compiled_resources_path,
         ]
         outputs = [
           invoker.output,
           invoker.srcjar_path,
         ]
         public_deps = [
-          ":${_process_resources_target_name}",
+          ":${_compile_resources_target_name}",
         ]
       }
     }
@@ -1764,14 +1954,14 @@
         invoker.output_apk_path,
       ]
 
-      _rebased_packaged_resources_path =
+      _rebased_compiled_resources_path =
           rebase_path(invoker.packaged_resources_path, root_build_dir)
       _rebased_packaged_apk_path =
           rebase_path(invoker.output_apk_path, root_build_dir)
       args = [
         "--depfile",
         rebase_path(depfile, root_build_dir),
-        "--resource-apk=$_rebased_packaged_resources_path",
+        "--resource-apk=$_rebased_compiled_resources_path",
         "--output-apk=$_rebased_packaged_apk_path",
       ]
       if (defined(invoker.assets_build_config)) {
@@ -1936,27 +2126,23 @@
           invoker.native_libs_even_when_incremental
     }
 
-    _incremental_packaged_resources_path = "${_base_path}_incremental.ap_"
+    _incremental_compiled_resources_path = "${_base_path}_incremental.ap_"
     _packaged_apk_path = "${_base_path}_unsigned.apk"
     _incremental_packaged_apk_path = "${_base_path}_incremental_unsigned.apk"
     _shared_resources =
         defined(invoker.shared_resources) && invoker.shared_resources
     assert(_shared_resources || true)  # Mark as used.
-    _app_as_shared_lib =
-        defined(invoker.app_as_shared_lib) && invoker.app_as_shared_lib
-    assert(_app_as_shared_lib || true)  # Mark as used.
-    assert(!(_shared_resources && _app_as_shared_lib))
 
     _keystore_path = invoker.keystore_path
     _keystore_name = invoker.keystore_name
     _keystore_password = invoker.keystore_password
 
-    _incremental_package_resources_target_name =
-        "${target_name}_incremental__package_resources"
+    _incremental_compile_resources_target_name =
+        "${target_name}_incremental__compile_resources"
     _incremental_android_manifest =
-        get_label_info(_incremental_package_resources_target_name,
+        get_label_info(_incremental_compile_resources_target_name,
                        "target_gen_dir") + "/AndroidManifest.xml"
-    action(_incremental_package_resources_target_name) {
+    action(_incremental_compile_resources_target_name) {
       deps = _incremental_deps
       script =
           "//build/android/incremental_install/generate_android_manifest.py"
@@ -1970,7 +2156,7 @@
         # Output the non-compiled manifest for easy debugging (as opposed to
         # generating to a temp file).
         _incremental_android_manifest,
-        _incremental_packaged_resources_path,
+        _incremental_compiled_resources_path,
       ]
 
       _android_sdk_jar = android_sdk_jar
@@ -1985,7 +2171,7 @@
         "--in-apk",
         rebase_path(invoker.packaged_resources_path, root_build_dir),
         "--out-apk",
-        rebase_path(_incremental_packaged_resources_path, root_build_dir),
+        rebase_path(_incremental_compiled_resources_path, root_build_dir),
         "--aapt-path",
         rebase_path(android_default_aapt_path, root_build_dir),
         "--android-sdk-jar",
@@ -2036,7 +2222,7 @@
       }
       _dex_target = "//build/android/incremental_install:bootstrap_java__dex"
       deps = _incremental_deps + [
-               ":${_incremental_package_resources_target_name}",
+               ":${_incremental_compile_resources_target_name}",
                _dex_target,
              ]
 
@@ -2055,7 +2241,7 @@
       }
 
       output_apk_path = _incremental_packaged_apk_path
-      packaged_resources_path = _incremental_packaged_resources_path
+      packaged_resources_path = _incremental_compiled_resources_path
     }
 
     finalize_apk(target_name) {
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 6db38cf..154a985 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -723,8 +723,6 @@
   #     false. (see build/android/gyp/generate_v14_compatible_resources.py)
   #   shared_resources: If true make a resource package that can be loaded by a
   #     different application at runtime to access the package's resources.
-  #   app_as_shared_lib: If true make a resource package that can be loaded as
-  #     both shared_resources and normal application.
   #   r_text_file: (optional) path to pre-generated R.txt to be used when
   #     generating R.java instead of resource-based aapt-generated one.
   #   create_srcjar: If false, does not create an R.java file. Needed only for
@@ -792,17 +790,15 @@
       }
     }
 
-    process_resources(target_name) {
+    prepare_resources(target_name) {
       forward_variables_from(invoker,
                              [
-                               "app_as_shared_lib",
                                "android_manifest",
                                "custom_package",
                                "deps",
                                "generated_resource_dirs",
                                "generated_resource_files",
                                "resource_dirs",
-                               "shared_resources",
                                "v14_skip",
                              ])
       if (!defined(deps)) {
@@ -1151,8 +1147,8 @@
       _deps += invoker.deps
     }
 
-    _process_resources_target = "${target_name}__process_resources"
-    process_resources(_process_resources_target) {
+    _prepare_resources_target = "${target_name}__prepare_resources"
+    prepare_resources(_prepare_resources_target) {
       deps = _deps + [ ":$_build_config_target_name" ]
       build_config = _build_config
       srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
@@ -1182,7 +1178,7 @@
         srcjar_deps = []
       }
       srcjar_deps += [
-        ":$_process_resources_target",
+        ":$_prepare_resources_target",
 
         # This dep is required for any targets that depend on //base:base_java.
         "//base:base_build_config_gen",
@@ -2014,12 +2010,11 @@
           "$_base_path.resources.main-dex-proguard.txt"
     }
     _generated_proguard_config = "$_base_path.resources.proguard.txt"
-    _process_resources_target = "${_template_name}__process_resources"
-    process_resources(_process_resources_target) {
+    _compile_resources_target = "${_template_name}__compile_resources"
+    compile_resources(_compile_resources_target) {
       forward_variables_from(invoker,
                              [
                                "alternative_android_sdk_jar",
-                               "app_as_shared_lib",
                                "shared_resources",
                                "support_zh_hk",
                                "aapt_locale_whitelist",
@@ -2036,7 +2031,6 @@
       }
       srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
       r_text_out_path = "${target_gen_dir}/${target_name}_R.txt"
-      generate_constant_ids = true
       proguard_file = _generated_proguard_config
       if (_enable_multidex) {
         proguard_file_main_dex = _generated_proguard_main_dex_config
@@ -2056,13 +2050,13 @@
             get_label_info(invoker.shared_resources_whitelist_target, "name")
         shared_resources_whitelist =
             "${_whitelist_gen_dir}/${_whitelist_target_name}" +
-            "__process_resources_R.txt"
+            "__compile_resources_R.txt"
         deps += [
-          "${invoker.shared_resources_whitelist_target}__process_resources",
+          "${invoker.shared_resources_whitelist_target}__compile_resources",
         ]
       }
     }
-    _srcjar_deps += [ ":$_process_resources_target" ]
+    _srcjar_deps += [ ":$_compile_resources_target" ]
 
     if (_native_libs_deps != []) {
       _enable_chromium_linker_tests = false
@@ -2240,7 +2234,7 @@
                                ])
         deps = _deps + [
                  ":$_build_config_target",
-                 ":$_process_resources_target",
+                 ":$_compile_resources_target",
                  ":$_java_target",
                ]
         inputs = [
@@ -2298,7 +2292,7 @@
 
       if (_enable_multidex) {
         extra_main_dex_proguard_config = _generated_proguard_main_dex_config
-        deps += [ ":$_process_resources_target" ]
+        deps += [ ":$_compile_resources_target" ]
       }
 
       # All deps are already included in _dex_sources when proguard is used.
@@ -2426,7 +2420,7 @@
       incremental_deps = _deps + [
                            ":$_merge_manifest_target",
                            ":$_build_config_target",
-                           ":$_process_resources_target",
+                           ":$_compile_resources_target",
                          ]
 
       # This target generates the input file _all_resources_zip_path.
@@ -2434,7 +2428,7 @@
                ":$_merge_manifest_target",
                ":$_build_config_target",
                ":$_final_dex_target_name",
-               ":$_process_resources_target",
+               ":$_compile_resources_target",
              ]
 
       if (_native_libs_deps != [] ||
diff --git a/build/util/java_action.gni b/build/util/java_action.gni
index d9ca472..646d5a4 100644
--- a/build/util/java_action.gni
+++ b/build/util/java_action.gni
@@ -46,6 +46,7 @@
                              "deps",
                              "outputs",
                              "sources",
+                             "testonly",
                              "visibility",
                            ])
   }
@@ -95,6 +96,7 @@
                              "deps",
                              "outputs",
                              "sources",
+                             "testonly",
                              "visibility",
                            ])
   }
diff --git a/cc/ipc/cc_serialization_perftest.cc b/cc/ipc/cc_serialization_perftest.cc
index 19baf09..7dc52dcf 100644
--- a/cc/ipc/cc_serialization_perftest.cc
+++ b/cc/ipc/cc_serialization_perftest.cc
@@ -14,7 +14,7 @@
 #include "gpu/ipc/common/mailbox_struct_traits.h"
 #include "gpu/ipc/common/sync_token_struct_traits.h"
 #include "ipc/ipc_message.h"
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "mojo/public/cpp/bindings/message.h"
 #include "services/viz/public/cpp/compositing/compositor_frame_metadata_struct_traits.h"
 #include "services/viz/public/cpp/compositing/compositor_frame_struct_traits.h"
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 082a926..8c4d640 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1842,7 +1842,6 @@
   RenderFrameMetadata metadata;
   metadata.root_scroll_offset =
       gfx::ScrollOffsetToVector2dF(active_tree_->TotalScrollOffset());
-  metadata.root_background_color = active_tree_->background_color();
   return metadata;
 }
 
diff --git a/cc/trees/render_frame_metadata.cc b/cc/trees/render_frame_metadata.cc
index 8d98106..fd3a1b9 100644
--- a/cc/trees/render_frame_metadata.cc
+++ b/cc/trees/render_frame_metadata.cc
@@ -15,11 +15,11 @@
 
 RenderFrameMetadata::~RenderFrameMetadata() {}
 
-// static
 bool RenderFrameMetadata::HasAlwaysUpdateMetadataChanged(
     const RenderFrameMetadata& rfm1,
     const RenderFrameMetadata& rfm2) {
-  return rfm1.root_background_color != rfm2.root_background_color;
+  // TODO(jonross): as low frequency fields are added, update this method.
+  return false;
 }
 
 RenderFrameMetadata& RenderFrameMetadata::operator=(
@@ -29,8 +29,7 @@
     RenderFrameMetadata&& other) = default;
 
 bool RenderFrameMetadata::operator==(const RenderFrameMetadata& other) {
-  return root_scroll_offset == other.root_scroll_offset &&
-         root_background_color == other.root_background_color;
+  return root_scroll_offset == other.root_scroll_offset;
 }
 
 bool RenderFrameMetadata::operator!=(const RenderFrameMetadata& other) {
diff --git a/cc/trees/render_frame_metadata.h b/cc/trees/render_frame_metadata.h
index 78f8744..a733fe6d 100644
--- a/cc/trees/render_frame_metadata.h
+++ b/cc/trees/render_frame_metadata.h
@@ -7,7 +7,6 @@
 
 #include "base/optional.h"
 #include "cc/cc_export.h"
-#include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 
 namespace cc {
@@ -30,11 +29,6 @@
   bool operator==(const RenderFrameMetadata& other);
   bool operator!=(const RenderFrameMetadata& other);
 
-  // The background color of a CompositorFrame. It can be used for filling the
-  // content area if the primary surface is unavailable and fallback is not
-  // specified.
-  SkColor root_background_color;
-
   // Scroll offset of the root layer. This optional parameter is only valid
   // during tests.
   base::Optional<gfx::Vector2dF> root_scroll_offset;
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index 3484bc2..4ab1fa9b 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -455,7 +455,7 @@
       ]
     }
 
-    if (is_clang && is_official_build && !use_lld) {
+    if (is_clang && is_official_build) {
       orderfile = "build/chrome.$target_cpu.orderfile"
       rebased_orderfile = rebase_path(orderfile, root_build_dir)
       inputs = [
@@ -517,7 +517,7 @@
         "/DELAYLOAD:wininet.dll",
       ]
 
-      if (is_clang && is_official_build && !use_lld) {
+      if (is_clang && is_official_build) {
         orderfile = "build/chrome_child.$target_cpu.orderfile"
         rebased_orderfile = rebase_path(orderfile, root_build_dir)
         inputs = [
diff --git a/chrome/VERSION b/chrome/VERSION
index 5e4cac8d..a4261225 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=67
 MINOR=0
-BUILD=3376
+BUILD=3377
 PATCH=0
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 8f85051..a63ae884 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -11,7 +11,7 @@
 
 declare_args() {
   # Enables ProGuard obfuscation of Chromium packages.
-  enable_proguard_obfuscation = false
+  enable_proguard_obfuscation = true
 
   # Enable multidex in release builds.
   multidex_in_release = false
@@ -112,7 +112,7 @@
     }
 
     alternative_android_sdk_jar = webview_framework_jar
-    app_as_shared_lib = true
+    shared_resources = true
     use_chromium_linker = false
     requires_sdk_api_level_23 = true
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java
index 19f08a17..1c1464cd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java
@@ -54,7 +54,8 @@
 /**
  * Base class for layouts that show one or more stacks of tabs.
  */
-public abstract class StackLayoutBase extends Layout implements Animatable<StackLayout.Property> {
+public abstract class StackLayoutBase
+        extends Layout implements Animatable<StackLayoutBase.Property> {
     public enum Property {
         INNER_MARGIN_PERCENT,
         STACK_SNAP,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
index cf702d0a..1728e45 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
@@ -795,13 +795,21 @@
 
     @VisibleForTesting
     void onPlay(int actionSource) {
-        if (!mMediaNotificationInfo.isPaused) return;
+        // MediaSessionCompat calls this sometimes when `mMediaNotificationInfo`
+        // is no longer available. It's unclear if it is a Support Library issue
+        // or something that isn't properly cleaned up but given that the
+        // crashes are rare and the fix is simple, null check was enough.
+        if (mMediaNotificationInfo == null || !mMediaNotificationInfo.isPaused) return;
         mMediaNotificationInfo.listener.onPlay(actionSource);
     }
 
     @VisibleForTesting
     void onPause(int actionSource) {
-        if (mMediaNotificationInfo.isPaused) return;
+        // MediaSessionCompat calls this sometimes when `mMediaNotificationInfo`
+        // is no longer available. It's unclear if it is a Support Library issue
+        // or something that isn't properly cleaned up but given that the
+        // crashes are rare and the fix is simple, null check was enough.
+        if (mMediaNotificationInfo == null || mMediaNotificationInfo.isPaused) return;
         mMediaNotificationInfo.listener.onPause(actionSource);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
index d9d5afd..e553ce8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
@@ -339,7 +339,7 @@
         // This flag ensures the broadcast is delivered with foreground priority. It also means the
         // receiver gets a shorter timeout interval before it may be killed, but this is ok because
         // we schedule a job to handle the intent in NotificationService.Receiver on N+.
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
         }
 
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 5dec4a3..a47d0be 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-67.0.3375.0_rc-r1.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-67.0.3376.0_rc-r1.afdo.bz2
\ No newline at end of file
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java
index 625d4ae..9a0c1db 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java
@@ -18,6 +18,7 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.FlakyTest;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -314,6 +315,7 @@
     @Test
     @LargeTest
     @Feature({"Sync"})
+    @FlakyTest(message = "crbug.com/823484")
     public void testUploadMovedBookmark() throws Exception {
         // Add the entity to test moving.
         BookmarkId bookmarkId = addClientBookmark(TITLE, URL);
diff --git a/chrome/browser/banners/app_banner_manager.cc b/chrome/browser/banners/app_banner_manager.cc
index afd5661..230b2ad 100644
--- a/chrome/browser/banners/app_banner_manager.cc
+++ b/chrome/browser/banners/app_banner_manager.cc
@@ -191,6 +191,10 @@
       mojo::MakeRequest(&installation_service));
   DCHECK(installation_service);
   installation_service->OnInstall();
+
+  // We've triggered an installation, so reset bindings to ensure that any
+  // existing beforeinstallprompt events cannot trigger add to home screen.
+  ResetBindings();
 }
 
 void AppBannerManager::SendBannerAccepted() {
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
index 40a9d2d..cb31cce7 100644
--- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
@@ -89,14 +89,12 @@
   if (accessibility_manager->profile() != profile)
     return arc::mojom::AccessibilityFilterType::OFF;
 
-  if (accessibility_manager->IsSelectToSpeakEnabled() ||
+  if (accessibility_manager->IsSpokenFeedbackEnabled() ||
+      accessibility_manager->IsSelectToSpeakEnabled() ||
       accessibility_manager->IsSwitchAccessEnabled()) {
     return arc::mojom::AccessibilityFilterType::ALL;
   }
 
-  if (accessibility_manager->IsSpokenFeedbackEnabled())
-    return arc::mojom::AccessibilityFilterType::WHITELISTED_PACKAGE_NAME;
-
   if (accessibility_manager->IsFocusHighlightEnabled())
     return arc::mojom::AccessibilityFilterType::FOCUS;
 
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc
index eff6be0..2168b71 100644
--- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc
@@ -95,7 +95,7 @@
 
   chromeos::AccessibilityManager::Get()->EnableSpokenFeedback(
       true /* enable */, ash::A11Y_NOTIFICATION_NONE);
-  EXPECT_EQ(mojom::AccessibilityFilterType::WHITELISTED_PACKAGE_NAME,
+  EXPECT_EQ(mojom::AccessibilityFilterType::ALL,
             fake_accessibility_helper_instance_->filter_type());
 
   // Touch exploration pass through of test_window_1 (current active window)
diff --git a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc
index 189991d..5043e11 100644
--- a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc
+++ b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc
@@ -8,8 +8,6 @@
 
 #include <utility>
 
-#include "ash/shell.h"
-#include "ash/wallpaper/wallpaper_controller.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "base/task_scheduler/post_task.h"
@@ -21,7 +19,6 @@
 #include "components/user_manager/user_manager.h"
 #include "components/wallpaper/wallpaper_files_id.h"
 #include "components/wallpaper/wallpaper_info.h"
-#include "components/wallpaper/wallpaper_resizer.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/geometry/size.h"
@@ -36,40 +33,12 @@
 
 constexpr char kAndroidWallpaperFilename[] = "android.jpg";
 
-// The structure must not go out from a method invoked on BrowserThread::UI
-// because the primary account referenced by the class will be released.
-struct PrimaryAccount {
-  const AccountId& id;
-  const bool is_active;
-  const bool is_ephemeral;
-  const user_manager::UserType type;
-};
-
-PrimaryAccount GetPrimaryAccount() {
-  UserManager* const user_manager = UserManager::Get();
-  const user_manager::User* const primary_user = user_manager->GetPrimaryUser();
-  DCHECK(primary_user);
-  const AccountId& account_id = primary_user->GetAccountId();
-  const bool is_ephemeral =
-      user_manager->IsUserNonCryptohomeDataEphemeral(account_id);
-  const user_manager::UserType type = primary_user->GetType();
-  return {account_id,
-          account_id == user_manager->GetActiveUser()->GetAccountId(),
-          is_ephemeral, type};
-}
-
-std::vector<uint8_t> EncodeImagePng(const gfx::ImageSkia image) {
+std::vector<uint8_t> EncodeImagePng(const gfx::ImageSkia& image) {
   std::vector<uint8_t> result;
   gfx::PNGCodec::FastEncodeBGRASkBitmap(*image.bitmap(), true, &result);
   return result;
 }
 
-ash::WallpaperController* GetWallpaperController() {
-  if (!ash::Shell::HasInstance())
-    return nullptr;
-  return ash::Shell::Get()->wallpaper_controller();
-}
-
 // Singleton factory for ArcWallpaperService.
 class ArcWallpaperServiceFactory
     : public internal::ArcBrowserContextKeyedServiceFactoryBase<
@@ -126,48 +95,7 @@
     gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(immutable_bitmap);
     image.MakeThreadSafe();
 
-    WallpaperIdPair pair;
-    pair.image_id = wallpaper::WallpaperResizer::GetImageId(image);
-    pair.android_id = android_id_;
-    DCHECK_NE(pair.image_id, 0u)
-        << "image_id should not be 0 as we succeeded to decode image here.";
-
-    const PrimaryAccount& account = GetPrimaryAccount();
-    wallpaper::WallpaperFilesId wallpaper_files_id =
-        WallpaperControllerClient::Get()->GetFilesId(account.id);
-    ash::WallpaperController* wallpaper_controller = GetWallpaperController();
-    // Decode request is only created when GetWallpaperController() returns
-    // non-null, so we can get the pointer here.
-    DCHECK(wallpaper_controller);
-
-    // TODO(crbug.com/776464): Replace |CanSetUserWallpaper| with mojo callback.
-    if (!wallpaper_controller->CanSetUserWallpaper(account.id,
-                                                   account.is_ephemeral)) {
-      // When kiosk app is running or policy is enforced, WallpaperController
-      // doesn't process custom wallpaper requests.
-      service_->NotifyWallpaperChangedAndReset(android_id_);
-    } else {
-      bool show_wallpaper = account.is_active;
-      // When |show_wallpaper| is false, WallpaperController still saves custom
-      // wallpaper for this user, but the wallpaper won't be shown right away.
-      // |SetArcWallpaper| calls |OnWallpaperDataChanged| synchronously, so the
-      // id pair should be added to the queue first.
-      if (show_wallpaper)
-        service_->id_pairs_.push_back(pair);
-      else
-        service_->NotifyWallpaperChangedAndReset(android_id_);
-      // TODO(crbug.com/618922): Allow specifying layout.
-      wallpaper_controller->SetArcWallpaper(
-          account.id, account.type, wallpaper_files_id.id(),
-          kAndroidWallpaperFilename, image,
-          wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, account.is_ephemeral,
-          show_wallpaper);
-    }
-
-    // TODO(crbug.com/618922): Register the wallpaper to Chrome OS wallpaper
-    // picker. Currently the new wallpaper does not appear there. The best way
-    // to make this happen seems to do the same things as wallpaper_api.cc and
-    // wallpaper_private_api.cc.
+    service_->OnWallpaperDecoded(image, android_id_);
   }
 
   void OnDecodeImageFailed() override {
@@ -200,34 +128,24 @@
 ArcWallpaperService::ArcWallpaperService(content::BrowserContext* context,
                                          ArcBridgeService* bridge_service)
     : arc_bridge_service_(bridge_service),
-      decode_request_sender_(std::make_unique<DecodeRequestSenderImpl>()) {
+      decode_request_sender_(std::make_unique<DecodeRequestSenderImpl>()),
+      observer_binding_(this),
+      weak_ptr_factory_(this) {
   arc_bridge_service_->wallpaper()->SetHost(this);
   arc_bridge_service_->wallpaper()->AddObserver(this);
 }
 
 ArcWallpaperService::~ArcWallpaperService() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  ash::WallpaperController* wc = GetWallpaperController();
-  if (wc)
-    wc->RemoveObserver(this);
-
   arc_bridge_service_->wallpaper()->RemoveObserver(this);
   arc_bridge_service_->wallpaper()->SetHost(nullptr);
 }
 
 void ArcWallpaperService::OnConnectionReady() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  ash::WallpaperController* wc = GetWallpaperController();
-  // TODO(mash): Support this functionality without ash::Shell access in Chrome.
-  if (wc)
-    wc->AddObserver(this);
-}
-
-void ArcWallpaperService::OnConnectionClosed() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  ash::WallpaperController* wc = GetWallpaperController();
-  if (wc)
-    wc->RemoveObserver(this);
+  ash::mojom::WallpaperObserverAssociatedPtrInfo ptr_info;
+  observer_binding_.Bind(mojo::MakeRequest(&ptr_info));
+  WallpaperControllerClient::Get()->AddObserver(std::move(ptr_info));
 }
 
 void ArcWallpaperService::SetWallpaper(const std::vector<uint8_t>& data,
@@ -235,10 +153,6 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (wallpaper_id == 0)
     wallpaper_id = -1;
-  if (!GetWallpaperController()) {
-    NotifyWallpaperChangedAndReset(wallpaper_id);
-    return;
-  }
 
   // Previous request will be cancelled at destructor of
   // ImageDecoder::ImageRequest.
@@ -252,37 +166,28 @@
   // Previous request will be cancelled at destructor of
   // ImageDecoder::ImageRequest.
   decode_request_.reset();
-  const PrimaryAccount& account = GetPrimaryAccount();
+  const user_manager::User* const primary_user =
+      UserManager::Get()->GetPrimaryUser();
   WallpaperControllerClient::Get()->SetDefaultWallpaper(
-      account.id, account.is_active /* show_wallpaper */);
+      primary_user->GetAccountId(),
+      primary_user->is_active() /*show_wallpaper=*/);
 }
 
 void ArcWallpaperService::GetWallpaper(GetWallpaperCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  ash::WallpaperController* const wc = GetWallpaperController();
-  DCHECK(wc);
-  gfx::ImageSkia wallpaper = wc->GetWallpaper();
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
-      base::BindOnce(&EncodeImagePng, wallpaper), std::move(callback));
+  WallpaperControllerClient::Get()->GetWallpaperImage(
+      base::BindOnce(&ArcWallpaperService::OnGetWallpaperImageCallback,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void ArcWallpaperService::OnWallpaperDataChanged() {
+void ArcWallpaperService::OnWallpaperChanged(uint32_t image_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  // OnWallpaperDataChanged is invoked from WallpaperController so
-  // we should be able to get the pointer.
-  ash::WallpaperController* const wallpaper_controller =
-      GetWallpaperController();
-  DCHECK(wallpaper_controller);
-  const uint32_t current_image_id =
-      wallpaper_controller->GetWallpaperOriginalImageId();
-
-  bool current_wallppaer_notified = false;
+  bool current_wallpaper_notified = false;
   for (auto it = id_pairs_.begin(); it != id_pairs_.end();) {
     int32_t const android_id = it->android_id;
-    if (it->image_id == current_image_id) {
-      current_wallppaer_notified = true;
+    if (it->image_id == image_id) {
+      current_wallpaper_notified = true;
       it = id_pairs_.erase(it);
       NotifyWallpaperChanged(android_id);
     } else {
@@ -290,10 +195,27 @@
     }
   }
 
-  if (!current_wallppaer_notified)
+  if (!current_wallpaper_notified)
     NotifyWallpaperChanged(-1);
 }
 
+void ArcWallpaperService::OnWallpaperColorsChanged(
+    const std::vector<SkColor>& prominent_colors) {}
+
+void ArcWallpaperService::OnWallpaperDecoded(const gfx::ImageSkia& image,
+                                             int32_t android_id) {
+  const AccountId account_id =
+      UserManager::Get()->GetPrimaryUser()->GetAccountId();
+  const wallpaper::WallpaperFilesId wallpaper_files_id =
+      WallpaperControllerClient::Get()->GetFilesId(account_id);
+
+  WallpaperControllerClient::Get()->SetThirdPartyWallpaper(
+      account_id, wallpaper_files_id, kAndroidWallpaperFilename,
+      wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, image,
+      base::BindOnce(&ArcWallpaperService::OnSetThirdPartyWallpaperCallback,
+                     weak_ptr_factory_.GetWeakPtr(), android_id));
+}
+
 void ArcWallpaperService::NotifyWallpaperChanged(int android_id) {
   mojom::WallpaperInstance* const wallpaper_instance =
       ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->wallpaper(),
@@ -312,4 +234,26 @@
   NotifyWallpaperChanged(-1);
 }
 
+void ArcWallpaperService::OnSetThirdPartyWallpaperCallback(int32_t android_id,
+                                                           bool allowed,
+                                                           uint32_t image_id) {
+  if (allowed)
+    id_pairs_.push_back({image_id, android_id});
+  else
+    NotifyWallpaperChangedAndReset(android_id);
+
+  // TODO(crbug.com/618922): Register the wallpaper to Chrome OS wallpaper
+  // picker. Currently the new wallpaper does not appear there. The best way
+  // to make this happen seems to do the same things as wallpaper_api.cc and
+  // wallpaper_private_api.cc.
+}
+
+void ArcWallpaperService::OnGetWallpaperImageCallback(
+    GetWallpaperCallback callback,
+    const gfx::ImageSkia& image) {
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
+      base::BindOnce(&EncodeImagePng, image), std::move(callback));
+}
+
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.h b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.h
index ebe7b0c..bf0829f 100644
--- a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.h
+++ b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.h
@@ -10,12 +10,14 @@
 #include <memory>
 #include <vector>
 
-#include "ash/wallpaper/wallpaper_controller_observer.h"
+#include "ash/public/interfaces/wallpaper.mojom.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/image_decoder.h"
 #include "components/arc/common/wallpaper.mojom.h"
 #include "components/arc/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
 
 namespace content {
 class BrowserContext;
@@ -27,9 +29,9 @@
 
 // Lives on the UI thread.
 class ArcWallpaperService : public KeyedService,
-                            public ash::WallpaperControllerObserver,
                             public ConnectionObserver<mojom::WallpaperInstance>,
-                            public mojom::WallpaperHost {
+                            public mojom::WallpaperHost,
+                            public ash::mojom::WallpaperObserver {
  public:
   // Returns singleton instance for the given BrowserContext,
   // or nullptr if the browser |context| is not allowed to use ARC.
@@ -42,7 +44,6 @@
 
   // ConnectionObserver<mojom::WallpaperInstance> overrides.
   void OnConnectionReady() override;
-  void OnConnectionClosed() override;
 
   // mojom::WallpaperHost overrides.
   void SetWallpaper(const std::vector<uint8_t>& data,
@@ -50,8 +51,10 @@
   void SetDefaultWallpaper() override;
   void GetWallpaper(GetWallpaperCallback callback) override;
 
-  // WallpaperControllerObserver implementation.
-  void OnWallpaperDataChanged() override;
+  // ash::mojom::WallpaperObserver overrides.
+  void OnWallpaperChanged(uint32_t image_id) override;
+  void OnWallpaperColorsChanged(
+      const std::vector<SkColor>& prominent_colors) override;
 
   class DecodeRequestSender {
    public:
@@ -73,17 +76,37 @@
   class DecodeRequest;
   struct WallpaperIdPair;
 
+  // Initiates a set wallpaper request to //ash.
+  void OnWallpaperDecoded(const gfx::ImageSkia& image, int32_t android_id);
+
   // Notifies wallpaper change if we have wallpaper instance.
   void NotifyWallpaperChanged(int android_id);
+
   // Notifies wallpaper change of |android_id|, then notify wallpaper change of
   // -1 to reset wallpaper cache at Android side.
   void NotifyWallpaperChangedAndReset(int android_id);
 
+  // If the wallpaper is allowed to be shown on screen, stores the |image_id|
+  // in order to track the wallpaper change later, otherwise notify the Android
+  // side immediately that the request is not going through.
+  void OnSetThirdPartyWallpaperCallback(int32_t android_id,
+                                        bool allowed,
+                                        uint32_t image_id);
+
+  // Initiates an encoding image request after getting the wallpaper image.
+  void OnGetWallpaperImageCallback(GetWallpaperCallback callback,
+                                   const gfx::ImageSkia& image);
+
   ArcBridgeService* const arc_bridge_service_;  // Owned by ArcServiceManager.
   std::unique_ptr<DecodeRequest> decode_request_;
   std::vector<WallpaperIdPair> id_pairs_;
   std::unique_ptr<DecodeRequestSender> decode_request_sender_;
 
+  // The binding this instance uses to implement ash::mojom::WallpaperObserver.
+  mojo::AssociatedBinding<ash::mojom::WallpaperObserver> observer_binding_;
+
+  base::WeakPtrFactory<ArcWallpaperService> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(ArcWallpaperService);
 };
 
diff --git a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc
index f78456a..fd481847 100644
--- a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc
+++ b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc
@@ -9,19 +9,13 @@
 #include <utility>
 
 #include "ash/public/cpp/ash_pref_names.h"
-#include "ash/shell.h"
-#include "ash/shell_test_api.h"
 #include "ash/test/ash_test_base.h"
-#include "ash/wallpaper/wallpaper_controller.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/path_service.h"
-#include "base/run_loop.h"
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/image_decoder.h"
 #include "chrome/browser/ui/ash/test_wallpaper_controller.h"
 #include "chrome/browser/ui/ash/wallpaper_controller_client.h"
-#include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
@@ -33,33 +27,11 @@
 #include "components/prefs/testing_pref_service.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "components/user_manager/user_names.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/test/test_service_manager_context.h"
 #include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
 
-// TODO(crbug.com/776464): Remove this after |SetCustomWallpaper| is migrated
-// to |WallpaperController|.
-void InitializeWallpaperPaths() {
-  base::FilePath user_data_path;
-  CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_path));
-  ash::WallpaperController::dir_user_data_path_ = user_data_path;
-
-  base::FilePath chromeos_wallpapers_path;
-  CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS,
-                         &chromeos_wallpapers_path));
-  ash::WallpaperController::dir_chrome_os_wallpapers_path_ =
-      chromeos_wallpapers_path;
-
-  base::FilePath chromeos_custom_wallpapers_path;
-  CHECK(PathService::Get(chrome::DIR_CHROMEOS_CUSTOM_WALLPAPERS,
-                         &chromeos_custom_wallpapers_path));
-  ash::WallpaperController::dir_chrome_os_custom_wallpapers_path_ =
-      chromeos_custom_wallpapers_path;
-}
-
 class SuccessDecodeRequestSender
     : public arc::ArcWallpaperService::DecodeRequestSender {
  public:
@@ -165,23 +137,19 @@
 }
 
 TEST_F(ArcWallpaperServiceTest, SetAndGetWallpaper) {
-  // TODO(crbug.com/776464): This test is supposed to call the mock method, but
-  // currently it's still calling the real method which relies on the paths.
-  InitializeWallpaperPaths();
-
   service_->SetDecodeRequestSenderForTesting(
       std::make_unique<SuccessDecodeRequestSender>());
   std::vector<uint8_t> bytes;
-  service_->SetWallpaper(bytes, 10 /* ID */);
-  content::RunAllTasksUntilIdle();
+  service_->SetWallpaper(bytes, 10 /*wallpaper_id=*/);
+  wallpaper_controller_client_->FlushForTesting();
   ASSERT_EQ(1u, wallpaper_instance_->changed_ids().size());
   EXPECT_EQ(10, wallpaper_instance_->changed_ids()[0]);
 
-  base::RunLoop run_loop;
   service_->GetWallpaper(
       base::BindOnce([](std::vector<uint8_t>* out,
                         const std::vector<uint8_t>& bytes) { *out = bytes; },
                      &bytes));
+  wallpaper_controller_client_->FlushForTesting();
   content::RunAllTasksUntilIdle();
   ASSERT_NE(0u, bytes.size());
 }
@@ -190,8 +158,8 @@
   service_->SetDecodeRequestSenderForTesting(
       std::make_unique<FailureDecodeRequestSender>());
   std::vector<uint8_t> bytes;
-  service_->SetWallpaper(bytes, 10 /* ID */);
-  content::RunAllTasksUntilIdle();
+  service_->SetWallpaper(bytes, 10 /*wallpaper_id=*/);
+  wallpaper_controller_client_->FlushForTesting();
 
   // For failure case, ArcWallpaperService reports that wallpaper is changed to
   // requested wallpaper (ID=10), then reports that the wallpaper is changed
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc
index 727b1332..3591fab 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc
@@ -134,6 +134,37 @@
     return;
   }
 
+  file_system->IsCacheFileMarkedAsMounted(
+      drive_path, base::Bind(&FileManagerPrivateAddMountFunction::
+                                 RunAfterIsCacheFileMarkedAsMounted,
+                             this, drive_path, cache_path));
+}
+
+void FileManagerPrivateAddMountFunction::RunAfterIsCacheFileMarkedAsMounted(
+    const base::FilePath& drive_path,
+    const base::FilePath& cache_path,
+    drive::FileError error,
+    bool is_marked_as_mounted) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (error != drive::FILE_ERROR_OK) {
+    SetError(FileErrorToString(error));
+    SendResponse(false);
+    return;
+  }
+  if (is_marked_as_mounted) {
+    // When the file is already mounted, we call the mount function as usual,
+    // so that it can issue events containing the VolumeInfo, which is
+    // necessary to make the app navigate to the mounted volume.
+    RunAfterMarkCacheFileAsMounted(drive_path.BaseName(), drive::FILE_ERROR_OK,
+                                   cache_path);
+    return;
+  }
+  drive::FileSystemInterface* const file_system =
+      drive::util::GetFileSystemByProfile(GetProfile());
+  if (!file_system) {
+    SendResponse(false);
+    return;
+  }
   file_system->MarkCacheFileAsMounted(
       drive_path,
       base::Bind(
@@ -225,7 +256,7 @@
   EXTENSION_FUNCTION_VALIDATE(params);
 
   const base::FilePath path(params->source_path);
-  bool isMounted = params->is_mounted;
+  bool is_mounted = params->is_mounted;
 
   if (path.empty())
     return false;
@@ -247,13 +278,13 @@
       drive_path,
       base::Bind(
           &FileManagerPrivateMarkCacheAsMountedFunction::RunAfterGetDriveFile,
-          this, drive_path, isMounted));
+          this, drive_path, is_mounted));
   return true;
 }
 
 void FileManagerPrivateMarkCacheAsMountedFunction::RunAfterGetDriveFile(
     const base::FilePath& drive_path,
-    bool isMounted,
+    bool is_mounted,
     drive::FileError error,
     const base::FilePath& cache_path,
     std::unique_ptr<drive::ResourceEntry> entry) {
@@ -272,10 +303,10 @@
     return;
   }
 
-  // TODO(yamaguchi): Check if the current status of the file.
+  // TODO(yamaguchi): Check the current status of the file.
   // Currently calling this method twice will result in error, although it
   // doesn't give bad side effect.
-  if (isMounted) {
+  if (is_mounted) {
     file_system->MarkCacheFileAsMounted(
         drive_path, base::Bind(&FileManagerPrivateMarkCacheAsMountedFunction::
                                    RunAfterMarkCacheFileAsMounted,
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h
index 3114997..18c4d5f 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h
@@ -36,8 +36,15 @@
                             const base::FilePath& cache_path,
                             std::unique_ptr<drive::ResourceEntry> entry);
 
+  // Part of Run(). Called after IsCacheMarkedAsMounted for Drive File System.
+  void RunAfterIsCacheFileMarkedAsMounted(const base::FilePath& display_name,
+                                          const base::FilePath& cache_path,
+                                          drive::FileError error,
+                                          bool is_marked_as_mounted);
+
   // Part of Run(). Called after MarkCacheFielAsMounted for Drive File System.
-  // (or directly called from RunAsync() for other file system).
+  // (or directly called from RunAsync() for other file system, or when the
+  // file is already marked as mounted).
   void RunAfterMarkCacheFileAsMounted(const base::FilePath& display_name,
                                       drive::FileError error,
                                       const base::FilePath& file_path);
@@ -75,7 +82,7 @@
  private:
   // Part of Run(). Called after GetFile for Drive File System.
   void RunAfterGetDriveFile(const base::FilePath& drive_path,
-                            bool isMounted,
+                            bool is_mounted,
                             drive::FileError error,
                             const base::FilePath& cache_path,
                             std::unique_ptr<drive::ResourceEntry> entry);
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc
index 0e2c8ce..328a729 100644
--- a/chrome/browser/client_hints/client_hints_browsertest.cc
+++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -721,6 +721,10 @@
       ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
                               &host_settings);
   EXPECT_EQ(1u, host_settings.size());
+
+  // Clear settings.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
 }
 
 // Ensure that when the JavaScript is blocked, persisted client hints are not
@@ -848,6 +852,10 @@
   EXPECT_EQ(3u, count_client_hints_headers_seen());
   EXPECT_EQ(3u, third_party_request_count_seen());
   EXPECT_EQ(0u, third_party_client_hints_count_seen());
+
+  // Clear settings.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
 }
 
 // Ensure that when the cookies is blocked, client hints are not attached to the
@@ -905,6 +913,10 @@
   EXPECT_EQ(3u, count_client_hints_headers_seen());
   EXPECT_EQ(3u, third_party_request_count_seen());
   EXPECT_EQ(0u, third_party_client_hints_count_seen());
+
+  // Clear settings.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_COOKIES);
 }
 
 // Check the client hints for the given URL in an incognito window.
diff --git a/chrome/browser/devtools/devtools_file_watcher.cc b/chrome/browser/devtools/devtools_file_watcher.cc
index 2195fc7..beb0c8f 100644
--- a/chrome/browser/devtools/devtools_file_watcher.cc
+++ b/chrome/browser/devtools/devtools_file_watcher.cc
@@ -79,6 +79,10 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   auto it = std::find(listeners_.begin(), listeners_.end(), watcher);
   listeners_.erase(it);
+  if (listeners_.empty()) {
+    file_path_times_.clear();
+    pending_paths_.clear();
+  }
 }
 
 void DevToolsFileWatcher::SharedFileWatcher::AddWatch(
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
index 0f19212..9be7c453 100644
--- a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
+++ b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
@@ -829,6 +829,33 @@
   EXPECT_TRUE(catcher.GetNextResult()) << message_;
 }
 
+// Test that a browser action popup can download data URLs. See
+// https://crbug.com/821219
+IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionPopupDownload) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  ASSERT_TRUE(LoadExtension(
+      test_data_dir_.AppendASCII("browser_action/popup_download")));
+  const Extension* extension = GetSingleLoadedExtension();
+  ASSERT_TRUE(extension) << message_;
+
+  content::DownloadTestObserverTerminal downloads_observer(
+      content::BrowserContext::GetDownloadManager(browser()->profile()), 1,
+      content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
+
+  // Simulate a click on the browser action to open the popup.
+  content::WebContents* popup = OpenPopup(0);
+  ASSERT_TRUE(popup);
+  content::ExecuteScriptAsync(popup, "run_tests()");
+
+  // Wait for the download that this should have triggered to finish.
+  downloads_observer.WaitForFinished();
+
+  EXPECT_EQ(1u, downloads_observer.NumDownloadsSeenInState(
+                    download::DownloadItem::COMPLETE));
+  EXPECT_TRUE(GetBrowserActionsBar()->HidePopup());
+}
+
 class NavigatingExtensionPopupBrowserTest : public BrowserActionApiTest {
  public:
   const Extension& popup_extension() { return *popup_extension_; }
diff --git a/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc b/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
index 220421ee..bd67c2e 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
@@ -26,6 +26,21 @@
 
 namespace {
 
+class ScopedScreenOverride {
+ public:
+  ~ScopedScreenOverride() {
+    display::Screen::SetScreenInstance(original_screen_);
+  }
+
+  void SetScreenInstance(display::Screen* instance) {
+    original_screen_ = display::Screen::GetScreen();
+    display::Screen::SetScreenInstance(instance);
+  }
+
+ private:
+  display::Screen* original_screen_ = nullptr;
+};
+
 std::unique_ptr<base::ListValue> RunTabsQueryFunction(
     Browser* browser,
     const Extension* extension,
@@ -58,6 +73,8 @@
 
   display::test::TestScreen test_screen_;
 
+  std::unique_ptr<ScopedScreenOverride> scoped_screen_override_;
+
   DISALLOW_COPY_AND_ASSIGN(TabsApiUnitTest);
 };
 
@@ -71,12 +88,14 @@
   params.type = Browser::TYPE_TABBED;
   params.window = browser_window_.get();
   browser_.reset(new Browser(params));
-  display::Screen::SetScreenInstance(&test_screen_);
+  scoped_screen_override_.reset(new ScopedScreenOverride);
+  scoped_screen_override_->SetScreenInstance(&test_screen_);
 }
 
 void TabsApiUnitTest::TearDown() {
   browser_.reset();
   browser_window_.reset();
+  scoped_screen_override_.reset();
   content::BrowserSideNavigationTearDown();
   ExtensionServiceTestBase::TearDown();
 }
diff --git a/chrome/browser/extensions/chrome_content_verifier_delegate.cc b/chrome/browser/extensions/chrome_content_verifier_delegate.cc
index 114d1b1a..90b4c75 100644
--- a/chrome/browser/extensions/chrome_content_verifier_delegate.cc
+++ b/chrome/browser/extensions/chrome_content_verifier_delegate.cc
@@ -13,6 +13,7 @@
 #include "base/command_line.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/no_destructor.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/syslog_logging.h"
@@ -41,18 +42,26 @@
 #include "chrome/browser/extensions/extension_assets_manager_chromeos.h"
 #endif
 
+namespace extensions {
+
 namespace {
 
+base::Optional<ContentVerifierDelegate::Mode>& GetModeForTesting() {
+  static base::NoDestructor<base::Optional<ContentVerifierDelegate::Mode>>
+      testing_mode;
+  return *testing_mode;
+}
+
 const char kContentVerificationExperimentName[] =
     "ExtensionContentVerification";
 
-
 }  // namespace
 
-namespace extensions {
-
 // static
 ContentVerifierDelegate::Mode ChromeContentVerifierDelegate::GetDefaultMode() {
+  if (GetModeForTesting())
+    return *GetModeForTesting();
+
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
 
   Mode experiment_value;
@@ -108,6 +117,14 @@
   return std::max(experiment_value, cmdline_value);
 }
 
+// static
+void ChromeContentVerifierDelegate::SetDefaultModeForTesting(
+    base::Optional<Mode> mode) {
+  DCHECK(!GetModeForTesting() || !mode)
+      << "Verification mode already overridden, unset it first.";
+  GetModeForTesting() = mode;
+}
+
 ChromeContentVerifierDelegate::ChromeContentVerifierDelegate(
     content::BrowserContext* context)
     : context_(context),
diff --git a/chrome/browser/extensions/chrome_content_verifier_delegate.h b/chrome/browser/extensions/chrome_content_verifier_delegate.h
index 1f489fd8..9a08eee 100644
--- a/chrome/browser/extensions/chrome_content_verifier_delegate.h
+++ b/chrome/browser/extensions/chrome_content_verifier_delegate.h
@@ -10,8 +10,8 @@
 #include <set>
 #include <string>
 
-#include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "base/optional.h"
 #include "extensions/browser/content_verifier_delegate.h"
 
 namespace content {
@@ -29,6 +29,7 @@
 class ChromeContentVerifierDelegate : public ContentVerifierDelegate {
  public:
   static Mode GetDefaultMode();
+  static void SetDefaultModeForTesting(base::Optional<Mode> mode);
 
   explicit ChromeContentVerifierDelegate(content::BrowserContext* context);
 
diff --git a/chrome/browser/extensions/content_verifier_browsertest.cc b/chrome/browser/extensions/content_verifier_browsertest.cc
index 9cc89a5..ea1fedab 100644
--- a/chrome/browser/extensions/content_verifier_browsertest.cc
+++ b/chrome/browser/extensions/content_verifier_browsertest.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/extensions/extension_management_test_util.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/policy_extension_reinstaller.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
@@ -181,11 +180,18 @@
   ContentVerifierTest() {}
   ~ContentVerifierTest() override {}
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    ExtensionBrowserTest::SetUpCommandLine(command_line);
-    command_line->AppendSwitchASCII(
-        switches::kExtensionContentVerification,
-        switches::kExtensionContentVerificationEnforce);
+  void SetUp() override {
+    // Override content verification mode before ExtensionSystemImpl initializes
+    // ChromeContentVerifierDelegate.
+    ChromeContentVerifierDelegate::SetDefaultModeForTesting(
+        ContentVerifierDelegate::ENFORCE);
+
+    ExtensionBrowserTest::SetUp();
+  }
+
+  void TearDown() override {
+    ExtensionBrowserTest::TearDown();
+    ChromeContentVerifierDelegate::SetDefaultModeForTesting(base::nullopt);
   }
 
   bool ShouldEnableContentVerification() override { return true; }
diff --git a/chrome/browser/extensions/content_verifier_hash_fetch_behavior_browsertest.cc b/chrome/browser/extensions/content_verifier_hash_fetch_behavior_browsertest.cc
index c7539c2..bc883c3e 100644
--- a/chrome/browser/extensions/content_verifier_hash_fetch_behavior_browsertest.cc
+++ b/chrome/browser/extensions/content_verifier_hash_fetch_behavior_browsertest.cc
@@ -7,9 +7,9 @@
 
 #include "base/macros.h"
 #include "chrome/browser/extensions/browsertest_util.h"
+#include "chrome/browser/extensions/chrome_content_verifier_delegate.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/extensions/extension_service.h"
-#include "chrome/common/chrome_switches.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/computed_hashes.h"
@@ -27,9 +27,9 @@
 
 // Specifies the content verification mode.
 enum ContentVerificationMode {
-  // Uses --extension-content-verification=enforce flag.
+  // Uses ContentVerifierDelegate::ENFORCE mode.
   kEnforce,
-  // Uses --extension-content-verification=enforce_strict flag.
+  // Uses ContentVerifierDelegate::ENFORCE_STRICT mode.
   kEnforceStrict
 };
 
@@ -55,13 +55,19 @@
   // ExtensionBrowserTest:
   bool ShouldEnableContentVerification() override { return true; }
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    ExtensionBrowserTest::SetUpCommandLine(command_line);
-    command_line->AppendSwitchASCII(
-        switches::kExtensionContentVerification,
-        uses_enforce_strict_mode()
-            ? switches::kExtensionContentVerificationEnforceStrict
-            : switches::kExtensionContentVerificationEnforce);
+  void SetUp() override {
+    // Override content verification mode before ExtensionSystemImpl initializes
+    // ChromeContentVerifierDelegate.
+    ChromeContentVerifierDelegate::SetDefaultModeForTesting(
+        uses_enforce_strict_mode() ? ContentVerifierDelegate::ENFORCE_STRICT
+                                   : ContentVerifierDelegate::ENFORCE);
+
+    ExtensionBrowserTest::SetUp();
+  }
+
+  void TearDown() override {
+    ExtensionBrowserTest::TearDown();
+    ChromeContentVerifierDelegate::SetDefaultModeForTesting(base::nullopt);
   }
 
   bool uses_enforce_strict_mode() {
diff --git a/chrome/browser/extensions/extension_view_host.cc b/chrome/browser/extensions/extension_view_host.cc
index b7e5e1b..96c0ecb 100644
--- a/chrome/browser/extensions/extension_view_host.cc
+++ b/chrome/browser/extensions/extension_view_host.cc
@@ -159,10 +159,25 @@
       // Only allow these from hosts that are bound to a browser (e.g. popups).
       // Otherwise they are not driven by a user gesture.
       Browser* browser = view_->GetBrowser();
-      return browser ? browser->OpenURL(params) : NULL;
+      return browser ? browser->OpenURL(params) : nullptr;
+    }
+    case WindowOpenDisposition::CURRENT_TAB: {
+      // Only allow these from hosts that are bound to a browser (e.g. popups).
+      // Otherwise they are not driven by a user gesture.
+      Browser* browser = view_->GetBrowser();
+      if (!browser)
+        return nullptr;
+
+      // Only allow navigations that will surely result in a download.
+      if (!params.suggested_filename.has_value() ||
+          !(params.url.SchemeIsBlob() || params.url.SchemeIsFileSystem() ||
+            params.url.SchemeIs(url::kDataScheme))) {
+        return nullptr;
+      }
+      return browser->OpenURL(params);
     }
     default:
-      return NULL;
+      return nullptr;
   }
 }
 
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc
index 06ae907..b666311 100644
--- a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc
+++ b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
 #include "chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h"
+#include "chrome/common/url_constants.h"
 #include "components/guest_view/browser/guest_view_event.h"
 #include "components/renderer_context_menu/context_menu_delegate.h"
 #include "content/public/browser/render_process_host.h"
@@ -106,4 +107,11 @@
   menu_delegate->ShowMenu(std::move(pending_menu_));
 }
 
+bool ChromeWebViewGuestDelegate::ShouldHandleFindRequestsForEmbedder() const {
+  // Find requests will be handled by the guest for the Chrome signin page.
+  return web_view_guest_->owner_web_contents()->GetWebUI() != nullptr &&
+         web_view_guest_->GetOwnerSiteURL().GetOrigin().spec() ==
+             chrome::kChromeUIChromeSigninURL;
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h
index ea58eab..468debd 100644
--- a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h
+++ b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h
@@ -27,6 +27,7 @@
   // WebViewGuestDelegate implementation.
   bool HandleContextMenu(const content::ContextMenuParams& params) override;
   void OnShowContextMenu(int request_id) override;
+  bool ShouldHandleFindRequestsForEmbedder() const override;
 
   WebViewGuest* web_view_guest() const { return web_view_guest_; }
 
diff --git a/chrome/browser/notifications/chrome_ash_message_center_client.cc b/chrome/browser/notifications/chrome_ash_message_center_client.cc
index 98f806c35..596f94f 100644
--- a/chrome/browser/notifications/chrome_ash_message_center_client.cc
+++ b/chrome/browser/notifications/chrome_ash_message_center_client.cc
@@ -104,11 +104,11 @@
 void ChromeAshMessageCenterClient::GetDisplayed(
     const std::string& /*profile_id*/,
     bool /*incognito*/,
-    const GetDisplayedNotificationsCallback& callback) const {
+    GetDisplayedNotificationsCallback callback) const {
   // Right now, this is only used to get web notifications that were created by
   // and have outlived a previous browser process. Ash itself doesn't outlive
   // the browser process, so there's no need to implement.
-  callback.Run(std::make_unique<std::set<std::string>>(), false);
+  std::move(callback).Run(std::make_unique<std::set<std::string>>(), false);
 }
 
 void ChromeAshMessageCenterClient::SetReadyCallback(
diff --git a/chrome/browser/notifications/chrome_ash_message_center_client.h b/chrome/browser/notifications/chrome_ash_message_center_client.h
index 104b87e0..736d7e51 100644
--- a/chrome/browser/notifications/chrome_ash_message_center_client.h
+++ b/chrome/browser/notifications/chrome_ash_message_center_client.h
@@ -34,10 +34,9 @@
                std::unique_ptr<NotificationCommon::Metadata> metadata) override;
   void Close(const std::string& profile_id,
              const std::string& notification_id) override;
-  void GetDisplayed(
-      const std::string& profile_id,
-      bool incognito,
-      const GetDisplayedNotificationsCallback& callback) const override;
+  void GetDisplayed(const std::string& profile_id,
+                    bool incognito,
+                    GetDisplayedNotificationsCallback callback) const override;
   void SetReadyCallback(NotificationBridgeReadyCallback callback) override;
 
   // ash::mojom::AshMessageCenterClient:
diff --git a/chrome/browser/notifications/notification_display_service.h b/chrome/browser/notifications/notification_display_service.h
index 35a54683..f630aa4 100644
--- a/chrome/browser/notifications/notification_display_service.h
+++ b/chrome/browser/notifications/notification_display_service.h
@@ -58,7 +58,7 @@
 
   // Gets the IDs of currently displaying notifications and invokes |callback|
   // once available. Not all backends support retrieving this information.
-  virtual void GetDisplayed(const DisplayedNotificationsCallback& callback) = 0;
+  virtual void GetDisplayed(DisplayedNotificationsCallback callback) = 0;
 
  protected:
   NotificationDisplayService() = default;
diff --git a/chrome/browser/notifications/notification_display_service_impl.cc b/chrome/browser/notifications/notification_display_service_impl.cc
index 0744469..bc4fd19 100644
--- a/chrome/browser/notifications/notification_display_service_impl.cc
+++ b/chrome/browser/notifications/notification_display_service_impl.cc
@@ -256,7 +256,7 @@
 }
 
 void NotificationDisplayServiceImpl::GetDisplayed(
-    const DisplayedNotificationsCallback& callback) {
+    DisplayedNotificationsCallback callback) {
   if (!bridge_initialized_) {
     actions_.push(base::BindOnce(&NotificationDisplayServiceImpl::GetDisplayed,
                                  weak_factory_.GetWeakPtr(), callback));
@@ -264,7 +264,7 @@
   }
 
   bridge_->GetDisplayed(GetProfileId(profile_), profile_->IsOffTheRecord(),
-                        callback);
+                        std::move(callback));
 }
 
 // Callback to run once the profile has been loaded in order to perform a
diff --git a/chrome/browser/notifications/notification_display_service_impl.h b/chrome/browser/notifications/notification_display_service_impl.h
index 9c5923a..909e0ac7 100644
--- a/chrome/browser/notifications/notification_display_service_impl.h
+++ b/chrome/browser/notifications/notification_display_service_impl.h
@@ -65,7 +65,7 @@
                    nullptr) override;
   void Close(NotificationHandler::Type notification_type,
              const std::string& notification_id) override;
-  void GetDisplayed(const DisplayedNotificationsCallback& callback) override;
+  void GetDisplayed(DisplayedNotificationsCallback callback) override;
 
   static void ProfileLoadedCallback(NotificationCommon::Operation operation,
                                     NotificationHandler::Type notification_type,
diff --git a/chrome/browser/notifications/notification_display_service_tester.cc b/chrome/browser/notifications/notification_display_service_tester.cc
index b772c8d..6ef2a641 100644
--- a/chrome/browser/notifications/notification_display_service_tester.cc
+++ b/chrome/browser/notifications/notification_display_service_tester.cc
@@ -41,13 +41,12 @@
       std::unique_ptr<NotificationCommon::Metadata> metadata) override {}
   void Close(const std::string& profile_id,
              const std::string& notification_id) override {}
-  void GetDisplayed(
-      const std::string& profile_id,
-      bool incognito,
-      const GetDisplayedNotificationsCallback& callback) const override {
+  void GetDisplayed(const std::string& profile_id,
+                    bool incognito,
+                    GetDisplayedNotificationsCallback callback) const override {
     auto displayed_notifications = std::make_unique<std::set<std::string>>();
-    callback.Run(std::move(displayed_notifications),
-                 false /* supports_synchronization */);
+    std::move(callback).Run(std::move(displayed_notifications),
+                            false /* supports_synchronization */);
   }
   void SetReadyCallback(NotificationBridgeReadyCallback callback) override {
     std::move(callback).Run(true /* ready */);
diff --git a/chrome/browser/notifications/notification_platform_bridge.h b/chrome/browser/notifications/notification_platform_bridge.h
index ea41f795..29bd17a 100644
--- a/chrome/browser/notifications/notification_platform_bridge.h
+++ b/chrome/browser/notifications/notification_platform_bridge.h
@@ -55,7 +55,7 @@
   virtual void GetDisplayed(
       const std::string& profile_id,
       bool incognito,
-      const GetDisplayedNotificationsCallback& callback) const = 0;
+      GetDisplayedNotificationsCallback callback) const = 0;
 
   // Calls |callback| once |this| is initialized. The argument is
   // true if |this| is ready to be used and false if initialization
diff --git a/chrome/browser/notifications/notification_platform_bridge_android.cc b/chrome/browser/notifications/notification_platform_bridge_android.cc
index 93fa8683..4f63928a 100644
--- a/chrome/browser/notifications/notification_platform_bridge_android.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_android.cc
@@ -321,12 +321,13 @@
 void NotificationPlatformBridgeAndroid::GetDisplayed(
     const std::string& profile_id,
     bool incognito,
-    const GetDisplayedNotificationsCallback& callback) const {
+    GetDisplayedNotificationsCallback callback) const {
   auto displayed_notifications = std::make_unique<std::set<std::string>>();
   content::BrowserThread::PostTask(
       content::BrowserThread::UI, FROM_HERE,
-      base::Bind(callback, base::Passed(&displayed_notifications),
-                 false /* supports_synchronization */));
+      base::BindOnce(std::move(callback),
+                     base::Passed(&displayed_notifications),
+                     false /* supports_synchronization */));
 }
 
 void NotificationPlatformBridgeAndroid::SetReadyCallback(
diff --git a/chrome/browser/notifications/notification_platform_bridge_android.h b/chrome/browser/notifications/notification_platform_bridge_android.h
index 23c83ea..087352b 100644
--- a/chrome/browser/notifications/notification_platform_bridge_android.h
+++ b/chrome/browser/notifications/notification_platform_bridge_android.h
@@ -77,10 +77,9 @@
                std::unique_ptr<NotificationCommon::Metadata> metadata) override;
   void Close(const std::string& profile_id,
              const std::string& notification_id) override;
-  void GetDisplayed(
-      const std::string& profile_id,
-      bool incognito,
-      const GetDisplayedNotificationsCallback& callback) const override;
+  void GetDisplayed(const std::string& profile_id,
+                    bool incognito,
+                    GetDisplayedNotificationsCallback callback) const override;
   void SetReadyCallback(NotificationBridgeReadyCallback callback) override;
 
   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
diff --git a/chrome/browser/notifications/notification_platform_bridge_chromeos.cc b/chrome/browser/notifications/notification_platform_bridge_chromeos.cc
index cdc0a378..dc30f8cab 100644
--- a/chrome/browser/notifications/notification_platform_bridge_chromeos.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_chromeos.cc
@@ -70,8 +70,8 @@
 void NotificationPlatformBridgeChromeOs::GetDisplayed(
     const std::string& profile_id,
     bool incognito,
-    const GetDisplayedNotificationsCallback& callback) const {
-  impl_->GetDisplayed(profile_id, incognito, callback);
+    GetDisplayedNotificationsCallback callback) const {
+  impl_->GetDisplayed(profile_id, incognito, std::move(callback));
 }
 
 void NotificationPlatformBridgeChromeOs::SetReadyCallback(
diff --git a/chrome/browser/notifications/notification_platform_bridge_chromeos.h b/chrome/browser/notifications/notification_platform_bridge_chromeos.h
index 0d64360..0a898190 100644
--- a/chrome/browser/notifications/notification_platform_bridge_chromeos.h
+++ b/chrome/browser/notifications/notification_platform_bridge_chromeos.h
@@ -61,10 +61,9 @@
                std::unique_ptr<NotificationCommon::Metadata> metadata) override;
   void Close(const std::string& profile_id,
              const std::string& notification_id) override;
-  void GetDisplayed(
-      const std::string& profile_id,
-      bool incognito,
-      const GetDisplayedNotificationsCallback& callback) const override;
+  void GetDisplayed(const std::string& profile_id,
+                    bool incognito,
+                    GetDisplayedNotificationsCallback callback) const override;
   void SetReadyCallback(NotificationBridgeReadyCallback callback) override;
 
   // NotificationPlatformBridgeDelegate:
diff --git a/chrome/browser/notifications/notification_platform_bridge_linux.cc b/chrome/browser/notifications/notification_platform_bridge_linux.cc
index 49cbbd9f..9a2a0e4 100644
--- a/chrome/browser/notifications/notification_platform_bridge_linux.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc
@@ -304,16 +304,15 @@
                        this, profile_id, notification_id));
   }
 
-  void GetDisplayed(
-      const std::string& profile_id,
-      bool incognito,
-      const GetDisplayedNotificationsCallback& callback) const override {
+  void GetDisplayed(const std::string& profile_id,
+                    bool incognito,
+                    GetDisplayedNotificationsCallback callback) const override {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
     task_runner_->PostTask(
         FROM_HERE,
         base::BindOnce(
             &NotificationPlatformBridgeLinuxImpl::GetDisplayedOnTaskRunner,
-            this, profile_id, incognito, callback));
+            this, profile_id, incognito, std::move(callback)));
   }
 
   void SetReadyCallback(NotificationBridgeReadyCallback callback) override {
@@ -720,7 +719,7 @@
   void GetDisplayedOnTaskRunner(
       const std::string& profile_id,
       bool incognito,
-      const GetDisplayedNotificationsCallback& callback) const {
+      GetDisplayedNotificationsCallback callback) const {
     DCHECK(task_runner_->RunsTasksInCurrentSequence());
     auto displayed = std::make_unique<std::set<std::string>>();
     for (const auto& pair : notifications_) {
@@ -730,7 +729,7 @@
     }
     content::BrowserThread::PostTask(
         content::BrowserThread::UI, FROM_HERE,
-        base::BindOnce(callback, std::move(displayed), true));
+        base::BindOnce(std::move(callback), std::move(displayed), true));
   }
 
   NotificationData* FindNotificationData(const std::string& notification_id,
@@ -1005,8 +1004,8 @@
 void NotificationPlatformBridgeLinux::GetDisplayed(
     const std::string& profile_id,
     bool incognito,
-    const GetDisplayedNotificationsCallback& callback) const {
-  impl_->GetDisplayed(profile_id, incognito, callback);
+    GetDisplayedNotificationsCallback callback) const {
+  impl_->GetDisplayed(profile_id, incognito, std::move(callback));
 }
 
 void NotificationPlatformBridgeLinux::SetReadyCallback(
diff --git a/chrome/browser/notifications/notification_platform_bridge_linux.h b/chrome/browser/notifications/notification_platform_bridge_linux.h
index cc73c05..7f066648 100644
--- a/chrome/browser/notifications/notification_platform_bridge_linux.h
+++ b/chrome/browser/notifications/notification_platform_bridge_linux.h
@@ -32,10 +32,9 @@
                std::unique_ptr<NotificationCommon::Metadata> metadata) override;
   void Close(const std::string& profile_id,
              const std::string& notification_id) override;
-  void GetDisplayed(
-      const std::string& profile_id,
-      bool incognito,
-      const GetDisplayedNotificationsCallback& callback) const override;
+  void GetDisplayed(const std::string& profile_id,
+                    bool incognito,
+                    GetDisplayedNotificationsCallback callback) const override;
   void SetReadyCallback(NotificationBridgeReadyCallback callback) override;
 
  private:
diff --git a/chrome/browser/notifications/notification_platform_bridge_mac.h b/chrome/browser/notifications/notification_platform_bridge_mac.h
index f6a1515..0c3e18e3 100644
--- a/chrome/browser/notifications/notification_platform_bridge_mac.h
+++ b/chrome/browser/notifications/notification_platform_bridge_mac.h
@@ -42,10 +42,9 @@
 
   void Close(const std::string& profile_id,
              const std::string& notification_id) override;
-  void GetDisplayed(
-      const std::string& profile_id,
-      bool incognito,
-      const GetDisplayedNotificationsCallback& callback) const override;
+  void GetDisplayed(const std::string& profile_id,
+                    bool incognito,
+                    GetDisplayedNotificationsCallback callback) const override;
   void SetReadyCallback(NotificationBridgeReadyCallback callback) override;
 
   // Processes a notification response generated from a user action
diff --git a/chrome/browser/notifications/notification_platform_bridge_mac.mm b/chrome/browser/notifications/notification_platform_bridge_mac.mm
index d5dcdd4e..98f18be 100644
--- a/chrome/browser/notifications/notification_platform_bridge_mac.mm
+++ b/chrome/browser/notifications/notification_platform_bridge_mac.mm
@@ -322,12 +322,12 @@
 void NotificationPlatformBridgeMac::GetDisplayed(
     const std::string& profile_id,
     bool incognito,
-    const GetDisplayedNotificationsCallback& callback) const {
+    GetDisplayedNotificationsCallback callback) const {
   [alert_dispatcher_
       getDisplayedAlertsForProfileId:base::SysUTF8ToNSString(profile_id)
                            incognito:incognito
                   notificationCenter:notification_center_
-                            callback:callback];
+                            callback:std::move(callback)];
 }
 
 void NotificationPlatformBridgeMac::SetReadyCallback(
diff --git a/chrome/browser/notifications/notification_platform_bridge_message_center.cc b/chrome/browser/notifications/notification_platform_bridge_message_center.cc
index a9fd0b3..e476d50b 100644
--- a/chrome/browser/notifications/notification_platform_bridge_message_center.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_message_center.cc
@@ -143,14 +143,14 @@
 void NotificationPlatformBridgeMessageCenter::GetDisplayed(
     const std::string& /* profile_id */,
     bool /* incognito */,
-    const GetDisplayedNotificationsCallback& callback) const {
+    GetDisplayedNotificationsCallback callback) const {
   auto displayed_notifications = std::make_unique<std::set<std::string>>(
       g_browser_process->notification_ui_manager()->GetAllIdsByProfile(
           NotificationUIManager::GetProfileID(profile_)));
 
   content::BrowserThread::PostTask(
       content::BrowserThread::UI, FROM_HERE,
-      base::BindOnce(callback, std::move(displayed_notifications),
+      base::BindOnce(std::move(callback), std::move(displayed_notifications),
                      true /* supports_synchronization */));
 }
 
diff --git a/chrome/browser/notifications/notification_platform_bridge_message_center.h b/chrome/browser/notifications/notification_platform_bridge_message_center.h
index 7d582530..3058dda 100644
--- a/chrome/browser/notifications/notification_platform_bridge_message_center.h
+++ b/chrome/browser/notifications/notification_platform_bridge_message_center.h
@@ -31,10 +31,9 @@
                std::unique_ptr<NotificationCommon::Metadata> metadata) override;
   void Close(const std::string& profile_id,
              const std::string& notification_id) override;
-  void GetDisplayed(
-      const std::string& profile_id,
-      bool incognito,
-      const GetDisplayedNotificationsCallback& callback) const override;
+  void GetDisplayed(const std::string& profile_id,
+                    bool incognito,
+                    GetDisplayedNotificationsCallback callback) const override;
   void SetReadyCallback(NotificationBridgeReadyCallback callback) override;
 
  private:
diff --git a/chrome/browser/notifications/notification_platform_bridge_win.cc b/chrome/browser/notifications/notification_platform_bridge_win.cc
index 43148db..65a01d49 100644
--- a/chrome/browser/notifications/notification_platform_bridge_win.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_win.cc
@@ -440,7 +440,7 @@
 
   void GetDisplayed(const std::string& profile_id,
                     bool incognito,
-                    const GetDisplayedNotificationsCallback& callback) const {
+                    GetDisplayedNotificationsCallback callback) const {
     // TODO(finnur): Once this function is properly implemented, add DCHECK(UI)
     // to NotificationPlatformBridgeWin::GetDisplayed.
     DCHECK(task_runner_->RunsTasksInCurrentSequence());
@@ -464,7 +464,7 @@
 
     content::BrowserThread::PostTask(
         content::BrowserThread::UI, FROM_HERE,
-        base::BindOnce(callback, std::move(displayed_notifications),
+        base::BindOnce(std::move(callback), std::move(displayed_notifications),
                        /*supports_synchronization=*/true));
   }
 
@@ -727,11 +727,11 @@
 void NotificationPlatformBridgeWin::GetDisplayed(
     const std::string& profile_id,
     bool incognito,
-    const GetDisplayedNotificationsCallback& callback) const {
+    GetDisplayedNotificationsCallback callback) const {
   task_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(&NotificationPlatformBridgeWinImpl::GetDisplayed, impl_,
-                     profile_id, incognito, callback));
+                     profile_id, incognito, std::move(callback)));
 }
 
 void NotificationPlatformBridgeWin::SetReadyCallback(
diff --git a/chrome/browser/notifications/notification_platform_bridge_win.h b/chrome/browser/notifications/notification_platform_bridge_win.h
index 11da138c..fab79ac4 100644
--- a/chrome/browser/notifications/notification_platform_bridge_win.h
+++ b/chrome/browser/notifications/notification_platform_bridge_win.h
@@ -36,10 +36,9 @@
                std::unique_ptr<NotificationCommon::Metadata> metadata) override;
   void Close(const std::string& profile_id,
              const std::string& notification_id) override;
-  void GetDisplayed(
-      const std::string& profile_id,
-      bool incognito,
-      const GetDisplayedNotificationsCallback& callback) const override;
+  void GetDisplayed(const std::string& profile_id,
+                    bool incognito,
+                    GetDisplayedNotificationsCallback callback) const override;
   void SetReadyCallback(NotificationBridgeReadyCallback callback) override;
 
   // Handles notification activation encoded in |command_line| from the
diff --git a/chrome/browser/notifications/stub_notification_display_service.cc b/chrome/browser/notifications/stub_notification_display_service.cc
index 184a0c6..b468b34 100644
--- a/chrome/browser/notifications/stub_notification_display_service.cc
+++ b/chrome/browser/notifications/stub_notification_display_service.cc
@@ -210,14 +210,15 @@
 }
 
 void StubNotificationDisplayService::GetDisplayed(
-    const DisplayedNotificationsCallback& callback) {
+    DisplayedNotificationsCallback callback) {
   std::unique_ptr<std::set<std::string>> notifications =
       std::make_unique<std::set<std::string>>();
 
   for (const auto& notification_data : notifications_)
     notifications->insert(notification_data.notification.id());
 
-  callback.Run(std::move(notifications), true /* supports_synchronization */);
+  std::move(callback).Run(std::move(notifications),
+                          true /* supports_synchronization */);
 }
 
 void StubNotificationDisplayService::ProcessNotificationOperation(
diff --git a/chrome/browser/notifications/stub_notification_display_service.h b/chrome/browser/notifications/stub_notification_display_service.h
index 3dfd487..a896cb12 100644
--- a/chrome/browser/notifications/stub_notification_display_service.h
+++ b/chrome/browser/notifications/stub_notification_display_service.h
@@ -94,7 +94,7 @@
                std::unique_ptr<NotificationCommon::Metadata> metadata) override;
   void Close(NotificationHandler::Type notification_type,
              const std::string& notification_id) override;
-  void GetDisplayed(const DisplayedNotificationsCallback& callback) override;
+  void GetDisplayed(DisplayedNotificationsCallback callback) override;
   void ProcessNotificationOperation(
       NotificationCommon::Operation operation,
       NotificationHandler::Type notification_type,
diff --git a/chrome/browser/resources/PRESUBMIT_test.py b/chrome/browser/resources/PRESUBMIT_test.py
old mode 100644
new mode 100755
index 923f2be1f..c741292
--- a/chrome/browser/resources/PRESUBMIT_test.py
+++ b/chrome/browser/resources/PRESUBMIT_test.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # Copyright 2014 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
diff --git a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc
index 6ac1b9e..a82bc18 100644
--- a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc
+++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc
@@ -31,6 +31,27 @@
 const char kAccountIdPrefix[] = "AccountId-";
 const size_t kAccountIdPrefixLength = 10;
 
+// Used to records token state transitions in histograms.
+// Do not change existing values, new values can only be added at the end.
+enum class TokenStateTransition {
+  // Update events.
+  kNoneToInvalid = 0,
+  kNoneToRegular,
+  kInvalidToRegular,
+  kRegularToInvalid,
+  kRegularToRegular,
+
+  // Revocation events.
+  kInvalidToNone,
+  kRegularToNone,
+
+  // Load events.
+  kLoadRegular,
+  kLoadInvalid,
+
+  kCount
+};
+
 // Enum for the Signin.LoadTokenFromDB histogram.
 // Do not modify, or add or delete other than directly before
 // NUM_LOAD_TOKEN_FROM_DB_STATUS.
@@ -46,6 +67,57 @@
   NUM_LOAD_TOKEN_FROM_DB_STATUS
 };
 
+// Adds a sample to the TokenStateTransition histogram. Encapsuled in a function
+// to reduce executable size, because histogram macros may generate a lot of
+// code.
+void RecordTokenStateTransition(TokenStateTransition transition) {
+  UMA_HISTOGRAM_ENUMERATION("Signin.TokenStateTransition", transition,
+                            TokenStateTransition::kCount);
+}
+
+// Record metrics when a token was updated.
+void RecordTokenChanged(const std::string& existing_token,
+                        const std::string& new_token) {
+  DCHECK_NE(existing_token, new_token);
+  DCHECK(!new_token.empty());
+  TokenStateTransition transition = TokenStateTransition::kCount;
+  if (existing_token.empty()) {
+    transition =
+        (new_token ==
+         MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken)
+            ? TokenStateTransition::kNoneToInvalid
+            : TokenStateTransition::kNoneToRegular;
+  } else if (existing_token ==
+             MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken) {
+    transition = TokenStateTransition::kInvalidToRegular;
+  } else {
+    // Existing token is a regular token.
+    transition =
+        (new_token ==
+         MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken)
+            ? TokenStateTransition::kRegularToInvalid
+            : transition = TokenStateTransition::kRegularToRegular;
+  }
+  DCHECK_NE(TokenStateTransition::kCount, transition);
+  RecordTokenStateTransition(transition);
+}
+
+// Record metrics when a token was loaded.
+void RecordTokenLoaded(const std::string& token) {
+  RecordTokenStateTransition(
+      (token == MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken)
+          ? TokenStateTransition::kLoadInvalid
+          : TokenStateTransition::kLoadRegular);
+}
+
+// Record metrics when a token was revoked.
+void RecordTokenRevoked(const std::string& token) {
+  RecordTokenStateTransition(
+      (token == MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken)
+          ? TokenStateTransition::kInvalidToNone
+          : TokenStateTransition::kRegularToNone);
+}
+
 std::string ApplyAccountIdPrefix(const std::string& account_id) {
   return kAccountIdPrefix + account_id;
 }
@@ -554,9 +626,11 @@
             LoadTokenFromDBStatus::NUM_LOAD_TOKEN_FROM_DB_STATUS);
 
         if (load_account) {
+          RecordTokenLoaded(refresh_token);
           UpdateCredentialsInMemory(account_id, refresh_token);
           FireRefreshTokenAvailable(account_id);
         } else {
+          RecordTokenRevoked(refresh_token);
           RevokeCredentialsOnServer(refresh_token);
           ClearPersistedCredentials(account_id);
           FireRefreshTokenRevoked(account_id);
@@ -585,8 +659,10 @@
   ValidateAccountId(account_id);
   signin_metrics::LogSigninAddAccount();
 
-  if (GetRefreshToken(account_id) != refresh_token) {
+  const std::string& existing_token = GetRefreshToken(account_id);
+  if (existing_token != refresh_token) {
     ScopedBatchChange batch(this);
+    RecordTokenChanged(existing_token, refresh_token);
     UpdateCredentialsInMemory(account_id, refresh_token);
     PersistCredentials(account_id, refresh_token);
     FireRefreshTokenAvailable(account_id);
@@ -663,7 +739,9 @@
   if (refresh_tokens_.count(account_id) > 0) {
     VLOG(1) << "MutablePO2TS::RevokeCredentials for account_id=" << account_id;
     ScopedBatchChange batch(this);
-    RevokeCredentialsOnServer(refresh_tokens_[account_id]->refresh_token());
+    const std::string& token = refresh_tokens_[account_id]->refresh_token();
+    RecordTokenRevoked(token);
+    RevokeCredentialsOnServer(token);
     refresh_tokens_.erase(account_id);
     ClearPersistedCredentials(account_id);
     FireRefreshTokenRevoked(account_id);
diff --git a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
index 7d6b8e4..0fc5ec4 100644
--- a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
@@ -6,6 +6,7 @@
 
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/bookmark_app_helper.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -90,7 +91,13 @@
 // Install some apps on both clients, some on only one client, some on only the
 // other, and sync.  Both clients should end up with all apps, and the app and
 // page ordinals should be identical.
-IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, StartWithDifferentApps) {
+// Flakily crashes on Windows, see crbug.com/434438.
+#if defined(OS_WIN)
+#define MAYBE_StartWithDifferentApps DISABLED_StartWithDifferentApps
+#else
+#define MAYBE_StartWithDifferentApps StartWithDifferentApps
+#endif
+IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, MAYBE_StartWithDifferentApps) {
   ASSERT_TRUE(SetupClients());
 
   int i = 0;
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc
index c77485c..6d4e9a8 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.cc
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -12,7 +12,6 @@
 #include "ash/app_list/model/app_list_model.h"
 #include "ash/app_list/model/search/search_model.h"
 #include "ash/public/cpp/menu_utils.h"
-#include "ash/public/interfaces/constants.mojom.h"
 #include "base/command_line.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
@@ -30,6 +29,7 @@
 #include "chrome/browser/ui/app_list/search/search_resource_manager.h"
 #include "chrome/browser/ui/apps/chrome_app_delegate.h"
 #include "chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h"
+#include "chrome/browser/ui/ash/wallpaper_controller_client.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/theme_resources.h"
@@ -41,12 +41,10 @@
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/speech_recognition_session_preamble.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension_set.h"
 #include "extensions/common/manifest_constants.h"
-#include "services/service_manager/public/cpp/connector.h"
 #include "ui/app_list/app_list_switches.h"
 #include "ui/app_list/app_list_view_delegate_observer.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -66,12 +64,9 @@
   registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
                  content::NotificationService::AllSources());
 
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &wallpaper_controller_ptr_);
   ash::mojom::WallpaperObserverAssociatedPtrInfo ptr_info;
   observer_binding_.Bind(mojo::MakeRequest(&ptr_info));
-  wallpaper_controller_ptr_->AddObserver(std::move(ptr_info));
+  WallpaperControllerClient::Get()->AddObserver(std::move(ptr_info));
 }
 
 AppListViewDelegate::~AppListViewDelegate() {
@@ -119,7 +114,7 @@
 
   // After |model_updater_| is initialized, make a GetWallpaperColors mojo call
   // to set wallpaper colors for |model_updater_|.
-  wallpaper_controller_ptr_->GetWallpaperColors(
+  WallpaperControllerClient::Get()->GetWallpaperColors(
       base::Bind(&AppListViewDelegate::OnGetWallpaperColorsCallback,
                  weak_ptr_factory_.GetWeakPtr()));
 
@@ -147,6 +142,8 @@
       app_list::CreateSearchController(profile_, model_updater_, controller_);
 }
 
+void AppListViewDelegate::OnWallpaperChanged(uint32_t image_id) {}
+
 void AppListViewDelegate::OnWallpaperColorsChanged(
     const std::vector<SkColor>& prominent_colors) {
   if (wallpaper_prominent_colors_ == prominent_colors)
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.h b/chrome/browser/ui/app_list/app_list_view_delegate.h
index 9fe3750..0fc40ce 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.h
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.h
@@ -96,6 +96,7 @@
   void SetUpSearchUI();
 
   // Overridden from ash::mojom::WallpaperObserver:
+  void OnWallpaperChanged(uint32_t image_id) override;
   void OnWallpaperColorsChanged(
       const std::vector<SkColor>& prominent_colors) override;
 
@@ -127,9 +128,6 @@
   // The binding this instance uses to implement mojom::WallpaperObserver.
   mojo::AssociatedBinding<ash::mojom::WallpaperObserver> observer_binding_;
 
-  // Ash's mojom::WallpaperController.
-  ash::mojom::WallpaperControllerPtr wallpaper_controller_ptr_;
-
   std::vector<SkColor> wallpaper_prominent_colors_;
 
   base::ObserverList<app_list::AppListViewDelegateObserver> observers_;
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc b/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc
index 2dd10d45..46e0d6d 100644
--- a/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc
+++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
+#include "content/public/browser/host_zoom_map.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/page_navigator.h"
 #include "content/public/browser/render_view_host.h"
@@ -263,6 +264,12 @@
 void AnswerCardWebContents::RenderViewCreated(content::RenderViewHost* host) {
   if (!host_)
     AttachToHost(host->GetWidget());
+
+  // Do not zoom for answer card web contents.
+  content::HostZoomMap* zoom_map =
+      content::HostZoomMap::GetForWebContents(web_contents());
+  DCHECK(zoom_map);
+  zoom_map->SetZoomLevelForHost(web_contents()->GetURL().host(), 0);
 }
 
 void AnswerCardWebContents::RenderViewDeleted(content::RenderViewHost* host) {
diff --git a/chrome/browser/ui/ash/test_wallpaper_controller.cc b/chrome/browser/ui/ash/test_wallpaper_controller.cc
index ecc2ace..bb0204c 100644
--- a/chrome/browser/ui/ash/test_wallpaper_controller.cc
+++ b/chrome/browser/ui/ash/test_wallpaper_controller.cc
@@ -4,10 +4,19 @@
 
 #include "chrome/browser/ui/ash/test_wallpaper_controller.h"
 
+constexpr uint32_t dummy_image_id = 1;
+
 TestWallpaperController::TestWallpaperController() : binding_(this) {}
 
 TestWallpaperController::~TestWallpaperController() = default;
 
+void TestWallpaperController::ShowWallpaperImage(const gfx::ImageSkia& image) {
+  current_wallpaper = image;
+  test_observers_.ForAllPtrs([this](ash::mojom::WallpaperObserver* observer) {
+    observer->OnWallpaperChanged(dummy_image_id);
+  });
+}
+
 void TestWallpaperController::ClearCounts() {
   remove_user_wallpaper_count_ = 0;
 }
@@ -33,14 +42,14 @@
     const std::string& wallpaper_files_id,
     const std::string& file_name,
     wallpaper::WallpaperLayout layout,
-    const SkBitmap& image,
+    const gfx::ImageSkia& image,
     bool preview_mode) {
   set_custom_wallpaper_count_++;
 }
 
 void TestWallpaperController::SetOnlineWallpaper(
     ash::mojom::WallpaperUserInfoPtr user_info,
-    const SkBitmap& image,
+    const gfx::ImageSkia& image,
     const std::string& url,
     wallpaper::WallpaperLayout layout,
     bool preview_mode) {
@@ -71,6 +80,17 @@
   NOTIMPLEMENTED();
 }
 
+void TestWallpaperController::SetThirdPartyWallpaper(
+    ash::mojom::WallpaperUserInfoPtr user_info,
+    const std::string& wallpaper_files_id,
+    const std::string& file_name,
+    wallpaper::WallpaperLayout layout,
+    const gfx::ImageSkia& image,
+    ash::mojom::WallpaperController::SetThirdPartyWallpaperCallback callback) {
+  std::move(callback).Run(true /*allowed=*/, dummy_image_id);
+  ShowWallpaperImage(image);
+}
+
 void TestWallpaperController::ConfirmPreviewWallpaper() {
   NOTIMPLEMENTED();
 }
@@ -117,11 +137,18 @@
 
 void TestWallpaperController::AddObserver(
     ash::mojom::WallpaperObserverAssociatedPtrInfo observer) {
-  NOTIMPLEMENTED();
+  ash::mojom::WallpaperObserverAssociatedPtr observer_ptr;
+  observer_ptr.Bind(std::move(observer));
+  test_observers_.AddPtr(std::move(observer_ptr));
+}
+
+void TestWallpaperController::GetWallpaperImage(
+    ash::mojom::WallpaperController::GetWallpaperImageCallback callback) {
+  std::move(callback).Run(current_wallpaper);
 }
 
 void TestWallpaperController::GetWallpaperColors(
-    GetWallpaperColorsCallback callback) {
+    ash::mojom::WallpaperController::GetWallpaperColorsCallback callback) {
   NOTIMPLEMENTED();
 }
 
diff --git a/chrome/browser/ui/ash/test_wallpaper_controller.h b/chrome/browser/ui/ash/test_wallpaper_controller.h
index dad20fa..19404d2 100644
--- a/chrome/browser/ui/ash/test_wallpaper_controller.h
+++ b/chrome/browser/ui/ash/test_wallpaper_controller.h
@@ -8,6 +8,7 @@
 #include "ash/public/interfaces/wallpaper.mojom.h"
 #include "base/macros.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
 
 // Simulates WallpaperController in ash.
 // TODO(crbug.com/776464): Maybe create an enum to represent each function to
@@ -18,6 +19,10 @@
 
   ~TestWallpaperController() override;
 
+  // Simulates showing the wallpaper on screen by updating |current_wallpaper|
+  // and notifying the observers.
+  void ShowWallpaperImage(const gfx::ImageSkia& image);
+
   void ClearCounts();
   bool was_client_set() const { return was_client_set_; }
   int remove_user_wallpaper_count() const {
@@ -41,10 +46,10 @@
                           const std::string& wallpaper_files_id,
                           const std::string& file_name,
                           wallpaper::WallpaperLayout layout,
-                          const SkBitmap& image,
+                          const gfx::ImageSkia& image,
                           bool preview_mode) override;
   void SetOnlineWallpaper(ash::mojom::WallpaperUserInfoPtr user_info,
-                          const SkBitmap& image,
+                          const gfx::ImageSkia& image,
                           const std::string& url,
                           wallpaper::WallpaperLayout layout,
                           bool preview_mode) override;
@@ -58,6 +63,14 @@
                           const std::string& wallpaper_files_id,
                           const std::string& data) override;
   void SetDeviceWallpaperPolicyEnforced(bool enforced) override;
+  void SetThirdPartyWallpaper(
+      ash::mojom::WallpaperUserInfoPtr user_info,
+      const std::string& wallpaper_files_id,
+      const std::string& file_name,
+      wallpaper::WallpaperLayout layout,
+      const gfx::ImageSkia& image,
+      ash::mojom::WallpaperController::SetThirdPartyWallpaperCallback callback)
+      override;
   void ConfirmPreviewWallpaper() override;
   void CancelPreviewWallpaper() override;
   void UpdateCustomWallpaperLayout(ash::mojom::WallpaperUserInfoPtr user_info,
@@ -72,7 +85,12 @@
   void OpenWallpaperPickerIfAllowed() override;
   void AddObserver(
       ash::mojom::WallpaperObserverAssociatedPtrInfo observer) override;
-  void GetWallpaperColors(GetWallpaperColorsCallback callback) override;
+  void GetWallpaperImage(
+      ash::mojom::WallpaperController::GetWallpaperImageCallback callback)
+      override;
+  void GetWallpaperColors(
+      ash::mojom::WallpaperController::GetWallpaperColorsCallback callback)
+      override;
   void IsActiveUserWallpaperControlledByPolicy(
       ash::mojom::WallpaperController::
           IsActiveUserWallpaperControlledByPolicyCallback callback) override;
@@ -88,6 +106,11 @@
   int set_default_wallpaper_count_ = 0;
   int set_custom_wallpaper_count_ = 0;
 
+  mojo::AssociatedInterfacePtrSet<ash::mojom::WallpaperObserver>
+      test_observers_;
+
+  gfx::ImageSkia current_wallpaper;
+
   DISALLOW_COPY_AND_ASSIGN(TestWallpaperController);
 };
 
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.cc b/chrome/browser/ui/ash/wallpaper_controller_client.cc
index e30ad85..586ba44 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client.cc
+++ b/chrome/browser/ui/ash/wallpaper_controller_client.cc
@@ -190,9 +190,9 @@
       AccountIdToWallpaperUserInfo(account_id);
   if (!user_info)
     return;
-  wallpaper_controller_->SetCustomWallpaper(
-      std::move(user_info), wallpaper_files_id.id(), file_name, layout,
-      *image.bitmap(), preview_mode);
+  wallpaper_controller_->SetCustomWallpaper(std::move(user_info),
+                                            wallpaper_files_id.id(), file_name,
+                                            layout, image, preview_mode);
 }
 
 void WallpaperControllerClient::SetOnlineWallpaper(
@@ -205,8 +205,8 @@
       AccountIdToWallpaperUserInfo(account_id);
   if (!user_info)
     return;
-  wallpaper_controller_->SetOnlineWallpaper(
-      std::move(user_info), *image.bitmap(), url, layout, preview_mode);
+  wallpaper_controller_->SetOnlineWallpaper(std::move(user_info), image, url,
+                                            layout, preview_mode);
 }
 
 void WallpaperControllerClient::SetDefaultWallpaper(const AccountId& account_id,
@@ -262,6 +262,22 @@
                                             GetFilesId(account_id).id(), *data);
 }
 
+void WallpaperControllerClient::SetThirdPartyWallpaper(
+    const AccountId& account_id,
+    const wallpaper::WallpaperFilesId& wallpaper_files_id,
+    const std::string& file_name,
+    wallpaper::WallpaperLayout layout,
+    const gfx::ImageSkia& image,
+    ash::mojom::WallpaperController::SetThirdPartyWallpaperCallback callback) {
+  ash::mojom::WallpaperUserInfoPtr user_info =
+      AccountIdToWallpaperUserInfo(account_id);
+  if (!user_info)
+    return;
+  wallpaper_controller_->SetThirdPartyWallpaper(
+      std::move(user_info), wallpaper_files_id.id(), file_name, layout, image,
+      std::move(callback));
+}
+
 void WallpaperControllerClient::ConfirmPreviewWallpaper() {
   wallpaper_controller_->ConfirmPreviewWallpaper();
 }
@@ -346,6 +362,21 @@
   wallpaper_controller_->OpenWallpaperPickerIfAllowed();
 }
 
+void WallpaperControllerClient::AddObserver(
+    ash::mojom::WallpaperObserverAssociatedPtrInfo observer) {
+  wallpaper_controller_->AddObserver(std::move(observer));
+}
+
+void WallpaperControllerClient::GetWallpaperImage(
+    ash::mojom::WallpaperController::GetWallpaperImageCallback callback) {
+  wallpaper_controller_->GetWallpaperImage(std::move(callback));
+}
+
+void WallpaperControllerClient::GetWallpaperColors(
+    ash::mojom::WallpaperController::GetWallpaperColorsCallback callback) {
+  wallpaper_controller_->GetWallpaperColors(std::move(callback));
+}
+
 void WallpaperControllerClient::IsActiveUserWallpaperControlledByPolicy(
     ash::mojom::WallpaperController::
         IsActiveUserWallpaperControlledByPolicyCallback callback) {
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.h b/chrome/browser/ui/ash/wallpaper_controller_client.h
index b01df2e..71b96fd 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client.h
+++ b/chrome/browser/ui/ash/wallpaper_controller_client.h
@@ -53,6 +53,13 @@
       const base::FilePath& customized_default_large_path);
   void SetPolicyWallpaper(const AccountId& account_id,
                           std::unique_ptr<std::string> data);
+  void SetThirdPartyWallpaper(
+      const AccountId& account_id,
+      const wallpaper::WallpaperFilesId& wallpaper_files_id,
+      const std::string& file_name,
+      wallpaper::WallpaperLayout layout,
+      const gfx::ImageSkia& image,
+      ash::mojom::WallpaperController::SetThirdPartyWallpaperCallback callback);
   void ConfirmPreviewWallpaper();
   void CancelPreviewWallpaper();
   void UpdateCustomWallpaperLayout(const AccountId& account_id,
@@ -63,6 +70,11 @@
   void RemovePolicyWallpaper(const AccountId& account_id);
   void SetAnimationDuration(const base::TimeDelta& animation_duration);
   void OpenWallpaperPickerIfAllowed();
+  void AddObserver(ash::mojom::WallpaperObserverAssociatedPtrInfo observer);
+  void GetWallpaperImage(
+      ash::mojom::WallpaperController::GetWallpaperImageCallback callback);
+  void GetWallpaperColors(
+      ash::mojom::WallpaperController::GetWallpaperColorsCallback callback);
   void IsActiveUserWallpaperControlledByPolicy(
       ash::mojom::WallpaperController::
           IsActiveUserWallpaperControlledByPolicyCallback callback);
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index 375ba74..68b755d 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -1864,7 +1864,13 @@
   EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
 }
 
-IN_PROC_BROWSER_TEST_F(BrowserTest, WindowOpenClose2) {
+// Flaky on Chrome OS only. TODO(https://crbug.com/823396) fix it.
+#if defined(OS_CHROMEOS)
+#define MAYBE_WindowOpenClose2 DISABLED_WindowOpenClose2
+#else
+#define MAYBE_WindowOpenClose2 WindowOpenClose2
+#endif
+IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_WindowOpenClose2) {
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kDisablePopupBlocking);
   ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chrome/browser/ui/extensions/application_launch.cc b/chrome/browser/ui/extensions/application_launch.cc
index 7efecc1..b2bcb90 100644
--- a/chrome/browser/ui/extensions/application_launch.cc
+++ b/chrome/browser/ui/extensions/application_launch.cc
@@ -29,13 +29,12 @@
 #include "chrome/browser/ui/extensions/app_launch_params.h"
 #include "chrome/browser/ui/extensions/extension_enable_flow.h"
 #include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h"
+#include "chrome/browser/ui/extensions/hosted_app_browser_controller.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
 #include "chrome/common/url_constants.h"
-#include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/renderer_preferences.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
@@ -219,8 +218,8 @@
   Navigate(&nav_params);
 
   WebContents* web_contents = nav_params.target_contents;
-  web_contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
-  web_contents->GetRenderViewHost()->SyncRendererPrefs();
+  extensions::HostedAppBrowserController::SetAppPrefsForWebContents(
+      web_contents);
 
   browser->window()->Show();
 
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
index 635a582..c614ab4 100644
--- a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
@@ -22,7 +22,9 @@
 #include "components/url_formatter/url_formatter.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/renderer_preferences.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension.h"
 #include "ui/gfx/favicon_size.h"
@@ -81,6 +83,14 @@
 }
 
 // static
+void HostedAppBrowserController::SetAppPrefsForWebContents(
+    content::WebContents* web_contents) {
+  auto* rvh = web_contents->GetRenderViewHost();
+
+  web_contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
+  rvh->SyncRendererPrefs();
+}
+
 base::string16 HostedAppBrowserController::FormatUrlOrigin(const GURL& url) {
   return url_formatter::FormatUrl(
       url.GetOrigin(),
@@ -96,9 +106,13 @@
     : SiteEngagementObserver(SiteEngagementService::Get(browser->profile())),
       browser_(browser),
       extension_id_(
-          web_app::GetExtensionIdFromApplicationName(browser->app_name())) {}
+          web_app::GetExtensionIdFromApplicationName(browser->app_name())) {
+  browser_->tab_strip_model()->AddObserver(this);
+}
 
-HostedAppBrowserController::~HostedAppBrowserController() {}
+HostedAppBrowserController::~HostedAppBrowserController() {
+  browser_->tab_strip_model()->RemoveObserver(this);
+}
 
 bool HostedAppBrowserController::IsForInstalledPwa(
     content::WebContents* web_contents) const {
@@ -228,4 +242,19 @@
                             SiteEngagementService::ENGAGEMENT_LAST);
 }
 
+void HostedAppBrowserController::TabInsertedAt(TabStripModel* tab_strip_model,
+                                               content::WebContents* contents,
+                                               int index,
+                                               bool foreground) {
+  HostedAppBrowserController::SetAppPrefsForWebContents(contents);
+}
+
+void HostedAppBrowserController::TabDetachedAt(content::WebContents* contents,
+                                               int index) {
+  auto* rvh = contents->GetRenderViewHost();
+
+  contents->GetMutableRendererPrefs()->can_accept_load_drops = true;
+  rvh->SyncRendererPrefs();
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.h b/chrome/browser/ui/extensions/hosted_app_browser_controller.h
index ae1cb19..7a1cf1f9 100644
--- a/chrome/browser/ui/extensions/hosted_app_browser_controller.h
+++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.h
@@ -11,6 +11,7 @@
 #include "base/optional.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/engagement/site_engagement_observer.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 class Browser;
@@ -26,7 +27,8 @@
 class Extension;
 
 // Class to encapsulate logic to control the browser UI for hosted apps.
-class HostedAppBrowserController : public SiteEngagementObserver {
+class HostedAppBrowserController : public SiteEngagementObserver,
+                                   public TabStripModelObserver {
  public:
   // Indicates whether |browser| is a hosted app browser.
   static bool IsForHostedApp(const Browser* browser);
@@ -34,6 +36,9 @@
   // Returns whether |browser| uses the experimental hosted app experience.
   static bool IsForExperimentalHostedAppBrowser(const Browser* browser);
 
+  // Functions to set preferences that are unique to app windows.
+  static void SetAppPrefsForWebContents(content::WebContents* web_contents);
+
   // Renders |url|'s origin as Unicode.
   static base::string16 FormatUrlOrigin(const GURL& url);
 
@@ -80,6 +85,13 @@
                          double score,
                          SiteEngagementService::EngagementType type) override;
 
+  // TabStripModelObserver overrides.
+  void TabInsertedAt(TabStripModel* tab_strip_model,
+                     content::WebContents* contents,
+                     int index,
+                     bool foreground) override;
+  void TabDetachedAt(content::WebContents* contents, int index) override;
+
  private:
   Browser* const browser_;
   const std::string extension_id_;
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
index 9c91225..d62d6cf7 100644
--- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -36,6 +36,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/context_menu_params.h"
+#include "content/public/common/renderer_preferences.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
@@ -99,6 +100,16 @@
       browser->hosted_app_controller()->ShouldShowLocationBar());
 }
 
+void CheckWebContentsHasAppPrefs(content::WebContents* web_contents) {
+  content::RendererPreferences* prefs = web_contents->GetMutableRendererPrefs();
+  EXPECT_FALSE(prefs->can_accept_load_drops);
+}
+
+void CheckWebContentsDoesNotHaveAppPrefs(content::WebContents* web_contents) {
+  content::RendererPreferences* prefs = web_contents->GetMutableRendererPrefs();
+  EXPECT_TRUE(prefs->can_accept_load_drops);
+}
+
 }  // namespace
 
 // Parameters are {app_type, desktop_pwa_flag}. |app_type| controls whether it
@@ -108,7 +119,7 @@
     : public ExtensionBrowserTest,
       public ::testing::WithParamInterface<std::tuple<AppType, bool>> {
  public:
-  HostedAppTest() : app_browser_(nullptr) {}
+  HostedAppTest() : app_browser_(nullptr), app_(nullptr) {}
   ~HostedAppTest() override {}
 
   void SetUp() override {
@@ -131,15 +142,15 @@
   }
 
   void SetupApp(const base::FilePath& app_folder) {
-    const Extension* app = InstallExtensionWithSourceAndFlags(
+    app_ = InstallExtensionWithSourceAndFlags(
         app_folder, 1, extensions::Manifest::INTERNAL,
         app_type_ == AppType::BOOKMARK_APP
             ? extensions::Extension::FROM_BOOKMARK
             : extensions::Extension::NO_FLAGS);
-    ASSERT_TRUE(app);
+    ASSERT_TRUE(app_);
 
     // Launch it in a window.
-    app_browser_ = LaunchAppBrowser(app);
+    app_browser_ = LaunchAppBrowser(app_);
     ASSERT_TRUE(app_browser_);
     ASSERT_TRUE(app_browser_ != browser());
   }
@@ -173,6 +184,7 @@
   }
 
   Browser* app_browser_;
+  const extensions::Extension* app_;
 
   AppType app_type() const { return app_type_; }
 
@@ -246,6 +258,46 @@
       url);
 }
 
+// Tests that the WebContents of an app window launched using OpenApplication
+// has the correct prefs.
+IN_PROC_BROWSER_TEST_P(HostedAppTest, WebContentsPrefsOpenApplication) {
+  SetupApp("https_app");
+  CheckWebContentsHasAppPrefs(
+      app_browser_->tab_strip_model()->GetActiveWebContents());
+}
+
+// Tests that the WebContents of an app window launched using
+// ReparentWebContentsIntoAppBrowser has the correct prefs.
+IN_PROC_BROWSER_TEST_P(HostedAppTest, WebContentsPrefsReparentWebContents) {
+  SetupApp("https_app");
+
+  content::WebContents* current_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  CheckWebContentsDoesNotHaveAppPrefs(current_tab);
+
+  ReparentWebContentsIntoAppBrowser(current_tab, app_);
+  ASSERT_NE(browser(), chrome::FindLastActive());
+
+  CheckWebContentsHasAppPrefs(
+      chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents());
+}
+
+// Tests that the WebContents of a regular browser window launched using
+// OpenInChrome has the correct prefs.
+IN_PROC_BROWSER_TEST_P(HostedAppTest, WebContentsPrefsOpenInChrome) {
+  SetupApp("https_app");
+
+  content::WebContents* app_contents =
+      app_browser_->tab_strip_model()->GetActiveWebContents();
+  CheckWebContentsHasAppPrefs(app_contents);
+
+  chrome::OpenInChrome(app_browser_);
+  ASSERT_EQ(browser(), chrome::FindLastActive());
+
+  CheckWebContentsDoesNotHaveAppPrefs(
+      browser()->tab_strip_model()->GetActiveWebContents());
+}
+
 // Check that the location bar is shown correctly.
 IN_PROC_BROWSER_TEST_P(HostedAppTest, ShouldShowLocationBar) {
   SetupApp("https_app");
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc
index 5c77f15..80d282a 100644
--- a/chrome/browser/ui/webui/settings/people_handler.cc
+++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -621,8 +621,7 @@
     return;
   }
 
-  SigninManagerBase* signin = SigninManagerFactory::GetForProfile(profile_);
-  if (!signin->IsAuthenticated()) {
+  if (IsProfileAuthNeeded()) {
     // For web-based signin, the signin page is not displayed in an overlay
     // on the settings page. So if we get here, it must be due to the user
     // cancelling signin (by reloading the sync settings page during initial
@@ -759,35 +758,6 @@
   if (service && !sync_blocker_)
     sync_blocker_ = service->GetSetupInProgressHandle();
 
-  // There are several different UI flows that can bring the user here:
-  // 1) Signin promo.
-  // 2) Normal signin through settings page (IsAuthenticated() is false).
-  // 3) Previously working credentials have expired.
-  // 4) User is signed in, but has stopped sync via the google dashboard, and
-  //    signout is prohibited by policy so we need to force a re-auth.
-  // 5) User clicks [Advanced Settings] button on options page while already
-  //    logged in.
-  // 6) One-click signin (credentials are already available, so should display
-  //    sync configure UI, not login UI).
-  // 7) User re-enables sync after disabling it via advanced settings.
-#if !defined(OS_CHROMEOS)
-  if (IsProfileAuthNeeded()) {
-    // User is not logged in (cases 1-2), or login has been specially requested
-    // because previously working credentials have expired (case 3). Close sync
-    // setup including any visible overlays, and display the gaia auth page.
-    // Control will be returned to the sync settings page once auth is complete.
-    CloseUI();
-    DisplayGaiaLogin(signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS);
-    return;
-  }
-#endif
-  if (!service) {
-    // This can happen if the user directly navigates to /settings/syncSetup.
-    DLOG(WARNING) << "Cannot display sync UI when sync is disabled";
-    CloseUI();
-    return;
-  }
-
   // Early exit if there is already a preferences push pending sync startup.
   if (sync_startup_tracker_)
     return;
diff --git a/chrome/browser/vr/model/color_scheme.cc b/chrome/browser/vr/model/color_scheme.cc
index 12f1943..341d42c9 100644
--- a/chrome/browser/vr/model/color_scheme.cc
+++ b/chrome/browser/vr/model/color_scheme.cc
@@ -154,7 +154,7 @@
 
   normal_scheme.content_reposition_frame = 0x66FFFFFF;
 
-  normal_scheme.cursor_background_center = 0x24000000;
+  normal_scheme.cursor_background_center = 0x66000000;
   normal_scheme.cursor_background_edge = SK_ColorTRANSPARENT;
   normal_scheme.cursor_foreground = SK_ColorWHITE;
 
diff --git a/chrome/browser/vr/ui_scene_constants.h b/chrome/browser/vr/ui_scene_constants.h
index ffde007..bdfab10 100644
--- a/chrome/browser/vr/ui_scene_constants.h
+++ b/chrome/browser/vr/ui_scene_constants.h
@@ -295,8 +295,8 @@
 static constexpr float kPromptShadowOffsetDMM = 0.1f;
 static constexpr float kPromptDistance = 2.4f;
 
-static constexpr float kRepositionCursorBackgroundSize = 1.4f;
-static constexpr float kRepositionCursorSize = 1.2f;
+static constexpr float kRepositionCursorBackgroundSize = 1.85f;
+static constexpr float kRepositionCursorSize = 1.5f;
 
 static constexpr float kMinResizerScale = 0.5f;
 static constexpr float kMaxResizerScale = 1.5f;
diff --git a/chrome/browser/vr/vector_icons/reposition.icon b/chrome/browser/vr/vector_icons/reposition.icon
index 3476931..5b02baf 100644
--- a/chrome/browser/vr/vector_icons/reposition.icon
+++ b/chrome/browser/vr/vector_icons/reposition.icon
@@ -1,41 +1,30 @@
 // Copyright 2018 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-
 CANVAS_DIMENSIONS, 24,
-MOVE_TO, 10, 9,
-R_H_LINE_TO, 4,
-V_LINE_TO, 6,
-R_H_LINE_TO, 3,
-R_LINE_TO, -5, -5,
-R_LINE_TO, -5, 5,
-R_H_LINE_TO, 3,
-R_V_LINE_TO, 3,
-CLOSE,
-R_MOVE_TO, -1, 1,
-H_LINE_TO, 6,
-V_LINE_TO, 7,
-R_LINE_TO, -5, 5,
-R_LINE_TO, 5, 5,
-R_V_LINE_TO, -3,
-R_H_LINE_TO, 3,
-R_V_LINE_TO, -4,
-CLOSE,
-R_MOVE_TO, 14, 2,
-R_LINE_TO, -5, -5,
-R_V_LINE_TO, 3,
-R_H_LINE_TO, -3,
-R_V_LINE_TO, 4,
-R_H_LINE_TO, 3,
-R_V_LINE_TO, 3,
-R_LINE_TO, 5, -5,
-CLOSE,
-R_MOVE_TO, -9, 3,
-R_H_LINE_TO, -4,
-R_V_LINE_TO, 3,
-H_LINE_TO, 7,
-R_LINE_TO, 5, 5,
-R_LINE_TO, 5, -5,
-R_H_LINE_TO, -3,
-R_V_LINE_TO, -3,
+R_MOVE_TO, 12, 1,
+R_CUBIC_TO, -1.67f, 1.67f, -3.33f, 3.33f, -5, 5,
+R_CUBIC_TO, 1, 0, 2, 0, 3, 0,
+R_CUBIC_TO, 0, 1.33f, 0, 2.67f, 0, 4,
+R_CUBIC_TO, -1.33f, 0, -2.67f, 0, -4, 0,
+R_CUBIC_TO, 0, -1, 0, -2, 0, -3,
+R_CUBIC_TO, -1.67f, 1.67f, -3.33f, 3.33f, -5, 5,
+R_CUBIC_TO, 1.67f, 1.67f, 3.33f, 3.33f, 5, 5,
+R_CUBIC_TO, 0, -1, 0, -2, 0, -3,
+R_CUBIC_TO, 1.33f, 0, 2.67f, 0, 4, 0,
+R_CUBIC_TO, 0, 1.33f, 0, 2.67f, 0, 4,
+R_CUBIC_TO, -1, 0, -2, 0, -3, 0,
+R_CUBIC_TO, 1.67f, 1.67f, 3.33f, 3.33f, 5, 5,
+R_CUBIC_TO, 1.67f, -1.67f, 3.33f, -3.33f, 5, -5,
+R_CUBIC_TO, -1, 0, -2, 0, -3, 0,
+R_CUBIC_TO, 0, -1.33f, 0, -2.67f, 0, -4,
+R_CUBIC_TO, 1.33f, 0, 2.67f, 0, 4, 0,
+R_CUBIC_TO, 0, 1, 0, 2, 0, 3,
+R_CUBIC_TO, 1.67f, -1.67f, 3.33f, -3.33f, 5, -5,
+R_CUBIC_TO, -1.67f, -1.67f, -3.33f, -3.33f, -5, -5,
+R_CUBIC_TO, 0, 1, 0, 2, 0, 3,
+R_CUBIC_TO, -1.33f, 0, -2.67f, 0, -4, 0,
+R_CUBIC_TO, 0, -1.33f, 0, -2.67f, 0, -4,
+R_CUBIC_TO, 1, 0, 2, 0, 3, 0,
+CUBIC_TO, 15.33f, 4.33f, 13.67f, 2.67f, 12, 1,
 CLOSE
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 4f1731b..d55b449 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -728,7 +728,7 @@
   ]
 
   public_deps = [
-    "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//third_party/WebKit/public:web_feature_mojo_bindings",
   ]
 }
@@ -739,7 +739,7 @@
   ]
 
   public_deps = [
-    "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//third_party/WebKit/public:web_client_hints_types_mojo_bindings",
     "//url/mojom:url_mojom_origin",
   ]
diff --git a/chrome/common/client_hints.mojom b/chrome/common/client_hints.mojom
index 0c64f9d..e708d7a1 100644
--- a/chrome/common/client_hints.mojom
+++ b/chrome/common/client_hints.mojom
@@ -4,7 +4,7 @@
 
 module client_hints.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "third_party/WebKit/public/platform/web_client_hints_types.mojom";
 import "url/mojom/origin.mojom";
 
@@ -15,5 +15,5 @@
 interface ClientHints {
   PersistClientHints(url.mojom.Origin primary_origin,
                      array<blink.mojom.WebClientHintsType> client_hints,
-                     mojo.common.mojom.TimeDelta expiration_duration);
+                     mojo_base.mojom.TimeDelta expiration_duration);
 };
\ No newline at end of file
diff --git a/chrome/common/extensions/permissions/permissions_data_unittest.cc b/chrome/common/extensions/permissions/permissions_data_unittest.cc
index 7d0b359..f78aac17 100644
--- a/chrome/common/extensions/permissions/permissions_data_unittest.cc
+++ b/chrome/common/extensions/permissions/permissions_data_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/common/extensions/extension_test_util.h"
 #include "components/crx_file/id_util.h"
@@ -392,75 +393,53 @@
     PermissionsData::SetPolicyDelegate(NULL);
   }
 
-  bool AllowedScript(const Extension* extension, const GURL& url) {
-    return AllowedScript(extension, url, -1);
+  enum AccessType {
+    DISALLOWED,
+    ALLOWED_SCRIPT_ONLY,
+    ALLOWED_CAPTURE_ONLY,
+    ALLOWED_SCRIPT_AND_CAPTURE,
+  };
+
+  bool IsAllowedScript(const Extension* extension, const GURL& url) {
+    return IsAllowedScript(extension, url, -1);
   }
 
-  bool AllowedScript(const Extension* extension, const GURL& url, int tab_id) {
-    return extension->permissions_data()->CanAccessPage(extension, url, tab_id,
-                                                        nullptr);
+  AccessType GetExtensionAccess(const Extension* extension,
+                                const GURL& url,
+                                int tab_id) {
+    bool allowed_script = IsAllowedScript(extension, url, tab_id);
+    bool allowed_capture =
+        extension->permissions_data()->CanCaptureVisiblePage(tab_id, nullptr);
+
+    if (allowed_script && allowed_capture)
+      return ALLOWED_SCRIPT_AND_CAPTURE;
+    if (allowed_script)
+      return ALLOWED_SCRIPT_ONLY;
+    if (allowed_capture)
+      return ALLOWED_CAPTURE_ONLY;
+    return DISALLOWED;
   }
 
-  bool BlockedScript(const Extension* extension, const GURL& url) {
-    return !extension->permissions_data()->CanAccessPage(extension, url, -1,
-                                                         nullptr);
+  AccessType GetExtensionAccess(const Extension* extension, const GURL& url) {
+    return GetExtensionAccess(extension, url, -1);
   }
 
-  bool Allowed(const Extension* extension, const GURL& url) {
-    return Allowed(extension, url, -1);
-  }
-
-  bool Allowed(const Extension* extension, const GURL& url, int tab_id) {
-    return (extension->permissions_data()->CanAccessPage(extension, url, tab_id,
-                                                         nullptr) &&
-            extension->permissions_data()->CanCaptureVisiblePage(tab_id, NULL));
-  }
-
-  bool CaptureOnly(const Extension* extension, const GURL& url) {
-    return CaptureOnly(extension, url, -1);
-  }
-
-  bool CaptureOnly(const Extension* extension, const GURL& url, int tab_id) {
-    return !extension->permissions_data()->CanAccessPage(extension, url, tab_id,
-                                                         nullptr) &&
-           extension->permissions_data()->CanCaptureVisiblePage(tab_id,
-                                                                nullptr);
-  }
-
-  bool ScriptOnly(const Extension* extension, const GURL& url) {
-    return ScriptOnly(extension, url, -1);
-  }
-
-  bool ScriptOnly(const Extension* extension, const GURL& url, int tab_id) {
-    return AllowedScript(extension, url, tab_id) &&
-           !extension->permissions_data()->CanCaptureVisiblePage(tab_id,
-                                                                 nullptr);
-  }
-
-  bool Blocked(const Extension* extension, const GURL& url) {
-    return Blocked(extension, url, -1);
-  }
-
-  bool Blocked(const Extension* extension, const GURL& url, int tab_id) {
-    return !extension->permissions_data()->CanAccessPage(extension, url, tab_id,
-                                                         nullptr) &&
-           !extension->permissions_data()->CanCaptureVisiblePage(tab_id,
-                                                                 nullptr);
-  }
-
-  bool ScriptAllowedExclusivelyOnTab(
+  testing::AssertionResult ScriptAllowedExclusivelyOnTab(
       const Extension* extension,
       const std::set<GURL>& allowed_urls,
       int tab_id) {
-    bool result = true;
-    for (std::set<GURL>::iterator it = urls_.begin(); it != urls_.end(); ++it) {
-      const GURL& url = *it;
-      if (allowed_urls.count(url))
-        result &= AllowedScript(extension, url, tab_id);
-      else
-        result &= Blocked(extension, url, tab_id);
+    std::vector<std::string> errors;
+    for (const GURL& url : urls_) {
+      bool allowed = IsAllowedScript(extension, url, tab_id);
+      if (allowed && !allowed_urls.count(url))
+        errors.push_back("Script unexpectedly disallowed on " + url.spec());
+      else if (!allowed && allowed_urls.count(url))
+        errors.push_back("Script unexpectedly allowed on " + url.spec());
     }
-    return result;
+
+    if (!errors.empty())
+      return testing::AssertionFailure() << base::JoinString(errors, "\n");
+    return testing::AssertionSuccess();
   }
 
   // URLs that are "safe" to provide scripting and capture visible tab access
@@ -483,6 +462,13 @@
   const GURL about_url;
 
  private:
+  bool IsAllowedScript(const Extension* extension,
+                       const GURL& url,
+                       int tab_id) {
+    return extension->permissions_data()->CanAccessPage(extension, url, tab_id,
+                                                        nullptr);
+  }
+
   // The set of all URLs above.
   std::set<GURL> urls_;
 };
@@ -492,21 +478,32 @@
   scoped_refptr<Extension> extension = LoadManifestStrict("script_and_capture",
       "extension_regular_all.json");
 
-  EXPECT_TRUE(Allowed(extension.get(), http_url));
-  EXPECT_TRUE(Allowed(extension.get(), https_url));
-  EXPECT_TRUE(CaptureOnly(extension.get(), file_url));
-  EXPECT_TRUE(CaptureOnly(extension.get(), settings_url));
-  EXPECT_TRUE(CaptureOnly(extension.get(), favicon_url));
-  EXPECT_TRUE(CaptureOnly(extension.get(), about_url));
-  EXPECT_TRUE(CaptureOnly(extension.get(), extension_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), http_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), https_url));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), file_url));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), favicon_url));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), about_url));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), extension_url));
 
   // Test access to iframed content.
   GURL within_extension_url = extension->GetResourceURL("page.html");
-  EXPECT_TRUE(AllowedScript(extension.get(), http_url));
-  EXPECT_TRUE(AllowedScript(extension.get(), http_url_with_path));
-  EXPECT_TRUE(AllowedScript(extension.get(), https_url));
-  EXPECT_TRUE(BlockedScript(extension.get(), within_extension_url));
-  EXPECT_TRUE(BlockedScript(extension.get(), extension_url));
+  // Note: this uses IsAllowedScript() (instead of GetExtensionAccess()) because
+  // they are theoretically testing iframed content, and capturing (just)
+  // iframed content doesn't make sense. It might be nice to more completely
+  // enforce that this is for subframe access, though.
+  EXPECT_TRUE(IsAllowedScript(extension.get(), http_url));
+  EXPECT_TRUE(IsAllowedScript(extension.get(), http_url_with_path));
+  EXPECT_TRUE(IsAllowedScript(extension.get(), https_url));
+  EXPECT_FALSE(IsAllowedScript(extension.get(), within_extension_url));
+  EXPECT_FALSE(IsAllowedScript(extension.get(), extension_url));
 
   EXPECT_FALSE(extension->permissions_data()->HasHostPermission(settings_url));
   EXPECT_FALSE(extension->permissions_data()->HasHostPermission(about_url));
@@ -515,15 +512,16 @@
   // Test * for scheme, which implies just the http/https schemes.
   extension = LoadManifestStrict("script_and_capture",
       "extension_wildcard.json");
-  EXPECT_TRUE(ScriptOnly(extension.get(), http_url));
-  EXPECT_TRUE(ScriptOnly(extension.get(), https_url));
-  EXPECT_TRUE(Blocked(extension.get(), settings_url));
-  EXPECT_TRUE(Blocked(extension.get(), about_url));
-  EXPECT_TRUE(Blocked(extension.get(), file_url));
-  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_ONLY, GetExtensionAccess(extension.get(), http_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_ONLY,
+            GetExtensionAccess(extension.get(), https_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), file_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
   extension =
       LoadManifest("script_and_capture", "extension_wildcard_settings.json");
-  EXPECT_TRUE(Blocked(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
 
   // Having chrome://*/ should not work for regular extensions. Note that
   // for favicon access, we require the explicit pattern chrome://favicon/*.
@@ -538,45 +536,50 @@
                 manifest_errors::kInvalidPermissionScheme,
                 "chrome://*/"),
             warnings[0].message);
-  EXPECT_TRUE(Blocked(extension.get(), settings_url));
-  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
-  EXPECT_TRUE(Blocked(extension.get(), about_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_url));
 
   // Having chrome://favicon/* should not give you chrome://*
   extension = LoadManifestStrict("script_and_capture",
       "extension_chrome_favicon_wildcard.json");
-  EXPECT_TRUE(Blocked(extension.get(), settings_url));
-  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
-  EXPECT_TRUE(Blocked(extension.get(), about_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_url));
   EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
 
   // Having http://favicon should not give you chrome://favicon
   extension = LoadManifestStrict("script_and_capture",
       "extension_http_favicon.json");
-  EXPECT_TRUE(Blocked(extension.get(), settings_url));
-  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
 
   // Component extensions with <all_urls> should get everything.
   extension = LoadManifest("script_and_capture", "extension_component_all.json",
       Manifest::COMPONENT, Extension::NO_FLAGS);
-  EXPECT_TRUE(Allowed(extension.get(), http_url));
-  EXPECT_TRUE(Allowed(extension.get(), https_url));
-  EXPECT_TRUE(Allowed(extension.get(), settings_url));
-  EXPECT_TRUE(Allowed(extension.get(), about_url));
-  EXPECT_TRUE(Allowed(extension.get(), favicon_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), http_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), https_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), about_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), favicon_url));
   EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
 
   // Component extensions should only get access to what they ask for.
   extension = LoadManifest("script_and_capture",
       "extension_component_google.json", Manifest::COMPONENT,
       Extension::NO_FLAGS);
-  EXPECT_TRUE(ScriptOnly(extension.get(), http_url));
-  EXPECT_TRUE(Blocked(extension.get(), https_url));
-  EXPECT_TRUE(Blocked(extension.get(), file_url));
-  EXPECT_TRUE(Blocked(extension.get(), settings_url));
-  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
-  EXPECT_TRUE(Blocked(extension.get(), about_url));
-  EXPECT_TRUE(Blocked(extension.get(), extension_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_ONLY, GetExtensionAccess(extension.get(), http_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), https_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), file_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), extension_url));
   EXPECT_FALSE(extension->permissions_data()->HasHostPermission(settings_url));
 }
 
@@ -589,21 +592,29 @@
   // Test <all_urls> for regular extensions.
   extension =
       LoadManifestStrict("script_and_capture", "extension_regular_all.json");
-  EXPECT_TRUE(Allowed(extension.get(), http_url));
-  EXPECT_TRUE(Allowed(extension.get(), https_url));
-  EXPECT_TRUE(CaptureOnly(extension.get(), file_url));
-  EXPECT_TRUE(CaptureOnly(extension.get(), settings_url));
-  EXPECT_TRUE(Allowed(extension.get(), favicon_url));  // chrome:// requested
-  EXPECT_TRUE(CaptureOnly(extension.get(), about_url));
-  EXPECT_TRUE(CaptureOnly(extension.get(), extension_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), http_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), https_url));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), file_url));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(
+      ALLOWED_SCRIPT_AND_CAPTURE,
+      GetExtensionAccess(extension.get(), favicon_url));  // chrome:// requested
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), about_url));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), extension_url));
 
   // Test access to iframed content.
   GURL within_extension_url = extension->GetResourceURL("page.html");
-  EXPECT_TRUE(AllowedScript(extension.get(), http_url));
-  EXPECT_TRUE(AllowedScript(extension.get(), http_url_with_path));
-  EXPECT_TRUE(AllowedScript(extension.get(), https_url));
-  EXPECT_TRUE(BlockedScript(extension.get(), within_extension_url));
-  EXPECT_TRUE(BlockedScript(extension.get(), extension_url));
+  EXPECT_TRUE(IsAllowedScript(extension.get(), http_url));
+  EXPECT_TRUE(IsAllowedScript(extension.get(), http_url_with_path));
+  EXPECT_TRUE(IsAllowedScript(extension.get(), https_url));
+  EXPECT_FALSE(IsAllowedScript(extension.get(), within_extension_url));
+  EXPECT_FALSE(IsAllowedScript(extension.get(), extension_url));
 
   const PermissionsData* permissions_data = extension->permissions_data();
   EXPECT_FALSE(permissions_data->HasHostPermission(settings_url));
@@ -613,15 +624,16 @@
   // Test * for scheme, which implies just the http/https schemes.
   extension =
       LoadManifestStrict("script_and_capture", "extension_wildcard.json");
-  EXPECT_TRUE(ScriptOnly(extension.get(), http_url));
-  EXPECT_TRUE(ScriptOnly(extension.get(), https_url));
-  EXPECT_TRUE(Blocked(extension.get(), settings_url));
-  EXPECT_TRUE(Blocked(extension.get(), about_url));
-  EXPECT_TRUE(Blocked(extension.get(), file_url));
-  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_ONLY, GetExtensionAccess(extension.get(), http_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_ONLY,
+            GetExtensionAccess(extension.get(), https_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), file_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
   extension =
       LoadManifest("script_and_capture", "extension_wildcard_settings.json");
-  EXPECT_TRUE(Blocked(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
 
   // Having chrome://*/ should work for regular extensions with the flag
   // enabled.
@@ -631,48 +643,56 @@
                                     Manifest::INTERNAL, Extension::NO_FLAGS,
                                     &error);
   EXPECT_FALSE(extension.get() == NULL);
-  EXPECT_TRUE(Blocked(extension.get(), http_url));
-  EXPECT_TRUE(Blocked(extension.get(), https_url));
-  EXPECT_TRUE(ScriptOnly(extension.get(), settings_url));
-  EXPECT_TRUE(Blocked(extension.get(), about_url));
-  EXPECT_TRUE(Blocked(extension.get(), file_url));
-  EXPECT_TRUE(ScriptOnly(extension.get(), favicon_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), http_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), https_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_ONLY,
+            GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), file_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_ONLY,
+            GetExtensionAccess(extension.get(), favicon_url));
 
   // Having chrome://favicon/* should not give you chrome://*
   extension = LoadManifestStrict("script_and_capture",
                                  "extension_chrome_favicon_wildcard.json");
-  EXPECT_TRUE(Blocked(extension.get(), settings_url));
-  EXPECT_TRUE(ScriptOnly(extension.get(), favicon_url));
-  EXPECT_TRUE(Blocked(extension.get(), about_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_ONLY,
+            GetExtensionAccess(extension.get(), favicon_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_url));
   EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
 
   // Having http://favicon should not give you chrome://favicon
   extension =
       LoadManifestStrict("script_and_capture", "extension_http_favicon.json");
-  EXPECT_TRUE(Blocked(extension.get(), settings_url));
-  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
 
   // Component extensions with <all_urls> should get everything.
   extension = LoadManifest("script_and_capture", "extension_component_all.json",
                            Manifest::COMPONENT, Extension::NO_FLAGS);
-  EXPECT_TRUE(Allowed(extension.get(), http_url));
-  EXPECT_TRUE(Allowed(extension.get(), https_url));
-  EXPECT_TRUE(Allowed(extension.get(), settings_url));
-  EXPECT_TRUE(Allowed(extension.get(), about_url));
-  EXPECT_TRUE(Allowed(extension.get(), favicon_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), http_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), https_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), about_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), favicon_url));
   EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
 
   // Component extensions should only get access to what they ask for.
   extension =
       LoadManifest("script_and_capture", "extension_component_google.json",
                    Manifest::COMPONENT, Extension::NO_FLAGS);
-  EXPECT_TRUE(ScriptOnly(extension.get(), http_url));
-  EXPECT_TRUE(Blocked(extension.get(), https_url));
-  EXPECT_TRUE(Blocked(extension.get(), file_url));
-  EXPECT_TRUE(Blocked(extension.get(), settings_url));
-  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
-  EXPECT_TRUE(Blocked(extension.get(), about_url));
-  EXPECT_TRUE(Blocked(extension.get(), extension_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_ONLY, GetExtensionAccess(extension.get(), http_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), https_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), file_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), extension_url));
   EXPECT_FALSE(extension->permissions_data()->HasHostPermission(settings_url));
 }
 
@@ -849,9 +869,12 @@
   // The default policy applies to all extensions at this point. The extension
   // should be able to access test.example.com but be blocked from
   // accessing any other subdomains of example.com or example.com itself.
-  EXPECT_TRUE(CaptureOnly(extension.get(), example_com));
-  EXPECT_TRUE(CaptureOnly(extension.get(), sample_example_com));
-  EXPECT_TRUE(Allowed(extension.get(), test_example_com));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), example_com));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), sample_example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), test_example_com));
 
   URLPatternSet blocked;
   blocked.AddPattern(test_example_com_pattern);
@@ -860,9 +883,12 @@
 
   // We've applied an individual policy which overrides the default policy.
   // The only URL that should be blocked is test.example.com.
-  EXPECT_TRUE(Allowed(extension.get(), example_com));
-  EXPECT_TRUE(Allowed(extension.get(), sample_example_com));
-  EXPECT_TRUE(CaptureOnly(extension.get(), test_example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), sample_example_com));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), test_example_com));
 
   blocked.AddPattern(example_com_pattern);
   allowed.AddPattern(test_example_com_pattern);
@@ -873,9 +899,12 @@
   // Since the whitelist overrides a blacklist we expect to allow access to
   // test.example.com but block access to all other example.com subdomains
   // (sample.example.com) and example.com itself.
-  EXPECT_TRUE(CaptureOnly(extension.get(), example_com));
-  EXPECT_TRUE(CaptureOnly(extension.get(), sample_example_com));
-  EXPECT_TRUE(Allowed(extension.get(), test_example_com));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), example_com));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), sample_example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), test_example_com));
 
   blocked.ClearPatterns();
   allowed.ClearPatterns();
@@ -884,9 +913,12 @@
   // Cleared all URLs from the individual policy, so all URLs should have
   // access. We want to make sure that a block at the default level doesn't
   // apply since we're still definining an individual policy.
-  EXPECT_TRUE(Allowed(extension.get(), example_com));
-  EXPECT_TRUE(Allowed(extension.get(), sample_example_com));
-  EXPECT_TRUE(Allowed(extension.get(), test_example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), sample_example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), test_example_com));
 
   // Flip back to using default policy for this extension.
   extension->permissions_data()->SetUsesDefaultHostRestrictions();
@@ -894,9 +926,12 @@
   // Make sure the default policy has the same effect as before we defined an
   // individual policy. Access to test.example.com should be allowed, but all
   // other subdomains and example.com itself should be blocked.
-  EXPECT_TRUE(CaptureOnly(extension.get(), example_com));
-  EXPECT_TRUE(CaptureOnly(extension.get(), sample_example_com));
-  EXPECT_TRUE(Allowed(extension.get(), test_example_com));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), example_com));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), sample_example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), test_example_com));
 }
 
 TEST_F(ExtensionScriptAndCaptureVisibleTest, PolicyHostRestrictions) {
@@ -918,27 +953,37 @@
   extension->permissions_data()->SetDefaultPolicyHostRestrictions(
       default_blocked, default_allowed);
 
-  EXPECT_TRUE(Allowed(extension.get(), http_url));
-  EXPECT_TRUE(Allowed(extension.get(), https_url));
-  EXPECT_TRUE(CaptureOnly(extension.get(), example_com));
-  EXPECT_TRUE(Allowed(extension.get(), test_example_com));
-  EXPECT_TRUE(CaptureOnly(extension.get(), sample_example_com));
-  EXPECT_TRUE(CaptureOnly(extension.get(), file_url));
-  EXPECT_TRUE(CaptureOnly(extension.get(), settings_url));
-  EXPECT_TRUE(CaptureOnly(extension.get(), favicon_url));
-  EXPECT_TRUE(CaptureOnly(extension.get(), about_url));
-  EXPECT_TRUE(CaptureOnly(extension.get(), extension_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), http_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), https_url));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), test_example_com));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), sample_example_com));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), file_url));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), favicon_url));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), about_url));
+  EXPECT_EQ(ALLOWED_CAPTURE_ONLY,
+            GetExtensionAccess(extension.get(), extension_url));
 
   // Test access to iframed content.
   GURL within_extension_url = extension->GetResourceURL("page.html");
-  EXPECT_TRUE(AllowedScript(extension.get(), http_url));
-  EXPECT_TRUE(AllowedScript(extension.get(), http_url_with_path));
-  EXPECT_TRUE(BlockedScript(extension.get(), example_com));
-  EXPECT_TRUE(AllowedScript(extension.get(), test_example_com));
-  EXPECT_TRUE(BlockedScript(extension.get(), sample_example_com));
-  EXPECT_TRUE(AllowedScript(extension.get(), https_url));
-  EXPECT_TRUE(BlockedScript(extension.get(), within_extension_url));
-  EXPECT_TRUE(BlockedScript(extension.get(), extension_url));
+  EXPECT_TRUE(IsAllowedScript(extension.get(), http_url));
+  EXPECT_TRUE(IsAllowedScript(extension.get(), http_url_with_path));
+  EXPECT_FALSE(IsAllowedScript(extension.get(), example_com));
+  EXPECT_TRUE(IsAllowedScript(extension.get(), test_example_com));
+  EXPECT_FALSE(IsAllowedScript(extension.get(), sample_example_com));
+  EXPECT_TRUE(IsAllowedScript(extension.get(), https_url));
+  EXPECT_FALSE(IsAllowedScript(extension.get(), within_extension_url));
+  EXPECT_FALSE(IsAllowedScript(extension.get(), extension_url));
 
   // Supress host permission for example.com since its on the blocklist
   EXPECT_FALSE(extension->permissions_data()->HasHostPermission(example_com));
@@ -955,20 +1000,23 @@
       LoadManifestStrict("script_and_capture", "extension_wildcard.json");
   extension->permissions_data()->SetDefaultPolicyHostRestrictions(
       default_blocked, default_allowed);
-  EXPECT_TRUE(ScriptOnly(extension.get(), http_url));
-  EXPECT_TRUE(Blocked(extension.get(), example_com));
-  EXPECT_TRUE(ScriptOnly(extension.get(), test_example_com));
-  EXPECT_TRUE(Blocked(extension.get(), sample_example_com));
-  EXPECT_TRUE(ScriptOnly(extension.get(), https_url));
-  EXPECT_TRUE(Blocked(extension.get(), settings_url));
-  EXPECT_TRUE(Blocked(extension.get(), about_url));
-  EXPECT_TRUE(Blocked(extension.get(), file_url));
-  EXPECT_TRUE(Blocked(extension.get(), favicon_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_ONLY, GetExtensionAccess(extension.get(), http_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_ONLY,
+            GetExtensionAccess(extension.get(), test_example_com));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), sample_example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_ONLY,
+            GetExtensionAccess(extension.get(), https_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), file_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
   extension =
       LoadManifest("script_and_capture", "extension_wildcard_settings.json");
   extension->permissions_data()->SetDefaultPolicyHostRestrictions(
       default_blocked, default_allowed);
-  EXPECT_TRUE(Blocked(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
 
   // Component extensions with <all_urls> should get everything regardless of
   // policy.
@@ -976,14 +1024,22 @@
                            Manifest::COMPONENT, Extension::NO_FLAGS);
   extension->permissions_data()->SetDefaultPolicyHostRestrictions(
       default_blocked, default_allowed);
-  EXPECT_TRUE(Allowed(extension.get(), http_url));
-  EXPECT_TRUE(Allowed(extension.get(), https_url));
-  EXPECT_TRUE(Allowed(extension.get(), example_com));
-  EXPECT_TRUE(Allowed(extension.get(), test_example_com));
-  EXPECT_TRUE(Allowed(extension.get(), sample_example_com));
-  EXPECT_TRUE(Allowed(extension.get(), settings_url));
-  EXPECT_TRUE(Allowed(extension.get(), about_url));
-  EXPECT_TRUE(Allowed(extension.get(), favicon_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), http_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), https_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), test_example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), sample_example_com));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), about_url));
+  EXPECT_EQ(ALLOWED_SCRIPT_AND_CAPTURE,
+            GetExtensionAccess(extension.get(), favicon_url));
   EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
 }
 
diff --git a/chrome/common/media_router/mojo/BUILD.gn b/chrome/common/media_router/mojo/BUILD.gn
index 285f3dd1..add44fd 100644
--- a/chrome/common/media_router/mojo/BUILD.gn
+++ b/chrome/common/media_router/mojo/BUILD.gn
@@ -11,7 +11,7 @@
   ]
 
   public_deps = [
-    "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
   ]
 }
 
@@ -23,7 +23,7 @@
   public_deps = [
     ":media_controller",
     "//media/mojo/interfaces:mirror_service_remoting",
-    "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//net/interfaces:interfaces",
     "//url/mojom:url_mojom_gurl",
     "//url/mojom:url_mojom_origin",
diff --git a/chrome/common/media_router/mojo/media_controller.mojom b/chrome/common/media_router/mojo/media_controller.mojom
index a2b5c8f..0d1fa9b2 100644
--- a/chrome/common/media_router/mojo/media_controller.mojom
+++ b/chrome/common/media_router/mojo/media_controller.mojom
@@ -5,7 +5,7 @@
 module media_router.mojom;
 
 import "chrome/common/media_router/mojo/media_status.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 // Interface for a controller to change the current state of a media content.
 // This interface should be kept free of details specific to Media Router, so
@@ -31,7 +31,7 @@
 
   // Sets the current playback position. |time| must be less than or equal to
   // the duration of the media. Is a no-op if the media doesn't support seeking.
-  Seek(mojo.common.mojom.TimeDelta time);
+  Seek(mojo_base.mojom.TimeDelta time);
 
   // Requests additional interface for commands used only for Hangouts routes.
   // TODO(crbug.com/684642): Moving this method to the MediaRouteProvider
diff --git a/chrome/common/media_router/mojo/media_router.mojom b/chrome/common/media_router/mojo/media_router.mojom
index 0545b24d..ac57bcf9 100644
--- a/chrome/common/media_router/mojo/media_router.mojom
+++ b/chrome/common/media_router/mojo/media_router.mojom
@@ -7,7 +7,7 @@
 import "chrome/common/media_router/mojo/media_controller.mojom";
 import "chrome/common/media_router/mojo/media_status.mojom";
 import "media/mojo/interfaces/mirror_service_remoting.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "net/interfaces/ip_address.mojom";
 import "net/interfaces/ip_endpoint.mojom";
 import "url/mojom/origin.mojom";
@@ -277,7 +277,7 @@
               string original_presentation_id,
               url.mojom.Origin origin,
               int32 tab_id,
-              mojo.common.mojom.TimeDelta timeout,
+              mojo_base.mojom.TimeDelta timeout,
               bool incognito) =>
                   (MediaRoute? route,
                    string? error_text,
@@ -305,7 +305,7 @@
             string presentation_id,
             url.mojom.Origin origin,
             int32 tab_id,
-            mojo.common.mojom.TimeDelta timeout,
+            mojo_base.mojom.TimeDelta timeout,
             bool incognito) =>
                 (MediaRoute? route,
                  string? error_text,
@@ -339,7 +339,7 @@
                         string presentation_id,
                         url.mojom.Origin origin,
                         int32 tab_id,
-                        mojo.common.mojom.TimeDelta timeout,
+                        mojo_base.mojom.TimeDelta timeout,
                         bool incognito) =>
                             (MediaRoute? route,
                              string? error_text,
diff --git a/chrome/common/media_router/mojo/media_status.mojom b/chrome/common/media_router/mojo/media_status.mojom
index 6811111..48a05b7 100644
--- a/chrome/common/media_router/mojo/media_status.mojom
+++ b/chrome/common/media_router/mojo/media_status.mojom
@@ -4,7 +4,7 @@
 
 module media_router.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 // Represents the current state of a media content. This struct should be kept
 // free of details specific to Media Router, so that it can be moved to the
@@ -50,10 +50,10 @@
 
   // The length of the media. A value of 0 indicates that this is a media with
   // no set duration (e.g. a live stream).
-  mojo.common.mojom.TimeDelta duration;
+  mojo_base.mojom.TimeDelta duration;
 
   // Current playback position. Must be less than or equal to |duration|.
-  mojo.common.mojom.TimeDelta current_time;
+  mojo_base.mojom.TimeDelta current_time;
 
   // Only set for Hangouts routes.
   HangoutsMediaStatusExtraData? hangouts_extra_data;
diff --git a/chrome/common/media_router/mojo/media_status_struct_traits.cc b/chrome/common/media_router/mojo/media_status_struct_traits.cc
index 9e4179ae..307dc235 100644
--- a/chrome/common/media_router/mojo/media_status_struct_traits.cc
+++ b/chrome/common/media_router/mojo/media_status_struct_traits.cc
@@ -5,7 +5,7 @@
 #include "chrome/common/media_router/mojo/media_status_struct_traits.h"
 
 #include "base/strings/string_util.h"
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 
 namespace mojo {
 
diff --git a/chrome/common/page_load_metrics/page_load_metrics.mojom b/chrome/common/page_load_metrics/page_load_metrics.mojom
index acc8580..3d30a36 100644
--- a/chrome/common/page_load_metrics/page_load_metrics.mojom
+++ b/chrome/common/page_load_metrics/page_load_metrics.mojom
@@ -4,52 +4,52 @@
 
 module page_load_metrics.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "third_party/WebKit/public/platform/web_feature.mojom";
 
 // TimeDeltas below relative to navigation start.
 struct DocumentTiming {
   // Time immediately before the DOMContentLoaded event is fired.
-  mojo.common.mojom.TimeDelta? dom_content_loaded_event_start;
+  mojo_base.mojom.TimeDelta? dom_content_loaded_event_start;
 
   // Time immediately before the load event is fired.
-  mojo.common.mojom.TimeDelta? load_event_start;
+  mojo_base.mojom.TimeDelta? load_event_start;
 
   // Time when the first layout is completed.
-  mojo.common.mojom.TimeDelta? first_layout;
+  mojo_base.mojom.TimeDelta? first_layout;
 };
 
 // TimeDeltas below relative to navigation start.
 struct PaintTiming {
   // Time when the first paint is performed.
-  mojo.common.mojom.TimeDelta? first_paint;
+  mojo_base.mojom.TimeDelta? first_paint;
 
   // Time when the first non-blank text is painted.
-  mojo.common.mojom.TimeDelta? first_text_paint;
+  mojo_base.mojom.TimeDelta? first_text_paint;
 
   // Time when the first image is painted.
-  mojo.common.mojom.TimeDelta? first_image_paint;
+  mojo_base.mojom.TimeDelta? first_image_paint;
 
   // Time when the first contentful thing (image, text, etc.) is painted.
-  mojo.common.mojom.TimeDelta? first_contentful_paint;
+  mojo_base.mojom.TimeDelta? first_contentful_paint;
 
   // (Experimental) Time when the page's primary content is painted.
-  mojo.common.mojom.TimeDelta? first_meaningful_paint;
+  mojo_base.mojom.TimeDelta? first_meaningful_paint;
 };
 
 // TimeDeltas below represent durations of time during the page load.
 struct ParseTiming {
   // Time that the document's parser started and stopped parsing main resource
   // content.
-  mojo.common.mojom.TimeDelta? parse_start;
-  mojo.common.mojom.TimeDelta? parse_stop;
+  mojo_base.mojom.TimeDelta? parse_start;
+  mojo_base.mojom.TimeDelta? parse_stop;
 
   // Sum of times when the parser is blocked waiting on the load of a script.
   // This duration takes place between parser_start and parser_stop, and thus
   // must be less than or equal to parser_stop - parser_start. Note that this
   // value may be updated multiple times during the period between parse_start
   // and parse_stop.
-  mojo.common.mojom.TimeDelta? parse_blocked_on_script_load_duration;
+  mojo_base.mojom.TimeDelta? parse_blocked_on_script_load_duration;
 
   // Sum of times when the parser is blocked waiting on the load of a script
   // that was inserted from document.write. This duration must be less than or
@@ -58,13 +58,13 @@
   // parse_stop. Note that some uncommon cases where scripts are loaded via
   // document.write are not currently covered by this field. See crbug/600711
   // for details.
-  mojo.common.mojom.TimeDelta? parse_blocked_on_script_load_from_document_write_duration;
+  mojo_base.mojom.TimeDelta? parse_blocked_on_script_load_from_document_write_duration;
 
   // Sum of times when the parser is executing a script.  This duration takes
   // place between parser_start and parser_stop, and thus must be less than or
   // equal to parser_stop - parser_start. Note that this value may be updated
   // multiple times during the period between parse_start and parse_stop.
-  mojo.common.mojom.TimeDelta? parse_blocked_on_script_execution_duration;
+  mojo_base.mojom.TimeDelta? parse_blocked_on_script_execution_duration;
 
   // Sum of times when the parser is executing a script that was inserted from
   // document.write. This duration must be less than or equal to
@@ -72,29 +72,29 @@
   // multiple times during the period between parse_start and parse_stop. Note
   // that some uncommon cases where scripts are loaded via document.write are
   // not currently covered by this field. See crbug/600711 for details.
-  mojo.common.mojom.TimeDelta? parse_blocked_on_script_execution_from_document_write_duration;
+  mojo_base.mojom.TimeDelta? parse_blocked_on_script_execution_from_document_write_duration;
 };
 
 struct StyleSheetTiming {
   // Total time spent parsing author style sheets, before the first contentful
   // paint.
-  mojo.common.mojom.TimeDelta? author_style_sheet_parse_duration_before_fcp;
+  mojo_base.mojom.TimeDelta? author_style_sheet_parse_duration_before_fcp;
   // Time spent in Document::updateStyle before FCP.
-  mojo.common.mojom.TimeDelta? update_style_duration_before_fcp;
+  mojo_base.mojom.TimeDelta? update_style_duration_before_fcp;
 };
 
 struct InteractiveTiming {
   // The first time the page is considered 'interactive'. This is determined
   // using heuristics based on main thread and network activity. Time delta is
   // relative to navigation_start.
-  mojo.common.mojom.TimeDelta? interactive;
+  mojo_base.mojom.TimeDelta? interactive;
 
   // The time of when we detect the page is interactive. There is a delay
   // between when the page was interactive and when we were able to detect it.
   // Time delta is relative to navigation_start.
   // This is a page load metrics internal value and not generally intended for
   // consumption by observers.
-  mojo.common.mojom.TimeDelta? interactive_detection;
+  mojo_base.mojom.TimeDelta? interactive_detection;
 
 
   // The time of when a significant input event happened that may cause
@@ -102,14 +102,14 @@
   // relative to navigation start.
   // This is a page load metrics internal value and not generally intended for
   // consumption by observers.
-  mojo.common.mojom.TimeDelta? first_invalidating_input;
+  mojo_base.mojom.TimeDelta? first_invalidating_input;
 
   // Queueing Time of the first click, tap, key press, cancellable touchstart,
   // or pointer down followed by a pointer up.
-  mojo.common.mojom.TimeDelta? first_input_delay;
+  mojo_base.mojom.TimeDelta? first_input_delay;
 
   // The timestamp of the event whose delay is reported by GetFirstInputDelay().
-  mojo.common.mojom.TimeDelta? first_input_timestamp;
+  mojo_base.mojom.TimeDelta? first_input_timestamp;
 };
 
 
@@ -121,11 +121,11 @@
   // this field is only used for internal tracking purposes and should not be
   // used by PageLoadMetricsObservers. This field will likely be removed in the
   // future.
-  mojo.common.mojom.Time navigation_start;
+  mojo_base.mojom.Time navigation_start;
 
   // Time relative to navigation_start that the first byte of the response is
   // received.
-  mojo.common.mojom.TimeDelta? response_start;
+  mojo_base.mojom.TimeDelta? response_start;
   DocumentTiming document_timing;
   InteractiveTiming interactive_timing;
   PaintTiming paint_timing;
diff --git a/chrome/common/search.mojom b/chrome/common/search.mojom
index 69d7c7f..02b2928 100644
--- a/chrome/common/search.mojom
+++ b/chrome/common/search.mojom
@@ -5,7 +5,7 @@
 module chrome.mojom;
 
 import "mojo/public/mojom/base/string16.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "url/mojom/url.mojom";
 
 [Native]
@@ -48,7 +48,7 @@
   // Logs events from InstantExtended New Tab Pages.
   LogEvent(int32 page_seq_no,
            NTPLoggingEventType event,
-           mojo.common.mojom.TimeDelta time);
+           mojo_base.mojom.TimeDelta time);
 
   // Logs an impression on one of the Most Visited tile on the InstantExtended
   // New Tab Page.
diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
index d945ef2..6dc4a350 100644
--- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
+++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
@@ -276,7 +276,8 @@
       IDR_MEDIA_STATUS_MOJOM_JS);
   source_map->RegisterSource("media_router_bindings",
                              IDR_MEDIA_ROUTER_BINDINGS_JS);
-  source_map->RegisterSource("mojo/common/time.mojom", IDR_MOJO_TIME_MOJOM_JS);
+  source_map->RegisterSource("mojo/public/mojom/base/time.mojom",
+                             IDR_MOJO_TIME_MOJOM_JS);
   source_map->RegisterSource("net/interfaces/ip_address.mojom",
                              IDR_MOJO_IP_ADDRESS_MOJOM_JS);
   source_map->RegisterSource("net/interfaces/ip_endpoint.mojom",
diff --git a/chrome/renderer/resources/extensions/media_router_bindings.js b/chrome/renderer/resources/extensions/media_router_bindings.js
index 1260b400..de8cdcd 100644
--- a/chrome/renderer/resources/extensions/media_router_bindings.js
+++ b/chrome/renderer/resources/extensions/media_router_bindings.js
@@ -15,7 +15,7 @@
 loadScript('extensions/common/mojo/keep_alive.mojom');
 loadScript('media/mojo/interfaces/mirror_service_remoting.mojom');
 loadScript('media/mojo/interfaces/remoting_common.mojom');
-loadScript('mojo/common/time.mojom');
+loadScript('mojo/public/mojom/base/time.mojom');
 loadScript('net/interfaces/ip_address.mojom');
 loadScript('net/interfaces/ip_endpoint.mojom');
 loadScript('url/mojom/origin.mojom');
@@ -761,7 +761,7 @@
     Origin: url.mojom.Origin,
     Sink: MediaSinkAdapter,
     SinkExtraData: MediaSinkExtraDataAdapter,
-    TimeDelta: mojo.common.mojom.TimeDelta,
+    TimeDelta: mojoBase.mojom.TimeDelta,
     Url: url.mojom.Url,
     interfaceControl: mojo.interfaceControl,
     makeRequest: mojo.makeRequest,
@@ -1168,7 +1168,7 @@
  *     requesting presentation. TODO(mfoltz): Remove.
  * @param {!url.mojom.Origin} origin Origin of site requesting presentation.
  * @param {!number} tabId ID of tab requesting presentation.
- * @param {!mojo.common.mojom.TimeDelta} timeout If positive, the timeout
+ * @param {!mojo_base.mojom.TimeDelta} timeout If positive, the timeout
  *     duration for the request. Otherwise, the default duration will be used.
  * @param {!boolean} incognito If true, the route is being requested by
  *     an incognito profile.
@@ -1199,7 +1199,7 @@
  * @param {!string} presentationId Presentation ID to join.
  * @param {!url.mojom.Origin} origin Origin of site requesting join.
  * @param {!number} tabId ID of tab requesting join.
- * @param {!mojo.common.mojom.TimeDelta} timeout If positive, the timeout
+ * @param {!mojo_base.mojom.TimeDelta} timeout If positive, the timeout
  *     duration for the request. Otherwise, the default duration will be used.
  * @param {!boolean} incognito If true, the route is being requested by
  *     an incognito profile.
@@ -1231,7 +1231,7 @@
  * @param {!string} presentationId Presentation ID to join.
  * @param {!url.mojom.Origin} origin Origin of site requesting join.
  * @param {!number} tabId ID of tab requesting join.
- * @param {!mojo.common.mojom.TimeDelta} timeout If positive, the timeout
+ * @param {!mojo_base.mojom.TimeDelta} timeout If positive, the timeout
  *     duration for the request. Otherwise, the default duration will be used.
  * @param {!boolean} incognito If true, the route is being requested by
  *     an incognito profile.
diff --git a/chrome/renderer/resources/renderer_resources.grd b/chrome/renderer/resources/renderer_resources.grd
index 8f15cf18..cedfb4dc6 100644
--- a/chrome/renderer/resources/renderer_resources.grd
+++ b/chrome/renderer/resources/renderer_resources.grd
@@ -83,7 +83,7 @@
         <include name="IDR_MEDIA_ROUTER_MOJOM_JS" file="${mojom_root}\chrome\common\media_router\mojo\media_router.mojom.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_MEDIA_ROUTER_BINDINGS_JS" file="extensions\media_router_bindings.js" type="BINDATA" />
         <include name="IDR_MEDIA_STATUS_MOJOM_JS" file="${mojom_root}\chrome\common\media_router\mojo\media_status.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_MOJO_TIME_MOJOM_JS" file="${mojom_root}\mojo\common\time.mojom.js" use_base_dir="false" type="BINDATA" />
+        <include name="IDR_MOJO_TIME_MOJOM_JS" file="${mojom_root}\mojo\public\mojom\base\time.mojom.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_MOJO_IP_ADDRESS_MOJOM_JS" file="${mojom_root}\net\interfaces\ip_address.mojom.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_MOJO_IP_ENDPOINT_MOJOM_JS" file="${mojom_root}\net\interfaces\ip_endpoint.mojom.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_ORIGIN_MOJOM_JS" file="${mojom_root}\url\mojom\origin.mojom.js" use_base_dir="false" type="BINDATA" />
diff --git a/chrome/services/media_gallery_util/public/mojom/media_parser.mojom b/chrome/services/media_gallery_util/public/mojom/media_parser.mojom
index 7e47cb9c..2b41147 100644
--- a/chrome/services/media_gallery_util/public/mojom/media_parser.mojom
+++ b/chrome/services/media_gallery_util/public/mojom/media_parser.mojom
@@ -4,9 +4,9 @@
 
 module chrome.mojom;
 
-import "mojo/common/time.mojom";
 import "mojo/common/values.mojom";
 import "mojo/public/mojom/base/file.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 interface MediaParser {
   // Extracts metadata from a |mime_type| blob of data of |total_size| and
@@ -26,7 +26,7 @@
   // |file| appears to be a well-formed media file, false otherwise.
   // Note: it is still not safe to decode the file in the calling process after
   // this check.
-  CheckMediaFile(mojo.common.mojom.TimeDelta decode_time,
+  CheckMediaFile(mojo_base.mojom.TimeDelta decode_time,
                  mojo_base.mojom.File file)
       => (bool success);
 };
diff --git a/chrome/test/chromedriver/chrome/navigation_tracker.cc b/chrome/test/chromedriver/chrome/navigation_tracker.cc
index ba4b593..83af346 100644
--- a/chrome/test/chromedriver/chrome/navigation_tracker.cc
+++ b/chrome/test/chromedriver/chrome/navigation_tracker.cc
@@ -353,7 +353,9 @@
       // contexts created and destroyed for this dummy frame.
       std::string name;
       if (!params.GetString("frame.name", &name))
-        return Status(kUnknownError, "missing or invalid 'frame.name'");
+        // https://bugs.chromium.org/p/chromium/issues/detail?id=823579
+        // OOPIF frames might not have names. Ignore them.
+        return Status(kOk);
       std::string url;
       if (!params.GetString("frame.url", &url))
         return Status(kUnknownError, "missing or invalid 'frame.url'");
diff --git a/chrome/test/data/extensions/api_test/browser_action/popup_download/chromium.png b/chrome/test/data/extensions/api_test/browser_action/popup_download/chromium.png
new file mode 100644
index 0000000..8c07cf84
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/browser_action/popup_download/chromium.png
Binary files differ
diff --git a/chrome/test/data/extensions/api_test/browser_action/popup_download/manifest.json b/chrome/test/data/extensions/api_test/browser_action/popup_download/manifest.json
new file mode 100644
index 0000000..d969024c
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/browser_action/popup_download/manifest.json
@@ -0,0 +1,11 @@
+{
+  "name": "Popup download tester",
+  "version": "0.1",
+  "manifest_version": 2,
+  "description": "apitest for downloads from popups",
+  "browser_action": {
+      "default_title": "grow",
+      "default_icon": "chromium.png",
+      "default_popup": "popup.html"
+  }
+}
diff --git a/chrome/test/data/extensions/api_test/browser_action/popup_download/popup.html b/chrome/test/data/extensions/api_test/browser_action/popup_download/popup.html
new file mode 100644
index 0000000..c0edd90
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/browser_action/popup_download/popup.html
@@ -0,0 +1,9 @@
+<!--
+ * Copyright 2018 The Chromium Authors. All rights reserved.  Use of this
+ * source code is governed by a BSD-style license that can be found in the
+ * LICENSE file.
+-->
+<body>
+<a href="data:text/plain,test" download>test download</a>
+<script src="popup.js"></script>
+</body>
diff --git a/chrome/test/data/extensions/api_test/browser_action/popup_download/popup.js b/chrome/test/data/extensions/api_test/browser_action/popup_download/popup.js
new file mode 100644
index 0000000..17901bcd
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/browser_action/popup_download/popup.js
@@ -0,0 +1,12 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function run_tests() {
+  var anchor = document.querySelector("a");
+  anchor.click();
+}
+
+window.addEventListener("load", function() {
+    chrome.test.notifyPass();
+}, false);
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 61e9e8a..3466b57 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-10500.0.0
\ No newline at end of file
+10503.0.0
\ No newline at end of file
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index b20cb41..e0633a3 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -681,9 +681,9 @@
 }
 
 bool IsZipArchiverPackerEnabled() {
-  // Disabled by default.
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      kEnableZipArchiverPacker);
+  // Enabled by default.
+  return !base::CommandLine::ForCurrentProcess()->HasSwitch(
+      kDisableZipArchiverPacker);
 }
 
 bool IsSigninFrameClientCertsEnabled() {
diff --git a/chromeos/dbus/fake_auth_policy_client.cc b/chromeos/dbus/fake_auth_policy_client.cc
index d5aa5c4..1238f40 100644
--- a/chromeos/dbus/fake_auth_policy_client.cc
+++ b/chromeos/dbus/fake_auth_policy_client.cc
@@ -23,9 +23,7 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "chromeos/login/auth/authpolicy_login_helper.h"
-#include "components/policy/proto/chrome_device_policy.pb.h"
 #include "components/policy/proto/cloud_policy.pb.h"
-#include "components/policy/proto/device_management_backend.pb.h"
 #include "components/signin/core/account_id/account_id.h"
 #include "dbus/message.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
@@ -60,11 +58,11 @@
 }
 
 void StoreDevicePolicy(
+    const em::ChromeDeviceSettingsProto& device_policy,
     const std::string& machine_name,
     chromeos::AuthPolicyClient::RefreshPolicyCallback callback) {
-  em::ChromeDeviceSettingsProto policy;
   std::string payload;
-  CHECK(policy.SerializeToString(&payload));
+  CHECK(device_policy.SerializeToString(&payload));
 
   em::PolicyFetchResponse response;
   em::PolicyData policy_data;
@@ -215,7 +213,7 @@
     return;
   }
 
-  StoreDevicePolicy(machine_name_, std::move(callback));
+  StoreDevicePolicy(device_policy_, machine_name_, std::move(callback));
 }
 
 void FakeAuthPolicyClient::RefreshUserPolicy(const AccountId& account_id,
@@ -274,7 +272,7 @@
   policy_data.ParseFromString(response.policy_data());
   if (policy_data.has_device_id())
     machine_name_ = policy_data.device_id();
-  StoreDevicePolicy(machine_name_, std::move(callback));
+  StoreDevicePolicy(device_policy_, machine_name_, std::move(callback));
 }
 
 }  // namespace chromeos
diff --git a/chromeos/dbus/fake_auth_policy_client.h b/chromeos/dbus/fake_auth_policy_client.h
index 9163106..6e801d5 100644
--- a/chromeos/dbus/fake_auth_policy_client.h
+++ b/chromeos/dbus/fake_auth_policy_client.h
@@ -14,6 +14,8 @@
 
 #include "chromeos/dbus/auth_policy_client.h"
 #include "chromeos/dbus/session_manager_client.h"
+#include "components/policy/proto/chrome_device_policy.pb.h"
+#include "components/policy/proto/device_management_backend.pb.h"
 
 class AccountId;
 
@@ -96,6 +98,11 @@
     on_get_status_closure_ = std::move(on_get_status_closure);
   }
 
+  void set_device_policy(
+      const enterprise_management::ChromeDeviceSettingsProto& device_policy) {
+    device_policy_ = device_policy;
+  }
+
   void DisableOperationDelayForTesting() {
     dbus_operation_delay_ = disk_operation_delay_ =
         base::TimeDelta::FromSeconds(0);
@@ -123,6 +130,7 @@
   base::TimeDelta dbus_operation_delay_ = base::TimeDelta::FromSeconds(3);
   base::TimeDelta disk_operation_delay_ =
       base::TimeDelta::FromMilliseconds(100);
+  enterprise_management::ChromeDeviceSettingsProto device_policy_;
 
   base::WeakPtrFactory<FakeAuthPolicyClient> weak_factory_{this};
 
diff --git a/chromeos/dbus/fake_auth_policy_client_unittest.cc b/chromeos/dbus/fake_auth_policy_client_unittest.cc
index e468c1a6..a3132ff 100644
--- a/chromeos/dbus/fake_auth_policy_client_unittest.cc
+++ b/chromeos/dbus/fake_auth_policy_client_unittest.cc
@@ -14,6 +14,8 @@
 #include "components/signin/core/account_id/account_id.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace em = enterprise_management;
+
 namespace chromeos {
 namespace {
 
@@ -31,11 +33,16 @@
 
  protected:
   FakeAuthPolicyClient* authpolicy_client() { return auth_policy_client_ptr_; }
+  FakeSessionManagerClient* session_manager_client() {
+    return session_manager_client_ptr_;
+  }
 
   void SetUp() override {
     ::testing::Test::SetUp();
+    auto session_manager_client = std::make_unique<FakeSessionManagerClient>();
+    session_manager_client_ptr_ = session_manager_client.get();
     DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::make_unique<FakeSessionManagerClient>());
+        std::move(session_manager_client));
     DBusThreadManager::GetSetterForTesting()->SetCryptohomeClient(
         std::make_unique<FakeCryptohomeClient>());
     auto auth_policy_client = std::make_unique<FakeAuthPolicyClient>();
@@ -84,6 +91,7 @@
 
  private:
   FakeAuthPolicyClient* auth_policy_client_ptr_;  // not owned.
+  FakeSessionManagerClient* session_manager_client_ptr_;  // not owned.
   base::MessageLoop loop_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeAuthPolicyClientTest);
@@ -287,4 +295,44 @@
   loop.Run();
 }
 
+// Tests that RefreshDevicePolicy stores device policy in the session manager.
+TEST_F(FakeAuthPolicyClientTest, RefreshDevicePolicyStoresPolicy) {
+  authpolicy_client()->set_started(true);
+  LockDeviceActiveDirectory();
+
+  {
+    // Call RefreshDevicePolicy.
+    base::RunLoop loop;
+    em::ChromeDeviceSettingsProto policy;
+    policy.mutable_allow_new_users()->set_allow_new_users(true);
+    authpolicy_client()->set_device_policy(policy);
+    authpolicy_client()->RefreshDevicePolicy(base::BindOnce(
+        [](base::OnceClosure closure, authpolicy::ErrorType error) {
+          EXPECT_EQ(authpolicy::ERROR_NONE, error);
+          std::move(closure).Run();
+        },
+        loop.QuitClosure()));
+    loop.Run();
+  }
+
+  {
+    // Retrieve device policy from the session manager.
+    std::string response_blob;
+    EXPECT_EQ(
+        SessionManagerClient::RetrievePolicyResponseType::SUCCESS,
+        session_manager_client()->BlockingRetrieveDevicePolicy(&response_blob));
+    em::PolicyFetchResponse response;
+    EXPECT_TRUE(response.ParseFromString(response_blob));
+    EXPECT_TRUE(response.has_policy_data());
+
+    em::PolicyData policy_data;
+    EXPECT_TRUE(policy_data.ParseFromString(response.policy_data()));
+
+    em::ChromeDeviceSettingsProto policy;
+    EXPECT_TRUE(policy.ParseFromString(policy_data.policy_value()));
+    EXPECT_TRUE(policy.has_allow_new_users());
+    EXPECT_TRUE(policy.allow_new_users().allow_new_users());
+  }
+}
+
 }  // namespace chromeos
diff --git a/chromeos/services/assistant/public/mojom/BUILD.gn b/chromeos/services/assistant/public/mojom/BUILD.gn
index 2e2a0da..e068ff59 100644
--- a/chromeos/services/assistant/public/mojom/BUILD.gn
+++ b/chromeos/services/assistant/public/mojom/BUILD.gn
@@ -11,7 +11,7 @@
   ]
 
   public_deps = [
-    "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//services/identity/public/mojom",
     "//url/mojom:url_mojom_gurl",
   ]
diff --git a/chromeos/services/assistant/public/mojom/assistant.mojom b/chromeos/services/assistant/public/mojom/assistant.mojom
index 179ec17e..5e65d3f 100644
--- a/chromeos/services/assistant/public/mojom/assistant.mojom
+++ b/chromeos/services/assistant/public/mojom/assistant.mojom
@@ -5,7 +5,7 @@
 module chromeos.assistant.mojom;
 
 import "url/mojom/url.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 // Interface to communicate with assistant backend.
 interface Assistant {
@@ -52,7 +52,7 @@
   // Notifies that audio frames are available.
   // TODO(muyuanli): Use data pipe.
   OnAudioInputFramesAvailable(array<int32> buffer, uint32 frame_count,
-                              mojo.common.mojom.TimeTicks timestamp);
+                              mojo_base.mojom.TimeTicks timestamp);
   // Notifies that audio input stream is closed.
   OnAudioInputClosed();
 };
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 2e842446..1be4632 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -175,6 +175,7 @@
   if (is_ios) {
     deps += [
       "//components/autofill/ios/browser:unit_tests",
+      "//components/autofill/ios/fill:unit_tests",
       "//components/image_fetcher/ios:unit_tests",
       "//components/signin/ios/browser:unit_tests",
       "//components/translate/ios/browser:unit_tests",
diff --git a/components/arc/common/file_system.mojom b/components/arc/common/file_system.mojom
index b3c2ef2..246bd13f 100644
--- a/components/arc/common/file_system.mojom
+++ b/components/arc/common/file_system.mojom
@@ -24,7 +24,7 @@
 
   // Timestamp when the document was modified last time, in milliseconds
   // since UNIX epoch.
-  // TODO(crbug.com/672737): Use mojo.common.mojom.Time once the type is
+  // TODO(crbug.com/672737): Use mojo_base.mojom.Time once the type is
   // converted to a non-native type so that it can be used from Java.
   uint64 last_modified;
 
diff --git a/components/arc/common/policy.mojom b/components/arc/common/policy.mojom
index 59aa7f0..2c0f0258 100644
--- a/components/arc/common/policy.mojom
+++ b/components/arc/common/policy.mojom
@@ -6,7 +6,7 @@
 
 module arc.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 [Extensible]
 //See depot/google3/wireless/android/enterprise/clouddps/proto/clouddps.proto
@@ -64,14 +64,14 @@
   [MinVersion=1] ReportCompliance@1(string request) => (string response);
 
   // Reports that request was sent to CloudDPS for set of packages.
-  [MinVersion=3] ReportCloudDpsRequested(mojo.common.mojom.Time time,
+  [MinVersion=3] ReportCloudDpsRequested(mojo_base.mojom.Time time,
                                          array<string> package_names);
   // Reports that successful response was received from CloudDPS for set of
   // packages.
-  [MinVersion=3] ReportCloudDpsSucceeded(mojo.common.mojom.Time time,
+  [MinVersion=3] ReportCloudDpsSucceeded(mojo_base.mojom.Time time,
                                          array<string> package_names);
   // Reports that CloudDPS reports an error for packages.
-  [MinVersion=3] ReportCloudDpsFailed(mojo.common.mojom.Time time,
+  [MinVersion=3] ReportCloudDpsFailed(mojo_base.mojom.Time time,
                                       string package_name,
                                       InstallErrorReason reason);
 };
diff --git a/components/arc/common/timer.mojom b/components/arc/common/timer.mojom
index f42fb94..6efb88e 100644
--- a/components/arc/common/timer.mojom
+++ b/components/arc/common/timer.mojom
@@ -6,7 +6,7 @@
 
 module arc.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 [Extensible]
 enum ArcTimerResult {
@@ -37,7 +37,7 @@
   // performed as an 8-byte write to the associated expiration fd. Returns
   // |ArcTimerResult::SUCCESS| if the timer can be started and
   // |ArcTimerResult::FAILURE| otherwise.
-  Start@0(mojo.common.mojom.TimeTicks absolute_expiration_time)
+  Start@0(mojo_base.mojom.TimeTicks absolute_expiration_time)
     => (ArcTimerResult result);
 };
 
diff --git a/components/autofill/content/common/autofill_driver.mojom b/components/autofill/content/common/autofill_driver.mojom
index e75d6fa..b867163 100644
--- a/components/autofill/content/common/autofill_driver.mojom
+++ b/components/autofill/content/common/autofill_driver.mojom
@@ -7,7 +7,7 @@
 import "components/autofill/content/common/autofill_types.mojom";
 import "mojo/public/mojom/base/string16.mojom";
 import "mojo/common/text_direction.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 import "url/mojom/url.mojom";
 
@@ -16,7 +16,7 @@
 interface AutofillDriver {
   // Notification that forms have been seen that are candidates for
   // filling/submitting by the AutofillManager.
-  FormsSeen(array<FormData> forms, mojo.common.mojom.TimeTicks timestamp);
+  FormsSeen(array<FormData> forms, mojo_base.mojom.TimeTicks timestamp);
 
   // Notification that a form has been submitted. The |known_success| indicates
   // whether the submission succeeded or not. Currently, we assume submission
@@ -24,13 +24,13 @@
   FormSubmitted(FormData form,
                 bool known_success,
                 SubmissionSource source,
-                mojo.common.mojom.TimeTicks timestamp);
+                mojo_base.mojom.TimeTicks timestamp);
 
   // Notification that a form field's value has changed.
   TextFieldDidChange(FormData form,
                      FormFieldData field,
                      gfx.mojom.RectF bounding_box,
-                     mojo.common.mojom.TimeTicks timestamp);
+                     mojo_base.mojom.TimeTicks timestamp);
 
   // Notification that a form field has scrolled.
   TextFieldDidScroll(FormData form,
@@ -61,7 +61,7 @@
                    gfx.mojom.RectF bounding_box);
 
   // Sent when a form is filled with Autofill suggestions.
-  DidFillAutofillFormData(FormData form, mojo.common.mojom.TimeTicks timestamp);
+  DidFillAutofillFormData(FormData form, mojo_base.mojom.TimeTicks timestamp);
 
   // Sent when a form is previewed with Autofill suggestions.
   DidPreviewAutofillFormData();
diff --git a/components/autofill/content/common/autofill_types.mojom b/components/autofill/content/common/autofill_types.mojom
index 7ffb633..61426fa 100644
--- a/components/autofill/content/common/autofill_types.mojom
+++ b/components/autofill/content/common/autofill_types.mojom
@@ -5,7 +5,7 @@
 module autofill.mojom;
 
 import "mojo/common/text_direction.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "mojo/public/mojom/base/string16.mojom";
 import "url/mojom/origin.mojom";
 import "url/mojom/url.mojom";
@@ -212,8 +212,8 @@
   bool new_password_marked_by_site;
   mojo_base.mojom.String16 confirmation_password_element;
   bool preferred;
-  mojo.common.mojom.Time date_created;
-  mojo.common.mojom.Time date_synced;
+  mojo_base.mojom.Time date_created;
+  mojo_base.mojom.Time date_synced;
   bool blacklisted_by_user;
   PasswordFormType type;
   int32 times_used;
diff --git a/components/autofill/content/common/autofill_types_struct_traits.cc b/components/autofill/content/common/autofill_types_struct_traits.cc
index 6a8cfe6..aab4414 100644
--- a/components/autofill/content/common/autofill_types_struct_traits.cc
+++ b/components/autofill/content/common/autofill_types_struct_traits.cc
@@ -6,8 +6,8 @@
 
 #include "base/i18n/rtl.h"
 #include "mojo/common/common_custom_types_struct_traits.h"
-#include "mojo/common/time_struct_traits.h"
 #include "mojo/public/cpp/base/string16_mojom_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "url/mojom/origin_mojom_traits.h"
 #include "url/mojom/url_gurl_mojom_traits.h"
 
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index 0f10d069..ad18985 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -387,6 +387,9 @@
 
 void AutofillAgent::DoAcceptDataListSuggestion(
     const base::string16& suggested_value) {
+  if (element_.IsNull())
+    return;
+
   WebInputElement* input_element = ToWebInputElement(&element_);
   DCHECK(input_element);
   base::string16 new_value = suggested_value;
@@ -418,6 +421,9 @@
 
 // mojom::AutofillAgent:
 void AutofillAgent::FillForm(int32_t id, const FormData& form) {
+  if (element_.IsNull())
+    return;
+
   if (id != autofill_query_id_ && id != kNoQueryId)
     return;
 
@@ -430,6 +436,9 @@
 }
 
 void AutofillAgent::PreviewForm(int32_t id, const FormData& form) {
+  if (element_.IsNull())
+    return;
+
   if (id != autofill_query_id_)
     return;
 
@@ -441,6 +450,9 @@
 
 void AutofillAgent::FieldTypePredictionsAvailable(
     const std::vector<FormDataPredictions>& forms) {
+  if (element_.IsNull())
+    return;
+
   bool attach_predictions_to_dom =
       base::FeatureList::IsEnabled(features::kAutofillShowTypePredictions);
   for (const auto& form : forms) {
@@ -449,6 +461,9 @@
 }
 
 void AutofillAgent::ClearForm() {
+  if (element_.IsNull())
+    return;
+
   form_cache_.ClearFormWithElement(element_);
 }
 
@@ -467,6 +482,9 @@
 }
 
 void AutofillAgent::FillFieldWithValue(const base::string16& value) {
+  if (element_.IsNull())
+    return;
+
   WebInputElement* input_element = ToWebInputElement(&element_);
   if (input_element) {
     DoFillFieldWithValue(value, input_element);
@@ -475,6 +493,9 @@
 }
 
 void AutofillAgent::PreviewFieldWithValue(const base::string16& value) {
+  if (element_.IsNull())
+    return;
+
   WebInputElement* input_element = ToWebInputElement(&element_);
   if (input_element)
     DoPreviewFieldWithValue(value, input_element);
@@ -486,6 +507,9 @@
 
 void AutofillAgent::FillPasswordSuggestion(const base::string16& username,
                                            const base::string16& password) {
+  if (element_.IsNull())
+    return;
+
   bool handled =
       password_autofill_agent_->FillSuggestion(element_, username, password);
   DCHECK(handled);
@@ -493,6 +517,9 @@
 
 void AutofillAgent::PreviewPasswordSuggestion(const base::string16& username,
                                               const base::string16& password) {
+  if (element_.IsNull())
+    return;
+
   bool handled = password_autofill_agent_->PreviewSuggestion(
       element_, blink::WebString::FromUTF16(username),
       blink::WebString::FromUTF16(password));
diff --git a/components/autofill/ios/browser/autofill_agent.mm b/components/autofill/ios/browser/autofill_agent.mm
index 4752dde..d4fd1839 100644
--- a/components/autofill/ios/browser/autofill_agent.mm
+++ b/components/autofill/ios/browser/autofill_agent.mm
@@ -726,7 +726,11 @@
 
   web::URLVerificationTrustLevel trustLevel;
   const GURL pageURL(webState->GetCurrentURL(&trustLevel));
+  [jsAutofillManager_ trackFormUpdates];
+  [self scanFormsInPage:webState pageURL:pageURL];
+}
 
+- (void)scanFormsInPage:(web::WebState*)webState pageURL:(const GURL&)pageURL {
   __weak AutofillAgent* weakSelf = self;
   id completionHandler = ^(BOOL success, const FormDataVector& forms) {
     AutofillAgent* strongSelf = weakSelf;
@@ -764,6 +768,17 @@
   // page is fully loaded.
   [self processPage:webState];
 
+  web::URLVerificationTrustLevel trustLevel;
+  const GURL pageURL(webState->GetCurrentURL(&trustLevel));
+
+  // If the event is a form_changed, then the event concerns the whole page and
+  // not a particular form. The whole page need to be reparsed to find the new
+  // forms.
+  if (params.type.compare("form_changed") == 0) {
+    [self scanFormsInPage:webState pageURL:pageURL];
+    return;
+  }
+
   // Blur not handled; we don't reset the suggestion state because if the
   // keyboard is about to be dismissed there's no point. If not it means the
   // next focus event will update the suggestion state within milliseconds, so
@@ -785,9 +800,6 @@
     }
   };
 
-  web::URLVerificationTrustLevel trustLevel;
-  const GURL pageURL(webState->GetCurrentURL(&trustLevel));
-
   // Re-extract the active form and field only. There is no minimum field
   // requirement because key/value suggestions are offered even on short forms.
   [self fetchFormsFiltered:YES
diff --git a/components/autofill/ios/browser/js_autofill_manager.h b/components/autofill/ios/browser/js_autofill_manager.h
index 02764c44..40e26028 100644
--- a/components/autofill/ios/browser/js_autofill_manager.h
+++ b/components/autofill/ios/browser/js_autofill_manager.h
@@ -52,6 +52,9 @@
 // Adds a delay between filling the form fields.
 - (void)addJSDelay;
 
+// Installs a tracker to check the form updates in the page every 500ms.
+- (void)trackFormUpdates;
+
 // Designated initializer. |receiver| should not be nil.
 - (instancetype)initWithReceiver:(CRWJSInjectionReceiver*)receiver
     NS_DESIGNATED_INITIALIZER;
diff --git a/components/autofill/ios/browser/js_autofill_manager.mm b/components/autofill/ios/browser/js_autofill_manager.mm
index 765b2ee..f8d4bc49 100644
--- a/components/autofill/ios/browser/js_autofill_manager.mm
+++ b/components/autofill/ios/browser/js_autofill_manager.mm
@@ -74,6 +74,11 @@
              }];
 }
 
+- (void)trackFormUpdates {
+  [_receiver executeJavaScript:@"__gCrWeb.form.trackFormUpdates(500)"
+             completionHandler:nil];
+}
+
 - (void)fillForm:(NSString*)dataString
     forceFillFieldName:(NSString*)forceFillFieldName
      completionHandler:(ProceduralBlock)completionHandler {
diff --git a/components/autofill/ios/fill/BUILD.gn b/components/autofill/ios/fill/BUILD.gn
new file mode 100644
index 0000000..2feac5a4
--- /dev/null
+++ b/components/autofill/ios/fill/BUILD.gn
@@ -0,0 +1,30 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//ios/web/js_compile.gni")
+import("//testing/test.gni")
+
+source_set("unit_tests") {
+  testonly = true
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "form_unittest.mm",
+  ]
+  deps = [
+    ":form_js",
+    "//base",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
+    "//ios/web/web_state/js",
+    "//testing/gtest",
+  ]
+}
+
+js_compile_checked("form_js") {
+  visibility = [ ":unit_tests" ]
+  testonly = true
+  sources = [
+    "resources/form.js",
+  ]
+}
diff --git a/components/autofill/ios/fill/DEPS b/components/autofill/ios/fill/DEPS
new file mode 100644
index 0000000..8ef0014
--- /dev/null
+++ b/components/autofill/ios/fill/DEPS
@@ -0,0 +1,5 @@
+specific_include_rules = {
+  "form_unittest\.mm": [
+    "+ios/web/web_state/js/page_script_util.h",
+  ],
+}
diff --git a/components/autofill/ios/fill/form_unittest.mm b/components/autofill/ios/fill/form_unittest.mm
new file mode 100644
index 0000000..e8067d04
--- /dev/null
+++ b/components/autofill/ios/fill/form_unittest.mm
@@ -0,0 +1,152 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/web/public/browser_state.h"
+#import "ios/web/public/test/fakes/test_web_client.h"
+#include "ios/web/public/test/fakes/test_web_state_observer.h"
+#import "ios/web/public/test/web_js_test.h"
+#import "ios/web/public/test/web_test_with_web_state.h"
+#import "ios/web/web_state/js/page_script_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+class FormTestClient : public web::TestWebClient {
+ public:
+  NSString* GetDocumentStartScriptForAllFrames(
+      web::BrowserState* browser_state) const override {
+    return web::GetPageScript(@"form");
+  }
+};
+
+// Text fixture to test password controller.
+class FormJsTest : public web::WebJsTest<web::WebTestWithWebState> {
+ public:
+  FormJsTest()
+      : web::WebJsTest<web::WebTestWithWebState>(
+            std::make_unique<FormTestClient>()) {}
+};
+
+// Tests that keyup event correctly delivered to WebStateObserver.
+TEST_F(FormJsTest, KeyUpEvent) {
+  web::TestWebStateObserver observer(web_state());
+  LoadHtml(@"<p></p>");
+  ASSERT_FALSE(observer.form_activity_info());
+  ExecuteJavaScript(@"document.dispatchEvent(new KeyboardEvent('keyup'));");
+  web::TestFormActivityInfo* info = observer.form_activity_info();
+  ASSERT_TRUE(info);
+  EXPECT_EQ("keyup", info->form_activity.type);
+  EXPECT_FALSE(info->form_activity.input_missing);
+}
+
+// Tests that focus event correctly delivered to WebStateObserver.
+TEST_F(FormJsTest, FocusMainFrame) {
+  web::TestWebStateObserver observer(web_state());
+  LoadHtml(
+      @"<form>"
+       "<input type='text' name='username' id='id1'>"
+       "<input type='password' name='password' id='id2'>"
+       "</form>");
+  ASSERT_FALSE(observer.form_activity_info());
+  ExecuteJavaScript(@"document.getElementById('id1').focus();");
+  web::TestFormActivityInfo* info = observer.form_activity_info();
+  ASSERT_TRUE(info);
+  EXPECT_EQ("focus", info->form_activity.type);
+  EXPECT_FALSE(info->form_activity.input_missing);
+}
+
+// Tests that submit event correctly delivered to WebStateObserver.
+TEST_F(FormJsTest, FormSubmitMainFrame) {
+  web::TestWebStateObserver observer(web_state());
+  LoadHtml(
+      @"<form id='form1'>"
+       "<input type='password'>"
+       "<input type='submit' id='submit_input'/>"
+       "</form>");
+  ASSERT_FALSE(observer.submit_document_info());
+  ExecuteJavaScript(@"document.getElementById('submit_input').click();");
+  web::TestSubmitDocumentInfo* info = observer.submit_document_info();
+  ASSERT_TRUE(info);
+  EXPECT_EQ("form1", info->form_name);
+}
+
+// Tests that focus event from same-origin iframe correctly delivered to
+// WebStateObserver.
+TEST_F(FormJsTest, FocusSameOriginIFrame) {
+  web::TestWebStateObserver observer(web_state());
+  LoadHtml(@"<iframe id='frame1'></iframe>");
+  ExecuteJavaScript(
+      @"document.getElementById('frame1').contentDocument.body.innerHTML = "
+       "'<form>"
+       "<input type=\"text\" name=\"username\" id=\"id1\">"
+       "<input type=\"password\" name=\"password\" id=\"id2\">"
+       "</form>'");
+
+  ExecuteJavaScript(
+      @"document.getElementById('frame1').contentDocument.getElementById('id1')"
+      @".focus()");
+  web::TestFormActivityInfo* info = observer.form_activity_info();
+  ASSERT_TRUE(info);
+  EXPECT_EQ("focus", info->form_activity.type);
+  EXPECT_FALSE(info->form_activity.input_missing);
+}
+
+// Tests that submit event from same-origin iframe correctly delivered to
+// WebStateObserver.
+TEST_F(FormJsTest, FormSameOriginIFrame) {
+  web::TestWebStateObserver observer(web_state());
+  LoadHtml(@"<iframe id='frame1'></iframe>");
+  ExecuteJavaScript(
+      @"document.getElementById('frame1').contentDocument.body.innerHTML = "
+       "'<form id=\"form1\">"
+       "<input type=\"password\" name=\"password\" id=\"id2\">"
+       "<input type=\"submit\" id=\"submit_input\"/>"
+       "</form>'");
+  ExecuteJavaScript(
+      @"document.getElementById('frame1').contentDocument.getElementById('"
+      @"submit_input').click();");
+  web::TestSubmitDocumentInfo* info = observer.submit_document_info();
+  ASSERT_TRUE(info);
+  EXPECT_EQ("form1", info->form_name);
+}
+
+// Tests that new form triggers form changed event.
+TEST_F(FormJsTest, FocusAddForm) {
+  web::TestWebStateObserver observer(web_state());
+  LoadHtml(@"<form/>");
+
+  ExecuteJavaScript(
+      @"__gCrWeb.form.trackFormUpdates(10);"
+      @"var form = document.createElement('form');"
+      @"document.body.appendChild(form);");
+  web::TestWebStateObserver* block_observer = &observer;
+  __block web::TestFormActivityInfo* info = nil;
+  WaitForCondition(^{
+    info = block_observer->form_activity_info();
+    return info != nil;
+  });
+  EXPECT_EQ("form_changed", info->form_activity.type);
+  EXPECT_FALSE(info->form_activity.input_missing);
+}
+
+// Tests that new input triggers form changed event.
+TEST_F(FormJsTest, FocusAddInput) {
+  web::TestWebStateObserver observer(web_state());
+  LoadHtml(@"<form id='formId'/>");
+
+  ExecuteJavaScript(
+      @"__gCrWeb.form.trackFormUpdates(10);"
+      @"var input = document.createElement('input');"
+      @"document.getElementById('formId').appendChild(input);");
+  web::TestWebStateObserver* block_observer = &observer;
+  __block web::TestFormActivityInfo* info = nil;
+  WaitForCondition(^{
+    info = block_observer->form_activity_info();
+    return info != nil;
+  });
+  EXPECT_EQ("form_changed", info->form_activity.type);
+  EXPECT_FALSE(info->form_activity.input_missing);
+}
diff --git a/ios/web/web_state/js/resources/form.js b/components/autofill/ios/fill/resources/form.js
similarity index 85%
rename from ios/web/web_state/js/resources/form.js
rename to components/autofill/ios/fill/resources/form.js
index 1eb2725..9e6c91d 100644
--- a/ios/web/web_state/js/resources/form.js
+++ b/components/autofill/ios/fill/resources/form.js
@@ -11,8 +11,6 @@
 
 goog.provide('__crWeb.form');
 
-goog.require('__crWeb.message');
-
 /**
  * Namespace for this file. It depends on |__gCrWeb| having already been
  * injected. String 'form' is used in |__gCrWeb['form']| as it needs to be
@@ -51,6 +49,17 @@
 __gCrWeb.form.kNamelessFieldIDPrefix = 'gChrome~field~';
 
 /**
+ * The interval watching for form changes.
+ */
+__gCrWeb.form.formWatcherInterval = null;
+
+/**
+ * The value of the form signature last time formWatcherInterval was
+ * triggerred.
+ */
+__gCrWeb.form.lastFormSignature = {};
+
+/**
  * Based on Element::isFormControlElement() (WebKit)
  * @param {Element} element A DOM element.
  * @return {boolean} true if the |element| is a form control element.
@@ -282,6 +291,48 @@
   return anchor.href;
 };
 
+  /**
+   * Returns a simple signature of the form content of the page. Must be fast
+   * as it is called regularly.
+   */
+  var getFormSignature_ = function() {
+    return {
+      forms: document.forms.length,
+      input: document.getElementsByTagName('input').length
+    };
+  };
+
+  /**
+   * Install a watcher to check the form changes. Delay is the interval between
+   * checks in milliseconds.
+   */
+  __gCrWeb.form['trackFormUpdates'] = function(delay) {
+    if (__gCrWeb.form.formWatcherInterval) {
+      clearInterval(__gCrWeb.form.formWatcherInterval);
+      __gCrWeb.form.formWatcherInterval = null;
+    }
+    if (delay) {
+      __gCrWeb.form.lastFormSignature = getFormSignature_();
+      __gCrWeb.form.formWatcherInterval = setInterval(function() {
+        var signature = getFormSignature_();
+        var old_signature = __gCrWeb.form.lastFormSignature;
+        if (signature.forms != old_signature.forms ||
+            signature.input != old_signature.input) {
+          var msg = {
+            'command': 'form.activity',
+            'formName': '',
+            'fieldName': '',
+            'fieldType': '',
+            'type': 'form_changed',
+            'value': ''
+          };
+          __gCrWeb.form.lastFormSignature = signature;
+          __gCrWeb.message.invokeOnHost(msg);
+        }
+      }, delay);
+    }
+  };
+
 /** Flush the message queue. */
 if (__gCrWeb.message) {
   __gCrWeb.message.invokeQueues();
diff --git a/components/download/internal/common/BUILD.gn b/components/download/internal/common/BUILD.gn
index e9aba21..8894045 100644
--- a/components/download/internal/common/BUILD.gn
+++ b/components/download/internal/common/BUILD.gn
@@ -27,6 +27,7 @@
     "download_utils.cc",
     "parallel_download_utils.cc",
     "rate_estimator.cc",
+    "resource_downloader.cc",
     "stream_handle_input_stream.cc",
   ]
 
diff --git a/content/browser/download/resource_downloader.cc b/components/download/internal/common/resource_downloader.cc
similarity index 88%
rename from content/browser/download/resource_downloader.cc
rename to components/download/internal/common/resource_downloader.cc
index 7f6ca04..6f1d74a 100644
--- a/content/browser/download/resource_downloader.cc
+++ b/components/download/internal/common/resource_downloader.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/download/resource_downloader.h"
+#include "components/download/public/common/resource_downloader.h"
 
 #include <memory>
 
@@ -14,7 +14,7 @@
 struct ResourceResponseHead;
 }
 
-namespace content {
+namespace download {
 
 // This object monitors the URLLoaderCompletionStatus change when
 // ResourceDownloader is asking |delegate_| whether download can proceed.
@@ -59,7 +59,7 @@
 // static
 std::unique_ptr<ResourceDownloader> ResourceDownloader::BeginDownload(
     base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
-    std::unique_ptr<download::DownloadUrlParameters> params,
+    std::unique_ptr<DownloadUrlParameters> params,
     std::unique_ptr<network::ResourceRequest> request,
     scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
     const GURL& site_url,
@@ -129,15 +129,15 @@
 
 void ResourceDownloader::Start(
     scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
-    std::unique_ptr<download::DownloadUrlParameters> download_url_parameters,
+    std::unique_ptr<DownloadUrlParameters> download_url_parameters,
     bool is_parallel_request) {
   callback_ = download_url_parameters->callback();
   guid_ = download_url_parameters->guid();
 
   // Set up the URLLoaderClient.
-  url_loader_client_ = std::make_unique<download::DownloadResponseHandler>(
+  url_loader_client_ = std::make_unique<DownloadResponseHandler>(
       resource_request_.get(), this,
-      std::make_unique<download::DownloadSaveInfo>(
+      std::make_unique<DownloadSaveInfo>(
           download_url_parameters->GetSaveInfo()),
       is_parallel_request, download_url_parameters->is_transient(),
       download_url_parameters->fetch_error_body(),
@@ -174,13 +174,12 @@
   url_loader_.Bind(std::move(endpoints->url_loader));
 
   // Create the new URLLoaderClient that will intercept the navigation.
-  auto save_info = std::make_unique<download::DownloadSaveInfo>();
+  auto save_info = std::make_unique<DownloadSaveInfo>();
   if (suggested_filename.has_value())
     save_info->suggested_name = base::UTF8ToUTF16(suggested_filename.value());
-  url_loader_client_ = std::make_unique<download::DownloadResponseHandler>(
+  url_loader_client_ = std::make_unique<DownloadResponseHandler>(
       resource_request_.get(), this, std::move(save_info), false, false, false,
-      std::string(), download::DownloadSource::NAVIGATION,
-      std::move(url_chain));
+      std::string(), DownloadSource::NAVIGATION, std::move(url_chain));
 
   // Simulate on the new URLLoaderClient calls that happened on the old client.
   net::SSLInfo info;
@@ -196,8 +195,8 @@
 }
 
 void ResourceDownloader::OnResponseStarted(
-    std::unique_ptr<download::DownloadCreateInfo> download_create_info,
-    download::mojom::DownloadStreamHandlePtr stream_handle) {
+    std::unique_ptr<DownloadCreateInfo> download_create_info,
+    mojom::DownloadStreamHandlePtr stream_handle) {
   download_create_info->download_id = download_id_;
   download_create_info->guid = guid_;
   download_create_info->site_url = site_url_;
@@ -208,15 +207,15 @@
 
   delegate_task_runner_->PostTask(
       FROM_HERE,
-      base::BindOnce(&UrlDownloadHandler::Delegate::OnUrlDownloadStarted,
-                     delegate_, std::move(download_create_info),
-                     std::make_unique<download::StreamHandleInputStream>(
-                         std::move(stream_handle)),
-                     callback_));
+      base::BindOnce(
+          &UrlDownloadHandler::Delegate::OnUrlDownloadStarted, delegate_,
+          std::move(download_create_info),
+          std::make_unique<StreamHandleInputStream>(std::move(stream_handle)),
+          callback_));
 }
 
 void ResourceDownloader::OnReceiveRedirect() {
   url_loader_->FollowRedirect();
 }
 
-}  // namespace content
+}  // namespace download
diff --git a/components/download/public/common/BUILD.gn b/components/download/public/common/BUILD.gn
index e1d98fcd..fb9f727 100644
--- a/components/download/public/common/BUILD.gn
+++ b/components/download/public/common/BUILD.gn
@@ -47,6 +47,7 @@
     "input_stream.h",
     "parallel_download_utils.h",
     "rate_estimator.h",
+    "resource_downloader.h",
     "resume_mode.h",
     "stream_handle_input_stream.h",
   ]
diff --git a/content/browser/download/resource_downloader.h b/components/download/public/common/resource_downloader.h
similarity index 87%
rename from content/browser/download/resource_downloader.h
rename to components/download/public/common/resource_downloader.h
index a22250a..3a587b8 100644
--- a/content/browser/download/resource_downloader.h
+++ b/components/download/public/common/resource_downloader.h
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_BROWSER_DOWNLOAD_RESOURCE_DOWNLOADER_
-#define CONTENT_BROWSER_DOWNLOAD_RESOURCE_DOWNLOADER_
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_RESOURCE_DOWNLOADER_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_RESOURCE_DOWNLOADER_H_
 
+#include "components/download/public/common/download_export.h"
 #include "components/download/public/common/download_response_handler.h"
-#include "content/browser/download/url_download_handler.h"
+#include "components/download/public/common/url_download_handler.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "net/cert/cert_status_flags.h"
 #include "services/network/public/cpp/resource_request.h"
@@ -16,15 +17,16 @@
 class SharedURLLoaderFactory;
 }
 
-namespace content {
+namespace download {
 
 // Class for handing the download of a url.
-class ResourceDownloader : public UrlDownloadHandler,
-                           public download::DownloadResponseHandler::Delegate {
+class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader
+    : public download::UrlDownloadHandler,
+      public download::DownloadResponseHandler::Delegate {
  public:
   // Called to start a download, must be called on IO thread.
   static std::unique_ptr<ResourceDownloader> BeginDownload(
-      base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+      base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
       std::unique_ptr<download::DownloadUrlParameters> download_url_parameters,
       std::unique_ptr<network::ResourceRequest> request,
       scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
@@ -86,7 +88,7 @@
       net::CertStatus cert_status,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints);
 
-  base::WeakPtr<UrlDownloadHandler::Delegate> delegate_;
+  base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate_;
 
   // The ResourceRequest for this object.
   std::unique_ptr<network::ResourceRequest> resource_request_;
@@ -135,6 +137,6 @@
   DISALLOW_COPY_AND_ASSIGN(ResourceDownloader);
 };
 
-}  // namespace content
+}  // namespace download
 
-#endif  // CONTENT_BROWSER_DOWNLOAD_RESOURCE_DOWNLOADER_
+#endif  // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_RESOURCE_DOWNLOADER_H_
diff --git a/components/download/public/common/url_download_handler.h b/components/download/public/common/url_download_handler.h
new file mode 100644
index 0000000..01102b5b
--- /dev/null
+++ b/components/download/public/common/url_download_handler.h
@@ -0,0 +1,37 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_URL_DOWNLOAD_HANDLER_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_URL_DOWNLOAD_HANDLER_H_
+
+#include "components/download/public/common/download_export.h"
+#include "components/download/public/common/download_url_parameters.h"
+
+namespace download {
+struct DownloadCreateInfo;
+class InputStream;
+
+// Class for handling the download of a url. Implemented by child classes.
+class COMPONENTS_DOWNLOAD_EXPORT UrlDownloadHandler {
+ public:
+  // Class to be notified when download starts/stops.
+  class COMPONENTS_DOWNLOAD_EXPORT Delegate {
+   public:
+    virtual void OnUrlDownloadStarted(
+        std::unique_ptr<DownloadCreateInfo> download_create_info,
+        std::unique_ptr<InputStream> input_stream,
+        const DownloadUrlParameters::OnStartedCallback& callback) = 0;
+    // Called after the connection is cancelled or finished.
+    virtual void OnUrlDownloadStopped(UrlDownloadHandler* downloader) = 0;
+  };
+
+  UrlDownloadHandler() = default;
+  virtual ~UrlDownloadHandler() = default;
+
+  DISALLOW_COPY_AND_ASSIGN(UrlDownloadHandler);
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_URL_DOWNLOAD_HANDLER_H_
diff --git a/components/drive/chromeos/dummy_file_system.h b/components/drive/chromeos/dummy_file_system.h
index 6a35125..e46935c 100644
--- a/components/drive/chromeos/dummy_file_system.h
+++ b/components/drive/chromeos/dummy_file_system.h
@@ -90,6 +90,8 @@
   void MarkCacheFileAsUnmounted(
       const base::FilePath& cache_file_path,
       const FileOperationCallback& callback) override {}
+  void IsCacheFileMarkedAsMounted(const base::FilePath& drive_file_path,
+                                  const IsMountedCallback& callback) override {}
   void AddPermission(const base::FilePath& drive_file_path,
                      const std::string& email,
                      google_apis::drive::PermissionRole role,
diff --git a/components/drive/chromeos/fake_file_system.cc b/components/drive/chromeos/fake_file_system.cc
index a80ef918..9fae65f 100644
--- a/components/drive/chromeos/fake_file_system.cc
+++ b/components/drive/chromeos/fake_file_system.cc
@@ -131,6 +131,12 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
+void FakeFileSystem::IsCacheFileMarkedAsMounted(
+    const base::FilePath& drive_file_path,
+    const IsMountedCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
 base::Closure FakeFileSystem::GetFileContent(
     const base::FilePath& file_path,
     const GetFileContentInitializedCallback& initialized_callback,
diff --git a/components/drive/chromeos/fake_file_system.h b/components/drive/chromeos/fake_file_system.h
index e892bd9a..e3f6bd05 100644
--- a/components/drive/chromeos/fake_file_system.h
+++ b/components/drive/chromeos/fake_file_system.h
@@ -117,6 +117,8 @@
                               const MarkMountedCallback& callback) override;
   void MarkCacheFileAsUnmounted(const base::FilePath& cache_file_path,
                                 const FileOperationCallback& callback) override;
+  void IsCacheFileMarkedAsMounted(const base::FilePath& drive_file_path,
+                                  const IsMountedCallback& callback) override;
   void AddPermission(const base::FilePath& drive_file_path,
                      const std::string& email,
                      google_apis::drive::PermissionRole role,
diff --git a/components/drive/chromeos/file_cache.cc b/components/drive/chromeos/file_cache.cc
index 927e16b..49b0fcce 100644
--- a/components/drive/chromeos/file_cache.cc
+++ b/components/drive/chromeos/file_cache.cc
@@ -475,6 +475,11 @@
   return FILE_ERROR_OK;
 }
 
+bool FileCache::IsMarkedAsMounted(const std::string& id) {
+  AssertOnSequencedWorkerPool();
+  return mounted_files_.count(id);
+}
+
 FileError FileCache::MarkAsMounted(const std::string& id,
                                    base::FilePath* cache_file_path) {
   AssertOnSequencedWorkerPool();
diff --git a/components/drive/chromeos/file_cache.h b/components/drive/chromeos/file_cache.h
index ab23b62..8d58c30 100644
--- a/components/drive/chromeos/file_cache.h
+++ b/components/drive/chromeos/file_cache.h
@@ -122,6 +122,9 @@
   FileError MarkAsMounted(const std::string& id,
                           base::FilePath* cache_file_path);
 
+  // Returns if a file corresponding to |id| is marked as mounted.
+  bool IsMarkedAsMounted(const std::string& id);
+
   // Sets the state of the cache entry corresponding to file_path as unmounted.
   FileError MarkAsUnmounted(const base::FilePath& file_path);
 
diff --git a/components/drive/chromeos/file_cache_unittest.cc b/components/drive/chromeos/file_cache_unittest.cc
index 14946c2..0357cc7 100644
--- a/components/drive/chromeos/file_cache_unittest.cc
+++ b/components/drive/chromeos/file_cache_unittest.cc
@@ -536,12 +536,16 @@
   base::FilePath cache_file_path;
   EXPECT_EQ(FILE_ERROR_OK, cache_->MarkAsMounted(id, &cache_file_path));
 
+  EXPECT_TRUE(cache_->IsMarkedAsMounted(id));
+
   // Try to remove it.
   EXPECT_EQ(FILE_ERROR_IN_USE, cache_->Remove(id));
 
   // Clear mounted state of the file.
   EXPECT_EQ(FILE_ERROR_OK, cache_->MarkAsUnmounted(cache_file_path));
 
+  EXPECT_FALSE(cache_->IsMarkedAsMounted(id));
+
   // Try to remove again.
   EXPECT_EQ(FILE_ERROR_OK, cache_->Remove(id));
 }
diff --git a/components/drive/chromeos/file_system.cc b/components/drive/chromeos/file_system.cc
index 4ea504da..a21fb11 100644
--- a/components/drive/chromeos/file_system.cc
+++ b/components/drive/chromeos/file_system.cc
@@ -145,6 +145,21 @@
   return cache->MarkAsMounted(local_id, cache_file_path);
 }
 
+// Used to implement IsCacheFileMarkedAsMounted().
+FileError IsCacheFileMarkedAsMountedInternal(
+    internal::ResourceMetadata* resource_metadata,
+    internal::FileCache* cache,
+    const base::FilePath& drive_file_path,
+    bool* result) {
+  std::string local_id;
+  FileError error = resource_metadata->GetIdByPath(drive_file_path, &local_id);
+  if (error != FILE_ERROR_OK)
+    return error;
+
+  *result = cache->IsMarkedAsMounted(local_id);
+  return FILE_ERROR_OK;
+}
+
 // Runs the callback with arguments.
 void RunMarkMountedCallback(const MarkMountedCallback& callback,
                             base::FilePath* cache_file_path,
@@ -153,6 +168,14 @@
   callback.Run(error, *cache_file_path);
 }
 
+// Runs the callback with arguments.
+void RunIsMountedCallback(const IsMountedCallback& callback,
+                          bool* result,
+                          FileError error) {
+  DCHECK(!callback.is_null());
+  callback.Run(error, *result);
+}
+
 // Callback for ResourceMetadata::GetLargestChangestamp.
 // |callback| must not be null.
 void OnGetLargestChangestamp(FileSystemMetadata metadata,  // Will be modified.
@@ -933,6 +956,20 @@
           &RunMarkMountedCallback, callback, base::Owned(cache_file_path)));
 }
 
+void FileSystem::IsCacheFileMarkedAsMounted(
+    const base::FilePath& drive_file_path,
+    const IsMountedCallback& callback) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(!callback.is_null());
+
+  bool* is_mounted = new bool(false);
+  base::PostTaskAndReplyWithResult(
+      blocking_task_runner_.get(), FROM_HERE,
+      base::Bind(&IsCacheFileMarkedAsMountedInternal, resource_metadata_,
+                 cache_, drive_file_path, is_mounted),
+      base::Bind(&RunIsMountedCallback, callback, base::Owned(is_mounted)));
+}
+
 void FileSystem::MarkCacheFileAsUnmounted(
     const base::FilePath& cache_file_path,
     const FileOperationCallback& callback) {
diff --git a/components/drive/chromeos/file_system.h b/components/drive/chromeos/file_system.h
index 7a87830..a575f300 100644
--- a/components/drive/chromeos/file_system.h
+++ b/components/drive/chromeos/file_system.h
@@ -149,6 +149,8 @@
   void GetMetadata(const GetFilesystemMetadataCallback& callback) override;
   void MarkCacheFileAsMounted(const base::FilePath& drive_file_path,
                               const MarkMountedCallback& callback) override;
+  void IsCacheFileMarkedAsMounted(const base::FilePath& drive_file_path,
+                                  const IsMountedCallback& callback) override;
   void MarkCacheFileAsUnmounted(const base::FilePath& cache_file_path,
                                 const FileOperationCallback& callback) override;
   void AddPermission(const base::FilePath& drive_file_path,
diff --git a/components/drive/chromeos/file_system_interface.h b/components/drive/chromeos/file_system_interface.h
index 043d5c0..9332d32 100644
--- a/components/drive/chromeos/file_system_interface.h
+++ b/components/drive/chromeos/file_system_interface.h
@@ -149,6 +149,10 @@
                             const base::FilePath& file_path)>
     MarkMountedCallback;
 
+// Used to check if a cached file is mounted.
+typedef base::Callback<void(FileError error, bool is_mounted)>
+    IsMountedCallback;
+
 // Used to get file path.
 typedef base::Callback<void(FileError error, const base::FilePath& file_path)>
     GetFilePathCallback;
@@ -442,6 +446,13 @@
   virtual void MarkCacheFileAsMounted(const base::FilePath& drive_file_path,
                                       const MarkMountedCallback& callback) = 0;
 
+  // Checks if the cached file is marked as mounted, and passes the result to
+  // |callback| upon completion. If the file was not found in the cache, the
+  // result is false. |callback| must not be null.
+  virtual void IsCacheFileMarkedAsMounted(
+      const base::FilePath& drive_file_path,
+      const IsMountedCallback& callback) = 0;
+
   // Marks the cached file as unmounted, and runs |callback| upon completion.
   // Note that this method expects that the |cached_file_path| is the path
   // returned by MarkCacheFileAsMounted().
diff --git a/components/drive/file_system_unittest.cc b/components/drive/file_system_unittest.cc
index 406c8183..2339f0c 100644
--- a/components/drive/file_system_unittest.cc
+++ b/components/drive/file_system_unittest.cc
@@ -1001,6 +1001,15 @@
   content::RunAllTasksUntilIdle();
   EXPECT_EQ(FILE_ERROR_OK, error);
 
+  error = FILE_ERROR_FAILED;
+  bool is_marked_as_mounted = false;
+  file_system_->IsCacheFileMarkedAsMounted(
+      file_in_root, google_apis::test_util::CreateCopyResultCallback(
+                        &error, &is_marked_as_mounted));
+  content::RunAllTasksUntilIdle();
+  EXPECT_EQ(FILE_ERROR_OK, error);
+  EXPECT_TRUE(is_marked_as_mounted);
+
   // Cannot remove a cache entry while it's being mounted.
   EXPECT_EQ(FILE_ERROR_IN_USE, cache_->Remove(entry->local_id()));
 
@@ -1012,6 +1021,15 @@
   content::RunAllTasksUntilIdle();
   EXPECT_EQ(FILE_ERROR_OK, error);
 
+  error = FILE_ERROR_FAILED;
+  is_marked_as_mounted = true;
+  file_system_->IsCacheFileMarkedAsMounted(
+      file_in_root, google_apis::test_util::CreateCopyResultCallback(
+                        &error, &is_marked_as_mounted));
+  content::RunAllTasksUntilIdle();
+  EXPECT_EQ(FILE_ERROR_OK, error);
+  EXPECT_FALSE(is_marked_as_mounted);
+
   // Now able to remove the cache entry.
   EXPECT_EQ(FILE_ERROR_OK, cache_->Remove(entry->local_id()));
 }
diff --git a/components/metrics/public/interfaces/call_stack_profile_collector.mojom b/components/metrics/public/interfaces/call_stack_profile_collector.mojom
index 7860cf1..c3c0ee74 100644
--- a/components/metrics/public/interfaces/call_stack_profile_collector.mojom
+++ b/components/metrics/public/interfaces/call_stack_profile_collector.mojom
@@ -4,8 +4,8 @@
 
 module metrics.mojom;
 
-import "mojo/common/time.mojom";
 import "mojo/public/mojom/base/file_path.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 // These structs mirror the corresponding types in base::StackSamplingProfiler.
 
@@ -28,8 +28,8 @@
 struct CallStackProfile {
   array<CallStackModule> modules;
   array<CallStackSample> samples;
-  mojo.common.mojom.TimeDelta profile_duration;
-  mojo.common.mojom.TimeDelta sampling_period;
+  mojo_base.mojom.TimeDelta profile_duration;
+  mojo_base.mojom.TimeDelta sampling_period;
 };
 
 enum Process {
@@ -80,6 +80,6 @@
 
 interface CallStackProfileCollector {
   Collect(CallStackProfileParams params,
-          mojo.common.mojom.TimeTicks start_timestamp,
+          mojo_base.mojom.TimeTicks start_timestamp,
           array<CallStackProfile> profiles);
 };
diff --git a/components/multidevice/service/public/interfaces/BUILD.gn b/components/multidevice/service/public/interfaces/BUILD.gn
index 00a11b79..69525c6 100644
--- a/components/multidevice/service/public/interfaces/BUILD.gn
+++ b/components/multidevice/service/public/interfaces/BUILD.gn
@@ -12,7 +12,7 @@
     ]
 
     public_deps = [
-      "//mojo/common:common_custom_types",
+      "//mojo/public/mojom/base",
     ]
   }
 }
diff --git a/components/multidevice/service/public/interfaces/device_sync.mojom b/components/multidevice/service/public/interfaces/device_sync.mojom
index 593c17a..787b8908 100644
--- a/components/multidevice/service/public/interfaces/device_sync.mojom
+++ b/components/multidevice/service/public/interfaces/device_sync.mojom
@@ -4,15 +4,15 @@
 
 module device_sync.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 // Used to generate rotating BLE advertisement data, which is necessary to
 // establish a BLE communication channel between two devices. To
 // create the BLE channel, both devices must possess the other's BeaconSeeds.
 struct BeaconSeed {
   string data;
-  mojo.common.mojom.TimeTicks start_time;
-  mojo.common.mojom.TimeTicks end_time;
+  mojo_base.mojom.TimeTicks start_time;
+  mojo_base.mojom.TimeTicks end_time;
 };
 
 // Metadata describing a remote device with which the current device can
diff --git a/components/startup_metric_utils/common/BUILD.gn b/components/startup_metric_utils/common/BUILD.gn
index 11026f69..d19682d 100644
--- a/components/startup_metric_utils/common/BUILD.gn
+++ b/components/startup_metric_utils/common/BUILD.gn
@@ -9,6 +9,6 @@
     "startup_metric.mojom",
   ]
   deps = [
-    "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
   ]
 }
diff --git a/components/startup_metric_utils/common/startup_metric.mojom b/components/startup_metric_utils/common/startup_metric.mojom
index f970df0..276bd3c 100644
--- a/components/startup_metric_utils/common/startup_metric.mojom
+++ b/components/startup_metric_utils/common/startup_metric.mojom
@@ -4,9 +4,9 @@
 
 module startup_metric_utils.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 interface StartupMetricHost {
   RecordRendererMainEntryTime(
-      mojo.common.mojom.TimeTicks renderer_main_entry_time);
+      mojo_base.mojom.TimeTicks renderer_main_entry_time);
 };
diff --git a/components/translate/content/common/translate.mojom b/components/translate/content/common/translate.mojom
index 0cfb34a..7d09c8f 100644
--- a/components/translate/content/common/translate.mojom
+++ b/components/translate/content/common/translate.mojom
@@ -4,7 +4,7 @@
 
 module translate.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "mojo/public/mojom/base/string16.mojom";
 import "url/mojom/url.mojom";
 
@@ -24,7 +24,7 @@
 };
 
 struct LanguageDetectionDetails {
-  mojo.common.mojom.Time time;
+  mojo_base.mojom.Time time;
   url.mojom.Url url;
   string content_language;
   string cld_language;
diff --git a/components/translate/content/common/translate_struct_traits.cc b/components/translate/content/common/translate_struct_traits.cc
index 49a877a..a5e8937 100644
--- a/components/translate/content/common/translate_struct_traits.cc
+++ b/components/translate/content/common/translate_struct_traits.cc
@@ -4,8 +4,8 @@
 
 #include "components/translate/content/common/translate_struct_traits.h"
 
-#include "mojo/common/time_struct_traits.h"
 #include "mojo/public/cpp/base/string16_mojom_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "url/mojom/url_gurl_mojom_traits.h"
 
 namespace mojo {
diff --git a/components/translate/core/language_detection/language_detection_util.cc b/components/translate/core/language_detection/language_detection_util.cc
index ac79f558..ea481c36e 100644
--- a/components/translate/core/language_detection/language_detection_util.cc
+++ b/components/translate/core/language_detection/language_detection_util.cc
@@ -49,12 +49,10 @@
 }
 
 // Well-known languages which often have wrong server configuration of
-// Content-Language: en. The list must be sorted alphabatically so
-// they can be binary searched.
+// Content-Language: en.
 const char* const kWellKnownCodesOnWrongConfiguration[] = {
-    "ar", "da", "de", "el", "es", "fa", "fr",    "hi",
-    "hu", "id", "it", "ja", "ms", "nl", "pl",    "pt",
-    "ro", "ru", "sv", "th", "tr", "vi", "zh-CN", "zh-TW"};
+    "es",    "pt", "ja", "ru", "de", "zh-CN",
+    "zh-TW", "ar", "id", "fr", "it", "th"};
 
 // Applies a series of language code modification in proper order.
 void ApplyLanguageCodeCorrection(std::string* code) {
@@ -328,9 +326,11 @@
 }
 
 bool IsServerWrongConfigurationLanguage(const std::string& language_code) {
-  return binary_search(kWellKnownCodesOnWrongConfiguration,
-                       std::end(kWellKnownCodesOnWrongConfiguration),
-                       language_code);
+  for (size_t i = 0; i < arraysize(kWellKnownCodesOnWrongConfiguration); ++i) {
+    if (language_code == kWellKnownCodesOnWrongConfiguration[i])
+      return true;
+  }
+  return false;
 }
 
 bool MaybeServerWrongConfiguration(const std::string& page_language,
diff --git a/components/translate/core/language_detection/language_detection_util_unittest.cc b/components/translate/core/language_detection/language_detection_util_unittest.cc
index a931556..b14331e571 100644
--- a/components/translate/core/language_detection/language_detection_util_unittest.cc
+++ b/components/translate/core/language_detection/language_detection_util_unittest.cc
@@ -178,10 +178,9 @@
 TEST_F(LanguageDetectionUtilTest, IsServerWrongConfigurationLanguage) {
   // These languages should all be identified as having the wrong server
   // configuration.
-  const char* const wrong_languages[] = {
-      "ar", "da", "de", "el", "es", "fa", "fr",    "hi",
-      "hu", "id", "it", "ja", "ms", "nl", "pl",    "pt",
-      "ro", "ru", "sv", "th", "tr", "vi", "zh-CN", "zh-TW"};
+  const char* const wrong_languages[] = {"es", "pt",    "ja",    "ru",
+                                         "de", "zh-CN", "zh-TW", "ar",
+                                         "id", "fr",    "it",    "th"};
   for (const char* const language : wrong_languages) {
     EXPECT_TRUE(translate::IsServerWrongConfigurationLanguage(language));
   }
diff --git a/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc b/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc
index ab641aa..10774dd 100644
--- a/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc
+++ b/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc
@@ -74,6 +74,9 @@
   void CreateJpegDecodeAccelerator(
       media::mojom::JpegDecodeAcceleratorRequest jda_request) override {}
 
+  void CreateJpegEncodeAccelerator(
+      media::mojom::JpegEncodeAcceleratorRequest jea_request) override {}
+
   void CreateVideoEncodeAcceleratorProvider(
       media::mojom::VideoEncodeAcceleratorProviderRequest request) override {}
 
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index 4a2f224..f63b2f10 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -1046,6 +1046,22 @@
 
   CHECK(debug_weak_this.get());
 
+  if (!damage_rect.IsEmpty()) {
+    // The following call can cause one or more copy requests to be added to the
+    // Surface. Therefore, no code before this point should have assumed
+    // anything about the presence or absence of copy requests after this point.
+    surface->NotifyAggregatedDamage(damage_rect);
+  }
+
+  // If any CopyOutputRequests were made at FrameSink level, make sure we grab
+  // them too.
+  surface->TakeCopyOutputRequestsFromClient();
+
+  if (will_draw)
+    surface->OnWillBeDrawn();
+
+  CHECK(debug_weak_this.get());
+
   for (const auto& surface_id : frame.metadata.referenced_surfaces) {
     if (!contained_surfaces_.count(surface_id)) {
       result->undrawn_surfaces.insert(surface_id);
@@ -1056,18 +1072,6 @@
   }
 
   CHECK(debug_weak_this.get());
-
-  if (!damage_rect.IsEmpty()) {
-    // The following call can cause one or more copy requests to be added to the
-    // Surface. Therefore, no code before this point should have assumed
-    // anything about the presence or absence of copy requests after this point.
-    surface->NotifyAggregatedDamage(damage_rect);
-  }
-
-  if (will_draw)
-    surface->OnWillBeDrawn();
-
-  CHECK(debug_weak_this.get());
   for (const auto& render_pass : frame.render_pass_list) {
     if (!render_pass->copy_requests.empty()) {
       RenderPassId remapped_pass_id =
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
index fe0d9edc..e54b5db 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -640,7 +640,7 @@
   request->set_source(kArbitrarySourceId1);
 
   support_->RequestCopyOfOutput(std::move(request));
-  GetSurfaceForId(surface_id)->OnWillBeDrawn();
+  GetSurfaceForId(surface_id)->TakeCopyOutputRequestsFromClient();
   EXPECT_FALSE(called1);
 
   bool called2 = false;
@@ -650,7 +650,7 @@
   request->set_source(kArbitrarySourceId2);
 
   support_->RequestCopyOfOutput(std::move(request));
-  GetSurfaceForId(surface_id)->OnWillBeDrawn();
+  GetSurfaceForId(surface_id)->TakeCopyOutputRequestsFromClient();
   // Callbacks have different sources so neither should be called.
   EXPECT_FALSE(called1);
   EXPECT_FALSE(called2);
@@ -662,7 +662,7 @@
   request->set_source(kArbitrarySourceId1);
 
   support_->RequestCopyOfOutput(std::move(request));
-  GetSurfaceForId(surface_id)->OnWillBeDrawn();
+  GetSurfaceForId(surface_id)->TakeCopyOutputRequestsFromClient();
   // Two callbacks are from source1, so the first should be called.
   EXPECT_TRUE(called1);
   EXPECT_FALSE(called2);
@@ -810,10 +810,11 @@
   EXPECT_EQ(frame_index + 1, surface2->GetActiveFrameIndex());
 }
 
-// If the first surface is the one reported being drawn by SurfaceAggregator,
-// move CopyOutputRequest to that surface.
+// Verifies that CopyOutputRequests made at frame sink level are sent to the
+// surface that takes them first. In this test this surface is not the last
+// activated surface.
 TEST_F(CompositorFrameSinkSupportTest,
-       FirstSurfaceIsDrawnAndReceivesCopyRequest) {
+       OldSurfaceTakesCopyOutputRequestsFromClient) {
   LocalSurfaceId local_surface_id1(1, kArbitraryToken);
   LocalSurfaceId local_surface_id2(2, kArbitraryToken);
   SurfaceId id1(support_->frame_sink_id(), local_surface_id1);
@@ -837,9 +838,15 @@
   EXPECT_TRUE(GetSurfaceForId(id1)->HasCopyOutputRequests());
   EXPECT_TRUE(GetSurfaceForId(id2)->HasCopyOutputRequests());
 
-  // Notify that the first surface will be drawn. Now only the first surface
-  // should report having CopyOutputRequests.
-  GetSurfaceForId(id1)->OnWillBeDrawn();
+  // First surface takes CopyOutputRequests from its client. Now only the first
+  // surface should report having CopyOutputRequests.
+  GetSurfaceForId(id1)->TakeCopyOutputRequestsFromClient();
+  EXPECT_TRUE(GetSurfaceForId(id1)->HasCopyOutputRequests());
+  EXPECT_FALSE(GetSurfaceForId(id2)->HasCopyOutputRequests());
+
+  // Calling TakeCopyOutputRequestsFromClient() on the second surface should
+  // have no effect.
+  GetSurfaceForId(id2)->TakeCopyOutputRequestsFromClient();
   EXPECT_TRUE(GetSurfaceForId(id1)->HasCopyOutputRequests());
   EXPECT_FALSE(GetSurfaceForId(id2)->HasCopyOutputRequests());
 
@@ -852,10 +859,11 @@
   EXPECT_FALSE(requests_map.empty());
 }
 
-// If the second surface is the one reported being drawn by SurfaceAggregator,
-// move CopyOutputRequest to that surface.
+// Verifies that CopyOutputRequests made at frame sink level are sent to the
+// surface that takes them first. In this test this surface is the last
+// activated surface.
 TEST_F(CompositorFrameSinkSupportTest,
-       SecondSurfaceIsDrawnAndReceivesCopyRequest) {
+       LastSurfaceTakesCopyOutputRequestsFromClient) {
   LocalSurfaceId local_surface_id1(1, kArbitraryToken);
   LocalSurfaceId local_surface_id2(2, kArbitraryToken);
   SurfaceId id1(support_->frame_sink_id(), local_surface_id1);
@@ -880,9 +888,15 @@
   EXPECT_TRUE(GetSurfaceForId(id1)->HasCopyOutputRequests());
   EXPECT_TRUE(GetSurfaceForId(id2)->HasCopyOutputRequests());
 
-  // Notify that the second surface will be drawn. Now only the second surface
-  // should report having CopyOutputRequests.
-  GetSurfaceForId(id2)->OnWillBeDrawn();
+  // Second surface takes CopyOutputRequests from its client. Now only the
+  // second surface should report having CopyOutputRequests.
+  GetSurfaceForId(id2)->TakeCopyOutputRequestsFromClient();
+  EXPECT_FALSE(GetSurfaceForId(id1)->HasCopyOutputRequests());
+  EXPECT_TRUE(GetSurfaceForId(id2)->HasCopyOutputRequests());
+
+  // Calling TakeCopyOutputRequestsFromClient() on the first surface should have
+  // no effect.
+  GetSurfaceForId(id1)->TakeCopyOutputRequestsFromClient();
   EXPECT_FALSE(GetSurfaceForId(id1)->HasCopyOutputRequests());
   EXPECT_TRUE(GetSurfaceForId(id2)->HasCopyOutputRequests());
 
@@ -895,96 +909,5 @@
   EXPECT_FALSE(requests_map.empty());
 }
 
-// Move CopyOutputRequests to whatever surface wants it first (in this test, the
-// first surface).
-TEST_F(CompositorFrameSinkSupportTest, FirstSurfaceTakesCopyRequest) {
-  LocalSurfaceId local_surface_id1(1, kArbitraryToken);
-  LocalSurfaceId local_surface_id2(2, kArbitraryToken);
-  SurfaceId id1(support_->frame_sink_id(), local_surface_id1);
-  SurfaceId id2(support_->frame_sink_id(), local_surface_id2);
-
-  // Create the first surface.
-  support_->SubmitCompositorFrame(local_surface_id1,
-                                  MakeDefaultCompositorFrame());
-
-  // Create the second surface.
-  support_->SubmitCompositorFrame(local_surface_id2,
-                                  MakeDefaultCompositorFrame());
-
-  // Send a CopyOutputRequest.
-  auto request = std::make_unique<CopyOutputRequest>(
-      CopyOutputRequest::ResultFormat::RGBA_BITMAP,
-      base::BindOnce(StubResultCallback));
-  support_->RequestCopyOfOutput(std::move(request));
-
-  // Both surfaces should report that they have a CopyOutputRequest.
-  EXPECT_TRUE(GetSurfaceForId(id1)->HasCopyOutputRequests());
-  EXPECT_TRUE(GetSurfaceForId(id2)->HasCopyOutputRequests());
-
-  // Neither surface will be reported drawn. We call TakeCopyOutputRequests()
-  // on |id1| first so it takes it.
-  Surface::CopyRequestsMap requests_map;
-  GetSurfaceForId(id1)->TakeCopyOutputRequests(&requests_map);
-  EXPECT_FALSE(requests_map.empty());
-
-  // Neither surface should report having CopyOutputRequests anymore.
-  EXPECT_FALSE(GetSurfaceForId(id1)->HasCopyOutputRequests());
-  EXPECT_FALSE(GetSurfaceForId(id2)->HasCopyOutputRequests());
-
-  // Also try TakeCopyOutputRequests, to see if its output is consistent with
-  // HasCopyOutputRequests.
-  requests_map.clear();
-  GetSurfaceForId(id2)->TakeCopyOutputRequests(&requests_map);
-  EXPECT_TRUE(requests_map.empty());
-  GetSurfaceForId(id1)->TakeCopyOutputRequests(&requests_map);
-  EXPECT_TRUE(requests_map.empty());
-}
-
-// Move CopyOutputRequests to whatever surface wants it first (in this test, the
-// second surface).
-TEST_F(CompositorFrameSinkSupportTest, SecondSurfaceTakesCopyRequest) {
-  LocalSurfaceId local_surface_id1(1, kArbitraryToken);
-  LocalSurfaceId local_surface_id2(2, kArbitraryToken);
-  SurfaceId id1(support_->frame_sink_id(), local_surface_id1);
-  SurfaceId id2(support_->frame_sink_id(), local_surface_id2);
-
-  // Create the first surface.
-  support_->SubmitCompositorFrame(local_surface_id1,
-                                  MakeDefaultCompositorFrame());
-
-  // Send a CopyOutputRequest. Note that the second surface doesn't even exist
-  // yet.
-  auto request = std::make_unique<CopyOutputRequest>(
-      CopyOutputRequest::ResultFormat::RGBA_BITMAP,
-      base::BindOnce(StubResultCallback));
-  support_->RequestCopyOfOutput(std::move(request));
-
-  // Create the second surface.
-  support_->SubmitCompositorFrame(local_surface_id2,
-                                  MakeDefaultCompositorFrame());
-
-  // Both surfaces should report that they have a CopyOutputRequest.
-  EXPECT_TRUE(GetSurfaceForId(id1)->HasCopyOutputRequests());
-  EXPECT_TRUE(GetSurfaceForId(id2)->HasCopyOutputRequests());
-
-  // Neither surface will be reported drawn. We call TakeCopyOutputRequests()
-  // on |id2| first so it takes it.
-  Surface::CopyRequestsMap requests_map;
-  GetSurfaceForId(id2)->TakeCopyOutputRequests(&requests_map);
-  EXPECT_FALSE(requests_map.empty());
-
-  // Neither surface should report having CopyOutputRequests anymore.
-  EXPECT_FALSE(GetSurfaceForId(id1)->HasCopyOutputRequests());
-  EXPECT_FALSE(GetSurfaceForId(id2)->HasCopyOutputRequests());
-
-  // Also try TakeCopyOutputRequests, to see if its output is consistent with
-  // HasCopyOutputRequests.
-  requests_map.clear();
-  GetSurfaceForId(id2)->TakeCopyOutputRequests(&requests_map);
-  EXPECT_TRUE(requests_map.empty());
-  GetSurfaceForId(id1)->TakeCopyOutputRequests(&requests_map);
-  EXPECT_TRUE(requests_map.empty());
-}
-
 }  // namespace
 }  // namespace viz
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index 29adbb5..06a030f 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -40,6 +40,7 @@
 #include "media/gpu/ipc/service/gpu_video_decode_accelerator.h"
 #include "media/gpu/ipc/service/media_gpu_channel_manager.h"
 #include "media/mojo/services/mojo_jpeg_decode_accelerator_service.h"
+#include "media/mojo/services/mojo_jpeg_encode_accelerator_service.h"
 #include "media/mojo/services/mojo_video_encode_accelerator_provider.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "ui/gl/gl_implementation.h"
@@ -320,6 +321,12 @@
   media::MojoJpegDecodeAcceleratorService::Create(std::move(jda_request));
 }
 
+void GpuServiceImpl::CreateJpegEncodeAccelerator(
+    media::mojom::JpegEncodeAcceleratorRequest jea_request) {
+  DCHECK(io_runner_->BelongsToCurrentThread());
+  media::MojoJpegEncodeAcceleratorService::Create(std::move(jea_request));
+}
+
 void GpuServiceImpl::CreateVideoEncodeAcceleratorProvider(
     media::mojom::VideoEncodeAcceleratorProviderRequest vea_provider_request) {
   DCHECK(io_runner_->BelongsToCurrentThread());
diff --git a/components/viz/service/gl/gpu_service_impl.h b/components/viz/service/gl/gpu_service_impl.h
index ffe6c8c..b14488a 100644
--- a/components/viz/service/gl/gpu_service_impl.h
+++ b/components/viz/service/gl/gpu_service_impl.h
@@ -148,6 +148,8 @@
       arc::mojom::ProtectedBufferManagerRequest pbm_request) override;
   void CreateJpegDecodeAccelerator(
       media::mojom::JpegDecodeAcceleratorRequest jda_request) override;
+  void CreateJpegEncodeAccelerator(
+      media::mojom::JpegEncodeAcceleratorRequest jea_request) override;
   void CreateVideoEncodeAcceleratorProvider(
       media::mojom::VideoEncodeAcceleratorProviderRequest vea_provider_request)
       override;
diff --git a/components/viz/service/surfaces/surface.cc b/components/viz/service/surfaces/surface.cc
index d9d92126..1cb5b95 100644
--- a/components/viz/service/surfaces/surface.cc
+++ b/components/viz/service/surfaces/surface.cc
@@ -423,7 +423,8 @@
   if (!active_frame_data_)
     return;
 
-  TakeCopyOutputRequestsFromClient();
+  // TakeCopyOutputRequestsFromClient() has to be called before this method.
+  DCHECK(!surface_client_ || !surface_client_->HasCopyOutputRequests());
 
   for (const auto& render_pass : active_frame_data_->frame.render_pass_list) {
     for (auto& request : render_pass->copy_requests) {
@@ -434,6 +435,15 @@
   }
 }
 
+void Surface::TakeCopyOutputRequestsFromClient() {
+  if (!surface_client_)
+    return;
+  for (std::unique_ptr<CopyOutputRequest>& request :
+       surface_client_->TakeCopyOutputRequests()) {
+    RequestCopyOfOutput(std::move(request));
+  }
+}
+
 bool Surface::HasCopyOutputRequests() {
   if (!active_frame_data_)
     return false;
@@ -543,17 +553,7 @@
 }
 
 void Surface::OnWillBeDrawn() {
-  TakeCopyOutputRequestsFromClient();
   surface_manager_->SurfaceWillBeDrawn(this);
 }
 
-void Surface::TakeCopyOutputRequestsFromClient() {
-  if (!surface_client_)
-    return;
-  for (std::unique_ptr<CopyOutputRequest>& request :
-       surface_client_->TakeCopyOutputRequests()) {
-    RequestCopyOfOutput(std::move(request));
-  }
-}
-
 }  // namespace viz
diff --git a/components/viz/service/surfaces/surface.h b/components/viz/service/surfaces/surface.h
index f3c6522..c742367 100644
--- a/components/viz/service/surfaces/surface.h
+++ b/components/viz/service/surfaces/surface.h
@@ -150,6 +150,10 @@
   // ids.
   void TakeCopyOutputRequests(CopyRequestsMap* copy_requests);
 
+  // Takes CopyOutputRequests made at the client level and adds them to this
+  // Surface.
+  void TakeCopyOutputRequestsFromClient();
+
   // Returns whether there is a CopyOutputRequest inside the active frame or at
   // the client level.
   bool HasCopyOutputRequests();
@@ -260,8 +264,6 @@
 
   void RequestCopyOfOutput(std::unique_ptr<CopyOutputRequest> copy_request);
 
-  void TakeCopyOutputRequestsFromClient();
-
   const SurfaceInfo surface_info_;
   SurfaceId previous_frame_surface_id_;
   SurfaceManager* const surface_manager_;
diff --git a/components/viz/service/surfaces/surface_unittest.cc b/components/viz/service/surfaces/surface_unittest.cc
index deecdf2..2cdc3b5 100644
--- a/components/viz/service/surfaces/surface_unittest.cc
+++ b/components/viz/service/surfaces/surface_unittest.cc
@@ -94,7 +94,7 @@
   support->RequestCopyOfOutput(std::make_unique<CopyOutputRequest>(
       CopyOutputRequest::ResultFormat::RGBA_BITMAP,
       base::BindOnce(&TestCopyResultCallback, &copy_called)));
-  surface->OnWillBeDrawn();
+  surface->TakeCopyOutputRequestsFromClient();
   EXPECT_TRUE(surface_manager->GetSurfaceForId(surface_id));
   EXPECT_FALSE(copy_called);
 
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 12fe458b..7c509fff 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -725,8 +725,6 @@
     "download/parallel_download_job.h",
     "download/parallel_download_utils.cc",
     "download/parallel_download_utils.h",
-    "download/resource_downloader.cc",
-    "download/resource_downloader.h",
     "download/save_file.cc",
     "download/save_file.h",
     "download/save_file_manager.cc",
@@ -739,7 +737,6 @@
     "download/save_package_download_job.h",
     "download/save_types.cc",
     "download/save_types.h",
-    "download/url_download_handler.h",
     "download/url_downloader.cc",
     "download/url_downloader.h",
     "field_trial_recorder.cc",
diff --git a/content/browser/android/content_view_core.cc b/content/browser/android/content_view_core.cc
index d79bc8a..8f8793f 100644
--- a/content/browser/android/content_view_core.cc
+++ b/content/browser/android/content_view_core.cc
@@ -71,8 +71,6 @@
 
 namespace {
 
-const void* const kContentViewUserDataKey = &kContentViewUserDataKey;
-
 int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
   DCHECK(host);
   RenderProcessHost* render_process = host->GetProcess();
@@ -82,33 +80,15 @@
   return 0;
 }
 
+void SetContentViewCore(WebContents* web_contents, ContentViewCore* cvc) {
+  WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
+      static_cast<WebContentsImpl*>(web_contents)->GetView());
+  DCHECK(wcva);
+  wcva->SetContentViewCore(cvc);
+}
+
 }  // namespace
 
-// Enables a callback when the underlying WebContents is destroyed, to enable
-// nulling the back-pointer.
-class ContentViewCore::ContentViewUserData
-    : public base::SupportsUserData::Data {
- public:
-  explicit ContentViewUserData(ContentViewCore* content_view_core)
-      : content_view_core_(content_view_core) {}
-
-  ~ContentViewUserData() override {
-    // TODO(joth): When chrome has finished removing the TabContents class (see
-    // crbug.com/107201) consider inverting relationship, so ContentViewCore
-    // would own WebContents. That effectively implies making the WebContents
-    // destructor private on Android.
-    delete content_view_core_;
-  }
-
-  ContentViewCore* get() const { return content_view_core_; }
-
- private:
-  // Not using scoped_ptr as ContentViewCore destructor is private.
-  ContentViewCore* content_view_core_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
-};
-
 ContentViewCore::ContentViewCore(JNIEnv* env,
                                  const JavaRef<jobject>& obj,
                                  WebContents* web_contents,
@@ -134,10 +114,6 @@
 }
 
 ContentViewCore::~ContentViewCore() {
-  for (auto* host : web_contents_->GetAllRenderWidgetHosts()) {
-    static_cast<RenderWidgetHostViewAndroid*>(host->GetView())
-        ->OnContentViewCoreDestroyed();
-  }
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
   java_ref_.reset();
@@ -165,12 +141,6 @@
 }
 
 base::android::ScopedJavaLocalRef<jobject>
-ContentViewCore::GetWebContentsAndroid(JNIEnv* env,
-                                       const JavaParamRef<jobject>& obj) {
-  return web_contents_->GetJavaWebContents();
-}
-
-base::android::ScopedJavaLocalRef<jobject>
 ContentViewCore::GetJavaWindowAndroid(JNIEnv* env,
                                       const JavaParamRef<jobject>& obj) {
   if (!GetWindowAndroid())
@@ -189,19 +159,12 @@
   // could have call in when swapping the WebContents,
   // see http://crbug.com/383939 .
   DCHECK(web_contents_);
-  static_cast<WebContentsViewAndroid*>(
-      static_cast<WebContentsImpl*>(web_contents_)->GetView())
-      ->SetContentViewCore(NULL);
+  SetContentViewCore(web_contents(), nullptr);
 }
 
 void ContentViewCore::InitWebContents() {
   DCHECK(web_contents_);
-  static_cast<WebContentsViewAndroid*>(
-      static_cast<WebContentsImpl*>(web_contents_)->GetView())
-      ->SetContentViewCore(this);
-  DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
-  web_contents_->SetUserData(kContentViewUserDataKey,
-                             std::make_unique<ContentViewUserData>(this));
+  SetContentViewCore(web_contents(), this);
 }
 
 void ContentViewCore::RenderViewReady() {
@@ -414,13 +377,6 @@
   return content::GetContentClient()->UsingSynchronousCompositing();
 }
 
-void ContentViewCore::WebContentsDestroyed() {
-  WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
-      static_cast<WebContentsImpl*>(web_contents())->GetView());
-  DCHECK(wcva);
-  wcva->SetContentViewCore(NULL);
-}
-
 // This is called for each ContentView.
 jlong JNI_ContentViewCoreImpl_Init(
     JNIEnv* env,
diff --git a/content/browser/android/content_view_core.h b/content/browser/android/content_view_core.h
index 9954566..48984d0e12 100644
--- a/content/browser/android/content_view_core.h
+++ b/content/browser/android/content_view_core.h
@@ -42,6 +42,8 @@
                   WebContents* web_contents,
                   float dpi_scale);
 
+  ~ContentViewCore() override;
+
   base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
   WebContents* GetWebContents() const;
   ui::WindowAndroid* GetWindowAndroid() const;
@@ -50,9 +52,6 @@
   // Methods called from Java via JNI
   // --------------------------------------------------------------------------
 
-  base::android::ScopedJavaLocalRef<jobject> GetWebContentsAndroid(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jobject>& obj);
   base::android::ScopedJavaLocalRef<jobject> GetJavaWindowAndroid(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj);
@@ -123,13 +122,11 @@
   class ContentViewUserData;
 
   friend class ContentViewUserData;
-  ~ContentViewCore() override;
 
   // WebContentsObserver implementation.
   void RenderViewReady() override;
   void RenderViewHostChanged(RenderViewHost* old_host,
                              RenderViewHost* new_host) override;
-  void WebContentsDestroyed() override;
 
   // --------------------------------------------------------------------------
   // Other private methods and data
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 13e5756..d2c0813 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -33,6 +33,7 @@
 #include "components/download/public/common/download_stats.h"
 #include "components/download/public/common/download_task_runner.h"
 #include "components/download/public/common/download_url_parameters.h"
+#include "components/download/public/common/resource_downloader.h"
 #include "content/browser/byte_stream.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/download/byte_stream_input_stream.h"
@@ -40,7 +41,6 @@
 #include "content/browser/download/download_item_impl.h"
 #include "content/browser/download/download_resource_handler.h"
 #include "content/browser/download/download_utils.h"
-#include "content/browser/download/resource_downloader.h"
 #include "content/browser/download/url_downloader.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/loader/resource_request_info_impl.h"
@@ -233,7 +233,7 @@
   // This is already done for context menu download, but it is missing for
   // download service and download resumption.
   return DownloadManagerImpl::UniqueUrlDownloadHandlerPtr(
-      ResourceDownloader::BeginDownload(
+      download::ResourceDownloader::BeginDownload(
           download_manager, std::move(params), std::move(request),
           std::move(shared_url_loader_factory), site_url, tab_url,
           tab_referrer_url, download_id, false, task_runner)
@@ -1092,7 +1092,8 @@
   StartDownload(std::move(download_create_info), std::move(stream), callback);
 }
 
-void DownloadManagerImpl::OnUrlDownloadStopped(UrlDownloadHandler* downloader) {
+void DownloadManagerImpl::OnUrlDownloadStopped(
+    download::UrlDownloadHandler* downloader) {
   for (auto ptr = url_download_handlers_.begin();
        ptr != url_download_handlers_.end(); ++ptr) {
     if (ptr->get() == downloader) {
@@ -1193,8 +1194,8 @@
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  std::unique_ptr<ResourceDownloader> resource_downloader =
-      ResourceDownloader::InterceptNavigationResponse(
+  std::unique_ptr<download::ResourceDownloader> resource_downloader =
+      download::ResourceDownloader::InterceptNavigationResponse(
           download_manager, std::move(resource_request), render_process_id,
           render_frame_id, site_url, tab_url, tab_referrer_url,
           std::move(url_chain), suggested_filename, std::move(response),
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
index f6d1b61..313e9f3 100644
--- a/content/browser/download/download_manager_impl.h
+++ b/content/browser/download/download_manager_impl.h
@@ -21,8 +21,8 @@
 #include "base/sequenced_task_runner_helpers.h"
 #include "base/synchronization/lock.h"
 #include "components/download/public/common/download_url_parameters.h"
+#include "components/download/public/common/url_download_handler.h"
 #include "content/browser/download/download_item_impl_delegate.h"
-#include "content/browser/download/url_download_handler.h"
 #include "content/browser/loader/navigation_url_loader.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_thread.h"
@@ -42,13 +42,15 @@
 class DownloadItemImpl;
 class ResourceContext;
 
-class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
-                                           public UrlDownloadHandler::Delegate,
-                                           private DownloadItemImplDelegate {
+class CONTENT_EXPORT DownloadManagerImpl
+    : public DownloadManager,
+      public download::UrlDownloadHandler::Delegate,
+      private DownloadItemImplDelegate {
  public:
   using DownloadItemImplCreated = base::Callback<void(DownloadItemImpl*)>;
   using UniqueUrlDownloadHandlerPtr =
-      std::unique_ptr<UrlDownloadHandler, BrowserThread::DeleteOnIOThread>;
+      std::unique_ptr<download::UrlDownloadHandler,
+                      BrowserThread::DeleteOnIOThread>;
 
   // Caller guarantees that |net_log| will remain valid
   // for the lifetime of DownloadManagerImpl (until Shutdown() is called).
@@ -133,7 +135,7 @@
       std::unique_ptr<download::InputStream> stream,
       const download::DownloadUrlParameters::OnStartedCallback& callback)
       override;
-  void OnUrlDownloadStopped(UrlDownloadHandler* downloader) override;
+  void OnUrlDownloadStopped(download::UrlDownloadHandler* downloader) override;
 
   // For testing; specifically, accessed from TestFileErrorInjector.
   void SetDownloadItemFactoryForTesting(
diff --git a/content/browser/download/download_worker.cc b/content/browser/download/download_worker.cc
index 2cbdf32a..37981901f 100644
--- a/content/browser/download/download_worker.cc
+++ b/content/browser/download/download_worker.cc
@@ -8,9 +8,9 @@
 #include "components/download/public/common/download_create_info.h"
 #include "components/download/public/common/download_interrupt_reasons.h"
 #include "components/download/public/common/input_stream.h"
+#include "components/download/public/common/resource_downloader.h"
 #include "content/browser/download/download_utils.h"
-#include "content/browser/download/resource_downloader.h"
-#include "content/public/browser/web_contents.h"
+#include "content/browser/download/url_downloader.h"
 #include "content/public/common/content_features.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -43,10 +43,10 @@
   DISALLOW_COPY_AND_ASSIGN(CompletedInputStream);
 };
 
-std::unique_ptr<UrlDownloadHandler, BrowserThread::DeleteOnIOThread>
+std::unique_ptr<download::UrlDownloadHandler, BrowserThread::DeleteOnIOThread>
 CreateUrlDownloadHandler(
     std::unique_ptr<download::DownloadUrlParameters> params,
-    base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+    base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
     scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -54,8 +54,9 @@
   if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
     std::unique_ptr<network::ResourceRequest> request =
         CreateResourceRequest(params.get());
-    return std::unique_ptr<ResourceDownloader, BrowserThread::DeleteOnIOThread>(
-        ResourceDownloader::BeginDownload(
+    return std::unique_ptr<download::ResourceDownloader,
+                           BrowserThread::DeleteOnIOThread>(
+        download::ResourceDownloader::BeginDownload(
             delegate, std::move(params), std::move(request),
             url_loader_factory_getter->GetNetworkFactory(), GURL(), GURL(),
             GURL(), download::DownloadItem::kInvalidId, true, task_runner)
@@ -158,15 +159,16 @@
   delegate_->OnInputStreamReady(this, std::move(input_stream));
 }
 
-void DownloadWorker::OnUrlDownloadStopped(UrlDownloadHandler* downloader) {
+void DownloadWorker::OnUrlDownloadStopped(
+    download::UrlDownloadHandler* downloader) {
   // Release the |url_download_handler_|, the object will be deleted on IO
   // thread.
   url_download_handler_.reset();
 }
 
 void DownloadWorker::AddUrlDownloadHandler(
-    std::unique_ptr<UrlDownloadHandler, BrowserThread::DeleteOnIOThread>
-        downloader) {
+    std::unique_ptr<download::UrlDownloadHandler,
+                    BrowserThread::DeleteOnIOThread> downloader) {
   url_download_handler_ = std::move(downloader);
 }
 
diff --git a/content/browser/download/download_worker.h b/content/browser/download/download_worker.h
index c7ecb758..b36bb211 100644
--- a/content/browser/download/download_worker.h
+++ b/content/browser/download/download_worker.h
@@ -11,7 +11,8 @@
 #include "base/memory/weak_ptr.h"
 #include "components/download/public/common/download_request_handle_interface.h"
 #include "components/download/public/common/download_url_parameters.h"
-#include "content/browser/download/url_downloader.h"
+#include "components/download/public/common/url_download_handler.h"
+#include "content/browser/download/download_request_core.h"
 #include "content/browser/url_loader_factory_getter.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_thread.h"
@@ -22,7 +23,8 @@
 // file after handling response of the original non-range request.
 // TODO(xingliu): we should consider to reuse this class for single connection
 // download.
-class CONTENT_EXPORT DownloadWorker : public UrlDownloadHandler::Delegate {
+class CONTENT_EXPORT DownloadWorker
+    : public download::UrlDownloadHandler::Delegate {
  public:
   class Delegate {
    public:
@@ -59,11 +61,11 @@
       std::unique_ptr<download::InputStream> input_stream,
       const download::DownloadUrlParameters::OnStartedCallback& callback)
       override;
-  void OnUrlDownloadStopped(UrlDownloadHandler* downloader) override;
+  void OnUrlDownloadStopped(download::UrlDownloadHandler* downloader) override;
 
   void AddUrlDownloadHandler(
-      std::unique_ptr<UrlDownloadHandler, BrowserThread::DeleteOnIOThread>
-          downloader);
+      std::unique_ptr<download::UrlDownloadHandler,
+                      BrowserThread::DeleteOnIOThread> downloader);
 
   DownloadWorker::Delegate* const delegate_;
 
@@ -82,7 +84,7 @@
   std::unique_ptr<download::DownloadRequestHandleInterface> request_handle_;
 
   // Used to handle the url request. Live and die on IO thread.
-  std::unique_ptr<UrlDownloadHandler, BrowserThread::DeleteOnIOThread>
+  std::unique_ptr<download::UrlDownloadHandler, BrowserThread::DeleteOnIOThread>
       url_download_handler_;
 
   base::WeakPtrFactory<DownloadWorker> weak_factory_;
diff --git a/content/browser/download/parallel_download_job_unittest.cc b/content/browser/download/parallel_download_job_unittest.cc
index 43a64a9..b6fe144 100644
--- a/content/browser/download/parallel_download_job_unittest.cc
+++ b/content/browser/download/parallel_download_job_unittest.cc
@@ -167,8 +167,8 @@
   void MakeWorkerReady(
       DownloadWorker* worker,
       std::unique_ptr<MockDownloadRequestHandle> request_handle) {
-    UrlDownloadHandler::Delegate* delegate =
-        static_cast<UrlDownloadHandler::Delegate*>(worker);
+    download::UrlDownloadHandler::Delegate* delegate =
+        static_cast<download::UrlDownloadHandler::Delegate*>(worker);
     std::unique_ptr<download::DownloadCreateInfo> create_info =
         std::make_unique<download::DownloadCreateInfo>();
     create_info->request_handle = std::move(request_handle);
diff --git a/content/browser/download/url_download_handler.h b/content/browser/download/url_download_handler.h
deleted file mode 100644
index 7986998..0000000
--- a/content/browser/download/url_download_handler.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOAD_HANDLER
-#define CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOAD_HANDLER
-
-#include "components/download/public/common/download_url_parameters.h"
-#include "content/common/content_export.h"
-
-namespace download {
-struct DownloadCreateInfo;
-class InputStream;
-}  // namespace download
-
-namespace content {
-
-// Class for handling the download of a url. Implemented by child classes.
-class CONTENT_EXPORT UrlDownloadHandler {
- public:
-  // Class to be notified when download starts/stops.
-  class CONTENT_EXPORT Delegate {
-   public:
-    virtual void OnUrlDownloadStarted(
-        std::unique_ptr<download::DownloadCreateInfo> download_create_info,
-        std::unique_ptr<download::InputStream> input_stream,
-        const download::DownloadUrlParameters::OnStartedCallback& callback) = 0;
-    // Called after the connection is cancelled or finished.
-    virtual void OnUrlDownloadStopped(UrlDownloadHandler* downloader) = 0;
-  };
-
-  UrlDownloadHandler() = default;
-  virtual ~UrlDownloadHandler() = default;
-
-  DISALLOW_COPY_AND_ASSIGN(UrlDownloadHandler);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOAD_HANDLER
diff --git a/content/browser/download/url_downloader.cc b/content/browser/download/url_downloader.cc
index 0943901..addee1e9a 100644
--- a/content/browser/download/url_downloader.cc
+++ b/content/browser/download/url_downloader.cc
@@ -64,7 +64,7 @@
 
 // static
 std::unique_ptr<UrlDownloader> UrlDownloader::BeginDownload(
-    base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+    base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
     std::unique_ptr<net::URLRequest> request,
     download::DownloadUrlParameters* params,
     bool is_parallel_request) {
@@ -90,7 +90,7 @@
 
 UrlDownloader::UrlDownloader(
     std::unique_ptr<net::URLRequest> request,
-    base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+    base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
     bool is_parallel_request,
     const std::string& request_origin,
     download::DownloadSource download_source)
@@ -227,8 +227,8 @@
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::BindOnce(
-          &UrlDownloadHandler::Delegate::OnUrlDownloadStarted, delegate_,
-          std::move(create_info),
+          &download::UrlDownloadHandler::Delegate::OnUrlDownloadStarted,
+          delegate_, std::move(create_info),
           std::make_unique<ByteStreamInputStream>(std::move(stream_reader)),
           callback));
 }
@@ -252,8 +252,9 @@
 void UrlDownloader::Destroy() {
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::BindOnce(&UrlDownloadHandler::Delegate::OnUrlDownloadStopped,
-                     delegate_, this));
+      base::BindOnce(
+          &download::UrlDownloadHandler::Delegate::OnUrlDownloadStopped,
+          delegate_, this));
 }
 
 }  // namespace content
diff --git a/content/browser/download/url_downloader.h b/content/browser/download/url_downloader.h
index c058081f1..0ee10fe 100644
--- a/content/browser/download/url_downloader.h
+++ b/content/browser/download/url_downloader.h
@@ -11,8 +11,8 @@
 
 #include "base/memory/weak_ptr.h"
 #include "components/download/public/common/download_url_parameters.h"
+#include "components/download/public/common/url_download_handler.h"
 #include "content/browser/download/download_request_core.h"
-#include "content/browser/download/url_download_handler.h"
 #include "content/public/common/referrer.h"
 #include "net/url_request/redirect_info.h"
 #include "net/url_request/url_request.h"
@@ -26,7 +26,7 @@
 
 class UrlDownloader : public net::URLRequest::Delegate,
                       public DownloadRequestCore::Delegate,
-                      public UrlDownloadHandler {
+                      public download::UrlDownloadHandler {
  public:
   UrlDownloader(std::unique_ptr<net::URLRequest> request,
                 base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
@@ -36,7 +36,7 @@
   ~UrlDownloader() override;
 
   static std::unique_ptr<UrlDownloader> BeginDownload(
-      base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+      base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
       std::unique_ptr<net::URLRequest> request,
       download::DownloadUrlParameters* params,
       bool is_parallel_request);
@@ -76,7 +76,7 @@
   std::unique_ptr<net::URLRequest> request_;
 
   // Live on UI thread, post task to call |delegate_| functions.
-  base::WeakPtr<UrlDownloadHandler::Delegate> delegate_;
+  base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate_;
   DownloadRequestCore core_;
 
   base::WeakPtrFactory<UrlDownloader> weak_ptr_factory_;
diff --git a/content/browser/payments/payment_app_provider_impl.cc b/content/browser/payments/payment_app_provider_impl.cc
index 1df4e6c..1174987a 100644
--- a/content/browser/payments/payment_app_provider_impl.cc
+++ b/content/browser/payments/payment_app_provider_impl.cc
@@ -18,7 +18,7 @@
 #include "content/public/browser/permission_type.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
-#include "mojo/common/time.mojom.h"
+#include "mojo/public/mojom/base/time.mojom.h"
 #include "third_party/WebKit/public/mojom/service_worker/service_worker_provider_type.mojom.h"
 #include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
 #include "third_party/skia/include/core/SkBitmap.h"
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index 0c13604a..94bf565 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -112,6 +112,24 @@
                                          std::move(request)));
 }
 
+void CreateJpegEncodeAcceleratorOnIOThread(
+    media::mojom::JpegEncodeAcceleratorRequest request) {
+  auto* host =
+      GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, false);
+  if (host) {
+    host->gpu_service()->CreateJpegEncodeAccelerator(std::move(request));
+  } else {
+    LOG(ERROR) << "No GpuProcessHost";
+  }
+}
+
+void CreateJpegEncodeAccelerator(
+    media::mojom::JpegEncodeAcceleratorRequest request) {
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::BindOnce(&CreateJpegEncodeAcceleratorOnIOThread,
+                                         std::move(request)));
+}
+
 void ParseStreamType(const StreamControls& controls,
                      MediaStreamType* audio_type,
                      MediaStreamType* video_type) {
@@ -495,7 +513,8 @@
               media::VideoCaptureDeviceFactory::CreateFactory(
                   BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
                   BrowserGpuMemoryBufferManager::current(),
-                  base::BindRepeating(&CreateJpegDecodeAccelerator))),
+                  base::BindRepeating(&CreateJpegDecodeAccelerator),
+                  base::BindRepeating(&CreateJpegEncodeAccelerator))),
           std::move(device_task_runner),
           base::BindRepeating(&SendVideoCaptureLogMessage));
     }
diff --git a/content/browser/renderer_host/render_frame_metadata_provider_impl.cc b/content/browser/renderer_host/render_frame_metadata_provider_impl.cc
index 4847c742..1850d56 100644
--- a/content/browser/renderer_host/render_frame_metadata_provider_impl.cc
+++ b/content/browser/renderer_host/render_frame_metadata_provider_impl.cc
@@ -58,11 +58,6 @@
     observer.OnRenderFrameSubmission();
 }
 
-void RenderFrameMetadataProviderImpl::SetLastRenderFrameMetadataForTest(
-    cc::RenderFrameMetadata metadata) {
-  last_render_frame_metadata_ = metadata;
-}
-
 void RenderFrameMetadataProviderImpl::OnRenderFrameMetadataChanged(
     uint32_t frame_token,
     const cc::RenderFrameMetadata& metadata) {
diff --git a/content/browser/renderer_host/render_frame_metadata_provider_impl.h b/content/browser/renderer_host/render_frame_metadata_provider_impl.h
index 48ab56154..b59187e 100644
--- a/content/browser/renderer_host/render_frame_metadata_provider_impl.h
+++ b/content/browser/renderer_host/render_frame_metadata_provider_impl.h
@@ -23,7 +23,7 @@
 // notified of all frame submissions.
 //
 // All RenderFrameMetadataProvider::Observer will be notified.
-class CONTENT_EXPORT RenderFrameMetadataProviderImpl
+class RenderFrameMetadataProviderImpl
     : public RenderFrameMetadataProvider,
       public mojom::RenderFrameMetadataObserverClient {
  public:
@@ -44,8 +44,6 @@
   const cc::RenderFrameMetadata& LastRenderFrameMetadata() const override;
 
  private:
-  friend class FakeRenderWidgetHostViewAura;
-
   // Paired with the mojom::RenderFrameMetadataObserverClient overrides, these
   // methods are enqueued in |frame_token_message_queue_|. They are invoked when
   // the browser process receives their associated frame tokens. These then
@@ -53,10 +51,6 @@
   void OnFrameTokenRenderFrameMetadataChanged(cc::RenderFrameMetadata metadata);
   void OnFrameTokenFrameSubmissionForTesting();
 
-  // Set |last_render_frame_metadata_| to the given |metadata| for testing
-  // purpose.
-  void SetLastRenderFrameMetadataForTest(cc::RenderFrameMetadata metadata);
-
   // mojom::RenderFrameMetadataObserverClient:
   void OnRenderFrameMetadataChanged(
       uint32_t frame_token,
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index cfcd003b..a9e5d18 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -95,6 +95,7 @@
 class BrowserAccessibilityManager;
 class InputRouter;
 class MockRenderWidgetHost;
+class RenderFrameMetadataProvider;
 class RenderWidgetHostOwnerDelegate;
 class SyntheticGestureController;
 class TimeoutMonitor;
@@ -601,7 +602,7 @@
     return last_auto_resize_request_number_;
   }
 
-  RenderFrameMetadataProviderImpl* render_frame_metadata_provider() {
+  RenderFrameMetadataProvider* render_frame_metadata_provider() {
     return &render_frame_metadata_provider_;
   }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 71e54a4..5c53c26 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1938,11 +1938,6 @@
   WasResized();
 }
 
-void RenderWidgetHostViewAndroid::OnContentViewCoreDestroyed() {
-  UpdateNativeViewTree(nullptr);
-  overscroll_controller_.reset();
-}
-
 void RenderWidgetHostViewAndroid::OnRootWindowVisibilityChanged(bool visible) {
   TRACE_EVENT1("browser",
                "RenderWidgetHostViewAndroid::OnRootWindowVisibilityChanged",
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 782db81..f13d8c7 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -249,7 +249,6 @@
 
   // Non-virtual methods
   void UpdateNativeViewTree(gfx::NativeView parent_native_view);
-  void OnContentViewCoreDestroyed();
   SkColor GetCachedBackgroundColor() const;
   void SendKeyEvent(const NativeWebKeyboardEvent& event);
   void SendMouseEvent(const ui::MotionEventAndroid&, int action_button);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index b7a19301..a62fdee 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -878,6 +878,12 @@
   DCHECK(delegated_frame_host_);
   TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
 
+  // Override the background color to the current compositor background.
+  // This allows us to, when navigating to a new page, transfer this color to
+  // that page. This allows us to pass this background color to new views on
+  // navigation.
+  UpdateBackgroundColorFromRenderer(frame.metadata.root_background_color);
+
   last_scroll_offset_ = frame.metadata.root_scroll_offset;
   if (IsUseZoomForDSFEnabled()) {
     // With zoom-for-DSF Blink pixel coordinates are used and zoom is used to
@@ -1777,16 +1783,6 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, RenderFrameMetadataProvider::Observer
-// implementation:
-void RenderWidgetHostViewAura::OnRenderFrameMetadataChanged() {
-  UpdateBackgroundColorFromRenderer(host()
-                                        ->render_frame_metadata_provider()
-                                        ->LastRenderFrameMetadata()
-                                        .root_background_color);
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // RenderWidgetHostViewAura, private:
 
 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index f54822b..3c65a71 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -283,9 +283,6 @@
   void OnHostMovedInPixels(aura::WindowTreeHost* host,
                            const gfx::Point& new_origin_in_pixels) override;
 
-  // RenderFrameMetadataProvider::Observer
-  void OnRenderFrameMetadataChanged() override;
-
 #if defined(OS_WIN)
   // Gets the HWND of the host window.
   HWND GetHostWindowHWND() const;
@@ -525,9 +522,7 @@
   void UpdateNeedsBeginFramesInternal();
 
   // Applies background color without notifying the RenderWidget about
-  // opaqueness changes. This allows us to, when navigating to a new page,
-  // transfer this color to that page. This allows us to pass this background
-  // color to new views on navigation.
+  // opaqueness changes.
   void UpdateBackgroundColorFromRenderer(SkColor color);
 
   const bool is_mus_browser_plugin_guest_;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index a916856..eb3ee7b7 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -25,7 +25,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
-#include "cc/trees/render_frame_metadata.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/quads/compositor_frame.h"
@@ -51,7 +50,6 @@
 #include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
 #include "content/browser/renderer_host/overscroll_controller.h"
 #include "content/browser/renderer_host/overscroll_controller_delegate.h"
-#include "content/browser/renderer_host/render_frame_metadata_provider_impl.h"
 #include "content/browser/renderer_host/render_view_host_factory.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -139,6 +137,8 @@
     RenderWidgetHostViewAura* render_widget_host_view,
     std::unique_ptr<DelegatedFrameHostClient> delegated_frame_host_client);
 
+namespace {
+
 constexpr uint64_t kFrameIndexStart =
     viz::CompositorFrameSinkSupport::kFrameIndexStart;
 
@@ -352,11 +352,6 @@
     return event_handler()->pointer_state();
   }
 
-  void SetRenderFrameMetadata(cc::RenderFrameMetadata metadata) {
-    host()->render_frame_metadata_provider()->SetLastRenderFrameMetadataForTest(
-        metadata);
-  }
-
   bool resize_locked() const {
     return delegated_frame_host_client_->resize_locked();
   }
@@ -484,6 +479,8 @@
   kAsyncWheelEvents,
 };
 
+}  // namespace
+
 class RenderWidgetHostViewAuraTest : public testing::Test {
  public:
   RenderWidgetHostViewAuraTest(
@@ -2762,10 +2759,11 @@
       gfx::Rect());
   view_->SetSize(frame_size);
   view_->Show();
-  cc::RenderFrameMetadata metadata;
-  metadata.root_background_color = SK_ColorRED;
-  view_->SetRenderFrameMetadata(metadata);
-  view_->OnRenderFrameMetadataChanged();
+  viz::CompositorFrame frame =
+      MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size));
+  frame.metadata.root_background_color = SK_ColorRED;
+  view_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr);
+
   ui::Layer* parent_layer = view_->GetNativeView()->layer();
 
   EXPECT_EQ(gfx::Rect(0, 0, 100, 100), parent_layer->bounds());
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index 122a22ae..37da659 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -51,9 +51,7 @@
           features::kTouchpadAndWheelScrollLatching)),
       web_contents_accessibility_(nullptr),
       renderer_frame_number_(0),
-      weak_factory_(this) {
-  host_->render_frame_metadata_provider()->AddObserver(this);
-}
+      weak_factory_(this) {}
 
 RenderWidgetHostViewBase::~RenderWidgetHostViewBase() {
   DCHECK(!mouse_locked_);
@@ -69,8 +67,6 @@
   // so that the |text_input_manager_| will free its state.
   if (text_input_manager_)
     text_input_manager_->Unregister(this);
-  if (host_)
-    host_->render_frame_metadata_provider()->RemoveObserver(this);
 }
 
 RenderWidgetHostImpl* RenderWidgetHostViewBase::GetFocusedWidget() const {
@@ -96,10 +92,6 @@
   return false;
 }
 
-void RenderWidgetHostViewBase::OnRenderFrameMetadataChanged() {}
-
-void RenderWidgetHostViewBase::OnRenderFrameSubmission() {}
-
 void RenderWidgetHostViewBase::SetBackgroundColorToDefault() {
   SetBackgroundColor(SK_ColorWHITE);
 }
@@ -476,10 +468,7 @@
 }
 
 void RenderWidgetHostViewBase::Destroy() {
-  if (host_) {
-    host_->render_frame_metadata_provider()->RemoveObserver(this);
-    host_ = nullptr;
-  }
+  host_ = nullptr;
 }
 
 void RenderWidgetHostViewBase::TextInputStateChanged(
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index 5937ae30..e44d950 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -23,7 +23,6 @@
 #include "components/viz/common/surfaces/surface_id.h"
 #include "content/browser/renderer_host/event_with_latency_info.h"
 #include "content/common/content_export.h"
-#include "content/public/browser/render_frame_metadata_provider.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/common/input_event_ack_state.h"
 #include "content/public/common/screen_info.h"
@@ -89,10 +88,8 @@
 struct TextInputState;
 
 // Basic implementation shared by concrete RenderWidgetHostView subclasses.
-class CONTENT_EXPORT RenderWidgetHostViewBase
-    : public RenderWidgetHostView,
-      public IPC::Listener,
-      public RenderFrameMetadataProvider::Observer {
+class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
+                                                public IPC::Listener {
  public:
   using CreateCompositorFrameSinkCallback =
       base::OnceCallback<void(const viz::FrameSinkId&)>;
@@ -139,10 +136,6 @@
   // IPC::Listener implementation:
   bool OnMessageReceived(const IPC::Message& msg) override;
 
-  // RenderFrameMetadataProvider::Observer
-  void OnRenderFrameMetadataChanged() override;
-  void OnRenderFrameSubmission() override;
-
   void SetPopupType(blink::WebPopupType popup_type);
 
   blink::WebPopupType GetPopupType();
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
index 8f029c47..6f871af2 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -408,6 +408,7 @@
   // RenderWidgetHostInputEventRouter afterwards.
   NotifyObserversAboutShutdown();
 
+  host()->SetView(nullptr);
   RenderWidgetHostViewBase::Destroy();
 
   delete this;
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc
index 1916f19..029aa1a 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -137,33 +137,6 @@
   return true;
 }
 
-void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
-    std::unique_ptr<ServiceWorkerHandle> handle) {
-  int handle_id = handle->handle_id();
-  handles_.AddWithID(std::move(handle), handle_id);
-}
-
-ServiceWorkerHandle* ServiceWorkerDispatcherHost::FindServiceWorkerHandle(
-    int provider_id,
-    int64_t version_id) {
-  for (base::IDMap<std::unique_ptr<ServiceWorkerHandle>>::iterator iter(
-           &handles_);
-       !iter.IsAtEnd(); iter.Advance()) {
-    ServiceWorkerHandle* handle = iter.GetCurrentValue();
-    DCHECK(handle);
-    DCHECK(handle->version());
-    if (handle->provider_id() == provider_id &&
-        handle->version()->version_id() == version_id) {
-      return handle;
-    }
-  }
-  return nullptr;
-}
-
-void ServiceWorkerDispatcherHost::UnregisterServiceWorkerHandle(int handle_id) {
-  handles_.Remove(handle_id);
-}
-
 base::WeakPtr<ServiceWorkerDispatcherHost>
 ServiceWorkerDispatcherHost::AsWeakPtr() {
   return weak_ptr_factory_.GetWeakPtr();
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.h b/content/browser/service_worker/service_worker_dispatcher_host.h
index e73c2c9..b921e949 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -10,7 +10,6 @@
 #include <memory>
 #include <vector>
 
-#include "base/containers/id_map.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
@@ -29,7 +28,6 @@
 class ResourceContext;
 class ServiceWorkerContextCore;
 class ServiceWorkerContextWrapper;
-class ServiceWorkerHandle;
 
 namespace service_worker_dispatcher_host_unittest {
 class ServiceWorkerDispatcherHostTest;
@@ -85,14 +83,6 @@
   // be destroyed.
   bool Send(IPC::Message* message) override;
 
-  // These methods are virtual only for testing.
-  virtual void RegisterServiceWorkerHandle(
-      std::unique_ptr<ServiceWorkerHandle> handle);
-  virtual void UnregisterServiceWorkerHandle(int handle_id);
-
-  ServiceWorkerHandle* FindServiceWorkerHandle(int provider_id,
-                                               int64_t version_id);
-
   ResourceContext* resource_context() { return resource_context_; }
 
   base::WeakPtr<ServiceWorkerDispatcherHost> AsWeakPtr();
@@ -133,8 +123,6 @@
   // Only accessed on the IO thread.
   scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
 
-  base::IDMap<std::unique_ptr<ServiceWorkerHandle>> handles_;
-
   bool channel_ready_;  // True after BrowserMessageFilter::sender_ != NULL.
   std::vector<std::unique_ptr<IPC::Message>> pending_messages_;
 
diff --git a/content/browser/service_worker/service_worker_handle.cc b/content/browser/service_worker/service_worker_handle.cc
index 0aee7f2..a77f48f 100644
--- a/content/browser/service_worker/service_worker_handle.cc
+++ b/content/browser/service_worker/service_worker_handle.cc
@@ -7,7 +7,6 @@
 #include "base/memory/ptr_util.h"
 #include "content/browser/service_worker/service_worker_client_utils.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
-#include "content/browser/service_worker/service_worker_dispatcher_host.h"
 #include "content/browser/service_worker/service_worker_provider_host.h"
 #include "content/browser/service_worker/service_worker_registration.h"
 #include "content/browser/service_worker/service_worker_type_converters.h"
@@ -153,40 +152,22 @@
 
 }  // namespace
 
-// static
-base::WeakPtr<ServiceWorkerHandle> ServiceWorkerHandle::Create(
-    ServiceWorkerDispatcherHost* dispatcher_host,
-    base::WeakPtr<ServiceWorkerContextCore> context,
-    base::WeakPtr<ServiceWorkerProviderHost> provider_host,
-    ServiceWorkerVersion* version,
-    blink::mojom::ServiceWorkerObjectInfoPtr* out_info) {
-  DCHECK(context && provider_host && version && out_info);
-  ServiceWorkerHandle* handle =
-      new ServiceWorkerHandle(dispatcher_host, context, provider_host, version);
-  *out_info = handle->CreateObjectInfo();
-  return handle->AsWeakPtr();
-}
-
 ServiceWorkerHandle::ServiceWorkerHandle(
-    ServiceWorkerDispatcherHost* dispatcher_host,
     base::WeakPtr<ServiceWorkerContextCore> context,
-    base::WeakPtr<ServiceWorkerProviderHost> provider_host,
-    ServiceWorkerVersion* version)
-    : dispatcher_host_(dispatcher_host),
-      context_(context),
+    ServiceWorkerProviderHost* provider_host,
+    scoped_refptr<ServiceWorkerVersion> version)
+    : context_(context),
       provider_host_(provider_host),
       provider_origin_(url::Origin::Create(provider_host->document_url())),
       provider_id_(provider_host->provider_id()),
       handle_id_(context->GetNewServiceWorkerHandleId()),
-      version_(version),
+      version_(std::move(version)),
       weak_ptr_factory_(this) {
   DCHECK(context_ && provider_host_ && version_);
   DCHECK(context_->GetLiveRegistration(version_->registration_id()));
   version_->AddListener(this);
   bindings_.set_connection_error_handler(base::BindRepeating(
       &ServiceWorkerHandle::OnConnectionError, base::Unretained(this)));
-  if (dispatcher_host_)
-    dispatcher_host_->RegisterServiceWorkerHandle(base::WrapUnique(this));
 }
 
 ServiceWorkerHandle::~ServiceWorkerHandle() {
@@ -195,8 +176,6 @@
 
 void ServiceWorkerHandle::OnVersionStateChanged(ServiceWorkerVersion* version) {
   DCHECK(version);
-  if (!provider_host_)
-    return;
   provider_host_->SendServiceWorkerStateChangedMessage(
       handle_id_,
       mojo::ConvertTo<blink::mojom::ServiceWorkerState>(version->status()));
@@ -214,15 +193,6 @@
   return info;
 }
 
-void ServiceWorkerHandle::RegisterIntoDispatcherHost(
-    ServiceWorkerDispatcherHost* dispatcher_host) {
-  DCHECK(ServiceWorkerUtils::IsServicificationEnabled() ||
-         IsNavigationMojoResponseEnabled());
-  DCHECK(!dispatcher_host_);
-  dispatcher_host_ = dispatcher_host;
-  dispatcher_host_->RegisterServiceWorkerHandle(base::WrapUnique(this));
-}
-
 void ServiceWorkerHandle::PostMessageToServiceWorker(
     ::blink::TransferableMessage message) {
   // When this method is called the encoded_message inside message could just
@@ -242,8 +212,8 @@
 void ServiceWorkerHandle::DispatchExtendableMessageEvent(
     ::blink::TransferableMessage message,
     StatusCallback callback) {
-  if (!context_ || !provider_host_) {
-    std::move(callback).Run(SERVICE_WORKER_ERROR_FAILED);
+  if (!context_) {
+    std::move(callback).Run(SERVICE_WORKER_ERROR_ABORT);
     return;
   }
   DCHECK_EQ(provider_origin_,
@@ -251,7 +221,7 @@
   switch (provider_host_->provider_type()) {
     case blink::mojom::ServiceWorkerProviderType::kForWindow:
       service_worker_client_utils::GetClient(
-          provider_host_.get(),
+          provider_host_,
           base::BindOnce(&DispatchExtendableMessageEventFromClient, version_,
                          std::move(message), provider_origin_,
                          std::move(callback)));
@@ -267,7 +237,7 @@
           base::BindOnce(&DispatchExtendableMessageEventFromServiceWorker,
                          version_, std::move(message), provider_origin_,
                          base::make_optional(timeout), std::move(callback),
-                         provider_host_));
+                         provider_host_->AsWeakPtr()));
       return;
     }
     case blink::mojom::ServiceWorkerProviderType::kForSharedWorker:
@@ -287,16 +257,8 @@
   // If there are still bindings, |this| is still being used.
   if (!bindings_.empty())
     return;
-  // S13nServiceWorker: This handle may have been precreated before registering
-  // to a dispatcher host. Just self-destruct since we're no longer needed.
-  if (!dispatcher_host_) {
-    DCHECK(ServiceWorkerUtils::IsServicificationEnabled() ||
-           IsNavigationMojoResponseEnabled());
-    delete this;
-    return;
-  }
   // Will destroy |this|.
-  dispatcher_host_->UnregisterServiceWorkerHandle(handle_id_);
+  provider_host_->RemoveServiceWorkerHandle(version_->version_id());
 }
 
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_handle.h b/content/browser/service_worker/service_worker_handle.h
index f9bfb06..d750aa7 100644
--- a/content/browser/service_worker/service_worker_handle.h
+++ b/content/browser/service_worker/service_worker_handle.h
@@ -20,7 +20,6 @@
 namespace content {
 
 class ServiceWorkerContextCore;
-class ServiceWorkerDispatcherHost;
 class ServiceWorkerProviderHost;
 
 namespace service_worker_handle_unittest {
@@ -39,22 +38,9 @@
     : public blink::mojom::ServiceWorkerObjectHost,
       public ServiceWorkerVersion::Listener {
  public:
-  // Creates a newly created instance for a live version. |out_info| holds the
-  // first ServiceWorkerObjectHost Mojo connection to this instance, which will
-  // delete itself once it detects that all the Mojo connections have gone
-  // away.
-  //
-  // This instance registers itself into |dispatcher_host| to be owned by the
-  // dispatcher host. S13nServiceWorker: |dispatcher_host| may be null.
-  // RegisterIntoDispatcherHost() should be called later to register the handle
-  // once the host is known.
-  static base::WeakPtr<ServiceWorkerHandle> Create(
-      ServiceWorkerDispatcherHost* dispatcher_host,
-      base::WeakPtr<ServiceWorkerContextCore> context,
-      base::WeakPtr<ServiceWorkerProviderHost> provider_host,
-      ServiceWorkerVersion* version,
-      blink::mojom::ServiceWorkerObjectInfoPtr* out_info);
-
+  ServiceWorkerHandle(base::WeakPtr<ServiceWorkerContextCore> context,
+                      ServiceWorkerProviderHost* provider_host,
+                      scoped_refptr<ServiceWorkerVersion> version);
   ~ServiceWorkerHandle() override;
 
   // ServiceWorkerVersion::Listener overrides.
@@ -63,10 +49,6 @@
   // Establishes a new mojo connection into |bindings_|.
   blink::mojom::ServiceWorkerObjectInfoPtr CreateObjectInfo();
 
-  // Should only be called on a ServiceWorkerHandle instance constructed with
-  // null |dispatcher_host| before.
-  void RegisterIntoDispatcherHost(ServiceWorkerDispatcherHost* dispatcher_host);
-
   int provider_id() const { return provider_id_; }
   int handle_id() const { return handle_id_; }
   ServiceWorkerVersion* version() { return version_.get(); }
@@ -74,11 +56,6 @@
  private:
   friend class service_worker_handle_unittest::ServiceWorkerHandleTest;
 
-  ServiceWorkerHandle(ServiceWorkerDispatcherHost* dispatcher_host,
-                      base::WeakPtr<ServiceWorkerContextCore> context,
-                      base::WeakPtr<ServiceWorkerProviderHost> provider_host,
-                      ServiceWorkerVersion* version);
-
   // Implements blink::mojom::ServiceWorkerObjectHost.
   void PostMessageToServiceWorker(
       ::blink::TransferableMessage message) override;
@@ -95,13 +72,10 @@
 
   void OnConnectionError();
 
-  // |dispatcher_host_| may get a valid value via ctor or
-  // RegisterIntoDispatcherHost() function, after that |dispatcher_host_| starts
-  // to own |this|, then, |dispatcher_host_| is valid throughout the lifetime of
-  // |this|.
-  ServiceWorkerDispatcherHost* dispatcher_host_;
   base::WeakPtr<ServiceWorkerContextCore> context_;
-  base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+  // |provider_host_| is valid throughout lifetime of |this| because it owns
+  // |this|.
+  ServiceWorkerProviderHost* provider_host_;
   // The origin of the |provider_host_|. Note that this is const because once a
   // JavaScript ServiceWorker object is created for an execution context, we
   // don't expect that context to change origins and still hold on to the
diff --git a/content/browser/service_worker/service_worker_handle_unittest.cc b/content/browser/service_worker/service_worker_handle_unittest.cc
index 519152a..6ef43f0 100644
--- a/content/browser/service_worker/service_worker_handle_unittest.cc
+++ b/content/browser/service_worker/service_worker_handle_unittest.cc
@@ -192,6 +192,15 @@
     return handle->bindings_.size();
   }
 
+  ServiceWorkerHandle* GetServiceWorkerHandle(
+      ServiceWorkerProviderHost* provider_host,
+      int64_t version_id) {
+    auto iter = provider_host->handles_.find(version_id);
+    if (iter != provider_host->handles_.end())
+      return iter->second.get();
+    return nullptr;
+  }
+
   IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); }
 
   TestBrowserThreadBundle browser_thread_bundle_;
@@ -221,12 +230,10 @@
           helper_->mock_render_process_id(), kProviderId,
           helper_->context()->AsWeakPtr(), kRenderFrameId,
           dispatcher_host_.get(), &remote_endpoint);
-  blink::mojom::ServiceWorkerObjectInfoPtr info;
-  // ServiceWorkerHandle lifetime is controlled by |info| and is also owned by
-  // |dispatcher_host_|.
-  base::WeakPtr<ServiceWorkerHandle> handle = ServiceWorkerHandle::Create(
-      dispatcher_host_.get(), helper_->context()->AsWeakPtr(),
-      provider_host->AsWeakPtr(), version_.get(), &info);
+  blink::mojom::ServiceWorkerObjectInfoPtr info =
+      provider_host->GetOrCreateServiceWorkerHandle(version_.get());
+  ServiceWorkerHandle* handle =
+      GetServiceWorkerHandle(provider_host.get(), version_->version_id());
 
   // Start the worker, and then...
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
@@ -281,16 +288,12 @@
 
   // Prepare a ServiceWorkerHandle corresponding to a JavaScript ServiceWorker
   // object in the service worker execution context for |version_|.
-  EXPECT_FALSE(dispatcher_host_->FindServiceWorkerHandle(
-      version_->provider_host()->provider_id(), version_->version_id()));
-  blink::mojom::ServiceWorkerObjectInfoPtr info;
-  // ServiceWorkerHandle lifetime is controlled by |info| and is also owned by
-  // |dispatcher_host_|.
-  base::WeakPtr<ServiceWorkerHandle> sender_worker_handle =
-      ServiceWorkerHandle::Create(
-          dispatcher_host_.get(), helper_->context()->AsWeakPtr(),
-          version_->provider_host()->AsWeakPtr(), version_.get(), &info);
-  EXPECT_EQ(1u, GetBindingsCount(sender_worker_handle.get()));
+  ServiceWorkerProviderHost* provider_host = version_->provider_host();
+  blink::mojom::ServiceWorkerObjectInfoPtr info =
+      provider_host->GetOrCreateServiceWorkerHandle(version_.get());
+  ServiceWorkerHandle* sender_worker_handle =
+      GetServiceWorkerHandle(provider_host, version_->version_id());
+  EXPECT_EQ(1u, GetBindingsCount(sender_worker_handle));
 
   // Dispatch an ExtendableMessageEvent simulating calling
   // ServiceWorker#postMessage() on the ServiceWorker object corresponding to
@@ -300,7 +303,7 @@
   called = false;
   status = SERVICE_WORKER_ERROR_MAX_VALUE;
   CallDispatchExtendableMessageEvent(
-      sender_worker_handle.get(), std::move(message),
+      sender_worker_handle, std::move(message),
       base::BindOnce(&SaveStatusCallback, &called, &status));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(called);
@@ -309,7 +312,7 @@
   // ExtendableMessageEventTestHelper, and the source service worker object info
   // should correspond to the pair (|version_->provider_host()|, |version_|),
   // means it should correspond to |sender_worker_handle|.
-  EXPECT_EQ(2u, GetBindingsCount(sender_worker_handle.get()));
+  EXPECT_EQ(2u, GetBindingsCount(sender_worker_handle));
   const std::vector<mojom::ExtendableMessageEventPtr>& events =
       static_cast<ExtendableMessageEventTestHelper*>(helper_.get())->events();
   EXPECT_EQ(1u, events.size());
@@ -349,12 +352,10 @@
           helper_->context()->AsWeakPtr(), dispatcher_host_->AsWeakPtr());
   provider_host->SetDocumentUrl(pattern);
   // Prepare a ServiceWorkerHandle for the above |provider_host|.
-  blink::mojom::ServiceWorkerObjectInfoPtr info;
-  // ServiceWorkerHandle lifetime is controlled by |info| and is also owned by
-  // |dispatcher_host_|.
-  base::WeakPtr<ServiceWorkerHandle> handle = ServiceWorkerHandle::Create(
-      dispatcher_host_.get(), helper_->context()->AsWeakPtr(),
-      provider_host->AsWeakPtr(), version_.get(), &info);
+  blink::mojom::ServiceWorkerObjectInfoPtr info =
+      provider_host->GetOrCreateServiceWorkerHandle(version_.get());
+  ServiceWorkerHandle* handle =
+      GetServiceWorkerHandle(provider_host.get(), version_->version_id());
 
   // Simulate dispatching an ExtendableMessageEvent.
   blink::TransferableMessage message;
@@ -362,7 +363,7 @@
   bool called = false;
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
   CallDispatchExtendableMessageEvent(
-      handle.get(), std::move(message),
+      handle, std::move(message),
       base::BindOnce(&SaveStatusCallback, &called, &status));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(called);
@@ -406,12 +407,10 @@
           helper_->context()->AsWeakPtr(), dispatcher_host_->AsWeakPtr());
   provider_host->SetDocumentUrl(pattern);
   // Prepare a ServiceWorkerHandle for the above |provider_host|.
-  blink::mojom::ServiceWorkerObjectInfoPtr info;
-  // ServiceWorkerHandle lifetime is controlled by |info| and is also owned by
-  // |dispatcher_host_|.
-  base::WeakPtr<ServiceWorkerHandle> handle = ServiceWorkerHandle::Create(
-      dispatcher_host_.get(), helper_->context()->AsWeakPtr(),
-      provider_host->AsWeakPtr(), version_.get(), &info);
+  blink::mojom::ServiceWorkerObjectInfoPtr info =
+      provider_host->GetOrCreateServiceWorkerHandle(version_.get());
+  ServiceWorkerHandle* handle =
+      GetServiceWorkerHandle(provider_host.get(), version_->version_id());
 
   // Try to dispatch ExtendableMessageEvent. This should fail to start the
   // worker and to dispatch the event.
@@ -420,7 +419,7 @@
   bool called = false;
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
   CallDispatchExtendableMessageEvent(
-      handle.get(), std::move(message),
+      handle, std::move(message),
       base::BindOnce(&SaveStatusCallback, &called, &status));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(called);
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc
index eda6e0d..8da6612 100644
--- a/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -19,7 +19,6 @@
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_disk_cache.h"
-#include "content/browser/service_worker/service_worker_dispatcher_host.h"
 #include "content/browser/service_worker/service_worker_handle.h"
 #include "content/browser/service_worker/service_worker_job_coordinator.h"
 #include "content/browser/service_worker/service_worker_registration.h"
@@ -50,42 +49,6 @@
 
 namespace {
 
-// A dispatcher host that holds on to all registered ServiceWorkerHandles.
-class KeepHandlesDispatcherHost : public ServiceWorkerDispatcherHost {
- public:
-  KeepHandlesDispatcherHost(int render_process_id,
-                            ResourceContext* resource_context)
-      : ServiceWorkerDispatcherHost(render_process_id, resource_context) {}
-  void RegisterServiceWorkerHandle(
-      std::unique_ptr<ServiceWorkerHandle> handle) override {
-    handles_.push_back(std::move(handle));
-  }
-
-  void UnregisterServiceWorkerHandle(int handle_id) override {
-    auto iter = handles_.begin();
-    for (; iter != handles_.end(); ++iter) {
-      if ((*iter)->handle_id() == handle_id)
-        break;
-    }
-    ASSERT_NE(handles_.end(), iter);
-    handles_.erase(iter);
-  }
-
-  void Clear() {
-    handles_.clear();
-  }
-
-  const std::vector<std::unique_ptr<ServiceWorkerHandle>>& handles() {
-    return handles_;
-  }
-
- private:
-  ~KeepHandlesDispatcherHost() override {}
-
-  std::vector<std::unique_ptr<ServiceWorkerHandle>> handles_;
-  DISALLOW_COPY_AND_ASSIGN(KeepHandlesDispatcherHost);
-};
-
 void SaveRegistrationCallback(
     ServiceWorkerStatusCode expected_status,
     bool* called,
@@ -338,41 +301,32 @@
 
 // Make sure registrations are cleaned up when they are unregistered.
 TEST_F(ServiceWorkerJobTest, Unregister) {
-  // During registration, service worker handles will be created to host the
-  // {installing,waiting,active} service worker objects for
-  // ServiceWorkerGlobalScope#registration. KeepHandlesDispatcherHost will store
-  // the handles.
-  scoped_refptr<KeepHandlesDispatcherHost> dispatcher_host =
-      base::MakeRefCounted<KeepHandlesDispatcherHost>(
-          helper_->mock_render_process_id(),
-          helper_->browser_context()->GetResourceContext());
-  helper_->RegisterDispatcherHost(helper_->mock_render_process_id(),
-                                  dispatcher_host);
-  dispatcher_host->Init(helper_->context_wrapper());
-
   blink::mojom::ServiceWorkerRegistrationOptions options;
   options.scope = GURL("http://www.example.com/");
   scoped_refptr<ServiceWorkerRegistration> registration =
       RunRegisterJob(GURL("http://www.example.com/service_worker.js"), options);
+  scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
 
-  // During the above registration, a service worker registration object host
-  // for ServiceWorkerGlobalScope#registration has been created/added into
-  // |provider_host|.
   ServiceWorkerProviderHost* provider_host =
       registration->active_version()->provider_host();
   ASSERT_NE(nullptr, provider_host);
+  // One ServiceWorkerRegistrationObjectHost should have been created for the
+  // new registration.
   EXPECT_EQ(1UL, provider_host->registration_object_hosts_.size());
-  EXPECT_EQ(3UL, dispatcher_host->handles().size());
+  // One ServiceWorkerHandle should have been created for the new service
+  // worker.
+  EXPECT_EQ(1UL, provider_host->handles_.size());
 
   RunUnregisterJob(options.scope);
 
-  // Clear all service worker handles.
-  dispatcher_host->Clear();
-  EXPECT_EQ(0UL, dispatcher_host->handles().size());
-  // The service worker registration object host has been destroyed together
-  // with |provider_host| by the above unregistration. Then the only reference
-  // to the registration should be |registration|.
+  // The service worker registration object host and service worker handle have
+  // been destroyed together with |provider_host| by the above unregistration.
+  // Then |registration| and |version| should be the last one reference to the
+  // corresponding instance.
   EXPECT_TRUE(registration->HasOneRef());
+  EXPECT_TRUE(version->HasOneRef());
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
+  EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
 
   registration =
       FindRegistrationForPattern(options.scope, SERVICE_WORKER_ERROR_NOT_FOUND);
@@ -415,16 +369,6 @@
 // Make sure that when registering a duplicate pattern+script_url
 // combination, that the same registration is used.
 TEST_F(ServiceWorkerJobTest, RegisterDuplicateScript) {
-  // During registration, handles will be created for hosting the worker's
-  // context. KeepHandlesDispatcherHost will store the handles.
-  scoped_refptr<KeepHandlesDispatcherHost> dispatcher_host =
-      new KeepHandlesDispatcherHost(
-          helper_->mock_render_process_id(),
-          helper_->browser_context()->GetResourceContext());
-  helper_->RegisterDispatcherHost(helper_->mock_render_process_id(),
-                                  dispatcher_host);
-  dispatcher_host->Init(helper_->context_wrapper());
-
   GURL script_url("http://www.example.com/service_worker.js");
   blink::mojom::ServiceWorkerRegistrationOptions options;
   options.scope = GURL("http://www.example.com/");
@@ -440,7 +384,7 @@
   ASSERT_NE(nullptr, provider_host);
 
   // Clear all service worker handles.
-  dispatcher_host->Clear();
+  provider_host->handles_.clear();
   // Ensure that the registration's object host doesn't have the reference.
   EXPECT_EQ(1UL, provider_host->registration_object_hosts_.size());
   provider_host->registration_object_hosts_.clear();
@@ -469,15 +413,6 @@
 // is updated when registering a duplicate pattern+script_url with a different
 // update_via_cache value.
 TEST_F(ServiceWorkerJobTest, RegisterWithDifferentUpdateViaCache) {
-  // During registration, handles will be created for hosting the worker's
-  // context. KeepHandlesDispatcherHost will store the handles.
-  auto dispatcher_host = base::MakeRefCounted<KeepHandlesDispatcherHost>(
-      helper_->mock_render_process_id(),
-      helper_->browser_context()->GetResourceContext());
-  helper_->RegisterDispatcherHost(helper_->mock_render_process_id(),
-                                  dispatcher_host);
-  dispatcher_host->Init(helper_->context_wrapper());
-
   GURL script_url("https://www.example.com/service_worker.js");
   blink::mojom::ServiceWorkerRegistrationOptions options;
   options.scope = GURL("https://www.example.com/");
@@ -496,7 +431,7 @@
   ASSERT_NE(nullptr, provider_host);
 
   // Clear all service worker handles.
-  dispatcher_host->Clear();
+  provider_host->handles_.clear();
   // Ensure that the registration's object host doesn't have the reference.
   EXPECT_EQ(1UL, provider_host->registration_object_hosts_.size());
   provider_host->registration_object_hosts_.clear();
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index 9d57fd88f..cc449730 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -444,6 +444,11 @@
   registration_object_hosts_.erase(registration_id);
 }
 
+void ServiceWorkerProviderHost::RemoveServiceWorkerHandle(int64_t version_id) {
+  DCHECK(base::ContainsKey(handles_, version_id));
+  handles_.erase(version_id);
+}
+
 bool ServiceWorkerProviderHost::AllowServiceWorker(const GURL& scope) {
   return GetContentClient()->browser()->AllowServiceWorker(
       scope, IsProviderForClient() ? topmost_frame_url() : document_url(),
@@ -507,29 +512,15 @@
     ServiceWorkerVersion* version) {
   if (!context_ || !version)
     return nullptr;
-  if (!dispatcher_host_) {
-    DCHECK(ServiceWorkerUtils::IsServicificationEnabled() ||
-           IsNavigationMojoResponseEnabled());
-    blink::mojom::ServiceWorkerObjectInfoPtr info;
-    // This is called before the dispatcher host is created.
-    // |precreated_controller_handle_| instance's lifetime is controlled by its
-    // own internal Mojo connections via |info|.
-    precreated_controller_handle_ = ServiceWorkerHandle::Create(
-        nullptr, context_, AsWeakPtr(), version, &info);
-    return info;
-  }
-  ServiceWorkerHandle* handle = dispatcher_host_->FindServiceWorkerHandle(
-      provider_id(), version->version_id());
-  if (handle) {
-    return handle->CreateObjectInfo();
-  }
 
-  blink::mojom::ServiceWorkerObjectInfoPtr info;
-  // ServiceWorkerHandle lifetime is controlled by |info| and is also owned by
-  // |dispatcher_host_|.
-  ServiceWorkerHandle::Create(dispatcher_host_.get(), context_, AsWeakPtr(),
-                              version, &info);
-  return info;
+  const int64_t version_id = version->version_id();
+  auto existing_handle = handles_.find(version_id);
+  if (existing_handle != handles_.end())
+    return existing_handle->second->CreateObjectInfo();
+
+  handles_[version_id] =
+      std::make_unique<ServiceWorkerHandle>(context_, this, version);
+  return handles_[version_id]->CreateObjectInfo();
 }
 
 bool ServiceWorkerProviderHost::CanAssociateRegistration(
@@ -603,18 +594,6 @@
   if (!controller_)
     return;
 
-  if ((ServiceWorkerUtils::IsServicificationEnabled() ||
-       IsNavigationMojoResponseEnabled()) &&
-      precreated_controller_handle_) {
-    // S13nServiceWorker: register the pre-created handle for the controller
-    // service worker with the dispatcher host, now that it exists.
-    DCHECK_NE(blink::mojom::kInvalidServiceWorkerHandleId,
-              precreated_controller_handle_->handle_id());
-    precreated_controller_handle_->RegisterIntoDispatcherHost(
-        dispatcher_host_.get());
-    precreated_controller_handle_ = nullptr;
-  }
-
   // In S13nServiceWorker/NavigationMojoResponse case the controller is already
   // sent in navigation commit, but we still need this for
   // S13nServiceWorker/NavigationMojoResponse case for setting the use counter
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index 3e0a0e7..8ba983d 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -40,6 +40,10 @@
 class ResourceRequestBody;
 }
 
+namespace service_worker_handle_unittest {
+class ServiceWorkerHandleTest;
+}
+
 namespace storage {
 class BlobStorageContext;
 }
@@ -282,6 +286,8 @@
   // The object info holds a Mojo connection to the ServiceWorkerHandle for the
   // |version| to ensure the handle stays alive while the object info is alive.
   // A new handle is created if one does not already exist.
+  // TODO(leonhsl): Make |version| be a scoped_refptr because we'll take its
+  // ownership.
   blink::mojom::ServiceWorkerObjectInfoPtr GetOrCreateServiceWorkerHandle(
       ServiceWorkerVersion* version);
 
@@ -345,6 +351,9 @@
   // |registration_id|.
   void RemoveServiceWorkerRegistrationObjectHost(int64_t registration_id);
 
+  // Removes the ServiceWorkerHandle corresponding to |version_id|.
+  void RemoveServiceWorkerHandle(int64_t version_id);
+
   // Calls ContentBrowserClient::AllowServiceWorker(). Returns true if content
   // settings allows service workers to run at |scope|. If this provider is for
   // a window client, the check involves the topmost frame url as well as
@@ -361,6 +370,7 @@
   friend class ServiceWorkerProviderHostTest;
   friend class ServiceWorkerWriteToCacheJobTest;
   friend class ServiceWorkerContextRequestHandlerTest;
+  friend class service_worker_handle_unittest::ServiceWorkerHandleTest;
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest, Update_SameScript);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest,
                            Update_SameSizeScript);
@@ -529,6 +539,13 @@
            std::unique_ptr<ServiceWorkerRegistrationObjectHost>>
       registration_object_hosts_;
 
+  // Contains all ServiceWorkerHandle instances corresponding to
+  // the service worker JavaScript objects for the hosted execution
+  // context (service worker global scope or service worker client) in the
+  // renderer process.
+  std::map<int64_t /* version_id */, std::unique_ptr<ServiceWorkerHandle>>
+      handles_;
+
   // The ready() promise is only allowed to be created once.
   // |get_ready_callback_| has three states:
   // 1. |get_ready_callback_| is null when ready() has not yet been called.
@@ -578,12 +595,6 @@
 
   std::vector<base::Closure> queued_events_;
 
-  // S13nServiceWorker/NavigationMojoResponse:
-  // A service worker handle for the controller service worker that is
-  // pre-created before the renderer process (and therefore the dispatcher host)
-  // is created.
-  base::WeakPtr<ServiceWorkerHandle> precreated_controller_handle_;
-
   // For provider hosts that are hosting a running service worker.
   mojo::Binding<service_manager::mojom::InterfaceProvider>
       interface_provider_binding_;
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc
index cd037f8..2efee91 100644
--- a/content/browser/web_contents/web_contents_view_android.cc
+++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -89,7 +89,6 @@
     WebContentsImpl* web_contents,
     WebContentsViewDelegate* delegate)
     : web_contents_(web_contents),
-      content_view_core_(NULL),
       delegate_(delegate),
       view_(this, ui::ViewAndroid::LayoutType::NORMAL),
       synchronous_compositor_client_(nullptr) {}
@@ -99,9 +98,9 @@
     view_.GetLayer()->RemoveFromParent();
 }
 
-void WebContentsViewAndroid::SetContentViewCore(
-    ContentViewCore* content_view_core) {
-  content_view_core_ = content_view_core;
+void WebContentsViewAndroid::SetContentViewCore(ContentViewCore* cvc) {
+  if (content_view_core_.get() != cvc)
+    content_view_core_.reset(cvc);
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   if (rwhv)
     rwhv->UpdateNativeViewTree(&view_);
diff --git a/content/browser/web_contents/web_contents_view_android.h b/content/browser/web_contents/web_contents_view_android.h
index 4466d290..fca6b3af 100644
--- a/content/browser/web_contents/web_contents_view_android.h
+++ b/content/browser/web_contents/web_contents_view_android.h
@@ -35,9 +35,7 @@
                          WebContentsViewDelegate* delegate);
   ~WebContentsViewAndroid() override;
 
-  // Sets the interface to the view system. ContentViewCore is owned
-  // by its Java ContentViewCore counterpart, whose lifetime is managed
-  // by the UI frontend.
+  // Sets the interface to the view system.
   void SetContentViewCore(ContentViewCore* content_view_core);
 
   // Sets the object that show/hide popup view for <select> tag.
@@ -136,7 +134,7 @@
   WebContentsImpl* web_contents_;
 
   // ContentViewCore is our interface to the view system.
-  ContentViewCore* content_view_core_;
+  std::unique_ptr<ContentViewCore> content_view_core_;
 
   // Handles "overscroll to refresh" events
   std::unique_ptr<ui::OverscrollRefreshHandler> overscroll_refresh_handler_;
diff --git a/content/browser/web_package/signed_exchange_handler_unittest.cc b/content/browser/web_package/signed_exchange_handler_unittest.cc
index 0bd781f..9ec506f2 100644
--- a/content/browser/web_package/signed_exchange_handler_unittest.cc
+++ b/content/browser/web_package/signed_exchange_handler_unittest.cc
@@ -17,6 +17,8 @@
 #include "net/base/test_completion_callback.h"
 #include "net/cert/mock_cert_verifier.h"
 #include "net/filter/mock_source_stream.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -27,7 +29,7 @@
 const uint64_t kSignatureHeaderDate = 1520834000;
 const int kOutputBufferSize = 4096;
 
-std::string GetTestFileContents(const char* name) {
+std::string GetTestFileContents(base::StringPiece name) {
   base::FilePath path;
   PathService::Get(content::DIR_TEST_DATA, &path);
   path = path.AppendASCII("htxg").AppendASCII(name);
@@ -37,12 +39,21 @@
   return contents;
 }
 
+scoped_refptr<net::X509Certificate> LoadCertificate(
+    const std::string& cert_file) {
+  base::ScopedAllowBlockingForTesting allow_io;
+  return net::CreateCertificateChainFromFile(
+      net::GetTestCertsDirectory(), cert_file,
+      net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
+}
+
 class MockSignedExchangeCertFetcherFactory
     : public SignedExchangeCertFetcherFactory {
  public:
-  MockSignedExchangeCertFetcherFactory(const GURL& expected_cert_url,
-                                       std::string cert_str)
-      : expected_cert_url_(expected_cert_url), cert_str_(cert_str) {}
+  void ExpectFetch(const GURL& cert_url, const std::string& cert_str) {
+    expected_cert_url_ = cert_url;
+    cert_str_ = cert_str;
+  }
 
   std::unique_ptr<SignedExchangeCertFetcher> CreateFetcherAndStart(
       const GURL& cert_url,
@@ -50,11 +61,15 @@
       SignedExchangeCertFetcher::CertificateCallback callback) override {
     EXPECT_EQ(cert_url, expected_cert_url_);
 
+    scoped_refptr<net::X509Certificate> cert;
+
     base::Optional<std::vector<base::StringPiece>> der_certs =
         SignedExchangeCertFetcher::GetCertChainFromMessage(cert_str_);
-    DCHECK(der_certs);
-    scoped_refptr<net::X509Certificate> cert =
-        net::X509Certificate::CreateFromDERCertChain(*der_certs);
+    EXPECT_TRUE(der_certs);
+    if (der_certs) {
+      cert = net::X509Certificate::CreateFromDERCertChain(*der_certs);
+      EXPECT_TRUE(cert);
+    }
 
     base::SequencedTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback), cert));
@@ -62,8 +77,8 @@
   }
 
  private:
-  const GURL expected_cert_url_;
-  const std::string cert_str_;
+  GURL expected_cert_url_;
+  std::string cert_str_;
 };
 
 }  // namespace
@@ -83,14 +98,12 @@
         base::TimeDelta::FromSeconds(kSignatureHeaderDate));
     feature_list_.InitAndEnableFeature(features::kSignedHTTPExchange);
 
-    output_buffer_ = new net::IOBuffer(kOutputBufferSize);
     std::unique_ptr<net::MockSourceStream> source(new net::MockSourceStream());
     source->set_read_one_byte_at_a_time(true);
     source_ = source.get();
     auto cert_fetcher_factory =
-        std::make_unique<MockSignedExchangeCertFetcherFactory>(
-            GURL("https://cert.example.org/cert.msg"),
-            GetTestFileContents("wildcard_example.org.public.pem.msg"));
+        std::make_unique<MockSignedExchangeCertFetcherFactory>();
+    mock_cert_fetcher_factory_ = cert_fetcher_factory.get();
     request_context_getter_ = new net::TestURLRequestContextGetter(
         scoped_task_environment_.GetMainThreadTaskRunner());
     handler_ = std::make_unique<SignedExchangeHandler>(
@@ -106,15 +119,18 @@
         base::Optional<base::Time>());
   }
 
-  // Reads from |payload_stream_| until an error occurs or the EOF is reached.
+  // Reads from |stream| until an error occurs or the EOF is reached.
   // When an error occurs, returns the net error code. When an EOF is reached,
-  // returns the number of bytes read and appends data read to |output|.
-  int ReadPayloadStream(std::string* output) {
+  // returns the number of bytes read. If |output| is non-null, appends data
+  // read to it.
+  int ReadStream(net::SourceStream* stream, std::string* output) {
+    scoped_refptr<net::IOBuffer> output_buffer =
+        new net::IOBuffer(kOutputBufferSize);
     int bytes_read = 0;
     while (true) {
       net::TestCompletionCallback callback;
-      int rv = payload_stream_->Read(output_buffer_.get(), kOutputBufferSize,
-                                     callback.callback());
+      int rv = stream->Read(output_buffer.get(), kOutputBufferSize,
+                            callback.callback());
       if (rv == net::ERR_IO_PENDING) {
         while (source_->awaiting_completion())
           source_->CompleteNextRead();
@@ -126,11 +142,16 @@
         return rv;
       EXPECT_GT(rv, net::OK);
       bytes_read += rv;
-      output->append(output_buffer_->data(), rv);
+      if (output)
+        output->append(output_buffer->data(), rv);
     }
     return bytes_read;
   }
 
+  int ReadPayloadStream(std::string* output) {
+    return ReadStream(payload_stream_.get(), output);
+  }
+
   bool read_header() const { return read_header_; }
   net::Error error() const { return error_; }
   const network::ResourceResponseHead& resource_response() const {
@@ -146,6 +167,7 @@
   }
 
  protected:
+  MockSignedExchangeCertFetcherFactory* mock_cert_fetcher_factory_;
   std::unique_ptr<net::MockCertVerifier> mock_cert_verifier_;
   net::MockSourceStream* source_;
   std::unique_ptr<SignedExchangeHandler> handler_;
@@ -167,7 +189,6 @@
   base::test::ScopedTaskEnvironment scoped_task_environment_;
   scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
   const url::Origin request_initiator_;
-  scoped_refptr<net::IOBuffer> output_buffer_;
 
   bool read_header_ = false;
   net::Error error_;
@@ -185,7 +206,20 @@
 }
 
 TEST_P(SignedExchangeHandlerTest, Simple) {
-  mock_cert_verifier_->set_default_result(net::OK);
+  mock_cert_fetcher_factory_->ExpectFetch(
+      GURL("https://cert.example.org/cert.msg"),
+      GetTestFileContents("wildcard_example.org.public.pem.msg"));
+
+  // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
+  // "*.example.org".
+  scoped_refptr<net::X509Certificate> original_cert =
+      LoadCertificate("wildcard.pem");
+  net::CertVerifyResult dummy_result;
+  dummy_result.verified_cert = original_cert;
+  dummy_result.cert_status = net::OK;
+  mock_cert_verifier_->AddResultForCertAndHost(original_cert, "*.example.org",
+                                               dummy_result, net::OK);
+
   std::string contents = GetTestFileContents("test.example.org_test.htxg");
   source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
   source_->AddReadResult(nullptr, 0, net::OK, GetParam());
@@ -213,6 +247,10 @@
 }
 
 TEST_P(SignedExchangeHandlerTest, MimeType) {
+  mock_cert_fetcher_factory_->ExpectFetch(
+      GURL("https://cert.example.org/cert.msg"),
+      GetTestFileContents("wildcard_example.org.public.pem.msg"));
+
   mock_cert_verifier_->set_default_result(net::OK);
   std::string contents = GetTestFileContents("test.example.org_hello.txt.htxg");
   source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
@@ -257,6 +295,61 @@
   EXPECT_EQ(net::ERR_FAILED, error());
 }
 
+TEST_P(SignedExchangeHandlerTest, CertSha256Mismatch) {
+  // The certificate is for "127.0.0.1". And the SHA 256 hash of the certificate
+  // is different from the certSha256 of the signature in the htxg file. So the
+  // certification verification must fail.
+  mock_cert_fetcher_factory_->ExpectFetch(
+      GURL("https://cert.example.org/cert.msg"),
+      GetTestFileContents("127.0.0.1.public.pem.msg"));
+
+  // Set the default result of MockCertVerifier to OK, to check that the
+  // verification of SignedExchange must fail even if the certificate is valid.
+  mock_cert_verifier_->set_default_result(net::OK);
+
+  std::string contents = GetTestFileContents("test.example.org_test.htxg");
+  source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
+  source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+
+  WaitForHeader();
+
+  ASSERT_TRUE(read_header());
+  EXPECT_EQ(net::ERR_FAILED, error());
+  // Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
+  ReadStream(source_, nullptr);
+}
+
+TEST_P(SignedExchangeHandlerTest, VerifyCertFailure) {
+  mock_cert_fetcher_factory_->ExpectFetch(
+      GURL("https://cert.example.org/cert.msg"),
+      GetTestFileContents("wildcard_example.org.public.pem.msg"));
+
+  // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
+  // "*.example.org".
+  scoped_refptr<net::X509Certificate> original_cert =
+      LoadCertificate("wildcard.pem");
+  net::CertVerifyResult dummy_result;
+  dummy_result.verified_cert = original_cert;
+  dummy_result.cert_status = net::OK;
+  mock_cert_verifier_->AddResultForCertAndHost(original_cert, "*.example.org",
+                                               dummy_result, net::OK);
+
+  // The certificate is for "*.example.com". But the request URL of the htxg
+  // file is "https://test.example.com/test/". So the certification verification
+  // must fail.
+  std::string contents =
+      GetTestFileContents("test.example.com_invalid_test.htxg");
+  source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
+  source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+
+  WaitForHeader();
+
+  ASSERT_TRUE(read_header());
+  EXPECT_EQ(net::ERR_CERT_INVALID, error());
+  // Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
+  ReadStream(source_, nullptr);
+}
+
 INSTANTIATE_TEST_CASE_P(SignedExchangeHandlerTests,
                         SignedExchangeHandlerTest,
                         ::testing::Values(net::MockSourceStream::SYNC,
diff --git a/content/browser/web_package/web_package_request_handler_browsertest.cc b/content/browser/web_package/web_package_request_handler_browsertest.cc
index 5e06e4a..1fcdc09 100644
--- a/content/browser/web_package/web_package_request_handler_browsertest.cc
+++ b/content/browser/web_package/web_package_request_handler_browsertest.cc
@@ -274,60 +274,6 @@
   EXPECT_EQ(content::PAGE_TYPE_ERROR, entry->GetPageType());
 }
 
-IN_PROC_BROWSER_TEST_P(WebPackageRequestHandlerBrowserTest,
-                       CertSha256Mismatch) {
-  // The certificate is for "127.0.0.1". And the SHA 256 hash of the certificate
-  // is different from the certSha256 of the signature in the htxg file. So the
-  // certification verification must fail.
-  InstallUrlInterceptor(GURL("https://cert.example.org/cert.msg"),
-                        "content/test/data/htxg/127.0.0.1.public.pem.msg");
-
-  // Set the default result of MockCertVerifier to OK, to check that the
-  // verification of SignedExchange must fail even if the certificate is valid.
-  mock_cert_verifier_->set_default_result(net::OK);
-
-  embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
-  ASSERT_TRUE(embedded_test_server()->Start());
-  GURL url = embedded_test_server()->GetURL("/htxg/test.example.org_test.htxg");
-
-  NavigationFailureObserver failure_observer(shell()->web_contents());
-  NavigateToURL(shell(), url);
-  EXPECT_TRUE(failure_observer.did_fail());
-  NavigationEntry* entry =
-      shell()->web_contents()->GetController().GetVisibleEntry();
-  EXPECT_EQ(content::PAGE_TYPE_ERROR, entry->GetPageType());
-}
-
-IN_PROC_BROWSER_TEST_P(WebPackageRequestHandlerBrowserTest, VerifyCertFailure) {
-  // The certificate is for "*.example.com". But the request URL of the htxg
-  // file is "https://test.example.com/test/". So the certification verification
-  // must fail.
-  InstallUrlInterceptor(
-      GURL("https://cert.example.org/cert.msg"),
-      "content/test/data/htxg/wildcard_example.org.public.pem.msg");
-
-  // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
-  // "*.example.org".
-  scoped_refptr<net::X509Certificate> original_cert =
-      LoadCertificate("wildcard.pem");
-  net::CertVerifyResult dummy_result;
-  dummy_result.verified_cert = original_cert;
-  dummy_result.cert_status = net::OK;
-  mock_cert_verifier_->AddResultForCertAndHost(original_cert, "*.example.org",
-                                               dummy_result, net::OK);
-
-  embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
-  ASSERT_TRUE(embedded_test_server()->Start());
-  GURL url = embedded_test_server()->GetURL(
-      "/htxg/test.example.com_invalid_test.htxg");
-  NavigationFailureObserver failure_observer(shell()->web_contents());
-  NavigateToURL(shell(), url);
-  EXPECT_TRUE(failure_observer.did_fail());
-  NavigationEntry* entry =
-      shell()->web_contents()->GetController().GetVisibleEntry();
-  EXPECT_EQ(content::PAGE_TYPE_ERROR, entry->GetPageType());
-}
-
 INSTANTIATE_TEST_CASE_P(WebPackageRequestHandlerBrowserTest,
                         WebPackageRequestHandlerBrowserTest,
                         testing::Bool());
diff --git a/content/common/indexed_db/indexed_db.mojom b/content/common/indexed_db/indexed_db.mojom
index 6c42a37..d8fd426 100644
--- a/content/common/indexed_db/indexed_db.mojom
+++ b/content/common/indexed_db/indexed_db.mojom
@@ -8,9 +8,10 @@
 
 module indexed_db.mojom;
 
-import "mojo/common/time.mojom";
 import "mojo/public/mojom/base/file_path.mojom";
 import "mojo/public/mojom/base/string16.mojom";
+import "mojo/public/mojom/base/string16.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "third_party/WebKit/public/mojom/blob/blob.mojom";
 import "url/mojom/origin.mojom";
 
@@ -133,7 +134,7 @@
 struct FileInfo {
   mojo_base.mojom.FilePath path;
   mojo_base.mojom.String16 name;
-  mojo.common.mojom.Time last_modified;
+  mojo_base.mojom.Time last_modified;
 };
 
 struct BlobInfo {
diff --git a/content/common/input/synchronous_compositor.mojom b/content/common/input/synchronous_compositor.mojom
index 5e72242..85684ea0 100644
--- a/content/common/input/synchronous_compositor.mojom
+++ b/content/common/input/synchronous_compositor.mojom
@@ -4,7 +4,7 @@
 
 module content.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 import "services/viz/public/interfaces/compositing/begin_frame_args.mojom";
 import "services/viz/public/interfaces/compositing/compositor_frame.mojom";
@@ -30,7 +30,7 @@
 // because input must be delivered in order with the compositing events.
 interface SynchronousCompositor {
   // Computes the scroll at given time.
-  ComputeScroll(mojo.common.mojom.TimeTicks time);
+  ComputeScroll(mojo_base.mojom.TimeTicks time);
 
   // Hardware draw asynchronously, ReturnFrame will return the result on
   // the associated SynchronousCompositorControlHost.
diff --git a/content/common/page_state.mojom b/content/common/page_state.mojom
index 830aae0..6275190c 100644
--- a/content/common/page_state.mojom
+++ b/content/common/page_state.mojom
@@ -5,7 +5,7 @@
 module content.history.mojom;
 
 import "mojo/public/mojom/base/string16.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "third_party/WebKit/public/platform/referrer.mojom";
 import "url/mojom/url.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
@@ -37,7 +37,7 @@
   url.mojom.Url filesystem_url@0;
   uint64 offset@1;
   uint64 length@2;
-  mojo.common.mojom.Time modification_time@3;
+  mojo_base.mojom.Time modification_time@3;
 };
 
 // Next Ordinal: 4
@@ -45,7 +45,7 @@
   mojo_base.mojom.String16 path@0;
   uint64 offset@1;
   uint64 length@2;
-  mojo.common.mojom.Time modification_time@3;
+  mojo_base.mojom.Time modification_time@3;
 };
 
 // Next Ordinal: 4
diff --git a/content/common/page_state_serialization.cc b/content/common/page_state_serialization.cc
index f4e8d254..906306c4a 100644
--- a/content/common/page_state_serialization.cc
+++ b/content/common/page_state_serialization.cc
@@ -16,8 +16,8 @@
 #include "content/common/unique_name_helper.h"
 #include "content/public/common/referrer_struct_traits.h"
 #include "ipc/ipc_message_utils.h"
-#include "mojo/common/time_struct_traits.h"
 #include "mojo/public/cpp/base/string16_mojom_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "services/network/public/cpp/resource_request_body.h"
 #include "third_party/WebKit/public/platform/WebHistoryScrollRestorationType.h"
 #include "ui/display/display.h"
diff --git a/content/common/render_frame_metadata.mojom b/content/common/render_frame_metadata.mojom
index bf659e5..ffc97dc 100644
--- a/content/common/render_frame_metadata.mojom
+++ b/content/common/render_frame_metadata.mojom
@@ -8,11 +8,6 @@
 
 // See components/viz/service/quads/render_frame_metadata.h
 struct RenderFrameMetadata {
-  // The background color of a CompositorFrame. It can be used for filling the
-  // content area if the primary surface is unavailable and fallback is not
-  // specified.
-  uint32 root_background_color;
-
   // Scroll offset of the root layer. This optional parameter is only sent
   // during tests.
   gfx.mojom.Vector2dF? root_scroll_offset;
diff --git a/content/common/render_frame_metadata_struct_traits.cc b/content/common/render_frame_metadata_struct_traits.cc
index 2897c954..c8c2719 100644
--- a/content/common/render_frame_metadata_struct_traits.cc
+++ b/content/common/render_frame_metadata_struct_traits.cc
@@ -13,7 +13,6 @@
                   cc::RenderFrameMetadata>::
     Read(content::mojom::RenderFrameMetadataDataView data,
          cc::RenderFrameMetadata* out) {
-  out->root_background_color = data.root_background_color();
   return data.ReadRootScrollOffset(&out->root_scroll_offset);
 }
 
diff --git a/content/common/render_frame_metadata_struct_traits.h b/content/common/render_frame_metadata_struct_traits.h
index 228a6792..ff267126 100644
--- a/content/common/render_frame_metadata_struct_traits.h
+++ b/content/common/render_frame_metadata_struct_traits.h
@@ -14,11 +14,6 @@
 template <>
 struct StructTraits<content::mojom::RenderFrameMetadataDataView,
                     cc::RenderFrameMetadata> {
-  static SkColor root_background_color(
-      const cc::RenderFrameMetadata& metadata) {
-    return metadata.root_background_color;
-  }
-
   static base::Optional<gfx::Vector2dF> root_scroll_offset(
       const cc::RenderFrameMetadata& metadata) {
     return metadata.root_scroll_offset;
diff --git a/content/common/render_message_filter.mojom b/content/common/render_message_filter.mojom
index 695bacc..b0df0aa1 100644
--- a/content/common/render_message_filter.mojom
+++ b/content/common/render_message_filter.mojom
@@ -8,7 +8,7 @@
 import "content/common/native_types.mojom";
 import "content/common/widget.mojom";
 import "mojo/common/thread_priority.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "url/mojom/origin.mojom";
 import "url/mojom/url.mojom";
 
@@ -28,12 +28,12 @@
   // Requests that the browser cache |data| associated with |url| and |expected_response_time|.
   // TODO(https://crbug.com/779444): Verify or remove |url| and |cache_storage_origin|.
   DidGenerateCacheableMetadata(url.mojom.Url url,
-                               mojo.common.mojom.Time expected_response_time,
+                               mojo_base.mojom.Time expected_response_time,
                                array<uint8> data);
 
   // Requests that the browser cache |data| for the specified CacheStorage entry.
   DidGenerateCacheableMetadataInCacheStorage(
-      url.mojom.Url url, mojo.common.mojom.Time expected_response_time,
+      url.mojom.Url url, mojo_base.mojom.Time expected_response_time,
       array<uint8> data, url.mojom.Origin cache_storage_origin,
       string cache_storage_cache_name);
 
diff --git a/content/common/renderer.mojom b/content/common/renderer.mojom
index e5691f1..ae90246 100644
--- a/content/common/renderer.mojom
+++ b/content/common/renderer.mojom
@@ -7,7 +7,7 @@
 import "content/common/native_types.mojom";
 import "content/common/service_worker/embedded_worker.mojom";
 import "ipc/constants.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "mojo/common/unguessable_token.mojom";
 import "services/network/public/mojom/network_types.mojom";
 import "services/service_manager/public/mojom/interface_provider.mojom";
@@ -226,8 +226,8 @@
   // unavailable, it will be set to net::nqe::internal::INVALID_RTT_THROUGHPUT.
   OnNetworkQualityChanged(
       network.mojom.EffectiveConnectionType effective_connection_type,
-      mojo.common.mojom.TimeDelta http_rtt,
-      mojo.common.mojom.TimeDelta transport_rtt,
+      mojo_base.mojom.TimeDelta http_rtt,
+      mojo_base.mojom.TimeDelta transport_rtt,
       double bandwidth_kbps);
 
   // Tells the renderer to suspend/resume the webkit timers. Only for use on
diff --git a/content/common/service_worker/controller_service_worker.mojom b/content/common/service_worker/controller_service_worker.mojom
index 89c2ea81..ab63e1c5 100644
--- a/content/common/service_worker/controller_service_worker.mojom
+++ b/content/common/service_worker/controller_service_worker.mojom
@@ -7,7 +7,7 @@
 import "content/common/service_worker/dispatch_fetch_event_params.mojom";
 import "content/common/service_worker/service_worker_event_dispatcher.mojom";
 import "content/common/service_worker/service_worker_fetch_response_callback.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "services/network/public/mojom/url_loader.mojom";
 import "third_party/WebKit/public/mojom/service_worker/service_worker_event_status.mojom";
 import "third_party/WebKit/public/mojom/service_worker/service_worker_object.mojom";
@@ -41,7 +41,7 @@
   DispatchFetchEvent(DispatchFetchEventParams params,
                      ServiceWorkerFetchResponseCallback response_callback)
       => (blink.mojom.ServiceWorkerEventStatus status,
-          mojo.common.mojom.Time dispatch_event_time);
+          mojo_base.mojom.Time dispatch_event_time);
 
   // TODO(kinuko): Add DispatchExtendableMessageEvent() as well.
 
diff --git a/content/common/service_worker/embedded_worker.mojom b/content/common/service_worker/embedded_worker.mojom
index 8cc4f055..4bc560f 100644
--- a/content/common/service_worker/embedded_worker.mojom
+++ b/content/common/service_worker/embedded_worker.mojom
@@ -9,7 +9,7 @@
 import "content/common/service_worker/service_worker_event_dispatcher.mojom";
 import "content/common/service_worker/service_worker_provider.mojom";
 import "mojo/public/mojom/base/string16.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "mojo/common/unguessable_token.mojom";
 import "services/service_manager/public/mojom/interface_provider.mojom";
 import "third_party/WebKit/public/mojom/service_worker/service_worker.mojom";
@@ -72,9 +72,9 @@
 // Holds timing information about the start worker sequence for UMA.
 struct EmbeddedWorkerStartTiming {
   // When this Blink instance finished initializing.
-  mojo.common.mojom.TimeTicks blink_initialized_time;
+  mojo_base.mojom.TimeTicks blink_initialized_time;
   // When the start worker message was received by the renderer.
-  mojo.common.mojom.TimeTicks start_worker_received_time;
+  mojo_base.mojom.TimeTicks start_worker_received_time;
 };
 
 // EmbeddedWorkerInstanceClient is the renderer-side ("Client") of
diff --git a/content/common/service_worker/service_worker_event_dispatcher.mojom b/content/common/service_worker/service_worker_event_dispatcher.mojom
index 815aa49..7096911 100644
--- a/content/common/service_worker/service_worker_event_dispatcher.mojom
+++ b/content/common/service_worker/service_worker_event_dispatcher.mojom
@@ -7,7 +7,7 @@
 import "content/common/service_worker/dispatch_fetch_event_params.mojom";
 import "content/common/service_worker/service_worker_fetch_response_callback.mojom";
 import "mojo/public/mojom/base/string16.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "third_party/WebKit/public/platform/modules/fetch/fetch_api_request.mojom";
 import "third_party/WebKit/public/platform/modules/payments/payment_app.mojom";
 import "third_party/WebKit/public/mojom/message_port/message_port.mojom";
@@ -59,17 +59,17 @@
 // to dispatch events from the browser-side.
 //
 // Those events expecting such response
-// (blink.mojom.ServiceWorkerEventStatus, mojo.common.mojom.Time) are considered
+// (blink.mojom.ServiceWorkerEventStatus, mojo_base.mojom.Time) are considered
 // 'simple events'. ServiceWorkerVersion::CreateSimpleEventCallback can be used
 // to create the callback for these.
 interface ServiceWorkerEventDispatcher {
   DispatchInstallEvent()
       => (blink.mojom.ServiceWorkerEventStatus status,
           bool has_fetch_handler,
-          mojo.common.mojom.Time dispatch_event_time);
+          mojo_base.mojom.Time dispatch_event_time);
   DispatchActivateEvent()
       => (blink.mojom.ServiceWorkerEventStatus status,
-          mojo.common.mojom.Time dispatch_event_time);
+          mojo_base.mojom.Time dispatch_event_time);
 
   // These methods dispatch to the ServiceWorkerGlobalScope the events listed on
   // https://wicg.github.io/background-fetch/#service-worker-global-events.
@@ -78,20 +78,20 @@
   // content::BackgroundFetchRegistrationId.
   DispatchBackgroundFetchAbortEvent(string developer_id)
       => (blink.mojom.ServiceWorkerEventStatus status,
-          mojo.common.mojom.Time dispatch_event_time);
+          mojo_base.mojom.Time dispatch_event_time);
   DispatchBackgroundFetchClickEvent(string developer_id,
                                     BackgroundFetchState state)
       => (blink.mojom.ServiceWorkerEventStatus status,
-          mojo.common.mojom.Time dispatch_event_time);
+          mojo_base.mojom.Time dispatch_event_time);
   DispatchBackgroundFetchFailEvent(string developer_id,
                                    array<BackgroundFetchSettledFetch> fetches)
       => (blink.mojom.ServiceWorkerEventStatus status,
-          mojo.common.mojom.Time dispatch_event_time);
+          mojo_base.mojom.Time dispatch_event_time);
   DispatchBackgroundFetchedEvent(string developer_id,
                                  string unique_id,
                                  array<BackgroundFetchSettledFetch> fetches)
       => (blink.mojom.ServiceWorkerEventStatus status,
-          mojo.common.mojom.Time dispatch_event_time);
+          mojo_base.mojom.Time dispatch_event_time);
 
   // The Dispatch*FetchEvent() callback is called once the event finishes,
   // which means the event handler ran and all outstanding respondWith() and
@@ -101,21 +101,21 @@
   DispatchFetchEvent(DispatchFetchEventParams params,
                      ServiceWorkerFetchResponseCallback response_callback)
       => (blink.mojom.ServiceWorkerEventStatus status,
-          mojo.common.mojom.Time dispatch_event_time);
+          mojo_base.mojom.Time dispatch_event_time);
 
   DispatchNotificationClickEvent(string notification_id,
                                  PlatformNotificationData notification_data,
                                  int32 action_index,
                                  mojo_base.mojom.String16? reply)
       => (blink.mojom.ServiceWorkerEventStatus status,
-          mojo.common.mojom.Time dispatch_event_time);
+          mojo_base.mojom.Time dispatch_event_time);
   DispatchNotificationCloseEvent(string notification_id,
                                  PlatformNotificationData notification_data)
       => (blink.mojom.ServiceWorkerEventStatus status,
-          mojo.common.mojom.Time dispatch_event_time);
+          mojo_base.mojom.Time dispatch_event_time);
   DispatchPushEvent(PushEventPayload payload)
       => (blink.mojom.ServiceWorkerEventStatus status,
-          mojo.common.mojom.Time dispatch_event_time);
+          mojo_base.mojom.Time dispatch_event_time);
   // Arguments are passed to the event handler as parameters of SyncEvent.
   // Ref: https://wicg.github.io/BackgroundSync/spec/#sync-event
   // S13nServiceWorker: |timeout| is the amount of time to allow this event to
@@ -123,29 +123,29 @@
   // Non-S13nServiceWorker: |timeout| is just ignored.
   DispatchSyncEvent(string id,
                     bool last_chance,
-                    mojo.common.mojom.TimeDelta timeout)
+                    mojo_base.mojom.TimeDelta timeout)
       => (blink.mojom.ServiceWorkerEventStatus status,
-          mojo.common.mojom.Time dispatch_event_time);
+          mojo_base.mojom.Time dispatch_event_time);
   DispatchAbortPaymentEvent(
       int32 event_id,
       payments.mojom.PaymentHandlerResponseCallback result_of_abort_payment)
           => (blink.mojom.ServiceWorkerEventStatus status,
-              mojo.common.mojom.Time dispatch_event_time);
+              mojo_base.mojom.Time dispatch_event_time);
   DispatchCanMakePaymentEvent(
       int32 event_id,
       payments.mojom.CanMakePaymentEventData event_data,
       payments.mojom.PaymentHandlerResponseCallback result_of_can_make_payment)
           => (blink.mojom.ServiceWorkerEventStatus status,
-              mojo.common.mojom.Time dispatch_event_time);
+              mojo_base.mojom.Time dispatch_event_time);
   DispatchPaymentRequestEvent(
       int32 payment_request_id,
       payments.mojom.PaymentRequestEventData request_data,
       payments.mojom.PaymentHandlerResponseCallback response_callback)
           => (blink.mojom.ServiceWorkerEventStatus status,
-              mojo.common.mojom.Time dispatch_event_time);
+              mojo_base.mojom.Time dispatch_event_time);
   DispatchExtendableMessageEvent(ExtendableMessageEvent event)
       => (blink.mojom.ServiceWorkerEventStatus status,
-          mojo.common.mojom.Time dispatch_event_time);
+          mojo_base.mojom.Time dispatch_event_time);
 
   // Pings the service worker to check if it is responsive. If the callback is
   // not called within a certain period of time, the browser will terminate the
diff --git a/content/common/service_worker/service_worker_fetch_response_callback.mojom b/content/common/service_worker/service_worker_fetch_response_callback.mojom
index 8b134fc..4b7c64b 100644
--- a/content/common/service_worker/service_worker_fetch_response_callback.mojom
+++ b/content/common/service_worker/service_worker_fetch_response_callback.mojom
@@ -4,7 +4,7 @@
 
 module content.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "third_party/WebKit/public/mojom/blob/blob.mojom";
 import "third_party/WebKit/public/mojom/service_worker/service_worker_stream_handle.mojom";
 
@@ -18,24 +18,24 @@
 interface ServiceWorkerFetchResponseCallback {
   // Responds to the request with |response|. The body is empty.
   OnResponse(ServiceWorkerResponse response,
-             mojo.common.mojom.Time dispatch_event_time);
+             mojo_base.mojom.Time dispatch_event_time);
   // Responds to the request with |response|. The body is returned as a blob.
   // TODO(kinuko): This should not be necessary once we properly support
   // transferring blob within |response|. See crbug.com/75523 for more details.
   OnResponseBlob(ServiceWorkerResponse response,
                  blink.mojom.Blob body_as_blob,
-                 mojo.common.mojom.Time dispatch_event_time);
+                 mojo_base.mojom.Time dispatch_event_time);
    // Responds to the request with |response|. The body is provided as a
    // non-Mojo Blob via |response.blob_uuid|. The callback is useful for Blob
    // lifetime management purposes and is called once the caller is done with
    // the Blob. TODO(kinuko): Remove this once MojoBlob is fully shipped.
   OnResponseLegacyBlob(ServiceWorkerResponse response,
-                       mojo.common.mojom.Time dispatch_event_time) => ();
+                       mojo_base.mojom.Time dispatch_event_time) => ();
   // Responds to the request with |response|. The body is returned as a stream.
   OnResponseStream(ServiceWorkerResponse response,
                    blink.mojom.ServiceWorkerStreamHandle body_as_stream,
-                   mojo.common.mojom.Time dispatch_event_time);
+                   mojo_base.mojom.Time dispatch_event_time);
   // Provides no response to the request. The callee should fall back to the
   // network.
-  OnFallback(mojo.common.mojom.Time dispatch_event_time);
+  OnFallback(mojo_base.mojom.Time dispatch_event_time);
 };
diff --git a/content/common/service_worker/service_worker_fetch_response_mojom_traits.cc b/content/common/service_worker/service_worker_fetch_response_mojom_traits.cc
index 5a86897..4d615363 100644
--- a/content/common/service_worker/service_worker_fetch_response_mojom_traits.cc
+++ b/content/common/service_worker/service_worker_fetch_response_mojom_traits.cc
@@ -14,7 +14,7 @@
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/public/common/referrer_struct_traits.h"
 #include "ipc/ipc_message_utils.h"
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "url/mojom/url_gurl_mojom_traits.h"
 
 namespace mojo {
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
index b33242d..1d90c999 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
@@ -262,7 +262,6 @@
 
         mNativeContentViewCore =
                 nativeInit(mWebContents, mViewAndroidDelegate, windowAndroid, dipScale);
-        mWebContents = (WebContentsImpl) nativeGetWebContentsAndroid(mNativeContentViewCore);
         ViewGroup containerView = viewDelegate.getContainerView();
         SelectionPopupControllerImpl controller = SelectionPopupControllerImpl.create(
                 mContext, windowAndroid, mWebContents, containerView);
@@ -856,7 +855,6 @@
     private native long nativeInit(WebContents webContents, ViewAndroidDelegate viewAndroidDelegate,
             WindowAndroid window, float dipScale);
     private native void nativeUpdateWindowAndroid(long nativeContentViewCore, WindowAndroid window);
-    private native WebContents nativeGetWebContentsAndroid(long nativeContentViewCore);
     private native WindowAndroid nativeGetJavaWindowAndroid(long nativeContentViewCore);
     private native void nativeOnJavaContentViewCoreDestroyed(long nativeContentViewCore);
     private native void nativeSetFocus(long nativeContentViewCore, boolean focused);
diff --git a/content/public/common/appcache_info.mojom b/content/public/common/appcache_info.mojom
index 1226f37..21d04ec 100644
--- a/content/public/common/appcache_info.mojom
+++ b/content/public/common/appcache_info.mojom
@@ -4,7 +4,7 @@
 
 module content.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "url/mojom/url.mojom";
 
 const int64 kAppCacheNoCacheId = 0;
@@ -22,9 +22,9 @@
 
 struct AppCacheInfo {
   url.mojom.Url manifest_url;
-  mojo.common.mojom.Time creation_time;
-  mojo.common.mojom.Time last_update_time;
-  mojo.common.mojom.Time last_access_time;
+  mojo_base.mojom.Time creation_time;
+  mojo_base.mojom.Time last_update_time;
+  mojo_base.mojom.Time last_access_time;
   int64 cache_id;
   int64 group_id;
   AppCacheStatus status;
diff --git a/device/bluetooth/bluetooth_device.h b/device/bluetooth/bluetooth_device.h
index 69efd03..13a8758 100644
--- a/device/bluetooth/bluetooth_device.h
+++ b/device/bluetooth/bluetooth_device.h
@@ -580,7 +580,7 @@
 
   // Helper class to easily update the sets of UUIDs and keep them in sync with
   // the set of all the device's UUIDs.
-  class DeviceUUIDs {
+  class DEVICE_BLUETOOTH_EXPORT DeviceUUIDs {
    public:
     DeviceUUIDs();
     ~DeviceUUIDs();
diff --git a/device/bluetooth/test/fake_peripheral.cc b/device/bluetooth/test/fake_peripheral.cc
index bf790f55..203ceee 100644
--- a/device/bluetooth/test/fake_peripheral.cc
+++ b/device/bluetooth/test/fake_peripheral.cc
@@ -8,6 +8,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "device/bluetooth/bluetooth_uuid.h"
 #include "device/bluetooth/test/fake_remote_gatt_service.h"
@@ -35,7 +36,20 @@
 }
 
 void FakePeripheral::SetServiceUUIDs(UUIDSet service_uuids) {
-  service_uuids_ = std::move(service_uuids);
+  device::BluetoothDevice::GattServiceMap services_map;
+  bool inserted;
+
+  // Create a temporary map of services, because ReplaceServiceUUids expects a
+  // GattServiceMap even though it only uses the UUIDs.
+  int count = 0;
+  for (const auto& uuid : service_uuids) {
+    std::string id = base::IntToString(count++);
+    std::tie(std::ignore, inserted) =
+        services_map.emplace(id, std::make_unique<FakeRemoteGattService>(
+                                     id, uuid, true /* is_primary */, this));
+    DCHECK(inserted);
+  }
+  device_uuids_.ReplaceServiceUUIDs(services_map);
 }
 
 void FakePeripheral::SetNextGATTConnectionResponse(uint16_t code) {
@@ -66,6 +80,7 @@
   // for more details.
   system_connected_ = false;
   gatt_connected_ = false;
+  device_uuids_.ClearServiceUUIDs();
   SetGattServicesDiscoveryComplete(false);
   DidDisconnectGatt();
 }
@@ -180,10 +195,6 @@
   return false;
 }
 
-device::BluetoothDevice::UUIDSet FakePeripheral::GetUUIDs() const {
-  return service_uuids_;
-}
-
 bool FakePeripheral::ExpectingPinCode() const {
   NOTREACHED();
   return false;
@@ -328,6 +339,7 @@
 
   pending_gatt_discovery_ = false;
   if (code == mojom::kHCISuccess) {
+    device_uuids_.ReplaceServiceUUIDs(gatt_services_);
     SetGattServicesDiscoveryComplete(true);
     GetAdapter()->NotifyGattServicesDiscovered(this);
   } else {
diff --git a/device/bluetooth/test/fake_peripheral.h b/device/bluetooth/test/fake_peripheral.h
index e9879063..5006f4c 100644
--- a/device/bluetooth/test/fake_peripheral.h
+++ b/device/bluetooth/test/fake_peripheral.h
@@ -81,7 +81,6 @@
   bool IsGattConnected() const override;
   bool IsConnectable() const override;
   bool IsConnecting() const override;
-  UUIDSet GetUUIDs() const override;
   bool ExpectingPinCode() const override;
   bool ExpectingPasskey() const override;
   bool ExpectingConfirmation() const override;
diff --git a/device/vr/public/mojom/BUILD.gn b/device/vr/public/mojom/BUILD.gn
index bf65531..02396377 100644
--- a/device/vr/public/mojom/BUILD.gn
+++ b/device/vr/public/mojom/BUILD.gn
@@ -14,7 +14,7 @@
 
   public_deps = [
     "//gpu/ipc/common:interfaces",
-    "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//ui/gfx/geometry/mojo",
     "//ui/gfx/mojo:mojo",
   ]
diff --git a/device/vr/public/mojom/vr_service.mojom b/device/vr/public/mojom/vr_service.mojom
index e6b977d0..2981376 100644
--- a/device/vr/public/mojom/vr_service.mojom
+++ b/device/vr/public/mojom/vr_service.mojom
@@ -4,7 +4,7 @@
 
 module device.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "gpu/ipc/common/mailbox_holder.mojom";
 import "gpu/ipc/common/sync_token.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
@@ -238,7 +238,7 @@
   // The frameId maps a VSync to a frame arriving from the compositor. IDs will
   // be reused after the frame arrives from the compositor. Negative IDs imply
   // no mapping.
-  GetVSync() => (VRPose? pose, mojo.common.mojom.TimeDelta time, int16 frame_id,
+  GetVSync() => (VRPose? pose, mojo_base.mojom.TimeDelta time, int16 frame_id,
                  VSyncStatus status);
 
   UpdateLayerBounds(int16 frame_id, gfx.mojom.RectF left_bounds,
@@ -246,7 +246,7 @@
 
   // VRDisplayFrameTransportMethod SUBMIT_AS_MAILBOX_HOLDER
   SubmitFrame(int16 frame_id, gpu.mojom.MailboxHolder mailbox_holder,
-              mojo.common.mojom.TimeDelta time_waited);
+              mojo_base.mojom.TimeDelta time_waited);
 
   // VRDisplayFrameTransportMethod SUBMIT_AS_TEXTURE_HANDLE
   // TODO(https://crbug.com/676224): Support preprocessing of mojom files, since
diff --git a/docs/security/mojo.md b/docs/security/mojo.md
index edacae87..7bc70770 100644
--- a/docs/security/mojo.md
+++ b/docs/security/mojo.md
@@ -323,8 +323,8 @@
 *   Nonces: use `mojo.common.mojom.UnguessableToken`, not `string`.
 *   Origins: use `url.mojom.Origin`, not `url.mojom.Url` and certainly not
     `string`.
-*   Time types: use `mojo.common.mojom.TimeDelta` /
-    `mojo.common.mojom.TimeTicks` / `mojo.common.mojom.Time`, not `int64` /
+*   Time types: use `mojo_base.mojom.TimeDelta` /
+    `mojo_base.mojom.TimeTicks` / `mojo_base.mojom.Time`, not `int64` /
     `uint64` / `double` / et cetera.
 *   URLs: use `url.mojom.Url`, not `string`.
 
@@ -332,7 +332,7 @@
 
 ```c++
 interface ReportingService {
-  ReportDeprecation(mojo.common.mojom.TimeTicks time,
+  ReportDeprecation(mojo_base.mojom.TimeTicks time,
                     url.mojom.Url resource,
                     uint32 line_number);
 };
diff --git a/extensions/browser/guest_view/web_view/web_view_apitest.cc b/extensions/browser/guest_view/web_view/web_view_apitest.cc
index 7427cfb..2258fc3 100644
--- a/extensions/browser/guest_view/web_view/web_view_apitest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_apitest.cc
@@ -10,7 +10,6 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -22,7 +21,6 @@
 #include "components/guest_view/browser/test_guest_view_manager.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
@@ -45,7 +43,6 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
-#include "third_party/WebKit/public/platform/WebMouseEvent.h"
 #include "ui/display/display_switches.h"
 
 using guest_view::GuestViewManager;
@@ -474,30 +471,6 @@
   RunTest("testContentLoadEvent", "web_view/apitest");
 }
 
-// Verifies that trying to show the context menu doesn't crash
-// (https://crbug.com/820604).
-IN_PROC_BROWSER_TEST_F(WebViewAPITest, TestContextMenu) {
-  // Launch some test app that displays a webview.
-  LaunchApp("web_view/visibility_changed");
-
-  // Ensure the webview's surface is ready for hit testing.
-  content::WebContents* guest_web_contents = GetGuestWebContents();
-  content::WaitForGuestSurfaceReady(guest_web_contents);
-
-  // Register a ContextMenuFilter to wait for the context menu event to be sent.
-  content::RenderProcessHost* guest_process_host =
-      guest_web_contents->GetMainFrame()->GetProcess();
-  auto context_menu_filter = base::MakeRefCounted<content::ContextMenuFilter>();
-  guest_process_host->AddFilter(context_menu_filter.get());
-
-  // Trigger the context menu. AppShell doesn't show a context menu; this is
-  // just a sanity check that nothing breaks.
-  content::SimulateRoutedMouseClickAt(
-      guest_web_contents, blink::WebInputEvent::kNoModifiers,
-      blink::WebMouseEvent::Button::kRight, gfx::Point(10, 10));
-  context_menu_filter->Wait();
-}
-
 IN_PROC_BROWSER_TEST_F(WebViewAPITest, TestDeclarativeWebRequestAPI) {
   std::string app_location = "web_view/apitest";
   StartTestServer(app_location);
diff --git a/extensions/browser/guest_view/web_view/web_view_guest_delegate.h b/extensions/browser/guest_view/web_view/web_view_guest_delegate.h
index 38562b9..b9a33b02 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest_delegate.h
+++ b/extensions/browser/guest_view/web_view/web_view_guest_delegate.h
@@ -20,6 +20,10 @@
 
   // Shows the context menu for the guest.
   virtual void OnShowContextMenu(int request_id) = 0;
+
+  // Returns true if the WebViewGuest should handle find requests for its
+  // embedder.
+  virtual bool ShouldHandleFindRequestsForEmbedder() const = 0;
 };
 
 }  // namespace extensions
diff --git a/extensions/browser/image_sanitizer.cc b/extensions/browser/image_sanitizer.cc
index 7aa1f34..71f706c 100644
--- a/extensions/browser/image_sanitizer.cc
+++ b/extensions/browser/image_sanitizer.cc
@@ -29,8 +29,9 @@
   int64_t file_size;
   if (base::GetFileSize(path, &file_size)) {
     contents.resize(file_size);
-    read_success = base::ReadFile(
-        path, reinterpret_cast<char*>(contents.data()), file_size);
+    read_success =
+        base::ReadFile(path, reinterpret_cast<char*>(contents.data()),
+                       file_size) == file_size;
   }
   bool delete_success = base::DeleteFile(path, /*recursive=*/false);
   return std::make_tuple(std::move(contents), read_success, delete_success);
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn
index 7df3e8c..01f8a88 100644
--- a/extensions/shell/BUILD.gn
+++ b/extensions/shell/BUILD.gn
@@ -174,8 +174,6 @@
     "browser/shell_url_request_context_getter.h",
     "browser/shell_virtual_keyboard_delegate.cc",
     "browser/shell_virtual_keyboard_delegate.h",
-    "browser/shell_web_view_guest_delegate.cc",
-    "browser/shell_web_view_guest_delegate.h",
     "common/shell_content_client.cc",
     "common/shell_content_client.h",
     "common/shell_extensions_client.cc",
diff --git a/extensions/shell/browser/shell_app_view_guest_delegate.cc b/extensions/shell/browser/shell_app_view_guest_delegate.cc
index 917c3936..4662eba 100644
--- a/extensions/shell/browser/shell_app_view_guest_delegate.cc
+++ b/extensions/shell/browser/shell_app_view_guest_delegate.cc
@@ -17,8 +17,7 @@
 bool ShellAppViewGuestDelegate::HandleContextMenu(
     content::WebContents* web_contents,
     const content::ContextMenuParams& params) {
-  // Eat the context menu request, as AppShell doesn't show context menus.
-  return true;
+  return false;
 }
 
 AppDelegate* ShellAppViewGuestDelegate::CreateAppDelegate() {
diff --git a/extensions/shell/browser/shell_extensions_api_client.cc b/extensions/shell/browser/shell_extensions_api_client.cc
index d10d921..e93e9b8 100644
--- a/extensions/shell/browser/shell_extensions_api_client.cc
+++ b/extensions/shell/browser/shell_extensions_api_client.cc
@@ -14,7 +14,6 @@
 #include "extensions/shell/browser/shell_app_view_guest_delegate.h"
 #include "extensions/shell/browser/shell_extension_web_contents_observer.h"
 #include "extensions/shell/browser/shell_virtual_keyboard_delegate.h"
-#include "extensions/shell/browser/shell_web_view_guest_delegate.h"
 
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
 #include "extensions/shell/browser/api/file_system/shell_file_system_delegate.h"
@@ -36,11 +35,6 @@
   return new ShellAppViewGuestDelegate();
 }
 
-WebViewGuestDelegate* ShellExtensionsAPIClient::CreateWebViewGuestDelegate(
-    WebViewGuest* web_view_guest) const {
-  return new ShellWebViewGuestDelegate();
-}
-
 std::unique_ptr<VirtualKeyboardDelegate>
 ShellExtensionsAPIClient::CreateVirtualKeyboardDelegate(
     content::BrowserContext* browser_context) const {
diff --git a/extensions/shell/browser/shell_extensions_api_client.h b/extensions/shell/browser/shell_extensions_api_client.h
index ffc1a8e..a460279 100644
--- a/extensions/shell/browser/shell_extensions_api_client.h
+++ b/extensions/shell/browser/shell_extensions_api_client.h
@@ -26,8 +26,6 @@
   void AttachWebContentsHelpers(content::WebContents* web_contents) const
       override;
   AppViewGuestDelegate* CreateAppViewGuestDelegate() const override;
-  WebViewGuestDelegate* CreateWebViewGuestDelegate(
-      WebViewGuest* web_view_guest) const override;
   std::unique_ptr<VirtualKeyboardDelegate> CreateVirtualKeyboardDelegate(
       content::BrowserContext* browser_context) const override;
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
diff --git a/extensions/shell/browser/shell_web_view_guest_delegate.cc b/extensions/shell/browser/shell_web_view_guest_delegate.cc
deleted file mode 100644
index 4a8d67b..0000000
--- a/extensions/shell/browser/shell_web_view_guest_delegate.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "extensions/shell/browser/shell_web_view_guest_delegate.h"
-
-namespace extensions {
-
-ShellWebViewGuestDelegate::ShellWebViewGuestDelegate() = default;
-ShellWebViewGuestDelegate::~ShellWebViewGuestDelegate() = default;
-
-bool ShellWebViewGuestDelegate::HandleContextMenu(
-    const content::ContextMenuParams& params) {
-  // Eat the context menu request, as AppShell doesn't show context menus.
-  return true;
-}
-
-void ShellWebViewGuestDelegate::OnShowContextMenu(int request_id) {}
-
-}  // namespace extensions
diff --git a/extensions/shell/browser/shell_web_view_guest_delegate.h b/extensions/shell/browser/shell_web_view_guest_delegate.h
deleted file mode 100644
index 2fc436a..0000000
--- a/extensions/shell/browser/shell_web_view_guest_delegate.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef EXTENSIONS_SHELL_BROWSER_SHELL_WEB_VIEW_GUEST_DELEGATE_H_
-#define EXTENSIONS_SHELL_BROWSER_SHELL_WEB_VIEW_GUEST_DELEGATE_H_
-
-#include "base/macros.h"
-#include "extensions/browser/guest_view/web_view/web_view_guest_delegate.h"
-
-namespace extensions {
-
-class ShellWebViewGuestDelegate : public WebViewGuestDelegate {
- public:
-  ShellWebViewGuestDelegate();
-  ~ShellWebViewGuestDelegate() override;
-
-  // WebViewGuestDelegate:
-  bool HandleContextMenu(const content::ContextMenuParams& params) override;
-  void OnShowContextMenu(int request_id) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ShellWebViewGuestDelegate);
-};
-
-}  // namespace extensions
-
-#endif  // EXTENSIONS_SHELL_BROWSER_SHELL_WEB_VIEW_GUEST_DELEGATE_H_
diff --git a/gpu/command_buffer/service/sync_point_manager.cc b/gpu/command_buffer/service/sync_point_manager.cc
index a3c4bf1..7fdf99e 100644
--- a/gpu/command_buffer/service/sync_point_manager.cc
+++ b/gpu/command_buffer/service/sync_point_manager.cc
@@ -72,8 +72,9 @@
 uint32_t SyncPointOrderData::GenerateUnprocessedOrderNumber() {
   base::AutoLock auto_lock(lock_);
   DCHECK(!destroyed_);
-  unprocessed_order_num_ = sync_point_manager_->GenerateOrderNumber();
-  return unprocessed_order_num_;
+  last_unprocessed_order_num_ = sync_point_manager_->GenerateOrderNumber();
+  unprocessed_order_nums_.push(last_unprocessed_order_num_);
+  return last_unprocessed_order_num_;
 }
 
 void SyncPointOrderData::BeginProcessingOrderNumber(uint32_t order_num) {
@@ -85,29 +86,6 @@
   DCHECK_LE(order_num, unprocessed_order_num());
   current_order_num_ = order_num;
   paused_ = false;
-
-  // Catch invalid waits which were waiting on fence syncs that do not exist.
-  // When we begin processing an order number, we should release any fence
-  // syncs which were enqueued but the order number never existed.
-  // Release without the lock to avoid possible deadlocks.
-  std::vector<OrderFence> ensure_releases;
-  {
-    base::AutoLock auto_lock(lock_);
-    while (!order_fence_queue_.empty()) {
-      const OrderFence& order_fence = order_fence_queue_.top();
-      if (order_fence_queue_.top().order_num < order_num) {
-        ensure_releases.push_back(order_fence);
-        order_fence_queue_.pop();
-        continue;
-      }
-      break;
-    }
-  }
-
-  for (OrderFence& order_fence : ensure_releases) {
-    order_fence.client_state->EnsureWaitReleased(order_fence.fence_release,
-                                                 order_fence.release_callback);
-  }
 }
 
 void SyncPointOrderData::PauseProcessingOrderNumber(uint32_t order_num) {
@@ -132,9 +110,20 @@
     DCHECK_GT(order_num, processed_order_num_);
     processed_order_num_ = order_num;
 
+    DCHECK(!unprocessed_order_nums_.empty());
+    DCHECK_EQ(order_num, unprocessed_order_nums_.front());
+    unprocessed_order_nums_.pop();
+
+    uint32_t next_order_num = 0;
+    if (!unprocessed_order_nums_.empty())
+      next_order_num = unprocessed_order_nums_.front();
+
     while (!order_fence_queue_.empty()) {
       const OrderFence& order_fence = order_fence_queue_.top();
-      if (order_fence_queue_.top().order_num <= order_num) {
+      // It's possible for the fence's order number to equal next order number.
+      // This happens when the wait was enqueued with an order number greater
+      // than the last unprocessed order number. So don't release the fence yet.
+      if (!next_order_num || order_fence.order_num < next_order_num) {
         ensure_releases.push_back(order_fence);
         order_fence_queue_.pop();
         continue;
@@ -144,6 +133,7 @@
   }
 
   for (OrderFence& order_fence : ensure_releases) {
+    DLOG(ERROR) << "Client did not release sync token as expected";
     order_fence.client_state->EnsureWaitReleased(order_fence.fence_release,
                                                  order_fence.release_callback);
   }
@@ -158,19 +148,22 @@
   if (destroyed_)
     return false;
 
-  // Release should have a possible unprocessed order number lower than the wait
-  // order number.
-  if ((processed_order_num_ + 1) >= wait_order_num)
+  // We should have unprocessed order numbers which could potentially release
+  // this fence.
+  if (unprocessed_order_nums_.empty())
     return false;
 
-  // Release should have more unprocessed numbers if we are waiting.
-  if (unprocessed_order_num_ <= processed_order_num_)
+  // We should have an unprocessed order number lower than the wait order
+  // number for the wait to be valid. It's not possible for wait order number to
+  // equal next unprocessed order number, but we handle that defensively.
+  DCHECK_NE(wait_order_num, unprocessed_order_nums_.front());
+  if (wait_order_num <= unprocessed_order_nums_.front())
     return false;
 
   // So far it could be valid, but add an order fence guard to be sure it
   // gets released eventually.
   uint32_t expected_order_num =
-      std::min(unprocessed_order_num_, wait_order_num);
+      std::min(unprocessed_order_nums_.back(), wait_order_num);
   order_fence_queue_.push(OrderFence(expected_order_num, fence_release,
                                      release_callback,
                                      std::move(client_state)));
@@ -237,17 +230,20 @@
                                           const base::Closure& callback) {
   // Lock must be held the whole time while we validate otherwise it could be
   // released while we are checking.
-  {
-    base::AutoLock auto_lock(fence_sync_lock_);
-    if (release > fence_sync_release_ &&
-        order_data_->ValidateReleaseOrderNumber(this, wait_order_num, release,
-                                                callback)) {
-      // Add the callback which will be called upon release.
-      release_callback_queue_.push(ReleaseCallback(release, callback));
-      return true;
-    }
-  }
+  base::AutoLock auto_lock(fence_sync_lock_);
+
   // Already released, do not run the callback.
+  if (release <= fence_sync_release_)
+    return false;
+
+  if (order_data_->ValidateReleaseOrderNumber(this, wait_order_num, release,
+                                              callback)) {
+    // Add the callback which will be called upon release.
+    release_callback_queue_.push(ReleaseCallback(release, callback));
+    return true;
+  }
+
+  DLOG(ERROR) << "Client waiting on non-existent sync token";
   return false;
 }
 
diff --git a/gpu/command_buffer/service/sync_point_manager.h b/gpu/command_buffer/service/sync_point_manager.h
index be8e510d..ca5c4c9 100644
--- a/gpu/command_buffer/service/sync_point_manager.h
+++ b/gpu/command_buffer/service/sync_point_manager.h
@@ -51,7 +51,7 @@
 
   uint32_t unprocessed_order_num() const {
     base::AutoLock auto_lock(lock_);
-    return unprocessed_order_num_;
+    return last_unprocessed_order_num_;
   }
 
   uint32_t current_order_num() const {
@@ -122,9 +122,7 @@
   bool paused_ = false;
 
   // This lock protects destroyed_, processed_order_num_,
-  // unprocessed_order_num_, and order_fence_queue_. All order numbers (n) in
-  // order_fence_queue_ must follow the invariant:
-  //   processed_order_num_ < n <= unprocessed_order_num_.
+  // unprocessed_order_nums_, and order_fence_queue_.
   mutable base::Lock lock_;
 
   bool destroyed_ = false;
@@ -132,8 +130,13 @@
   // Last finished IPC order number.
   uint32_t processed_order_num_ = 0;
 
-  // Unprocessed order number expected to be processed under normal execution.
-  uint32_t unprocessed_order_num_ = 0;
+  // Last unprocessed order number. Updated in GenerateUnprocessedOrderNumber.
+  uint32_t last_unprocessed_order_num_ = 0;
+
+  // Queue of unprocessed order numbers. Order numbers are enqueued in
+  // GenerateUnprocessedOrderNumber, and dequeued in
+  // FinishProcessingOrderNumber.
+  std::queue<uint32_t> unprocessed_order_nums_;
 
   // In situations where we are waiting on fence syncs that do not exist, we
   // validate by making sure the order number does not pass the order number
@@ -141,7 +144,9 @@
   // wait command's, we should automatically release up to the expected
   // release count. Note that this also releases other lower release counts,
   // so a single misbehaved fence sync is enough to invalidate/signal all
-  // previous fence syncs.
+  // previous fence syncs. All order numbers (n) in order_fence_queue_ must
+  // follow the invariant:
+  //   unprocessed_order_nums_.front() < n <= unprocessed_order_nums_.back().
   OrderFenceQueue order_fence_queue_;
 
   DISALLOW_COPY_AND_ASSIGN(SyncPointOrderData);
diff --git a/gpu/command_buffer/service/sync_point_manager_unittest.cc b/gpu/command_buffer/service/sync_point_manager_unittest.cc
index a72c48a..f926a74 100644
--- a/gpu/command_buffer/service/sync_point_manager_unittest.cc
+++ b/gpu/command_buffer/service/sync_point_manager_unittest.cc
@@ -431,26 +431,20 @@
   EXPECT_TRUE(valid_wait);
   EXPECT_EQ(10, test_num);
 
-  // Release stream should know it should release fence sync by order [3],
-  // so going through order [1] should not release it yet.
+  // Release stream should know it should release fence sync by order [3], but
+  // it has no unprocessed order numbers less than 3, so it runs the callback.
   release_stream.BeginProcessing();
   EXPECT_EQ(1u, release_stream.order_data->current_order_num());
   release_stream.EndProcessing();
   EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
-  EXPECT_EQ(10, test_num);
-
-  // Beginning order [4] should immediately trigger the wait although the fence
-  // sync is still not released yet.
-  release_stream.BeginProcessing();
-  EXPECT_EQ(4u, release_stream.order_data->current_order_num());
   EXPECT_EQ(123, test_num);
-  EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
 
   // Ensure that the wait callback does not get triggered again when it is
   // actually released.
-  test_num = 1;
+  release_stream.BeginProcessing();
+  test_num = 10;
   release_stream.client_state->ReleaseFenceSync(1);
-  EXPECT_EQ(1, test_num);
+  EXPECT_EQ(10, test_num);
   EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token));
 }
 
@@ -480,4 +474,123 @@
   EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
 }
 
+TEST_F(SyncPointManagerTest, HandleInvalidWaitOrderNumber) {
+  CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
+  CommandBufferId kCmdBufferId1 = CommandBufferId::FromUnsafeValue(0x123);
+  CommandBufferId kCmdBufferId2 = CommandBufferId::FromUnsafeValue(0x234);
+
+  SyncPointStream stream1(sync_point_manager_.get(), kNamespaceId,
+                          kCmdBufferId1);
+  SyncPointStream stream2(sync_point_manager_.get(), kNamespaceId,
+                          kCmdBufferId2);
+
+  stream1.AllocateOrderNum();  // stream 1, order num 1
+  stream2.AllocateOrderNum();  // stream 2, order num 2
+  stream2.AllocateOrderNum();  // stream 2, order num 3
+  stream1.AllocateOrderNum();  // stream 1, order num 4
+
+  // Run stream 1, order num 1.
+  stream1.BeginProcessing();
+  stream1.EndProcessing();
+
+  // Stream 2 waits on stream 1 with order num 3. This wait is invalid because
+  // there's no unprocessed order num less than 3 on stream 1.
+  int test_num = 10;
+  bool valid_wait = sync_point_manager_->Wait(
+      SyncToken(kNamespaceId, kCmdBufferId1, 1),
+      stream2.order_data->sequence_id(), 3,
+      base::Bind(&SyncPointManagerTest::SetIntegerFunction, &test_num, 123));
+  EXPECT_FALSE(valid_wait);
+  EXPECT_EQ(10, test_num);
+}
+
+TEST_F(SyncPointManagerTest, RetireInvalidWaitAfterOrderNumberPasses) {
+  CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
+  CommandBufferId kCmdBufferId1 = CommandBufferId::FromUnsafeValue(0x123);
+  CommandBufferId kCmdBufferId2 = CommandBufferId::FromUnsafeValue(0x234);
+
+  SyncPointStream stream1(sync_point_manager_.get(), kNamespaceId,
+                          kCmdBufferId1);
+  SyncPointStream stream2(sync_point_manager_.get(), kNamespaceId,
+                          kCmdBufferId2);
+
+  stream1.AllocateOrderNum();  // stream 1, order num 1
+  stream1.AllocateOrderNum();  // stream 1, order num 2
+  stream2.AllocateOrderNum();  // stream 2, order num 3
+
+  // Stream 2 waits on stream 1 with order num 3.
+  int test_num = 10;
+  bool valid_wait = sync_point_manager_->Wait(
+      SyncToken(kNamespaceId, kCmdBufferId1, 1),
+      stream2.order_data->sequence_id(), 3,
+      base::Bind(&SyncPointManagerTest::SetIntegerFunction, &test_num, 123));
+  EXPECT_TRUE(valid_wait);
+  EXPECT_EQ(10, test_num);
+
+  stream1.AllocateOrderNum();  // stream 1, order num 4
+
+  // Run stream 1, order num 1. The wait isn't retired.
+  stream1.BeginProcessing();
+  stream1.EndProcessing();
+  EXPECT_EQ(10, test_num);
+
+  // Run stream 1, order num 2. Wait is retired because we reach the last order
+  // number that was unprocessed at the time the wait was enqueued.
+  stream1.BeginProcessing();
+  stream1.EndProcessing();
+  EXPECT_EQ(123, test_num);
+}
+
+TEST_F(SyncPointManagerTest, HandleInvalidCyclicWaits) {
+  CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
+  CommandBufferId kCmdBufferId1 = CommandBufferId::FromUnsafeValue(0x123);
+  CommandBufferId kCmdBufferId2 = CommandBufferId::FromUnsafeValue(0x234);
+
+  SyncPointStream stream1(sync_point_manager_.get(), kNamespaceId,
+                          kCmdBufferId1);
+  SyncPointStream stream2(sync_point_manager_.get(), kNamespaceId,
+                          kCmdBufferId2);
+
+  stream1.AllocateOrderNum();  // stream 1, order num 1
+  stream2.AllocateOrderNum();  // stream 2, order num 2
+  stream1.AllocateOrderNum();  // stream 1, order num 3
+  stream2.AllocateOrderNum();  // stream 2, order num 4
+
+  // Stream 2 waits on stream 1 with order num 2.
+  int test_num1 = 10;
+  bool valid_wait = sync_point_manager_->Wait(
+      SyncToken(kNamespaceId, kCmdBufferId1, 1),
+      stream2.order_data->sequence_id(), 2,
+      base::Bind(&SyncPointManagerTest::SetIntegerFunction, &test_num1, 123));
+  EXPECT_TRUE(valid_wait);
+  EXPECT_EQ(10, test_num1);
+
+  // Stream 1 waits on stream 2 with order num 3.
+  int test_num2 = 10;
+  valid_wait = sync_point_manager_->Wait(
+      SyncToken(kNamespaceId, kCmdBufferId2, 1),
+      stream1.order_data->sequence_id(), 3,
+      base::Bind(&SyncPointManagerTest::SetIntegerFunction, &test_num2, 123));
+  EXPECT_TRUE(valid_wait);
+  EXPECT_EQ(10, test_num2);
+
+  // Run stream 1, order num 1.
+  stream1.BeginProcessing();
+  stream1.EndProcessing();
+
+  // Since there's no unprocessed order num less than 2 on stream 1, the wait is
+  // released.
+  EXPECT_EQ(123, test_num1);
+  EXPECT_EQ(10, test_num2);
+
+  // Run stream 2, order num 2.
+  stream2.BeginProcessing();
+  stream2.EndProcessing();
+
+  // Since there's no unprocessed order num less than 3 on stream 2, the wait is
+  // released.
+  EXPECT_EQ(123, test_num1);
+  EXPECT_EQ(123, test_num2);
+}
+
 }  // namespace gpu
diff --git a/gpu/ipc/common/BUILD.gn b/gpu/ipc/common/BUILD.gn
index c2ebaa2..3a176c8 100644
--- a/gpu/ipc/common/BUILD.gn
+++ b/gpu/ipc/common/BUILD.gn
@@ -188,6 +188,7 @@
 
   public_deps = [
     "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//ui/gfx/geometry/mojo",
     "//ui/gfx/mojo",
   ]
diff --git a/gpu/ipc/common/gpu_info.mojom b/gpu/ipc/common/gpu_info.mojom
index 5d9d403..8754694 100644
--- a/gpu/ipc/common/gpu_info.mojom
+++ b/gpu/ipc/common/gpu_info.mojom
@@ -6,7 +6,7 @@
 module gpu.mojom;
 
 import "gpu/ipc/common/dx_diag_node.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "mojo/common/version.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
@@ -73,7 +73,7 @@
 
 // Corresponds to |gpu::GPUInfo| in gpu/config/gpu_info.h
 struct GpuInfo {
-  mojo.common.mojom.TimeDelta initialization_time;
+  mojo_base.mojom.TimeDelta initialization_time;
   bool optimus;
   bool amd_switchable;
   GpuDevice gpu;
diff --git a/gpu/ipc/common/gpu_info_struct_traits.cc b/gpu/ipc/common/gpu_info_struct_traits.cc
index c97c165..12c83cc 100644
--- a/gpu/ipc/common/gpu_info_struct_traits.cc
+++ b/gpu/ipc/common/gpu_info_struct_traits.cc
@@ -4,7 +4,7 @@
 
 #include "gpu/ipc/common/gpu_info_struct_traits.h"
 
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 
 namespace mojo {
 
diff --git a/headless/public/util/generic_url_request_job.cc b/headless/public/util/generic_url_request_job.cc
index fd5f4cf4..c0dac42c 100644
--- a/headless/public/util/generic_url_request_job.cc
+++ b/headless/public/util/generic_url_request_job.cc
@@ -339,6 +339,12 @@
   return request_resource_info_->GetFrameTreeNodeId() != -1;
 }
 
+bool GenericURLRequestJob::HasUserGesture() const {
+  if (!request_resource_info_)
+    return false;
+  return request_resource_info_->HasUserGesture();
+}
+
 namespace {
 void CompletionCallback(int* dest, base::Closure* quit_closure, int value) {
   *dest = value;
diff --git a/headless/public/util/generic_url_request_job.h b/headless/public/util/generic_url_request_job.h
index f9f660ef..25d91ea8 100644
--- a/headless/public/util/generic_url_request_job.h
+++ b/headless/public/util/generic_url_request_job.h
@@ -87,6 +87,8 @@
   // Whether or not an asynchronous IPC was used to load this resource.
   virtual bool IsAsync() const = 0;
 
+  virtual bool HasUserGesture() const = 0;
+
  protected:
   Request() {}
   virtual ~Request() {}
@@ -165,6 +167,7 @@
   uint64_t GetPostDataSize() const override;
   ResourceType GetResourceType() const override;
   bool IsAsync() const override;
+  bool HasUserGesture() const override;
   bool IsBrowserSideFetch() const override;
 
  private:
diff --git a/ios/PRESUBMIT_test.py b/ios/PRESUBMIT_test.py
old mode 100644
new mode 100755
index 48c5a36..bc5acaf1
--- a/ios/PRESUBMIT_test.py
+++ b/ios/PRESUBMIT_test.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # Copyright 2017 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
diff --git a/ios/chrome/browser/passwords/BUILD.gn b/ios/chrome/browser/passwords/BUILD.gn
index 86570322..54de21bb 100644
--- a/ios/chrome/browser/passwords/BUILD.gn
+++ b/ios/chrome/browser/passwords/BUILD.gn
@@ -192,7 +192,7 @@
     "resources/password_controller.js",
   ]
   js_modules = [
-    "//ios/web/web_state/js/resources/form.js",
+    "//components/autofill/ios/fill/resources/form.js",
     "//components/autofill/ios/fill/resources/fill.js",
   ]
 }
diff --git a/ios/chrome/browser/passwords/password_controller_js_unittest.mm b/ios/chrome/browser/passwords/password_controller_js_unittest.mm
index bbcda77..5cde324 100644
--- a/ios/chrome/browser/passwords/password_controller_js_unittest.mm
+++ b/ios/chrome/browser/passwords/password_controller_js_unittest.mm
@@ -22,8 +22,10 @@
     : public web::WebJsTest<web::WebTestWithWebState> {
  public:
   PasswordControllerJsTest()
-      : web::WebJsTest<web::WebTestWithWebState>(
-            @[ @"chrome_bundle", @"password_controller" ]) {}
+      : web::WebJsTest<web::WebTestWithWebState>(@[
+          @"chrome_bundle_all_frames", @"chrome_bundle_main_frame",
+          @"password_controller"
+        ]) {}
 };
 
 // IDs used in the Username and Password <input> elements.
diff --git a/ios/chrome/browser/ui/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/BUILD.gn
index 3b681ae..01a0f42 100644
--- a/ios/chrome/browser/ui/tab_grid/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_grid/BUILD.gn
@@ -57,6 +57,8 @@
     "tab_grid_constants.mm",
     "tab_grid_empty_state_view.h",
     "tab_grid_empty_state_view.mm",
+    "tab_grid_new_tab_button.h",
+    "tab_grid_new_tab_button.mm",
     "tab_grid_page_control.h",
     "tab_grid_page_control.mm",
     "tab_grid_paging.h",
diff --git a/ios/chrome/browser/ui/tab_grid/grid_cell.mm b/ios/chrome/browser/ui/tab_grid/grid_cell.mm
index fa73d72..98c02ff4 100644
--- a/ios/chrome/browser/ui/tab_grid/grid_cell.mm
+++ b/ios/chrome/browser/ui/tab_grid/grid_cell.mm
@@ -190,6 +190,8 @@
   UIImage* closeImage = [[UIImage imageNamed:@"grid_cell_close_button"]
       imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
   [closeButton setImage:closeImage forState:UIControlStateNormal];
+  closeButton.contentEdgeInsets = UIEdgeInsetsMake(
+      0, kGridCellCloseButtonContentInset, 0, kGridCellCloseButtonContentInset);
   [closeButton addTarget:self
                   action:@selector(closeButtonTapped:)
         forControlEvents:UIControlEventTouchUpInside];
@@ -213,19 +215,20 @@
         constraintEqualToAnchor:iconView.trailingAnchor
                        constant:kGridCellHeaderLeadingInset],
     [titleLabel.centerYAnchor constraintEqualToAnchor:topBar.centerYAnchor],
-    [closeButton.leadingAnchor
-        constraintEqualToAnchor:titleLabel.trailingAnchor],
-    [closeButton.centerYAnchor constraintEqualToAnchor:topBar.centerYAnchor],
-    [closeButton.trailingAnchor
-        constraintEqualToAnchor:topBar.trailingAnchor
-                       constant:-kGridCellHeaderTrailingInset],
+    [titleLabel.trailingAnchor
+        constraintLessThanOrEqualToAnchor:closeButton.leadingAnchor
+                                 constant:kGridCellCloseButtonContentInset],
+    [closeButton.topAnchor constraintEqualToAnchor:topBar.topAnchor],
+    [closeButton.bottomAnchor constraintEqualToAnchor:topBar.bottomAnchor],
+    [closeButton.trailingAnchor constraintEqualToAnchor:topBar.trailingAnchor],
   ];
   [NSLayoutConstraint activateConstraints:constraints];
-  [titleLabel setContentHuggingPriority:UILayoutPriorityDefaultLow
-                                forAxis:UILayoutConstraintAxisHorizontal];
   [titleLabel
       setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
                                       forAxis:UILayoutConstraintAxisHorizontal];
+  [closeButton
+      setContentCompressionResistancePriority:UILayoutPriorityRequired
+                                      forAxis:UILayoutConstraintAxisHorizontal];
   [closeButton setContentHuggingPriority:UILayoutPriorityRequired
                                  forAxis:UILayoutConstraintAxisHorizontal];
   return topBar;
diff --git a/ios/chrome/browser/ui/tab_grid/grid_constants.h b/ios/chrome/browser/ui/tab_grid/grid_constants.h
index 5162be552..2f37d925 100644
--- a/ios/chrome/browser/ui/tab_grid/grid_constants.h
+++ b/ios/chrome/browser/ui/tab_grid/grid_constants.h
@@ -44,7 +44,7 @@
 // The cell header contains the icon, title, and close button.
 extern const CGFloat kGridCellHeaderHeight;
 extern const CGFloat kGridCellHeaderLeadingInset;
-extern const CGFloat kGridCellHeaderTrailingInset;
+extern const CGFloat kGridCellCloseButtonContentInset;
 extern const CGFloat kGridCellIconDiameter;
 extern const CGFloat kGridCellSelectionRingGapWidth;
 extern const CGFloat kGridCellSelectionRingTintWidth;
diff --git a/ios/chrome/browser/ui/tab_grid/grid_constants.mm b/ios/chrome/browser/ui/tab_grid/grid_constants.mm
index c12868e..960e7035 100644
--- a/ios/chrome/browser/ui/tab_grid/grid_constants.mm
+++ b/ios/chrome/browser/ui/tab_grid/grid_constants.mm
@@ -39,7 +39,7 @@
 // The cell header contains the icon, title, and close button.
 const CGFloat kGridCellHeaderHeight = 32.0f;
 const CGFloat kGridCellHeaderLeadingInset = 5.0f;
-const CGFloat kGridCellHeaderTrailingInset = 8.5f;
+const CGFloat kGridCellCloseButtonContentInset = 8.5f;
 const CGFloat kGridCellIconDiameter = 22.0f;
 const CGFloat kGridCellSelectionRingGapWidth = 2.0f;
 const CGFloat kGridCellSelectionRingTintWidth = 5.0f;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h
index 0b17be703..7042962 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h
@@ -7,6 +7,8 @@
 
 #import <UIKit/UIKit.h>
 
+@class TabGridNewTabButton;
+
 // Toolbar view with three buttons. The contents have a fixed height and are
 // pinned to the top of this view, therefore it is intended to be used as a
 // bottom toolbar.
@@ -15,7 +17,7 @@
 // contents, visibility and actions.
 @property(nonatomic, weak, readonly) UIButton* leadingButton;
 @property(nonatomic, weak, readonly) UIButton* trailingButton;
-@property(nonatomic, weak, readonly) UIButton* centerButton;
+@property(nonatomic, weak, readonly) TabGridNewTabButton* centerButton;
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_BOTTOM_TOOLBAR_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
index 85171cb..287ea3f 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h"
 
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_constants.h"
+#import "ios/chrome/browser/ui/tab_grid/tab_grid_new_tab_button.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -48,7 +49,8 @@
   UIButton* trailingButton = [UIButton buttonWithType:UIButtonTypeSystem];
   trailingButton.translatesAutoresizingMaskIntoConstraints = NO;
   trailingButton.tintColor = UIColorFromRGB(kTabGridToolbarTextButtonColor);
-  UIButton* centerButton = [UIButton buttonWithType:UIButtonTypeSystem];
+  TabGridNewTabButton* centerButton = [TabGridNewTabButton
+      buttonWithSizeClass:TabGridNewTabButtonSizeClassSmall];
   centerButton.translatesAutoresizingMaskIntoConstraints = NO;
 
   [toolbar.contentView addSubview:leadingButton];
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_new_tab_button.h b/ios/chrome/browser/ui/tab_grid/tab_grid_new_tab_button.h
new file mode 100644
index 0000000..bea9853
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_new_tab_button.h
@@ -0,0 +1,27 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_NEW_TAB_BUTTON_H_
+#define IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_NEW_TAB_BUTTON_H_
+
+#import <UIKit/UIKit.h>
+
+#import "ios/chrome/browser/ui/tab_grid/tab_grid_paging.h"
+
+// The size class determines the intrinsic size of the button.
+typedef NS_ENUM(NSUInteger, TabGridNewTabButtonSizeClass) {
+  TabGridNewTabButtonSizeClassSmall = 1,
+  TabGridNewTabButtonSizeClassLarge,
+};
+
+// The "new tab" button is a button that the user taps when they want to create
+// a new tab. Every combination of |sizeClass| and |page| results in a
+// differently configured button.
+@interface TabGridNewTabButton : UIButton
+@property(nonatomic, assign) TabGridPage page;
+@property(nonatomic, assign) TabGridNewTabButtonSizeClass sizeClass;
++ (instancetype)buttonWithSizeClass:(TabGridNewTabButtonSizeClass)sizeClass;
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_NEW_TAB_BUTTON_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_new_tab_button.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_new_tab_button.mm
new file mode 100644
index 0000000..b37c1a00
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_new_tab_button.mm
@@ -0,0 +1,84 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/tab_grid/tab_grid_new_tab_button.h"
+
+#include "ios/chrome/grit/ios_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface TabGridNewTabButton ()
+@property(nonatomic, strong) UIImage* incognitoImage;
+@property(nonatomic, strong) UIImage* regularImage;
+@end
+
+@implementation TabGridNewTabButton
+// Public properties.
+@synthesize page = _page;
+@synthesize sizeClass = _sizeClass;
+// Private properties.
+@synthesize incognitoImage;
+@synthesize regularImage;
+
++ (instancetype)buttonWithSizeClass:(TabGridNewTabButtonSizeClass)sizeClass {
+  TabGridNewTabButton* button = [super buttonWithType:UIButtonTypeSystem];
+  button.sizeClass = sizeClass;
+  return button;
+}
+
+#pragma mark - Public
+
+- (void)setPage:(TabGridPage)page {
+  UIImage* renderedImage;
+  switch (page) {
+    case TabGridPageIncognitoTabs:
+      self.enabled = YES;
+      self.accessibilityLabel =
+          l10n_util::GetNSString(IDS_IOS_TAB_GRID_CREATE_NEW_INCOGNITO_TAB);
+      renderedImage = [self.incognitoImage
+          imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
+      break;
+    case TabGridPageRegularTabs:
+      self.enabled = YES;
+      self.accessibilityLabel =
+          l10n_util::GetNSString(IDS_IOS_TAB_GRID_CREATE_NEW_TAB);
+      renderedImage = [self.regularImage
+          imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
+      break;
+    case TabGridPageRemoteTabs:
+      self.enabled = NO;
+      // Accessibility label is same as the regular tabs button, except it will
+      // say it is disabled.
+      self.accessibilityLabel =
+          l10n_util::GetNSString(IDS_IOS_TAB_GRID_CREATE_NEW_TAB);
+      // The incognito new tab button image was made so that it can be a
+      // template image. A template image becomes greyed out when disabled.
+      renderedImage = [self.incognitoImage
+          imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+      break;
+  }
+  [self setImage:renderedImage forState:UIControlStateNormal];
+  _page = page;
+}
+
+- (void)setSizeClass:(TabGridNewTabButtonSizeClass)sizeClass {
+  switch (sizeClass) {
+    case TabGridNewTabButtonSizeClassSmall:
+      self.incognitoImage =
+          [UIImage imageNamed:@"new_tab_toolbar_button_incognito"];
+      self.regularImage = [UIImage imageNamed:@"new_tab_toolbar_button"];
+      break;
+    case TabGridNewTabButtonSizeClassLarge:
+      self.incognitoImage =
+          [UIImage imageNamed:@"new_tab_floating_button_incognito"];
+      self.regularImage = [UIImage imageNamed:@"new_tab_floating_button"];
+      break;
+  }
+  _sizeClass = sizeClass;
+}
+
+@end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index 3dbfee5..6ddc567 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -12,6 +12,7 @@
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_constants.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_empty_state_view.h"
+#import "ios/chrome/browser/ui/tab_grid/tab_grid_new_tab_button.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_page_control.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
@@ -50,9 +51,9 @@
 // Clang does not allow property getters to start with the reserved word "new",
 // but provides a workaround. The getter must be set before the property is
 // declared.
-- (UIButton*)newTabButton __attribute__((objc_method_family(none)));
-@property(nonatomic, weak) UIButton* newTabButton;
-@property(nonatomic, weak) UIButton* floatingButton;
+- (TabGridNewTabButton*)newTabButton __attribute__((objc_method_family(none)));
+@property(nonatomic, weak) TabGridNewTabButton* newTabButton;
+@property(nonatomic, weak) TabGridNewTabButton* floatingButton;
 @property(nonatomic, assign) TabGridConfiguration configuration;
 
 @end
@@ -455,7 +456,8 @@
 
 // Adds floating button and constraints.
 - (void)setupFloatingButton {
-  UIButton* button = [UIButton buttonWithType:UIButtonTypeSystem];
+  TabGridNewTabButton* button = [TabGridNewTabButton
+      buttonWithSizeClass:TabGridNewTabButtonSizeClassLarge];
   button.translatesAutoresizingMaskIntoConstraints = NO;
   [self.view addSubview:button];
   self.floatingButton = button;
@@ -538,6 +540,7 @@
 
 - (void)configureButtonsForCurrentPage {
   [self.topToolbar.pageControl setSelectedPage:self.currentPage animated:YES];
+  self.newTabButton.page = self.currentPage;
   switch (self.currentPage) {
     case TabGridPageIncognitoTabs:
       self.doneButton.enabled = !self.incognitoTabsViewController.isGridEmpty;
@@ -552,52 +555,6 @@
       self.closeAllButton.enabled = NO;
       break;
   }
-  switch (self.configuration) {
-    case TabGridConfigurationBottomToolbar:
-      [self updateNewTabButtonWithIncognitoImageName:
-                @"new_tab_toolbar_button_incognito"
-                                    regularImageName:@"new_tab_toolbar_button"];
-      break;
-    case TabGridConfigurationFloatingButton:
-      [self
-          updateNewTabButtonWithIncognitoImageName:
-              @"new_tab_floating_button_incognito"
-                                  regularImageName:@"new_tab_floating_button"];
-      break;
-  }
-}
-
-- (void)updateNewTabButtonWithIncognitoImageName:(NSString*)incognitoName
-                                regularImageName:(NSString*)regularName {
-  switch (self.currentPage) {
-    case TabGridPageIncognitoTabs:
-      self.newTabButton.enabled = YES;
-      [self.newTabButton setImage:[[UIImage imageNamed:incognitoName]
-                                      imageWithRenderingMode:
-                                          UIImageRenderingModeAlwaysOriginal]
-                         forState:UIControlStateNormal];
-      self.newTabButton.accessibilityLabel =
-          l10n_util::GetNSString(IDS_IOS_TAB_GRID_CREATE_NEW_INCOGNITO_TAB);
-      break;
-    case TabGridPageRegularTabs:
-      self.newTabButton.enabled = YES;
-      [self.newTabButton setImage:[[UIImage imageNamed:regularName]
-                                      imageWithRenderingMode:
-                                          UIImageRenderingModeAlwaysOriginal]
-                         forState:UIControlStateNormal];
-      self.newTabButton.accessibilityLabel =
-          l10n_util::GetNSString(IDS_IOS_TAB_GRID_CREATE_NEW_TAB);
-      break;
-    case TabGridPageRemoteTabs:
-      self.newTabButton.enabled = NO;
-      // The incognito new tab button image was made so that it can be a
-      // template image. A template image becomes greyed out when disabled.
-      [self.newTabButton setImage:[[UIImage imageNamed:incognitoName]
-                                      imageWithRenderingMode:
-                                          UIImageRenderingModeAlwaysTemplate]
-                         forState:UIControlStateNormal];
-      break;
-  }
 }
 
 // Translates the toolbar views offscreen and then animates them back in using
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn
index 604b2d1..cb2d34ea 100644
--- a/ios/chrome/browser/web/BUILD.gn
+++ b/ios/chrome/browser/web/BUILD.gn
@@ -108,12 +108,20 @@
   ]
 }
 
-js_compile_bundle("chrome_bundle") {
-  closure_entry_point = "__crWeb.chromeBundle"
+js_compile_bundle("chrome_bundle_all_frames") {
+  closure_entry_point = "__crWeb.chromeBundleAllFrames"
+  sources = [
+    "//components/autofill/ios/fill/resources/form.js",
+    "resources/chrome_bundle_all_frames.js",
+  ]
+}
+
+js_compile_bundle("chrome_bundle_main_frame") {
+  closure_entry_point = "__crWeb.chromeBundleMainFrame"
   sources = [
     "//components/autofill/ios/browser/resources/autofill_controller.js",
     "//components/autofill/ios/fill/resources/fill.js",
-    "resources/chrome_bundle.js",
+    "resources/chrome_bundle_main_frame.js",
     "resources/print.js",
   ]
 
@@ -155,7 +163,8 @@
     "web_state_printer.h",
   ]
   deps = [
-    ":chrome_bundle",
+    ":chrome_bundle_all_frames",
+    ":chrome_bundle_main_frame",
     "//base",
     "//components/content_settings/core/browser",
     "//components/dom_distiller/core",
diff --git a/ios/chrome/browser/web/chrome_web_client.h b/ios/chrome/browser/web/chrome_web_client.h
index ad623c1..ebb79c8 100644
--- a/ios/chrome/browser/web/chrome_web_client.h
+++ b/ios/chrome/browser/web/chrome_web_client.h
@@ -38,6 +38,8 @@
       std::vector<std::string>* additional_schemes) override;
   void PostBrowserURLRewriterCreation(
       web::BrowserURLRewriter* rewriter) override;
+  NSString* GetDocumentStartScriptForAllFrames(
+      web::BrowserState* browser_state) const override;
   NSString* GetDocumentStartScriptForMainFrame(
       web::BrowserState* browser_state) const override;
   void AllowCertificateError(
diff --git a/ios/chrome/browser/web/chrome_web_client.mm b/ios/chrome/browser/web/chrome_web_client.mm
index 4c5beaf..4584ea3 100644
--- a/ios/chrome/browser/web/chrome_web_client.mm
+++ b/ios/chrome/browser/web/chrome_web_client.mm
@@ -173,10 +173,15 @@
   rewriter->AddURLRewriter(&WillHandleWebBrowserAboutURL);
 }
 
+NSString* ChromeWebClient::GetDocumentStartScriptForAllFrames(
+    web::BrowserState* browser_state) const {
+  return GetPageScript(@"chrome_bundle_all_frames");
+}
+
 NSString* ChromeWebClient::GetDocumentStartScriptForMainFrame(
     web::BrowserState* browser_state) const {
   NSMutableArray* scripts = [NSMutableArray array];
-  [scripts addObject:GetPageScript(@"chrome_bundle")];
+  [scripts addObject:GetPageScript(@"chrome_bundle_main_frame")];
 
   if (base::FeatureList::IsEnabled(features::kCredentialManager)) {
     [scripts addObject:GetPageScript(@"credential_manager")];
diff --git a/ios/chrome/browser/web/resources/chrome_bundle.js b/ios/chrome/browser/web/resources/chrome_bundle_all_frames.js
similarity index 64%
copy from ios/chrome/browser/web/resources/chrome_bundle.js
copy to ios/chrome/browser/web/resources/chrome_bundle_all_frames.js
index f32b4f7..2f1b5fee 100644
--- a/ios/chrome/browser/web/resources/chrome_bundle.js
+++ b/ios/chrome/browser/web/resources/chrome_bundle_all_frames.js
@@ -3,8 +3,6 @@
 // found in the LICENSE file.
 
 // The set of scripts to be injected into the web view as early as possible.
-goog.provide('__crWeb.chromeBundle');
+goog.provide('__crWeb.chromeBundleAllFrames');
 
-goog.require('__crWeb.autofill');
-goog.require('__crWeb.fill');
-goog.require('__crWeb.print');
+goog.require('__crWeb.form');
diff --git a/ios/chrome/browser/web/resources/chrome_bundle.js b/ios/chrome/browser/web/resources/chrome_bundle_main_frame.js
similarity index 87%
rename from ios/chrome/browser/web/resources/chrome_bundle.js
rename to ios/chrome/browser/web/resources/chrome_bundle_main_frame.js
index f32b4f7..e5a9caf 100644
--- a/ios/chrome/browser/web/resources/chrome_bundle.js
+++ b/ios/chrome/browser/web/resources/chrome_bundle_main_frame.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 // The set of scripts to be injected into the web view as early as possible.
-goog.provide('__crWeb.chromeBundle');
+goog.provide('__crWeb.chromeBundleMainFrame');
 
 goog.require('__crWeb.autofill');
 goog.require('__crWeb.fill');
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index ead43b8..ba02ae8b 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -570,7 +570,6 @@
     "url_loader_inttest.mm",
     "web_state/favicon_callbacks_inttest.mm",
     "web_state/http_auth_inttest.mm",
-    "web_state/js/form_inttest.mm",
     "web_state/navigation_and_load_callbacks_inttest.mm",
     "webui/web_ui_mojo_inttest.mm",
   ]
@@ -614,7 +613,6 @@
     "web_state/js/resources/all_frames_web_bundle.js",
     "web_state/js/resources/base.js",
     "web_state/js/resources/common.js",
-    "web_state/js/resources/form.js",
     "web_state/js/resources/message.js",
   ]
 }
diff --git a/ios/web/js_compile.gni b/ios/web/js_compile.gni
index 96c8161e..82e6ceb 100644
--- a/ios/web/js_compile.gni
+++ b/ios/web/js_compile.gni
@@ -44,6 +44,7 @@
 
   java_action(compile_js_target_name) {
     visibility = [ ":$_target_name" ]
+    forward_variables_from(invoker, [ "testonly" ])
     script = closure_compiler_path
     sources = invoker.sources
     outputs = [
@@ -68,6 +69,7 @@
                              "data_deps",
                              "deps",
                              "public_deps",
+                             "testonly",
                              "visibility",
                            ])
 
@@ -114,6 +116,7 @@
 
     java_action_foreach(compile_js_target_name) {
       visibility = [ ":$_target_name" ]
+      forward_variables_from(invoker, [ "testonly" ])
       script = closure_compiler_path
       sources = invoker.sources
       _js_modules = [
@@ -178,6 +181,7 @@
                                "data_deps",
                                "deps",
                                "public_deps",
+                               "testonly",
                                "visibility",
                              ])
 
@@ -197,6 +201,7 @@
                                "data_deps",
                                "deps",
                                "public_deps",
+                               "testonly",
                                "visibility",
                              ])
 
@@ -233,6 +238,7 @@
 
     java_action_foreach(compile_js_target_name) {
       visibility = [ ":$_target_name" ]
+      forward_variables_from(invoker, [ "testonly" ])
       script = closure_compiler_path
       sources = invoker.sources
       outputs = [
@@ -255,6 +261,7 @@
                                "data_deps",
                                "deps",
                                "public_deps",
+                               "testonly",
                                "visibility",
                              ])
 
@@ -274,6 +281,7 @@
                                "data_deps",
                                "deps",
                                "public_deps",
+                               "testonly",
                                "visibility",
                              ])
 
diff --git a/ios/web/public/test/BUILD.gn b/ios/web/public/test/BUILD.gn
index 5e8d8dd..2b10807 100644
--- a/ios/web/public/test/BUILD.gn
+++ b/ios/web/public/test/BUILD.gn
@@ -6,6 +6,10 @@
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
 
+  public_deps = [
+    "//ios/web/public/test/fakes",
+  ]
+
   deps = [
     "//base",
     "//base/test:test_support",
@@ -13,7 +17,6 @@
     "//ios/web:web",
     "//ios/web/interstitials",
     "//ios/web/navigation:core",
-    "//ios/web/public/test/fakes",
     "//ios/web/public/test/http_server",
     "//ios/web/test:test_support",
     "//testing/gtest",
diff --git a/ios/web/public/test/fakes/BUILD.gn b/ios/web/public/test/fakes/BUILD.gn
index a675250a..5b74224 100644
--- a/ios/web/public/test/fakes/BUILD.gn
+++ b/ios/web/public/test/fakes/BUILD.gn
@@ -8,7 +8,6 @@
 
   deps = [
     "//base",
-    "//ios/web/public",
     "//ios/web/public/download",
     "//ios/web/test:test_constants",
     "//ios/web/web_state:navigation_context",
@@ -20,6 +19,10 @@
     "//ui/base",
   ]
 
+  public_deps = [
+    "//ios/web/public",
+  ]
+
   sources = [
     "crw_test_js_injection_receiver.h",
     "crw_test_js_injection_receiver.mm",
diff --git a/ios/web/public/test/web_test_with_web_state.mm b/ios/web/public/test/web_test_with_web_state.mm
index 9737f70..058467a 100644
--- a/ios/web/public/test/web_test_with_web_state.mm
+++ b/ios/web/public/test/web_test_with_web_state.mm
@@ -171,7 +171,7 @@
 
 void WebTestWithWebState::WaitForCondition(ConditionBlock condition) {
   base::test::ios::WaitUntilCondition(condition, true,
-                                      base::TimeDelta::FromSeconds(10));
+                                      base::TimeDelta::FromSeconds(1000));
 }
 
 id WebTestWithWebState::ExecuteJavaScript(NSString* script) {
diff --git a/ios/web/public/web_client.h b/ios/web/public/web_client.h
index 57bc943..839a432 100644
--- a/ios/web/public/web_client.h
+++ b/ios/web/public/web_client.h
@@ -120,6 +120,16 @@
 
   // Gives the embedder a chance to provide the JavaScript to be injected into
   // the web view as early as possible. Result must not be nil.
+  // The script returned will be injected in all frames (main and subframes).
+  //
+  // TODO(crbug.com/703964): Change the return value to NSArray<NSString*> to
+  // improve performance.
+  virtual NSString* GetDocumentStartScriptForAllFrames(
+      BrowserState* browser_state) const;
+
+  // Gives the embedder a chance to provide the JavaScript to be injected into
+  // the web view as early as possible. Result must not be nil.
+  // The script returned will only be injected in the main frame.
   //
   // TODO(crbug.com/703964): Change the return value to NSArray<NSString*> to
   // improve performance.
diff --git a/ios/web/public/web_state/web_state_observer.h b/ios/web/public/web_state/web_state_observer.h
index 9651b6e..400c1fd 100644
--- a/ios/web/public/web_state/web_state_observer.h
+++ b/ios/web/public/web_state/web_state_observer.h
@@ -138,6 +138,7 @@
   // Called on form submission in the main frame or in a same-origin iframe.
   // |user_initiated| is true if the user interacted with the page.
   // |is_main_frame| is true if the submitted form is in the main frame.
+  // TODO(crbug.com/823285): move this handler to components/autofill.
   virtual void DocumentSubmitted(WebState* web_state,
                                  const std::string& form_name,
                                  bool user_initiated,
@@ -146,6 +147,7 @@
   // Called when the user is typing on a form field in the main frame or in a
   // same-origin iframe. |params.input_missing| is indicating if there is any
   // error when parsing the form field information.
+  // TODO(crbug.com/823285): move this handler to components/autofill.
   virtual void FormActivityRegistered(WebState* web_state,
                                       const FormActivityParams& params) {}
 
diff --git a/ios/web/web_client.mm b/ios/web/web_client.mm
index 0115c80..34d6a85 100644
--- a/ios/web/web_client.mm
+++ b/ios/web/web_client.mm
@@ -70,6 +70,11 @@
   return nullptr;
 }
 
+NSString* WebClient::GetDocumentStartScriptForAllFrames(
+    BrowserState* browser_state) const {
+  return @"";
+}
+
 NSString* WebClient::GetDocumentStartScriptForMainFrame(
     BrowserState* browser_state) const {
   return @"";
diff --git a/ios/web/web_state/js/form_inttest.mm b/ios/web/web_state/js/form_inttest.mm
deleted file mode 100644
index c40063c..0000000
--- a/ios/web/web_state/js/form_inttest.mm
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ios/web/public/test/fakes/test_web_state_observer.h"
-#import "ios/web/public/test/web_test_with_web_state.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace web {
-
-using FormJsTest = WebTestWithWebState;
-
-// Tests that keyup event correctly delivered to WebStateObserver.
-TEST_F(FormJsTest, KeyUpEvent) {
-  TestWebStateObserver observer(web_state());
-  LoadHtml(@"<p></p>");
-  ASSERT_FALSE(observer.form_activity_info());
-  ExecuteJavaScript(@"document.dispatchEvent(new KeyboardEvent('keyup'));");
-  TestFormActivityInfo* info = observer.form_activity_info();
-  ASSERT_TRUE(info);
-  EXPECT_EQ("keyup", info->form_activity.type);
-  EXPECT_FALSE(info->form_activity.input_missing);
-}
-
-// Tests that focus event correctly delivered to WebStateObserver.
-TEST_F(FormJsTest, FocusMainFrame) {
-  TestWebStateObserver observer(web_state());
-  LoadHtml(
-      @"<form>"
-       "<input type='text' name='username' id='id1'>"
-       "<input type='password' name='password' id='id2'>"
-       "</form>");
-  ASSERT_FALSE(observer.form_activity_info());
-  ExecuteJavaScript(@"document.getElementById('id1').focus();");
-  TestFormActivityInfo* info = observer.form_activity_info();
-  ASSERT_TRUE(info);
-  EXPECT_EQ("focus", info->form_activity.type);
-  EXPECT_FALSE(info->form_activity.input_missing);
-}
-
-// Tests that submit event correctly delivered to WebStateObserver.
-TEST_F(FormJsTest, FormSubmitMainFrame) {
-  TestWebStateObserver observer(web_state());
-  LoadHtml(
-      @"<form id='form1'>"
-       "<input type='password'>"
-       "<input type='submit' id='submit_input'/>"
-       "</form>");
-  ASSERT_FALSE(observer.submit_document_info());
-  ExecuteJavaScript(@"document.getElementById('submit_input').click();");
-  TestSubmitDocumentInfo* info = observer.submit_document_info();
-  ASSERT_TRUE(info);
-  EXPECT_EQ("form1", info->form_name);
-}
-
-// Tests that focus event from same-origin iframe correctly delivered to
-// WebStateObserver.
-TEST_F(FormJsTest, FocusSameOriginIFrame) {
-  TestWebStateObserver observer(web_state());
-  LoadHtml(@"<iframe id='frame1'></iframe>");
-  ExecuteJavaScript(
-      @"document.getElementById('frame1').contentDocument.body.innerHTML = "
-       "'<form>"
-       "<input type=\"text\" name=\"username\" id=\"id1\">"
-       "<input type=\"password\" name=\"password\" id=\"id2\">"
-       "</form>'");
-
-  ExecuteJavaScript(
-      @"document.getElementById('frame1').contentDocument.getElementById('id1')"
-      @".focus()");
-  TestFormActivityInfo* info = observer.form_activity_info();
-  ASSERT_TRUE(info);
-  EXPECT_EQ("focus", info->form_activity.type);
-  EXPECT_FALSE(info->form_activity.input_missing);
-}
-
-// Tests that submit event from same-origin iframe correctly delivered to
-// WebStateObserver.
-TEST_F(FormJsTest, FormSameOriginIFrame) {
-  TestWebStateObserver observer(web_state());
-  LoadHtml(@"<iframe id='frame1'></iframe>");
-  ExecuteJavaScript(
-      @"document.getElementById('frame1').contentDocument.body.innerHTML = "
-       "'<form id=\"form1\">"
-       "<input type=\"password\" name=\"password\" id=\"id2\">"
-       "<input type=\"submit\" id=\"submit_input\"/>"
-       "</form>'");
-  ExecuteJavaScript(
-      @"document.getElementById('frame1').contentDocument.getElementById('"
-      @"submit_input').click();");
-  TestSubmitDocumentInfo* info = observer.submit_document_info();
-  ASSERT_TRUE(info);
-  EXPECT_EQ("form1", info->form_name);
-}
-
-}  // namespace web
diff --git a/ios/web/web_state/js/page_script_util.mm b/ios/web/web_state/js/page_script_util.mm
index b4ff6ac3..6a3d8307 100644
--- a/ios/web/web_state/js/page_script_util.mm
+++ b/ios/web/web_state/js/page_script_util.mm
@@ -93,8 +93,14 @@
 }
 
 NSString* GetDocumentStartScriptForAllFrames(BrowserState* browser_state) {
-  return MakeScriptInjectableOnce(@"start_all_frames",
-                                  GetPageScript(@"all_frames_web_bundle"));
+  DCHECK(GetWebClient());
+  NSString* embedder_page_script =
+      GetWebClient()->GetDocumentStartScriptForAllFrames(browser_state);
+  DCHECK(embedder_page_script);
+  NSString* web_bundle = GetPageScript(@"all_frames_web_bundle");
+  NSString* script =
+      [NSString stringWithFormat:@"%@; %@", web_bundle, embedder_page_script];
+  return MakeScriptInjectableOnce(@"start_all_frames", script);
 }
 
 NSString* GetDocumentEndScriptForAllFrames(BrowserState* browser_state) {
diff --git a/ios/web/web_state/js/resources/all_frames_web_bundle.js b/ios/web/web_state/js/resources/all_frames_web_bundle.js
index 5828def..de81c0a1 100644
--- a/ios/web/web_state/js/resources/all_frames_web_bundle.js
+++ b/ios/web/web_state/js/resources/all_frames_web_bundle.js
@@ -5,4 +5,7 @@
 // Set of scripts required by web layer backed up by WKWebView.
 goog.provide('__crWeb.allFramesWebBundle');
 
-goog.require('__crWeb.form');
+goog.require('__crWeb.base');
+goog.require('__crWeb.common');
+goog.require('__crWeb.message');
+
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 2498b94..d2024ea 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -831,9 +831,11 @@
 - (BOOL)handleDocumentFaviconsMessage:(base::DictionaryValue*)message
                               context:(NSDictionary*)context;
 // Handles 'document.submit' message.
+// TODO(crbug.com/823285): move this handler to components/autofill.
 - (BOOL)handleDocumentSubmitMessage:(base::DictionaryValue*)message
                             context:(NSDictionary*)context;
 // Handles 'form.activity' message.
+// TODO(crbug.com/823285): move this handler to components/autofill.
 - (BOOL)handleFormActivityMessage:(base::DictionaryValue*)message
                           context:(NSDictionary*)context;
 // Handles 'window.error' message.
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn
index b0588793..57d006f 100644
--- a/ios/web_view/BUILD.gn
+++ b/ios/web_view/BUILD.gn
@@ -312,6 +312,7 @@
   sources = [
     "//components/autofill/ios/browser/resources/autofill_controller.js",
     "//components/autofill/ios/fill/resources/fill.js",
+    "//components/autofill/ios/fill/resources/form.js",
     "resources/web_view_bundle.js",
   ]
 }
diff --git a/ios/web_view/resources/web_view_bundle.js b/ios/web_view/resources/web_view_bundle.js
index 72f26cbe..0eec4949 100644
--- a/ios/web_view/resources/web_view_bundle.js
+++ b/ios/web_view/resources/web_view_bundle.js
@@ -7,3 +7,4 @@
 
 goog.require('__crWeb.autofill');
 goog.require('__crWeb.fill');
+goog.require('__crWeb.form');
diff --git a/media/PRESUBMIT_test.py b/media/PRESUBMIT_test.py
old mode 100644
new mode 100755
index f537a6d..6ca6687
--- a/media/PRESUBMIT_test.py
+++ b/media/PRESUBMIT_test.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # Copyright 2014 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
diff --git a/media/capture/mojom/BUILD.gn b/media/capture/mojom/BUILD.gn
index 0cd5b67..42038dc 100644
--- a/media/capture/mojom/BUILD.gn
+++ b/media/capture/mojom/BUILD.gn
@@ -13,6 +13,7 @@
   public_deps = [
     "//media/mojo/interfaces",
     "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//ui/gfx/geometry/mojo",
   ]
 }
diff --git a/media/capture/mojom/video_capture_types.mojom b/media/capture/mojom/video_capture_types.mojom
index 4e30b745..8f87b94 100644
--- a/media/capture/mojom/video_capture_types.mojom
+++ b/media/capture/mojom/video_capture_types.mojom
@@ -5,7 +5,7 @@
 module media.mojom;
 
 import "media/mojo/interfaces/media_types.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "mojo/common/values.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
@@ -60,7 +60,7 @@
 };
 
 struct VideoFrameInfo{
-  mojo.common.mojom.TimeDelta timestamp;
+  mojo_base.mojom.TimeDelta timestamp;
   mojo.common.mojom.DictionaryValue metadata;
   VideoPixelFormat pixel_format;
   VideoPixelStorage storage_type;
diff --git a/media/capture/video/android/video_capture_device_factory_android.cc b/media/capture/video/android/video_capture_device_factory_android.cc
index 300f7e43..b6191cc 100644
--- a/media/capture/video/android/video_capture_device_factory_android.cc
+++ b/media/capture/video/android/video_capture_device_factory_android.cc
@@ -146,7 +146,8 @@
 VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
-    MojoJpegDecodeAcceleratorFactoryCB jda_factory) {
+    MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+    MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
   return new VideoCaptureDeviceFactoryAndroid();
 }
 
diff --git a/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc b/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc
index 2b8dc26c..96334307 100644
--- a/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc
+++ b/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc
@@ -114,11 +114,13 @@
 }
 
 bool CameraHalDispatcherImpl::Start(
-    MojoJpegDecodeAcceleratorFactoryCB jda_factory) {
+    MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+    MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
   if (!StartThreads()) {
     return false;
   }
-  jda_factory_ = jda_factory;
+  jda_factory_ = std::move(jda_factory);
+  jea_factory_ = std::move(jea_factory);
   base::WaitableEvent started(base::WaitableEvent::ResetPolicy::MANUAL,
                               base::WaitableEvent::InitialState::NOT_SIGNALED);
   blocking_io_task_runner_->PostTask(
@@ -199,6 +201,11 @@
   jda_factory_.Run(std::move(jda_request));
 }
 
+void CameraHalDispatcherImpl::GetJpegEncodeAccelerator(
+    media::mojom::JpegEncodeAcceleratorRequest jea_request) {
+  jea_factory_.Run(std::move(jea_request));
+}
+
 void CameraHalDispatcherImpl::CreateSocket(base::WaitableEvent* started) {
   DCHECK(blocking_io_task_runner_->BelongsToCurrentThread());
 
diff --git a/media/capture/video/chromeos/camera_hal_dispatcher_impl.h b/media/capture/video/chromeos/camera_hal_dispatcher_impl.h
index da3591c..5be8a0fc 100644
--- a/media/capture/video/chromeos/camera_hal_dispatcher_impl.h
+++ b/media/capture/video/chromeos/camera_hal_dispatcher_impl.h
@@ -47,7 +47,8 @@
  public:
   static CameraHalDispatcherImpl* GetInstance();
 
-  bool Start(MojoJpegDecodeAcceleratorFactoryCB jda_factory);
+  bool Start(MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+             MojoJpegEncodeAcceleratorFactoryCB jea_factory);
 
   void AddClientObserver(std::unique_ptr<CameraClientObserver> observer);
 
@@ -58,6 +59,8 @@
   void RegisterClient(arc::mojom::CameraHalClientPtr client) final;
   void GetJpegDecodeAccelerator(
       media::mojom::JpegDecodeAcceleratorRequest jda_request) final;
+  void GetJpegEncodeAccelerator(
+      media::mojom::JpegEncodeAcceleratorRequest jea_request) final;
 
  private:
   friend struct base::DefaultSingletonTraits<CameraHalDispatcherImpl>;
@@ -108,6 +111,8 @@
 
   MojoJpegDecodeAcceleratorFactoryCB jda_factory_;
 
+  MojoJpegEncodeAcceleratorFactoryCB jea_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(CameraHalDispatcherImpl);
 };
 
diff --git a/media/capture/video/chromeos/mojo/arc_camera3_service.mojom b/media/capture/video/chromeos/mojo/arc_camera3_service.mojom
index dfef34d..24e7475 100644
--- a/media/capture/video/chromeos/mojo/arc_camera3_service.mojom
+++ b/media/capture/video/chromeos/mojo/arc_camera3_service.mojom
@@ -8,6 +8,7 @@
 
 import "media/capture/video/chromeos/mojo/camera_common.mojom";
 import "media/mojo/interfaces/jpeg_decode_accelerator.mojom";
+import "media/mojo/interfaces/jpeg_encode_accelerator.mojom";
 
 // The ARC++ camera HAL v3 Mojo dispatcher.  The dispatcher acts as a proxy and
 // waits for the server and the clients to register.  There can only be one
@@ -16,7 +17,7 @@
 // channel to the server and pass the established Mojo channel to the client in
 // order to set up a Mojo channel between the client and the server.
 //
-// Next method ID: 2
+// Next method ID: 4
 interface CameraHalDispatcher {
   // A CameraHalServer calls RegisterServer to register itself with the
   // dispatcher.
@@ -29,6 +30,10 @@
   // Get JpegDecodeAccelerator from dispatcher.
   [MinVersion=1] GetJpegDecodeAccelerator@2(
     media.mojom.JpegDecodeAccelerator& jda_request);
+
+  // Get JpegEncodeAccelerator from dispatcher.
+  [MinVersion=2] GetJpegEncodeAccelerator@3(
+    media.mojom.JpegEncodeAccelerator& jea_request);
 };
 
 // The ARC++ camera HAL v3 Mojo server.
diff --git a/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc b/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc
index 3e3bec8..19fd4992 100644
--- a/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc
+++ b/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc
@@ -20,10 +20,11 @@
 VideoCaptureDeviceFactoryChromeOS::VideoCaptureDeviceFactoryChromeOS(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer,
     gpu::GpuMemoryBufferManager* gpu_buffer_manager,
-    MojoJpegDecodeAcceleratorFactoryCB jda_factory)
+    MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+    MojoJpegEncodeAcceleratorFactoryCB jea_factory)
     : task_runner_for_screen_observer_(task_runner_for_screen_observer),
       camera_hal_ipc_thread_("CameraHalIpcThread"),
-      initialized_(Init(jda_factory)) {
+      initialized_(Init(std::move(jda_factory), std::move(jea_factory))) {
   g_gpu_buffer_manager = gpu_buffer_manager;
 }
 
@@ -91,14 +92,16 @@
 }
 
 bool VideoCaptureDeviceFactoryChromeOS::Init(
-    MojoJpegDecodeAcceleratorFactoryCB jda_factory) {
+    MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+    MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
   if (!camera_hal_ipc_thread_.Start()) {
     LOG(ERROR) << "Module thread failed to start";
     return false;
   }
 
   if (!CameraHalDispatcherImpl::GetInstance()->IsStarted() &&
-      !CameraHalDispatcherImpl::GetInstance()->Start(jda_factory)) {
+      !CameraHalDispatcherImpl::GetInstance()->Start(std::move(jda_factory),
+                                                     std::move(jea_factory))) {
     LOG(ERROR) << "Failed to start CameraHalDispatcherImpl";
     return false;
   }
@@ -115,7 +118,8 @@
 VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer,
     gpu::GpuMemoryBufferManager* gpu_buffer_manager,
-    MojoJpegDecodeAcceleratorFactoryCB jda_factory) {
+    MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+    MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
   // On Chrome OS we have to support two use cases:
   //
   // 1. For devices that have the camera HAL v3 service running on Chrome OS,
@@ -127,7 +131,8 @@
   //    v3.
   if (VideoCaptureDeviceFactoryChromeOS::ShouldEnable()) {
     return new VideoCaptureDeviceFactoryChromeOS(
-        task_runner_for_screen_observer, gpu_buffer_manager, jda_factory);
+        task_runner_for_screen_observer, gpu_buffer_manager,
+        std::move(jda_factory), std::move(jea_factory));
   } else {
     return new VideoCaptureDeviceFactoryLinux(task_runner_for_screen_observer);
   }
diff --git a/media/capture/video/chromeos/video_capture_device_factory_chromeos.h b/media/capture/video/chromeos/video_capture_device_factory_chromeos.h
index d621591..e1cdbbde 100644
--- a/media/capture/video/chromeos/video_capture_device_factory_chromeos.h
+++ b/media/capture/video/chromeos/video_capture_device_factory_chromeos.h
@@ -20,7 +20,8 @@
       scoped_refptr<base::SingleThreadTaskRunner>
           task_runner_for_screen_observer,
       gpu::GpuMemoryBufferManager* gpu_buffer_manager,
-      MojoJpegDecodeAcceleratorFactoryCB jda_factory);
+      MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+      MojoJpegEncodeAcceleratorFactoryCB jea_factory);
 
   ~VideoCaptureDeviceFactoryChromeOS() override;
 
@@ -46,7 +47,8 @@
  private:
   // Initializes the factory. The factory is functional only after this call
   // succeeds.
-  bool Init(MojoJpegDecodeAcceleratorFactoryCB jda_factory);
+  bool Init(MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+            MojoJpegEncodeAcceleratorFactoryCB jea_factory);
 
   const scoped_refptr<base::SingleThreadTaskRunner>
       task_runner_for_screen_observer_;
diff --git a/media/capture/video/linux/video_capture_device_factory_linux.cc b/media/capture/video/linux/video_capture_device_factory_linux.cc
index 9dd68b78..3699cb9 100644
--- a/media/capture/video/linux/video_capture_device_factory_linux.cc
+++ b/media/capture/video/linux/video_capture_device_factory_linux.cc
@@ -293,7 +293,8 @@
 VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
-    MojoJpegDecodeAcceleratorFactoryCB jda_factory) {
+    MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+    MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
   return new VideoCaptureDeviceFactoryLinux(ui_task_runner);
 }
 #endif
diff --git a/media/capture/video/mac/video_capture_device_factory_mac.mm b/media/capture/video/mac/video_capture_device_factory_mac.mm
index 7ce93c4..d240605 100644
--- a/media/capture/video/mac/video_capture_device_factory_mac.mm
+++ b/media/capture/video/mac/video_capture_device_factory_mac.mm
@@ -125,7 +125,8 @@
 VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
-    MojoJpegDecodeAcceleratorFactoryCB jda_factory) {
+    MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+    MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
   return new VideoCaptureDeviceFactoryMac();
 }
 
diff --git a/media/capture/video/video_capture_device_factory.cc b/media/capture/video/video_capture_device_factory.cc
index 63e03bc..89f37c4 100644
--- a/media/capture/video/video_capture_device_factory.cc
+++ b/media/capture/video/video_capture_device_factory.cc
@@ -19,7 +19,8 @@
 VideoCaptureDeviceFactory::CreateFactory(
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     gpu::GpuMemoryBufferManager* gpu_buffer_manager,
-    MojoJpegDecodeAcceleratorFactoryCB jda_factory) {
+    MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+    MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
   const base::CommandLine* command_line =
       base::CommandLine::ForCurrentProcess();
   // Use a Fake or File Video Device Factory if the command line flags are
@@ -43,7 +44,8 @@
     // screen rotations.
     return std::unique_ptr<VideoCaptureDeviceFactory>(
         CreateVideoCaptureDeviceFactory(ui_task_runner, gpu_buffer_manager,
-                                        jda_factory));
+                                        std::move(jda_factory),
+                                        std::move(jea_factory)));
   }
 }
 
@@ -60,7 +62,8 @@
 VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     gpu::GpuMemoryBufferManager* gpu_buffer_manager,
-    MojoJpegDecodeAcceleratorFactoryCB jda_factory) {
+    MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+    MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
   NOTIMPLEMENTED();
   return NULL;
 }
diff --git a/media/capture/video/video_capture_device_factory.h b/media/capture/video/video_capture_device_factory.h
index 7476852..73a8c48 100644
--- a/media/capture/video/video_capture_device_factory.h
+++ b/media/capture/video/video_capture_device_factory.h
@@ -11,11 +11,14 @@
 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
 #include "media/capture/video/video_capture_device.h"
 #include "media/mojo/interfaces/jpeg_decode_accelerator.mojom.h"
+#include "media/mojo/interfaces/jpeg_encode_accelerator.mojom.h"
 
 namespace media {
 
 using MojoJpegDecodeAcceleratorFactoryCB =
     base::RepeatingCallback<void(media::mojom::JpegDecodeAcceleratorRequest)>;
+using MojoJpegEncodeAcceleratorFactoryCB =
+    base::RepeatingCallback<void(media::mojom::JpegEncodeAcceleratorRequest)>;
 
 // VideoCaptureDeviceFactory is the base class for creation of video capture
 // devices in the different platforms. VCDFs are created by MediaStreamManager
@@ -34,7 +37,8 @@
   static std::unique_ptr<VideoCaptureDeviceFactory> CreateFactory(
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
       gpu::GpuMemoryBufferManager* gpu_buffer_manager,
-      MojoJpegDecodeAcceleratorFactoryCB jpeg_decoder_factory);
+      MojoJpegDecodeAcceleratorFactoryCB jpeg_decoder_factory,
+      MojoJpegEncodeAcceleratorFactoryCB jpeg_encoder_factory);
 
   VideoCaptureDeviceFactory();
   virtual ~VideoCaptureDeviceFactory();
@@ -65,7 +69,8 @@
   static VideoCaptureDeviceFactory* CreateVideoCaptureDeviceFactory(
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
       gpu::GpuMemoryBufferManager* gpu_buffer_manager,
-      MojoJpegDecodeAcceleratorFactoryCB jda_factory);
+      MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+      MojoJpegEncodeAcceleratorFactoryCB jea_factory);
 
   DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactory);
 };
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc
index 9e9f874..dfb901b9 100644
--- a/media/capture/video/video_capture_device_unittest.cc
+++ b/media/capture/video/video_capture_device_unittest.cc
@@ -285,7 +285,9 @@
             nullptr,
 #endif
             base::BindRepeating(
-                [](media::mojom::JpegDecodeAcceleratorRequest) {}))) {
+                [](media::mojom::JpegDecodeAcceleratorRequest) {}),
+            base::DoNothing::Repeatedly<
+                media::mojom::JpegEncodeAcceleratorRequest>())) {
   }
 
   void SetUp() override {
diff --git a/media/capture/video/win/video_capture_device_factory_win.cc b/media/capture/video/win/video_capture_device_factory_win.cc
index ea65e95..4475bbbe 100644
--- a/media/capture/video/win/video_capture_device_factory_win.cc
+++ b/media/capture/video/win/video_capture_device_factory_win.cc
@@ -483,7 +483,8 @@
 VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
-    MojoJpegDecodeAcceleratorFactoryCB jda_factory) {
+    MojoJpegDecodeAcceleratorFactoryCB jda_factory,
+    MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
   return new VideoCaptureDeviceFactoryWin();
 }
 
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index 6d67ac1fd..173afb5 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -449,7 +449,7 @@
       if (packet_end - header_start < MPEG1AudioStreamParser::kHeaderSize ||
           !MPEG1AudioStreamParser::ParseHeader(nullptr, header_start,
                                                nullptr)) {
-        LIMITED_MEDIA_LOG(INFO, nullptr, num_discarded_packet_warnings_, 5)
+        LIMITED_MEDIA_LOG(INFO, media_log_, num_discarded_packet_warnings_, 5)
             << "Discarding invalid MP3 packet, ts: "
             << ConvertStreamTimestamp(stream_->time_base, packet->pts)
             << ", duration: "
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index 6128e26..ba89d7c 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -95,6 +95,8 @@
     "gles2_decoder_helper.h",
     "gpu_jpeg_decode_accelerator_factory.cc",
     "gpu_jpeg_decode_accelerator_factory.h",
+    "gpu_jpeg_encode_accelerator_factory.cc",
+    "gpu_jpeg_encode_accelerator_factory.h",
     "gpu_video_accelerator_util.cc",
     "gpu_video_accelerator_util.h",
     "gpu_video_decode_accelerator_factory.cc",
diff --git a/media/gpu/gpu_jpeg_encode_accelerator_factory.cc b/media/gpu/gpu_jpeg_encode_accelerator_factory.cc
new file mode 100644
index 0000000..57bf628
--- /dev/null
+++ b/media/gpu/gpu_jpeg_encode_accelerator_factory.cc
@@ -0,0 +1,55 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/gpu/gpu_jpeg_encode_accelerator_factory.h"
+
+#include "base/bind.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
+#include "media/base/media_switches.h"
+#include "media/gpu/features.h"
+
+#if BUILDFLAG(USE_V4L2_CODEC) && defined(ARCH_CPU_ARM_FAMILY)
+#define USE_V4L2_JEA
+#endif
+
+#if BUILDFLAG(USE_VAAPI)
+#include "media/gpu/vaapi/vaapi_jpeg_encode_accelerator.h"
+#endif
+
+namespace media {
+
+namespace {
+
+#if BUILDFLAG(USE_VAAPI)
+std::unique_ptr<JpegEncodeAccelerator> CreateVaapiJEA(
+    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
+  return std::make_unique<VaapiJpegEncodeAccelerator>(
+      std::move(io_task_runner));
+}
+#endif
+
+}  // namespace
+
+// static
+bool GpuJpegEncodeAcceleratorFactory::IsAcceleratedJpegEncodeSupported() {
+  auto accelerator_factory_functions = GetAcceleratorFactories();
+  return !accelerator_factory_functions.empty();
+}
+
+// static
+std::vector<GpuJpegEncodeAcceleratorFactory::CreateAcceleratorCB>
+GpuJpegEncodeAcceleratorFactory::GetAcceleratorFactories() {
+  // This list is ordered by priority of use.
+  std::vector<CreateAcceleratorCB> result;
+#if defined(USE_V4L2_JEA)
+// TODO(mojahsu): Add CreateV4l2JEA here.
+#endif
+#if BUILDFLAG(USE_VAAPI)
+  result.push_back(base::BindRepeating(&CreateVaapiJEA));
+#endif
+  return result;
+}
+
+}  // namespace media
diff --git a/media/gpu/gpu_jpeg_encode_accelerator_factory.h b/media/gpu/gpu_jpeg_encode_accelerator_factory.h
new file mode 100644
index 0000000..765562e
--- /dev/null
+++ b/media/gpu/gpu_jpeg_encode_accelerator_factory.h
@@ -0,0 +1,33 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_GPU_GPU_JPEG_ENCODE_ACCELERATOR_FACTORY_H_
+#define MEDIA_GPU_GPU_JPEG_ENCODE_ACCELERATOR_FACTORY_H_
+
+#include "base/memory/ref_counted.h"
+#include "media/gpu/media_gpu_export.h"
+#include "media/video/jpeg_encode_accelerator.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace media {
+
+class MEDIA_GPU_EXPORT GpuJpegEncodeAcceleratorFactory {
+ public:
+  using CreateAcceleratorCB =
+      base::RepeatingCallback<std::unique_ptr<JpegEncodeAccelerator>(
+          scoped_refptr<base::SingleThreadTaskRunner>)>;
+
+  // Static query for JPEG supported. This query calls the appropriate
+  // platform-specific version.
+  static bool IsAcceleratedJpegEncodeSupported();
+
+  static std::vector<CreateAcceleratorCB> GetAcceleratorFactories();
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_GPU_JPEG_ENCODE_ACCELERATOR_FACTORY_H_
diff --git a/media/gpu/vaapi/va_surface.h b/media/gpu/vaapi/va_surface.h
index 8979480..79f8cbe 100644
--- a/media/gpu/vaapi/va_surface.h
+++ b/media/gpu/vaapi/va_surface.h
@@ -87,6 +87,7 @@
  public:
   // Provided by user, will be called when all references to the surface
   // are released.
+  // TODO(mcasas): make this a OnceCallback, https://crbug.com/822346.
   using ReleaseCB = base::Callback<void(VASurfaceID)>;
 
   VASurface(VASurfaceID va_surface_id,
diff --git a/media/gpu/vaapi/vaapi_video_decode_accelerator.cc b/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
index 84d8189..a6d995a8 100644
--- a/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
+++ b/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
@@ -55,13 +55,23 @@
   return VA_RT_FORMAT_YUV420;
 }
 
-}  // namespace
-
-static void ReportToUMA(VAVDADecoderFailure failure) {
+void ReportToUMA(VAVDADecoderFailure failure) {
   UMA_HISTOGRAM_ENUMERATION("Media.VAVDA.DecoderFailure", failure,
                             VAVDA_DECODER_FAILURES_MAX + 1);
 }
 
+#if defined(USE_OZONE)
+void CloseGpuMemoryBufferHandle(const gfx::GpuMemoryBufferHandle& handle) {
+  for (const auto& fd : handle.native_pixmap_handle.fds) {
+    // Close the fd by wrapping it in a ScopedFD and letting
+    // it fall out of scope.
+    base::ScopedFD scoped_fd(fd.fd);
+  }
+}
+#endif
+
+}  // namespace
+
 #define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret) \
   do {                                                             \
     if (!(result)) {                                               \
@@ -610,15 +620,6 @@
 }
 
 #if defined(USE_OZONE)
-static void CloseGpuMemoryBufferHandle(
-    const gfx::GpuMemoryBufferHandle& handle) {
-  for (const auto& fd : handle.native_pixmap_handle.fds) {
-    // Close the fd by wrapping it in a ScopedFD and letting
-    // it fall out of scope.
-    base::ScopedFD scoped_fd(fd.fd);
-  }
-}
-
 void VaapiVideoDecodeAccelerator::ImportBufferForPicture(
     int32_t picture_buffer_id,
     VideoPixelFormat pixel_format,
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc
index 764c64c0..b716573bb 100644
--- a/media/gpu/vaapi/vaapi_wrapper.cc
+++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -824,14 +824,23 @@
   va_attribs[1].value.type = VAGenericValueTypePointer;
   va_attribs[1].value.value.p = &va_attrib_extbuf;
 
-  scoped_refptr<VASurface> va_surface = CreateUnownedSurface(
-      BufferFormatToVARTFormat(pixmap->GetBufferFormat()), size, va_attribs);
-  if (!va_surface) {
-    LOG(ERROR) << "Failed to create VASurface for an Ozone NativePixmap";
-    return nullptr;
+  const unsigned int va_format =
+      BufferFormatToVARTFormat(pixmap->GetBufferFormat());
+
+  VASurfaceID va_surface_id = VA_INVALID_ID;
+  {
+    base::AutoLock auto_lock(*va_lock_);
+    VAStatus va_res =
+        vaCreateSurfaces(va_display_, va_format, size.width(), size.height(),
+                         &va_surface_id, 1, &va_attribs[0], va_attribs.size());
+    VA_SUCCESS_OR_RETURN(va_res, "Failed to create unowned VASurface", nullptr);
   }
 
-  return va_surface;
+  // It's safe to use Unretained() here, because the caller takes care of the
+  // destruction order. All the surfaces will be destroyed before VaapiWrapper.
+  return new VASurface(
+      va_surface_id, size, va_format,
+      base::Bind(&VaapiWrapper::DestroySurface, base::Unretained(this)));
 }
 
 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type,
@@ -1280,33 +1289,7 @@
   va_surface_format_ = 0;
 }
 
-scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface(
-    unsigned int va_format,
-    const gfx::Size& size,
-    const std::vector<VASurfaceAttrib>& va_attribs) {
-  base::AutoLock auto_lock(*va_lock_);
-
-  std::vector<VASurfaceAttrib> attribs(va_attribs);
-  VASurfaceID va_surface_id;
-  VAStatus va_res =
-      vaCreateSurfaces(va_display_, va_format, size.width(), size.height(),
-                       &va_surface_id, 1, &attribs[0], attribs.size());
-
-  scoped_refptr<VASurface> va_surface;
-  VA_SUCCESS_OR_RETURN(va_res, "Failed to create unowned VASurface",
-                       va_surface);
-
-  // This is safe to use Unretained() here, because the VDA takes care
-  // of the destruction order. All the surfaces will be destroyed
-  // before VaapiWrapper.
-  va_surface = new VASurface(
-      va_surface_id, size, va_format,
-      base::Bind(&VaapiWrapper::DestroyUnownedSurface, base::Unretained(this)));
-
-  return va_surface;
-}
-
-void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) {
+void VaapiWrapper::DestroySurface(VASurfaceID va_surface_id) {
   base::AutoLock auto_lock(*va_lock_);
 
   VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1);
diff --git a/media/gpu/vaapi/vaapi_wrapper.h b/media/gpu/vaapi/vaapi_wrapper.h
index b1b646f..f019e7a 100644
--- a/media/gpu/vaapi/vaapi_wrapper.h
+++ b/media/gpu/vaapi/vaapi_wrapper.h
@@ -218,16 +218,8 @@
   // Free all memory allocated in CreateSurfaces.
   void DestroySurfaces_Locked();
 
-  // Create a VASurface of |va_format|, |size| and using |va_attribs|
-  // attributes. The ownership of the surface is transferred to the
-  // caller. It differs from surfaces created using CreateSurfaces(),
-  // where VaapiWrapper is the owner of the surfaces.
-  scoped_refptr<VASurface> CreateUnownedSurface(
-      unsigned int va_format,
-      const gfx::Size& size,
-      const std::vector<VASurfaceAttrib>& va_attribs);
-  // Destroys a |va_surface| created using CreateUnownedSurface.
-  void DestroyUnownedSurface(VASurfaceID va_surface_id);
+  // Destroys a |va_surface_id|.
+  void DestroySurface(VASurfaceID va_surface_id);
 
   // Initialize the video post processing context with the |size| of
   // the input pictures to be processed.
diff --git a/media/mojo/interfaces/BUILD.gn b/media/mojo/interfaces/BUILD.gn
index df02d768..8cb651c6 100644
--- a/media/mojo/interfaces/BUILD.gn
+++ b/media/mojo/interfaces/BUILD.gn
@@ -23,6 +23,7 @@
     "demuxer_stream.mojom",
     "interface_factory.mojom",
     "jpeg_decode_accelerator.mojom",
+    "jpeg_encode_accelerator.mojom",
     "key_system_support.mojom",
     "media_log.mojom",
     "media_metrics_provider.mojom",
diff --git a/media/mojo/interfaces/audio_data_pipe.mojom b/media/mojo/interfaces/audio_data_pipe.mojom
index b9d5a28..be0fa56 100644
--- a/media/mojo/interfaces/audio_data_pipe.mojom
+++ b/media/mojo/interfaces/audio_data_pipe.mojom
@@ -6,7 +6,22 @@
 
 // Used by audio streams for realtime-ish data transfer. Used for both input
 // and output streams, see AudioDeviceThread, AudioSyncReader, and
-// AudioInputSyncWriter.
+// AudioInputSyncWriter. |socket| is a base::SyncSocket used for signaling and
+// |shared_memory| is used for the actual audio data.
+//
+// When using a pull model, the code pulling the data writes |n| (an unsigned
+// 32 bit sequence number) to the socket, and the source from which data is
+// pulled writes a buffer to |shared_memory| and writes |n| back to signal that
+// it finished writing. Then the process continues with |n+1|. This model is
+// used to get data for playout.
+//
+// When using a push model, the code pushing data writes a buffer to
+// |shared_memory| and writes |n| to the socket. When the other side finished
+// reading the buffer, it writes |n| to the socket to signal that the memory is
+// safe to write to again. |shared_memory| may have room for several buffers,
+// in which case the next buffer can be pushed without waiting for the previous
+// one to be consumed. This model used is to deliver microphone data to a
+// consumer.
 struct AudioDataPipe {
   handle<shared_buffer> shared_memory;
   handle socket;
diff --git a/media/mojo/interfaces/audio_decoder_config_struct_traits.cc b/media/mojo/interfaces/audio_decoder_config_struct_traits.cc
index f9e912d..844597df 100644
--- a/media/mojo/interfaces/audio_decoder_config_struct_traits.cc
+++ b/media/mojo/interfaces/audio_decoder_config_struct_traits.cc
@@ -4,7 +4,7 @@
 
 #include "media/mojo/interfaces/audio_decoder_config_struct_traits.h"
 
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 
 namespace mojo {
 
diff --git a/media/mojo/interfaces/audio_decoder_config_struct_traits_unittest.cc b/media/mojo/interfaces/audio_decoder_config_struct_traits_unittest.cc
index 74a2f76..00c81d51 100644
--- a/media/mojo/interfaces/audio_decoder_config_struct_traits_unittest.cc
+++ b/media/mojo/interfaces/audio_decoder_config_struct_traits_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/macros.h"
 #include "media/base/audio_decoder_config.h"
 #include "media/base/media_util.h"
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace media {
diff --git a/media/mojo/interfaces/jpeg_decode_accelerator.mojom b/media/mojo/interfaces/jpeg_decode_accelerator.mojom
index a07f276..3112c6b 100644
--- a/media/mojo/interfaces/jpeg_decode_accelerator.mojom
+++ b/media/mojo/interfaces/jpeg_decode_accelerator.mojom
@@ -5,7 +5,7 @@
 module media.mojom;
 
 import "media/mojo/interfaces/media_types.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
 // Decode errors (see media/video/jpeg_decode_accelerator.h).
@@ -25,7 +25,7 @@
   handle<shared_buffer> memory_handle;
   uint32 size;
   int64 offset;
-  mojo.common.mojom.TimeDelta timestamp;
+  mojo_base.mojom.TimeDelta timestamp;
   string key_id;
   string iv;
   array<SubsampleEntry> subsamples;
diff --git a/media/mojo/interfaces/jpeg_decode_accelerator_typemap_traits.cc b/media/mojo/interfaces/jpeg_decode_accelerator_typemap_traits.cc
index afaec30..e1fd29b 100644
--- a/media/mojo/interfaces/jpeg_decode_accelerator_typemap_traits.cc
+++ b/media/mojo/interfaces/jpeg_decode_accelerator_typemap_traits.cc
@@ -6,7 +6,7 @@
 
 #include "base/logging.h"
 #include "media/base/ipc/media_param_traits_macros.h"
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
 namespace mojo {
diff --git a/media/mojo/interfaces/jpeg_encode_accelerator.mojom b/media/mojo/interfaces/jpeg_encode_accelerator.mojom
new file mode 100644
index 0000000..0c8018e
--- /dev/null
+++ b/media/mojo/interfaces/jpeg_encode_accelerator.mojom
@@ -0,0 +1,46 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module media.mojom;
+
+import "media/mojo/interfaces/media_types.mojom";
+
+// Encode errors (see media/video/jpeg_encode_accelerator.h).
+enum EncodeStatus {
+  ENCODE_OK,
+  HW_JPEG_ENCODE_NOT_SUPPORTED,
+  THREAD_CREATION_FAILED,
+  INVALID_ARGUMENT,
+  INACCESSIBLE_OUTPUT_BUFFER,
+  PARSE_IMAGE_FAILED,
+  PLATFORM_FAILURE,
+};
+
+// GPU process interface exposed to the browser for encoding JPEG images.
+interface JpegEncodeAccelerator {
+  // Initializes the JPEG encoder. Should be called once per encoder
+  // construction and before using EncodeWithFD(). This call returns true if
+  // initialization is successful.
+  Initialize() => (bool success);
+
+  // Encodes the given buffer that contains one I420 image.
+  // |input_fd| and |output_fd| are file descriptors of shared memory.
+  // The image is encoded from memory of |input_fd|
+  // with size |input_buffer_size|. The output buffer is associated with
+  // |buffer_id| and the dimension of I420 image is |coded_size_width| and
+  // |coded_size_height|.
+  // |exif_fd| is the shared memory buffer, with |exif_buffer_size| as size,
+  // containing Exif data which will be put onto APP1 segment in the output
+  // JPEG image.
+  // Encoded JPEG image will be put onto memory associated with |output_fd|
+  // with allocated size |output_buffer_size|.
+  // Returns |buffer_id| and |error| in a callback to notify the
+  // encode status. |buffer_id| is the id of |output_buffer| and |status| is the
+  // status code. |encoded_buffer_size| is the actual size of the encoded JPEG.
+  EncodeWithFD(int32 buffer_id, handle input_fd, uint32 input_buffer_size,
+               int32 coded_size_width, int32 coded_size_height,
+               handle exif_fd, uint32 exif_buffer_size,
+               handle output_fd, uint32 output_buffer_size)
+      => (int32 buffer_id, uint32 encoded_buffer_size, EncodeStatus status);
+};
diff --git a/media/mojo/interfaces/jpeg_encode_accelerator.typemap b/media/mojo/interfaces/jpeg_encode_accelerator.typemap
new file mode 100644
index 0000000..18148b0
--- /dev/null
+++ b/media/mojo/interfaces/jpeg_encode_accelerator.typemap
@@ -0,0 +1,24 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom = "//media/mojo/interfaces/jpeg_encode_accelerator.mojom"
+
+public_headers = [ "//media/video/jpeg_encode_accelerator.h" ]
+
+traits_headers =
+    [ "//media/mojo/interfaces/jpeg_encode_accelerator_typemap_traits.h" ]
+
+sources = [
+  "//media/mojo/interfaces/jpeg_encode_accelerator_typemap_traits.cc",
+]
+
+deps = [
+  "//base",
+  "//media",
+  "//media/base/ipc",
+  "//mojo/common:struct_traits",
+]
+
+type_mappings =
+    [ "media.mojom.EncodeStatus=media::JpegEncodeAccelerator::Status" ]
diff --git a/media/mojo/interfaces/jpeg_encode_accelerator_typemap_traits.cc b/media/mojo/interfaces/jpeg_encode_accelerator_typemap_traits.cc
new file mode 100644
index 0000000..ba38fd1
--- /dev/null
+++ b/media/mojo/interfaces/jpeg_encode_accelerator_typemap_traits.cc
@@ -0,0 +1,67 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/mojo/interfaces/jpeg_encode_accelerator_typemap_traits.h"
+
+#include "base/logging.h"
+
+namespace mojo {
+
+// static
+media::mojom::EncodeStatus
+EnumTraits<media::mojom::EncodeStatus, media::JpegEncodeAccelerator::Status>::
+    ToMojom(media::JpegEncodeAccelerator::Status status) {
+  switch (status) {
+    case media::JpegEncodeAccelerator::ENCODE_OK:
+      return media::mojom::EncodeStatus::ENCODE_OK;
+    case media::JpegEncodeAccelerator::HW_JPEG_ENCODE_NOT_SUPPORTED:
+      return media::mojom::EncodeStatus::HW_JPEG_ENCODE_NOT_SUPPORTED;
+    case media::JpegEncodeAccelerator::THREAD_CREATION_FAILED:
+      return media::mojom::EncodeStatus::THREAD_CREATION_FAILED;
+    case media::JpegEncodeAccelerator::INVALID_ARGUMENT:
+      return media::mojom::EncodeStatus::INVALID_ARGUMENT;
+    case media::JpegEncodeAccelerator::INACCESSIBLE_OUTPUT_BUFFER:
+      return media::mojom::EncodeStatus::INACCESSIBLE_OUTPUT_BUFFER;
+    case media::JpegEncodeAccelerator::PARSE_IMAGE_FAILED:
+      return media::mojom::EncodeStatus::PARSE_IMAGE_FAILED;
+    case media::JpegEncodeAccelerator::PLATFORM_FAILURE:
+      return media::mojom::EncodeStatus::PLATFORM_FAILURE;
+  }
+  NOTREACHED();
+  return media::mojom::EncodeStatus::ENCODE_OK;
+}
+
+// static
+bool EnumTraits<media::mojom::EncodeStatus,
+                media::JpegEncodeAccelerator::Status>::
+    FromMojom(media::mojom::EncodeStatus status,
+              media::JpegEncodeAccelerator::Status* out) {
+  switch (status) {
+    case media::mojom::EncodeStatus::ENCODE_OK:
+      *out = media::JpegEncodeAccelerator::Status::ENCODE_OK;
+      return true;
+    case media::mojom::EncodeStatus::HW_JPEG_ENCODE_NOT_SUPPORTED:
+      *out = media::JpegEncodeAccelerator::Status::HW_JPEG_ENCODE_NOT_SUPPORTED;
+      return true;
+    case media::mojom::EncodeStatus::THREAD_CREATION_FAILED:
+      *out = media::JpegEncodeAccelerator::Status::THREAD_CREATION_FAILED;
+      return true;
+    case media::mojom::EncodeStatus::INVALID_ARGUMENT:
+      *out = media::JpegEncodeAccelerator::Status::INVALID_ARGUMENT;
+      return true;
+    case media::mojom::EncodeStatus::INACCESSIBLE_OUTPUT_BUFFER:
+      *out = media::JpegEncodeAccelerator::Status::INACCESSIBLE_OUTPUT_BUFFER;
+      return true;
+    case media::mojom::EncodeStatus::PARSE_IMAGE_FAILED:
+      *out = media::JpegEncodeAccelerator::Status::PARSE_IMAGE_FAILED;
+      return true;
+    case media::mojom::EncodeStatus::PLATFORM_FAILURE:
+      *out = media::JpegEncodeAccelerator::Status::PLATFORM_FAILURE;
+      return true;
+  }
+  NOTREACHED();
+  return false;
+}
+
+}  // namespace mojo
diff --git a/media/mojo/interfaces/jpeg_encode_accelerator_typemap_traits.h b/media/mojo/interfaces/jpeg_encode_accelerator_typemap_traits.h
new file mode 100644
index 0000000..6257881
--- /dev/null
+++ b/media/mojo/interfaces/jpeg_encode_accelerator_typemap_traits.h
@@ -0,0 +1,25 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_MOJO_INTERFACES_JPEG_ENCODE_ACCELERATOR_TYPEMAP_TRAITS_H_
+#define MEDIA_MOJO_INTERFACES_JPEG_ENCODE_ACCELERATOR_TYPEMAP_TRAITS_H_
+
+#include "media/mojo/interfaces/jpeg_encode_accelerator.mojom.h"
+#include "media/video/jpeg_encode_accelerator.h"
+
+namespace mojo {
+
+template <>
+struct EnumTraits<media::mojom::EncodeStatus,
+                  media::JpegEncodeAccelerator::Status> {
+  static media::mojom::EncodeStatus ToMojom(
+      media::JpegEncodeAccelerator::Status status);
+
+  static bool FromMojom(media::mojom::EncodeStatus input,
+                        media::JpegEncodeAccelerator::Status* out);
+};
+
+}  // namespace mojo
+
+#endif  // MEDIA_MOJO_INTERFACES_JPEG_ENCODE_ACCELERATOR_TYPEMAP_TRAITS_H_
diff --git a/media/mojo/interfaces/media_metrics_provider.mojom b/media/mojo/interfaces/media_metrics_provider.mojom
index 90c9319..570a58c 100644
--- a/media/mojo/interfaces/media_metrics_provider.mojom
+++ b/media/mojo/interfaces/media_metrics_provider.mojom
@@ -7,7 +7,7 @@
 import "media/mojo/interfaces/media_types.mojom";
 import "media/mojo/interfaces/video_decode_stats_recorder.mojom";
 import "media/mojo/interfaces/watch_time_recorder.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 import "url/mojom/origin.mojom";
 
@@ -28,9 +28,9 @@
 
   // Setters for various one-time lazily generated metrics or properties.
   SetIsEME();
-  SetTimeToMetadata(mojo.common.mojom.TimeDelta elapsed);
-  SetTimeToFirstFrame(mojo.common.mojom.TimeDelta elapsed);
-  SetTimeToPlayReady(mojo.common.mojom.TimeDelta elapsed);
+  SetTimeToMetadata(mojo_base.mojom.TimeDelta elapsed);
+  SetTimeToFirstFrame(mojo_base.mojom.TimeDelta elapsed);
+  SetTimeToPlayReady(mojo_base.mojom.TimeDelta elapsed);
 
   // Creates a WatchTimeRecorder instance using |properties|. If any of those
   // properties changes, a new recorder should be requested.
diff --git a/media/mojo/interfaces/media_types.mojom b/media/mojo/interfaces/media_types.mojom
index 4382a9e..552fba8 100644
--- a/media/mojo/interfaces/media_types.mojom
+++ b/media/mojo/interfaces/media_types.mojom
@@ -5,7 +5,7 @@
 module media.mojom;
 
 import "gpu/ipc/common/mailbox_holder.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "mojo/common/values.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
@@ -128,7 +128,7 @@
   ChannelLayout channel_layout;
   int32 samples_per_second;
   array<uint8> extra_data;
-  mojo.common.mojom.TimeDelta seek_preroll;
+  mojo_base.mojom.TimeDelta seek_preroll;
   int32 codec_delay;
   EncryptionScheme encryption_scheme;
 };
@@ -164,8 +164,8 @@
 
 // This defines a mojo transport format for media::DecoderBuffer.
 struct DecoderBuffer {
-  mojo.common.mojom.TimeDelta timestamp;
-  mojo.common.mojom.TimeDelta duration;
+  mojo_base.mojom.TimeDelta timestamp;
+  mojo_base.mojom.TimeDelta duration;
 
   // Whether the buffer is an end-of-stream (EOS) buffer.
   bool is_end_of_stream;
@@ -186,8 +186,8 @@
   DecryptConfig? decrypt_config;
 
   // These fields indicate the amount of data to discard after decoding.
-  mojo.common.mojom.TimeDelta front_discard;
-  mojo.common.mojom.TimeDelta back_discard;
+  mojo_base.mojom.TimeDelta front_discard;
+  mojo_base.mojom.TimeDelta back_discard;
 };
 
 // This defines a mojo transport format for media::AudioBuffer.
@@ -211,7 +211,7 @@
   bool end_of_stream;
 
   // Timestamp in microseconds of the first frame.
-  mojo.common.mojom.TimeDelta timestamp;
+  mojo_base.mojom.TimeDelta timestamp;
 
   // Channel data. Will be empty for EOS buffers.
   array<uint8> data;
@@ -232,7 +232,7 @@
   gfx.mojom.Size natural_size;
 
   // Timestamp in microseconds of the associated frame.
-  mojo.common.mojom.TimeDelta timestamp;
+  mojo_base.mojom.TimeDelta timestamp;
 
   // Contents of the video frame (or EOS marker).
   VideoFrameData data;
diff --git a/media/mojo/interfaces/renderer.mojom b/media/mojo/interfaces/renderer.mojom
index c433401..f8c04b1 100644
--- a/media/mojo/interfaces/renderer.mojom
+++ b/media/mojo/interfaces/renderer.mojom
@@ -6,7 +6,7 @@
 
 import "media/mojo/interfaces/demuxer_stream.mojom";
 import "media/mojo/interfaces/media_types.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "mojo/common/unguessable_token.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 import "url/mojom/url.mojom";
@@ -26,7 +26,7 @@
   Flush() => ();
 
   // Starts rendering from |time|.
-  StartPlayingFrom(mojo.common.mojom.TimeDelta time);
+  StartPlayingFrom(mojo_base.mojom.TimeDelta time);
 
   // Updates the current playback rate. The default playback rate should be 1.
   SetPlaybackRate(double playback_rate);
@@ -57,9 +57,9 @@
   //     buffered by the audio hardware.
   // |capture_time| is monotonic clock time at which the times were captured.
   // |max_time| must be greater or equal to |time|.
-  OnTimeUpdate(mojo.common.mojom.TimeDelta time,
-               mojo.common.mojom.TimeDelta max_time,
-               mojo.common.mojom.TimeTicks capture_time);
+  OnTimeUpdate(mojo_base.mojom.TimeDelta time,
+               mojo_base.mojom.TimeDelta max_time,
+               mojo_base.mojom.TimeTicks capture_time);
 
   // Called to report buffering state changes, see media_types.mojom.
   OnBufferingStateChange(BufferingState state);
@@ -93,5 +93,5 @@
 
   // Executed the first time the metadata is updated, and whenever the duration
   // changes.
-  OnDurationChange(mojo.common.mojom.TimeDelta duration);
+  OnDurationChange(mojo_base.mojom.TimeDelta duration);
 };
diff --git a/media/mojo/interfaces/typemaps.gni b/media/mojo/interfaces/typemaps.gni
index 61e7af6..a7627bea 100644
--- a/media/mojo/interfaces/typemaps.gni
+++ b/media/mojo/interfaces/typemaps.gni
@@ -12,6 +12,7 @@
   "//media/mojo/interfaces/encryption_scheme.typemap",
   "//media/mojo/interfaces/hdr_metadata.typemap",
   "//media/mojo/interfaces/jpeg_decode_accelerator.typemap",
+  "//media/mojo/interfaces/jpeg_encode_accelerator.typemap",
   "//media/mojo/interfaces/media_types.typemap",
   "//media/mojo/interfaces/pipeline_statistics.typemap",
   "//media/mojo/interfaces/video_color_space.typemap",
diff --git a/media/mojo/interfaces/video_encode_accelerator.mojom b/media/mojo/interfaces/video_encode_accelerator.mojom
index da1d54d6..d2846b0 100644
--- a/media/mojo/interfaces/video_encode_accelerator.mojom
+++ b/media/mojo/interfaces/video_encode_accelerator.mojom
@@ -5,7 +5,7 @@
 module media.mojom;
 
 import "media/mojo/interfaces/media_types.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
 // This file is the Mojo version of the media::VideoEncodeAccelerator interface
@@ -70,7 +70,7 @@
                           uint32 output_buffer_size);
 
   BitstreamBufferReady(int32 bitstream_buffer_id, uint32 payload_size,
-                       bool key_frame, mojo.common.mojom.TimeDelta timestamp);
+                       bool key_frame, mojo_base.mojom.TimeDelta timestamp);
 
   NotifyError(VideoEncodeAccelerator.Error error);
 };
diff --git a/media/mojo/interfaces/video_frame_struct_traits.cc b/media/mojo/interfaces/video_frame_struct_traits.cc
index 8390938c..b6285b2 100644
--- a/media/mojo/interfaces/video_frame_struct_traits.cc
+++ b/media/mojo/interfaces/video_frame_struct_traits.cc
@@ -9,7 +9,7 @@
 
 #include "base/logging.h"
 #include "media/mojo/common/mojo_shared_buffer_video_frame.h"
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 
 namespace mojo {
 
diff --git a/media/mojo/interfaces/watch_time_recorder.mojom b/media/mojo/interfaces/watch_time_recorder.mojom
index b2a8d4bb8..e0258df 100644
--- a/media/mojo/interfaces/watch_time_recorder.mojom
+++ b/media/mojo/interfaces/watch_time_recorder.mojom
@@ -5,7 +5,7 @@
 module media.mojom;
 
 import "media/mojo/interfaces/media_types.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 import "url/mojom/origin.mojom";
 
@@ -44,7 +44,7 @@
   // not a delta since the last call. Any necessary relative processing should
   // be handled prior to calling this method. As described in WatchTimeReporter,
   // |watch_time| is the elapsed media (not wall clock) time for |key|.
-  RecordWatchTime(WatchTimeKey key, mojo.common.mojom.TimeDelta watch_time);
+  RecordWatchTime(WatchTimeKey key, mojo_base.mojom.TimeDelta watch_time);
 
   // Request finalization (recording to UMA) for the given keys. If no keys are
   // specified, all currently held keys will be finalized.
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn
index 5c96e4b..c4ce9f7f 100644
--- a/media/mojo/services/BUILD.gn
+++ b/media/mojo/services/BUILD.gn
@@ -47,6 +47,8 @@
     "mojo_demuxer_stream_adapter.h",
     "mojo_jpeg_decode_accelerator_service.cc",
     "mojo_jpeg_decode_accelerator_service.h",
+    "mojo_jpeg_encode_accelerator_service.cc",
+    "mojo_jpeg_encode_accelerator_service.h",
     "mojo_media_client.cc",
     "mojo_media_client.h",
     "mojo_media_log.cc",
diff --git a/media/mojo/services/mojo_jpeg_encode_accelerator_service.cc b/media/mojo/services/mojo_jpeg_encode_accelerator_service.cc
new file mode 100644
index 0000000..25b6784
--- /dev/null
+++ b/media/mojo/services/mojo_jpeg_encode_accelerator_service.cc
@@ -0,0 +1,209 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/mojo/services/mojo_jpeg_encode_accelerator_service.h"
+
+#include <stdint.h>
+
+#include <memory>
+#include <utility>
+
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/shared_memory.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
+#include "media/base/bind_to_current_loop.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace {
+
+#if defined(OS_CHROMEOS)
+const int kJpegQuality = 90;
+#endif
+
+}  // namespace
+
+namespace media {
+
+// static
+void MojoJpegEncodeAcceleratorService::Create(
+    mojom::JpegEncodeAcceleratorRequest request) {
+  auto* jpeg_encoder = new MojoJpegEncodeAcceleratorService();
+  mojo::MakeStrongBinding(base::WrapUnique(jpeg_encoder), std::move(request));
+}
+
+MojoJpegEncodeAcceleratorService::MojoJpegEncodeAcceleratorService()
+    : accelerator_factory_functions_(
+          GpuJpegEncodeAcceleratorFactory::GetAcceleratorFactories()) {}
+
+MojoJpegEncodeAcceleratorService::~MojoJpegEncodeAcceleratorService() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+}
+
+void MojoJpegEncodeAcceleratorService::VideoFrameReady(
+    int32_t bitstream_buffer_id,
+    size_t encoded_picture_size) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  NotifyEncodeStatus(bitstream_buffer_id, encoded_picture_size,
+                     ::media::JpegEncodeAccelerator::Status::ENCODE_OK);
+}
+
+void MojoJpegEncodeAcceleratorService::NotifyError(
+    int32_t bitstream_buffer_id,
+    ::media::JpegEncodeAccelerator::Status error) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  NotifyEncodeStatus(bitstream_buffer_id, 0, error);
+}
+
+void MojoJpegEncodeAcceleratorService::Initialize(InitializeCallback callback) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  // When adding non-chromeos platforms, VideoCaptureGpuJpegEncoder::Initialize
+  // needs to be updated.
+
+  std::unique_ptr<::media::JpegEncodeAccelerator> accelerator;
+  for (const auto& create_jea_function : accelerator_factory_functions_) {
+    std::unique_ptr<::media::JpegEncodeAccelerator> tmp_accelerator =
+        create_jea_function.Run(base::ThreadTaskRunnerHandle::Get());
+    if (tmp_accelerator &&
+        tmp_accelerator->Initialize(this) ==
+            ::media::JpegEncodeAccelerator::Status::ENCODE_OK) {
+      accelerator = std::move(tmp_accelerator);
+      break;
+    }
+  }
+
+  if (!accelerator) {
+    DLOG(ERROR) << "JPEG accelerator initialization failed";
+    std::move(callback).Run(false);
+    return;
+  }
+
+  accelerator_ = std::move(accelerator);
+  std::move(callback).Run(true);
+}
+
+void MojoJpegEncodeAcceleratorService::EncodeWithFD(
+    int32_t buffer_id,
+    mojo::ScopedHandle input_handle,
+    uint32_t input_buffer_size,
+    int32_t coded_size_width,
+    int32_t coded_size_height,
+    mojo::ScopedHandle exif_handle,
+    uint32_t exif_buffer_size,
+    mojo::ScopedHandle output_handle,
+    uint32_t output_buffer_size,
+    EncodeWithFDCallback callback) {
+#if defined(OS_CHROMEOS)
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  base::PlatformFile input_fd;
+  base::PlatformFile exif_fd;
+  base::PlatformFile output_fd;
+  MojoResult result;
+
+  if (coded_size_width <= 0 || coded_size_height <= 0) {
+    std::move(callback).Run(
+        buffer_id, 0, ::media::JpegEncodeAccelerator::Status::INVALID_ARGUMENT);
+    return;
+  }
+
+  result = mojo::UnwrapPlatformFile(std::move(input_handle), &input_fd);
+  if (result != MOJO_RESULT_OK) {
+    std::move(callback).Run(
+        buffer_id, 0, ::media::JpegEncodeAccelerator::Status::PLATFORM_FAILURE);
+    return;
+  }
+
+  result = mojo::UnwrapPlatformFile(std::move(exif_handle), &exif_fd);
+  if (result != MOJO_RESULT_OK) {
+    std::move(callback).Run(
+        buffer_id, 0, ::media::JpegEncodeAccelerator::Status::PLATFORM_FAILURE);
+    return;
+  }
+
+  result = mojo::UnwrapPlatformFile(std::move(output_handle), &output_fd);
+  if (result != MOJO_RESULT_OK) {
+    std::move(callback).Run(
+        buffer_id, 0, ::media::JpegEncodeAccelerator::Status::PLATFORM_FAILURE);
+    return;
+  }
+
+  base::UnguessableToken input_guid = base::UnguessableToken::Create();
+  base::UnguessableToken exif_guid = base::UnguessableToken::Create();
+  base::UnguessableToken output_guid = base::UnguessableToken::Create();
+  base::SharedMemoryHandle input_shm_handle(
+      base::FileDescriptor(input_fd, true), 0u, input_guid);
+  base::SharedMemoryHandle exif_shm_handle(base::FileDescriptor(exif_fd, true),
+                                           0u, exif_guid);
+  base::SharedMemoryHandle output_shm_handle(
+      base::FileDescriptor(output_fd, true), 0u, output_guid);
+
+  media::BitstreamBuffer output_buffer(buffer_id, output_shm_handle,
+                                       output_buffer_size);
+  media::BitstreamBuffer exif_buffer(buffer_id, exif_shm_handle,
+                                     exif_buffer_size);
+  gfx::Size coded_size(coded_size_width, coded_size_height);
+
+  if (encode_cb_map_.find(buffer_id) != encode_cb_map_.end()) {
+    mojo::ReportBadMessage("buffer_id is already registered in encode_cb_map_");
+    return;
+  }
+  encode_cb_map_.emplace(buffer_id, std::move(callback));
+
+  auto input_shm = std::make_unique<base::SharedMemory>(input_shm_handle, true);
+  if (!input_shm->Map(input_buffer_size)) {
+    DLOG(ERROR) << "Could not map input shared memory for buffer id "
+                << buffer_id;
+    NotifyEncodeStatus(
+        buffer_id, 0, ::media::JpegEncodeAccelerator::Status::PLATFORM_FAILURE);
+    return;
+  }
+
+  uint8_t* input_shm_memory = static_cast<uint8_t*>(input_shm->memory());
+  scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalSharedMemory(
+      PIXEL_FORMAT_I420,      // format
+      coded_size,             // coded_size
+      gfx::Rect(coded_size),  // visible_rect
+      coded_size,             // natural_size
+      input_shm_memory,       // data
+      input_buffer_size,      // data_size
+      input_shm_handle,       // handle
+      0,                      // data_offset
+      base::TimeDelta());     // timestamp
+  if (!frame.get()) {
+    LOG(ERROR) << "Could not create VideoFrame for buffer id " << buffer_id;
+    NotifyEncodeStatus(
+        buffer_id, 0, ::media::JpegEncodeAccelerator::Status::PLATFORM_FAILURE);
+    return;
+  }
+  // Keep |input_shm| referenced until |frame| is destructed.
+  frame->AddDestructionObserver(base::BindOnce(
+      base::DoNothing::Once<std::unique_ptr<base::SharedMemory>>(),
+      base::Passed(&input_shm)));
+
+  DCHECK(accelerator_);
+  accelerator_->Encode(frame, kJpegQuality, &exif_buffer, output_buffer);
+#else
+  NOTREACHED();
+#endif
+}
+
+void MojoJpegEncodeAcceleratorService::NotifyEncodeStatus(
+    int32_t bitstream_buffer_id,
+    size_t encoded_picture_size,
+    ::media::JpegEncodeAccelerator::Status error) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  auto iter = encode_cb_map_.find(bitstream_buffer_id);
+  DCHECK(iter != encode_cb_map_.end());
+  EncodeWithFDCallback encode_cb = std::move(iter->second);
+  encode_cb_map_.erase(iter);
+  std::move(encode_cb).Run(bitstream_buffer_id, encoded_picture_size, error);
+}
+
+}  // namespace media
diff --git a/media/mojo/services/mojo_jpeg_encode_accelerator_service.h b/media/mojo/services/mojo_jpeg_encode_accelerator_service.h
new file mode 100644
index 0000000..7603f18a
--- /dev/null
+++ b/media/mojo/services/mojo_jpeg_encode_accelerator_service.h
@@ -0,0 +1,77 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_MOJO_SERVICES_MOJO_JPEG_ENCODE_ACCELERATOR_SERVICE_H_
+#define MEDIA_MOJO_SERVICES_MOJO_JPEG_ENCODE_ACCELERATOR_SERVICE_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "media/gpu/gpu_jpeg_encode_accelerator_factory.h"
+#include "media/mojo/interfaces/jpeg_encode_accelerator.mojom.h"
+#include "media/mojo/services/media_mojo_export.h"
+#include "media/video/jpeg_encode_accelerator.h"
+
+namespace media {
+
+// Implementation of a mojom::JpegEncodeAccelerator which runs in the GPU
+// process, and wraps a JpegEncodeAccelerator.
+class MEDIA_MOJO_EXPORT MojoJpegEncodeAcceleratorService
+    : public mojom::JpegEncodeAccelerator,
+      public JpegEncodeAccelerator::Client {
+ public:
+  static void Create(mojom::JpegEncodeAcceleratorRequest request);
+
+  ~MojoJpegEncodeAcceleratorService() override;
+
+  // JpegEncodeAccelerator::Client implementation.
+  void VideoFrameReady(int32_t buffer_id, size_t encoded_picture_size) override;
+  void NotifyError(int32_t buffer_id,
+                   ::media::JpegEncodeAccelerator::Status status) override;
+
+ private:
+  using EncodeCallbackMap = std::unordered_map<int32_t, EncodeWithFDCallback>;
+
+  // This constructor internally calls
+  // GpuJpegEncodeAcceleratorFactory::GetAcceleratorFactories() to
+  // fill |accelerator_factory_functions_|.
+  MojoJpegEncodeAcceleratorService();
+
+  // mojom::JpegEncodeAccelerator implementation.
+  void Initialize(InitializeCallback callback) override;
+  void EncodeWithFD(int32_t buffer_id,
+                    mojo::ScopedHandle input_fd,
+                    uint32_t input_buffer_size,
+                    int32_t coded_size_width,
+                    int32_t coded_size_height,
+                    mojo::ScopedHandle exif_fd,
+                    uint32_t exif_buffer_size,
+                    mojo::ScopedHandle output_fd,
+                    uint32_t output_buffer_size,
+                    EncodeWithFDCallback callback) override;
+
+  void NotifyEncodeStatus(int32_t bitstream_buffer_id,
+                          size_t encoded_picture_size,
+                          ::media::JpegEncodeAccelerator::Status status);
+
+  const std::vector<GpuJpegEncodeAcceleratorFactory::CreateAcceleratorCB>
+      accelerator_factory_functions_;
+
+  // A map from bitstream_buffer_id to EncodeCallback.
+  EncodeCallbackMap encode_cb_map_;
+
+  std::unique_ptr<::media::JpegEncodeAccelerator> accelerator_;
+
+  THREAD_CHECKER(thread_checker_);
+
+  DISALLOW_COPY_AND_ASSIGN(MojoJpegEncodeAcceleratorService);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_MOJO_SERVICES_MOJO_JPEG_ENCODE_ACCELERATOR_SERVICE_H_
diff --git a/media/video/BUILD.gn b/media/video/BUILD.gn
index c5aacea..863d98e 100644
--- a/media/video/BUILD.gn
+++ b/media/video/BUILD.gn
@@ -29,6 +29,7 @@
     "half_float_maker.h",
     "jpeg_decode_accelerator.cc",
     "jpeg_decode_accelerator.h",
+    "jpeg_encode_accelerator.cc",
     "jpeg_encode_accelerator.h",
     "picture.cc",
     "picture.h",
diff --git a/media/video/jpeg_encode_accelerator.cc b/media/video/jpeg_encode_accelerator.cc
new file mode 100644
index 0000000..91b2bf2
--- /dev/null
+++ b/media/video/jpeg_encode_accelerator.cc
@@ -0,0 +1,11 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/video/jpeg_encode_accelerator.h"
+
+namespace media {
+
+JpegEncodeAccelerator::~JpegEncodeAccelerator() = default;
+
+}  // namespace media
diff --git a/media/video/jpeg_encode_accelerator.h b/media/video/jpeg_encode_accelerator.h
index 313509c..f766ec9 100644
--- a/media/video/jpeg_encode_accelerator.h
+++ b/media/video/jpeg_encode_accelerator.h
@@ -72,7 +72,7 @@
   // call may asynchronously free system resources, but its client-visible
   // effects are synchronous. After destructor returns, no more callbacks
   // will be made on the client.
-  virtual ~JpegEncodeAccelerator() {}
+  virtual ~JpegEncodeAccelerator() = 0;
 
   // Initializes the JPEG encoder. Should be called once per encoder
   // construction. This call is synchronous and returns ENCODE_OK iff
diff --git a/mojo/common/BUILD.gn b/mojo/common/BUILD.gn
index d36b56e6..a651d60 100644
--- a/mojo/common/BUILD.gn
+++ b/mojo/common/BUILD.gn
@@ -18,7 +18,6 @@
     "process_id.mojom",
     "text_direction.mojom",
     "thread_priority.mojom",
-    "time.mojom",
     "unguessable_token.mojom",
     "values.mojom",
     "version.mojom",
@@ -95,7 +94,6 @@
   sources = [
     "common_custom_types_struct_traits.cc",
     "common_custom_types_struct_traits.h",
-    "time_struct_traits.h",
   ]
   deps = [
     ":common_custom_types_shared_cpp_sources",
diff --git a/mojo/common/common_custom_types_unittest.cc b/mojo/common/common_custom_types_unittest.cc
index e4eec32..79282f9 100644
--- a/mojo/common/common_custom_types_unittest.cc
+++ b/mojo/common/common_custom_types_unittest.cc
@@ -76,30 +76,6 @@
   mojo::Binding<TestUnguessableToken> binding_;
 };
 
-class TestTimeImpl : public TestTime {
- public:
-  explicit TestTimeImpl(TestTimeRequest request)
-      : binding_(this, std::move(request)) {}
-
-  // TestTime implementation:
-  void BounceTime(base::Time in, BounceTimeCallback callback) override {
-    std::move(callback).Run(in);
-  }
-
-  void BounceTimeDelta(base::TimeDelta in,
-                       BounceTimeDeltaCallback callback) override {
-    std::move(callback).Run(in);
-  }
-
-  void BounceTimeTicks(base::TimeTicks in,
-                       BounceTimeTicksCallback callback) override {
-    std::move(callback).Run(in);
-  }
-
- private:
-  mojo::Binding<TestTime> binding_;
-};
-
 class TestValueImpl : public TestValue {
  public:
   explicit TestValueImpl(TestValueRequest request)
@@ -175,45 +151,6 @@
   EXPECT_EQ(pid, out_pid);
 }
 
-TEST_F(CommonCustomTypesTest, Time) {
-  base::RunLoop run_loop;
-
-  TestTimePtr ptr;
-  TestTimeImpl impl(MakeRequest(&ptr));
-
-  base::Time t = base::Time::Now();
-
-  ptr->BounceTime(t, ExpectResponse(&t, run_loop.QuitClosure()));
-
-  run_loop.Run();
-}
-
-TEST_F(CommonCustomTypesTest, TimeDelta) {
-  base::RunLoop run_loop;
-
-  TestTimePtr ptr;
-  TestTimeImpl impl(MakeRequest(&ptr));
-
-  base::TimeDelta t = base::TimeDelta::FromDays(123);
-
-  ptr->BounceTimeDelta(t, ExpectResponse(&t, run_loop.QuitClosure()));
-
-  run_loop.Run();
-}
-
-TEST_F(CommonCustomTypesTest, TimeTicks) {
-  base::RunLoop run_loop;
-
-  TestTimePtr ptr;
-  TestTimeImpl impl(MakeRequest(&ptr));
-
-  base::TimeTicks t = base::TimeTicks::Now();
-
-  ptr->BounceTimeTicks(t, ExpectResponse(&t, run_loop.QuitClosure()));
-
-  run_loop.Run();
-}
-
 TEST_F(CommonCustomTypesTest, Value) {
   TestValuePtr ptr;
   TestValueImpl impl(MakeRequest(&ptr));
diff --git a/mojo/common/test_common_custom_types.mojom b/mojo/common/test_common_custom_types.mojom
index 5ff47c73..c9c20a3 100644
--- a/mojo/common/test_common_custom_types.mojom
+++ b/mojo/common/test_common_custom_types.mojom
@@ -5,7 +5,6 @@
 module mojo.common.test;
 
 import "mojo/common/text_direction.mojom";
-import "mojo/common/time.mojom";
 import "mojo/common/unguessable_token.mojom";
 import "mojo/common/values.mojom";
 
@@ -14,14 +13,6 @@
       => (mojo.common.mojom.UnguessableToken out);
 };
 
-interface TestTime {
-  BounceTime(mojo.common.mojom.Time time) => (mojo.common.mojom.Time time);
-  BounceTimeDelta(mojo.common.mojom.TimeDelta time_delta)
-      => (mojo.common.mojom.TimeDelta time_delta);
-  BounceTimeTicks(mojo.common.mojom.TimeTicks time_ticks)
-      => (mojo.common.mojom.TimeTicks time_ticks);
-};
-
 interface TestValue {
   [Sync]
   BounceDictionaryValue(mojo.common.mojom.DictionaryValue in)
diff --git a/mojo/common/time.typemap b/mojo/common/time.typemap
deleted file mode 100644
index 20661f6..0000000
--- a/mojo/common/time.typemap
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-mojom = "//mojo/common/time.mojom"
-public_headers = [ "//base/time/time.h" ]
-traits_headers = [ "//mojo/common/time_struct_traits.h" ]
-public_deps = [
-  "//base",
-  "//mojo/common:struct_traits",
-]
-
-type_mappings = [
-  "mojo.common.mojom.Time=base::Time[copyable_pass_by_value]",
-  "mojo.common.mojom.TimeDelta=base::TimeDelta[copyable_pass_by_value]",
-  "mojo.common.mojom.TimeTicks=base::TimeTicks[copyable_pass_by_value]",
-]
diff --git a/mojo/common/time_struct_traits.h b/mojo/common/time_struct_traits.h
deleted file mode 100644
index b480edb..0000000
--- a/mojo/common/time_struct_traits.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_COMMON_TIME_STRUCT_TRAITS_H_
-#define MOJO_COMMON_TIME_STRUCT_TRAITS_H_
-
-#include "base/time/time.h"
-#include "mojo/common/time.mojom-shared.h"
-
-namespace mojo {
-
-template <>
-struct StructTraits<common::mojom::TimeDataView, base::Time> {
-  static int64_t internal_value(const base::Time& time) {
-    return time.since_origin().InMicroseconds();
-  }
-
-  static bool Read(common::mojom::TimeDataView data, base::Time* time) {
-    *time =
-        base::Time() + base::TimeDelta::FromMicroseconds(data.internal_value());
-    return true;
-  }
-};
-
-template <>
-struct StructTraits<common::mojom::TimeDeltaDataView, base::TimeDelta> {
-  static int64_t microseconds(const base::TimeDelta& delta) {
-    return delta.InMicroseconds();
-  }
-
-  static bool Read(common::mojom::TimeDeltaDataView data,
-                   base::TimeDelta* delta) {
-    *delta = base::TimeDelta::FromMicroseconds(data.microseconds());
-    return true;
-  }
-};
-
-template <>
-struct StructTraits<common::mojom::TimeTicksDataView, base::TimeTicks> {
-  static int64_t internal_value(const base::TimeTicks& time) {
-    return time.since_origin().InMicroseconds();
-  }
-
-  static bool Read(common::mojom::TimeTicksDataView data,
-                   base::TimeTicks* time) {
-    *time = base::TimeTicks() +
-            base::TimeDelta::FromMicroseconds(data.internal_value());
-    return true;
-  }
-};
-
-}  // namespace mojo
-
-#endif  // MOJO_COMMON_TIME_STRUCT_TRAITS_H_
diff --git a/mojo/common/typemaps.gni b/mojo/common/typemaps.gni
index db85b3a..681a3f2 100644
--- a/mojo/common/typemaps.gni
+++ b/mojo/common/typemaps.gni
@@ -9,7 +9,6 @@
   "//mojo/common/read_only_buffer.typemap",
   "//mojo/common/text_direction.typemap",
   "//mojo/common/thread_priority.typemap",
-  "//mojo/common/time.typemap",
   "//mojo/common/unguessable_token.typemap",
   "//mojo/common/values.typemap",
   "//mojo/common/version.typemap",
diff --git a/mojo/public/cpp/base/BUILD.gn b/mojo/public/cpp/base/BUILD.gn
index 867495e..a266b73 100644
--- a/mojo/public/cpp/base/BUILD.gn
+++ b/mojo/public/cpp/base/BUILD.gn
@@ -50,6 +50,7 @@
     "file_unittest.cc",
     "ref_counted_memory_unittest.cc",
     "string16_unittest.cc",
+    "time_unittest.cc",
   ]
 
   public_deps = [
diff --git a/mojo/public/cpp/base/file_unittest.cc b/mojo/public/cpp/base/file_unittest.cc
index 5e6be9c6..fb3cff40 100644
--- a/mojo/public/cpp/base/file_unittest.cc
+++ b/mojo/public/cpp/base/file_unittest.cc
@@ -20,9 +20,8 @@
       base::File::FLAG_CREATE | base::File::FLAG_WRITE | base::File::FLAG_READ);
   const base::StringPiece test_content =
       "A test string to be stored in a test file";
-  file.WriteAtCurrentPos(
-      test_content.data(),
-      base::checked_cast<int>(test_content.size()));
+  file.WriteAtCurrentPos(test_content.data(),
+                         base::checked_cast<int>(test_content.size()));
 
   base::File file_out;
   ASSERT_TRUE(
@@ -30,9 +29,8 @@
   std::vector<char> content(test_content.size());
   ASSERT_TRUE(file_out.IsValid());
   ASSERT_EQ(static_cast<int>(test_content.size()),
-            file_out.Read(
-                0, content.data(),
-                base::checked_cast<int>(test_content.size())));
+            file_out.Read(0, content.data(),
+                          base::checked_cast<int>(test_content.size())));
   EXPECT_EQ(test_content,
             base::StringPiece(content.data(), test_content.size()));
 }
diff --git a/mojo/public/cpp/base/time.typemap b/mojo/public/cpp/base/time.typemap
new file mode 100644
index 0000000..b3b2e8b
--- /dev/null
+++ b/mojo/public/cpp/base/time.typemap
@@ -0,0 +1,20 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom = "//mojo/public/mojom/base/time.mojom"
+public_headers = [ "//base/time/time.h" ]
+traits_headers = [ "//mojo/public/cpp/base/time_mojom_traits.h" ]
+sources = [
+  "//mojo/public/cpp/base/time_mojom_traits.cc",
+  "//mojo/public/cpp/base/time_mojom_traits.h",
+]
+public_deps = [
+  "//base",
+]
+
+type_mappings = [
+  "mojo_base.mojom.Time=base::Time[copyable_pass_by_value]",
+  "mojo_base.mojom.TimeDelta=base::TimeDelta[copyable_pass_by_value]",
+  "mojo_base.mojom.TimeTicks=base::TimeTicks[copyable_pass_by_value]",
+]
diff --git a/mojo/public/cpp/base/time_mojom_traits.cc b/mojo/public/cpp/base/time_mojom_traits.cc
new file mode 100644
index 0000000..094df9f
--- /dev/null
+++ b/mojo/public/cpp/base/time_mojom_traits.cc
@@ -0,0 +1,50 @@
+
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/base/time_mojom_traits.h"
+
+namespace mojo {
+
+int64_t StructTraits<mojo_base::mojom::TimeDataView,
+                     base::Time>::internal_value(const base::Time& time) {
+  return time.since_origin().InMicroseconds();
+}
+
+bool StructTraits<mojo_base::mojom::TimeDataView, base::Time>::Read(
+    mojo_base::mojom::TimeDataView data,
+    base::Time* time) {
+  *time =
+      base::Time() + base::TimeDelta::FromMicroseconds(data.internal_value());
+  return true;
+}
+
+int64_t
+StructTraits<mojo_base::mojom::TimeDeltaDataView,
+             base::TimeDelta>::microseconds(const base::TimeDelta& delta) {
+  return delta.InMicroseconds();
+}
+
+bool StructTraits<mojo_base::mojom::TimeDeltaDataView, base::TimeDelta>::Read(
+    mojo_base::mojom::TimeDeltaDataView data,
+    base::TimeDelta* delta) {
+  *delta = base::TimeDelta::FromMicroseconds(data.microseconds());
+  return true;
+}
+
+int64_t
+StructTraits<mojo_base::mojom::TimeTicksDataView,
+             base::TimeTicks>::internal_value(const base::TimeTicks& time) {
+  return time.since_origin().InMicroseconds();
+}
+
+bool StructTraits<mojo_base::mojom::TimeTicksDataView, base::TimeTicks>::Read(
+    mojo_base::mojom::TimeTicksDataView data,
+    base::TimeTicks* time) {
+  *time = base::TimeTicks() +
+          base::TimeDelta::FromMicroseconds(data.internal_value());
+  return true;
+}
+
+}  // namespace mojo
\ No newline at end of file
diff --git a/mojo/public/cpp/base/time_mojom_traits.h b/mojo/public/cpp/base/time_mojom_traits.h
new file mode 100644
index 0000000..db54476
--- /dev/null
+++ b/mojo/public/cpp/base/time_mojom_traits.h
@@ -0,0 +1,42 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BASE_TIME_MOJOM_TRAITS_H_
+#define MOJO_PUBLIC_CPP_BASE_TIME_MOJOM_TRAITS_H_
+
+#include "base/component_export.h"
+#include "base/time/time.h"
+#include "mojo/public/mojom/base/time.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
+    StructTraits<mojo_base::mojom::TimeDataView, base::Time> {
+  static int64_t internal_value(const base::Time& time);
+
+  static bool Read(mojo_base::mojom::TimeDataView data, base::Time* time);
+};
+
+template <>
+struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
+    StructTraits<mojo_base::mojom::TimeDeltaDataView, base::TimeDelta> {
+  static int64_t microseconds(const base::TimeDelta& delta);
+
+  static bool Read(mojo_base::mojom::TimeDeltaDataView data,
+                   base::TimeDelta* delta);
+};
+
+template <>
+struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
+    StructTraits<mojo_base::mojom::TimeTicksDataView, base::TimeTicks> {
+  static int64_t internal_value(const base::TimeTicks& time);
+
+  static bool Read(mojo_base::mojom::TimeTicksDataView data,
+                   base::TimeTicks* time);
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BASE_TIME_MOJOM_TRAITS_H_
diff --git a/mojo/public/cpp/base/time_unittest.cc b/mojo/public/cpp/base/time_unittest.cc
new file mode 100644
index 0000000..9ab39107
--- /dev/null
+++ b/mojo/public/cpp/base/time_unittest.cc
@@ -0,0 +1,38 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/base/time_mojom_traits.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "mojo/public/mojom/base/time.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo_base {
+namespace time_unittest {
+
+TEST(TimeTest, Time) {
+  base::Time in = base::Time::Now();
+  base::Time out;
+
+  ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Time>(&in, &out));
+  EXPECT_EQ(in, out);
+}
+
+TEST(TimeTest, TimeDelta) {
+  base::TimeDelta in = base::TimeDelta::FromDays(123);
+  base::TimeDelta out;
+
+  ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::TimeDelta>(&in, &out));
+  EXPECT_EQ(in, out);
+}
+
+TEST(TimeTest, TimeTicks) {
+  base::TimeTicks in = base::TimeTicks::Now();
+  base::TimeTicks out;
+
+  ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::TimeTicks>(&in, &out));
+  EXPECT_EQ(in, out);
+}
+
+}  // namespace time_unittest
+}  // namespace mojo_base
\ No newline at end of file
diff --git a/mojo/public/cpp/base/typemaps.gni b/mojo/public/cpp/base/typemaps.gni
index 7984097..bd906f13 100644
--- a/mojo/public/cpp/base/typemaps.gni
+++ b/mojo/public/cpp/base/typemaps.gni
@@ -11,4 +11,5 @@
   "//mojo/public/cpp/base/file.typemap",
   "//mojo/public/cpp/base/file_info.typemap",
   "//mojo/public/cpp/base/file_path.typemap",
+  "//mojo/public/cpp/base/time.typemap",
 ]
diff --git a/mojo/public/mojom/base/BUILD.gn b/mojo/public/mojom/base/BUILD.gn
index 626defd..7f6ba328 100644
--- a/mojo/public/mojom/base/BUILD.gn
+++ b/mojo/public/mojom/base/BUILD.gn
@@ -14,6 +14,7 @@
     "file_path.mojom",
     "ref_counted_memory.mojom",
     "string16.mojom",
+    "time.mojom",
   ]
 
   output_prefix = "mojo_base_mojom"
diff --git a/mojo/common/time.mojom b/mojo/public/mojom/base/time.mojom
similarity index 94%
rename from mojo/common/time.mojom
rename to mojo/public/mojom/base/time.mojom
index b403bca..78cde1a1 100644
--- a/mojo/common/time.mojom
+++ b/mojo/public/mojom/base/time.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-module mojo.common.mojom;
+module mojo_base.mojom;
 
 struct Time {
   // The internal value is expressed in terms of microseconds since a fixed but
diff --git a/net/base/load_flags_list.h b/net/base/load_flags_list.h
index 76ff4fe..9b58859 100644
--- a/net/base/load_flags_list.h
+++ b/net/base/load_flags_list.h
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// This file intentionally does not have header guards, it's included
+// inside a macro to generate values. The following line silences a
+// presubmit warning that would otherwise be triggered by this:
+// no-include-guard-because-multiply-included
+
 // This is the list of load flags and their values. For the enum values,
 // include the file "net/base/load_flags.h".
 //
diff --git a/net/base/load_states_list.h b/net/base/load_states_list.h
index c4f0f87d..4e776c7 100644
--- a/net/base/load_states_list.h
+++ b/net/base/load_states_list.h
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// This file intentionally does not have header guards, it's included
+// inside a macro to generate values. The following line silences a
+// presubmit warning that would otherwise be triggered by this:
+// no-include-guard-because-multiply-included
+
 // This is the list of load states and their values. For the enum values,
 // include the file "net/base/load_states.h".
 //
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index 76a8c899..3b4d6ea 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -3,7 +3,9 @@
 // found in the LICENSE file.
 
 // This file intentionally does not have header guards, it's included
-// inside a macro to generate enum values.
+// inside a macro to generate enum values. The following line silences a
+// presubmit warning that would otherwise be triggered by this:
+// no-include-guard-because-multiply-included
 
 // This file contains the list of network errors.
 
diff --git a/net/base/net_info_source_list.h b/net/base/net_info_source_list.h
index 4277aba5..14a6496 100644
--- a/net/base/net_info_source_list.h
+++ b/net/base/net_info_source_list.h
@@ -3,7 +3,9 @@
 // found in the LICENSE file.
 
 // This file intentionally does not have header guards, it's included
-// inside a macro to generate enum values.
+// inside a macro to generate enum values. The following line silences a
+// presubmit warning that would otherwise be triggered by this:
+// no-include-guard-because-multiply-included
 
 // Flags used to request different types of information about the current state
 // of a URLRequestContext.
diff --git a/net/cert/cert_status_flags_list.h b/net/cert/cert_status_flags_list.h
index d285472..cbde71f 100644
--- a/net/cert/cert_status_flags_list.h
+++ b/net/cert/cert_status_flags_list.h
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// This file intentionally does not have header guards, it's included
+// inside a macro to generate enum values. The following line silences a
+// presubmit warning that would otherwise be triggered by this:
+// no-include-guard-because-multiply-included
+
 // This is the list of CertStatus flags and their values.
 //
 // Defines the values using a macro CERT_STATUS_FLAG,
diff --git a/net/filter/source_stream_type_list.h b/net/filter/source_stream_type_list.h
index 2a79296..cc507909 100644
--- a/net/filter/source_stream_type_list.h
+++ b/net/filter/source_stream_type_list.h
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// This file intentionally does not have header guards, it's included
+// inside a macro to generate values. The following line silences a
+// presubmit warning that would otherwise be triggered by this:
+// no-include-guard-because-multiply-included
+
 // Specifies type of filters that can be created.  Do not change the values
 // of this enum; it is preserved in a histogram.
 SOURCE_STREAM_TYPE(BROTLI)
diff --git a/net/http/http_status_code_list.h b/net/http/http_status_code_list.h
index 75c2304..53f633c 100644
--- a/net/http/http_status_code_list.h
+++ b/net/http/http_status_code_list.h
@@ -3,8 +3,10 @@
 // found in the LICENSE file.
 
 // This file intentionally does not have header guards, it's included
-// inside a macro to generate enum.
-//
+// inside a macro to generate enum. The following line silences a
+// presubmit warning that would otherwise be triggered by this:
+// no-include-guard-because-multiply-included
+
 // This file contains the list of HTTP status codes. Taken from IANA HTTP Status
 // Code Registry.
 // http://www.iana.org/assignments/http-status-codes/http-status-codes.xml
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h
index 30d1298..9f3f4bf7 100644
--- a/net/log/net_log_event_type_list.h
+++ b/net/log/net_log_event_type_list.h
@@ -4,6 +4,9 @@
 
 // NOTE: No header guards are used, since this file is intended to be expanded
 // directly into net_log.h. DO NOT include this file anywhere else.
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
 
 // In the event of a failure, a many end events will have a |net_error|
 // parameter with the integer error code associated with the failure.  Most
diff --git a/net/log/net_log_source_type_list.h b/net/log/net_log_source_type_list.h
index 103e9ad..86a07cb 100644
--- a/net/log/net_log_source_type_list.h
+++ b/net/log/net_log_source_type_list.h
@@ -4,6 +4,9 @@
 
 // NOTE: No header guards are used, since this file is intended to be expanded
 // directly within a block where the SOURCE_TYPE macro is defined.
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this:
+// no-include-guard-because-multiply-included
 
 // Used for global events which don't correspond to a particular entity.
 SOURCE_TYPE(NONE)
diff --git a/ppapi/proxy/ppapi_command_buffer_proxy.cc b/ppapi/proxy/ppapi_command_buffer_proxy.cc
index 2de3ed5..73a743e6 100644
--- a/ppapi/proxy/ppapi_command_buffer_proxy.cc
+++ b/ppapi/proxy/ppapi_command_buffer_proxy.cc
@@ -170,6 +170,11 @@
 }
 
 void PpapiCommandBufferProxy::EnsureWorkVisible() {
+  if (last_state_.error != gpu::error::kNoError)
+    return;
+
+  if (flush_info_->flush_pending)
+    FlushInternal();
   DCHECK_GE(flushed_fence_sync_release_, validated_fence_sync_release_);
   Send(new PpapiHostMsg_PPBGraphics3D_EnsureWorkVisible(
       ppapi::API_ID_PPB_GRAPHICS_3D, resource_));
diff --git a/remoting/base/chromoting_event_log_writer.h b/remoting/base/chromoting_event_log_writer.h
index 8bbb99a..d6802f72 100644
--- a/remoting/base/chromoting_event_log_writer.h
+++ b/remoting/base/chromoting_event_log_writer.h
@@ -14,7 +14,6 @@
   virtual ~ChromotingEventLogWriter(){};
 
   virtual void SetAuthToken(const std::string& auth_token) = 0;
-  virtual void SetAuthClosure(const base::Closure& closure) = 0;
   virtual void Log(const ChromotingEvent& entry) = 0;
 };
 
diff --git a/remoting/base/telemetry_log_writer.cc b/remoting/base/telemetry_log_writer.cc
index 9900e92..dea194a 100644
--- a/remoting/base/telemetry_log_writer.cc
+++ b/remoting/base/telemetry_log_writer.cc
@@ -17,25 +17,24 @@
 
 TelemetryLogWriter::TelemetryLogWriter(
     const std::string& telemetry_base_url,
-    std::unique_ptr<UrlRequestFactory> request_factory)
+    std::unique_ptr<UrlRequestFactory> request_factory,
+    const base::RepeatingClosure& auth_closure)
     : telemetry_base_url_(telemetry_base_url),
-      request_factory_(std::move(request_factory)) {}
+      request_factory_(std::move(request_factory)),
+      auth_closure_(auth_closure) {
+  thread_checker_.DetachFromThread();
+}
 
 TelemetryLogWriter::~TelemetryLogWriter() {
   DCHECK(thread_checker_.CalledOnValidThread());
 }
 
-void TelemetryLogWriter::SetAuthToken(const std::string& auth_token) {
+void TelemetryLogWriter::SetAuthToken(const std::string& access_token) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  auth_token_ = auth_token;
+  access_token_ = access_token;
   SendPendingEntries();
 }
 
-void TelemetryLogWriter::SetAuthClosure(const base::Closure& closure) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  auth_closure_ = closure;
-}
-
 void TelemetryLogWriter::Log(const ChromotingEvent& entry) {
   DCHECK(thread_checker_.CalledOnValidThread());
   pending_entries_.push_back(entry);
@@ -96,15 +95,15 @@
         })");
   request_ = request_factory_->CreateUrlRequest(
       UrlRequest::Type::POST, telemetry_base_url_, traffic_annotation);
-  if (!auth_token_.empty()) {
-    request_->AddHeader("Authorization:Bearer " + auth_token_);
+  if (!access_token_.empty()) {
+    request_->AddHeader("Authorization:Bearer " + access_token_);
   }
 
   VLOG(1) << "Posting log to telemetry server: " << json;
 
   request_->SetPostData("application/json", json);
-  request_->Start(
-      base::Bind(&TelemetryLogWriter::OnSendLogResult, base::Unretained(this)));
+  request_->Start(base::BindRepeating(&TelemetryLogWriter::OnSendLogResult,
+                                      base::Unretained(this)));
 }
 
 void TelemetryLogWriter::OnSendLogResult(
diff --git a/remoting/base/telemetry_log_writer.h b/remoting/base/telemetry_log_writer.h
index 6de40af..36c9e27 100644
--- a/remoting/base/telemetry_log_writer.h
+++ b/remoting/base/telemetry_log_writer.h
@@ -23,21 +23,23 @@
 // Logs to be sent will be queued and sent when it is available. Logs failed
 // to send will be retried for a few times and dropped if they still can't be
 // sent.
+// The log writer should be used entirely on one thread after it is created,
+// unless otherwise noted.
 class TelemetryLogWriter : public ChromotingEventLogWriter {
  public:
+  // |auth_closure| will be called when the request fails with unauthorized
+  // error code. The closure should call SetAccessToken to set the token.
+  // If the closure is null, the log writer will try to resend the logs
+  // immediately.
+  // TODO(yuweih): Pass in centralized OAuthTokenGetter.
   TelemetryLogWriter(const std::string& telemetry_base_url,
-                     std::unique_ptr<UrlRequestFactory> request_factory);
+                     std::unique_ptr<UrlRequestFactory> request_factory,
+                     const base::RepeatingClosure& auth_closure);
 
-  // "Authorization:Bearer {TOKEN}" will be added if auth_token is not empty.
+  // "Authorization:Bearer {TOKEN}" will be added if access_token is not empty.
   // After this function is called, the log writer will try to send out pending
   // logs if the list is not empty.
-  void SetAuthToken(const std::string& auth_token) override;
-
-  // The closure will be called when the request fails with unauthorized error
-  // code. The closure should call SetAuthToken to set the token.
-  // If the closure is not set, the log writer will try to resend the logs
-  // immediately.
-  void SetAuthClosure(const base::Closure& closure) override;
+  void SetAuthToken(const std::string& access_token) override;
 
   // Push the log entry to the pending list and send out all the pending logs.
   void Log(const ChromotingEvent& entry) override;
@@ -52,8 +54,8 @@
   base::ThreadChecker thread_checker_;
   std::string telemetry_base_url_;
   std::unique_ptr<UrlRequestFactory> request_factory_;
-  std::string auth_token_;
-  base::Closure auth_closure_;
+  std::string access_token_;
+  base::RepeatingClosure auth_closure_;
   std::unique_ptr<UrlRequest> request_;
 
   // Entries to be sent.
diff --git a/remoting/base/telemetry_log_writer_unittest.cc b/remoting/base/telemetry_log_writer_unittest.cc
index d0cd555..d4b4f9b31 100644
--- a/remoting/base/telemetry_log_writer_unittest.cc
+++ b/remoting/base/telemetry_log_writer_unittest.cc
@@ -82,7 +82,10 @@
  public:
   TelemetryLogWriterTest()
       : request_factory_(new FakeUrlRequestFactory()),
-        log_writer_("", base::WrapUnique(request_factory_)) {
+        log_writer_("",
+                    base::WrapUnique(request_factory_),
+                    base::BindRepeating(&TelemetryLogWriterTest::SetAuth,
+                                        base::Unretained(this))) {
     success_result_.success = true;
     success_result_.status = 200;
     success_result_.response_body = "{}";
@@ -100,11 +103,6 @@
     log_writer_.Log(entry);
   }
 
-  void SetAuthClosure() {
-    log_writer_.SetAuthClosure(
-        base::Bind(&TelemetryLogWriterTest::SetAuth, base::Unretained(this)));
-  }
-
   UrlRequest::Result success_result_;
   UrlRequest::Result unauth_result_;
 
@@ -204,8 +202,6 @@
 }
 
 TEST_F(TelemetryLogWriterTest, PostOneUnauthorizedCallClosureAndRetry) {
-  SetAuthClosure();
-
   auto respond1 = request_factory_->AddExpectedRequest(
       "{\"event\":[{\"id\":0}]}", unauth_result_);
   LogFakeEvent();
@@ -218,17 +214,4 @@
   EXPECT_EQ(1, set_auth_count_);
 }
 
-TEST_F(TelemetryLogWriterTest, PostOneUnauthorizedAndJustRetry) {
-  auto respond1 = request_factory_->AddExpectedRequest(
-      "{\"event\":[{\"id\":0}]}", unauth_result_);
-  LogFakeEvent();
-
-  auto respond2 = request_factory_->AddExpectedRequest(
-      "{\"event\":[{\"id\":0}]}", success_result_);
-  respond1.Run();
-  respond2.Run();
-
-  EXPECT_EQ(0, set_auth_count_);
-}
-
 }  // namespace remoting
diff --git a/remoting/client/chromoting_client_runtime.cc b/remoting/client/chromoting_client_runtime.cc
index 383e6fc3..94d95840 100644
--- a/remoting/client/chromoting_client_runtime.cc
+++ b/remoting/client/chromoting_client_runtime.cc
@@ -63,7 +63,11 @@
   url_requester_ =
       new URLRequestContextGetter(network_task_runner_, file_task_runner_);
 
-  CreateLogWriter();
+  log_writer_ = std::make_unique<TelemetryLogWriter>(
+      kTelemetryBaseUrl,
+      std::make_unique<ChromiumUrlRequestFactory>(url_requester()),
+      base::BindRepeating(&ChromotingClientRuntime::RequestAuthTokenForLogger,
+                          base::Unretained(this)));
 }
 
 ChromotingClientRuntime::~ChromotingClientRuntime() {
@@ -86,21 +90,6 @@
   delegate_ = delegate;
 }
 
-void ChromotingClientRuntime::CreateLogWriter() {
-  if (!network_task_runner()->BelongsToCurrentThread()) {
-    network_task_runner()->PostTask(
-        FROM_HERE, base::Bind(&ChromotingClientRuntime::CreateLogWriter,
-                              base::Unretained(this)));
-    return;
-  }
-  log_writer_.reset(new TelemetryLogWriter(
-      kTelemetryBaseUrl,
-      std::make_unique<ChromiumUrlRequestFactory>(url_requester())));
-  log_writer_->SetAuthClosure(
-      base::Bind(&ChromotingClientRuntime::RequestAuthTokenForLogger,
-                 base::Unretained(this)));
-}
-
 void ChromotingClientRuntime::RequestAuthTokenForLogger() {
   if (delegate_) {
     delegate_->RequestAuthTokenForLogger();
@@ -109,11 +98,6 @@
   }
 }
 
-ChromotingEventLogWriter* ChromotingClientRuntime::log_writer() {
-  DCHECK(network_task_runner()->BelongsToCurrentThread());
-  return log_writer_.get();
-}
-
 OAuthTokenGetter* ChromotingClientRuntime::token_getter() {
   return delegate_->token_getter();
 }
diff --git a/remoting/client/chromoting_client_runtime.h b/remoting/client/chromoting_client_runtime.h
index 722afa9..4b3eb64f 100644
--- a/remoting/client/chromoting_client_runtime.h
+++ b/remoting/client/chromoting_client_runtime.h
@@ -80,8 +80,7 @@
     return url_requester_;
   }
 
-  // Must call and use log_writer on the network thread.
-  ChromotingEventLogWriter* log_writer();
+  ChromotingEventLogWriter* log_writer() { return log_writer_.get(); }
 
   OAuthTokenGetter* token_getter();
 
@@ -89,7 +88,6 @@
   ChromotingClientRuntime();
   virtual ~ChromotingClientRuntime();
 
-  void CreateLogWriter();
   void RequestAuthTokenForLogger();
 
   // Chromium code's connection to the app message loop. Once created the
diff --git a/remoting/client/chromoting_session.cc b/remoting/client/chromoting_session.cc
index 1ed7669..bcf98067 100644
--- a/remoting/client/chromoting_session.cc
+++ b/remoting/client/chromoting_session.cc
@@ -7,12 +7,14 @@
 #include <stdint.h>
 
 #include <algorithm>
+#include <utility>
 
 #include "base/bind.h"
+#include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/format_macros.h"
 #include "base/logging.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/timer/timer.h"
 #include "jingle/glue/thread_wrapper.h"
 #include "net/socket/client_socket_factory.h"
 #include "remoting/base/chromium_url_request.h"
@@ -42,15 +44,15 @@
 const int kXmppPort = 5222;
 const bool kXmppUseTls = true;
 
-// Interval at which to log performance statistics, if enabled.
-const int kPerfStatsIntervalMs = 60000;
-
 // Default DPI to assume for old clients that use notifyClientResolution.
 const int kDefaultDPI = 96;
 
 // Used by NormalizeclientResolution. See comment below.
 const int kMinDimension = 640;
 
+// Interval at which to log performance statistics, if enabled.
+constexpr base::TimeDelta kPerfStatsInterval = base::TimeDelta::FromMinutes(1);
+
 // Normalizes the resolution so that both dimensions are not smaller than
 // kMinDimension.
 void NormalizeClientResolution(protocol::ClientResolution* resolution) {
@@ -66,134 +68,169 @@
   resolution->set_dips_height(resolution->dips_height() * scale);
 }
 
-}  // namespace
-
-ChromotingSession::ChromotingSession(
-    base::WeakPtr<ChromotingSession::Delegate> delegate,
-    std::unique_ptr<protocol::CursorShapeStub> cursor_shape_stub,
-    std::unique_ptr<protocol::VideoRenderer> video_renderer,
-    base::WeakPtr<protocol::AudioStub> audio_player,
-    const ConnectToHostInfo& info,
-    const protocol::ClientAuthenticationConfig& client_auth_config)
-    : delegate_(delegate),
-      connection_info_(info),
-      client_auth_config_(client_auth_config),
-      cursor_shape_stub_(std::move(cursor_shape_stub)),
-      video_renderer_(std::move(video_renderer)),
-      audio_player_(audio_player),
-      capabilities_(info.capabilities),
-      weak_factory_per_connection_(this),
-      weak_factory_per_instance_lifetime_(this) {
-  runtime_ = ChromotingClientRuntime::GetInstance();
-  DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
-  weak_ptr_per_connection_ = weak_factory_per_connection_.GetWeakPtr();
-  weak_ptr_per_instance_lifetime_ =
-      weak_factory_per_instance_lifetime_.GetWeakPtr();
-
-  // Initialize XMPP config.
-  xmpp_config_.host = kXmppServer;
-  xmpp_config_.port = kXmppPort;
-  xmpp_config_.use_tls = kXmppUseTls;
-  xmpp_config_.username = info.username;
-  xmpp_config_.auth_token = info.auth_token;
-
-  client_auth_config_.fetch_third_party_token_callback =
-      base::BindRepeating(&ChromotingSession::FetchThirdPartyToken,
-                          weak_ptr_per_connection_, info.host_pubkey);
-}
-
-ChromotingSession::~ChromotingSession() {
-  DCHECK(runtime_->network_task_runner()->BelongsToCurrentThread());
-  ReleaseResources();
-}
-
-void ChromotingSession::Connect() {
-  if (runtime_->network_task_runner()->BelongsToCurrentThread()) {
-    ConnectToHostOnNetworkThread();
+void GetFeedbackDataOnNetworkThread(
+    ChromotingClientRuntime* runtime,
+    base::WeakPtr<ClientTelemetryLogger> logger,
+    ChromotingSession::GetFeedbackDataCallback callback,
+    scoped_refptr<base::SingleThreadTaskRunner> response_thread) {
+  DCHECK(runtime->network_task_runner()->BelongsToCurrentThread());
+  auto data = std::make_unique<FeedbackData>();
+  if (logger) {
+    data->FillWithChromotingEvent(logger->current_session_state_event());
+  }
+  if (response_thread->BelongsToCurrentThread()) {
+    std::move(callback).Run(std::move(data));
   } else {
-    runtime_->network_task_runner()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&ChromotingSession::ConnectToHostOnNetworkThread,
-                       weak_ptr_per_connection_));
+    response_thread->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), base::Passed(&data)));
   }
 }
 
-void ChromotingSession::Disconnect() {
+}  // namespace
+
+struct ChromotingSession::SessionContext {
+  ChromotingClientRuntime* runtime;
+  base::WeakPtr<ChromotingSession::Delegate> delegate;
+  base::WeakPtr<ClientTelemetryLogger> logger;
+  base::WeakPtr<protocol::AudioStub> audio_player;
+  std::unique_ptr<protocol::CursorShapeStub> cursor_shape_stub;
+  std::unique_ptr<protocol::VideoRenderer> video_renderer;
+
+  ConnectToHostInfo info;
+  protocol::ClientAuthenticationConfig client_auth_config;
+};
+
+class ChromotingSession::Core : public ClientUserInterface,
+                                public protocol::ClipboardStub {
+ public:
+  explicit Core(std::unique_ptr<SessionContext> session_context);
+  ~Core() override;
+
+  void RequestPairing(const std::string& device_name);
+  void FetchThirdPartyToken(
+      const std::string& host_public_key,
+      const std::string& token_url,
+      const std::string& scope,
+      const protocol::ThirdPartyTokenFetchedCallback& token_fetched_callback);
+  void HandleOnThirdPartyTokenFetched(const std::string& token,
+                                      const std::string& shared_secret);
+  void SendMouseEvent(int x,
+                      int y,
+                      protocol::MouseEvent_MouseButton button,
+                      bool button_down);
+  void SendMouseWheelEvent(int delta_x, int delta_y);
+  void SendKeyEvent(int usb_key_code, bool key_down);
+  void SendTextEvent(const std::string& text);
+  void SendTouchEvent(const protocol::TouchEvent& touch_event);
+  void SendClientResolution(int dips_width, int dips_height, int scale);
+  void EnableVideoChannel(bool enable);
+  void SendClientMessage(const std::string& type, const std::string& data);
+
+  // Logs the disconnect event and invalidates weak pointers.
+  void DisconnectForReason(protocol::ErrorCode error);
+
+  // ClientUserInterface implementation.
+  void OnConnectionState(protocol::ConnectionToHost::State state,
+                         protocol::ErrorCode error) override;
+  void OnConnectionReady(bool ready) override;
+  void OnRouteChanged(const std::string& channel_name,
+                      const protocol::TransportRoute& route) override;
+  void SetCapabilities(const std::string& capabilities) override;
+  void SetPairingResponse(const protocol::PairingResponse& response) override;
+  void DeliverHostMessage(const protocol::ExtensionMessage& message) override;
+  void SetDesktopSize(const webrtc::DesktopSize& size,
+                      const webrtc::DesktopVector& dpi) override;
+  protocol::ClipboardStub* GetClipboardStub() override;
+  protocol::CursorShapeStub* GetCursorShapeStub() override;
+
+  // CursorShapeStub implementation.
+  void InjectClipboardEvent(const protocol::ClipboardEvent& event) override;
+
+  base::WeakPtr<Core> GetWeakPtr();
+
+ private:
+  void ConnectOnNetworkThread();
+  void LogPerfStats();
+
+  scoped_refptr<AutoThreadTaskRunner> ui_task_runner() {
+    return session_context_->runtime->ui_task_runner();
+  }
+
+  scoped_refptr<AutoThreadTaskRunner> network_task_runner() {
+    return session_context_->runtime->network_task_runner();
+  }
+
+  std::unique_ptr<SessionContext> session_context_;
+
+  std::unique_ptr<ClientContext> client_context_;
+  std::unique_ptr<protocol::PerformanceTracker> perf_tracker_;
+
+  // |signaling_| must outlive |client_|, so it must be declared above
+  // |client_|.
+  std::unique_ptr<XmppSignalStrategy> signaling_;
+  std::unique_ptr<ChromotingClient> client_;
+
+  protocol::ThirdPartyTokenFetchedCallback third_party_token_fetched_callback_;
+
+  // Empty string if client doesn't request for pairing.
+  std::string device_name_for_pairing_;
+
+  // The current session state.
+  protocol::ConnectionToHost::State session_state_ =
+      protocol::ConnectionToHost::INITIALIZING;
+
+  base::RepeatingTimer perf_stats_logging_timer_;
+
+  base::WeakPtrFactory<Core> weak_factory_;
+  DISALLOW_COPY_AND_ASSIGN(Core);
+};
+
+ChromotingSession::Core::Core(std::unique_ptr<SessionContext> session_context)
+    : session_context_(std::move(session_context)), weak_factory_(this) {
+  DCHECK(ui_task_runner()->BelongsToCurrentThread());
+
+  session_context_->client_auth_config.fetch_third_party_token_callback =
+      base::BindRepeating(&Core::FetchThirdPartyToken, GetWeakPtr(),
+                          session_context_->info.host_pubkey);
+
+  network_task_runner()->PostTask(
+      FROM_HERE, base::BindOnce(&Core::ConnectOnNetworkThread, GetWeakPtr()));
+}
+
+ChromotingSession::Core::~Core() {
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
+
+  // Make sure we log a close event if the session has not been disconnected
+  // yet.
   DisconnectForReason(protocol::ErrorCode::OK);
 }
 
-void ChromotingSession::DisconnectForReason(protocol::ErrorCode error) {
-  if (!runtime_->network_task_runner()->BelongsToCurrentThread()) {
-    runtime_->network_task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(&ChromotingSession::DisconnectForReason,
-                                  weak_ptr_per_connection_, error));
-    return;
-  }
-
-  EnableStatsLogging(false);
-
-  // Do not log session state change if the connection is never started or is
-  // already closed.
-  if (session_state_ != protocol::ConnectionToHost::INITIALIZING &&
-      session_state_ != protocol::ConnectionToHost::FAILED &&
-      session_state_ != protocol::ConnectionToHost::CLOSED) {
-    ChromotingEvent::SessionState session_state_to_log;
-    if (error != protocol::ErrorCode::OK) {
-      session_state_to_log = ChromotingEvent::SessionState::CONNECTION_FAILED;
-    } else if (session_state_ == protocol::ConnectionToHost::CONNECTED) {
-      session_state_to_log = ChromotingEvent::SessionState::CLOSED;
-    } else {
-      session_state_to_log = ChromotingEvent::SessionState::CONNECTION_CANCELED;
-    }
-    logger_->LogSessionStateChange(
-        session_state_to_log, ClientTelemetryLogger::TranslateError(error));
-    session_state_ = (error == protocol::ErrorCode::OK)
-                         ? protocol::ConnectionToHost::CLOSED
-                         : protocol::ConnectionToHost::FAILED;
-  }
-
-  ReleaseResources();
+void ChromotingSession::Core::RequestPairing(const std::string& device_name) {
+  DCHECK(!device_name.empty());
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
+  device_name_for_pairing_ = device_name;
 }
 
-void ChromotingSession::FetchThirdPartyToken(
+void ChromotingSession::Core::FetchThirdPartyToken(
     const std::string& host_public_key,
     const std::string& token_url,
     const std::string& scope,
     const protocol::ThirdPartyTokenFetchedCallback& token_fetched_callback) {
-  DCHECK(runtime_->network_task_runner()->BelongsToCurrentThread());
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
   DCHECK(third_party_token_fetched_callback_.is_null());
 
   third_party_token_fetched_callback_ = token_fetched_callback;
-  runtime_->ui_task_runner()->PostTask(
+  ui_task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&ChromotingSession::Delegate::FetchThirdPartyToken,
-                     delegate_, token_url, host_public_key, scope));
+                     session_context_->delegate, token_url, host_public_key,
+                     scope));
 }
 
-void ChromotingSession::GetFeedbackData(
-    GetFeedbackDataCallback callback) const {
-  if (!runtime_->network_task_runner()->BelongsToCurrentThread()) {
-    runtime_->network_task_runner()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&ChromotingSession::GetFeedbackDataOnNetworkThread,
-                       weak_ptr_per_instance_lifetime_, base::Passed(&callback),
-                       base::ThreadTaskRunnerHandle::Get()));
-    return;
-  }
-  GetFeedbackDataOnNetworkThread(std::move(callback),
-                                 base::ThreadTaskRunnerHandle::Get());
-}
-
-void ChromotingSession::HandleOnThirdPartyTokenFetched(
+void ChromotingSession::Core::HandleOnThirdPartyTokenFetched(
     const std::string& token,
     const std::string& shared_secret) {
-  if (!runtime_->network_task_runner()->BelongsToCurrentThread()) {
-    runtime_->network_task_runner()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&ChromotingSession::HandleOnThirdPartyTokenFetched,
-                       weak_ptr_per_connection_, token, shared_secret));
-    return;
-  }
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
 
   if (!third_party_token_fetched_callback_.is_null()) {
     base::ResetAndReturn(&third_party_token_fetched_callback_)
@@ -204,35 +241,12 @@
   }
 }
 
-void ChromotingSession::ProvideSecret(const std::string& pin,
-                                      bool create_pairing,
-                                      const std::string& device_name) {
-  DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
-
-  // TODO(nicholss): |pin| here is not used. Maybe there was an api refactor and
-  // this was not cleaned up. The auth pin providing mechanism seems to be call
-  // ProvideSecret, and then call the auth callback. When session moves to
-  // Connected state, this chromoing session calls RequestPairing  based on
-  // create_pairing.
-
-  create_pairing_ = create_pairing;
-
-  if (create_pairing)
-    SetDeviceName(device_name);
-}
-
-void ChromotingSession::SendMouseEvent(int x,
-                                       int y,
-                                       protocol::MouseEvent_MouseButton button,
-                                       bool button_down) {
-  if (!runtime_->network_task_runner()->BelongsToCurrentThread()) {
-    runtime_->network_task_runner()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&ChromotingSession::SendMouseEvent,
-                       weak_ptr_per_connection_, x, y, button, button_down));
-    return;
-  }
-
+void ChromotingSession::Core::SendMouseEvent(
+    int x,
+    int y,
+    protocol::MouseEvent_MouseButton button,
+    bool button_down) {
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
   protocol::MouseEvent event;
   event.set_x(x);
   event.set_y(y);
@@ -243,74 +257,39 @@
   client_->input_stub()->InjectMouseEvent(event);
 }
 
-void ChromotingSession::SendMouseWheelEvent(int delta_x, int delta_y) {
-  if (!runtime_->network_task_runner()->BelongsToCurrentThread()) {
-    runtime_->network_task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(&ChromotingSession::SendMouseWheelEvent,
-                                  weak_ptr_per_connection_, delta_x, delta_y));
-    return;
-  }
-
+void ChromotingSession::Core::SendMouseWheelEvent(int delta_x, int delta_y) {
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
   protocol::MouseEvent event;
   event.set_wheel_delta_x(delta_x);
   event.set_wheel_delta_y(delta_y);
   client_->input_stub()->InjectMouseEvent(event);
 }
 
-bool ChromotingSession::SendKeyEvent(int scan_code,
-                                     int key_code,
-                                     bool key_down) {
-  // For software keyboards |scan_code| is set to 0, in which case the
-  // |key_code| is used instead.
-  uint32_t usb_key_code =
-      scan_code ? ui::KeycodeConverter::NativeKeycodeToUsbKeycode(scan_code)
-                : NativeDeviceKeycodeToUsbKeycode(key_code);
-  if (!usb_key_code) {
-    LOG(WARNING) << "Ignoring unknown key code: " << key_code
-                 << " scan code: " << scan_code;
-    return false;
-  }
-
-  SendKeyEventInternal(usb_key_code, key_down);
-  return true;
+void ChromotingSession::Core::SendKeyEvent(int usb_key_code, bool key_down) {
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
+  protocol::KeyEvent event;
+  event.set_usb_keycode(usb_key_code);
+  event.set_pressed(key_down);
+  client_->input_stub()->InjectKeyEvent(event);
 }
 
-void ChromotingSession::SendTextEvent(const std::string& text) {
-  if (!runtime_->network_task_runner()->BelongsToCurrentThread()) {
-    runtime_->network_task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(&ChromotingSession::SendTextEvent,
-                                  weak_ptr_per_connection_, text));
-    return;
-  }
-
+void ChromotingSession::Core::SendTextEvent(const std::string& text) {
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
   protocol::TextEvent event;
   event.set_text(text);
   client_->input_stub()->InjectTextEvent(event);
 }
 
-void ChromotingSession::SendTouchEvent(
+void ChromotingSession::Core::SendTouchEvent(
     const protocol::TouchEvent& touch_event) {
-  if (!runtime_->network_task_runner()->BelongsToCurrentThread()) {
-    runtime_->network_task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(&ChromotingSession::SendTouchEvent,
-                                  weak_ptr_per_connection_, touch_event));
-    return;
-  }
-
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
   client_->input_stub()->InjectTouchEvent(touch_event);
 }
 
-void ChromotingSession::SendClientResolution(int dips_width,
-                                             int dips_height,
-                                             int scale) {
-  if (!runtime_->network_task_runner()->BelongsToCurrentThread()) {
-    runtime_->network_task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(&ChromotingSession::SendClientResolution,
-                                  weak_ptr_per_connection_, dips_width,
-                                  dips_height, scale));
-    return;
-  }
-
+void ChromotingSession::Core::SendClientResolution(int dips_width,
+                                                   int dips_height,
+                                                   int scale) {
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
   protocol::ClientResolution client_resolution;
   client_resolution.set_dips_width(dips_width);
   client_resolution.set_dips_height(dips_height);
@@ -326,159 +305,198 @@
   client_->host_stub()->NotifyClientResolution(client_resolution);
 }
 
-void ChromotingSession::EnableVideoChannel(bool enable) {
-  if (!runtime_->network_task_runner()->BelongsToCurrentThread()) {
-    runtime_->network_task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(&ChromotingSession::EnableVideoChannel,
-                                  weak_ptr_per_connection_, enable));
-    return;
-  }
-
+void ChromotingSession::Core::EnableVideoChannel(bool enable) {
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
   protocol::VideoControl video_control;
   video_control.set_enable(enable);
   client_->host_stub()->ControlVideo(video_control);
 }
 
-void ChromotingSession::SendClientMessage(const std::string& type,
-                                          const std::string& data) {
-  if (!runtime_->network_task_runner()->BelongsToCurrentThread()) {
-    runtime_->network_task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(&ChromotingSession::SendClientMessage,
-                                  weak_ptr_per_connection_, type, data));
-    return;
-  }
-
+void ChromotingSession::Core::SendClientMessage(const std::string& type,
+                                                const std::string& data) {
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
   protocol::ExtensionMessage extension_message;
   extension_message.set_type(type);
   extension_message.set_data(data);
   client_->host_stub()->DeliverClientMessage(extension_message);
 }
 
-void ChromotingSession::OnConnectionState(
+void ChromotingSession::Core::DisconnectForReason(protocol::ErrorCode error) {
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
+
+  // Do not log session state change if the connection is already closed.
+  if (session_state_ != protocol::ConnectionToHost::INITIALIZING &&
+      session_state_ != protocol::ConnectionToHost::FAILED &&
+      session_state_ != protocol::ConnectionToHost::CLOSED) {
+    ChromotingEvent::SessionState session_state_to_log;
+    if (error != protocol::ErrorCode::OK) {
+      session_state_to_log = ChromotingEvent::SessionState::CONNECTION_FAILED;
+    } else if (session_state_ == protocol::ConnectionToHost::CONNECTED) {
+      session_state_to_log = ChromotingEvent::SessionState::CLOSED;
+    } else {
+      session_state_to_log = ChromotingEvent::SessionState::CONNECTION_CANCELED;
+    }
+    session_context_->logger->LogSessionStateChange(
+        session_state_to_log, ClientTelemetryLogger::TranslateError(error));
+    session_state_ = (error == protocol::ErrorCode::OK)
+                         ? protocol::ConnectionToHost::CLOSED
+                         : protocol::ConnectionToHost::FAILED;
+    // Prevent all pending and future calls from ChromotingSession.
+    weak_factory_.InvalidateWeakPtrs();
+  }
+}
+
+void ChromotingSession::Core::OnConnectionState(
     protocol::ConnectionToHost::State state,
     protocol::ErrorCode error) {
-  DCHECK(runtime_->network_task_runner()->BelongsToCurrentThread());
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
 
   // This code assumes no intermediate connection state between CONNECTED and
   // CLOSED/FAILED.
   session_state_ = state;
-  EnableStatsLogging(session_state_ == protocol::ConnectionToHost::CONNECTED);
 
-  logger_->LogSessionStateChange(ClientTelemetryLogger::TranslateState(state),
-                                 ClientTelemetryLogger::TranslateError(error));
+  if (session_state_ == protocol::ConnectionToHost::CONNECTED) {
+    perf_stats_logging_timer_.Start(
+        FROM_HERE, kPerfStatsInterval,
+        base::BindRepeating(&Core::LogPerfStats, GetWeakPtr()));
+  } else if (perf_stats_logging_timer_.IsRunning()) {
+    perf_stats_logging_timer_.Stop();
+  }
 
-  if (create_pairing_ && state == protocol::ConnectionToHost::CONNECTED) {
+  session_context_->logger->LogSessionStateChange(
+      ClientTelemetryLogger::TranslateState(state),
+      ClientTelemetryLogger::TranslateError(error));
+
+  if (!device_name_for_pairing_.empty() &&
+      state == protocol::ConnectionToHost::CONNECTED) {
     protocol::PairingRequest request;
-    DCHECK(!device_name_.empty());
-    request.set_client_name(device_name_);
+    request.set_client_name(device_name_for_pairing_);
     client_->host_stub()->RequestPairing(request);
   }
 
-  runtime_->ui_task_runner()->PostTask(
+  ui_task_runner()->PostTask(
       FROM_HERE, base::BindOnce(&ChromotingSession::Delegate::OnConnectionState,
-                                delegate_, state, error));
+                                session_context_->delegate, state, error));
 
   if (state == protocol::ConnectionToHost::CLOSED ||
       state == protocol::ConnectionToHost::FAILED) {
-    ReleaseResources();
+    weak_factory_.InvalidateWeakPtrs();
   }
 }
 
-void ChromotingSession::OnConnectionReady(bool ready) {
+void ChromotingSession::Core::OnConnectionReady(bool ready) {
   // We ignore this message, since OnConnectionState tells us the same thing.
 }
 
-void ChromotingSession::OnRouteChanged(const std::string& channel_name,
-                                       const protocol::TransportRoute& route) {
+void ChromotingSession::Core::OnRouteChanged(
+    const std::string& channel_name,
+    const protocol::TransportRoute& route) {
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
   std::string message = "Channel " + channel_name + " using " +
                         protocol::TransportRoute::GetTypeString(route.type) +
                         " connection.";
   VLOG(1) << "Route: " << message;
-  logger_->SetTransportRoute(route);
+  session_context_->logger->SetTransportRoute(route);
 }
 
-void ChromotingSession::SetCapabilities(const std::string& capabilities) {
-  runtime_->ui_task_runner()->PostTask(
+void ChromotingSession::Core::SetCapabilities(const std::string& capabilities) {
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
+  ui_task_runner()->PostTask(
       FROM_HERE, base::BindOnce(&ChromotingSession::Delegate::SetCapabilities,
-                                delegate_, capabilities));
+                                session_context_->delegate, capabilities));
 }
 
-void ChromotingSession::SetPairingResponse(
+void ChromotingSession::Core::SetPairingResponse(
     const protocol::PairingResponse& response) {
-  runtime_->ui_task_runner()->PostTask(
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
+  ui_task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&ChromotingSession::Delegate::CommitPairingCredentials,
-                     delegate_, client_auth_config_.host_id,
+                     session_context_->delegate,
+                     session_context_->client_auth_config.host_id,
                      response.client_id(), response.shared_secret()));
 }
 
-void ChromotingSession::DeliverHostMessage(
+void ChromotingSession::Core::DeliverHostMessage(
     const protocol::ExtensionMessage& message) {
-  runtime_->ui_task_runner()->PostTask(
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
+  ui_task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&ChromotingSession::Delegate::HandleExtensionMessage,
-                     delegate_, message.type(), message.data()));
+                     session_context_->delegate, message.type(),
+                     message.data()));
 }
 
-void ChromotingSession::SetDesktopSize(const webrtc::DesktopSize& size,
-                                       const webrtc::DesktopVector& dpi) {
+void ChromotingSession::Core::SetDesktopSize(const webrtc::DesktopSize& size,
+                                             const webrtc::DesktopVector& dpi) {
   // ChromotingSession's VideoRenderer gets size from the frames and it doesn't
   // use DPI, so this call can be ignored.
 }
 
-protocol::ClipboardStub* ChromotingSession::GetClipboardStub() {
+protocol::ClipboardStub* ChromotingSession::Core::GetClipboardStub() {
   return this;
 }
 
-protocol::CursorShapeStub* ChromotingSession::GetCursorShapeStub() {
-  return cursor_shape_stub_.get();
+protocol::CursorShapeStub* ChromotingSession::Core::GetCursorShapeStub() {
+  return session_context_->cursor_shape_stub.get();
 }
 
-void ChromotingSession::InjectClipboardEvent(
+void ChromotingSession::Core::InjectClipboardEvent(
     const protocol::ClipboardEvent& event) {
   NOTIMPLEMENTED();
 }
 
-void ChromotingSession::ConnectToHostOnNetworkThread() {
-  DCHECK(runtime_->network_task_runner()->BelongsToCurrentThread());
+base::WeakPtr<ChromotingSession::Core> ChromotingSession::Core::GetWeakPtr() {
+  return weak_factory_.GetWeakPtr();
+}
+
+void ChromotingSession::Core::ConnectOnNetworkThread() {
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
 
   jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
 
-  client_context_.reset(new ClientContext(runtime_->network_task_runner()));
+  client_context_.reset(new ClientContext(network_task_runner()));
   client_context_->Start();
 
   perf_tracker_.reset(new protocol::PerformanceTracker());
 
-  video_renderer_->Initialize(*client_context_, perf_tracker_.get());
-
-  logger_.reset(new ClientTelemetryLogger(runtime_->log_writer(),
-                                          ChromotingEvent::Mode::ME2ME));
-  logger_->SetHostInfo(
-      connection_info_.host_version,
-      ChromotingEvent::ParseOsFromString(connection_info_.host_os),
-      connection_info_.host_os_version);
+  session_context_->video_renderer->Initialize(*client_context_,
+                                               perf_tracker_.get());
+  session_context_->logger->SetHostInfo(
+      session_context_->info.host_version,
+      ChromotingEvent::ParseOsFromString(session_context_->info.host_os),
+      session_context_->info.host_os_version);
 
   client_.reset(new ChromotingClient(client_context_.get(), this,
-                                     video_renderer_.get(), audio_player_));
+                                     session_context_->video_renderer.get(),
+                                     session_context_->audio_player));
 
-  signaling_.reset(
-      new XmppSignalStrategy(net::ClientSocketFactory::GetDefaultFactory(),
-                             runtime_->url_requester(), xmpp_config_));
+  XmppSignalStrategy::XmppServerConfig xmpp_config;
+  xmpp_config.host = kXmppServer;
+  xmpp_config.port = kXmppPort;
+  xmpp_config.use_tls = kXmppUseTls;
+  xmpp_config.username = session_context_->info.username;
+  xmpp_config.auth_token = session_context_->info.auth_token;
+
+  signaling_.reset(new XmppSignalStrategy(
+      net::ClientSocketFactory::GetDefaultFactory(),
+      session_context_->runtime->url_requester(), xmpp_config));
 
   scoped_refptr<protocol::TransportContext> transport_context =
       new protocol::TransportContext(
           signaling_.get(),
           std::make_unique<protocol::ChromiumPortAllocatorFactory>(),
           std::make_unique<ChromiumUrlRequestFactory>(
-              runtime_->url_requester()),
+              session_context_->runtime->url_requester()),
           protocol::NetworkSettings(
               protocol::NetworkSettings::NAT_TRAVERSAL_FULL),
           protocol::TransportRole::CLIENT);
   transport_context->set_ice_config_url(
-      ServiceUrls::GetInstance()->ice_config_url(), runtime_->token_getter());
+      ServiceUrls::GetInstance()->ice_config_url(),
+      session_context_->runtime->token_getter());
 
 #if defined(ENABLE_WEBRTC_REMOTING_CLIENT)
-  if (connection_info_.flags.find("useWebrtc") != std::string::npos) {
+  if (session_context_->info.flags.find("useWebrtc") != std::string::npos) {
     VLOG(0) << "Attempting to connect using WebRTC.";
     std::unique_ptr<protocol::CandidateSessionConfig> protocol_config =
         protocol::CandidateSessionConfig::CreateEmpty();
@@ -487,99 +505,180 @@
     client_->set_protocol_config(std::move(protocol_config));
   }
 #endif  // defined(ENABLE_WEBRTC_REMOTING_CLIENT)
-  client_->Start(signaling_.get(), client_auth_config_, transport_context,
-                 connection_info_.host_jid, capabilities_);
+  client_->Start(signaling_.get(), session_context_->client_auth_config,
+                 transport_context, session_context_->info.host_jid,
+                 session_context_->info.capabilities);
 }
 
-void ChromotingSession::SetDeviceName(const std::string& device_name) {
-  if (!runtime_->network_task_runner()->BelongsToCurrentThread()) {
-    runtime_->network_task_runner()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&ChromotingSession::SetDeviceName,
-                       weak_ptr_per_instance_lifetime_, device_name));
+void ChromotingSession::Core::LogPerfStats() {
+  DCHECK(network_task_runner()->BelongsToCurrentThread());
+
+  session_context_->logger->LogStatistics(perf_tracker_.get());
+}
+
+// ChromotingSession implementation.
+
+ChromotingSession::ChromotingSession(
+    base::WeakPtr<ChromotingSession::Delegate> delegate,
+    std::unique_ptr<protocol::CursorShapeStub> cursor_shape_stub,
+    std::unique_ptr<protocol::VideoRenderer> video_renderer,
+    base::WeakPtr<protocol::AudioStub> audio_player,
+    const ConnectToHostInfo& info,
+    const protocol::ClientAuthenticationConfig& client_auth_config)
+    : weak_factory_(this) {
+  DCHECK(delegate);
+  DCHECK(cursor_shape_stub);
+  DCHECK(video_renderer);
+  // Don't DCHECK audio_player since it will bind audio_player to the ui thread.
+
+  runtime_ = ChromotingClientRuntime::GetInstance();
+  DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
+  weak_ptr_ = weak_factory_.GetWeakPtr();
+
+  logger_ = std::make_unique<ClientTelemetryLogger>(
+      runtime_->log_writer(), ChromotingEvent::Mode::ME2ME);
+
+  // logger is set when connection is started.
+  session_context_ = std::make_unique<SessionContext>();
+  session_context_->runtime = runtime_;
+  session_context_->delegate = delegate;
+  session_context_->logger = logger_->GetWeakPtr();
+  session_context_->audio_player = audio_player;
+  session_context_->cursor_shape_stub = std::move(cursor_shape_stub);
+  session_context_->video_renderer = std::move(video_renderer);
+  session_context_->info = info;
+  session_context_->client_auth_config = client_auth_config;
+}
+
+ChromotingSession::~ChromotingSession() {
+  DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
+
+  if (core_) {
+    runtime_->network_task_runner()->DeleteSoon(FROM_HERE, core_.release());
+  }
+  runtime_->network_task_runner()->DeleteSoon(FROM_HERE, logger_.release());
+}
+
+void ChromotingSession::Connect() {
+  DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
+  DCHECK(session_context_) << "Session has already been connected before.";
+  core_ = std::make_unique<Core>(std::move(session_context_));
+}
+
+void ChromotingSession::Disconnect() {
+  DisconnectForReason(protocol::ErrorCode::OK);
+}
+
+void ChromotingSession::DisconnectForReason(protocol::ErrorCode error) {
+  RunCoreTaskOnNetworkThread(FROM_HERE, &Core::DisconnectForReason, error);
+}
+
+void ChromotingSession::GetFeedbackData(
+    GetFeedbackDataCallback callback) const {
+  DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
+
+  runtime_->network_task_runner()->PostTask(
+      FROM_HERE, base::BindOnce(&GetFeedbackDataOnNetworkThread, runtime_,
+                                logger_->GetWeakPtr(), base::Passed(&callback),
+                                runtime_->ui_task_runner()));
+}
+
+void ChromotingSession::HandleOnThirdPartyTokenFetched(
+    const std::string& token,
+    const std::string& shared_secret) {
+  RunCoreTaskOnNetworkThread(FROM_HERE, &Core::HandleOnThirdPartyTokenFetched,
+                             token, shared_secret);
+}
+
+void ChromotingSession::ProvideSecret(const std::string& pin,
+                                      bool create_pairing,
+                                      const std::string& device_name) {
+  // TODO(nicholss): |pin| here is not used. Maybe there was an api refactor and
+  // this was not cleaned up. The auth pin providing mechanism seems to be call
+  // ProvideSecret, and then call the auth callback. When session moves to
+  // Connected state, this chromoing session calls RequestPairing  based on
+  // create_pairing.
+
+  if (create_pairing) {
+    RunCoreTaskOnNetworkThread(FROM_HERE, &Core::RequestPairing, device_name);
+  }
+}
+
+void ChromotingSession::SendMouseEvent(int x,
+                                       int y,
+                                       protocol::MouseEvent_MouseButton button,
+                                       bool button_down) {
+  RunCoreTaskOnNetworkThread(FROM_HERE, &Core::SendMouseEvent, x, y, button,
+                             button_down);
+}
+
+void ChromotingSession::SendMouseWheelEvent(int delta_x, int delta_y) {
+  RunCoreTaskOnNetworkThread(FROM_HERE, &Core::SendMouseWheelEvent, delta_x,
+                             delta_y);
+}
+
+bool ChromotingSession::SendKeyEvent(int scan_code,
+                                     int key_code,
+                                     bool key_down) {
+  DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
+
+  // For software keyboards |scan_code| is set to 0, in which case the
+  // |key_code| is used instead.
+  uint32_t usb_key_code =
+      scan_code ? ui::KeycodeConverter::NativeKeycodeToUsbKeycode(scan_code)
+                : NativeDeviceKeycodeToUsbKeycode(key_code);
+  if (!usb_key_code) {
+    LOG(WARNING) << "Ignoring unknown key code: " << key_code
+                 << " scan code: " << scan_code;
+    return false;
+  }
+  RunCoreTaskOnNetworkThread(FROM_HERE, &Core::SendKeyEvent, usb_key_code,
+                             key_down);
+
+  return true;
+}
+
+void ChromotingSession::SendTextEvent(const std::string& text) {
+  RunCoreTaskOnNetworkThread(FROM_HERE, &Core::SendTextEvent, text);
+}
+
+void ChromotingSession::SendTouchEvent(
+    const protocol::TouchEvent& touch_event) {
+  RunCoreTaskOnNetworkThread(FROM_HERE, &Core::SendTouchEvent, touch_event);
+}
+
+void ChromotingSession::SendClientResolution(int dips_width,
+                                             int dips_height,
+                                             int scale) {
+  RunCoreTaskOnNetworkThread(FROM_HERE, &Core::SendClientResolution, dips_width,
+                             dips_height, scale);
+}
+
+void ChromotingSession::EnableVideoChannel(bool enable) {
+  RunCoreTaskOnNetworkThread(FROM_HERE, &Core::EnableVideoChannel, enable);
+}
+
+void ChromotingSession::SendClientMessage(const std::string& type,
+                                          const std::string& data) {
+  RunCoreTaskOnNetworkThread(FROM_HERE, &Core::SendClientMessage, type, data);
+}
+
+template <typename Functor, typename... Args>
+void ChromotingSession::RunCoreTaskOnNetworkThread(
+    const base::Location& from_here,
+    Functor&& core_functor,
+    Args&&... args) {
+  DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
+
+  if (!core_) {
+    LOG(WARNING) << "Session is not connected.";
     return;
   }
 
-  device_name_ = device_name;
-}
-
-void ChromotingSession::SendKeyEventInternal(int usb_key_code, bool key_down) {
-  if (!runtime_->network_task_runner()->BelongsToCurrentThread()) {
-    runtime_->network_task_runner()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&ChromotingSession::SendKeyEventInternal,
-                       weak_ptr_per_connection_, usb_key_code, key_down));
-    return;
-  }
-
-  protocol::KeyEvent event;
-  event.set_usb_keycode(usb_key_code);
-  event.set_pressed(key_down);
-  client_->input_stub()->InjectKeyEvent(event);
-}
-
-void ChromotingSession::EnableStatsLogging(bool enabled) {
-  DCHECK(runtime_->network_task_runner()->BelongsToCurrentThread());
-
-  if (enabled && !stats_logging_enabled_) {
-    runtime_->network_task_runner()->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&ChromotingSession::LogPerfStats,
-                       weak_ptr_per_connection_),
-        base::TimeDelta::FromMilliseconds(kPerfStatsIntervalMs));
-  }
-  stats_logging_enabled_ = enabled;
-}
-
-void ChromotingSession::LogPerfStats() {
-  DCHECK(runtime_->network_task_runner()->BelongsToCurrentThread());
-
-  if (!stats_logging_enabled_)
-    return;
-
-  logger_->LogStatistics(perf_tracker_.get());
-
-  runtime_->network_task_runner()->PostDelayedTask(
+  runtime_->network_task_runner()->PostTask(
       FROM_HERE,
-      base::BindOnce(&ChromotingSession::LogPerfStats,
-                     weak_ptr_per_connection_),
-      base::TimeDelta::FromMilliseconds(kPerfStatsIntervalMs));
-}
-
-void ChromotingSession::ChromotingSession::GetFeedbackDataOnNetworkThread(
-    GetFeedbackDataCallback callback,
-    scoped_refptr<base::SingleThreadTaskRunner> response_thread) const {
-  DCHECK(runtime_->network_task_runner()->BelongsToCurrentThread());
-  auto data = std::make_unique<FeedbackData>();
-  if (logger_) {
-    data->FillWithChromotingEvent(logger_->current_session_state_event());
-  }
-  if (response_thread->BelongsToCurrentThread()) {
-    std::move(callback).Run(std::move(data));
-    return;
-  }
-  response_thread->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback), base::Passed(&data)));
-}
-
-void ChromotingSession::ReleaseResources() {
-  // |client_| must be torn down before |signaling_|.
-  client_.reset();
-  delegate_.reset();
-  audio_player_.reset();
-  video_renderer_.reset();
-  signaling_.reset();
-  perf_tracker_.reset();
-  client_context_.reset();
-  cursor_shape_stub_.reset();
-
-  // Weak factory can only be invalidated once (due to DCHECK in it). After that
-  // the instance will no longer be usable. This is a design flaw that makes the
-  // instance no longer reusable after the caller calls Disconnect. Ideally we
-  // should factor out a Core that lives between (Connect, Disconnect).
-  if (weak_ptr_per_connection_) {
-    weak_factory_per_connection_.InvalidateWeakPtrs();
-  }
+      base::BindOnce(std::forward<Functor>(core_functor), core_->GetWeakPtr(),
+                     std::forward<Args>(args)...));
 }
 
 }  // namespace remoting
diff --git a/remoting/client/chromoting_session.h b/remoting/client/chromoting_session.h
index 241f8cd..a3e6414 100644
--- a/remoting/client/chromoting_session.h
+++ b/remoting/client/chromoting_session.h
@@ -29,27 +29,27 @@
 
 namespace protocol {
 class AudioStub;
-class ClipboardEvent;
-class PerformanceTracker;
 class VideoRenderer;
 }  // namespace protocol
 
 class ChromotingClientRuntime;
 
 // ChromotingSession is scoped to the session.
-// This class is Created on the UI thread but thereafter it is used and
-// destroyed on the network thread. Except where indicated, all methods are
-// called on the network thread.
-class ChromotingSession : public ClientUserInterface,
-                          public protocol::ClipboardStub,
-                          public ClientInputInjector {
+// Construction, destruction, and all method calls must occur on the UI Thread.
+// All callbacks will be posted to the UI Thread.
+// A ChromotingSession instance can be used for at most one connection attempt.
+// If you need to reconnect an ended session, you will need to create a new
+// session instance.
+class ChromotingSession : public ClientInputInjector {
  public:
   // All methods of the delegate are called on the UI threads.
   class Delegate {
    public:
     virtual ~Delegate() {}
 
-    // Notifies Java code of the current connection status.
+    // Notifies the delegate of the current connection status. The delegate
+    // should destroy the ChromotingSession instance when the connection state
+    // is an end state.
     virtual void OnConnectionState(protocol::ConnectionToHost::State state,
                                    protocol::ErrorCode error) = 0;
 
@@ -76,7 +76,7 @@
   using GetFeedbackDataCallback =
       base::OnceCallback<void(std::unique_ptr<FeedbackData>)>;
 
-  // Initiates a connection with the specified host. Call from the UI thread.
+  // Initiates a connection with the specified host.
   ChromotingSession(
       base::WeakPtr<ChromotingSession::Delegate> delegate,
       std::unique_ptr<protocol::CursorShapeStub> cursor_stub,
@@ -87,39 +87,34 @@
 
   ~ChromotingSession() override;
 
-  // Starts the connection. Can be called on any thread.
+  // Starts the connection. Can be called no more than once.
   void Connect();
 
   // Terminates the current connection (if it hasn't already failed) and cleans
-  // up. The instance will no longer be valid after calling this function.
-  // Must be called before destruction.
+  // up.
   void Disconnect();
 
   // Similar to Disconnect(), except that this method allows you to specify the
   // reason to disconnect, which will be reported to telemetry.
   void DisconnectForReason(protocol::ErrorCode error);
 
-  // Requests the client to fetch a third-party token.
-  void FetchThirdPartyToken(
-      const std::string& host_public_key,
-      const std::string& token_url,
-      const std::string& scope,
-      const protocol::ThirdPartyTokenFetchedCallback& token_fetched_callback);
-
   // Gets the current feedback data and returns it to the callback on the
-  // caller's thread. If the session is never connected, then an empty feedback
+  // UI thread. If the session is never connected, then an empty feedback
   // will be returned, otherwise feedback for current session (either still
   // connected or already disconnected) will be returned.
   void GetFeedbackData(GetFeedbackDataCallback callback) const;
 
   // Called by the client when the token is fetched. Can be called on any
   // thread.
+  // TODO(yuweih): Refactor this with ChromotingClientRuntime::token_getter.
   void HandleOnThirdPartyTokenFetched(const std::string& token,
                                       const std::string& shared_secret);
 
   // Provides the user's PIN and resumes the host authentication attempt. Call
   // on the UI thread once the user has finished entering this PIN into the UI,
   // but only after the UI has been asked to provide a PIN (via FetchSecret()).
+  // TODO(yuweih): Rename this to RequestPairing(). PIN is provided by a
+  // completely different codepath.
   void ProvideSecret(const std::string& pin,
                      bool create_pair,
                      const std::string& device_name);
@@ -146,110 +141,34 @@
 
   void SendClientMessage(const std::string& type, const std::string& data);
 
-  // ClientUserInterface implementation.
-  void OnConnectionState(protocol::ConnectionToHost::State state,
-                         protocol::ErrorCode error) override;
-  void OnConnectionReady(bool ready) override;
-  void OnRouteChanged(const std::string& channel_name,
-                      const protocol::TransportRoute& route) override;
-  void SetCapabilities(const std::string& capabilities) override;
-  void SetPairingResponse(const protocol::PairingResponse& response) override;
-  void DeliverHostMessage(const protocol::ExtensionMessage& message) override;
-  void SetDesktopSize(const webrtc::DesktopSize& size,
-                      const webrtc::DesktopVector& dpi) override;
-  protocol::ClipboardStub* GetClipboardStub() override;
-  protocol::CursorShapeStub* GetCursorShapeStub() override;
-
-  // CursorShapeStub implementation.
-  void InjectClipboardEvent(const protocol::ClipboardEvent& event) override;
-
  private:
-  void ConnectToHostOnNetworkThread();
+  struct SessionContext;
+  class Core;
 
-  // Sets the device name. Can be called on any thread.
-  void SetDeviceName(const std::string& device_name);
-
-  void SendKeyEventInternal(int usb_key_code, bool key_down);
-
-  // Enables or disables periodic logging of performance statistics. Called on
-  // the network thread.
-  void EnableStatsLogging(bool enabled);
-
-  // If logging is enabled, logs the current connection statistics, and
-  // triggers another call to this function after the logging time interval.
-  // Called on the network thread.
-  void LogPerfStats();
-
-  void GetFeedbackDataOnNetworkThread(
-      GetFeedbackDataCallback callback,
-      scoped_refptr<base::SingleThreadTaskRunner> response_thread) const;
-
-  // Releases the resource in the right order.
-  void ReleaseResources();
+  template <typename Functor, typename... Args>
+  void RunCoreTaskOnNetworkThread(const base::Location& from_here,
+                                  Functor&& core_functor,
+                                  Args&&... args);
 
   // Used to obtain task runner references.
   ChromotingClientRuntime* runtime_;
 
-  // Called on UI thread.
-  base::WeakPtr<ChromotingSession::Delegate> delegate_;
-  ConnectToHostInfo connection_info_;
-  protocol::ClientAuthenticationConfig client_auth_config_;
+  // Becomes null after the session is connected, and thereafter will not be
+  // reassigned.
+  std::unique_ptr<SessionContext> session_context_;
 
-  // This group of variables is to be used on the network thread.
-  std::unique_ptr<ClientContext> client_context_;
-  std::unique_ptr<protocol::PerformanceTracker> perf_tracker_;
-  std::unique_ptr<protocol::CursorShapeStub> cursor_shape_stub_;
-  std::unique_ptr<protocol::VideoRenderer> video_renderer_;
-  std::unique_ptr<ChromotingClient> client_;
-  XmppSignalStrategy::XmppServerConfig xmpp_config_;
-  std::unique_ptr<XmppSignalStrategy> signaling_;  // Must outlive client_
-  protocol::ThirdPartyTokenFetchedCallback third_party_token_fetched_callback_;
+  // Created when the session is connected, then used, and destroyed on the
+  // network thread when the instance is destroyed.
+  std::unique_ptr<Core> core_;
 
-  // Called on UI Thread.
-  base::WeakPtr<protocol::AudioStub> audio_player_;
-
-  // Indicates whether to establish a new pairing with this host. This is
-  // modified in ProvideSecret(), but thereafter to be used only from the
-  // network thread. (This is safe because ProvideSecret() is invoked at most
-  // once per run, and always before any reference to this flag.)
-  bool create_pairing_ = false;
-
-  // The device name to appear in the paired-clients list. Accessed on the
-  // network thread.
-  std::string device_name_;
-
-  // If this is true, performance statistics will be periodically written to
-  // the Android log. Used on the network thread.
-  bool stats_logging_enabled_ = false;
-
-  // The set of capabilities supported by the client. Accessed on the network
-  // thread. Once SetCapabilities() is called, this will contain the negotiated
-  // set of capabilities for this remoting session.
-  std::string capabilities_;
-
-  // The current session state. Used on network thread.
-  protocol::ConnectionToHost::State session_state_ =
-      protocol::ConnectionToHost::INITIALIZING;
-
-  // The logger is created when the session is connected and destroyed when the
-  // session object is destroyed, rather than when the session is disconnected,
-  // so that caller can have a chance to see logs from a previously disconnected
-  // session.
+  // Created when the session is created, then used, and destroyed on the
+  // network thread when the instance is destroyed. This is stored out of
+  // |core_| to allow accessing logs after |core_| becomes invalid.
   std::unique_ptr<ClientTelemetryLogger> logger_;
 
-  // These weak pointers are used on network thread.
-  base::WeakPtr<ChromotingSession> weak_ptr_per_connection_;
-  base::WeakPtr<ChromotingSession> weak_ptr_per_instance_lifetime_;
-
-  // Both weak_ptr's are constructed when the instance is created, while
-  // |weak_ptr_per_connection_| is invalidated when the session is disconnected,
-  // so that tasks do not leak after the session is disconnected, while
-  // |weak_factory_per_instance_lifetime_| is invalidated when the instace
-  // itself is invalidated.
-  // TODO(crbug/817566): Once we have a shell-core pair, make
-  // |weak_factory_per_connection_| the weak pointer of the core.
-  base::WeakPtrFactory<ChromotingSession> weak_factory_per_connection_;
-  base::WeakPtrFactory<ChromotingSession> weak_factory_per_instance_lifetime_;
+  // This is bound to UI thread.
+  base::WeakPtr<ChromotingSession> weak_ptr_;
+  base::WeakPtrFactory<ChromotingSession> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromotingSession);
 };
diff --git a/remoting/client/client_telemetry_logger.cc b/remoting/client/client_telemetry_logger.cc
index 8adfae9..23dcf82 100644
--- a/remoting/client/client_telemetry_logger.cc
+++ b/remoting/client/client_telemetry_logger.cc
@@ -34,7 +34,9 @@
 ClientTelemetryLogger::ClientTelemetryLogger(
     ChromotingEventLogWriter* log_writer,
     ChromotingEvent::Mode mode)
-    : mode_(mode), log_writer_(log_writer) {}
+    : mode_(mode), log_writer_(log_writer), weak_factory_(this) {
+  thread_checker_.DetachFromThread();
+}
 
 ClientTelemetryLogger::~ClientTelemetryLogger() {
   DCHECK(thread_checker_.CalledOnValidThread());
@@ -90,6 +92,10 @@
   log_writer_->Log(event);
 }
 
+base::WeakPtr<ClientTelemetryLogger> ClientTelemetryLogger::GetWeakPtr() {
+  return weak_factory_.GetWeakPtr();
+}
+
 void ClientTelemetryLogger::PrintLogStatistics(
     protocol::PerformanceTracker* perf_tracker) {
 #if defined(OS_ANDROID)
diff --git a/remoting/client/client_telemetry_logger.h b/remoting/client/client_telemetry_logger.h
index 474de92..dd9b2c1 100644
--- a/remoting/client/client_telemetry_logger.h
+++ b/remoting/client/client_telemetry_logger.h
@@ -11,6 +11,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
 #include "remoting/base/chromoting_event.h"
 #include "remoting/base/chromoting_event_log_writer.h"
 #include "remoting/base/url_request.h"
@@ -21,7 +22,7 @@
 namespace remoting {
 
 // ClientTelemetryLogger sends client log entries to the telemetry server.
-// The logger should be run entirely on one single thread.
+// The logger should be used entirely on one single thread after it is created.
 // TODO(yuweih): Implement new features that session_logger.js provides.
 class ClientTelemetryLogger {
  public:
@@ -52,6 +53,8 @@
     return current_session_state_event_;
   }
 
+  base::WeakPtr<ClientTelemetryLogger> GetWeakPtr();
+
   static ChromotingEvent::SessionState TranslateState(
       protocol::ConnectionToHost::State state);
 
@@ -104,6 +107,7 @@
 
   base::ThreadChecker thread_checker_;
 
+  base::WeakPtrFactory<ClientTelemetryLogger> weak_factory_;
   DISALLOW_COPY_AND_ASSIGN(ClientTelemetryLogger);
 };
 
diff --git a/remoting/client/client_telemetry_logger_unittest.cc b/remoting/client/client_telemetry_logger_unittest.cc
index c2a7176..d58d1e2c 100644
--- a/remoting/client/client_telemetry_logger_unittest.cc
+++ b/remoting/client/client_telemetry_logger_unittest.cc
@@ -60,15 +60,12 @@
   // ChromotingEventLogWriter overrides.
   void Log(const ChromotingEvent& entry) override;
   void SetAuthToken(const std::string& auth_token) override;
-  void SetAuthClosure(const base::Closure& closure) override;
 
   const std::string& auth_token() const { return auth_token_; }
-  const base::Closure& auth_closure() const { return auth_closure_; }
 
  private:
   base::circular_deque<ChromotingEvent> expected_events_;
   std::string auth_token_;
-  base::Closure auth_closure_;
 };
 
 void FakeLogWriter::AddExpectedEvent(const ChromotingEvent& entry) {
@@ -87,10 +84,6 @@
   auth_token_ = auth_token;
 }
 
-void FakeLogWriter::SetAuthClosure(const base::Closure& closure) {
-  auth_closure_ = closure;
-}
-
 class ClientTelemetryLoggerTest : public testing::Test {
  public:
   // testing::Test override.
diff --git a/remoting/client/connect_to_host_info.cc b/remoting/client/connect_to_host_info.cc
index 0cbcf90..dbe612d 100644
--- a/remoting/client/connect_to_host_info.cc
+++ b/remoting/client/connect_to_host_info.cc
@@ -11,4 +11,7 @@
 ConnectToHostInfo::ConnectToHostInfo(ConnectToHostInfo&& other) = default;
 ConnectToHostInfo::~ConnectToHostInfo() = default;
 
+ConnectToHostInfo& ConnectToHostInfo::operator=(
+    const ConnectToHostInfo& other) = default;
+
 }  // namespace remoting
diff --git a/remoting/client/connect_to_host_info.h b/remoting/client/connect_to_host_info.h
index b4a8db3..f8885ea3 100644
--- a/remoting/client/connect_to_host_info.h
+++ b/remoting/client/connect_to_host_info.h
@@ -15,6 +15,8 @@
   ConnectToHostInfo(ConnectToHostInfo&& other);
   ~ConnectToHostInfo();
 
+  ConnectToHostInfo& operator=(const ConnectToHostInfo& other);
+
   std::string username;
   std::string auth_token;
   std::string host_jid;
diff --git a/remoting/client/jni/jni_client.cc b/remoting/client/jni/jni_client.cc
index 3d42b3e..49ec4a1 100644
--- a/remoting/client/jni/jni_client.cc
+++ b/remoting/client/jni/jni_client.cc
@@ -67,11 +67,7 @@
 
 void JniClient::DisconnectFromHost() {
   DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
-  if (session_) {
-    session_->Disconnect();
-    runtime_->network_task_runner()->DeleteSoon(FROM_HERE,
-                                                session_.release());
-  }
+  session_.reset();
   if (secret_fetcher_) {
     runtime_->network_task_runner()->DeleteSoon(FROM_HERE,
                                                 secret_fetcher_.release());
diff --git a/remoting/ios/session/remoting_client.mm b/remoting/ios/session/remoting_client.mm
index c734f27..f82a4d7 100644
--- a/remoting/ios/session/remoting_client.mm
+++ b/remoting/ios/session/remoting_client.mm
@@ -184,10 +184,7 @@
 }
 
 - (void)disconnectFromHost {
-  if (_session) {
-    _session->Disconnect();
-    _runtime->network_task_runner()->DeleteSoon(FROM_HERE, _session.release());
-  }
+  _session.reset();
 
   _displayHandler = nil;
 
diff --git a/services/data_decoder/public/mojom/BUILD.gn b/services/data_decoder/public/mojom/BUILD.gn
index 25fb5fe..edfd0750 100644
--- a/services/data_decoder/public/mojom/BUILD.gn
+++ b/services/data_decoder/public/mojom/BUILD.gn
@@ -14,6 +14,7 @@
   public_deps = [
     ":constants",
     "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//skia/public/interfaces",
     "//ui/gfx/geometry/mojo",
   ]
diff --git a/services/data_decoder/public/mojom/image_decoder.mojom b/services/data_decoder/public/mojom/image_decoder.mojom
index 4fa72b9..20a9166 100644
--- a/services/data_decoder/public/mojom/image_decoder.mojom
+++ b/services/data_decoder/public/mojom/image_decoder.mojom
@@ -4,7 +4,7 @@
 
 module data_decoder.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "skia/public/interfaces/bitmap.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
@@ -16,7 +16,7 @@
 
 struct AnimationFrame {
   skia.mojom.Bitmap bitmap;
-  mojo.common.mojom.TimeDelta duration;
+  mojo_base.mojom.TimeDelta duration;
 };
 
 interface ImageDecoder {
diff --git a/services/device/public/mojom/BUILD.gn b/services/device/public/mojom/BUILD.gn
index fc5fb1f..82a26f7 100644
--- a/services/device/public/mojom/BUILD.gn
+++ b/services/device/public/mojom/BUILD.gn
@@ -32,7 +32,7 @@
 
   public_deps = [
     ":constants",
-    "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//services/network/public/mojom",
     "//services/network/public/mojom:mutable_network_traffic_annotation_interface",
   ]
diff --git a/services/device/public/mojom/geoposition.mojom b/services/device/public/mojom/geoposition.mojom
index a64e9b7..0fd5b0c 100644
--- a/services/device/public/mojom/geoposition.mojom
+++ b/services/device/public/mojom/geoposition.mojom
@@ -4,7 +4,7 @@
 
 module device.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 // Sentinel values to mark invalid data. (WebKit carries companion is_valid
 // bools for this purpose; we may eventually follow that approach, but
@@ -51,7 +51,7 @@
   // Time of position measurement in seconds since the Windows FILETIME epoch
   // (1601-01-01 00:00:00 UTC). This is taken from the host computer's system
   // clock (i.e. from Time::Now(), not the source device's clock).
-  mojo.common.mojom.Time timestamp;
+  mojo_base.mojom.Time timestamp;
 
   // Error code, see enum above.
   ErrorCode error_code = NONE;
diff --git a/services/identity/public/mojom/BUILD.gn b/services/identity/public/mojom/BUILD.gn
index fbfa2ea..1614d49b 100644
--- a/services/identity/public/mojom/BUILD.gn
+++ b/services/identity/public/mojom/BUILD.gn
@@ -16,7 +16,7 @@
 
   public_deps = [
     ":constants",
-    "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//url/mojom:url_mojom_gurl",
   ]
 }
diff --git a/services/identity/public/mojom/identity_manager.mojom b/services/identity/public/mojom/identity_manager.mojom
index 4410269a..789d8e6 100644
--- a/services/identity/public/mojom/identity_manager.mojom
+++ b/services/identity/public/mojom/identity_manager.mojom
@@ -4,7 +4,7 @@
 
 module identity.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "services/identity/public/mojom/account.mojom";
 import "services/identity/public/mojom/account_info.mojom";
 import "services/identity/public/mojom/account_state.mojom";
@@ -50,6 +50,6 @@
   // NOTE: |account_id| corresponds to that used by OAuth2TokenService.
   GetAccessToken(string account_id, ScopeSet scopes, string consumer_id) =>
      (string? token,
-      mojo.common.mojom.Time expiration_time,
+      mojo_base.mojom.Time expiration_time,
       GoogleServiceAuthError error);
 };
diff --git a/services/network/public/cpp/cookie_manager_mojom_traits.cc b/services/network/public/cpp/cookie_manager_mojom_traits.cc
index 19ae612f..f283864 100644
--- a/services/network/public/cpp/cookie_manager_mojom_traits.cc
+++ b/services/network/public/cpp/cookie_manager_mojom_traits.cc
@@ -4,7 +4,7 @@
 
 #include "services/network/public/cpp/cookie_manager_mojom_traits.h"
 
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 
 namespace mojo {
 
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn
index 835461c..595ad7f 100644
--- a/services/network/public/mojom/BUILD.gn
+++ b/services/network/public/mojom/BUILD.gn
@@ -80,7 +80,6 @@
     ":data_pipe_interfaces",
     ":mutable_network_traffic_annotation_interface",
     ":udp_socket_interface",
-    "//mojo/common:common_custom_types",
     "//mojo/public/mojom/base",
     "//net/interfaces",
     "//services/proxy_resolver/public/mojom",
diff --git a/services/network/public/mojom/cookie_manager.mojom b/services/network/public/mojom/cookie_manager.mojom
index d1df23d..2eb1788 100644
--- a/services/network/public/mojom/cookie_manager.mojom
+++ b/services/network/public/mojom/cookie_manager.mojom
@@ -4,7 +4,7 @@
 
 module network.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "url/mojom/url.mojom";
 
 enum CookiePriority {
@@ -35,7 +35,7 @@
   bool update_access_time = true;
   // TODO(rdsmith): Remove this element from the mojo structure?  It's only
   // used in the underlying net:: structure in CanonicalCookie::Create().
-  mojo.common.mojom.Time? server_time;
+  mojo_base.mojom.Time? server_time;
 };
 
 // See net/cookies/canonical_cookie.{h,cc} for documentation.
@@ -45,9 +45,9 @@
   string value;
   string domain;
   string path;
-  mojo.common.mojom.Time? creation;
-  mojo.common.mojom.Time? expiry;
-  mojo.common.mojom.Time? last_access;
+  mojo_base.mojom.Time? creation;
+  mojo_base.mojom.Time? expiry;
+  mojo_base.mojom.Time? last_access;
   bool secure = false;
   bool httponly = false;
   CookieSameSite site_restrictions = NO_RESTRICTION;
@@ -106,10 +106,10 @@
 //        address or private hostname) is used.
 struct CookieDeletionFilter {
   // Delete cookies created after a date.
-  mojo.common.mojom.Time? created_after_time;
+  mojo_base.mojom.Time? created_after_time;
 
   // Delete cookies created before a date.
-  mojo.common.mojom.Time? created_before_time;
+  mojo_base.mojom.Time? created_before_time;
 
   // Delete cookies whose domains are not listed.
   array<string>? excluding_domains;
diff --git a/services/network/public/mojom/network_service.mojom b/services/network/public/mojom/network_service.mojom
index eaa3144..d4f44f8 100644
--- a/services/network/public/mojom/network_service.mojom
+++ b/services/network/public/mojom/network_service.mojom
@@ -4,8 +4,8 @@
 
 module network.mojom;
 
-import "mojo/common/time.mojom";
 import "mojo/public/mojom/base/file_path.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "net/interfaces/address_list.mojom";
 import "net/interfaces/ip_endpoint.mojom";
 import "services/network/public/mojom/cookie_manager.mojom";
@@ -116,7 +116,7 @@
 
   // Channel round-trip latency, i.e. minimum time between request sent and
   // response received.
-  mojo.common.mojom.TimeDelta latency;
+  mojo_base.mojom.TimeDelta latency;
 
   // Maximal aggregated download throughput (bytes/sec). 0 disables download throttling.
   double download_throughput;
@@ -167,13 +167,13 @@
   // only covers server properties and transport security state.
   //
   // The callback will be invoked once the data has been deleted.
-  ClearNetworkingHistorySince(mojo.common.mojom.Time start_time) => ();
+  ClearNetworkingHistorySince(mojo_base.mojom.Time start_time) => ();
 
   // Clears content from the HTTP cache. A specific range of time can be
   // specified with |start_time| and |end_time|. This supports unbounded deletes
   // in either direction by using null Time values for either argument.
-  ClearHttpCache(mojo.common.mojom.Time start_time,
-                 mojo.common.mojom.Time end_time,
+  ClearHttpCache(mojo_base.mojom.Time start_time,
+                 mojo_base.mojom.Time end_time,
                  ClearCacheUrlFilter? filter) => ();
 
   // Configures network conditions for the specified throttling profile.
@@ -237,7 +237,7 @@
   // Adds explicitly-specified data as if it was processed from an
   // HSTS header.
   AddHSTSForTesting(string host,
-                    mojo.common.mojom.Time expiry,
+                    mojo_base.mojom.Time expiry,
                     bool include_subdomains) => ();
 };
 
diff --git a/services/network/public/mojom/restricted_cookie_manager.mojom b/services/network/public/mojom/restricted_cookie_manager.mojom
index 96143fc3..97d2fc4 100644
--- a/services/network/public/mojom/restricted_cookie_manager.mojom
+++ b/services/network/public/mojom/restricted_cookie_manager.mojom
@@ -5,7 +5,7 @@
 module network.mojom;
 
 import "services/network/public/mojom/cookie_manager.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "url/mojom/url.mojom";
 
 enum CookieMatchType {
diff --git a/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc b/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
index df0d758..f703f67 100644
--- a/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
+++ b/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
@@ -341,6 +341,9 @@
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   QueuedRequest* request = GetCurrentRequest();
 
+  if (request == nullptr)
+    return;
+
   std::vector<QueuedRequestDispatcher::ClientInfo> clients;
   for (const auto& kv : clients_) {
     auto client_identity = kv.second->identity;
diff --git a/services/resource_coordinator/public/mojom/BUILD.gn b/services/resource_coordinator/public/mojom/BUILD.gn
index a0297d63..9ba1694 100644
--- a/services/resource_coordinator/public/mojom/BUILD.gn
+++ b/services/resource_coordinator/public/mojom/BUILD.gn
@@ -21,6 +21,7 @@
 
   public_deps = [
     "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//services/metrics/public/mojom",
   ]
 
diff --git a/services/resource_coordinator/public/mojom/coordination_unit.mojom b/services/resource_coordinator/public/mojom/coordination_unit.mojom
index c086930..0ede349 100644
--- a/services/resource_coordinator/public/mojom/coordination_unit.mojom
+++ b/services/resource_coordinator/public/mojom/coordination_unit.mojom
@@ -4,7 +4,7 @@
 
 module resource_coordinator.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "services/resource_coordinator/public/mojom/signals.mojom";
 
 // Any new type here needs to be mirrored between coordination_unit_types.h and
@@ -79,8 +79,8 @@
 
   // Property signals.
   SetCPUUsage(double cpu_usage);
-  SetExpectedTaskQueueingDuration(mojo.common.mojom.TimeDelta duration);
-  SetLaunchTime(mojo.common.mojom.Time launch_time);
+  SetExpectedTaskQueueingDuration(mojo_base.mojom.TimeDelta duration);
+  SetLaunchTime(mojo_base.mojom.Time launch_time);
   SetMainThreadTaskLoadIsLow(bool main_thread_task_load_is_low);
   SetPID(int64 pid);
 };
diff --git a/services/resource_coordinator/public/mojom/coordination_unit_introspector.mojom b/services/resource_coordinator/public/mojom/coordination_unit_introspector.mojom
index a19f567..912a2bbc 100644
--- a/services/resource_coordinator/public/mojom/coordination_unit_introspector.mojom
+++ b/services/resource_coordinator/public/mojom/coordination_unit_introspector.mojom
@@ -6,19 +6,19 @@
 
 import "services/resource_coordinator/public/mojom/coordination_unit.mojom";
 import "mojo/common/process_id.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 struct PageInfo {
   int64 ukm_source_id;
   bool is_visible;
-  mojo.common.mojom.TimeDelta time_since_last_navigation;
-  mojo.common.mojom.TimeDelta time_since_last_visibility_change;
+  mojo_base.mojom.TimeDelta time_since_last_navigation;
+  mojo_base.mojom.TimeDelta time_since_last_visibility_change;
 };
 
 struct ProcessInfo {
   mojo.common.mojom.ProcessId pid;
   array<PageInfo> page_infos;
-  mojo.common.mojom.Time? launch_time;
+  mojo_base.mojom.Time? launch_time;
 };
 
 interface CoordinationUnitIntrospector {
diff --git a/services/resource_coordinator/public/mojom/page_signal.mojom b/services/resource_coordinator/public/mojom/page_signal.mojom
index 318cbfe..4eeec2a 100644
--- a/services/resource_coordinator/public/mojom/page_signal.mojom
+++ b/services/resource_coordinator/public/mojom/page_signal.mojom
@@ -5,7 +5,7 @@
 module resource_coordinator.mojom;
 
 import "services/resource_coordinator/public/mojom/coordination_unit.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 // A PageSignalReceiver implementation receives page-scoped signal from
 // PageSignalGenerator.
@@ -16,7 +16,7 @@
 interface PageSignalReceiver {
   NotifyPageAlmostIdle(CoordinationUnitID cu_id);
   SetExpectedTaskQueueingDuration(CoordinationUnitID cu_id,
-                                  mojo.common.mojom.TimeDelta duration);
+                                  mojo_base.mojom.TimeDelta duration);
 };
 
 // A PageSignalGenerator implementation will be implemented inside GRC to receive
diff --git a/services/tracing/public/mojom/BUILD.gn b/services/tracing/public/mojom/BUILD.gn
index ebfa6b9..5c5a1aa 100644
--- a/services/tracing/public/mojom/BUILD.gn
+++ b/services/tracing/public/mojom/BUILD.gn
@@ -15,6 +15,7 @@
 
   public_deps = [
     "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
   ]
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
diff --git a/services/tracing/public/mojom/tracing.mojom b/services/tracing/public/mojom/tracing.mojom
index 39a74c1..51a84d6 100644
--- a/services/tracing/public/mojom/tracing.mojom
+++ b/services/tracing/public/mojom/tracing.mojom
@@ -4,7 +4,7 @@
 
 module tracing.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "mojo/common/values.mojom";
 
 // The JSON type of data coming from a tracing agents.
@@ -37,12 +37,12 @@
 // close the recorder connection to signal the tracing service that no more data
 // will be sent.
 interface Agent {
-  StartTracing(string config, mojo.common.mojom.TimeTicks coordinator_time) => (
+  StartTracing(string config, mojo_base.mojom.TimeTicks coordinator_time) => (
       bool success);
   StopAndFlush(Recorder recorder);
   RequestClockSyncMarker(string sync_id) => (
-      mojo.common.mojom.TimeTicks issue_ts,
-      mojo.common.mojom.TimeTicks issue_end_ts);
+      mojo_base.mojom.TimeTicks issue_ts,
+      mojo_base.mojom.TimeTicks issue_end_ts);
   RequestBufferStatus() => (uint32 capacity, uint32 count);
   GetCategories() => (string categories);
 };
diff --git a/services/ui/public/interfaces/cursor/BUILD.gn b/services/ui/public/interfaces/cursor/BUILD.gn
index 28dc7a4..d4b3bac1 100644
--- a/services/ui/public/interfaces/cursor/BUILD.gn
+++ b/services/ui/public/interfaces/cursor/BUILD.gn
@@ -11,6 +11,7 @@
 
   public_deps = [
     "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//skia/public/interfaces",
     "//ui/gfx/geometry/mojo",
   ]
diff --git a/services/ui/public/interfaces/cursor/cursor.mojom b/services/ui/public/interfaces/cursor/cursor.mojom
index a4f5806..ae4e4533 100644
--- a/services/ui/public/interfaces/cursor/cursor.mojom
+++ b/services/ui/public/interfaces/cursor/cursor.mojom
@@ -4,7 +4,7 @@
 
 module ui.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "skia/public/interfaces/bitmap.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
@@ -73,7 +73,7 @@
   CursorType cursor_type;
 
   // The delay between cursor frames.
-  mojo.common.mojom.TimeDelta frame_delay;
+  mojo_base.mojom.TimeDelta frame_delay;
 
   // The hotspot in pixels in the source cursor frames.
   gfx.mojom.Point hotspot_in_pixels;
diff --git a/services/ui/public/interfaces/cursor/cursor_struct_traits.cc b/services/ui/public/interfaces/cursor/cursor_struct_traits.cc
index aa09a4d5..5bf9d17 100644
--- a/services/ui/public/interfaces/cursor/cursor_struct_traits.cc
+++ b/services/ui/public/interfaces/cursor/cursor_struct_traits.cc
@@ -5,7 +5,7 @@
 #include "services/ui/public/interfaces/cursor/cursor_struct_traits.h"
 
 #include "mojo/common/common_custom_types_struct_traits.h"
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "services/ui/public/interfaces/cursor/cursor.mojom.h"
 #include "skia/public/interfaces/bitmap_skbitmap_struct_traits.h"
 #include "third_party/skia/include/core/SkBitmap.h"
diff --git a/services/ui/public/interfaces/cursor/cursor_struct_traits_unittest.cc b/services/ui/public/interfaces/cursor/cursor_struct_traits_unittest.cc
index e37ea64..17ca5a4 100644
--- a/services/ui/public/interfaces/cursor/cursor_struct_traits_unittest.cc
+++ b/services/ui/public/interfaces/cursor/cursor_struct_traits_unittest.cc
@@ -5,7 +5,7 @@
 #include "services/ui/public/interfaces/cursor/cursor_struct_traits.h"
 
 #include "base/message_loop/message_loop.h"
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/ui/public/interfaces/cursor/cursor.mojom.h"
 #include "skia/public/interfaces/bitmap_skbitmap_struct_traits.h"
diff --git a/services/ui/public/interfaces/input_devices/input_device_controller.mojom b/services/ui/public/interfaces/input_devices/input_device_controller.mojom
index 4d9dfa8..2d97bdf30 100644
--- a/services/ui/public/interfaces/input_devices/input_device_controller.mojom
+++ b/services/ui/public/interfaces/input_devices/input_device_controller.mojom
@@ -4,8 +4,8 @@
 
 module ui.mojom;
 
-import "mojo/common/time.mojom";
 import "mojo/public/mojom/base/file_path.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "ui/events/devices/mojo/input_devices.mojom";
 
 struct KeyboardDeviceState {
@@ -31,8 +31,8 @@
   SetCapsLockEnabled(bool enabled);
   SetNumLockEnabled(bool enabled);
   SetAutoRepeatEnabled(bool enabled);
-  SetAutoRepeatRate(mojo.common.mojom.TimeDelta auto_repeat_delay,
-                    mojo.common.mojom.TimeDelta auto_repeat_interval);
+  SetAutoRepeatRate(mojo_base.mojom.TimeDelta auto_repeat_delay,
+                    mojo_base.mojom.TimeDelta auto_repeat_interval);
   SetKeyboardLayoutByName(string name);
 
   // Touchpad settings.
diff --git a/services/video_capture/device_factory_provider_impl.cc b/services/video_capture/device_factory_provider_impl.cc
index 3b70305..04f181a 100644
--- a/services/video_capture/device_factory_provider_impl.cc
+++ b/services/video_capture/device_factory_provider_impl.cc
@@ -59,7 +59,9 @@
           nullptr,
           // TODO(mojahsu): Create a GpuJpegDecoderMojoFactoryCB here.
           base::BindRepeating(
-              [](media::mojom::JpegDecodeAcceleratorRequest) {}));
+              [](media::mojom::JpegDecodeAcceleratorRequest) {}),
+          base::BindRepeating(
+              [](media::mojom::JpegEncodeAcceleratorRequest) {}));
   auto video_capture_system = std::make_unique<media::VideoCaptureSystemImpl>(
       std::move(media_device_factory));
 
diff --git a/services/viz/privileged/interfaces/compositing/BUILD.gn b/services/viz/privileged/interfaces/compositing/BUILD.gn
index 843f111..cbd4d1da 100644
--- a/services/viz/privileged/interfaces/compositing/BUILD.gn
+++ b/services/viz/privileged/interfaces/compositing/BUILD.gn
@@ -17,7 +17,7 @@
     "//gpu/ipc/common:interfaces",
     "//media/capture/mojom:video_capture",
     "//media/mojo/interfaces:interfaces",
-    "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//services/viz/public/interfaces",
     "//ui/gfx/geometry/mojo",
     "//ui/gfx/mojo",
diff --git a/services/viz/privileged/interfaces/compositing/display_private.mojom b/services/viz/privileged/interfaces/compositing/display_private.mojom
index f2082e6..fa85cf40 100644
--- a/services/viz/privileged/interfaces/compositing/display_private.mojom
+++ b/services/viz/privileged/interfaces/compositing/display_private.mojom
@@ -4,7 +4,7 @@
 
 module viz.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "ui/gfx/mojo/ca_layer_params.mojom";
 import "ui/gfx/mojo/color_space.mojom";
 import "ui/gfx/mojo/transform.mojom";
@@ -26,13 +26,13 @@
   // Locks the vsync interval used to generate BeginFrames for this display to
   // |interval|. Changes to vsync interval from other sources will be ignored.
   // This will do nothing if the display is using an external BeginFrame source.
-  SetAuthoritativeVSyncInterval(mojo.common.mojom.TimeDelta interval);
+  SetAuthoritativeVSyncInterval(mojo_base.mojom.TimeDelta interval);
 
   // Updates vsync parameters used to generate BeginFrames for this display.
   // This will do nothing if the display is using an external BeginFrame source.
   SetDisplayVSyncParameters(
-    mojo.common.mojom.TimeTicks timebase,
-    mojo.common.mojom.TimeDelta interval);
+    mojo_base.mojom.TimeTicks timebase,
+    mojo_base.mojom.TimeDelta interval);
 };
 
 interface DisplayClient {
diff --git a/services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom b/services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom
index faceda7..028f5528 100644
--- a/services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom
+++ b/services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom
@@ -5,7 +5,7 @@
 module viz.mojom;
 
 import "gpu/ipc/common/surface_handle.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "services/viz/privileged/interfaces/compositing/display_private.mojom";
 import "services/viz/privileged/interfaces/compositing/external_begin_frame_controller.mojom";
 import "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom";
diff --git a/services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom b/services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom
index f9f3747..aefe35f9 100644
--- a/services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom
+++ b/services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom
@@ -6,7 +6,7 @@
 
 import "media/capture/mojom/video_capture_types.mojom";
 import "media/mojo/interfaces/media_types.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "services/viz/public/interfaces/compositing/frame_sink_id.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
@@ -84,7 +84,7 @@
   // Default, if never called: a very conservative 1/5 second (for 5 FPS
   // max). Usually 30-60 FPS is desired for frame sinks that may contain video
   // content.
-  SetMinCapturePeriod(mojo.common.mojom.TimeDelta min_period);
+  SetMinCapturePeriod(mojo_base.mojom.TimeDelta min_period);
 
   // Specifies the minimum amount of time that must elapse between changing the
   // size of video frames. This can be set to zero to disable resize throttling,
@@ -93,7 +93,7 @@
   // consider disabling auto-throttling in such cases.
   //
   // Default, if never called: 3 seconds.
-  SetMinSizeChangePeriod(mojo.common.mojom.TimeDelta min_period);
+  SetMinSizeChangePeriod(mojo_base.mojom.TimeDelta min_period);
 
   // Specifies the range (if any) of acceptable capture resolutions and whether
   // a fixed aspect ratio is required. When |min_size| is equal to |max_size|,
diff --git a/services/viz/privileged/interfaces/gl/gpu_service.mojom b/services/viz/privileged/interfaces/gl/gpu_service.mojom
index 528698ed..f060ee1 100644
--- a/services/viz/privileged/interfaces/gl/gpu_service.mojom
+++ b/services/viz/privileged/interfaces/gl/gpu_service.mojom
@@ -12,6 +12,7 @@
 import "gpu/ipc/common/surface_handle.mojom";
 import "gpu/ipc/common/sync_token.mojom";
 import "media/mojo/interfaces/jpeg_decode_accelerator.mojom";
+import "media/mojo/interfaces/jpeg_encode_accelerator.mojom";
 import "media/mojo/interfaces/video_encode_accelerator.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 import "ui/gfx/mojo/buffer_types.mojom";
@@ -40,6 +41,9 @@
   // Creates a new JpegDecodeAccelerator and binds it to |jda|.
   CreateJpegDecodeAccelerator(media.mojom.JpegDecodeAccelerator& jda);
 
+  // Creates a new JpegEncodeAccelerator and binds it to |jea|.
+  CreateJpegEncodeAccelerator(media.mojom.JpegEncodeAccelerator& jea);
+
   // Creates a VideoEncodeAcceleratorProvider and binds it to |vea_provider|.
   CreateVideoEncodeAcceleratorProvider(
       media.mojom.VideoEncodeAcceleratorProvider& vea_provider);
diff --git a/services/viz/public/cpp/compositing/begin_frame_args_struct_traits.cc b/services/viz/public/cpp/compositing/begin_frame_args_struct_traits.cc
index 7f5db93..e03765ae 100644
--- a/services/viz/public/cpp/compositing/begin_frame_args_struct_traits.cc
+++ b/services/viz/public/cpp/compositing/begin_frame_args_struct_traits.cc
@@ -4,7 +4,7 @@
 
 #include "services/viz/public/cpp/compositing/begin_frame_args_struct_traits.h"
 
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 
 namespace mojo {
 
diff --git a/services/viz/public/cpp/compositing/frame_deadline_struct_traits.h b/services/viz/public/cpp/compositing/frame_deadline_struct_traits.h
index 8770b1b5..2945a61 100644
--- a/services/viz/public/cpp/compositing/frame_deadline_struct_traits.h
+++ b/services/viz/public/cpp/compositing/frame_deadline_struct_traits.h
@@ -8,7 +8,7 @@
 #include "services/viz/public/interfaces/compositing/frame_deadline.mojom.h"
 
 #include "components/viz/common/quads/frame_deadline.h"
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 
 namespace mojo {
 
diff --git a/services/viz/public/cpp/compositing/struct_traits_unittest.cc b/services/viz/public/cpp/compositing/struct_traits_unittest.cc
index 7433f9f..a3249f05 100644
--- a/services/viz/public/cpp/compositing/struct_traits_unittest.cc
+++ b/services/viz/public/cpp/compositing/struct_traits_unittest.cc
@@ -23,7 +23,7 @@
 #include "gpu/ipc/common/mailbox_struct_traits.h"
 #include "gpu/ipc/common/sync_token_struct_traits.h"
 #include "ipc/ipc_message_utils.h"
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/viz/public/cpp/compositing/begin_frame_args_struct_traits.h"
 #include "services/viz/public/cpp/compositing/compositor_frame_metadata_struct_traits.h"
diff --git a/services/viz/public/interfaces/BUILD.gn b/services/viz/public/interfaces/BUILD.gn
index 1cad4c4..9bbb279 100644
--- a/services/viz/public/interfaces/BUILD.gn
+++ b/services/viz/public/interfaces/BUILD.gn
@@ -39,6 +39,7 @@
   public_deps = [
     "//gpu/ipc/common:interfaces",
     "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//skia/public/interfaces",
     "//ui/gfx/geometry/mojo",
     "//ui/gfx/mojo",
diff --git a/services/viz/public/interfaces/compositing/begin_frame_args.mojom b/services/viz/public/interfaces/compositing/begin_frame_args.mojom
index d6472ee..d440f60f 100644
--- a/services/viz/public/interfaces/compositing/begin_frame_args.mojom
+++ b/services/viz/public/interfaces/compositing/begin_frame_args.mojom
@@ -4,7 +4,7 @@
 
 module viz.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 enum BeginFrameArgsType {
   INVALID,
@@ -15,9 +15,9 @@
 
 // See cc/output/begin_frame_args.h.
 struct BeginFrameArgs {
-  mojo.common.mojom.TimeTicks frame_time;
-  mojo.common.mojom.TimeTicks deadline;
-  mojo.common.mojom.TimeDelta interval;
+  mojo_base.mojom.TimeTicks frame_time;
+  mojo_base.mojom.TimeTicks deadline;
+  mojo_base.mojom.TimeDelta interval;
   uint64 source_id;
   uint64 sequence_number;
   BeginFrameArgsType type;
diff --git a/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom b/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom
index c1b95a4..07e7afc 100644
--- a/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom
+++ b/services/viz/public/interfaces/compositing/compositor_frame_sink.mojom
@@ -4,7 +4,7 @@
 
 module viz.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "services/viz/public/interfaces/compositing/begin_frame_args.mojom";
 import "services/viz/public/interfaces/compositing/compositor_frame.mojom";
 import "services/viz/public/interfaces/compositing/local_surface_id.mojom";
@@ -79,8 +79,8 @@
   // presentation time, |refresh| indicates the time till next refresh, |flags|
   // is a combination of |gfx::PresentationFlags|.
   DidPresentCompositorFrame(uint32 presentation_token,
-                            mojo.common.mojom.TimeTicks time,
-                            mojo.common.mojom.TimeDelta refresh,
+                            mojo_base.mojom.TimeTicks time,
+                            mojo_base.mojom.TimeDelta refresh,
                             uint32 flags);
 
   // Notification that a CompositorFrame with given presentation_token has been
diff --git a/services/viz/public/interfaces/compositing/frame_deadline.mojom b/services/viz/public/interfaces/compositing/frame_deadline.mojom
index 851e0b2..ceb7310f 100644
--- a/services/viz/public/interfaces/compositing/frame_deadline.mojom
+++ b/services/viz/public/interfaces/compositing/frame_deadline.mojom
@@ -4,11 +4,11 @@
 
 module viz.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 struct FrameDeadline {
-  mojo.common.mojom.TimeTicks frame_start_time;
+  mojo_base.mojom.TimeTicks frame_start_time;
   uint32 deadline_in_frames;
-  mojo.common.mojom.TimeDelta frame_interval;
+  mojo_base.mojom.TimeDelta frame_interval;
   bool use_default_lower_bound_deadline;
 };
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 23925ed..918c6dc 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -3920,7 +3920,8 @@
     "gtest_tests": [
       {
         "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.base_unittests.filter"
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.base_unittests.filter",
+          "--use-new-test-runner"
         ],
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -3970,8 +3971,7 @@
       },
       {
         "args": [
-          "--use-new-test-runner",
-          "-v"
+          "--use-new-test-runner"
         ],
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -3985,7 +3985,8 @@
       },
       {
         "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ipc_tests.filter"
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ipc_tests.filter",
+          "--use-new-test-runner"
         ],
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -3998,6 +3999,9 @@
         "test": "ipc_tests"
       },
       {
+        "args": [
+          "--use-new-test-runner"
+        ],
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -4025,7 +4029,8 @@
       },
       {
         "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.mojo_unittests.filter"
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.mojo_unittests.filter",
+          "--use-new-test-runner"
         ],
         "swarming": {
           "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json
index 48f2f52d..b6378741 100644
--- a/testing/buildbot/chromium.perf.fyi.json
+++ b/testing/buildbot/chromium.perf.fyi.json
@@ -454,8 +454,7 @@
           "-v",
           "--upload-results",
           "--output-format=chartjson",
-          "--browser=release",
-          "--xvfb"
+          "--browser=release"
         ],
         "isolate_name": "telemetry_perf_tests",
         "name": "loading.desktop.network_service",
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index b3bc9f05..890baed 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -4722,7 +4722,7 @@
     "isolated_scripts": [
       {
         "args": [
-          "--shard-timeout=180"
+          "--shard-timeout=300"
         ],
         "isolate_name": "angle_perftests",
         "name": "angle_perftests",
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
index 6403a58e..f005267a 100644
--- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -324,6 +324,9 @@
 -SBNavigationObserverBrowserTest.DownloadViaHTML5FileApi
 -ProcessManagerBrowserTest.NestedURLNavigationsToExtensionBlocked
 
+# Fails because data: URL is not downloaded but navigated to.
+-BrowserActionApiTest.BrowserActionPopupDownload
+
 # Flakes https://logs.chromium.org/v/?s=chromium%2Fbb%2Fchromium.linux%2FLinux_Tests%2F65822%2F%2B%2Frecipes%2Fsteps%2Fnetwork_service_browser_tests%2F0%2Flogs%2FNoSessionRestoreTest.PRE_CookiesClearedOnExit%2F0
 -NoSessionRestoreTest.CookiesClearedOnExit
 
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index b4210a1..01719a2 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -187,6 +187,11 @@
         },
       },
       # chromium.fyi
+      'Fuchsia': {
+        'args': [
+          '--use-new-test-runner',
+        ],
+      },
       'Out of Process Profiling Mac': {
         'swarming': {
           'shards': 5,
@@ -1448,7 +1453,6 @@
       'Fuchsia': {
         'args': [
           '--use-new-test-runner',
-          '-v',  # Useful for getting debug info and SCP throughput stats.
         ],
       },
     },
@@ -2058,6 +2062,12 @@
           '600',
         ],
       },
+      # chromium.fyi
+      'Fuchsia': {
+        'args': [
+          '--use-new-test-runner',
+        ],
+      },
     },
   },
   'jingle_unittests': {
@@ -2233,6 +2243,14 @@
       # chromium.fyi
       'Fuchsia ARM64',
     ],
+    'modifications': {
+      # chromium.fyi
+      'Fuchsia': {
+        'args': [
+          '--use-new-test-runner',
+        ],
+      },
+    },
   },
   'message_center_unittests': {
     'remove_from': [
@@ -2394,6 +2412,16 @@
       },
     },
   },
+  'mojo_unittests': {
+    'modifications': {
+      # chromium.fyi
+      'Fuchsia': {
+        'args': [
+          '--use-new-test-runner',
+        ],
+      },
+    },
+  },
   'nacl_helper_nonsfi_unittests': {
     'remove_from': [
       # chromium.clang
diff --git a/third_party/.gitignore b/third_party/.gitignore
index 255183b..4831896 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -85,6 +85,7 @@
 /gperf
 /guava/lib/
 /hamcrest/lib/
+/harfbuzz-ng/src
 /hunspell_dictionaries
 /icu
 /icu4j/lib/
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index f32266b..9dee7e2 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -61,7 +61,7 @@
 crbug.com/714962 accessibility/bounds-calc.html [ Failure ]
 crbug.com/591099 accessibility/canvas-fallback-content-2.html [ Timeout ]
 crbug.com/591099 accessibility/computed-name.html [ Timeout ]
-crbug.com/591099 accessibility/computed-role.html [ Timeout ]
+crbug.com/591099 accessibility/computed-role.html [ Pass Timeout ]
 crbug.com/714962 accessibility/css-first-letter-children.html [ Failure ]
 crbug.com/591099 accessibility/css-generated-content.html [ Failure ]
 crbug.com/591099 accessibility/css-styles.html [ Failure ]
@@ -99,7 +99,7 @@
 crbug.com/591099 animations/interpolation/backdrop-filter-interpolation.html [ Timeout ]
 crbug.com/591099 animations/interpolation/line-height-interpolation.html [ Timeout ]
 crbug.com/591099 animations/interpolation/svg-stroke-dasharray-interpolation.html [ Timeout ]
-crbug.com/591099 animations/interpolation/webkit-clip-path-interpolation.html [ Timeout ]
+crbug.com/591099 animations/interpolation/webkit-clip-path-interpolation.html [ Pass Timeout ]
 crbug.com/591099 animations/rotate-transform-equivalent.html [ Failure ]
 crbug.com/591099 animations/timing/timing-model.html [ Timeout ]
 crbug.com/714962 compositing/background-color/view-blending-base-background.html [ Failure ]
@@ -129,8 +129,6 @@
 crbug.com/591099 compositing/scrollbars/nested-overlay-scrollbars.html [ Failure ]
 crbug.com/591099 compositing/squashing/add-remove-squashed-layers.html [ Failure ]
 crbug.com/591099 compositing/squashing/selection-repaint-with-gaps.html [ Failure ]
-crbug.com/591099 compositing/squashing/squash-onto-distant-relative.html [ Crash Pass ]
-crbug.com/591099 compositing/squashing/vertical-writing-mode-squashed.html [ Failure ]
 crbug.com/591099 crypto/subtle/hkdf/cloneKey.html [ Timeout ]
 crbug.com/591099 crypto/subtle/hmac/cloneKey.html [ Timeout ]
 crbug.com/591099 crypto/subtle/pbkdf2/cloneKey.html [ Timeout ]
@@ -140,7 +138,6 @@
 crbug.com/591099 css1/classification/list_style.html [ Failure ]
 crbug.com/591099 css1/classification/list_style_image.html [ Failure ]
 crbug.com/591099 css1/font_properties/font_variant.html [ Failure ]
-crbug.com/591099 css1/pseudo/multiple_pseudo_elements.html [ Crash Failure ]
 crbug.com/591099 css2.1/20110323/margin-applies-to-008.htm [ Failure ]
 crbug.com/714962 css2.1/20110323/overflow-applies-to-012.htm [ Failure ]
 crbug.com/591099 css2.1/20110323/table-caption-margins-001.htm [ Failure ]
@@ -188,17 +185,12 @@
 crbug.com/591099 css3/selectors3/xml/css3-modsel-167a.xml [ Failure ]
 crbug.com/591099 css3/selectors3/xml/css3-modsel-179a.xml [ Failure ]
 crbug.com/591099 css3/selectors3/xml/css3-modsel-38.xml [ Failure ]
-crbug.com/714962 css3/unicode-bidi-isolate-basic.html [ Failure Pass ]
 crbug.com/591099 editing/assert_selection.html [ Failure ]
 crbug.com/591099 editing/caret/caret-color-014.html [ Failure ]
 crbug.com/591099 editing/caret/caret-color-015.html [ Failure ]
 crbug.com/591099 editing/deleting/5272440.html [ Failure ]
-crbug.com/591099 editing/deleting/delete-at-paragraph-boundaries-011.html [ Failure ]
-crbug.com/591099 editing/deleting/merge-different-styles.html [ Failure ]
-crbug.com/591099 editing/deleting/merge-endOfParagraph.html [ Failure ]
 crbug.com/591099 editing/deleting/merge-no-br.html [ Failure ]
 crbug.com/591099 editing/deleting/merge-whitespace-pre.html [ Failure ]
-crbug.com/591099 editing/deleting/table-cells.html [ Failure ]
 crbug.com/591099 editing/deleting/transpose-empty.html [ Failure ]
 crbug.com/591099 editing/deleting/type-delete-after-quote.html [ Failure ]
 crbug.com/591099 editing/execCommand/4580583-1.html [ Failure ]
@@ -209,7 +201,6 @@
 crbug.com/591099 editing/execCommand/findString.html [ Failure ]
 crbug.com/591099 editing/execCommand/format-block-multiple-paragraphs-in-pre.html [ Failure ]
 crbug.com/591099 editing/execCommand/format-block-multiple-paragraphs.html [ Failure ]
-crbug.com/591099 editing/execCommand/insertImage.html [ Failure ]
 crbug.com/591099 editing/execCommand/query-format-block.html [ Pass Timeout ]
 crbug.com/591099 editing/execCommand/remove-list-from-range-selection.html [ Failure ]
 crbug.com/591099 editing/inserting/4875189-1.html [ Failure ]
@@ -222,32 +213,21 @@
 crbug.com/591099 editing/inserting/insert-br-quoted-004.html [ Failure ]
 crbug.com/591099 editing/inserting/insert-br-quoted-005.html [ Failure ]
 crbug.com/591099 editing/inserting/insert-br-quoted-006.html [ Failure ]
-crbug.com/591099 editing/inserting/line-break.html [ Failure ]
-crbug.com/591099 editing/inserting/paragraph-separator-in-table-1.html [ Failure ]
-crbug.com/591099 editing/inserting/paragraph-separator-in-table-2.html [ Failure ]
-crbug.com/591099 editing/pasteboard/4631972.html [ Failure ]
-crbug.com/591099 editing/pasteboard/bad-placeholder.html [ Failure ]
 crbug.com/714962 editing/pasteboard/copy-element-with-conflicting-background-color-from-rule.html [ Failure ]
 crbug.com/714962 editing/pasteboard/copy-paste-pre-line-content.html [ Failure ]
 crbug.com/591099 editing/pasteboard/copy-paste-white-space.html [ Failure ]
 crbug.com/591099 editing/pasteboard/drag-image-to-contenteditable-in-iframe.html [ Failure ]
 crbug.com/591099 editing/pasteboard/drag-list-item.html [ Failure ]
 crbug.com/591099 editing/pasteboard/drag-selected-image-to-contenteditable.html [ Failure ]
-crbug.com/591099 editing/pasteboard/drop-text-without-selection.html [ Failure ]
 crbug.com/591099 editing/pasteboard/innerText-inline-table.html [ Failure ]
 crbug.com/591099 editing/pasteboard/input-field-1.html [ Failure ]
 crbug.com/591099 editing/pasteboard/merge-start-blockquote.html [ Failure ]
 crbug.com/591099 editing/pasteboard/merge-start-list.html [ Failure ]
-crbug.com/591099 editing/pasteboard/paste-line-endings-001.html [ Failure ]
 crbug.com/591099 editing/pasteboard/paste-line-endings-002.html [ Failure ]
-crbug.com/591099 editing/pasteboard/paste-line-endings-003.html [ Failure ]
 crbug.com/591099 editing/pasteboard/paste-line-endings-004.html [ Failure ]
 crbug.com/591099 editing/pasteboard/paste-line-endings-005.html [ Failure ]
 crbug.com/591099 editing/pasteboard/paste-noscript.html [ Failure ]
 crbug.com/591099 editing/pasteboard/paste-text-016.html [ Failure ]
-crbug.com/591099 editing/pasteboard/pasting-tabs.html [ Failure ]
-crbug.com/591099 editing/pasteboard/quirks-mode-br-1.html [ Failure ]
-crbug.com/591099 editing/pasteboard/styled-element-markup.html [ Failure ]
 crbug.com/591099 editing/selection/4402375.html [ Failure ]
 crbug.com/591099 editing/selection/4776665.html [ Failure ]
 crbug.com/591099 editing/selection/4960137.html [ Failure ]
@@ -264,8 +244,6 @@
 crbug.com/591099 editing/selection/dont-select-text-overflow-ellipsis-when-wrapping.html [ Failure ]
 crbug.com/591099 editing/selection/doubleclick-beside-cr-span.html [ Failure Timeout ]
 crbug.com/591099 editing/selection/drag-in-iframe.html [ Failure ]
-crbug.com/591099 editing/selection/expanding-selections.html [ Failure ]
-crbug.com/591099 editing/selection/expanding-selections2.html [ Failure ]
 crbug.com/591099 editing/selection/extend-by-sentence-001.html [ Failure ]
 crbug.com/591099 editing/selection/extend-inside-transforms-backward.html [ Failure ]
 crbug.com/591099 editing/selection/extend-inside-transforms-forward.html [ Failure ]
@@ -293,8 +271,6 @@
 crbug.com/591099 editing/selection/paragraph-granularity.html [ Failure ]
 crbug.com/591099 editing/selection/programmatic-selection-on-mac-is-directionless.html [ Timeout ]
 crbug.com/591099 editing/selection/select-bidi-run.html [ Failure ]
-crbug.com/591099 editing/selection/select-box.html [ Failure ]
-crbug.com/591099 editing/selection/select-element-paragraph-boundary.html [ Failure ]
 crbug.com/714962 editing/selection/select-from-textfield-outwards.html [ Failure ]
 crbug.com/591099 editing/selection/select-missing-image.html [ Failure ]
 crbug.com/591099 editing/selection/select-text-overflow-ellipsis-mixed-in-ltr-2.html [ Failure ]
@@ -305,14 +281,9 @@
 crbug.com/591099 editing/selection/selection-button-text.html [ Failure ]
 crbug.com/591099 editing/selection/shift-click.html [ Failure ]
 crbug.com/591099 editing/selection/transformed-selection-rects.html [ Failure ]
-crbug.com/591099 editing/selection/triple-click-in-pre.html [ Failure ]
 crbug.com/591099 editing/selection/word-granularity.html [ Failure ]
-crbug.com/591099 editing/style/block-styles-007.html [ Failure ]
 crbug.com/591099 editing/text-iterator/findString.html [ Timeout ]
 crbug.com/591099 editing/unsupported-content/list-delete-001.html [ Failure ]
-crbug.com/591099 editing/unsupported-content/table-delete-002.html [ Failure ]
-crbug.com/591099 editing/unsupported-content/table-type-after.html [ Failure ]
-crbug.com/591099 editing/unsupported-content/table-type-before.html [ Failure ]
 crbug.com/591099 external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_11.html [ Pass ]
 crbug.com/591099 external/wpt/WebCryptoAPI/derive_bits_keys/hkdf.https.worker.html [ Timeout ]
 crbug.com/591099 external/wpt/WebCryptoAPI/derive_bits_keys/test_hkdf.https.html [ Timeout ]
@@ -349,7 +320,6 @@
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-nested-002.xht [ Pass ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-percents-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-remove-006.xht [ Pass ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/max-height-percentage-002.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/root-box-001.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Failure ]
 crbug.com/714962 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-image-5.html [ Failure ]
@@ -357,11 +327,8 @@
 crbug.com/591099 external/wpt/css/css-display/display-contents-details.html [ Crash ]
 crbug.com/591099 external/wpt/css/css-display/display-contents-dynamic-list-001-inline.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-display/display-contents-dynamic-list-001-none.html [ Failure ]
-crbug.com/714962 external/wpt/css/css-display/display-contents-dynamic-multicol-001-inline.html [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-display/display-contents-dynamic-multicol-001-none.html [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-display/display-contents-dynamic-table-001-inline.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-display/display-contents-list-001.html [ Failure ]
-crbug.com/714962 external/wpt/css/css-display/display-contents-multicol-001.html [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-flexbox/percentage-heights-001.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-flexbox/percentage-heights-003.html [ Pass ]
 crbug.com/714962 external/wpt/css/css-fonts/font-features-across-space-1.html [ Pass ]
@@ -444,16 +411,12 @@
 crbug.com/591099 external/wpt/css/css-multicol/multicol-gap-negative-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-height-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-height-block-child-001.xht [ Failure ]
-crbug.com/714962 external/wpt/css/css-multicol/multicol-inherit-001.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-inherit-002.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-inherit-003.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-list-item-001.xht [ Failure ]
-crbug.com/714962 external/wpt/css/css-multicol/multicol-margin-001.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-margin-002.xht [ Failure ]
-crbug.com/714962 external/wpt/css/css-multicol/multicol-margin-child-001.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-nested-002.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-nested-005.xht [ Failure ]
-crbug.com/714962 external/wpt/css/css-multicol/multicol-nested-margin-001.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-nested-margin-002.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-nested-margin-003.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-nested-margin-004.xht [ Failure ]
@@ -497,7 +460,6 @@
 crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-margin-002.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-margin-bottom-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-margin-nested-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-margin-nested-002.xht [ Crash ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-margin-nested-003.xht [ Crash ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-margin-nested-firstchild-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-multicol/multicol-span-none-001.xht [ Failure ]
@@ -798,9 +760,6 @@
 crbug.com/591099 external/wpt/css/css-writing-modes/float-vrl-010.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/float-vrl-012.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/inline-block-alignment-006.xht [ Failure ]
-crbug.com/714962 external/wpt/css/css-writing-modes/inline-table-alignment-002.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/inline-table-alignment-004.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/line-box-direction-vrl-006.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/line-box-direction-vrl-009.xht [ Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/margin-collapse-vrl-010.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/mongolian-orientation-002.html [ Pass ]
@@ -823,10 +782,6 @@
 crbug.com/591099 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001w.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001x.html [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/percent-padding-vrl-006.xht [ Failure ]
-crbug.com/714962 external/wpt/css/css-writing-modes/row-progression-vrl-002.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/row-progression-vrl-004.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/row-progression-vrl-006.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/row-progression-vrl-008.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vlr-001.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vrl-007.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vrl-008.xht [ Failure ]
@@ -1077,7 +1032,7 @@
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html [ Timeout ]
 crbug.com/591099 external/wpt/pointerevents/pointerevent_touch-action-button-test_touch-manual.html [ Timeout ]
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-keyboard-manual.html [ Timeout ]
-crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-mouse-manual.html [ Timeout ]
+crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-mouse-manual.html [ Pass Timeout ]
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-pan-left-css_touch-manual.html [ Pass ]
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-pan-right-css_touch-manual.html [ Failure ]
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html [ Timeout ]
@@ -1111,8 +1066,9 @@
 crbug.com/591099 external/wpt/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html [ Failure ]
 crbug.com/591099 external/wpt/svg/interfaces.html [ Timeout ]
 crbug.com/591099 external/wpt/svg/linking/reftests/href-filter-element.html [ Failure ]
-crbug.com/591099 external/wpt/url/url-setters.html [ Timeout ]
+crbug.com/591099 external/wpt/url/url-setters.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/wasm/wasm_local_iframe_test.html [ Failure ]
+crbug.com/591099 external/wpt/webaudio/idlharness.https.html [ Timeout ]
 crbug.com/591099 external/wpt/webmessaging/broadcastchannel/sandbox.html [ Failure ]
 crbug.com/591099 external/wpt/webrtc/interfaces.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/webrtc/interfaces.https.html [ Timeout ]
@@ -1460,7 +1416,7 @@
 crbug.com/714962 fast/dom/Range/getBoundingClientRect.html [ Failure ]
 crbug.com/714962 fast/dom/Range/getClientRects-character.html [ Failure ]
 crbug.com/591099 fast/dom/Range/getClientRects-leading-trailing-whitespaces.html [ Failure ]
-crbug.com/591099 fast/dom/Window/property-access-on-cached-window-after-frame-navigated.html [ Timeout ]
+crbug.com/591099 fast/dom/Window/property-access-on-cached-window-after-frame-navigated.html [ Failure Pass Timeout ]
 crbug.com/591099 fast/dom/Window/window-lookup-precedence.html [ Timeout ]
 crbug.com/591099 fast/dom/Window/window-postmessage-clone-deep-array.html [ Failure ]
 crbug.com/714962 fast/dom/anchor-without-content.html [ Failure ]
@@ -1493,7 +1449,7 @@
 crbug.com/714962 fast/events/event-on-culled_inline.html [ Failure ]
 crbug.com/591099 fast/events/keyboardevent-getModifierState.html [ Timeout ]
 crbug.com/591099 fast/events/menu-key-context-menu-document-pinch-zoom.html [ Failure ]
-crbug.com/714962 fast/events/middleClickAutoscroll-latching.html [ Timeout ]
+crbug.com/714962 fast/events/middleClickAutoscroll-latching.html [ Pass Timeout ]
 crbug.com/714962 fast/events/mouse-down-on-pseudo-element-remove-crash.html [ Failure ]
 crbug.com/591099 fast/events/mouse-event-buttons-attribute.html [ Timeout ]
 crbug.com/591099 fast/events/mouse-relative-position.html [ Failure ]
@@ -1522,7 +1478,6 @@
 crbug.com/714962 fast/forms/calendar-picker/month-picker-mouse-operations.html [ Failure ]
 crbug.com/591099 fast/forms/calendar-picker/week-picker-key-operations.html [ Timeout ]
 crbug.com/714962 fast/forms/calendar-picker/week-picker-mouse-operations.html [ Failure ]
-crbug.com/591099 fast/forms/caret-rtl.html [ Failure ]
 crbug.com/591099 fast/forms/control-clip-overflow.html [ Failure ]
 crbug.com/591099 fast/forms/fieldset/fieldset-with-float.html [ Failure ]
 crbug.com/591099 fast/forms/form-hides-table.html [ Failure ]
@@ -1532,7 +1487,6 @@
 crbug.com/591099 fast/forms/long-text-in-input.html [ Crash Failure ]
 crbug.com/591099 fast/forms/number/number-spinbutton-in-multi-column.html [ Failure ]
 crbug.com/591099 fast/forms/placeholder-position.html [ Failure ]
-crbug.com/591099 fast/forms/range/range-stepup-stepdown-from-renderer.html [ Pass Timeout ]
 crbug.com/591099 fast/forms/range/slider-in-multi-column.html [ Failure ]
 crbug.com/591099 fast/forms/select-popup/popup-menu-appearance-transform.html [ Failure ]
 crbug.com/591099 fast/forms/select/listbox-in-multi-column.html [ Failure ]
@@ -1579,7 +1533,6 @@
 crbug.com/591099 fast/js/dfg-arguments-alias-activation.html [ Timeout ]
 crbug.com/591099 fast/js/dfg-byte-array-put.html [ Timeout ]
 crbug.com/591099 fast/js/document-all-triggers-masquerades-watchpoint.html [ Timeout ]
-crbug.com/591099 fast/layers/layer-visibility.html [ Failure ]
 crbug.com/591099 fast/layers/overflow-scroll-auto-switch.html [ Failure ]
 crbug.com/591099 fast/layers/scroll-rect-to-visible.html [ Failure ]
 crbug.com/591099 fast/lists/001-vertical.html [ Failure ]
@@ -2185,7 +2138,6 @@
 crbug.com/714962 fast/table/backgr_simple-table-row-group.html [ Failure ]
 crbug.com/714962 fast/table/backgr_simple-table-row.html [ Failure ]
 crbug.com/714962 fast/table/backgr_simple-table.html [ Failure ]
-crbug.com/591099 fast/table/border-collapsing/001-vertical.html [ Failure Pass ]
 crbug.com/591099 fast/table/border-collapsing/003-vertical.html [ Failure ]
 crbug.com/591099 fast/table/border-collapsing/004-vertical.html [ Failure ]
 crbug.com/591099 fast/table/border-collapsing/border-collapsing-head-foot-vertical.html [ Failure ]
@@ -2490,7 +2442,7 @@
 crbug.com/591099 fullscreen/full-screen-element-stack.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-iframe-not-allowed.html [ Failure ]
 crbug.com/591099 fullscreen/full-screen-remove-ancestor-after.html [ Crash Pass ]
-crbug.com/591099 fullscreen/full-screen-ruleset-crash.html [ Crash ]
+crbug.com/591099 fullscreen/full-screen-ruleset-crash.html [ Crash Pass ]
 crbug.com/591099 fullscreen/full-screen-twice-newapi.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-with-css-reference-filter.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-with-flex-item.html [ Crash ]
@@ -2558,7 +2510,6 @@
 crbug.com/591099 http/tests/loading/preload-picture-nested.html [ Failure ]
 crbug.com/591099 http/tests/loading/preload-picture-sizes-2x.html [ Failure ]
 crbug.com/591099 http/tests/loading/preload-picture-sizes.html [ Failure ]
-crbug.com/591099 http/tests/loading/simple-subframe.html [ Failure ]
 crbug.com/591099 http/tests/local/file-url-sent-as-referer.html [ Failure ]
 crbug.com/591099 http/tests/local/fileapi/select-dragged-file-input.html [ Skip ]
 crbug.com/591099 http/tests/misc/acid3.html [ Crash ]
@@ -2646,11 +2597,8 @@
 crbug.com/591099 inspector-protocol/timeline/page-frames.js [ Pass ]
 crbug.com/714962 intersection-observer/root-margin.html [ Failure ]
 crbug.com/714962 intersection-observer/text-target.html [ Failure ]
-crbug.com/591099 media/audio-controls-rendering.html [ Failure ]
 crbug.com/591099 media/autoplay/document-user-activation.html [ Failure ]
-crbug.com/591099 media/video-display-toggle.html [ Failure ]
 crbug.com/591099 media/video-persistence.html [ Crash ]
-crbug.com/591099 media/video-transformed.html [ Failure ]
 crbug.com/591099 netinfo/estimate-multiple-frames.html [ Failure Pass ]
 crbug.com/591099 overflow/overflow-basic-002.html [ Pass ]
 crbug.com/591099 overflow/overflow-position-003.html [ Failure ]
@@ -2679,7 +2627,6 @@
 crbug.com/591099 paint/invalidation/clip/outline-clip-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/repaint-tile-clipped.html [ Crash ]
 crbug.com/591099 paint/invalidation/clip/replaced-clipped-positioned-not-wrong-incremental-repainting.html [ Failure ]
-crbug.com/591099 paint/invalidation/compositing/column-span-under-composited-column-child.html [ Crash Pass ]
 crbug.com/714962 paint/invalidation/compositing/composited-inline-change-text-data-keep-geometry.html [ Crash ]
 crbug.com/591099 paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/iframe-clip-removed.html [ Failure ]
@@ -3016,9 +2963,7 @@
 crbug.com/591099 payments/payment-request-in-iframe-nested-not-allowed.html [ Failure ]
 crbug.com/591099 payments/payment-request-in-iframe.html [ Failure ]
 crbug.com/591099 plugins/mouse-click-plugin-clears-selection.html [ Failure ]
-crbug.com/591099 plugins/plugin-scroll.html [ Failure ]
 crbug.com/591099 plugins/webview-plugin-nested-iframe-scroll.html [ Failure ]
-crbug.com/591099 plugins/webview-plugin-scroll.html [ Failure ]
 crbug.com/591099 printing/absolute-position-headers-and-footers.html [ Failure ]
 crbug.com/591099 printing/absolute-positioned.html [ Failure ]
 crbug.com/591099 printing/allowed-page-breaks.html [ Failure ]
@@ -3105,7 +3050,6 @@
 crbug.com/591099 svg/filters/feTurbulence-bad-seeds.html [ Failure ]
 crbug.com/591099 svg/foreign-object-under-shadow-root-under-hidden.html [ Failure ]
 crbug.com/591099 svg/hixie/error/012.xml [ Failure ]
-crbug.com/591099 svg/hixie/error/013.xml [ Failure ]
 crbug.com/591099 svg/hixie/error/dumpAsText/004.xml [ Failure ]
 crbug.com/591099 svg/hixie/error/dumpAsText/005.xml [ Failure ]
 crbug.com/591099 svg/in-html/sizing/svg-inline.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 1ecfbd0..0c11c5a 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -47785,6 +47785,18 @@
      {}
     ]
    ],
+   "css/css-scoping/shadow-disabled-sheet-001.html": [
+    [
+     "/css/css-scoping/shadow-disabled-sheet-001.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-scoping/shadow-fallback-dynamic-001.html": [
     [
      "/css/css-scoping/shadow-fallback-dynamic-001.html",
@@ -47845,6 +47857,18 @@
      {}
     ]
    ],
+   "css/css-scoping/shadow-root-insert-into-document.html": [
+    [
+     "/css/css-scoping/shadow-root-insert-into-document.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-scoping/slotted-with-pseudo-element.html": [
     [
      "/css/css-scoping/slotted-with-pseudo-element.html",
@@ -150478,6 +150502,11 @@
      {}
     ]
    ],
+   "interfaces/webaudio.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/webauthn.idl": [
     [
      {}
@@ -160038,6 +160067,11 @@
      {}
     ]
    ],
+   "url/data-uri-fragment-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "url/historical.any-expected.txt": [
     [
      {}
@@ -160648,6 +160682,11 @@
      {}
     ]
    ],
+   "webaudio/idlharness.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "webaudio/js/buffer-loader.js": [
     [
      {}
@@ -183844,6 +183883,12 @@
      {}
     ]
    ],
+   "css/css-typed-om/the-stylepropertymap/properties/pointer-events.html": [
+    [
+     "/css/css-typed-om/the-stylepropertymap/properties/pointer-events.html",
+     {}
+    ]
+   ],
    "css/css-typed-om/the-stylepropertymap/properties/position.html": [
     [
      "/css/css-typed-om/the-stylepropertymap/properties/position.html",
@@ -230234,6 +230279,12 @@
      {}
     ]
    ],
+   "webaudio/idlharness.https.html": [
+    [
+     "/webaudio/idlharness.https.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-analysernode-interface/test-analyser-gain.html": [
     [
      "/webaudio/the-audio-api/the-analysernode-interface/test-analyser-gain.html",
@@ -237256,6 +237307,12 @@
      {}
     ]
    ],
+   "xhr/xmlhttprequest-closing-worker.html": [
+    [
+     "/xhr/xmlhttprequest-closing-worker.html",
+     {}
+    ]
+   ],
    "xhr/xmlhttprequest-eventtarget.htm": [
     [
      "/xhr/xmlhttprequest-eventtarget.htm",
@@ -289567,24 +289624,32 @@
    "46913ea7e47811b11be898de5c3bd0a330ea6637",
    "testharness"
   ],
+  "css/css-scoping/shadow-disabled-sheet-001.html": [
+   "3de2d23c1b3339b964ec2c009832a3207a3b9dc4",
+   "reftest"
+  ],
   "css/css-scoping/shadow-fallback-dynamic-001.html": [
-   "062c99df18077a0205d0170d641b1d1e61199657",
+   "741cd9e29067a4634aa5beb6bd06afa540895d22",
    "reftest"
   ],
   "css/css-scoping/shadow-fallback-dynamic-002.html": [
-   "2f66c8bca48c2ce5c9e82c5d67b152e2d143f4c6",
+   "e9a0d8178387901404030dde1b7ae7b2842f2eca",
    "reftest"
   ],
   "css/css-scoping/shadow-fallback-dynamic-003.html": [
-   "f054b0974277fbee38a96a26559c9a15400266db",
+   "0b75fadbaee366349576e2d6f3ca8d6a49069f66",
    "reftest"
   ],
   "css/css-scoping/shadow-fallback-dynamic-004.html": [
-   "fc33527eaaa7711ecb2c7cd9523e793bce2503f2",
+   "71dcc60c4ff59690927c1575fff2eecf85ee558f",
    "reftest"
   ],
   "css/css-scoping/shadow-fallback-dynamic-005.html": [
-   "46d78b6d6931505bbc4bfc2f83e2bd0bac0d3472",
+   "ab3c3d205e59df800ba5b4217245b83685521c31",
+   "reftest"
+  ],
+  "css/css-scoping/shadow-root-insert-into-document.html": [
+   "2cee9fff35c9222074f4ef78dcfcb8a3e02bbc98",
    "reftest"
   ],
   "css/css-scoping/slotted-invalidation.html": [
@@ -289984,7 +290049,7 @@
    "reftest"
   ],
   "css/css-shapes/shape-outside/shape-image/shape-image-002.html": [
-   "299635765004bd1cf9cff8a0888678a2331d7b19",
+   "1f3ace2827629f37439108e43f6528d8d728e5a2",
    "reftest"
   ],
   "css/css-shapes/shape-outside/shape-image/shape-image-003.html": [
@@ -289996,7 +290061,7 @@
    "reftest"
   ],
   "css/css-shapes/shape-outside/shape-image/shape-image-005.html": [
-   "38883b770a73cc4eac3170a356b272edb6a5c483",
+   "274932a778268e3fda90b289e7f5ca22ee0f9adc",
    "reftest"
   ],
   "css/css-shapes/shape-outside/shape-image/shape-image-006.html": [
@@ -303975,6 +304040,10 @@
    "70c2e29badef7528469bcf11e1cb7bbc6cd519ea",
    "testharness"
   ],
+  "css/css-typed-om/the-stylepropertymap/properties/pointer-events.html": [
+   "71b42cb53d950eb62309b4567d3c7bc62dd1e28e",
+   "testharness"
+  ],
   "css/css-typed-om/the-stylepropertymap/properties/position.html": [
    "4e3eccee58cec470febe4cd9a9149f4b4436487e",
    "testharness"
@@ -303984,7 +304053,7 @@
    "testharness"
   ],
   "css/css-typed-om/the-stylepropertymap/properties/resources/testsuite.js": [
-   "6b7b909fe2cf5576ea5e483a0c0ee8a2977171f6",
+   "7e6c530cf36cce5d7b8d02abbbefbdd4370d1be1",
    "support"
   ],
   "css/css-typed-om/the-stylepropertymap/properties/right.html": [
@@ -325776,7 +325845,7 @@
    "support"
   ],
   "fetch/data-urls/processing.any-expected.txt": [
-   "bd8f280e1ee3a935e7f73e1ff89a623c14f270b3",
+   "ab294538e1879d2c51dab2818cd108568923d4c8",
    "support"
   ],
   "fetch/data-urls/processing.any.js": [
@@ -325784,7 +325853,7 @@
    "testharness"
   ],
   "fetch/data-urls/processing.any.worker-expected.txt": [
-   "bd8f280e1ee3a935e7f73e1ff89a623c14f270b3",
+   "ab294538e1879d2c51dab2818cd108568923d4c8",
    "support"
   ],
   "fetch/data-urls/resources/base64.json": [
@@ -325928,7 +325997,7 @@
    "testharness"
   ],
   "fetch/security/dangling-markup-mitigation-data-url.tentative.sub.html": [
-   "38b29bbb63189ca52dde1a4ff7e596321cf43f88",
+   "92c4633c3d684de4b1d959dbff4f2bab1eaf15a0",
    "testharness"
   ],
   "fetch/security/dangling-markup-mitigation.tentative.html": [
@@ -342384,7 +342453,7 @@
    "testharness"
   ],
   "html/semantics/scripting-1/the-script-element/execution-timing/077.html": [
-   "5870ab81ecc385f26d52b066f6a40388b4a2cce4",
+   "2bfe280f0ae7b745f2217055e66579ab6fb06769",
    "testharness"
   ],
   "html/semantics/scripting-1/the-script-element/execution-timing/078.html": [
@@ -346823,6 +346892,10 @@
    "d3ab33fa078f1b3bd4b29e174369073aab3963d5",
    "support"
   ],
+  "interfaces/webaudio.idl": [
+   "43a244276b9795b137c2e46c194d56dbb957635d",
+   "support"
+  ],
   "interfaces/webauthn.idl": [
    "77076f0828383c0f48f36131a81b25186622b3a3",
    "support"
@@ -372003,6 +372076,10 @@
    "cf3fd382286fe89570e68e0d90131db35e03e6ef",
    "support"
   ],
+  "url/data-uri-fragment-expected.txt": [
+   "75c21b6444b4b4b67818a6052ee1ec8ce34ac370",
+   "support"
+  ],
   "url/data-uri-fragment.html": [
    "2db7660e8dab868a2dc771a3a702832b8978a980",
    "testharness"
@@ -373267,6 +373344,14 @@
    "93068df297042344669093ce899f0230c87ebf54",
    "testharness"
   ],
+  "webaudio/idlharness.https-expected.txt": [
+   "fb80b7f73175870f1424df7fdfefb32053029983",
+   "support"
+  ],
+  "webaudio/idlharness.https.html": [
+   "7876e16ea643f69315e18c3e17af0d7f95769420",
+   "testharness"
+  ],
   "webaudio/js/buffer-loader.js": [
    "4d564eae0b3d7d1045626d1f144cd2638dba64e5",
    "support"
@@ -382283,6 +382368,10 @@
    "a67d1876d6245fb94d60a937b633c87c51a04d21",
    "testharness"
   ],
+  "xhr/xmlhttprequest-closing-worker.html": [
+   "2e12b49aca2dc3908837b6b419c92cb890e60e3f",
+   "testharness"
+  ],
   "xhr/xmlhttprequest-eventtarget.htm": [
    "40c886f79399108db3ded8a23848905dcf9e0862",
    "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-disabled-sheet-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-disabled-sheet-001.html
new file mode 100644
index 0000000..275ac47a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-disabled-sheet-001.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>CSS Scoping Module Level 1 - Disabled stylesheet dynamically</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors-data-model">
+<link rel="match" href="reference/green-box.html"/>
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<div id="host"></div>
+<script>
+  let root = host.attachShadow({ mode: 'open' });
+  root.innerHTML = `
+    <style>
+      div { background: green; width: 100px; height: 100px; }
+    </style>
+    <style>
+      div { background: red; }
+    </style>
+    <div></div>
+  `;
+  document.body.offsetTop;
+  root.styleSheets[1].disabled = true;
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-001.html
index 6bf12aa..9a5672e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-001.html
@@ -1,6 +1,6 @@
 <!doctype html>
 <title>CSS Scoping Module Level 1 - Dynamic fallback content</title>
-<link rel="author" href="mailto:emilio@crisal.io">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
 <link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors-data-model">
 <link rel="match" href="reference/green-box.html"/>
 <p>Test passes if you see a single 100px by 100px green box below.</p>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-002.html
index 7553049e..f65d0c7 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-002.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-002.html
@@ -1,6 +1,6 @@
 <!doctype html>
 <title>CSS Scoping Module Level 1 - Dynamic fallback content</title>
-<link rel="author" href="mailto:emilio@crisal.io">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
 <link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors-data-model">
 <link rel="match" href="reference/green-box.html"/>
 <p>Test passes if you see a single 100px by 100px green box below.</p>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-003.html
index 59f8b53..a30e8fe 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-003.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-003.html
@@ -1,6 +1,6 @@
 <!doctype html>
 <title>CSS Scoping Module Level 1 - Dynamic fallback content</title>
-<link rel="author" href="mailto:emilio@crisal.io">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
 <link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors-data-model">
 <link rel="match" href="reference/green-box.html"/>
 <p>Test passes if you see a single 100px by 100px green box below.</p>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-004.html
index b301741..29e40757 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-004.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-004.html
@@ -1,6 +1,6 @@
 <!doctype html>
 <title>CSS Scoping Module Level 1 - Dynamic fallback content</title>
-<link rel="author" href="mailto:emilio@crisal.io">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
 <link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors-data-model">
 <link rel="match" href="reference/green-box.html"/>
 <p>Test passes if you see a single 100px by 100px green box below.</p>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-005.html
index ff030c0c..1d84907 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-005.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-005.html
@@ -1,6 +1,6 @@
 <!doctype html>
 <title>CSS Scoping Module Level 1 - Dynamic fallback content</title>
-<link rel="author" href="mailto:emilio@crisal.io">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
 <link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors-data-model">
 <link rel="match" href="reference/green-box.html"/>
 <p>Test passes if you see a single 100px by 100px green box below.</p>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-root-insert-into-document.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-root-insert-into-document.html
new file mode 100644
index 0000000..a3b89be38
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-root-insert-into-document.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>CSS Scoping Module Level 1 - Dynamic insertion of shadow host</title>
+<link rel="author" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors-data-model">
+<link rel="match" href="reference/green-box.html"/>
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<script>
+  let host = document.createElement('div');
+  let root = host.attachShadow({ mode: 'open' });
+  root.innerHTML = `
+    <style>
+      div { background: green; width: 100px; height: 100px; }
+    </style>
+    <div></div>
+  `;
+  document.body.offsetTop;
+  document.body.appendChild(host);
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general-serviceworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general-serviceworker.https-expected.txt
index 863b6cf..99afa96 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general-serviceworker.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general-serviceworker.https-expected.txt
@@ -36,11 +36,11 @@
 PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
 PASS Underlying connection is closed when aborting after receiving response
 PASS Underlying connection is closed when aborting after receiving response - no-cors
-FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
+PASS Fetch aborted & connection closed when aborted after calling response.arrayBuffer()
+PASS Fetch aborted & connection closed when aborted after calling response.blob()
+PASS Fetch aborted & connection closed when aborted after calling response.formData()
+PASS Fetch aborted & connection closed when aborted after calling response.json()
+PASS Fetch aborted & connection closed when aborted after calling response.text()
 PASS Stream errors once aborted. Underlying connection closed.
 PASS Stream errors once aborted, after reading. Underlying connection closed.
 PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general-sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general-sharedworker-expected.txt
index 863b6cf..99afa96 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general-sharedworker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general-sharedworker-expected.txt
@@ -36,11 +36,11 @@
 PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
 PASS Underlying connection is closed when aborting after receiving response
 PASS Underlying connection is closed when aborting after receiving response - no-cors
-FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
+PASS Fetch aborted & connection closed when aborted after calling response.arrayBuffer()
+PASS Fetch aborted & connection closed when aborted after calling response.blob()
+PASS Fetch aborted & connection closed when aborted after calling response.formData()
+PASS Fetch aborted & connection closed when aborted after calling response.json()
+PASS Fetch aborted & connection closed when aborted after calling response.text()
 PASS Stream errors once aborted. Underlying connection closed.
 PASS Stream errors once aborted, after reading. Underlying connection closed.
 PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general.any-expected.txt
index 863b6cf..99afa96 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general.any-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general.any-expected.txt
@@ -36,11 +36,11 @@
 PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
 PASS Underlying connection is closed when aborting after receiving response
 PASS Underlying connection is closed when aborting after receiving response - no-cors
-FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
+PASS Fetch aborted & connection closed when aborted after calling response.arrayBuffer()
+PASS Fetch aborted & connection closed when aborted after calling response.blob()
+PASS Fetch aborted & connection closed when aborted after calling response.formData()
+PASS Fetch aborted & connection closed when aborted after calling response.json()
+PASS Fetch aborted & connection closed when aborted after calling response.text()
 PASS Stream errors once aborted. Underlying connection closed.
 PASS Stream errors once aborted, after reading. Underlying connection closed.
 PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general.any.worker-expected.txt
index 863b6cf..99afa96 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general.any.worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -36,11 +36,11 @@
 PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting
 PASS Underlying connection is closed when aborting after receiving response
 PASS Underlying connection is closed when aborting after receiving response - no-cors
-FAIL Fetch aborted & connection closed when aborted after calling response.arrayBuffer() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.blob() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.formData() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.json() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
-FAIL Fetch aborted & connection closed when aborted after calling response.text() assert_throws: function "function() { throw e }" threw object "TypeError: Failed to fetch" that is not a DOMException AbortError: property "code" is equal to undefined, expected 20
+PASS Fetch aborted & connection closed when aborted after calling response.arrayBuffer()
+PASS Fetch aborted & connection closed when aborted after calling response.blob()
+PASS Fetch aborted & connection closed when aborted after calling response.formData()
+PASS Fetch aborted & connection closed when aborted after calling response.json()
+PASS Fetch aborted & connection closed when aborted after calling response.text()
 PASS Stream errors once aborted. Underlying connection closed.
 PASS Stream errors once aborted, after reading. Underlying connection closed.
 PASS Stream will not error if body is empty. It's closed with an empty queue before it errors.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist b/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist
index 42c7d48..958adb2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist
+++ b/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist
@@ -197,6 +197,7 @@
 SET TIMEOUT: screen-orientation/onchange-event.html
 SET TIMEOUT: screen-orientation/resources/sandboxed-iframe-locking.html
 SET TIMEOUT: secure-contexts/basic-popup-and-iframe-tests.https.js
+SET TIMEOUT: service-workers/cache-storage/script-tests/cache-abort.js
 SET TIMEOUT: service-workers/service-worker/activation.https.html
 SET TIMEOUT: service-workers/service-worker/fetch-frame-resource.https.html
 SET TIMEOUT: service-workers/service-worker/fetch-request-redirect.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/script-tests/cache-abort.js b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/script-tests/cache-abort.js
new file mode 100644
index 0000000..ec4130fd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/script-tests/cache-abort.js
@@ -0,0 +1,81 @@
+if (self.importScripts) {
+  importScripts('/resources/testharness.js');
+  importScripts('../resources/test-helpers.js');
+  importScripts('/common/utils.js');
+}
+
+// We perform the same tests on put, add, addAll. Parameterise the tests to
+// reduce repetition.
+const methodsToTest = {
+  put: async (cache, request) => {
+    const response = await fetch(request);
+    return cache.put(request, response);
+  },
+  add: async (cache, request) => cache.add(request),
+  addAll: async (cache, request) => cache.addAll([request]),
+};
+
+for (const method in methodsToTest) {
+  const perform = methodsToTest[method];
+
+  cache_test(async (cache, test) => {
+    const controller = new AbortController();
+    const signal = controller.signal;
+    controller.abort();
+    const request = new Request('../resources/simple.txt', { signal });
+    return promise_rejects(test, 'AbortError', perform(cache, request),
+                          `${method} should reject`);
+  }, `${method}() on an already-aborted request should reject with AbortError`);
+
+  cache_test(async (cache, test) => {
+    const controller = new AbortController();
+    const signal = controller.signal;
+    const request = new Request('../resources/simple.txt', { signal });
+    const promise = perform(cache, request);
+    controller.abort();
+    return promise_rejects(test, 'AbortError', promise,
+                          `${method} should reject`);
+  }, `${method}() synchronously followed by abort should reject with ` +
+     `AbortError`);
+
+  cache_test(async (cache, test) => {
+    const controller = new AbortController();
+    const signal = controller.signal;
+    const stateKey = token();
+    const abortKey = token();
+    const request = new Request(
+        `../../../fetch/api/resources/infinite-slow-response.py?stateKey=${stateKey}&abortKey=${abortKey}`,
+        { signal });
+
+    const promise = perform(cache, request);
+
+    // Wait for the server to start sending the response body.
+    let opened = false;
+    do {
+      // Normally only one fetch to 'stash-take' is needed, but the fetches
+      // will be served in reverse order sometimes
+      // (i.e., 'stash-take' gets served before 'infinite-slow-response').
+
+      const response =
+            await fetch(`../../../fetch/api/resources/stash-take.py?key=${stateKey}`);
+      const body = await response.json();
+      if (body === 'open') opened = true;
+    } while (!opened);
+
+    // Sadly the above loop cannot guarantee that the browser has started
+    // processing the response body. This delay is needed to make the test
+    // failures non-flaky in Chrome version 66. My deepest apologies.
+    await new Promise(resolve => setTimeout(resolve, 250));
+
+    controller.abort();
+
+    await promise_rejects(test, 'AbortError', promise,
+                          `${method} should reject`);
+
+    // infinite-slow-response.py doesn't know when to stop.
+    return fetch(`../../../fetch/api/resources/stash-put.py?key=${abortKey}`);
+  }, `${method}() followed by abort after headers received should reject ` +
+     `with AbortError`);
+}
+
+done();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html
new file mode 100644
index 0000000..b4f203b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/serviceworker/cache-abort.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Cache Storage: Abort</title>
+<link rel="help" href="https://fetch.spec.whatwg.org/#request-signal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../service-worker/resources/test-helpers.sub.js"></script>
+<script>
+service_worker_test('../script-tests/cache-abort.js');
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/window/cache-abort.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/window/cache-abort.https.html
new file mode 100644
index 0000000..935023d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/window/cache-abort.https.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<title>Cache Storage: Abort</title>
+<link rel="help" href="https://fetch.spec.whatwg.org/#request-signal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/test-helpers.js"></script>
+<script src="/common/utils.js"></script>
+<script src="../script-tests/cache-abort.js"></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html
new file mode 100644
index 0000000..ccd7191
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/worker/cache-abort.https.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<title>>Cache Storage: Abort</title>
+<link rel="help" href="https://fetch.spec.whatwg.org/#request-signal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+fetch_tests_from_worker(new Worker('../script-tests/cache-abort.js'));
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/xhr/xmlhttprequest-closing-worker.html b/third_party/WebKit/LayoutTests/external/wpt/xhr/xmlhttprequest-closing-worker.html
new file mode 100644
index 0000000..5c8142f2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/xhr/xmlhttprequest-closing-worker.html
@@ -0,0 +1,32 @@
+<!--
+self.close()
+var xhr = new XMLHttpRequest();
+xhr.open("GET", "/resources/testharness.js");
+xhr.send(42);
+postMessage(xhr.readyState)
+/*-->
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <title>XHR used when worker is closing itself</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+  </head>
+  <body>
+    <div id="log"></div>
+    <script>
+      var test = async_test();
+      test.step(function() {
+        var worker = new Worker('#')
+        worker.onmessage = function(e) {
+          test.step(function() {
+            assert_equals(e.data, XMLHttpRequest.OPENED, 'XHR.readyState')
+          })
+          test.done()
+        }
+      })
+    </script>
+  </body>
+</html>
+<!--*/ //-->
diff --git a/third_party/WebKit/LayoutTests/fast/scroll-behavior/snaps-after-scrollbar-dragging.html b/third_party/WebKit/LayoutTests/fast/scroll-behavior/snaps-after-scrollbar-dragging.html
new file mode 100644
index 0000000..d61b9673
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/scroll-behavior/snaps-after-scrollbar-dragging.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-scroll-snap-1" />
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<style>
+body {
+  margin: 0px;
+}
+div {
+  position: absolute;
+}
+#scroller {
+  width: 400px;
+  height: 400px;
+  overflow: scroll;
+  scroll-snap-type: both mandatory;
+  padding: 0px;
+}
+.snap {
+  width: 200px;
+  height: 200px;
+  background-color: blue;
+  scroll-snap-align: start;
+}
+#space {
+  width: 1000px;
+  height: 1000px;
+}
+#left-top {
+  left: 0px;
+  top: 0px;
+}
+#right-top {
+  left: 400px;
+  top: 0px;
+}
+#left-bottom {
+  left: 0px;
+  top: 400px;
+}
+
+</style>
+
+<div id='scroller'>
+  <div id="space"></div>
+  <div class="snap" id="left-top"></div>
+  <div class="snap" id="right-top"></div>
+  <div class="snap" id="left-bottom"></div>
+</div>
+
+<script>
+var scroller = document.getElementById("scroller");
+function waitForAnimationEnd() {
+  const MAX_FRAME = 500;
+  var last_changed_frame = 0;
+  var last_scroller_x = scroller.scrollLeft;
+  var last_scroller_y = scroller.scrollTop;
+  return new Promise((resolve, reject) => {
+    function tick(frames) {
+      // We requestAnimationFrame either for 500 frames or until 20 frames with
+      // no change have been observed.
+      if (frames >= MAX_FRAME || frames - last_changed_frame > 20) {
+        resolve();
+      } else {
+        if (scroller.scrollLeft != last_scroller_x ||
+            scroller.scrollTop != last_scroller_y) {
+          last_changed_frame = frames;
+          last_scroller_x = scroller.scrollLeft;
+          last_scroller_y = scroller.scrollTop;
+        }
+        requestAnimationFrame(tick.bind(this, frames + 1));
+      }
+    }
+    tick(0);
+  });
+}
+
+function dragScrollbar(x, y, w, h) {
+  return new Promise((resolve, reject) => {
+    chrome.gpuBenchmarking.smoothDrag(x, y, x + w, y + h, resolve, 2);
+  });
+}
+
+function vertical_scrollbar() {
+  scroller.scrollTo(0, 0);
+  assert_equals(scroller.scrollTop, 0);
+  assert_equals(scroller.scrollLeft, 0);
+  return dragScrollbar(398, 20, 0, 100)
+  .then(waitForAnimationEnd)
+  .then(() => {
+    assert_equals(scroller.scrollTop, 400);
+  })
+}
+
+function horizontal_scrollbar() {
+  scroller.scrollTo(0, 0);
+  assert_equals(scroller.scrollTop, 0);
+  assert_equals(scroller.scrollLeft, 0);
+  return dragScrollbar(20, 398, 100, 0)
+  .then(waitForAnimationEnd)
+  .then(() => {
+    assert_equals(scroller.scrollLeft, 400);
+  })
+}
+
+promise_test(t => {
+  return vertical_scrollbar();
+}, "Snaps after dragging the vertical scrollbar.");
+
+promise_test(t => {
+  return horizontal_scrollbar();
+}, "Snaps after dragging the horizontal scrollbar.");
+
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/compositing/squashing/vertical-writing-mode-squashed-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/compositing/squashing/vertical-writing-mode-squashed-expected.txt
new file mode 100644
index 0000000..9256734
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/compositing/squashing/vertical-writing-mode-squashed-expected.txt
@@ -0,0 +1,19 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x416
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x416
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x400
+layer at (8,8) size 400x400 clip at (8,8) size 400x385 scrollX 9640.00 scrollWidth 10040
+  LayoutNGBlockFlow {DIV} at (0,0) size 400x400
+    LayoutNGBlockFlow {DIV} at (40,0) size 10000x200 [bgcolor=#FFFF00]
+layer at (368,8) size 40x385
+  LayoutNGBlockFlow (relative positioned) {DIV} at (0,0) size 40x385
+    LayoutNGBlockFlow (anonymous) at (0,0) size 20x385
+      LayoutText {#text} at (1,0) size 19x63
+        text run at (1,0) width 63: "Some text"
+    LayoutNGBlockFlow {DIV} at (20,0) size 20x385
+      LayoutText {#text} at (0,0) size 0x0
+layer at (368,8) size 19x262
+  LayoutInline (relative positioned) {A} at (0,0) size 19x262
+    LayoutText {#text} at (1,0) size 19x262
+      text run at (1,0) width 262: "This text should not overlap the other text"
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/multiple_pseudo_elements-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/multiple_pseudo_elements-expected.txt
new file mode 100644
index 0000000..67d4b1ec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/multiple_pseudo_elements-expected.txt
@@ -0,0 +1,93 @@
+layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 1089
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 785x1089 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 785x1089
+    LayoutNGBlockFlow {BODY} at (8,8) size 769x1073 [bgcolor=#CCCCCC]
+      LayoutNGBlockFlow {P} at (0,0) size 769x20
+        LayoutInline {<pseudo:first-letter>} at (0,0) size 10x19 [color=#800000]
+          LayoutTextFragment (anonymous) at (0,0) size 10x19
+            text run at (0,0) width 10: "T"
+        LayoutTextFragment {#text} at (10,0) size 345x19
+          text run at (10,0) width 345: "he style declarations which apply to the text below are:"
+      LayoutNGBlockFlow {PRE} at (0,36) size 769x112
+        LayoutText {#text} at (0,0) size 368x96
+          text run at (0,0) width 224: "P:first-line {color: green;}"
+          text run at (224,0) width 0: " "
+          text run at (0,16) width 248: "P:first-letter {color: maroon;}"
+          text run at (248,16) width 0: " "
+          text run at (0,32) width 272: ".two:first-line {font-size: 200%;}"
+          text run at (272,32) width 0: " "
+          text run at (0,48) width 288: ".two:first-letter {font-size: 350%;}"
+          text run at (288,48) width 0: " "
+          text run at (0,64) width 312: "P.three:first-letter {font-size: 350%;}"
+          text run at (312,64) width 0: " "
+          text run at (0,80) width 368: "P.three:first-line {font-variant: small-caps;}"
+          text run at (368,80) width 0: " "
+          text run at (0,96) width 0: " "
+      LayoutNGBlockFlow {P} at (0,179) size 769x60
+        LayoutInline {<pseudo:first-letter>} at (0,0) size 10x19 [color=#800000]
+          LayoutTextFragment (anonymous) at (0,0) size 10x19
+            text run at (0,0) width 10: "T"
+        LayoutTextFragment {#text} at (10,0) size 764x59
+          text run at (10,0) width 717: "he first letter of this paragraph, and only that one, should be maroon (dark red), while the entire first line should be"
+          text run at (0,20) width 764: "green. If this precise combination does not occur, then the user agent has failed this test. Remember that in order to ensure"
+          text run at (0,40) width 449: "a complete test, the paragraph must be displayed on more than one line."
+      LayoutNGBlockFlow {P} at (0,255) size 769x192
+        LayoutInline {<pseudo:first-letter>} at (0,0) size 68x127 [color=#800000]
+          LayoutTextFragment (anonymous) at (0,2) size 68x127
+            text run at (0,2) width 68: "T"
+        LayoutTextFragment {#text} at (68,74) size 751x117
+          text run at (68,74) width 634: "he first letter of this paragraph, and only that one,"
+          text run at (0,132) width 736: "should be 350% bigger than the rest of the first line of this paragraph and maroon (dark red), while the entire first line"
+          text run at (0,152) width 751: "should be 200% bigger than normal and green. If this precise combination does not occur, then the user agent has failed"
+          text run at (0,172) width 718: "this test. Remember that in order to ensure a complete test, the paragraph must be displayed on more than one line."
+      LayoutNGBlockFlow {P} at (0,463) size 769x126
+        LayoutInline {<pseudo:first-letter>} at (0,0) size 76x64 [color=#800000]
+          LayoutTextFragment (anonymous) at (0,1) size 76x64
+            text run at (0,1) width 76: "\"W"
+        LayoutTextFragment {#text} at (76,36) size 765x89
+          text run at (76,36) width 685: "e should check for quotation support,\" it was said. The first two characters in this paragraph-- a double-"
+          text run at (0,66) width 764: "quote mark and a capital 'W'-- should be 350% bigger than the rest of the paragraph, and maroon (dark red). Note that the"
+          text run at (0,86) width 765: "inclusion of both the quotation mark and the 'W' in the first-letter style is not required under CSS1, but it is recommended."
+          text run at (0,106) width 450: "In addition, the entire first line should be in a small-caps font and green."
+      LayoutTable {TABLE} at (0,605) size 769x468 [border: (1px outset #808080)]
+        LayoutTableSection {TBODY} at (1,1) size 767x466
+          LayoutTableRow {TR} at (0,0) size 767x28
+            LayoutNGTableCell {TD} at (0,0) size 767x28 [bgcolor=#C0C0C0] [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=2]
+              LayoutInline {STRONG} at (0,0) size 159x19
+                LayoutText {#text} at (4,4) size 159x19
+                  text run at (4,4) width 159: "TABLE Testing Section"
+          LayoutTableRow {TR} at (0,28) size 767x438
+            LayoutNGTableCell {TD} at (0,233) size 12x28 [bgcolor=#C0C0C0] [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
+              LayoutText {#text} at (4,209) size 4x19
+                text run at (4,209) width 4: " "
+            LayoutNGTableCell {TD} at (12,28) size 755x438 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
+              LayoutNGBlockFlow {P} at (4,4) size 747x60
+                LayoutInline {<pseudo:first-letter>} at (0,0) size 10x19 [color=#800000]
+                  LayoutTextFragment (anonymous) at (0,0) size 10x19
+                    text run at (0,0) width 10: "T"
+                LayoutTextFragment {#text} at (10,0) size 727x59
+                  text run at (10,0) width 717: "he first letter of this paragraph, and only that one, should be maroon (dark red), while the entire first line should be"
+                  text run at (0,20) width 719: "green. If this precise combination does not occur, then the user agent has failed this test. Remember that in order to"
+                  text run at (0,40) width 494: "ensure a complete test, the paragraph must be displayed on more than one line."
+              LayoutNGBlockFlow {P} at (4,80) size 747x212
+                LayoutInline {<pseudo:first-letter>} at (0,0) size 68x127 [color=#800000]
+                  LayoutTextFragment (anonymous) at (0,2) size 68x127
+                    text run at (0,2) width 68: "T"
+                LayoutTextFragment {#text} at (68,74) size 736x137
+                  text run at (68,74) width 634: "he first letter of this paragraph, and only that one,"
+                  text run at (0,132) width 736: "should be 350% bigger than the rest of the first line of this paragraph and maroon (dark red), while the entire first line"
+                  text run at (0,152) width 712: "should be 200% bigger than normal and green. If this precise combination does not occur, then the user agent has"
+                  text run at (0,172) width 726: "failed this test. Remember that in order to ensure a complete test, the paragraph must be displayed on more than one"
+                  text run at (0,192) width 27: "line."
+              LayoutNGBlockFlow {P} at (4,308) size 747x126
+                LayoutInline {<pseudo:first-letter>} at (0,0) size 76x64 [color=#800000]
+                  LayoutTextFragment (anonymous) at (0,1) size 76x64
+                    text run at (0,1) width 76: "\"W"
+                LayoutTextFragment {#text} at (76,36) size 739x89
+                  text run at (76,36) width 631: "e should check for quotation support,\" it was said. The first two characters in this paragraph-- a"
+                  text run at (0,66) width 727: "double-quote mark and a capital 'W'-- should be 350% bigger than the rest of the paragraph, and maroon (dark red)."
+                  text run at (0,86) width 739: "Note that the inclusion of both the quotation mark and the 'W' in the first-letter style is not required under CSS1, but it"
+                  text run at (0,106) width 561: "is recommended. In addition, the entire first line should be in a small-caps font and green."
+layer at (8,169) size 769x2 clip at (0,0) size 0x0
+  LayoutNGBlockFlow {HR} at (0,161) size 769x2 [border: (1px inset #EEEEEE)]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/deleting/delete-at-paragraph-boundaries-011-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/deleting/delete-at-paragraph-boundaries-011-expected.txt
new file mode 100644
index 0000000..0885fe1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/deleting/delete-at-paragraph-boundaries-011-expected.txt
@@ -0,0 +1,37 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {DIV} at (0,0) size 784x238 [border: (2px solid #0000FF)]
+        LayoutNGBlockFlow {DIV} at (14,14) size 756x83
+          LayoutText {#text} at (0,0) size 59x26
+            text run at (0,0) width 59: "Tests:"
+          LayoutBR {BR} at (59,0) size 0x0
+          LayoutText {#text} at (0,27) size 623x27
+            text run at (0,27) width 623: "Delete at the end of document when there is a BR following a P."
+          LayoutBR {BR} at (623,27) size 0x0
+          LayoutText {#text} at (0,55) size 442x27
+            text run at (0,55) width 442: "This is a test case for rdar://problem/4110366"
+        LayoutNGBlockFlow {DIV} at (14,113) size 756x111
+          LayoutText {#text} at (0,0) size 183x26
+            text run at (0,0) width 183: "Expected Results:"
+          LayoutBR {BR} at (183,0) size 0x0
+          LayoutText {#text} at (0,27) size 720x55
+            text run at (0,27) width 720: "Red box with four lines. The second line is a nested red box with the word"
+            text run at (0,55) width 389: "\"hello\". The other three lines are empty."
+          LayoutBR {BR} at (389,55) size 0x0
+          LayoutText {#text} at (0,83) size 468x27
+            text run at (0,83) width 468: "Selection is a caret at the start of the fourth line."
+      LayoutBlockFlow {DIV} at (0,262) size 784x140 [border: (2px solid #FF0000)]
+        LayoutBlockFlow {P} at (2,26) size 780x32 [border: (2px solid #FF0000)]
+          LayoutText {#text} at (2,2) size 49x27
+            text run at (2,2) width 49: "hello"
+        LayoutBlockFlow {P} at (2,82) size 780x32 [border: (2px solid #FF0000)]
+          LayoutBR {BR} at (2,2) size 0x27
+caret: position 0 of child 0 {BR} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/deleting/merge-different-styles-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/deleting/merge-different-styles-expected.txt
new file mode 100644
index 0000000..890904b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/deleting/merge-different-styles-expected.txt
@@ -0,0 +1,20 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 749x39
+          text run at (0,0) width 749: "This places the caret before the 'b' in 'bar' and Deletes. 'foo' and 'bar' should end up on the same line, but neither should"
+          text run at (0,20) width 82: "change style."
+      LayoutBlockFlow {DIV} at (0,56) size 784x20
+        LayoutBlockFlow {DIV} at (0,0) size 784x20
+          LayoutText {#text} at (0,0) size 21x19
+            text run at (0,0) width 21: "foo"
+          LayoutInline {SPAN} at (0,0) size 24x19
+            LayoutText {#text} at (21,0) size 24x19
+              text run at (21,0) width 24: "bar"
+caret: position 3 of child 0 {#text} of child 1 {DIV} of child 2 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/deleting/merge-endOfParagraph-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/deleting/merge-endOfParagraph-expected.txt
new file mode 100644
index 0000000..f9fd0835
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/deleting/merge-endOfParagraph-expected.txt
@@ -0,0 +1,27 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 747x39
+          text run at (0,0) width 747: "When the selection to delete ends at the end of a paragraph, that paragraph will be completely deleted, but a <br> or an"
+          text run at (0,20) width 555: "empty block will remain. Merging must happen to remove that <br> or prune that block."
+      LayoutNGBlockFlow {P} at (0,56) size 784x40
+        LayoutText {#text} at (0,0) size 763x39
+          text run at (0,0) width 763: "This test illustrates a case where merging wasn't allowed to happen just because the end of the selection to delete was in a"
+          text run at (0,20) width 237: "fully selected line, which is nonsense."
+      LayoutNGBlockFlow {P} at (0,112) size 784x60
+        LayoutText {#text} at (0,0) size 779x59
+          text run at (0,0) width 777: "Fixing that bug exposed a problem with merging. If deletion empties out the block that contained the start of the selection to"
+          text run at (0,20) width 779: "delete, that block can collapse away and become impossible to merge into. So we insert a placeholder to prop it open so that"
+          text run at (0,40) width 142: "the merge can happen."
+      LayoutBlockFlow {DIV} at (5,188) size 774x34 [border: (1px solid #000000)]
+        LayoutBlockFlow {DIV} at (6,6) size 762x22 [border: (1px solid #FF0000)]
+          LayoutBR {BR} at (1,1) size 0x19
+caret: position 0 of child 0 {BR} of child 0 {DIV} of child 6 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/deleting/table-cells-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/deleting/table-cells-expected.txt
new file mode 100644
index 0000000..8d0094b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/deleting/table-cells-expected.txt
@@ -0,0 +1,24 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x20
+        LayoutText {#text} at (0,0) size 717x19
+          text run at (0,0) width 717: "This tests deletion of a selection that spans multiple cells. Just table content should be removed, not table structure."
+      LayoutBlockFlow {DIV} at (0,36) size 784x30
+        LayoutTable {TABLE} at (0,0) size 343x30 [border: (1px outset #808080)]
+          LayoutTableSection {TBODY} at (1,1) size 341x28
+            LayoutTableRow {TR} at (0,2) size 341x24
+              LayoutTableCell {TD} at (2,2) size 157x24 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+                LayoutBlockFlow {DIV} at (2,2) size 153x20
+                  LayoutText {#text} at (0,0) size 153x19
+                    text run at (0,0) width 153: "These two pieces of text"
+              LayoutTableCell {TD} at (161,2) size 178x24 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+                LayoutBlockFlow {DIV} at (2,2) size 174x20
+                  LayoutText {#text} at (0,0) size 174x19
+                    text run at (0,0) width 174: " should be in different cells."
+caret: position 24 of child 0 {#text} of child 0 {DIV} of child 0 {TD} of child 0 {TR} of child 0 {TBODY} of child 0 {TABLE} of child 2 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/execCommand/insertImage-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/execCommand/insertImage-expected.txt
new file mode 100644
index 0000000..376e8f3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/execCommand/insertImage-expected.txt
@@ -0,0 +1,22 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x576
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 748x39
+          text run at (0,0) width 748: "This is a test of execCommand(InsertImage, ...). The first test passes execCommand a path to a valid image, the second"
+          text run at (0,20) width 369: "passes execCommand a path where no image should exist."
+      LayoutBlockFlow {DIV} at (0,56) size 784x103
+        LayoutImage {IMG} at (0,0) size 76x103
+        LayoutNGBlockFlow {IMG} at (76,87) size 16x16
+          LayoutInline {SPAN} at (0,0) size 0x0
+            LayoutImage (floating) {IMG} at (0,0) size 16x16
+            LayoutInline {SPAN} at (0,0) size 0x0
+      LayoutNGBlockFlow {UL} at (0,175) size 784x0
+caret: position 1 of child 1 {IMG} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/inserting/line-break-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/inserting/line-break-expected.txt
new file mode 100644
index 0000000..610e677
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/inserting/line-break-expected.txt
@@ -0,0 +1,17 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 753x39
+          text run at (0,0) width 753: "This testcase used to break InsertLineBreak. The editable region below should have two empty paragraphs in it, and the"
+          text run at (0,20) width 186: "caret should be in the second."
+      LayoutBlockFlow {DIV} at (0,56) size 784x40
+        LayoutBlockFlow {DIV} at (0,0) size 784x40
+          LayoutBR {BR} at (0,0) size 0x19
+          LayoutBR {BR} at (0,20) size 0x19
+caret: position 0 of child 2 {BR} of child 0 {DIV} of child 2 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/inserting/paragraph-separator-in-table-1-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/inserting/paragraph-separator-in-table-1-expected.txt
new file mode 100644
index 0000000..89aa163e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/inserting/paragraph-separator-in-table-1-expected.txt
@@ -0,0 +1,26 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x20
+        LayoutText {#text} at (0,0) size 611x19
+          text run at (0,0) width 611: "This tests InsertParagraphSeparator inside table cells. 'Cell' and 'Two' should be on separate lines."
+      LayoutBlockFlow {DIV} at (0,36) size 784x50
+        LayoutTable {TABLE} at (0,0) size 103x50 [border: (1px outset #808080)]
+          LayoutTableSection {TBODY} at (1,1) size 101x48
+            LayoutTableRow {TR} at (0,2) size 101x44
+              LayoutTableCell {TD} at (2,12) size 61x24 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 57x19
+                  text run at (2,2) width 57: "Cell One"
+              LayoutTableCell {TD} at (65,2) size 34x44 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 30x19
+                  text run at (2,2) width 30: "Cell "
+                LayoutBR {BR} at (32,17) size 0x0
+                LayoutInline {SPAN} at (0,0) size 28x19
+                  LayoutText {#text} at (2,22) size 28x19
+                    text run at (2,22) width 28: "Two"
+caret: position 0 of child 0 {#text} of child 2 {SPAN} of child 1 {TD} of child 0 {TR} of child 0 {TBODY} of child 0 {TABLE} of child 2 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/inserting/paragraph-separator-in-table-2-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/inserting/paragraph-separator-in-table-2-expected.txt
new file mode 100644
index 0000000..e1cbf7e8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/inserting/paragraph-separator-in-table-2-expected.txt
@@ -0,0 +1,25 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 768x39
+          text run at (0,0) width 768: "This tests InsertParagraphSeparator inside table cells. The first cell should contain 'Cell' and a newline, and the second cell"
+          text run at (0,20) width 134: "should contain 'Two'."
+      LayoutBlockFlow {DIV} at (0,56) size 784x50
+        LayoutTable {TABLE} at (0,0) size 78x50 [border: (1px outset #808080)]
+          LayoutTableSection {TBODY} at (1,1) size 76x48
+            LayoutTableRow {TR} at (0,2) size 76x44
+              LayoutTableCell {TD} at (2,2) size 34x44 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 30x19
+                  text run at (2,2) width 30: "Cell "
+                LayoutBR {BR} at (32,17) size 0x0
+                LayoutBR {BR} at (2,22) size 0x19
+              LayoutTableCell {TD} at (38,12) size 36x24 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 32x19
+                  text run at (2,2) width 32: " Two"
+caret: position 0 of child 2 {BR} of child 0 {TD} of child 0 {TR} of child 0 {TBODY} of child 0 {TABLE} of child 2 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/4631972-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/4631972-expected.txt
new file mode 100644
index 0000000..d24f7bfc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/4631972-expected.txt
@@ -0,0 +1,25 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 638x39
+          text run at (0,0) width 638: "This tests pasting a fragment containing an <iframe> after a <div>. This used to fail on an assertion in"
+          text run at (0,20) width 632: "moveParagraphContentsToNewBlockIfNecessary. You should see 'foo' and then an <iframe> below."
+      LayoutBlockFlow {DIV} at (0,56) size 784x72
+        LayoutBlockFlow {DIV} at (0,0) size 784x20
+          LayoutText {#text} at (0,0) size 21x19
+            text run at (0,0) width 21: "foo"
+        LayoutNGBlockFlow (anonymous) at (0,20) size 784x52
+layer at (8,84) size 102x52
+  LayoutIFrame {IFRAME} at (0,0) size 102x52 [border: (1px solid #000000)]
+    layer at (0,0) size 100x50
+      LayoutView at (0,0) size 100x50
+    layer at (0,0) size 100x50
+      LayoutNGBlockFlow {HTML} at (0,0) size 100x50
+        LayoutNGBlockFlow {BODY} at (8,8) size 84x34
+caret: position 1 of child 1 {IFRAME} of child 2 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/bad-placeholder-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/bad-placeholder-expected.txt
new file mode 100644
index 0000000..fac0c06
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/bad-placeholder-expected.txt
@@ -0,0 +1,24 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 751x39
+          text run at (0,0) width 751: "This is a test to make sure that a placeholder, even one without our special class on it, is removed only when it has been"
+          text run at (0,20) width 405: "collapsed away or when it has been displaced by pasted content."
+      LayoutNGBlockFlow {P} at (0,56) size 784x40
+        LayoutText {#text} at (0,0) size 763x39
+          text run at (0,0) width 754: "Placeholders with our special class can, through bugs in deletion, be inserted into the document unnecessarily. Once that"
+          text run at (0,20) width 763: "happens, we don't want to make matters worse by removing them if they are acting as line breaks instead of placeholders."
+      LayoutBlockFlow {DIV} at (0,112) size 784x40
+        LayoutText {#text} at (0,0) size 99x19
+          text run at (0,0) width 99: "First paragraph."
+        LayoutBR {BR} at (99,15) size 0x0
+        LayoutText {#text} at (0,20) size 118x19
+          text run at (0,20) width 118: "Second paragraph."
+caret: position 16 of child 0 {#text} of child 4 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/drop-text-without-selection-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/drop-text-without-selection-expected.txt
new file mode 100644
index 0000000..639a488
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/drop-text-without-selection-expected.txt
@@ -0,0 +1,39 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 104x19
+          text run at (0,0) width 104: "This is a test for "
+        LayoutInline {I} at (0,0) size 751x39
+          LayoutInline {A} at (0,0) size 348x19 [color=#0000EE]
+            LayoutText {#text} at (104,0) size 348x19
+              text run at (104,0) width 348: "http://bugzilla.opendarwin.org/show_bug.cgi?id=8394"
+          LayoutText {#text} at (452,0) size 751x39
+            text run at (452,0) width 299: " Editable region does not accept dropped text if"
+            text run at (0,20) width 125: "there is no selection"
+        LayoutText {#text} at (125,20) size 4x19
+          text run at (125,20) width 4: "."
+      LayoutNGBlockFlow {P} at (0,56) size 784x20
+        LayoutText {#text} at (0,0) size 653x19
+          text run at (0,0) width 653: "The text field should accept drag-and-dropped text, such as the link, even if no text is currently selected."
+      LayoutNGBlockFlow (anonymous) at (0,102) size 784x22
+        LayoutTextControl {INPUT} at (0,0) size 154x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
+        LayoutText {#text} at (154,1) size 4x19
+          text run at (154,1) width 4: " "
+        LayoutInline {A} at (0,0) size 162x19 [color=#0000EE]
+          LayoutText {#text} at (158,1) size 162x19
+            text run at (158,1) width 162: "drop me into the text field"
+        LayoutText {#text} at (0,0) size 0x0
+layer at (8,100) size 784x2 clip at (0,0) size 0x0
+  LayoutNGBlockFlow {HR} at (0,92) size 784x2 [border: (1px inset #EEEEEE)]
+layer at (10,113) size 150x16
+  LayoutBlockFlow {DIV} at (2,3) size 150x16
+    LayoutText {#text} at (0,0) size 119x16
+      text run at (0,0) width 119: "http://www.ibm.com/"
+selection start: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
+selection end:   position 19 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/paste-line-endings-001-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/paste-line-endings-001-expected.txt
new file mode 100644
index 0000000..c62fbf5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/paste-line-endings-001-expected.txt
@@ -0,0 +1,45 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {DIV} at (0,0) size 784x210 [border: (2px solid #0000FF)]
+        LayoutNGBlockFlow {DIV} at (14,14) size 756x83
+          LayoutText {#text} at (0,0) size 59x26
+            text run at (0,0) width 59: "Tests:"
+          LayoutBR {BR} at (59,0) size 0x0
+          LayoutText {#text} at (0,27) size 162x27
+            text run at (0,27) width 162: "Fix for this bug: "
+          LayoutInline {A} at (0,0) size 260x27 [color=#0000EE]
+            LayoutText {#text} at (162,27) size 260x27
+              text run at (162,27) width 260: "<rdar://problem/4045511>"
+          LayoutText {#text} at (422,27) size 705x55
+            text run at (422,27) width 283: " Copying and pasting end-of-"
+            text run at (0,55) width 533: "paragraph selection puts insertion point in wrong place"
+        LayoutNGBlockFlow {DIV} at (14,113) size 756x83
+          LayoutText {#text} at (0,0) size 183x26
+            text run at (0,0) width 183: "Expected Results:"
+          LayoutBR {BR} at (183,0) size 0x0
+          LayoutText {#text} at (0,27) size 715x55
+            text run at (0,27) width 706: "Should see two lines of text below, self-documenting themselves as \"line"
+            text run at (0,55) width 715: "one\" and \"line two\". The insertion point must be at the start of \"line two\"."
+      LayoutBlockFlow {DIV} at (0,234) size 784x60
+        LayoutBlockFlow {DIV} at (0,0) size 784x60 [border: (2px solid #FF0000)]
+          LayoutText {#text} at (2,2) size 78x27
+            text run at (2,2) width 78: "line one"
+          LayoutBR {BR} at (80,23) size 0x0
+          LayoutText {#text} at (2,30) size 79x27
+            text run at (2,30) width 79: "line two"
+caret: position 0 of child 2 {#text} of child 1 {DIV} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/paste-line-endings-003-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/paste-line-endings-003-expected.txt
new file mode 100644
index 0000000..2b00bb4d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/paste-line-endings-003-expected.txt
@@ -0,0 +1,46 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {DIV} at (0,0) size 784x210 [border: (2px solid #0000FF)]
+        LayoutNGBlockFlow {DIV} at (14,14) size 756x83
+          LayoutText {#text} at (0,0) size 59x26
+            text run at (0,0) width 59: "Tests:"
+          LayoutBR {BR} at (59,0) size 0x0
+          LayoutText {#text} at (0,27) size 162x27
+            text run at (0,27) width 162: "Fix for this bug: "
+          LayoutInline {A} at (0,0) size 260x27 [color=#0000EE]
+            LayoutText {#text} at (162,27) size 260x27
+              text run at (162,27) width 260: "<rdar://problem/4045511>"
+          LayoutText {#text} at (422,27) size 705x55
+            text run at (422,27) width 283: " Copying and pasting end-of-"
+            text run at (0,55) width 533: "paragraph selection puts insertion point in wrong place"
+        LayoutNGBlockFlow {DIV} at (14,113) size 756x83
+          LayoutText {#text} at (0,0) size 183x26
+            text run at (0,0) width 183: "Expected Results:"
+          LayoutBR {BR} at (183,0) size 0x0
+          LayoutText {#text} at (0,27) size 715x55
+            text run at (0,27) width 706: "Should see two lines of text below, self-documenting themselves as \"line"
+            text run at (0,55) width 715: "one\" and \"line two\". The insertion point must be at the start of \"line two\"."
+      LayoutBlockFlow {DIV} at (0,234) size 784x60
+        LayoutBlockFlow {DIV} at (0,0) size 784x60 [border: (2px solid #FF0000)]
+          LayoutBlockFlow {DIV} at (2,2) size 780x28
+            LayoutText {#text} at (0,0) size 78x27
+              text run at (0,0) width 78: "line one"
+          LayoutBlockFlow {DIV} at (2,30) size 780x28
+            LayoutText {#text} at (0,0) size 79x27
+              text run at (0,0) width 79: "line two"
+caret: position 0 of child 0 {#text} of child 2 {DIV} of child 1 {DIV} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/pasting-tabs-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/pasting-tabs-expected.txt
new file mode 100644
index 0000000..9e24c16c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/pasting-tabs-expected.txt
@@ -0,0 +1,30 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 766x39
+          text run at (0,0) width 766: "This tests copying plain text with tabs and pasting it into an editable region using paste and match tyle. The tabs should be"
+          text run at (0,20) width 65: "preserved."
+      LayoutNGBlockFlow (anonymous) at (0,56) size 784x36
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {DIV} at (0,92) size 784x20
+        LayoutText {#text} at (0,0) size 37x19
+          text run at (0,0) width 37: "Tab->"
+        LayoutInline {SPAN} at (0,0) size 27x19
+          LayoutText {#text} at (37,0) size 27x19
+            text run at (37,0) width 27: "\x{9}"
+        LayoutText {#text} at (64,0) size 37x19
+          text run at (64,0) width 37: "<-Tab"
+layer at (8,64) size 179x36 clip at (9,65) size 177x34
+  LayoutTextControl {TEXTAREA} at (0,0) size 179x36 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+    LayoutBlockFlow {DIV} at (3,3) size 175x16
+      LayoutText {#text} at (0,0) size 104x16
+        text run at (0,0) width 104: "Tab->\x{9}<-Tab"
+caret: position 5 of child 2 {#text} of child 4 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/quirks-mode-br-1-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/quirks-mode-br-1-expected.txt
new file mode 100644
index 0000000..f6c15097
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/quirks-mode-br-1-expected.txt
@@ -0,0 +1,22 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 779x39
+          text run at (0,0) width 779: "This is a test to make sure that the final <br> in an incoming fragment is interpretted strictly in quirks mode (where brs at the"
+          text run at (0,20) width 693: "end of blocks are collapsed). This test used to fail because of unrendered content to the left of the collapsed br."
+      LayoutBlockFlow {DIV} at (0,56) size 784x40
+        LayoutBlockFlow {DIV} at (0,0) size 784x20
+          LayoutText {#text} at (0,0) size 370x19
+            text run at (0,0) width 370: "The test should add a single blank line after this paragraph."
+          LayoutInline {SPAN} at (0,0) size 0x19
+          LayoutBR {BR} at (370,15) size 0x0
+        LayoutNGBlockFlow (anonymous) at (0,20) size 784x20
+          LayoutBR {BR} at (0,0) size 0x19
+caret: position 0 of child 1 {BR} of child 2 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/styled-element-markup-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/styled-element-markup-expected.txt
new file mode 100644
index 0000000..ddc9661
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/pasteboard/styled-element-markup-expected.txt
@@ -0,0 +1,25 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 772x39
+          text run at (0,0) width 772: "This tests copy/paste of styled elements, like images. The image in the region below should be centered after its copied and"
+          text run at (0,20) width 44: "pasted."
+      LayoutNGBlockFlow {P} at (0,56) size 784x40
+        LayoutInline {B} at (0,0) size 778x39
+          LayoutText {#text} at (0,0) size 778x39
+            text run at (0,0) width 778: "This demonstrates a bug: createMarkup puts the text-align property on the image, which doesn't center it, so its left"
+            text run at (0,20) width 113: "aligned on paste."
+      LayoutBlockFlow {DIV} at (0,112) size 784x103
+        LayoutBlockFlow {CENTER} at (0,0) size 784x103
+          LayoutImage {IMG} at (354,0) size 76x103
+      LayoutBlockFlow {DIV} at (0,215) size 784x103
+        LayoutImage {IMG} at (0,0) size 76x103
+caret: position 1 of child 0 {IMG} of child 6 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/expanding-selections-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/expanding-selections-expected.txt
new file mode 100644
index 0000000..c36e068
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/expanding-selections-expected.txt
@@ -0,0 +1,21 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x576
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 774x39
+          text run at (0,0) width 774: "This tests double clicking inside and at the end of an editable div. The selection that is created should not extend outside the"
+          text run at (0,20) width 97: "editable region."
+      LayoutBlockFlow {DIV} at (0,56) size 784x20
+        LayoutText {#text} at (0,0) size 206x19
+          text run at (0,0) width 206: "This text is inside an editable div"
+        LayoutInline {SPAN} at (0,0) size 4x19
+          LayoutText {#text} at (206,0) size 4x19
+            text run at (206,0) width 4: " "
+layer at (8,100) size 784x20
+  LayoutNGBlockFlow {P} at (0,92) size 784x20
+    LayoutText {#text} at (0,0) size 150x19
+      text run at (0,0) width 150: "This text is not editable."
+caret: position 1 of child 0 {#text} of child 1 {SPAN} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/expanding-selections2-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/expanding-selections2-expected.txt
new file mode 100644
index 0000000..bdd3fed
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/expanding-selections2-expected.txt
@@ -0,0 +1,20 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 774x39
+          text run at (0,0) width 774: "This tests double clicking inside and at the end of an editable div. The selection that is created should not extend outside the"
+          text run at (0,20) width 97: "editable region."
+      LayoutBlockFlow {DIV} at (0,56) size 784x20
+        LayoutText {#text} at (0,0) size 181x19
+          text run at (0,0) width 181: "This text is in an editable div"
+        LayoutInline {SPAN} at (0,0) size 4x19
+          LayoutText {#text} at (181,0) size 4x19
+            text run at (181,0) width 4: "."
+      LayoutNGBlockFlow (anonymous) at (0,76) size 784x20
+        LayoutText {#text} at (0,0) size 242x19
+          text run at (0,0) width 242: "This text is outside the editable region."
+caret: position 1 of child 0 {#text} of child 1 {SPAN} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/select-box-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/select-box-expected.txt
new file mode 100644
index 0000000..1b9a84e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/select-box-expected.txt
@@ -0,0 +1,70 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x20
+        LayoutText {#text} at (0,0) size 691x19
+          text run at (0,0) width 691: "This tests caret movement across a select box. The caret should skip over the select box as if it were an image."
+      LayoutBlockFlow {DIV} at (0,36) size 784x20
+        LayoutBlockFlow {DIV} at (0,0) size 784x20
+          LayoutText {#text} at (0,0) size 71x19
+            text run at (0,0) width 71: "select box: "
+          LayoutMenuList {SELECT} at (71,0) size 29x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+            LayoutNGBlockFlow (anonymous) at (1,1) size 27x18
+              LayoutText (anonymous) at (4,1) size 7x16
+                text run at (4,1) width 7: "1"
+          LayoutText {#text} at (100,0) size 66x19
+            text run at (100,0) width 66: " the end ..."
+caret: position 1 of child 0 {#text} of child 1 {DIV} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/select-element-paragraph-boundary-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/select-element-paragraph-boundary-expected.txt
new file mode 100644
index 0000000..aec8f19
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/select-element-paragraph-boundary-expected.txt
@@ -0,0 +1,17 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 748x39
+          text run at (0,0) width 748: "This tests paragraphBoundary selection navigation. The caret should be at the end of the paragraph below, just after the"
+          text run at (0,20) width 67: "select box."
+      LayoutBlockFlow {DIV} at (0,56) size 784x20
+        LayoutMenuList {SELECT} at (0,0) size 29x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+          LayoutNGBlockFlow (anonymous) at (1,1) size 27x18
+            LayoutText (anonymous) at (4,1) size 7x16
+              text run at (4,1) width 7: "1"
+caret: position 1 of child 0 {SELECT} of child 2 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/triple-click-in-pre-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/triple-click-in-pre-expected.txt
new file mode 100644
index 0000000..34592689
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/triple-click-in-pre-expected.txt
@@ -0,0 +1,23 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x20
+        LayoutText {#text} at (0,0) size 676x19
+          text run at (0,0) width 676: "This tests modifying a selection created with a double click. The new selection should use word granularity."
+      LayoutNGBlockFlow {P} at (0,36) size 784x40 [color=#008000]
+        LayoutText {#text} at (0,0) size 781x39
+          text run at (0,0) width 781: "This test does not run interactively. It uses the testRunners eventSender to do mouse clicks. To run it manually, triple click on"
+          text run at (0,20) width 705: "the second line in the box below (anywhere after \"whitespace:pre\"). The triple click should select the entire line."
+      LayoutBlockFlow {DIV} at (0,92) size 784x60
+        LayoutBlockFlow {DIV} at (0,0) size 784x60 [border: (1px solid #0000FF)]
+          LayoutBlockFlow {PRE} at (1,14) size 782x32
+            LayoutText {#text} at (0,0) size 120x32
+              text run at (0,0) width 120: "this text is in"
+              text run at (120,0) width 0: " "
+              text run at (0,16) width 112: "whitespace:pre"
+selection start: position 16 of child 0 {#text} of child 1 {PRE} of child 1 {DIV} of child 5 {DIV} of body
+selection end:   position 30 of child 0 {#text} of child 1 {PRE} of child 1 {DIV} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/style/block-styles-007-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/style/block-styles-007-expected.txt
new file mode 100644
index 0000000..fb52781
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/style/block-styles-007-expected.txt
@@ -0,0 +1,49 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {DIV} at (0,0) size 784x237 [border: (2px solid #0000FF)]
+        LayoutNGBlockFlow {DIV} at (14,14) size 756x83
+          LayoutText {#text} at (0,0) size 59x26
+            text run at (0,0) width 59: "Tests:"
+          LayoutBR {BR} at (59,0) size 0x0
+          LayoutText {#text} at (0,27) size 162x27
+            text run at (0,27) width 162: "Fix for this bug: "
+          LayoutInline {A} at (0,0) size 260x27 [color=#0000EE]
+            LayoutText {#text} at (162,27) size 260x27
+              text run at (162,27) width 260: "<rdar://problem/3977962>"
+          LayoutText {#text} at (422,27) size 749x55
+            text run at (422,27) width 327: " font loses bold style after pasting"
+            text run at (0,55) width 384: "next to existing text and pressing return"
+        LayoutNGBlockFlow {DIV} at (14,113) size 756x110
+          LayoutNGBlockFlow (anonymous) at (0,0) size 756x55
+            LayoutText {#text} at (0,0) size 183x26
+              text run at (0,0) width 183: "Expected Results:"
+            LayoutBR {BR} at (183,0) size 0x0
+            LayoutText {#text} at (0,27) size 436x27
+              text run at (0,27) width 436: "Should see this content in the red box below:"
+          LayoutNGBlockFlow {DIV} at (0,55) size 756x55
+            LayoutNGBlockFlow (anonymous) at (0,0) size 756x28
+              LayoutText {#text} at (0,0) size 32x27
+                text run at (0,0) width 32: "foo"
+            LayoutNGBlockFlow {DIV} at (0,28) size 756x27
+              LayoutInline {B} at (0,0) size 36x26
+                LayoutText {#text} at (0,0) size 36x26
+                  text run at (0,0) width 36: "bar"
+      LayoutBlockFlow {DIV} at (0,261) size 784x59
+        LayoutBlockFlow {DIV} at (0,0) size 784x59 [border: (2px solid #FF0000)]
+          LayoutBlockFlow {DIV} at (2,2) size 780x28
+            LayoutText {#text} at (0,0) size 32x27
+              text run at (0,0) width 32: "foo"
+          LayoutBlockFlow {DIV} at (2,30) size 780x27
+            LayoutInline {B} at (0,0) size 36x26
+              LayoutText {#text} at (0,0) size 36x26
+                text run at (0,0) width 36: "bar"
+caret: position 0 of child 0 {#text} of child 0 {B} of child 1 {DIV} of child 1 {DIV} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-002-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-002-expected.txt
new file mode 100644
index 0000000..96e3614e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-002-expected.txt
@@ -0,0 +1,61 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {DIV} at (0,0) size 784x241 [border: (4px solid #0000FF)]
+        LayoutNGBlockFlow {DIV} at (20,20) size 744x69
+          LayoutText {#text} at (0,0) size 59x26
+            text run at (0,0) width 59: "Tests:"
+          LayoutBR {BR} at (59,0) size 0x0
+          LayoutText {#text} at (0,27) size 658x20
+            text run at (0,27) width 658: "Our ability to \"edit around\" content the HTML editing code does not yet handle very well."
+          LayoutBR {BR} at (658,27) size 0x0
+          LayoutInline {I} at (0,0) size 99x20
+            LayoutText {#text} at (0,48) size 99x20
+              text run at (0,48) width 99: "For this test: "
+          LayoutText {#text} at (99,48) size 405x20
+            text run at (99,48) width 405: "Select and delete a table and some surrounding content."
+        LayoutNGBlockFlow (anonymous) at (20,89) size 744x21
+          LayoutBR {BR} at (0,0) size 0x0
+        LayoutNGBlockFlow {DIV} at (20,110) size 744x111
+          LayoutText {#text} at (0,0) size 183x26
+            text run at (0,0) width 183: "Expected Results:"
+          LayoutBR {BR} at (183,0) size 0x0
+          LayoutText {#text} at (0,27) size 709x41
+            text run at (0,27) width 709: "The content in the red box must exactly match the content in the green box (except for the border"
+            text run at (0,48) width 48: "color)."
+          LayoutBR {BR} at (48,48) size 0x0
+          LayoutInline {I} at (0,0) size 99x20
+            LayoutText {#text} at (0,69) size 99x20
+              text run at (0,69) width 99: "For this test: "
+          LayoutText {#text} at (99,69) size 744x41
+            text run at (99,69) width 645: "Only selected content should get deleted. Surrounding content that is not selected should"
+            text run at (0,90) width 201: "(obviously) not be affected."
+      LayoutNGBlockFlow {DIV} at (0,251) size 784x32 [border: (2px solid #008000)]
+        LayoutText {#text} at (2,2) size 62x27
+          text run at (2,2) width 62: "before"
+      LayoutBlockFlow {DIV} at (0,293) size 784x32
+        LayoutBlockFlow {DIV} at (0,0) size 784x32 [border: (2px solid #FF0000)]
+          LayoutText {#text} at (2,2) size 62x27
+            text run at (2,2) width 62: "before"
+caret: position 7 of child 0 {#text} of child 1 {DIV} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-type-after-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-type-after-expected.txt
new file mode 100644
index 0000000..005c018
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-type-after-expected.txt
@@ -0,0 +1,124 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {DIV} at (0,0) size 784x220 [border: (4px solid #0000FF)]
+        LayoutNGBlockFlow {DIV} at (20,20) size 744x69
+          LayoutText {#text} at (0,0) size 59x26
+            text run at (0,0) width 59: "Tests:"
+          LayoutBR {BR} at (59,0) size 0x0
+          LayoutText {#text} at (0,27) size 658x20
+            text run at (0,27) width 658: "Our ability to \"edit around\" content the HTML editing code does not yet handle very well."
+          LayoutBR {BR} at (658,27) size 0x0
+          LayoutInline {I} at (0,0) size 99x20
+            LayoutText {#text} at (0,48) size 99x20
+              text run at (0,48) width 99: "For this test: "
+          LayoutText {#text} at (99,48) size 176x20
+            text run at (99,48) width 176: "Test typing after a table."
+        LayoutNGBlockFlow (anonymous) at (20,89) size 744x21
+          LayoutBR {BR} at (0,0) size 0x0
+        LayoutNGBlockFlow {DIV} at (20,110) size 744x90
+          LayoutText {#text} at (0,0) size 183x26
+            text run at (0,0) width 183: "Expected Results:"
+          LayoutBR {BR} at (183,0) size 0x0
+          LayoutText {#text} at (0,27) size 709x41
+            text run at (0,27) width 709: "The content in the red box must exactly match the content in the green box (except for the border"
+            text run at (0,48) width 48: "color)."
+          LayoutBR {BR} at (48,48) size 0x0
+          LayoutInline {I} at (0,0) size 99x20
+            LayoutText {#text} at (0,69) size 99x20
+              text run at (0,69) width 99: "For this test: "
+          LayoutText {#text} at (99,69) size 435x20
+            text run at (99,69) width 435: "Typed text should appear after (on the line below) the table."
+      LayoutNGBlockFlow {DIV} at (0,230) size 784x114 [border: (2px solid #008000)]
+        LayoutTable {TABLE} at (2,2) size 46x82 [border: (1px outset #808080)]
+          LayoutTableSection {TBODY} at (1,1) size 44x80
+            LayoutTableRow {TR} at (0,2) size 44x24
+              LayoutNGTableCell {TD} at (2,2) size 12x24 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "1"
+              LayoutNGTableCell {TD} at (16,2) size 12x24 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "2"
+              LayoutNGTableCell {TD} at (30,2) size 12x24 [border: (1px inset #808080)] [r=0 c=2 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "3"
+            LayoutTableRow {TR} at (0,28) size 44x24
+              LayoutNGTableCell {TD} at (2,28) size 12x24 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "4"
+              LayoutNGTableCell {TD} at (16,28) size 12x24 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "5"
+              LayoutNGTableCell {TD} at (30,28) size 12x24 [border: (1px inset #808080)] [r=1 c=2 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "6"
+            LayoutTableRow {TR} at (0,54) size 44x24
+              LayoutNGTableCell {TD} at (2,54) size 12x24 [border: (1px inset #808080)] [r=2 c=0 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "7"
+              LayoutNGTableCell {TD} at (16,54) size 12x24 [border: (1px inset #808080)] [r=2 c=1 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "8"
+              LayoutNGTableCell {TD} at (30,54) size 12x24 [border: (1px inset #808080)] [r=2 c=2 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "9"
+        LayoutNGBlockFlow (anonymous) at (2,84) size 780x28
+          LayoutText {#text} at (0,0) size 36x27
+            text run at (0,0) width 36: "xxx"
+      LayoutBlockFlow {DIV} at (0,354) size 784x114
+        LayoutBlockFlow {DIV} at (0,0) size 784x114 [border: (2px solid #FF0000)]
+          LayoutTable {TABLE} at (2,2) size 46x82 [border: (1px outset #808080)]
+            LayoutTableSection {TBODY} at (1,1) size 44x80
+              LayoutTableRow {TR} at (0,2) size 44x24
+                LayoutTableCell {TD} at (2,2) size 12x24 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "1"
+                LayoutTableCell {TD} at (16,2) size 12x24 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "2"
+                LayoutTableCell {TD} at (30,2) size 12x24 [border: (1px inset #808080)] [r=0 c=2 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "3"
+              LayoutTableRow {TR} at (0,28) size 44x24
+                LayoutTableCell {TD} at (2,28) size 12x24 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "4"
+                LayoutTableCell {TD} at (16,28) size 12x24 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "5"
+                LayoutTableCell {TD} at (30,28) size 12x24 [border: (1px inset #808080)] [r=1 c=2 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "6"
+              LayoutTableRow {TR} at (0,54) size 44x24
+                LayoutTableCell {TD} at (2,54) size 12x24 [border: (1px inset #808080)] [r=2 c=0 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "7"
+                LayoutTableCell {TD} at (16,54) size 12x24 [border: (1px inset #808080)] [r=2 c=1 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "8"
+                LayoutTableCell {TD} at (30,54) size 12x24 [border: (1px inset #808080)] [r=2 c=2 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "9"
+          LayoutNGBlockFlow (anonymous) at (2,84) size 780x28
+            LayoutText {#text} at (0,0) size 36x27
+              text run at (0,0) width 36: "xxx"
+caret: position 3 of child 2 {#text} of child 1 {DIV} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-type-before-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-type-before-expected.txt
new file mode 100644
index 0000000..7f9e63363
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-type-before-expected.txt
@@ -0,0 +1,114 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {DIV} at (0,0) size 784x220 [border: (4px solid #0000FF)]
+        LayoutNGBlockFlow {DIV} at (20,20) size 744x69
+          LayoutText {#text} at (0,0) size 59x26
+            text run at (0,0) width 59: "Tests:"
+          LayoutBR {BR} at (59,0) size 0x0
+          LayoutText {#text} at (0,27) size 658x20
+            text run at (0,27) width 658: "Our ability to \"edit around\" content the HTML editing code does not yet handle very well."
+          LayoutBR {BR} at (658,27) size 0x0
+          LayoutInline {I} at (0,0) size 99x20
+            LayoutText {#text} at (0,48) size 99x20
+              text run at (0,48) width 99: "For this test: "
+          LayoutText {#text} at (99,48) size 189x20
+            text run at (99,48) width 189: "Test typing before a table."
+        LayoutNGBlockFlow (anonymous) at (20,89) size 744x21
+          LayoutBR {BR} at (0,0) size 0x0
+        LayoutNGBlockFlow {DIV} at (20,110) size 744x90
+          LayoutText {#text} at (0,0) size 183x26
+            text run at (0,0) width 183: "Expected Results:"
+          LayoutBR {BR} at (183,0) size 0x0
+          LayoutText {#text} at (0,27) size 709x41
+            text run at (0,27) width 709: "The content in the red box must exactly match the content in the green box (except for the border"
+            text run at (0,48) width 48: "color)."
+          LayoutBR {BR} at (48,48) size 0x0
+          LayoutInline {I} at (0,0) size 99x20
+            LayoutText {#text} at (0,69) size 99x20
+              text run at (0,69) width 99: "For this test: "
+          LayoutText {#text} at (99,69) size 447x20
+            text run at (99,69) width 447: "Typed text should appear before (on the line above) the table."
+      LayoutNGBlockFlow {DIV} at (0,230) size 784x114 [border: (2px solid #008000)]
+        LayoutNGBlockFlow (anonymous) at (2,2) size 780x28
+          LayoutText {#text} at (0,0) size 36x27
+            text run at (0,0) width 36: "xxx"
+        LayoutTable {TABLE} at (2,30) size 46x82 [border: (1px outset #808080)]
+          LayoutTableSection {TBODY} at (1,1) size 44x80
+            LayoutTableRow {TR} at (0,2) size 44x24
+              LayoutNGTableCell {TD} at (2,2) size 12x24 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "1"
+              LayoutNGTableCell {TD} at (16,2) size 12x24 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "2"
+              LayoutNGTableCell {TD} at (30,2) size 12x24 [border: (1px inset #808080)] [r=0 c=2 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "3"
+            LayoutTableRow {TR} at (0,28) size 44x24
+              LayoutNGTableCell {TD} at (2,28) size 12x24 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "4"
+              LayoutNGTableCell {TD} at (16,28) size 12x24 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "5"
+              LayoutNGTableCell {TD} at (30,28) size 12x24 [border: (1px inset #808080)] [r=1 c=2 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "6"
+            LayoutTableRow {TR} at (0,54) size 44x24
+              LayoutNGTableCell {TD} at (2,54) size 12x24 [border: (1px inset #808080)] [r=2 c=0 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "7"
+              LayoutNGTableCell {TD} at (16,54) size 12x24 [border: (1px inset #808080)] [r=2 c=1 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "8"
+              LayoutNGTableCell {TD} at (30,54) size 12x24 [border: (1px inset #808080)] [r=2 c=2 rs=1 cs=1]
+                LayoutText {#text} at (2,2) size 8x19
+                  text run at (2,2) width 8: "9"
+      LayoutBlockFlow {DIV} at (0,354) size 784x114
+        LayoutBlockFlow {DIV} at (0,0) size 784x114 [border: (2px solid #FF0000)]
+          LayoutNGBlockFlow (anonymous) at (2,2) size 780x28
+            LayoutText {#text} at (0,0) size 36x27
+              text run at (0,0) width 36: "xxx"
+          LayoutTable {TABLE} at (2,30) size 46x82 [border: (1px outset #808080)]
+            LayoutTableSection {TBODY} at (1,1) size 44x80
+              LayoutTableRow {TR} at (0,2) size 44x24
+                LayoutTableCell {TD} at (2,2) size 12x24 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "1"
+                LayoutTableCell {TD} at (16,2) size 12x24 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "2"
+                LayoutTableCell {TD} at (30,2) size 12x24 [border: (1px inset #808080)] [r=0 c=2 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "3"
+              LayoutTableRow {TR} at (0,28) size 44x24
+                LayoutTableCell {TD} at (2,28) size 12x24 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "4"
+                LayoutTableCell {TD} at (16,28) size 12x24 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "5"
+                LayoutTableCell {TD} at (30,28) size 12x24 [border: (1px inset #808080)] [r=1 c=2 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "6"
+              LayoutTableRow {TR} at (0,54) size 44x24
+                LayoutTableCell {TD} at (2,54) size 12x24 [border: (1px inset #808080)] [r=2 c=0 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "7"
+                LayoutTableCell {TD} at (16,54) size 12x24 [border: (1px inset #808080)] [r=2 c=1 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "8"
+                LayoutTableCell {TD} at (30,54) size 12x24 [border: (1px inset #808080)] [r=2 c=2 rs=1 cs=1]
+                  LayoutText {#text} at (2,2) size 8x19
+                    text run at (2,2) width 8: "9"
+caret: position 3 of child 1 {#text} of child 1 {DIV} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/caret-rtl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/caret-rtl-expected.txt
new file mode 100644
index 0000000..0844456
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/caret-rtl-expected.txt
@@ -0,0 +1,15 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow (anonymous) at (0,0) size 784x20
+        LayoutText {#text} at (0,0) size 566x19
+          text run at (0,0) width 566: "This tests that clicking in a contenteditable div will set the caret in the right edge of the div"
+        LayoutBR {BR} at (566,0) size 0x0
+      LayoutNGBlockFlow {P} at (0,36) size 784x20
+        LayoutText {#text} at (0,0) size 397x19
+          text run at (0,0) width 397: "Click in the div, the caret should be on the right edge of the div."
+      LayoutBlockFlow {DIV} at (0,72) size 200x368
+caret: position 0 of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/layers/layer-visibility-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/layers/layer-visibility-expected.txt
new file mode 100644
index 0000000..686afe1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/layers/layer-visibility-expected.txt
@@ -0,0 +1,304 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow (floating) {DIV} at (0,0) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (134,0) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (268,0) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (402,0) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (536,0) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (0,104) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (134,104) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (268,104) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (402,104) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (536,104) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (0,208) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (134,208) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (268,208) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (402,208) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (536,208) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (0,312) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (134,312) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (268,312) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (402,312) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (536,312) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (0,416) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (134,416) size 134x104 [border: (2px solid #0000FF)]
+      LayoutNGBlockFlow (floating) {DIV} at (268,416) size 134x104 [border: (2px solid #0000FF)]
+layer at (10,10) size 130x48
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x48
+    LayoutNGBlockFlow (anonymous) at (0,0) size 130x20
+      LayoutText {#text} at (0,0) size 79x19
+        text run at (0,0) width 79: "1 green box:"
+    LayoutNGBlockFlow {DIV} at (0,20) size 130x28 [border: (2px solid #008000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 126x24 [border: (2px solid #FF0000)]
+        LayoutText {#text} at (2,2) size 35x19
+          text run at (2,2) width 35: "failed"
+layer at (144,10) size 130x68
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x68
+    LayoutNGBlockFlow (anonymous) at (0,0) size 130x40
+      LayoutText {#text} at (0,0) size 107x39
+        text run at (0,0) width 107: "2 green box with"
+        text run at (0,20) width 57: "word ok:"
+    LayoutNGBlockFlow {DIV} at (0,40) size 130x28 [border: (2px solid #FF0000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 126x24 [border: (2px solid #008000)]
+        LayoutText {#text} at (2,2) size 16x19
+          text run at (2,2) width 16: "ok"
+layer at (278,10) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 107x39
+      text run at (0,0) width 107: "3 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (278,50) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+    LayoutNGBlockFlow {DIV} at (2,2) size 126x24 [border: (2px solid #008000)]
+      LayoutText {#text} at (2,2) size 16x19
+        text run at (2,2) width 16: "ok"
+layer at (412,10) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 107x39
+      text run at (0,0) width 107: "4 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (412,50) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+layer at (414,52) size 126x30
+  LayoutNGBlockFlow (positioned) {DIV} at (2,2) size 126x30 [border: (2px solid #008000)]
+    LayoutText {#text} at (2,2) size 16x19
+      text run at (2,2) width 16: "ok"
+layer at (546,10) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 107x39
+      text run at (0,0) width 107: "5 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (546,50) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+    LayoutNGBlockFlow {DIV} at (2,2) size 126x28 [border: (2px solid #FF0000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 122x24 [border: (2px solid #008000)]
+        LayoutText {#text} at (2,2) size 16x19
+          text run at (2,2) width 16: "ok"
+layer at (10,114) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 107x39
+      text run at (0,0) width 107: "6 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (10,154) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+hidden layer at (12,156) size 126x30
+  LayoutNGBlockFlow (positioned) {DIV} at (2,2) size 126x30 [border: (2px solid #FF0000)]
+    LayoutNGBlockFlow {DIV} at (2,2) size 122x24 [border: (2px solid #008000)]
+      LayoutText {#text} at (2,2) size 16x19
+        text run at (2,2) width 16: "ok"
+layer at (144,114) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 107x39
+      text run at (0,0) width 107: "7 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (144,154) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+hidden layer at (146,156) size 126x30
+  LayoutNGBlockFlow (positioned) {DIV} at (2,2) size 126x30 [border: (2px solid #FF0000)]
+layer at (148,158) size 122x26
+  LayoutNGBlockFlow (positioned) {DIV} at (2,2) size 122x26 [border: (2px solid #008000)]
+    LayoutText {#text} at (2,2) size 16x19
+      text run at (2,2) width 16: "ok"
+layer at (278,114) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 122x39
+      text run at (0,0) width 122: "8 double green box"
+      text run at (0,20) width 89: "with word ok:"
+layer at (278,154) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #008000)]
+hidden layer at (280,156) size 126x30
+  LayoutNGBlockFlow (positioned) {DIV} at (2,2) size 126x30 [border: (2px solid #FF0000)]
+layer at (282,158) size 122x26
+  LayoutNGBlockFlow (positioned) {DIV} at (2,2) size 122x26 [border: (2px solid #008000)]
+    LayoutText {#text} at (2,2) size 16x19
+      text run at (2,2) width 16: "ok"
+layer at (412,114) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 107x39
+      text run at (0,0) width 107: "9 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (412,154) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+hidden layer at (414,156) size 126x30
+  LayoutNGBlockFlow (positioned) {DIV} at (2,2) size 126x30 [border: (2px solid #FF0000)]
+layer at (416,158) size 122x26
+  LayoutNGBlockFlow (positioned) {DIV} at (2,2) size 122x26 [border: (2px solid #008000)]
+    LayoutText {#text} at (2,2) size 16x19
+      text run at (2,2) width 16: "ok"
+layer at (546,114) size 130x20
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x20
+    LayoutText {#text} at (0,0) size 87x19
+      text run at (0,0) width 87: "10 green box:"
+hidden layer at (546,134) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,20) size 130x34 [border: (2px solid #FF0000)]
+layer at (548,136) size 126x30
+  LayoutNGBlockFlow (positioned) {DIV} at (2,2) size 126x30 [border: (2px solid #008000)]
+hidden layer at (550,138) size 122x26
+  LayoutNGBlockFlow (positioned) {DIV} at (2,2) size 122x26 [border: (2px solid #FF0000)]
+    LayoutText {#text} at (2,2) size 35x19
+      text run at (2,2) width 35: "failed"
+layer at (10,218) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 115x39
+      text run at (0,0) width 115: "11 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (10,258) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+    LayoutNGBlockFlow {DIV} at (2,2) size 126x28 [border: (2px solid #FF0000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 122x24 [border: (2px solid #008000)]
+        LayoutText {#text} at (2,2) size 16x19
+          text run at (2,2) width 16: "ok"
+layer at (144,218) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 115x39
+      text run at (0,0) width 115: "12 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (144,258) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+    LayoutNGBlockFlow {DIV} at (2,2) size 126x28 [border: (2px solid #FF0000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 122x24 [border: (2px solid #008000)]
+        LayoutText {#text} at (2,2) size 16x19
+          text run at (2,2) width 16: "ok"
+layer at (278,218) size 130x20
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x20
+    LayoutText {#text} at (0,0) size 87x19
+      text run at (0,0) width 87: "13 green box:"
+hidden layer at (278,238) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,20) size 130x34 [border: (2px solid #FF0000)]
+    LayoutNGBlockFlow {DIV} at (2,2) size 126x28 [border: (2px solid #008000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 122x24 [border: (2px solid #FF0000)]
+        LayoutText {#text} at (2,2) size 35x19
+          text run at (2,2) width 35: "failed"
+layer at (412,218) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 115x39
+      text run at (0,0) width 115: "14 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (412,258) size 130x30
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x30
+    LayoutNGBlockFlow {DIV} at (0,0) size 130x24 [border: (2px solid #008000)]
+      LayoutText {#text} at (2,2) size 16x19
+        text run at (2,2) width 16: "ok"
+layer at (546,218) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 115x39
+      text run at (0,0) width 115: "15 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (546,258) size 130x30
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x30
+layer at (546,258) size 130x30
+  LayoutNGBlockFlow (positioned) {DIV} at (0,0) size 130x30 [border: (2px solid #008000)]
+    LayoutText {#text} at (2,2) size 16x19
+      text run at (2,2) width 16: "ok"
+layer at (10,322) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 115x39
+      text run at (0,0) width 115: "16 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (10,362) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+    LayoutNGBlockFlow {DIV} at (2,2) size 126x52 [border: (2px solid #FF0000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 122x24 [border: (2px solid #FF0000)]
+        LayoutText {#text} at (2,2) size 20x19
+          text run at (2,2) width 20: "fail"
+      LayoutNGBlockFlow {DIV} at (2,26) size 122x24 [border: (2px solid #008000)]
+        LayoutText {#text} at (2,2) size 16x19
+          text run at (2,2) width 16: "ok"
+layer at (144,322) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 115x39
+      text run at (0,0) width 115: "17 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (144,362) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+    LayoutNGBlockFlow {DIV} at (2,2) size 126x52 [border: (2px solid #FF0000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 122x24 [border: (2px solid #008000)]
+        LayoutText {#text} at (2,2) size 16x19
+          text run at (2,2) width 16: "ok"
+      LayoutNGBlockFlow {DIV} at (2,26) size 122x24 [border: (2px solid #FF0000)]
+        LayoutText {#text} at (2,2) size 20x19
+          text run at (2,2) width 20: "fail"
+layer at (278,322) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 115x39
+      text run at (0,0) width 115: "18 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (278,362) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+    LayoutNGBlockFlow {DIV} at (2,2) size 126x52 [border: (2px solid #FF0000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 122x24 [border: (2px solid #FF0000)]
+        LayoutText {#text} at (2,2) size 20x19
+          text run at (2,2) width 20: "fail"
+      LayoutNGBlockFlow {DIV} at (2,26) size 122x24 [border: (2px solid #008000)]
+        LayoutText {#text} at (2,2) size 16x19
+          text run at (2,2) width 16: "ok"
+layer at (412,322) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 115x39
+      text run at (0,0) width 115: "19 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (412,362) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+    LayoutNGBlockFlow {DIV} at (2,2) size 126x28 [border: (2px solid #FF0000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 122x24 [border: (2px solid #FF0000)]
+        LayoutText {#text} at (2,2) size 20x19
+          text run at (2,2) width 20: "fail"
+    LayoutNGBlockFlow {DIV} at (2,30) size 126x28 [border: (2px solid #FF0000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 122x24 [border: (2px solid #008000)]
+        LayoutText {#text} at (2,2) size 16x19
+          text run at (2,2) width 16: "ok"
+layer at (546,322) size 130x20
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x20
+    LayoutText {#text} at (0,0) size 87x19
+      text run at (0,0) width 87: "20 green box:"
+hidden layer at (546,342) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,20) size 130x34 [border: (2px solid #FF0000)]
+    LayoutNGBlockFlow {DIV} at (2,2) size 126x52 [border: (2px solid #008000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 122x24 [border: (2px solid #FF0000)]
+        LayoutText {#text} at (2,2) size 16x19
+          text run at (2,2) width 16: "ok"
+      LayoutNGBlockFlow {DIV} at (2,26) size 122x24 [border: (2px solid #008000)]
+        LayoutText {#text} at (2,2) size 16x19
+          text run at (2,2) width 16: "ok"
+layer at (10,426) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 124x39
+      text run at (0,0) width 124: "21 two green boxes"
+      text run at (0,20) width 89: "with word ok:"
+hidden layer at (10,466) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+    LayoutNGBlockFlow {DIV} at (2,2) size 126x28 [border: (2px solid #FF0000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 122x24 [border: (2px solid #008000)]
+        LayoutText {#text} at (2,2) size 16x19
+          text run at (2,2) width 16: "ok"
+    LayoutNGBlockFlow {DIV} at (2,30) size 126x28 [border: (2px solid #FF0000)]
+      LayoutNGBlockFlow {DIV} at (2,2) size 122x24 [border: (2px solid #008000)]
+        LayoutText {#text} at (2,2) size 16x19
+          text run at (2,2) width 16: "ok"
+layer at (144,426) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 115x39
+      text run at (0,0) width 115: "22 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (144,466) size 130x34
+  LayoutNGBlockFlow (positioned) {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+layer at (146,468) size 126x30
+  LayoutNGBlockFlow (positioned) {DIV} at (2,2) size 126x30 [border: (2px solid #008000)]
+    LayoutText {#text} at (2,2) size 16x19
+      text run at (2,2) width 16: "ok"
+layer at (278,426) size 130x40
+  LayoutNGBlockFlow (relative positioned) {DIV} at (2,2) size 130x40
+    LayoutText {#text} at (0,0) size 115x39
+      text run at (0,0) width 115: "23 green box with"
+      text run at (0,20) width 57: "word ok:"
+hidden layer at (278,466) size 130x34
+  LayoutNGBlockFlow (positioned) zI: 1 {DIV} at (0,40) size 130x34 [border: (2px solid #FF0000)]
+hidden layer at (280,468) size 126x30
+  LayoutNGBlockFlow (positioned) {DIV} at (2,2) size 126x30 [border: (2px solid #FF0000)]
+layer at (282,470) size 122x26
+  LayoutNGBlockFlow (positioned) {DIV} at (2,2) size 122x26 [border: (2px solid #008000)]
+    LayoutText {#text} at (2,2) size 16x19
+      text run at (2,2) width 16: "ok"
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/simple-subframe-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/simple-subframe-expected.txt
new file mode 100644
index 0000000..80108c2e7d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/simple-subframe-expected.txt
@@ -0,0 +1,32 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+frame "f1" - didReceiveTitle: 
+frame "f1" - didStartProvisionalLoadForFrame
+main frame - didReceiveTitle: 
+main frame - didFinishDocumentLoadForFrame
+frame "f1" - didCommitLoadForFrame
+frame "f1" - didReceiveTitle: 
+frame "f1" - didFinishDocumentLoadForFrame
+frame "f1" - didHandleOnloadEventsForFrame
+frame "f1" - didFinishLoadForFrame
+main frame - didHandleOnloadEventsForFrame
+main frame - didFinishLoadForFrame
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutText {#text} at (0,0) size 482x19
+        text run at (0,0) width 482: "This is a test of load callbacks. It is only useful inside the regression test tool."
+      LayoutBR {BR} at (482,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+layer at (8,28) size 304x154
+  LayoutIFrame {IFRAME} at (0,20) size 304x154 [border: (2px inset #EEEEEE)]
+    layer at (0,0) size 300x150
+      LayoutView at (0,0) size 300x150
+    layer at (0,0) size 300x150
+      LayoutNGBlockFlow {HTML} at (0,0) size 300x150
+        LayoutNGBlockFlow {BODY} at (8,8) size 284x134
+          LayoutInline {B} at (0,0) size 23x19
+            LayoutText {#text} at (0,0) size 23x19
+              text run at (0,0) width 23: "test"
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/media/audio-controls-rendering-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/media/audio-controls-rendering-expected.txt
new file mode 100644
index 0000000..62b4705
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/media/audio-controls-rendering-expected.txt
@@ -0,0 +1,137 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x20
+        LayoutText {#text} at (0,0) size 151x19
+          text run at (0,0) width 151: "Test controls placement."
+      LayoutNGBlockFlow (anonymous) at (0,36) size 784x124
+        LayoutBR {BR} at (300,32) size 0x0
+        LayoutBR {BR} at (0,32) size 0x0
+        LayoutBR {BR} at (320,69) size 0x0
+        LayoutBR {BR} at (0,84) size 0x0
+        LayoutBR {BR} at (0,104) size 0x0
+layer at (8,44) size 300x32
+  LayoutMedia {AUDIO} at (0,0) size 300x32 [bgcolor=#0000FF]
+layer at (8,96) size 320x32
+  LayoutMedia {AUDIO} at (0,52) size 320x32 [bgcolor=#0000FF]
+layer at (8,44) size 300x32
+  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 300x32
+    LayoutNGBlockFlow {DIV} at (0,0) size 300x32
+layer at (8,44) size 300x32 scrollHeight 40
+  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 300x32 [bgcolor=#FAFAFA]
+    LayoutButton {INPUT} at (0,0) size 32x32
+    LayoutFlexibleBox {DIV} at (32,0) size 24x32 [color=#5A5A5A]
+      LayoutNGBlockFlow (anonymous) at (0,0) size 24x32
+        LayoutText {#text} at (0,8) size 24x15
+          text run at (0,8) width 24: "0:00"
+    LayoutFlexibleBox {DIV} at (56,0) size 34x32 [color=#5A5A5A]
+      LayoutNGBlockFlow (anonymous) at (4,0) size 30x32
+        LayoutText {#text} at (0,8) size 30x15
+          text run at (0,8) width 30: "/ 0:07"
+    LayoutSlider {INPUT} at (108,2) size 81x28
+      LayoutFlexibleBox {DIV} at (0,14) size 81x0
+    LayoutButton {INPUT} at (207,0) size 32x32
+    LayoutSlider {INPUT} at (257,2) size 25x28
+      LayoutFlexibleBox {DIV} at (0,14) size 25x0
+layer at (98,60) size 117x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,0) size 117x0
+layer at (116,59) size 81x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 81x2 [bgcolor=#DADADA]
+layer at (247,60) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,0) size 61x0
+layer at (265,59) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (116,59) size 81x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 81x2 [bgcolor=#5A5A5A]
+layer at (116,59) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (265,59) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (265,59) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (98,36) size 36x48 backgroundClip at (8,44) size 300x32 clip at (8,44) size 300x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (272,36) size 36x48 backgroundClip at (8,44) size 300x32 clip at (8,44) size 300x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
+layer at (8,96) size 320x32
+  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x32
+    LayoutNGBlockFlow {DIV} at (0,0) size 320x32
+layer at (8,96) size 320x32 scrollHeight 40
+  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x32 [bgcolor=#FAFAFA]
+    LayoutButton {INPUT} at (0,0) size 32x32
+    LayoutFlexibleBox {DIV} at (32,0) size 24x32 [color=#5A5A5A]
+      LayoutNGBlockFlow (anonymous) at (0,0) size 24x32
+        LayoutText {#text} at (0,8) size 24x15
+          text run at (0,8) width 24: "0:00"
+    LayoutFlexibleBox {DIV} at (56,0) size 34x32 [color=#5A5A5A]
+      LayoutNGBlockFlow (anonymous) at (4,0) size 30x32
+        LayoutText {#text} at (0,8) size 30x15
+          text run at (0,8) width 30: "/ 0:07"
+    LayoutSlider {INPUT} at (108,2) size 93.06x28
+      LayoutFlexibleBox {DIV} at (0,14) size 93.06x0
+    LayoutButton {INPUT} at (219.06,0) size 32x32
+    LayoutSlider {INPUT} at (269.06,2) size 32.94x28
+      LayoutFlexibleBox {DIV} at (0,14) size 32.94x0
+layer at (98,112) size 129x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,0) size 129.06x0
+layer at (116,111) size 93x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 93.06x2 [bgcolor=#DADADA]
+layer at (259,112) size 69x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,0) size 68.94x0
+layer at (277,111) size 33x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 32.94x2 [bgcolor=#DADADA]
+layer at (116,111) size 93x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 93x2 [bgcolor=#5A5A5A]
+layer at (116,111) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (277,111) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (277,111) size 33x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 33x2 [bgcolor=#4285F4]
+layer at (98,88) size 36x48 backgroundClip at (8,96) size 320x32 clip at (8,96) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (292,88) size 36x48 backgroundClip at (8,96) size 320x32 clip at (8,96) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (32.94,-24) size 36x48
+layer at (8,148) size 320x100
+  LayoutMedia (positioned) {AUDIO} at (8,148) size 320x100 [bgcolor=#0000FF]
+layer at (8,148) size 320x100
+  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x100
+    LayoutNGBlockFlow {DIV} at (0,68) size 320x32
+layer at (8,216) size 320x32 scrollHeight 40
+  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x32 [bgcolor=#FAFAFA]
+    LayoutButton {INPUT} at (0,0) size 32x32
+    LayoutFlexibleBox {DIV} at (32,0) size 24x32 [color=#5A5A5A]
+      LayoutNGBlockFlow (anonymous) at (0,0) size 24x32
+        LayoutText {#text} at (0,8) size 24x15
+          text run at (0,8) width 24: "0:00"
+    LayoutFlexibleBox {DIV} at (56,0) size 34x32 [color=#5A5A5A]
+      LayoutNGBlockFlow (anonymous) at (4,0) size 30x32
+        LayoutText {#text} at (0,8) size 30x15
+          text run at (0,8) width 30: "/ 0:07"
+    LayoutSlider {INPUT} at (108,2) size 93.06x28
+      LayoutFlexibleBox {DIV} at (0,14) size 93.06x0
+    LayoutButton {INPUT} at (219.06,0) size 32x32
+    LayoutSlider {INPUT} at (269.06,2) size 32.94x28
+      LayoutFlexibleBox {DIV} at (0,14) size 32.94x0
+layer at (98,232) size 129x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,0) size 129.06x0
+layer at (116,231) size 93x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 93.06x2 [bgcolor=#DADADA]
+layer at (259,232) size 69x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,0) size 68.94x0
+layer at (277,231) size 33x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 32.94x2 [bgcolor=#DADADA]
+layer at (116,231) size 93x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 93x2 [bgcolor=#5A5A5A]
+layer at (116,231) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (277,231) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (277,231) size 33x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 33x2 [bgcolor=#4285F4]
+layer at (98,208) size 36x48 backgroundClip at (8,216) size 320x32 clip at (8,216) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (292,208) size 36x48 backgroundClip at (8,216) size 320x32 clip at (8,216) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (32.94,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/media/video-display-toggle-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/media/video-display-toggle-expected.txt
new file mode 100644
index 0000000..76c9c8b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/media/video-display-toggle-expected.txt
@@ -0,0 +1,54 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutText {#text} at (0,0) size 493x19
+        text run at (0,0) width 493: "This tests that toggling the display property won't make the controls disappear."
+      LayoutBR {BR} at (493,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+layer at (8,28) size 320x240
+  LayoutVideo {VIDEO} at (0,20) size 320x240
+layer at (8,28) size 320x240
+  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x240
+    LayoutNGBlockFlow {DIV} at (0,208) size 320x32
+layer at (8,28) size 320x198
+  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x198
+layer at (8,236) size 320x32 scrollHeight 40
+  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x32 [bgcolor=#FAFAFA]
+    LayoutButton {INPUT} at (0,0) size 32x32
+    LayoutFlexibleBox {DIV} at (32,0) size 24x32 [color=#5A5A5A]
+      LayoutNGBlockFlow (anonymous) at (0,0) size 24x32
+        LayoutText {#text} at (0,8) size 24x15
+          text run at (0,8) width 24: "0:00"
+    LayoutFlexibleBox {DIV} at (56,0) size 34x32 [color=#5A5A5A]
+      LayoutNGBlockFlow (anonymous) at (4,0) size 30x32
+        LayoutText {#text} at (0,8) size 30x15
+          text run at (0,8) width 30: "/ 0:06"
+    LayoutSlider {INPUT} at (108,2) size 69x28
+      LayoutFlexibleBox {DIV} at (0,14) size 69x0
+    LayoutButton {INPUT} at (195,0) size 32x32
+    LayoutSlider {INPUT} at (245,2) size 25x28
+      LayoutFlexibleBox {DIV} at (0,14) size 25x0
+layer at (296,236) size 32x32
+  LayoutButton {INPUT} at (288,0) size 32x32
+layer at (98,252) size 105x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,0) size 105x0
+layer at (116,251) size 69x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 69x2 [bgcolor=#DADADA]
+layer at (235,252) size 61x0
+  LayoutBlockFlow (relative positioned) {DIV} at (-18,0) size 61x0
+layer at (253,251) size 25x2
+  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 25x2 [bgcolor=#DADADA]
+layer at (116,251) size 69x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 69x2 [bgcolor=#5A5A5A]
+layer at (116,251) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
+layer at (253,251) size 0x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
+layer at (253,251) size 25x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 25x2 [bgcolor=#4285F4]
+layer at (98,228) size 36x48 backgroundClip at (8,236) size 320x32 clip at (8,236) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
+layer at (260,228) size 36x48 backgroundClip at (8,236) size 320x32 clip at (8,236) size 320x32
+  LayoutBlockFlow (positioned) zI: 2 {DIV} at (25,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/media/video-transformed-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/media/video-transformed-expected.txt
new file mode 100644
index 0000000..45a7ae6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/media/video-transformed-expected.txt
@@ -0,0 +1,39 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
+      LayoutNGBlockFlow {P} at (0,0) size 784x20
+        LayoutText {#text} at (0,0) size 215x19
+          text run at (0,0) width 215: "Test painting of transformed video"
+      LayoutNGBlockFlow (anonymous) at (0,36) size 784x483
+        LayoutText {#text} at (0,141) size 4x19
+          text run at (0,141) width 4: " "
+        LayoutBR {BR} at (210,141) size 0x0
+        LayoutText {#text} at (0,302) size 4x19
+          text run at (0,302) width 4: " "
+        LayoutBR {BR} at (210,302) size 0x0
+        LayoutText {#text} at (0,463) size 4x19
+          text run at (0,463) width 4: " "
+        LayoutBR {BR} at (210,463) size 0x0
+layer at (12,44) size 206x156
+  LayoutVideo {VIDEO} at (4,0) size 206x156 [border: (3px solid #FF0000)]
+layer at (15,47) size 200x150
+  LayoutFlexibleBox (relative positioned) {DIV} at (3,3) size 200x150
+    LayoutNGBlockFlow {DIV} at (0,118) size 200x32
+layer at (15,47) size 200x108
+  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 200x108
+layer at (12,205) size 206x156
+  LayoutVideo {VIDEO} at (4,161) size 206x156 [border: (3px solid #FF0000)]
+layer at (15,208) size 200x150
+  LayoutFlexibleBox (relative positioned) {DIV} at (3,3) size 200x150
+    LayoutNGBlockFlow {DIV} at (0,118) size 200x32
+layer at (15,208) size 200x108 backgroundClip at (65,246) size 100x54 clip at (65,246) size 100x54
+  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 200x108
+layer at (12,366) size 206x156
+  LayoutVideo {VIDEO} at (4,322) size 206x156 [border: (3px solid #FF0000)]
+layer at (15,369) size 200x150
+  LayoutFlexibleBox (relative positioned) {DIV} at (3,3) size 200x150
+    LayoutNGBlockFlow {DIV} at (0,118) size 200x32
+layer at (15,369) size 200x108
+  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 200x108
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/plugins/plugin-scroll-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/plugins/plugin-scroll-expected.txt
new file mode 100644
index 0000000..8b6a87c5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/plugins/plugin-scroll-expected.txt
@@ -0,0 +1,19 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
+CONSOLE MESSAGE: Blink Test Plugin: initializing
+CONSOLE MESSAGE: Blink Test Plugin: initializing
+layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollY 100.00 scrollHeight 3016
+  LayoutView at (0,0) size 800x600
+layer at (0,-100) size 785x3016 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 785x3016
+    LayoutNGBlockFlow {BODY} at (8,8) size 769x3000
+      LayoutNGBlockFlow {DIV} at (0,0) size 769x3000
+        LayoutBR {BR} at (284,149) size 0x0
+        LayoutBR {BR} at (284,318) size 0x0
+        LayoutBR {BR} at (284,487) size 0x0
+layer at (28,-72) size 244x124 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutEmbeddedObject {EMBED} at (20,20) size 244x124 [border: (2px solid #000000)]
+layer at (28,97) size 244x124
+  LayoutEmbeddedObject {EMBED} at (20,189) size 244x124 [border: (2px solid #000000)]
+layer at (28,266) size 244x124
+  LayoutEmbeddedObject {EMBED} at (20,358) size 244x124 [border: (2px solid #000000)]
+scrolled to 0,100
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/plugins/webview-plugin-scroll-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/plugins/webview-plugin-scroll-expected.txt
new file mode 100644
index 0000000..68a91cc5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/plugins/webview-plugin-scroll-expected.txt
@@ -0,0 +1,17 @@
+layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollY 100.00 scrollHeight 3523
+  LayoutView at (0,0) size 800x600
+layer at (0,-100) size 785x3523 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 785x3523
+    LayoutNGBlockFlow {BODY} at (8,8) size 769x3507
+      LayoutNGBlockFlow (anonymous) at (0,0) size 769x507
+        LayoutBR {BR} at (284,149) size 0x0
+        LayoutBR {BR} at (284,318) size 0x0
+        LayoutBR {BR} at (284,487) size 0x0
+      LayoutNGBlockFlow {DIV} at (0,507) size 769x3000
+layer at (28,-72) size 244x124 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutEmbeddedObject {EMBED} at (20,20) size 244x124 [border: (2px solid #000000)]
+layer at (28,97) size 244x124
+  LayoutEmbeddedObject {EMBED} at (20,189) size 244x124 [border: (2px solid #000000)]
+layer at (28,266) size 244x124
+  LayoutEmbeddedObject {EMBED} at (20,358) size 244x124 [border: (2px solid #000000)]
+scrolled to 0,100
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/svg/hixie/error/013-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/svg/hixie/error/013-expected.txt
new file mode 100644
index 0000000..c9f33d9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/svg/hixie/error/013-expected.txt
@@ -0,0 +1,16 @@
+CONSOLE ERROR: line 10: Error: <svg> attribute width: A negative value is not valid. ("-100")
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x105
+  LayoutNGBlockFlow {html} at (0,0) size 800x105
+    LayoutNGBlockFlow {body} at (8,8) size 784x81
+      LayoutNGBlockFlow (anonymous) at (0,0) size 784x25
+        LayoutSVGRoot {svg} at (0,0) size 784x20
+          LayoutSVGText {text} at (10,20) size 125x12 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (10,20) size 125x12
+              chunk 1 text run 1 at (10.00,30.00) startOffset 0 endOffset 30 width 125.00: "FAIL (This should not render.)"
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutNGBlockFlow {p} at (0,41) size 784x40 [color=#008000]
+        LayoutText {#text} at (0,0) size 747x39
+          text run at (0,0) width 747: "This line should be green, the word \"FAIL\" should not appear on this page, but a highly perceivable indication of error"
+          text run at (0,20) width 190: "should be present somewhere."
diff --git a/third_party/WebKit/LayoutTests/geolocation-api/resources/geolocation-mock.js b/third_party/WebKit/LayoutTests/geolocation-api/resources/geolocation-mock.js
index b9b3fbe..05b33b9 100644
--- a/third_party/WebKit/LayoutTests/geolocation-api/resources/geolocation-mock.js
+++ b/third_party/WebKit/LayoutTests/geolocation-api/resources/geolocation-mock.js
@@ -86,7 +86,7 @@
     this.geoposition_.altitudeAccuracy = altitudeAccuracy;
     this.geoposition_.heading = heading;
     this.geoposition_.speed = speed;
-    this.geoposition_.timestamp = new mojo.common.mojom.Time();
+    this.geoposition_.timestamp = new mojoBase.mojom.Time();
     // The new Date().getTime() returns the number of milliseconds since the
     // UNIX epoch (1970-01-01 00::00:00 UTC), while |internalValue| of the
     // device.mojom.Geoposition represents the value of microseconds since the
@@ -111,7 +111,7 @@
   setGeolocationPositionUnavailableError(message) {
     this.geoposition_ = new device.mojom.Geoposition();
     this.geoposition_.valid = false;
-    this.geoposition_.timestamp = new mojo.common.mojom.Time();
+    this.geoposition_.timestamp = new mojoBase.mojom.Time();
     this.geoposition_.errorMessage = message;
     this.geoposition_.errorCode =
         device.mojom.Geoposition.ErrorCode.POSITION_UNAVAILABLE;
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame-expected.txt b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame-expected.txt
index 924331a..e58e3453 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame-expected.txt
@@ -1,9 +1,9 @@
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/origin.mojom
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/url.mojom
-CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/common/time.mojom
+CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/public/mojom/base/time.mojom
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/origin.mojom
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/url.mojom
-CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/common/time.mojom
+CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/public/mojom/base/time.mojom
 This is a testharness.js-based test.
 PASS navigator.credentials should be undefined in documents generated from `data:` URLs.
 PASS navigator.credentials.create({publicKey}) in a javascript url should should succeed.
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame-expected.txt b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame-expected.txt
index 69122ca6..3f782f4 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame-expected.txt
@@ -1,9 +1,9 @@
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/origin.mojom
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/url.mojom
-CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/common/time.mojom
+CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/public/mojom/base/time.mojom
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/origin.mojom
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/url.mojom
-CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/common/time.mojom
+CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/public/mojom/base/time.mojom
 This is a testharness.js-based test.
 PASS navigator.credentials should be undefined in documents generated from `data:` URLs.
 PASS navigator.credentials.get({publicKey}) in a javascript url should should succeed.
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/profiler/cpu-profiler-fix-missing-samples-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/profiler/cpu-profiler-fix-missing-samples-expected.txt
new file mode 100644
index 0000000..370f5357
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/profiler/cpu-profiler-fix-missing-samples-expected.txt
@@ -0,0 +1,41 @@
+Tests missing samples are replaced with neighbor stacks.
+Profile tree:
+(root) id:1 total:16 self:0 depth:-1
+  (garbage collector) id:2 total:3.2 self:3.2 depth:0
+  (program) id:3 total:3.2 self:3.2 depth:0
+  bar id:4 total:6.4 self:3.2 depth:0
+    foo id:6 total:3.2 self:3.2 depth:1
+  baz id:5 total:3.2 self:3.2 depth:0
+raw samples: 3  4  3  4  3  6  2  2  3  6  3  3  6  5  3  6
+samples:     3  4  4  4  4  6  2  2  3  6  3  3  6  5  3  6
+timestamps: 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17
+forEachFrame iterator structure:
++ 0 (program) 1
+- 0 (program) 1 1 1
++ 0 bar 2
+  + 1 foo 6
+    + 2 (garbage collector) 7
+    - 2 (garbage collector) 7 2 2
+  - 1 foo 6 3 1
+- 0 bar 2 7 4
++ 0 (program) 9
+- 0 (program) 9 1 1
++ 0 bar 10
+  + 1 foo 10
+  - 1 foo 10 1 1
+- 0 bar 10 1 0
++ 0 (program) 11
+- 0 (program) 11 2 2
++ 0 bar 13
+  + 1 foo 13
+  - 1 foo 13 1 1
+- 0 bar 13 1 0
++ 0 baz 14
+- 0 baz 14 1 1
++ 0 (program) 15
+- 0 (program) 15 1 1
++ 0 bar 16
+  + 1 foo 16
+  - 1 foo 16 1 1
+- 0 bar 16 1 0
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/profiler/cpu-profiler-fix-missing-samples.js b/third_party/WebKit/LayoutTests/http/tests/devtools/profiler/cpu-profiler-fix-missing-samples.js
new file mode 100644
index 0000000..0f9d35c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/profiler/cpu-profiler-fix-missing-samples.js
@@ -0,0 +1,43 @@
+
+ // Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+(async function() {
+  TestRunner.addResult(`Tests missing samples are replaced with neighbor stacks.`);
+  await TestRunner.loadModule('cpu_profiler_test_runner');
+  const profile = {
+    startTime: 1000,
+    endTime: 4000,
+    nodes: [
+      {id: 1, hitCount: 0, callFrame: {functionName: '(root)'}, children: [2,3,4,5]},
+      {id: 2, hitCount: 1000, callFrame: {functionName: '(garbage collector)'}},
+      {id: 3, hitCount: 1000, callFrame: {functionName: '(program)'}},
+      {id: 4, hitCount: 1000, callFrame: {functionName: 'bar'}, children: [6]},
+      {id: 5, hitCount: 1000, callFrame: {functionName: 'baz'}},
+      {id: 6, hitCount: 1000, callFrame: {functionName: 'foo'}}
+    ],
+    samples: [3, 4, 3, 4, 3, 6, 2, 2, 3, 6, 3, 3, 6, 5, 3, 6]
+  };
+  profile.timeDeltas = profile.samples.map(_ => 1000);
+  profile.endTime = profile.startTime + profile.timeDeltas.length * 1000;
+  const rawSamples = profile.samples.slice();
+  const model = new SDK.CPUProfileDataModel(profile);
+  TestRunner.addResult('Profile tree:');
+  printTree('', model.profileHead);
+  function printTree(padding, node) {
+    TestRunner.addResult(
+        `${padding}${node.functionName} id:${node.id} total:${node.total} self:${node.self} depth:${node.depth}`);
+    node.children.sort((a, b) => a.id - b.id).forEach(printTree.bind(null, padding + '  '));
+  }
+  TestRunner.addResult('raw samples: ' + rawSamples.join('  '));
+  TestRunner.addResult('samples:     ' + model.samples.join('  '));
+  TestRunner.addResult('timestamps: ' + model.timestamps.join('  '));
+  TestRunner.addResult('forEachFrame iterator structure:');
+  model.forEachFrame(
+    (depth, node, ts) =>
+      TestRunner.addResult('  '.repeat(depth) + `+ ${depth} ${node.callFrame.functionName} ${ts}`),
+    (depth, node, ts, total, self) =>
+      TestRunner.addResult('  '.repeat(depth) + `- ${depth} ${node.callFrame.functionName} ${ts} ${total} ${self}`),
+  );
+  TestRunner.completeTest();
+})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details.js b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details.js
index 2f6a931c..210eb5b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details.js
@@ -38,10 +38,11 @@
         'data': {
           'page': '0x2f7b63884000',
           'sessionId': sessionId,
+          'persistentIds': true,
           'frames': [
             {'frame': '0x2f7b63884000', 'url': 'top-page-url', 'name': 'top-page-name'},
-            {'frame': '0x2f7b63884100', 'url': 'subframe-url1', 'name': 'subframe-name1'},
-            {'frame': '0x2f7b63884200', 'url': 'about:blank', 'name': 'subframe-name2'}
+            {'frame': '0x2f7b63884100', 'url': 'subframe-url1', 'name': 'subframe-name1', 'parent': '0x2f7b63884000'},
+            {'frame': '0x2f7b63884200', 'url': 'about:blank', 'name': 'subframe-name2', 'parent': '0x2f7b63884000'}
           ]
         }
       },
@@ -54,7 +55,7 @@
       'tts': 606543
     },
     {
-      'args': {'data': {'frame': '0x2f7b63884300', 'url': 'subframe-url3', 'name': 'subframe-name3'}},
+      'args': {'data': {'frame': '0x2f7b63884300', 'url': 'subframe-url3', 'name': 'subframe-name3', 'parent': '0x2f7b63884000'}},
       'cat': 'disabled-by-default-devtools.timeline',
       'name': 'CommitLoad',
       'ph': 'I',
diff --git a/third_party/WebKit/LayoutTests/virtual/enable-webauthn/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame-expected.txt b/third_party/WebKit/LayoutTests/virtual/enable-webauthn/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame-expected.txt
index 29354b75..dff5413 100644
--- a/third_party/WebKit/LayoutTests/virtual/enable-webauthn/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/enable-webauthn/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame-expected.txt
@@ -1,9 +1,9 @@
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/origin.mojom
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/url.mojom
-CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/common/time.mojom
+CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/public/mojom/base/time.mojom
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/origin.mojom
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/url.mojom
-CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/common/time.mojom
+CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/public/mojom/base/time.mojom
 This is a testharness.js-based test.
 PASS navigator.credentials should be undefined in documents generated from `data:` URLs.
 PASS navigator.credentials.create({publicKey}) in a javascript url should should succeed.
diff --git a/third_party/WebKit/LayoutTests/virtual/enable-webauthn/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame-expected.txt b/third_party/WebKit/LayoutTests/virtual/enable-webauthn/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame-expected.txt
index b80afa9..cb497f3 100644
--- a/third_party/WebKit/LayoutTests/virtual/enable-webauthn/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/enable-webauthn/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame-expected.txt
@@ -1,9 +1,9 @@
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/origin.mojom
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/url.mojom
-CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/common/time.mojom
+CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/public/mojom/base/time.mojom
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/origin.mojom
 CONSOLE WARNING: line 10: The following mojom is loaded multiple times: url/mojom/url.mojom
-CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/common/time.mojom
+CONSOLE WARNING: line 10: The following mojom is loaded multiple times: mojo/public/mojom/base/time.mojom
 This is a testharness.js-based test.
 PASS navigator.credentials should be undefined in documents generated from `data:` URLs.
 PASS navigator.credentials.get({publicKey}) in a javascript url should should succeed.
diff --git a/third_party/WebKit/LayoutTests/whitespace.txt b/third_party/WebKit/LayoutTests/whitespace.txt
index 949d9db..f062b30f 100644
--- a/third_party/WebKit/LayoutTests/whitespace.txt
+++ b/third_party/WebKit/LayoutTests/whitespace.txt
@@ -15,3 +15,4 @@
 T'was the sound of a broken interval record.
 
 But the data was inacurate.
+
diff --git a/third_party/WebKit/PRESUBMIT_test.py b/third_party/WebKit/PRESUBMIT_test.py
old mode 100644
new mode 100755
index c1ff0b0..5bbfafe
--- a/third_party/WebKit/PRESUBMIT_test.py
+++ b/third_party/WebKit/PRESUBMIT_test.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # Copyright 2017 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
diff --git a/third_party/WebKit/Source/DEPS b/third_party/WebKit/Source/DEPS
index 8d9ac22..b8756d4 100644
--- a/third_party/WebKit/Source/DEPS
+++ b/third_party/WebKit/Source/DEPS
@@ -12,11 +12,17 @@
     "+base/thread_annotations.h",
     "+base/time/time.h",
     "+build",
+    "+platform",
+    "+public/platform",
     "+services/service_manager/public/cpp/connector.h",
     "+services/service_manager/public/cpp/interface_provider.h",
     "+testing/gmock/include/gmock",
     "+testing/gtest/include/gtest",
     "+v8",
+
+    # We are moving from WTF_MAKE_NONCOPYABLE to DISALLOW_COPY_AND_ASSIGN. Stop
+    # new dependencies on WTF_MAKE_NONCOPYABLE.
+    "!platform/wtf/Noncopyable.h",
 ]
 
 skip_child_includes = [
diff --git a/third_party/WebKit/Source/bindings/DEPS b/third_party/WebKit/Source/bindings/DEPS
index e11836d..1bf0ed5f 100644
--- a/third_party/WebKit/Source/bindings/DEPS
+++ b/third_party/WebKit/Source/bindings/DEPS
@@ -4,8 +4,6 @@
     "+core",
     "+gin/public",
     "+modules",
-    "+platform",
-    "+public/platform",
     "+services/network/public/mojom/fetch_api.mojom-blink.h",
     "+web/api",
 ]
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8WasmResponseExtensions.cpp b/third_party/WebKit/Source/bindings/core/v8/V8WasmResponseExtensions.cpp
index 3ed76217..ab6e290c 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8WasmResponseExtensions.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8WasmResponseExtensions.cpp
@@ -126,6 +126,12 @@
   explicit WasmDataLoaderClient() = default;
   void DidFetchDataLoadedCustomFormat() override {}
   void DidFetchDataLoadFailed() override { NOTREACHED(); }
+  void Abort() override {
+    // TODO(ricea): This should probably cause the promise owned by
+    // v8::WasmModuleObjectBuilderStreaming to reject with an AbortError
+    // DOMException. As it is, the cancellation will cause it to reject with a
+    // TypeError later.
+  }
 };
 
 // This callback may be entered as a promise is resolved, or directly
diff --git a/third_party/WebKit/Source/controller/DEPS b/third_party/WebKit/Source/controller/DEPS
index aca33a8..a6d0aaf 100644
--- a/third_party/WebKit/Source/controller/DEPS
+++ b/third_party/WebKit/Source/controller/DEPS
@@ -5,8 +5,6 @@
     "+modules",
     "+mojo/public",
     "+controller",
-    "+platform",
     "+web",
-    "+public/platform",
     "+public/web",
 ]
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index 885dc76..525c6866 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1923,8 +1923,6 @@
     "layout/LayoutTableRowTest.cpp",
     "layout/LayoutTableSectionTest.cpp",
     "layout/LayoutTableTest.cpp",
-    "layout/LayoutTestHelper.cpp",
-    "layout/LayoutTestHelper.h",
     "layout/LayoutTextControlTest.cpp",
     "layout/LayoutTextFragmentTest.cpp",
     "layout/LayoutTextTest.cpp",
@@ -2082,6 +2080,8 @@
     "svg/SVGTextContentElementTest.cpp",
     "svg/UnsafeSVGAttributeSanitizationTest.cpp",
     "svg/graphics/SVGImageTest.cpp",
+    "testing/CoreUnitTestHelper.cpp",
+    "testing/CoreUnitTestHelper.h",
     "testing/PageTestBase.cpp",
     "testing/PageTestBase.h",
     "testing/sim/SimCanvas.cpp",
diff --git a/third_party/WebKit/Source/core/DEPS b/third_party/WebKit/Source/core/DEPS
index b02be456..021ac60 100644
--- a/third_party/WebKit/Source/core/DEPS
+++ b/third_party/WebKit/Source/core/DEPS
@@ -13,10 +13,8 @@
     "-modules",
     "+mojo/public/cpp/bindings",
     "+mojo/public/cpp/system",
-    "+platform",
     "+public/common",
     "+public/mojom",
-    "+public/platform",
     "+public/public_features.h",
     "+public/web",
     "+services/metrics/public",
@@ -36,9 +34,6 @@
     # we resolve the control layer.
     "!core/frame/WebLocalFrameImpl.h",
     "!core/frame/WebRemoteFrameImpl.h",
-    # We are moving from WTF_MAKE_NONCOPYABLE to DISALLOW_COPY_AND_ASSIGN. Stop
-    # new dependencies on WTF_MAKE_NONCOPYABLE.
-    "!platform/wtf/Noncopyable.h",
 ]
 
 specific_include_rules = {
diff --git a/third_party/WebKit/Source/core/animation/AnimationTest.cpp b/third_party/WebKit/Source/core/animation/AnimationTest.cpp
index a13c3a7..70777eb6 100644
--- a/third_party/WebKit/Source/core/animation/AnimationTest.cpp
+++ b/third_party/WebKit/Source/core/animation/AnimationTest.cpp
@@ -40,8 +40,8 @@
 #include "core/dom/DOMNodeIds.h"
 #include "core/dom/Document.h"
 #include "core/dom/QualifiedName.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/paint/PaintLayer.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "core/testing/DummyPageHolder.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "platform/weborigin/KURL.h"
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp
index 8800b86..dc7f058 100644
--- a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp
+++ b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp
@@ -48,10 +48,10 @@
 #include "core/frame/FrameTestHelpers.h"
 #include "core/frame/WebLocalFrameImpl.h"
 #include "core/layout/LayoutObject.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/paint/ObjectPaintProperties.h"
 #include "core/style/ComputedStyle.h"
 #include "core/style/FilterOperations.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "core/testing/DummyPageHolder.h"
 #include "platform/animation/CompositorAnimationHost.h"
 #include "platform/animation/CompositorFloatAnimationCurve.h"
diff --git a/third_party/WebKit/Source/core/clipboard/DataTransferTest.cpp b/third_party/WebKit/Source/core/clipboard/DataTransferTest.cpp
index 26c80902..17671d73 100644
--- a/third_party/WebKit/Source/core/clipboard/DataTransferTest.cpp
+++ b/third_party/WebKit/Source/core/clipboard/DataTransferTest.cpp
@@ -9,7 +9,7 @@
 #include "core/frame/LocalFrameView.h"
 #include "core/frame/Settings.h"
 #include "core/layout/LayoutObject.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/DragImage.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleAdjusterTest.cpp b/third_party/WebKit/Source/core/css/resolver/StyleAdjusterTest.cpp
index 6a19bd9..3851057 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleAdjusterTest.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleAdjusterTest.cpp
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "core/dom/NodeComputedStyle.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/third_party/WebKit/Source/core/dom/LayoutTreeBuilderTraversalTest.cpp b/third_party/WebKit/Source/core/dom/LayoutTreeBuilderTraversalTest.cpp
index 70b26e1..fdb9409 100644
--- a/third_party/WebKit/Source/core/dom/LayoutTreeBuilderTraversalTest.cpp
+++ b/third_party/WebKit/Source/core/dom/LayoutTreeBuilderTraversalTest.cpp
@@ -8,8 +8,8 @@
 #include "core/dom/Element.h"
 #include "core/dom/Node.h"
 #include "core/dom/PseudoElement.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutText.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "core/testing/DummyPageHolder.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/third_party/WebKit/Source/core/dom/events/EventTargetTest.cpp b/third_party/WebKit/Source/core/dom/events/EventTargetTest.cpp
index 640fbedc..589e725b 100644
--- a/third_party/WebKit/Source/core/dom/events/EventTargetTest.cpp
+++ b/third_party/WebKit/Source/core/dom/events/EventTargetTest.cpp
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "bindings/core/v8/ScriptController.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/HistogramTester.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/editing/BUILD.gn b/third_party/WebKit/Source/core/editing/BUILD.gn
index bdb002f9..a6c2221 100644
--- a/third_party/WebKit/Source/core/editing/BUILD.gn
+++ b/third_party/WebKit/Source/core/editing/BUILD.gn
@@ -101,6 +101,7 @@
     "commands/ApplyStyleCommand.h",
     "commands/BreakBlockquoteCommand.cpp",
     "commands/BreakBlockquoteCommand.h",
+    "commands/ClipboardCommands.cpp",
     "commands/ClipboardCommands.h",
     "commands/CompositeEditCommand.cpp",
     "commands/CompositeEditCommand.h",
@@ -122,6 +123,7 @@
     "commands/EditingState.cpp",
     "commands/EditingState.h",
     "commands/EditorCommand.cpp",
+    "commands/EditorCommand.h",
     "commands/EditorCommandNames.h",
     "commands/FormatBlockCommand.cpp",
     "commands/FormatBlockCommand.h",
diff --git a/third_party/WebKit/Source/core/editing/CaretDisplayItemClientTest.cpp b/third_party/WebKit/Source/core/editing/CaretDisplayItemClientTest.cpp
index 4220ab6..577bca0 100644
--- a/third_party/WebKit/Source/core/editing/CaretDisplayItemClientTest.cpp
+++ b/third_party/WebKit/Source/core/editing/CaretDisplayItemClientTest.cpp
@@ -8,10 +8,10 @@
 #include "core/editing/SelectionTemplate.h"
 #include "core/frame/LocalFrameView.h"
 #include "core/html_names.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutView.h"
 #include "core/page/FocusController.h"
 #include "core/paint/PaintLayer.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/graphics/GraphicsLayer.h"
 #include "platform/graphics/paint/RasterInvalidationTracking.h"
 #include "platform/testing/PaintTestConfigurations.h"
diff --git a/third_party/WebKit/Source/core/editing/Editor.h b/third_party/WebKit/Source/core/editing/Editor.h
index 283f0b1..2eedb8f 100644
--- a/third_party/WebKit/Source/core/editing/Editor.h
+++ b/third_party/WebKit/Source/core/editing/Editor.h
@@ -44,7 +44,7 @@
 
 class CompositeEditCommand;
 class DragData;
-class EditorInternalCommand;
+class EditorCommand;
 class FrameSelection;
 class LocalFrame;
 class HitTestResult;
@@ -101,51 +101,16 @@
   void SetShouldStyleWithCSS(bool flag) { should_style_with_css_ = flag; }
   bool ShouldStyleWithCSS() const { return should_style_with_css_; }
 
-  class CORE_EXPORT Command {
-    STACK_ALLOCATED();
-
-   public:
-    Command();
-    Command(const EditorInternalCommand*, EditorCommandSource, LocalFrame*);
-
-    bool Execute(const String& parameter = String(),
-                 Event* triggering_event = nullptr) const;
-    bool Execute(Event* triggering_event) const;
-
-    bool CanExecute(Event* triggering_event = nullptr) const;
-    bool IsSupported() const;
-    bool IsEnabled(Event* triggering_event = nullptr) const;
-
-    EditingTriState GetState(Event* triggering_event = nullptr) const;
-    String Value(Event* triggering_event = nullptr) const;
-
-    bool IsTextInsertion() const;
-
-    // Returns 0 if this Command is not supported.
-    int IdForHistogram() const;
-
-   private:
-    LocalFrame& GetFrame() const {
-      DCHECK(frame_);
-      return *frame_;
-    }
-
-    // Returns target ranges for the command, currently only supports delete
-    // related commands. Used by InputEvent.
-    const StaticRangeVector* GetTargetRanges() const;
-
-    const EditorInternalCommand* command_;
-    EditorCommandSource source_;
-    Member<LocalFrame> frame_;
-  };
-  Command CreateCommand(const String& command_name)
+  EditorCommand CreateCommand(const String& command_name)
       const;  // Command source is CommandFromMenuOrKeyBinding.
-  Command CreateCommand(const String& command_name, EditorCommandSource) const;
+  EditorCommand CreateCommand(const String& command_name,
+                              EditorCommandSource) const;
 
   // |Editor::executeCommand| is implementation of |WebFrame::executeCommand|
   // rather than |Document::execCommand|.
   bool ExecuteCommand(const String&);
   bool ExecuteCommand(const String& command_name, const String& value);
+  bool IsCommandEnabled(const String&) const;
 
   bool InsertText(const String&, KeyboardEvent* triggering_event);
   bool InsertTextWithoutSendingTextEvent(
diff --git a/third_party/WebKit/Source/core/editing/EditorKeyBindings.cpp b/third_party/WebKit/Source/core/editing/EditorKeyBindings.cpp
index a265805..5493905 100644
--- a/third_party/WebKit/Source/core/editing/EditorKeyBindings.cpp
+++ b/third_party/WebKit/Source/core/editing/EditorKeyBindings.cpp
@@ -28,6 +28,7 @@
 
 #include "core/editing/EditingUtilities.h"
 #include "core/editing/FrameSelection.h"
+#include "core/editing/commands/EditorCommand.h"
 #include "core/events/KeyboardEvent.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/LocalFrameClient.h"
@@ -42,7 +43,7 @@
     return false;
 
   String command_name = Behavior().InterpretKeyEvent(*evt);
-  Command command = this->CreateCommand(command_name);
+  const EditorCommand command = this->CreateCommand(command_name);
 
   if (key_event->GetType() == WebInputEvent::kRawKeyDown) {
     // WebKit doesn't have enough information about mode to decide how
diff --git a/third_party/WebKit/Source/core/editing/EditorTest.cpp b/third_party/WebKit/Source/core/editing/EditorTest.cpp
index 24d4fdd..9f0f81b 100644
--- a/third_party/WebKit/Source/core/editing/EditorTest.cpp
+++ b/third_party/WebKit/Source/core/editing/EditorTest.cpp
@@ -5,6 +5,7 @@
 #include "core/editing/Editor.h"
 
 #include "core/clipboard/Pasteboard.h"
+#include "core/editing/commands/EditorCommand.h"
 #include "core/editing/testing/EditingTestBase.h"
 #include "core/html/forms/HTMLInputElement.h"
 
diff --git a/third_party/WebKit/Source/core/editing/InlineBoxPosition.cpp b/third_party/WebKit/Source/core/editing/InlineBoxPosition.cpp
index f3531f1..d0ae30dc 100644
--- a/third_party/WebKit/Source/core/editing/InlineBoxPosition.cpp
+++ b/third_party/WebKit/Source/core/editing/InlineBoxPosition.cpp
@@ -66,7 +66,7 @@
     if (next->IsText()) {
       InlineTextBox* match = nullptr;
       int min_offset = INT_MAX;
-      for (InlineTextBox* box : InlineTextBoxesOf(*ToLayoutText(next))) {
+      for (InlineTextBox* box : ToLayoutText(next)->TextBoxes()) {
         int caret_min_offset = box->CaretMinOffset();
         if (caret_min_offset < min_offset) {
           match = box;
@@ -233,7 +233,7 @@
   InlineBox* inline_box = nullptr;
   InlineTextBox* candidate = nullptr;
 
-  for (InlineTextBox* box : InlineTextBoxesOf(*text_layout_object)) {
+  for (InlineTextBox* box : text_layout_object->TextBoxes()) {
     int caret_min_offset = box->CaretMinOffset();
     int caret_max_offset = box->CaretMaxOffset();
 
diff --git a/third_party/WebKit/Source/core/editing/LocalCaretRectBiDiTest.cpp b/third_party/WebKit/Source/core/editing/LocalCaretRectBiDiTest.cpp
index 4363975..a3f7da2 100644
--- a/third_party/WebKit/Source/core/editing/LocalCaretRectBiDiTest.cpp
+++ b/third_party/WebKit/Source/core/editing/LocalCaretRectBiDiTest.cpp
@@ -1225,4 +1225,420 @@
             LocalCaretRectOfPosition(position_with_affinity).rect);
 }
 
+TEST_F(LocalCaretRectBiDiTest, InLtrBlockLineBeginLtrBaseRunWithTwoNestedRuns) {
+  // Sample:|A B C d e f
+  // BiDi:   1 1 1 0 0 0
+  // Visual:|C B A d e f
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=ltr><bdo dir=ltr><bdo dir=rtl>|ABC</bdo>def</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(0, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest,
+       InLtrBlockLineBeginLtrBaseRunWithThreeNestedRuns) {
+  // Sample:|a b c D E F g h i
+  // BiDi:   2 2 2 1 1 1 0 0 0
+  // Visual:|F E D a b c g h i
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=ltr><bdo dir=ltr><bdo dir=rtl><bdo "
+      "dir=ltr>|abc</bdo>DEF</bdo>ghi</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(0, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest,
+       InLtrBlockLineBeginLtrBaseRunWithFourNestedRuns) {
+  // Sample:|A B C d e f G H I j k l
+  // BiDi:   3 3 3 2 2 2 1 1 1 0 0 0
+  // Visual: I H G|C B A d e f j k l
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=ltr><bdo dir=ltr><bdo dir=rtl><bdo dir=ltr><bdo "
+      "dir=rtl>|ABC</bdo>def</bdo>GHI</bdo>jkl</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(30, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InLtrBlockLineEndLtrBaseRunWithTwoNestedRuns) {
+  // Sample: d e f A B C|
+  // BiDi:   0 0 0 1 1 1
+  // Visual: d e f C B A|
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=ltr><bdo dir=ltr>def<bdo dir=rtl>ABC|</bdo></bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(60, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InLtrBlockLineEndLtrBaseRunWithThreeNestedRuns) {
+  // Sample: g h i D E F a b c|
+  // BiDi:   0 0 0 1 1 1 2 2 2
+  // Visual: g h i a b c F E D|
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=ltr><bdo dir=ltr>ghi<bdo dir=rtl>DEF<bdo "
+      "dir=ltr>abc|</bdo></bdo></bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(90, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InLtrBlockLineEndLtrBaseRunWithFourNestedRuns) {
+  // Sample: j k l G H I d e f A B C|
+  // BiDi:   0 0 0 1 1 1 2 2 2 3 3 3
+  // Visual: j k l d e f C B A|I H G
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=ltr><bdo dir=ltr>jkl<bdo dir=rtl>GHI<bdo dir=ltr>def<bdo "
+      "dir=rtl>ABC|</bdo></bdo></bdo></bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(90, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InLtrBlockLineBeginWithRtlRunOnly) {
+  // Sample:|A B C
+  // BiDi:   1 1 1
+  // Visual:|C B A
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position =
+      SetCaretTextToBody("<div dir=ltr><bdo dir=rtl>|ABC</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(0, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InLtrBlockLineBeginRtlBaseRunWithTwoNestedRuns) {
+  // Sample:|a b c D E F
+  // BiDi:   2 2 2 1 1 1
+  // Visual:|F E D a b c
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>|abc</bdo>DEF</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(0, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest,
+       InLtrBlockLineBeginRtlBaseRunWithThreeNestedRuns) {
+  // Sample:|A B C d e f G H I
+  // BiDi:   3 3 3 2 2 2 1 1 1
+  // Visual: I H G|C B A d e f
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=ltr><bdo dir=rtl><bdo dir=ltr><bdo "
+      "dir=rtl>|ABC</bdo>def</bdo>GHI</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(30, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest,
+       InLtrBlockLineBeginRtlBaseRunWithFourNestedRuns) {
+  // Sample:|a b c D E F g h i J K L
+  // BiDi:   4 4 4 3 3 3 2 2 2 1 1 1
+  // Visual: L K J|F E D a b c g h i
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=ltr><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl><bdo "
+      "dir=ltr>|abc</bdo>DEF</bdo>ghi</bdo>JKL</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(30, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InLtrBlockLineEndWithRtlRunOnly) {
+  // Sample: A B C|
+  // BiDi:   1 1 1
+  // Visual: C B A|
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position =
+      SetCaretTextToBody("<div dir=ltr><bdo dir=rtl>ABC|</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(30, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InLtrBlockLineEndRtlBaseRunWithTwoNestedRuns) {
+  // Sample: D E F a b c|
+  // BiDi:   1 1 1 2 2 2
+  // Visual: a b c F E D|
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=ltr><bdo dir=rtl>DEF<bdo dir=ltr>abc|</bdo></bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(60, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InLtrBlockLineEndRtlBaseRunWithThreeNestedRuns) {
+  // Sample: G H I d e f A B C|
+  // BiDi:   1 1 1 2 2 2 3 3 3
+  // Visual: d e f C B A|I H G
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=ltr><bdo dir=rtl>GHI<bdo dir=ltr>def<bdo "
+      "dir=rtl>ABC|</bdo></bdo></bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(60, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InLtrBlockLineEndRtlBaseRunWithFourNestedRuns) {
+  // Sample: J K L g h i D E F a b c|
+  // BiDi:   1 1 1 2 2 2 3 3 3 4 4 4
+  // Visual: g h i a b c F E D|L K J
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=ltr><bdo dir=rtl>JKL<bdo dir=ltr>ghi<bdo dir=rtl>DEF<bdo "
+      "dir=ltr>abc|</bdo></bdo></bdo></bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(90, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InRtlBlockLineBeginWithLtrRunOnly) {
+  // Sample:|a b c
+  // BiDi:   2 2 2
+  // Visual: a b c|
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position =
+      SetCaretTextToBody("<div dir=rtl><bdo dir=ltr>|abc</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(299, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InRtlBlockLineBeginLtrBaseRunWithTwoNestedRuns) {
+  // Sample:|A B C d e f
+  // BiDi:   3 3 3 2 2 2
+  // Visual: C B A d e f|
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=rtl><bdo dir=ltr><bdo dir=rtl>|ABC</bdo>def</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(299, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest,
+       InRtlBlockLineBeginLtrBaseRunWithThreeNestedRuns) {
+  // Sample:|a b c D E F g h i
+  // BiDi:   4 4 4 3 3 3 2 2 2
+  // Visual: F E D a b c|g h i
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=rtl><bdo dir=ltr><bdo dir=rtl><bdo "
+      "dir=ltr>|abc</bdo>DEF</bdo>ghi</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(270, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest,
+       InRtlBlockLineBeginLtrBaseRunWithFourNestedRuns) {
+  // Sample:|A B C d e f G H I j k l
+  // BiDi:   5 5 5 4 4 4 3 3 3 2 2 2
+  // Visual: I H G C B A d e f|j k l
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=rtl><bdo dir=ltr><bdo dir=rtl><bdo dir=ltr><bdo "
+      "dir=rtl>|ABC</bdo>def</bdo>GHI</bdo>jkl</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(270, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InRtlBlockLineEndWithLtrRunOnly) {
+  // Sample: a b c|
+  // BiDi:   2 2 2
+  // Visual:|a b c
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position =
+      SetCaretTextToBody("<div dir=rtl><bdo dir=ltr>abc|</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(270, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InRtlBlockLineEndLtrBaseRunWithTwoNestedRuns) {
+  // Sample: d e f A B C|
+  // BiDi:   2 2 2 3 3 3
+  // Visual:|d e f C B A
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=rtl><bdo dir=ltr>def<bdo dir=rtl>ABC|</bdo></bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(240, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InRtlBlockLineEndLtrBaseRunWithThreeNestedRuns) {
+  // Sample: g h i D E F a b c|
+  // BiDi:   2 2 2 3 3 3 4 4 4
+  // Visual: g h i|a b c F E D
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl>DEF<bdo "
+      "dir=ltr>abc|</bdo></bdo></bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(240, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InRtlBlockLineEndLtrBaseRunWithFourNestedRuns) {
+  // Sample: j k l G H I d e f A B C|
+  // BiDi:   2 2 2 3 3 3 4 4 4 5 5 5
+  // Visual: j k l|d e f C B A I H G
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=rtl><bdo dir=ltr>jkl<bdo dir=rtl>GHI<bdo dir=ltr>def<bdo "
+      "dir=rtl>ABC|</bdo></bdo></bdo></bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(210, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InRtlBlockLineBeginRtlBaseRunWithTwoNestedRuns) {
+  // Sample:|a b c D E F
+  // BiDi:   2 2 2 1 1 1
+  // Visual: F E D a b c|
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>|abc</bdo>DEF</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(299, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest,
+       InRtlBlockLineBeginRtlBaseRunWithThreeNestedRuns) {
+  // Sample:|A B C d e f G H I
+  // BiDi:   3 3 3 2 2 2 1 1 1
+  // Visual: I H G C B A d e f|
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo "
+      "dir=rtl>|ABC</bdo>def</bdo>GHI</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(299, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest,
+       InRtlBlockLineBeginRtlBaseRunWithFourNestedRuns) {
+  // Sample:|a b c D E F g h i J K L
+  // BiDi:   4 4 4 3 3 3 2 2 2 1 1 1
+  // Visual: L K J F E D a b c|g h i
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl><bdo "
+      "dir=ltr>|abc</bdo>DEF</bdo>ghi</bdo>JKL</bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(270, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InRtlBlockLineEndRtlBaseRunWithTwoNestedRuns) {
+  // Sample: D E F a b c|
+  // BiDi:   1 1 1 2 2 2
+  // Visual:|a b c F E D
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=rtl><bdo dir=rtl>DEF<bdo dir=ltr>abc|</bdo></bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(240, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InRtlBlockLineEndRtlBaseRunWithThreeNestedRuns) {
+  // Sample: G H I d e f A B C|
+  // BiDi:   1 1 1 2 2 2 3 3 3
+  // Visual:|d e f C B A I H G
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=rtl><bdo dir=rtl>GHI<bdo dir=ltr>def<bdo "
+      "dir=rtl>ABC|</bdo></bdo></bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(210, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
+TEST_F(LocalCaretRectBiDiTest, InRtlBlockLineEndRtlBaseRunWithFourNestedRuns) {
+  // Sample: J K L g h i D E F a b c|
+  // BiDi:   1 1 1 2 2 2 3 3 3 4 4 4
+  // Visual: g h i|a b c F E D L K J
+  LoadAhem();
+  InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}");
+  const Position position = SetCaretTextToBody(
+      "<div dir=rtl><bdo dir=rtl>JKL<bdo dir=ltr>ghi<bdo dir=rtl>DEF<bdo "
+      "dir=ltr>abc|</bdo></bdo></bdo></bdo></div>");
+  const PositionWithAffinity position_with_affinity(position,
+                                                    TextAffinity::kDownstream);
+  EXPECT_EQ(LayoutRect(210, 0, 1, 10),
+            LocalCaretRectOfPosition(position_with_affinity).rect);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyBlockElementCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyBlockElementCommand.cpp
index 5b83038..09ba5c9 100644
--- a/third_party/WebKit/Source/core/editing/commands/ApplyBlockElementCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ApplyBlockElementCommand.cpp
@@ -88,10 +88,7 @@
     builder.Collapse(visible_start.ToPositionWithAffinity());
     if (new_end.IsNotNull())
       builder.Extend(new_end);
-    const SelectionInDOMTree& new_selection = builder.Build();
-    if (new_selection.IsNone())
-      return;
-    SetEndingSelection(SelectionForUndoStep::From(new_selection));
+    SetEndingSelection(SelectionForUndoStep::From(builder.Build()));
   }
 
   VisibleSelection selection =
diff --git a/third_party/WebKit/Source/core/editing/commands/ClipboardCommands.cpp b/third_party/WebKit/Source/core/editing/commands/ClipboardCommands.cpp
new file mode 100644
index 0000000..70ba2f9a
--- /dev/null
+++ b/third_party/WebKit/Source/core/editing/commands/ClipboardCommands.cpp
@@ -0,0 +1,488 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/editing/commands/ClipboardCommands.h"
+
+#include "core/clipboard/DataTransferAccessPolicy.h"
+#include "core/clipboard/Pasteboard.h"
+#include "core/editing/EditingUtilities.h"
+#include "core/editing/Editor.h"
+#include "core/editing/EphemeralRange.h"
+#include "core/editing/FrameSelection.h"
+#include "core/editing/commands/EditingCommandsUtilities.h"
+#include "core/editing/serializers/Serialization.h"
+#include "core/events/ClipboardEvent.h"
+#include "core/events/TextEvent.h"
+#include "core/frame/ContentSettingsClient.h"
+#include "core/frame/Settings.h"
+#include "core/html/HTMLImageElement.h"
+#include "core/html/forms/TextControlElement.h"
+#include "platform/PasteMode.h"
+#include "platform/loader/fetch/ResourceFetcher.h"
+
+namespace blink {
+
+bool ClipboardCommands::CanReadClipboard(LocalFrame& frame,
+                                         EditorCommandSource source) {
+  if (source == EditorCommandSource::kMenuOrKeyBinding)
+    return true;
+  Settings* const settings = frame.GetSettings();
+  const bool default_value = settings &&
+                             settings->GetJavaScriptCanAccessClipboard() &&
+                             settings->GetDOMPasteAllowed();
+  if (!frame.GetContentSettingsClient())
+    return default_value;
+  return frame.GetContentSettingsClient()->AllowReadFromClipboard(
+      default_value);
+}
+
+bool ClipboardCommands::CanWriteClipboard(LocalFrame& frame,
+                                          EditorCommandSource source) {
+  if (source == EditorCommandSource::kMenuOrKeyBinding)
+    return true;
+  Settings* const settings = frame.GetSettings();
+  const bool default_value =
+      (settings && settings->GetJavaScriptCanAccessClipboard()) ||
+      Frame::HasTransientUserActivation(&frame);
+  if (!frame.GetContentSettingsClient())
+    return default_value;
+  return frame.GetContentSettingsClient()->AllowWriteToClipboard(default_value);
+}
+
+bool ClipboardCommands::CanSmartReplaceWithPasteboard(LocalFrame& frame,
+                                                      Pasteboard* pasteboard) {
+  return frame.GetEditor().SmartInsertDeleteEnabled() &&
+         pasteboard->CanSmartReplace();
+}
+
+Element* ClipboardCommands::FindEventTargetForClipboardEvent(
+    LocalFrame& frame,
+    EditorCommandSource source) {
+  // https://www.w3.org/TR/clipboard-apis/#fire-a-clipboard-event says:
+  //  "Set target to be the element that contains the start of the selection in
+  //   document order, or the body element if there is no selection or cursor."
+  // We treat hidden selections as "no selection or cursor".
+  if (source == EditorCommandSource::kMenuOrKeyBinding &&
+      frame.Selection().IsHidden())
+    return frame.Selection().GetDocument().body();
+
+  return FindEventTargetFrom(
+      frame, frame.Selection().ComputeVisibleSelectionInDOMTree());
+}
+
+// Returns true if Editor should continue with default processing.
+bool ClipboardCommands::DispatchClipboardEvent(LocalFrame& frame,
+                                               const AtomicString& event_type,
+                                               DataTransferAccessPolicy policy,
+                                               EditorCommandSource source,
+                                               PasteMode paste_mode) {
+  Element* const target = FindEventTargetForClipboardEvent(frame, source);
+  if (!target)
+    return true;
+
+  DataTransfer* const data_transfer =
+      DataTransfer::Create(DataTransfer::kCopyAndPaste, policy,
+                           policy == DataTransferAccessPolicy::kWritable
+                               ? DataObject::Create()
+                               : DataObject::CreateFromPasteboard(paste_mode));
+
+  Event* const evt = ClipboardEvent::Create(event_type, data_transfer);
+  target->DispatchEvent(evt);
+  const bool no_default_processing = evt->defaultPrevented();
+  if (no_default_processing && policy == DataTransferAccessPolicy::kWritable) {
+    Pasteboard::GeneralPasteboard()->WriteDataObject(
+        data_transfer->GetDataObject());
+  }
+
+  // Invalidate clipboard here for security.
+  data_transfer->SetAccessPolicy(DataTransferAccessPolicy::kNumb);
+  return !no_default_processing;
+}
+
+bool ClipboardCommands::DispatchCopyOrCutEvent(LocalFrame& frame,
+                                               EditorCommandSource source,
+                                               const AtomicString& event_type) {
+  // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
+  // needs to be audited.  See http://crbug.com/590369 for more details.
+  frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
+  if (IsInPasswordField(
+          frame.Selection().ComputeVisibleSelectionInDOMTree().Start()))
+    return true;
+
+  return DispatchClipboardEvent(frame, event_type,
+                                DataTransferAccessPolicy::kWritable, source,
+                                PasteMode::kAllMimeTypes);
+}
+
+bool ClipboardCommands::DispatchPasteEvent(LocalFrame& frame,
+                                           PasteMode paste_mode,
+                                           EditorCommandSource source) {
+  return DispatchClipboardEvent(frame, EventTypeNames::paste,
+                                DataTransferAccessPolicy::kReadable, source,
+                                paste_mode);
+}
+
+// WinIE uses onbeforecut and onbeforepaste to enables the cut and paste menu
+// items. They also send onbeforecopy, apparently for symmetry, but it doesn't
+// affect the menu items. We need to use onbeforecopy as a real menu enabler
+// because we allow elements that are not normally selectable to implement
+// copy/paste (like divs, or a document body).
+
+bool ClipboardCommands::EnabledCopy(LocalFrame& frame,
+                                    Event*,
+                                    EditorCommandSource source) {
+  if (!CanWriteClipboard(frame, source))
+    return false;
+  return !DispatchCopyOrCutEvent(frame, source, EventTypeNames::beforecopy) ||
+         frame.GetEditor().CanCopy();
+}
+
+bool ClipboardCommands::EnabledCut(LocalFrame& frame,
+                                   Event*,
+                                   EditorCommandSource source) {
+  if (!CanWriteClipboard(frame, source))
+    return false;
+  if (source == EditorCommandSource::kMenuOrKeyBinding &&
+      !frame.Selection().SelectionHasFocus())
+    return false;
+  return !DispatchCopyOrCutEvent(frame, source, EventTypeNames::beforecut) ||
+         frame.GetEditor().CanCut();
+}
+
+bool ClipboardCommands::EnabledPaste(LocalFrame& frame,
+                                     Event*,
+                                     EditorCommandSource source) {
+  if (!CanReadClipboard(frame, source))
+    return false;
+  if (source == EditorCommandSource::kMenuOrKeyBinding &&
+      !frame.Selection().SelectionHasFocus())
+    return false;
+  return frame.GetEditor().CanPaste();
+}
+
+static Pasteboard::SmartReplaceOption GetSmartReplaceOption(
+    const LocalFrame& frame) {
+  if (frame.GetEditor().SmartInsertDeleteEnabled() &&
+      frame.Selection().Granularity() == TextGranularity::kWord)
+    return Pasteboard::kCanSmartReplace;
+  return Pasteboard::kCannotSmartReplace;
+}
+
+void ClipboardCommands::WriteSelectionToPasteboard(LocalFrame& frame) {
+  const KURL& url = frame.GetDocument()->Url();
+  const String html = frame.Selection().SelectedHTMLForClipboard();
+  const String plain_text = frame.SelectedTextForClipboard();
+  Pasteboard::GeneralPasteboard()->WriteHTML(html, url, plain_text,
+                                             GetSmartReplaceOption(frame));
+}
+
+bool ClipboardCommands::PasteSupported(LocalFrame* frame) {
+  const Settings* const settings = frame->GetSettings();
+  const bool default_value = settings &&
+                             settings->GetJavaScriptCanAccessClipboard() &&
+                             settings->GetDOMPasteAllowed();
+  if (!frame->GetContentSettingsClient())
+    return default_value;
+  return frame->GetContentSettingsClient()->AllowReadFromClipboard(
+      default_value);
+}
+
+bool ClipboardCommands::ExecuteCopy(LocalFrame& frame,
+                                    Event*,
+                                    EditorCommandSource source,
+                                    const String&) {
+  if (!DispatchCopyOrCutEvent(frame, source, EventTypeNames::copy))
+    return true;
+  if (!frame.GetEditor().CanCopy())
+    return true;
+
+  // Since copy is a read-only operation it succeeds anytime a selection
+  // is *visible*. In contrast to cut or paste, the selection does not
+  // need to be focused - being visible is enough.
+  if (source == EditorCommandSource::kMenuOrKeyBinding &&
+      frame.Selection().IsHidden())
+    return true;
+
+  // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
+  // needs to be audited.  See http://crbug.com/590369 for more details.
+  // A 'copy' event handler might have dirtied the layout so we need to update
+  // before we obtain the selection.
+  frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
+
+  if (EnclosingTextControl(
+          frame.Selection().ComputeVisibleSelectionInDOMTree().Start())) {
+    Pasteboard::GeneralPasteboard()->WritePlainText(
+        frame.SelectedTextForClipboard(), GetSmartReplaceOption(frame));
+    return true;
+  }
+  const Document* const document = frame.GetDocument();
+  if (HTMLImageElement* image_element =
+          ImageElementFromImageDocument(document)) {
+    WriteImageNodeToPasteboard(Pasteboard::GeneralPasteboard(), *image_element,
+                               document->title());
+    return true;
+  }
+  WriteSelectionToPasteboard(frame);
+  return true;
+}
+
+bool ClipboardCommands::CanDeleteRange(const EphemeralRange& range) {
+  if (range.IsCollapsed())
+    return false;
+
+  const Node& start_container = *range.StartPosition().ComputeContainerNode();
+  const Node& end_container = *range.EndPosition().ComputeContainerNode();
+
+  return HasEditableStyle(start_container) && HasEditableStyle(end_container);
+}
+
+static DeleteMode ConvertSmartReplaceOptionToDeleteMode(
+    Pasteboard::SmartReplaceOption smart_replace_option) {
+  if (smart_replace_option == Pasteboard::kCanSmartReplace)
+    return DeleteMode::kSmart;
+  DCHECK_EQ(smart_replace_option, Pasteboard::kCannotSmartReplace);
+  return DeleteMode::kSimple;
+}
+
+bool ClipboardCommands::ExecuteCut(LocalFrame& frame,
+                                   Event*,
+                                   EditorCommandSource source,
+                                   const String&) {
+  if (!DispatchCopyOrCutEvent(frame, source, EventTypeNames::cut))
+    return true;
+  if (!frame.GetEditor().CanCut())
+    return true;
+
+  // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
+  // needs to be audited.  See http://crbug.com/590369 for more details.
+  // A 'cut' event handler might have dirtied the layout so we need to update
+  // before we obtain the selection.
+  frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
+
+  if (source == EditorCommandSource::kMenuOrKeyBinding &&
+      !frame.Selection().SelectionHasFocus())
+    return true;
+
+  if (!CanDeleteRange(frame.GetEditor().SelectedRange()))
+    return true;
+  if (EnclosingTextControl(
+          frame.Selection().ComputeVisibleSelectionInDOMTree().Start())) {
+    const String plain_text = frame.SelectedTextForClipboard();
+    Pasteboard::GeneralPasteboard()->WritePlainText(
+        plain_text, GetSmartReplaceOption(frame));
+  } else {
+    WriteSelectionToPasteboard(frame);
+  }
+
+  if (source == EditorCommandSource::kMenuOrKeyBinding) {
+    if (DispatchBeforeInputDataTransfer(
+            FindEventTargetForClipboardEvent(frame, source),
+            InputEvent::InputType::kDeleteByCut,
+            nullptr) != DispatchEventResult::kNotCanceled)
+      return true;
+    // 'beforeinput' event handler may destroy target frame.
+    if (frame.GetDocument()->GetFrame() != frame)
+      return true;
+  }
+  frame.GetEditor().DeleteSelectionWithSmartDelete(
+      ConvertSmartReplaceOptionToDeleteMode(GetSmartReplaceOption(frame)),
+      InputEvent::InputType::kDeleteByCut);
+
+  return true;
+}
+
+void ClipboardCommands::PasteAsFragment(LocalFrame& frame,
+                                        DocumentFragment* pasting_fragment,
+                                        bool smart_replace,
+                                        bool match_style,
+                                        EditorCommandSource source) {
+  Element* const target = FindEventTargetForClipboardEvent(frame, source);
+  if (!target)
+    return;
+  target->DispatchEvent(TextEvent::CreateForFragmentPaste(
+      frame.DomWindow(), pasting_fragment, smart_replace, match_style));
+}
+
+void ClipboardCommands::PasteAsPlainTextWithPasteboard(
+    LocalFrame& frame,
+    Pasteboard* pasteboard,
+    EditorCommandSource source) {
+  Element* const target = FindEventTargetForClipboardEvent(frame, source);
+  if (!target)
+    return;
+  target->DispatchEvent(TextEvent::CreateForPlainTextPaste(
+      frame.DomWindow(), pasteboard->PlainText(),
+      CanSmartReplaceWithPasteboard(frame, pasteboard)));
+}
+
+ClipboardCommands::FragmentAndPlainText
+ClipboardCommands::GetFragmentFromClipboard(LocalFrame& frame,
+                                            Pasteboard* pasteboard) {
+  DocumentFragment* fragment = nullptr;
+  if (pasteboard->IsHTMLAvailable()) {
+    unsigned fragment_start = 0;
+    unsigned fragment_end = 0;
+    KURL url;
+    const String markup =
+        pasteboard->ReadHTML(url, fragment_start, fragment_end);
+    if (!markup.IsEmpty()) {
+      DCHECK(frame.GetDocument());
+      fragment = CreateFragmentFromMarkupWithContext(
+          *frame.GetDocument(), markup, fragment_start, fragment_end, url,
+          kDisallowScriptingAndPluginContent);
+    }
+  }
+  if (fragment)
+    return std::make_pair(fragment, false);
+
+  const String text = pasteboard->PlainText();
+  if (text.IsEmpty())
+    return std::make_pair(fragment, false);
+
+  // TODO(editing-dev): Use of UpdateStyleAndLayoutIgnorePendingStylesheets
+  // needs to be audited. See http://crbug.com/590369 for more details.
+  // |SelectedRange| requires clean layout for visible selection
+  // normalization.
+  frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
+  fragment = CreateFragmentFromText(frame.GetEditor().SelectedRange(), text);
+  return std::make_pair(fragment, true);
+}
+
+void ClipboardCommands::PasteWithPasteboard(LocalFrame& frame,
+                                            Pasteboard* pasteboard,
+                                            EditorCommandSource source) {
+  const ClipboardCommands::FragmentAndPlainText fragment_and_plain_text =
+      GetFragmentFromClipboard(frame, pasteboard);
+
+  if (!fragment_and_plain_text.first)
+    return;
+
+  PasteAsFragment(frame, fragment_and_plain_text.first,
+                  CanSmartReplaceWithPasteboard(frame, pasteboard),
+                  fragment_and_plain_text.second, source);
+}
+
+void ClipboardCommands::Paste(LocalFrame& frame, EditorCommandSource source) {
+  DCHECK(frame.GetDocument());
+  if (!DispatchPasteEvent(frame, PasteMode::kAllMimeTypes, source))
+    return;
+  if (!frame.GetEditor().CanPaste())
+    return;
+
+  // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
+  // needs to be audited.  See http://crbug.com/590369 for more details.
+  // A 'paste' event handler might have dirtied the layout so we need to update
+  // before we obtain the selection.
+  frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
+
+  if (source == EditorCommandSource::kMenuOrKeyBinding &&
+      !frame.Selection().SelectionHasFocus())
+    return;
+
+  ResourceFetcher* const loader = frame.GetDocument()->Fetcher();
+  ResourceCacheValidationSuppressor validation_suppressor(loader);
+
+  const PasteMode paste_mode = frame.GetEditor().CanEditRichly()
+                                   ? PasteMode::kAllMimeTypes
+                                   : PasteMode::kPlainTextOnly;
+
+  if (source == EditorCommandSource::kMenuOrKeyBinding) {
+    DataTransfer* data_transfer = DataTransfer::Create(
+        DataTransfer::kCopyAndPaste, DataTransferAccessPolicy::kReadable,
+        DataObject::CreateFromPasteboard(paste_mode));
+
+    if (DispatchBeforeInputDataTransfer(
+            FindEventTargetForClipboardEvent(frame, source),
+            InputEvent::InputType::kInsertFromPaste,
+            data_transfer) != DispatchEventResult::kNotCanceled)
+      return;
+    // 'beforeinput' event handler may destroy target frame.
+    if (frame.GetDocument()->GetFrame() != frame)
+      return;
+  }
+
+  if (paste_mode == PasteMode::kAllMimeTypes) {
+    PasteWithPasteboard(frame, Pasteboard::GeneralPasteboard(), source);
+    return;
+  }
+  PasteAsPlainTextWithPasteboard(frame, Pasteboard::GeneralPasteboard(),
+                                 source);
+}
+
+bool ClipboardCommands::ExecutePaste(LocalFrame& frame,
+                                     Event*,
+                                     EditorCommandSource source,
+                                     const String&) {
+  Paste(frame, source);
+  return true;
+}
+
+bool ClipboardCommands::ExecutePasteGlobalSelection(LocalFrame& frame,
+                                                    Event*,
+                                                    EditorCommandSource source,
+                                                    const String&) {
+  if (!frame.GetEditor().Behavior().SupportsGlobalSelection())
+    return false;
+  DCHECK_EQ(source, EditorCommandSource::kMenuOrKeyBinding);
+
+  const bool old_selection_mode =
+      Pasteboard::GeneralPasteboard()->IsSelectionMode();
+  Pasteboard::GeneralPasteboard()->SetSelectionMode(true);
+  Paste(frame, source);
+  Pasteboard::GeneralPasteboard()->SetSelectionMode(old_selection_mode);
+  return true;
+}
+
+bool ClipboardCommands::ExecutePasteAndMatchStyle(LocalFrame& frame,
+                                                  Event*,
+                                                  EditorCommandSource source,
+                                                  const String&) {
+  if (!DispatchPasteEvent(frame, PasteMode::kPlainTextOnly, source))
+    return false;
+  if (!frame.GetEditor().CanPaste())
+    return false;
+
+  // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
+  // needs to be audited.  See http://crbug.com/590369 for more details.
+  // A 'paste' event handler might have dirtied the layout so we need to update
+  // before we obtain the selection.
+  frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
+
+  if (source == EditorCommandSource::kMenuOrKeyBinding &&
+      !frame.Selection().SelectionHasFocus())
+    return false;
+
+  PasteAsPlainTextWithPasteboard(frame, Pasteboard::GeneralPasteboard(),
+                                 source);
+  return true;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/commands/ClipboardCommands.h b/third_party/WebKit/Source/core/editing/commands/ClipboardCommands.h
index e3c9e144a..4bedb06 100644
--- a/third_party/WebKit/Source/core/editing/commands/ClipboardCommands.h
+++ b/third_party/WebKit/Source/core/editing/commands/ClipboardCommands.h
@@ -32,7 +32,6 @@
 #ifndef ClipboardCommands_h
 #define ClipboardCommands_h
 
-#include "core/clipboard/DataTransferAccessPolicy.h"
 #include "core/editing/Forward.h"
 #include "platform/wtf/Allocator.h"
 #include "platform/wtf/text/WTFString.h"
@@ -45,6 +44,7 @@
 class LocalFrame;
 class Pasteboard;
 
+enum class DataTransferAccessPolicy;
 enum class EditorCommandSource;
 enum class PasteMode;
 
@@ -114,6 +114,10 @@
   static void PasteWithPasteboard(LocalFrame&,
                                   Pasteboard*,
                                   EditorCommandSource);
+
+  using FragmentAndPlainText = std::pair<DocumentFragment*, const bool>;
+  static FragmentAndPlainText GetFragmentFromClipboard(LocalFrame&,
+                                                       Pasteboard*);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
index 1f46ac97..45ef127 100644
--- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
@@ -814,7 +814,7 @@
   Vector<InlineTextBox*> sorted_text_boxes;
   size_t sorted_text_boxes_position = 0;
 
-  for (InlineTextBox* text_box : InlineTextBoxesOf(*text_layout_object))
+  for (InlineTextBox* text_box : text_layout_object->TextBoxes())
     sorted_text_boxes.push_back(text_box);
 
   // If there is mixed directionality text, the boxes can be out of order,
diff --git a/third_party/WebKit/Source/core/editing/commands/DocumentExecCommand.cpp b/third_party/WebKit/Source/core/editing/commands/DocumentExecCommand.cpp
index 8a18dde..2c22dc1 100644
--- a/third_party/WebKit/Source/core/editing/commands/DocumentExecCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/DocumentExecCommand.cpp
@@ -33,6 +33,7 @@
 #include "core/editing/EditingTriState.h"
 #include "core/editing/Editor.h"
 #include "core/editing/commands/EditingCommandsUtilities.h"
+#include "core/editing/commands/EditorCommand.h"
 #include "core/frame/UseCounter.h"
 #include "core/html/forms/TextControlElement.h"
 #include "core/inspector/ConsoleMessage.h"
@@ -44,10 +45,10 @@
 
 namespace {
 
-Editor::Command GetCommand(Document* document, const String& command_name) {
+EditorCommand GetCommand(Document* document, const String& command_name) {
   LocalFrame* frame = document->GetFrame();
   if (!frame || frame->GetDocument() != document)
-    return Editor::Command();
+    return EditorCommand();
 
   document->UpdateStyleAndLayoutTree();
   return frame->GetEditor().CreateCommand(command_name,
@@ -87,7 +88,7 @@
   // DOM tree against implementation assumption.
   EventQueueScope event_queue_scope;
   TidyUpHTMLStructure(*this);
-  Editor::Command editor_command = GetCommand(this, command_name);
+  const EditorCommand editor_command = GetCommand(this, command_name);
 
   DEFINE_STATIC_LOCAL(SparseHistogram, editor_command_histogram,
                       ("WebCore.Document.execCommand"));
diff --git a/third_party/WebKit/Source/core/editing/commands/EditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditCommand.cpp
index 71ec31b..7e6f735 100644
--- a/third_party/WebKit/Source/core/editing/commands/EditCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/EditCommand.cpp
@@ -73,7 +73,7 @@
   // TODO(editing-dev): This doesn't handle first-letter correctly. Fix it.
   const LayoutText* layout_text = ToLayoutText(layout_object);
   const int offset_in_node = position.OffsetInContainerNode();
-  for (InlineTextBox* box : InlineTextBoxesOf(*layout_text)) {
+  for (InlineTextBox* box : layout_text->TextBoxes()) {
     if (offset_in_node < static_cast<int>(box->Start()) &&
         !layout_text->ContainsReversedText()) {
       // The offset we're looking for is before this node this means the offset
diff --git a/third_party/WebKit/Source/core/editing/commands/EditingCommandTest.cpp b/third_party/WebKit/Source/core/editing/commands/EditingCommandTest.cpp
index cc10071..f7f7e0f7 100644
--- a/third_party/WebKit/Source/core/editing/commands/EditingCommandTest.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/EditingCommandTest.cpp
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "core/editing/Editor.h"
+#include "core/editing/commands/EditorCommand.h"
 #include "core/editing/commands/EditorCommandNames.h"
 #include "core/editing/testing/EditingTestBase.h"
 #include "core/frame/LocalFrame.h"
@@ -45,7 +46,7 @@
 TEST_F(EditingCommandTest, CreateCommandFromString) {
   Editor& dummy_editor = GetDocument().GetFrame()->GetEditor();
   for (const auto& entry : kCommandNameEntries) {
-    Editor::Command command = dummy_editor.CreateCommand(entry.name);
+    const EditorCommand command = dummy_editor.CreateCommand(entry.name);
     EXPECT_EQ(static_cast<int>(entry.type), command.IdForHistogram())
         << entry.name;
   }
@@ -54,12 +55,13 @@
 TEST_F(EditingCommandTest, CreateCommandFromStringCaseFolding) {
   Editor& dummy_editor = GetDocument().GetFrame()->GetEditor();
   for (const auto& entry : kCommandNameEntries) {
-    Editor::Command command =
+    const EditorCommand lower_name_command =
         dummy_editor.CreateCommand(String(entry.name).DeprecatedLower());
-    EXPECT_EQ(static_cast<int>(entry.type), command.IdForHistogram())
+    EXPECT_EQ(static_cast<int>(entry.type), lower_name_command.IdForHistogram())
         << entry.name;
-    command = dummy_editor.CreateCommand(String(entry.name).UpperASCII());
-    EXPECT_EQ(static_cast<int>(entry.type), command.IdForHistogram())
+    const EditorCommand upper_name_command =
+        dummy_editor.CreateCommand(String(entry.name).UpperASCII());
+    EXPECT_EQ(static_cast<int>(entry.type), upper_name_command.IdForHistogram())
         << entry.name;
   }
 }
@@ -70,7 +72,7 @@
   };
   Editor& dummy_editor = GetDocument().GetFrame()->GetEditor();
   for (const auto& command_name : kInvalidCommandName) {
-    Editor::Command command = dummy_editor.CreateCommand(command_name);
+    const EditorCommand command = dummy_editor.CreateCommand(command_name);
     EXPECT_EQ(0, command.IdForHistogram());
   }
 }
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
index 5e4078379..f48d492 100644
--- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -25,11 +25,9 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "core/editing/Editor.h"
+#include "core/editing/commands/EditorCommand.h"
 
 #include "bindings/core/v8/ExceptionState.h"
-#include "core/clipboard/DataTransferAccessPolicy.h"
-#include "core/clipboard/Pasteboard.h"
 #include "core/css/CSSComputedStyleDeclaration.h"
 #include "core/css/CSSIdentifierValue.h"
 #include "core/css/CSSPropertyValueSet.h"
@@ -42,6 +40,7 @@
 #include "core/editing/EditingStyleUtilities.h"
 #include "core/editing/EditingTriState.h"
 #include "core/editing/EditingUtilities.h"
+#include "core/editing/Editor.h"
 #include "core/editing/EphemeralRange.h"
 #include "core/editing/FrameSelection.h"
 #include "core/editing/SelectionModifier.h"
@@ -63,16 +62,11 @@
 #include "core/editing/iterators/TextIterator.h"
 #include "core/editing/serializers/Serialization.h"
 #include "core/editing/spellcheck/SpellChecker.h"
-#include "core/events/ClipboardEvent.h"
-#include "core/events/TextEvent.h"
-#include "core/frame/ContentSettingsClient.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/LocalFrameView.h"
-#include "core/frame/Settings.h"
 #include "core/html/HTMLFontElement.h"
 #include "core/html/HTMLHRElement.h"
 #include "core/html/HTMLImageElement.h"
-#include "core/html/forms/TextControlElement.h"
 #include "core/html_names.h"
 #include "core/input/EventHandler.h"
 #include "core/layout/LayoutBox.h"
@@ -80,8 +74,6 @@
 #include "core/page/Page.h"
 #include "platform/Histogram.h"
 #include "platform/KillRing.h"
-#include "platform/PasteMode.h"
-#include "platform/loader/fetch/ResourceFetcher.h"
 #include "platform/scroll/Scrollbar.h"
 #include "platform/wtf/StringExtras.h"
 #include "platform/wtf/text/AtomicString.h"
@@ -736,134 +728,11 @@
                            CSSPropertyBackgroundColor, value);
 }
 
-bool ClipboardCommands::CanWriteClipboard(LocalFrame& frame,
-                                          EditorCommandSource source) {
-  if (source == EditorCommandSource::kMenuOrKeyBinding)
-    return true;
-  Settings* settings = frame.GetSettings();
-  bool default_value =
-      (settings && settings->GetJavaScriptCanAccessClipboard()) ||
-      Frame::HasTransientUserActivation(&frame);
-  if (!frame.GetContentSettingsClient())
-    return default_value;
-  return frame.GetContentSettingsClient()->AllowWriteToClipboard(default_value);
-}
-
-Element* ClipboardCommands::FindEventTargetForClipboardEvent(
-    LocalFrame& frame,
-    EditorCommandSource source) {
-  // https://www.w3.org/TR/clipboard-apis/#fire-a-clipboard-event says:
-  //  "Set target to be the element that contains the start of the selection in
-  //   document order, or the body element if there is no selection or cursor."
-  // We treat hidden selections as "no selection or cursor".
-  if (source == EditorCommandSource::kMenuOrKeyBinding &&
-      frame.Selection().IsHidden())
-    return frame.Selection().GetDocument().body();
-
-  return FindEventTargetFrom(
-      frame, frame.Selection().ComputeVisibleSelectionInDOMTree());
-}
-
-// Returns true if Editor should continue with default processing.
-bool ClipboardCommands::DispatchClipboardEvent(LocalFrame& frame,
-                                               const AtomicString& event_type,
-                                               DataTransferAccessPolicy policy,
-                                               EditorCommandSource source,
-                                               PasteMode paste_mode) {
-  Element* const target = FindEventTargetForClipboardEvent(frame, source);
-  if (!target)
-    return true;
-
-  DataTransfer* const data_transfer =
-      DataTransfer::Create(DataTransfer::kCopyAndPaste, policy,
-                           policy == DataTransferAccessPolicy::kWritable
-                               ? DataObject::Create()
-                               : DataObject::CreateFromPasteboard(paste_mode));
-
-  Event* const evt = ClipboardEvent::Create(event_type, data_transfer);
-  target->DispatchEvent(evt);
-  const bool no_default_processing = evt->defaultPrevented();
-  if (no_default_processing && policy == DataTransferAccessPolicy::kWritable) {
-    Pasteboard::GeneralPasteboard()->WriteDataObject(
-        data_transfer->GetDataObject());
-  }
-
-  // Invalidate clipboard here for security.
-  data_transfer->SetAccessPolicy(DataTransferAccessPolicy::kNumb);
-  return !no_default_processing;
-}
-
-bool ClipboardCommands::DispatchCopyOrCutEvent(LocalFrame& frame,
-                                               EditorCommandSource source,
-                                               const AtomicString& event_type) {
-  // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
-  // needs to be audited.  See http://crbug.com/590369 for more details.
-  frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
-  if (IsInPasswordField(
-          frame.Selection().ComputeVisibleSelectionInDOMTree().Start()))
-    return true;
-
-  return DispatchClipboardEvent(frame, event_type,
-                                DataTransferAccessPolicy::kWritable, source,
-                                PasteMode::kAllMimeTypes);
-}
-
 static bool CanSmartCopyOrDelete(LocalFrame& frame) {
   return frame.GetEditor().SmartInsertDeleteEnabled() &&
          frame.Selection().Granularity() == TextGranularity::kWord;
 }
 
-void ClipboardCommands::WriteSelectionToPasteboard(LocalFrame& frame) {
-  const KURL& url = frame.GetDocument()->Url();
-  const String html = frame.Selection().SelectedHTMLForClipboard();
-  const String plain_text = frame.SelectedTextForClipboard();
-  Pasteboard::GeneralPasteboard()->WriteHTML(
-      html, url, plain_text,
-      CanSmartCopyOrDelete(frame) ? Pasteboard::kCanSmartReplace
-                                  : Pasteboard::kCannotSmartReplace);
-}
-
-bool ClipboardCommands::ExecuteCopy(LocalFrame& frame,
-                                    Event*,
-                                    EditorCommandSource source,
-                                    const String&) {
-  if (!DispatchCopyOrCutEvent(frame, source, EventTypeNames::copy))
-    return true;
-  if (!frame.GetEditor().CanCopy())
-    return true;
-
-  // Since copy is a read-only operation it succeeds anytime a selection
-  // is *visible*. In contrast to cut or paste, the selection does not
-  // need to be focused - being visible is enough.
-  if (source == EditorCommandSource::kMenuOrKeyBinding &&
-      frame.Selection().IsHidden())
-    return true;
-
-  // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
-  // needs to be audited.  See http://crbug.com/590369 for more details.
-  // A 'copy' event handler might have dirtied the layout so we need to update
-  // before we obtain the selection.
-  frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
-
-  if (EnclosingTextControl(
-          frame.Selection().ComputeVisibleSelectionInDOMTree().Start())) {
-    Pasteboard::GeneralPasteboard()->WritePlainText(
-        frame.SelectedTextForClipboard(),
-        CanSmartCopyOrDelete(frame) ? Pasteboard::kCanSmartReplace
-                                    : Pasteboard::kCannotSmartReplace);
-    return true;
-  }
-  const Document* const document = frame.GetDocument();
-  if (HTMLImageElement* image_element =
-          ImageElementFromImageDocument(document)) {
-    WriteImageNodeToPasteboard(Pasteboard::GeneralPasteboard(), *image_element,
-                               document->title());
-    return true;
-  }
-  WriteSelectionToPasteboard(frame);
-  return true;
-}
-
 static bool ExecuteCreateLink(LocalFrame& frame,
                               Event*,
                               EditorCommandSource,
@@ -874,68 +743,6 @@
   return CreateLinkCommand::Create(*frame.GetDocument(), value)->Apply();
 }
 
-bool ClipboardCommands::CanDeleteRange(const EphemeralRange& range) {
-  if (range.IsCollapsed())
-    return false;
-
-  const Node* const start_container =
-      range.StartPosition().ComputeContainerNode();
-  const Node* const end_container = range.EndPosition().ComputeContainerNode();
-  if (!start_container || !end_container)
-    return false;
-
-  return HasEditableStyle(*start_container) && HasEditableStyle(*end_container);
-}
-
-bool ClipboardCommands::ExecuteCut(LocalFrame& frame,
-                                   Event*,
-                                   EditorCommandSource source,
-                                   const String&) {
-  if (!DispatchCopyOrCutEvent(frame, source, EventTypeNames::cut))
-    return true;
-  if (!frame.GetEditor().CanCut())
-    return true;
-
-  // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
-  // needs to be audited.  See http://crbug.com/590369 for more details.
-  // A 'cut' event handler might have dirtied the layout so we need to update
-  // before we obtain the selection.
-  frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
-
-  if (source == EditorCommandSource::kMenuOrKeyBinding &&
-      !frame.Selection().SelectionHasFocus())
-    return true;
-
-  if (!CanDeleteRange(frame.GetEditor().SelectedRange()))
-    return true;
-  if (EnclosingTextControl(
-          frame.Selection().ComputeVisibleSelectionInDOMTree().Start())) {
-    const String plain_text = frame.SelectedTextForClipboard();
-    Pasteboard::GeneralPasteboard()->WritePlainText(
-        plain_text, CanSmartCopyOrDelete(frame)
-                        ? Pasteboard::kCanSmartReplace
-                        : Pasteboard::kCannotSmartReplace);
-  } else {
-    WriteSelectionToPasteboard(frame);
-  }
-
-  if (source == EditorCommandSource::kMenuOrKeyBinding) {
-    if (DispatchBeforeInputDataTransfer(
-            FindEventTargetForClipboardEvent(frame, source),
-            InputEvent::InputType::kDeleteByCut,
-            nullptr) != DispatchEventResult::kNotCanceled)
-      return true;
-    // 'beforeinput' event handler may destroy target frame.
-    if (frame.GetDocument()->GetFrame() != frame)
-      return true;
-  }
-  frame.GetEditor().DeleteSelectionWithSmartDelete(
-      CanSmartCopyOrDelete(frame) ? DeleteMode::kSmart : DeleteMode::kSimple,
-      InputEvent::InputType::kDeleteByCut);
-
-  return true;
-}
-
 static bool ExecuteDefaultParagraphSeparator(LocalFrame& frame,
                                              Event*,
                                              EditorCommandSource,
@@ -2015,196 +1822,6 @@
   return true;
 }
 
-bool ClipboardCommands::CanReadClipboard(LocalFrame& frame,
-                                         EditorCommandSource source) {
-  if (source == EditorCommandSource::kMenuOrKeyBinding)
-    return true;
-  Settings* settings = frame.GetSettings();
-  bool default_value = settings &&
-                       settings->GetJavaScriptCanAccessClipboard() &&
-                       settings->GetDOMPasteAllowed();
-  if (!frame.GetContentSettingsClient())
-    return default_value;
-  return frame.GetContentSettingsClient()->AllowReadFromClipboard(
-      default_value);
-}
-
-bool ClipboardCommands::CanSmartReplaceWithPasteboard(LocalFrame& frame,
-                                                      Pasteboard* pasteboard) {
-  return frame.GetEditor().SmartInsertDeleteEnabled() &&
-         pasteboard->CanSmartReplace();
-}
-
-void ClipboardCommands::PasteAsPlainTextWithPasteboard(
-    LocalFrame& frame,
-    Pasteboard* pasteboard,
-    EditorCommandSource source) {
-  Element* const target = FindEventTargetForClipboardEvent(frame, source);
-  if (!target)
-    return;
-  target->DispatchEvent(TextEvent::CreateForPlainTextPaste(
-      frame.DomWindow(), pasteboard->PlainText(),
-      CanSmartReplaceWithPasteboard(frame, pasteboard)));
-}
-
-bool ClipboardCommands::DispatchPasteEvent(LocalFrame& frame,
-                                           PasteMode paste_mode,
-                                           EditorCommandSource source) {
-  return DispatchClipboardEvent(frame, EventTypeNames::paste,
-                                DataTransferAccessPolicy::kReadable, source,
-                                paste_mode);
-}
-
-void ClipboardCommands::PasteAsFragment(LocalFrame& frame,
-                                        DocumentFragment* pasting_fragment,
-                                        bool smart_replace,
-                                        bool match_style,
-                                        EditorCommandSource source) {
-  Element* const target = FindEventTargetForClipboardEvent(frame, source);
-  if (!target)
-    return;
-  target->DispatchEvent(TextEvent::CreateForFragmentPaste(
-      frame.DomWindow(), pasting_fragment, smart_replace, match_style));
-}
-
-void ClipboardCommands::PasteWithPasteboard(LocalFrame& frame,
-                                            Pasteboard* pasteboard,
-                                            EditorCommandSource source) {
-  DocumentFragment* fragment = nullptr;
-  bool chose_plain_text = false;
-
-  if (pasteboard->IsHTMLAvailable()) {
-    unsigned fragment_start = 0;
-    unsigned fragment_end = 0;
-    KURL url;
-    const String markup =
-        pasteboard->ReadHTML(url, fragment_start, fragment_end);
-    if (!markup.IsEmpty()) {
-      DCHECK(frame.GetDocument());
-      fragment = CreateFragmentFromMarkupWithContext(
-          *frame.GetDocument(), markup, fragment_start, fragment_end, url,
-          kDisallowScriptingAndPluginContent);
-    }
-  }
-
-  if (!fragment) {
-    const String text = pasteboard->PlainText();
-    if (!text.IsEmpty()) {
-      chose_plain_text = true;
-
-      // TODO(editing-dev): Use of UpdateStyleAndLayoutIgnorePendingStylesheets
-      // needs to be audited.  See http://crbug.com/590369 for more details.
-      // |SelectedRange| requires clean layout for visible selection
-      // normalization.
-      frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
-
-      fragment =
-          CreateFragmentFromText(frame.GetEditor().SelectedRange(), text);
-    }
-  }
-
-  if (!fragment)
-    return;
-
-  PasteAsFragment(frame, fragment,
-                  CanSmartReplaceWithPasteboard(frame, pasteboard),
-                  chose_plain_text, source);
-}
-
-void ClipboardCommands::Paste(LocalFrame& frame, EditorCommandSource source) {
-  DCHECK(frame.GetDocument());
-  if (!DispatchPasteEvent(frame, PasteMode::kAllMimeTypes, source))
-    return;
-  if (!frame.GetEditor().CanPaste())
-    return;
-
-  // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
-  // needs to be audited.  See http://crbug.com/590369 for more details.
-  // A 'paste' event handler might have dirtied the layout so we need to update
-  // before we obtain the selection.
-  frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
-
-  if (source == EditorCommandSource::kMenuOrKeyBinding &&
-      !frame.Selection().SelectionHasFocus())
-    return;
-
-  ResourceFetcher* const loader = frame.GetDocument()->Fetcher();
-  ResourceCacheValidationSuppressor validation_suppressor(loader);
-
-  const PasteMode paste_mode = frame.GetEditor().CanEditRichly()
-                                   ? PasteMode::kAllMimeTypes
-                                   : PasteMode::kPlainTextOnly;
-
-  if (source == EditorCommandSource::kMenuOrKeyBinding) {
-    DataTransfer* data_transfer = DataTransfer::Create(
-        DataTransfer::kCopyAndPaste, DataTransferAccessPolicy::kReadable,
-        DataObject::CreateFromPasteboard(paste_mode));
-
-    if (DispatchBeforeInputDataTransfer(
-            FindEventTargetForClipboardEvent(frame, source),
-            InputEvent::InputType::kInsertFromPaste,
-            data_transfer) != DispatchEventResult::kNotCanceled)
-      return;
-    // 'beforeinput' event handler may destroy target frame.
-    if (frame.GetDocument()->GetFrame() != frame)
-      return;
-  }
-
-  if (paste_mode == PasteMode::kAllMimeTypes) {
-    PasteWithPasteboard(frame, Pasteboard::GeneralPasteboard(), source);
-    return;
-  }
-  PasteAsPlainTextWithPasteboard(frame, Pasteboard::GeneralPasteboard(),
-                                 source);
-}
-
-bool ClipboardCommands::ExecutePaste(LocalFrame& frame,
-                                     Event*,
-                                     EditorCommandSource source,
-                                     const String&) {
-  Paste(frame, source);
-  return true;
-}
-
-bool ClipboardCommands::ExecutePasteGlobalSelection(LocalFrame& frame,
-                                                    Event*,
-                                                    EditorCommandSource source,
-                                                    const String&) {
-  if (!frame.GetEditor().Behavior().SupportsGlobalSelection())
-    return false;
-  DCHECK_EQ(source, EditorCommandSource::kMenuOrKeyBinding);
-
-  bool old_selection_mode = Pasteboard::GeneralPasteboard()->IsSelectionMode();
-  Pasteboard::GeneralPasteboard()->SetSelectionMode(true);
-  Paste(frame, source);
-  Pasteboard::GeneralPasteboard()->SetSelectionMode(old_selection_mode);
-  return true;
-}
-
-bool ClipboardCommands::ExecutePasteAndMatchStyle(LocalFrame& frame,
-                                                  Event*,
-                                                  EditorCommandSource source,
-                                                  const String&) {
-  if (!DispatchPasteEvent(frame, PasteMode::kPlainTextOnly, source))
-    return false;
-  if (!frame.GetEditor().CanPaste())
-    return false;
-
-  // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
-  // needs to be audited.  See http://crbug.com/590369 for more details.
-  // A 'paste' event handler might have dirtied the layout so we need to update
-  // before we obtain the selection.
-  frame.GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
-
-  if (source == EditorCommandSource::kMenuOrKeyBinding &&
-      !frame.Selection().SelectionHasFocus())
-    return false;
-
-  PasteAsPlainTextWithPasteboard(frame, Pasteboard::GeneralPasteboard(),
-                                 source);
-  return true;
-}
-
 static bool ExecutePrint(LocalFrame& frame,
                          Event*,
                          EditorCommandSource,
@@ -2591,17 +2208,6 @@
   return true;
 }
 
-bool ClipboardCommands::PasteSupported(LocalFrame* frame) {
-  const Settings* const settings = frame->GetSettings();
-  const bool default_value = settings &&
-                             settings->GetJavaScriptCanAccessClipboard() &&
-                             settings->GetDOMPasteAllowed();
-  if (!frame->GetContentSettingsClient())
-    return default_value;
-  return frame->GetContentSettingsClient()->AllowReadFromClipboard(
-      default_value);
-}
-
 static bool SupportedFromMenuOrKeyBinding(LocalFrame*) {
   return false;
 }
@@ -2658,33 +2264,6 @@
   return selection.IsCaret() && selection.IsContentEditable();
 }
 
-// WinIE uses onbeforecut and onbeforepaste to enables the cut and paste menu
-// items. They also send onbeforecopy, apparently for symmetry, but it doesn't
-// affect the menu items. We need to use onbeforecopy as a real menu enabler
-// because we allow elements that are not normally selectable to implement
-// copy/paste (like divs, or a document body).
-
-bool ClipboardCommands::EnabledCopy(LocalFrame& frame,
-                                    Event*,
-                                    EditorCommandSource source) {
-  if (!CanWriteClipboard(frame, source))
-    return false;
-  return !DispatchCopyOrCutEvent(frame, source, EventTypeNames::beforecopy) ||
-         frame.GetEditor().CanCopy();
-}
-
-bool ClipboardCommands::EnabledCut(LocalFrame& frame,
-                                   Event*,
-                                   EditorCommandSource source) {
-  if (!CanWriteClipboard(frame, source))
-    return false;
-  if (source == EditorCommandSource::kMenuOrKeyBinding &&
-      !frame.Selection().SelectionHasFocus())
-    return false;
-  return !DispatchCopyOrCutEvent(frame, source, EventTypeNames::beforecut) ||
-         frame.GetEditor().CanCut();
-}
-
 static bool EnabledInEditableText(LocalFrame& frame,
                                   Event* event,
                                   EditorCommandSource source) {
@@ -2727,17 +2306,6 @@
          selection.RootEditableElement();
 }
 
-bool ClipboardCommands::EnabledPaste(LocalFrame& frame,
-                                     Event*,
-                                     EditorCommandSource source) {
-  if (!CanReadClipboard(frame, source))
-    return false;
-  if (source == EditorCommandSource::kMenuOrKeyBinding &&
-      !frame.Selection().SelectionHasFocus())
-    return false;
-  return frame.GetEditor().CanPaste();
-}
-
 static bool EnabledRangeInEditableText(LocalFrame& frame,
                                        Event*,
                                        EditorCommandSource source) {
@@ -3466,14 +3034,14 @@
   return &kEditorCommands[command_index];
 }
 
-Editor::Command Editor::CreateCommand(const String& command_name) const {
-  return Command(InternalCommand(command_name),
-                 EditorCommandSource::kMenuOrKeyBinding, frame_);
+EditorCommand Editor::CreateCommand(const String& command_name) const {
+  return EditorCommand(InternalCommand(command_name),
+                       EditorCommandSource::kMenuOrKeyBinding, frame_);
 }
 
-Editor::Command Editor::CreateCommand(const String& command_name,
-                                      EditorCommandSource source) const {
-  return Command(InternalCommand(command_name), source, frame_);
+EditorCommand Editor::CreateCommand(const String& command_name,
+                                    EditorCommandSource source) const {
+  return EditorCommand(InternalCommand(command_name), source, frame_);
 }
 
 bool Editor::ExecuteCommand(const String& command_name) {
@@ -3539,11 +3107,16 @@
   return CreateCommand(command_name).Execute(value);
 }
 
-Editor::Command::Command() : command_(nullptr) {}
+bool Editor::IsCommandEnabled(const String& command_name) const {
+  return CreateCommand(command_name).IsEnabled();
+}
 
-Editor::Command::Command(const EditorInternalCommand* command,
-                         EditorCommandSource source,
-                         LocalFrame* frame)
+EditorCommand::EditorCommand()
+    : command_(nullptr), source_(EditorCommandSource::kMenuOrKeyBinding) {}
+
+EditorCommand::EditorCommand(const EditorInternalCommand* command,
+                             EditorCommandSource source,
+                             LocalFrame* frame)
     : command_(command), source_(source), frame_(command ? frame : nullptr) {
   // Use separate assertions so we can tell which bad thing happened.
   if (!command)
@@ -3552,8 +3125,13 @@
     DCHECK(frame_);
 }
 
-bool Editor::Command::Execute(const String& parameter,
-                              Event* triggering_event) const {
+LocalFrame& EditorCommand::GetFrame() const {
+  DCHECK(frame_);
+  return *frame_;
+}
+
+bool EditorCommand::Execute(const String& parameter,
+                            Event* triggering_event) const {
   if (!CanExecute(triggering_event))
     return false;
 
@@ -3578,17 +3156,17 @@
   return command_->execute(*frame_, triggering_event, source_, parameter);
 }
 
-bool Editor::Command::Execute(Event* triggering_event) const {
+bool EditorCommand::Execute(Event* triggering_event) const {
   return Execute(String(), triggering_event);
 }
 
-bool Editor::Command::CanExecute(Event* triggering_event) const {
+bool EditorCommand::CanExecute(Event* triggering_event) const {
   if (IsEnabled(triggering_event))
     return true;
   return IsSupported() && frame_ && command_->can_execute(*frame_, source_);
 }
 
-bool Editor::Command::IsSupported() const {
+bool EditorCommand::IsSupported() const {
   if (!command_)
     return false;
   switch (source_) {
@@ -3601,33 +3179,33 @@
   return false;
 }
 
-bool Editor::Command::IsEnabled(Event* triggering_event) const {
+bool EditorCommand::IsEnabled(Event* triggering_event) const {
   if (!IsSupported() || !frame_)
     return false;
   return command_->is_enabled(*frame_, triggering_event, source_);
 }
 
-EditingTriState Editor::Command::GetState(Event* triggering_event) const {
+EditingTriState EditorCommand::GetState(Event* triggering_event) const {
   if (!IsSupported() || !frame_)
     return EditingTriState::kFalse;
   return command_->state(*frame_, triggering_event);
 }
 
-String Editor::Command::Value(Event* triggering_event) const {
+String EditorCommand::Value(Event* triggering_event) const {
   if (!IsSupported() || !frame_)
     return String();
   return command_->value(*command_, *frame_, triggering_event);
 }
 
-bool Editor::Command::IsTextInsertion() const {
+bool EditorCommand::IsTextInsertion() const {
   return command_ && command_->is_text_insertion;
 }
 
-int Editor::Command::IdForHistogram() const {
+int EditorCommand::IdForHistogram() const {
   return IsSupported() ? static_cast<int>(command_->command_type) : 0;
 }
 
-const StaticRangeVector* Editor::Command::GetTargetRanges() const {
+const StaticRangeVector* EditorCommand::GetTargetRanges() const {
   const Node* target = EventTargetNodeForDocument(frame_->GetDocument());
   if (!IsSupported() || !frame_ || !target || !HasRichlyEditableStyle(*target))
     return nullptr;
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.h b/third_party/WebKit/Source/core/editing/commands/EditorCommand.h
new file mode 100644
index 0000000..b9c4332
--- /dev/null
+++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EditorCommand_h
+#define EditorCommand_h
+
+#include "core/CoreExport.h"
+#include "core/dom/StaticRange.h"
+#include "platform/heap/Handle.h"
+#include "platform/wtf/text/WTFString.h"
+
+namespace blink {
+
+class EditorInternalCommand;
+class Event;
+class LocalFrame;
+
+enum class EditingTriState;
+enum class EditorCommandSource;
+
+class CORE_EXPORT EditorCommand {
+  STACK_ALLOCATED();
+
+ public:
+  EditorCommand();
+  EditorCommand(const EditorInternalCommand*, EditorCommandSource, LocalFrame*);
+
+  bool Execute(const String& parameter = String(),
+               Event* triggering_event = nullptr) const;
+  bool Execute(Event* triggering_event) const;
+
+  bool CanExecute(Event* triggering_event = nullptr) const;
+  bool IsSupported() const;
+  bool IsEnabled(Event* triggering_event = nullptr) const;
+
+  EditingTriState GetState(Event* triggering_event = nullptr) const;
+  String Value(Event* triggering_event = nullptr) const;
+
+  bool IsTextInsertion() const;
+
+  // Returns 0 if this EditorCommand is not supported.
+  int IdForHistogram() const;
+
+ private:
+  LocalFrame& GetFrame() const;
+
+  // Returns target ranges for the command, currently only supports delete
+  // related commands. Used by InputEvent.
+  const StaticRangeVector* GetTargetRanges() const;
+
+  const EditorInternalCommand* command_;
+  const EditorCommandSource source_;
+  const Member<LocalFrame> frame_;
+};
+
+}  // namespace blink
+
+#endif  // EditorCommand_h
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
index 2f4bbdf..3639b7f 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
@@ -142,7 +142,7 @@
 }
 
 void InsertListCommand::DoApply(EditingState* editing_state) {
-  // Only entry points are Editor::Command::execute and
+  // Only entry points are EditorCommand::execute and
   // IndentOutdentCommand::outdentParagraph, both of which ensure clean layout.
   DCHECK(!GetDocument().NeedsLayoutTreeUpdate());
 
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp
index 3d66ddc6..efb2a9d 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp
@@ -283,7 +283,7 @@
   // Used when text boxes are out of order (Hebrew/Arabic w/ embeded LTR text)
   if (layout_object->ContainsReversedText()) {
     sorted_text_boxes_.clear();
-    for (InlineTextBox* text_box : InlineTextBoxesOf(*layout_object)) {
+    for (InlineTextBox* text_box : layout_object->TextBoxes()) {
       sorted_text_boxes_.push_back(text_box);
     }
     std::sort(sorted_text_boxes_.begin(), sorted_text_boxes_.end(),
@@ -392,7 +392,7 @@
         if (sorted_text_boxes_position_ + 1 < sorted_text_boxes_.size())
           next_text_box = sorted_text_boxes_[sorted_text_boxes_position_ + 1];
       } else {
-        next_text_box = text_box_->NextTextBox();
+        next_text_box = text_box_->NextForSameLayoutObject();
       }
 
       // FIXME: Based on the outcome of crbug.com/446502 it's possible we can
diff --git a/third_party/WebKit/Source/core/fetch/Body.cpp b/third_party/WebKit/Source/core/fetch/Body.cpp
index 3ac50ca4..cba4800 100644
--- a/third_party/WebKit/Source/core/fetch/Body.cpp
+++ b/third_party/WebKit/Source/core/fetch/Body.cpp
@@ -39,6 +39,10 @@
         Resolver()->GetScriptState()->GetIsolate(), "Failed to fetch"));
   }
 
+  void Abort() override {
+    resolver_->Reject(DOMException::Create(kAbortError));
+  }
+
   void Trace(blink::Visitor* visitor) override {
     visitor->Trace(resolver_);
     FetchDataLoader::Client::Trace(visitor);
@@ -295,15 +299,6 @@
             script_state->GetIsolate(),
             used ? "body stream already read" : "body stream is locked"));
   }
-
-  // It should not be necessary to check IsAborted() here, because reading
-  // from the stream should reject with an AbortError once the stream has been
-  // aborted.
-  // TODO(ricea): Remove this check once there is a better way to do it.
-  if (BodyBuffer() && BodyBuffer()->IsAborted()) {
-    return ScriptPromise::RejectWithDOMException(
-        script_state, DOMException::Create(kAbortError));
-  }
   return ScriptPromise();
 }
 
diff --git a/third_party/WebKit/Source/core/fetch/BodyStreamBuffer.cpp b/third_party/WebKit/Source/core/fetch/BodyStreamBuffer.cpp
index a821932..90cb96a 100644
--- a/third_party/WebKit/Source/core/fetch/BodyStreamBuffer.cpp
+++ b/third_party/WebKit/Source/core/fetch/BodyStreamBuffer.cpp
@@ -19,6 +19,7 @@
 #include "platform/bindings/V8ThrowException.h"
 #include "platform/blob/BlobData.h"
 #include "platform/network/EncodedFormData.h"
+#include "platform/wtf/Assertions.h"
 #include "platform/wtf/AutoReset.h"
 
 namespace blink {
@@ -73,6 +74,8 @@
     client_->DidFetchDataLoadFailed();
   }
 
+  void Abort() override { NOTREACHED(); }
+
   void Trace(blink::Visitor* visitor) override {
     visitor->Trace(buffer_);
     visitor->Trace(client_);
@@ -188,9 +191,14 @@
   DCHECK(!loader_);
   DCHECK(script_state_->ContextIsValid());
   loader_ = loader;
-  // TODO(ricea): Call Abort() on |client| if |signal_| is aborted.  Add an
-  // algorithm to |signal_| to call Abort() on |client| when SignalAbort() is
-  // called.
+  if (signal_) {
+    if (signal_->aborted()) {
+      client->Abort();
+      return;
+    }
+    signal_->AddAlgorithm(
+        WTF::Bind(&FetchDataLoader::Client::Abort, WrapWeakPersistent(client)));
+  }
   loader->Start(ReleaseHandle(),
                 new LoaderClient(ExecutionContext::From(script_state_.get()),
                                  this, client));
diff --git a/third_party/WebKit/Source/core/fetch/BodyStreamBufferTest.cpp b/third_party/WebKit/Source/core/fetch/BodyStreamBufferTest.cpp
index ad0fc49..291a2da 100644
--- a/third_party/WebKit/Source/core/fetch/BodyStreamBufferTest.cpp
+++ b/third_party/WebKit/Source/core/fetch/BodyStreamBufferTest.cpp
@@ -8,11 +8,13 @@
 #include "bindings/core/v8/V8BindingForTesting.h"
 #include "core/dom/Document.h"
 #include "core/fetch/BlobBytesConsumer.h"
+#include "core/fetch/BytesConsumer.h"
 #include "core/fetch/BytesConsumerTestUtil.h"
 #include "core/fetch/FormDataBytesConsumer.h"
 #include "core/html/forms/FormData.h"
 #include "platform/blob/BlobData.h"
 #include "platform/blob/BlobURL.h"
+#include "platform/heap/GarbageCollected.h"
 #include "platform/network/EncodedFormData.h"
 #include "platform/testing/UnitTestHelpers.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -67,6 +69,22 @@
   }
 };
 
+class MockFetchDataLoader : public FetchDataLoader {
+ public:
+  // Cancel() gets called during garbage collection after the test is
+  // finished. Since most tests don't care about this, use NiceMock so that the
+  // calls to Cancel() are ignored.
+  static ::testing::NiceMock<MockFetchDataLoader>* Create() {
+    return new ::testing::NiceMock<MockFetchDataLoader>();
+  }
+
+  MOCK_METHOD2(Start, void(BytesConsumer*, FetchDataLoader::Client*));
+  MOCK_METHOD0(Cancel, void());
+
+ protected:
+  MockFetchDataLoader() = default;
+};
+
 TEST_F(BodyStreamBufferTest, Tee) {
   V8TestingScope scope;
   Checkpoint checkpoint;
@@ -547,6 +565,112 @@
   EXPECT_TRUE(buffer->IsAborted());
 }
 
+TEST_F(BodyStreamBufferTest,
+       AbortBeforeStartLoadingCallsDataLoaderClientAbort) {
+  V8TestingScope scope;
+  Checkpoint checkpoint;
+  MockFetchDataLoader* loader = MockFetchDataLoader::Create();
+  MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::Create();
+  auto* src = BytesConsumerTestUtil::MockBytesConsumer::Create();
+
+  EXPECT_CALL(*loader, Start(_, _)).Times(0);
+
+  InSequence s;
+  EXPECT_CALL(*src, SetClient(_));
+  EXPECT_CALL(*src, GetPublicState())
+      .WillOnce(Return(BytesConsumer::PublicState::kReadableOrWaiting));
+
+  EXPECT_CALL(checkpoint, Call(1));
+  EXPECT_CALL(*src, Cancel());
+
+  EXPECT_CALL(checkpoint, Call(2));
+  EXPECT_CALL(*client, Abort());
+
+  EXPECT_CALL(checkpoint, Call(3));
+
+  auto* signal = new AbortSignal(scope.GetExecutionContext());
+  BodyStreamBuffer* buffer =
+      new BodyStreamBuffer(scope.GetScriptState(), src, signal);
+
+  checkpoint.Call(1);
+  signal->SignalAbort();
+
+  checkpoint.Call(2);
+  buffer->StartLoading(loader, client);
+
+  checkpoint.Call(3);
+}
+
+TEST_F(BodyStreamBufferTest, AbortAfterStartLoadingCallsDataLoaderClientAbort) {
+  V8TestingScope scope;
+  Checkpoint checkpoint;
+  MockFetchDataLoader* loader = MockFetchDataLoader::Create();
+  MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::Create();
+  auto* src = BytesConsumerTestUtil::MockBytesConsumer::Create();
+
+  InSequence s;
+  EXPECT_CALL(*src, SetClient(_));
+  EXPECT_CALL(*src, GetPublicState())
+      .WillOnce(Return(BytesConsumer::PublicState::kReadableOrWaiting));
+
+  EXPECT_CALL(checkpoint, Call(1));
+  EXPECT_CALL(*src, ClearClient());
+  EXPECT_CALL(*loader, Start(_, _));
+
+  EXPECT_CALL(checkpoint, Call(2));
+  EXPECT_CALL(*client, Abort());
+
+  EXPECT_CALL(checkpoint, Call(3));
+
+  auto* signal = new AbortSignal(scope.GetExecutionContext());
+  BodyStreamBuffer* buffer =
+      new BodyStreamBuffer(scope.GetScriptState(), src, signal);
+
+  checkpoint.Call(1);
+  buffer->StartLoading(loader, client);
+
+  checkpoint.Call(2);
+  signal->SignalAbort();
+
+  checkpoint.Call(3);
+}
+
+TEST_F(BodyStreamBufferTest,
+       AsyncAbortAfterStartLoadingCallsDataLoaderClientAbort) {
+  V8TestingScope scope;
+  Checkpoint checkpoint;
+  MockFetchDataLoader* loader = MockFetchDataLoader::Create();
+  MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::Create();
+  auto* src = BytesConsumerTestUtil::MockBytesConsumer::Create();
+
+  InSequence s;
+  EXPECT_CALL(*src, SetClient(_));
+  EXPECT_CALL(*src, GetPublicState())
+      .WillOnce(Return(BytesConsumer::PublicState::kReadableOrWaiting));
+
+  EXPECT_CALL(checkpoint, Call(1));
+  EXPECT_CALL(*src, ClearClient());
+  EXPECT_CALL(*loader, Start(_, _));
+
+  EXPECT_CALL(checkpoint, Call(2));
+  EXPECT_CALL(*client, Abort());
+
+  EXPECT_CALL(checkpoint, Call(3));
+
+  auto* signal = new AbortSignal(scope.GetExecutionContext());
+  BodyStreamBuffer* buffer =
+      new BodyStreamBuffer(scope.GetScriptState(), src, signal);
+
+  checkpoint.Call(1);
+  buffer->StartLoading(loader, client);
+  testing::RunPendingTasks();
+
+  checkpoint.Call(2);
+  signal->SignalAbort();
+
+  checkpoint.Call(3);
+}
+
 }  // namespace
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/fetch/BytesConsumerTestUtil.h b/third_party/WebKit/Source/core/fetch/BytesConsumerTestUtil.h
index 6fc50b2..1e9ffd8 100644
--- a/third_party/WebKit/Source/core/fetch/BytesConsumerTestUtil.h
+++ b/third_party/WebKit/Source/core/fetch/BytesConsumerTestUtil.h
@@ -65,6 +65,7 @@
     MOCK_METHOD1(DidFetchDataLoadedString, void(const String&));
     MOCK_METHOD0(DidFetchDataLoadStream, void());
     MOCK_METHOD0(DidFetchDataLoadFailed, void());
+    MOCK_METHOD0(Abort, void());
 
     void DidFetchDataLoadedArrayBuffer(DOMArrayBuffer* array_buffer) override {
       DidFetchDataLoadedArrayBufferMock(array_buffer);
diff --git a/third_party/WebKit/Source/core/fetch/FetchDataLoader.h b/third_party/WebKit/Source/core/fetch/FetchDataLoader.h
index 57516e8..a8c3c38 100644
--- a/third_party/WebKit/Source/core/fetch/FetchDataLoader.h
+++ b/third_party/WebKit/Source/core/fetch/FetchDataLoader.h
@@ -53,6 +53,9 @@
 
     virtual void DidFetchDataLoadFailed() = 0;
 
+    // This function is called when an abort has been signalled.
+    virtual void Abort() = 0;
+
     void Trace(blink::Visitor* visitor) override {}
   };
 
diff --git a/third_party/WebKit/Source/core/frame/DOMTimerTest.cpp b/third_party/WebKit/Source/core/frame/DOMTimerTest.cpp
index 6172e56..5bbe3fc 100644
--- a/third_party/WebKit/Source/core/frame/DOMTimerTest.cpp
+++ b/third_party/WebKit/Source/core/frame/DOMTimerTest.cpp
@@ -12,7 +12,7 @@
 #include "bindings/core/v8/ScriptSourceCode.h"
 #include "bindings/core/v8/V8BindingForCore.h"
 #include "core/dom/Document.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/TestingPlatformSupportWithMockScheduler.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp b/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp
index de2af794..2373404e 100644
--- a/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp
@@ -34,7 +34,7 @@
 
 #include "core/exported/WebRemoteFrameImpl.h"
 #include "core/frame/WebLocalFrameImpl.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/URLTestHelpers.h"
 #include "platform/testing/UnitTestHelpers.h"
 #include "platform/wtf/Functional.h"
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
index 7635e566..edee3fb9 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -141,6 +141,46 @@
   return true;
 }
 
+class EmptyFrameScheduler final : public WebFrameScheduler {
+ public:
+  EmptyFrameScheduler() { DCHECK(IsMainThread()); }
+
+  scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
+      TaskType type) override {
+    return Platform::Current()->MainThread()->GetTaskRunner();
+  }
+
+  std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
+      ObserverType,
+      Observer*) override {
+    return nullptr;
+  }
+  void SetFrameVisible(bool) override {}
+  bool IsFrameVisible() const override { return false; }
+  bool IsPageVisible() const override { return false; }
+  void SetPaused(bool) override {}
+  void SetCrossOrigin(bool) override {}
+  bool IsCrossOrigin() const override { return false; }
+  void TraceUrlChange(const String& override) {}
+  WebFrameScheduler::FrameType GetFrameType() const override {
+    return WebFrameScheduler::FrameType::kSubframe;
+  }
+  PageScheduler* GetPageScheduler() const override { return nullptr; }
+  WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser(
+      WebScopedVirtualTimePauser::VirtualTaskDuration) {
+    return WebScopedVirtualTimePauser();
+  }
+  void DidStartProvisionalLoad(bool is_main_frame) override {}
+  void DidCommitProvisionalLoad(bool is_web_history_inert_commit,
+                                bool is_reload,
+                                bool is_main_frame) override {}
+  void OnFirstMeaningfulPaint() override {}
+  std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override {
+    return nullptr;
+  }
+  bool IsExemptFromBudgetBasedThrottling() const override { return false; }
+};
+
 }  // namespace
 
 template class CORE_TEMPLATE_EXPORT Supplement<LocalFrame>;
@@ -799,10 +839,13 @@
                               FrameOwner* owner,
                               InterfaceRegistry* interface_registry)
     : Frame(client, page, owner, LocalWindowProxyManager::Create(*this)),
-      frame_scheduler_(page.GetChromeClient().CreateFrameScheduler(
-          client->GetFrameBlameContext(),
-          IsMainFrame() ? WebFrameScheduler::FrameType::kMainFrame
-                        : WebFrameScheduler::FrameType::kSubframe)),
+      frame_scheduler_(page.GetPageScheduler()
+                           ? page.GetPageScheduler()->CreateFrameScheduler(
+                                 client->GetFrameBlameContext(),
+                                 IsMainFrame()
+                                     ? WebFrameScheduler::FrameType::kMainFrame
+                                     : WebFrameScheduler::FrameType::kSubframe)
+                           : std::make_unique<EmptyFrameScheduler>()),
       loader_(this),
       navigation_scheduler_(NavigationScheduler::Create(this)),
       script_controller_(ScriptController::Create(
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameTest.cpp b/third_party/WebKit/Source/core/frame/LocalFrameTest.cpp
index a222616..6c3fb0c 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameTest.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrameTest.cpp
@@ -4,8 +4,8 @@
 
 #include "core/frame/LocalFrame.h"
 
-#include "core/layout/LayoutTestHelper.h"
 #include "core/loader/EmptyClients.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "core/testing/DummyPageHolder.h"
 #include "platform/loader/fetch/FetchParameters.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
index 712c5a2..2fe34f7 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -508,6 +508,17 @@
                            &box->GetFrame()->GetPage()->GetChromeClient());
 }
 
+void LocalFrameView::SnapAfterScrollbarDragging(
+    ScrollbarOrientation orientation) {
+  SnapCoordinator* snap_coordinator =
+      frame_->GetDocument()->GetSnapCoordinator();
+  if (!snap_coordinator)
+    return;
+  snap_coordinator->PerformSnapping(*GetLayoutBox(),
+                                    orientation == kHorizontalScrollbar,
+                                    orientation == kVerticalScrollbar);
+}
+
 void LocalFrameView::ScrollbarManager::DestroyScrollbar(
     ScrollbarOrientation orientation) {
   Member<Scrollbar>& scrollbar =
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.h b/third_party/WebKit/Source/core/frame/LocalFrameView.h
index f110ade..faad33e 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.h
@@ -156,6 +156,8 @@
 
   Scrollbar* CreateScrollbar(ScrollbarOrientation) override;
 
+  void SnapAfterScrollbarDragging(ScrollbarOrientation) override;
+
   void SetLayoutOverflowSize(const IntSize&);
 
   void UpdateLayout();
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameViewTest.cpp b/third_party/WebKit/Source/core/frame/LocalFrameViewTest.cpp
index fe515e5..c62edf1a 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameViewTest.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrameViewTest.cpp
@@ -7,9 +7,9 @@
 #include <memory>
 
 #include "core/html/HTMLElement.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutView.h"
 #include "core/paint/PaintLayer.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/geometry/IntSize.h"
 #include "platform/graphics/paint/PaintArtifact.h"
 #include "platform/runtime_enabled_features.h"
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
index 188ab0de..ffc9e869 100644
--- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -1087,7 +1087,7 @@
 
 bool WebLocalFrameImpl::IsCommandEnabled(const WebString& name) const {
   DCHECK(GetFrame());
-  return GetFrame()->GetEditor().CreateCommand(name).IsEnabled();
+  return GetFrame()->GetEditor().IsCommandEnabled(name);
 }
 
 bool WebLocalFrameImpl::SelectionTextDirection(WebTextDirection& start,
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
index 431655d..5032124 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -1167,7 +1167,7 @@
 
   FontCachePurgePreventer preventer;
   LayoutText* layout_text = ToLayoutText(layout_object);
-  for (InlineTextBox* box : InlineTextBoxesOf(*layout_text)) {
+  for (InlineTextBox* box : layout_text->TextBoxes()) {
     const ComputedStyle& style = layout_text->StyleRef(box->IsFirstLineStyle());
     const Font& font = style.GetFont();
     TextRun run = box->ConstructTextRunForInspector(style);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp
index 338b730d..ed92831 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp
@@ -406,8 +406,7 @@
       std::unique_ptr<protocol::Array<protocol::DOMSnapshot::InlineTextBox>>
           inline_text_nodes =
               protocol::Array<protocol::DOMSnapshot::InlineTextBox>::create();
-      for (const InlineTextBox* text_box = layout_text->FirstTextBox();
-           text_box; text_box = text_box->NextTextBox()) {
+      for (const InlineTextBox* text_box : layout_text->TextBoxes()) {
         FloatRect local_coords_text_box_rect(text_box->FrameRect());
         FloatRect absolute_coords_text_box_rect =
             layout_object->LocalToAbsoluteQuad(local_coords_text_box_rect)
diff --git a/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.cpp b/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.cpp
index 8eec487..2e105554 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.cpp
@@ -983,6 +983,8 @@
   std::unique_ptr<TracedValue> value = TracedValue::Create();
   bool is_main_frame = frame && frame->IsMainFrame();
   value->SetBoolean("isMainFrame", is_main_frame);
+  // TODO(dgozman): this does not work with OOPIF, so everyone who
+  // uses it should migrate to frame instead.
   value->SetString("page",
                    IdentifiersFactory::FrameId(&frame->LocalFrameRoot()));
   return value;
@@ -1270,6 +1272,7 @@
   value->SetString("sessionId", session_id);
   value->SetString("page",
                    IdentifiersFactory::FrameId(&frame->LocalFrameRoot()));
+  value->SetBoolean("persistentIds", true);
   value->BeginArray("frames");
   for (Frame* f = frame; f; f = f->Tree().TraverseNext(frame)) {
     if (!f->IsLocalFrame())
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
index 1018967..5036549b 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -2904,8 +2904,7 @@
       // that will outlast this block. In the non-anonymous block case those
       // children will be destroyed by the time we return from this function.
       if (IsAnonymousBlock()) {
-        for (InlineFlowBox* box = FirstLineBox(); box;
-             box = box->NextLineBox()) {
+        for (InlineFlowBox* box : *LineBoxes()) {
           while (InlineBox* child_box = box->FirstChild())
             child_box->Remove();
         }
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
index b270e92..1bf87b15 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
@@ -186,8 +186,8 @@
 
   const LineBoxList& LineBoxes() const { return line_boxes_; }
   LineBoxList* LineBoxes() { return &line_boxes_; }
-  InlineFlowBox* FirstLineBox() const { return line_boxes_.FirstLineBox(); }
-  InlineFlowBox* LastLineBox() const { return line_boxes_.LastLineBox(); }
+  InlineFlowBox* FirstLineBox() const { return line_boxes_.First(); }
+  InlineFlowBox* LastLineBox() const { return line_boxes_.Last(); }
   RootInlineBox* FirstRootBox() const {
     return static_cast<RootInlineBox*>(FirstLineBox());
   }
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockTest.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockTest.cpp
index 4cda2b9b..d2f85271 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockTest.cpp
@@ -6,7 +6,7 @@
 #include "core/layout/LayoutBlock.h"
 
 #include "core/layout/LayoutBlockFlow.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObjectTest.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObjectTest.cpp
index 6d24707..3e50876e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObjectTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObjectTest.cpp
@@ -7,10 +7,10 @@
 #include "core/dom/DOMTokenList.h"
 #include "core/dom/DocumentLifecycle.h"
 #include "core/html/HTMLElement.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/page/scrolling/StickyPositionScrollingConstraints.h"
 #include "core/paint/PaintLayer.h"
 #include "core/paint/PaintLayerScrollableArea.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxTest.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxTest.cpp
index 982b430..8330810b 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBoxTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBoxTest.cpp
@@ -7,7 +7,7 @@
 #include "build/build_config.h"
 #include "core/html/HTMLElement.h"
 #include "core/layout/LayoutImage.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/graphics/test/StubImage.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutCountTest.cpp b/third_party/WebKit/Source/core/layout/LayoutCountTest.cpp
index 6214622..7b76c192 100644
--- a/third_party/WebKit/Source/core/layout/LayoutCountTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutCountTest.cpp
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "core/layout/LayoutBlockFlow.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutEmbeddedContentTest.cpp b/third_party/WebKit/Source/core/layout/LayoutEmbeddedContentTest.cpp
index d39ee55d..12a449c 100644
--- a/third_party/WebKit/Source/core/layout/LayoutEmbeddedContentTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutEmbeddedContentTest.cpp
@@ -5,7 +5,7 @@
 #include "core/layout/LayoutEmbeddedContent.h"
 
 #include "core/html/HTMLElement.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/layout/LayoutInline.cpp b/third_party/WebKit/Source/core/layout/LayoutInline.cpp
index 34cbe61..b0c54bb 100644
--- a/third_party/WebKit/Source/core/layout/LayoutInline.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutInline.cpp
@@ -111,7 +111,7 @@
       // not have a parent that means they are either already disconnected or
       // root lines that can just be destroyed without disconnecting.
       if (FirstLineBox()->Parent()) {
-        for (InlineFlowBox* box = FirstLineBox(); box; box = box->NextLineBox())
+        for (InlineFlowBox* box : *LineBoxes())
           box->Remove();
       }
     } else if (Parent()) {
@@ -667,8 +667,8 @@
   }
   if (!AlwaysCreateLineBoxes()) {
     GenerateCulledLineBoxRects(yield, this);
-  } else if (InlineFlowBox* curr = FirstLineBox()) {
-    for (; curr; curr = curr->NextLineBox())
+  } else {
+    for (InlineFlowBox* curr : *LineBoxes())
       yield(LayoutRect(curr->Location(), curr->Size()));
   }
 }
@@ -738,8 +738,7 @@
       if (!curr_inline->AlwaysCreateLineBoxes()) {
         curr_inline->GenerateCulledLineBoxRects(yield, container);
       } else {
-        for (InlineFlowBox* child_line = curr_inline->FirstLineBox();
-             child_line; child_line = child_line->NextLineBox()) {
+        for (InlineFlowBox* child_line : *curr_inline->LineBoxes()) {
           RootInlineBox& root_box = child_line->Root();
           ComputeItemTopHeight(container, root_box, &logical_top,
                                &logical_height);
@@ -759,7 +758,7 @@
       }
     } else if (curr->IsText()) {
       LayoutText* curr_text = ToLayoutText(curr);
-      for (InlineTextBox* child_text : InlineTextBoxesOf(*curr_text)) {
+      for (InlineTextBox* child_text : curr_text->TextBoxes()) {
         RootInlineBox& root_box = child_text->Root();
         ComputeItemTopHeight(container, root_box, &logical_top,
                              &logical_height);
@@ -1037,8 +1036,7 @@
     // Return the width of the minimal left side and the maximal right side.
     LayoutUnit logical_left_side;
     LayoutUnit logical_right_side;
-    for (InlineFlowBox* curr = FirstLineBox(); curr;
-         curr = curr->NextLineBox()) {
+    for (InlineFlowBox* curr : *LineBoxes()) {
       if (curr == FirstLineBox() || curr->LogicalLeft() < logical_left_side)
         logical_left_side = curr->LogicalLeft();
       if (curr == FirstLineBox() || curr->LogicalRight() > logical_right_side)
@@ -1171,7 +1169,7 @@
   // Return the width of the minimal left side and the maximal right side.
   LayoutUnit logical_left_side = LayoutUnit::Max();
   LayoutUnit logical_right_side = LayoutUnit::Min();
-  for (InlineFlowBox* curr = FirstLineBox(); curr; curr = curr->NextLineBox()) {
+  for (InlineFlowBox* curr : *LineBoxes()) {
     logical_left_side =
         std::min(logical_left_side, curr->LogicalLeftVisualOverflow());
     logical_right_side =
@@ -1395,12 +1393,11 @@
       } else if (!curr->SelfNeedsLayout()) {
         if (curr->IsLayoutInline()) {
           LayoutInline* curr_inline = ToLayoutInline(curr);
-          for (InlineFlowBox* child_line = curr_inline->FirstLineBox();
-               child_line; child_line = child_line->NextLineBox())
+          for (InlineFlowBox* child_line : *curr_inline->LineBoxes())
             child_line->Root().MarkDirty();
         } else if (curr->IsText()) {
           LayoutText* curr_text = ToLayoutText(curr);
-          for (InlineTextBox* child_text : InlineTextBoxesOf(*curr_text))
+          for (InlineTextBox* child_text : curr_text->TextBoxes())
             child_text->Root().MarkDirty();
         }
       }
@@ -1639,7 +1636,7 @@
 
   paint_invalidator.InvalidateDisplayItemClient(*this, invalidation_reason);
 
-  for (InlineFlowBox* box = FirstLineBox(); box; box = box->NextLineBox())
+  for (InlineFlowBox* box : *LineBoxes())
     paint_invalidator.InvalidateDisplayItemClient(*box, invalidation_reason);
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutInline.h b/third_party/WebKit/Source/core/layout/LayoutInline.h
index bf2d791c..aa08f71 100644
--- a/third_party/WebKit/Source/core/layout/LayoutInline.h
+++ b/third_party/WebKit/Source/core/layout/LayoutInline.h
@@ -158,8 +158,8 @@
   LineBoxList* LineBoxes() { return &line_boxes_; }
   const LineBoxList* LineBoxes() const { return &line_boxes_; }
 
-  InlineFlowBox* FirstLineBox() const { return line_boxes_.FirstLineBox(); }
-  InlineFlowBox* LastLineBox() const { return line_boxes_.LastLineBox(); }
+  InlineFlowBox* FirstLineBox() const { return line_boxes_.First(); }
+  InlineFlowBox* LastLineBox() const { return line_boxes_.Last(); }
   InlineBox* FirstLineBoxIncludingCulling() const {
     return AlwaysCreateLineBoxes() ? FirstLineBox()
                                    : CulledInlineFirstLineBox();
diff --git a/third_party/WebKit/Source/core/layout/LayoutInlineTest.cpp b/third_party/WebKit/Source/core/layout/LayoutInlineTest.cpp
index 0724e6f..48c2e72 100644
--- a/third_party/WebKit/Source/core/layout/LayoutInlineTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutInlineTest.cpp
@@ -5,7 +5,7 @@
 #include "core/layout/LayoutInline.h"
 
 #include "core/layout/LayoutBlockFlow.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/runtime_enabled_features.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/core/layout/LayoutMediaTest.cpp b/third_party/WebKit/Source/core/layout/LayoutMediaTest.cpp
index c7866b3..e39037be 100644
--- a/third_party/WebKit/Source/core/layout/LayoutMediaTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutMediaTest.cpp
@@ -4,7 +4,7 @@
 
 #include "core/layout/LayoutVideo.h"
 
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThreadTest.cpp b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThreadTest.cpp
index eaae4c0..bf8024a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThreadTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThreadTest.cpp
@@ -6,7 +6,7 @@
 
 #include "core/layout/LayoutMultiColumnSet.h"
 #include "core/layout/LayoutMultiColumnSpannerPlaceholder.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp
index b7c24a4e..422a35d8 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp
@@ -6,10 +6,10 @@
 
 #include "bindings/core/v8/V8BindingForTesting.h"
 #include "core/frame/LocalFrameView.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutTextFragment.h"
 #include "core/layout/LayoutView.h"
 #include "core/svg/SVGGElement.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/json/JSONValues.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/third_party/WebKit/Source/core/layout/LayoutProgressTest.cpp b/third_party/WebKit/Source/core/layout/LayoutProgressTest.cpp
index 07af22a0..9012c5a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutProgressTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutProgressTest.cpp
@@ -6,7 +6,7 @@
 
 #include "core/html/HTMLElement.h"
 #include "core/html_names.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/layout/LayoutReplacedTest.cpp b/third_party/WebKit/Source/core/layout/LayoutReplacedTest.cpp
index 9dfb9fa4..5b0fe9fe 100644
--- a/third_party/WebKit/Source/core/layout/LayoutReplacedTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutReplacedTest.cpp
@@ -5,7 +5,7 @@
 #include "core/layout/LayoutReplaced.h"
 
 #include "build/build_config.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCellTest.cpp b/third_party/WebKit/Source/core/layout/LayoutTableCellTest.cpp
index 2d7cdc4..19c203d 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableCellTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableCellTest.cpp
@@ -26,7 +26,7 @@
 #include "core/layout/LayoutTableCell.h"
 
 #include "build/build_config.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableColTest.cpp b/third_party/WebKit/Source/core/layout/LayoutTableColTest.cpp
index a8c08f7..1e3d1d3 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableColTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableColTest.cpp
@@ -4,7 +4,7 @@
 
 #include "core/layout/LayoutTableCol.h"
 
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableRowTest.cpp b/third_party/WebKit/Source/core/layout/LayoutTableRowTest.cpp
index 86ffacd..472dc8c 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableRowTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableRowTest.cpp
@@ -26,7 +26,7 @@
 #include "core/layout/LayoutTableRow.h"
 
 #include "build/build_config.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSectionTest.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSectionTest.cpp
index e61954ae..c0ffe756 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSectionTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSectionTest.cpp
@@ -5,7 +5,7 @@
 #include "core/layout/LayoutTableSection.h"
 
 #include "core/layout/LayoutTableCell.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableTest.cpp b/third_party/WebKit/Source/core/layout/LayoutTableTest.cpp
index 221f532e..4e73b773 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableTest.cpp
@@ -5,7 +5,7 @@
 #include "core/layout/LayoutTable.h"
 #include "core/layout/LayoutTableSection.h"
 
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutText.cpp b/third_party/WebKit/Source/core/layout/LayoutText.cpp
index 300a09e..7da03cf 100644
--- a/third_party/WebKit/Source/core/layout/LayoutText.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutText.cpp
@@ -166,9 +166,7 @@
       max_width_(-1),
       first_line_min_width_(0),
       last_line_line_min_width_(0),
-      text_(std::move(str)),
-      first_text_box_(nullptr),
-      last_text_box_(nullptr) {
+      text_(std::move(str)) {
   DCHECK(text_);
   DCHECK(!node || !node->IsDocumentNode());
 
@@ -178,15 +176,6 @@
     GetFrameView()->IncrementVisuallyNonEmptyCharacterCount(text_.length());
 }
 
-#if DCHECK_IS_ON()
-
-LayoutText::~LayoutText() {
-  DCHECK(!first_text_box_);
-  DCHECK(!last_text_box_);
-}
-
-#endif
-
 LayoutText* LayoutText::CreateEmptyAnonymous(Document& doc) {
   LayoutText* text = new LayoutText(nullptr, StringImpl::empty_);
   text->SetDocumentForAnonymous(&doc);
@@ -238,7 +227,7 @@
         if (next)
           next->MarkDirty();
       }
-      for (InlineTextBox* box : InlineTextBoxesOf(*this))
+      for (InlineTextBox* box : TextBoxes())
         box->Remove();
     } else if (Parent()) {
       Parent()->DirtyLinesFromChangedChild(this);
@@ -257,51 +246,19 @@
 }
 
 void LayoutText::ExtractTextBox(InlineTextBox* box) {
-  last_text_box_ = box->PrevTextBox();
-  if (box == first_text_box_)
-    first_text_box_ = nullptr;
-  if (box->PrevTextBox())
-    box->PrevTextBox()->SetNextTextBox(nullptr);
-  box->SetPreviousTextBox(nullptr);
-  for (InlineTextBox* curr = box; curr; curr = curr->NextTextBox())
-    curr->SetExtracted();
+  text_boxes_.ExtractLineBox(box);
 }
 
 void LayoutText::AttachTextBox(InlineTextBox* box) {
-  if (last_text_box_) {
-    last_text_box_->SetNextTextBox(box);
-    box->SetPreviousTextBox(last_text_box_);
-  } else {
-    first_text_box_ = box;
-  }
-  InlineTextBox* last = box;
-  for (InlineTextBox* curr = box; curr; curr = curr->NextTextBox()) {
-    curr->SetExtracted(false);
-    last = curr;
-  }
-  last_text_box_ = last;
+  text_boxes_.AttachLineBox(box);
 }
 
 void LayoutText::RemoveTextBox(InlineTextBox* box) {
-  if (box == first_text_box_)
-    first_text_box_ = box->NextTextBox();
-  if (box == last_text_box_)
-    last_text_box_ = box->PrevTextBox();
-  if (box->NextTextBox())
-    box->NextTextBox()->SetPreviousTextBox(box->PrevTextBox());
-  if (box->PrevTextBox())
-    box->PrevTextBox()->SetNextTextBox(box->NextTextBox());
+  text_boxes_.RemoveLineBox(box);
 }
 
 void LayoutText::DeleteTextBoxes() {
-  if (FirstTextBox()) {
-    InlineTextBox* next;
-    for (InlineTextBox* curr = FirstTextBox(); curr; curr = next) {
-      next = curr->NextTextBox();
-      curr->Destroy();
-    }
-    first_text_box_ = last_text_box_ = nullptr;
-  }
+  text_boxes_.DeleteLineBoxes();
 }
 
 Optional<FloatPoint> LayoutText::GetUpperLeftCorner() const {
@@ -337,13 +294,13 @@
   // FIXME: this is just a stopgap until TextIterator is adapted to support
   // generated text.
   StringBuilder plain_text_builder;
-  for (InlineTextBox* text_box : InlineTextBoxesOf(*this)) {
+  for (InlineTextBox* text_box : TextBoxes()) {
     String text = text_.Substring(text_box->Start(), text_box->Len())
                       .SimplifyWhiteSpace(WTF::kDoNotStripWhiteSpace);
     plain_text_builder.Append(text);
-    if (text_box->NextTextBox() &&
-        text_box->NextTextBox()->Start() > text_box->end() && text.length() &&
-        !text.Right(1).ContainsOnlyWhitespace())
+    if (text_box->NextForSameLayoutObject() &&
+        text_box->NextForSameLayoutObject()->Start() > text_box->end() &&
+        text.length() && !text.Right(1).ContainsOnlyWhitespace())
       plain_text_builder.Append(kSpaceCharacter);
   }
   return plain_text_builder.ToString();
@@ -351,7 +308,7 @@
 
 void LayoutText::AbsoluteRects(Vector<IntRect>& rects,
                                const LayoutPoint& accumulated_offset) const {
-  for (InlineTextBox* box : InlineTextBoxesOf(*this)) {
+  for (InlineTextBox* box : TextBoxes()) {
     rects.push_back(EnclosingIntRect(LayoutRect(
         LayoutPoint(accumulated_offset) + box->Location(), box->Size())));
   }
@@ -438,7 +395,7 @@
     }
     return;
   }
-  for (InlineTextBox* box : InlineTextBoxesOf(*this)) {
+  for (InlineTextBox* box : TextBoxes()) {
     const IntRect ellipsis_rect = (option == kClipToEllipsis)
                                       ? EllipsisRectForBox(box, 0, TextLength())
                                       : IntRect();
@@ -478,7 +435,7 @@
   // This function is always called in sequence that this check should work.
   bool has_checked_box_in_range = !quads.IsEmpty();
 
-  for (InlineTextBox* box : InlineTextBoxesOf(*this)) {
+  for (InlineTextBox* box : TextBoxes()) {
     // Note: box->end() returns the index of the last character, not the index
     // past it
     if (start <= box->Start() && box->end() < end) {
@@ -701,10 +658,10 @@
   bool blocks_are_flipped = Style()->IsFlippedBlocksWritingMode();
 
   InlineTextBox* last_box = nullptr;
-  for (InlineTextBox* box : InlineTextBoxesOf(*this)) {
+  for (InlineTextBox* box : TextBoxes()) {
     if (box->IsLineBreak() && !box->PrevLeafChild() && box->NextLeafChild() &&
         !box->NextLeafChild()->IsLineBreak())
-      box = box->NextTextBox();
+      box = box->NextForSameLayoutObject();
 
     RootInlineBox& root_box = box->Root();
     LayoutUnit top = std::min(root_box.SelectionTop(), root_box.LineTop());
@@ -1477,11 +1434,11 @@
 }
 
 float LayoutText::FirstRunX() const {
-  return first_text_box_ ? first_text_box_->X().ToFloat() : 0;
+  return FirstTextBox() ? FirstTextBox()->X().ToFloat() : 0;
 }
 
 float LayoutText::FirstRunY() const {
-  return first_text_box_ ? first_text_box_->Y().ToFloat() : 0;
+  return FirstTextBox() ? FirstTextBox()->Y().ToFloat() : 0;
 }
 
 void LayoutText::SetTextWithOffset(scoped_refptr<StringImpl> text,
@@ -1503,7 +1460,7 @@
 
   // Dirty all text boxes that include characters in between offset and
   // offset+len.
-  for (InlineTextBox* curr : InlineTextBoxesOf(*this)) {
+  for (InlineTextBox* curr : TextBoxes()) {
     // FIXME: This shouldn't rely on the end of a dirty line box. See
     // https://bugs.webkit.org/show_bug.cgi?id=97264
     // Text run is entirely before the affected range.
@@ -1719,7 +1676,7 @@
 }
 
 void LayoutText::DirtyLineBoxes() {
-  for (InlineTextBox* box : InlineTextBoxesOf(*this))
+  for (InlineTextBox* box : TextBoxes())
     box->DirtyLineBoxes();
   lines_dirty_ = false;
 }
@@ -1731,13 +1688,7 @@
 InlineTextBox* LayoutText::CreateInlineTextBox(int start,
                                                unsigned short length) {
   InlineTextBox* text_box = CreateTextBox(start, length);
-  if (!first_text_box_) {
-    first_text_box_ = last_text_box_ = text_box;
-  } else {
-    last_text_box_->SetNextTextBox(text_box);
-    text_box->SetPreviousTextBox(last_text_box_);
-    last_text_box_ = text_box;
-  }
+  text_boxes_.AppendLineBox(text_box);
   return text_box;
 }
 
@@ -1748,14 +1699,7 @@
   if (!s->Len()) {
     // We want the box to be destroyed.
     s->Remove(kDontMarkLineBoxes);
-    if (first_text_box_ == s)
-      first_text_box_ = s->NextTextBox();
-    else
-      s->PrevTextBox()->SetNextTextBox(s->NextTextBox());
-    if (last_text_box_ == s)
-      last_text_box_ = s->PrevTextBox();
-    else
-      s->NextTextBox()->SetPreviousTextBox(s->PrevTextBox());
+    text_boxes_.RemoveLineBox(s);
     s->Destroy();
     return;
   }
@@ -1853,7 +1797,7 @@
     // Return the width of the minimal left side and the maximal right side.
     float logical_left_side = 0;
     float logical_right_side = 0;
-    for (InlineTextBox* curr : InlineTextBoxesOf(*this)) {
+    for (InlineTextBox* curr : TextBoxes()) {
       if (curr == FirstTextBox() || curr->LogicalLeft() < logical_left_side)
         logical_left_side = curr->LogicalLeft().ToFloat();
       if (curr == FirstTextBox() || curr->LogicalRight() > logical_right_side)
@@ -1881,7 +1825,7 @@
   // Return the width of the minimal left side and the maximal right side.
   LayoutUnit logical_left_side = LayoutUnit::Max();
   LayoutUnit logical_right_side = LayoutUnit::Min();
-  for (InlineTextBox* curr : InlineTextBoxesOf(*this)) {
+  for (InlineTextBox* curr : TextBoxes()) {
     LayoutRect logical_visual_overflow = curr->LogicalOverflowRect();
     logical_left_side =
         std::min(logical_left_side, logical_visual_overflow.X());
@@ -1967,7 +1911,7 @@
   if (start_pos == end_pos)
     return rect;
 
-  for (InlineTextBox* box : InlineTextBoxesOf(*this)) {
+  for (InlineTextBox* box : TextBoxes()) {
     rect.Unite(box->LocalSelectionRect(start_pos, end_pos));
     rect.Unite(LayoutRect(EllipsisRectForBox(box, start_pos, end_pos)));
   }
@@ -2048,7 +1992,7 @@
   if (!box)
     return 0;
   int min_offset = box->Start();
-  for (box = box->NextTextBox(); box; box = box->NextTextBox())
+  while ((box = box->NextForSameLayoutObject()))
     min_offset = std::min<int>(min_offset, box->Start());
   return min_offset;
 }
@@ -2073,7 +2017,7 @@
     return TextLength();
 
   int max_offset = box->Start() + box->Len();
-  for (box = box->PrevTextBox(); box; box = box->PrevTextBox())
+  while ((box = box->PrevForSameLayoutObject()))
     max_offset = std::max<int>(max_offset, box->Start() + box->Len());
   return max_offset;
 }
@@ -2099,7 +2043,7 @@
   }
 
   int len = 0;
-  for (InlineTextBox* box : InlineTextBoxesOf(*this))
+  for (InlineTextBox* box : TextBoxes())
     len += box->Len();
   return len;
 }
@@ -2126,7 +2070,7 @@
     return *mapping->GetCharacterBefore(position) != kNewlineCharacter;
   }
 
-  for (InlineTextBox* box : InlineTextBoxesOf(*this)) {
+  for (InlineTextBox* box : TextBoxes()) {
     if (text_offset < static_cast<int>(box->Start()) &&
         !ContainsReversedText()) {
       // The offset we're looking for is before this node
@@ -2185,7 +2129,7 @@
   }
 
   InlineTextBox* const last_text_box = LastTextBox();
-  for (InlineTextBox* box : InlineTextBoxesOf(*this)) {
+  for (InlineTextBox* box : TextBoxes()) {
     if (text_offset <= box->end()) {
       if (text_offset >= box->Start())
         return true;
@@ -2218,7 +2162,7 @@
   }
 
   InlineTextBox* const last_text_box = LastTextBox();
-  for (InlineTextBox* box : InlineTextBoxesOf(*this)) {
+  for (InlineTextBox* box : TextBoxes()) {
     if (text_offset == box->Start())
       continue;
     if (text_offset <= box->Start() + box->Len()) {
@@ -2257,7 +2201,7 @@
 
 scoped_refptr<AbstractInlineTextBox> LayoutText::FirstAbstractInlineTextBox() {
   return AbstractInlineTextBox::GetOrCreate(LineLayoutText(this),
-                                            first_text_box_);
+                                            FirstTextBox());
 }
 
 void LayoutText::InvalidateDisplayItemClients(
@@ -2280,7 +2224,7 @@
 
   paint_invalidator.InvalidateDisplayItemClient(*this, invalidation_reason);
 
-  for (InlineTextBox* box : InlineTextBoxesOf(*this)) {
+  for (InlineTextBox* box : TextBoxes()) {
     paint_invalidator.InvalidateDisplayItemClient(*box, invalidation_reason);
     if (EllipsisBox* ellipsis_box = box->Root().GetEllipsisBox()) {
       paint_invalidator.InvalidateDisplayItemClient(*ellipsis_box,
@@ -2317,25 +2261,4 @@
   return rect;
 }
 
-// -----
-InlineTextBoxRange::Iterator::Iterator(InlineTextBox* current)
-    : current_(current) {}
-
-InlineTextBoxRange::Iterator& InlineTextBoxRange::Iterator::operator++() {
-  current_ = current_->NextTextBox();
-  return *this;
-}
-
-InlineTextBox* InlineTextBoxRange::Iterator::operator*() const {
-  DCHECK(current_);
-  return current_;
-}
-
-InlineTextBoxRange::InlineTextBoxRange(const LayoutText& layout_text)
-    : layout_text_(&layout_text) {}
-
-InlineTextBoxRange InlineTextBoxesOf(const LayoutText& layout_text) {
-  return InlineTextBoxRange(layout_text);
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/LayoutText.h b/third_party/WebKit/Source/core/layout/LayoutText.h
index 0805a04..e348d75d 100644
--- a/third_party/WebKit/Source/core/layout/LayoutText.h
+++ b/third_party/WebKit/Source/core/layout/LayoutText.h
@@ -29,6 +29,7 @@
 #include "core/dom/Text.h"
 #include "core/layout/LayoutObject.h"
 #include "core/layout/TextRunConstructor.h"
+#include "core/layout/line/LineBoxList.h"
 #include "platform/LengthFunctions.h"
 #include "platform/wtf/Forward.h"
 
@@ -58,7 +59,7 @@
 //
 //
 // ***** LINE BOXES OWNERSHIP *****
-// m_firstTextBox and m_lastTextBox are not owned by LayoutText
+// InlineTextBox in text_boxes_ are not owned by LayoutText
 // but are pointers into the enclosing inline / block (see LayoutInline's
 // and LayoutBlockFlow's m_lineBoxes).
 //
@@ -76,9 +77,6 @@
   // not the content of the Text node, updating text-transform property
   // doesn't re-transform the string.
   LayoutText(Node*, scoped_refptr<StringImpl>);
-#if DCHECK_IS_ON()
-  ~LayoutText() override;
-#endif
 
   static LayoutText* CreateEmptyAnonymous(Document&);
 
@@ -195,8 +193,10 @@
       int caret_offset,
       LayoutUnit* extra_width_to_end_of_line = nullptr) const override;
 
-  InlineTextBox* FirstTextBox() const { return first_text_box_; }
-  InlineTextBox* LastTextBox() const { return last_text_box_; }
+  const InlineTextBoxList& TextBoxes() const { return text_boxes_; }
+
+  InlineTextBox* FirstTextBox() const { return text_boxes_.First(); }
+  InlineTextBox* LastTextBox() const { return text_boxes_.Last(); }
 
   // Returns upper left corner point in local coordinate if this object has
   // rendered text.
@@ -370,8 +370,7 @@
 
   // The line boxes associated with this object.
   // Read the LINE BOXES OWNERSHIP section in the class header comment.
-  InlineTextBox* first_text_box_;
-  InlineTextBox* last_text_box_;
+  InlineTextBoxList text_boxes_;
 };
 
 inline UChar LayoutText::UncheckedCharacterAt(unsigned i) const {
@@ -409,39 +408,6 @@
   return ToLayoutText(CharacterData::GetLayoutObject());
 }
 
-// Represents list of |InlineTextBox| objects associated to |LayoutText| in
-// layout order.
-class InlineTextBoxRange {
- public:
-  class Iterator
-      : public std::iterator<std::input_iterator_tag, InlineTextBox*> {
-   public:
-    explicit Iterator(InlineTextBox*);
-    Iterator(const Iterator&) = default;
-
-    Iterator& operator++();
-    InlineTextBox* operator*() const;
-
-    bool operator==(const Iterator& other) const {
-      return current_ == other.current_;
-    }
-    bool operator!=(const Iterator& other) const { return !operator==(other); }
-
-   private:
-    InlineTextBox* current_;
-  };
-
-  explicit InlineTextBoxRange(const LayoutText&);
-
-  Iterator begin() const { return Iterator(layout_text_->FirstTextBox()); }
-  Iterator end() const { return Iterator(nullptr); }
-
- private:
-  const LayoutText* layout_text_;
-};
-
-InlineTextBoxRange InlineTextBoxesOf(const LayoutText&);
-
 void ApplyTextTransform(const ComputedStyle*, String&, UChar);
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextControlTest.cpp b/third_party/WebKit/Source/core/layout/LayoutTextControlTest.cpp
index c1fc526..6fc403a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTextControlTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTextControlTest.cpp
@@ -6,7 +6,7 @@
 
 #include "build/build_config.h"
 #include "core/html/forms/HTMLInputElement.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextFragmentTest.cpp b/third_party/WebKit/Source/core/layout/LayoutTextFragmentTest.cpp
index 92e604b..5c74ce1 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTextFragmentTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTextFragmentTest.cpp
@@ -5,7 +5,7 @@
 #include "core/layout/LayoutTextFragment.h"
 
 #include "core/html/HTMLHeadElement.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/runtime_enabled_features.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextTest.cpp b/third_party/WebKit/Source/core/layout/LayoutTextTest.cpp
index 8b5f742..ecd1ec6 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTextTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTextTest.cpp
@@ -4,8 +4,8 @@
 
 #include "core/layout/LayoutText.h"
 
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/line/InlineTextBox.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/runtime_enabled_features.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/core/layout/LayoutTreeAsText.cpp b/third_party/WebKit/Source/core/layout/LayoutTreeAsText.cpp
index c2aa158..fba0b19 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTreeAsText.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTreeAsText.cpp
@@ -410,8 +410,7 @@
 void LayoutTreeAsText::WriteLineBoxTree(TextStream& ts,
                                         const LayoutBlockFlow& o,
                                         int indent) {
-  for (const InlineFlowBox* root_box = o.FirstLineBox(); root_box;
-       root_box = root_box->NextLineBox()) {
+  for (const InlineFlowBox* root_box : o.LineBoxes()) {
     WriteInlineFlowBox(ts, *root_box, indent);
   }
 }
@@ -551,8 +550,7 @@
         WriteTextFragment(ts, *child.fragment, child.offset_to_container_box);
       }
     } else {
-      for (InlineTextBox* box = text.FirstTextBox(); box;
-           box = box->NextTextBox()) {
+      for (InlineTextBox* box : text.TextBoxes()) {
         WriteIndent(ts, indent + 1);
         WriteTextRun(ts, text, *box);
       }
diff --git a/third_party/WebKit/Source/core/layout/LayoutViewTest.cpp b/third_party/WebKit/Source/core/layout/LayoutViewTest.cpp
index ef33a6f..2a743efa 100644
--- a/third_party/WebKit/Source/core/layout/LayoutViewTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutViewTest.cpp
@@ -4,7 +4,7 @@
 
 #include "core/layout/LayoutView.h"
 
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/core/layout/MapCoordinatesTest.cpp b/third_party/WebKit/Source/core/layout/MapCoordinatesTest.cpp
index 8fe790d..7a5b0a3 100644
--- a/third_party/WebKit/Source/core/layout/MapCoordinatesTest.cpp
+++ b/third_party/WebKit/Source/core/layout/MapCoordinatesTest.cpp
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 #include "core/layout/LayoutInline.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutView.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/geometry/TransformState.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroupTest.cpp b/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroupTest.cpp
index 5e62dd9..ff7b246 100644
--- a/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroupTest.cpp
+++ b/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroupTest.cpp
@@ -6,7 +6,7 @@
 
 #include "core/layout/LayoutMultiColumnFlowThread.h"
 #include "core/layout/LayoutMultiColumnSet.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/layout/PaginationTest.cpp b/third_party/WebKit/Source/core/layout/PaginationTest.cpp
index 51cd2c5..59ba3a43 100644
--- a/third_party/WebKit/Source/core/layout/PaginationTest.cpp
+++ b/third_party/WebKit/Source/core/layout/PaginationTest.cpp
@@ -5,7 +5,7 @@
 #include "core/layout/LayoutBlockFlow.h"
 #include "core/layout/LayoutMultiColumnFlowThread.h"
 
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/layout/PaintContainmentTest.cpp b/third_party/WebKit/Source/core/layout/PaintContainmentTest.cpp
index 9fc241fd..f70fbc37 100644
--- a/third_party/WebKit/Source/core/layout/PaintContainmentTest.cpp
+++ b/third_party/WebKit/Source/core/layout/PaintContainmentTest.cpp
@@ -4,7 +4,7 @@
 
 #include "core/layout/LayoutBlock.h"
 #include "core/layout/LayoutInline.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "core/paint/PaintLayer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp b/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp
index c80dd48..5ce4e526 100644
--- a/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp
+++ b/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp
@@ -99,8 +99,7 @@
     }
   } else if (layout_object->IsText()) {
     // TODO(skobes): Use first and last InlineTextBox only?
-    for (InlineTextBox* box = ToLayoutText(layout_object)->FirstTextBox(); box;
-         box = box->NextTextBox())
+    for (InlineTextBox* box : ToLayoutText(layout_object)->TextBoxes())
       local_bounds.Unite(box->FrameRect());
   } else {
     // Only LayoutBox and LayoutText are supported.
diff --git a/third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp b/third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp
index 3d54180..3d4edab 100644
--- a/third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp
+++ b/third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp
@@ -8,9 +8,9 @@
 #include "core/frame/VisualViewport.h"
 #include "core/geometry/DOMRect.h"
 #include "core/layout/LayoutBox.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/page/PrintContext.h"
 #include "core/paint/PaintLayerScrollableArea.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/HistogramTester.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 
diff --git a/third_party/WebKit/Source/core/layout/TextAutosizerTest.cpp b/third_party/WebKit/Source/core/layout/TextAutosizerTest.cpp
index f506b31..42a82e50 100644
--- a/third_party/WebKit/Source/core/layout/TextAutosizerTest.cpp
+++ b/third_party/WebKit/Source/core/layout/TextAutosizerTest.cpp
@@ -4,9 +4,9 @@
 
 #include "core/frame/LocalFrame.h"
 #include "core/layout/LayoutObject.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/TextAutosizer.h"
 #include "core/loader/EmptyClients.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/PlatformFrameView.h"
 #include "platform/geometry/IntRect.h"
 #include "public/platform/WebFloatRect.h"
diff --git a/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp b/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
index 6e621b1..ff1a1260 100644
--- a/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
+++ b/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutView.h"
 #include "core/paint/PaintLayer.h"
 #include "core/paint/PaintPropertyTreePrinter.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/graphics/paint/GeometryMapper.h"
 #include "platform/testing/PaintTestConfigurations.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/core/layout/line/AbstractInlineTextBox.cpp b/third_party/WebKit/Source/core/layout/line/AbstractInlineTextBox.cpp
index 86dd3545..7e4f9d4 100644
--- a/third_party/WebKit/Source/core/layout/line/AbstractInlineTextBox.cpp
+++ b/third_party/WebKit/Source/core/layout/line/AbstractInlineTextBox.cpp
@@ -95,7 +95,8 @@
   if (!inline_text_box_)
     return nullptr;
 
-  return GetOrCreate(line_layout_item_, inline_text_box_->NextTextBox());
+  return GetOrCreate(line_layout_item_,
+                     inline_text_box_->NextForSameLayoutObject());
 }
 
 LayoutRect AbstractInlineTextBox::LocalBounds() const {
@@ -181,8 +182,9 @@
   String result = line_layout_item_.GetText()
                       .Substring(start, len)
                       .SimplifyWhiteSpace(WTF::kDoNotStripWhiteSpace);
-  if (inline_text_box_->NextTextBox() &&
-      inline_text_box_->NextTextBox()->Start() > inline_text_box_->end() &&
+  if (inline_text_box_->NextForSameLayoutObject() &&
+      inline_text_box_->NextForSameLayoutObject()->Start() >
+          inline_text_box_->end() &&
       result.length() && !result.Right(1).ContainsOnlyWhitespace())
     return result + " ";
   return result;
@@ -191,13 +193,13 @@
 bool AbstractInlineTextBox::IsFirst() const {
   DCHECK(!inline_text_box_ ||
          !inline_text_box_->GetLineLayoutItem().NeedsLayout());
-  return !inline_text_box_ || !inline_text_box_->PrevTextBox();
+  return !inline_text_box_ || !inline_text_box_->PrevForSameLayoutObject();
 }
 
 bool AbstractInlineTextBox::IsLast() const {
   DCHECK(!inline_text_box_ ||
          !inline_text_box_->GetLineLayoutItem().NeedsLayout());
-  return !inline_text_box_ || !inline_text_box_->NextTextBox();
+  return !inline_text_box_ || !inline_text_box_->NextForSameLayoutObject();
 }
 
 scoped_refptr<AbstractInlineTextBox> AbstractInlineTextBox::NextOnLine() const {
diff --git a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
index 699da84..cf3b408 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
+++ b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
@@ -359,18 +359,18 @@
     // Check to see if all initial lines are unconstructed.  If so, then
     // we know the inline began on this line (unless we are a continuation).
     LineBoxList* line_box_list = LineBoxes();
-    if (!line_box_list->FirstLineBox()->IsConstructed() &&
+    if (!line_box_list->First()->IsConstructed() &&
         !GetLineLayoutItem().IsInlineElementContinuation()) {
       if (GetLineLayoutItem().Style()->BoxDecorationBreak() ==
           EBoxDecorationBreak::kClone)
         include_left_edge = include_right_edge = true;
-      else if (ltr && line_box_list->FirstLineBox() == this)
+      else if (ltr && line_box_list->First() == this)
         include_left_edge = true;
-      else if (!ltr && line_box_list->LastLineBox() == this)
+      else if (!ltr && line_box_list->Last() == this)
         include_right_edge = true;
     }
 
-    if (!line_box_list->LastLineBox()->IsConstructed()) {
+    if (!line_box_list->Last()->IsConstructed()) {
       LineLayoutInline inline_flow = LineLayoutInline(GetLineLayoutItem());
       LineLayoutItem logically_last_run_layout_item(
           logically_last_run_layout_object);
@@ -394,11 +394,13 @@
           EBoxDecorationBreak::kClone) {
         include_left_edge = include_right_edge = true;
       } else if (ltr) {
-        if (!NextLineBox() && ((last_line || is_last_object_on_line) &&
-                               !inline_flow.Continuation()))
+        if (!NextForSameLayoutObject() &&
+            ((last_line || is_last_object_on_line) &&
+             !inline_flow.Continuation()))
           include_right_edge = true;
       } else {
-        if ((!PrevLineBox() || PrevLineBox()->IsConstructed()) &&
+        if ((!PrevForSameLayoutObject() ||
+             PrevForSameLayoutObject()->IsConstructed()) &&
             ((last_line || is_last_object_on_line) &&
              !inline_flow.Continuation()))
           include_left_edge = true;
@@ -1399,7 +1401,8 @@
   StyleImage* image = last_background_layer.GetImage();
   bool has_fill_image = image && image->CanRender();
   return (!has_fill_image && !GetLineLayoutItem().Style()->HasBorderRadius()) ||
-         (!PrevLineBox() && !NextLineBox()) || !Parent();
+         (!PrevForSameLayoutObject() && !NextForSameLayoutObject()) ||
+         !Parent();
 }
 
 InlineBox* InlineFlowBox::FirstLeafChild() const {
diff --git a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h
index 8bff1d00..e7d91f73 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h
+++ b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h
@@ -93,10 +93,10 @@
 #endif
   const char* BoxName() const override;
 
-  InlineFlowBox* PrevLineBox() const { return prev_line_box_; }
-  InlineFlowBox* NextLineBox() const { return next_line_box_; }
-  void SetNextLineBox(InlineFlowBox* n) { next_line_box_ = n; }
-  void SetPreviousLineBox(InlineFlowBox* p) { prev_line_box_ = p; }
+  InlineFlowBox* PrevForSameLayoutObject() const { return prev_line_box_; }
+  InlineFlowBox* NextForSameLayoutObject() const { return next_line_box_; }
+  void SetNextForSameLayoutObject(InlineFlowBox* n) { next_line_box_ = n; }
+  void SetPreviousForSameLayoutObject(InlineFlowBox* p) { prev_line_box_ = p; }
 
   InlineBox* FirstChild() const { return first_child_; }
   InlineBox* LastChild() const { return last_child_; }
@@ -455,10 +455,11 @@
   InlineBox* first_child_;
   InlineBox* last_child_;
 
-  InlineFlowBox*
-      prev_line_box_;  // The previous box that also uses our LayoutObject
-  InlineFlowBox*
-      next_line_box_;  // The next box that also uses our LayoutObject
+  // The next/previous box that also uses our LayoutObject.
+  // RootInlineBox, a subclass of this class, uses these fields for
+  // next/previous RootInlineBox.
+  InlineFlowBox* prev_line_box_;
+  InlineFlowBox* next_line_box_;
 
  private:
   unsigned include_logical_left_edge_ : 1;
diff --git a/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
index 11dd916c..1517f65 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
+++ b/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
@@ -258,7 +258,7 @@
   // If we're the last inline text box in containing block, our containing block
   // is inline, and the selection continues into that block, then rely on the
   // next inline text box (if any) to paint a wrapped new line as needed.
-  if (NextTextBox())
+  if (NextForSameLayoutObject())
     return true;
   auto root_block = Root().Block();
   if (root_block.IsInline() &&
diff --git a/third_party/WebKit/Source/core/layout/line/InlineTextBox.h b/third_party/WebKit/Source/core/layout/line/InlineTextBox.h
index 976bb0a..620b212 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineTextBox.h
+++ b/third_party/WebKit/Source/core/layout/line/InlineTextBox.h
@@ -56,10 +56,10 @@
 
   void Destroy() final;
 
-  InlineTextBox* PrevTextBox() const { return prev_text_box_; }
-  InlineTextBox* NextTextBox() const { return next_text_box_; }
-  void SetNextTextBox(InlineTextBox* n) { next_text_box_ = n; }
-  void SetPreviousTextBox(InlineTextBox* p) { prev_text_box_ = p; }
+  InlineTextBox* PrevForSameLayoutObject() const { return prev_text_box_; }
+  InlineTextBox* NextForSameLayoutObject() const { return next_text_box_; }
+  void SetNextForSameLayoutObject(InlineTextBox* n) { next_text_box_ = n; }
+  void SetPreviousForSameLayoutObject(InlineTextBox* p) { prev_text_box_ = p; }
 
   // FIXME: These accessors should DCHECK(!isDirty()). See
   // https://bugs.webkit.org/show_bug.cgi?id=97264
@@ -216,9 +216,8 @@
   void CharacterWidths(Vector<float>&) const;
 
  private:
-  // The previous box that also uses our LayoutObject.
+  // The next/previous box that also uses our LayoutObject.
   InlineTextBox* prev_text_box_;
-  // The next box that also uses our LayoutObject.
   InlineTextBox* next_text_box_;
 
   int start_;
diff --git a/third_party/WebKit/Source/core/layout/line/InlineTextBoxTest.cpp b/third_party/WebKit/Source/core/layout/line/InlineTextBoxTest.cpp
index 026059a..5c63e3dc 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineTextBoxTest.cpp
+++ b/third_party/WebKit/Source/core/layout/line/InlineTextBoxTest.cpp
@@ -4,7 +4,7 @@
 
 #include "core/layout/line/InlineTextBox.h"
 
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/layout/line/LineBoxList.cpp b/third_party/WebKit/Source/core/layout/line/LineBoxList.cpp
index 90b6d6a8..3f6364c 100644
--- a/third_party/WebKit/Source/core/layout/line/LineBoxList.cpp
+++ b/third_party/WebKit/Source/core/layout/line/LineBoxList.cpp
@@ -39,86 +39,92 @@
 #include "core/paint/PaintInfo.h"
 
 namespace blink {
-
 #if DCHECK_IS_ON()
-LineBoxList::~LineBoxList() {
-  DCHECK(!first_line_box_);
-  DCHECK(!last_line_box_);
+template <typename InlineBoxType>
+InlineBoxList<InlineBoxType>::~InlineBoxList() {
+  DCHECK(!first_);
+  DCHECK(!last_);
 }
 #endif
 
-void LineBoxList::AppendLineBox(InlineFlowBox* box) {
-  if (!first_line_box_) {
-    first_line_box_ = last_line_box_ = box;
+template <typename InlineBoxType>
+void InlineBoxList<InlineBoxType>::AppendLineBox(InlineBoxType* box) {
+  if (!first_) {
+    first_ = last_ = box;
   } else {
-    last_line_box_->SetNextLineBox(box);
-    box->SetPreviousLineBox(last_line_box_);
-    last_line_box_ = box;
+    last_->SetNextForSameLayoutObject(box);
+    box->SetPreviousForSameLayoutObject(last_);
+    last_ = box;
   }
 }
 
 void LineBoxList::DeleteLineBoxTree() {
-  InlineFlowBox* line = first_line_box_;
+  InlineFlowBox* line = first_;
   InlineFlowBox* next_line;
   while (line) {
-    next_line = line->NextLineBox();
+    next_line = line->NextForSameLayoutObject();
     line->DeleteLine();
     line = next_line;
   }
-  first_line_box_ = last_line_box_ = nullptr;
+  first_ = last_ = nullptr;
 }
 
-void LineBoxList::ExtractLineBox(InlineFlowBox* box) {
-  last_line_box_ = box->PrevLineBox();
-  if (box == first_line_box_)
-    first_line_box_ = nullptr;
-  if (box->PrevLineBox())
-    box->PrevLineBox()->SetNextLineBox(nullptr);
-  box->SetPreviousLineBox(nullptr);
-  for (InlineFlowBox* curr = box; curr; curr = curr->NextLineBox())
+template <typename InlineBoxType>
+void InlineBoxList<InlineBoxType>::ExtractLineBox(InlineBoxType* box) {
+  last_ = box->PrevForSameLayoutObject();
+  if (box == first_)
+    first_ = nullptr;
+  if (box->PrevForSameLayoutObject())
+    box->PrevForSameLayoutObject()->SetNextForSameLayoutObject(nullptr);
+  box->SetPreviousForSameLayoutObject(nullptr);
+  for (InlineBoxType* curr = box; curr; curr = curr->NextForSameLayoutObject())
     curr->SetExtracted();
 }
 
-void LineBoxList::AttachLineBox(InlineFlowBox* box) {
-  if (last_line_box_) {
-    last_line_box_->SetNextLineBox(box);
-    box->SetPreviousLineBox(last_line_box_);
+template <typename InlineBoxType>
+void InlineBoxList<InlineBoxType>::AttachLineBox(InlineBoxType* box) {
+  if (last_) {
+    last_->SetNextForSameLayoutObject(box);
+    box->SetPreviousForSameLayoutObject(last_);
   } else {
-    first_line_box_ = box;
+    first_ = box;
   }
-  InlineFlowBox* last = box;
-  for (InlineFlowBox* curr = box; curr; curr = curr->NextLineBox()) {
+  InlineBoxType* last = box;
+  for (InlineBoxType* curr = box; curr;
+       curr = curr->NextForSameLayoutObject()) {
     curr->SetExtracted(false);
     last = curr;
   }
-  last_line_box_ = last;
+  last_ = last;
 }
 
-void LineBoxList::RemoveLineBox(InlineFlowBox* box) {
-  if (box == first_line_box_)
-    first_line_box_ = box->NextLineBox();
-  if (box == last_line_box_)
-    last_line_box_ = box->PrevLineBox();
-  if (box->NextLineBox())
-    box->NextLineBox()->SetPreviousLineBox(box->PrevLineBox());
-  if (box->PrevLineBox())
-    box->PrevLineBox()->SetNextLineBox(box->NextLineBox());
+template <typename InlineBoxType>
+void InlineBoxList<InlineBoxType>::RemoveLineBox(InlineBoxType* box) {
+  if (box == first_)
+    first_ = box->NextForSameLayoutObject();
+  if (box == last_)
+    last_ = box->PrevForSameLayoutObject();
+  if (InlineBoxType* next = box->NextForSameLayoutObject())
+    next->SetPreviousForSameLayoutObject(box->PrevForSameLayoutObject());
+  if (InlineBoxType* prev = box->PrevForSameLayoutObject())
+    prev->SetNextForSameLayoutObject(box->NextForSameLayoutObject());
 }
 
-void LineBoxList::DeleteLineBoxes() {
-  if (first_line_box_) {
-    InlineFlowBox* next;
-    for (InlineFlowBox* curr = first_line_box_; curr; curr = next) {
-      next = curr->NextLineBox();
+template <typename InlineBoxType>
+void InlineBoxList<InlineBoxType>::DeleteLineBoxes() {
+  if (first_) {
+    InlineBoxType* next;
+    for (InlineBoxType* curr = first_; curr; curr = next) {
+      next = curr->NextForSameLayoutObject();
       curr->Destroy();
     }
-    first_line_box_ = nullptr;
-    last_line_box_ = nullptr;
+    first_ = nullptr;
+    last_ = nullptr;
   }
 }
 
 void LineBoxList::DirtyLineBoxes() {
-  for (InlineFlowBox* curr = FirstLineBox(); curr; curr = curr->NextLineBox())
+  for (InlineFlowBox* curr : *this)
     curr->DirtyLineBoxes();
 }
 
@@ -157,12 +163,12 @@
   // FIXME: This check is flawed in the following extremely obscure way:
   // if some line in the middle has a huge overflow, it might actually extend
   // below the last line.
-  RootInlineBox& first_root_box = FirstLineBox()->Root();
-  RootInlineBox& last_root_box = LastLineBox()->Root();
+  RootInlineBox& first_root_box = First()->Root();
+  RootInlineBox& last_root_box = Last()->Root();
   LayoutUnit first_line_top =
-      FirstLineBox()->LogicalTopVisualOverflow(first_root_box.LineTop());
+      First()->LogicalTopVisualOverflow(first_root_box.LineTop());
   LayoutUnit last_line_bottom =
-      LastLineBox()->LogicalBottomVisualOverflow(last_root_box.LineBottom());
+      Last()->LogicalBottomVisualOverflow(last_root_box.LineBottom());
 
   return RangeIntersectsRect(layout_object, first_line_top, last_line_bottom,
                              cull_rect, offset);
@@ -195,14 +201,14 @@
          (layout_object.IsLayoutInline() && layout_object.HasLayer()));
 
   // If we have no lines then we have no work to do.
-  if (!FirstLineBox())
+  if (!First())
     return false;
 
   const LayoutPoint& point = location_in_container.Point();
   IntRect hit_search_bounding_box = location_in_container.EnclosingIntRect();
 
   CullRect cull_rect(
-      FirstLineBox()->IsHorizontal()
+      First()->IsHorizontal()
           ? IntRect(point.X().ToInt(), hit_search_bounding_box.Y(), 1,
                     hit_search_bounding_box.Height())
           : IntRect(hit_search_bounding_box.X(), point.Y().ToInt(),
@@ -214,7 +220,7 @@
   // See if our root lines contain the point. If so, then we hit test them
   // further. Note that boxes can easily overlap, so we can't make any
   // assumptions based off positions of our first line box or our last line box.
-  for (InlineFlowBox* curr = LastLineBox(); curr; curr = curr->PrevLineBox()) {
+  for (InlineFlowBox* curr : InReverseOrder()) {
     RootInlineBox& root = curr->Root();
     if (RangeIntersectsRect(
             layout_object, curr->LogicalTopVisualOverflow(root.LineTop()),
@@ -255,7 +261,7 @@
 
   InlineBox* first_box = inline_container
                              ? inline_container.FirstLineBoxIncludingCulling()
-                             : FirstLineBox();
+                             : First();
 
   // If we have no first line box, then just bail early.
   if (!first_box) {
@@ -353,4 +359,7 @@
   }
 }
 
+template class InlineBoxList<InlineFlowBox>;
+template class InlineBoxList<InlineTextBox>;
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/line/LineBoxList.h b/third_party/WebKit/Source/core/layout/line/LineBoxList.h
index d639d1f..11ca41cf 100644
--- a/third_party/WebKit/Source/core/layout/line/LineBoxList.h
+++ b/third_party/WebKit/Source/core/layout/line/LineBoxList.h
@@ -29,6 +29,7 @@
 #ifndef LineBoxList_h
 #define LineBoxList_h
 
+#include "core/CoreExport.h"
 #include "core/layout/api/HitTestAction.h"
 #include "platform/wtf/Allocator.h"
 #include "platform/wtf/Assertions.h"
@@ -39,32 +40,108 @@
 class HitTestLocation;
 class HitTestResult;
 class InlineFlowBox;
+class InlineTextBox;
 class LayoutPoint;
 class LayoutUnit;
 class LineLayoutBoxModel;
 class LineLayoutItem;
 
-class LineBoxList {
+template <typename InlineBoxType>
+class CORE_TEMPLATE_CLASS_EXPORT InlineBoxList {
   DISALLOW_NEW();
 
  public:
-  LineBoxList() : first_line_box_(nullptr), last_line_box_(nullptr) {}
+  InlineBoxList() : first_(nullptr), last_(nullptr) {}
 
 #if DCHECK_IS_ON()
-  ~LineBoxList();
+  ~InlineBoxList();
 #endif
 
-  InlineFlowBox* FirstLineBox() const { return first_line_box_; }
-  InlineFlowBox* LastLineBox() const { return last_line_box_; }
+  InlineBoxType* First() const { return first_; }
+  InlineBoxType* Last() const { return last_; }
 
-  void AppendLineBox(InlineFlowBox*);
+  void AppendLineBox(InlineBoxType*);
 
-  void DeleteLineBoxTree();
   void DeleteLineBoxes();
 
-  void ExtractLineBox(InlineFlowBox*);
-  void AttachLineBox(InlineFlowBox*);
-  void RemoveLineBox(InlineFlowBox*);
+  void ExtractLineBox(InlineBoxType*);
+  void AttachLineBox(InlineBoxType*);
+  void RemoveLineBox(InlineBoxType*);
+
+  class BaseIterator {
+    STACK_ALLOCATED();
+
+   public:
+    explicit BaseIterator(InlineBoxType* first) : current_(first) {}
+
+    InlineBoxType* operator*() const {
+      DCHECK(current_);
+      return current_;
+    }
+    InlineBoxType* operator->() const { return operator*(); }
+
+    bool operator==(const BaseIterator& other) const {
+      return current_ == other.current_;
+    }
+    bool operator!=(const BaseIterator& other) const {
+      return !operator==(other);
+    }
+
+   protected:
+    InlineBoxType* current_;
+  };
+
+  class Iterator final : public BaseIterator {
+   public:
+    using BaseIterator::BaseIterator;
+    using BaseIterator::current_;
+    void operator++() {
+      DCHECK(current_);
+      current_ = current_->NextForSameLayoutObject();
+    }
+  };
+
+  class ReverseIterator final : public BaseIterator {
+   public:
+    using BaseIterator::BaseIterator;
+    using BaseIterator::current_;
+    void operator++() {
+      DCHECK(current_);
+      current_ = current_->PrevForSameLayoutObject();
+    }
+  };
+
+  Iterator begin() const { return Iterator(first_); }
+  Iterator end() const { return Iterator(nullptr); }
+
+  class ReverseRange final {
+    STACK_ALLOCATED();
+
+   public:
+    explicit ReverseRange(InlineBoxType* last) : last_(last){};
+    ReverseIterator begin() const { return ReverseIterator(last_); }
+    ReverseIterator end() const { return ReverseIterator(nullptr); }
+
+   private:
+    InlineBoxType* last_;
+  };
+
+  ReverseRange InReverseOrder() const { return ReverseRange(last_); }
+
+ protected:
+  // For block flows, each box represents the root inline box for a line in the
+  // paragraph.
+  // For inline flows, each box represents a portion of that inline.
+  InlineBoxType* first_;
+  InlineBoxType* last_;
+};
+
+extern template class CORE_EXTERN_TEMPLATE_EXPORT InlineBoxList<InlineFlowBox>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT InlineBoxList<InlineTextBox>;
+
+class LineBoxList : public InlineBoxList<InlineFlowBox> {
+ public:
+  void DeleteLineBoxTree();
 
   void DirtyLineBoxes();
   void DirtyLinesFromChangedChild(LineLayoutItem parent,
@@ -90,14 +167,10 @@
                            LayoutUnit logical_bottom,
                            const CullRect&,
                            const LayoutPoint&) const;
-
-  // For block flows, each box represents the root inline box for a line in the
-  // paragraph.
-  // For inline flows, each box represents a portion of that inline.
-  InlineFlowBox* first_line_box_;
-  InlineFlowBox* last_line_box_;
 };
 
+class InlineTextBoxList : public InlineBoxList<InlineTextBox> {};
+
 }  // namespace blink
 
 #endif  // LineBoxList_h
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_base_layout_algorithm_test.h b/third_party/WebKit/Source/core/layout/ng/ng_base_layout_algorithm_test.h
index 387ca5c..b6611a80 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_base_layout_algorithm_test.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_base_layout_algorithm_test.h
@@ -5,13 +5,12 @@
 #ifndef NG_BASE_LAYOUT_ALGORITHM_TEST_H_
 #define NG_BASE_LAYOUT_ALGORITHM_TEST_H_
 
-#include "core/layout/LayoutTestHelper.h"
-
 #include "core/layout/ng/geometry/ng_logical_size.h"
 #include "core/layout/ng/layout_ng_block_flow.h"
 #include "core/layout/ng/ng_constraint_space.h"
 #include "core/layout/ng/ng_layout_test.h"
 #include "core/layout/ng/ng_physical_box_fragment.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/text/TextDirection.h"
 #include "platform/text/WritingMode.h"
 #include "platform/wtf/Allocator.h"
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
index 1840fa6..958bc53 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
@@ -6,7 +6,6 @@
 
 #include "core/dom/NodeComputedStyle.h"
 #include "core/dom/TagCollection.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/ng/layout_ng_block_flow.h"
 #include "core/layout/ng/ng_base_layout_algorithm_test.h"
 #include "core/layout/ng/ng_block_break_token.h"
@@ -18,6 +17,7 @@
 #include "core/layout/ng/ng_physical_box_fragment.h"
 #include "core/layout/ng/ng_physical_fragment.h"
 #include "core/style/ComputedStyle.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_test.h b/third_party/WebKit/Source/core/layout/ng/ng_layout_test.h
index 65dd674..26d22cd 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_layout_test.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_test.h
@@ -6,7 +6,7 @@
 #define NGLayoutTest_h
 
 #include "core/frame/LocalFrameClient.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGForeignObjectTest.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGForeignObjectTest.cpp
index 1a6081a..66ade90 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGForeignObjectTest.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGForeignObjectTest.cpp
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "core/layout/LayoutGeometryMap.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.cpp
index 778b394..eb88832 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInline.cpp
@@ -107,7 +107,7 @@
     return;
 
   FloatRect text_bounding_box = text_root->StrokeBoundingBox();
-  for (InlineFlowBox* box = FirstLineBox(); box; box = box->NextLineBox()) {
+  for (InlineFlowBox* box : *LineBoxes()) {
     quads.push_back(LocalToAbsoluteQuad(
         FloatRect(text_bounding_box.X() + box->X().ToFloat(),
                   text_bounding_box.Y() + box->Y().ToFloat(),
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.cpp
index fc4cbba..c6cd85d 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.cpp
@@ -125,7 +125,7 @@
 
 FloatRect LayoutSVGInlineText::FloatLinesBoundingBox() const {
   FloatRect bounding_box;
-  for (InlineTextBox* box : InlineTextBoxesOf(*this))
+  for (InlineTextBox* box : TextBoxes())
     bounding_box.Unite(FloatRect(box->FrameRect()));
   return bounding_box;
 }
@@ -177,7 +177,7 @@
   const SVGTextFragment* closest_distance_fragment = nullptr;
   SVGInlineTextBox* closest_distance_box = nullptr;
 
-  for (InlineTextBox* box : InlineTextBoxesOf(*this)) {
+  for (InlineTextBox* box : TextBoxes()) {
     if (!box->IsSVGInlineTextBox())
       continue;
 
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGRootTest.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGRootTest.cpp
index 74ce4c18..e337730 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGRootTest.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGRootTest.cpp
@@ -4,9 +4,9 @@
 
 #include "core/layout/svg/LayoutSVGRoot.h"
 
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/svg/LayoutSVGShape.h"
 #include "core/layout/svg/SVGLayoutSupport.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp b/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp
index b0d663d..53ba25e 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp
@@ -501,8 +501,7 @@
 static inline void WriteSVGInlineTextBoxes(TextStream& ts,
                                            const LayoutText& text,
                                            int indent) {
-  for (InlineTextBox* box = text.FirstTextBox(); box;
-       box = box->NextTextBox()) {
+  for (InlineTextBox* box : text.TextBoxes()) {
     if (!box->IsSVGInlineTextBox())
       continue;
 
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp b/third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp
index 70ebab0..ede8988 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp
@@ -138,7 +138,7 @@
     Vector<SVGInlineTextBox*>& text_boxes) {
   text_boxes.Shrink(0);
   for (InlineTextBox* text_box = text_line_layout.FirstTextBox(); text_box;
-       text_box = text_box->NextTextBox())
+       text_box = text_box->NextForSameLayoutObject())
     text_boxes.push_back(ToSVGInlineTextBox(text_box));
   std::sort(text_boxes.begin(), text_boxes.end(),
             InlineTextBox::CompareByStart);
diff --git a/third_party/WebKit/Source/core/layout/svg/line/SVGInlineTextBox.cpp b/third_party/WebKit/Source/core/layout/svg/line/SVGInlineTextBox.cpp
index de209c95..dc4fdb86 100644
--- a/third_party/WebKit/Source/core/layout/svg/line/SVGInlineTextBox.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/line/SVGInlineTextBox.cpp
@@ -52,7 +52,7 @@
 
   // And clear any following text fragments as the text on which they depend may
   // now no longer exist, or glyph positions may be wrong.
-  InlineTextBox* next_box = NextTextBox();
+  InlineTextBox* next_box = NextForSameLayoutObject();
   if (next_box)
     next_box->DirtyLineBoxes();
 }
diff --git a/third_party/WebKit/Source/core/loader/EmptyClients.cpp b/third_party/WebKit/Source/core/loader/EmptyClients.cpp
index 734b431..1544926 100644
--- a/third_party/WebKit/Source/core/loader/EmptyClients.cpp
+++ b/third_party/WebKit/Source/core/loader/EmptyClients.cpp
@@ -59,46 +59,6 @@
   void DisconnectClient() override {}
 };
 
-class EmptyFrameScheduler : public WebFrameScheduler {
- public:
-  EmptyFrameScheduler() { DCHECK(IsMainThread()); }
-
-  scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
-      TaskType type) override {
-    return Platform::Current()->MainThread()->GetTaskRunner();
-  }
-
-  std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
-      ObserverType,
-      Observer*) override {
-    return nullptr;
-  }
-  void SetFrameVisible(bool) override {}
-  bool IsFrameVisible() const override { return false; }
-  bool IsPageVisible() const override { return false; }
-  void SetPaused(bool) override {}
-  void SetCrossOrigin(bool) override {}
-  bool IsCrossOrigin() const override { return false; }
-  void TraceUrlChange(const String&) override {}
-  WebFrameScheduler::FrameType GetFrameType() const override {
-    return WebFrameScheduler::FrameType::kSubframe;
-  }
-  PageScheduler* GetPageScheduler() const override { return nullptr; }
-  WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser(
-      WebScopedVirtualTimePauser::VirtualTaskDuration) {
-    return WebScopedVirtualTimePauser();
-  }
-  void DidStartProvisionalLoad(bool is_main_frame) override {}
-  void DidCommitProvisionalLoad(bool is_web_history_inert_commit,
-                                bool is_reload,
-                                bool is_main_frame) override {}
-  void OnFirstMeaningfulPaint() override {}
-  std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override {
-    return nullptr;
-  }
-  bool IsExemptFromBudgetBasedThrottling() const override { return false; }
-};
-
 PopupMenu* EmptyChromeClient::OpenPopupMenu(LocalFrame&, HTMLSelectElement&) {
   return new EmptyPopupMenu();
 }
@@ -132,12 +92,6 @@
   return String();
 }
 
-std::unique_ptr<WebFrameScheduler> EmptyChromeClient::CreateFrameScheduler(
-    BlameContext* blame_context,
-    WebFrameScheduler::FrameType frame_type) {
-  return std::make_unique<EmptyFrameScheduler>();
-}
-
 NavigationPolicy EmptyLocalFrameClient::DecidePolicyForNavigation(
     const ResourceRequest&,
     Document* origin_document,
diff --git a/third_party/WebKit/Source/core/loader/EmptyClients.h b/third_party/WebKit/Source/core/loader/EmptyClients.h
index 81e48df..b2e26a7 100644
--- a/third_party/WebKit/Source/core/loader/EmptyClients.h
+++ b/third_party/WebKit/Source/core/loader/EmptyClients.h
@@ -39,7 +39,6 @@
 #include "core/page/ChromeClient.h"
 #include "core/page/Page.h"
 #include "platform/DragImage.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/exported/WrappedResourceRequest.h"
 #include "platform/geometry/FloatPoint.h"
 #include "platform/geometry/FloatRect.h"
@@ -221,10 +220,6 @@
   void SetCursorForPlugin(const WebCursorInfo&, LocalFrame*) override {}
 
   void InstallSupplements(LocalFrame&) override {}
-
-  std::unique_ptr<WebFrameScheduler> CreateFrameScheduler(
-      BlameContext*,
-      WebFrameScheduler::FrameType) override;
 };
 
 class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
diff --git a/third_party/WebKit/Source/core/page/ChromeClient.h b/third_party/WebKit/Source/core/page/ChromeClient.h
index a0a9686..6d072df 100644
--- a/third_party/WebKit/Source/core/page/ChromeClient.h
+++ b/third_party/WebKit/Source/core/page/ChromeClient.h
@@ -36,7 +36,6 @@
 #include "core/style/ComputedStyleConstants.h"
 #include "platform/Cursor.h"
 #include "platform/PlatformChromeClient.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/graphics/TouchAction.h"
 #include "platform/heap/Handle.h"
 #include "platform/scroll/ScrollTypes.h"
@@ -335,10 +334,6 @@
 
   virtual FloatSize ElasticOverscroll() const { return FloatSize(); }
 
-  virtual std::unique_ptr<WebFrameScheduler> CreateFrameScheduler(
-      BlameContext*,
-      WebFrameScheduler::FrameType) = 0;
-
   virtual void InstallSupplements(LocalFrame&);
 
   virtual WebLayerTreeView* GetWebLayerTreeView(LocalFrame*) { return nullptr; }
diff --git a/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp b/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp
index d6ba0aa..5c989e4 100644
--- a/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp
+++ b/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp
@@ -82,7 +82,6 @@
 #include "platform/graphics/GraphicsLayer.h"
 #include "platform/graphics/TouchAction.h"
 #include "platform/runtime_enabled_features.h"
-#include "platform/scheduler/renderer/page_scheduler.h"
 #include "platform/weborigin/SecurityOrigin.h"
 #include "platform/wtf/Optional.h"
 #include "platform/wtf/text/CString.h"
@@ -1107,13 +1106,6 @@
   return web_view_->ElasticOverscroll();
 }
 
-std::unique_ptr<WebFrameScheduler> ChromeClientImpl::CreateFrameScheduler(
-    BlameContext* blame_context,
-    WebFrameScheduler::FrameType frame_type) {
-  return web_view_->Scheduler()->CreateFrameScheduler(blame_context,
-                                                      frame_type);
-}
-
 WebAutofillClient* ChromeClientImpl::AutofillClientFromFrame(
     LocalFrame* frame) {
   if (!frame) {
diff --git a/third_party/WebKit/Source/core/page/ChromeClientImpl.h b/third_party/WebKit/Source/core/page/ChromeClientImpl.h
index ccafeb4e..74ae635 100644
--- a/third_party/WebKit/Source/core/page/ChromeClientImpl.h
+++ b/third_party/WebKit/Source/core/page/ChromeClientImpl.h
@@ -219,10 +219,6 @@
 
   FloatSize ElasticOverscroll() const override;
 
-  std::unique_ptr<WebFrameScheduler> CreateFrameScheduler(
-      BlameContext*,
-      WebFrameScheduler::FrameType) override;
-
   void RegisterPopupOpeningObserver(PopupOpeningObserver*) override;
   void UnregisterPopupOpeningObserver(PopupOpeningObserver*) override;
   void NotifyPopupOpeningObservers() const override;
diff --git a/third_party/WebKit/Source/core/page/DragControllerTest.cpp b/third_party/WebKit/Source/core/page/DragControllerTest.cpp
index 6691be9..3fedc81 100644
--- a/third_party/WebKit/Source/core/page/DragControllerTest.cpp
+++ b/third_party/WebKit/Source/core/page/DragControllerTest.cpp
@@ -11,11 +11,11 @@
 #include "core/frame/LocalFrame.h"
 #include "core/frame/LocalFrameView.h"
 #include "core/frame/VisualViewport.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/page/AutoscrollController.h"
 #include "core/page/DragData.h"
 #include "core/page/DragSession.h"
 #include "core/page/DragState.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "core/testing/sim/SimRequest.h"
 #include "core/testing/sim/SimTest.h"
 #include "platform/DragImage.h"
diff --git a/third_party/WebKit/Source/core/page/PrintContextTest.cpp b/third_party/WebKit/Source/core/page/PrintContextTest.cpp
index fe02e02..2b15753f 100644
--- a/third_party/WebKit/Source/core/page/PrintContextTest.cpp
+++ b/third_party/WebKit/Source/core/page/PrintContextTest.cpp
@@ -9,10 +9,10 @@
 #include "core/dom/Document.h"
 #include "core/frame/LocalFrameView.h"
 #include "core/html/HTMLElement.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutView.h"
 #include "core/paint/PaintLayer.h"
 #include "core/paint/PaintLayerPainter.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "core/testing/DummyPageHolder.h"
 #include "platform/graphics/GraphicsContext.h"
 #include "platform/graphics/paint/DrawingRecorder.h"
diff --git a/third_party/WebKit/Source/core/page/SpatialNavigationTest.cpp b/third_party/WebKit/Source/core/page/SpatialNavigationTest.cpp
index db4f673..0306d48 100644
--- a/third_party/WebKit/Source/core/page/SpatialNavigationTest.cpp
+++ b/third_party/WebKit/Source/core/page/SpatialNavigationTest.cpp
@@ -4,7 +4,7 @@
 
 #include "core/page/SpatialNavigation.h"
 
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/paint/BoxModelObjectPainter.cpp b/third_party/WebKit/Source/core/paint/BoxModelObjectPainter.cpp
index e37115f..9819137 100644
--- a/third_party/WebKit/Source/core/paint/BoxModelObjectPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxModelObjectPainter.cpp
@@ -33,12 +33,12 @@
   // unbroken continuous strip (c.f box-decoration-break: slice.)
   LayoutUnit logical_offset_on_line;
   if (flow_box.IsLeftToRightDirection()) {
-    for (const InlineFlowBox* curr = flow_box.PrevLineBox(); curr;
-         curr = curr->PrevLineBox())
+    for (const InlineFlowBox* curr = flow_box.PrevForSameLayoutObject(); curr;
+         curr = curr->PrevForSameLayoutObject())
       logical_offset_on_line += curr->LogicalWidth();
   } else {
-    for (const InlineFlowBox* curr = flow_box.NextLineBox(); curr;
-         curr = curr->NextLineBox())
+    for (const InlineFlowBox* curr = flow_box.NextForSameLayoutObject(); curr;
+         curr = curr->NextForSameLayoutObject())
       logical_offset_on_line += curr->LogicalWidth();
   }
   LayoutSize logical_offset(logical_offset_on_line, LayoutUnit());
@@ -102,7 +102,8 @@
     bool include_logical_right_edge) const {
   FloatRoundedRect border = BoxPainterBase::GetBackgroundRoundedRect(
       border_rect, include_logical_left_edge, include_logical_right_edge);
-  if (flow_box_ && (flow_box_->NextLineBox() || flow_box_->PrevLineBox())) {
+  if (flow_box_ && (flow_box_->NextForSameLayoutObject() ||
+                    flow_box_->PrevForSameLayoutObject())) {
     FloatRoundedRect segment_border = box_model_.StyleRef().GetRoundedBorderFor(
         LayoutRect(LayoutPoint(), LayoutSize(FlooredIntSize(flow_box_size_))),
         include_logical_left_edge, include_logical_right_edge);
diff --git a/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp b/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp
index a263961..89eb5cb 100644
--- a/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp
@@ -7,11 +7,11 @@
 #include "core/frame/LocalFrameView.h"
 #include "core/html/HTMLFrameOwnerElement.h"
 #include "core/html_names.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutView.h"
 #include "core/paint/PaintControllerPaintTest.h"
 #include "core/paint/PaintInvalidator.h"
 #include "core/paint/PaintLayer.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/graphics/GraphicsLayer.h"
 #include "platform/graphics/paint/RasterInvalidationTracking.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
diff --git a/third_party/WebKit/Source/core/paint/CSSMaskPainterTest.cpp b/third_party/WebKit/Source/core/paint/CSSMaskPainterTest.cpp
index 8c85461..ab46198 100644
--- a/third_party/WebKit/Source/core/paint/CSSMaskPainterTest.cpp
+++ b/third_party/WebKit/Source/core/paint/CSSMaskPainterTest.cpp
@@ -5,7 +5,7 @@
 #include "core/paint/CSSMaskPainter.h"
 
 #include <gtest/gtest.h>
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 
 namespace blink {
 namespace {
diff --git a/third_party/WebKit/Source/core/paint/ClipPathClipperTest.cpp b/third_party/WebKit/Source/core/paint/ClipPathClipperTest.cpp
index 6d72ef8..7d80a40 100644
--- a/third_party/WebKit/Source/core/paint/ClipPathClipperTest.cpp
+++ b/third_party/WebKit/Source/core/paint/ClipPathClipperTest.cpp
@@ -5,7 +5,7 @@
 #include "core/paint/ClipPathClipper.h"
 
 #include <gtest/gtest.h>
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 
 namespace blink {
 namespace {
diff --git a/third_party/WebKit/Source/core/paint/InlineFlowBoxPainter.cpp b/third_party/WebKit/Source/core/paint/InlineFlowBoxPainter.cpp
index 9aec87f..c42d4cb 100644
--- a/third_party/WebKit/Source/core/paint/InlineFlowBoxPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/InlineFlowBoxPainter.cpp
@@ -78,7 +78,8 @@
                                           rect.Size());
   if ((!has_fill_image &&
        !inline_flow_box_.GetLineLayoutItem().Style()->HasBorderRadius()) ||
-      (!inline_flow_box_.PrevLineBox() && !inline_flow_box_.NextLineBox()) ||
+      (!inline_flow_box_.PrevForSameLayoutObject() &&
+       !inline_flow_box_.NextForSameLayoutObject()) ||
       !inline_flow_box_.Parent()) {
     box_model_painter.PaintFillLayer(paint_info, c, fill_layer, rect,
                                      kBackgroundBleedNone, geometry, op);
@@ -106,7 +107,8 @@
 }
 
 inline bool InlineFlowBoxPainter::ShouldForceIncludeLogicalEdges() const {
-  return (!inline_flow_box_.PrevLineBox() && !inline_flow_box_.NextLineBox()) ||
+  return (!inline_flow_box_.PrevForSameLayoutObject() &&
+          !inline_flow_box_.NextForSameLayoutObject()) ||
          !inline_flow_box_.Parent();
 }
 
@@ -178,20 +180,20 @@
   LayoutUnit logical_offset_on_line;
   LayoutUnit total_logical_width;
   if (direction == TextDirection::kLtr) {
-    for (const InlineFlowBox* curr = inline_flow_box_.PrevLineBox(); curr;
-         curr = curr->PrevLineBox())
+    for (const InlineFlowBox* curr = inline_flow_box_.PrevForSameLayoutObject();
+         curr; curr = curr->PrevForSameLayoutObject())
       logical_offset_on_line += curr->LogicalWidth();
     total_logical_width = logical_offset_on_line;
     for (const InlineFlowBox* curr = &inline_flow_box_; curr;
-         curr = curr->NextLineBox())
+         curr = curr->NextForSameLayoutObject())
       total_logical_width += curr->LogicalWidth();
   } else {
-    for (const InlineFlowBox* curr = inline_flow_box_.NextLineBox(); curr;
-         curr = curr->NextLineBox())
+    for (const InlineFlowBox* curr = inline_flow_box_.NextForSameLayoutObject();
+         curr; curr = curr->NextForSameLayoutObject())
       logical_offset_on_line += curr->LogicalWidth();
     total_logical_width = logical_offset_on_line;
     for (const InlineFlowBox* curr = &inline_flow_box_; curr;
-         curr = curr->PrevLineBox())
+         curr = curr->PrevForSameLayoutObject())
       total_logical_width += curr->LogicalWidth();
   }
   LayoutUnit strip_x =
@@ -225,8 +227,8 @@
     // The simple case is where we either have no border image or we are the
     // only box for this object.  In those cases only a single call to draw is
     // required.
-    if (!has_border_image ||
-        (!inline_flow_box_.PrevLineBox() && !inline_flow_box_.NextLineBox()))
+    if (!has_border_image || (!inline_flow_box_.PrevForSameLayoutObject() &&
+                              !inline_flow_box_.NextForSameLayoutObject()))
       return kPaintBordersWithoutClip;
 
     // We have a border image that spans multiple lines.
@@ -383,7 +385,8 @@
 
   // The simple case is where we are the only box for this object. In those
   // cases only a single call to draw is required.
-  if (!inline_flow_box_.PrevLineBox() && !inline_flow_box_.NextLineBox()) {
+  if (!inline_flow_box_.PrevForSameLayoutObject() &&
+      !inline_flow_box_.NextForSameLayoutObject()) {
     NinePieceImagePainter::Paint(paint_info.context, box_model,
                                  box_model.GetDocument(), GetNode(&box_model),
                                  paint_rect, box_model.StyleRef(),
diff --git a/third_party/WebKit/Source/core/paint/LineBoxListPainter.cpp b/third_party/WebKit/Source/core/paint/LineBoxListPainter.cpp
index 17748394..3cb97bd 100644
--- a/third_party/WebKit/Source/core/paint/LineBoxListPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/LineBoxListPainter.cpp
@@ -52,7 +52,7 @@
                                                paint_offset);
 
   // If we have no lines then we have no work to do.
-  if (!line_box_list_.FirstLineBox())
+  if (!line_box_list_.First())
     return;
 
   if (!line_box_list_.AnyLineIntersectsRect(
@@ -63,8 +63,7 @@
   // See if our root lines intersect with the dirty rect. If so, then we paint
   // them. Note that boxes can easily overlap, so we can't make any assumptions
   // based off positions of our first line box or our last line box.
-  for (InlineFlowBox* curr = line_box_list_.FirstLineBox(); curr;
-       curr = curr->NextLineBox()) {
+  for (InlineFlowBox* curr : line_box_list_) {
     if (line_box_list_.LineIntersectsDirtyRect(
             LineLayoutBoxModel(
                 const_cast<LayoutBoxModelObject*>(&layout_object)),
diff --git a/third_party/WebKit/Source/core/paint/NinePieceImageGridTest.cpp b/third_party/WebKit/Source/core/paint/NinePieceImageGridTest.cpp
index a1dfec5..69b03c5 100644
--- a/third_party/WebKit/Source/core/paint/NinePieceImageGridTest.cpp
+++ b/third_party/WebKit/Source/core/paint/NinePieceImageGridTest.cpp
@@ -5,9 +5,9 @@
 #include "core/paint/NinePieceImageGrid.h"
 
 #include "core/css/CSSGradientValue.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/style/NinePieceImage.h"
 #include "core/style/StyleGeneratedImage.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/paint/ObjectPaintInvalidatorTest.cpp b/third_party/WebKit/Source/core/paint/ObjectPaintInvalidatorTest.cpp
index 5c95bfc4..4feff81 100644
--- a/third_party/WebKit/Source/core/paint/ObjectPaintInvalidatorTest.cpp
+++ b/third_party/WebKit/Source/core/paint/ObjectPaintInvalidatorTest.cpp
@@ -6,8 +6,8 @@
 
 #include "core/editing/FrameSelection.h"
 #include "core/layout/LayoutObject.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/paint/PaintLayer.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/graphics/GraphicsLayer.h"
 #include "platform/json/JSONValues.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp
index 07868ab3..770918b 100644
--- a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp
@@ -78,7 +78,8 @@
 
   LayoutText& new_text = *ToLayoutText(div_block.FirstChild());
   InlineTextBox& new_first_text_box = *new_text.FirstTextBox();
-  InlineTextBox& second_text_box = *new_text.FirstTextBox()->NextTextBox();
+  InlineTextBox& second_text_box =
+      *new_text.FirstTextBox()->NextForSameLayoutObject();
 
   EXPECT_DISPLAY_LIST(
       RootPaintController().GetDisplayItemList(), 3,
diff --git a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h
index 01a3367..eb1819c1 100644
--- a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h
+++ b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h
@@ -7,9 +7,9 @@
 
 #include "core/editing/FrameSelection.h"
 #include "core/frame/LocalFrameView.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutView.h"
 #include "core/paint/PaintLayer.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/graphics/GraphicsContext.h"
 #include "platform/graphics/GraphicsLayer.h"
 #include "platform/graphics/paint/CullRect.h"
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidationTest.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidationTest.cpp
index 2d381d0..561de04 100644
--- a/third_party/WebKit/Source/core/paint/PaintInvalidationTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintInvalidationTest.cpp
@@ -3,9 +3,9 @@
 // found in the LICENSE file.
 
 #include "core/frame/LocalFrameView.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutView.h"
 #include "core/paint/PaintLayer.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/graphics/GraphicsLayer.h"
 #include "platform/graphics/compositing/PaintArtifactCompositor.h"
 #include "platform/graphics/paint/RasterInvalidationTracking.h"
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp
index a07fa96..2191f40 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp
@@ -6,9 +6,9 @@
 
 #include "build/build_config.h"
 #include "core/layout/LayoutBoxModelObject.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutView.h"
 #include "core/paint/PaintLayer.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/LayoutTestSupport.h"
 #include "platform/testing/UnitTestHelpers.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index 5fa4e46..1a5d3e00 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -76,6 +76,7 @@
 #include "core/page/scrolling/RootScrollerController.h"
 #include "core/page/scrolling/RootScrollerUtil.h"
 #include "core/page/scrolling/ScrollingCoordinator.h"
+#include "core/page/scrolling/SnapCoordinator.h"
 #include "core/page/scrolling/TopDocumentRootScrollerController.h"
 #include "core/paint/PaintLayerFragment.h"
 #include "core/paint/compositing/CompositedLayerMapping.h"
@@ -1613,6 +1614,17 @@
   return HorizontalScrollbar()->ScrollbarThickness();
 }
 
+void PaintLayerScrollableArea::SnapAfterScrollbarDragging(
+    ScrollbarOrientation orientation) {
+  SnapCoordinator* snap_coordinator =
+      GetLayoutBox()->GetDocument().GetSnapCoordinator();
+  if (!snap_coordinator)
+    return;
+  snap_coordinator->PerformSnapping(*GetLayoutBox(),
+                                    orientation == kHorizontalScrollbar,
+                                    orientation == kVerticalScrollbar);
+}
+
 void PaintLayerScrollableArea::PositionOverflowControls() {
   if (!HasScrollbar() && !GetLayoutBox()->CanResize())
     return;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
index 4b1b920..6fb460c5 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
@@ -537,6 +537,8 @@
   bool SetHasHorizontalScrollbar(bool has_scrollbar);
   bool SetHasVerticalScrollbar(bool has_scrollbar);
 
+  void SnapAfterScrollbarDragging(ScrollbarOrientation) override;
+
   void UpdateScrollCornerStyle();
   LayoutSize MinimumSizeForResizing(float zoom_factor);
   LayoutRect LayoutContentRect(IncludeScrollbarsInRect) const;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
index 615e4346..81ff9e4 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
@@ -6,8 +6,8 @@
 
 #include "core/frame/LocalFrameView.h"
 #include "core/layout/LayoutBoxModelObject.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/paint/PaintLayer.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/graphics/GraphicsLayer.h"
 #include "platform/scroll/ScrollTypes.h"
 #include "platform/scroll/ScrollbarTheme.h"
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
index 6206cde..a5dcc51 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
@@ -6,8 +6,8 @@
 
 #include "core/html/HTMLIFrameElement.h"
 #include "core/layout/LayoutBoxModelObject.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutView.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/PaintTestConfigurations.h"
 #include "platform/testing/UnitTestHelpers.h"
 
diff --git a/third_party/WebKit/Source/core/paint/PrePaintTreeWalkTest.cpp b/third_party/WebKit/Source/core/paint/PrePaintTreeWalkTest.cpp
index 5d90695..c811e1f 100644
--- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalkTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalkTest.cpp
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutTreeAsText.h"
 #include "core/layout/LayoutView.h"
 #include "core/paint/ObjectPaintProperties.h"
@@ -10,6 +9,7 @@
 #include "core/paint/PaintLayer.h"
 #include "core/paint/PaintPropertyTreePrinter.h"
 #include "core/paint/PrePaintTreeWalk.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/graphics/paint/GeometryMapper.h"
 #include "platform/graphics/paint/ScrollPaintPropertyNode.h"
 #include "platform/graphics/paint/TransformPaintPropertyNode.h"
diff --git a/third_party/WebKit/Source/core/paint/TextPainterTest.cpp b/third_party/WebKit/Source/core/paint/TextPainterTest.cpp
index 826153b..a87f45c1f7 100644
--- a/third_party/WebKit/Source/core/paint/TextPainterTest.cpp
+++ b/third_party/WebKit/Source/core/paint/TextPainterTest.cpp
@@ -9,11 +9,11 @@
 #include "core/css_property_names.h"
 #include "core/css_value_keywords.h"
 #include "core/frame/Settings.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/api/LineLayoutText.h"
 #include "core/paint/PaintInfo.h"
 #include "core/style/ShadowData.h"
 #include "core/style/ShadowList.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/graphics/paint/PaintController.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMappingTest.cpp b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMappingTest.cpp
index 38a3b41..78b8049 100644
--- a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMappingTest.cpp
+++ b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMappingTest.cpp
@@ -6,9 +6,9 @@
 
 #include "core/frame/LocalFrameView.h"
 #include "core/layout/LayoutBoxModelObject.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutView.h"
 #include "core/paint/PaintLayer.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "public/platform/WebContentLayer.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositingInputsUpdaterTest.cpp b/third_party/WebKit/Source/core/paint/compositing/CompositingInputsUpdaterTest.cpp
index f368c306..facea704 100644
--- a/third_party/WebKit/Source/core/paint/compositing/CompositingInputsUpdaterTest.cpp
+++ b/third_party/WebKit/Source/core/paint/compositing/CompositingInputsUpdaterTest.cpp
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "core/layout/LayoutTestHelper.h"
 #include "core/paint/PaintLayer.h"
 #include "core/paint/compositing/CompositingInputsUpdater.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositingLayerAssignerTest.cpp b/third_party/WebKit/Source/core/paint/compositing/CompositingLayerAssignerTest.cpp
index 58e058c..457c4ba4 100644
--- a/third_party/WebKit/Source/core/paint/compositing/CompositingLayerAssignerTest.cpp
+++ b/third_party/WebKit/Source/core/paint/compositing/CompositingLayerAssignerTest.cpp
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "core/layout/LayoutTestHelper.h"
 #include "core/paint/PaintLayer.h"
 #include "core/paint/compositing/CompositedLayerMapping.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/graphics/GraphicsLayer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositingReasonFinderTest.cpp b/third_party/WebKit/Source/core/paint/compositing/CompositingReasonFinderTest.cpp
index 0054aaa..f4b1c838 100644
--- a/third_party/WebKit/Source/core/paint/compositing/CompositingReasonFinderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/compositing/CompositingReasonFinderTest.cpp
@@ -6,8 +6,8 @@
 
 #include "core/frame/LocalFrameView.h"
 #include "core/layout/LayoutBlock.h"
-#include "core/layout/LayoutTestHelper.h"
 #include "core/paint/PaintLayer.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/graphics/GraphicsLayer.h"
 #include "platform/scroll/ScrollTypes.h"
 #include "platform/testing/TestingPlatformSupport.h"
diff --git a/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositorTest.cpp b/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositorTest.cpp
index 25da82e..fdf26a9 100644
--- a/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositorTest.cpp
+++ b/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositorTest.cpp
@@ -6,7 +6,7 @@
 
 #include "core/animation/Animation.h"
 #include "core/animation/ElementAnimation.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "core/paint/PaintLayer.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/paint/ng/ng_paint_fragment_test.cc b/third_party/WebKit/Source/core/paint/ng/ng_paint_fragment_test.cc
index ec6e76dc..24a54ac 100644
--- a/third_party/WebKit/Source/core/paint/ng/ng_paint_fragment_test.cc
+++ b/third_party/WebKit/Source/core/paint/ng/ng_paint_fragment_test.cc
@@ -4,10 +4,10 @@
 
 #include "core/paint/ng/ng_paint_fragment.h"
 
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/ng/inline/ng_physical_line_box_fragment.h"
 #include "core/layout/ng/inline/ng_physical_text_fragment.h"
 #include "core/layout/ng/layout_ng_block_flow.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/paint/ng/ng_text_fragment_painter_test.cc b/third_party/WebKit/Source/core/paint/ng/ng_text_fragment_painter_test.cc
index 5deab30..3f5d406 100644
--- a/third_party/WebKit/Source/core/paint/ng/ng_text_fragment_painter_test.cc
+++ b/third_party/WebKit/Source/core/paint/ng/ng_text_fragment_painter_test.cc
@@ -4,7 +4,6 @@
 
 #include "core/paint/ng/ng_text_fragment_painter.h"
 
-#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/ng/inline/ng_physical_line_box_fragment.h"
 #include "core/layout/ng/inline/ng_physical_text_fragment.h"
 #include "core/layout/ng/layout_ng_block_flow.h"
@@ -13,6 +12,7 @@
 #include "core/paint/PaintInfo.h"
 #include "core/paint/PaintLayerPainter.h"
 #include "core/style/ComputedStyle.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/graphics/GraphicsContext.h"
 #include "platform/graphics/paint/PaintController.h"
 #include "platform/runtime_enabled_features.h"
diff --git a/third_party/WebKit/Source/core/layout/LayoutTestHelper.cpp b/third_party/WebKit/Source/core/testing/CoreUnitTestHelper.cpp
similarity index 97%
rename from third_party/WebKit/Source/core/layout/LayoutTestHelper.cpp
rename to third_party/WebKit/Source/core/testing/CoreUnitTestHelper.cpp
index 6e0cb39e..29b0087 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTestHelper.cpp
+++ b/third_party/WebKit/Source/core/testing/CoreUnitTestHelper.cpp
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 
 #include "bindings/core/v8/V8BindingForCore.h"
 #include "core/html/HTMLIFrameElement.h"
diff --git a/third_party/WebKit/Source/core/layout/LayoutTestHelper.h b/third_party/WebKit/Source/core/testing/CoreUnitTestHelper.h
similarity index 96%
rename from third_party/WebKit/Source/core/layout/LayoutTestHelper.h
rename to third_party/WebKit/Source/core/testing/CoreUnitTestHelper.h
index 176efd35..220a488f 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTestHelper.h
+++ b/third_party/WebKit/Source/core/testing/CoreUnitTestHelper.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef LayoutTestHelper_h
-#define LayoutTestHelper_h
+#ifndef CoreUnitTestHelper_h
+#define CoreUnitTestHelper_h
 
 #include <gtest/gtest.h>
 #include <memory>
@@ -111,4 +111,4 @@
 
 }  // namespace blink
 
-#endif  // LayoutTestHelper_h
+#endif  // CoreUnitTestHelper_h
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
index cb24db2..ff4c6557 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
@@ -103,19 +103,28 @@
   DCHECK(IsParentContextThread());
   was_script_evaluated_ = true;
 
+  Vector<QueuedTask> tasks;
+  queued_early_tasks_.swap(tasks);
+
+  // The worker thread can already be terminated.
+  if (!GetWorkerThread()) {
+    DCHECK(AskedToTerminate());
+    return;
+  }
+
   // Post all queued tasks to the worker.
-  for (auto& queued_task : queued_early_tasks_) {
-    WTF::CrossThreadClosure task = CrossThreadBind(
-        &DedicatedWorkerObjectProxy::ProcessMessageFromWorkerObject,
-        CrossThreadUnretained(&WorkerObjectProxy()),
-        WTF::Passed(std::move(queued_task.message)),
-        WTF::Passed(std::move(queued_task.channels)),
-        CrossThreadUnretained(GetWorkerThread()), queued_task.stack_id);
+  // TODO(nhiroki): Consider whether to post the queued tasks to the worker when
+  // |success| is false.
+  for (auto& task : tasks) {
     PostCrossThreadTask(
         *GetWorkerThread()->GetTaskRunner(TaskType::kPostedMessage), FROM_HERE,
-        std::move(task));
+        CrossThreadBind(
+            &DedicatedWorkerObjectProxy::ProcessMessageFromWorkerObject,
+            CrossThreadUnretained(&WorkerObjectProxy()),
+            WTF::Passed(std::move(task.message)),
+            WTF::Passed(std::move(task.channels)),
+            CrossThreadUnretained(GetWorkerThread()), task.stack_id));
   }
-  queued_early_tasks_.clear();
 }
 
 void DedicatedWorkerMessagingProxy::PostMessageToWorkerObject(
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleSidebar.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleSidebar.js
index 2fba6d56..8154fb9 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleSidebar.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleSidebar.js
@@ -133,7 +133,7 @@
    * @param {!Common.Setting} selectedFilterSetting
    */
   constructor(filter, icon, badgePool, selectedFilterSetting) {
-    super(filter.name, true /* expandable */);
+    super(filter.name);
     this._filter = filter;
     this._badgePool = badgePool;
     this._selectedFilterSetting = selectedFilterSetting;
@@ -173,6 +173,7 @@
     const pluralizedName = this._messageCount === 1 ? this._filter.name :
                                                       Console.ConsoleSidebar._groupPluralNameMap.get(this._filter.name);
     this.title = `${prefix} ${pluralizedName}`;
+    this.setExpandable(!!this.childCount());
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/console/consoleSidebar.css b/third_party/WebKit/Source/devtools/front_end/console/consoleSidebar.css
index 0cd387e..13ef25d 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/consoleSidebar.css
+++ b/third_party/WebKit/Source/devtools/front_end/console/consoleSidebar.css
@@ -46,3 +46,8 @@
     overflow: hidden;
     text-overflow: ellipsis;
 }
+
+.tree-outline li:hover:not(.selected) .selection {
+    display: block;
+    background-color: rgba(56, 121, 217, 0.1);
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js b/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js
index 4256f76..e710051 100644
--- a/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js
+++ b/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js
@@ -2616,26 +2616,20 @@
   }
 
   _markDetachedDOMTreeNodes() {
+    const nodes = this.nodes;
+    const nodesLength = nodes.length;
+    const nodeFieldCount = this._nodeFieldCount;
+    const nodeNativeType = this._nodeNativeType;
+    const nodeTypeOffset = this._nodeTypeOffset;
     const flag = this._nodeFlags.detachedDOMTreeNode;
-    let detachedDOMTreesRoot;
-    for (let iter = this.rootNode().edges(); iter.hasNext(); iter.next()) {
-      const node = iter.edge.node();
-      if (node.name() === '(Detached DOM trees)') {
-        detachedDOMTreesRoot = node;
-        break;
-      }
-    }
-
-    if (!detachedDOMTreesRoot)
-      return;
-
-    const detachedDOMTreeRE = /^Detached DOM tree/;
-    for (let iter = detachedDOMTreesRoot.edges(); iter.hasNext(); iter.next()) {
-      const node = iter.edge.node();
-      if (detachedDOMTreeRE.test(node.className())) {
-        for (let edgesIter = node.edges(); edgesIter.hasNext(); edgesIter.next())
-          this._flags[edgesIter.edge.node().nodeIndex / this._nodeFieldCount] |= flag;
-      }
+    const node = this.rootNode();
+    for (let nodeIndex = 0, ordinal = 0; nodeIndex < nodesLength; nodeIndex += nodeFieldCount, ordinal++) {
+      const nodeType = nodes[nodeIndex + nodeTypeOffset];
+      if (nodeType !== nodeNativeType)
+        continue;
+      node.nodeIndex = nodeIndex;
+      if (node.name().startsWith('Detached '))
+        this._flags[ordinal] |= flag;
     }
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotGridNodes.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotGridNodes.js
index c2e0d78..6e454a5 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotGridNodes.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotGridNodes.js
@@ -549,7 +549,7 @@
         value = (value || '') + '[]';
         break;
     }
-    if (this._reachableFromWindow)
+    if (this._reachableFromWindow && !this.detachedDOMTreeNode)
       valueStyle += ' highlight';
     if (value === 'Object')
       value = '';
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CPUProfileDataModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CPUProfileDataModel.js
index 32672610..95f87ae0 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/CPUProfileDataModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/CPUProfileDataModel.js
@@ -58,6 +58,7 @@
       this._buildIdToNodeMap();
       this._sortSamples();
       this._normalizeTimestamps();
+      this._fixMissingSamples();
     }
   }
 
@@ -246,6 +247,53 @@
     }
   }
 
+  _fixMissingSamples() {
+    // Sometimes sampler is not able to parse the JS stack and returns
+    // a (program) sample instead. The issue leads to call frames belong
+    // to the same function invocation being split apart.
+    // Here's a workaround for that. When there's a single (program) sample
+    // between two call stacks sharing the same bottom node, it is replaced
+    // with the preceeding sample.
+    const samples = this.samples;
+    const samplesCount = samples.length;
+    if (!this.programNode || samplesCount < 3)
+      return;
+    const idToNode = this._idToNode;
+    const programNodeId = this.programNode.id;
+    const gcNodeId = this.gcNode ? this.gcNode.id : -1;
+    const idleNodeId = this.idleNode ? this.idleNode.id : -1;
+    let prevNodeId = samples[0];
+    let nodeId = samples[1];
+    let count = 0;
+    for (let sampleIndex = 1; sampleIndex < samplesCount - 1; sampleIndex++) {
+      const nextNodeId = samples[sampleIndex + 1];
+      if (nodeId === programNodeId && !isSystemNode(prevNodeId) && !isSystemNode(nextNodeId) &&
+          bottomNode(idToNode.get(prevNodeId)) === bottomNode(idToNode.get(nextNodeId))) {
+        ++count;
+        samples[sampleIndex] = prevNodeId;
+      }
+      prevNodeId = nodeId;
+      nodeId = nextNodeId;
+    }
+    Common.console.warn(ls`DevTools: CPU profile parser is fixing ${count} missing samples.`);
+    /**
+     * @param {!SDK.ProfileNode} node
+     * @return {!SDK.ProfileNode}
+     */
+    function bottomNode(node) {
+      while (node.parent && node.parent.parent)
+        node = node.parent;
+      return node;
+    }
+    /**
+     * @param {number} nodeId
+     * @return {boolean}
+     */
+    function isSystemNode(nodeId) {
+      return nodeId === programNodeId || nodeId === gcNodeId || nodeId === idleNodeId;
+    }
+  }
+
   /**
    * @param {function(number, !SDK.CPUProfileNode, number)} openFrameCallback
    * @param {function(number, !SDK.CPUProfileNode, number, number, number)} closeFrameCallback
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineJSProfile.js b/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineJSProfile.js
index aaacba6..d544dd7 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineJSProfile.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineJSProfile.js
@@ -69,6 +69,7 @@
         case TimelineModel.TimelineModel.RecordType.EvaluateScript:
         case TimelineModel.TimelineModel.RecordType.EvaluateModule:
         case TimelineModel.TimelineModel.RecordType.EventDispatch:
+        case TimelineModel.TimelineModel.RecordType.V8Execute:
           return true;
       }
       return false;
@@ -199,10 +200,8 @@
     }
 
     const firstTopLevelEvent = events.find(SDK.TracingModel.isTopLevelEvent);
-    if (firstTopLevelEvent) {
-      TimelineModel.TimelineModel.forEachEvent(
-          events, onStartEvent, onEndEvent, onInstantEvent, firstTopLevelEvent.startTime);
-    }
+    const startTime = firstTopLevelEvent ? firstTopLevelEvent.startTime : 0;
+    TimelineModel.TimelineModel.forEachEvent(events, onStartEvent, onEndEvent, onInstantEvent, startTime);
     return jsFrameEvents;
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineModel.js b/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineModel.js
index 244a0a7..70ce69b 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineModel.js
@@ -188,7 +188,7 @@
         const metaEvent = metadataEvents.page[i];
         const process = metaEvent.thread.process();
         const endTime = i + 1 < length ? metadataEvents.page[i + 1].startTime : Infinity;
-        this._currentPage = metaEvent.args['data'] && metaEvent.args['data']['page'];
+        this._legacyCurrentPage = metaEvent.args['data'] && metaEvent.args['data']['page'];
         for (const thread of process.sortedThreads()) {
           if (thread.name() === TimelineModel.TimelineModel.WorkerThreadName) {
             const workerMetaEvent = metadataEvents.workers.find(e => e.args['data']['workerThreadId'] === thread.id());
@@ -224,6 +224,8 @@
     for (const event of metadataEvents) {
       if (event.name === TimelineModel.TimelineModel.DevToolsMetadataEvent.TracingStartedInPage) {
         pageDevToolsMetadataEvents.push(event);
+        if (event.args['data'] && event.args['data']['persistentIds'])
+          this._persistentIds = true;
         const frames = ((event.args['data'] && event.args['data']['frames']) || []);
         frames.forEach(payload => this._addPageFrame(event, payload));
         const rootFrame = this.rootFrames()[0];
@@ -283,11 +285,12 @@
    */
   _makeMockPageMetadataEvent(tracingModel) {
     const rendererMainThreadName = TimelineModel.TimelineModel.RendererMainThreadName;
-    // FIXME: pick up the first renderer process for now.
-    const process = tracingModel.sortedProcesses().filter(function(p) {
-      return p.threadByName(rendererMainThreadName);
-    })[0];
-    const thread = process && process.threadByName(rendererMainThreadName);
+    // TODO(alph): Support selection of process and thread.
+    const processes = tracingModel.sortedProcesses();
+    const process = processes.find(p => !!p.threadByName(rendererMainThreadName)) || processes[0];
+    if (!process)
+      return null;
+    const thread = process.threadByName(rendererMainThreadName) || process.sortedThreads()[0];
     if (!thread)
       return null;
     const pageMetaEvent = new SDK.TracingModel.Event(
@@ -362,7 +365,8 @@
     this._firstCompositeLayers = null;
     /** @type {!Set<string>} */
     this._knownInputEvents = new Set();
-    this._currentPage = null;
+    this._persistentIds = false;
+    this._legacyCurrentPage = null;
   }
 
   /**
@@ -760,28 +764,36 @@
 
       case recordTypes.MarkDOMContent:
       case recordTypes.MarkLoad: {
-        const page = eventData['page'];
-        if (page && page !== this._currentPage)
+        const frameId = TimelineModel.TimelineModel.eventFrameId(event);
+        if (!this._pageFrames.get(frameId))
           return false;
         break;
       }
 
       case recordTypes.CommitLoad: {
         const frameId = TimelineModel.TimelineModel.eventFrameId(event);
+        const isMainFrame = !!eventData['isMainFrame'];
         const pageFrame = this._pageFrames.get(frameId);
-        if (pageFrame)
+        if (pageFrame) {
           pageFrame.update(eventData.name || '', eventData.url || '');
-        else
-          this._addPageFrame(event, eventData);
-        const page = eventData['page'];
-        if (page && page !== this._currentPage)
-          return false;
-        if (!eventData['isMainFrame'])
-          break;
-        if (eventData.url)
-          this._pageURL = eventData.url;
-        this._hadCommitLoad = true;
-        this._firstCompositeLayers = null;
+        } else {
+          // We should only have one main frame which has persistent id,
+          // unless it's an old trace without 'persistentIds' flag.
+          if (!this._persistentIds) {
+            if (eventData['page'] && eventData['page'] !== this._legacyCurrentPage)
+              return false;
+          } else if (isMainFrame) {
+            return false;
+          } else if (!this._addPageFrame(event, eventData)) {
+            return false;
+          }
+        }
+        if (isMainFrame) {
+          if (eventData.url)
+            this._pageURL = eventData.url;
+          this._hadCommitLoad = true;
+          this._firstCompositeLayers = null;
+        }
         break;
       }
 
@@ -875,14 +887,18 @@
   /**
    * @param {!SDK.TracingModel.Event} event
    * @param {!Object} payload
+   * @return {boolean}
    */
   _addPageFrame(event, payload) {
     const processId = event.thread.process().id();
+    const parent = payload['parent'] && this._pageFrames.get(`${processId}.${payload['parent']}`);
+    if (payload['parent'] && !parent)
+      return false;
     const pageFrame = new TimelineModel.TimelineModel.PageFrame(this.targetByEvent(event), processId, payload);
     this._pageFrames.set(pageFrame.id, pageFrame);
-    const parent = payload['parent'] && this._pageFrames.get(`${processId}.${payload['parent']}`);
     if (parent)
       parent.addChild(pageFrame);
+    return true;
   }
 
   _reset() {
@@ -1138,6 +1154,7 @@
   JitCodeAdded: 'JitCodeAdded',
   JitCodeMoved: 'JitCodeMoved',
   ParseScriptOnBackground: 'v8.parseOnBackground',
+  V8Execute: 'V8.Execute',
 
   UpdateCounters: 'UpdateCounters',
 
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ARIAUtils.js b/third_party/WebKit/Source/devtools/front_end/ui/ARIAUtils.js
index 0579e69..3d039a0 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/ARIAUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/ARIAUtils.js
@@ -62,6 +62,17 @@
 
 /**
  * @param {!Element} element
+ * @param {?string} placeholder
+ */
+UI.ARIAUtils.setPlaceholder = function(element, placeholder) {
+  if (placeholder)
+    element.setAttribute('aria-placeholder', placeholder);
+  else
+    element.removeAttribute('aria-placeholder');
+};
+
+/**
+ * @param {!Element} element
  */
 UI.ARIAUtils.markAsPresentation = function(element) {
   element.setAttribute('role', 'presentation');
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js b/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
index 8ba1818..55906f0 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
@@ -199,10 +199,13 @@
    * @param {string} placeholder
    */
   setPlaceholder(placeholder) {
-    if (placeholder)
+    if (placeholder) {
       this._element.setAttribute('data-placeholder', placeholder);
-    else
+      UI.ARIAUtils.setPlaceholder(this._element, placeholder);
+    } else {
       this._element.removeAttribute('data-placeholder');
+      UI.ARIAUtils.setPlaceholder(this._element, null);
+    }
   }
 
   /**
diff --git a/third_party/WebKit/Source/modules/DEPS b/third_party/WebKit/Source/modules/DEPS
index e0900010..ce3b693b 100644
--- a/third_party/WebKit/Source/modules/DEPS
+++ b/third_party/WebKit/Source/modules/DEPS
@@ -9,12 +9,7 @@
     "!core/frame/WebLocalFrameImpl.h",
     "!core/frame/WebRemoteFrameImpl.h",
     "+modules",
-    "+platform",
-    # We are moving from WTF_MAKE_NONCOPYABLE to DISALLOW_COPY_AND_ASSIGN. Stop
-    # new dependencies on WTF_MAKE_NONCOPYABLE.
-    "!platform/wtf/Noncopyable.h",
     "+public/common",
-    "+public/platform",
     "+public/web",
     "+services/service_manager/public/mojom/interface_provider.mojom-blink.h",
     "-web",
diff --git a/third_party/WebKit/Source/modules/accessibility/testing/AccessibilityTest.h b/third_party/WebKit/Source/modules/accessibility/testing/AccessibilityTest.h
index b7675a57..73b2753 100644
--- a/third_party/WebKit/Source/modules/accessibility/testing/AccessibilityTest.h
+++ b/third_party/WebKit/Source/modules/accessibility/testing/AccessibilityTest.h
@@ -9,7 +9,7 @@
 #include <sstream>
 #include <string>
 
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "platform/wtf/Allocator.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/modules/animationworklet/WorkletAnimationTest.cpp b/third_party/WebKit/Source/modules/animationworklet/WorkletAnimationTest.cpp
index 4546004..662cb212 100644
--- a/third_party/WebKit/Source/modules/animationworklet/WorkletAnimationTest.cpp
+++ b/third_party/WebKit/Source/modules/animationworklet/WorkletAnimationTest.cpp
@@ -9,7 +9,7 @@
 #include "core/animation/KeyframeEffect.h"
 #include "core/animation/KeyframeEffectModel.h"
 #include "core/dom/Document.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "core/testing/CoreUnitTestHelper.h"
 #include "core/testing/DummyPageHolder.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/third_party/WebKit/Source/modules/cachestorage/Cache.cpp b/third_party/WebKit/Source/modules/cachestorage/Cache.cpp
index 11642752..10ce253 100644
--- a/third_party/WebKit/Source/modules/cachestorage/Cache.cpp
+++ b/third_party/WebKit/Source/modules/cachestorage/Cache.cpp
@@ -15,6 +15,7 @@
 #include "bindings/core/v8/V8Response.h"
 #include "bindings/core/v8/V8ScriptRunner.h"
 #include "core/dom/DOMException.h"
+#include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/fetch/BodyStreamBuffer.h"
 #include "core/fetch/FetchDataLoader.h"
@@ -291,10 +292,7 @@
   void OnSuccess(size_t index,
                  const WebServiceWorkerCache::BatchOperation& batch_operation) {
     DCHECK_LT(index, batch_operations_.size());
-    if (completed_)
-      return;
-    if (!resolver_->GetExecutionContext() ||
-        resolver_->GetExecutionContext()->IsContextDestroyed())
+    if (!StillActive())
       return;
     batch_operations_[index] = batch_operation;
     if (--number_of_remaining_operations_ != 0)
@@ -307,16 +305,20 @@
   }
 
   void OnError(const String& error_message) {
-    if (completed_)
+    if (!StillActive())
       return;
     completed_ = true;
-    if (!resolver_->GetExecutionContext() ||
-        resolver_->GetExecutionContext()->IsContextDestroyed())
-      return;
     ScriptState* state = resolver_->GetScriptState();
-    ScriptState::Scope scope(state);
-    resolver_->Reject(
-        V8ThrowException::CreateTypeError(state->GetIsolate(), error_message));
+    RejectWithState(state, V8ThrowException::CreateTypeError(
+                               state->GetIsolate(), error_message));
+  }
+
+  void Abort() {
+    if (!StillActive())
+      return;
+    completed_ = true;
+    RejectWithState(resolver_->GetScriptState(),
+                    DOMException::Create(kAbortError));
   }
 
   virtual void Trace(blink::Visitor* visitor) {
@@ -325,6 +327,22 @@
   }
 
  private:
+  bool StillActive() {
+    if (completed_)
+      return false;
+    if (!resolver_->GetExecutionContext() ||
+        resolver_->GetExecutionContext()->IsContextDestroyed())
+      return false;
+
+    return true;
+  }
+
+  template <typename T>
+  void RejectWithState(ScriptState* state, T value) {
+    ScriptState::Scope scope(state);
+    resolver_->Reject(value);
+  }
+
   // Report the script stats if this cache storage is for service worker
   // execution context and it's in installation phase.
   void MaybeReportInstalledScripts() {
@@ -387,6 +405,8 @@
     barrier_callback_->OnError("network error");
   }
 
+  void Abort() override { barrier_callback_->Abort(); }
+
   void Trace(blink::Visitor* visitor) override {
     visitor->Trace(barrier_callback_);
     FetchDataLoader::Client::Trace(visitor);
@@ -467,6 +487,8 @@
     barrier_callback_->OnError("network error");
   }
 
+  void Abort() override { barrier_callback_->Abort(); }
+
   void Trace(blink::Visitor* visitor) override {
     visitor->Trace(barrier_callback_);
     FetchDataLoader::Client::Trace(visitor);
diff --git a/third_party/WebKit/Source/modules/serviceworkers/FetchRespondWithObserver.cpp b/third_party/WebKit/Source/modules/serviceworkers/FetchRespondWithObserver.cpp
index bbe19cf..cf1e694 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/FetchRespondWithObserver.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/FetchRespondWithObserver.cpp
@@ -128,6 +128,12 @@
 
   void DidFetchDataLoadedDataPipe() override { handle_->Completed(); }
   void DidFetchDataLoadFailed() override { handle_->Aborted(); }
+  void Abort() override {
+    // A fetch() aborted via AbortSignal in the ServiceWorker will just look
+    // like an ordinary failure to the page.
+    // TODO(ricea): Should a fetch() on the page get an AbortError instead?
+    handle_->Aborted();
+  }
 
   void Trace(blink::Visitor* visitor) override {
     FetchDataLoader::Client::Trace(visitor);
diff --git a/third_party/WebKit/Source/platform/DEPS b/third_party/WebKit/Source/platform/DEPS
index 8b6a947..456527a 100644
--- a/third_party/WebKit/Source/platform/DEPS
+++ b/third_party/WebKit/Source/platform/DEPS
@@ -46,8 +46,6 @@
     "+gpu/GLES2",
     "+mojo/public",
     "+mozilla",
-    "+platform",
-    "+public/platform",
     #TODO(nverne): remove this
     "+public/web/WebKit.h",
     "+services/metrics/public/cpp/ukm_entry_builder.h",
diff --git a/third_party/WebKit/Source/platform/audio/DirectConvolver.cpp b/third_party/WebKit/Source/platform/audio/DirectConvolver.cpp
index 5029d82b..180c39af 100644
--- a/third_party/WebKit/Source/platform/audio/DirectConvolver.cpp
+++ b/third_party/WebKit/Source/platform/audio/DirectConvolver.cpp
@@ -28,6 +28,8 @@
 
 #include "platform/audio/DirectConvolver.h"
 
+#include <utility>
+
 #include "build/build_config.h"
 #include "platform/audio/VectorMath.h"
 
@@ -41,13 +43,23 @@
 
 namespace blink {
 
-using namespace VectorMath;
+namespace {
+using VectorMath::Conv;
+using VectorMath::PrepareFilterForConv;
+}  // namespace
 
-DirectConvolver::DirectConvolver(size_t input_block_size)
-    : input_block_size_(input_block_size), buffer_(input_block_size * 2) {}
+DirectConvolver::DirectConvolver(
+    size_t input_block_size,
+    std::unique_ptr<AudioFloatArray> convolution_kernel)
+    : input_block_size_(input_block_size),
+      buffer_(input_block_size * 2),
+      convolution_kernel_(std::move(convolution_kernel)) {
+  size_t kernel_size = ConvolutionKernelSize();
+  PrepareFilterForConv(convolution_kernel_->Data() + kernel_size - 1, -1,
+                       kernel_size, &prepared_convolution_kernel_);
+}
 
-void DirectConvolver::Process(AudioFloatArray* convolution_kernel,
-                              const float* source_p,
+void DirectConvolver::Process(const float* source_p,
                               float* dest_p,
                               size_t frames_to_process) {
   DCHECK_EQ(frames_to_process, input_block_size_);
@@ -55,12 +67,12 @@
     return;
 
   // Only support kernelSize <= m_inputBlockSize
-  size_t kernel_size = convolution_kernel->size();
+  size_t kernel_size = ConvolutionKernelSize();
   DCHECK_LE(kernel_size, input_block_size_);
   if (kernel_size > input_block_size_)
     return;
 
-  float* kernel_p = convolution_kernel->Data();
+  float* kernel_p = convolution_kernel_->Data();
 
   // Sanity check
   bool is_copy_good = kernel_p && source_p && dest_p && buffer_.Data();
@@ -74,7 +86,7 @@
   memcpy(input_p, source_p, sizeof(float) * frames_to_process);
 
   Conv(input_p - kernel_size + 1, 1, kernel_p + kernel_size - 1, -1, dest_p, 1,
-       frames_to_process, kernel_size);
+       frames_to_process, kernel_size, &prepared_convolution_kernel_);
 
   // Copy 2nd half of input buffer to 1st half.
   memcpy(buffer_.Data(), input_p, sizeof(float) * frames_to_process);
diff --git a/third_party/WebKit/Source/platform/audio/DirectConvolver.h b/third_party/WebKit/Source/platform/audio/DirectConvolver.h
index e0ac898..b70bc1f 100644
--- a/third_party/WebKit/Source/platform/audio/DirectConvolver.h
+++ b/third_party/WebKit/Source/platform/audio/DirectConvolver.h
@@ -29,6 +29,8 @@
 #ifndef DirectConvolver_h
 #define DirectConvolver_h
 
+#include <memory>
+
 #include "platform/PlatformExport.h"
 #include "platform/audio/AudioArray.h"
 #include "platform/wtf/Allocator.h"
@@ -41,19 +43,21 @@
   WTF_MAKE_NONCOPYABLE(DirectConvolver);
 
  public:
-  DirectConvolver(size_t input_block_size);
+  DirectConvolver(size_t input_block_size,
+                  std::unique_ptr<AudioFloatArray> convolution_kernel);
 
-  void Process(AudioFloatArray* convolution_kernel,
-               const float* source_p,
-               float* dest_p,
-               size_t frames_to_process);
+  void Process(const float* source_p, float* dest_p, size_t frames_to_process);
 
   void Reset();
 
+  size_t ConvolutionKernelSize() const { return convolution_kernel_->size(); }
+
  private:
   size_t input_block_size_;
 
   AudioFloatArray buffer_;
+  std::unique_ptr<AudioFloatArray> convolution_kernel_;
+  AudioFloatArray prepared_convolution_kernel_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/DownSampler.cpp b/third_party/WebKit/Source/platform/audio/DownSampler.cpp
index b12106f..5bc98d56 100644
--- a/third_party/WebKit/Source/platform/audio/DownSampler.cpp
+++ b/third_party/WebKit/Source/platform/audio/DownSampler.cpp
@@ -29,27 +29,27 @@
  */
 
 #include "platform/audio/DownSampler.h"
+
+#include <memory>
+
 #include "platform/wtf/MathExtras.h"
 
 namespace blink {
 
-DownSampler::DownSampler(size_t input_block_size)
-    : input_block_size_(input_block_size),
-      reduced_kernel_(kDefaultKernelSize / 2),
-      convolver_(input_block_size / 2),  // runs at 1/2 source sample-rate
-      temp_buffer_(input_block_size / 2),
-      input_buffer_(input_block_size * 2) {
-  InitializeKernel();
-}
+namespace {
 
-void DownSampler::InitializeKernel() {
+// Computes ideal band-limited half-band filter coefficients.
+// In other words, filter out all frequencies higher than 0.25 * Nyquist.
+std::unique_ptr<AudioFloatArray> MakeReducedKernel(size_t size) {
+  auto reduced_kernel = std::make_unique<AudioFloatArray>(size / 2);
+
   // Blackman window parameters.
   double alpha = 0.16;
   double a0 = 0.5 * (1.0 - alpha);
   double a1 = 0.5;
   double a2 = 0.5 * alpha;
 
-  int n = kDefaultKernelSize;
+  int n = size;
   int half_size = n / 2;
 
   // Half-band filter.
@@ -73,10 +73,21 @@
     // Then store only the odd terms in the kernel.
     // In a sense, this is shifting forward in time by one sample-frame at the
     // destination sample-rate.
-    reduced_kernel_[(i - 1) / 2] = sinc * window;
+    (*reduced_kernel)[(i - 1) / 2] = sinc * window;
   }
+
+  return reduced_kernel;
 }
 
+}  // namespace
+
+DownSampler::DownSampler(size_t input_block_size)
+    : input_block_size_(input_block_size),
+      convolver_(input_block_size / 2,  // runs at 1/2 source sample-rate
+                 MakeReducedKernel(kDefaultKernelSize)),
+      temp_buffer_(input_block_size / 2),
+      input_buffer_(input_block_size * 2) {}
+
 void DownSampler::Process(const float* source_p,
                           float* dest_p,
                           size_t source_frames_to_process) {
@@ -93,7 +104,7 @@
     return;
 
   bool is_reduced_kernel_good =
-      reduced_kernel_.size() == kDefaultKernelSize / 2;
+      convolver_.ConvolutionKernelSize() == kDefaultKernelSize / 2;
   DCHECK(is_reduced_kernel_good);
   if (!is_reduced_kernel_good)
     return;
@@ -121,8 +132,7 @@
   // Actually process oddSamplesP with m_reducedKernel for efficiency.
   // The theoretical kernel is double this size with 0 values for even terms
   // (except center).
-  convolver_.Process(&reduced_kernel_, odd_samples_p, dest_p,
-                     dest_frames_to_process);
+  convolver_.Process(odd_samples_p, dest_p, dest_frames_to_process);
 
   // Now, account for the 0.5 term right in the middle of the kernel.
   // This amounts to a delay-line of length halfSize (at the source
@@ -145,7 +155,7 @@
 size_t DownSampler::LatencyFrames() const {
   // Divide by two since this is a linear phase kernel and the delay is at the
   // center of the kernel.
-  return reduced_kernel_.size() / 2;
+  return convolver_.ConvolutionKernelSize() / 2;
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/DownSampler.h b/third_party/WebKit/Source/platform/audio/DownSampler.h
index 1de8af0..812f7dd 100644
--- a/third_party/WebKit/Source/platform/audio/DownSampler.h
+++ b/third_party/WebKit/Source/platform/audio/DownSampler.h
@@ -45,7 +45,7 @@
   WTF_MAKE_NONCOPYABLE(DownSampler);
 
  public:
-  DownSampler(size_t input_block_size);
+  explicit DownSampler(size_t input_block_size);
 
   // The destination buffer |destP| is of size sourceFramesToProcess / 2.
   void Process(const float* source_p,
@@ -62,11 +62,6 @@
 
   size_t input_block_size_;
 
-  // Computes ideal band-limited half-band filter coefficients.
-  // In other words, filter out all frequencies higher than 0.25 * Nyquist.
-  void InitializeKernel();
-  AudioFloatArray reduced_kernel_;
-
   // Half-band filter.
   DirectConvolver convolver_;
 
diff --git a/third_party/WebKit/Source/platform/audio/ReverbConvolverStage.cpp b/third_party/WebKit/Source/platform/audio/ReverbConvolverStage.cpp
index 20014d462..15ca07f0 100644
--- a/third_party/WebKit/Source/platform/audio/ReverbConvolverStage.cpp
+++ b/third_party/WebKit/Source/platform/audio/ReverbConvolverStage.cpp
@@ -30,6 +30,7 @@
 
 #include <algorithm>
 #include <memory>
+#include <utility>
 
 #include "platform/audio/ReverbAccumulationBuffer.h"
 #include "platform/audio/ReverbConvolver.h"
@@ -38,8 +39,6 @@
 
 namespace blink {
 
-using namespace VectorMath;
-
 ReverbConvolverStage::ReverbConvolverStage(
     const float* impulse_response,
     size_t,
@@ -66,9 +65,10 @@
     DCHECK(!stage_offset);
     DCHECK_LE(stage_length, fft_size / 2);
 
-    direct_kernel_ = std::make_unique<AudioFloatArray>(fft_size / 2);
-    direct_kernel_->CopyToRange(impulse_response, 0, stage_length);
-    direct_convolver_ = std::make_unique<DirectConvolver>(render_slice_size);
+    auto direct_kernel = std::make_unique<AudioFloatArray>(fft_size / 2);
+    direct_kernel->CopyToRange(impulse_response, 0, stage_length);
+    direct_convolver_ = std::make_unique<DirectConvolver>(
+        render_slice_size, std::move(direct_kernel));
   }
   temporary_buffer_.Allocate(render_slice_size);
 
@@ -166,8 +166,8 @@
       fft_convolver_->Process(fft_kernel_.get(), pre_delayed_source,
                               temporary_buffer, frames_to_process);
     else
-      direct_convolver_->Process(direct_kernel_.get(), pre_delayed_source,
-                                 temporary_buffer, frames_to_process);
+      direct_convolver_->Process(pre_delayed_source, temporary_buffer,
+                                 frames_to_process);
 
     // Now accumulate into reverb's accumulation buffer.
     accumulation_buffer_->Accumulate(temporary_buffer, frames_to_process,
diff --git a/third_party/WebKit/Source/platform/audio/ReverbConvolverStage.h b/third_party/WebKit/Source/platform/audio/ReverbConvolverStage.h
index 380bc79..ebd93499 100644
--- a/third_party/WebKit/Source/platform/audio/ReverbConvolverStage.h
+++ b/third_party/WebKit/Source/platform/audio/ReverbConvolverStage.h
@@ -30,6 +30,7 @@
 #define ReverbConvolverStage_h
 
 #include <memory>
+
 #include "platform/audio/AudioArray.h"
 #include "platform/audio/FFTFrame.h"
 #include "platform/wtf/Allocator.h"
@@ -95,7 +96,6 @@
   AudioFloatArray temporary_buffer_;
 
   bool direct_mode_;
-  std::unique_ptr<AudioFloatArray> direct_kernel_;
   std::unique_ptr<DirectConvolver> direct_convolver_;
 };
 
diff --git a/third_party/WebKit/Source/platform/audio/UpSampler.cpp b/third_party/WebKit/Source/platform/audio/UpSampler.cpp
index f7c253e..842df27 100644
--- a/third_party/WebKit/Source/platform/audio/UpSampler.cpp
+++ b/third_party/WebKit/Source/platform/audio/UpSampler.cpp
@@ -29,27 +29,29 @@
  */
 
 #include "platform/audio/UpSampler.h"
+
+#include <memory>
+
 #include "platform/wtf/MathExtras.h"
 
 namespace blink {
 
-UpSampler::UpSampler(size_t input_block_size)
-    : input_block_size_(input_block_size),
-      kernel_(kDefaultKernelSize),
-      convolver_(input_block_size),
-      temp_buffer_(input_block_size),
-      input_buffer_(input_block_size * 2) {
-  InitializeKernel();
-}
+namespace {
 
-void UpSampler::InitializeKernel() {
+// Computes ideal band-limited filter coefficients to sample in between each
+// source sample-frame.  This filter will be used to compute the odd
+// sample-frames of the output.
+std::unique_ptr<AudioFloatArray> MakeKernel(size_t size) {
+  std::unique_ptr<AudioFloatArray> kernel =
+      std::make_unique<AudioFloatArray>(size);
+
   // Blackman window parameters.
   double alpha = 0.16;
   double a0 = 0.5 * (1.0 - alpha);
   double a1 = 0.5;
   double a2 = 0.5 * alpha;
 
-  int n = kernel_.size();
+  int n = kernel->size();
   int half_size = n / 2;
   double subsample_offset = -0.5;
 
@@ -64,10 +66,20 @@
         a0 - a1 * cos(twoPiDouble * x) + a2 * cos(twoPiDouble * 2.0 * x);
 
     // Window the sinc() function.
-    kernel_[i] = sinc * window;
+    (*kernel)[i] = sinc * window;
   }
+
+  return kernel;
 }
 
+}  // namespace
+
+UpSampler::UpSampler(size_t input_block_size)
+    : input_block_size_(input_block_size),
+      convolver_(input_block_size, MakeKernel(kDefaultKernelSize)),
+      temp_buffer_(input_block_size),
+      input_buffer_(input_block_size * 2) {}
+
 void UpSampler::Process(const float* source_p,
                         float* dest_p,
                         size_t source_frames_to_process) {
@@ -81,12 +93,13 @@
   if (!is_temp_buffer_good)
     return;
 
-  bool is_kernel_good = kernel_.size() == kDefaultKernelSize;
+  bool is_kernel_good =
+      convolver_.ConvolutionKernelSize() == kDefaultKernelSize;
   DCHECK(is_kernel_good);
   if (!is_kernel_good)
     return;
 
-  size_t half_size = kernel_.size() / 2;
+  size_t half_size = convolver_.ConvolutionKernelSize() / 2;
 
   // Copy source samples to 2nd half of input buffer.
   bool is_input_buffer_good =
@@ -106,8 +119,7 @@
 
   // Compute odd sample-frames 1,3,5,7...
   float* odd_samples_p = temp_buffer_.Data();
-  convolver_.Process(&kernel_, source_p, odd_samples_p,
-                     source_frames_to_process);
+  convolver_.Process(source_p, odd_samples_p, source_frames_to_process);
 
   for (unsigned i = 0; i < source_frames_to_process; ++i)
     dest_p[i * 2 + 1] = odd_samples_p[i];
@@ -125,7 +137,7 @@
 size_t UpSampler::LatencyFrames() const {
   // Divide by two since this is a linear phase kernel and the delay is at the
   // center of the kernel.
-  return kernel_.size() / 2;
+  return convolver_.ConvolutionKernelSize() / 2;
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/UpSampler.h b/third_party/WebKit/Source/platform/audio/UpSampler.h
index bc60d12..a78cd84b 100644
--- a/third_party/WebKit/Source/platform/audio/UpSampler.h
+++ b/third_party/WebKit/Source/platform/audio/UpSampler.h
@@ -45,7 +45,7 @@
   WTF_MAKE_NONCOPYABLE(UpSampler);
 
  public:
-  UpSampler(size_t input_block_size);
+  explicit UpSampler(size_t input_block_size);
 
   // The destination buffer |destP| is of size sourceFramesToProcess * 2.
   void Process(const float* source_p,
@@ -62,12 +62,6 @@
 
   size_t input_block_size_;
 
-  // Computes ideal band-limited filter coefficients to sample in between each
-  // source sample-frame.  This filter will be used to compute the odd
-  // sample-frames of the output.
-  void InitializeKernel();
-  AudioFloatArray kernel_;
-
   // Computes the odd sample-frames of the output.
   DirectConvolver convolver_;
 
diff --git a/third_party/WebKit/Source/platform/audio/VectorMath.cpp b/third_party/WebKit/Source/platform/audio/VectorMath.cpp
index 570d404d..d1a556a 100644
--- a/third_party/WebKit/Source/platform/audio/VectorMath.cpp
+++ b/third_party/WebKit/Source/platform/audio/VectorMath.cpp
@@ -61,6 +61,21 @@
 #endif
 }  // namespace
 
+void PrepareFilterForConv(const float* filter_p,
+                          int filter_stride,
+                          size_t filter_size,
+                          AudioFloatArray* prepared_filter) {
+  // Only contiguous convolution is implemented by all implementations.
+  // Correlation (positive |filter_stride|) and support for non-contiguous
+  // vectors are not implemented by all implementations.
+  DCHECK_EQ(-1, filter_stride);
+  DCHECK(prepared_filter);
+#if defined(ARCH_CPU_X86_FAMILY) && !defined(OS_MACOSX)
+  X86::PrepareFilterForConv(filter_p, filter_stride, filter_size,
+                            prepared_filter);
+#endif
+}
+
 void Conv(const float* source_p,
           int source_stride,
           const float* filter_p,
@@ -68,7 +83,8 @@
           float* dest_p,
           int dest_stride,
           size_t frames_to_process,
-          size_t filter_size) {
+          size_t filter_size,
+          const AudioFloatArray* prepared_filter) {
   // Only contiguous convolution is implemented by all implementations.
   // Correlation (positive |filter_stride|) and support for non-contiguous
   // vectors are not implemented by all implementations.
@@ -76,7 +92,7 @@
   DCHECK_EQ(-1, filter_stride);
   DCHECK_EQ(1, dest_stride);
   Impl::Conv(source_p, source_stride, filter_p, filter_stride, dest_p,
-             dest_stride, frames_to_process, filter_size);
+             dest_stride, frames_to_process, filter_size, prepared_filter);
 }
 
 void Vadd(const float* source1p,
diff --git a/third_party/WebKit/Source/platform/audio/VectorMath.h b/third_party/WebKit/Source/platform/audio/VectorMath.h
index c5828ce..cf7d13d 100644
--- a/third_party/WebKit/Source/platform/audio/VectorMath.h
+++ b/third_party/WebKit/Source/platform/audio/VectorMath.h
@@ -29,6 +29,7 @@
 #include <cstddef>
 
 #include "platform/PlatformExport.h"
+#include "platform/audio/AudioArray.h"
 
 // Defines the interface for several vector math functions whose implementation
 // will ideally be optimized.
@@ -47,7 +48,14 @@
                           float* dest_p,
                           int dest_stride,
                           size_t frames_to_process,
-                          size_t filter_size);
+                          size_t filter_size,
+                          const AudioFloatArray* prepared_filter);
+
+// Prepare filter for Conv for faster processing.
+PLATFORM_EXPORT void PrepareFilterForConv(const float* filter_p,
+                                          int filter_stride,
+                                          size_t filter_size,
+                                          AudioFloatArray* prepared_filter);
 
 // Vector scalar multiply and then add.
 //
diff --git a/third_party/WebKit/Source/platform/audio/VectorMathScalar.h b/third_party/WebKit/Source/platform/audio/VectorMathScalar.h
index ad6fe4f..0b47222 100644
--- a/third_party/WebKit/Source/platform/audio/VectorMathScalar.h
+++ b/third_party/WebKit/Source/platform/audio/VectorMathScalar.h
@@ -8,6 +8,7 @@
 #include <algorithm>
 #include <cmath>
 
+#include "platform/audio/AudioArray.h"
 #include "platform/wtf/Assertions.h"
 #include "platform/wtf/MathExtras.h"
 
@@ -22,7 +23,8 @@
                                float* dest_p,
                                int dest_stride,
                                size_t frames_to_process,
-                               size_t filter_size) {
+                               size_t filter_size,
+                               const AudioFloatArray* /*prepared_filter*/) {
   // Only contiguous convolution is implemented. Correlation (positive
   // |filter_stride|) and support for non-contiguous vectors are not
   // implemented.
@@ -30,26 +32,22 @@
   DCHECK_EQ(-1, filter_stride);
   DCHECK_EQ(1, dest_stride);
 
-  size_t kernel_size = filter_size;
-  const float* input_p = source_p + kernel_size - 1;
-  const float* kernel_p = filter_p + 1 - kernel_size;
-
   size_t i = 0;
 
 // FIXME: The macro can be further optimized to avoid pipeline stalls. One
 // possibility is to maintain 4 separate sums and change the macro to
 // CONVOLVE_FOUR_SAMPLES.
-#define CONVOLVE_ONE_SAMPLE              \
-  do {                                   \
-    sum += input_p[i - j] * kernel_p[j]; \
-    j++;                                 \
+#define CONVOLVE_ONE_SAMPLE                   \
+  do {                                        \
+    sum += source_p[i + j] * *(filter_p - j); \
+    j++;                                      \
   } while (0)
 
   while (i < frames_to_process) {
     size_t j = 0;
     float sum = 0;
 
-    if (kernel_size == 32) {
+    if (filter_size == 32) {
       CONVOLVE_ONE_SAMPLE;  // 1
       CONVOLVE_ONE_SAMPLE;  // 2
       CONVOLVE_ONE_SAMPLE;  // 3
@@ -86,7 +84,7 @@
       CONVOLVE_ONE_SAMPLE;  // 31
       CONVOLVE_ONE_SAMPLE;  // 32
 
-    } else if (kernel_size == 64) {
+    } else if (filter_size == 64) {
       CONVOLVE_ONE_SAMPLE;  // 1
       CONVOLVE_ONE_SAMPLE;  // 2
       CONVOLVE_ONE_SAMPLE;  // 3
@@ -158,7 +156,7 @@
       CONVOLVE_ONE_SAMPLE;  // 63
       CONVOLVE_ONE_SAMPLE;  // 64
 
-    } else if (kernel_size == 128) {
+    } else if (filter_size == 128) {
       CONVOLVE_ONE_SAMPLE;  // 1
       CONVOLVE_ONE_SAMPLE;  // 2
       CONVOLVE_ONE_SAMPLE;  // 3
@@ -300,7 +298,7 @@
       CONVOLVE_ONE_SAMPLE;  // 127
       CONVOLVE_ONE_SAMPLE;  // 128
     } else {
-      while (j < kernel_size) {
+      while (j < filter_size) {
         // Non-optimized using actual while loop.
         CONVOLVE_ONE_SAMPLE;
       }
diff --git a/third_party/WebKit/Source/platform/audio/VectorMathTest.cpp b/third_party/WebKit/Source/platform/audio/VectorMathTest.cpp
index d60af4ba..59bf010 100644
--- a/third_party/WebKit/Source/platform/audio/VectorMathTest.cpp
+++ b/third_party/WebKit/Source/platform/audio/VectorMathTest.cpp
@@ -264,7 +264,7 @@
   for (const auto& source : GetPrimaryVectors(GetSource(kFullyFiniteSource))) {
     if (source.stride() != 1)
       continue;
-    for (size_t filter_size : {3u, 20u, 32u, 64u, 128u}) {
+    for (size_t filter_size : {3u, 32u, 64u, 128u}) {
       // The maximum number of frames which could be processed here is
       // |source.size() - filter_size + 1|. However, in order to test
       // optimization paths, |frames_to_process| should be optimal (divisible
@@ -289,8 +289,10 @@
       }
       for (auto& dest : GetSecondaryVectors(
                GetDestination(1u), source.memory_layout(), frames_to_process)) {
+        AudioFloatArray prepared_filter;
+        PrepareFilterForConv(filter_p, -1, filter_size, &prepared_filter);
         Conv(source.p(), 1, filter_p, -1, dest.p(), 1, frames_to_process,
-             filter_size);
+             filter_size, &prepared_filter);
         for (size_t i = 0u; i < frames_to_process; ++i) {
           EXPECT_NEAR(expected_dest[i], dest[i],
                       1e-3 * std::abs(expected_dest[i]));
diff --git a/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathAVX.h b/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathAVX.h
index 1132a711..ee693653 100644
--- a/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathAVX.h
+++ b/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathAVX.h
@@ -7,6 +7,8 @@
 
 #include <cstddef>
 
+#include "platform/audio/AudioArray.h"
+
 namespace blink {
 namespace VectorMath {
 namespace AVX {
@@ -17,6 +19,21 @@
 
 bool IsAligned(const float*);
 
+// Direct vector convolution:
+// dest[k] = sum(source[k+m]*filter[m*filter_stride]) for all m
+// provided that |prepared_filter_p| is |prepared_filter->Data()| and that
+// |prepared_filter| is prepared with |PrepareFilterForConv|.
+void Conv(const float* source_p,
+          const float* prepared_filter_p,
+          float* dest_p,
+          size_t frames_to_process,
+          size_t filter_size);
+
+void PrepareFilterForConv(const float* filter_p,
+                          int filter_stride,
+                          size_t filter_size,
+                          AudioFloatArray* prepared_filter);
+
 // dest[k] = source1[k] + source2[k]
 void Vadd(const float* source1p,
           const float* source2p,
diff --git a/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathImpl.h b/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathImpl.h
index 8259733..167e757 100644
--- a/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathImpl.h
+++ b/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathImpl.h
@@ -2,25 +2,98 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// This file intentionally does not have header guards, it's included from
+// VectorMathAVX.h and from VectorMathSSE.h with different macro definitions.
+// The following line silences a presubmit warning that would otherwise be
+// triggered by this: no-include-guard-because-multiply-included
+
 #include "build/build_config.h"
 
 #if defined(ARCH_CPU_X86_FAMILY) && !defined(OS_MACOSX)
 
-#include "platform/wtf/Assertions.h"
-
 #include <algorithm>
 #include <cmath>
 
+#include "platform/audio/AudioArray.h"
+#include "platform/wtf/Assertions.h"
+
 namespace blink {
 namespace VectorMath {
 namespace VECTOR_MATH_SIMD_NAMESPACE_NAME {
 
+// This stride is chosen so that the same prepared filter created by
+// AVX::PrepareFilterForConv can be used by both AVX::Conv and SSE::Conv.
+// A prepared filter created by SSE::PrepareFilterForConv can only be used
+// by SSE::Conv.
+constexpr size_t kReversedFilterStride = 8u / kPackedFloatsPerRegister;
+
 bool IsAligned(const float* p) {
   constexpr size_t kBytesPerRegister = kBitsPerRegister / 8u;
   constexpr size_t kAlignmentOffsetMask = kBytesPerRegister - 1u;
   return (reinterpret_cast<size_t>(p) & kAlignmentOffsetMask) == 0u;
 }
 
+void PrepareFilterForConv(const float* filter_p,
+                          int filter_stride,
+                          size_t filter_size,
+                          AudioFloatArray* prepared_filter) {
+  // Only contiguous convolution is implemented. Correlation (positive
+  // |filter_stride|) and support for non-contiguous vectors are not
+  // implemented.
+  DCHECK_EQ(-1, filter_stride);
+  DCHECK(prepared_filter);
+
+  // Reverse the filter and repeat each value across a vector
+  prepared_filter->Allocate(kReversedFilterStride * kPackedFloatsPerRegister *
+                            filter_size);
+  MType* reversed_filter = reinterpret_cast<MType*>(prepared_filter->Data());
+  for (size_t i = 0; i < filter_size; ++i) {
+    reversed_filter[kReversedFilterStride * i] = MM_PS(set1)(*(filter_p - i));
+  }
+}
+
+// Direct vector convolution:
+// dest[k] = sum(source[k+m]*filter[m*filter_stride]) for all m
+// provided that |prepared_filter_p| is |prepared_filter->Data()| and that
+// |prepared_filter| is prepared with |PrepareFilterForConv|.
+void Conv(const float* source_p,
+          const float* prepared_filter_p,
+          float* dest_p,
+          size_t frames_to_process,
+          size_t filter_size) {
+  const float* const dest_end_p = dest_p + frames_to_process;
+
+  DCHECK_EQ(0u, frames_to_process % kPackedFloatsPerRegister);
+  DCHECK_EQ(0u, filter_size % kPackedFloatsPerRegister);
+
+  const MType* reversed_filter =
+      reinterpret_cast<const MType*>(prepared_filter_p);
+
+  // Do convolution with kPackedFloatsPerRegister inputs at a time.
+  while (dest_p < dest_end_p) {
+    MType m_convolution_sum = MM_PS(setzero)();
+
+    // |filter_size| is a multiple of kPackedFloatsPerRegister so we can unroll
+    // the loop by kPackedFloatsPerRegister, manually.
+    for (size_t i = 0; i < filter_size; i += kPackedFloatsPerRegister) {
+      for (size_t j = 0; j < kPackedFloatsPerRegister; ++j) {
+        size_t k = i + j;
+        MType m_product;
+        MType m_source;
+
+        m_source = MM_PS(loadu)(source_p + k);
+        m_product =
+            MM_PS(mul)(reversed_filter[kReversedFilterStride * k], m_source);
+        m_convolution_sum = MM_PS(add)(m_convolution_sum, m_product);
+      }
+    }
+    MM_PS(storeu)(dest_p, m_convolution_sum);
+
+    source_p += kPackedFloatsPerRegister;
+    dest_p += kPackedFloatsPerRegister;
+  }
+}
+
 // dest[k] = source1[k] + source2[k]
 void Vadd(const float* source1p,
           const float* source2p,
diff --git a/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathSSE.h b/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathSSE.h
index 771065b..fa34731 100644
--- a/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathSSE.h
+++ b/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathSSE.h
@@ -7,6 +7,8 @@
 
 #include <cstddef>
 
+#include "platform/audio/AudioArray.h"
+
 namespace blink {
 namespace VectorMath {
 namespace SSE {
@@ -17,6 +19,21 @@
 
 bool IsAligned(const float*);
 
+// Direct vector convolution:
+// dest[k] = sum(source[k+m]*filter[m*filter_stride]) for all m
+// provided that |prepared_filter_p| is |prepared_filter->Data()| and that
+// |prepared_filter| is prepared with |PrepareFilterForConv|.
+void Conv(const float* source_p,
+          const float* prepared_filter_p,
+          float* dest_p,
+          size_t frames_to_process,
+          size_t filter_size);
+
+void PrepareFilterForConv(const float* filter_p,
+                          int filter_stride,
+                          size_t filter_size,
+                          AudioFloatArray* prepared_filter);
+
 // dest[k] = source1[k] + source2[k]
 void Vadd(const float* source1p,
           const float* source2p,
diff --git a/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathX86.h b/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathX86.h
index 2a94532..c06e287 100644
--- a/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathX86.h
+++ b/third_party/WebKit/Source/platform/audio/cpu/x86/VectorMathX86.h
@@ -6,14 +6,11 @@
 #define VectorMathX86_h
 
 #include "base/cpu.h"
-#include "platform/audio/AudioArray.h"
 #include "platform/audio/VectorMathScalar.h"
 #include "platform/audio/cpu/x86/VectorMathAVX.h"
 #include "platform/audio/cpu/x86/VectorMathSSE.h"
 #include "platform/wtf/Assertions.h"
 
-#include <xmmintrin.h>
-
 namespace blink {
 namespace VectorMath {
 namespace X86 {
@@ -94,6 +91,20 @@
   return counts;
 }
 
+static ALWAYS_INLINE void PrepareFilterForConv(
+    const float* filter_p,
+    int filter_stride,
+    size_t filter_size,
+    AudioFloatArray* prepared_filter) {
+  if (CPUSupportsAVX()) {
+    AVX::PrepareFilterForConv(filter_p, filter_stride, filter_size,
+                              prepared_filter);
+  } else {
+    SSE::PrepareFilterForConv(filter_p, filter_stride, filter_size,
+                              prepared_filter);
+  }
+}
+
 static ALWAYS_INLINE void Conv(const float* source_p,
                                int source_stride,
                                const float* filter_p,
@@ -101,61 +112,30 @@
                                float* dest_p,
                                int dest_stride,
                                size_t frames_to_process,
-                               size_t filter_size) {
-  // Only contiguous convolution is implemented. Correlation (positive
-  // |filter_stride|) and support for non-contiguous vectors are not
-  // implemented.
-  DCHECK_EQ(1, source_stride);
-  DCHECK_EQ(-1, filter_stride);
-  DCHECK_EQ(1, dest_stride);
-
-  size_t kernel_size = filter_size;
-  const float* input_p = source_p + kernel_size - 1;
-  const float* kernel_p = filter_p + 1 - kernel_size;
-
-  size_t i = 0;
-
-  // Convolution using SSE2. Currently only do this if both |kernel_size| and
-  // |frames_to_process| are multiples of 4. If not, use Scalar::Conv.
-
-  if ((kernel_size % 4 == 0) && (frames_to_process % 4 == 0)) {
-    // AudioFloatArray's are always aligned on at least a 32-byte boundary.
-    AudioFloatArray kernel_buffer(4 * kernel_size);
-    __m128* kernel_reversed = reinterpret_cast<__m128*>(kernel_buffer.Data());
-
-    // Reverse the kernel and repeat each value across a vector
-    for (i = 0; i < kernel_size; ++i) {
-      kernel_reversed[i] = _mm_set1_ps(kernel_p[kernel_size - i - 1]);
+                               size_t filter_size,
+                               const AudioFloatArray* prepared_filter) {
+  const float* prepared_filter_p =
+      prepared_filter ? prepared_filter->Data() : nullptr;
+  if (source_stride == 1 && dest_stride == 1 && prepared_filter_p) {
+    if (CPUSupportsAVX() && (filter_size & ~AVX::kFramesToProcessMask) == 0u) {
+      // |frames_to_process| is always a multiply of render quantum and
+      // therefore the frames can always be processed using AVX.
+      CHECK_EQ(frames_to_process & ~AVX::kFramesToProcessMask, 0u);
+      AVX::Conv(source_p, prepared_filter_p, dest_p, frames_to_process,
+                filter_size);
+      return;
     }
-
-    const float* input_start_p = input_p - kernel_size + 1;
-
-    // Do convolution with 4 inputs at a time.
-    for (i = 0; i < frames_to_process; i += 4) {
-      __m128 convolution_sum;
-
-      convolution_sum = _mm_setzero_ps();
-
-      // |kernel_size| is a multiple of 4 so we can unroll the loop by 4,
-      // manually.
-      for (size_t k = 0; k < kernel_size; k += 4) {
-        size_t data_offset = i + k;
-
-        for (size_t m = 0; m < 4; ++m) {
-          __m128 source_block;
-          __m128 product;
-
-          source_block = _mm_loadu_ps(input_start_p + data_offset + m);
-          product = _mm_mul_ps(kernel_reversed[k + m], source_block);
-          convolution_sum = _mm_add_ps(convolution_sum, product);
-        }
-      }
-      _mm_storeu_ps(dest_p + i, convolution_sum);
+    if ((filter_size & ~SSE::kFramesToProcessMask) == 0u) {
+      // |frames_to_process| is always a multiply of render quantum and
+      // therefore the frames can always be processed using SSE.
+      CHECK_EQ(frames_to_process & ~SSE::kFramesToProcessMask, 0u);
+      SSE::Conv(source_p, prepared_filter_p, dest_p, frames_to_process,
+                filter_size);
+      return;
     }
-  } else {
-    Scalar::Conv(source_p, source_stride, filter_p, filter_stride, dest_p,
-                 dest_stride, frames_to_process, filter_size);
   }
+  Scalar::Conv(source_p, source_stride, filter_p, filter_stride, dest_p,
+               dest_stride, frames_to_process, filter_size, nullptr);
 }
 
 static ALWAYS_INLINE void Vadd(const float* source1p,
diff --git a/third_party/WebKit/Source/platform/audio/mac/VectorMathMac.h b/third_party/WebKit/Source/platform/audio/mac/VectorMathMac.h
index fc348ba..dfff7d4 100644
--- a/third_party/WebKit/Source/platform/audio/mac/VectorMathMac.h
+++ b/third_party/WebKit/Source/platform/audio/mac/VectorMathMac.h
@@ -8,6 +8,7 @@
 #include <Accelerate/Accelerate.h>
 
 #include "build/build_config.h"
+#include "platform/audio/AudioArray.h"
 
 namespace blink {
 namespace VectorMath {
@@ -26,7 +27,8 @@
                                float* dest_p,
                                int dest_stride,
                                size_t frames_to_process,
-                               size_t filter_size) {
+                               size_t filter_size,
+                               const AudioFloatArray* /*prepared_filter*/) {
 #if defined(ARCH_CPU_X86)
   ::conv(source_p, source_stride, filter_p, filter_stride, dest_p, dest_stride,
          frames_to_process, filter_size);
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
index 178cbdf..dc04f49 100644
--- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
+++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
@@ -356,7 +356,7 @@
 
 void OffscreenCanvasFrameDispatcherImpl::DidPresentCompositorFrame(
     uint32_t presentation_token,
-    ::mojo::common::mojom::blink::TimeTicksPtr time,
+    mojo_base::mojom::blink::TimeTicksPtr time,
     WTF::TimeDelta refresh,
     uint32_t flags) {
   NOTIMPLEMENTED();
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h
index 6f3f6c9..7619f9e0 100644
--- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h
+++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h
@@ -47,7 +47,7 @@
   void DidReceiveCompositorFrameAck(
       const WTF::Vector<viz::ReturnedResource>& resources) final;
   void DidPresentCompositorFrame(uint32_t presentation_token,
-                                 ::mojo::common::mojom::blink::TimeTicksPtr,
+                                 mojo_base::mojom::blink::TimeTicksPtr,
                                  WTF::TimeDelta refresh,
                                  uint32_t flags) final;
   void DidDiscardCompositorFrame(uint32_t presentation_token) final;
diff --git a/third_party/WebKit/Source/platform/graphics/VideoFrameSubmitter.cpp b/third_party/WebKit/Source/platform/graphics/VideoFrameSubmitter.cpp
index ccc12b0..689f857 100644
--- a/third_party/WebKit/Source/platform/graphics/VideoFrameSubmitter.cpp
+++ b/third_party/WebKit/Source/platform/graphics/VideoFrameSubmitter.cpp
@@ -198,7 +198,7 @@
 
 void VideoFrameSubmitter::DidPresentCompositorFrame(
     uint32_t presentation_token,
-    ::mojo::common::mojom::blink::TimeTicksPtr time,
+    mojo_base::mojom::blink::TimeTicksPtr time,
     WTF::TimeDelta refresh,
     uint32_t flags) {}
 
diff --git a/third_party/WebKit/Source/platform/graphics/VideoFrameSubmitter.h b/third_party/WebKit/Source/platform/graphics/VideoFrameSubmitter.h
index ee7af8b2..78cef1e2 100644
--- a/third_party/WebKit/Source/platform/graphics/VideoFrameSubmitter.h
+++ b/third_party/WebKit/Source/platform/graphics/VideoFrameSubmitter.h
@@ -59,7 +59,7 @@
   void DidReceiveCompositorFrameAck(
       const WTF::Vector<viz::ReturnedResource>& resources) override;
   void DidPresentCompositorFrame(uint32_t presentation_token,
-                                 ::mojo::common::mojom::blink::TimeTicksPtr,
+                                 mojo_base::mojom::blink::TimeTicksPtr,
                                  WTF::TimeDelta refresh,
                                  uint32_t flags) final;
   void DidDiscardCompositorFrame(uint32_t presentation_token) final;
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
index cfcb00f..a37e628 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
@@ -510,8 +510,8 @@
     properties_before_subsequence =
         new_paint_chunks_.CurrentPaintChunkProperties();
     new_paint_chunks_.ForceNewChunk();
-    UpdateCurrentPaintChunkProperties(cached_chunk->id,
-                                      cached_chunk->properties);
+    UpdateCurrentPaintChunkPropertiesUsingIdWithFragment(
+        cached_chunk->id, cached_chunk->properties);
   } else {
     // Avoid uninitialized variable error on Windows.
     cached_chunk = current_paint_artifact_.PaintChunks().begin();
@@ -530,8 +530,8 @@
       ++cached_chunk;
       DCHECK(cached_chunk != current_paint_artifact_.PaintChunks().end());
       new_paint_chunks_.ForceNewChunk();
-      UpdateCurrentPaintChunkProperties(cached_chunk->id,
-                                        cached_chunk->properties);
+      UpdateCurrentPaintChunkPropertiesUsingIdWithFragment(
+          cached_chunk->id, cached_chunk->properties);
     }
 
 #if DCHECK_IS_ON()
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.h b/third_party/WebKit/Source/platform/graphics/paint/PaintController.h
index 6d9de569..b2c7232 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.h
@@ -79,8 +79,8 @@
       const PaintChunkProperties& properties) {
     if (id) {
       PaintChunk::Id id_with_fragment(*id, current_fragment_);
-      new_paint_chunks_.UpdateCurrentPaintChunkProperties(id_with_fragment,
-                                                          properties);
+      UpdateCurrentPaintChunkPropertiesUsingIdWithFragment(id_with_fragment,
+                                                           properties);
 #if DCHECK_IS_ON()
       CheckDuplicatePaintChunkId(id_with_fragment);
 #endif
@@ -283,6 +283,13 @@
   size_t FindOutOfOrderCachedItemForward(const DisplayItem::Id&);
   void CopyCachedSubsequence(size_t begin_index, size_t end_index);
 
+  void UpdateCurrentPaintChunkPropertiesUsingIdWithFragment(
+      const PaintChunk::Id& id_with_fragment,
+      const PaintChunkProperties& properties) {
+    new_paint_chunks_.UpdateCurrentPaintChunkProperties(id_with_fragment,
+                                                        properties);
+  }
+
   // Resets the indices (e.g. next_item_to_match_) of
   // current_paint_artifact_.GetDisplayItemList() to their initial values. This
   // should be called when the DisplayItemList in current_paint_artifact_ is
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
index 967f2ae..ec17f06 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
@@ -12,6 +12,8 @@
 #include "platform/graphics/paint/DisplayItemCacheSkipper.h"
 #include "platform/graphics/paint/DrawingDisplayItem.h"
 #include "platform/graphics/paint/DrawingRecorder.h"
+#include "platform/graphics/paint/ScopedDisplayItemFragment.h"
+#include "platform/graphics/paint/ScopedPaintChunkProperties.h"
 #include "platform/graphics/paint/SubsequenceRecorder.h"
 #include "platform/runtime_enabled_features.h"
 #include "platform/testing/PaintTestConfigurations.h"
@@ -1145,6 +1147,79 @@
   EXPECT_EQ(4u, markers->end);
 }
 
+TEST_P(PaintControllerTest, CachedSubsequenceWithFragments) {
+  if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
+    return;
+
+  GraphicsContext context(GetPaintController());
+  FakeDisplayItemClient root("root");
+  constexpr size_t kFragmentCount = 3;
+  FakeDisplayItemClient container("container");
+
+  // The first paint.
+  auto paint_container = [this, &context, &container, kFragmentCount]() {
+    SubsequenceRecorder r(context, container);
+    for (size_t i = 0; i < kFragmentCount; ++i) {
+      ScopedDisplayItemFragment scoped_fragment(context, i);
+      ScopedPaintChunkProperties content_chunk_properties(
+          GetPaintController(), testing::DefaultPaintChunkProperties(),
+          container, kBackgroundType);
+      DrawRect(context, container, kBackgroundType,
+               FloatRect(100, 100, 100, 100));
+    }
+  };
+  {
+    ScopedPaintChunkProperties root_chunk_properties(
+        GetPaintController(), testing::DefaultPaintChunkProperties(), root,
+        kBackgroundType);
+    DrawRect(context, root, kBackgroundType, FloatRect(100, 100, 100, 100));
+    paint_container();
+    DrawRect(context, root, kForegroundType, FloatRect(100, 100, 100, 100));
+  }
+  GetPaintController().CommitNewDisplayItems();
+
+  // Check results of the first paint.
+  auto check_paint_results = [this, &root, &container, kFragmentCount]() {
+    const auto& chunks = GetPaintController().PaintChunks();
+    ASSERT_EQ(2u + kFragmentCount, chunks.size());
+    EXPECT_EQ(root, chunks[0].id.client);
+    EXPECT_EQ(kBackgroundType, chunks[0].id.type);
+    EXPECT_EQ(0u, chunks[0].id.fragment);
+    for (size_t i = 0; i < kFragmentCount; ++i) {
+      const auto& id = chunks[i + 1].id;
+      EXPECT_EQ(container, id.client);
+      EXPECT_EQ(kBackgroundType, id.type);
+      EXPECT_EQ(i, id.fragment);
+    }
+    EXPECT_EQ(root, chunks.back().id.client);
+    EXPECT_EQ(kForegroundType, chunks.back().id.type);
+    EXPECT_EQ(0u, chunks.back().id.fragment);
+  };
+  check_paint_results();
+
+  // The second paint.
+  {
+    ScopedPaintChunkProperties root_chunk_properties(
+        GetPaintController(), testing::DefaultPaintChunkProperties(), root,
+        kBackgroundType);
+    DrawRect(context, root, kBackgroundType, FloatRect(100, 100, 100, 100));
+
+    if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
+      EXPECT_FALSE(
+          GetPaintController().UseCachedSubsequenceIfPossible(container));
+      paint_container();
+    } else {
+      EXPECT_TRUE(
+          GetPaintController().UseCachedSubsequenceIfPossible(container));
+    }
+    DrawRect(context, root, kForegroundType, FloatRect(100, 100, 100, 100));
+  }
+  GetPaintController().CommitNewDisplayItems();
+
+  // The second paint should produce the exactly same results.
+  check_paint_results();
+}
+
 TEST_P(PaintControllerTest, UpdateSwapOrderCrossingChunks) {
   FakeDisplayItemClient container1("container1",
                                    LayoutRect(100, 100, 100, 100));
diff --git a/third_party/WebKit/Source/platform/mojo/DEPS b/third_party/WebKit/Source/platform/mojo/DEPS
index a116843..9278750 100644
--- a/third_party/WebKit/Source/platform/mojo/DEPS
+++ b/third_party/WebKit/Source/platform/mojo/DEPS
@@ -8,7 +8,7 @@
     "+base/strings/string16.h",
     "+mojo/common/big_string.mojom-blink.h",
     "+mojo/common/test_common_custom_types.mojom-blink.h",
-    "+mojo/common/time_struct_traits.h",
+    "+mojo/public/cpp/base/time_mojom_traits.h",
     "+mojo/public/cpp/bindings/binding.h",
     "+mojo/public/mojom/base/string16.mojom-blink.h",
     "+services/network/public/mojom/fetch_api.mojom-blink.h",
diff --git a/third_party/WebKit/Source/platform/mojo/Time.typemap b/third_party/WebKit/Source/platform/mojo/Time.typemap
index 59cbfbd..9b6967d 100644
--- a/third_party/WebKit/Source/platform/mojo/Time.typemap
+++ b/third_party/WebKit/Source/platform/mojo/Time.typemap
@@ -2,18 +2,18 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-mojom = "//mojo/common/time.mojom"
+mojom = "//mojo/public/mojom/base/time.mojom"
 public_headers = [ "//third_party/WebKit/Source/platform/wtf/Time.h" ]
 traits_headers = [
   "//ipc/ipc_message_utils.h",
-  "//mojo/common/time_struct_traits.h",
+  "//mojo/public/cpp/base/time_mojom_traits.h",
 ]
 public_deps = [
   "//ipc",
-  "//mojo/common:struct_traits",
+  "//mojo/public/mojom/base",
 ]
 
 type_mappings = [
-  "mojo.common.mojom.Time=WTF::Time[copyable_pass_by_value]",
-  "mojo.common.mojom.TimeDelta=WTF::TimeDelta[copyable_pass_by_value]",
+  "mojo_base.mojom.Time=WTF::Time[copyable_pass_by_value]",
+  "mojo_base.mojom.TimeDelta=WTF::TimeDelta[copyable_pass_by_value]",
 ]
diff --git a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
index 181bb3c..47991081 100644
--- a/third_party/WebKit/Source/platform/runtime_enabled_features.json5
+++ b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
@@ -188,7 +188,7 @@
     },
     {
       name: "ClientHintsPersistent",
-      status: "experimental",
+      status: "stable",
     },
     {
       name: "ClientPlaceholdersForServerLoFi",
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
index 004cd4d..0714535 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
@@ -395,10 +395,11 @@
     fade_overlay_scrollbars_timer_->Stop();
 }
 
-void ScrollableArea::MouseReleasedScrollbar() {
+void ScrollableArea::MouseReleasedScrollbar(ScrollbarOrientation orientation) {
   scrollbar_captured_ = false;
   // This will kick off the fade out timer.
   ShowOverlayScrollbars();
+  SnapAfterScrollbarDragging(orientation);
 }
 
 void ScrollableArea::ContentAreaDidShow() const {
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
index 9ba8209..6edc346 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
@@ -112,10 +112,12 @@
   void MouseEnteredScrollbar(Scrollbar&);
   void MouseExitedScrollbar(Scrollbar&);
   void MouseCapturedScrollbar();
-  void MouseReleasedScrollbar();
+  void MouseReleasedScrollbar(ScrollbarOrientation);
   void ContentAreaDidShow() const;
   void ContentAreaDidHide() const;
 
+  virtual void SnapAfterScrollbarDragging(ScrollbarOrientation) {}
+
   void FinishCurrentScrollAnimations() const;
 
   virtual void DidAddScrollbar(Scrollbar&, ScrollbarOrientation);
diff --git a/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp b/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp
index d9b6b9d..95a767b 100644
--- a/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp
+++ b/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp
@@ -476,7 +476,7 @@
 
   if (scrollable_area_) {
     if (is_captured)
-      scrollable_area_->MouseReleasedScrollbar();
+      scrollable_area_->MouseReleasedScrollbar(orientation_);
 
     ScrollbarPart part = GetTheme().HitTest(
         *this, FlooredIntPoint(mouse_event.PositionInRootFrame()));
diff --git a/third_party/WebKit/Source/platform/wtf/experimental/ContainerTypeOperationsTest.cpp b/third_party/WebKit/Source/platform/wtf/experimental/ContainerTypeOperationsTest.cpp
index 64a6bcc..f3a3ac6 100644
--- a/third_party/WebKit/Source/platform/wtf/experimental/ContainerTypeOperationsTest.cpp
+++ b/third_party/WebKit/Source/platform/wtf/experimental/ContainerTypeOperationsTest.cpp
@@ -4,6 +4,8 @@
 
 #include "platform/wtf/experimental/ContainerTypeOperations.h"
 
+#include <cstring>
+
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace WTF {
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
index a16e3369..a165da67 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
@@ -39,6 +39,7 @@
 
 # Sheriff calendar URL, used for getting the ecosystem infra sheriff to TBR.
 ROTATIONS_URL = 'https://build.chromium.org/deprecated/chromium/all_rotations.js'
+TBR_FALLBACK = 'qyearsley'
 
 _log = logging.getLogger(__file__)
 
@@ -524,7 +525,7 @@
             username = self._fetch_ecosystem_infra_sheriff_username()
         except (IOError, KeyError, ValueError) as error:
             _log.error('Exception while fetching current sheriff: %s', error)
-        return username or 'qyearsley'  # Fallback in case of failure.
+        return username or TBR_FALLBACK
 
     def _fetch_ecosystem_infra_sheriff_username(self):
         content = self.host.web.get_binary(ROTATIONS_URL)
@@ -535,8 +536,10 @@
         for entry in calendar:
             if entry['date'] == today:
                 if not entry['participants'][index]:
+                    _log.info('No sheriff today.')
                     return ''
                 return entry['participants'][index][0]
+        _log.error('No entry found for date %s in rotations table.', today)
         return ''
 
     def fetch_new_expectations_and_baselines(self):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py
index f183a34e..55f2242d 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py
@@ -18,7 +18,7 @@
 from webkitpy.w3c.chromium_commit_mock import MockChromiumCommit
 from webkitpy.w3c.local_wpt import LocalWPT
 from webkitpy.w3c.local_wpt_mock import MockLocalWPT
-from webkitpy.w3c.test_importer import TestImporter, ROTATIONS_URL
+from webkitpy.w3c.test_importer import TestImporter, ROTATIONS_URL, TBR_FALLBACK
 from webkitpy.w3c.wpt_github_mock import MockWPTGitHub
 
 
@@ -326,13 +326,13 @@
     def test_tbr_reviewer_no_response_uses_backup(self):
         host = MockHost()
         importer = TestImporter(host)
-        self.assertEqual('qyearsley', importer.tbr_reviewer())
+        self.assertEqual(TBR_FALLBACK, importer.tbr_reviewer())
         self.assertLog([
             'ERROR: Exception while fetching current sheriff: '
             'No JSON object could be decoded\n'
         ])
 
-    def test_tbr_reviewer_nobody_on_rotation(self):
+    def test_tbr_reviewer_date_not_found(self):
         host = MockHost()
         yesterday = (datetime.date.fromtimestamp(host.time()) -
                      datetime.timedelta(days=1)).isoformat()
@@ -340,27 +340,34 @@
             'calendar': [
                 {
                     'date': yesterday,
-                    'participants': [['some-sheriff']],
+                    'participants': [['some-sheriff'], ['other-sheriff']],
                 },
             ],
-            'rotations': ['ecosystem_infra']
+            'rotations': ['ecosystem_infra', 'other_rotation']
         })
         importer = TestImporter(host)
-        self.assertEqual('qyearsley', importer.tbr_reviewer())
-        self.assertLog([])
+        self.assertEqual(TBR_FALLBACK, importer.tbr_reviewer())
+        self.assertLog([
+            'ERROR: No entry found for date 1969-12-31 in rotations table.\n'
+        ])
 
+    def test_tbr_reviewer_nobody_on_rotation(self):
+        host = MockHost()
         today = datetime.date.fromtimestamp(host.time()).isoformat()
         host.web.urls[ROTATIONS_URL] = json.dumps({
             'calendar': [
                 {
                     'date': today,
-                    'participants': [[''], ['some-sheriff']],
+                    'participants': [[], ['some-sheriff']],
                 },
             ],
             'rotations': ['ecosystem_infra', 'other-rotation']
         })
-        self.assertEqual('qyearsley', importer.tbr_reviewer())
-        self.assertLog([])
+        importer = TestImporter(host)
+        self.assertEqual(TBR_FALLBACK, importer.tbr_reviewer())
+        self.assertLog([
+            'INFO: No sheriff today.\n'
+        ])
 
     def test_tbr_reviewer(self):
         host = MockHost()
diff --git a/third_party/WebKit/public/mojom/blob/data_element.mojom b/third_party/WebKit/public/mojom/blob/data_element.mojom
index 8e44de2..1687a51e 100644
--- a/third_party/WebKit/public/mojom/blob/data_element.mojom
+++ b/third_party/WebKit/public/mojom/blob/data_element.mojom
@@ -4,9 +4,9 @@
 
 module blink.mojom;
 
-import "mojo/common/time.mojom";
 import "mojo/public/mojom/base/file.mojom";
 import "mojo/public/mojom/base/file_path.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "third_party/WebKit/public/mojom/blob/blob.mojom";
 import "url/mojom/origin.mojom";
 import "url/mojom/url.mojom";
@@ -67,7 +67,7 @@
   // modification time.
   RequestAsFile(uint64 source_offset, uint64 source_size,
                 mojo_base.mojom.File file, uint64 file_offset)
-      => (mojo.common.mojom.Time? time_file_modified);
+      => (mojo_base.mojom.Time? time_file_modified);
 };
 
 // A reference to a slice of a file on disk.
@@ -82,7 +82,7 @@
   uint64 length;
   // Expected modification time of the file being referenced. Can be null if the
   // modification time is unknown.
-  mojo.common.mojom.Time? expected_modification_time;
+  mojo_base.mojom.Time? expected_modification_time;
 };
 
 // A reference to a slice of a file as a filesystem URL.
@@ -97,7 +97,7 @@
   uint64 length;
   // Expected modification time of the file being referenced. Can be null if the
   // modification time is unknown.
-  mojo.common.mojom.Time? expected_modification_time;
+  mojo_base.mojom.Time? expected_modification_time;
 };
 
 // A reference to a slice of another blob.
diff --git a/third_party/WebKit/public/mojom/service_worker/service_worker_client.mojom b/third_party/WebKit/public/mojom/service_worker/service_worker_client.mojom
index 7c502f6..42a3b63 100644
--- a/third_party/WebKit/public/mojom/service_worker/service_worker_client.mojom
+++ b/third_party/WebKit/public/mojom/service_worker/service_worker_client.mojom
@@ -4,7 +4,7 @@
 
 module blink.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "services/network/public/mojom/request_context_frame_type.mojom";
 import "third_party/WebKit/public/mojom/page/page_visibility_state.mojom";
 import "url/mojom/url.mojom";
@@ -58,8 +58,8 @@
 
   // The time this window was last focused. Set to base::TimeTicks() if it's
   // a non-window client.
-  mojo.common.mojom.TimeTicks last_focus_time;
+  mojo_base.mojom.TimeTicks last_focus_time;
 
   // The time this client was created.
-  mojo.common.mojom.TimeTicks creation_time;
+  mojo_base.mojom.TimeTicks creation_time;
 };
diff --git a/third_party/WebKit/public/platform/modules/fetch/fetch_api_response.mojom b/third_party/WebKit/public/platform/modules/fetch/fetch_api_response.mojom
index 3efb355..e5157f1 100644
--- a/third_party/WebKit/public/platform/modules/fetch/fetch_api_response.mojom
+++ b/third_party/WebKit/public/platform/modules/fetch/fetch_api_response.mojom
@@ -4,7 +4,7 @@
 
 module blink.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "services/network/public/mojom/fetch_api.mojom";
 import "third_party/WebKit/public/mojom/blob/blob.mojom";
 import "third_party/WebKit/public/mojom/service_worker/service_worker_error_type.mojom";
@@ -49,7 +49,7 @@
 
   // The time at which the response headers were received.  For cached
   // responses, this time could be "far" in the past.
-  mojo.common.mojom.Time response_time;
+  mojo_base.mojom.Time response_time;
 
   // Name of cache where this response was retrieved, empty otherwise.
   string cache_storage_cache_name;
diff --git a/third_party/WebKit/public/platform/modules/payments/payment_app.mojom b/third_party/WebKit/public/platform/modules/payments/payment_app.mojom
index afd0758..aee2fc6 100644
--- a/third_party/WebKit/public/platform/modules/payments/payment_app.mojom
+++ b/third_party/WebKit/public/platform/modules/payments/payment_app.mojom
@@ -5,7 +5,7 @@
 module payments.mojom;
 
 import "components/payments/mojom/payment_request_data.mojom";
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "third_party/WebKit/public/platform/modules/manifest/manifest.mojom";
 import "third_party/WebKit/public/platform/modules/payments/payment_request.mojom";
 import "url/mojom/url.mojom";
@@ -90,9 +90,9 @@
 // request event in renderer side to browser side by calling respondWith().
 interface PaymentHandlerResponseCallback {
   OnResponseForAbortPayment(bool payment_aborted,
-                            mojo.common.mojom.Time dispatch_event_time);
+                            mojo_base.mojom.Time dispatch_event_time);
   OnResponseForCanMakePayment(bool can_make_payment,
-                              mojo.common.mojom.Time dispatch_event_time);
+                              mojo_base.mojom.Time dispatch_event_time);
   OnResponseForPaymentRequest(PaymentHandlerResponse response,
-                              mojo.common.mojom.Time dispatch_event_time);
+                              mojo_base.mojom.Time dispatch_event_time);
 };
diff --git a/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom b/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom
index 749aaae..b1540b6 100644
--- a/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom
+++ b/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom
@@ -4,7 +4,7 @@
 
 module webauth.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "url/mojom/url.mojom";
 
 // This file describes the communication between the WebAuthentication renderer
@@ -118,7 +118,7 @@
 
   // Time to wait for an authenticator to complete an operation.
   // Adjusted to fall within a client-defined range.
-  mojo.common.mojom.TimeDelta adjusted_timeout;
+  mojo_base.mojom.TimeDelta adjusted_timeout;
 
   // An ASCII serialization of the origin claimed by the relying party.
   string relying_party_id;
@@ -181,7 +181,7 @@
 
   // Time to wait for an authenticator to complete an operation.
   // Adjusted to fall within a client-defined range.
-  mojo.common.mojom.TimeDelta adjusted_timeout;
+  mojo_base.mojom.TimeDelta adjusted_timeout;
 
   // A list of credentials the relying party knows about. If an
   // authenticator has one of these credentials, it should not
diff --git a/third_party/WebKit/public/platform/reporting.mojom b/third_party/WebKit/public/platform/reporting.mojom
index 80186da37..8d859b17 100644
--- a/third_party/WebKit/public/platform/reporting.mojom
+++ b/third_party/WebKit/public/platform/reporting.mojom
@@ -4,7 +4,7 @@
 
 module blink.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "url/mojom/url.mojom";
 
 interface ReportingServiceProxy {
@@ -22,7 +22,7 @@
   // (See //third_party/WebKit/Source/core/frame/DeprecationReport.h.)
   QueueDeprecationReport(url.mojom.Url url,
                          string id,
-                         mojo.common.mojom.Time anticipatedRemoval,
+                         mojo_base.mojom.Time anticipatedRemoval,
                          string message,
                          string source_file,
                          int32 line_number,
diff --git a/third_party/harfbuzz-ng/BUILD.gn b/third_party/harfbuzz-ng/BUILD.gn
index f6c731e..c8bd9c6 100644
--- a/third_party/harfbuzz-ng/BUILD.gn
+++ b/third_party/harfbuzz-ng/BUILD.gn
@@ -20,7 +20,7 @@
   }
 } else {
   config("harfbuzz_config") {
-    include_dirs = [ "src" ]
+    include_dirs = [ "src/src" ]
   }
 
   config("harfbuzz_warnings") {
@@ -45,130 +45,130 @@
     visibility = [ "//third_party:freetype_harfbuzz" ]
 
     sources = [
-      "src/hb-atomic-private.hh",
-      "src/hb-blob.cc",
-      "src/hb-blob.h",
-      "src/hb-buffer-deserialize-json.hh",
-      "src/hb-buffer-deserialize-text.hh",
-      "src/hb-buffer-private.hh",
-      "src/hb-buffer-serialize.cc",
-      "src/hb-buffer.cc",
-      "src/hb-buffer.h",
-      "src/hb-cache-private.hh",
-      "src/hb-common.cc",
-      "src/hb-common.h",
-      "src/hb-debug.hh",
-      "src/hb-deprecated.h",
-      "src/hb-dsalgs.hh",
-      "src/hb-face-private.hh",
-      "src/hb-face.cc",
-      "src/hb-face.h",
-      "src/hb-font-private.hh",
-      "src/hb-font.cc",
-      "src/hb-font.h",
-      "src/hb-ft.cc",
-      "src/hb-ft.h",
-      "src/hb-icu.cc",
-      "src/hb-icu.h",
-      "src/hb-mutex-private.hh",
-      "src/hb-object-private.hh",
-      "src/hb-open-file-private.hh",
-      "src/hb-open-type-private.hh",
-      "src/hb-ot-color-cbdt-table.hh",
-      "src/hb-ot-color-colr-table.hh",
-      "src/hb-ot-color-cpal-table.hh",
-      "src/hb-ot-font.cc",
-      "src/hb-ot-font.h",
-      "src/hb-ot-hdmx-table.hh",
-      "src/hb-ot-head-table.hh",
-      "src/hb-ot-hhea-table.hh",
-      "src/hb-ot-hmtx-table.hh",
-      "src/hb-ot-kern-table.hh",
-      "src/hb-ot-layout-base-table.hh",
-      "src/hb-ot-layout-base-table.hh",
-      "src/hb-ot-layout-common-private.hh",
-      "src/hb-ot-layout-gdef-table.hh",
-      "src/hb-ot-layout-gpos-table.hh",
-      "src/hb-ot-layout-gsub-table.hh",
-      "src/hb-ot-layout-gsubgpos-private.hh",
-      "src/hb-ot-layout-private.hh",
-      "src/hb-ot-layout.cc",
-      "src/hb-ot-layout.h",
-      "src/hb-ot-map-private.hh",
-      "src/hb-ot-map.cc",
-      "src/hb-ot-math-table.hh",
-      "src/hb-ot-math.cc",
-      "src/hb-ot-math.h",
-      "src/hb-ot-maxp-table.hh",
-      "src/hb-ot-name-table.hh",
-      "src/hb-ot-os2-unicode-ranges.hh",
-      "src/hb-ot-post-macroman.hh",
-      "src/hb-ot-shape-complex-arabic-fallback.hh",
-      "src/hb-ot-shape-complex-arabic-private.hh",
-      "src/hb-ot-shape-complex-arabic-table.hh",
-      "src/hb-ot-shape-complex-arabic.cc",
-      "src/hb-ot-shape-complex-default.cc",
-      "src/hb-ot-shape-complex-hangul.cc",
-      "src/hb-ot-shape-complex-hebrew.cc",
-      "src/hb-ot-shape-complex-indic-machine.hh",
-      "src/hb-ot-shape-complex-indic-private.hh",
-      "src/hb-ot-shape-complex-indic-table.cc",
-      "src/hb-ot-shape-complex-indic.cc",
-      "src/hb-ot-shape-complex-khmer-machine.hh",
-      "src/hb-ot-shape-complex-khmer-private.hh",
-      "src/hb-ot-shape-complex-khmer.cc",
-      "src/hb-ot-shape-complex-myanmar-machine.hh",
-      "src/hb-ot-shape-complex-myanmar-private.hh",
-      "src/hb-ot-shape-complex-myanmar.cc",
-      "src/hb-ot-shape-complex-private.hh",
-      "src/hb-ot-shape-complex-thai.cc",
-      "src/hb-ot-shape-complex-tibetan.cc",
-      "src/hb-ot-shape-complex-use-machine.hh",
-      "src/hb-ot-shape-complex-use-private.hh",
-      "src/hb-ot-shape-complex-use-table.cc",
-      "src/hb-ot-shape-complex-use.cc",
-      "src/hb-ot-shape-fallback-private.hh",
-      "src/hb-ot-shape-fallback.cc",
-      "src/hb-ot-shape-normalize-private.hh",
-      "src/hb-ot-shape-normalize.cc",
-      "src/hb-ot-shape-private.hh",
-      "src/hb-ot-shape.cc",
-      "src/hb-ot-shape.h",
-      "src/hb-ot-tag.cc",
-      "src/hb-ot-tag.h",
-      "src/hb-ot-var-avar-table.hh",
-      "src/hb-ot-var-fvar-table.hh",
-      "src/hb-ot-var-hvar-table.hh",
-      "src/hb-ot-var-mvar-table.hh",
-      "src/hb-ot-var.cc",
-      "src/hb-ot-var.h",
-      "src/hb-ot.h",
-      "src/hb-private.hh",
-      "src/hb-set-digest-private.hh",
-      "src/hb-set-private.hh",
-      "src/hb-set.cc",
-      "src/hb-set.h",
-      "src/hb-shape-plan-private.hh",
-      "src/hb-shape-plan.cc",
-      "src/hb-shape-plan.h",
-      "src/hb-shape.cc",
-      "src/hb-shape.h",
-      "src/hb-shaper-impl-private.hh",
-      "src/hb-shaper-list.hh",
-      "src/hb-shaper-private.hh",
-      "src/hb-shaper.cc",
-      "src/hb-string-array.hh",
-      "src/hb-subset-glyf.hh",
-      "src/hb-subset-plan.h",
-      "src/hb-subset-private.hh",
-      "src/hb-subset.h",
-      "src/hb-unicode-private.hh",
-      "src/hb-unicode.cc",
-      "src/hb-unicode.h",
-      "src/hb-utf-private.hh",
-      "src/hb-version.h",
-      "src/hb-warning.cc",
-      "src/hb.h",
+      "src/src/hb-atomic-private.hh",
+      "src/src/hb-blob.cc",
+      "src/src/hb-blob.h",
+      "src/src/hb-buffer-deserialize-json.hh",
+      "src/src/hb-buffer-deserialize-text.hh",
+      "src/src/hb-buffer-private.hh",
+      "src/src/hb-buffer-serialize.cc",
+      "src/src/hb-buffer.cc",
+      "src/src/hb-buffer.h",
+      "src/src/hb-cache-private.hh",
+      "src/src/hb-common.cc",
+      "src/src/hb-common.h",
+      "src/src/hb-debug.hh",
+      "src/src/hb-deprecated.h",
+      "src/src/hb-dsalgs.hh",
+      "src/src/hb-face-private.hh",
+      "src/src/hb-face.cc",
+      "src/src/hb-face.h",
+      "src/src/hb-font-private.hh",
+      "src/src/hb-font.cc",
+      "src/src/hb-font.h",
+      "src/src/hb-ft.cc",
+      "src/src/hb-ft.h",
+      "src/src/hb-icu.cc",
+      "src/src/hb-icu.h",
+      "src/src/hb-mutex-private.hh",
+      "src/src/hb-object-private.hh",
+      "src/src/hb-open-file-private.hh",
+      "src/src/hb-open-type-private.hh",
+      "src/src/hb-ot-color-cbdt-table.hh",
+      "src/src/hb-ot-color-colr-table.hh",
+      "src/src/hb-ot-color-cpal-table.hh",
+      "src/src/hb-ot-font.cc",
+      "src/src/hb-ot-font.h",
+      "src/src/hb-ot-hdmx-table.hh",
+      "src/src/hb-ot-head-table.hh",
+      "src/src/hb-ot-hhea-table.hh",
+      "src/src/hb-ot-hmtx-table.hh",
+      "src/src/hb-ot-kern-table.hh",
+      "src/src/hb-ot-layout-base-table.hh",
+      "src/src/hb-ot-layout-base-table.hh",
+      "src/src/hb-ot-layout-common-private.hh",
+      "src/src/hb-ot-layout-gdef-table.hh",
+      "src/src/hb-ot-layout-gpos-table.hh",
+      "src/src/hb-ot-layout-gsub-table.hh",
+      "src/src/hb-ot-layout-gsubgpos-private.hh",
+      "src/src/hb-ot-layout-private.hh",
+      "src/src/hb-ot-layout.cc",
+      "src/src/hb-ot-layout.h",
+      "src/src/hb-ot-map-private.hh",
+      "src/src/hb-ot-map.cc",
+      "src/src/hb-ot-math-table.hh",
+      "src/src/hb-ot-math.cc",
+      "src/src/hb-ot-math.h",
+      "src/src/hb-ot-maxp-table.hh",
+      "src/src/hb-ot-name-table.hh",
+      "src/src/hb-ot-os2-unicode-ranges.hh",
+      "src/src/hb-ot-post-macroman.hh",
+      "src/src/hb-ot-shape-complex-arabic-fallback.hh",
+      "src/src/hb-ot-shape-complex-arabic-private.hh",
+      "src/src/hb-ot-shape-complex-arabic-table.hh",
+      "src/src/hb-ot-shape-complex-arabic.cc",
+      "src/src/hb-ot-shape-complex-default.cc",
+      "src/src/hb-ot-shape-complex-hangul.cc",
+      "src/src/hb-ot-shape-complex-hebrew.cc",
+      "src/src/hb-ot-shape-complex-indic-machine.hh",
+      "src/src/hb-ot-shape-complex-indic-private.hh",
+      "src/src/hb-ot-shape-complex-indic-table.cc",
+      "src/src/hb-ot-shape-complex-indic.cc",
+      "src/src/hb-ot-shape-complex-khmer-machine.hh",
+      "src/src/hb-ot-shape-complex-khmer-private.hh",
+      "src/src/hb-ot-shape-complex-khmer.cc",
+      "src/src/hb-ot-shape-complex-myanmar-machine.hh",
+      "src/src/hb-ot-shape-complex-myanmar-private.hh",
+      "src/src/hb-ot-shape-complex-myanmar.cc",
+      "src/src/hb-ot-shape-complex-private.hh",
+      "src/src/hb-ot-shape-complex-thai.cc",
+      "src/src/hb-ot-shape-complex-tibetan.cc",
+      "src/src/hb-ot-shape-complex-use-machine.hh",
+      "src/src/hb-ot-shape-complex-use-private.hh",
+      "src/src/hb-ot-shape-complex-use-table.cc",
+      "src/src/hb-ot-shape-complex-use.cc",
+      "src/src/hb-ot-shape-fallback-private.hh",
+      "src/src/hb-ot-shape-fallback.cc",
+      "src/src/hb-ot-shape-normalize-private.hh",
+      "src/src/hb-ot-shape-normalize.cc",
+      "src/src/hb-ot-shape-private.hh",
+      "src/src/hb-ot-shape.cc",
+      "src/src/hb-ot-shape.h",
+      "src/src/hb-ot-tag.cc",
+      "src/src/hb-ot-tag.h",
+      "src/src/hb-ot-var-avar-table.hh",
+      "src/src/hb-ot-var-fvar-table.hh",
+      "src/src/hb-ot-var-hvar-table.hh",
+      "src/src/hb-ot-var-mvar-table.hh",
+      "src/src/hb-ot-var.cc",
+      "src/src/hb-ot-var.h",
+      "src/src/hb-ot.h",
+      "src/src/hb-private.hh",
+      "src/src/hb-set-digest-private.hh",
+      "src/src/hb-set-private.hh",
+      "src/src/hb-set.cc",
+      "src/src/hb-set.h",
+      "src/src/hb-shape-plan-private.hh",
+      "src/src/hb-shape-plan.cc",
+      "src/src/hb-shape-plan.h",
+      "src/src/hb-shape.cc",
+      "src/src/hb-shape.h",
+      "src/src/hb-shaper-impl-private.hh",
+      "src/src/hb-shaper-list.hh",
+      "src/src/hb-shaper-private.hh",
+      "src/src/hb-shaper.cc",
+      "src/src/hb-string-array.hh",
+      "src/src/hb-subset-glyf.hh",
+      "src/src/hb-subset-plan.h",
+      "src/src/hb-subset-private.hh",
+      "src/src/hb-subset.h",
+      "src/src/hb-unicode-private.hh",
+      "src/src/hb-unicode.cc",
+      "src/src/hb-unicode.h",
+      "src/src/hb-utf-private.hh",
+      "src/src/hb-version.h",
+      "src/src/hb-warning.cc",
+      "src/src/hb.h",
     ]
 
     defines = [
@@ -208,8 +208,8 @@
 
     if (is_mac) {
       sources += [
-        "src/hb-coretext.cc",
-        "src/hb-coretext.h",
+        "src/src/hb-coretext.cc",
+        "src/src/hb-coretext.h",
       ]
       defines += [ "HAVE_CORETEXT" ]
       libs = [
@@ -222,8 +222,8 @@
     if (use_glib) {
       configs += [ "//build/config/linux:glib" ]
       sources += [
-        "src/hb-glib.cc",
-        "src/hb-glib.h",
+        "src/src/hb-glib.cc",
+        "src/src/hb-glib.h",
       ]
     }
   }
diff --git a/third_party/harfbuzz-ng/COPYING b/third_party/harfbuzz-ng/COPYING
deleted file mode 100644
index 9d1056f..0000000
--- a/third_party/harfbuzz-ng/COPYING
+++ /dev/null
@@ -1,36 +0,0 @@
-HarfBuzz is licensed under the so-called "Old MIT" license.  Details follow.
-For parts of HarfBuzz that are licensed under different licenses see individual
-files names COPYING in subdirectories where applicable.
-
-Copyright © 2010,2011,2012  Google, Inc.
-Copyright © 2012  Mozilla Foundation
-Copyright © 2011  Codethink Limited
-Copyright © 2008,2010  Nokia Corporation and/or its subsidiary(-ies)
-Copyright © 2009  Keith Stribley
-Copyright © 2009  Martin Hosken and SIL International
-Copyright © 2007  Chris Wilson
-Copyright © 2006  Behdad Esfahbod
-Copyright © 2005  David Turner
-Copyright © 2004,2007,2008,2009,2010  Red Hat, Inc.
-Copyright © 1998-2004  David Turner and Werner Lemberg
-
-For full copyright notices consult the individual files in the package.
-
-
-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.
diff --git a/third_party/harfbuzz-ng/NEWS b/third_party/harfbuzz-ng/NEWS
deleted file mode 100644
index 6b116e7..0000000
--- a/third_party/harfbuzz-ng/NEWS
+++ /dev/null
@@ -1,1832 +0,0 @@
-Overview of changes leading to 1.7.6
-Wednesday, March 7, 2018
-====================================
-
-- Fix to hb_set_t binary operations. Ouch.
-- New experimental harfbuzz-subset library. All of hb-subset.h
-  is experimental right now and API WILL change.
-
-- New API:
-hb_blob_copy_writable_or_fail()
-HB_OT_TAG_BASE
-hb_set_previous()
-hb_set_previous_range()
-
-
-Overview of changes leading to 1.7.5
-Tuesday, January 30, 2018
-====================================
-
-- Separate Khmer shaper from Indic.
-- First stab at AAT morx. Not hooked up.
-- Misc bug fixes.
-
-
-Overview of changes leading to 1.7.4
-Wednesday, December 20, 2017
-====================================
-
-- Fix collect_glyphs() regression caused by hb_set_t changes.
-
-
-Overview of changes leading to 1.7.3
-Monday, December 18, 2017
-====================================
-
-- hb_set_t performance tuning and optimizations.
-- Speed up collect_glyphs() and reject garbage data.
-- In hb_coretext_font_create() set font point-size (ptem).
-- Misc fixes.
-
-
-Overview of changes leading to 1.7.2
-Monday, December 4, 2017
-====================================
-
-- Optimize hb_set_add_range().
-- Misc fixes.
-- New API:
-hb_coretext_font_create()
-
-
-Overview of changes leading to 1.7.1
-Tuesday, November 14, 2017
-====================================
-
-- Fix atexit object destruction regression.
-- Fix minor integer-overflow.
-
-
-Overview of changes leading to 1.7.0
-Monday, November 13, 2017
-====================================
-
-- Minor Indic fixes.
-- Implement kerning and glyph names in hb-ot-font.
-- Various DSO optimization re .data and .bss sizes.
-- Make C++11 optional; build fixes.
-- Mark all other backends "unsafe-to-break".
-- Graphite fix.
-
-
-Overview of changes leading to 1.6.3
-Thursday, October 26th, 2017
-====================================
-
-- Fix hb_set_t some more.  Should be solid now.
-- Implement get_glyph_name() for hb-ot-font.
-- Misc fixes.
-
-
-Overview of changes leading to 1.6.2
-Monday, October 23nd, 2017
-====================================
-
-- Yesterday's release had a bad crasher; don't use it.  That's what
-  happens when one works on Sunday...
-  https://github.com/behdad/harfbuzz/issues/578
-- Build fixes for FreeBSD and Chrome Android.
-
-
-Overview of changes leading to 1.6.1
-Sunday, October 22nd, 2017
-====================================
-
-- Don't skip over COMBINING GRAPHEME JOINER when ligating, etc.
-  To be refined: https://github.com/behdad/harfbuzz/issues/554
-- Faster hb_set_t implementation.
-- Don't use deprecated ICU API.
-- Fix undefined-behavior in Myanmar shaper, introduced in 1.6.0
-- Deprecated API:
-  hb_set_invert()
-
-
-Overview of changes leading to 1.6.0
-Friday, October the 13th, 2017
-====================================
-
-- Update to Unicode 10.
-
-- Various Indic and Universal Shaping Engine fixes as a result of
-  HarfBuzz Hackfest with Jonathan Kew at Web Engines Hackfest at
-  the Igalia offices in A Coruña, Spain.  Thanks Igalia for having
-  us!
-
-- Implement Unicode Arabic Mark Ordering Algorithm UTR#53.
-
-- Implement optical sizing / tracking in CoreText backend, using
-  new API hb_font_set_ptem().
-
-- Allow notifying hb_font_t that underlying FT_Face changed sizing,
-  using new API hb_ft_font_changed().
-
-- More Graphite backend RTL fixes.
-
-- Fix caching of variable font shaping plans.
-
-- hb-view / hb-shape now accept following new arguments:
-
-  o --unicodes: takes a list of hex numbers that represent Unicode
-    codepoints.
-
-New API:
-+hb_face_get_table_tags()
-+hb_font_set_ptem()
-+hb_font_get_ptem()
-+hb_ft_font_changed()
-
-
-Overview of changes leading to 1.5.1
-Tuesday, September 5, 2017
-====================================
-
-- Fix "unsafe-to-break" in fallback shaping and other corner cases.
-  All our tests pass with --verify now, meaning unsafe-to-break API
-  works as expected.
-- Add --unicodes to hb-view / hb-shape.
-- [indic] Treat Consonant_With_Stacker as consonant.  This will need
-  further tweaking.
-- hb_buffer_diff() tweaks.
-
-
-Overview of changes leading to 1.5.0
-Wednesday, August 23, 2017
-====================================
-
-- Misc new API, for appending a buffer to another, and for comparing
-  contents of two buffers for types of differences.
-
-- New "unsafe-to-break" API.  Can be used to speed up reshaping
-  in line-breaking situations.  Essentially, after shaping, it returns
-  positions in the input string (some of the cluster boundaries) that
-  are "safe to break" in that if the text is segmented at that position
-  and two sides reshaped and concatenated, the shaping result is
-  exactly the same as shaping the text in one piece.
-
-  hb-view and hb-shape and hb-shape now take --verify, which verifies
-  the above property.
-
-  Some corner cases of the implementation are still not quite working.
-  Those will be fixed in subsequent releases.
-
-- New API:
-
-hb_buffer_append()
-
-hb_glyph_flags_t
-HB_GLYPH_FLAG_UNSAFE_TO_BREAK
-HB_GLYPH_FLAG_DEFINED
-hb_glyph_info_get_glyph_flags()
-
-HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS
-
-hb_buffer_diff_flags_t
-HB_BUFFER_DIFF_FLAG_EQUAL
-HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH
-HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH
-HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT
-HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
-HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH
-HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH
-HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH
-HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH
-hb_buffer_diff
-
-
-Overview of changes leading to 1.4.8
-Tuesday, August 8, 2017
-====================================
-
-- Major fix to avar table handling.
-- Rename hb-shape --show-message to --trace.
-- Build fixes.
-
-
-Overview of changes leading to 1.4.7
-Tuesday, July 18, 2017
-====================================
-
-- Multiple Indic, Tibetan, and Cham fixes.
-- CoreText: Allow disabling kerning.
-- Adjust Arabic feature order again.
-- Misc build fixes.
-
-
-Overview of changes leading to 1.4.6
-Sunday, April 23, 2017
-====================================
-
-- Graphite2: Fix RTL positioning issue.
-- Backlist GDEF of more versions of Padauk and Tahoma.
-- New, experimental, cmake alternative build system.
-
-
-Overview of changes leading to 1.4.5
-Friday, March 10, 2017
-====================================
-
-- Revert "Fix Context lookup application when moving back after a glyph..."
-  This introduced memory access problems.  To be fixed properly soon.
-
-
-Overview of changes leading to 1.4.4
-Sunday, March 5, 2017
-====================================
-
-- Fix Context lookup application when moving back after a glyph deletion.
-- Fix buffer-overrun in Bengali.
-
-
-Overview of changes leading to 1.4.3
-Saturday, February 25, 2017
-====================================
-
-- Route Adlam script to Arabic shaper.
-- Misc fixes.
-- New API:
-  hb_font_set_face()
-- Deprecate API:
-  hb_graphite2_font_get_gr_font()
-
-
-Overview of changes leading to 1.4.2
-Monday, January 23, 2017
-====================================
-
-- Implement OpenType Font Variation tables avar/fvar/HVAR/VVAR.
-- hb-shape and hb-view now accept --variations.
-- New API:
-
-hb_variation_t
-hb_variation_from_string()
-hb_variation_to_string()
-
-hb_font_set_variations()
-hb_font_set_var_coords_design()
-hb_font_get_var_coords_normalized()
-
-hb-ot-var.h:
-hb_ot_var_axis_t
-hb_ot_var_has_data()
-hb_ot_var_get_axis_count()
-hb_ot_var_get_axes()
-hb_ot_var_find_axis()
-hb_ot_var_normalize_variations()
-hb_ot_var_normalize_coords()
-
-- MVAR to be implemented later.  Access to named instances to be
-  implemented later as well.
-
-- Misc fixes.
-
-
-Overview of changes leading to 1.4.1
-Thursday, January 5, 2017
-====================================
-
-- Always build and use UCDN for Unicode data by default.
-  Reduces dependence on version of Unicode data in glib,
-  specially in the Windows bundles we are shipping, which
-  have very old glib.
-
-
-Overview of changes leading to 1.4.0
-Thursday, January 5, 2017
-====================================
-
-- Merged "OpenType GX" branch which adds core of support for
-  OpenType 1.8 Font Variations.  To that extent, the relevant
-  new API is:
-
-New API:
-hb_font_set_var_coords_normalized()
-
-  with supporting API:
-
-New API:
-HB_OT_LAYOUT_NO_VARIATIONS_INDEX
-hb_ot_layout_table_find_feature_variations()
-hb_ot_layout_feature_with_variations_get_lookups()
-hb_shape_plan_create2()
-hb_shape_plan_create_cached2()
-
-  Currently variations in GSUB/GPOS/GDEF are fully supported,
-  and no other tables are supported.  In particular, fvar/avar
-  are NOT supported, hence the hb_font_set_var_coords_normalized()
-  taking normalized coordinates.  API to take design coordinates
-  will be added in the future.
-
-  HVAR/VVAR/MVAR support will also be added to hb-ot-font in the
-  future.
-
-- Fix regression in GDEF glyph class processing.
-- Add decompositions for Chakma, Limbu, and Balinese in USE shaper.
-- Misc fixes.
-
-
-Overview of changes leading to 1.3.4
-Monday, December 5, 2016
-====================================
-
-- Fix vertical glyph origin in hb-ot-font.
-- Implement CBDT/CBLC color font glyph extents in hb-ot-font.
-
-
-Overview of changes leading to 1.3.3
-Wednesday, September 28, 2016
-====================================
-
-- Implement parsing of OpenType MATH table.
-New API:
-HB_OT_TAG_MATH
-HB_OT_MATH_SCRIPT
-hb_ot_math_constant_t
-hb_ot_math_kern_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
-hb_ot_math_get_glyph_top_accent_attachment
-hb_ot_math_get_glyph_kerning
-hb_ot_math_is_glyph_extended_shape
-hb_ot_math_get_glyph_variants
-hb_ot_math_get_min_connector_overlap
-hb_ot_math_get_glyph_assembly
-
-
-Overview of changes leading to 1.3.2
-Wednesday, September 27, 2016
-====================================
-
-- Fix build of hb-coretext on older OS X versions.
-
-
-Overview of changes leading to 1.3.1
-Wednesday, September 7, 2016
-====================================
-
-- Blacklist bad GDEF of more fonts (Padauk).
-- More CoreText backend crash fixes with OS X 10.9.5.
-- Misc fixes.
-
-
-Overview of changes leading to 1.3.0
-Thursday, July 21, 2016
-====================================
-
-- Update to Unicode 9.0.0
-- Move Javanese from Indic shaper to Universal Shaping Engine.
-- Allow MultipleSubst to delete a glyph (matching Windows engine).
-- Update Universal Shaping Engine to latest draft from Microsoft.
-- DirectWrite backend improvements.  Note: this backend is for testing ONLY.
-- CoreText backend improvements with unreachable fonts.
-- Implement symbol fonts (cmap 3.0.0) in hb-ft and hb-ot-font.
-- Blacklist bad GDEF of more fonts (Tahoma & others).
-- Misc fixes.
-
-
-Overview of changes leading to 1.2.7
-Monday, May 2, 2016
-====================================
-
-- Blacklist another version of Times New Roman (Bold) Italic from Windows 7.
-- Fix Mongolian Free Variation Selectors shaping with certain fonts.
-- Fix Tibetan shorthand contractions shaping.
-- Improved list of language tag mappings.
-- Unbreak build on Windows CE.
-- Make 'glyf' table loading lazy in hb-ot-font.
-
-
-Overview of changes leading to 1.2.6
-Friday, April 8, 2016
-====================================
-
-- Blacklist GDEF table of another set of Times New Roman (Bold) Italic.
-- DirectWrite backend improvements.  Note: DirectWrite backend is
-  exclusively for our internal testing and should NOT be used in any
-  production system whatsoever.
-
-
-Overview of changes leading to 1.2.5
-Monday, April 4, 2016
-====================================
-
-- Fix GDEF mark-filtering-set, which was broken in 1.2.3.
-
-
-Overview of changes leading to 1.2.4
-Thursday, March 17, 2016
-====================================
-
-- Synthesize GDEF glyph class for any glyph that does not have one in GDEF.
-  I really hope we don't discover broken fonts that shape badly with this
-  change.
-- Misc build and other minor fixes.
-- API changes:
-  - Added HB_NDEBUG.  It's fine for production systems to define this to
-    disable high-overhead debugging checks.  However, I also reduced the
-    overhead of those checks, so it's a non-issue right now.  You can
-    forget it.  Just not defining anything at all is fine.
-
-
-Overview of changes leading to 1.2.3
-Thursday, February 25, 2016
-====================================
-
-- Blacklist GDEF table of certain versions of Times New Roman (Bold) Italic,
-  due to bug in glyph class of ASCII double-quote character.  This should
-  address "regression" introduced in 1.2.0 when we switched mark zeroing
-  in most shapers from BY_UNICODE_LATE to BY_GDEF_LATE.
-  This fourth release in a week should finally stablize things...
-
-- hb-ot-font's get_glyph() implementation saw some optimizations.  Though,
-  might be really hard to measure in real-world situations.
-
-- Also, two rather small API changes:
-
-We now disable some time-consuming internal bookkeeping if built with NDEBUG
-defined.  This is a first time that we use NDEBUG to disable debug code.  If
-there exist production systems that do NOT want to enable NDEBUG, please let
-me know and I'll add HB_NDEBUG.
-
-Added get_nominal_glyph() and get_variation_glyph() instead of get_glyph()
-
-New API:
-- hb_font_get_nominal_glyph_func_t
-- hb_font_get_variation_glyph_func_t
-- hb_font_funcs_set_nominal_glyph_func()
-- hb_font_funcs_set_variation_glyph_func()
-- hb_font_get_nominal_glyph()
-- hb_font_get_variation_glyph()
-
-Deprecated API:
-- hb_font_get_glyph_func_t
-- hb_font_funcs_set_glyph_func()
-
-Clients that implement their own font-funcs are encouraged to replace
-their get_glyph() implementation with a get_nominal_glyph() and
-get_variation_glyph() pair.  The variation version can assume that
-variation_selector argument is not zero.  Old (deprecated) functions
-will continue working indefinitely using internal gymnastics; it is
-just more efficient to use the new functions.
-
-
-Overview of changes leading to 1.2.2
-Wednesday, February 24, 2016
-====================================
-
-- Fix regression with mark positioning with fonts that have
-  non-zero mark advances.  This was introduced in 1.2.0 while
-  trying to make mark and cursive attachments to work together.
-  I have partially reverted that, so this version is much more
-  like what we had before.  All clients who updated to 1.2.0
-  should update to this version.
-
-
-Overview of changes leading to 1.2.1
-Tuesday, February 23, 2016
-====================================
-
-- CoreText: Fix bug with wrong scale if font scale was changed later.
-  https://github.com/libass/libass/issues/212
-- CoreText: Drastically speed up font initialization.
-- CoreText: Fix tiny leak.
-- Group ZWJ/ZWNJ with previous syllable under cluster-level=0.
-  https://github.com/behdad/harfbuzz/issues/217
-- Add test/shaping/README.md about how to add tests to the suite.
-
-
-Overview of changes leading to 1.2.0
-Friday, February 19, 2016
-====================================
-
-- Fix various issues (hangs mostly) in case of memory allocation failure.
-- Change mark zeroing types of most shapers from BY_UNICODE_LATE to
-  BY_GDEF_LATE.  This seems to be what Uniscribe does.
-- Change mark zeroing of USE shaper from NONE to BY_GDEF_EARLY.  That's
-  what Windows does.
-- Allow GPOS cursive connection on marks, and fix the interaction with
-  mark attachment.  This work resulted in some changes to how mark
-  attachments work.  See:
-  https://github.com/behdad/harfbuzz/issues/211
-  https://github.com/behdad/harfbuzz/commit/86c68c7a2c971efe8e35b1f1bd99401dc8b688d2
-- Graphite2 shaper: improved negative advance handling (eg. Nastaliq).
-- Add nmake-based build system for Windows.
-- Minor speedup.
-- Misc. improvements.
-
-
-Overview of changes leading to 1.1.3
-Monday, January 11, 2016
-====================================
-
-- Ported Indic shaper to Unicode 8.0 data.
-- Universal Shaping Engine fixes.
-- Speed up CoreText shaper when font fallback happens in CoreText.
-- Documentation improvements, thanks to Khaled Hosny.
-- Very rough directwrite shaper for testing, thanks to Ebrahim Byagowi.
-- Misc bug fixes.
-- New API:
-
-  * Font extents:
-      hb_font_extents_t
-      hb_font_get_font_extents_func_t
-      hb_font_get_font_h_extents_func_t
-      hb_font_get_font_v_extents_func_t
-      hb_font_funcs_set_font_h_extents_func
-      hb_font_funcs_set_font_v_extents_func
-      hb_font_get_h_extents
-      hb_font_get_v_extents
-      hb_font_get_extents_for_direction
-
-  * Buffer message (aka debug):
-      hb_buffer_message_func_t
-      hb_buffer_set_message_func()
-    Actual message protocol to be fleshed out later.
-
-
-Overview of changes leading to 1.1.2
-Wednesday, November 26, 2015
-====================================
-
-- Fix badly-broken fallback shaper that affected terminology.
-  https://github.com/behdad/harfbuzz/issues/187
-- Fix y_scaling in Graphite shaper.
-- API changes:
-  * An unset glyph_h_origin() function in font-funcs now (sensibly)
-    implies horizontal origin at 0,0.  Ie, the nil callback returns
-    true instead of false.  As such, implementations that have a
-    glyph_h_origin() that simply returns true, can remove that function
-    with HarfBuzz >= 1.1.2.  This results in a tiny speedup.
-
-
-Overview of changes leading to 1.1.1
-Wednesday, November 24, 2015
-====================================
-
-- Build fixes, specially for hb-coretext.
-
-
-Overview of changes leading to 1.1.0
-Wednesday, November 18, 2015
-====================================
-
-- Implement 'stch' stretch feature for Syriac Abbreviation Mark.
-  https://github.com/behdad/harfbuzz/issues/141
-- Disable use of decompose_compatibility() callback.
-- Implement "shaping" of various Unicode space characters, even
-  if the font does not support them.
-  https://github.com/behdad/harfbuzz/issues/153
-- If font does not support U+2011 NO-BREAK HYPHEN, fallback to
-  U+2010 HYPHEN.
-- Changes resulting from libFuzzer continuous fuzzing:
-  * Reject font tables that need more than 8 edits,
-  * Bound buffer growth during shaping to 32x,
-  * Fix assertions and other issues at OOM / buffer max-growth.
-- Misc fixes and optimizations.
-- API changes:
-  * All fonts created with hb_font_create() now inherit from
-    (ie. have parent) hb_font_get_empty().
-
-
-Overview of changes leading to 1.0.6
-Thursday, October 15, 2015
-====================================
-
-- Reduce max nesting level in OT lookups from 8 to 6.
-  Should not affect any real font as far as I know.
-- Fix memory access issue in ot-font.
-- Revert default load-flags of fonts created using hb_ft_font_create()
-  back to FT_LOAD_DEFAULT|FT_LOAD_NO_HINTING.  This was changed in
-  last release (1.0.5), but caused major issues, so revert.
-  https://github.com/behdad/harfbuzz/issues/143
-
-
-Overview of changes leading to 1.0.5
-Tuesday, October 13, 2015
-====================================
-
-- Fix multiple memory access bugs discovered using libFuzzer.
-  https://github.com/behdad/harfbuzz/issues/139
-  Everyone should upgrade to this version as soon as possible.
-  We now have continuous fuzzing set up, to avoid issues like
-  these creeping in again.
-- Misc fixes.
-
-- New API:
-  * hb_font_set_parent().
-  * hb_ft_font_[sg]et_load_flags()
-    The default flags for fonts created using hb_ft_font_create()
-    has changed to default to FT_LOAD_DEFAULT now.  Previously it
-    was defaulting to FT_LOAD_DFEAULT|FT_LOAD_NO_HINTING.
-
-- API changes:
-  * Fonts now default to units-per-EM as their scale, instead of 0.
-  * hb_font_create_sub_font() does NOT make parent font immutable
-    anymore.  hb_font_make_immutable() does.
-
-
-Overview of changes leading to 1.0.4
-Wednesday, September 30, 2015
-====================================
-
-- Fix minor out-of-bounds read error.
-
-
-Overview of changes leading to 1.0.3
-Tuesday, September 1, 2015
-====================================
-
-- Start of user documentation, from Simon Cozens!
-- Implement glyph_extents() for TrueType fonts in hb-ot-font.
-- Improve GPOS cursive attachments with conflicting lookups.
-- More fixes for cluster-level = 1.
-- Uniscribe positioning fix.
-
-
-Overview of changes leading to 1.0.2
-Wednesday, August 19, 2015
-====================================
-
-- Fix shaping with cluster-level > 0.
-- Fix Uniscribe backend font-size scaling.
-- Declare dependencies in harfbuzz.pc.
-  FreeType is not declared though, to avoid bugs in pkg-config
-  0.26 with recursive dependencies.
-- Slightly improved debug infrastructure.  More to come later.
-- Misc build fixes.
-
-
-Overview of changes leading to 1.0.1
-Monday, July 27, 2015
-====================================
-
-- Fix out-of-bounds access in USE shaper.
-
-
-Overview of changes leading to 1.0.0
-Sunday, July 26, 2015
-====================================
-
-- Implement Universal Shaping Engine:
-  https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm
-  http://blogs.windows.com/bloggingwindows/2015/02/23/windows-shapes-the-worlds-languages/
-- Bump version to 1.0.0.  The soname was NOT bumped.
-
-
-Overview of changes leading to 0.9.42
-Thursday, July 26, 2015
-=====================================
-
-- New API to allow for retrieving finer-grained cluster
-  mappings if the client desires to handle them.  Default
-  behavior is unchanged.
-- Fix cluster merging when removing default-ignorables.
-- Update to Unicode 8.0
-- hb-graphite2 fixes.
-- Misc fixes.
-- Removed HB_NO_MERGE_CLUSTERS hack.
-- New API:
-  hb_buffer_cluster_level_t enum
-  hb_buffer_get_cluster_level()
-  hb_buffer_set_cluster_level()
-  hb-shape / hb-view --cluster-level
-
-
-Overview of changes leading to 0.9.41
-Thursday, June 18, 2015
-=====================================
-
-- Fix hb-coretext with trailing whitespace in right-to-left.
-- New API: hb_buffer_reverse_range().
-- Allow implementing atomic ops in config.h.
-- Fix hb_language_t in language bindings.
-- Misc fixes.
-
-
-Overview of changes leading to 0.9.40
-Friday, March 20, 2015
-=====================================
-
-- Another hb-coretext crasher fix.  Ouch!
-- Happy Norouz!
-
-
-Overview of changes leading to 0.9.39
-Wednesday, March 4, 2015
-=====================================
-
-- Critical hb-coretext fixes.
-- Optimizations and refactoring; no functional change
-  expected.
-- Misc build fixes.
-
-
-Overview of changes leading to 0.9.38
-Friday, January 23, 2015
-=====================================
-
-- Fix minor out-of-bounds access in Indic shaper.
-- Change New Tai Lue shaping engine from South-East Asian to default,
-  reflecting change in Unicode encoding model.
-- Add hb-shape --font-size.  Can take up to two numbers for separate
-  x / y size.
-- Fix CoreText and FreeType scale issues with negative scales.
-- Reject blobs larger than 2GB.  This might break some icu-le-hb clients
-  that need security fixes.  See:
-  http://www.icu-project.org/trac/ticket/11450
-- Avoid accessing font tables during face destruction, in casce rogue
-  clients released face data already.
-- Fix up gobject-introspection a bit.  Python bindings kinda working.
-  See README.python.
-- Misc fixes.
-- API additions:
-  hb_ft_face_create_referenced()
-  hb_ft_font_create_referenced()
-
-
-Overview of changes leading to 0.9.37
-Wednesday, December 17, 2014
-=====================================
-
-- Fix out-of-bounds access in Context lookup format 3.
-- Indic: Allow ZWJ/ZWNJ before syllable modifiers.
-
-
-Overview of changes leading to 0.9.36
-Thursday, November 20, 2014
-=====================================
-
-- First time that three months went by without a release since
-  0.9.2 was released on August 10, 2012!
-- Fix performance bug in hb_ot_collect_glyphs():
-  https://bugzilla.mozilla.org/show_bug.cgi?id=1090869
-- Add basic vertical-text support to hb-ot-font.
-- Misc build fixes.
-
-
-Overview of changes leading to 0.9.35
-Saturday, August 13, 2014
-=====================================
-
-- Fix major shape-plan caching bug when more than one shaper were
-  provided to hb_shape_full() (as exercised by XeTeX).
-  http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg1246370.html
-- Fix Arabic fallback shaping regression.  This was broken in 0.9.32.
-- Major hb-coretext fixes.  That backend is complete now, including
-  respecing buffer direction and language, down to vertical writing.
-- Build fixes for Windows CE.  Should build fine now.
-- Misc fixes:
-  Use atexit() only if it's safe to call from shared library
-  https://bugs.freedesktop.org/show_bug.cgi?id=82246
-  Mandaic had errors in its Unicode Joining_Type
-  https://bugs.freedesktop.org/show_bug.cgi?id=82306
-- API changes:
-
-  * hb_buffer_clear_contents() does not reset buffer flags now.
-
-    After 763e5466c0a03a7c27020e1e2598e488612529a7, one doesn't
-    need to set flags for different pieces of text.  The flags now
-    are something the client sets up once, depending on how it
-    actually uses the buffer.  As such, don't clear it in
-    clear_contents().
-
-    I don't expect any changes to be needed to any existing client.
-
-
-Overview of changes leading to 0.9.34
-Saturday, August 2, 2014
-=====================================
-
-- hb_feature_from_string() now accepts CSS font-feature-settings format.
-- As a result, hb-shape / hb-view --features also accept CSS-style strings.
-  Eg, "'liga' off" is accepted now.
-- Add old-spec Myanmar shaper:
-  https://bugs.freedesktop.org/show_bug.cgi?id=81775
-- Don't apply 'calt' in Hangul shaper.
-- Fix mark advance zeroing for Hebrew shaper:
-  https://bugs.freedesktop.org/show_bug.cgi?id=76767
-- Implement Windows-1256 custom Arabic shaping.  Only built on Windows,
-  and requires help from get_glyph().  Used by Firefox.
-  https://bugzilla.mozilla.org/show_bug.cgi?id=1045139
-- Disable 'liga' in vertical text.
-- Build fixes.
-- API changes:
-
-  * Make HB_BUFFER_FLAG_BOT/EOT easier to use.
-
-    Previously, we expected users to provide BOT/EOT flags when the
-    text *segment* was at paragraph boundaries.  This meant that for
-    clients that provide full paragraph to HarfBuzz (eg. Pango), they
-    had code like this:
-
-      hb_buffer_set_flags (hb_buffer,
-                           (item_offset == 0 ? HB_BUFFER_FLAG_BOT : 0) |
-                           (item_offset + item_length == paragraph_length ?
-                            HB_BUFFER_FLAG_EOT : 0));
-
-      hb_buffer_add_utf8 (hb_buffer,
-                          paragraph_text, paragraph_length,
-                          item_offset, item_length);
-
-    After this change such clients can simply say:
-
-      hb_buffer_set_flags (hb_buffer,
-                           HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT);
-
-      hb_buffer_add_utf8 (hb_buffer,
-                          paragraph_text, paragraph_length,
-                          item_offset, item_length);
-
-    Ie, HarfBuzz itself checks whether the segment is at the beginning/end
-    of the paragraph.  Clients that only pass item-at-a-time to HarfBuzz
-    continue not setting any flags whatsoever.
-
-    Another way to put it is: if there's pre-context text in the buffer,
-    HarfBuzz ignores the BOT flag.  If there's post-context, it ignores
-    EOT flag.
-
-
-Overview of changes leading to 0.9.33
-Tuesday, July 22, 2014
-=====================================
-
-- Turn off ARabic 'cswh' feature that was accidentally turned on.
-- Add HB_TAG_MAX_SIGNED.
-- Make hb_face_make_immutable() really make face immutable!
-- Windows build fixes.
-
-
-Overview of changes leading to 0.9.32
-Thursday, July 17, 2014
-=====================================
-
-- Apply Arabic shaping features in spec order exactly.
-- Another fix for Mongolian free variation selectors.
-- For non-Arabic scripts in Arabic shaper apply 'rlig' and 'calt'
-  together.
-- Minor adjustment to U+FFFD logic.
-- Fix hb-coretext build.
-
-
-Overview of changes leading to 0.9.31
-Wednesday, July 16, 2014
-=====================================
-
-- Only accept valid UTF-8/16/32; we missed many cases before.
-- Better shaping of invalid UTF-8/16/32.  Falls back to
-  U+FFFD REPLACEMENT CHARACTER now.
-- With all changes in this release, the buffer will contain fully
-  valid Unicode after hb_buffer_add_utf8/16/32 no matter how
-  broken the input is.  This can be overriden though.  See below.
-- Fix Mongolian Variation Selectors for fonts without GDEF.
-- Fix minor invalid buffer access.
-- Accept zh-Hant and zh-Hans language tags.  hb_ot_tag_to_language()
-  now uses these instead of private tags.
-- Build fixes.
-- New API:
-  * hb_buffer_add_codepoints().  This does what hb_buffer_add_utf32()
-    used to do, ie. no validity check on the input at all.  add_utf32
-    now replaces invalid Unicode codepoints with the replacement
-    character (see below).
-  * hb_buffer_set_replacement_codepoint()
-  * hb_buffer_get_replacement_codepoint()
-    Previously, in hb_buffer_add_utf8 and hb_buffer_add_utf16, when
-    we detected broken input, we replaced that with (hb_codepoint_t)-1.
-    This has changed to use U+FFFD now, but can be changed using these
-    new API.
-
-
-Overview of changes leading to 0.9.30
-Wednesday, July 9, 2014
-=====================================
-
-- Update to Unicode 7.0.0:
-  * New scripts Manichaean and Psalter Pahlavi are shaped using
-    Arabic shaper.
-  * All the other new scripts to through the generic shaper for
-    now.
-- Minor Indic improvements.
-- Fix graphite2 backend cluster mapping [crasher!]
-- API changes:
-  * New HB_SCRIPT_* values for Unicode 7.0 scripts.
-  * New function hb_ot_layout_language_get_required_feature().
-- Build fixes.
-
-
-Overview of changes leading to 0.9.29
-Thursday, May 29, 2014
-=====================================
-
-- Implement cmap in hb-ot-font.h.  No variation-selectors yet.
-- Myanmar: Allow MedialYa+Asat.
-- Various Indic fixes:
-  * Support most characters in Extended Devanagary and Vedic
-    Unicode blocks.
-  * Allow digits and a some punctuation as consonant placeholders.
-- Build fixes.
-
-
-Overview of changes leading to 0.9.28
-Monday, April 28, 2014
-=====================================
-
-- Unbreak old-spec Indic shaping. (bug 76705)
-- Fix shaping of U+17DD and U+0FC6.
-- Add HB_NO_MERGE_CLUSTERS build option.  NOT to be enabled by default
-  for shipping libraries.  It's an option for further experimentation
-  right now.  When we are sure how to do it properly, we will add
-  public run-time API for the functionality.
-- Build fixes.
-
-
-Overview of changes leading to 0.9.27
-Tuesday, March 18, 2014
-=====================================
-
-- Don't use "register" storage class specifier
-- Wrap definition of free_langs() with HAVE_ATEXIT
-- Add coretext_aat shaper and hb_coretext_face_create() constructor
-- If HAVE_ICU_BUILTIN is defined, use hb-icu Unicode callbacks
-- Add Myanmar test case from OpenType Myanmar spec
-- Only do fallback Hebrew composition if no GPOS 'mark' available
-- Allow bootstrapping without gtk-doc
-- Use AM_MISSING_PROG for ragel and git
-- Typo in ucdn's Makefile.am
-- Improve MemoryBarrier() implementation
-
-
-Overview of changes leading to 0.9.26
-Thursday, January 30, 2014
-=====================================
-
-- Misc fixes.
-- Fix application of 'rtlm' feature.
-- Automatically apply frac/numr/dnom around U+2044 FRACTION SLASH.
-- New header: hb-ot-shape.h
-- Uniscribe: fix scratch-buffer accounting.
-- Reorder Tai Tham SAKOT to after tone-marks.
-- Add Hangul shaper.
-- New files:
-  hb-ot-shape-complex-hangul.cc
-  hb-ot-shape-complex-hebrew.cc
-  hb-ot-shape-complex-tibetan.cc
-- Disable 'cswh' feature in Arabic shaper.
-- Coretext: better handle surrogate pairs.
-- Add HB_TAG_MAX and _HB_SCRIPT_MAX_VALUE.
-
-
-Overview of changes leading to 0.9.25
-Wednesday, December 4, 2013
-=====================================
-
-- Myanmar shaper improvements.
-- Avoid font fallback in CoreText backend.
-- Additional OpenType language tag mappiongs.
-- More aggressive shape-plan caching.
-- Build with / require automake 1.13.
-- Build with libtool 2.4.2.418 alpha to support ppc64le.
-
-
-Overview of changes leading to 0.9.24
-Tuesday, November 13, 2013
-=====================================
-
-- Misc compiler warning fixes with clang.
-- No functional changes.
-
-
-Overview of changes leading to 0.9.23
-Monday, October 28, 2013
-=====================================
-
-- "Udupi HarfBuzz Hackfest", Paris, October 14..18 2013.
-- Fix (Chain)Context recursion with non-monotone lookup positions.
-- Misc Indic bug fixes.
-- New Javanese / Buginese shaping, similar to Windows 8.1.
-
-
-Overview of changes leading to 0.9.22
-Thursday, October 3, 2013
-=====================================
-
-- Fix use-after-end-of-scope in hb_language_from_string().
-- Fix hiding of default_ignorables if font doesn't have space glyph.
-- Protect against out-of-range lookup indices.
-
-- API Changes:
-
-  * Added hb_ot_layout_table_get_lookup_count()
-
-
-Overview of changes leading to 0.9.21
-Monday, September 16, 2013
-=====================================
-
-- Rename gobject-introspection library name from harfbuzz to HarfBuzz.
-- Remove (long disabled) hb-old and hb-icu-le test shapers.
-- Misc gtk-doc and gobject-introspection annotations.
-- Misc fixes.
-- API changes:
-
-  * Add HB_SET_VALUE_INVALID
-
-Overview of changes leading to 0.9.20
-Thursday, August 29, 2013
-=====================================
-
-General:
-- Misc substitute_closure() fixes.
-- Build fixes.
-
-Documentation:
-- gtk-doc boilerplate integrated.  Docs are built now, but
-  contain no contents.  By next release hopefully we have
-  some content in.  Enable using --enable-gtk-doc.
-
-GObject and Introspection:
-- Added harfbuzz-gobject library (hb-gobject.h) that has type
-  bindings for all HarfBuzz objects and enums.  Enable using
-  --with-gobject.
-- Added gobject-introspection boilerplate.  Nothing useful
-  right now.  Work in progress.  Gets enabled automatically if
-  --with-gobject is used.  Override with --disable-introspection.
-
-OpenType shaper:
-- Apply 'mark' in Myanmar shaper.
-- Don't apply 'dlig' by default.
-
-Uniscribe shaper:
-- Support user features.
-- Fix loading of fonts that are also installed on the system.
-- Fix shaping of Arabic Presentation Forms.
-- Fix build with wide chars.
-
-CoreText shaper:
-- Support user features.
-
-Source changes:
-- hb_face_t code moved to hb-face.h / hb-face.cc.
-- Added hb-deprecated.h.
-
-API changes:
-- Added HB_DISABLE_DEPRECATED.
-- Deprecated HB_SCRIPT_CANADIAN_ABORIGINAL; replaced by
-  HB_SCRIPT_CANADIAN_SYLLABICS.
-- Deprecated HB_BUFFER_FLAGS_DEFAULT; replaced by
-  HB_BUFFER_FLAG_DEFAULT.
-- Deprecated HB_BUFFER_SERIALIZE_FLAGS_DEFAULT; replaced by
-  HB_BUFFER_SERIALIZE_FLAG_DEFAULT.
-
-
-Overview of changes leading to 0.9.19
-Tuesday, July 16, 2013
-=====================================
-
-- Build fixes.
-- Better handling of multiple variation selectors in a row.
-- Pass on variation selector to GSUB if not consumed by cmap.
-- Fix undefined memory access.
-- Add Javanese config to Indic shaper.
-- Misc bug fixes.
-
-Overview of changes leading to 0.9.18
-Tuesday, May 28, 2013
-=====================================
-
-New build system:
-
-- All unneeded code is all disabled by default,
-
-- Uniscribe and CoreText shapers can be enabled with their --with options,
-
-- icu_le and old shapers cannot be enabled for now,
-
-- glib, freetype, and cairo will be detected automatically.
-  They can be force on/off'ed with their --with options,
-
-- icu and graphite2 are default off, can be enabled with their --with
-  options,
-
-Moreover, ICU support is now build into a separate library:
-libharfbuzz-icu.so, and a new harfbuzz-icu.pc is shipped for it.
-Distros can enable ICU now without every application on earth
-getting linked to via libharfbuzz.so.
-
-For distros I recommend that they make sure they are building --with-glib
---with-freetype --with-cairo, --with-icu, and optionally --with-graphite2;
-And package harfbuzz and harfbuzz-icu separately.
-
-
-Overview of changes leading to 0.9.17
-Monday, May 20, 2013
-=====================================
-
-- Build fixes.
-- Fix bug in hb_set_get_min().
-- Fix regression with Arabic mark positioning / width-zeroing.
-
-Overview of changes leading to 0.9.16
-Friday, April 19, 2013
-=====================================
-
-- Major speedup in OpenType lookup processing.  With the Amiri
-  Arabic font, this release is over 3x faster than previous
-  release.  All scripts / languages should see this speedup.
-
-- New --num-iterations option for hb-shape / hb-view; useful for
-  profiling.
-
-Overview of changes leading to 0.9.15
-Friday, April 05, 2013
-=====================================
-
-- Build fixes.
-- Fix crasher in graphite2 shaper.
-- Fix Arabic mark width zeroing regression.
-- Don't compose Hangul jamo into Unicode syllables.
-
-
-Overview of changes leading to 0.9.14
-Thursday, March 21, 2013
-=====================================
-
-- Build fixes.
-- Fix time-consuming sanitize with malicious fonts.
-- Implement hb_buffer_deserialize_glyphs() for both json and text.
-- Do not ignore Hangul filler characters.
-- Indic fixes:
-  * Fix Malayalam pre-base reordering interaction with post-forms.
-  * Further adjust ZWJ handling.  Should fix known regressions from
-    0.9.13.
-
-
-Overview of changes leading to 0.9.13
-Thursday, February 25, 2013
-=====================================
-
-- Build fixes.
-- Ngapi HarfBuzz Hackfest in London (February 2013):
-  * Fixed all known Indic bugs,
-  * New Win8-style Myanmar shaper,
-  * New South-East Asian shaper for Tai Tham, Cham, and New Tai Lue,
-  * Smartly ignore Default_Ignorable characters (joiners, etc) wheb
-    matching GSUB/GPOS lookups,
-  * Fix 'Phags-Pa U+A872 shaping,
-  * Fix partial disabling of default-on features,
-  * Allow disabling of TrueType kerning.
-- Fix possible crasher with broken fonts with overlapping tables.
-- Removed generated files from git again.  So, one needs ragel to
-  bootstrap from the git tree.
-
-API changes:
-- hb_shape() and related APIs now abort if buffer direction is
-  HB_DIRECTION_INVALID.  Previously, hb_shape() was calling
-  hb_buffer_guess_segment_properties() on the buffer before
-  shaping.  The heuristics in that function are fragile.  If the
-  user really wants the old behvaior, they can call that function
-  right before calling hb_shape() to get the old behavior.
-- hb_blob_create_sub_blob() always creates sub-blob with
-  HB_MEMORY_MODE_READONLY.  See comments for the reason.
-
-
-Overview of changes leading to 0.9.12
-Thursday, January 18, 2013
-=====================================
-
-- Build fixes for Sun compiler.
-- Minor bug fix.
-
-Overview of changes leading to 0.9.11
-Thursday, January 10, 2013
-=====================================
-
-- Build fixes.
-- Fix GPOS mark attachment with null Anchor offsets.
-- [Indic] Fix old-spec reordering of viramas if sequence ends in one.
-- Fix multi-threaded shaper data creation crash.
-- Add atomic ops for Solaris.
-
-API changes:
-- Rename hb_buffer_clear() to hb_buffer_clear_contents().
-
-
-Overview of changes leading to 0.9.10
-Thursday, January 3, 2013
-=====================================
-
-- [Indic] Fixed rendering of Malayalam dot-reph
-- Updated OT language tags.
-- Updated graphite2 backend.
-- Improved hb_ot_layout_get_size_params() logic.
-- Improve hb-shape/hb-view help output.
-- Fixed hb-set.h implementation to not crash.
-- Fixed various issues with hb_ot_layout_collect_lookups().
-- Various build fixes.
-
-New API:
-
-hb_graphite2_face_get_gr_face()
-hb_graphite2_font_get_gr_font()
-hb_coretext_face_get_cg_font()
-
-Modified API:
-
-hb_ot_layout_get_size_params()
-
-
-Overview of changes leading to 0.9.9
-Wednesday, December 5, 2012
-====================================
-
-- Fix build on Windows.
-- Minor improvements.
-
-
-Overview of changes leading to 0.9.8
-Tuesday, December 4, 2012
-====================================
-
-
-- Actually implement hb_shape_plan_get_shaper ().
-- Make UCDB data tables const.
-- Lots of internal refactoring in OTLayout tables.
-- Flesh out hb_ot_layout_lookup_collect_glyphs().
-
-New API:
-
-hb_ot_layout_collect_lookups()
-hb_ot_layout_get_size_params()
-
-
-Overview of changes leading to 0.9.7
-Sunday, November 21, 2012
-====================================
-
-
-HarfBuzz "All-You-Can-Eat-Sushi" (aka Vancouver) Hackfest and follow-on fixes.
-
-- Fix Arabic contextual joining using pre-context text.
-- Fix Sinhala "split matra" mess.
-- Fix Khmer shaping with broken fonts.
-- Implement Thai "PUA" shaping for old fonts.
-- Do NOT route Kharoshthi script through the Indic shaper.
-- Disable fallback positioning for Indic and Thai shapers.
-- Misc fixes.
-
-
-hb-shape / hb-view changes:
-
-- Add --text-before and --text-after
-- Add --bot / --eot / --preserve-default-ignorables
-- hb-shape --output-format=json
-
-
-New API:
-
-hb_buffer_clear()
-
-hb_buffer_flags_t
-
-HB_BUFFER_FLAGS_DEFAULT
-HB_BUFFER_FLAG_BOT
-HB_BUFFER_FLAG_EOT
-HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES
-
-hb_buffer_set_flags()
-hb_buffer_get_flags()
-
-HB_BUFFER_SERIALIZE_FLAGS
-hb_buffer_serialize_glyphs()
-hb_buffer_deserialize_glyphs()
-hb_buffer_serialize_list_formats()
-
-hb_set_add_range()
-hb_set_del_range()
-hb_set_get_population()
-hb_set_next_range()
-
-hb_face_[sg]et_glyph_count()
-
-hb_segment_properties_t
-HB_SEGMENT_PROPERTIES_DEFAULT
-hb_segment_properties_equal()
-hb_segment_properties_hash()
-
-hb_buffer_set_segment_properties()
-hb_buffer_get_segment_properties()
-
-hb_ot_layout_glyph_class_t
-hb_ot_layout_get_glyph_class()
-hb_ot_layout_get_glyphs_in_class()
-
-hb_shape_plan_t
-hb_shape_plan_create()
-hb_shape_plan_create_cached()
-hb_shape_plan_get_empty()
-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_ot_shape_plan_collect_lookups()
-
-
-API changes:
-
-- Remove "mask" parameter from hb_buffer_add().
-- Rename hb_ot_layout_would_substitute_lookup() and hb_ot_layout_substitute_closure_lookup().
-- hb-set.h API const correction.
-- Renamed hb_set_min/max() to hb_set_get_min/max().
-- Rename hb_ot_layout_feature_get_lookup_indexes() to hb_ot_layout_feature_get_lookups().
-- Rename hb_buffer_guess_properties() to hb_buffer_guess_segment_properties().
-
-
-
-Overview of changes leading to 0.9.6
-Sunday, November 13, 2012
-====================================
-
-- Don't clear pre-context text if no new context is provided.
-- Fix ReverseChainingSubstLookup, which was totally borked.
-- Adjust output format of hb-shape a bit.
-- Include config.h.in in-tree.  Makes it easier for alternate build systems.
-- Fix hb_buffer_set_length(buffer, 0) invalid memory allocation.
-- Use ICU LayoutEngine's C API instead of C++.  Avoids much headache.
-- Drop glyphs for all of Unicode Default_Ignorable characters.
-- Misc build fixes.
-
-Arabic shaper:
-- Enable 'dlig' and 'mset' features in Arabic shaper.
-- Implement 'Phags-pa shaping, improve Mongolian.
-
-Indic shaper:
-- Decompose Sinhala split matras the way old HarfBuzz / Pango did.
-- Initial support for Consonant Medials.
-- Start adding new-style Myanmar shaping.
-- Make reph and 'pref' logic introspect the font.
-- Route Meetei-Mayek through the Indic shaper.
-- Don't apply 'liga' in Indic shaper.
-- Improve Malayalam pre-base reordering Ra interaction with Chillus.
-
-
-
-Overview of changes leading to 0.9.5
-Sunday, October 14, 2012
-====================================
-
-- Synthetic-GSUB Arabic fallback shaping.
-
-- Misc Indic improvements.
-
-- Add build system support for pthread.
-
-- Imported UCDN for in-tree Unicode callbacks implementation.
-
-- Context-aware Arabic joining.
-
-- Misc other fixes.
-
-- New API:
-
-  hb_feature_to/from-string()
-  hb_buffer_[sg]et_content_type()
-
-
-
-Overview of changes leading to 0.9.4
-Tuesday, Sep 03, 2012
-====================================
-
-- Indic improvements with old-spec Malayalam.
-
-- Better fallback glyph positioning, specially with Thai / Lao marks.
-
-- Implement dotted-circle insertion.
-
-- Better Arabic fallback shaping / ligation.
-
-- Added ICU LayoutEngine backend for testing.  Call it by the 'icu_le' name.
-
-- Misc fixes.
-
-
-
-Overview of changes leading to 0.9.3
-Friday, Aug 18, 2012
-====================================
-
-- Fixed fallback mark positioning for left-to-right text.
-
-- Improve mark positioning for the remaining combining classes.
-
-- Unbreak Thai and fallback Arabic shaping.
-
-- Port Arabic shaper to shape-plan caching.
-
-- Use new ICU normalizer functions.
-
-
-
-Overview of changes leading to 0.9.2
-Friday, Aug 10, 2012
-====================================
-
-- Over a thousand commits!  This is the first major release of HarfBuzz.
-
-- HarfBuzz is feature-complete now!  It should be in par, or better, than
-  both Pango's shapers and old HarfBuzz / Qt shapers.
-
-- New Indic shaper, supporting main Indic scripts, Sinhala, and Khmer.
-
-- Improved Arabic shaper, with fallback Arabic shaping, supporting Arabic,
-  Sinhala, N'ko, Mongolian, and Mandaic.
-
-- New Thai / Lao shaper.
-
-- Tibetan / Hangul support in the generic shaper.
-
-- Synthetic GDEF support for fonts without a GDEF table.
-
-- Fallback mark positioning for fonts without a GPOS table.
-
-- Unicode normalization shaping heuristic during glyph mapping.
-
-- New experimental Graphite2 backend.
-
-- New Uniscribe backend (primarily for testing).
-
-- New CoreText backend (primarily for testing).
-
-- Major optimization and speedup.
-
-- Test suites and testing infrastructure (work in progress).
-
-- Greatly improved hb-view cmdline tool.
-
-- hb-shape cmdline tool.
-
-- Unicode 6.1 support.
-
-Summary of API changes:
-
-o Changed API:
-
-  - Users are expected to only include main header files now (ie. hb.h,
-    hb-glib.h, hb-ft.h, ...)
-
-  - All struct tag names had their initial underscore removed.
-    Ie. "struct _hb_buffer_t" is "struct hb_buffer_t" now.
-
-  - All set_user_data() functions now take a "replace" boolean parameter.
-
-  - hb_buffer_create() takes zero arguments now.
-    Use hb_buffer_pre_allocate() to pre-allocate.
-
-  - hb_buffer_add_utf*() now accept -1 for length parameteres,
-    meaning "nul-terminated".
-
-  - hb_direction_t enum values changed.
-
-  - All *_from_string() APIs now take a length parameter to allow for
-    non-nul-terminated strings. A -1 length means "nul-terminated".
-
-  - Typedef for hb_language_t changed.
-
-  - hb_get_table_func_t renamed to hb_reference_table_func_t.
-
-  - hb_ot_layout_table_choose_script()
-
-  - Various renames in hb-unicode.h.
-
-o New API:
-
-  - hb_buffer_guess_properties()
-    Automatically called by hb_shape().
-
-  - hb_buffer_normalize_glyphs()
-
-  - hb_tag_from_string()
-
-  - hb-coretext.h
-
-  - hb-uniscribe.h
-
-  - hb_face_reference_blob()
-  - hb_face_[sg]et_index()
-  - hb_face_set_upem()
-
-  - hb_font_get_glyph_name_func_t
-    hb_font_get_glyph_from_name_func_t
-    hb_font_funcs_set_glyph_name_func()
-    hb_font_funcs_set_glyph_from_name_func()
-    hb_font_get_glyph_name()
-    hb_font_get_glyph_from_name()
-    hb_font_glyph_to_string()
-    hb_font_glyph_from_string()
-
-  - hb_font_set_funcs_data()
-
-  - hb_ft_font_set_funcs()
-  - hb_ft_font_get_face()
-
-  - hb-gobject.h (work in progress)
-
-  - hb_ot_shape_glyphs_closure()
-    hb_ot_layout_substitute_closure_lookup()
-
-  - hb-set.h
-
-  - hb_shape_full()
-
-  - hb_unicode_combining_class_t
-
-  - hb_unicode_compose_func_t
-    hb_unicode_decompose_func_t
-    hb_unicode_decompose_compatibility_func_t
-    hb_unicode_funcs_set_compose_func()
-    hb_unicode_funcs_set_decompose_func()
-    hb_unicode_funcs_set_decompose_compatibility_func()
-    hb_unicode_compose()
-    hb_unicode_decompose()
-    hb_unicode_decompose_compatibility()
-
-o Removed API:
-
-  - hb_ft_get_font_funcs()
-
-  - hb_ot_layout_substitute_start()
-    hb_ot_layout_substitute_lookup()
-    hb_ot_layout_substitute_finish()
-    hb_ot_layout_position_start()
-    hb_ot_layout_position_lookup()
-    hb_ot_layout_position_finish()
-
-
-
-Overview of changes leading to 0.6.0
-Friday, May 27, 2011
-====================================
-
-- Vertical text support in GPOS
-- Almost all API entries have unit tests now, under test/
-- All thread-safety issues are fixed
-
-Summary of API changes follows.
-
-
-* Simple Types API:
-
-  o New API:
-    HB_LANGUAGE_INVALID
-    hb_language_get_default()
-    hb_direction_to_string()
-    hb_direction_from_string()
-    hb_script_get_horizontal_direction()
-    HB_UNTAG()
-
-  o Renamed API:
-    hb_category_t renamed to hb_unicode_general_category_t
-
-  o Changed API:
-    hb_language_t is a typed pointers now
-
-  o Removed API:
-    HB_TAG_STR()
-
-
-* Use ISO 15924 tags for hb_script_t:
-
-  o New API:
-    hb_script_from_iso15924_tag()
-    hb_script_to_iso15924_tag()
-    hb_script_from_string()
-
-  o Changed API:
-    HB_SCRIPT_* enum members changed value.
-
-
-* Buffer API streamlined:
-
-  o New API:
-    hb_buffer_reset()
-    hb_buffer_set_length()
-    hb_buffer_allocation_successful()
-
-  o Renamed API:
-    hb_buffer_ensure() renamed to hb_buffer_pre_allocate()
-    hb_buffer_add_glyph() renamed to hb_buffer_add()
-
-  o Removed API:
-    hb_buffer_clear()
-    hb_buffer_clear_positions()
-
-  o Changed API:
-    hb_buffer_get_glyph_infos() takes an out length parameter now
-    hb_buffer_get_glyph_positions() takes an out length parameter now
-
-
-* Blob API streamlined:
-
-  o New API:
-    hb_blob_get_data()
-    hb_blob_get_data_writable()
-
-  o Renamed API:
-    hb_blob_create_empty() renamed to hb_blob_get_empty()
-
-  o Removed API:
-    hb_blob_lock()
-    hb_blob_unlock()
-    hb_blob_is_writable()
-    hb_blob_try_writable()
-
-  o Changed API:
-    hb_blob_create() takes user_data before destroy now
-
-
-* Unicode functions API:
-
-  o Unicode function vectors can subclass other unicode function vectors now.
-    Unimplemented callbacks in the subclass automatically chainup to the parent.
-
-  o All hb_unicode_funcs_t callbacks take a user_data now.  Their setters
-    take a user_data and its respective destroy callback.
-
-  o New API:
-    hb_unicode_funcs_get_empty()
-    hb_unicode_funcs_get_default()
-    hb_unicode_funcs_get_parent()
-
-  o Changed API:
-    hb_unicode_funcs_create() now takes a parent_funcs.
-
-  o Removed func getter functions:
-    hb_unicode_funcs_get_mirroring_func()
-    hb_unicode_funcs_get_general_category_func()
-    hb_unicode_funcs_get_script_func()
-    hb_unicode_funcs_get_combining_class_func()
-    hb_unicode_funcs_get_eastasian_width_func()
-
-
-* Face API:
-
-  o Renamed API:
-    hb_face_get_table() renamed to hb_face_reference_table()
-    hb_face_create_for_data() renamed to hb_face_create()
-
-  o Changed API:
-    hb_face_create_for_tables() takes user_data before destroy now
-    hb_face_reference_table() returns empty blob instead of NULL
-    hb_get_table_func_t accepts the face as first parameter now
-
-* Font API:
-
-  o Fonts can subclass other fonts now.  Unimplemented callbacks in the
-    subclass automatically chainup to the parent.  When chaining up,
-    scale is adjusted if the parent font has a different scale.
-
-  o All hb_font_funcs_t callbacks take a user_data now.  Their setters
-    take a user_data and its respective destroy callback.
-
-  o New API:
-    hb_font_get_parent()
-    hb_font_funcs_get_empty()
-    hb_font_create_sub_font()
-
-  o Removed API:
-    hb_font_funcs_copy()
-    hb_font_unset_funcs()
-
-  o Removed func getter functions:
-    hb_font_funcs_get_glyph_func()
-    hb_font_funcs_get_glyph_advance_func()
-    hb_font_funcs_get_glyph_extents_func()
-    hb_font_funcs_get_contour_point_func()
-    hb_font_funcs_get_kerning_func()
-
-  o Changed API:
-    hb_font_create() takes a face and references it now
-    hb_font_set_funcs() takes user_data before destroy now
-    hb_font_set_scale() accepts signed integers now
-    hb_font_get_contour_point_func_t now takes glyph first, then point_index
-    hb_font_get_glyph_func_t returns a success boolean now
-
-
-* Changed object model:
-
-  o All object types have a _get_empty() now:
-    hb_blob_get_empty()
-    hb_buffer_get_empty()
-    hb_face_get_empty()
-    hb_font_get_empty()
-    hb_font_funcs_get_empty()
-    hb_unicode_funcs_get_empty()
-
-  o Added _set_user_data() and _get_user_data() for all object types:
-    hb_blob_get_user_data()
-    hb_blob_set_user_data()
-    hb_buffer_get_user_data()
-    hb_buffer_set_user_data()
-    hb_face_get_user_data()
-    hb_face_set_user_data()
-    hb_font_funcs_get_user_data()
-    hb_font_funcs_set_user_data()
-    hb_font_get_user_data()
-    hb_font_set_user_data()
-    hb_unicode_funcs_get_user_data()
-    hb_unicode_funcs_set_user_data()
-
-  o Removed the _get_reference_count() from all object types:
-    hb_blob_get_reference_count()
-    hb_buffer_get_reference_count()
-    hb_face_get_reference_count()
-    hb_font_funcs_get_reference_count()
-    hb_font_get_reference_count()
-    hb_unicode_funcs_get_reference_count()
-
-  o Added _make_immutable() and _is_immutable() for all object types except for buffer:
-    hb_blob_make_immutable()
-    hb_blob_is_immutable()
-    hb_face_make_immutable()
-    hb_face_is_immutable()
-
-
-* Changed API for vertical text support
-
-  o The following callbacks where removed:
-    hb_font_get_glyph_advance_func_t
-    hb_font_get_kerning_func_t
-
-  o The following new callbacks added instead:
-    hb_font_get_glyph_h_advance_func_t
-    hb_font_get_glyph_v_advance_func_t
-    hb_font_get_glyph_h_origin_func_t
-    hb_font_get_glyph_v_origin_func_t
-    hb_font_get_glyph_h_kerning_func_t
-    hb_font_get_glyph_v_kerning_func_t
-
-  o The following API removed as such:
-    hb_font_funcs_set_glyph_advance_func()
-    hb_font_funcs_set_kerning_func()
-    hb_font_get_glyph_advance()
-    hb_font_get_kerning()
-
-  o New API added instead:
-    hb_font_funcs_set_glyph_h_advance_func()
-    hb_font_funcs_set_glyph_v_advance_func()
-    hb_font_funcs_set_glyph_h_origin_func()
-    hb_font_funcs_set_glyph_v_origin_func()
-    hb_font_funcs_set_glyph_h_kerning_func()
-    hb_font_funcs_set_glyph_v_kerning_func()
-    hb_font_get_glyph_h_advance()
-    hb_font_get_glyph_v_advance()
-    hb_font_get_glyph_h_origin()
-    hb_font_get_glyph_v_origin()
-    hb_font_get_glyph_h_kerning()
-    hb_font_get_glyph_v_kerning()
-
-  o The following higher-leve API added for convenience:
-    hb_font_get_glyph_advance_for_direction()
-    hb_font_get_glyph_origin_for_direction()
-    hb_font_add_glyph_origin_for_direction()
-    hb_font_subtract_glyph_origin_for_direction()
-    hb_font_get_glyph_kerning_for_direction()
-    hb_font_get_glyph_extents_for_origin()
-    hb_font_get_glyph_contour_point_for_origin()
-
-
-* OpenType Layout API:
-
-  o New API:
-    hb_ot_layout_position_start()
-    hb_ot_layout_substitute_start()
-    hb_ot_layout_substitute_finish()
-
-
-* Glue code:
-
-  o New API:
-    hb_glib_script_to_script()
-    hb_glib_script_from_script()
-    hb_icu_script_to_script()
-    hb_icu_script_from_script()
-
-
-* Version API added:
-
-  o New API:
-    HB_VERSION_MAJOR
-    HB_VERSION_MINOR
-    HB_VERSION_MICRO
-    HB_VERSION_STRING
-    HB_VERSION_CHECK()
-    hb_version()
-    hb_version_string()
-    hb_version_check()
-
-
diff --git a/third_party/harfbuzz-ng/README b/third_party/harfbuzz-ng/README
deleted file mode 100644
index 69a1bdd..0000000
--- a/third_party/harfbuzz-ng/README
+++ /dev/null
@@ -1,12 +0,0 @@
-[![Build Status](https://travis-ci.org/behdad/harfbuzz.svg)](https://travis-ci.org/behdad/harfbuzz)
-[![Build Status](https://ci.appveyor.com/api/projects/status/4oaq58ns2h0m2soa?svg=true)](https://ci.appveyor.com/project/behdad/harfbuzz)
-[![Coverage Status](https://img.shields.io/coveralls/behdad/harfbuzz.svg)](https://coveralls.io/r/behdad/harfbuzz)
-[ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
-
-This is HarfBuzz, a text shaping library.
-
-For bug reports, mailing list, and other information please visit:
-
-  http://harfbuzz.org/
-
-For license information, see the file COPYING.
diff --git a/third_party/harfbuzz-ng/README.chromium b/third_party/harfbuzz-ng/README.chromium
index aa9b164c..98165ba 100644
--- a/third_party/harfbuzz-ng/README.chromium
+++ b/third_party/harfbuzz-ng/README.chromium
@@ -2,23 +2,31 @@
 Short Name: harfbuzz-ng
 URL: http://harfbuzz.org
 Version: 1.7.6
-Date: 20180307
+Date: 20180319
+Revision: 957e7756634a4fdf1654041e20e883cf964ecac9
 Security Critical: yes
 License: MIT
-License File: COPYING
+License File: src/COPYING
 
 Description:
 This is harfbuzz-ng, a new implementation of harfbuzz with a different
 API from the old one.
 
-This copy of harfbuzz is usually updated by downloading the release tarball from
-http://www.freedesktop.org/software/harfbuzz/release/ , removing files in src,
-copying *.h *.hh *.cc (except for the files below) from the tarball's src folder
-over to src, then checking for removed or added files and update our build
-recipes in BUILD.gn and harfbuzz.gyp accordingly, update the NEWS file from
-HarfBuzz' release notes, and bump the version numbers in README.chromium.
+This copy of harfbuzz is updated by putting the new commit hash matching one in
+https://chromium.googlesource.com/external/github.com/harfbuzz/harfbuzz/ to the
+top level DEPS file. When upgrading, check whether files have been added or
+removed in upstream and whether the BUILD.gn file needs to be updated to reflect
+that.
 
-Currently the following files from HarfBuzz are unused and not copied:
+Chromium-local cherry picks or patches can be done by pushing new branches to
+refs/heads/chromium/ of [1]. The set of HarfBuzz OWNERS has write rights to this
+part of the tree. We suggest to follow a pattern of naming branches needed for
+Chromium revisions by the chromium milestone number. For example, if a
+cherry-pick is needed for M65, push to "refs/heads/chromium/m65" and reference
+the new commit in DEPS. Take a look at
+https://chromium-review.googlesource.com/c/chromium/src/+/937502 for an example.
+
+Currently we are intentionally not building the following files from HarfBuzz.
     dump-indic-data.cc
     dump-khmer-data.cc
     dump-myanmar-data.cc
diff --git a/third_party/harfbuzz-ng/src/hb-atomic-private.hh b/third_party/harfbuzz-ng/src/hb-atomic-private.hh
deleted file mode 100644
index a7e9b11a..0000000
--- a/third_party/harfbuzz-ng/src/hb-atomic-private.hh
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright © 2007  Chris Wilson
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Contributor(s):
- *	Chris Wilson <chris@chris-wilson.co.uk>
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_ATOMIC_PRIVATE_HH
-#define HB_ATOMIC_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-/* atomic_int */
-
-/* We need external help for these */
-
-#if defined(hb_atomic_int_impl_add) \
- && defined(hb_atomic_ptr_impl_get) \
- && defined(hb_atomic_ptr_impl_cmpexch)
-
-/* Defined externally, i.e. in config.h; must have typedef'ed hb_atomic_int_impl_t as well. */
-
-
-#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
-
-#include <windows.h>
-
-/* MinGW has a convoluted history of supporting MemoryBarrier
- * properly.  As such, define a function to wrap the whole
- * thing. */
-static inline void _HBMemoryBarrier (void) {
-#if !defined(MemoryBarrier)
-  long dummy = 0;
-  InterlockedExchange (&dummy, 1);
-#else
-  MemoryBarrier ();
-#endif
-}
-
-typedef LONG hb_atomic_int_impl_t;
-#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
-#define hb_atomic_int_impl_add(AI, V)		InterlockedExchangeAdd (&(AI), (V))
-
-#define hb_atomic_ptr_impl_get(P)		(_HBMemoryBarrier (), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)	(InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
-
-typedef int hb_atomic_int_impl_t;
-#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
-#define hb_atomic_int_impl_add(AI, V)		__sync_fetch_and_add (&(AI), (V))
-
-#define hb_atomic_ptr_impl_get(P)		(void *) (__sync_synchronize (), *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)	__sync_bool_compare_and_swap ((P), (O), (N))
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
-
-#include <atomic.h>
-#include <mbarrier.h>
-
-typedef unsigned int hb_atomic_int_impl_t;
-#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
-#define hb_atomic_int_impl_add(AI, V)		( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)		( ({__machine_rw_barrier ();}), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)	( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false)
-
-
-#elif !defined(HB_NO_MT) && defined(__APPLE__)
-
-#include <libkern/OSAtomic.h>
-#ifdef __MAC_OS_X_MIN_REQUIRED
-#include <AvailabilityMacros.h>
-#elif defined(__IPHONE_OS_MIN_REQUIRED)
-#include <Availability.h>
-#endif
-
-
-typedef int32_t hb_atomic_int_impl_t;
-#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
-#define hb_atomic_int_impl_add(AI, V)		(OSAtomicAdd32Barrier ((V), &(AI)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)		(OSMemoryBarrier (), (void *) *(P))
-#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)	OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
-#else
-#if __ppc64__ || __x86_64__ || __aarch64__
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)	OSAtomicCompareAndSwap64Barrier ((int64_t) (void *) (O), (int64_t) (void *) (N), (int64_t*) (P))
-#else
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)	OSAtomicCompareAndSwap32Barrier ((int32_t) (void *) (O), (int32_t) (void *) (N), (int32_t*) (P))
-#endif
-#endif
-
-
-#elif !defined(HB_NO_MT) && defined(_AIX) && defined(__IBMCPP__)
-
-#include <builtins.h>
-
-
-static inline int _hb_fetch_and_add(volatile int* AI, unsigned int V) {
-  __lwsync();
-  int result = __fetch_and_add(AI, V);
-  __isync();
-  return result;
-}
-static inline int _hb_compare_and_swaplp(volatile long* P, long O, long N) {
-  __sync();
-  int result = __compare_and_swaplp (P, &O, N);
-  __sync();
-  return result;
-}
-
-typedef int hb_atomic_int_impl_t;
-#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
-#define hb_atomic_int_impl_add(AI, V)           _hb_fetch_and_add (&(AI), (V))
-
-#define hb_atomic_ptr_impl_get(P)               (__sync(), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N))
-
-#elif !defined(HB_NO_MT)
-
-#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
-
-typedef volatile int hb_atomic_int_impl_t;
-#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
-#define hb_atomic_int_impl_add(AI, V)		(((AI) += (V)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)		((void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)	(* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false)
-
-
-#else /* HB_NO_MT */
-
-typedef int hb_atomic_int_impl_t;
-#define HB_ATOMIC_INT_IMPL_INIT(V)		(V)
-#define hb_atomic_int_impl_add(AI, V)		(((AI) += (V)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)		((void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)	(* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
-
-
-#endif
-
-
-#define HB_ATOMIC_INT_INIT(V)		{HB_ATOMIC_INT_IMPL_INIT(V)}
-
-struct hb_atomic_int_t
-{
-  hb_atomic_int_impl_t v;
-
-  inline void set_unsafe (int v_) { v = v_; }
-  inline int get_unsafe (void) const { return v; }
-  inline int inc (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v),  1); }
-  inline int dec (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v), -1); }
-};
-
-
-#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get(P)
-#define hb_atomic_ptr_cmpexch(P,O,N) hb_atomic_ptr_impl_cmpexch((P),(O),(N))
-
-
-#endif /* HB_ATOMIC_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-blob.cc b/third_party/harfbuzz-ng/src/hb-blob.cc
deleted file mode 100644
index b5291f6..0000000
--- a/third_party/harfbuzz-ng/src/hb-blob.cc
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */
-#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 200809L
-#endif
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-
-#include "hb-object-private.hh"
-
-#ifdef HAVE_SYS_MMAN_H
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#include <sys/mman.h>
-#endif /* HAVE_SYS_MMAN_H */
-
-#include <stdio.h>
-#include <errno.h>
-
-
-struct hb_blob_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  bool immutable;
-
-  const char *data;
-  unsigned int length;
-  hb_memory_mode_t mode;
-
-  void *user_data;
-  hb_destroy_func_t destroy;
-};
-
-
-static bool _try_writable (hb_blob_t *blob);
-
-static void
-_hb_blob_destroy_user_data (hb_blob_t *blob)
-{
-  if (blob->destroy) {
-    blob->destroy (blob->user_data);
-    blob->user_data = nullptr;
-    blob->destroy = nullptr;
-  }
-}
-
-/**
- * hb_blob_create: (skip)
- * @data: Pointer to blob data.
- * @length: Length of @data in bytes.
- * @mode: Memory mode for @data.
- * @user_data: Data parameter to pass to @destroy.
- * @destroy: Callback to call when @data is not needed anymore.
- *
- * Creates a new "blob" object wrapping @data.  The @mode parameter is used
- * to negotiate ownership and lifecycle of @data.
- *
- * Return value: New blob, or the empty blob if something failed or if @length is
- * zero.  Destroy with hb_blob_destroy().
- *
- * Since: 0.9.2
- **/
-hb_blob_t *
-hb_blob_create (const char        *data,
-		unsigned int       length,
-		hb_memory_mode_t   mode,
-		void              *user_data,
-		hb_destroy_func_t  destroy)
-{
-  hb_blob_t *blob;
-
-  if (!length ||
-      length >= 1u << 31 ||
-      !(blob = hb_object_create<hb_blob_t> ())) {
-    if (destroy)
-      destroy (user_data);
-    return hb_blob_get_empty ();
-  }
-
-  blob->data = data;
-  blob->length = length;
-  blob->mode = mode;
-
-  blob->user_data = user_data;
-  blob->destroy = destroy;
-
-  if (blob->mode == HB_MEMORY_MODE_DUPLICATE) {
-    blob->mode = HB_MEMORY_MODE_READONLY;
-    if (!_try_writable (blob)) {
-      hb_blob_destroy (blob);
-      return hb_blob_get_empty ();
-    }
-  }
-
-  return blob;
-}
-
-static void
-_hb_blob_destroy (void *data)
-{
-  hb_blob_destroy ((hb_blob_t *) data);
-}
-
-/**
- * hb_blob_create_sub_blob:
- * @parent: Parent blob.
- * @offset: Start offset of sub-blob within @parent, in bytes.
- * @length: Length of sub-blob.
- *
- * Returns a blob that represents a range of bytes in @parent.  The new
- * blob is always created with %HB_MEMORY_MODE_READONLY, meaning that it
- * will never modify data in the parent blob.  The parent data is not
- * expected to be modified, and will result in undefined behavior if it
- * is.
- *
- * Makes @parent immutable.
- *
- * Return value: New blob, or the empty blob if something failed or if
- * @length is zero or @offset is beyond the end of @parent's data.  Destroy
- * with hb_blob_destroy().
- *
- * Since: 0.9.2
- **/
-hb_blob_t *
-hb_blob_create_sub_blob (hb_blob_t    *parent,
-			 unsigned int  offset,
-			 unsigned int  length)
-{
-  hb_blob_t *blob;
-
-  if (!length || offset >= parent->length)
-    return hb_blob_get_empty ();
-
-  hb_blob_make_immutable (parent);
-
-  blob = hb_blob_create (parent->data + offset,
-			 MIN (length, parent->length - offset),
-			 HB_MEMORY_MODE_READONLY,
-			 hb_blob_reference (parent),
-			 _hb_blob_destroy);
-
-  return blob;
-}
-
-/**
- * hb_blob_copy_writable_or_fail:
- * @blob: A blob.
- *
- * Makes a writable copy of @blob.
- *
- * Return value: New blob, or nullptr if allocation failed.
- *
- * Since: 1.8.0
- **/
-hb_blob_t *
-hb_blob_copy_writable_or_fail (hb_blob_t *blob)
-{
-  blob = hb_blob_create (blob->data,
-			 blob->length,
-			 HB_MEMORY_MODE_DUPLICATE,
-			 nullptr,
-			 nullptr);
-
-  if (unlikely (blob == hb_blob_get_empty ()))
-    blob = nullptr;
-
-  return blob;
-}
-
-/**
- * hb_blob_get_empty:
- *
- * Returns the singleton empty blob.
- *
- * See TODO:link object types for more information.
- *
- * Return value: (transfer full): the empty blob.
- *
- * Since: 0.9.2
- **/
-hb_blob_t *
-hb_blob_get_empty (void)
-{
-  static const hb_blob_t _hb_blob_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* immutable */
-
-    nullptr, /* data */
-    0, /* length */
-    HB_MEMORY_MODE_READONLY, /* mode */
-
-    nullptr, /* user_data */
-    nullptr  /* destroy */
-  };
-
-  return const_cast<hb_blob_t *> (&_hb_blob_nil);
-}
-
-/**
- * hb_blob_reference: (skip)
- * @blob: a blob.
- *
- * Increases the reference count on @blob.
- *
- * See TODO:link object types for more information.
- *
- * Return value: @blob.
- *
- * Since: 0.9.2
- **/
-hb_blob_t *
-hb_blob_reference (hb_blob_t *blob)
-{
-  return hb_object_reference (blob);
-}
-
-/**
- * hb_blob_destroy: (skip)
- * @blob: a blob.
- *
- * Decreases the reference count on @blob, and if it reaches zero, destroys
- * @blob, freeing all memory, possibly calling the destroy-callback the blob
- * was created for if it has not been called already.
- *
- * See TODO:link object types for more information.
- *
- * Since: 0.9.2
- **/
-void
-hb_blob_destroy (hb_blob_t *blob)
-{
-  if (!hb_object_destroy (blob)) return;
-
-  _hb_blob_destroy_user_data (blob);
-
-  free (blob);
-}
-
-/**
- * hb_blob_set_user_data: (skip)
- * @blob: a blob.
- * @key: key for data to set.
- * @data: data to set.
- * @destroy: callback to call when @data is not needed anymore.
- * @replace: whether to replace an existing data with the same key.
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_blob_set_user_data (hb_blob_t          *blob,
-		       hb_user_data_key_t *key,
-		       void *              data,
-		       hb_destroy_func_t   destroy,
-		       hb_bool_t           replace)
-{
-  return hb_object_set_user_data (blob, key, data, destroy, replace);
-}
-
-/**
- * hb_blob_get_user_data: (skip)
- * @blob: a blob.
- * @key: key for data to get.
- *
- * 
- *
- * Return value: (transfer none): 
- *
- * Since: 0.9.2
- **/
-void *
-hb_blob_get_user_data (hb_blob_t          *blob,
-		       hb_user_data_key_t *key)
-{
-  return hb_object_get_user_data (blob, key);
-}
-
-
-/**
- * hb_blob_make_immutable:
- * @blob: a blob.
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_blob_make_immutable (hb_blob_t *blob)
-{
-  if (hb_object_is_inert (blob))
-    return;
-
-  blob->immutable = true;
-}
-
-/**
- * hb_blob_is_immutable:
- * @blob: a blob.
- *
- * 
- *
- * Return value: TODO
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_blob_is_immutable (hb_blob_t *blob)
-{
-  return blob->immutable;
-}
-
-
-/**
- * hb_blob_get_length:
- * @blob: a blob.
- *
- * 
- *
- * Return value: the length of blob data in bytes.
- *
- * Since: 0.9.2
- **/
-unsigned int
-hb_blob_get_length (hb_blob_t *blob)
-{
-  return blob->length;
-}
-
-/**
- * hb_blob_get_data:
- * @blob: a blob.
- * @length: (out):
- *
- * 
- *
- * Returns: (transfer none) (array length=length): 
- *
- * Since: 0.9.2
- **/
-const char *
-hb_blob_get_data (hb_blob_t *blob, unsigned int *length)
-{
-  if (length)
-    *length = blob->length;
-
-  return blob->data;
-}
-
-/**
- * hb_blob_get_data_writable:
- * @blob: a blob.
- * @length: (out): output length of the writable data.
- *
- * Tries to make blob data writable (possibly copying it) and
- * return pointer to data.
- *
- * Fails if blob has been made immutable, or if memory allocation
- * fails.
- *
- * Returns: (transfer none) (array length=length): Writable blob data,
- * or %NULL if failed.
- *
- * Since: 0.9.2
- **/
-char *
-hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length)
-{
-  if (!_try_writable (blob)) {
-    if (length)
-      *length = 0;
-
-    return nullptr;
-  }
-
-  if (length)
-    *length = blob->length;
-
-  return const_cast<char *> (blob->data);
-}
-
-
-static hb_bool_t
-_try_make_writable_inplace_unix (hb_blob_t *blob)
-{
-#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT)
-  uintptr_t pagesize = -1, mask, length;
-  const char *addr;
-
-#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
-  pagesize = (uintptr_t) sysconf (_SC_PAGE_SIZE);
-#elif defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
-  pagesize = (uintptr_t) sysconf (_SC_PAGESIZE);
-#elif defined(HAVE_GETPAGESIZE)
-  pagesize = (uintptr_t) getpagesize ();
-#endif
-
-  if ((uintptr_t) -1L == pagesize) {
-    DEBUG_MSG_FUNC (BLOB, blob, "failed to get pagesize: %s", strerror (errno));
-    return false;
-  }
-  DEBUG_MSG_FUNC (BLOB, blob, "pagesize is %lu", (unsigned long) pagesize);
-
-  mask = ~(pagesize-1);
-  addr = (const char *) (((uintptr_t) blob->data) & mask);
-  length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask)  - addr;
-  DEBUG_MSG_FUNC (BLOB, blob,
-		  "calling mprotect on [%p..%p] (%lu bytes)",
-		  addr, addr+length, (unsigned long) length);
-  if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) {
-    DEBUG_MSG_FUNC (BLOB, blob, "mprotect failed: %s", strerror (errno));
-    return false;
-  }
-
-  blob->mode = HB_MEMORY_MODE_WRITABLE;
-
-  DEBUG_MSG_FUNC (BLOB, blob,
-		  "successfully made [%p..%p] (%lu bytes) writable\n",
-		  addr, addr+length, (unsigned long) length);
-  return true;
-#else
-  return false;
-#endif
-}
-
-static bool
-_try_writable_inplace (hb_blob_t *blob)
-{
-  DEBUG_MSG_FUNC (BLOB, blob, "making writable inplace\n");
-
-  if (_try_make_writable_inplace_unix (blob))
-    return true;
-
-  DEBUG_MSG_FUNC (BLOB, blob, "making writable -> FAILED\n");
-
-  /* Failed to make writable inplace, mark that */
-  blob->mode = HB_MEMORY_MODE_READONLY;
-  return false;
-}
-
-static bool
-_try_writable (hb_blob_t *blob)
-{
-  if (blob->immutable)
-    return false;
-
-  if (blob->mode == HB_MEMORY_MODE_WRITABLE)
-    return true;
-
-  if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE && _try_writable_inplace (blob))
-    return true;
-
-  if (blob->mode == HB_MEMORY_MODE_WRITABLE)
-    return true;
-
-
-  DEBUG_MSG_FUNC (BLOB, blob, "current data is -> %p\n", blob->data);
-
-  char *new_data;
-
-  new_data = (char *) malloc (blob->length);
-  if (unlikely (!new_data))
-    return false;
-
-  DEBUG_MSG_FUNC (BLOB, blob, "dupped successfully -> %p\n", blob->data);
-
-  memcpy (new_data, blob->data, blob->length);
-  _hb_blob_destroy_user_data (blob);
-  blob->mode = HB_MEMORY_MODE_WRITABLE;
-  blob->data = new_data;
-  blob->user_data = new_data;
-  blob->destroy = free;
-
-  return true;
-}
diff --git a/third_party/harfbuzz-ng/src/hb-blob.h b/third_party/harfbuzz-ng/src/hb-blob.h
deleted file mode 100644
index fd561f7..0000000
--- a/third_party/harfbuzz-ng/src/hb-blob.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_H_IN
-#error "Include <hb.h> instead."
-#endif
-
-#ifndef HB_BLOB_H
-#define HB_BLOB_H
-
-#include "hb-common.h"
-
-HB_BEGIN_DECLS
-
-
-/*
- * Note re various memory-modes:
- *
- * - In no case shall the HarfBuzz client modify memory
- *   that is passed to HarfBuzz in a blob.  If there is
- *   any such possibility, MODE_DUPLICATE should be used
- *   such that HarfBuzz makes a copy immediately,
- *
- * - Use MODE_READONLY otherwise, unless you really really
- *   really know what you are doing,
- *
- * - MODE_WRITABLE is appropriate if you really made a
- *   copy of data solely for the purpose of passing to
- *   HarfBuzz and doing that just once (no reuse!),
- *
- * - If the font is mmap()ed, it's ok to use
- *   READONLY_MAY_MAKE_WRITABLE, however, using that mode
- *   correctly is very tricky.  Use MODE_READONLY instead.
- */
-typedef enum {
-  HB_MEMORY_MODE_DUPLICATE,
-  HB_MEMORY_MODE_READONLY,
-  HB_MEMORY_MODE_WRITABLE,
-  HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE
-} hb_memory_mode_t;
-
-typedef struct hb_blob_t hb_blob_t;
-
-HB_EXTERN hb_blob_t *
-hb_blob_create (const char        *data,
-		unsigned int       length,
-		hb_memory_mode_t   mode,
-		void              *user_data,
-		hb_destroy_func_t  destroy);
-
-/* Always creates with MEMORY_MODE_READONLY.
- * Even if the parent blob is writable, we don't
- * want the user of the sub-blob to be able to
- * modify the parent data as that data may be
- * shared among multiple sub-blobs.
- */
-HB_EXTERN hb_blob_t *
-hb_blob_create_sub_blob (hb_blob_t    *parent,
-			 unsigned int  offset,
-			 unsigned int  length);
-
-HB_EXTERN hb_blob_t *
-hb_blob_copy_writable_or_fail (hb_blob_t *blob);
-
-HB_EXTERN hb_blob_t *
-hb_blob_get_empty (void);
-
-HB_EXTERN hb_blob_t *
-hb_blob_reference (hb_blob_t *blob);
-
-HB_EXTERN void
-hb_blob_destroy (hb_blob_t *blob);
-
-HB_EXTERN hb_bool_t
-hb_blob_set_user_data (hb_blob_t          *blob,
-		       hb_user_data_key_t *key,
-		       void *              data,
-		       hb_destroy_func_t   destroy,
-		       hb_bool_t           replace);
-
-
-HB_EXTERN void *
-hb_blob_get_user_data (hb_blob_t          *blob,
-		       hb_user_data_key_t *key);
-
-
-HB_EXTERN void
-hb_blob_make_immutable (hb_blob_t *blob);
-
-HB_EXTERN hb_bool_t
-hb_blob_is_immutable (hb_blob_t *blob);
-
-
-HB_EXTERN unsigned int
-hb_blob_get_length (hb_blob_t *blob);
-
-HB_EXTERN const char *
-hb_blob_get_data (hb_blob_t *blob, unsigned int *length);
-
-HB_EXTERN char *
-hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length);
-
-
-HB_END_DECLS
-
-#endif /* HB_BLOB_H */
diff --git a/third_party/harfbuzz-ng/src/hb-buffer-deserialize-json.hh b/third_party/harfbuzz-ng/src/hb-buffer-deserialize-json.hh
deleted file mode 100644
index be374c7..0000000
--- a/third_party/harfbuzz-ng/src/hb-buffer-deserialize-json.hh
+++ /dev/null
@@ -1,643 +0,0 @@
-
-#line 1 "hb-buffer-deserialize-json.rl"
-/*
- * Copyright © 2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_BUFFER_DESERIALIZE_JSON_HH
-#define HB_BUFFER_DESERIALIZE_JSON_HH
-
-#include "hb-private.hh"
-
-
-#line 36 "hb-buffer-deserialize-json.hh"
-static const unsigned char _deserialize_json_trans_keys[] = {
-	0u, 0u, 9u, 123u, 9u, 34u, 97u, 103u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u,
-	48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u,
-	9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u,
-	120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u,
-	9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
-	65u, 122u, 34u, 122u, 9u, 125u, 9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0
-};
-
-static const char _deserialize_json_key_spans[] = {
-	0, 115, 26, 7, 2, 1, 50, 49,
-	10, 117, 117, 117, 1, 50, 49, 10,
-	117, 117, 1, 1, 50, 49, 117, 117,
-	2, 1, 50, 49, 10, 117, 117, 1,
-	50, 49, 10, 117, 117, 1, 50, 49,
-	58, 89, 117, 117, 85, 115, 0
-};
-
-static const short _deserialize_json_index_offsets[] = {
-	0, 0, 116, 143, 151, 154, 156, 207,
-	257, 268, 386, 504, 622, 624, 675, 725,
-	736, 854, 972, 974, 976, 1027, 1077, 1195,
-	1313, 1316, 1318, 1369, 1419, 1430, 1548, 1666,
-	1668, 1719, 1769, 1780, 1898, 2016, 2018, 2069,
-	2119, 2178, 2268, 2386, 2504, 2590, 2706
-};
-
-static const char _deserialize_json_indicies[] = {
-	0, 0, 0, 0, 0, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	0, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 2, 1, 3, 3, 3,
-	3, 3, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 3, 1, 4, 1,
-	5, 1, 6, 7, 1, 1, 8, 1,
-	9, 10, 1, 11, 1, 11, 11, 11,
-	11, 11, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 11, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 12, 1,
-	12, 12, 12, 12, 12, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 12,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 13, 1, 1, 14,
-	15, 15, 15, 15, 15, 15, 15, 15,
-	15, 1, 16, 17, 17, 17, 17, 17,
-	17, 17, 17, 17, 1, 18, 18, 18,
-	18, 18, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 18, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	19, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 20, 1, 21, 21, 21, 21, 21,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 21, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 3, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 22,
-	1, 18, 18, 18, 18, 18, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	18, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 19, 1, 1, 1,
-	17, 17, 17, 17, 17, 17, 17, 17,
-	17, 17, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 20, 1, 23,
-	1, 23, 23, 23, 23, 23, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	23, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 24, 1, 24, 24, 24, 24,
-	24, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 24, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 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, 30, 30, 30, 30, 30, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	30, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 31, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 32, 1, 30,
-	30, 30, 30, 30, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 30, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 31, 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, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 32, 1, 33, 1, 34,
-	1, 34, 34, 34, 34, 34, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	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, 35, 1, 35, 35, 35, 35,
-	35, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 35, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 36, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 1, 38, 38,
-	38, 38, 38, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 38, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 39, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 40, 1, 38, 38, 38, 38,
-	38, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 38, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 39,
-	1, 1, 1, 41, 41, 41, 41, 41,
-	41, 41, 41, 41, 41, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	40, 1, 42, 43, 1, 44, 1, 44,
-	44, 44, 44, 44, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 44, 1,
-	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, 45, 45, 45, 45, 45, 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, 46, 1,
-	1, 47, 48, 48, 48, 48, 48, 48,
-	48, 48, 48, 1, 49, 50, 50, 50,
-	50, 50, 50, 50, 50, 50, 1, 51,
-	51, 51, 51, 51, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 51, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 52, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 53, 1, 51, 51, 51,
-	51, 51, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 51, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	52, 1, 1, 1, 50, 50, 50, 50,
-	50, 50, 50, 50, 50, 50, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 53, 1, 54, 1, 54, 54, 54,
-	54, 54, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 54, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 55, 1,
-	55, 55, 55, 55, 55, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 55,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 56, 1, 1, 57,
-	58, 58, 58, 58, 58, 58, 58, 58,
-	58, 1, 59, 60, 60, 60, 60, 60,
-	60, 60, 60, 60, 1, 61, 61, 61,
-	61, 61, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 61, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	62, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 63, 1, 61, 61, 61, 61, 61,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 61, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 62, 1,
-	1, 1, 60, 60, 60, 60, 60, 60,
-	60, 60, 60, 60, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 63,
-	1, 64, 1, 64, 64, 64, 64, 64,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 64, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 65, 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, 66,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 67, 68, 68,
-	68, 68, 68, 68, 68, 68, 68, 1,
-	69, 69, 69, 69, 69, 69, 69, 69,
-	69, 69, 69, 69, 69, 69, 69, 69,
-	69, 69, 69, 69, 69, 69, 69, 69,
-	69, 69, 1, 1, 1, 1, 1, 1,
-	69, 69, 69, 69, 69, 69, 69, 69,
-	69, 69, 69, 69, 69, 69, 69, 69,
-	69, 69, 69, 69, 69, 69, 69, 69,
-	69, 69, 1, 70, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 71, 71,
-	1, 71, 71, 71, 71, 71, 71, 71,
-	71, 71, 71, 1, 1, 1, 1, 1,
-	1, 1, 71, 71, 71, 71, 71, 71,
-	71, 71, 71, 71, 71, 71, 71, 71,
-	71, 71, 71, 71, 71, 71, 71, 71,
-	71, 71, 71, 71, 1, 1, 1, 1,
-	71, 1, 71, 71, 71, 71, 71, 71,
-	71, 71, 71, 71, 71, 71, 71, 71,
-	71, 71, 71, 71, 71, 71, 71, 71,
-	71, 71, 71, 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, 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, 1, 1, 1, 1, 1, 1, 1,
-	1, 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, 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,
-	1, 1, 1, 1, 1, 1, 73, 1,
-	1, 1, 75, 75, 75, 75, 75, 75,
-	75, 75, 75, 75, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 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, 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, 1, 1, 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, 1, 1, 1, 1, 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, 0,
-	0, 0, 0, 0, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 0, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 2, 1, 1, 0
-};
-
-static const char _deserialize_json_trans_targs[] = {
-	1, 0, 2, 2, 3, 4, 18, 24,
-	37, 5, 12, 6, 7, 8, 9, 11,
-	9, 11, 10, 2, 44, 10, 44, 13,
-	14, 15, 16, 17, 16, 17, 10, 2,
-	44, 19, 20, 21, 22, 23, 10, 2,
-	44, 23, 25, 31, 26, 27, 28, 29,
-	30, 29, 30, 10, 2, 44, 32, 33,
-	34, 35, 36, 35, 36, 10, 2, 44,
-	38, 39, 40, 42, 43, 41, 10, 41,
-	10, 2, 44, 43, 44, 45, 46
-};
-
-static const char _deserialize_json_trans_actions[] = {
-	0, 0, 1, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 2, 2, 2,
-	0, 0, 3, 3, 4, 0, 5, 0,
-	0, 2, 2, 2, 0, 0, 6, 6,
-	7, 0, 0, 0, 2, 2, 8, 8,
-	9, 0, 0, 0, 0, 0, 2, 2,
-	2, 0, 0, 10, 10, 11, 0, 0,
-	2, 2, 2, 0, 0, 12, 12, 13,
-	0, 0, 0, 2, 2, 2, 14, 0,
-	15, 15, 16, 0, 0, 0, 0
-};
-
-static const int deserialize_json_start = 1;
-static const int deserialize_json_first_final = 44;
-static const int deserialize_json_error = 0;
-
-static const int deserialize_json_en_main = 1;
-
-
-#line 97 "hb-buffer-deserialize-json.rl"
-
-
-static hb_bool_t
-_hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer,
-				    const char *buf,
-				    unsigned int buf_len,
-				    const char **end_ptr,
-				    hb_font_t *font)
-{
-  const char *p = buf, *pe = buf + buf_len;
-
-  /* Ensure we have positions. */
-  (void) hb_buffer_get_glyph_positions (buffer, nullptr);
-
-  while (p < pe && ISSPACE (*p))
-    p++;
-  if (p < pe && *p == (buffer->len ? ',' : '['))
-  {
-    *end_ptr = ++p;
-  }
-
-  const char *tok = nullptr;
-  int cs;
-  hb_glyph_info_t info = {0};
-  hb_glyph_position_t pos = {0};
-
-#line 466 "hb-buffer-deserialize-json.hh"
-	{
-	cs = deserialize_json_start;
-	}
-
-#line 471 "hb-buffer-deserialize-json.hh"
-	{
-	int _slen;
-	int _trans;
-	const unsigned char *_keys;
-	const char *_inds;
-	if ( p == pe )
-		goto _test_eof;
-	if ( cs == 0 )
-		goto _out;
-_resume:
-	_keys = _deserialize_json_trans_keys + (cs<<1);
-	_inds = _deserialize_json_indicies + _deserialize_json_index_offsets[cs];
-
-	_slen = _deserialize_json_key_spans[cs];
-	_trans = _inds[ _slen > 0 && _keys[0] <=(*p) &&
-		(*p) <= _keys[1] ?
-		(*p) - _keys[0] : _slen ];
-
-	cs = _deserialize_json_trans_targs[_trans];
-
-	if ( _deserialize_json_trans_actions[_trans] == 0 )
-		goto _again;
-
-	switch ( _deserialize_json_trans_actions[_trans] ) {
-	case 1:
-#line 38 "hb-buffer-deserialize-json.rl"
-	{
-	memset (&info, 0, sizeof (info));
-	memset (&pos , 0, sizeof (pos ));
-}
-	break;
-	case 5:
-#line 43 "hb-buffer-deserialize-json.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 2:
-#line 51 "hb-buffer-deserialize-json.rl"
-	{
-	tok = p;
-}
-	break;
-	case 14:
-#line 55 "hb-buffer-deserialize-json.rl"
-	{
-	if (!hb_font_glyph_from_string (font,
-					tok, p - tok,
-					&info.codepoint))
-	  return false;
-}
-	break;
-	case 15:
-#line 62 "hb-buffer-deserialize-json.rl"
-	{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
-	break;
-	case 8:
-#line 63 "hb-buffer-deserialize-json.rl"
-	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
-	break;
-	case 10:
-#line 64 "hb-buffer-deserialize-json.rl"
-	{ if (!parse_int  (tok, p, &pos.x_offset )) return false; }
-	break;
-	case 12:
-#line 65 "hb-buffer-deserialize-json.rl"
-	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
-	break;
-	case 3:
-#line 66 "hb-buffer-deserialize-json.rl"
-	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
-	break;
-	case 6:
-#line 67 "hb-buffer-deserialize-json.rl"
-	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
-	break;
-	case 16:
-#line 62 "hb-buffer-deserialize-json.rl"
-	{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 9:
-#line 63 "hb-buffer-deserialize-json.rl"
-	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 11:
-#line 64 "hb-buffer-deserialize-json.rl"
-	{ if (!parse_int  (tok, p, &pos.x_offset )) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 13:
-#line 65 "hb-buffer-deserialize-json.rl"
-	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 4:
-#line 66 "hb-buffer-deserialize-json.rl"
-	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 7:
-#line 67 "hb-buffer-deserialize-json.rl"
-	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-#line 624 "hb-buffer-deserialize-json.hh"
-	}
-
-_again:
-	if ( cs == 0 )
-		goto _out;
-	if ( ++p != pe )
-		goto _resume;
-	_test_eof: {}
-	_out: {}
-	}
-
-#line 125 "hb-buffer-deserialize-json.rl"
-
-
-  *end_ptr = p;
-
-  return p == pe && *(p-1) != ']';
-}
-
-#endif /* HB_BUFFER_DESERIALIZE_JSON_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-buffer-deserialize-text.hh b/third_party/harfbuzz-ng/src/hb-buffer-deserialize-text.hh
deleted file mode 100644
index a6ab0bb..0000000
--- a/third_party/harfbuzz-ng/src/hb-buffer-deserialize-text.hh
+++ /dev/null
@@ -1,571 +0,0 @@
-
-#line 1 "hb-buffer-deserialize-text.rl"
-/*
- * Copyright © 2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_BUFFER_DESERIALIZE_TEXT_HH
-#define HB_BUFFER_DESERIALIZE_TEXT_HH
-
-#include "hb-private.hh"
-
-
-#line 36 "hb-buffer-deserialize-text.hh"
-static const unsigned char _deserialize_text_trans_keys[] = {
-	0u, 0u, 9u, 122u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u,
-	48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 9u, 124u, 9u, 124u, 0u, 0u,
-	9u, 122u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
-	9u, 124u, 9u, 124u, 9u, 124u, 0
-};
-
-static const char _deserialize_text_key_spans[] = {
-	0, 114, 13, 10, 13, 10, 10, 13,
-	10, 1, 13, 10, 14, 116, 116, 0,
-	114, 116, 116, 116, 116, 116, 116, 116,
-	116, 116, 116
-};
-
-static const short _deserialize_text_index_offsets[] = {
-	0, 0, 115, 129, 140, 154, 165, 176,
-	190, 201, 203, 217, 228, 243, 360, 477,
-	478, 593, 710, 827, 944, 1061, 1178, 1295,
-	1412, 1529, 1646
-};
-
-static const char _deserialize_text_indicies[] = {
-	0, 0, 0, 0, 0, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	0, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	2, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 1, 1, 1, 1, 1, 1,
-	1, 4, 4, 4, 4, 4, 4, 4,
-	4, 4, 4, 4, 4, 4, 4, 4,
-	4, 4, 4, 4, 4, 4, 4, 4,
-	4, 4, 4, 1, 1, 1, 1, 1,
-	1, 4, 4, 4, 4, 4, 4, 4,
-	4, 4, 4, 4, 4, 4, 4, 4,
-	4, 4, 4, 4, 4, 4, 4, 4,
-	4, 4, 4, 1, 5, 1, 1, 6,
-	7, 7, 7, 7, 7, 7, 7, 7,
-	7, 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, 13, 14, 14, 14, 14,
-	14, 14, 14, 14, 14, 1, 15, 16,
-	16, 16, 16, 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, 1, 23, 1, 1, 24,
-	25, 25, 25, 25, 25, 25, 25, 25,
-	25, 1, 26, 27, 27, 27, 27, 27,
-	27, 27, 27, 27, 1, 22, 1, 1,
-	1, 21, 21, 21, 21, 21, 21, 21,
-	21, 21, 21, 1, 28, 28, 28, 28,
-	28, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 28, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 29, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	30, 1, 1, 31, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	32, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 33,
-	1, 34, 34, 34, 34, 34, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	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, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 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,
-	1, 1, 1, 1, 36, 1, 1, 0,
-	0, 0, 0, 0, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 0, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 2, 3,
-	3, 3, 3, 3, 3, 3, 3, 3,
-	1, 1, 1, 1, 1, 1, 1, 4,
-	4, 4, 4, 4, 4, 4, 4, 4,
-	4, 4, 4, 4, 4, 4, 4, 4,
-	4, 4, 4, 4, 4, 4, 4, 4,
-	4, 1, 1, 1, 1, 1, 1, 4,
-	4, 4, 4, 4, 4, 4, 4, 4,
-	4, 4, 4, 4, 4, 4, 4, 4,
-	4, 4, 4, 4, 4, 4, 4, 4,
-	4, 1, 28, 28, 28, 28, 28, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 28, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 29, 1, 1, 1,
-	1, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 1, 1, 1, 30, 1,
-	1, 31, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 32, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 33, 1, 38,
-	38, 38, 38, 38, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 38, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 39, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 40, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 41, 1, 42, 42, 42, 42,
-	42, 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, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	43, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 44,
-	1, 42, 42, 42, 42, 42, 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,
-	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, 43, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 44, 1, 38, 38,
-	38, 38, 38, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 38, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 39, 1, 1, 1, 9, 9, 9,
-	9, 9, 9, 9, 9, 9, 9, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 40, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 41, 1, 45, 45, 45, 45, 45,
-	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, 46, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 47, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 48,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 49, 1,
-	50, 50, 50, 50, 50, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 50,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 51, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 52, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 53, 1, 50, 50, 50,
-	50, 50, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 50, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 51,
-	1, 1, 1, 1, 27, 27, 27, 27,
-	27, 27, 27, 27, 27, 27, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 52, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	53, 1, 45, 45, 45, 45, 45, 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, 46, 1, 1, 1,
-	1, 54, 54, 54, 54, 54, 54, 54,
-	54, 54, 54, 1, 1, 1, 1, 1,
-	1, 47, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 48, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 49, 1, 28,
-	28, 28, 28, 28, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 28, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 29, 1, 55, 55, 1, 55, 55,
-	55, 55, 55, 55, 55, 55, 55, 55,
-	1, 1, 1, 30, 1, 1, 31, 55,
-	55, 55, 55, 55, 55, 55, 55, 55,
-	55, 55, 55, 55, 55, 55, 55, 55,
-	55, 55, 55, 55, 55, 55, 55, 55,
-	55, 1, 1, 32, 1, 55, 1, 55,
-	55, 55, 55, 55, 55, 55, 55, 55,
-	55, 55, 55, 55, 55, 55, 55, 55,
-	55, 55, 55, 55, 55, 55, 55, 55,
-	55, 1, 33, 1, 0
-};
-
-static const char _deserialize_text_trans_targs[] = {
-	1, 0, 13, 17, 26, 3, 18, 21,
-	18, 21, 5, 19, 20, 19, 20, 22,
-	25, 8, 9, 12, 9, 12, 10, 11,
-	23, 24, 23, 24, 14, 2, 6, 7,
-	15, 16, 14, 15, 16, 17, 14, 4,
-	15, 16, 14, 15, 16, 14, 2, 7,
-	15, 16, 14, 2, 15, 16, 25, 26
-};
-
-static const char _deserialize_text_trans_actions[] = {
-	0, 0, 1, 1, 1, 2, 2, 2,
-	0, 0, 2, 2, 2, 0, 0, 2,
-	2, 2, 2, 2, 0, 0, 3, 2,
-	2, 2, 0, 0, 4, 5, 5, 5,
-	4, 4, 0, 0, 0, 0, 6, 7,
-	6, 6, 8, 8, 8, 9, 10, 10,
-	9, 9, 11, 12, 11, 11, 0, 0
-};
-
-static const char _deserialize_text_eof_actions[] = {
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 4, 0, 0,
-	0, 4, 6, 8, 8, 6, 9, 11,
-	11, 9, 4
-};
-
-static const int deserialize_text_start = 1;
-static const int deserialize_text_first_final = 13;
-static const int deserialize_text_error = 0;
-
-static const int deserialize_text_en_main = 1;
-
-
-#line 91 "hb-buffer-deserialize-text.rl"
-
-
-static hb_bool_t
-_hb_buffer_deserialize_glyphs_text (hb_buffer_t *buffer,
-				    const char *buf,
-				    unsigned int buf_len,
-				    const char **end_ptr,
-				    hb_font_t *font)
-{
-  const char *p = buf, *pe = buf + buf_len;
-
-  /* Ensure we have positions. */
-  (void) hb_buffer_get_glyph_positions (buffer, nullptr);
-
-  while (p < pe && ISSPACE (*p))
-    p++;
-  if (p < pe && *p == (buffer->len ? '|' : '['))
-  {
-    *end_ptr = ++p;
-  }
-
-  const char *eof = pe, *tok = nullptr;
-  int cs;
-  hb_glyph_info_t info = {0};
-  hb_glyph_position_t pos = {0};
-
-#line 343 "hb-buffer-deserialize-text.hh"
-	{
-	cs = deserialize_text_start;
-	}
-
-#line 348 "hb-buffer-deserialize-text.hh"
-	{
-	int _slen;
-	int _trans;
-	const unsigned char *_keys;
-	const char *_inds;
-	if ( p == pe )
-		goto _test_eof;
-	if ( cs == 0 )
-		goto _out;
-_resume:
-	_keys = _deserialize_text_trans_keys + (cs<<1);
-	_inds = _deserialize_text_indicies + _deserialize_text_index_offsets[cs];
-
-	_slen = _deserialize_text_key_spans[cs];
-	_trans = _inds[ _slen > 0 && _keys[0] <=(*p) &&
-		(*p) <= _keys[1] ?
-		(*p) - _keys[0] : _slen ];
-
-	cs = _deserialize_text_trans_targs[_trans];
-
-	if ( _deserialize_text_trans_actions[_trans] == 0 )
-		goto _again;
-
-	switch ( _deserialize_text_trans_actions[_trans] ) {
-	case 2:
-#line 51 "hb-buffer-deserialize-text.rl"
-	{
-	tok = p;
-}
-	break;
-	case 5:
-#line 55 "hb-buffer-deserialize-text.rl"
-	{
-	if (!hb_font_glyph_from_string (font,
-					tok, p - tok,
-					&info.codepoint))
-	  return false;
-}
-	break;
-	case 10:
-#line 62 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
-	break;
-	case 3:
-#line 63 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_int  (tok, p, &pos.x_offset )) return false; }
-	break;
-	case 12:
-#line 64 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
-	break;
-	case 7:
-#line 65 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
-	break;
-	case 1:
-#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;
-}
-	break;
-	case 4:
-#line 55 "hb-buffer-deserialize-text.rl"
-	{
-	if (!hb_font_glyph_from_string (font,
-					tok, p - tok,
-					&info.codepoint))
-	  return false;
-}
-#line 43 "hb-buffer-deserialize-text.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 9:
-#line 62 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 11:
-#line 64 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 6:
-#line 65 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 8:
-#line 66 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-#line 480 "hb-buffer-deserialize-text.hh"
-	}
-
-_again:
-	if ( cs == 0 )
-		goto _out;
-	if ( ++p != pe )
-		goto _resume;
-	_test_eof: {}
-	if ( p == eof )
-	{
-	switch ( _deserialize_text_eof_actions[cs] ) {
-	case 4:
-#line 55 "hb-buffer-deserialize-text.rl"
-	{
-	if (!hb_font_glyph_from_string (font,
-					tok, p - tok,
-					&info.codepoint))
-	  return false;
-}
-#line 43 "hb-buffer-deserialize-text.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 9:
-#line 62 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 11:
-#line 64 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 6:
-#line 65 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-	case 8:
-#line 66 "hb-buffer-deserialize-text.rl"
-	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
-	{
-	buffer->add_info (info);
-	if (buffer->in_error)
-	  return false;
-	buffer->pos[buffer->len - 1] = pos;
-	*end_ptr = p;
-}
-	break;
-#line 557 "hb-buffer-deserialize-text.hh"
-	}
-	}
-
-	_out: {}
-	}
-
-#line 119 "hb-buffer-deserialize-text.rl"
-
-
-  *end_ptr = p;
-
-  return p == pe && *(p-1) != ']';
-}
-
-#endif /* HB_BUFFER_DESERIALIZE_TEXT_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-buffer-private.hh b/third_party/harfbuzz-ng/src/hb-buffer-private.hh
deleted file mode 100644
index af4767f5..0000000
--- a/third_party/harfbuzz-ng/src/hb-buffer-private.hh
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright © 1998-2004  David Turner and Werner Lemberg
- * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_BUFFER_PRIVATE_HH
-#define HB_BUFFER_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-#include "hb-unicode-private.hh"
-
-
-#ifndef HB_BUFFER_MAX_LEN_FACTOR
-#define HB_BUFFER_MAX_LEN_FACTOR 32
-#endif
-#ifndef HB_BUFFER_MAX_LEN_MIN
-#define HB_BUFFER_MAX_LEN_MIN 8192
-#endif
-#ifndef HB_BUFFER_MAX_LEN_DEFAULT
-#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
-#endif
-
-#ifndef HB_BUFFER_MAX_OPS_FACTOR
-#define HB_BUFFER_MAX_OPS_FACTOR 64
-#endif
-#ifndef HB_BUFFER_MAX_OPS_MIN
-#define HB_BUFFER_MAX_OPS_MIN 1024
-#endif
-#ifndef HB_BUFFER_MAX_OPS_DEFAULT
-#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
-#endif
-
-static_assert ((sizeof (hb_glyph_info_t) == 20), "");
-static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
-
-HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
-HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
-HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
-
-enum hb_buffer_scratch_flags_t {
-  HB_BUFFER_SCRATCH_FLAG_DEFAULT			= 0x00000000u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII			= 0x00000001u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES		= 0x00000002u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK		= 0x00000004u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT		= 0x00000008u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK		= 0x00000010u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_CGJ			= 0x00000020u,
-
-  /* Reserved for complex shapers' internal use. */
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX0			= 0x01000000u,
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX1			= 0x02000000u,
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX2			= 0x04000000u,
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX3			= 0x08000000u,
-};
-HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
-
-
-/*
- * hb_buffer_t
- */
-
-struct hb_buffer_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  /* Information about how the text in the buffer should be treated */
-  hb_unicode_funcs_t *unicode; /* Unicode functions */
-  hb_buffer_flags_t flags; /* BOT / EOT / etc. */
-  hb_buffer_cluster_level_t cluster_level;
-  hb_codepoint_t replacement; /* U+FFFD or something else. */
-  hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
-  unsigned int max_len; /* Maximum allowed len. */
-  int max_ops; /* Maximum allowed operations. */
-
-  /* Buffer contents */
-  hb_buffer_content_type_t content_type;
-  hb_segment_properties_t props; /* Script, language, direction */
-
-  bool in_error; /* Allocation failed */
-  bool have_output; /* Whether we have an output buffer going on */
-  bool have_positions; /* Whether we have positions */
-
-  unsigned int idx; /* Cursor into ->info and ->pos arrays */
-  unsigned int len; /* Length of ->info and ->pos arrays */
-  unsigned int out_len; /* Length of ->out array if have_output */
-
-  unsigned int allocated; /* Length of allocated arrays */
-  hb_glyph_info_t     *info;
-  hb_glyph_info_t     *out_info;
-  hb_glyph_position_t *pos;
-
-  unsigned int serial;
-
-  /* Text before / after the main buffer contents.
-   * Always in Unicode, and ordered outward.
-   * Index 0 is for "pre-context", 1 for "post-context". */
-  static const unsigned int CONTEXT_LENGTH = 5;
-  hb_codepoint_t context[2][CONTEXT_LENGTH];
-  unsigned int context_len[2];
-
-  /* Debugging API */
-  hb_buffer_message_func_t message_func;
-  void *message_data;
-  hb_destroy_func_t message_destroy;
-
-  /* Internal debugging. */
-  /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
-#ifndef HB_NDEBUG
-  uint8_t allocated_var_bits;
-#endif
-
-
-  /* Methods */
-
-  inline void allocate_var (unsigned int start, unsigned int count)
-  {
-#ifndef HB_NDEBUG
-    unsigned int end = start + count;
-    assert (end <= 8);
-    unsigned int bits = (1u<<end) - (1u<<start);
-    assert (0 == (allocated_var_bits & bits));
-    allocated_var_bits |= bits;
-#endif
-  }
-  inline void deallocate_var (unsigned int start, unsigned int count)
-  {
-#ifndef HB_NDEBUG
-    unsigned int end = start + count;
-    assert (end <= 8);
-    unsigned int bits = (1u<<end) - (1u<<start);
-    assert (bits == (allocated_var_bits & bits));
-    allocated_var_bits &= ~bits;
-#endif
-  }
-  inline void assert_var (unsigned int start, unsigned int count)
-  {
-#ifndef HB_NDEBUG
-    unsigned int end = start + count;
-    assert (end <= 8);
-    unsigned int bits = (1u<<end) - (1u<<start);
-    assert (bits == (allocated_var_bits & bits));
-#endif
-  }
-  inline void deallocate_var_all (void)
-  {
-#ifndef HB_NDEBUG
-    allocated_var_bits = 0;
-#endif
-  }
-
-  inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
-  inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
-
-  inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
-  inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
-
-  inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; }
-  inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; }
-
-  inline bool has_separate_output (void) const { return info != out_info; }
-
-
-  HB_INTERNAL void reset (void);
-  HB_INTERNAL void clear (void);
-
-  inline unsigned int backtrack_len (void) const
-  { return have_output? out_len : idx; }
-  inline unsigned int lookahead_len (void) const
-  { return len - idx; }
-  inline unsigned int next_serial (void) { return serial++; }
-
-  HB_INTERNAL void add (hb_codepoint_t  codepoint,
-			unsigned int    cluster);
-  HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
-
-  HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
-  HB_INTERNAL void reverse (void);
-  HB_INTERNAL void reverse_clusters (void);
-  HB_INTERNAL void guess_segment_properties (void);
-
-  HB_INTERNAL void swap_buffers (void);
-  HB_INTERNAL void remove_output (void);
-  HB_INTERNAL void clear_output (void);
-  HB_INTERNAL void clear_positions (void);
-
-  HB_INTERNAL void replace_glyphs (unsigned int num_in,
-				   unsigned int num_out,
-				   const hb_codepoint_t *glyph_data);
-
-  HB_INTERNAL void replace_glyph (hb_codepoint_t glyph_index);
-  /* Makes a copy of the glyph at idx to output and replace glyph_index */
-  HB_INTERNAL void output_glyph (hb_codepoint_t glyph_index);
-  HB_INTERNAL void output_info (const hb_glyph_info_t &glyph_info);
-  /* Copies glyph at idx to output but doesn't advance idx */
-  HB_INTERNAL void copy_glyph (void);
-  HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
-  /* Copies glyph at idx to output and advance idx.
-   * If there's no output, just advance idx. */
-  inline void
-  next_glyph (void)
-  {
-    if (have_output)
-    {
-      if (unlikely (out_info != info || out_len != idx)) {
-	if (unlikely (!make_room_for (1, 1))) return;
-	out_info[out_len] = info[idx];
-      }
-      out_len++;
-    }
-
-    idx++;
-  }
-
-  /* Advance idx without copying to output. */
-  inline void skip_glyph (void) { idx++; }
-
-  inline void reset_masks (hb_mask_t mask)
-  {
-    for (unsigned int j = 0; j < len; j++)
-      info[j].mask = mask;
-  }
-  inline void add_masks (hb_mask_t mask)
-  {
-    for (unsigned int j = 0; j < len; j++)
-      info[j].mask |= mask;
-  }
-  HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
-			      unsigned int cluster_start, unsigned int cluster_end);
-
-  inline void merge_clusters (unsigned int start, unsigned int end)
-  {
-    if (end - start < 2)
-      return;
-    merge_clusters_impl (start, end);
-  }
-  HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end);
-  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 (void);
-
-  inline void unsafe_to_break (unsigned int start,
-			       unsigned int end)
-  {
-    if (end - start < 2)
-      return;
-    unsafe_to_break_impl (start, end);
-  }
-  HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
-  HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
-
-
-  /* Internal methods */
-  HB_INTERNAL bool enlarge (unsigned int size);
-
-  inline bool ensure (unsigned int size)
-  { return likely (!size || size < allocated) ? true : enlarge (size); }
-
-  inline bool ensure_inplace (unsigned int size)
-  { return likely (!size || size < allocated); }
-
-  HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
-  HB_INTERNAL bool shift_forward (unsigned int count);
-
-  typedef long scratch_buffer_t;
-  HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
-
-  inline void clear_context (unsigned int side) { context_len[side] = 0; }
-
-  HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
-
-  inline bool messaging (void) { return unlikely (message_func); }
-  inline bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
-  {
-    if (!messaging ())
-      return true;
-    va_list ap;
-    va_start (ap, fmt);
-    bool ret = message_impl (font, fmt, ap);
-    va_end (ap);
-    return ret;
-  }
-  HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
-
-  static inline void
-  set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
-  {
-    if (inf.cluster != cluster)
-    {
-      if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
-	inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-      else
-	inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-    }
-    inf.cluster = cluster;
-  }
-
-  inline int
-  _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
-				     unsigned int start, unsigned int end,
-				     unsigned int cluster) const
-  {
-    for (unsigned int i = start; i < end; i++)
-      cluster = MIN<unsigned int> (cluster, infos[i].cluster);
-    return cluster;
-  }
-  inline void
-  _unsafe_to_break_set_mask (hb_glyph_info_t *infos,
-			     unsigned int start, unsigned int end,
-			     unsigned int cluster)
-  {
-    for (unsigned int i = start; i < end; i++)
-      if (cluster != infos[i].cluster)
-      {
-	scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
-	infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-      }
-  }
-
-  inline void
-  unsafe_to_break_all (void)
-  {
-    unsafe_to_break_impl (0, len);
-  }
-  inline void
-  safe_to_break_all (void)
-  {
-    for (unsigned int i = 0; i < len; i++)
-      info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-  }
-};
-
-
-/* Loop over clusters. Duplicated in foreach_syllable(). */
-#define foreach_cluster(buffer, start, end) \
-  for (unsigned int \
-       _count = buffer->len, \
-       start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
-       start < _count; \
-       start = end, end = _next_cluster (buffer, start))
-
-static inline unsigned int
-_next_cluster (hb_buffer_t *buffer, unsigned int start)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  unsigned int cluster = info[start].cluster;
-  while (++start < count && cluster == info[start].cluster)
-    ;
-
-  return start;
-}
-
-
-#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
-  b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
-	   sizeof (b->info[0].var))
-#define HB_BUFFER_ALLOCATE_VAR(b, var)		HB_BUFFER_XALLOCATE_VAR (b, allocate_var,   var ())
-#define HB_BUFFER_DEALLOCATE_VAR(b, var)	HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
-#define HB_BUFFER_ASSERT_VAR(b, var)		HB_BUFFER_XALLOCATE_VAR (b, assert_var,     var ())
-
-
-#endif /* HB_BUFFER_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-buffer-serialize.cc b/third_party/harfbuzz-ng/src/hb-buffer-serialize.cc
deleted file mode 100644
index 1147194..0000000
--- a/third_party/harfbuzz-ng/src/hb-buffer-serialize.cc
+++ /dev/null
@@ -1,486 +0,0 @@
-/*
- * Copyright © 2012,2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-buffer-private.hh"
-
-
-static const char *serialize_formats[] = {
-  "text",
-  "json",
-  nullptr
-};
-
-/**
- * hb_buffer_serialize_list_formats:
- *
- * Returns a list of supported buffer serialization formats.
- *
- * Return value: (transfer none):
- * A string array of buffer serialization formats. Should not be freed.
- *
- * Since: 0.9.7
- **/
-const char **
-hb_buffer_serialize_list_formats (void)
-{
-  return serialize_formats;
-}
-
-/**
- * hb_buffer_serialize_format_from_string:
- * @str: (array length=len) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is %NULL terminated
- *
- * Parses a string into an #hb_buffer_serialize_format_t. Does not check if
- * @str is a valid buffer serialization format, use
- * hb_buffer_serialize_list_formats() to get the list of supported formats.
- *
- * Return value: 
- * The parsed #hb_buffer_serialize_format_t.
- *
- * Since: 0.9.7
- **/
-hb_buffer_serialize_format_t
-hb_buffer_serialize_format_from_string (const char *str, int len)
-{
-  /* Upper-case it. */
-  return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020u);
-}
-
-/**
- * hb_buffer_serialize_format_to_string:
- * @format: an #hb_buffer_serialize_format_t to convert.
- *
- * Converts @format to the string corresponding it, or %NULL if it is not a valid
- * #hb_buffer_serialize_format_t.
- *
- * Return value: (transfer none):
- * A %NULL terminated string corresponding to @format. Should not be freed.
- *
- * Since: 0.9.7
- **/
-const char *
-hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
-{
-  switch (format)
-  {
-    case HB_BUFFER_SERIALIZE_FORMAT_TEXT:	return serialize_formats[0];
-    case HB_BUFFER_SERIALIZE_FORMAT_JSON:	return serialize_formats[1];
-    default:
-    case HB_BUFFER_SERIALIZE_FORMAT_INVALID:	return nullptr;
-  }
-}
-
-static unsigned int
-_hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
-				  unsigned int start,
-				  unsigned int end,
-				  char *buf,
-				  unsigned int buf_size,
-				  unsigned int *buf_consumed,
-				  hb_font_t *font,
-				  hb_buffer_serialize_flags_t flags)
-{
-  hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr);
-  hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ?
-			     nullptr : hb_buffer_get_glyph_positions (buffer, nullptr);
-
-  *buf_consumed = 0;
-  hb_position_t x = 0, y = 0;
-  for (unsigned int i = start; i < end; i++)
-  {
-    char b[1024];
-    char *p = b;
-
-    /* In the following code, we know b is large enough that no overflow can happen. */
-
-#define APPEND(s) HB_STMT_START { strcpy (p, s); p += strlen (s); } HB_STMT_END
-
-    if (i)
-      *p++ = ',';
-
-    *p++ = '{';
-
-    APPEND ("\"g\":");
-    if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES))
-    {
-      char g[128];
-      hb_font_glyph_to_string (font, info[i].codepoint, g, sizeof (g));
-      *p++ = '"';
-      for (char *q = g; *q; q++) {
-        if (*q == '"')
-	  *p++ = '\\';
-	*p++ = *q;
-      }
-      *p++ = '"';
-    }
-    else
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
-
-    if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster));
-    }
-
-    if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
-    {
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
-			     x+pos[i].x_offset, y+pos[i].y_offset));
-      if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
-	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
-			       pos[i].x_advance, pos[i].y_advance));
-    }
-
-    if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
-    {
-      if (info[i].mask & HB_GLYPH_FLAG_DEFINED)
-	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED));
-    }
-
-    if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
-    {
-      hb_glyph_extents_t extents;
-      hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
-		extents.x_bearing, extents.y_bearing));
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
-		extents.width, extents.height));
-    }
-
-    *p++ = '}';
-
-    unsigned int l = p - b;
-    if (buf_size > l)
-    {
-      memcpy (buf, b, l);
-      buf += l;
-      buf_size -= l;
-      *buf_consumed += l;
-      *buf = '\0';
-    } else
-      return i - start;
-
-    if (pos && (flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
-    {
-      x += pos[i].x_advance;
-      y += pos[i].y_advance;
-    }
-  }
-
-  return end - start;
-}
-
-static unsigned int
-_hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
-				  unsigned int start,
-				  unsigned int end,
-				  char *buf,
-				  unsigned int buf_size,
-				  unsigned int *buf_consumed,
-				  hb_font_t *font,
-				  hb_buffer_serialize_flags_t flags)
-{
-  hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr);
-  hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ?
-			     nullptr : hb_buffer_get_glyph_positions (buffer, nullptr);
-
-  *buf_consumed = 0;
-  hb_position_t x = 0, y = 0;
-  for (unsigned int i = start; i < end; i++)
-  {
-    char b[1024];
-    char *p = b;
-
-    /* In the following code, we know b is large enough that no overflow can happen. */
-
-    if (i)
-      *p++ = '|';
-
-    if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES))
-    {
-      hb_font_glyph_to_string (font, info[i].codepoint, p, 128);
-      p += strlen (p);
-    }
-    else
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
-
-    if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster));
-    }
-
-    if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
-    {
-      if (x+pos[i].x_offset || y+pos[i].y_offset)
-	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", x+pos[i].x_offset, y+pos[i].y_offset));
-
-      if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
-      {
-	*p++ = '+';
-	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance));
-	if (pos[i].y_advance)
-	  p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance));
-      }
-    }
-
-    if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
-    {
-      if (info[i].mask &HB_GLYPH_FLAG_DEFINED)
-	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED));
-    }
-
-    if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
-    {
-      hb_glyph_extents_t extents;
-      hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
-    }
-
-    unsigned int l = p - b;
-    if (buf_size > l)
-    {
-      memcpy (buf, b, l);
-      buf += l;
-      buf_size -= l;
-      *buf_consumed += l;
-      *buf = '\0';
-    } else
-      return i - start;
-
-    if (pos && (flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
-    {
-      x += pos[i].x_advance;
-      y += pos[i].y_advance;
-    }
-  }
-
-  return end - start;
-}
-
-/**
- * hb_buffer_serialize_glyphs:
- * @buffer: an #hb_buffer_t buffer.
- * @start: the first item in @buffer to serialize.
- * @end: the last item in @buffer to serialize.
- * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
- *       write serialized buffer into.
- * @buf_size: the size of @buf.
- * @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf.
- * @font: (allow-none): the #hb_font_t used to shape this buffer, needed to
- *        read glyph names and extents. If %NULL, and empty font will be used.
- * @format: the #hb_buffer_serialize_format_t to use for formatting the output.
- * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
- *         to serialize.
- *
- * Serializes @buffer into a textual representation of its glyph content,
- * useful for showing the contents of the buffer, for example during debugging.
- * There are currently two supported serialization formats:
- *
- * ## text
- * A human-readable, plain text format.
- * The serialized glyphs will look something like:
- *
- * ```
- * [uni0651=0@518,0+0|uni0628=0+1897]
- * ```
- * - The serialized glyphs are delimited with `[` and `]`.
- * - Glyphs are separated with `|`
- * - Each glyph starts with glyph name, or glyph index if
- *   #HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES flag is set. Then,
- *   - If #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set, `=` then #hb_glyph_info_t.cluster.
- *   - If #HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS is not set, the #hb_glyph_position_t in the format:
- *     - If both #hb_glyph_position_t.x_offset and #hb_glyph_position_t.y_offset are not 0, `@x_offset,y_offset`. Then,
- *     - `+x_advance`, then `,y_advance` if #hb_glyph_position_t.y_advance is not 0. Then,
- *   - If #HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS is set, the
- *     #hb_glyph_extents_t in the format
- *     `&lt;x_bearing,y_bearing,width,height&gt;`
- *
- * ## json
- * TODO.
- *
- * Return value: 
- * The number of serialized items.
- *
- * Since: 0.9.7
- **/
-unsigned int
-hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
-			    unsigned int start,
-			    unsigned int end,
-			    char *buf,
-			    unsigned int buf_size,
-			    unsigned int *buf_consumed,
-			    hb_font_t *font,
-			    hb_buffer_serialize_format_t format,
-			    hb_buffer_serialize_flags_t flags)
-{
-  assert (start <= end && end <= buffer->len);
-
-  unsigned int sconsumed;
-  if (!buf_consumed)
-    buf_consumed = &sconsumed;
-  *buf_consumed = 0;
-  if (buf_size)
-    *buf = '\0';
-
-  assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
-	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
-
-  if (!buffer->have_positions)
-    flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS;
-
-  if (unlikely (start == end))
-    return 0;
-
-  if (!font)
-    font = hb_font_get_empty ();
-
-  switch (format)
-  {
-    case HB_BUFFER_SERIALIZE_FORMAT_TEXT:
-      return _hb_buffer_serialize_glyphs_text (buffer, start, end,
-					       buf, buf_size, buf_consumed,
-					       font, flags);
-
-    case HB_BUFFER_SERIALIZE_FORMAT_JSON:
-      return _hb_buffer_serialize_glyphs_json (buffer, start, end,
-					       buf, buf_size, buf_consumed,
-					       font, flags);
-
-    default:
-    case HB_BUFFER_SERIALIZE_FORMAT_INVALID:
-      return 0;
-
-  }
-}
-
-
-static hb_bool_t
-parse_uint (const char *pp, const char *end, uint32_t *pv)
-{
-  char buf[32];
-  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
-  strncpy (buf, pp, len);
-  buf[len] = '\0';
-
-  char *p = buf;
-  char *pend = p;
-  uint32_t v;
-
-  errno = 0;
-  v = strtol (p, &pend, 10);
-  if (errno || p == pend || pend - p != end - pp)
-    return false;
-
-  *pv = v;
-  return true;
-}
-
-static hb_bool_t
-parse_int (const char *pp, const char *end, int32_t *pv)
-{
-  char buf[32];
-  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
-  strncpy (buf, pp, len);
-  buf[len] = '\0';
-
-  char *p = buf;
-  char *pend = p;
-  int32_t v;
-
-  errno = 0;
-  v = strtol (p, &pend, 10);
-  if (errno || p == pend || pend - p != end - pp)
-    return false;
-
-  *pv = v;
-  return true;
-}
-
-#include "hb-buffer-deserialize-json.hh"
-#include "hb-buffer-deserialize-text.hh"
-
-/**
- * hb_buffer_deserialize_glyphs:
- * @buffer: an #hb_buffer_t buffer.
- * @buf: (array length=buf_len):
- * @buf_len: 
- * @end_ptr: (out):
- * @font: 
- * @format: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.7
- **/
-hb_bool_t
-hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
-			      const char *buf,
-			      int buf_len, /* -1 means nul-terminated */
-			      const char **end_ptr, /* May be nullptr */
-			      hb_font_t *font, /* May be nullptr */
-			      hb_buffer_serialize_format_t format)
-{
-  const char *end;
-  if (!end_ptr)
-    end_ptr = &end;
-  *end_ptr = buf;
-
-  assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
-	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
-
-  if (buf_len == -1)
-    buf_len = strlen (buf);
-
-  if (!buf_len)
-  {
-    *end_ptr = buf;
-    return false;
-  }
-
-  hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS);
-
-  if (!font)
-    font = hb_font_get_empty ();
-
-  switch (format)
-  {
-    case HB_BUFFER_SERIALIZE_FORMAT_TEXT:
-      return _hb_buffer_deserialize_glyphs_text (buffer,
-						 buf, buf_len, end_ptr,
-						 font);
-
-    case HB_BUFFER_SERIALIZE_FORMAT_JSON:
-      return _hb_buffer_deserialize_glyphs_json (buffer,
-						 buf, buf_len, end_ptr,
-						 font);
-
-    default:
-    case HB_BUFFER_SERIALIZE_FORMAT_INVALID:
-      return false;
-
-  }
-}
diff --git a/third_party/harfbuzz-ng/src/hb-buffer.cc b/third_party/harfbuzz-ng/src/hb-buffer.cc
deleted file mode 100644
index dc0639f..0000000
--- a/third_party/harfbuzz-ng/src/hb-buffer.cc
+++ /dev/null
@@ -1,2010 +0,0 @@
-/*
- * Copyright © 1998-2004  David Turner and Werner Lemberg
- * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-buffer-private.hh"
-#include "hb-utf-private.hh"
-
-
-/**
- * SECTION: hb-buffer
- * @title: Buffers
- * @short_description: Input and output buffers
- * @include: hb.h
- *
- * Buffers serve dual role in HarfBuzz; they hold the input characters that are
- * passed hb_shape(), and after shaping they hold the output glyphs.
- **/
-
-/**
- * hb_segment_properties_equal:
- * @a: first #hb_segment_properties_t to compare.
- * @b: second #hb_segment_properties_t to compare.
- *
- * Checks the equality of two #hb_segment_properties_t's.
- *
- * Return value:
- * %true if all properties of @a equal those of @b, false otherwise.
- *
- * Since: 0.9.7
- **/
-hb_bool_t
-hb_segment_properties_equal (const hb_segment_properties_t *a,
-			     const hb_segment_properties_t *b)
-{
-  return a->direction == b->direction &&
-	 a->script    == b->script    &&
-	 a->language  == b->language  &&
-	 a->reserved1 == b->reserved1 &&
-	 a->reserved2 == b->reserved2;
-
-}
-
-/**
- * hb_segment_properties_hash:
- * @p: #hb_segment_properties_t to hash.
- *
- * Creates a hash representing @p.
- *
- * Return value:
- * A hash of @p.
- *
- * Since: 0.9.7
- **/
-unsigned int
-hb_segment_properties_hash (const hb_segment_properties_t *p)
-{
-  return (unsigned int) p->direction ^
-	 (unsigned int) p->script ^
-	 (intptr_t) (p->language);
-}
-
-
-
-/* Here is how the buffer works internally:
- *
- * There are two info pointers: info and out_info.  They always have
- * the same allocated size, but different lengths.
- *
- * As an optimization, both info and out_info may point to the
- * same piece of memory, which is owned by info.  This remains the
- * case as long as out_len doesn't exceed i at any time.
- * In that case, swap_buffers() is no-op and the glyph operations operate
- * mostly in-place.
- *
- * As soon as out_info gets longer than info, out_info is moved over
- * to an alternate buffer (which we reuse the pos buffer for!), and its
- * current contents (out_len entries) are copied to the new place.
- * This should all remain transparent to the user.  swap_buffers() then
- * switches info and out_info.
- */
-
-
-
-/* Internal API */
-
-bool
-hb_buffer_t::enlarge (unsigned int size)
-{
-  if (unlikely (in_error))
-    return false;
-  if (unlikely (size > max_len))
-  {
-    in_error = true;
-    return false;
-  }
-
-  unsigned int new_allocated = allocated;
-  hb_glyph_position_t *new_pos = nullptr;
-  hb_glyph_info_t *new_info = nullptr;
-  bool separate_out = out_info != info;
-
-  if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
-    goto done;
-
-  while (size >= new_allocated)
-    new_allocated += (new_allocated >> 1) + 32;
-
-  static_assert ((sizeof (info[0]) == sizeof (pos[0])), "");
-  if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
-    goto done;
-
-  new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
-  new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0]));
-
-done:
-  if (unlikely (!new_pos || !new_info))
-    in_error = true;
-
-  if (likely (new_pos))
-    pos = new_pos;
-
-  if (likely (new_info))
-    info = new_info;
-
-  out_info = separate_out ? (hb_glyph_info_t *) pos : info;
-  if (likely (!in_error))
-    allocated = new_allocated;
-
-  return likely (!in_error);
-}
-
-bool
-hb_buffer_t::make_room_for (unsigned int num_in,
-			    unsigned int num_out)
-{
-  if (unlikely (!ensure (out_len + num_out))) return false;
-
-  if (out_info == info &&
-      out_len + num_out > idx + num_in)
-  {
-    assert (have_output);
-
-    out_info = (hb_glyph_info_t *) pos;
-    memcpy (out_info, info, out_len * sizeof (out_info[0]));
-  }
-
-  return true;
-}
-
-bool
-hb_buffer_t::shift_forward (unsigned int count)
-{
-  assert (have_output);
-  if (unlikely (!ensure (len + count))) return false;
-
-  memmove (info + idx + count, info + idx, (len - idx) * sizeof (info[0]));
-  if (idx + count > len)
-  {
-    /* Under memory failure we might expose this area.  At least
-     * clean it up.  Oh well... */
-    memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
-  }
-  len += count;
-  idx += count;
-
-  return true;
-}
-
-hb_buffer_t::scratch_buffer_t *
-hb_buffer_t::get_scratch_buffer (unsigned int *size)
-{
-  have_output = false;
-  have_positions = false;
-
-  out_len = 0;
-  out_info = info;
-
-  assert ((uintptr_t) pos % sizeof (scratch_buffer_t) == 0);
-  *size = allocated * sizeof (pos[0]) / sizeof (scratch_buffer_t);
-  return (scratch_buffer_t *) (void *) pos;
-}
-
-
-
-/* HarfBuzz-Internal API */
-
-void
-hb_buffer_t::reset (void)
-{
-  if (unlikely (hb_object_is_inert (this)))
-    return;
-
-  hb_unicode_funcs_destroy (unicode);
-  unicode = hb_unicode_funcs_get_default ();
-  flags = HB_BUFFER_FLAG_DEFAULT;
-  replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
-
-  clear ();
-}
-
-void
-hb_buffer_t::clear (void)
-{
-  if (unlikely (hb_object_is_inert (this)))
-    return;
-
-  hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
-  props = default_props;
-  scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
-
-  content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
-  in_error = false;
-  have_output = false;
-  have_positions = false;
-
-  idx = 0;
-  len = 0;
-  out_len = 0;
-  out_info = info;
-
-  serial = 0;
-
-  memset (context, 0, sizeof context);
-  memset (context_len, 0, sizeof context_len);
-
-  deallocate_var_all ();
-}
-
-void
-hb_buffer_t::add (hb_codepoint_t  codepoint,
-		  unsigned int    cluster)
-{
-  hb_glyph_info_t *glyph;
-
-  if (unlikely (!ensure (len + 1))) return;
-
-  glyph = &info[len];
-
-  memset (glyph, 0, sizeof (*glyph));
-  glyph->codepoint = codepoint;
-  glyph->mask = 0;
-  glyph->cluster = cluster;
-
-  len++;
-}
-
-void
-hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info)
-{
-  if (unlikely (!ensure (len + 1))) return;
-
-  info[len] = glyph_info;
-
-  len++;
-}
-
-
-void
-hb_buffer_t::remove_output (void)
-{
-  if (unlikely (hb_object_is_inert (this)))
-    return;
-
-  have_output = false;
-  have_positions = false;
-
-  out_len = 0;
-  out_info = info;
-}
-
-void
-hb_buffer_t::clear_output (void)
-{
-  if (unlikely (hb_object_is_inert (this)))
-    return;
-
-  have_output = true;
-  have_positions = false;
-
-  out_len = 0;
-  out_info = info;
-}
-
-void
-hb_buffer_t::clear_positions (void)
-{
-  if (unlikely (hb_object_is_inert (this)))
-    return;
-
-  have_output = false;
-  have_positions = true;
-
-  out_len = 0;
-  out_info = info;
-
-  memset (pos, 0, sizeof (pos[0]) * len);
-}
-
-void
-hb_buffer_t::swap_buffers (void)
-{
-  if (unlikely (in_error)) return;
-
-  assert (have_output);
-  have_output = false;
-
-  if (out_info != info)
-  {
-    hb_glyph_info_t *tmp_string;
-    tmp_string = info;
-    info = out_info;
-    out_info = tmp_string;
-    pos = (hb_glyph_position_t *) out_info;
-  }
-
-  unsigned int tmp;
-  tmp = len;
-  len = out_len;
-  out_len = tmp;
-
-  idx = 0;
-}
-
-
-void
-hb_buffer_t::replace_glyphs (unsigned int num_in,
-			     unsigned int num_out,
-			     const uint32_t *glyph_data)
-{
-  if (unlikely (!make_room_for (num_in, num_out))) return;
-
-  merge_clusters (idx, idx + num_in);
-
-  hb_glyph_info_t orig_info = info[idx];
-  hb_glyph_info_t *pinfo = &out_info[out_len];
-  for (unsigned int i = 0; i < num_out; i++)
-  {
-    *pinfo = orig_info;
-    pinfo->codepoint = glyph_data[i];
-    pinfo++;
-  }
-
-  idx  += num_in;
-  out_len += num_out;
-}
-
-void
-hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = info[idx];
-  out_info[out_len].codepoint = glyph_index;
-
-  out_len++;
-}
-
-void
-hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = glyph_info;
-
-  out_len++;
-}
-
-void
-hb_buffer_t::copy_glyph (void)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = info[idx];
-
-  out_len++;
-}
-
-bool
-hb_buffer_t::move_to (unsigned int i)
-{
-  if (!have_output)
-  {
-    assert (i <= len);
-    idx = i;
-    return true;
-  }
-  if (unlikely (in_error))
-    return false;
-
-  assert (i <= out_len + (len - idx));
-
-  if (out_len < i)
-  {
-    unsigned int count = i - out_len;
-    if (unlikely (!make_room_for (count, count))) return false;
-
-    memmove (out_info + out_len, info + idx, count * sizeof (out_info[0]));
-    idx += count;
-    out_len += count;
-  }
-  else if (out_len > i)
-  {
-    /* Tricky part: rewinding... */
-    unsigned int count = out_len - i;
-
-    /* This will blow in our face if memory allocation fails later
-     * in this same lookup... */
-    if (unlikely (idx < count && !shift_forward (count + 32))) return false;
-
-    assert (idx >= count);
-
-    idx -= count;
-    out_len -= count;
-    memmove (info + idx, out_info + out_len, count * sizeof (out_info[0]));
-  }
-
-  return true;
-}
-
-void
-hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
-{
-  if (unlikely (out_info != info || out_len != idx)) {
-    if (unlikely (!make_room_for (1, 1))) return;
-    out_info[out_len] = info[idx];
-  }
-  out_info[out_len].codepoint = glyph_index;
-
-  idx++;
-  out_len++;
-}
-
-
-void
-hb_buffer_t::set_masks (hb_mask_t    value,
-			hb_mask_t    mask,
-			unsigned int cluster_start,
-			unsigned int cluster_end)
-{
-  hb_mask_t not_mask = ~mask;
-  value &= mask;
-
-  if (!mask)
-    return;
-
-  if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      info[i].mask = (info[i].mask & not_mask) | value;
-    return;
-  }
-
-  unsigned int count = len;
-  for (unsigned int i = 0; i < count; i++)
-    if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end)
-      info[i].mask = (info[i].mask & not_mask) | value;
-}
-
-void
-hb_buffer_t::reverse_range (unsigned int start,
-			    unsigned int end)
-{
-  unsigned int i, j;
-
-  if (end - start < 2)
-    return;
-
-  for (i = start, j = end - 1; i < j; i++, j--) {
-    hb_glyph_info_t t;
-
-    t = info[i];
-    info[i] = info[j];
-    info[j] = t;
-  }
-
-  if (have_positions) {
-    for (i = start, j = end - 1; i < j; i++, j--) {
-      hb_glyph_position_t t;
-
-      t = pos[i];
-      pos[i] = pos[j];
-      pos[j] = t;
-    }
-  }
-}
-
-void
-hb_buffer_t::reverse (void)
-{
-  if (unlikely (!len))
-    return;
-
-  reverse_range (0, len);
-}
-
-void
-hb_buffer_t::reverse_clusters (void)
-{
-  unsigned int i, start, count, last_cluster;
-
-  if (unlikely (!len))
-    return;
-
-  reverse ();
-
-  count = len;
-  start = 0;
-  last_cluster = info[0].cluster;
-  for (i = 1; i < count; i++) {
-    if (last_cluster != info[i].cluster) {
-      reverse_range (start, i);
-      start = i;
-      last_cluster = info[i].cluster;
-    }
-  }
-  reverse_range (start, i);
-}
-
-void
-hb_buffer_t::merge_clusters_impl (unsigned int start,
-				  unsigned int end)
-{
-  if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
-  {
-    unsafe_to_break (start, end);
-    return;
-  }
-
-  unsigned int cluster = info[start].cluster;
-
-  for (unsigned int i = start + 1; i < end; i++)
-    cluster = MIN<unsigned int> (cluster, info[i].cluster);
-
-  /* Extend end */
-  while (end < len && info[end - 1].cluster == info[end].cluster)
-    end++;
-
-  /* Extend start */
-  while (idx < start && info[start - 1].cluster == info[start].cluster)
-    start--;
-
-  /* If we hit the start of buffer, continue in out-buffer. */
-  if (idx == start)
-    for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--)
-      set_cluster (out_info[i - 1], cluster);
-
-  for (unsigned int i = start; i < end; i++)
-    set_cluster (info[i], cluster);
-}
-void
-hb_buffer_t::merge_out_clusters (unsigned int start,
-				 unsigned int end)
-{
-  if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
-    return;
-
-  if (unlikely (end - start < 2))
-    return;
-
-  unsigned int cluster = out_info[start].cluster;
-
-  for (unsigned int i = start + 1; i < end; i++)
-    cluster = MIN<unsigned int> (cluster, out_info[i].cluster);
-
-  /* Extend start */
-  while (start && out_info[start - 1].cluster == out_info[start].cluster)
-    start--;
-
-  /* Extend end */
-  while (end < out_len && out_info[end - 1].cluster == out_info[end].cluster)
-    end++;
-
-  /* If we hit the end of out-buffer, continue in buffer. */
-  if (end == out_len)
-    for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++)
-      set_cluster (info[i], cluster);
-
-  for (unsigned int i = start; i < end; i++)
-    set_cluster (out_info[i], cluster);
-}
-void
-hb_buffer_t::delete_glyph ()
-{
-  /* The logic here is duplicated in hb_ot_hide_default_ignorables(). */
-
-  unsigned int cluster = info[idx].cluster;
-  if (idx + 1 < len && cluster == info[idx + 1].cluster)
-  {
-    /* Cluster survives; do nothing. */
-    goto done;
-  }
-
-  if (out_len)
-  {
-    /* Merge cluster backward. */
-    if (cluster < out_info[out_len - 1].cluster)
-    {
-      unsigned int mask = info[idx].mask;
-      unsigned int old_cluster = out_info[out_len - 1].cluster;
-      for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--)
-	set_cluster (out_info[i - 1], cluster, mask);
-    }
-    goto done;
-  }
-
-  if (idx + 1 < len)
-  {
-    /* Merge cluster forward. */
-    merge_clusters (idx, idx + 2);
-    goto done;
-  }
-
-done:
-  skip_glyph ();
-}
-
-void
-hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end)
-{
-  unsigned int cluster = (unsigned int) -1;
-  cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster);
-  _unsafe_to_break_set_mask (info, start, end, cluster);
-}
-void
-hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end)
-{
-  if (!have_output)
-  {
-    unsafe_to_break_impl (start, end);
-    return;
-  }
-
-  assert (start <= out_len);
-  assert (idx <= end);
-
-  unsigned int cluster = (unsigned int) -1;
-  cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster);
-  cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster);
-  _unsafe_to_break_set_mask (out_info, start, out_len, cluster);
-  _unsafe_to_break_set_mask (info, idx, end, cluster);
-}
-
-void
-hb_buffer_t::guess_segment_properties (void)
-{
-  assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
-	  (!len && content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
-
-  /* If script is set to INVALID, guess from buffer contents */
-  if (props.script == HB_SCRIPT_INVALID) {
-    for (unsigned int i = 0; i < len; i++) {
-      hb_script_t script = unicode->script (info[i].codepoint);
-      if (likely (script != HB_SCRIPT_COMMON &&
-		  script != HB_SCRIPT_INHERITED &&
-		  script != HB_SCRIPT_UNKNOWN)) {
-        props.script = script;
-        break;
-      }
-    }
-  }
-
-  /* If direction is set to INVALID, guess from script */
-  if (props.direction == HB_DIRECTION_INVALID) {
-    props.direction = hb_script_get_horizontal_direction (props.script);
-  }
-
-  /* If language is not set, use default language from locale */
-  if (props.language == HB_LANGUAGE_INVALID) {
-    /* TODO get_default_for_script? using $LANGUAGE */
-    props.language = hb_language_get_default ();
-  }
-}
-
-
-/* Public API */
-
-/**
- * hb_buffer_create: (Xconstructor)
- *
- * Creates a new #hb_buffer_t with all properties to defaults.
- *
- * Return value: (transfer full):
- * A newly allocated #hb_buffer_t with a reference count of 1. The initial
- * reference count should be released with hb_buffer_destroy() when you are done
- * using the #hb_buffer_t. This function never returns %NULL. If memory cannot
- * be allocated, a special #hb_buffer_t object will be returned on which
- * hb_buffer_allocation_successful() returns %false.
- *
- * Since: 0.9.2
- **/
-hb_buffer_t *
-hb_buffer_create (void)
-{
-  hb_buffer_t *buffer;
-
-  if (!(buffer = hb_object_create<hb_buffer_t> ()))
-    return hb_buffer_get_empty ();
-
-  buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
-  buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
-
-  buffer->reset ();
-
-  return buffer;
-}
-
-/**
- * hb_buffer_get_empty:
- *
- * 
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.2
- **/
-hb_buffer_t *
-hb_buffer_get_empty (void)
-{
-  static const hb_buffer_t _hb_buffer_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
-    HB_BUFFER_FLAG_DEFAULT,
-    HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
-    HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
-    HB_BUFFER_SCRATCH_FLAG_DEFAULT,
-    HB_BUFFER_MAX_LEN_DEFAULT,
-    HB_BUFFER_MAX_OPS_DEFAULT,
-
-    HB_BUFFER_CONTENT_TYPE_INVALID,
-    HB_SEGMENT_PROPERTIES_DEFAULT,
-    true, /* in_error */
-    true, /* have_output */
-    true  /* have_positions */
-
-    /* Zero is good enough for everything else. */
-  };
-
-  return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
-}
-
-/**
- * hb_buffer_reference: (skip)
- * @buffer: an #hb_buffer_t.
- *
- * Increases the reference count on @buffer by one. This prevents @buffer from
- * being destroyed until a matching call to hb_buffer_destroy() is made.
- *
- * Return value: (transfer full):
- * The referenced #hb_buffer_t.
- *
- * Since: 0.9.2
- **/
-hb_buffer_t *
-hb_buffer_reference (hb_buffer_t *buffer)
-{
-  return hb_object_reference (buffer);
-}
-
-/**
- * hb_buffer_destroy: (skip)
- * @buffer: an #hb_buffer_t.
- *
- * Deallocate the @buffer.
- * Decreases the reference count on @buffer by one. If the result is zero, then
- * @buffer and all associated resources are freed. See hb_buffer_reference().
- *
- * Since: 0.9.2
- **/
-void
-hb_buffer_destroy (hb_buffer_t *buffer)
-{
-  if (!hb_object_destroy (buffer)) return;
-
-  hb_unicode_funcs_destroy (buffer->unicode);
-
-  free (buffer->info);
-  free (buffer->pos);
-  if (buffer->message_destroy)
-    buffer->message_destroy (buffer->message_data);
-
-  free (buffer);
-}
-
-/**
- * hb_buffer_set_user_data: (skip)
- * @buffer: an #hb_buffer_t.
- * @key: 
- * @data: 
- * @destroy: 
- * @replace: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_buffer_set_user_data (hb_buffer_t        *buffer,
-			 hb_user_data_key_t *key,
-			 void *              data,
-			 hb_destroy_func_t   destroy,
-			 hb_bool_t           replace)
-{
-  return hb_object_set_user_data (buffer, key, data, destroy, replace);
-}
-
-/**
- * hb_buffer_get_user_data: (skip)
- * @buffer: an #hb_buffer_t.
- * @key: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-void *
-hb_buffer_get_user_data (hb_buffer_t        *buffer,
-			 hb_user_data_key_t *key)
-{
-  return hb_object_get_user_data (buffer, key);
-}
-
-
-/**
- * hb_buffer_set_content_type:
- * @buffer: an #hb_buffer_t.
- * @content_type: the type of buffer contents to set
- *
- * Sets the type of @buffer contents, buffers are either empty, contain
- * characters (before shaping) or glyphs (the result of shaping).
- *
- * Since: 0.9.5
- **/
-void
-hb_buffer_set_content_type (hb_buffer_t              *buffer,
-			    hb_buffer_content_type_t  content_type)
-{
-  buffer->content_type = content_type;
-}
-
-/**
- * hb_buffer_get_content_type:
- * @buffer: an #hb_buffer_t.
- *
- * see hb_buffer_set_content_type().
- *
- * Return value:
- * The type of @buffer contents.
- *
- * Since: 0.9.5
- **/
-hb_buffer_content_type_t
-hb_buffer_get_content_type (hb_buffer_t *buffer)
-{
-  return buffer->content_type;
-}
-
-
-/**
- * hb_buffer_set_unicode_funcs:
- * @buffer: an #hb_buffer_t.
- * @unicode_funcs: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
-			     hb_unicode_funcs_t *unicode_funcs)
-{
-  if (unlikely (hb_object_is_inert (buffer)))
-    return;
-
-  if (!unicode_funcs)
-    unicode_funcs = hb_unicode_funcs_get_default ();
-
-
-  hb_unicode_funcs_reference (unicode_funcs);
-  hb_unicode_funcs_destroy (buffer->unicode);
-  buffer->unicode = unicode_funcs;
-}
-
-/**
- * hb_buffer_get_unicode_funcs:
- * @buffer: an #hb_buffer_t.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_unicode_funcs_t *
-hb_buffer_get_unicode_funcs (hb_buffer_t        *buffer)
-{
-  return buffer->unicode;
-}
-
-/**
- * hb_buffer_set_direction:
- * @buffer: an #hb_buffer_t.
- * @direction: the #hb_direction_t of the @buffer
- *
- * Set the text flow direction of the buffer. No shaping can happen without
- * setting @buffer direction, and it controls the visual direction for the
- * output glyphs; for RTL direction the glyphs will be reversed. Many layout
- * features depend on the proper setting of the direction, for example,
- * reversing RTL text before shaping, then shaping with LTR direction is not
- * the same as keeping the text in logical order and shaping with RTL
- * direction.
- *
- * Since: 0.9.2
- **/
-void
-hb_buffer_set_direction (hb_buffer_t    *buffer,
-			 hb_direction_t  direction)
-
-{
-  if (unlikely (hb_object_is_inert (buffer)))
-    return;
-
-  buffer->props.direction = direction;
-}
-
-/**
- * hb_buffer_get_direction:
- * @buffer: an #hb_buffer_t.
- *
- * See hb_buffer_set_direction()
- *
- * Return value:
- * The direction of the @buffer.
- *
- * Since: 0.9.2
- **/
-hb_direction_t
-hb_buffer_get_direction (hb_buffer_t    *buffer)
-{
-  return buffer->props.direction;
-}
-
-/**
- * hb_buffer_set_script:
- * @buffer: an #hb_buffer_t.
- * @script: an #hb_script_t to set.
- *
- * Sets the script of @buffer to @script.
- *
- * Script is crucial for choosing the proper shaping behaviour for scripts that
- * require it (e.g. Arabic) and the which OpenType features defined in the font
- * to be applied.
- *
- * You can pass one of the predefined #hb_script_t values, or use
- * hb_script_from_string() or hb_script_from_iso15924_tag() to get the
- * corresponding script from an ISO 15924 script tag.
- *
- * Since: 0.9.2
- **/
-void
-hb_buffer_set_script (hb_buffer_t *buffer,
-		      hb_script_t  script)
-{
-  if (unlikely (hb_object_is_inert (buffer)))
-    return;
-
-  buffer->props.script = script;
-}
-
-/**
- * hb_buffer_get_script:
- * @buffer: an #hb_buffer_t.
- *
- * See hb_buffer_set_script().
- *
- * Return value:
- * The #hb_script_t of the @buffer.
- *
- * Since: 0.9.2
- **/
-hb_script_t
-hb_buffer_get_script (hb_buffer_t *buffer)
-{
-  return buffer->props.script;
-}
-
-/**
- * hb_buffer_set_language:
- * @buffer: an #hb_buffer_t.
- * @language: an hb_language_t to set.
- *
- * Sets the language of @buffer to @language.
- *
- * Languages are crucial for selecting which OpenType feature to apply to the
- * buffer which can result in applying language-specific behaviour. Languages
- * are orthogonal to the scripts, and though they are related, they are
- * different concepts and should not be confused with each other.
- *
- * Use hb_language_from_string() to convert from ISO 639 language codes to
- * #hb_language_t.
- *
- * Since: 0.9.2
- **/
-void
-hb_buffer_set_language (hb_buffer_t   *buffer,
-			hb_language_t  language)
-{
-  if (unlikely (hb_object_is_inert (buffer)))
-    return;
-
-  buffer->props.language = language;
-}
-
-/**
- * hb_buffer_get_language:
- * @buffer: an #hb_buffer_t.
- *
- * See hb_buffer_set_language().
- *
- * Return value: (transfer none):
- * The #hb_language_t of the buffer. Must not be freed by the caller.
- *
- * Since: 0.9.2
- **/
-hb_language_t
-hb_buffer_get_language (hb_buffer_t *buffer)
-{
-  return buffer->props.language;
-}
-
-/**
- * hb_buffer_set_segment_properties:
- * @buffer: an #hb_buffer_t.
- * @props: an #hb_segment_properties_t to use.
- *
- * Sets the segment properties of the buffer, a shortcut for calling
- * hb_buffer_set_direction(), hb_buffer_set_script() and
- * hb_buffer_set_language() individually.
- *
- * Since: 0.9.7
- **/
-void
-hb_buffer_set_segment_properties (hb_buffer_t *buffer,
-				  const hb_segment_properties_t *props)
-{
-  if (unlikely (hb_object_is_inert (buffer)))
-    return;
-
-  buffer->props = *props;
-}
-
-/**
- * hb_buffer_get_segment_properties:
- * @buffer: an #hb_buffer_t.
- * @props: (out): the output #hb_segment_properties_t.
- *
- * Sets @props to the #hb_segment_properties_t of @buffer.
- *
- * Since: 0.9.7
- **/
-void
-hb_buffer_get_segment_properties (hb_buffer_t *buffer,
-				  hb_segment_properties_t *props)
-{
-  *props = buffer->props;
-}
-
-
-/**
- * hb_buffer_set_flags:
- * @buffer: an #hb_buffer_t.
- * @flags: the buffer flags to set.
- *
- * Sets @buffer flags to @flags. See #hb_buffer_flags_t.
- *
- * Since: 0.9.7
- **/
-void
-hb_buffer_set_flags (hb_buffer_t       *buffer,
-		     hb_buffer_flags_t  flags)
-{
-  if (unlikely (hb_object_is_inert (buffer)))
-    return;
-
-  buffer->flags = flags;
-}
-
-/**
- * hb_buffer_get_flags:
- * @buffer: an #hb_buffer_t.
- *
- * See hb_buffer_set_flags().
- *
- * Return value: 
- * The @buffer flags.
- *
- * Since: 0.9.7
- **/
-hb_buffer_flags_t
-hb_buffer_get_flags (hb_buffer_t *buffer)
-{
-  return buffer->flags;
-}
-
-/**
- * hb_buffer_set_cluster_level:
- * @buffer: an #hb_buffer_t.
- * @cluster_level: 
- *
- * 
- *
- * Since: 0.9.42
- **/
-void
-hb_buffer_set_cluster_level (hb_buffer_t       *buffer,
-		     hb_buffer_cluster_level_t  cluster_level)
-{
-  if (unlikely (hb_object_is_inert (buffer)))
-    return;
-
-  buffer->cluster_level = cluster_level;
-}
-
-/**
- * hb_buffer_get_cluster_level:
- * @buffer: an #hb_buffer_t.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.42
- **/
-hb_buffer_cluster_level_t
-hb_buffer_get_cluster_level (hb_buffer_t *buffer)
-{
-  return buffer->cluster_level;
-}
-
-
-/**
- * hb_buffer_set_replacement_codepoint:
- * @buffer: an #hb_buffer_t.
- * @replacement: the replacement #hb_codepoint_t
- *
- * Sets the #hb_codepoint_t that replaces invalid entries for a given encoding
- * when adding text to @buffer.
- *
- * Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT.
- *
- * Since: 0.9.31
- **/
-void
-hb_buffer_set_replacement_codepoint (hb_buffer_t    *buffer,
-				     hb_codepoint_t  replacement)
-{
-  if (unlikely (hb_object_is_inert (buffer)))
-    return;
-
-  buffer->replacement = replacement;
-}
-
-/**
- * hb_buffer_get_replacement_codepoint:
- * @buffer: an #hb_buffer_t.
- *
- * See hb_buffer_set_replacement_codepoint().
- *
- * Return value: 
- * The @buffer replacement #hb_codepoint_t.
- *
- * Since: 0.9.31
- **/
-hb_codepoint_t
-hb_buffer_get_replacement_codepoint (hb_buffer_t    *buffer)
-{
-  return buffer->replacement;
-}
-
-
-/**
- * hb_buffer_reset:
- * @buffer: an #hb_buffer_t.
- *
- * Resets the buffer to its initial status, as if it was just newly created
- * with hb_buffer_create().
- *
- * Since: 0.9.2
- **/
-void
-hb_buffer_reset (hb_buffer_t *buffer)
-{
-  buffer->reset ();
-}
-
-/**
- * hb_buffer_clear_contents:
- * @buffer: an #hb_buffer_t.
- *
- * Similar to hb_buffer_reset(), but does not clear the Unicode functions and
- * the replacement code point.
- *
- * Since: 0.9.11
- **/
-void
-hb_buffer_clear_contents (hb_buffer_t *buffer)
-{
-  buffer->clear ();
-}
-
-/**
- * hb_buffer_pre_allocate:
- * @buffer: an #hb_buffer_t.
- * @size: number of items to pre allocate.
- *
- * Pre allocates memory for @buffer to fit at least @size number of items.
- *
- * Return value:
- * %true if @buffer memory allocation succeeded, %false otherwise.
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
-{
-  return buffer->ensure (size);
-}
-
-/**
- * hb_buffer_allocation_successful:
- * @buffer: an #hb_buffer_t.
- *
- * Check if allocating memory for the buffer succeeded.
- *
- * Return value:
- * %true if @buffer memory allocation succeeded, %false otherwise.
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_buffer_allocation_successful (hb_buffer_t  *buffer)
-{
-  return !buffer->in_error;
-}
-
-/**
- * hb_buffer_add:
- * @buffer: an #hb_buffer_t.
- * @codepoint: a Unicode code point.
- * @cluster: the cluster value of @codepoint.
- *
- * Appends a character with the Unicode value of @codepoint to @buffer, and
- * gives it the initial cluster value of @cluster. Clusters can be any thing
- * the client wants, they are usually used to refer to the index of the
- * character in the input text stream and are output in
- * #hb_glyph_info_t.cluster field.
- *
- * This function does not check the validity of @codepoint, it is up to the
- * caller to ensure it is a valid Unicode code point.
- *
- * Since: 0.9.7
- **/
-void
-hb_buffer_add (hb_buffer_t    *buffer,
-	       hb_codepoint_t  codepoint,
-	       unsigned int    cluster)
-{
-  buffer->add (codepoint, cluster);
-  buffer->clear_context (1);
-}
-
-/**
- * hb_buffer_set_length:
- * @buffer: an #hb_buffer_t.
- * @length: the new length of @buffer.
- *
- * Similar to hb_buffer_pre_allocate(), but clears any new items added at the
- * end.
- *
- * Return value: 
- * %true if @buffer memory allocation succeeded, %false otherwise.
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_buffer_set_length (hb_buffer_t  *buffer,
-		      unsigned int  length)
-{
-  if (unlikely (hb_object_is_inert (buffer)))
-    return length == 0;
-
-  if (!buffer->ensure (length))
-    return false;
-
-  /* Wipe the new space */
-  if (length > buffer->len) {
-    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));
-  }
-
-  buffer->len = length;
-
-  if (!length)
-  {
-    buffer->content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
-    buffer->clear_context (0);
-  }
-  buffer->clear_context (1);
-
-  return true;
-}
-
-/**
- * hb_buffer_get_length:
- * @buffer: an #hb_buffer_t.
- *
- * Returns the number of items in the buffer.
- *
- * Return value:
- * The @buffer length.
- * The value valid as long as buffer has not been modified.
- *
- * Since: 0.9.2
- **/
-unsigned int
-hb_buffer_get_length (hb_buffer_t *buffer)
-{
-  return buffer->len;
-}
-
-/**
- * hb_buffer_get_glyph_infos:
- * @buffer: an #hb_buffer_t.
- * @length: (out): output array length.
- *
- * Returns @buffer glyph information array.  Returned pointer
- * is valid as long as @buffer contents are not modified.
- *
- * Return value: (transfer none) (array length=length):
- * The @buffer glyph information array.
- * The value valid as long as buffer has not been modified.
- *
- * Since: 0.9.2
- **/
-hb_glyph_info_t *
-hb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
-                           unsigned int *length)
-{
-  if (length)
-    *length = buffer->len;
-
-  return (hb_glyph_info_t *) buffer->info;
-}
-
-/**
- * hb_buffer_get_glyph_positions:
- * @buffer: an #hb_buffer_t.
- * @length: (out): output length.
- *
- * Returns @buffer glyph position array.  Returned pointer
- * is valid as long as @buffer contents are not modified.
- *
- * Return value: (transfer none) (array length=length):
- * The @buffer glyph position array.
- * The value valid as long as buffer has not been modified.
- *
- * Since: 0.9.2
- **/
-hb_glyph_position_t *
-hb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
-                               unsigned int *length)
-{
-  if (!buffer->have_positions)
-    buffer->clear_positions ();
-
-  if (length)
-    *length = buffer->len;
-
-  return (hb_glyph_position_t *) buffer->pos;
-}
-
-/**
- * hb_glyph_info_get_glyph_flags:
- * @info: a #hb_glyph_info_t.
- *
- * Returns glyph flags encoded within a #hb_glyph_info_t.
- *
- * Return value:
- * The #hb_glyph_flags_t encoded within @info.
- *
- * Since: 1.5.0
- **/
-hb_glyph_flags_t
-(hb_glyph_info_get_glyph_flags) (const hb_glyph_info_t *info)
-{
-  return hb_glyph_info_get_glyph_flags (info);
-}
-
-/**
- * hb_buffer_reverse:
- * @buffer: an #hb_buffer_t.
- *
- * Reverses buffer contents.
- *
- * Since: 0.9.2
- **/
-void
-hb_buffer_reverse (hb_buffer_t *buffer)
-{
-  buffer->reverse ();
-}
-
-/**
- * hb_buffer_reverse_range:
- * @buffer: an #hb_buffer_t.
- * @start: start index.
- * @end: end index.
- *
- * Reverses buffer contents between start to end.
- *
- * Since: 0.9.41
- **/
-void
-hb_buffer_reverse_range (hb_buffer_t *buffer,
-			 unsigned int start, unsigned int end)
-{
-  buffer->reverse_range (start, end);
-}
-
-/**
- * hb_buffer_reverse_clusters:
- * @buffer: an #hb_buffer_t.
- *
- * Reverses buffer clusters.  That is, the buffer contents are
- * reversed, then each cluster (consecutive items having the
- * same cluster number) are reversed again.
- *
- * Since: 0.9.2
- **/
-void
-hb_buffer_reverse_clusters (hb_buffer_t *buffer)
-{
-  buffer->reverse_clusters ();
-}
-
-/**
- * hb_buffer_guess_segment_properties:
- * @buffer: an #hb_buffer_t.
- *
- * Sets unset buffer segment properties based on buffer Unicode
- * contents.  If buffer is not empty, it must have content type
- * %HB_BUFFER_CONTENT_TYPE_UNICODE.
- *
- * If buffer script is not set (ie. is %HB_SCRIPT_INVALID), it
- * will be set to the Unicode script of the first character in
- * the buffer that has a script other than %HB_SCRIPT_COMMON,
- * %HB_SCRIPT_INHERITED, and %HB_SCRIPT_UNKNOWN.
- *
- * Next, if buffer direction is not set (ie. is %HB_DIRECTION_INVALID),
- * it will be set to the natural horizontal direction of the
- * buffer script as returned by hb_script_get_horizontal_direction().
- *
- * Finally, if buffer language is not set (ie. is %HB_LANGUAGE_INVALID),
- * it will be set to the process's default language as returned by
- * hb_language_get_default().  This may change in the future by
- * taking buffer script into consideration when choosing a language.
- *
- * Since: 0.9.7
- **/
-void
-hb_buffer_guess_segment_properties (hb_buffer_t *buffer)
-{
-  buffer->guess_segment_properties ();
-}
-
-template <typename utf_t>
-static inline void
-hb_buffer_add_utf (hb_buffer_t  *buffer,
-		   const typename utf_t::codepoint_t *text,
-		   int           text_length,
-		   unsigned int  item_offset,
-		   int           item_length)
-{
-  typedef typename utf_t::codepoint_t T;
-  const hb_codepoint_t replacement = buffer->replacement;
-
-  assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
-	  (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
-
-  if (unlikely (hb_object_is_inert (buffer)))
-    return;
-
-  if (text_length == -1)
-    text_length = utf_t::strlen (text);
-
-  if (item_length == -1)
-    item_length = text_length - item_offset;
-
-  buffer->ensure (buffer->len + item_length * sizeof (T) / 4);
-
-  /* If buffer is empty and pre-context provided, install it.
-   * This check is written this way, to make sure people can
-   * provide pre-context in one add_utf() call, then provide
-   * text in a follow-up call.  See:
-   *
-   * https://bugzilla.mozilla.org/show_bug.cgi?id=801410#c13
-   */
-  if (!buffer->len && item_offset > 0)
-  {
-    /* Add pre-context */
-    buffer->clear_context (0);
-    const T *prev = text + item_offset;
-    const T *start = text;
-    while (start < prev && buffer->context_len[0] < buffer->CONTEXT_LENGTH)
-    {
-      hb_codepoint_t u;
-      prev = utf_t::prev (prev, start, &u, replacement);
-      buffer->context[0][buffer->context_len[0]++] = u;
-    }
-  }
-
-  const T *next = text + item_offset;
-  const T *end = next + item_length;
-  while (next < end)
-  {
-    hb_codepoint_t u;
-    const T *old_next = next;
-    next = utf_t::next (next, end, &u, replacement);
-    buffer->add (u, old_next - (const T *) text);
-  }
-
-  /* Add post-context */
-  buffer->clear_context (1);
-  end = text + text_length;
-  while (next < end && buffer->context_len[1] < buffer->CONTEXT_LENGTH)
-  {
-    hb_codepoint_t u;
-    next = utf_t::next (next, end, &u, replacement);
-    buffer->context[1][buffer->context_len[1]++] = u;
-  }
-
-  buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE;
-}
-
-/**
- * hb_buffer_add_utf8:
- * @buffer: an #hb_buffer_t.
- * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
- *               characters to append.
- * @text_length: the length of the @text, or -1 if it is %NULL terminated.
- * @item_offset: the offset of the first character to add to the @buffer.
- * @item_length: the number of characters to add to the @buffer, or -1 for the
- *               end of @text (assuming it is %NULL terminated).
- *
- * See hb_buffer_add_codepoints().
- *
- * Replaces invalid UTF-8 characters with the @buffer replacement code point,
- * see hb_buffer_set_replacement_codepoint().
- *
- * Since: 0.9.2
- **/
-void
-hb_buffer_add_utf8 (hb_buffer_t  *buffer,
-		    const char   *text,
-		    int           text_length,
-		    unsigned int  item_offset,
-		    int           item_length)
-{
-  hb_buffer_add_utf<hb_utf8_t> (buffer, (const uint8_t *) text, text_length, item_offset, item_length);
-}
-
-/**
- * hb_buffer_add_utf16:
- * @buffer: an #hb_buffer_t.
- * @text: (array length=text_length): an array of UTF-16 characters to append.
- * @text_length: the length of the @text, or -1 if it is %NULL terminated.
- * @item_offset: the offset of the first character to add to the @buffer.
- * @item_length: the number of characters to add to the @buffer, or -1 for the
- *               end of @text (assuming it is %NULL terminated).
- *
- * See hb_buffer_add_codepoints().
- *
- * Replaces invalid UTF-16 characters with the @buffer replacement code point,
- * see hb_buffer_set_replacement_codepoint().
- *
- * Since: 0.9.2
- **/
-void
-hb_buffer_add_utf16 (hb_buffer_t    *buffer,
-		     const uint16_t *text,
-		     int             text_length,
-		     unsigned int    item_offset,
-		     int             item_length)
-{
-  hb_buffer_add_utf<hb_utf16_t> (buffer, text, text_length, item_offset, item_length);
-}
-
-/**
- * hb_buffer_add_utf32:
- * @buffer: an #hb_buffer_t.
- * @text: (array length=text_length): an array of UTF-32 characters to append.
- * @text_length: the length of the @text, or -1 if it is %NULL terminated.
- * @item_offset: the offset of the first character to add to the @buffer.
- * @item_length: the number of characters to add to the @buffer, or -1 for the
- *               end of @text (assuming it is %NULL terminated).
- *
- * See hb_buffer_add_codepoints().
- *
- * Replaces invalid UTF-32 characters with the @buffer replacement code point,
- * see hb_buffer_set_replacement_codepoint().
- *
- * Since: 0.9.2
- **/
-void
-hb_buffer_add_utf32 (hb_buffer_t    *buffer,
-		     const uint32_t *text,
-		     int             text_length,
-		     unsigned int    item_offset,
-		     int             item_length)
-{
-  hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length);
-}
-
-/**
- * hb_buffer_add_latin1:
- * @buffer: an #hb_buffer_t.
- * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
- *               characters to append.
- * @text_length: the length of the @text, or -1 if it is %NULL terminated.
- * @item_offset: the offset of the first character to add to the @buffer.
- * @item_length: the number of characters to add to the @buffer, or -1 for the
- *               end of @text (assuming it is %NULL terminated).
- *
- * Similar to hb_buffer_add_codepoints(), but allows only access to first 256
- * Unicode code points that can fit in 8-bit strings.
- *
- * <note>Has nothing to do with non-Unicode Latin-1 encoding.</note>
- *
- * Since: 0.9.39
- **/
-void
-hb_buffer_add_latin1 (hb_buffer_t   *buffer,
-		      const uint8_t *text,
-		      int            text_length,
-		      unsigned int   item_offset,
-		      int            item_length)
-{
-  hb_buffer_add_utf<hb_latin1_t> (buffer, text, text_length, item_offset, item_length);
-}
-
-/**
- * hb_buffer_add_codepoints:
- * @buffer: a #hb_buffer_t to append characters to.
- * @text: (array length=text_length): an array of Unicode code points to append.
- * @text_length: the length of the @text, or -1 if it is %NULL terminated.
- * @item_offset: the offset of the first code point to add to the @buffer.
- * @item_length: the number of code points to add to the @buffer, or -1 for the
- *               end of @text (assuming it is %NULL terminated).
- *
- * Appends characters from @text array to @buffer. The @item_offset is the
- * position of the first character from @text that will be appended, and
- * @item_length is the number of character. When shaping part of a larger text
- * (e.g. a run of text from a paragraph), instead of passing just the substring
- * corresponding to the run, it is preferable to pass the whole
- * paragraph and specify the run start and length as @item_offset and
- * @item_length, respectively, to give HarfBuzz the full context to be able,
- * for example, to do cross-run Arabic shaping or properly handle combining
- * 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.
- *
- * Since: 0.9.31
- **/
-void
-hb_buffer_add_codepoints (hb_buffer_t          *buffer,
-			  const hb_codepoint_t *text,
-			  int                   text_length,
-			  unsigned int          item_offset,
-			  int                   item_length)
-{
-  hb_buffer_add_utf<hb_utf32_t<false> > (buffer, text, text_length, item_offset, item_length);
-}
-
-
-/**
- * hb_buffer_append:
- * @buffer: an #hb_buffer_t.
- * @source: source #hb_buffer_t.
- * @start: start index into source buffer to copy.  Use 0 to copy from start of buffer.
- * @end: end index into source buffer to copy.  Use (unsigned int) -1 to copy to end of buffer.
- *
- * Append (part of) contents of another buffer to this buffer.
- *
- * Since: 1.5.0
- **/
-HB_EXTERN void
-hb_buffer_append (hb_buffer_t *buffer,
-		  hb_buffer_t *source,
-		  unsigned int start,
-		  unsigned int end)
-{
-  assert (!buffer->have_output && !source->have_output);
-  assert (buffer->have_positions == source->have_positions ||
-	  !buffer->len || !source->len);
-  assert (buffer->content_type == source->content_type ||
-	  !buffer->len || !source->len);
-
-  if (end > source->len)
-    end = source->len;
-  if (start > end)
-    start = end;
-  if (start == end)
-    return;
-
-  if (!buffer->len)
-    buffer->content_type = source->content_type;
-  if (!buffer->have_positions && source->have_positions)
-    buffer->clear_positions ();
-
-  if (buffer->len + (end - start) < buffer->len) /* Overflows. */
-  {
-    buffer->in_error = true;
-    return;
-  }
-
-  unsigned int orig_len = buffer->len;
-  hb_buffer_set_length (buffer, buffer->len + (end - start));
-  if (buffer->in_error)
-    return;
-
-  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]));
-}
-
-
-static int
-compare_info_codepoint (const hb_glyph_info_t *pa,
-			const hb_glyph_info_t *pb)
-{
-  return (int) pb->codepoint - (int) pa->codepoint;
-}
-
-static inline void
-normalize_glyphs_cluster (hb_buffer_t *buffer,
-			  unsigned int start,
-			  unsigned int end,
-			  bool backward)
-{
-  hb_glyph_position_t *pos = buffer->pos;
-
-  /* Total cluster advance */
-  hb_position_t total_x_advance = 0, total_y_advance = 0;
-  for (unsigned int i = start; i < end; i++)
-  {
-    total_x_advance += pos[i].x_advance;
-    total_y_advance += pos[i].y_advance;
-  }
-
-  hb_position_t x_advance = 0, y_advance = 0;
-  for (unsigned int i = start; i < end; i++)
-  {
-    pos[i].x_offset += x_advance;
-    pos[i].y_offset += y_advance;
-
-    x_advance += pos[i].x_advance;
-    y_advance += pos[i].y_advance;
-
-    pos[i].x_advance = 0;
-    pos[i].y_advance = 0;
-  }
-
-  if (backward)
-  {
-    /* Transfer all cluster advance to the last glyph. */
-    pos[end - 1].x_advance = total_x_advance;
-    pos[end - 1].y_advance = total_y_advance;
-
-    hb_stable_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start);
-  } else {
-    /* Transfer all cluster advance to the first glyph. */
-    pos[start].x_advance += total_x_advance;
-    pos[start].y_advance += total_y_advance;
-    for (unsigned int i = start + 1; i < end; i++) {
-      pos[i].x_offset -= total_x_advance;
-      pos[i].y_offset -= total_y_advance;
-    }
-    hb_stable_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1);
-  }
-}
-
-/**
- * hb_buffer_normalize_glyphs:
- * @buffer: an #hb_buffer_t.
- *
- * Reorders a glyph buffer to have canonical in-cluster glyph order / position.
- * The resulting clusters should behave identical to pre-reordering clusters.
- *
- * <note>This has nothing to do with Unicode normalization.</note>
- *
- * Since: 0.9.2
- **/
-void
-hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
-{
-  assert (buffer->have_positions);
-  assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS ||
-	  (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
-
-  bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
-
-  unsigned int count = buffer->len;
-  if (unlikely (!count)) return;
-  hb_glyph_info_t *info = buffer->info;
-
-  unsigned int start = 0;
-  unsigned int end;
-  for (end = start + 1; end < count; end++)
-    if (info[start].cluster != info[end].cluster) {
-      normalize_glyphs_cluster (buffer, start, end, backward);
-      start = end;
-    }
-  normalize_glyphs_cluster (buffer, start, end, backward);
-}
-
-void
-hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *))
-{
-  assert (!have_positions);
-  for (unsigned int i = start + 1; i < end; i++)
-  {
-    unsigned int j = i;
-    while (j > start && compar (&info[j - 1], &info[i]) > 0)
-      j--;
-    if (i == j)
-      continue;
-    /* Move item i to occupy place for item j, shift what's in between. */
-    merge_clusters (j, i + 1);
-    {
-      hb_glyph_info_t t = info[i];
-      memmove (&info[j + 1], &info[j], (i - j) * sizeof (hb_glyph_info_t));
-      info[j] = t;
-    }
-  }
-}
-
-
-/*
- * Comparing buffers.
- */
-
-/**
- * hb_buffer_diff:
- *
- * If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
- * and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned.  This should be used by most
- * callers if just comparing two buffers is needed.
- *
- * Since: 1.5.0
- **/
-hb_buffer_diff_flags_t
-hb_buffer_diff (hb_buffer_t *buffer,
-		hb_buffer_t *reference,
-		hb_codepoint_t dottedcircle_glyph,
-		unsigned int position_fuzz)
-{
-  if (buffer->content_type != reference->content_type && buffer->len && reference->len)
-    return HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH;
-
-  hb_buffer_diff_flags_t result = HB_BUFFER_DIFF_FLAG_EQUAL;
-  bool contains = dottedcircle_glyph != (hb_codepoint_t) -1;
-
-  unsigned int count = reference->len;
-
-  if (buffer->len != count)
-  {
-    /*
-     * we can't compare glyph-by-glyph, but we do want to know if there
-     * are .notdef or dottedcircle glyphs present in the reference buffer
-     */
-    const hb_glyph_info_t *info = reference->info;
-    unsigned int i;
-    for (i = 0; i < count; i++)
-    {
-      if (contains && info[i].codepoint == dottedcircle_glyph)
-        result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT;
-      if (contains && info[i].codepoint == 0)
-        result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT;
-    }
-    result |= HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH;
-    return hb_buffer_diff_flags_t (result);
-  }
-
-  if (!count)
-    return hb_buffer_diff_flags_t (result);
-
-  const hb_glyph_info_t *buf_info = buffer->info;
-  const hb_glyph_info_t *ref_info = reference->info;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    if (buf_info->codepoint != ref_info->codepoint)
-      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))
-      result |= HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH;
-    if (contains && ref_info->codepoint == dottedcircle_glyph)
-      result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT;
-    if (contains && ref_info->codepoint == 0)
-      result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT;
-    buf_info++;
-    ref_info++;
-  }
-
-  if (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS)
-  {
-    assert (buffer->have_positions);
-    const hb_glyph_position_t *buf_pos = buffer->pos;
-    const hb_glyph_position_t *ref_pos = reference->pos;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if ((unsigned int) abs (buf_pos->x_advance - ref_pos->x_advance) > position_fuzz ||
-          (unsigned int) abs (buf_pos->y_advance - ref_pos->y_advance) > position_fuzz ||
-          (unsigned int) abs (buf_pos->x_offset - ref_pos->x_offset) > position_fuzz ||
-          (unsigned int) abs (buf_pos->y_offset - ref_pos->y_offset) > position_fuzz)
-      {
-        result |= HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH;
-        break;
-      }
-      buf_pos++;
-      ref_pos++;
-    }
-  }
-
-  return result;
-}
-
-
-/*
- * Debugging.
- */
-
-/**
- * hb_buffer_set_message_func:
- * @buffer: an #hb_buffer_t.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 1.1.3
- **/
-void
-hb_buffer_set_message_func (hb_buffer_t *buffer,
-			    hb_buffer_message_func_t func,
-			    void *user_data, hb_destroy_func_t destroy)
-{
-  if (buffer->message_destroy)
-    buffer->message_destroy (buffer->message_data);
-
-  if (func) {
-    buffer->message_func = func;
-    buffer->message_data = user_data;
-    buffer->message_destroy = destroy;
-  } else {
-    buffer->message_func = nullptr;
-    buffer->message_data = nullptr;
-    buffer->message_destroy = nullptr;
-  }
-}
-
-bool
-hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
-{
-  char buf[100];
-  vsnprintf (buf, sizeof (buf),  fmt, ap);
-  return (bool) this->message_func (this, font, buf, this->message_data);
-}
diff --git a/third_party/harfbuzz-ng/src/hb-buffer.h b/third_party/harfbuzz-ng/src/hb-buffer.h
deleted file mode 100644
index 8a2d3e8..0000000
--- a/third_party/harfbuzz-ng/src/hb-buffer.h
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * Copyright © 1998-2004  David Turner and Werner Lemberg
- * Copyright © 2004,2007,2009  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_H_IN
-#error "Include <hb.h> instead."
-#endif
-
-#ifndef HB_BUFFER_H
-#define HB_BUFFER_H
-
-#include "hb-common.h"
-#include "hb-unicode.h"
-#include "hb-font.h"
-
-HB_BEGIN_DECLS
-
-/**
- * hb_glyph_info_t:
- * @codepoint: either a Unicode code point (before shaping) or a glyph index
- *             (after shaping).
- * @mask: 
- * @cluster: the index of the character in the original text that corresponds
- *           to this #hb_glyph_info_t, or whatever the client passes to
- *           hb_buffer_add(). More than one #hb_glyph_info_t can have the same
- *           @cluster value, if they resulted from the same character (e.g. one
- *           to many glyph substitution), and when more than one character gets
- *           merged in the same glyph (e.g. many to one glyph substitution) the
- *           #hb_glyph_info_t will have the smallest cluster value of them.
- *           By default some characters are merged into the same cluster
- *           (e.g. combining marks have the same cluster as their bases)
- *           even if they are separate glyphs, hb_buffer_set_cluster_level()
- *           allow selecting more fine-grained cluster handling.
- *
- * The #hb_glyph_info_t is the structure that holds information about the
- * glyphs and their relation to input text.
- *
- */
-typedef struct hb_glyph_info_t {
-  hb_codepoint_t codepoint;
-  hb_mask_t      mask; /* Holds hb_glyph_flags_t after hb_shape(), plus other things. */
-  uint32_t       cluster;
-
-  /*< private >*/
-  hb_var_int_t   var1;
-  hb_var_int_t   var2;
-} hb_glyph_info_t;
-
-/**
- * hb_glyph_flags_t:
- * @HB_GLYPH_FLAG_UNSAFE_TO_BREAK: Indicates that if input text is broken at the
- * 				   beginning of the cluster this glyph is part of,
- * 				   then both sides need to be re-shaped, as the
- * 				   result might be different.  On the flip side,
- * 				   it means that when this flag is not present,
- * 				   then it's safe to break the glyph-run at the
- * 				   beginning of this cluster, and the two sides
- * 				   represent the exact same result one would get
- * 				   if breaking input text at the beginning of
- * 				   this cluster and shaping the two sides
- * 				   separately.  This can be used to optimize
- * 				   paragraph layout, by avoiding re-shaping
- * 				   of each line after line-breaking, or limiting
- * 				   the reshaping to a small piece around the
- * 				   breaking point only.
- */
-typedef enum { /*< flags >*/
-  HB_GLYPH_FLAG_UNSAFE_TO_BREAK		= 0x00000001,
-
-  HB_GLYPH_FLAG_DEFINED			= 0x00000001 /* OR of all defined flags */
-} hb_glyph_flags_t;
-
-HB_EXTERN hb_glyph_flags_t
-hb_glyph_info_get_glyph_flags (const hb_glyph_info_t *info);
-
-#define hb_glyph_info_get_glyph_flags(info) \
-	((hb_glyph_flags_t) ((unsigned int) (info)->mask & HB_GLYPH_FLAG_DEFINED))
-
-
-/**
- * hb_glyph_position_t:
- * @x_advance: how much the line advances after drawing this glyph when setting
- *             text in horizontal direction.
- * @y_advance: how much the line advances after drawing this glyph when setting
- *             text in vertical direction.
- * @x_offset: how much the glyph moves on the X-axis before drawing it, this
- *            should not affect how much the line advances.
- * @y_offset: how much the glyph moves on the Y-axis before drawing it, this
- *            should not affect how much the line advances.
- *
- * The #hb_glyph_position_t is the structure that holds the positions of the
- * glyph in both horizontal and vertical directions. All positions in
- * #hb_glyph_position_t are relative to the current point.
- *
- */
-typedef struct hb_glyph_position_t {
-  hb_position_t  x_advance;
-  hb_position_t  y_advance;
-  hb_position_t  x_offset;
-  hb_position_t  y_offset;
-
-  /*< private >*/
-  hb_var_int_t   var;
-} hb_glyph_position_t;
-
-/**
- * hb_segment_properties_t:
- * @direction: the #hb_direction_t of the buffer, see hb_buffer_set_direction().
- * @script: the #hb_script_t of the buffer, see hb_buffer_set_script().
- * @language: the #hb_language_t of the buffer, see hb_buffer_set_language().
- *
- * The structure that holds various text properties of an #hb_buffer_t. Can be
- * set and retrieved using hb_buffer_set_segment_properties() and
- * hb_buffer_get_segment_properties(), respectively.
- */
-typedef struct hb_segment_properties_t {
-  hb_direction_t  direction;
-  hb_script_t     script;
-  hb_language_t   language;
-  /*< private >*/
-  void           *reserved1;
-  void           *reserved2;
-} hb_segment_properties_t;
-
-#define HB_SEGMENT_PROPERTIES_DEFAULT {HB_DIRECTION_INVALID, \
-				       HB_SCRIPT_INVALID, \
-				       HB_LANGUAGE_INVALID, \
-				       (void *) 0, \
-				       (void *) 0}
-
-HB_EXTERN hb_bool_t
-hb_segment_properties_equal (const hb_segment_properties_t *a,
-			     const hb_segment_properties_t *b);
-
-HB_EXTERN unsigned int
-hb_segment_properties_hash (const hb_segment_properties_t *p);
-
-
-
-/**
- * hb_buffer_t:
- *
- * The main structure holding the input text and its properties before shaping,
- * and output glyphs and their information after shaping.
- */
-
-typedef struct hb_buffer_t hb_buffer_t;
-
-HB_EXTERN hb_buffer_t *
-hb_buffer_create (void);
-
-HB_EXTERN hb_buffer_t *
-hb_buffer_get_empty (void);
-
-HB_EXTERN hb_buffer_t *
-hb_buffer_reference (hb_buffer_t *buffer);
-
-HB_EXTERN void
-hb_buffer_destroy (hb_buffer_t *buffer);
-
-HB_EXTERN hb_bool_t
-hb_buffer_set_user_data (hb_buffer_t        *buffer,
-			 hb_user_data_key_t *key,
-			 void *              data,
-			 hb_destroy_func_t   destroy,
-			 hb_bool_t           replace);
-
-HB_EXTERN void *
-hb_buffer_get_user_data (hb_buffer_t        *buffer,
-			 hb_user_data_key_t *key);
-
-
-/**
- * hb_buffer_content_type_t:
- * @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer.
- * @HB_BUFFER_CONTENT_TYPE_UNICODE: The buffer contains input characters (before shaping).
- * @HB_BUFFER_CONTENT_TYPE_GLYPHS: The buffer contains output glyphs (after shaping).
- */
-typedef enum {
-  HB_BUFFER_CONTENT_TYPE_INVALID = 0,
-  HB_BUFFER_CONTENT_TYPE_UNICODE,
-  HB_BUFFER_CONTENT_TYPE_GLYPHS
-} hb_buffer_content_type_t;
-
-HB_EXTERN void
-hb_buffer_set_content_type (hb_buffer_t              *buffer,
-			    hb_buffer_content_type_t  content_type);
-
-HB_EXTERN hb_buffer_content_type_t
-hb_buffer_get_content_type (hb_buffer_t *buffer);
-
-
-HB_EXTERN void
-hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
-			     hb_unicode_funcs_t *unicode_funcs);
-
-HB_EXTERN hb_unicode_funcs_t *
-hb_buffer_get_unicode_funcs (hb_buffer_t        *buffer);
-
-HB_EXTERN void
-hb_buffer_set_direction (hb_buffer_t    *buffer,
-			 hb_direction_t  direction);
-
-HB_EXTERN hb_direction_t
-hb_buffer_get_direction (hb_buffer_t *buffer);
-
-HB_EXTERN void
-hb_buffer_set_script (hb_buffer_t *buffer,
-		      hb_script_t  script);
-
-HB_EXTERN hb_script_t
-hb_buffer_get_script (hb_buffer_t *buffer);
-
-HB_EXTERN void
-hb_buffer_set_language (hb_buffer_t   *buffer,
-			hb_language_t  language);
-
-
-HB_EXTERN hb_language_t
-hb_buffer_get_language (hb_buffer_t *buffer);
-
-HB_EXTERN void
-hb_buffer_set_segment_properties (hb_buffer_t *buffer,
-				  const hb_segment_properties_t *props);
-
-HB_EXTERN void
-hb_buffer_get_segment_properties (hb_buffer_t *buffer,
-				  hb_segment_properties_t *props);
-
-HB_EXTERN void
-hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
-
-
-/**
- * hb_buffer_flags_t:
- * @HB_BUFFER_FLAG_DEFAULT: the default buffer flag.
- * @HB_BUFFER_FLAG_BOT: flag indicating that special handling of the beginning
- *                      of text paragraph can be applied to this buffer. Should usually
- *                      be set, unless you are passing to the buffer only part
- *                      of the text without the full context.
- * @HB_BUFFER_FLAG_EOT: flag indicating that special handling of the end of text
- *                      paragraph can be applied to this buffer, similar to
- *                      @HB_BUFFER_FLAG_BOT.
- * @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES:
- *                      flag indication that character with Default_Ignorable
- *                      Unicode property should use the corresponding glyph
- *                      from the font, instead of hiding them (done by
- *                      replacing them with the space glyph and zeroing the
- *                      advance width.)  This flag takes precedence over
- *                      @HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES.
- * @HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES:
- *                      flag indication that character with Default_Ignorable
- *                      Unicode property should be removed from glyph string
- *                      instead of hiding them (done by replacing them with the
- *                      space glyph and zeroing the advance width.)
- *                      @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES takes
- *                      precedence over this flag. Since: 1.8.0
- *
- * Since: 0.9.20
- */
-typedef enum { /*< flags >*/
-  HB_BUFFER_FLAG_DEFAULT			= 0x00000000u,
-  HB_BUFFER_FLAG_BOT				= 0x00000001u, /* Beginning-of-text */
-  HB_BUFFER_FLAG_EOT				= 0x00000002u, /* End-of-text */
-  HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES	= 0x00000004u,
-  HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES	= 0x00000008u
-} hb_buffer_flags_t;
-
-HB_EXTERN void
-hb_buffer_set_flags (hb_buffer_t       *buffer,
-		     hb_buffer_flags_t  flags);
-
-HB_EXTERN hb_buffer_flags_t
-hb_buffer_get_flags (hb_buffer_t *buffer);
-
-/*
- * Since: 0.9.42
- */
-typedef enum {
-  HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES	= 0,
-  HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS	= 1,
-  HB_BUFFER_CLUSTER_LEVEL_CHARACTERS		= 2,
-  HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
-} hb_buffer_cluster_level_t;
-
-HB_EXTERN void
-hb_buffer_set_cluster_level (hb_buffer_t               *buffer,
-			     hb_buffer_cluster_level_t  cluster_level);
-
-HB_EXTERN hb_buffer_cluster_level_t
-hb_buffer_get_cluster_level (hb_buffer_t *buffer);
-
-/**
- * HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT:
- *
- * The default code point for replacing invalid characters in a given encoding.
- * Set to U+FFFD REPLACEMENT CHARACTER.
- *
- * Since: 0.9.31
- */
-#define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu
-
-HB_EXTERN void
-hb_buffer_set_replacement_codepoint (hb_buffer_t    *buffer,
-				     hb_codepoint_t  replacement);
-
-HB_EXTERN hb_codepoint_t
-hb_buffer_get_replacement_codepoint (hb_buffer_t    *buffer);
-
-
-HB_EXTERN void
-hb_buffer_reset (hb_buffer_t *buffer);
-
-HB_EXTERN void
-hb_buffer_clear_contents (hb_buffer_t *buffer);
-
-HB_EXTERN hb_bool_t
-hb_buffer_pre_allocate (hb_buffer_t  *buffer,
-		        unsigned int  size);
-
-
-HB_EXTERN hb_bool_t
-hb_buffer_allocation_successful (hb_buffer_t  *buffer);
-
-HB_EXTERN void
-hb_buffer_reverse (hb_buffer_t *buffer);
-
-HB_EXTERN void
-hb_buffer_reverse_range (hb_buffer_t *buffer,
-			 unsigned int start, unsigned int end);
-
-HB_EXTERN void
-hb_buffer_reverse_clusters (hb_buffer_t *buffer);
-
-
-/* Filling the buffer in */
-
-HB_EXTERN void
-hb_buffer_add (hb_buffer_t    *buffer,
-	       hb_codepoint_t  codepoint,
-	       unsigned int    cluster);
-
-HB_EXTERN void
-hb_buffer_add_utf8 (hb_buffer_t  *buffer,
-		    const char   *text,
-		    int           text_length,
-		    unsigned int  item_offset,
-		    int           item_length);
-
-HB_EXTERN void
-hb_buffer_add_utf16 (hb_buffer_t    *buffer,
-		     const uint16_t *text,
-		     int             text_length,
-		     unsigned int    item_offset,
-		     int             item_length);
-
-HB_EXTERN void
-hb_buffer_add_utf32 (hb_buffer_t    *buffer,
-		     const uint32_t *text,
-		     int             text_length,
-		     unsigned int    item_offset,
-		     int             item_length);
-
-HB_EXTERN void
-hb_buffer_add_latin1 (hb_buffer_t   *buffer,
-		      const uint8_t *text,
-		      int            text_length,
-		      unsigned int   item_offset,
-		      int            item_length);
-
-HB_EXTERN void
-hb_buffer_add_codepoints (hb_buffer_t          *buffer,
-			  const hb_codepoint_t *text,
-			  int                   text_length,
-			  unsigned int          item_offset,
-			  int                   item_length);
-
-HB_EXTERN void
-hb_buffer_append (hb_buffer_t *buffer,
-		  hb_buffer_t *source,
-		  unsigned int start,
-		  unsigned int end);
-
-HB_EXTERN hb_bool_t
-hb_buffer_set_length (hb_buffer_t  *buffer,
-		      unsigned int  length);
-
-HB_EXTERN unsigned int
-hb_buffer_get_length (hb_buffer_t *buffer);
-
-/* Getting glyphs out of the buffer */
-
-HB_EXTERN hb_glyph_info_t *
-hb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
-                           unsigned int *length);
-
-HB_EXTERN hb_glyph_position_t *
-hb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
-                               unsigned int *length);
-
-
-HB_EXTERN void
-hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
-
-
-/*
- * Serialize
- */
-
-/**
- * hb_buffer_serialize_flags_t:
- * @HB_BUFFER_SERIALIZE_FLAG_DEFAULT: serialize glyph names, clusters and positions.
- * @HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS: do not serialize glyph cluster.
- * @HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS: do not serialize glyph position information.
- * @HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES: do no serialize glyph name.
- * @HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS: serialize glyph extents.
- * @HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS: serialize glyph flags. Since: 1.5.0
- * @HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES: do not serialize glyph advances,
- *  glyph offsets will reflect absolute glyph positions. Since: 1.8.0
- *
- * Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs().
- *
- * Since: 0.9.20
- */
-typedef enum { /*< flags >*/
-  HB_BUFFER_SERIALIZE_FLAG_DEFAULT		= 0x00000000u,
-  HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS		= 0x00000001u,
-  HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS		= 0x00000002u,
-  HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES	= 0x00000004u,
-  HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS	= 0x00000008u,
-  HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS		= 0x00000010u,
-  HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES		= 0x00000020u
-} hb_buffer_serialize_flags_t;
-
-/**
- * hb_buffer_serialize_format_t:
- * @HB_BUFFER_SERIALIZE_FORMAT_TEXT: a human-readable, plain text format.
- * @HB_BUFFER_SERIALIZE_FORMAT_JSON: a machine-readable JSON format.
- * @HB_BUFFER_SERIALIZE_FORMAT_INVALID: invalid format.
- *
- * The buffer serialization and de-serialization format used in
- * hb_buffer_serialize_glyphs() and hb_buffer_deserialize_glyphs().
- *
- * Since: 0.9.2
- */
-typedef enum {
-  HB_BUFFER_SERIALIZE_FORMAT_TEXT	= HB_TAG('T','E','X','T'),
-  HB_BUFFER_SERIALIZE_FORMAT_JSON	= HB_TAG('J','S','O','N'),
-  HB_BUFFER_SERIALIZE_FORMAT_INVALID	= HB_TAG_NONE
-} hb_buffer_serialize_format_t;
-
-HB_EXTERN hb_buffer_serialize_format_t
-hb_buffer_serialize_format_from_string (const char *str, int len);
-
-HB_EXTERN const char *
-hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format);
-
-HB_EXTERN const char **
-hb_buffer_serialize_list_formats (void);
-
-HB_EXTERN unsigned int
-hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
-			    unsigned int start,
-			    unsigned int end,
-			    char *buf,
-			    unsigned int buf_size,
-			    unsigned int *buf_consumed,
-			    hb_font_t *font,
-			    hb_buffer_serialize_format_t format,
-			    hb_buffer_serialize_flags_t flags);
-
-HB_EXTERN hb_bool_t
-hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
-			      const char *buf,
-			      int buf_len,
-			      const char **end_ptr,
-			      hb_font_t *font,
-			      hb_buffer_serialize_format_t format);
-
-
-/*
- * Compare buffers
- */
-
-typedef enum { /*< flags >*/
-  HB_BUFFER_DIFF_FLAG_EQUAL			= 0x0000,
-
-  /* Buffers with different content_type cannot be meaningfully compared
-   * in any further detail. */
-  HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH	= 0x0001,
-
-  /* For buffers with differing length, the per-glyph comparison is not
-   * attempted, though we do still scan reference for dottedcircle / .notdef
-   * glyphs. */
-  HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH		= 0x0002,
-
-  /* We want to know if dottedcircle / .notdef glyphs are present in the
-   * reference, as we may not care so much about other differences in this
-   * case. */
-  HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT		= 0x0004,
-  HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT	= 0x0008,
-
-  /* If the buffers have the same length, we compare them glyph-by-glyph
-   * and report which aspect(s) of the glyph info/position are different. */
-  HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH	= 0x0010,
-  HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH		= 0x0020,
-  HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH	= 0x0040,
-  HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH		= 0x0080
-
-} hb_buffer_diff_flags_t;
-
-/* Compare the contents of two buffers, report types of differences. */
-HB_EXTERN hb_buffer_diff_flags_t
-hb_buffer_diff (hb_buffer_t *buffer,
-		hb_buffer_t *reference,
-		hb_codepoint_t dottedcircle_glyph,
-		unsigned int position_fuzz);
-
-
-/*
- * Debugging.
- */
-
-typedef hb_bool_t	(*hb_buffer_message_func_t)	(hb_buffer_t *buffer,
-							 hb_font_t   *font,
-							 const char  *message,
-							 void        *user_data);
-
-HB_EXTERN void
-hb_buffer_set_message_func (hb_buffer_t *buffer,
-			    hb_buffer_message_func_t func,
-			    void *user_data, hb_destroy_func_t destroy);
-
-
-HB_END_DECLS
-
-#endif /* HB_BUFFER_H */
diff --git a/third_party/harfbuzz-ng/src/hb-common.cc b/third_party/harfbuzz-ng/src/hb-common.cc
deleted file mode 100644
index d1fcf79..0000000
--- a/third_party/harfbuzz-ng/src/hb-common.cc
+++ /dev/null
@@ -1,1050 +0,0 @@
-/*
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-
-#include "hb-mutex-private.hh"
-#include "hb-object-private.hh"
-
-#include <locale.h>
-#ifdef HAVE_XLOCALE_H
-#include <xlocale.h>
-#endif
-
-
-/* hb_options_t */
-
-hb_options_union_t _hb_options;
-
-void
-_hb_options_init (void)
-{
-  hb_options_union_t u;
-  u.i = 0;
-  u.opts.initialized = 1;
-
-  char *c = getenv ("HB_OPTIONS");
-  u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible");
-
-  /* This is idempotent and threadsafe. */
-  _hb_options = u;
-}
-
-
-/* hb_tag_t */
-
-/**
- * hb_tag_from_string:
- * @str: (array length=len) (element-type uint8_t): 
- * @len: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_tag_t
-hb_tag_from_string (const char *str, int len)
-{
-  char tag[4];
-  unsigned int i;
-
-  if (!str || !len || !*str)
-    return HB_TAG_NONE;
-
-  if (len < 0 || len > 4)
-    len = 4;
-  for (i = 0; i < (unsigned) len && str[i]; i++)
-    tag[i] = str[i];
-  for (; i < 4; i++)
-    tag[i] = ' ';
-
-  return HB_TAG (tag[0], tag[1], tag[2], tag[3]);
-}
-
-/**
- * hb_tag_to_string:
- * @tag: 
- * @buf: (out caller-allocates) (array fixed-size=4) (element-type uint8_t): 
- *
- * 
- *
- * Since: 0.9.5
- **/
-void
-hb_tag_to_string (hb_tag_t tag, char *buf)
-{
-  buf[0] = (char) (uint8_t) (tag >> 24);
-  buf[1] = (char) (uint8_t) (tag >> 16);
-  buf[2] = (char) (uint8_t) (tag >>  8);
-  buf[3] = (char) (uint8_t) (tag >>  0);
-}
-
-
-/* hb_direction_t */
-
-const char direction_strings[][4] = {
-  "ltr",
-  "rtl",
-  "ttb",
-  "btt"
-};
-
-/**
- * hb_direction_from_string:
- * @str: (array length=len) (element-type uint8_t): 
- * @len: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_direction_t
-hb_direction_from_string (const char *str, int len)
-{
-  if (unlikely (!str || !len || !*str))
-    return HB_DIRECTION_INVALID;
-
-  /* Lets match loosely: just match the first letter, such that
-   * all of "ltr", "left-to-right", etc work!
-   */
-  char c = TOLOWER (str[0]);
-  for (unsigned int i = 0; i < ARRAY_LENGTH (direction_strings); i++)
-    if (c == direction_strings[i][0])
-      return (hb_direction_t) (HB_DIRECTION_LTR + i);
-
-  return HB_DIRECTION_INVALID;
-}
-
-/**
- * hb_direction_to_string:
- * @direction: 
- *
- * 
- *
- * Return value: (transfer none): 
- *
- * Since: 0.9.2
- **/
-const char *
-hb_direction_to_string (hb_direction_t direction)
-{
-  if (likely ((unsigned int) (direction - HB_DIRECTION_LTR)
-	      < ARRAY_LENGTH (direction_strings)))
-    return direction_strings[direction - HB_DIRECTION_LTR];
-
-  return "invalid";
-}
-
-
-/* hb_language_t */
-
-struct hb_language_impl_t {
-  const char s[1];
-};
-
-static const char canon_map[256] = {
-   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
-   0,   0,   0,   0,   0,   0,   0,   0,    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', '5', '6', '7',  '8', '9',  0,   0,   0,   0,   0,   0,
-  '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
-  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,  '-',
-   0,  'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
-  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,   0
-};
-
-static bool
-lang_equal (hb_language_t  v1,
-	    const void    *v2)
-{
-  const unsigned char *p1 = (const unsigned char *) v1;
-  const unsigned char *p2 = (const unsigned char *) v2;
-
-  while (*p1 && *p1 == canon_map[*p2]) {
-    p1++;
-    p2++;
-  }
-
-  return *p1 == canon_map[*p2];
-}
-
-#if 0
-static unsigned int
-lang_hash (const void *key)
-{
-  const unsigned char *p = key;
-  unsigned int h = 0;
-  while (canon_map[*p])
-    {
-      h = (h << 5) - h + canon_map[*p];
-      p++;
-    }
-
-  return h;
-}
-#endif
-
-
-struct hb_language_item_t {
-
-  struct hb_language_item_t *next;
-  hb_language_t lang;
-
-  inline bool operator == (const char *s) const {
-    return lang_equal (lang, s);
-  }
-
-  inline hb_language_item_t & operator = (const char *s) {
-    /* If a custom allocated is used calling strdup() pairs
-    badly with a call to the custom free() in finish() below.
-    Therefore don't call strdup(), implement its behavior.
-    */
-    size_t len = strlen(s) + 1;
-    lang = (hb_language_t) malloc(len);
-    if (likely (lang))
-    {
-      memcpy((unsigned char *) lang, s, len);
-      for (unsigned char *p = (unsigned char *) lang; *p; p++)
-	*p = canon_map[*p];
-    }
-
-    return *this;
-  }
-
-  void finish (void) { free ((void *) lang); }
-};
-
-
-/* Thread-safe lock-free language list */
-
-static hb_language_item_t *langs;
-
-#ifdef HB_USE_ATEXIT
-static void
-free_langs (void)
-{
-  while (langs) {
-    hb_language_item_t *next = langs->next;
-    langs->finish ();
-    free (langs);
-    langs = next;
-  }
-}
-#endif
-
-static hb_language_item_t *
-lang_find_or_insert (const char *key)
-{
-retry:
-  hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs);
-
-  for (hb_language_item_t *lang = first_lang; lang; lang = lang->next)
-    if (*lang == key)
-      return lang;
-
-  /* Not found; allocate one. */
-  hb_language_item_t *lang = (hb_language_item_t *) calloc (1, sizeof (hb_language_item_t));
-  if (unlikely (!lang))
-    return nullptr;
-  lang->next = first_lang;
-  *lang = key;
-  if (unlikely (!lang->lang))
-  {
-    free (lang);
-    return nullptr;
-  }
-
-  if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
-    lang->finish ();
-    free (lang);
-    goto retry;
-  }
-
-#ifdef HB_USE_ATEXIT
-  if (!first_lang)
-    atexit (free_langs); /* First person registers atexit() callback. */
-#endif
-
-  return lang;
-}
-
-
-/**
- * hb_language_from_string:
- * @str: (array length=len) (element-type uint8_t): a string representing
- *       ISO 639 language code
- * @len: length of the @str, or -1 if it is %NULL-terminated.
- *
- * Converts @str representing an ISO 639 language code to the corresponding
- * #hb_language_t.
- *
- * Return value: (transfer none):
- * The #hb_language_t corresponding to the ISO 639 language code.
- *
- * Since: 0.9.2
- **/
-hb_language_t
-hb_language_from_string (const char *str, int len)
-{
-  if (!str || !len || !*str)
-    return HB_LANGUAGE_INVALID;
-
-  hb_language_item_t *item = nullptr;
-  if (len >= 0)
-  {
-    /* NUL-terminate it. */
-    char strbuf[64];
-    len = MIN (len, (int) sizeof (strbuf) - 1);
-    memcpy (strbuf, str, len);
-    strbuf[len] = '\0';
-    item = lang_find_or_insert (strbuf);
-  }
-  else
-    item = lang_find_or_insert (str);
-
-  return likely (item) ? item->lang : HB_LANGUAGE_INVALID;
-}
-
-/**
- * hb_language_to_string:
- * @language: an #hb_language_t to convert.
- *
- * See hb_language_from_string().
- *
- * Return value: (transfer none):
- * A %NULL-terminated string representing the @language. Must not be freed by
- * the caller.
- *
- * Since: 0.9.2
- **/
-const char *
-hb_language_to_string (hb_language_t language)
-{
-  /* This is actually nullptr-safe! */
-  return language->s;
-}
-
-/**
- * hb_language_get_default:
- *
- * 
- *
- * Return value: (transfer none):
- *
- * Since: 0.9.2
- **/
-hb_language_t
-hb_language_get_default (void)
-{
-  static hb_language_t default_language = HB_LANGUAGE_INVALID;
-
-  hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
-  if (unlikely (language == HB_LANGUAGE_INVALID)) {
-    language = hb_language_from_string (setlocale (LC_CTYPE, nullptr), -1);
-    (void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
-  }
-
-  return default_language;
-}
-
-
-/* hb_script_t */
-
-/**
- * hb_script_from_iso15924_tag:
- * @tag: an #hb_tag_t representing an ISO 15924 tag.
- *
- * Converts an ISO 15924 script tag to a corresponding #hb_script_t.
- *
- * Return value: 
- * An #hb_script_t corresponding to the ISO 15924 tag.
- *
- * Since: 0.9.2
- **/
-hb_script_t
-hb_script_from_iso15924_tag (hb_tag_t tag)
-{
-  if (unlikely (tag == HB_TAG_NONE))
-    return HB_SCRIPT_INVALID;
-
-  /* Be lenient, adjust case (one capital letter followed by three small letters) */
-  tag = (tag & 0xDFDFDFDFu) | 0x00202020u;
-
-  switch (tag) {
-
-    /* These graduated from the 'Q' private-area codes, but
-     * the old code is still aliased by Unicode, and the Qaai
-     * one in use by ICU. */
-    case HB_TAG('Q','a','a','i'): return HB_SCRIPT_INHERITED;
-    case HB_TAG('Q','a','a','c'): return HB_SCRIPT_COPTIC;
-
-    /* Script variants from http://unicode.org/iso15924/ */
-    case HB_TAG('C','y','r','s'): return HB_SCRIPT_CYRILLIC;
-    case HB_TAG('L','a','t','f'): return HB_SCRIPT_LATIN;
-    case HB_TAG('L','a','t','g'): return HB_SCRIPT_LATIN;
-    case HB_TAG('S','y','r','e'): return HB_SCRIPT_SYRIAC;
-    case HB_TAG('S','y','r','j'): return HB_SCRIPT_SYRIAC;
-    case HB_TAG('S','y','r','n'): return HB_SCRIPT_SYRIAC;
-  }
-
-  /* If it looks right, just use the tag as a script */
-  if (((uint32_t) tag & 0xE0E0E0E0u) == 0x40606060u)
-    return (hb_script_t) tag;
-
-  /* Otherwise, return unknown */
-  return HB_SCRIPT_UNKNOWN;
-}
-
-/**
- * hb_script_from_string:
- * @str: (array length=len) (element-type uint8_t): a string representing an
- *       ISO 15924 tag.
- * @len: length of the @str, or -1 if it is %NULL-terminated.
- *
- * Converts a string @str representing an ISO 15924 script tag to a
- * corresponding #hb_script_t. Shorthand for hb_tag_from_string() then
- * hb_script_from_iso15924_tag().
- *
- * Return value: 
- * An #hb_script_t corresponding to the ISO 15924 tag.
- *
- * Since: 0.9.2
- **/
-hb_script_t
-hb_script_from_string (const char *str, int len)
-{
-  return hb_script_from_iso15924_tag (hb_tag_from_string (str, len));
-}
-
-/**
- * hb_script_to_iso15924_tag:
- * @script: an #hb_script_ to convert.
- *
- * See hb_script_from_iso15924_tag().
- *
- * Return value:
- * An #hb_tag_t representing an ISO 15924 script tag.
- *
- * Since: 0.9.2
- **/
-hb_tag_t
-hb_script_to_iso15924_tag (hb_script_t script)
-{
-  return (hb_tag_t) script;
-}
-
-/**
- * hb_script_get_horizontal_direction:
- * @script: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_direction_t
-hb_script_get_horizontal_direction (hb_script_t script)
-{
-  /* http://goo.gl/x9ilM */
-  switch ((hb_tag_t) script)
-  {
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_ARABIC:
-    case HB_SCRIPT_HEBREW:
-
-    /* Unicode-3.0 additions */
-    case HB_SCRIPT_SYRIAC:
-    case HB_SCRIPT_THAANA:
-
-    /* Unicode-4.0 additions */
-    case HB_SCRIPT_CYPRIOT:
-
-    /* Unicode-4.1 additions */
-    case HB_SCRIPT_KHAROSHTHI:
-
-    /* Unicode-5.0 additions */
-    case HB_SCRIPT_PHOENICIAN:
-    case HB_SCRIPT_NKO:
-
-    /* Unicode-5.1 additions */
-    case HB_SCRIPT_LYDIAN:
-
-    /* Unicode-5.2 additions */
-    case HB_SCRIPT_AVESTAN:
-    case HB_SCRIPT_IMPERIAL_ARAMAIC:
-    case HB_SCRIPT_INSCRIPTIONAL_PAHLAVI:
-    case HB_SCRIPT_INSCRIPTIONAL_PARTHIAN:
-    case HB_SCRIPT_OLD_SOUTH_ARABIAN:
-    case HB_SCRIPT_OLD_TURKIC:
-    case HB_SCRIPT_SAMARITAN:
-
-    /* Unicode-6.0 additions */
-    case HB_SCRIPT_MANDAIC:
-
-    /* Unicode-6.1 additions */
-    case HB_SCRIPT_MEROITIC_CURSIVE:
-    case HB_SCRIPT_MEROITIC_HIEROGLYPHS:
-
-    /* Unicode-7.0 additions */
-    case HB_SCRIPT_MANICHAEAN:
-    case HB_SCRIPT_MENDE_KIKAKUI:
-    case HB_SCRIPT_NABATAEAN:
-    case HB_SCRIPT_OLD_NORTH_ARABIAN:
-    case HB_SCRIPT_PALMYRENE:
-    case HB_SCRIPT_PSALTER_PAHLAVI:
-
-    /* Unicode-8.0 additions */
-    case HB_SCRIPT_HATRAN:
-    case HB_SCRIPT_OLD_HUNGARIAN:
-
-    /* Unicode-9.0 additions */
-    case HB_SCRIPT_ADLAM:
-
-      return HB_DIRECTION_RTL;
-  }
-
-  return HB_DIRECTION_LTR;
-}
-
-
-/* hb_user_data_array_t */
-
-bool
-hb_user_data_array_t::set (hb_user_data_key_t *key,
-			   void *              data,
-			   hb_destroy_func_t   destroy,
-			   hb_bool_t           replace)
-{
-  if (!key)
-    return false;
-
-  if (replace) {
-    if (!data && !destroy) {
-      items.remove (key, lock);
-      return true;
-    }
-  }
-  hb_user_data_item_t item = {key, data, destroy};
-  bool ret = !!items.replace_or_insert (item, lock, (bool) replace);
-
-  return ret;
-}
-
-void *
-hb_user_data_array_t::get (hb_user_data_key_t *key)
-{
-  hb_user_data_item_t item = {nullptr, nullptr, nullptr};
-
-  return items.find (key, &item, lock) ? item.data : nullptr;
-}
-
-
-/* hb_version */
-
-/**
- * hb_version:
- * @major: (out): Library major version component.
- * @minor: (out): Library minor version component.
- * @micro: (out): Library micro version component.
- *
- * Returns library version as three integer components.
- *
- * Since: 0.9.2
- **/
-void
-hb_version (unsigned int *major,
-	    unsigned int *minor,
-	    unsigned int *micro)
-{
-  *major = HB_VERSION_MAJOR;
-  *minor = HB_VERSION_MINOR;
-  *micro = HB_VERSION_MICRO;
-}
-
-/**
- * hb_version_string:
- *
- * Returns library version as a string with three components.
- *
- * Return value: library version string.
- *
- * Since: 0.9.2
- **/
-const char *
-hb_version_string (void)
-{
-  return HB_VERSION_STRING;
-}
-
-/**
- * hb_version_atleast:
- * @major: 
- * @minor: 
- * @micro: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.30
- **/
-hb_bool_t
-hb_version_atleast (unsigned int major,
-		    unsigned int minor,
-		    unsigned int micro)
-{
-  return HB_VERSION_ATLEAST (major, minor, micro);
-}
-
-
-
-/* hb_feature_t and hb_variation_t */
-
-static bool
-parse_space (const char **pp, const char *end)
-{
-  while (*pp < end && ISSPACE (**pp))
-    (*pp)++;
-  return true;
-}
-
-static bool
-parse_char (const char **pp, const char *end, char c)
-{
-  parse_space (pp, end);
-
-  if (*pp == end || **pp != c)
-    return false;
-
-  (*pp)++;
-  return true;
-}
-
-static bool
-parse_uint (const char **pp, const char *end, unsigned int *pv)
-{
-  char buf[32];
-  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
-  strncpy (buf, *pp, len);
-  buf[len] = '\0';
-
-  char *p = buf;
-  char *pend = p;
-  unsigned int v;
-
-  /* Intentionally use strtol instead of strtoul, such that
-   * -1 turns into "big number"... */
-  errno = 0;
-  v = strtol (p, &pend, 0);
-  if (errno || p == pend)
-    return false;
-
-  *pv = v;
-  *pp += pend - p;
-  return true;
-}
-
-static bool
-parse_uint32 (const char **pp, const char *end, uint32_t *pv)
-{
-  char buf[32];
-  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
-  strncpy (buf, *pp, len);
-  buf[len] = '\0';
-
-  char *p = buf;
-  char *pend = p;
-  unsigned int v;
-
-  /* Intentionally use strtol instead of strtoul, such that
-   * -1 turns into "big number"... */
-  errno = 0;
-  v = strtol (p, &pend, 0);
-  if (errno || p == pend)
-    return false;
-
-  *pv = v;
-  *pp += pend - p;
-  return true;
-}
-
-#if defined (HAVE_NEWLOCALE) && defined (HAVE_STRTOD_L)
-#define USE_XLOCALE 1
-#define HB_LOCALE_T locale_t
-#define HB_CREATE_LOCALE(locName) newlocale (LC_ALL_MASK, locName, nullptr)
-#define HB_FREE_LOCALE(loc) freelocale (loc)
-#elif defined(_MSC_VER)
-#define USE_XLOCALE 1
-#define HB_LOCALE_T _locale_t
-#define HB_CREATE_LOCALE(locName) _create_locale (LC_ALL, locName)
-#define HB_FREE_LOCALE(loc) _free_locale (loc)
-#define strtod_l(a, b, c) _strtod_l ((a), (b), (c))
-#endif
-
-#ifdef USE_XLOCALE
-
-static HB_LOCALE_T C_locale;
-
-#ifdef HB_USE_ATEXIT
-static void
-free_C_locale (void)
-{
-  if (C_locale)
-    HB_FREE_LOCALE (C_locale);
-}
-#endif
-
-static HB_LOCALE_T
-get_C_locale (void)
-{
-retry:
-  HB_LOCALE_T C = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale);
-
-  if (unlikely (!C))
-  {
-    C = HB_CREATE_LOCALE ("C");
-
-    if (!hb_atomic_ptr_cmpexch (&C_locale, nullptr, C))
-    {
-      HB_FREE_LOCALE (C_locale);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_C_locale); /* First person registers atexit() callback. */
-#endif
-  }
-
-  return C;
-}
-#endif
-
-static bool
-parse_float (const char **pp, const char *end, float *pv)
-{
-  char buf[32];
-  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
-  strncpy (buf, *pp, len);
-  buf[len] = '\0';
-
-  char *p = buf;
-  char *pend = p;
-  float v;
-
-  errno = 0;
-#ifdef USE_XLOCALE
-  v = strtod_l (p, &pend, get_C_locale ());
-#else
-  v = strtod (p, &pend);
-#endif
-  if (errno || p == pend)
-    return false;
-
-  *pv = v;
-  *pp += pend - p;
-  return true;
-}
-
-static bool
-parse_bool (const char **pp, const char *end, uint32_t *pv)
-{
-  parse_space (pp, end);
-
-  const char *p = *pp;
-  while (*pp < end && ISALPHA(**pp))
-    (*pp)++;
-
-  /* CSS allows on/off as aliases 1/0. */
-  if (*pp - p == 2 && 0 == strncmp (p, "on", 2))
-    *pv = 1;
-  else if (*pp - p == 3 && 0 == strncmp (p, "off", 3))
-    *pv = 0;
-  else
-    return false;
-
-  return true;
-}
-
-/* hb_feature_t */
-
-static bool
-parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
-{
-  if (parse_char (pp, end, '-'))
-    feature->value = 0;
-  else {
-    parse_char (pp, end, '+');
-    feature->value = 1;
-  }
-
-  return true;
-}
-
-static bool
-parse_tag (const char **pp, const char *end, hb_tag_t *tag)
-{
-  parse_space (pp, end);
-
-  char quote = 0;
-
-  if (*pp < end && (**pp == '\'' || **pp == '"'))
-  {
-    quote = **pp;
-    (*pp)++;
-  }
-
-  const char *p = *pp;
-  while (*pp < end && ISALNUM(**pp))
-    (*pp)++;
-
-  if (p == *pp || *pp - p > 4)
-    return false;
-
-  *tag = hb_tag_from_string (p, *pp - p);
-
-  if (quote)
-  {
-    /* CSS expects exactly four bytes.  And we only allow quotations for
-     * CSS compatibility.  So, enforce the length. */
-     if (*pp - p != 4)
-       return false;
-    if (*pp == end || **pp != quote)
-      return false;
-    (*pp)++;
-  }
-
-  return true;
-}
-
-static bool
-parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
-{
-  parse_space (pp, end);
-
-  bool has_start;
-
-  feature->start = 0;
-  feature->end = (unsigned int) -1;
-
-  if (!parse_char (pp, end, '['))
-    return true;
-
-  has_start = parse_uint (pp, end, &feature->start);
-
-  if (parse_char (pp, end, ':')) {
-    parse_uint (pp, end, &feature->end);
-  } else {
-    if (has_start)
-      feature->end = feature->start + 1;
-  }
-
-  return parse_char (pp, end, ']');
-}
-
-static bool
-parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
-{
-  bool had_equal = parse_char (pp, end, '=');
-  bool had_value = parse_uint32 (pp, end, &feature->value) ||
-                   parse_bool (pp, end, &feature->value);
-  /* CSS doesn't use equal-sign between tag and value.
-   * If there was an equal-sign, then there *must* be a value.
-   * A value without an equal-sign is ok, but not required. */
-  return !had_equal || had_value;
-}
-
-static bool
-parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
-{
-  return parse_feature_value_prefix (pp, end, feature) &&
-	 parse_tag (pp, end, &feature->tag) &&
-	 parse_feature_indices (pp, end, feature) &&
-	 parse_feature_value_postfix (pp, end, feature) &&
-	 parse_space (pp, end) &&
-	 *pp == end;
-}
-
-/**
- * hb_feature_from_string:
- * @str: (array length=len) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is %NULL terminated
- * @feature: (out): the #hb_feature_t to initialize with the parsed values
- *
- * Parses a string into a #hb_feature_t.
- *
- * TODO: document the syntax here.
- *
- * Return value:
- * %true if @str is successfully parsed, %false otherwise.
- *
- * Since: 0.9.5
- **/
-hb_bool_t
-hb_feature_from_string (const char *str, int len,
-			hb_feature_t *feature)
-{
-  hb_feature_t feat;
-
-  if (len < 0)
-    len = strlen (str);
-
-  if (likely (parse_one_feature (&str, str + len, &feat)))
-  {
-    if (feature)
-      *feature = feat;
-    return true;
-  }
-
-  if (feature)
-    memset (feature, 0, sizeof (*feature));
-  return false;
-}
-
-/**
- * hb_feature_to_string:
- * @feature: an #hb_feature_t to convert
- * @buf: (array length=size) (out): output string
- * @size: the allocated size of @buf
- *
- * Converts a #hb_feature_t into a %NULL-terminated string in the format
- * understood by hb_feature_from_string(). The client in responsible for
- * allocating big enough size for @buf, 128 bytes is more than enough.
- *
- * Since: 0.9.5
- **/
-void
-hb_feature_to_string (hb_feature_t *feature,
-		      char *buf, unsigned int size)
-{
-  if (unlikely (!size)) return;
-
-  char s[128];
-  unsigned int len = 0;
-  if (feature->value == 0)
-    s[len++] = '-';
-  hb_tag_to_string (feature->tag, s + len);
-  len += 4;
-  while (len && s[len - 1] == ' ')
-    len--;
-  if (feature->start != 0 || feature->end != (unsigned int) -1)
-  {
-    s[len++] = '[';
-    if (feature->start)
-      len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
-    if (feature->end != feature->start + 1) {
-      s[len++] = ':';
-      if (feature->end != (unsigned int) -1)
-	len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
-    }
-    s[len++] = ']';
-  }
-  if (feature->value > 1)
-  {
-    s[len++] = '=';
-    len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
-  }
-  assert (len < ARRAY_LENGTH (s));
-  len = MIN (len, size - 1);
-  memcpy (buf, s, len);
-  buf[len] = '\0';
-}
-
-/* hb_variation_t */
-
-static bool
-parse_variation_value (const char **pp, const char *end, hb_variation_t *variation)
-{
-  parse_char (pp, end, '='); /* Optional. */
-  return parse_float (pp, end, &variation->value);
-}
-
-static bool
-parse_one_variation (const char **pp, const char *end, hb_variation_t *variation)
-{
-  return parse_tag (pp, end, &variation->tag) &&
-	 parse_variation_value (pp, end, variation) &&
-	 parse_space (pp, end) &&
-	 *pp == end;
-}
-
-/**
- * hb_variation_from_string:
- *
- * Since: 1.4.2
- */
-hb_bool_t
-hb_variation_from_string (const char *str, int len,
-			  hb_variation_t *variation)
-{
-  hb_variation_t var;
-
-  if (len < 0)
-    len = strlen (str);
-
-  if (likely (parse_one_variation (&str, str + len, &var)))
-  {
-    if (variation)
-      *variation = var;
-    return true;
-  }
-
-  if (variation)
-    memset (variation, 0, sizeof (*variation));
-  return false;
-}
-
-/**
- * hb_variation_to_string:
- *
- * Since: 1.4.2
- */
-void
-hb_variation_to_string (hb_variation_t *variation,
-			char *buf, unsigned int size)
-{
-  if (unlikely (!size)) return;
-
-  char s[128];
-  unsigned int len = 0;
-  hb_tag_to_string (variation->tag, s + len);
-  len += 4;
-  while (len && s[len - 1] == ' ')
-    len--;
-  s[len++] = '=';
-  len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", variation->value));
-
-  assert (len < ARRAY_LENGTH (s));
-  len = MIN (len, size - 1);
-  memcpy (buf, s, len);
-  buf[len] = '\0';
-}
diff --git a/third_party/harfbuzz-ng/src/hb-common.h b/third_party/harfbuzz-ng/src/hb-common.h
deleted file mode 100644
index 26200ce1..0000000
--- a/third_party/harfbuzz-ng/src/hb-common.h
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_H_IN
-#error "Include <hb.h> instead."
-#endif
-
-#ifndef HB_COMMON_H
-#define HB_COMMON_H
-
-#ifndef HB_BEGIN_DECLS
-# ifdef __cplusplus
-#  define HB_BEGIN_DECLS	extern "C" {
-#  define HB_END_DECLS		}
-# else /* !__cplusplus */
-#  define HB_BEGIN_DECLS
-#  define HB_END_DECLS
-# endif /* !__cplusplus */
-#endif
-
-#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \
-    defined (_sgi) || defined (__sun) || defined (sun) || \
-    defined (__digital__) || defined (__HP_cc)
-#  include <inttypes.h>
-#elif defined (_AIX)
-#  include <sys/inttypes.h>
-#else
-#  include <stdint.h>
-#endif
-
-HB_BEGIN_DECLS
-
-
-typedef int hb_bool_t;
-
-typedef uint32_t hb_codepoint_t;
-typedef int32_t hb_position_t;
-typedef uint32_t hb_mask_t;
-
-typedef union _hb_var_int_t {
-  uint32_t u32;
-  int32_t i32;
-  uint16_t u16[2];
-  int16_t i16[2];
-  uint8_t u8[4];
-  int8_t i8[4];
-} hb_var_int_t;
-
-
-/* hb_tag_t */
-
-typedef uint32_t hb_tag_t;
-
-#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint8_t)(c1))<<24)|(((uint8_t)(c2))<<16)|(((uint8_t)(c3))<<8)|((uint8_t)(c4))))
-#define HB_UNTAG(tag)   ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag))
-
-#define HB_TAG_NONE HB_TAG(0,0,0,0)
-#define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff)
-#define HB_TAG_MAX_SIGNED HB_TAG(0x7f,0xff,0xff,0xff)
-
-/* len=-1 means str is NUL-terminated. */
-HB_EXTERN hb_tag_t
-hb_tag_from_string (const char *str, int len);
-
-/* buf should have 4 bytes. */
-HB_EXTERN void
-hb_tag_to_string (hb_tag_t tag, char *buf);
-
-
-/**
- * hb_direction_t:
- * @HB_DIRECTION_INVALID: Initial, unset direction.
- * @HB_DIRECTION_LTR: Text is set horizontally from left to right.
- * @HB_DIRECTION_RTL: Text is set horizontally from right to left.
- * @HB_DIRECTION_TTB: Text is set vertically from top to bottom.
- * @HB_DIRECTION_BTT: Text is set vertically from bottom to top.
- */
-typedef enum {
-  HB_DIRECTION_INVALID = 0,
-  HB_DIRECTION_LTR = 4,
-  HB_DIRECTION_RTL,
-  HB_DIRECTION_TTB,
-  HB_DIRECTION_BTT
-} hb_direction_t;
-
-/* len=-1 means str is NUL-terminated */
-HB_EXTERN hb_direction_t
-hb_direction_from_string (const char *str, int len);
-
-HB_EXTERN const char *
-hb_direction_to_string (hb_direction_t direction);
-
-#define HB_DIRECTION_IS_VALID(dir)	((((unsigned int) (dir)) & ~3U) == 4)
-/* Direction must be valid for the following */
-#define HB_DIRECTION_IS_HORIZONTAL(dir)	((((unsigned int) (dir)) & ~1U) == 4)
-#define HB_DIRECTION_IS_VERTICAL(dir)	((((unsigned int) (dir)) & ~1U) == 6)
-#define HB_DIRECTION_IS_FORWARD(dir)	((((unsigned int) (dir)) & ~2U) == 4)
-#define HB_DIRECTION_IS_BACKWARD(dir)	((((unsigned int) (dir)) & ~2U) == 5)
-#define HB_DIRECTION_REVERSE(dir)	((hb_direction_t) (((unsigned int) (dir)) ^ 1))
-
-
-/* hb_language_t */
-
-typedef const struct hb_language_impl_t *hb_language_t;
-
-HB_EXTERN hb_language_t
-hb_language_from_string (const char *str, int len);
-
-HB_EXTERN const char *
-hb_language_to_string (hb_language_t language);
-
-#define HB_LANGUAGE_INVALID ((hb_language_t) 0)
-
-HB_EXTERN hb_language_t
-hb_language_get_default (void);
-
-
-/* hb_script_t */
-
-/* http://unicode.org/iso15924/ */
-/* http://goo.gl/x9ilM */
-/* Unicode Character Database property: Script (sc) */
-typedef enum
-{
-  /*1.1*/ HB_SCRIPT_COMMON			= HB_TAG ('Z','y','y','y'),
-  /*1.1*/ HB_SCRIPT_INHERITED			= HB_TAG ('Z','i','n','h'),
-  /*5.0*/ HB_SCRIPT_UNKNOWN			= HB_TAG ('Z','z','z','z'),
-
-  /*1.1*/ HB_SCRIPT_ARABIC			= HB_TAG ('A','r','a','b'),
-  /*1.1*/ HB_SCRIPT_ARMENIAN			= HB_TAG ('A','r','m','n'),
-  /*1.1*/ HB_SCRIPT_BENGALI			= HB_TAG ('B','e','n','g'),
-  /*1.1*/ HB_SCRIPT_CYRILLIC			= HB_TAG ('C','y','r','l'),
-  /*1.1*/ HB_SCRIPT_DEVANAGARI			= HB_TAG ('D','e','v','a'),
-  /*1.1*/ HB_SCRIPT_GEORGIAN			= HB_TAG ('G','e','o','r'),
-  /*1.1*/ HB_SCRIPT_GREEK			= HB_TAG ('G','r','e','k'),
-  /*1.1*/ HB_SCRIPT_GUJARATI			= HB_TAG ('G','u','j','r'),
-  /*1.1*/ HB_SCRIPT_GURMUKHI			= HB_TAG ('G','u','r','u'),
-  /*1.1*/ HB_SCRIPT_HANGUL			= HB_TAG ('H','a','n','g'),
-  /*1.1*/ HB_SCRIPT_HAN				= HB_TAG ('H','a','n','i'),
-  /*1.1*/ HB_SCRIPT_HEBREW			= HB_TAG ('H','e','b','r'),
-  /*1.1*/ HB_SCRIPT_HIRAGANA			= HB_TAG ('H','i','r','a'),
-  /*1.1*/ HB_SCRIPT_KANNADA			= HB_TAG ('K','n','d','a'),
-  /*1.1*/ HB_SCRIPT_KATAKANA			= HB_TAG ('K','a','n','a'),
-  /*1.1*/ HB_SCRIPT_LAO				= HB_TAG ('L','a','o','o'),
-  /*1.1*/ HB_SCRIPT_LATIN			= HB_TAG ('L','a','t','n'),
-  /*1.1*/ HB_SCRIPT_MALAYALAM			= HB_TAG ('M','l','y','m'),
-  /*1.1*/ HB_SCRIPT_ORIYA			= HB_TAG ('O','r','y','a'),
-  /*1.1*/ HB_SCRIPT_TAMIL			= HB_TAG ('T','a','m','l'),
-  /*1.1*/ HB_SCRIPT_TELUGU			= HB_TAG ('T','e','l','u'),
-  /*1.1*/ HB_SCRIPT_THAI			= HB_TAG ('T','h','a','i'),
-
-  /*2.0*/ HB_SCRIPT_TIBETAN			= HB_TAG ('T','i','b','t'),
-
-  /*3.0*/ HB_SCRIPT_BOPOMOFO			= HB_TAG ('B','o','p','o'),
-  /*3.0*/ HB_SCRIPT_BRAILLE			= HB_TAG ('B','r','a','i'),
-  /*3.0*/ HB_SCRIPT_CANADIAN_SYLLABICS		= HB_TAG ('C','a','n','s'),
-  /*3.0*/ HB_SCRIPT_CHEROKEE			= HB_TAG ('C','h','e','r'),
-  /*3.0*/ HB_SCRIPT_ETHIOPIC			= HB_TAG ('E','t','h','i'),
-  /*3.0*/ HB_SCRIPT_KHMER			= HB_TAG ('K','h','m','r'),
-  /*3.0*/ HB_SCRIPT_MONGOLIAN			= HB_TAG ('M','o','n','g'),
-  /*3.0*/ HB_SCRIPT_MYANMAR			= HB_TAG ('M','y','m','r'),
-  /*3.0*/ HB_SCRIPT_OGHAM			= HB_TAG ('O','g','a','m'),
-  /*3.0*/ HB_SCRIPT_RUNIC			= HB_TAG ('R','u','n','r'),
-  /*3.0*/ HB_SCRIPT_SINHALA			= HB_TAG ('S','i','n','h'),
-  /*3.0*/ HB_SCRIPT_SYRIAC			= HB_TAG ('S','y','r','c'),
-  /*3.0*/ HB_SCRIPT_THAANA			= HB_TAG ('T','h','a','a'),
-  /*3.0*/ HB_SCRIPT_YI				= HB_TAG ('Y','i','i','i'),
-
-  /*3.1*/ HB_SCRIPT_DESERET			= HB_TAG ('D','s','r','t'),
-  /*3.1*/ HB_SCRIPT_GOTHIC			= HB_TAG ('G','o','t','h'),
-  /*3.1*/ HB_SCRIPT_OLD_ITALIC			= HB_TAG ('I','t','a','l'),
-
-  /*3.2*/ HB_SCRIPT_BUHID			= HB_TAG ('B','u','h','d'),
-  /*3.2*/ HB_SCRIPT_HANUNOO			= HB_TAG ('H','a','n','o'),
-  /*3.2*/ HB_SCRIPT_TAGALOG			= HB_TAG ('T','g','l','g'),
-  /*3.2*/ HB_SCRIPT_TAGBANWA			= HB_TAG ('T','a','g','b'),
-
-  /*4.0*/ HB_SCRIPT_CYPRIOT			= HB_TAG ('C','p','r','t'),
-  /*4.0*/ HB_SCRIPT_LIMBU			= HB_TAG ('L','i','m','b'),
-  /*4.0*/ HB_SCRIPT_LINEAR_B			= HB_TAG ('L','i','n','b'),
-  /*4.0*/ HB_SCRIPT_OSMANYA			= HB_TAG ('O','s','m','a'),
-  /*4.0*/ HB_SCRIPT_SHAVIAN			= HB_TAG ('S','h','a','w'),
-  /*4.0*/ HB_SCRIPT_TAI_LE			= HB_TAG ('T','a','l','e'),
-  /*4.0*/ HB_SCRIPT_UGARITIC			= HB_TAG ('U','g','a','r'),
-
-  /*4.1*/ HB_SCRIPT_BUGINESE			= HB_TAG ('B','u','g','i'),
-  /*4.1*/ HB_SCRIPT_COPTIC			= HB_TAG ('C','o','p','t'),
-  /*4.1*/ HB_SCRIPT_GLAGOLITIC			= HB_TAG ('G','l','a','g'),
-  /*4.1*/ HB_SCRIPT_KHAROSHTHI			= HB_TAG ('K','h','a','r'),
-  /*4.1*/ HB_SCRIPT_NEW_TAI_LUE			= HB_TAG ('T','a','l','u'),
-  /*4.1*/ HB_SCRIPT_OLD_PERSIAN			= HB_TAG ('X','p','e','o'),
-  /*4.1*/ HB_SCRIPT_SYLOTI_NAGRI		= HB_TAG ('S','y','l','o'),
-  /*4.1*/ HB_SCRIPT_TIFINAGH			= HB_TAG ('T','f','n','g'),
-
-  /*5.0*/ HB_SCRIPT_BALINESE			= HB_TAG ('B','a','l','i'),
-  /*5.0*/ HB_SCRIPT_CUNEIFORM			= HB_TAG ('X','s','u','x'),
-  /*5.0*/ HB_SCRIPT_NKO				= HB_TAG ('N','k','o','o'),
-  /*5.0*/ HB_SCRIPT_PHAGS_PA			= HB_TAG ('P','h','a','g'),
-  /*5.0*/ HB_SCRIPT_PHOENICIAN			= HB_TAG ('P','h','n','x'),
-
-  /*5.1*/ HB_SCRIPT_CARIAN			= HB_TAG ('C','a','r','i'),
-  /*5.1*/ HB_SCRIPT_CHAM			= HB_TAG ('C','h','a','m'),
-  /*5.1*/ HB_SCRIPT_KAYAH_LI			= HB_TAG ('K','a','l','i'),
-  /*5.1*/ HB_SCRIPT_LEPCHA			= HB_TAG ('L','e','p','c'),
-  /*5.1*/ HB_SCRIPT_LYCIAN			= HB_TAG ('L','y','c','i'),
-  /*5.1*/ HB_SCRIPT_LYDIAN			= HB_TAG ('L','y','d','i'),
-  /*5.1*/ HB_SCRIPT_OL_CHIKI			= HB_TAG ('O','l','c','k'),
-  /*5.1*/ HB_SCRIPT_REJANG			= HB_TAG ('R','j','n','g'),
-  /*5.1*/ HB_SCRIPT_SAURASHTRA			= HB_TAG ('S','a','u','r'),
-  /*5.1*/ HB_SCRIPT_SUNDANESE			= HB_TAG ('S','u','n','d'),
-  /*5.1*/ HB_SCRIPT_VAI				= HB_TAG ('V','a','i','i'),
-
-  /*5.2*/ HB_SCRIPT_AVESTAN			= HB_TAG ('A','v','s','t'),
-  /*5.2*/ HB_SCRIPT_BAMUM			= HB_TAG ('B','a','m','u'),
-  /*5.2*/ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS	= HB_TAG ('E','g','y','p'),
-  /*5.2*/ HB_SCRIPT_IMPERIAL_ARAMAIC		= HB_TAG ('A','r','m','i'),
-  /*5.2*/ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI	= HB_TAG ('P','h','l','i'),
-  /*5.2*/ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN	= HB_TAG ('P','r','t','i'),
-  /*5.2*/ HB_SCRIPT_JAVANESE			= HB_TAG ('J','a','v','a'),
-  /*5.2*/ HB_SCRIPT_KAITHI			= HB_TAG ('K','t','h','i'),
-  /*5.2*/ HB_SCRIPT_LISU			= HB_TAG ('L','i','s','u'),
-  /*5.2*/ HB_SCRIPT_MEETEI_MAYEK		= HB_TAG ('M','t','e','i'),
-  /*5.2*/ HB_SCRIPT_OLD_SOUTH_ARABIAN		= HB_TAG ('S','a','r','b'),
-  /*5.2*/ HB_SCRIPT_OLD_TURKIC			= HB_TAG ('O','r','k','h'),
-  /*5.2*/ HB_SCRIPT_SAMARITAN			= HB_TAG ('S','a','m','r'),
-  /*5.2*/ HB_SCRIPT_TAI_THAM			= HB_TAG ('L','a','n','a'),
-  /*5.2*/ HB_SCRIPT_TAI_VIET			= HB_TAG ('T','a','v','t'),
-
-  /*6.0*/ HB_SCRIPT_BATAK			= HB_TAG ('B','a','t','k'),
-  /*6.0*/ HB_SCRIPT_BRAHMI			= HB_TAG ('B','r','a','h'),
-  /*6.0*/ HB_SCRIPT_MANDAIC			= HB_TAG ('M','a','n','d'),
-
-  /*6.1*/ HB_SCRIPT_CHAKMA			= HB_TAG ('C','a','k','m'),
-  /*6.1*/ HB_SCRIPT_MEROITIC_CURSIVE		= HB_TAG ('M','e','r','c'),
-  /*6.1*/ HB_SCRIPT_MEROITIC_HIEROGLYPHS	= HB_TAG ('M','e','r','o'),
-  /*6.1*/ HB_SCRIPT_MIAO			= HB_TAG ('P','l','r','d'),
-  /*6.1*/ HB_SCRIPT_SHARADA			= HB_TAG ('S','h','r','d'),
-  /*6.1*/ HB_SCRIPT_SORA_SOMPENG		= HB_TAG ('S','o','r','a'),
-  /*6.1*/ HB_SCRIPT_TAKRI			= HB_TAG ('T','a','k','r'),
-
-  /*
-   * Since: 0.9.30
-   */
-  /*7.0*/ HB_SCRIPT_BASSA_VAH			= HB_TAG ('B','a','s','s'),
-  /*7.0*/ HB_SCRIPT_CAUCASIAN_ALBANIAN		= HB_TAG ('A','g','h','b'),
-  /*7.0*/ HB_SCRIPT_DUPLOYAN			= HB_TAG ('D','u','p','l'),
-  /*7.0*/ HB_SCRIPT_ELBASAN			= HB_TAG ('E','l','b','a'),
-  /*7.0*/ HB_SCRIPT_GRANTHA			= HB_TAG ('G','r','a','n'),
-  /*7.0*/ HB_SCRIPT_KHOJKI			= HB_TAG ('K','h','o','j'),
-  /*7.0*/ HB_SCRIPT_KHUDAWADI			= HB_TAG ('S','i','n','d'),
-  /*7.0*/ HB_SCRIPT_LINEAR_A			= HB_TAG ('L','i','n','a'),
-  /*7.0*/ HB_SCRIPT_MAHAJANI			= HB_TAG ('M','a','h','j'),
-  /*7.0*/ HB_SCRIPT_MANICHAEAN			= HB_TAG ('M','a','n','i'),
-  /*7.0*/ HB_SCRIPT_MENDE_KIKAKUI		= HB_TAG ('M','e','n','d'),
-  /*7.0*/ HB_SCRIPT_MODI			= HB_TAG ('M','o','d','i'),
-  /*7.0*/ HB_SCRIPT_MRO				= HB_TAG ('M','r','o','o'),
-  /*7.0*/ HB_SCRIPT_NABATAEAN			= HB_TAG ('N','b','a','t'),
-  /*7.0*/ HB_SCRIPT_OLD_NORTH_ARABIAN		= HB_TAG ('N','a','r','b'),
-  /*7.0*/ HB_SCRIPT_OLD_PERMIC			= HB_TAG ('P','e','r','m'),
-  /*7.0*/ HB_SCRIPT_PAHAWH_HMONG		= HB_TAG ('H','m','n','g'),
-  /*7.0*/ HB_SCRIPT_PALMYRENE			= HB_TAG ('P','a','l','m'),
-  /*7.0*/ HB_SCRIPT_PAU_CIN_HAU			= HB_TAG ('P','a','u','c'),
-  /*7.0*/ HB_SCRIPT_PSALTER_PAHLAVI		= HB_TAG ('P','h','l','p'),
-  /*7.0*/ HB_SCRIPT_SIDDHAM			= HB_TAG ('S','i','d','d'),
-  /*7.0*/ HB_SCRIPT_TIRHUTA			= HB_TAG ('T','i','r','h'),
-  /*7.0*/ HB_SCRIPT_WARANG_CITI			= HB_TAG ('W','a','r','a'),
-
-  /*8.0*/ HB_SCRIPT_AHOM			= HB_TAG ('A','h','o','m'),
-  /*8.0*/ HB_SCRIPT_ANATOLIAN_HIEROGLYPHS	= HB_TAG ('H','l','u','w'),
-  /*8.0*/ HB_SCRIPT_HATRAN			= HB_TAG ('H','a','t','r'),
-  /*8.0*/ HB_SCRIPT_MULTANI			= HB_TAG ('M','u','l','t'),
-  /*8.0*/ HB_SCRIPT_OLD_HUNGARIAN		= HB_TAG ('H','u','n','g'),
-  /*8.0*/ HB_SCRIPT_SIGNWRITING			= HB_TAG ('S','g','n','w'),
-
-  /*
-   * Since 1.3.0
-   */
-  /*9.0*/ HB_SCRIPT_ADLAM			= HB_TAG ('A','d','l','m'),
-  /*9.0*/ HB_SCRIPT_BHAIKSUKI			= HB_TAG ('B','h','k','s'),
-  /*9.0*/ HB_SCRIPT_MARCHEN			= HB_TAG ('M','a','r','c'),
-  /*9.0*/ HB_SCRIPT_OSAGE			= HB_TAG ('O','s','g','e'),
-  /*9.0*/ HB_SCRIPT_TANGUT			= HB_TAG ('T','a','n','g'),
-  /*9.0*/ HB_SCRIPT_NEWA			= HB_TAG ('N','e','w','a'),
-
-  /*
-   * Since 1.6.0
-   */
-  /*10.0*/HB_SCRIPT_MASARAM_GONDI		= HB_TAG ('G','o','n','m'),
-  /*10.0*/HB_SCRIPT_NUSHU			= HB_TAG ('N','s','h','u'),
-  /*10.0*/HB_SCRIPT_SOYOMBO			= HB_TAG ('S','o','y','o'),
-  /*10.0*/HB_SCRIPT_ZANABAZAR_SQUARE		= HB_TAG ('Z','a','n','b'),
-
-  /* No script set. */
-  HB_SCRIPT_INVALID				= HB_TAG_NONE,
-
-  /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t
-   * without risking undefined behavior.  Include both a signed and unsigned max,
-   * since technically enums are int, and indeed, hb_script_t ends up being signed.
-   * See this thread for technicalities:
-   *
-   *   http://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html
-   */
-  _HB_SCRIPT_MAX_VALUE				= HB_TAG_MAX, /*< skip >*/
-  _HB_SCRIPT_MAX_VALUE_SIGNED			= HB_TAG_MAX_SIGNED /*< skip >*/
-
-} hb_script_t;
-
-
-/* Script functions */
-
-HB_EXTERN hb_script_t
-hb_script_from_iso15924_tag (hb_tag_t tag);
-
-HB_EXTERN hb_script_t
-hb_script_from_string (const char *str, int len);
-
-HB_EXTERN hb_tag_t
-hb_script_to_iso15924_tag (hb_script_t script);
-
-HB_EXTERN hb_direction_t
-hb_script_get_horizontal_direction (hb_script_t script);
-
-
-/* User data */
-
-typedef struct hb_user_data_key_t {
-  /*< private >*/
-  char unused;
-} hb_user_data_key_t;
-
-typedef void (*hb_destroy_func_t) (void *user_data);
-
-
-/* Font features and variations. */
-
-typedef struct hb_feature_t {
-  hb_tag_t      tag;
-  uint32_t      value;
-  unsigned int  start;
-  unsigned int  end;
-} hb_feature_t;
-
-HB_EXTERN hb_bool_t
-hb_feature_from_string (const char *str, int len,
-			hb_feature_t *feature);
-
-HB_EXTERN void
-hb_feature_to_string (hb_feature_t *feature,
-		      char *buf, unsigned int size);
-
-/**
- * hb_variation_t:
- *
- * Since: 1.4.2
- */
-typedef struct hb_variation_t {
-  hb_tag_t tag;
-  float    value;
-} hb_variation_t;
-
-HB_EXTERN hb_bool_t
-hb_variation_from_string (const char *str, int len,
-			  hb_variation_t *variation);
-
-HB_EXTERN void
-hb_variation_to_string (hb_variation_t *variation,
-			char *buf, unsigned int size);
-
-
-HB_END_DECLS
-
-#endif /* HB_COMMON_H */
diff --git a/third_party/harfbuzz-ng/src/hb-coretext.cc b/third_party/harfbuzz-ng/src/hb-coretext.cc
deleted file mode 100644
index aba7cf4..0000000
--- a/third_party/harfbuzz-ng/src/hb-coretext.cc
+++ /dev/null
@@ -1,1401 +0,0 @@
-/*
- * Copyright © 2012,2013  Mozilla Foundation.
- * Copyright © 2012,2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#define HB_SHAPER coretext
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-shaper-impl-private.hh"
-
-#include "hb-coretext.h"
-#include <math.h>
-
-/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
-#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
-
-static CGFloat
-coretext_font_size_from_ptem (float ptem)
-{
-  /* CoreText points are CSS pixels (96 per inch),
-   * NOT typographic points (72 per inch).
-   *
-   * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
-   */
-  ptem *= 96.f / 72.f;
-  return ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem;
-}
-static float
-coretext_font_size_to_ptem (CGFloat size)
-{
-  size *= 72.f / 96.f;
-  return size <= 0.f ? 0 : size;
-}
-
-static void
-release_table_data (void *user_data)
-{
-  CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data);
-  CFRelease(cf_data);
-}
-
-static hb_blob_t *
-reference_table  (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
-{
-  CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
-  CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag);
-  if (unlikely (!cf_data))
-    return nullptr;
-
-  const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data));
-  const size_t length = CFDataGetLength (cf_data);
-  if (!data || !length)
-  {
-    CFRelease (cf_data);
-    return nullptr;
-  }
-
-  return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
-			 reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
-			 release_table_data);
-}
-
-static void
-_hb_cg_font_release (void *data)
-{
-  CGFontRelease ((CGFontRef) data);
-}
-
-
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
-HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
-	fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) <= .5
-)
-
-static CTFontDescriptorRef
-get_last_resort_font_desc (void)
-{
-  // TODO Handle allocation failures?
-  CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0);
-  CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault,
-					   (const void **) &last_resort,
-					   1,
-					   &kCFTypeArrayCallBacks);
-  CFRelease (last_resort);
-  CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault,
-						   (const void **) &kCTFontCascadeListAttribute,
-						   (const void **) &cascade_list,
-						   1,
-						   &kCFTypeDictionaryKeyCallBacks,
-						   &kCFTypeDictionaryValueCallBacks);
-  CFRelease (cascade_list);
-
-  CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes);
-  CFRelease (attributes);
-  return font_desc;
-}
-
-static void
-release_data (void *info, const void *data, size_t size)
-{
-  assert (hb_blob_get_length ((hb_blob_t *) info) == size &&
-          hb_blob_get_data ((hb_blob_t *) info, nullptr) == data);
-
-  hb_blob_destroy ((hb_blob_t *) info);
-}
-
-static CGFontRef
-create_cg_font (hb_face_t *face)
-{
-  CGFontRef cg_font = nullptr;
-  if (face->destroy == _hb_cg_font_release)
-  {
-    cg_font = CGFontRetain ((CGFontRef) face->user_data);
-  }
-  else
-  {
-    hb_blob_t *blob = hb_face_reference_blob (face);
-    unsigned int blob_length;
-    const char *blob_data = hb_blob_get_data (blob, &blob_length);
-    if (unlikely (!blob_length))
-      DEBUG_MSG (CORETEXT, face, "Face has empty blob");
-
-    CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data);
-    if (likely (provider))
-    {
-      cg_font = CGFontCreateWithDataProvider (provider);
-      if (unlikely (!cg_font))
-	DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed");
-      CGDataProviderRelease (provider);
-    }
-  }
-  return cg_font;
-}
-
-static CTFontRef
-create_ct_font (CGFontRef cg_font, CGFloat font_size)
-{
-  CTFontRef ct_font = nullptr;
-
-  /* CoreText does not enable trak table usage / tracking when creating a CTFont
-   * using CTFontCreateWithGraphicsFont. The only way of enabling tracking seems
-   * to be through the CTFontCreateUIFontForLanguage call. */
-  CFStringRef cg_postscript_name = CGFontCopyPostScriptName (cg_font);
-  if (CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSText")) ||
-      CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSDisplay")))
-  {
-    CTFontUIFontType font_type = kCTFontUIFontSystem;
-    if (CFStringHasSuffix (cg_postscript_name, CFSTR ("-Bold")))
-      font_type = kCTFontUIFontEmphasizedSystem;
-
-    ct_font = CTFontCreateUIFontForLanguage (font_type, font_size, nullptr);
-    CFStringRef ct_result_name = CTFontCopyPostScriptName(ct_font);
-    if (CFStringCompare (ct_result_name, cg_postscript_name, 0) != kCFCompareEqualTo)
-    {
-      CFRelease(ct_font);
-      ct_font = nullptr;
-    }
-    CFRelease (ct_result_name);
-  }
-  CFRelease (cg_postscript_name);
-
-  if (!ct_font)
-    ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, nullptr, nullptr);
-
-  if (unlikely (!ct_font)) {
-    DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed");
-    return nullptr;
-  }
-
-  /* crbug.com/576941 and crbug.com/625902 and the investigation in the latter
-   * bug indicate that the cascade list reconfiguration occasionally causes
-   * crashes in CoreText on OS X 10.9, thus let's skip this step on older
-   * operating system versions. Except for the emoji font, where _not_
-   * reconfiguring the cascade list causes CoreText crashes. For details, see
-   * crbug.com/549610 */
-  // 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h
-  if (&CTGetCoreTextVersion != nullptr && CTGetCoreTextVersion() < 0x00070000) {
-    CFStringRef fontName = CTFontCopyPostScriptName (ct_font);
-    bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo;
-    CFRelease (fontName);
-    if (!isEmojiFont)
-      return ct_font;
-  }
-
-  CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttribute);
-
-  /* Create font copy with cascade list that has LastResort first; this speeds up CoreText
-   * font fallback which we don't need anyway. */
-  {
-    CTFontDescriptorRef last_resort_font_desc = get_last_resort_font_desc ();
-    CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0.0, nullptr, last_resort_font_desc);
-    CFRelease (last_resort_font_desc);
-    if (new_ct_font)
-    {
-      /* The CTFontCreateCopyWithAttributes call fails to stay on the same font
-       * when reconfiguring the cascade list and may switch to a different font
-       * when there are fonts that go by the same name, since the descriptor is
-       * just name and size.
-       *
-       * Avoid reconfiguring the cascade lists if the new font is outside the
-       * system locations that we cannot access from the sandboxed renderer
-       * process in Blink. This can be detected by the new file URL location
-       * that the newly found font points to. */
-      CFURLRef new_url = (CFURLRef) CTFontCopyAttribute (new_ct_font, kCTFontURLAttribute);
-      // Keep reconfigured font if URL cannot be retrieved (seems to be the case
-      // on Mac OS 10.12 Sierra), speculative fix for crbug.com/625606
-      if (!original_url || !new_url || CFEqual (original_url, new_url)) {
-        CFRelease (ct_font);
-        ct_font = new_ct_font;
-      } else {
-        CFRelease (new_ct_font);
-        DEBUG_MSG (CORETEXT, ct_font, "Discarding reconfigured CTFont, location changed.");
-      }
-      if (new_url)
-        CFRelease (new_url);
-    }
-    else
-      DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed");
-  }
-
-  if (original_url)
-    CFRelease (original_url);
-  return ct_font;
-}
-
-hb_coretext_shaper_face_data_t *
-_hb_coretext_shaper_face_data_create (hb_face_t *face)
-{
-  CGFontRef cg_font = create_cg_font (face);
-
-  if (unlikely (!cg_font))
-  {
-    DEBUG_MSG (CORETEXT, face, "CGFont creation failed..");
-    return nullptr;
-  }
-
-  return (hb_coretext_shaper_face_data_t *) cg_font;
-}
-
-void
-_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
-{
-  CFRelease ((CGFontRef) data);
-}
-
-hb_face_t *
-hb_coretext_face_create (CGFontRef cg_font)
-{
-  return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
-}
-
-/*
- * Since: 0.9.10
- */
-CGFontRef
-hb_coretext_face_get_cg_font (hb_face_t *face)
-{
-  if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
-  return (CGFontRef) HB_SHAPER_DATA_GET (face);
-}
-
-
-hb_coretext_shaper_font_data_t *
-_hb_coretext_shaper_font_data_create (hb_font_t *font)
-{
-  hb_face_t *face = font->face;
-  if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
-  CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
-
-  CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem));
-
-  if (unlikely (!ct_font))
-  {
-    DEBUG_MSG (CORETEXT, font, "CGFont creation failed..");
-    return nullptr;
-  }
-
-  return (hb_coretext_shaper_font_data_t *) ct_font;
-}
-
-void
-_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
-{
-  CFRelease ((CTFontRef) data);
-}
-
-/*
- * Since: 1.7.2
- */
-hb_font_t *
-hb_coretext_font_create (CTFontRef ct_font)
-{
-  CGFontRef cg_font = CTFontCopyGraphicsFont (ct_font, nullptr);
-  hb_face_t *face = hb_coretext_face_create (cg_font);
-  CFRelease (cg_font);
-  hb_font_t *font = hb_font_create (face);
-  hb_face_destroy (face);
-
-  if (unlikely (hb_object_is_inert (font)))
-    return font;
-
-  hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font)));
-
-  /* Let there be dragons here... */
-  HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font);
-
-  return font;
-}
-
-CTFontRef
-hb_coretext_font_get_ct_font (hb_font_t *font)
-{
-  if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr;
-  return (CTFontRef) HB_SHAPER_DATA_GET (font);
-}
-
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_coretext_shaper_shape_plan_data_t {};
-
-hb_coretext_shaper_shape_plan_data_t *
-_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-					     const hb_feature_t *user_features HB_UNUSED,
-					     unsigned int        num_user_features HB_UNUSED,
-					     const int          *coords HB_UNUSED,
-					     unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
- * shaper
- */
-
-struct feature_record_t {
-  unsigned int feature;
-  unsigned int setting;
-};
-
-struct active_feature_t {
-  feature_record_t rec;
-  unsigned int order;
-
-  static int cmp (const void *pa, const void *pb) {
-    const active_feature_t *a = (const active_feature_t *) pa;
-    const active_feature_t *b = (const active_feature_t *) pb;
-    return a->rec.feature < b->rec.feature ? -1 : a->rec.feature > b->rec.feature ? 1 :
-	   a->order < b->order ? -1 : a->order > b->order ? 1 :
-	   a->rec.setting < b->rec.setting ? -1 : a->rec.setting > b->rec.setting ? 1 :
-	   0;
-  }
-  bool operator== (const active_feature_t *f) {
-    return cmp (this, f) == 0;
-  }
-};
-
-struct feature_event_t {
-  unsigned int index;
-  bool start;
-  active_feature_t feature;
-
-  static int cmp (const void *pa, const void *pb) {
-    const feature_event_t *a = (const feature_event_t *) pa;
-    const feature_event_t *b = (const feature_event_t *) pb;
-    return a->index < b->index ? -1 : a->index > b->index ? 1 :
-	   a->start < b->start ? -1 : a->start > b->start ? 1 :
-	   active_feature_t::cmp (&a->feature, &b->feature);
-  }
-};
-
-struct range_record_t {
-  CTFontRef font;
-  unsigned int index_first; /* == start */
-  unsigned int index_last;  /* == end - 1 */
-};
-
-
-/* The following enum members are added in OS X 10.8. */
-#define kAltHalfWidthTextSelector		6
-#define kAltProportionalTextSelector		5
-#define kAlternateHorizKanaOffSelector		1
-#define kAlternateHorizKanaOnSelector		0
-#define kAlternateKanaType			34
-#define kAlternateVertKanaOffSelector		3
-#define kAlternateVertKanaOnSelector		2
-#define kCaseSensitiveLayoutOffSelector		1
-#define kCaseSensitiveLayoutOnSelector		0
-#define kCaseSensitiveLayoutType		33
-#define kCaseSensitiveSpacingOffSelector	3
-#define kCaseSensitiveSpacingOnSelector		2
-#define kContextualAlternatesOffSelector	1
-#define kContextualAlternatesOnSelector		0
-#define kContextualAlternatesType		36
-#define kContextualLigaturesOffSelector		19
-#define kContextualLigaturesOnSelector		18
-#define kContextualSwashAlternatesOffSelector	5
-#define kContextualSwashAlternatesOnSelector	4
-#define kDefaultLowerCaseSelector		0
-#define kDefaultUpperCaseSelector		0
-#define kHistoricalLigaturesOffSelector		21
-#define kHistoricalLigaturesOnSelector		20
-#define kHojoCharactersSelector			12
-#define kJIS2004CharactersSelector		11
-#define kLowerCasePetiteCapsSelector		2
-#define kLowerCaseSmallCapsSelector		1
-#define kLowerCaseType				37
-#define kMathematicalGreekOffSelector		11
-#define kMathematicalGreekOnSelector		10
-#define kNLCCharactersSelector			13
-#define kQuarterWidthTextSelector		4
-#define kScientificInferiorsSelector		4
-#define kStylisticAltEightOffSelector		17
-#define kStylisticAltEightOnSelector		16
-#define kStylisticAltEighteenOffSelector	37
-#define kStylisticAltEighteenOnSelector		36
-#define kStylisticAltElevenOffSelector		23
-#define kStylisticAltElevenOnSelector		22
-#define kStylisticAltFifteenOffSelector		31
-#define kStylisticAltFifteenOnSelector		30
-#define kStylisticAltFiveOffSelector		11
-#define kStylisticAltFiveOnSelector		10
-#define kStylisticAltFourOffSelector		9
-#define kStylisticAltFourOnSelector		8
-#define kStylisticAltFourteenOffSelector	29
-#define kStylisticAltFourteenOnSelector		28
-#define kStylisticAltNineOffSelector		19
-#define kStylisticAltNineOnSelector		18
-#define kStylisticAltNineteenOffSelector	39
-#define kStylisticAltNineteenOnSelector		38
-#define kStylisticAltOneOffSelector		3
-#define kStylisticAltOneOnSelector		2
-#define kStylisticAltSevenOffSelector		15
-#define kStylisticAltSevenOnSelector		14
-#define kStylisticAltSeventeenOffSelector	35
-#define kStylisticAltSeventeenOnSelector	34
-#define kStylisticAltSixOffSelector		13
-#define kStylisticAltSixOnSelector		12
-#define kStylisticAltSixteenOffSelector		33
-#define kStylisticAltSixteenOnSelector		32
-#define kStylisticAltTenOffSelector		21
-#define kStylisticAltTenOnSelector		20
-#define kStylisticAltThirteenOffSelector	27
-#define kStylisticAltThirteenOnSelector		26
-#define kStylisticAltThreeOffSelector		7
-#define kStylisticAltThreeOnSelector		6
-#define kStylisticAltTwelveOffSelector		25
-#define kStylisticAltTwelveOnSelector		24
-#define kStylisticAltTwentyOffSelector		41
-#define kStylisticAltTwentyOnSelector		40
-#define kStylisticAltTwoOffSelector		5
-#define kStylisticAltTwoOnSelector		4
-#define kStylisticAlternativesType		35
-#define kSwashAlternatesOffSelector		3
-#define kSwashAlternatesOnSelector		2
-#define kThirdWidthTextSelector			3
-#define kTraditionalNamesCharactersSelector	14
-#define kUpperCasePetiteCapsSelector		2
-#define kUpperCaseSmallCapsSelector		1
-#define kUpperCaseType				38
-
-/* Table data courtesy of Apple. */
-static const struct feature_mapping_t {
-    FourCharCode otFeatureTag;
-    uint16_t aatFeatureType;
-    uint16_t selectorToEnable;
-    uint16_t selectorToDisable;
-} feature_mappings[] = {
-    { 'c2pc',   kUpperCaseType,             kUpperCasePetiteCapsSelector,           kDefaultUpperCaseSelector },
-    { 'c2sc',   kUpperCaseType,             kUpperCaseSmallCapsSelector,            kDefaultUpperCaseSelector },
-    { 'calt',   kContextualAlternatesType,  kContextualAlternatesOnSelector,        kContextualAlternatesOffSelector },
-    { 'case',   kCaseSensitiveLayoutType,   kCaseSensitiveLayoutOnSelector,         kCaseSensitiveLayoutOffSelector },
-    { 'clig',   kLigaturesType,             kContextualLigaturesOnSelector,         kContextualLigaturesOffSelector },
-    { 'cpsp',   kCaseSensitiveLayoutType,   kCaseSensitiveSpacingOnSelector,        kCaseSensitiveSpacingOffSelector },
-    { 'cswh',   kContextualAlternatesType,  kContextualSwashAlternatesOnSelector,   kContextualSwashAlternatesOffSelector },
-    { 'dlig',   kLigaturesType,             kRareLigaturesOnSelector,               kRareLigaturesOffSelector },
-    { 'expt',   kCharacterShapeType,        kExpertCharactersSelector,              16 },
-    { 'frac',   kFractionsType,             kDiagonalFractionsSelector,             kNoFractionsSelector },
-    { 'fwid',   kTextSpacingType,           kMonospacedTextSelector,                7 },
-    { 'halt',   kTextSpacingType,           kAltHalfWidthTextSelector,              7 },
-    { 'hist',   kLigaturesType,             kHistoricalLigaturesOnSelector,         kHistoricalLigaturesOffSelector },
-    { 'hkna',   kAlternateKanaType,         kAlternateHorizKanaOnSelector,          kAlternateHorizKanaOffSelector, },
-    { 'hlig',   kLigaturesType,             kHistoricalLigaturesOnSelector,         kHistoricalLigaturesOffSelector },
-    { 'hngl',   kTransliterationType,       kHanjaToHangulSelector,                 kNoTransliterationSelector },
-    { 'hojo',   kCharacterShapeType,        kHojoCharactersSelector,                16 },
-    { 'hwid',   kTextSpacingType,           kHalfWidthTextSelector,                 7 },
-    { 'ital',   kItalicCJKRomanType,        kCJKItalicRomanOnSelector,              kCJKItalicRomanOffSelector },
-    { 'jp04',   kCharacterShapeType,        kJIS2004CharactersSelector,             16 },
-    { 'jp78',   kCharacterShapeType,        kJIS1978CharactersSelector,             16 },
-    { 'jp83',   kCharacterShapeType,        kJIS1983CharactersSelector,             16 },
-    { 'jp90',   kCharacterShapeType,        kJIS1990CharactersSelector,             16 },
-    { 'liga',   kLigaturesType,             kCommonLigaturesOnSelector,             kCommonLigaturesOffSelector },
-    { 'lnum',   kNumberCaseType,            kUpperCaseNumbersSelector,              2 },
-    { 'mgrk',   kMathematicalExtrasType,    kMathematicalGreekOnSelector,           kMathematicalGreekOffSelector },
-    { 'nlck',   kCharacterShapeType,        kNLCCharactersSelector,                 16 },
-    { 'onum',   kNumberCaseType,            kLowerCaseNumbersSelector,              2 },
-    { 'ordn',   kVerticalPositionType,      kOrdinalsSelector,                      kNormalPositionSelector },
-    { 'palt',   kTextSpacingType,           kAltProportionalTextSelector,           7 },
-    { 'pcap',   kLowerCaseType,             kLowerCasePetiteCapsSelector,           kDefaultLowerCaseSelector },
-    { 'pkna',   kTextSpacingType,           kProportionalTextSelector,              7 },
-    { 'pnum',   kNumberSpacingType,         kProportionalNumbersSelector,           4 },
-    { 'pwid',   kTextSpacingType,           kProportionalTextSelector,              7 },
-    { 'qwid',   kTextSpacingType,           kQuarterWidthTextSelector,              7 },
-    { 'ruby',   kRubyKanaType,              kRubyKanaOnSelector,                    kRubyKanaOffSelector },
-    { 'sinf',   kVerticalPositionType,      kScientificInferiorsSelector,           kNormalPositionSelector },
-    { 'smcp',   kLowerCaseType,             kLowerCaseSmallCapsSelector,            kDefaultLowerCaseSelector },
-    { 'smpl',   kCharacterShapeType,        kSimplifiedCharactersSelector,          16 },
-    { 'ss01',   kStylisticAlternativesType, kStylisticAltOneOnSelector,             kStylisticAltOneOffSelector },
-    { 'ss02',   kStylisticAlternativesType, kStylisticAltTwoOnSelector,             kStylisticAltTwoOffSelector },
-    { 'ss03',   kStylisticAlternativesType, kStylisticAltThreeOnSelector,           kStylisticAltThreeOffSelector },
-    { 'ss04',   kStylisticAlternativesType, kStylisticAltFourOnSelector,            kStylisticAltFourOffSelector },
-    { 'ss05',   kStylisticAlternativesType, kStylisticAltFiveOnSelector,            kStylisticAltFiveOffSelector },
-    { 'ss06',   kStylisticAlternativesType, kStylisticAltSixOnSelector,             kStylisticAltSixOffSelector },
-    { 'ss07',   kStylisticAlternativesType, kStylisticAltSevenOnSelector,           kStylisticAltSevenOffSelector },
-    { 'ss08',   kStylisticAlternativesType, kStylisticAltEightOnSelector,           kStylisticAltEightOffSelector },
-    { 'ss09',   kStylisticAlternativesType, kStylisticAltNineOnSelector,            kStylisticAltNineOffSelector },
-    { 'ss10',   kStylisticAlternativesType, kStylisticAltTenOnSelector,             kStylisticAltTenOffSelector },
-    { 'ss11',   kStylisticAlternativesType, kStylisticAltElevenOnSelector,          kStylisticAltElevenOffSelector },
-    { 'ss12',   kStylisticAlternativesType, kStylisticAltTwelveOnSelector,          kStylisticAltTwelveOffSelector },
-    { 'ss13',   kStylisticAlternativesType, kStylisticAltThirteenOnSelector,        kStylisticAltThirteenOffSelector },
-    { 'ss14',   kStylisticAlternativesType, kStylisticAltFourteenOnSelector,        kStylisticAltFourteenOffSelector },
-    { 'ss15',   kStylisticAlternativesType, kStylisticAltFifteenOnSelector,         kStylisticAltFifteenOffSelector },
-    { 'ss16',   kStylisticAlternativesType, kStylisticAltSixteenOnSelector,         kStylisticAltSixteenOffSelector },
-    { 'ss17',   kStylisticAlternativesType, kStylisticAltSeventeenOnSelector,       kStylisticAltSeventeenOffSelector },
-    { 'ss18',   kStylisticAlternativesType, kStylisticAltEighteenOnSelector,        kStylisticAltEighteenOffSelector },
-    { 'ss19',   kStylisticAlternativesType, kStylisticAltNineteenOnSelector,        kStylisticAltNineteenOffSelector },
-    { 'ss20',   kStylisticAlternativesType, kStylisticAltTwentyOnSelector,          kStylisticAltTwentyOffSelector },
-    { 'subs',   kVerticalPositionType,      kInferiorsSelector,                     kNormalPositionSelector },
-    { 'sups',   kVerticalPositionType,      kSuperiorsSelector,                     kNormalPositionSelector },
-    { 'swsh',   kContextualAlternatesType,  kSwashAlternatesOnSelector,             kSwashAlternatesOffSelector },
-    { 'titl',   kStyleOptionsType,          kTitlingCapsSelector,                   kNoStyleOptionsSelector },
-    { 'tnam',   kCharacterShapeType,        kTraditionalNamesCharactersSelector,    16 },
-    { 'tnum',   kNumberSpacingType,         kMonospacedNumbersSelector,             4 },
-    { 'trad',   kCharacterShapeType,        kTraditionalCharactersSelector,         16 },
-    { 'twid',   kTextSpacingType,           kThirdWidthTextSelector,                7 },
-    { 'unic',   kLetterCaseType,            14,                                     15 },
-    { 'valt',   kTextSpacingType,           kAltProportionalTextSelector,           7 },
-    { 'vert',   kVerticalSubstitutionType,  kSubstituteVerticalFormsOnSelector,     kSubstituteVerticalFormsOffSelector },
-    { 'vhal',   kTextSpacingType,           kAltHalfWidthTextSelector,              7 },
-    { 'vkna',   kAlternateKanaType,         kAlternateVertKanaOnSelector,           kAlternateVertKanaOffSelector },
-    { 'vpal',   kTextSpacingType,           kAltProportionalTextSelector,           7 },
-    { 'vrt2',   kVerticalSubstitutionType,  kSubstituteVerticalFormsOnSelector,     kSubstituteVerticalFormsOffSelector },
-    { 'zero',   kTypographicExtrasType,     kSlashedZeroOnSelector,                 kSlashedZeroOffSelector },
-};
-
-static int
-_hb_feature_mapping_cmp (const void *key_, const void *entry_)
-{
-  unsigned int key = * (unsigned int *) key_;
-  const feature_mapping_t * entry = (const feature_mapping_t *) entry_;
-  return key < entry->otFeatureTag ? -1 :
-	 key > entry->otFeatureTag ? 1 :
-	 0;
-}
-
-hb_bool_t
-_hb_coretext_shape (hb_shape_plan_t    *shape_plan,
-		    hb_font_t          *font,
-                    hb_buffer_t        *buffer,
-                    const hb_feature_t *features,
-                    unsigned int        num_features)
-{
-  hb_face_t *face = font->face;
-  CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
-  CTFontRef ct_font = (CTFontRef) HB_SHAPER_DATA_GET (font);
-
-  CGFloat ct_font_size = CTFontGetSize (ct_font);
-  CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
-  CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size;
-
-  /* Attach marks to their bases, to match the 'ot' shaper.
-   * Adapted from hb-ot-shape:hb_form_clusters().
-   * Note that this only makes us be closer to the 'ot' shaper,
-   * but by no means the same.  For example, if there's
-   * B1 M1 B2 M2, and B1-B2 form a ligature, M2's cluster will
-   * continue pointing to B2 even though B2 was merged into B1's
-   * cluster... */
-  if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
-  {
-    hb_unicode_funcs_t *unicode = buffer->unicode;
-    unsigned int count = buffer->len;
-    hb_glyph_info_t *info = buffer->info;
-    for (unsigned int i = 1; i < count; i++)
-      if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (unicode->general_category (info[i].codepoint)))
-	buffer->merge_clusters (i - 1, i + 1);
-  }
-
-  hb_auto_array_t<feature_record_t> feature_records;
-  hb_auto_array_t<range_record_t> range_records;
-
-  /*
-   * Set up features.
-   * (copied + modified from code from hb-uniscribe.cc)
-   */
-  if (num_features)
-  {
-    /* Sort features by start/end events. */
-    hb_auto_array_t<feature_event_t> feature_events;
-    for (unsigned int i = 0; i < num_features; i++)
-    {
-      const feature_mapping_t * mapping = (const feature_mapping_t *) bsearch (&features[i].tag,
-									       feature_mappings,
-									       ARRAY_LENGTH (feature_mappings),
-									       sizeof (feature_mappings[0]),
-									       _hb_feature_mapping_cmp);
-      if (!mapping)
-        continue;
-
-      active_feature_t feature;
-      feature.rec.feature = mapping->aatFeatureType;
-      feature.rec.setting = features[i].value ? mapping->selectorToEnable : mapping->selectorToDisable;
-      feature.order = i;
-
-      feature_event_t *event;
-
-      event = feature_events.push ();
-      if (unlikely (!event))
-	goto fail_features;
-      event->index = features[i].start;
-      event->start = true;
-      event->feature = feature;
-
-      event = feature_events.push ();
-      if (unlikely (!event))
-	goto fail_features;
-      event->index = features[i].end;
-      event->start = false;
-      event->feature = feature;
-    }
-    feature_events.qsort ();
-    /* Add a strategic final event. */
-    {
-      active_feature_t feature;
-      feature.rec.feature = HB_TAG_NONE;
-      feature.rec.setting = 0;
-      feature.order = num_features + 1;
-
-      feature_event_t *event = feature_events.push ();
-      if (unlikely (!event))
-	goto fail_features;
-      event->index = 0; /* This value does magic. */
-      event->start = false;
-      event->feature = feature;
-    }
-
-    /* Scan events and save features for each range. */
-    hb_auto_array_t<active_feature_t> active_features;
-    unsigned int last_index = 0;
-    for (unsigned int i = 0; i < feature_events.len; i++)
-    {
-      feature_event_t *event = &feature_events[i];
-
-      if (event->index != last_index)
-      {
-        /* Save a snapshot of active features and the range. */
-	range_record_t *range = range_records.push ();
-	if (unlikely (!range))
-	  goto fail_features;
-
-	if (active_features.len)
-	{
-	  CFMutableArrayRef features_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-
-	  /* TODO sort and resolve conflicting features? */
-	  /* active_features.qsort (); */
-	  for (unsigned int j = 0; j < active_features.len; j++)
-	  {
-	    CFStringRef keys[] = {
-	      kCTFontFeatureTypeIdentifierKey,
-	      kCTFontFeatureSelectorIdentifierKey
-	    };
-	    CFNumberRef values[] = {
-	      CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.feature),
-	      CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.setting)
-	    };
-	    static_assert ((ARRAY_LENGTH_CONST (keys) == ARRAY_LENGTH_CONST (values)), "");
-	    CFDictionaryRef dict = CFDictionaryCreate (kCFAllocatorDefault,
-						       (const void **) keys,
-						       (const void **) values,
-						       ARRAY_LENGTH (keys),
-						       &kCFTypeDictionaryKeyCallBacks,
-						       &kCFTypeDictionaryValueCallBacks);
-	    for (unsigned int i = 0; i < ARRAY_LENGTH (values); i++)
-	      CFRelease (values[i]);
-
-	    CFArrayAppendValue (features_array, dict);
-	    CFRelease (dict);
-
-	  }
-
-	  CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault,
-							   (const void **) &kCTFontFeatureSettingsAttribute,
-							   (const void **) &features_array,
-							   1,
-							   &kCFTypeDictionaryKeyCallBacks,
-							   &kCFTypeDictionaryValueCallBacks);
-	  CFRelease (features_array);
-
-	  CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes);
-	  CFRelease (attributes);
-
-	  range->font = CTFontCreateCopyWithAttributes (ct_font, 0.0, nullptr, font_desc);
-	  CFRelease (font_desc);
-	}
-	else
-	{
-	  range->font = nullptr;
-	}
-
-	range->index_first = last_index;
-	range->index_last  = event->index - 1;
-
-	last_index = event->index;
-      }
-
-      if (event->start) {
-        active_feature_t *feature = active_features.push ();
-	if (unlikely (!feature))
-	  goto fail_features;
-	*feature = event->feature;
-      } else {
-        active_feature_t *feature = active_features.find (&event->feature);
-	if (feature)
-	  active_features.remove (feature - active_features.array);
-      }
-    }
-  }
-  else
-  {
-  fail_features:
-    num_features = 0;
-  }
-
-  unsigned int scratch_size;
-  hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
-
-#define ALLOCATE_ARRAY(Type, name, len, on_no_room) \
-  Type *name = (Type *) scratch; \
-  { \
-    unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
-    if (unlikely (_consumed > scratch_size)) \
-    { \
-      on_no_room; \
-      assert (0); \
-    } \
-    scratch += _consumed; \
-    scratch_size -= _consumed; \
-  }
-
-  ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2, /*nothing*/);
-  unsigned int chars_len = 0;
-  for (unsigned int i = 0; i < buffer->len; i++) {
-    hb_codepoint_t c = buffer->info[i].codepoint;
-    if (likely (c <= 0xFFFFu))
-      pchars[chars_len++] = c;
-    else if (unlikely (c > 0x10FFFFu))
-      pchars[chars_len++] = 0xFFFDu;
-    else {
-      pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
-      pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1));
-    }
-  }
-
-  ALLOCATE_ARRAY (unsigned int, log_clusters, chars_len, /*nothing*/);
-  chars_len = 0;
-  for (unsigned int i = 0; i < buffer->len; i++)
-  {
-    hb_codepoint_t c = buffer->info[i].codepoint;
-    unsigned int cluster = buffer->info[i].cluster;
-    log_clusters[chars_len++] = cluster;
-    if (hb_in_range (c, 0x10000u, 0x10FFFFu))
-      log_clusters[chars_len++] = cluster; /* Surrogates. */
-  }
-
-#define FAIL(...) \
-  HB_STMT_START { \
-    DEBUG_MSG (CORETEXT, nullptr, __VA_ARGS__); \
-    ret = false; \
-    goto fail; \
-  } HB_STMT_END;
-
-  bool ret = true;
-  CFStringRef string_ref = nullptr;
-  CTLineRef line = nullptr;
-
-  if (0)
-  {
-resize_and_retry:
-    DEBUG_MSG (CORETEXT, buffer, "Buffer resize");
-    /* string_ref uses the scratch-buffer for backing store, and line references
-     * string_ref (via attr_string).  We must release those before resizing buffer. */
-    assert (string_ref);
-    assert (line);
-    CFRelease (string_ref);
-    CFRelease (line);
-    string_ref = nullptr;
-    line = nullptr;
-
-    /* Get previous start-of-scratch-area, that we use later for readjusting
-     * our existing scratch arrays. */
-    unsigned int old_scratch_used;
-    hb_buffer_t::scratch_buffer_t *old_scratch;
-    old_scratch = buffer->get_scratch_buffer (&old_scratch_used);
-    old_scratch_used = scratch - old_scratch;
-
-    if (unlikely (!buffer->ensure (buffer->allocated * 2)))
-      FAIL ("Buffer resize failed");
-
-    /* Adjust scratch, pchars, and log_cluster arrays.  This is ugly, but really the
-     * cleanest way to do without completely restructuring the rest of this shaper. */
-    scratch = buffer->get_scratch_buffer (&scratch_size);
-    pchars = reinterpret_cast<UniChar *> (((char *) scratch + ((char *) pchars - (char *) old_scratch)));
-    log_clusters = reinterpret_cast<unsigned int *> (((char *) scratch + ((char *) log_clusters - (char *) old_scratch)));
-    scratch += old_scratch_used;
-    scratch_size -= old_scratch_used;
-  }
-  {
-    string_ref = CFStringCreateWithCharactersNoCopy (nullptr,
-						     pchars, chars_len,
-						     kCFAllocatorNull);
-    if (unlikely (!string_ref))
-      FAIL ("CFStringCreateWithCharactersNoCopy failed");
-
-    /* Create an attributed string, populate it, and create a line from it, then release attributed string. */
-    {
-      CFMutableAttributedStringRef attr_string = CFAttributedStringCreateMutable (kCFAllocatorDefault,
-										  chars_len);
-      if (unlikely (!attr_string))
-	FAIL ("CFAttributedStringCreateMutable failed");
-      CFAttributedStringReplaceString (attr_string, CFRangeMake (0, 0), string_ref);
-      if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
-      {
-	CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
-					kCTVerticalFormsAttributeName, kCFBooleanTrue);
-      }
-
-      if (buffer->props.language)
-      {
-/* What's the iOS equivalent of this check?
- * The symbols was introduced in iOS 7.0.
- * At any rate, our fallback is safe and works fine. */
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
-#  define kCTLanguageAttributeName CFSTR ("NSLanguage")
-#endif
-        CFStringRef lang = CFStringCreateWithCStringNoCopy (kCFAllocatorDefault,
-							    hb_language_to_string (buffer->props.language),
-							    kCFStringEncodingUTF8,
-							    kCFAllocatorNull);
-	if (unlikely (!lang))
-        {
-	  CFRelease (attr_string);
-	  FAIL ("CFStringCreateWithCStringNoCopy failed");
-        }
-	CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
-					kCTLanguageAttributeName, lang);
-	CFRelease (lang);
-      }
-      CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
-				      kCTFontAttributeName, ct_font);
-
-      if (num_features && range_records.len)
-      {
-	unsigned int start = 0;
-	range_record_t *last_range = &range_records[0];
-	for (unsigned int k = 0; k < chars_len; k++)
-	{
-	  range_record_t *range = last_range;
-	  while (log_clusters[k] < range->index_first)
-	    range--;
-	  while (log_clusters[k] > range->index_last)
-	    range++;
-	  if (range != last_range)
-	  {
-	    if (last_range->font)
-	      CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, k - start),
-					      kCTFontAttributeName, last_range->font);
-
-	    start = k;
-	  }
-
-	  last_range = range;
-	}
-	if (start != chars_len && last_range->font)
-	  CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, chars_len - start),
-					  kCTFontAttributeName, last_range->font);
-      }
-      /* Enable/disable kern if requested.
-       *
-       * Note: once kern is disabled, reenabling it doesn't currently seem to work in CoreText.
-       */
-      if (num_features)
-      {
-	unsigned int zeroint = 0;
-	CFNumberRef zero = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &zeroint);
-	for (unsigned int i = 0; i < num_features; i++)
-	{
-	  const hb_feature_t &feature = features[i];
-	  if (feature.tag == HB_TAG('k','e','r','n') &&
-	      feature.start < chars_len && feature.start < feature.end)
-	  {
-	    CFRange feature_range = CFRangeMake (feature.start,
-	                                         MIN (feature.end, chars_len) - feature.start);
-	    if (feature.value)
-	      CFAttributedStringRemoveAttribute (attr_string, feature_range, kCTKernAttributeName);
-	    else
-	      CFAttributedStringSetAttribute (attr_string, feature_range, kCTKernAttributeName, zero);
-	  }
-	}
-	CFRelease (zero);
-      }
-
-      int level = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
-      CFNumberRef level_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &level);
-      CFDictionaryRef options = CFDictionaryCreate (kCFAllocatorDefault,
-						    (const void **) &kCTTypesetterOptionForcedEmbeddingLevel,
-						    (const void **) &level_number,
-						    1,
-						    &kCFTypeDictionaryKeyCallBacks,
-						    &kCFTypeDictionaryValueCallBacks);
-      CFRelease (level_number);
-      if (unlikely (!options))
-      {
-        CFRelease (attr_string);
-        FAIL ("CFDictionaryCreate failed");
-      }
-
-      CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedStringAndOptions (attr_string, options);
-      CFRelease (options);
-      CFRelease (attr_string);
-      if (unlikely (!typesetter))
-	FAIL ("CTTypesetterCreateWithAttributedStringAndOptions failed");
-
-      line = CTTypesetterCreateLine (typesetter, CFRangeMake(0, 0));
-      CFRelease (typesetter);
-      if (unlikely (!line))
-	FAIL ("CTTypesetterCreateLine failed");
-    }
-
-    CFArrayRef glyph_runs = CTLineGetGlyphRuns (line);
-    unsigned int num_runs = CFArrayGetCount (glyph_runs);
-    DEBUG_MSG (CORETEXT, nullptr, "Num runs: %d", num_runs);
-
-    buffer->len = 0;
-    uint32_t status_and = ~0, status_or = 0;
-    double advances_so_far = 0;
-    /* For right-to-left runs, CoreText returns the glyphs positioned such that
-     * any trailing whitespace is to the left of (0,0).  Adjust coordinate system
-     * to fix for that.  Test with any RTL string with trailing spaces.
-     * https://code.google.com/p/chromium/issues/detail?id=469028
-     */
-    if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
-    {
-      advances_so_far -= CTLineGetTrailingWhitespaceWidth (line);
-      if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
-	  advances_so_far = -advances_so_far;
-    }
-
-    const CFRange range_all = CFRangeMake (0, 0);
-
-    for (unsigned int i = 0; i < num_runs; i++)
-    {
-      CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex (glyph_runs, i));
-      CTRunStatus run_status = CTRunGetStatus (run);
-      status_or  |= run_status;
-      status_and &= run_status;
-      DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status);
-      double run_advance = CTRunGetTypographicBounds (run, range_all, nullptr, nullptr, nullptr);
-      if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
-	  run_advance = -run_advance;
-      DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance);
-
-      /* CoreText does automatic font fallback (AKA "cascading") for  characters
-       * not supported by the requested font, and provides no way to turn it off,
-       * so we must detect if the returned run uses a font other than the requested
-       * one and fill in the buffer with .notdef glyphs instead of random glyph
-       * indices from a different font.
-       */
-      CFDictionaryRef attributes = CTRunGetAttributes (run);
-      CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName));
-      if (!CFEqual (run_ct_font, ct_font))
-      {
-	/* The run doesn't use our main font instance.  We have to figure out
-	 * whether font fallback happened, or this is just CoreText giving us
-	 * another CTFont using the same underlying CGFont.  CoreText seems
-	 * to do that in a variety of situations, one of which being vertical
-	 * text, but also perhaps for caching reasons.
-	 *
-	 * First, see if it uses any of our subfonts created to set font features...
-	 *
-	 * Next, compare the CGFont to the one we used to create our fonts.
-	 * Even this doesn't work all the time.
-	 *
-	 * Finally, we compare PS names, which I don't think are unique...
-	 *
-	 * Looks like if we really want to be sure here we have to modify the
-	 * font to change the name table, similar to what we do in the uniscribe
-	 * backend.
-	 *
-	 * However, even that wouldn't work if we were passed in the CGFont to
-	 * construct a hb_face to begin with.
-	 *
-	 * See: http://github.com/harfbuzz/harfbuzz/pull/36
-	 *
-	 * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
-	 */
-	bool matched = false;
-	for (unsigned int i = 0; i < range_records.len; i++)
-	  if (range_records[i].font && CFEqual (run_ct_font, range_records[i].font))
-	  {
-	    matched = true;
-	    break;
-	  }
-	if (!matched)
-	{
-	  CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, nullptr);
-	  if (run_cg_font)
-	  {
-	    matched = CFEqual (run_cg_font, cg_font);
-	    CFRelease (run_cg_font);
-	  }
-	}
-	if (!matched)
-	{
-	  CFStringRef font_ps_name = CTFontCopyName (ct_font, kCTFontPostScriptNameKey);
-	  CFStringRef run_ps_name = CTFontCopyName (run_ct_font, kCTFontPostScriptNameKey);
-	  CFComparisonResult result = CFStringCompare (run_ps_name, font_ps_name, 0);
-	  CFRelease (run_ps_name);
-	  CFRelease (font_ps_name);
-	  if (result == kCFCompareEqualTo)
-	    matched = true;
-	}
-	if (!matched)
-	{
-	  CFRange range = CTRunGetStringRange (run);
-          DEBUG_MSG (CORETEXT, run, "Run used fallback font: %ld..%ld",
-		     range.location, range.location + range.length);
-	  if (!buffer->ensure_inplace (buffer->len + range.length))
-	    goto resize_and_retry;
-	  hb_glyph_info_t *info = buffer->info + buffer->len;
-
-	  hb_codepoint_t notdef = 0;
-	  hb_direction_t dir = buffer->props.direction;
-	  hb_position_t x_advance, y_advance, x_offset, y_offset;
-	  hb_font_get_glyph_advance_for_direction (font, notdef, dir, &x_advance, &y_advance);
-	  hb_font_get_glyph_origin_for_direction (font, notdef, dir, &x_offset, &y_offset);
-	  hb_position_t advance = x_advance + y_advance;
-	  x_offset = -x_offset;
-	  y_offset = -y_offset;
-
-	  unsigned int old_len = buffer->len;
-	  for (CFIndex j = range.location; j < range.location + range.length; j++)
-	  {
-	      UniChar ch = CFStringGetCharacterAtIndex (string_ref, j);
-	      if (hb_in_range<UniChar> (ch, 0xDC00u, 0xDFFFu) && range.location < j)
-	      {
-		ch = CFStringGetCharacterAtIndex (string_ref, j - 1);
-		if (hb_in_range<UniChar> (ch, 0xD800u, 0xDBFFu))
-		  /* This is the second of a surrogate pair.  Don't need .notdef
-		   * for this one. */
-		  continue;
-	      }
-	      if (buffer->unicode->is_default_ignorable (ch))
-	        continue;
-
-	      info->codepoint = notdef;
-	      info->cluster = log_clusters[j];
-
-	      info->mask = advance;
-	      info->var1.i32 = x_offset;
-	      info->var2.i32 = y_offset;
-
-	      info++;
-	      buffer->len++;
-	  }
-	  if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
-	    buffer->reverse_range (old_len, buffer->len);
-	  advances_so_far += run_advance;
-	  continue;
-	}
-      }
-
-      unsigned int num_glyphs = CTRunGetGlyphCount (run);
-      if (num_glyphs == 0)
-	continue;
-
-      if (!buffer->ensure_inplace (buffer->len + num_glyphs))
-	goto resize_and_retry;
-
-      hb_glyph_info_t *run_info = buffer->info + buffer->len;
-
-      /* Testing used to indicate that CTRunGetGlyphsPtr, etc (almost?) always
-       * succeed, and so copying data to our own buffer will be rare.  Reports
-       * have it that this changed in OS X 10.10 Yosemite, and nullptr is returned
-       * frequently.  At any rate, we can test that codepath by setting USE_PTR
-       * to false. */
-
-#define USE_PTR true
-
-#define SCRATCH_SAVE() \
-  unsigned int scratch_size_saved = scratch_size; \
-  hb_buffer_t::scratch_buffer_t *scratch_saved = scratch
-
-#define SCRATCH_RESTORE() \
-  scratch_size = scratch_size_saved; \
-  scratch = scratch_saved;
-
-      { /* Setup glyphs */
-        SCRATCH_SAVE();
-	const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : nullptr;
-	if (!glyphs) {
-	  ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs, goto resize_and_retry);
-	  CTRunGetGlyphs (run, range_all, glyph_buf);
-	  glyphs = glyph_buf;
-	}
-	const CFIndex* string_indices = USE_PTR ? CTRunGetStringIndicesPtr (run) : nullptr;
-	if (!string_indices) {
-	  ALLOCATE_ARRAY (CFIndex, index_buf, num_glyphs, goto resize_and_retry);
-	  CTRunGetStringIndices (run, range_all, index_buf);
-	  string_indices = index_buf;
-	}
-	hb_glyph_info_t *info = run_info;
-	for (unsigned int j = 0; j < num_glyphs; j++)
-	{
-	  info->codepoint = glyphs[j];
-	  info->cluster = log_clusters[string_indices[j]];
-	  info++;
-	}
-	SCRATCH_RESTORE();
-      }
-      {
-        /* Setup positions.
-	 * Note that CoreText does not return advances for glyphs.  As such,
-	 * for all but last glyph, we use the delta position to next glyph as
-	 * advance (in the advance direction only), and for last glyph we set
-	 * whatever is needed to make the whole run's advance add up. */
-        SCRATCH_SAVE();
-	const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : nullptr;
-	if (!positions) {
-	  ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs, goto resize_and_retry);
-	  CTRunGetPositions (run, range_all, position_buf);
-	  positions = position_buf;
-	}
-	hb_glyph_info_t *info = run_info;
-	if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
-	{
-	  hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult;
-	  for (unsigned int j = 0; j < num_glyphs; j++)
-	  {
-	    double advance;
-	    if (likely (j + 1 < num_glyphs))
-	      advance = positions[j + 1].x - positions[j].x;
-	    else /* last glyph */
-	      advance = run_advance - (positions[j].x - positions[0].x);
-	    info->mask = advance * x_mult;
-	    info->var1.i32 = x_offset;
-	    info->var2.i32 = positions[j].y * y_mult;
-	    info++;
-	  }
-	}
-	else
-	{
-	  hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult;
-	  for (unsigned int j = 0; j < num_glyphs; j++)
-	  {
-	    double advance;
-	    if (likely (j + 1 < num_glyphs))
-	      advance = positions[j + 1].y - positions[j].y;
-	    else /* last glyph */
-	      advance = run_advance - (positions[j].y - positions[0].y);
-	    info->mask = advance * y_mult;
-	    info->var1.i32 = positions[j].x * x_mult;
-	    info->var2.i32 = y_offset;
-	    info++;
-	  }
-	}
-	SCRATCH_RESTORE();
-	advances_so_far += run_advance;
-      }
-#undef SCRATCH_RESTORE
-#undef SCRATCH_SAVE
-#undef USE_PTR
-#undef ALLOCATE_ARRAY
-
-      buffer->len += num_glyphs;
-    }
-
-    /* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel,
-     * or if it does, it doesn't respect it.  So we get runs with wrong
-     * directions.  As such, disable the assert...  It wouldn't crash, but
-     * cursoring will be off...
-     *
-     * http://crbug.com/419769
-     */
-    if (0)
-    {
-      /* Make sure all runs had the expected direction. */
-      bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
-      assert (bool (status_and & kCTRunStatusRightToLeft) == backward);
-      assert (bool (status_or  & kCTRunStatusRightToLeft) == backward);
-    }
-
-    buffer->clear_positions ();
-
-    unsigned int count = buffer->len;
-    hb_glyph_info_t *info = buffer->info;
-    hb_glyph_position_t *pos = buffer->pos;
-    if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
-      for (unsigned int i = 0; i < count; i++)
-      {
-	pos->x_advance = info->mask;
-	pos->x_offset = info->var1.i32;
-	pos->y_offset = info->var2.i32;
-
-	info++, pos++;
-      }
-    else
-      for (unsigned int i = 0; i < count; i++)
-      {
-	pos->y_advance = info->mask;
-	pos->x_offset = info->var1.i32;
-	pos->y_offset = info->var2.i32;
-
-	info++, pos++;
-      }
-
-    /* Fix up clusters so that we never return out-of-order indices;
-     * if core text has reordered glyphs, we'll merge them to the
-     * beginning of the reordered cluster.  CoreText is nice enough
-     * to tell us whenever it has produced nonmonotonic results...
-     * Note that we assume the input clusters were nonmonotonic to
-     * begin with.
-     *
-     * This does *not* mean we'll form the same clusters as Uniscribe
-     * or the native OT backend, only that the cluster indices will be
-     * monotonic in the output buffer. */
-    if (count > 1 && (status_or & kCTRunStatusNonMonotonic))
-    {
-      hb_glyph_info_t *info = buffer->info;
-      if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
-      {
-	unsigned int cluster = info[count - 1].cluster;
-	for (unsigned int i = count - 1; i > 0; i--)
-	{
-	  cluster = MIN (cluster, info[i - 1].cluster);
-	  info[i - 1].cluster = cluster;
-	}
-      }
-      else
-      {
-	unsigned int cluster = info[0].cluster;
-	for (unsigned int i = 1; i < count; i++)
-	{
-	  cluster = MIN (cluster, info[i].cluster);
-	  info[i].cluster = cluster;
-	}
-      }
-    }
-  }
-
-  buffer->unsafe_to_break_all ();
-
-#undef FAIL
-
-fail:
-  if (string_ref)
-    CFRelease (string_ref);
-  if (line)
-    CFRelease (line);
-
-  for (unsigned int i = 0; i < range_records.len; i++)
-    if (range_records[i].font)
-      CFRelease (range_records[i].font);
-
-  return ret;
-}
-
-
-/*
- * AAT shaper
- */
-
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, face)
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font)
-
-/*
- * shaper face data
- */
-
-struct hb_coretext_aat_shaper_face_data_t {};
-
-hb_coretext_aat_shaper_face_data_t *
-_hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
-{
-  static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX};
-
-  for (unsigned int i = 0; i < ARRAY_LENGTH (tags); i++)
-  {
-    hb_blob_t *blob = face->reference_table (tags[i]);
-    if (hb_blob_get_length (blob))
-    {
-      hb_blob_destroy (blob);
-      return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
-    }
-    hb_blob_destroy (blob);
-  }
-
-  return nullptr;
-}
-
-void
-_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
- * shaper font data
- */
-
-struct hb_coretext_aat_shaper_font_data_t {};
-
-hb_coretext_aat_shaper_font_data_t *
-_hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
-{
-  return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
-}
-
-void
-_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_coretext_aat_shaper_shape_plan_data_t {};
-
-hb_coretext_aat_shaper_shape_plan_data_t *
-_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-					     const hb_feature_t *user_features HB_UNUSED,
-					     unsigned int        num_user_features HB_UNUSED,
-					     const int          *coords HB_UNUSED,
-					     unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shaper_shape_plan_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
- * shaper
- */
-
-hb_bool_t
-_hb_coretext_aat_shape (hb_shape_plan_t    *shape_plan,
-			hb_font_t          *font,
-			hb_buffer_t        *buffer,
-			const hb_feature_t *features,
-			unsigned int        num_features)
-{
-  return _hb_coretext_shape (shape_plan, font, buffer, features, num_features);
-}
diff --git a/third_party/harfbuzz-ng/src/hb-coretext.h b/third_party/harfbuzz-ng/src/hb-coretext.h
deleted file mode 100644
index 4b0a6f01..0000000
--- a/third_party/harfbuzz-ng/src/hb-coretext.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright © 2012  Mozilla Foundation.
- *
- *  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.
- *
- * Mozilla Author(s): Jonathan Kew
- */
-
-#ifndef HB_CORETEXT_H
-#define HB_CORETEXT_H
-
-#include "hb.h"
-
-#include <TargetConditionals.h>
-#if TARGET_OS_IPHONE
-#  include <CoreText/CoreText.h>
-#  include <CoreGraphics/CoreGraphics.h>
-#else
-#  include <ApplicationServices/ApplicationServices.h>
-#endif
-
-HB_BEGIN_DECLS
-
-
-#define HB_CORETEXT_TAG_MORT HB_TAG('m','o','r','t')
-#define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x')
-#define HB_CORETEXT_TAG_KERX HB_TAG('k','e','r','x')
-
-
-HB_EXTERN hb_face_t *
-hb_coretext_face_create (CGFontRef cg_font);
-
-HB_EXTERN hb_font_t *
-hb_coretext_font_create (CTFontRef ct_font);
-
-
-HB_EXTERN CGFontRef
-hb_coretext_face_get_cg_font (hb_face_t *face);
-
-HB_EXTERN CTFontRef
-hb_coretext_font_get_ct_font (hb_font_t *font);
-
-
-HB_END_DECLS
-
-#endif /* HB_CORETEXT_H */
diff --git a/third_party/harfbuzz-ng/src/hb-debug.hh b/third_party/harfbuzz-ng/src/hb-debug.hh
deleted file mode 100644
index c244347..0000000
--- a/third_party/harfbuzz-ng/src/hb-debug.hh
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_DEBUG_HH
-#define HB_DEBUG_HH
-
-#include "hb-private.hh"
-
-
-#ifndef HB_DEBUG
-#define HB_DEBUG 0
-#endif
-
-static inline bool
-_hb_debug (unsigned int level,
-	   unsigned int max_level)
-{
-  return level < max_level;
-}
-
-#define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
-#define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
-
-static inline void
-_hb_print_func (const char *func)
-{
-  if (func)
-  {
-    unsigned int func_len = strlen (func);
-    /* Skip "static" */
-    if (0 == strncmp (func, "static ", 7))
-      func += 7;
-    /* Skip "typename" */
-    if (0 == strncmp (func, "typename ", 9))
-      func += 9;
-    /* Skip return type */
-    const char *space = strchr (func, ' ');
-    if (space)
-      func = space + 1;
-    /* Skip parameter list */
-    const char *paren = strchr (func, '(');
-    if (paren)
-      func_len = paren - func;
-    fprintf (stderr, "%.*s", func_len, func);
-  }
-}
-
-template <int max_level> static inline void
-_hb_debug_msg_va (const char *what,
-		  const void *obj,
-		  const char *func,
-		  bool indented,
-		  unsigned int level,
-		  int level_dir,
-		  const char *message,
-		  va_list ap) HB_PRINTF_FUNC(7, 0);
-template <int max_level> static inline void
-_hb_debug_msg_va (const char *what,
-		  const void *obj,
-		  const char *func,
-		  bool indented,
-		  unsigned int level,
-		  int level_dir,
-		  const char *message,
-		  va_list ap)
-{
-  if (!_hb_debug (level, max_level))
-    return;
-
-  fprintf (stderr, "%-10s", what ? what : "");
-
-  if (obj)
-    fprintf (stderr, "(%*p) ", (unsigned int) (2 * sizeof (void *)), obj);
-  else
-    fprintf (stderr, " %*s  ", (unsigned int) (2 * sizeof (void *)), "");
-
-  if (indented) {
-#define VBAR	"\342\224\202"	/* U+2502 BOX DRAWINGS LIGHT VERTICAL */
-#define VRBAR	"\342\224\234"	/* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
-#define DLBAR	"\342\225\256"	/* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
-#define ULBAR	"\342\225\257"	/* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
-#define LBAR	"\342\225\264"	/* U+2574 BOX DRAWINGS LIGHT LEFT */
-    static const char bars[] =
-      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
-      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
-      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
-      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
-      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
-    fprintf (stderr, "%2u %s" VRBAR "%s",
-	     level,
-	     bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
-	     level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
-  } else
-    fprintf (stderr, "   " VRBAR LBAR);
-
-  _hb_print_func (func);
-
-  if (message)
-  {
-    fprintf (stderr, ": ");
-    vfprintf (stderr, message, ap);
-  }
-
-  fprintf (stderr, "\n");
-}
-template <> inline void
-_hb_debug_msg_va<0> (const char *what HB_UNUSED,
-		     const void *obj HB_UNUSED,
-		     const char *func HB_UNUSED,
-		     bool indented HB_UNUSED,
-		     unsigned int level HB_UNUSED,
-		     int level_dir HB_UNUSED,
-		     const char *message HB_UNUSED,
-		     va_list ap HB_UNUSED) {}
-
-template <int max_level> static inline void
-_hb_debug_msg (const char *what,
-	       const void *obj,
-	       const char *func,
-	       bool indented,
-	       unsigned int level,
-	       int level_dir,
-	       const char *message,
-	       ...) HB_PRINTF_FUNC(7, 8);
-template <int max_level> static inline void
-_hb_debug_msg (const char *what,
-	       const void *obj,
-	       const char *func,
-	       bool indented,
-	       unsigned int level,
-	       int level_dir,
-	       const char *message,
-	       ...)
-{
-  va_list ap;
-  va_start (ap, message);
-  _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
-  va_end (ap);
-}
-template <> inline void
-_hb_debug_msg<0> (const char *what HB_UNUSED,
-		  const void *obj HB_UNUSED,
-		  const char *func HB_UNUSED,
-		  bool indented HB_UNUSED,
-		  unsigned int level HB_UNUSED,
-		  int level_dir HB_UNUSED,
-		  const char *message HB_UNUSED,
-		  ...) HB_PRINTF_FUNC(7, 8);
-template <> inline void
-_hb_debug_msg<0> (const char *what HB_UNUSED,
-		  const void *obj HB_UNUSED,
-		  const char *func HB_UNUSED,
-		  bool indented HB_UNUSED,
-		  unsigned int level HB_UNUSED,
-		  int level_dir HB_UNUSED,
-		  const char *message HB_UNUSED,
-		  ...) {}
-
-#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...)	_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr,    true, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
-#define DEBUG_MSG(WHAT, OBJ, ...) 				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr,    false, 0, 0, __VA_ARGS__)
-#define DEBUG_MSG_FUNC(WHAT, OBJ, ...)				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
-
-
-/*
- * Printer
- */
-
-template <typename T>
-struct hb_printer_t {
-  const char *print (const T&) { return "something"; }
-};
-
-template <>
-struct hb_printer_t<bool> {
-  const char *print (bool v) { return v ? "true" : "false"; }
-};
-
-template <>
-struct hb_printer_t<hb_void_t> {
-  const char *print (hb_void_t) { return ""; }
-};
-
-
-/*
- * Trace
- */
-
-template <typename T>
-static inline void _hb_warn_no_return (bool returned)
-{
-  if (unlikely (!returned)) {
-    fprintf (stderr, "OUCH, returned with no call to return_trace().  This is a bug, please report.\n");
-  }
-}
-template <>
-/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
-{}
-
-template <int max_level, typename ret_t>
-struct hb_auto_trace_t
-{
-  explicit inline hb_auto_trace_t (unsigned int *plevel_,
-				   const char *what_,
-				   const void *obj_,
-				   const char *func,
-				   const char *message,
-				   ...) HB_PRINTF_FUNC(6, 7)
-				   : plevel (plevel_), what (what_), obj (obj_), returned (false)
-  {
-    if (plevel) ++*plevel;
-
-    va_list ap;
-    va_start (ap, message);
-    _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
-    va_end (ap);
-  }
-  inline ~hb_auto_trace_t (void)
-  {
-    _hb_warn_no_return<ret_t> (returned);
-    if (!returned) {
-      _hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1, " ");
-    }
-    if (plevel) --*plevel;
-  }
-
-  inline ret_t ret (ret_t v, unsigned int line = 0)
-  {
-    if (unlikely (returned)) {
-      fprintf (stderr, "OUCH, double calls to return_trace().  This is a bug, please report.\n");
-      return v;
-    }
-
-    _hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1,
-			      "return %s (line %d)",
-			      hb_printer_t<ret_t>().print (v), line);
-    if (plevel) --*plevel;
-    plevel = nullptr;
-    returned = true;
-    return v;
-  }
-
-  private:
-  unsigned int *plevel;
-  const char *what;
-  const void *obj;
-  bool returned;
-};
-template <typename ret_t> /* Make sure we don't use hb_auto_trace_t when not tracing. */
-struct hb_auto_trace_t<0, ret_t>
-{
-  explicit inline hb_auto_trace_t (unsigned int *plevel_,
-				   const char *what_,
-				   const void *obj_,
-				   const char *func,
-				   const char *message,
-				   ...) HB_PRINTF_FUNC(6, 7) {}
-
-  inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
-};
-
-/* For disabled tracing; optimize out everything.
- * https://github.com/harfbuzz/harfbuzz/pull/605 */
-template <typename ret_t>
-struct hb_no_trace_t {
-  inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
-};
-
-#define return_trace(RET) return trace.ret (RET, __LINE__)
-
-
-/*
- * Instances.
- */
-
-#ifndef HB_DEBUG_ARABIC
-#define HB_DEBUG_ARABIC (HB_DEBUG+0)
-#endif
-
-#ifndef HB_DEBUG_BLOB
-#define HB_DEBUG_BLOB (HB_DEBUG+0)
-#endif
-
-#ifndef HB_DEBUG_CORETEXT
-#define HB_DEBUG_CORETEXT (HB_DEBUG+0)
-#endif
-
-#ifndef HB_DEBUG_DIRECTWRITE
-#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
-#endif
-
-#ifndef HB_DEBUG_FT
-#define HB_DEBUG_FT (HB_DEBUG+0)
-#endif
-
-#ifndef HB_DEBUG_GET_COVERAGE
-#define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0)
-#endif
-
-#ifndef HB_DEBUG_OBJECT
-#define HB_DEBUG_OBJECT (HB_DEBUG+0)
-#endif
-
-#ifndef HB_DEBUG_SHAPE_PLAN
-#define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0)
-#endif
-
-#ifndef HB_DEBUG_UNISCRIBE
-#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
-#endif
-
-/*
- * With tracing.
- */
-
-#ifndef HB_DEBUG_APPLY
-#define HB_DEBUG_APPLY (HB_DEBUG+0)
-#endif
-#if HB_DEBUG_APPLY
-#define TRACE_APPLY(this) \
-	hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
-	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 "idx %d gid %u lookup %d", \
-	 c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index)
-#else
-#define TRACE_APPLY(this) hb_no_trace_t<bool> trace
-#endif
-
-#ifndef HB_DEBUG_CLOSURE
-#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
-#endif
-#if HB_DEBUG_CLOSURE
-#define TRACE_CLOSURE(this) \
-	hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
-	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 " ")
-#else
-#define TRACE_CLOSURE(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
-#endif
-
-#ifndef HB_DEBUG_COLLECT_GLYPHS
-#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
-#endif
-#if HB_DEBUG_COLLECT_GLYPHS
-#define TRACE_COLLECT_GLYPHS(this) \
-	hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
-	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 " ")
-#else
-#define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
-#endif
-
-#ifndef HB_DEBUG_SANITIZE
-#define HB_DEBUG_SANITIZE (HB_DEBUG+0)
-#endif
-#if HB_DEBUG_SANITIZE
-#define TRACE_SANITIZE(this) \
-	hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
-	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 " ");
-#else
-#define TRACE_SANITIZE(this) hb_no_trace_t<bool> trace
-#endif
-
-#ifndef HB_DEBUG_SERIALIZE
-#define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
-#endif
-#if HB_DEBUG_SERIALIZE
-#define TRACE_SERIALIZE(this) \
-	hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
-	(&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
-	 " ");
-#else
-#define TRACE_SERIALIZE(this) hb_no_trace_t<bool> trace
-#endif
-
-#ifndef HB_DEBUG_SUBSET
-#define HB_DEBUG_SUBSET (HB_DEBUG+0)
-#endif
-#if HB_DEBUG_SUBSET
-#define TRACE_SUBSET(this) \
-  hb_auto_trace_t<HB_DEBUG_SUBSET, bool> trace \
-  (&c->debug_depth, c->get_name (), this, HB_FUNC, \
-   " ");
-#else
-#define TRACE_SUBSET(this) hb_no_trace_t<bool> trace
-#endif
-
-#ifndef HB_DEBUG_WOULD_APPLY
-#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
-#endif
-#if HB_DEBUG_WOULD_APPLY
-#define TRACE_WOULD_APPLY(this) \
-	hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \
-	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 "%d glyphs", c->len);
-#else
-#define TRACE_WOULD_APPLY(this) hb_no_trace_t<bool> trace
-#endif
-
-#ifndef HB_DEBUG_DISPATCH
-#define HB_DEBUG_DISPATCH ( \
-	HB_DEBUG_APPLY + \
-	HB_DEBUG_CLOSURE + \
-	HB_DEBUG_COLLECT_GLYPHS + \
-	HB_DEBUG_SANITIZE + \
-	HB_DEBUG_SERIALIZE + \
-  HB_DEBUG_SUBSET + \
-	HB_DEBUG_WOULD_APPLY + \
-	0)
-#endif
-#if HB_DEBUG_DISPATCH
-#define TRACE_DISPATCH(this, format) \
-	hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
-	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 "format %d", (int) format);
-#else
-#define TRACE_DISPATCH(this, format) hb_no_trace_t<typename context_t::return_t> trace
-#endif
-
-
-#endif /* HB_DEBUG_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-deprecated.h b/third_party/harfbuzz-ng/src/hb-deprecated.h
deleted file mode 100644
index eac7efb..0000000
--- a/third_party/harfbuzz-ng/src/hb-deprecated.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright © 2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_H_IN
-#error "Include <hb.h> instead."
-#endif
-
-#ifndef HB_DEPRECATED_H
-#define HB_DEPRECATED_H
-
-#include "hb-common.h"
-#include "hb-unicode.h"
-#include "hb-font.h"
-#include "hb-set.h"
-
-HB_BEGIN_DECLS
-
-#ifndef HB_DISABLE_DEPRECATED
-
-#define HB_SCRIPT_CANADIAN_ABORIGINAL		HB_SCRIPT_CANADIAN_SYLLABICS
-
-#define HB_BUFFER_FLAGS_DEFAULT			HB_BUFFER_FLAG_DEFAULT
-#define HB_BUFFER_SERIALIZE_FLAGS_DEFAULT	HB_BUFFER_SERIALIZE_FLAG_DEFAULT
-
-typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
-					       hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-					       hb_codepoint_t *glyph,
-					       void *user_data);
-
-HB_EXTERN void
-hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
-			      hb_font_get_glyph_func_t func,
-			      void *user_data, hb_destroy_func_t destroy);
-
-HB_EXTERN void
-hb_set_invert (hb_set_t *set);
-
-#endif
-
-HB_END_DECLS
-
-#endif /* HB_DEPRECATED_H */
diff --git a/third_party/harfbuzz-ng/src/hb-dsalgs.hh b/third_party/harfbuzz-ng/src/hb-dsalgs.hh
deleted file mode 100644
index e4138475..0000000
--- a/third_party/harfbuzz-ng/src/hb-dsalgs.hh
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_DSALGS_HH
-#define HB_DSALGS_HH
-
-#include "hb-private.hh"
-
-
-static inline void *
-hb_bsearch_r (const void *key, const void *base,
-	      size_t nmemb, size_t size,
-	      int (*compar)(const void *_key, const void *_item, void *_arg),
-	      void *arg)
-{
-  int min = 0, max = (int) nmemb - 1;
-  while (min <= max)
-  {
-    int mid = (min + max) / 2;
-    const void *p = (const void *) (((const char *) base) + (mid * size));
-    int c = compar (key, p, arg);
-    if (c < 0)
-      max = mid - 1;
-    else if (c > 0)
-      min = mid + 1;
-    else
-      return (void *) p;
-  }
-  return NULL;
-}
-
-
-
-/* From https://github.com/noporpoise/sort_r */
-
-/* Isaac Turner 29 April 2014 Public Domain */
-
-/*
-
-hb_sort_r function to be exported.
-
-Parameters:
-  base is the array to be sorted
-  nel is the number of elements in the array
-  width is the size in bytes of each element of the array
-  compar is the comparison function
-  arg is a pointer to be passed to the comparison function
-
-void hb_sort_r(void *base, size_t nel, size_t width,
-               int (*compar)(const void *_a, const void *_b, void *_arg),
-               void *arg);
-*/
-
-
-/* swap a, b iff a>b */
-/* __restrict is same as restrict but better support on old machines */
-static int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w,
-			  int (*compar)(const void *_a, const void *_b,
-					void *_arg),
-			  void *arg)
-{
-  char tmp, *end = a+w;
-  if(compar(a, b, arg) > 0) {
-    for(; a < end; a++, b++) { tmp = *a; *a = *b; *b = tmp; }
-    return 1;
-  }
-  return 0;
-}
-
-/* Note: quicksort is not stable, equivalent values may be swapped */
-static inline void sort_r_simple(void *base, size_t nel, size_t w,
-				 int (*compar)(const void *_a, const void *_b,
-					       void *_arg),
-				 void *arg)
-{
-  char *b = (char *)base, *end = b + nel*w;
-  if(nel < 7) {
-    /* Insertion sort for arbitrarily small inputs */
-    char *pi, *pj;
-    for(pi = b+w; pi < end; pi += w) {
-      for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {}
-    }
-  }
-  else
-  {
-    /* nel > 6; Quicksort */
-
-    /* Use median of first, middle and last items as pivot */
-    char *x, *y, *xend, ch;
-    char *pl, *pr;
-    char *last = b+w*(nel-1), *tmp;
-    char *l[3];
-    l[0] = b;
-    l[1] = b+w*(nel/2);
-    l[2] = last;
-
-    if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
-    if(compar(l[1],l[2],arg) > 0) {
-      tmp=l[1]; l[1]=l[2]; l[2]=tmp; /* swap(l[1],l[2]) */
-      if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
-    }
-
-    /* swap l[id], l[2] to put pivot as last element */
-    for(x = l[1], y = last, xend = x+w; x<xend; x++, y++) {
-      ch = *x; *x = *y; *y = ch;
-    }
-
-    pl = b;
-    pr = last;
-
-    while(pl < pr) {
-      for(; pl < pr; pl += w) {
-        if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
-          pr -= w; /* pivot now at pl */
-          break;
-        }
-      }
-      for(; pl < pr; pr -= w) {
-        if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
-          pl += w; /* pivot now at pr */
-          break;
-        }
-      }
-    }
-
-    sort_r_simple(b, (pl-b)/w, w, compar, arg);
-    sort_r_simple(pl+w, (end-(pl+w))/w, w, compar, arg);
-  }
-}
-
-static inline void hb_sort_r(void *base, size_t nel, size_t width,
-			     int (*compar)(const void *_a, const void *_b, void *_arg),
-			     void *arg)
-{
-    sort_r_simple(base, nel, width, compar, arg);
-}
-
-#endif /* HB_DSALGS_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-face-private.hh b/third_party/harfbuzz-ng/src/hb-face-private.hh
deleted file mode 100644
index 43e7b1c..0000000
--- a/third_party/harfbuzz-ng/src/hb-face-private.hh
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_FACE_PRIVATE_HH
-#define HB_FACE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-object-private.hh"
-#include "hb-shaper-private.hh"
-#include "hb-shape-plan-private.hh"
-
-
-/*
- * hb_face_t
- */
-
-struct hb_face_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t immutable;
-
-  hb_reference_table_func_t  reference_table_func;
-  void                      *user_data;
-  hb_destroy_func_t          destroy;
-
-  unsigned int index;			/* Face index in a collection, zero-based. */
-  mutable unsigned int upem;		/* Units-per-EM. */
-  mutable unsigned int num_glyphs;	/* Number of glyphs. */
-
-  struct hb_shaper_data_t shaper_data;	/* Various shaper data. */
-
-  /* Various non-shaping data. */
-  /* ... */
-
-  /* Cache */
-  struct plan_node_t {
-    hb_shape_plan_t *shape_plan;
-    plan_node_t *next;
-  } *shape_plans;
-
-
-  inline hb_blob_t *reference_table (hb_tag_t tag) const
-  {
-    hb_blob_t *blob;
-
-    if (unlikely (!reference_table_func))
-      return hb_blob_get_empty ();
-
-    blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
-    if (unlikely (!blob))
-      return hb_blob_get_empty ();
-
-    return blob;
-  }
-
-  inline HB_PURE_FUNC unsigned int get_upem (void) const
-  {
-    if (unlikely (!upem))
-      load_upem ();
-    return upem;
-  }
-
-  inline unsigned int get_num_glyphs (void) const
-  {
-    if (unlikely (num_glyphs == (unsigned int) -1))
-      load_num_glyphs ();
-    return num_glyphs;
-  }
-
-  private:
-  HB_INTERNAL void load_upem (void) const;
-  HB_INTERNAL void load_num_glyphs (void) const;
-};
-
-extern HB_INTERNAL const hb_face_t _hb_face_nil;
-
-#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
-
-#endif /* HB_FACE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-face.cc b/third_party/harfbuzz-ng/src/hb-face.cc
deleted file mode 100644
index d8af8c1..0000000
--- a/third_party/harfbuzz-ng/src/hb-face.cc
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-
-#include "hb-face-private.hh"
-#include "hb-open-file-private.hh"
-#include "hb-ot-head-table.hh"
-#include "hb-ot-maxp-table.hh"
-
-
-/*
- * hb_face_t
- */
-
-const hb_face_t _hb_face_nil = {
-  HB_OBJECT_HEADER_STATIC,
-
-  true, /* immutable */
-
-  nullptr, /* reference_table_func */
-  nullptr, /* user_data */
-  nullptr, /* destroy */
-
-  0,    /* index */
-  1000, /* upem */
-  0,    /* num_glyphs */
-
-  {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-  },
-
-  nullptr, /* shape_plans */
-};
-
-
-/**
- * hb_face_create_for_tables:
- * @reference_table_func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data: 
- * @destroy: 
- *
- * 
- *
- * Return value: (transfer full)
- *
- * Since: 0.9.2
- **/
-hb_face_t *
-hb_face_create_for_tables (hb_reference_table_func_t  reference_table_func,
-			   void                      *user_data,
-			   hb_destroy_func_t          destroy)
-{
-  hb_face_t *face;
-
-  if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
-    if (destroy)
-      destroy (user_data);
-    return hb_face_get_empty ();
-  }
-
-  face->reference_table_func = reference_table_func;
-  face->user_data = user_data;
-  face->destroy = destroy;
-
-  face->upem = 0;
-  face->num_glyphs = (unsigned int) -1;
-
-  return face;
-}
-
-
-typedef struct hb_face_for_data_closure_t {
-  hb_blob_t *blob;
-  unsigned int  index;
-} hb_face_for_data_closure_t;
-
-static hb_face_for_data_closure_t *
-_hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
-{
-  hb_face_for_data_closure_t *closure;
-
-  closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t));
-  if (unlikely (!closure))
-    return nullptr;
-
-  closure->blob = blob;
-  closure->index = index;
-
-  return closure;
-}
-
-static void
-_hb_face_for_data_closure_destroy (void *data)
-{
-  hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data;
-
-  hb_blob_destroy (closure->blob);
-  free (closure);
-}
-
-static hb_blob_t *
-_hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
-{
-  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
-
-  if (tag == HB_TAG_NONE)
-    return hb_blob_reference (data->blob);
-
-  const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob);
-  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
-
-  const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
-
-  hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
-
-  return blob;
-}
-
-/**
- * hb_face_create: (Xconstructor)
- * @blob: 
- * @index: 
- *
- * 
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.2
- **/
-hb_face_t *
-hb_face_create (hb_blob_t    *blob,
-		unsigned int  index)
-{
-  hb_face_t *face;
-
-  if (unlikely (!blob))
-    blob = hb_blob_get_empty ();
-
-  hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>().sanitize (hb_blob_reference (blob)), index);
-
-  if (unlikely (!closure))
-    return hb_face_get_empty ();
-
-  face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
-				    closure,
-				    _hb_face_for_data_closure_destroy);
-
-  face->index = index;
-
-  return face;
-}
-
-/**
- * hb_face_get_empty:
- *
- * 
- *
- * Return value: (transfer full)
- *
- * Since: 0.9.2
- **/
-hb_face_t *
-hb_face_get_empty (void)
-{
-  return const_cast<hb_face_t *> (&_hb_face_nil);
-}
-
-
-/**
- * hb_face_reference: (skip)
- * @face: a face.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_face_t *
-hb_face_reference (hb_face_t *face)
-{
-  return hb_object_reference (face);
-}
-
-/**
- * hb_face_destroy: (skip)
- * @face: a face.
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_face_destroy (hb_face_t *face)
-{
-  if (!hb_object_destroy (face)) return;
-
-  for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
-  {
-    hb_face_t::plan_node_t *next = node->next;
-    hb_shape_plan_destroy (node->shape_plan);
-    free (node);
-    node = next;
-  }
-
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-  if (face->destroy)
-    face->destroy (face->user_data);
-
-  free (face);
-}
-
-/**
- * hb_face_set_user_data: (skip)
- * @face: a face.
- * @key: 
- * @data: 
- * @destroy: 
- * @replace: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_face_set_user_data (hb_face_t          *face,
-		       hb_user_data_key_t *key,
-		       void *              data,
-		       hb_destroy_func_t   destroy,
-		       hb_bool_t           replace)
-{
-  return hb_object_set_user_data (face, key, data, destroy, replace);
-}
-
-/**
- * hb_face_get_user_data: (skip)
- * @face: a face.
- * @key: 
- *
- * 
- *
- * Return value: (transfer none):
- *
- * Since: 0.9.2
- **/
-void *
-hb_face_get_user_data (hb_face_t          *face,
-		       hb_user_data_key_t *key)
-{
-  return hb_object_get_user_data (face, key);
-}
-
-/**
- * hb_face_make_immutable:
- * @face: a face.
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_face_make_immutable (hb_face_t *face)
-{
-  if (unlikely (hb_object_is_inert (face)))
-    return;
-
-  face->immutable = true;
-}
-
-/**
- * hb_face_is_immutable:
- * @face: a face.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_face_is_immutable (hb_face_t *face)
-{
-  return face->immutable;
-}
-
-
-/**
- * hb_face_reference_table:
- * @face: a face.
- * @tag: 
- *
- * 
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.2
- **/
-hb_blob_t *
-hb_face_reference_table (hb_face_t *face,
-			 hb_tag_t   tag)
-{
-  return face->reference_table (tag);
-}
-
-/**
- * hb_face_reference_blob:
- * @face: a face.
- *
- * 
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.2
- **/
-hb_blob_t *
-hb_face_reference_blob (hb_face_t *face)
-{
-  return face->reference_table (HB_TAG_NONE);
-}
-
-/**
- * hb_face_set_index:
- * @face: a face.
- * @index: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_face_set_index (hb_face_t    *face,
-		   unsigned int  index)
-{
-  if (face->immutable)
-    return;
-
-  face->index = index;
-}
-
-/**
- * hb_face_get_index:
- * @face: a face.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-unsigned int
-hb_face_get_index (hb_face_t    *face)
-{
-  return face->index;
-}
-
-/**
- * hb_face_set_upem:
- * @face: a face.
- * @upem: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_face_set_upem (hb_face_t    *face,
-		  unsigned int  upem)
-{
-  if (face->immutable)
-    return;
-
-  face->upem = upem;
-}
-
-/**
- * hb_face_get_upem:
- * @face: a face.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-unsigned int
-hb_face_get_upem (hb_face_t *face)
-{
-  return face->get_upem ();
-}
-
-void
-hb_face_t::load_upem (void) const
-{
-  hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (reference_table (HB_OT_TAG_head));
-  const OT::head *head_table = OT::Sanitizer<OT::head>::lock_instance (head_blob);
-  upem = head_table->get_upem ();
-  hb_blob_destroy (head_blob);
-}
-
-/**
- * hb_face_set_glyph_count:
- * @face: a face.
- * @glyph_count: 
- *
- * 
- *
- * Since: 0.9.7
- **/
-void
-hb_face_set_glyph_count (hb_face_t    *face,
-			 unsigned int  glyph_count)
-{
-  if (face->immutable)
-    return;
-
-  face->num_glyphs = glyph_count;
-}
-
-/**
- * hb_face_get_glyph_count:
- * @face: a face.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.7
- **/
-unsigned int
-hb_face_get_glyph_count (hb_face_t *face)
-{
-  return face->get_num_glyphs ();
-}
-
-void
-hb_face_t::load_num_glyphs (void) const
-{
-  hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (reference_table (HB_OT_TAG_maxp));
-  const OT::maxp *maxp_table = OT::Sanitizer<OT::maxp>::lock_instance (maxp_blob);
-  num_glyphs = maxp_table->get_num_glyphs ();
-  hb_blob_destroy (maxp_blob);
-}
-
-/**
- * hb_face_get_table_tags:
- * @face: a face.
- *
- * Retrieves table tags for a face, if possible.
- *
- * Return value: total number of tables, or 0 if not possible to list.
- *
- * Since: 1.6.0
- **/
-unsigned int
-hb_face_get_table_tags (hb_face_t    *face,
-			unsigned int  start_offset,
-			unsigned int *table_count, /* IN/OUT */
-			hb_tag_t     *table_tags /* OUT */)
-{
-  if (face->destroy != _hb_face_for_data_closure_destroy)
-  {
-    if (table_count)
-      *table_count = 0;
-    return 0;
-  }
-
-  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
-
-  const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob);
-  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
-
-  return ot_face.get_table_tags (start_offset, table_count, table_tags);
-}
diff --git a/third_party/harfbuzz-ng/src/hb-face.h b/third_party/harfbuzz-ng/src/hb-face.h
deleted file mode 100644
index 0ce8d046..0000000
--- a/third_party/harfbuzz-ng/src/hb-face.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_H_IN
-#error "Include <hb.h> instead."
-#endif
-
-#ifndef HB_FACE_H
-#define HB_FACE_H
-
-#include "hb-common.h"
-#include "hb-blob.h"
-
-HB_BEGIN_DECLS
-
-
-/*
- * hb_face_t
- */
-
-typedef struct hb_face_t hb_face_t;
-
-HB_EXTERN hb_face_t *
-hb_face_create (hb_blob_t    *blob,
-		unsigned int  index);
-
-typedef hb_blob_t * (*hb_reference_table_func_t)  (hb_face_t *face, hb_tag_t tag, void *user_data);
-
-/* calls destroy() when not needing user_data anymore */
-HB_EXTERN hb_face_t *
-hb_face_create_for_tables (hb_reference_table_func_t  reference_table_func,
-			   void                      *user_data,
-			   hb_destroy_func_t          destroy);
-
-HB_EXTERN hb_face_t *
-hb_face_get_empty (void);
-
-HB_EXTERN hb_face_t *
-hb_face_reference (hb_face_t *face);
-
-HB_EXTERN void
-hb_face_destroy (hb_face_t *face);
-
-HB_EXTERN hb_bool_t
-hb_face_set_user_data (hb_face_t          *face,
-		       hb_user_data_key_t *key,
-		       void *              data,
-		       hb_destroy_func_t   destroy,
-		       hb_bool_t           replace);
-
-HB_EXTERN void *
-hb_face_get_user_data (hb_face_t          *face,
-		       hb_user_data_key_t *key);
-
-HB_EXTERN void
-hb_face_make_immutable (hb_face_t *face);
-
-HB_EXTERN hb_bool_t
-hb_face_is_immutable (hb_face_t *face);
-
-
-HB_EXTERN hb_blob_t *
-hb_face_reference_table (hb_face_t *face,
-			 hb_tag_t   tag);
-
-HB_EXTERN hb_blob_t *
-hb_face_reference_blob (hb_face_t *face);
-
-HB_EXTERN void
-hb_face_set_index (hb_face_t    *face,
-		   unsigned int  index);
-
-HB_EXTERN unsigned int
-hb_face_get_index (hb_face_t    *face);
-
-HB_EXTERN void
-hb_face_set_upem (hb_face_t    *face,
-		  unsigned int  upem);
-
-HB_EXTERN unsigned int
-hb_face_get_upem (hb_face_t *face);
-
-HB_EXTERN void
-hb_face_set_glyph_count (hb_face_t    *face,
-			 unsigned int  glyph_count);
-
-HB_EXTERN unsigned int
-hb_face_get_glyph_count (hb_face_t *face);
-
-HB_EXTERN unsigned int
-hb_face_get_table_tags (hb_face_t    *face,
-			unsigned int  start_offset,
-			unsigned int *table_count, /* IN/OUT */
-			hb_tag_t     *table_tags /* OUT */);
-
-HB_END_DECLS
-
-#endif /* HB_FACE_H */
diff --git a/third_party/harfbuzz-ng/src/hb-font-private.hh b/third_party/harfbuzz-ng/src/hb-font-private.hh
deleted file mode 100644
index 992152f..0000000
--- a/third_party/harfbuzz-ng/src/hb-font-private.hh
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_FONT_PRIVATE_HH
-#define HB_FONT_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-object-private.hh"
-#include "hb-face-private.hh"
-#include "hb-shaper-private.hh"
-
-
-
-/*
- * hb_font_funcs_t
- */
-
-#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
-  HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
-  HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
-  HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
-  HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_name) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
-  /* ^--- Add new callbacks here */
-
-struct hb_font_funcs_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t immutable;
-
-  struct {
-#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
-    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-  } user_data;
-
-  struct {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
-    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-  } destroy;
-
-  /* Don't access these directly.  Call font->get_*() instead. */
-  union get_t {
-    struct get_funcs_t {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
-      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-    } f;
-    void (*array[VAR]) (void);
-  } get;
-};
-
-
-
-/*
- * hb_font_t
- */
-
-struct hb_font_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t immutable;
-
-  hb_font_t *parent;
-  hb_face_t *face;
-
-  int x_scale;
-  int y_scale;
-
-  unsigned int x_ppem;
-  unsigned int y_ppem;
-
-  float ptem;
-
-  /* Font variation coordinates. */
-  unsigned int num_coords;
-  int *coords;
-
-  hb_font_funcs_t   *klass;
-  void              *user_data;
-  hb_destroy_func_t  destroy;
-
-  struct hb_shaper_data_t shaper_data;
-
-
-  /* Convert from font-space to user-space */
-  inline int dir_scale (hb_direction_t direction)
-  { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
-  inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
-  inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
-  inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
-  inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
-  inline float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
-  inline float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
-  inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
-  { return em_scale (v, dir_scale (direction)); }
-
-  /* Convert from parent-font user-space to our user-space */
-  inline hb_position_t parent_scale_x_distance (hb_position_t v) {
-    if (unlikely (parent && parent->x_scale != x_scale))
-      return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
-    return v;
-  }
-  inline hb_position_t parent_scale_y_distance (hb_position_t v) {
-    if (unlikely (parent && parent->y_scale != y_scale))
-      return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
-    return v;
-  }
-  inline hb_position_t parent_scale_x_position (hb_position_t v) {
-    return parent_scale_x_distance (v);
-  }
-  inline hb_position_t parent_scale_y_position (hb_position_t v) {
-    return parent_scale_y_distance (v);
-  }
-
-  inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
-    *x = parent_scale_x_distance (*x);
-    *y = parent_scale_y_distance (*y);
-  }
-  inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
-    *x = parent_scale_x_position (*x);
-    *y = parent_scale_y_position (*y);
-  }
-
-
-  /* Public getters */
-
-  HB_INTERNAL bool has_func (unsigned int i);
-
-  /* has_* ... */
-#define HB_FONT_FUNC_IMPLEMENT(name) \
-  bool \
-  has_##name##_func (void) \
-  { \
-    hb_font_funcs_t *funcs = this->klass; \
-    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
-    return has_func (i); \
-  }
-  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-
-  inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
-  {
-    memset (extents, 0, sizeof (*extents));
-    return klass->get.f.font_h_extents (this, user_data,
-					extents,
-					klass->user_data.font_h_extents);
-  }
-  inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
-  {
-    memset (extents, 0, sizeof (*extents));
-    return klass->get.f.font_v_extents (this, user_data,
-					extents,
-					klass->user_data.font_v_extents);
-  }
-
-  inline bool has_glyph (hb_codepoint_t unicode)
-  {
-    hb_codepoint_t glyph;
-    return get_nominal_glyph (unicode, &glyph);
-  }
-
-  inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
-				      hb_codepoint_t *glyph)
-  {
-    *glyph = 0;
-    return klass->get.f.nominal_glyph (this, user_data,
-				       unicode, glyph,
-				       klass->user_data.nominal_glyph);
-  }
-
-  inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-					hb_codepoint_t *glyph)
-  {
-    *glyph = 0;
-    return klass->get.f.variation_glyph (this, user_data,
-					 unicode, variation_selector, glyph,
-					 klass->user_data.variation_glyph);
-  }
-
-  inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
-  {
-    return klass->get.f.glyph_h_advance (this, user_data,
-					 glyph,
-					 klass->user_data.glyph_h_advance);
-  }
-
-  inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
-  {
-    return klass->get.f.glyph_v_advance (this, user_data,
-					 glyph,
-					 klass->user_data.glyph_v_advance);
-  }
-
-  inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
-				       hb_position_t *x, hb_position_t *y)
-  {
-    *x = *y = 0;
-    return klass->get.f.glyph_h_origin (this, user_data,
-					glyph, x, y,
-					klass->user_data.glyph_h_origin);
-  }
-
-  inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
-				       hb_position_t *x, hb_position_t *y)
-  {
-    *x = *y = 0;
-    return klass->get.f.glyph_v_origin (this, user_data,
-					glyph, x, y,
-					klass->user_data.glyph_v_origin);
-  }
-
-  inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
-  {
-    return klass->get.f.glyph_h_kerning (this, user_data,
-					 left_glyph, right_glyph,
-					 klass->user_data.glyph_h_kerning);
-  }
-
-  inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
-  {
-    return klass->get.f.glyph_v_kerning (this, user_data,
-					 top_glyph, bottom_glyph,
-					 klass->user_data.glyph_v_kerning);
-  }
-
-  inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
-				      hb_glyph_extents_t *extents)
-  {
-    memset (extents, 0, sizeof (*extents));
-    return klass->get.f.glyph_extents (this, user_data,
-				       glyph,
-				       extents,
-				       klass->user_data.glyph_extents);
-  }
-
-  inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
-					    hb_position_t *x, hb_position_t *y)
-  {
-    *x = *y = 0;
-    return klass->get.f.glyph_contour_point (this, user_data,
-					     glyph, point_index,
-					     x, y,
-					     klass->user_data.glyph_contour_point);
-  }
-
-  inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
-				   char *name, unsigned int size)
-  {
-    if (size) *name = '\0';
-    return klass->get.f.glyph_name (this, user_data,
-				    glyph,
-				    name, size,
-				    klass->user_data.glyph_name);
-  }
-
-  inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
-					hb_codepoint_t *glyph)
-  {
-    *glyph = 0;
-    if (len == -1) len = strlen (name);
-    return klass->get.f.glyph_from_name (this, user_data,
-					 name, len,
-					 glyph,
-					 klass->user_data.glyph_from_name);
-  }
-
-
-  /* A bit higher-level, and with fallback */
-
-  inline void get_h_extents_with_fallback (hb_font_extents_t *extents)
-  {
-    if (!get_font_h_extents (extents))
-    {
-      extents->ascender = y_scale * .8;
-      extents->descender = extents->ascender - y_scale;
-      extents->line_gap = 0;
-    }
-  }
-  inline void get_v_extents_with_fallback (hb_font_extents_t *extents)
-  {
-    if (!get_font_v_extents (extents))
-    {
-      extents->ascender = x_scale / 2;
-      extents->descender = extents->ascender - x_scale;
-      extents->line_gap = 0;
-    }
-  }
-
-  inline void get_extents_for_direction (hb_direction_t direction,
-					 hb_font_extents_t *extents)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
-      get_h_extents_with_fallback (extents);
-    else
-      get_v_extents_with_fallback (extents);
-  }
-
-  inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
-					       hb_direction_t direction,
-					       hb_position_t *x, hb_position_t *y)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
-      *x = get_glyph_h_advance (glyph);
-      *y = 0;
-    } else {
-      *x = 0;
-      *y = get_glyph_v_advance (glyph);
-    }
-  }
-
-  inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
-					     hb_position_t *x, hb_position_t *y)
-  {
-    *x = get_glyph_h_advance (glyph) / 2;
-
-    /* TODO cache this somehow?! */
-    hb_font_extents_t extents;
-    get_h_extents_with_fallback (&extents);
-    *y = extents.ascender;
-  }
-
-  inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
-						hb_position_t *x, hb_position_t *y)
-  {
-    if (!get_glyph_h_origin (glyph, x, y) &&
-	 get_glyph_v_origin (glyph, x, y))
-    {
-      hb_position_t dx, dy;
-      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
-      *x -= dx; *y -= dy;
-    }
-  }
-  inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
-						hb_position_t *x, hb_position_t *y)
-  {
-    if (!get_glyph_v_origin (glyph, x, y) &&
-	 get_glyph_h_origin (glyph, x, y))
-    {
-      hb_position_t dx, dy;
-      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
-      *x += dx; *y += dy;
-    }
-  }
-
-  inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
-					      hb_direction_t direction,
-					      hb_position_t *x, hb_position_t *y)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
-      get_glyph_h_origin_with_fallback (glyph, x, y);
-    else
-      get_glyph_v_origin_with_fallback (glyph, x, y);
-  }
-
-  inline void add_glyph_h_origin (hb_codepoint_t glyph,
-				  hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x += origin_x;
-    *y += origin_y;
-  }
-  inline void add_glyph_v_origin (hb_codepoint_t glyph,
-				  hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x += origin_x;
-    *y += origin_y;
-  }
-  inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
-					      hb_direction_t direction,
-					      hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
-
-    *x += origin_x;
-    *y += origin_y;
-  }
-
-  inline void subtract_glyph_h_origin (hb_codepoint_t glyph,
-				       hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x -= origin_x;
-    *y -= origin_y;
-  }
-  inline void subtract_glyph_v_origin (hb_codepoint_t glyph,
-				       hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x -= origin_x;
-    *y -= origin_y;
-  }
-  inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
-						   hb_direction_t direction,
-						   hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
-
-    *x -= origin_x;
-    *y -= origin_y;
-  }
-
-  inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-					       hb_direction_t direction,
-					       hb_position_t *x, hb_position_t *y)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
-      *x = get_glyph_h_kerning (first_glyph, second_glyph);
-      *y = 0;
-    } else {
-      *x = 0;
-      *y = get_glyph_v_kerning (first_glyph, second_glyph);
-    }
-  }
-
-  inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
-						 hb_direction_t direction,
-						 hb_glyph_extents_t *extents)
-  {
-    hb_bool_t ret = get_glyph_extents (glyph, extents);
-
-    if (ret)
-      subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
-
-    return ret;
-  }
-
-  inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
-						       hb_direction_t direction,
-						       hb_position_t *x, hb_position_t *y)
-  {
-    hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
-
-    if (ret)
-      subtract_glyph_origin_for_direction (glyph, direction, x, y);
-
-    return ret;
-  }
-
-  /* Generates gidDDD if glyph has no name. */
-  inline void
-  glyph_to_string (hb_codepoint_t glyph,
-		   char *s, unsigned int size)
-  {
-    if (get_glyph_name (glyph, s, size)) return;
-
-    if (size && snprintf (s, size, "gid%u", glyph) < 0)
-      *s = '\0';
-  }
-
-  /* Parses gidDDD and uniUUUU strings automatically. */
-  inline hb_bool_t
-  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
-		     hb_codepoint_t *glyph)
-  {
-    if (get_glyph_from_name (s, len, glyph)) return true;
-
-    if (len == -1) len = strlen (s);
-
-    /* Straight glyph index. */
-    if (hb_codepoint_parse (s, len, 10, glyph))
-      return true;
-
-    if (len > 3)
-    {
-      /* gidDDD syntax for glyph indices. */
-      if (0 == strncmp (s, "gid", 3) &&
-	  hb_codepoint_parse (s + 3, len - 3, 10, glyph))
-	return true;
-
-      /* uniUUUU and other Unicode character indices. */
-      hb_codepoint_t unichar;
-      if (0 == strncmp (s, "uni", 3) &&
-	  hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
-	  get_nominal_glyph (unichar, glyph))
-	return true;
-    }
-
-    return false;
-  }
-
-  inline hb_position_t em_scale (int16_t v, int scale)
-  {
-    int upem = face->get_upem ();
-    int64_t scaled = v * (int64_t) scale;
-    scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
-    return (hb_position_t) (scaled / upem);
-  }
-  inline hb_position_t em_scalef (float v, int scale)
-  {
-    return (hb_position_t) round (v * scale / face->get_upem ());
-  }
-  inline float em_fscale (int16_t v, int scale)
-  {
-    return (float) v * scale / face->get_upem ();
-  }
-};
-
-#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
-
-#endif /* HB_FONT_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-font.cc b/third_party/harfbuzz-ng/src/hb-font.cc
deleted file mode 100644
index f3534b68..0000000
--- a/third_party/harfbuzz-ng/src/hb-font.cc
+++ /dev/null
@@ -1,1846 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-
-#include "hb-font-private.hh"
-
-
-/*
- * hb_font_funcs_t
- */
-
-static hb_bool_t
-hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED,
-				void *font_data HB_UNUSED,
-				hb_font_extents_t *metrics,
-				void *user_data HB_UNUSED)
-{
-  memset (metrics, 0, sizeof (*metrics));
-  return false;
-}
-static hb_bool_t
-hb_font_get_font_h_extents_parent (hb_font_t *font,
-				   void *font_data HB_UNUSED,
-				   hb_font_extents_t *metrics,
-				   void *user_data HB_UNUSED)
-{
-  hb_bool_t ret = font->parent->get_font_h_extents (metrics);
-  if (ret) {
-    metrics->ascender = font->parent_scale_y_distance (metrics->ascender);
-    metrics->descender = font->parent_scale_y_distance (metrics->descender);
-    metrics->line_gap = font->parent_scale_y_distance (metrics->line_gap);
-  }
-  return ret;
-}
-
-static hb_bool_t
-hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED,
-				void *font_data HB_UNUSED,
-				hb_font_extents_t *metrics,
-				void *user_data HB_UNUSED)
-{
-  memset (metrics, 0, sizeof (*metrics));
-  return false;
-}
-static hb_bool_t
-hb_font_get_font_v_extents_parent (hb_font_t *font,
-				   void *font_data HB_UNUSED,
-				   hb_font_extents_t *metrics,
-				   void *user_data HB_UNUSED)
-{
-  hb_bool_t ret = font->parent->get_font_v_extents (metrics);
-  if (ret) {
-    metrics->ascender = font->parent_scale_x_distance (metrics->ascender);
-    metrics->descender = font->parent_scale_x_distance (metrics->descender);
-    metrics->line_gap = font->parent_scale_x_distance (metrics->line_gap);
-  }
-  return ret;
-}
-
-static hb_bool_t
-hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED,
-			       void *font_data HB_UNUSED,
-			       hb_codepoint_t unicode,
-			       hb_codepoint_t *glyph,
-			       void *user_data HB_UNUSED)
-{
-  *glyph = 0;
-  return false;
-}
-static hb_bool_t
-hb_font_get_nominal_glyph_parent (hb_font_t *font,
-				  void *font_data HB_UNUSED,
-				  hb_codepoint_t unicode,
-				  hb_codepoint_t *glyph,
-				  void *user_data HB_UNUSED)
-{
-  return font->parent->get_nominal_glyph (unicode, glyph);
-}
-
-static hb_bool_t
-hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED,
-				 void *font_data HB_UNUSED,
-				 hb_codepoint_t unicode,
-				 hb_codepoint_t variation_selector,
-				 hb_codepoint_t *glyph,
-				 void *user_data HB_UNUSED)
-{
-  *glyph = 0;
-  return false;
-}
-static hb_bool_t
-hb_font_get_variation_glyph_parent (hb_font_t *font,
-				    void *font_data HB_UNUSED,
-				    hb_codepoint_t unicode,
-				    hb_codepoint_t variation_selector,
-				    hb_codepoint_t *glyph,
-				    void *user_data HB_UNUSED)
-{
-  return font->parent->get_variation_glyph (unicode, variation_selector, glyph);
-}
-
-
-static hb_position_t
-hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
-				 void *font_data HB_UNUSED,
-				 hb_codepoint_t glyph,
-				 void *user_data HB_UNUSED)
-{
-  return font->x_scale;
-}
-static hb_position_t
-hb_font_get_glyph_h_advance_parent (hb_font_t *font,
-				    void *font_data HB_UNUSED,
-				    hb_codepoint_t glyph,
-				    void *user_data HB_UNUSED)
-{
-  return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
-}
-
-static hb_position_t
-hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
-				 void *font_data HB_UNUSED,
-				 hb_codepoint_t glyph,
-				 void *user_data HB_UNUSED)
-{
-  /* TODO use font_extents.ascender+descender */
-  return font->y_scale;
-}
-static hb_position_t
-hb_font_get_glyph_v_advance_parent (hb_font_t *font,
-				    void *font_data HB_UNUSED,
-				    hb_codepoint_t glyph,
-				    void *user_data HB_UNUSED)
-{
-  return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
-}
-
-static hb_bool_t
-hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
-				void *font_data HB_UNUSED,
-				hb_codepoint_t glyph,
-				hb_position_t *x,
-				hb_position_t *y,
-				void *user_data HB_UNUSED)
-{
-  *x = *y = 0;
-  return true;
-}
-static hb_bool_t
-hb_font_get_glyph_h_origin_parent (hb_font_t *font,
-				   void *font_data HB_UNUSED,
-				   hb_codepoint_t glyph,
-				   hb_position_t *x,
-				   hb_position_t *y,
-				   void *user_data HB_UNUSED)
-{
-  hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
-  if (ret)
-    font->parent_scale_position (x, y);
-  return ret;
-}
-
-static hb_bool_t
-hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
-				void *font_data HB_UNUSED,
-				hb_codepoint_t glyph,
-				hb_position_t *x,
-				hb_position_t *y,
-				void *user_data HB_UNUSED)
-{
-  *x = *y = 0;
-  return false;
-}
-static hb_bool_t
-hb_font_get_glyph_v_origin_parent (hb_font_t *font,
-				   void *font_data HB_UNUSED,
-				   hb_codepoint_t glyph,
-				   hb_position_t *x,
-				   hb_position_t *y,
-				   void *user_data HB_UNUSED)
-{
-  hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
-  if (ret)
-    font->parent_scale_position (x, y);
-  return ret;
-}
-
-static hb_position_t
-hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
-				 void *font_data HB_UNUSED,
-				 hb_codepoint_t left_glyph,
-				 hb_codepoint_t right_glyph,
-				 void *user_data HB_UNUSED)
-{
-  return 0;
-}
-static hb_position_t
-hb_font_get_glyph_h_kerning_parent (hb_font_t *font,
-				    void *font_data HB_UNUSED,
-				    hb_codepoint_t left_glyph,
-				    hb_codepoint_t right_glyph,
-				    void *user_data HB_UNUSED)
-{
-  return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
-}
-
-static hb_position_t
-hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
-				 void *font_data HB_UNUSED,
-				 hb_codepoint_t top_glyph,
-				 hb_codepoint_t bottom_glyph,
-				 void *user_data HB_UNUSED)
-{
-  return 0;
-}
-static hb_position_t
-hb_font_get_glyph_v_kerning_parent (hb_font_t *font,
-				    void *font_data HB_UNUSED,
-				    hb_codepoint_t top_glyph,
-				    hb_codepoint_t bottom_glyph,
-				    void *user_data HB_UNUSED)
-{
-  return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
-}
-
-static hb_bool_t
-hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
-			       void *font_data HB_UNUSED,
-			       hb_codepoint_t glyph,
-			       hb_glyph_extents_t *extents,
-			       void *user_data HB_UNUSED)
-{
-  memset (extents, 0, sizeof (*extents));
-  return false;
-}
-static hb_bool_t
-hb_font_get_glyph_extents_parent (hb_font_t *font,
-				  void *font_data HB_UNUSED,
-				  hb_codepoint_t glyph,
-				  hb_glyph_extents_t *extents,
-				  void *user_data HB_UNUSED)
-{
-  hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
-  if (ret) {
-    font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
-    font->parent_scale_distance (&extents->width, &extents->height);
-  }
-  return ret;
-}
-
-static hb_bool_t
-hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
-				     void *font_data HB_UNUSED,
-				     hb_codepoint_t glyph,
-				     unsigned int point_index,
-				     hb_position_t *x,
-				     hb_position_t *y,
-				     void *user_data HB_UNUSED)
-{
-  *x = *y = 0;
-  return false;
-}
-static hb_bool_t
-hb_font_get_glyph_contour_point_parent (hb_font_t *font,
-					void *font_data HB_UNUSED,
-					hb_codepoint_t glyph,
-					unsigned int point_index,
-					hb_position_t *x,
-					hb_position_t *y,
-					void *user_data HB_UNUSED)
-{
-  hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
-  if (ret)
-    font->parent_scale_position (x, y);
-  return ret;
-}
-
-static hb_bool_t
-hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED,
-			    void *font_data HB_UNUSED,
-			    hb_codepoint_t glyph,
-			    char *name, unsigned int size,
-			    void *user_data HB_UNUSED)
-{
-  if (size) *name = '\0';
-  return false;
-}
-static hb_bool_t
-hb_font_get_glyph_name_parent (hb_font_t *font,
-			       void *font_data HB_UNUSED,
-			       hb_codepoint_t glyph,
-			       char *name, unsigned int size,
-			       void *user_data HB_UNUSED)
-{
-  return font->parent->get_glyph_name (glyph, name, size);
-}
-
-static hb_bool_t
-hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED,
-				 void *font_data HB_UNUSED,
-				 const char *name, int len, /* -1 means nul-terminated */
-				 hb_codepoint_t *glyph,
-				 void *user_data HB_UNUSED)
-{
-  *glyph = 0;
-  return false;
-}
-static hb_bool_t
-hb_font_get_glyph_from_name_parent (hb_font_t *font,
-				    void *font_data HB_UNUSED,
-				    const char *name, int len, /* -1 means nul-terminated */
-				    hb_codepoint_t *glyph,
-				    void *user_data HB_UNUSED)
-{
-  return font->parent->get_glyph_from_name (name, len, glyph);
-}
-
-static const hb_font_funcs_t _hb_font_funcs_nil = {
-  HB_OBJECT_HEADER_STATIC,
-
-  true, /* immutable */
-
-  {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
-    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-  },
-  {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
-    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-  },
-  {
-    {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
-      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-    }
-  }
-};
-static const hb_font_funcs_t _hb_font_funcs_parent = {
-  HB_OBJECT_HEADER_STATIC,
-
-  true, /* immutable */
-
-  {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
-    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-  },
-  {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
-    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-  },
-  {
-    {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent,
-      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-    }
-  }
-};
-
-
-/**
- * hb_font_funcs_create: (Xconstructor)
- *
- * 
- *
- * Return value: (transfer full): 
- *
- * Since: 0.9.2
- **/
-hb_font_funcs_t *
-hb_font_funcs_create (void)
-{
-  hb_font_funcs_t *ffuncs;
-
-  if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
-    return hb_font_funcs_get_empty ();
-
-  ffuncs->get = _hb_font_funcs_parent.get;
-
-  return ffuncs;
-}
-
-/**
- * hb_font_funcs_get_empty:
- *
- * 
- *
- * Return value: (transfer full): 
- *
- * Since: 0.9.2
- **/
-hb_font_funcs_t *
-hb_font_funcs_get_empty (void)
-{
-  return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_parent);
-}
-
-/**
- * hb_font_funcs_reference: (skip)
- * @ffuncs: font functions.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_font_funcs_t *
-hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
-{
-  return hb_object_reference (ffuncs);
-}
-
-/**
- * hb_font_funcs_destroy: (skip)
- * @ffuncs: font functions.
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
-{
-  if (!hb_object_destroy (ffuncs)) return;
-
-#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
-  ffuncs->destroy.name (ffuncs->user_data.name);
-  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-
-  free (ffuncs);
-}
-
-/**
- * hb_font_funcs_set_user_data: (skip)
- * @ffuncs: font functions.
- * @key: 
- * @data: 
- * @destroy: 
- * @replace: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
-			     hb_user_data_key_t *key,
-			     void *              data,
-			     hb_destroy_func_t   destroy,
-			     hb_bool_t           replace)
-{
-  return hb_object_set_user_data (ffuncs, key, data, destroy, replace);
-}
-
-/**
- * hb_font_funcs_get_user_data: (skip)
- * @ffuncs: font functions.
- * @key: 
- *
- * 
- *
- * Return value: (transfer none): 
- *
- * Since: 0.9.2
- **/
-void *
-hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
-			     hb_user_data_key_t *key)
-{
-  return hb_object_get_user_data (ffuncs, key);
-}
-
-
-/**
- * hb_font_funcs_make_immutable:
- * @ffuncs: font functions.
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
-{
-  if (unlikely (hb_object_is_inert (ffuncs)))
-    return;
-
-  ffuncs->immutable = true;
-}
-
-/**
- * hb_font_funcs_is_immutable:
- * @ffuncs: font functions.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
-{
-  return ffuncs->immutable;
-}
-
-
-#define HB_FONT_FUNC_IMPLEMENT(name) \
-                                                                         \
-void                                                                     \
-hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
-                                 hb_font_get_##name##_func_t  func,      \
-                                 void                        *user_data, \
-                                 hb_destroy_func_t            destroy)   \
-{                                                                        \
-  if (ffuncs->immutable) {                                               \
-    if (destroy)                                                         \
-      destroy (user_data);                                               \
-    return;                                                              \
-  }                                                                      \
-                                                                         \
-  if (ffuncs->destroy.name)                                              \
-    ffuncs->destroy.name (ffuncs->user_data.name);                       \
-                                                                         \
-  if (func) {                                                            \
-    ffuncs->get.f.name = func;                                           \
-    ffuncs->user_data.name = user_data;                                  \
-    ffuncs->destroy.name = destroy;                                      \
-  } else {                                                               \
-    ffuncs->get.f.name = hb_font_get_##name##_parent;                    \
-    ffuncs->user_data.name = nullptr;                                       \
-    ffuncs->destroy.name = nullptr;                                         \
-  }                                                                      \
-}
-
-HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-
-bool
-hb_font_t::has_func (unsigned int i)
-{
-  if (parent && parent != hb_font_get_empty () && parent->has_func (i))
-    return true;
-  return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i];
-}
-
-/* Public getters */
-
-/**
- * hb_font_get_h_extents:
- * @font: a font.
- * @extents: (out):
- *
- *
- *
- * Return value:
- *
- * Since: 1.1.3
- **/
-hb_bool_t
-hb_font_get_h_extents (hb_font_t *font,
-		       hb_font_extents_t *extents)
-{
-  return font->get_font_h_extents (extents);
-}
-
-/**
- * hb_font_get_v_extents:
- * @font: a font.
- * @extents: (out):
- *
- *
- *
- * Return value:
- *
- * Since: 1.1.3
- **/
-hb_bool_t
-hb_font_get_v_extents (hb_font_t *font,
-		       hb_font_extents_t *extents)
-{
-  return font->get_font_v_extents (extents);
-}
-
-/**
- * hb_font_get_glyph:
- * @font: a font.
- * @unicode: 
- * @variation_selector: 
- * @glyph: (out): 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_get_glyph (hb_font_t *font,
-		   hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-		   hb_codepoint_t *glyph)
-{
-  if (unlikely (variation_selector))
-    return font->get_variation_glyph (unicode, variation_selector, glyph);
-  return font->get_nominal_glyph (unicode, glyph);
-}
-
-/**
- * hb_font_get_nominal_glyph:
- * @font: a font.
- * @unicode: 
- * @glyph: (out): 
- *
- * 
- *
- * Return value: 
- *
- * Since: 1.2.3
- **/
-hb_bool_t
-hb_font_get_nominal_glyph (hb_font_t *font,
-			   hb_codepoint_t unicode,
-			   hb_codepoint_t *glyph)
-{
-  return font->get_nominal_glyph (unicode, glyph);
-}
-
-/**
- * hb_font_get_variation_glyph:
- * @font: a font.
- * @unicode: 
- * @variation_selector: 
- * @glyph: (out): 
- *
- * 
- *
- * Return value: 
- *
- * Since: 1.2.3
- **/
-hb_bool_t
-hb_font_get_variation_glyph (hb_font_t *font,
-			     hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-			     hb_codepoint_t *glyph)
-{
-  return font->get_variation_glyph (unicode, variation_selector, glyph);
-}
-
-/**
- * hb_font_get_glyph_h_advance:
- * @font: a font.
- * @glyph: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_position_t
-hb_font_get_glyph_h_advance (hb_font_t *font,
-			     hb_codepoint_t glyph)
-{
-  return font->get_glyph_h_advance (glyph);
-}
-
-/**
- * hb_font_get_glyph_v_advance:
- * @font: a font.
- * @glyph: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_position_t
-hb_font_get_glyph_v_advance (hb_font_t *font,
-			     hb_codepoint_t glyph)
-{
-  return font->get_glyph_v_advance (glyph);
-}
-
-/**
- * hb_font_get_glyph_h_origin:
- * @font: a font.
- * @glyph: 
- * @x: (out): 
- * @y: (out): 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_get_glyph_h_origin (hb_font_t *font,
-			    hb_codepoint_t glyph,
-			    hb_position_t *x, hb_position_t *y)
-{
-  return font->get_glyph_h_origin (glyph, x, y);
-}
-
-/**
- * hb_font_get_glyph_v_origin:
- * @font: a font.
- * @glyph: 
- * @x: (out): 
- * @y: (out): 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_get_glyph_v_origin (hb_font_t *font,
-			    hb_codepoint_t glyph,
-			    hb_position_t *x, hb_position_t *y)
-{
-  return font->get_glyph_v_origin (glyph, x, y);
-}
-
-/**
- * hb_font_get_glyph_h_kerning:
- * @font: a font.
- * @left_glyph: 
- * @right_glyph: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_position_t
-hb_font_get_glyph_h_kerning (hb_font_t *font,
-			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
-{
-  return font->get_glyph_h_kerning (left_glyph, right_glyph);
-}
-
-/**
- * hb_font_get_glyph_v_kerning:
- * @font: a font.
- * @top_glyph: 
- * @bottom_glyph: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_position_t
-hb_font_get_glyph_v_kerning (hb_font_t *font,
-			     hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
-{
-  return font->get_glyph_v_kerning (top_glyph, bottom_glyph);
-}
-
-/**
- * hb_font_get_glyph_extents:
- * @font: a font.
- * @glyph: 
- * @extents: (out): 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_get_glyph_extents (hb_font_t *font,
-			   hb_codepoint_t glyph,
-			   hb_glyph_extents_t *extents)
-{
-  return font->get_glyph_extents (glyph, extents);
-}
-
-/**
- * hb_font_get_glyph_contour_point:
- * @font: a font.
- * @glyph: 
- * @point_index: 
- * @x: (out): 
- * @y: (out): 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_get_glyph_contour_point (hb_font_t *font,
-				 hb_codepoint_t glyph, unsigned int point_index,
-				 hb_position_t *x, hb_position_t *y)
-{
-  return font->get_glyph_contour_point (glyph, point_index, x, y);
-}
-
-/**
- * hb_font_get_glyph_name:
- * @font: a font.
- * @glyph: 
- * @name: (array length=size): 
- * @size: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_get_glyph_name (hb_font_t *font,
-			hb_codepoint_t glyph,
-			char *name, unsigned int size)
-{
-  return font->get_glyph_name (glyph, name, size);
-}
-
-/**
- * hb_font_get_glyph_from_name:
- * @font: a font.
- * @name: (array length=len): 
- * @len: 
- * @glyph: (out): 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_get_glyph_from_name (hb_font_t *font,
-			     const char *name, int len, /* -1 means nul-terminated */
-			     hb_codepoint_t *glyph)
-{
-  return font->get_glyph_from_name (name, len, glyph);
-}
-
-
-/* A bit higher-level, and with fallback */
-
-/**
- * hb_font_get_extents_for_direction:
- * @font: a font.
- * @direction:
- * @extents:
- *
- *
- *
- * Since: 1.1.3
- **/
-void
-hb_font_get_extents_for_direction (hb_font_t *font,
-				   hb_direction_t direction,
-				   hb_font_extents_t *extents)
-{
-  return font->get_extents_for_direction (direction, extents);
-}
-/**
- * hb_font_get_glyph_advance_for_direction:
- * @font: a font.
- * @glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_get_glyph_advance_for_direction (hb_font_t *font,
-					 hb_codepoint_t glyph,
-					 hb_direction_t direction,
-					 hb_position_t *x, hb_position_t *y)
-{
-  return font->get_glyph_advance_for_direction (glyph, direction, x, y);
-}
-
-/**
- * hb_font_get_glyph_origin_for_direction:
- * @font: a font.
- * @glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_get_glyph_origin_for_direction (hb_font_t *font,
-					hb_codepoint_t glyph,
-					hb_direction_t direction,
-					hb_position_t *x, hb_position_t *y)
-{
-  return font->get_glyph_origin_for_direction (glyph, direction, x, y);
-}
-
-/**
- * hb_font_add_glyph_origin_for_direction:
- * @font: a font.
- * @glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_add_glyph_origin_for_direction (hb_font_t *font,
-					hb_codepoint_t glyph,
-					hb_direction_t direction,
-					hb_position_t *x, hb_position_t *y)
-{
-  return font->add_glyph_origin_for_direction (glyph, direction, x, y);
-}
-
-/**
- * hb_font_subtract_glyph_origin_for_direction:
- * @font: a font.
- * @glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
-					     hb_codepoint_t glyph,
-					     hb_direction_t direction,
-					     hb_position_t *x, hb_position_t *y)
-{
-  return font->subtract_glyph_origin_for_direction (glyph, direction, x, y);
-}
-
-/**
- * hb_font_get_glyph_kerning_for_direction:
- * @font: a font.
- * @first_glyph: 
- * @second_glyph: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
-					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-					 hb_direction_t direction,
-					 hb_position_t *x, hb_position_t *y)
-{
-  return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y);
-}
-
-/**
- * hb_font_get_glyph_extents_for_origin:
- * @font: a font.
- * @glyph: 
- * @direction: 
- * @extents: (out): 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_get_glyph_extents_for_origin (hb_font_t *font,
-				      hb_codepoint_t glyph,
-				      hb_direction_t direction,
-				      hb_glyph_extents_t *extents)
-{
-  return font->get_glyph_extents_for_origin (glyph, direction, extents);
-}
-
-/**
- * hb_font_get_glyph_contour_point_for_origin:
- * @font: a font.
- * @glyph: 
- * @point_index: 
- * @direction: 
- * @x: (out): 
- * @y: (out): 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
-					    hb_codepoint_t glyph, unsigned int point_index,
-					    hb_direction_t direction,
-					    hb_position_t *x, hb_position_t *y)
-{
-  return font->get_glyph_contour_point_for_origin (glyph, point_index, direction, x, y);
-}
-
-/* Generates gidDDD if glyph has no name. */
-/**
- * hb_font_glyph_to_string:
- * @font: a font.
- * @glyph: 
- * @s: (array length=size): 
- * @size: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_glyph_to_string (hb_font_t *font,
-			 hb_codepoint_t glyph,
-			 char *s, unsigned int size)
-{
-  font->glyph_to_string (glyph, s, size);
-}
-
-/* Parses gidDDD and uniUUUU strings automatically. */
-/**
- * hb_font_glyph_from_string:
- * @font: a font.
- * @s: (array length=len) (element-type uint8_t): 
- * @len: 
- * @glyph: (out): 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_glyph_from_string (hb_font_t *font,
-			   const char *s, int len, /* -1 means nul-terminated */
-			   hb_codepoint_t *glyph)
-{
-  return font->glyph_from_string (s, len, glyph);
-}
-
-
-/*
- * hb_font_t
- */
-
-/**
- * hb_font_create: (Xconstructor)
- * @face: a face.
- *
- * 
- *
- * Return value: (transfer full): 
- *
- * Since: 0.9.2
- **/
-hb_font_t *
-hb_font_create (hb_face_t *face)
-{
-  hb_font_t *font;
-
-  if (unlikely (!face))
-    face = hb_face_get_empty ();
-  if (!(font = hb_object_create<hb_font_t> ()))
-    return hb_font_get_empty ();
-
-  hb_face_make_immutable (face);
-  font->parent = hb_font_get_empty ();
-  font->face = hb_face_reference (face);
-  font->klass = hb_font_funcs_get_empty ();
-
-  font->x_scale = font->y_scale = hb_face_get_upem (face);
-
-  return font;
-}
-
-/**
- * hb_font_create_sub_font:
- * @parent: parent font.
- *
- * 
- *
- * Return value: (transfer full): 
- *
- * Since: 0.9.2
- **/
-hb_font_t *
-hb_font_create_sub_font (hb_font_t *parent)
-{
-  if (unlikely (!parent))
-    parent = hb_font_get_empty ();
-
-  hb_font_t *font = hb_font_create (parent->face);
-
-  if (unlikely (hb_object_is_inert (font)))
-    return font;
-
-  font->parent = hb_font_reference (parent);
-
-  font->x_scale = parent->x_scale;
-  font->y_scale = parent->y_scale;
-  font->x_ppem = parent->x_ppem;
-  font->y_ppem = parent->y_ppem;
-  font->ptem = parent->ptem;
-
-  font->num_coords = parent->num_coords;
-  if (!font->num_coords)
-    font->coords = nullptr;
-  else
-  {
-    unsigned int size = parent->num_coords * sizeof (parent->coords[0]);
-    font->coords = (int *) malloc (size);
-    if (unlikely (!font->coords))
-      font->num_coords = 0;
-    else
-      memcpy (font->coords, parent->coords, size);
-  }
-
-  return font;
-}
-
-/**
- * hb_font_get_empty:
- *
- * 
- *
- * Return value: (transfer full)
- *
- * Since: 0.9.2
- **/
-hb_font_t *
-hb_font_get_empty (void)
-{
-  static const hb_font_t _hb_font_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* immutable */
-
-    nullptr, /* parent */
-    const_cast<hb_face_t *> (&_hb_face_nil),
-
-    1000, /* x_scale */
-    1000, /* y_scale */
-
-    0, /* x_ppem */
-    0, /* y_ppem */
-    0, /* ptem */
-
-    0, /* num_coords */
-    nullptr, /* coords */
-
-    const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
-    nullptr, /* user_data */
-    nullptr, /* destroy */
-
-    {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-    }
-  };
-
-  return const_cast<hb_font_t *> (&_hb_font_nil);
-}
-
-/**
- * hb_font_reference: (skip)
- * @font: a font.
- *
- * 
- *
- * Return value: (transfer full): 
- *
- * Since: 0.9.2
- **/
-hb_font_t *
-hb_font_reference (hb_font_t *font)
-{
-  return hb_object_reference (font);
-}
-
-/**
- * hb_font_destroy: (skip)
- * @font: a font.
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_destroy (hb_font_t *font)
-{
-  if (!hb_object_destroy (font)) return;
-
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-  if (font->destroy)
-    font->destroy (font->user_data);
-
-  hb_font_destroy (font->parent);
-  hb_face_destroy (font->face);
-  hb_font_funcs_destroy (font->klass);
-
-  free (font->coords);
-
-  free (font);
-}
-
-/**
- * hb_font_set_user_data: (skip)
- * @font: a font.
- * @key: 
- * @data: 
- * @destroy: 
- * @replace: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_set_user_data (hb_font_t          *font,
-		       hb_user_data_key_t *key,
-		       void *              data,
-		       hb_destroy_func_t   destroy,
-		       hb_bool_t           replace)
-{
-  return hb_object_set_user_data (font, key, data, destroy, replace);
-}
-
-/**
- * hb_font_get_user_data: (skip)
- * @font: a font.
- * @key: 
- *
- * 
- *
- * Return value: (transfer none): 
- *
- * Since: 0.9.2
- **/
-void *
-hb_font_get_user_data (hb_font_t          *font,
-		       hb_user_data_key_t *key)
-{
-  return hb_object_get_user_data (font, key);
-}
-
-/**
- * hb_font_make_immutable:
- * @font: a font.
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_make_immutable (hb_font_t *font)
-{
-  if (unlikely (hb_object_is_inert (font)))
-    return;
-
-  if (font->parent)
-    hb_font_make_immutable (font->parent);
-
-  font->immutable = true;
-}
-
-/**
- * hb_font_is_immutable:
- * @font: a font.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_font_is_immutable (hb_font_t *font)
-{
-  return font->immutable;
-}
-
-/**
- * hb_font_set_parent:
- * @font: a font.
- * @parent: new parent.
- *
- * Sets parent font of @font.
- *
- * Since: 1.0.5
- **/
-void
-hb_font_set_parent (hb_font_t *font,
-		    hb_font_t *parent)
-{
-  if (font->immutable)
-    return;
-
-  if (!parent)
-    parent = hb_font_get_empty ();
-
-  hb_font_t *old = font->parent;
-
-  font->parent = hb_font_reference (parent);
-
-  hb_font_destroy (old);
-}
-
-/**
- * hb_font_get_parent:
- * @font: a font.
- *
- * 
- *
- * Return value: (transfer none): 
- *
- * Since: 0.9.2
- **/
-hb_font_t *
-hb_font_get_parent (hb_font_t *font)
-{
-  return font->parent;
-}
-
-/**
- * hb_font_set_face:
- * @font: a font.
- * @face: new face.
- *
- * Sets font-face of @font.
- *
- * Since: 1.4.3
- **/
-void
-hb_font_set_face (hb_font_t *font,
-		  hb_face_t *face)
-{
-  if (font->immutable)
-    return;
-
-  if (unlikely (!face))
-    face = hb_face_get_empty ();
-
-  hb_face_t *old = font->face;
-
-  font->face = hb_face_reference (face);
-
-  hb_face_destroy (old);
-}
-
-/**
- * hb_font_get_face:
- * @font: a font.
- *
- * 
- *
- * Return value: (transfer none): 
- *
- * Since: 0.9.2
- **/
-hb_face_t *
-hb_font_get_face (hb_font_t *font)
-{
-  return font->face;
-}
-
-
-/**
- * hb_font_set_funcs:
- * @font: a font.
- * @klass: (closure font_data) (destroy destroy) (scope notified):
- * @font_data: 
- * @destroy: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_set_funcs (hb_font_t         *font,
-		   hb_font_funcs_t   *klass,
-		   void              *font_data,
-		   hb_destroy_func_t  destroy)
-{
-  if (font->immutable) {
-    if (destroy)
-      destroy (font_data);
-    return;
-  }
-
-  if (font->destroy)
-    font->destroy (font->user_data);
-
-  if (!klass)
-    klass = hb_font_funcs_get_empty ();
-
-  hb_font_funcs_reference (klass);
-  hb_font_funcs_destroy (font->klass);
-  font->klass = klass;
-  font->user_data = font_data;
-  font->destroy = destroy;
-}
-
-/**
- * hb_font_set_funcs_data:
- * @font: a font.
- * @font_data: (destroy destroy) (scope notified):
- * @destroy: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_set_funcs_data (hb_font_t         *font,
-		        void              *font_data,
-		        hb_destroy_func_t  destroy)
-{
-  /* Destroy user_data? */
-  if (font->immutable) {
-    if (destroy)
-      destroy (font_data);
-    return;
-  }
-
-  if (font->destroy)
-    font->destroy (font->user_data);
-
-  font->user_data = font_data;
-  font->destroy = destroy;
-}
-
-
-/**
- * hb_font_set_scale:
- * @font: a font.
- * @x_scale: 
- * @y_scale: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_set_scale (hb_font_t *font,
-		   int x_scale,
-		   int y_scale)
-{
-  if (font->immutable)
-    return;
-
-  font->x_scale = x_scale;
-  font->y_scale = y_scale;
-}
-
-/**
- * hb_font_get_scale:
- * @font: a font.
- * @x_scale: (out): 
- * @y_scale: (out): 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_get_scale (hb_font_t *font,
-		   int *x_scale,
-		   int *y_scale)
-{
-  if (x_scale) *x_scale = font->x_scale;
-  if (y_scale) *y_scale = font->y_scale;
-}
-
-/**
- * hb_font_set_ppem:
- * @font: a font.
- * @x_ppem: 
- * @y_ppem: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_set_ppem (hb_font_t *font,
-		  unsigned int x_ppem,
-		  unsigned int y_ppem)
-{
-  if (font->immutable)
-    return;
-
-  font->x_ppem = x_ppem;
-  font->y_ppem = y_ppem;
-}
-
-/**
- * hb_font_get_ppem:
- * @font: a font.
- * @x_ppem: (out): 
- * @y_ppem: (out): 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_font_get_ppem (hb_font_t *font,
-		  unsigned int *x_ppem,
-		  unsigned int *y_ppem)
-{
-  if (x_ppem) *x_ppem = font->x_ppem;
-  if (y_ppem) *y_ppem = font->y_ppem;
-}
-
-/**
- * hb_font_set_ptem:
- * @font: a font.
- * @ptem: 
- *
- * Sets "point size" of the font.
- *
- * Since: 1.6.0
- **/
-void
-hb_font_set_ptem (hb_font_t *font, float ptem)
-{
-  if (font->immutable)
-    return;
-
-  font->ptem = ptem;
-}
-
-/**
- * hb_font_get_ptem:
- * @font: a font.
- *
- * Gets the "point size" of the font.  A value of 0 means unset.
- *
- * Return value: Point size.
- *
- * Since: 0.9.2
- **/
-float
-hb_font_get_ptem (hb_font_t *font)
-{
-  return font->ptem;
-}
-
-/*
- * Variations
- */
-
-static void
-_hb_font_adopt_var_coords_normalized (hb_font_t *font,
-				      int *coords, /* 2.14 normalized */
-				      unsigned int coords_length)
-{
-  free (font->coords);
-
-  font->coords = coords;
-  font->num_coords = coords_length;
-}
-
-/**
- * hb_font_set_variations:
- *
- * Since: 1.4.2
- */
-void
-hb_font_set_variations (hb_font_t *font,
-			const hb_variation_t *variations,
-			unsigned int variations_length)
-{
-  if (font->immutable)
-    return;
-
-  if (!variations_length)
-  {
-    hb_font_set_var_coords_normalized (font, nullptr, 0);
-    return;
-  }
-
-  unsigned int coords_length = hb_ot_var_get_axis_count (font->face);
-
-  int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
-  if (unlikely (coords_length && !normalized))
-    return;
-
-  hb_ot_var_normalize_variations (font->face,
-				  variations, variations_length,
-				  normalized, coords_length);
-  _hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
-}
-
-/**
- * hb_font_set_var_coords_design:
- *
- * Since: 1.4.2
- */
-void
-hb_font_set_var_coords_design (hb_font_t *font,
-			       const float *coords,
-			       unsigned int coords_length)
-{
-  if (font->immutable)
-    return;
-
-  int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
-  if (unlikely (coords_length && !normalized))
-    return;
-
-  hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
-  _hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
-}
-
-/**
- * hb_font_set_var_coords_normalized:
- *
- * Since: 1.4.2
- */
-void
-hb_font_set_var_coords_normalized (hb_font_t *font,
-				   const int *coords, /* 2.14 normalized */
-				   unsigned int coords_length)
-{
-  if (font->immutable)
-    return;
-
-  int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr;
-  if (unlikely (coords_length && !copy))
-    return;
-
-  if (coords_length)
-    memcpy (copy, coords, coords_length * sizeof (coords[0]));
-
-  _hb_font_adopt_var_coords_normalized (font, copy, coords_length);
-}
-
-/**
- * hb_font_get_var_coords_normalized:
- *
- * Return value is valid as long as variation coordinates of the font
- * are not modified.
- *
- * Since: 1.4.2
- */
-const int *
-hb_font_get_var_coords_normalized (hb_font_t *font,
-				   unsigned int *length)
-{
-  if (length)
-    *length = font->num_coords;
-
-  return font->coords;
-}
-
-
-#ifndef HB_DISABLE_DEPRECATED
-
-/*
- * Deprecated get_glyph_func():
- */
-
-struct hb_trampoline_closure_t
-{
-  void *user_data;
-  hb_destroy_func_t destroy;
-  unsigned int ref_count;
-};
-
-template <typename FuncType>
-struct hb_trampoline_t
-{
-  hb_trampoline_closure_t closure; /* Must be first. */
-  FuncType func;
-};
-
-template <typename FuncType>
-static hb_trampoline_t<FuncType> *
-trampoline_create (FuncType           func,
-		   void              *user_data,
-		   hb_destroy_func_t  destroy)
-{
-  typedef hb_trampoline_t<FuncType> trampoline_t;
-
-  trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t));
-
-  if (unlikely (!trampoline))
-    return nullptr;
-
-  trampoline->closure.user_data = user_data;
-  trampoline->closure.destroy = destroy;
-  trampoline->closure.ref_count = 1;
-  trampoline->func = func;
-
-  return trampoline;
-}
-
-static void
-trampoline_reference (hb_trampoline_closure_t *closure)
-{
-  closure->ref_count++;
-}
-
-static void
-trampoline_destroy (void *user_data)
-{
-  hb_trampoline_closure_t *closure = (hb_trampoline_closure_t *) user_data;
-
-  if (--closure->ref_count)
-    return;
-
-  if (closure->destroy)
-    closure->destroy (closure->user_data);
-  free (closure);
-}
-
-typedef hb_trampoline_t<hb_font_get_glyph_func_t> hb_font_get_glyph_trampoline_t;
-
-static hb_bool_t
-hb_font_get_nominal_glyph_trampoline (hb_font_t *font,
-				      void *font_data,
-				      hb_codepoint_t unicode,
-				      hb_codepoint_t *glyph,
-				      void *user_data)
-{
-  hb_font_get_glyph_trampoline_t *trampoline = (hb_font_get_glyph_trampoline_t *) user_data;
-  return trampoline->func (font, font_data, unicode, 0, glyph, trampoline->closure.user_data);
-}
-
-static hb_bool_t
-hb_font_get_variation_glyph_trampoline (hb_font_t *font,
-					void *font_data,
-					hb_codepoint_t unicode,
-					hb_codepoint_t variation_selector,
-					hb_codepoint_t *glyph,
-					void *user_data)
-{
-  hb_font_get_glyph_trampoline_t *trampoline = (hb_font_get_glyph_trampoline_t *) user_data;
-  return trampoline->func (font, font_data, unicode, variation_selector, glyph, trampoline->closure.user_data);
-}
-
-/**
- * hb_font_funcs_set_glyph_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * Deprecated.  Use hb_font_funcs_set_nominal_glyph_func() and
- * hb_font_funcs_set_variation_glyph_func() instead.
- *
- * Since: 0.9.2
- * Deprecated: 1.2.3
- **/
-void
-hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
-			      hb_font_get_glyph_func_t func,
-			      void *user_data, hb_destroy_func_t destroy)
-{
-  hb_font_get_glyph_trampoline_t *trampoline;
-
-  trampoline = trampoline_create (func, user_data, destroy);
-  if (unlikely (!trampoline))
-  {
-    if (destroy)
-      destroy (user_data);
-    return;
-  }
-
-  hb_font_funcs_set_nominal_glyph_func (ffuncs,
-					hb_font_get_nominal_glyph_trampoline,
-					trampoline,
-					trampoline_destroy);
-
-  trampoline_reference (&trampoline->closure);
-  hb_font_funcs_set_variation_glyph_func (ffuncs,
-					  hb_font_get_variation_glyph_trampoline,
-					  trampoline,
-					  trampoline_destroy);
-}
-
-#endif /* HB_DISABLE_DEPRECATED */
diff --git a/third_party/harfbuzz-ng/src/hb-font.h b/third_party/harfbuzz-ng/src/hb-font.h
deleted file mode 100644
index c95b61d..0000000
--- a/third_party/harfbuzz-ng/src/hb-font.h
+++ /dev/null
@@ -1,641 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_H_IN
-#error "Include <hb.h> instead."
-#endif
-
-#ifndef HB_FONT_H
-#define HB_FONT_H
-
-#include "hb-common.h"
-#include "hb-face.h"
-
-HB_BEGIN_DECLS
-
-
-typedef struct hb_font_t hb_font_t;
-
-
-/*
- * hb_font_funcs_t
- */
-
-typedef struct hb_font_funcs_t hb_font_funcs_t;
-
-HB_EXTERN hb_font_funcs_t *
-hb_font_funcs_create (void);
-
-HB_EXTERN hb_font_funcs_t *
-hb_font_funcs_get_empty (void);
-
-HB_EXTERN hb_font_funcs_t *
-hb_font_funcs_reference (hb_font_funcs_t *ffuncs);
-
-HB_EXTERN void
-hb_font_funcs_destroy (hb_font_funcs_t *ffuncs);
-
-HB_EXTERN hb_bool_t
-hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
-			     hb_user_data_key_t *key,
-			     void *              data,
-			     hb_destroy_func_t   destroy,
-			     hb_bool_t           replace);
-
-
-HB_EXTERN void *
-hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
-			     hb_user_data_key_t *key);
-
-
-HB_EXTERN void
-hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs);
-
-HB_EXTERN hb_bool_t
-hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs);
-
-
-/* font and glyph extents */
-
-/* Note that typically ascender is positive and descender negative in coordinate systems that grow up. */
-typedef struct hb_font_extents_t
-{
-  hb_position_t ascender; /* typographic ascender. */
-  hb_position_t descender; /* typographic descender. */
-  hb_position_t line_gap; /* suggested line spacing gap. */
-  /*< private >*/
-  hb_position_t reserved9;
-  hb_position_t reserved8;
-  hb_position_t reserved7;
-  hb_position_t reserved6;
-  hb_position_t reserved5;
-  hb_position_t reserved4;
-  hb_position_t reserved3;
-  hb_position_t reserved2;
-  hb_position_t reserved1;
-} hb_font_extents_t;
-
-/* Note that height is negative in coordinate systems that grow up. */
-typedef struct hb_glyph_extents_t
-{
-  hb_position_t x_bearing; /* left side of glyph from origin. */
-  hb_position_t y_bearing; /* top side of glyph from origin. */
-  hb_position_t width; /* distance from left to right side. */
-  hb_position_t height; /* distance from top to bottom side. */
-} hb_glyph_extents_t;
-
-/* func types */
-
-typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data,
-						       hb_font_extents_t *metrics,
-						       void *user_data);
-typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t;
-typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
-
-
-typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *font_data,
-						       hb_codepoint_t unicode,
-						       hb_codepoint_t *glyph,
-						       void *user_data);
-typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *font_data,
-							 hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-							 hb_codepoint_t *glyph,
-							 void *user_data);
-
-
-typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data,
-							   hb_codepoint_t glyph,
-							   void *user_data);
-typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t;
-typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t;
-
-typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
-						      hb_codepoint_t glyph,
-						      hb_position_t *x, hb_position_t *y,
-						      void *user_data);
-typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t;
-typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t;
-
-typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
-							   hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-							   void *user_data);
-typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
-typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
-
-
-typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
-						       hb_codepoint_t glyph,
-						       hb_glyph_extents_t *extents,
-						       void *user_data);
-typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data,
-							     hb_codepoint_t glyph, unsigned int point_index,
-							     hb_position_t *x, hb_position_t *y,
-							     void *user_data);
-
-
-typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_data,
-						    hb_codepoint_t glyph,
-						    char *name, unsigned int size,
-						    void *user_data);
-typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *font_data,
-							 const char *name, int len, /* -1 means nul-terminated */
-							 hb_codepoint_t *glyph,
-							 void *user_data);
-
-
-/* func setters */
-
-/**
- * hb_font_funcs_set_font_h_extents_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- *
- *
- * Since: 1.1.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_font_h_extents_func (hb_font_funcs_t *ffuncs,
-				       hb_font_get_font_h_extents_func_t func,
-				       void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_font_v_extents_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- *
- *
- * Since: 1.1.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t *ffuncs,
-				       hb_font_get_font_v_extents_func_t func,
-				       void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_nominal_glyph_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 1.2.3
- **/
-HB_EXTERN void
-hb_font_funcs_set_nominal_glyph_func (hb_font_funcs_t *ffuncs,
-				      hb_font_get_nominal_glyph_func_t func,
-				      void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_variation_glyph_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 1.2.3
- **/
-HB_EXTERN void
-hb_font_funcs_set_variation_glyph_func (hb_font_funcs_t *ffuncs,
-					hb_font_get_variation_glyph_func_t func,
-					void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_glyph_h_advance_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs,
-					hb_font_get_glyph_h_advance_func_t func,
-					void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_glyph_v_advance_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
-					hb_font_get_glyph_v_advance_func_t func,
-					void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_glyph_h_origin_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs,
-				       hb_font_get_glyph_h_origin_func_t func,
-				       void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_glyph_v_origin_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
-				       hb_font_get_glyph_v_origin_func_t func,
-				       void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_glyph_h_kerning_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
-					hb_font_get_glyph_h_kerning_func_t func,
-					void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_glyph_v_kerning_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
-					hb_font_get_glyph_v_kerning_func_t func,
-					void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_glyph_extents_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
-				      hb_font_get_glyph_extents_func_t func,
-				      void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_glyph_contour_point_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs,
-					    hb_font_get_glyph_contour_point_func_t func,
-					    void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_glyph_name_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs,
-				   hb_font_get_glyph_name_func_t func,
-				   void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_glyph_from_name_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
-					hb_font_get_glyph_from_name_func_t func,
-					void *user_data, hb_destroy_func_t destroy);
-
-/* func dispatch */
-
-HB_EXTERN hb_bool_t
-hb_font_get_h_extents (hb_font_t *font,
-		       hb_font_extents_t *extents);
-HB_EXTERN hb_bool_t
-hb_font_get_v_extents (hb_font_t *font,
-		       hb_font_extents_t *extents);
-
-HB_EXTERN hb_bool_t
-hb_font_get_nominal_glyph (hb_font_t *font,
-			   hb_codepoint_t unicode,
-			   hb_codepoint_t *glyph);
-HB_EXTERN hb_bool_t
-hb_font_get_variation_glyph (hb_font_t *font,
-			     hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-			     hb_codepoint_t *glyph);
-
-HB_EXTERN hb_position_t
-hb_font_get_glyph_h_advance (hb_font_t *font,
-			     hb_codepoint_t glyph);
-HB_EXTERN hb_position_t
-hb_font_get_glyph_v_advance (hb_font_t *font,
-			     hb_codepoint_t glyph);
-
-HB_EXTERN hb_bool_t
-hb_font_get_glyph_h_origin (hb_font_t *font,
-			    hb_codepoint_t glyph,
-			    hb_position_t *x, hb_position_t *y);
-HB_EXTERN hb_bool_t
-hb_font_get_glyph_v_origin (hb_font_t *font,
-			    hb_codepoint_t glyph,
-			    hb_position_t *x, hb_position_t *y);
-
-HB_EXTERN hb_position_t
-hb_font_get_glyph_h_kerning (hb_font_t *font,
-			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
-HB_EXTERN hb_position_t
-hb_font_get_glyph_v_kerning (hb_font_t *font,
-			     hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
-
-HB_EXTERN hb_bool_t
-hb_font_get_glyph_extents (hb_font_t *font,
-			   hb_codepoint_t glyph,
-			   hb_glyph_extents_t *extents);
-
-HB_EXTERN hb_bool_t
-hb_font_get_glyph_contour_point (hb_font_t *font,
-				 hb_codepoint_t glyph, unsigned int point_index,
-				 hb_position_t *x, hb_position_t *y);
-
-HB_EXTERN hb_bool_t
-hb_font_get_glyph_name (hb_font_t *font,
-			hb_codepoint_t glyph,
-			char *name, unsigned int size);
-HB_EXTERN hb_bool_t
-hb_font_get_glyph_from_name (hb_font_t *font,
-			     const char *name, int len, /* -1 means nul-terminated */
-			     hb_codepoint_t *glyph);
-
-
-/* high-level funcs, with fallback */
-
-/* Calls either hb_font_get_nominal_glyph() if variation_selector is 0,
- * otherwise calls hb_font_get_variation_glyph(). */
-HB_EXTERN hb_bool_t
-hb_font_get_glyph (hb_font_t *font,
-		   hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-		   hb_codepoint_t *glyph);
-
-HB_EXTERN void
-hb_font_get_extents_for_direction (hb_font_t *font,
-				   hb_direction_t direction,
-				   hb_font_extents_t *extents);
-HB_EXTERN void
-hb_font_get_glyph_advance_for_direction (hb_font_t *font,
-					 hb_codepoint_t glyph,
-					 hb_direction_t direction,
-					 hb_position_t *x, hb_position_t *y);
-HB_EXTERN void
-hb_font_get_glyph_origin_for_direction (hb_font_t *font,
-					hb_codepoint_t glyph,
-					hb_direction_t direction,
-					hb_position_t *x, hb_position_t *y);
-HB_EXTERN void
-hb_font_add_glyph_origin_for_direction (hb_font_t *font,
-					hb_codepoint_t glyph,
-					hb_direction_t direction,
-					hb_position_t *x, hb_position_t *y);
-HB_EXTERN void
-hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
-					     hb_codepoint_t glyph,
-					     hb_direction_t direction,
-					     hb_position_t *x, hb_position_t *y);
-
-HB_EXTERN void
-hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
-					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-					 hb_direction_t direction,
-					 hb_position_t *x, hb_position_t *y);
-
-HB_EXTERN hb_bool_t
-hb_font_get_glyph_extents_for_origin (hb_font_t *font,
-				      hb_codepoint_t glyph,
-				      hb_direction_t direction,
-				      hb_glyph_extents_t *extents);
-
-HB_EXTERN hb_bool_t
-hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
-					    hb_codepoint_t glyph, unsigned int point_index,
-					    hb_direction_t direction,
-					    hb_position_t *x, hb_position_t *y);
-
-/* Generates gidDDD if glyph has no name. */
-HB_EXTERN void
-hb_font_glyph_to_string (hb_font_t *font,
-			 hb_codepoint_t glyph,
-			 char *s, unsigned int size);
-/* Parses gidDDD and uniUUUU strings automatically. */
-HB_EXTERN hb_bool_t
-hb_font_glyph_from_string (hb_font_t *font,
-			   const char *s, int len, /* -1 means nul-terminated */
-			   hb_codepoint_t *glyph);
-
-
-/*
- * hb_font_t
- */
-
-/* Fonts are very light-weight objects */
-
-HB_EXTERN hb_font_t *
-hb_font_create (hb_face_t *face);
-
-HB_EXTERN hb_font_t *
-hb_font_create_sub_font (hb_font_t *parent);
-
-HB_EXTERN hb_font_t *
-hb_font_get_empty (void);
-
-HB_EXTERN hb_font_t *
-hb_font_reference (hb_font_t *font);
-
-HB_EXTERN void
-hb_font_destroy (hb_font_t *font);
-
-HB_EXTERN hb_bool_t
-hb_font_set_user_data (hb_font_t          *font,
-		       hb_user_data_key_t *key,
-		       void *              data,
-		       hb_destroy_func_t   destroy,
-		       hb_bool_t           replace);
-
-
-HB_EXTERN void *
-hb_font_get_user_data (hb_font_t          *font,
-		       hb_user_data_key_t *key);
-
-HB_EXTERN void
-hb_font_make_immutable (hb_font_t *font);
-
-HB_EXTERN hb_bool_t
-hb_font_is_immutable (hb_font_t *font);
-
-HB_EXTERN void
-hb_font_set_parent (hb_font_t *font,
-		    hb_font_t *parent);
-
-HB_EXTERN hb_font_t *
-hb_font_get_parent (hb_font_t *font);
-
-HB_EXTERN void
-hb_font_set_face (hb_font_t *font,
-		  hb_face_t *face);
-
-HB_EXTERN hb_face_t *
-hb_font_get_face (hb_font_t *font);
-
-
-HB_EXTERN void
-hb_font_set_funcs (hb_font_t         *font,
-		   hb_font_funcs_t   *klass,
-		   void              *font_data,
-		   hb_destroy_func_t  destroy);
-
-/* Be *very* careful with this function! */
-HB_EXTERN void
-hb_font_set_funcs_data (hb_font_t         *font,
-		        void              *font_data,
-		        hb_destroy_func_t  destroy);
-
-
-HB_EXTERN void
-hb_font_set_scale (hb_font_t *font,
-		   int x_scale,
-		   int y_scale);
-
-HB_EXTERN void
-hb_font_get_scale (hb_font_t *font,
-		   int *x_scale,
-		   int *y_scale);
-
-/*
- * A zero value means "no hinting in that direction"
- */
-HB_EXTERN void
-hb_font_set_ppem (hb_font_t *font,
-		  unsigned int x_ppem,
-		  unsigned int y_ppem);
-
-HB_EXTERN void
-hb_font_get_ppem (hb_font_t *font,
-		  unsigned int *x_ppem,
-		  unsigned int *y_ppem);
-
-/*
- * Point size per EM.  Used for optical-sizing in CoreText.
- * A value of zero means "not set".
- */
-HB_EXTERN void
-hb_font_set_ptem (hb_font_t *font, float ptem);
-
-HB_EXTERN float
-hb_font_get_ptem (hb_font_t *font);
-
-HB_EXTERN void
-hb_font_set_variations (hb_font_t *font,
-			const hb_variation_t *variations,
-			unsigned int variations_length);
-
-HB_EXTERN void
-hb_font_set_var_coords_design (hb_font_t *font,
-			       const float *coords,
-			       unsigned int coords_length);
-
-HB_EXTERN void
-hb_font_set_var_coords_normalized (hb_font_t *font,
-				   const int *coords, /* 2.14 normalized */
-				   unsigned int coords_length);
-
-HB_EXTERN const int *
-hb_font_get_var_coords_normalized (hb_font_t *font,
-				   unsigned int *length);
-
-HB_END_DECLS
-
-#endif /* HB_FONT_H */
diff --git a/third_party/harfbuzz-ng/src/hb-ft.cc b/third_party/harfbuzz-ng/src/hb-ft.cc
deleted file mode 100644
index fc4b112..0000000
--- a/third_party/harfbuzz-ng/src/hb-ft.cc
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2009  Keith Stribley
- * Copyright © 2015  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-
-#include "hb-ft.h"
-
-#include "hb-font-private.hh"
-
-#include FT_ADVANCES_H
-#include FT_MULTIPLE_MASTERS_H
-#include FT_TRUETYPE_TABLES_H
-
-
-/* TODO:
- *
- * In general, this file does a fine job of what it's supposed to do.
- * There are, however, things that need more work:
- *
- *   - I remember seeing FT_Get_Advance() without the NO_HINTING flag to be buggy.
- *     Have not investigated.
- *
- *   - FreeType works in 26.6 mode.  Clients can decide to use that mode, and everything
- *     would work fine.  However, we also abuse this API for performing in font-space,
- *     but don't pass the correct flags to FreeType.  We just abuse the no-hinting mode
- *     for that, such that no rounding etc happens.  As such, we don't set ppem, and
- *     pass NO_HINTING as load_flags.  Would be much better to use NO_SCALE, and scale
- *     ourselves, like we do in uniscribe, etc.
- *
- *   - We don't handle / allow for emboldening / obliqueing.
- *
- *   - In the future, we should add constructors to create fonts in font space?
- *
- *   - FT_Load_Glyph() is extremely costly.  Do something about it?
- */
-
-
-struct hb_ft_font_t
-{
-  FT_Face ft_face;
-  int load_flags;
-  bool symbol; /* Whether selected cmap is symbol cmap. */
-  bool unref; /* Whether to destroy ft_face when done. */
-};
-
-static hb_ft_font_t *
-_hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
-{
-  hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t));
-
-  if (unlikely (!ft_font))
-    return nullptr;
-
-  ft_font->ft_face = ft_face;
-  ft_font->symbol = symbol;
-  ft_font->unref = unref;
-
-  ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
-
-  return ft_font;
-}
-
-static void
-_hb_ft_face_destroy (void *data)
-{
-  FT_Done_Face ((FT_Face) data);
-}
-
-static void
-_hb_ft_font_destroy (void *data)
-{
-  hb_ft_font_t *ft_font = (hb_ft_font_t *) data;
-
-  if (ft_font->unref)
-    _hb_ft_face_destroy (ft_font->ft_face);
-
-  free (ft_font);
-}
-
-/**
- * hb_ft_font_set_load_flags:
- * @font:
- * @load_flags:
- *
- * 
- *
- * Since: 1.0.5
- **/
-void
-hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
-{
-  if (font->immutable)
-    return;
-
-  if (font->destroy != _hb_ft_font_destroy)
-    return;
-
-  hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
-
-  ft_font->load_flags = load_flags;
-}
-
-/**
- * hb_ft_font_get_load_flags:
- * @font:
- *
- * 
- *
- * Return value:
- * Since: 1.0.5
- **/
-int
-hb_ft_font_get_load_flags (hb_font_t *font)
-{
-  if (font->destroy != _hb_ft_font_destroy)
-    return 0;
-
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
-
-  return ft_font->load_flags;
-}
-
-FT_Face
-hb_ft_font_get_face (hb_font_t *font)
-{
-  if (font->destroy != _hb_ft_font_destroy)
-    return nullptr;
-
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
-
-  return ft_font->ft_face;
-}
-
-
-
-static hb_bool_t
-hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
-			 void *font_data,
-			 hb_codepoint_t unicode,
-			 hb_codepoint_t *glyph,
-			 void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode);
-
-  if (unlikely (!g))
-  {
-    if (unlikely (ft_font->symbol) && unicode <= 0x00FFu)
-    {
-      /* For symbol-encoded OpenType fonts, we duplicate the
-       * U+F000..F0FF range at U+0000..U+00FF.  That's what
-       * Windows seems to do, and that's hinted about at:
-       * http://www.microsoft.com/typography/otspec/recom.htm
-       * under "Non-Standard (Symbol) Fonts". */
-      g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode);
-      if (!g)
-	return false;
-    }
-    else
-      return false;
-  }
-
-  *glyph = g;
-  return true;
-}
-
-static hb_bool_t
-hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
-			   void *font_data,
-			   hb_codepoint_t unicode,
-			   hb_codepoint_t variation_selector,
-			   hb_codepoint_t *glyph,
-			   void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
-
-  if (unlikely (!g))
-    return false;
-
-  *glyph = g;
-  return true;
-}
-
-static hb_position_t
-hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
-			   void *font_data,
-			   hb_codepoint_t glyph,
-			   void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Fixed v;
-
-  if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags, &v)))
-    return 0;
-
-  if (font->x_scale < 0)
-    v = -v;
-
-  return (v + (1<<9)) >> 10;
-}
-
-static hb_position_t
-hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
-			   void *font_data,
-			   hb_codepoint_t glyph,
-			   void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Fixed v;
-
-  if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
-    return 0;
-
-  if (font->y_scale < 0)
-    v = -v;
-
-  /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
-   * have a Y growing upward.  Hence the extra negation. */
-  return (-v + (1<<9)) >> 10;
-}
-
-static hb_bool_t
-hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
-			  void *font_data,
-			  hb_codepoint_t glyph,
-			  hb_position_t *x,
-			  hb_position_t *y,
-			  void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Face ft_face = ft_font->ft_face;
-
-  if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
-    return false;
-
-  /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
-   * have a Y growing upward.  Hence the extra negation. */
-  *x = ft_face->glyph->metrics.horiBearingX -   ft_face->glyph->metrics.vertBearingX;
-  *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY);
-
-  if (font->x_scale < 0)
-    *x = -*x;
-  if (font->y_scale < 0)
-    *y = -*y;
-
-  return true;
-}
-
-static hb_position_t
-hb_ft_get_glyph_h_kerning (hb_font_t *font,
-			   void *font_data,
-			   hb_codepoint_t left_glyph,
-			   hb_codepoint_t right_glyph,
-			   void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Vector kerningv;
-
-  FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
-  if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv))
-    return 0;
-
-  return kerningv.x;
-}
-
-static hb_bool_t
-hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
-			 void *font_data,
-			 hb_codepoint_t glyph,
-			 hb_glyph_extents_t *extents,
-			 void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Face ft_face = ft_font->ft_face;
-
-  if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
-    return false;
-
-  extents->x_bearing = ft_face->glyph->metrics.horiBearingX;
-  extents->y_bearing = ft_face->glyph->metrics.horiBearingY;
-  extents->width = ft_face->glyph->metrics.width;
-  extents->height = -ft_face->glyph->metrics.height;
-  if (font->x_scale < 0)
-  {
-    extents->x_bearing = -extents->x_bearing;
-    extents->width = -extents->width;
-  }
-  if (font->y_scale < 0)
-  {
-    extents->y_bearing = -extents->y_bearing;
-    extents->height = -extents->height;
-  }
-  return true;
-}
-
-static hb_bool_t
-hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
-			       void *font_data,
-			       hb_codepoint_t glyph,
-			       unsigned int point_index,
-			       hb_position_t *x,
-			       hb_position_t *y,
-			       void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Face ft_face = ft_font->ft_face;
-
-  if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
-      return false;
-
-  if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE))
-      return false;
-
-  if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points))
-      return false;
-
-  *x = ft_face->glyph->outline.points[point_index].x;
-  *y = ft_face->glyph->outline.points[point_index].y;
-
-  return true;
-}
-
-static hb_bool_t
-hb_ft_get_glyph_name (hb_font_t *font HB_UNUSED,
-		      void *font_data,
-		      hb_codepoint_t glyph,
-		      char *name, unsigned int size,
-		      void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-
-  hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size);
-  if (ret && (size && !*name))
-    ret = false;
-
-  return ret;
-}
-
-static hb_bool_t
-hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED,
-			   void *font_data,
-			   const char *name, int len, /* -1 means nul-terminated */
-			   hb_codepoint_t *glyph,
-			   void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Face ft_face = ft_font->ft_face;
-
-  if (len < 0)
-    *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name);
-  else {
-    /* Make a nul-terminated version. */
-    char buf[128];
-    len = MIN (len, (int) sizeof (buf) - 1);
-    strncpy (buf, name, len);
-    buf[len] = '\0';
-    *glyph = FT_Get_Name_Index (ft_face, buf);
-  }
-
-  if (*glyph == 0)
-  {
-    /* Check whether the given name was actually the name of glyph 0. */
-    char buf[128];
-    if (!FT_Get_Glyph_Name(ft_face, 0, buf, sizeof (buf)) &&
-        len < 0 ? !strcmp (buf, name) : !strncmp (buf, name, len))
-      return true;
-  }
-
-  return *glyph != 0;
-}
-
-static hb_bool_t
-hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
-			  void *font_data,
-			  hb_font_extents_t *metrics,
-			  void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Face ft_face = ft_font->ft_face;
-  metrics->ascender = ft_face->size->metrics.ascender;
-  metrics->descender = ft_face->size->metrics.descender;
-  metrics->line_gap = ft_face->size->metrics.height - (ft_face->size->metrics.ascender - ft_face->size->metrics.descender);
-  if (font->y_scale < 0)
-  {
-    metrics->ascender = -metrics->ascender;
-    metrics->descender = -metrics->descender;
-    metrics->line_gap = -metrics->line_gap;
-  }
-  return true;
-}
-
-static hb_font_funcs_t *static_ft_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_ft_funcs (void)
-{
-  hb_font_funcs_destroy (static_ft_funcs);
-}
-#endif
-
-static void
-_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
-{
-retry:
-  hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
-
-  if (unlikely (!funcs))
-  {
-    funcs = hb_font_funcs_create ();
-
-    hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
-    //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
-    hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
-    hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, nullptr, nullptr);
-    hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
-    hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr);
-    hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr);
-    hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr);
-    hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
-    hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
-
-    hb_font_funcs_make_immutable (funcs);
-
-    if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, nullptr, funcs)) {
-      hb_font_funcs_destroy (funcs);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_ft_funcs); /* First person registers atexit() callback. */
-#endif
-  };
-
-  bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
-
-  hb_font_set_funcs (font,
-		     funcs,
-		     _hb_ft_font_create (ft_face, symbol, unref),
-		     _hb_ft_font_destroy);
-}
-
-
-static hb_blob_t *
-reference_table  (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
-{
-  FT_Face ft_face = (FT_Face) user_data;
-  FT_Byte *buffer;
-  FT_ULong  length = 0;
-  FT_Error error;
-
-  /* Note: FreeType like HarfBuzz uses the NONE tag for fetching the entire blob */
-
-  error = FT_Load_Sfnt_Table (ft_face, tag, 0, nullptr, &length);
-  if (error)
-    return nullptr;
-
-  buffer = (FT_Byte *) malloc (length);
-  if (!buffer)
-    return nullptr;
-
-  error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
-  if (error)
-    return nullptr;
-
-  return hb_blob_create ((const char *) buffer, length,
-			 HB_MEMORY_MODE_WRITABLE,
-			 buffer, free);
-}
-
-/**
- * hb_ft_face_create:
- * @ft_face: (destroy destroy) (scope notified): 
- * @destroy:
- *
- * 
- *
- * Return value: (transfer full): 
- * Since: 0.9.2
- **/
-hb_face_t *
-hb_ft_face_create (FT_Face           ft_face,
-		   hb_destroy_func_t destroy)
-{
-  hb_face_t *face;
-
-  if (!ft_face->stream->read) {
-    hb_blob_t *blob;
-
-    blob = hb_blob_create ((const char *) ft_face->stream->base,
-			   (unsigned int) ft_face->stream->size,
-			   HB_MEMORY_MODE_READONLY,
-			   ft_face, destroy);
-    face = hb_face_create (blob, ft_face->face_index);
-    hb_blob_destroy (blob);
-  } else {
-    face = hb_face_create_for_tables (reference_table, ft_face, destroy);
-  }
-
-  hb_face_set_index (face, ft_face->face_index);
-  hb_face_set_upem (face, ft_face->units_per_EM);
-
-  return face;
-}
-
-/**
- * hb_ft_face_create_referenced:
- * @ft_face:
- *
- * 
- *
- * Return value: (transfer full): 
- * Since: 0.9.38
- **/
-hb_face_t *
-hb_ft_face_create_referenced (FT_Face ft_face)
-{
-  FT_Reference_Face (ft_face);
-  return hb_ft_face_create (ft_face, _hb_ft_face_destroy);
-}
-
-static void
-hb_ft_face_finalize (FT_Face ft_face)
-{
-  hb_face_destroy ((hb_face_t *) ft_face->generic.data);
-}
-
-/**
- * hb_ft_face_create_cached:
- * @ft_face: 
- *
- * 
- *
- * Return value: (transfer full): 
- * Since: 0.9.2
- **/
-hb_face_t *
-hb_ft_face_create_cached (FT_Face ft_face)
-{
-  if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != (FT_Generic_Finalizer) hb_ft_face_finalize))
-  {
-    if (ft_face->generic.finalizer)
-      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;
-  }
-
-  return hb_face_reference ((hb_face_t *) ft_face->generic.data);
-}
-
-
-/**
- * hb_ft_font_create:
- * @ft_face: (destroy destroy) (scope notified): 
- * @destroy:
- *
- * 
- *
- * Return value: (transfer full): 
- * Since: 0.9.2
- **/
-hb_font_t *
-hb_ft_font_create (FT_Face           ft_face,
-		   hb_destroy_func_t destroy)
-{
-  hb_font_t *font;
-  hb_face_t *face;
-
-  face = hb_ft_face_create (ft_face, destroy);
-  font = hb_font_create (face);
-  hb_face_destroy (face);
-  _hb_ft_font_set_funcs (font, ft_face, false);
-  hb_ft_font_changed (font);
-  return font;
-}
-
-void
-hb_ft_font_changed (hb_font_t *font)
-{
-  if (font->destroy != _hb_ft_font_destroy)
-    return;
-
-  hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
-  FT_Face ft_face = ft_font->ft_face;
-
-  hb_font_set_scale (font,
-		     (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16),
-		     (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16));
-#if 0 /* hb-ft works in no-hinting model */
-  hb_font_set_ppem (font,
-		    ft_face->size->metrics.x_ppem,
-		    ft_face->size->metrics.y_ppem);
-#endif
-
-#ifdef HAVE_FT_GET_VAR_BLEND_COORDINATES
-  FT_MM_Var *mm_var = nullptr;
-  if (!FT_Get_MM_Var (ft_face, &mm_var))
-  {
-    FT_Fixed *ft_coords = (FT_Fixed *) calloc (mm_var->num_axis, sizeof (FT_Fixed));
-    int *coords = (int *) calloc (mm_var->num_axis, sizeof (int));
-    if (coords && ft_coords)
-    {
-      if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, ft_coords))
-      {
-	bool nonzero = false;
-
-	for (unsigned int i = 0; i < mm_var->num_axis; ++i)
-	 {
-	  coords[i] = ft_coords[i] >>= 2;
-	  nonzero = nonzero || coords[i];
-	 }
-
-	if (nonzero)
-	  hb_font_set_var_coords_normalized (font, coords, mm_var->num_axis);
-	else
-	  hb_font_set_var_coords_normalized (font, nullptr, 0);
-      }
-    }
-    free (coords);
-    free (ft_coords);
-#ifdef HAVE_FT_DONE_MM_VAR
-    FT_Done_MM_Var (ft_face->glyph->library, mm_var);
-#else
-    free (mm_var);
-#endif
-  }
-#endif
-}
-
-/**
- * hb_ft_font_create_referenced:
- * @ft_face:
- *
- * 
- *
- * Return value: (transfer full): 
- * Since: 0.9.38
- **/
-hb_font_t *
-hb_ft_font_create_referenced (FT_Face ft_face)
-{
-  FT_Reference_Face (ft_face);
-  return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
-}
-
-
-/* Thread-safe, lock-free, FT_Library */
-
-static FT_Library ft_library;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_ft_library (void)
-{
-  FT_Done_FreeType (ft_library);
-}
-#endif
-
-static FT_Library
-get_ft_library (void)
-{
-retry:
-  FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library);
-
-  if (unlikely (!library))
-  {
-    /* Not found; allocate one. */
-    if (FT_Init_FreeType (&library))
-      return nullptr;
-
-    if (!hb_atomic_ptr_cmpexch (&ft_library, nullptr, library)) {
-      FT_Done_FreeType (library);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_ft_library); /* First person registers atexit() callback. */
-#endif
-  }
-
-  return library;
-}
-
-static void
-_release_blob (FT_Face ft_face)
-{
-  hb_blob_destroy ((hb_blob_t *) ft_face->generic.data);
-}
-
-void
-hb_ft_font_set_funcs (hb_font_t *font)
-{
-  hb_blob_t *blob = hb_face_reference_blob (font->face);
-  unsigned int blob_length;
-  const char *blob_data = hb_blob_get_data (blob, &blob_length);
-  if (unlikely (!blob_length))
-    DEBUG_MSG (FT, font, "Font face has empty blob");
-
-  FT_Face ft_face = nullptr;
-  FT_Error err = FT_New_Memory_Face (get_ft_library (),
-				     (const FT_Byte *) blob_data,
-				     blob_length,
-				     hb_face_get_index (font->face),
-				     &ft_face);
-
-  if (unlikely (err)) {
-    hb_blob_destroy (blob);
-    DEBUG_MSG (FT, font, "Font face FT_New_Memory_Face() failed");
-    return;
-  }
-
-  if (FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE))
-    FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL);
-
-  FT_Set_Char_Size (ft_face,
-		    abs (font->x_scale), abs (font->y_scale),
-		    0, 0);
-#if 0
-		    font->x_ppem * 72 * 64 / font->x_scale,
-		    font->y_ppem * 72 * 64 / font->y_scale);
-#endif
-  if (font->x_scale < 0 || font->y_scale < 0)
-  {
-    FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
-			  0, font->y_scale < 0 ? -1 : +1};
-    FT_Set_Transform (ft_face, &matrix, nullptr);
-  }
-
-#ifdef HAVE_FT_SET_VAR_BLEND_COORDINATES
-  unsigned int num_coords;
-  const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
-  if (num_coords)
-  {
-    FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed));
-    if (ft_coords)
-    {
-      for (unsigned int i = 0; i < num_coords; i++)
-	ft_coords[i] = coords[i] << 2;
-      FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
-      free (ft_coords);
-    }
-  }
-#endif
-
-  ft_face->generic.data = blob;
-  ft_face->generic.finalizer = (FT_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/third_party/harfbuzz-ng/src/hb-ft.h b/third_party/harfbuzz-ng/src/hb-ft.h
deleted file mode 100644
index 94013ee..0000000
--- a/third_party/harfbuzz-ng/src/hb-ft.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2015  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_FT_H
-#define HB_FT_H
-
-#include "hb.h"
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-HB_BEGIN_DECLS
-
-/*
- * Note: FreeType is not thread-safe.
- * Hence, these functions are not either.
- */
-
-/*
- * hb-face from ft-face.
- */
-
-/* This one creates a new hb-face for given ft-face.
- * When the returned hb-face is destroyed, the destroy
- * callback is called (if not NULL), with the ft-face passed
- * to it.
- *
- * The client is responsible to make sure that ft-face is
- * destroyed after hb-face is destroyed.
- *
- * Most often you don't want this function.  You should use either
- * hb_ft_face_create_cached(), or hb_ft_face_create_referenced().
- * In particular, if you are going to pass NULL as destroy, you
- * probably should use (the more recent) hb_ft_face_create_referenced()
- * instead.
- */
-HB_EXTERN hb_face_t *
-hb_ft_face_create (FT_Face           ft_face,
-		   hb_destroy_func_t destroy);
-
-/* This version is like hb_ft_face_create(), except that it caches
- * the hb-face using the generic pointer of the ft-face.  This means
- * that subsequent calls to this function with the same ft-face will
- * return the same hb-face (correctly referenced).
- *
- * Client is still responsible for making sure that ft-face is destroyed
- * after hb-face is.
- */
-HB_EXTERN hb_face_t *
-hb_ft_face_create_cached (FT_Face ft_face);
-
-/* This version is like hb_ft_face_create(), except that it calls
- * FT_Reference_Face() on ft-face, as such keeping ft-face alive
- * as long as the hb-face is.
- *
- * This is the most convenient version to use.  Use it unless you have
- * very good reasons not to.
- */
-HB_EXTERN hb_face_t *
-hb_ft_face_create_referenced (FT_Face ft_face);
-
-
-/*
- * hb-font from ft-face.
- */
-
-/*
- * Note:
- *
- * Set face size on ft-face before creating hb-font from it.
- * Otherwise hb-ft would NOT pick up the font size correctly.
- */
-
-/* See notes on hb_ft_face_create().  Same issues re lifecycle-management
- * apply here.  Use hb_ft_font_create_referenced() if you can. */
-HB_EXTERN hb_font_t *
-hb_ft_font_create (FT_Face           ft_face,
-		   hb_destroy_func_t destroy);
-
-/* See notes on hb_ft_face_create_referenced() re lifecycle-management
- * issues. */
-HB_EXTERN hb_font_t *
-hb_ft_font_create_referenced (FT_Face ft_face);
-
-HB_EXTERN FT_Face
-hb_ft_font_get_face (hb_font_t *font);
-
-HB_EXTERN void
-hb_ft_font_set_load_flags (hb_font_t *font, int load_flags);
-
-HB_EXTERN int
-hb_ft_font_get_load_flags (hb_font_t *font);
-
-/* Call when size or variations settings on underlying FT_Face change. */
-HB_EXTERN void
-hb_ft_font_changed (hb_font_t *font);
-
-/* Makes an hb_font_t use FreeType internally to implement font functions.
- * Note: this internally creates an FT_Face.  Use it when you create your
- * hb_face_t using hb_face_create(). */
-HB_EXTERN void
-hb_ft_font_set_funcs (hb_font_t *font);
-
-
-HB_END_DECLS
-
-#endif /* HB_FT_H */
diff --git a/third_party/harfbuzz-ng/src/hb-glib.cc b/third_party/harfbuzz-ng/src/hb-glib.cc
deleted file mode 100644
index 50c30e9c..0000000
--- a/third_party/harfbuzz-ng/src/hb-glib.cc
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-
-#include "hb-glib.h"
-
-#include "hb-unicode-private.hh"
-
-
-#if !GLIB_CHECK_VERSION(2,29,14)
-static const hb_script_t
-glib_script_to_script[] =
-{
-  HB_SCRIPT_COMMON,
-  HB_SCRIPT_INHERITED,
-  HB_SCRIPT_ARABIC,
-  HB_SCRIPT_ARMENIAN,
-  HB_SCRIPT_BENGALI,
-  HB_SCRIPT_BOPOMOFO,
-  HB_SCRIPT_CHEROKEE,
-  HB_SCRIPT_COPTIC,
-  HB_SCRIPT_CYRILLIC,
-  HB_SCRIPT_DESERET,
-  HB_SCRIPT_DEVANAGARI,
-  HB_SCRIPT_ETHIOPIC,
-  HB_SCRIPT_GEORGIAN,
-  HB_SCRIPT_GOTHIC,
-  HB_SCRIPT_GREEK,
-  HB_SCRIPT_GUJARATI,
-  HB_SCRIPT_GURMUKHI,
-  HB_SCRIPT_HAN,
-  HB_SCRIPT_HANGUL,
-  HB_SCRIPT_HEBREW,
-  HB_SCRIPT_HIRAGANA,
-  HB_SCRIPT_KANNADA,
-  HB_SCRIPT_KATAKANA,
-  HB_SCRIPT_KHMER,
-  HB_SCRIPT_LAO,
-  HB_SCRIPT_LATIN,
-  HB_SCRIPT_MALAYALAM,
-  HB_SCRIPT_MONGOLIAN,
-  HB_SCRIPT_MYANMAR,
-  HB_SCRIPT_OGHAM,
-  HB_SCRIPT_OLD_ITALIC,
-  HB_SCRIPT_ORIYA,
-  HB_SCRIPT_RUNIC,
-  HB_SCRIPT_SINHALA,
-  HB_SCRIPT_SYRIAC,
-  HB_SCRIPT_TAMIL,
-  HB_SCRIPT_TELUGU,
-  HB_SCRIPT_THAANA,
-  HB_SCRIPT_THAI,
-  HB_SCRIPT_TIBETAN,
-  HB_SCRIPT_CANADIAN_SYLLABICS,
-  HB_SCRIPT_YI,
-  HB_SCRIPT_TAGALOG,
-  HB_SCRIPT_HANUNOO,
-  HB_SCRIPT_BUHID,
-  HB_SCRIPT_TAGBANWA,
-
-  /* Unicode-4.0 additions */
-  HB_SCRIPT_BRAILLE,
-  HB_SCRIPT_CYPRIOT,
-  HB_SCRIPT_LIMBU,
-  HB_SCRIPT_OSMANYA,
-  HB_SCRIPT_SHAVIAN,
-  HB_SCRIPT_LINEAR_B,
-  HB_SCRIPT_TAI_LE,
-  HB_SCRIPT_UGARITIC,
-
-  /* Unicode-4.1 additions */
-  HB_SCRIPT_NEW_TAI_LUE,
-  HB_SCRIPT_BUGINESE,
-  HB_SCRIPT_GLAGOLITIC,
-  HB_SCRIPT_TIFINAGH,
-  HB_SCRIPT_SYLOTI_NAGRI,
-  HB_SCRIPT_OLD_PERSIAN,
-  HB_SCRIPT_KHAROSHTHI,
-
-  /* Unicode-5.0 additions */
-  HB_SCRIPT_UNKNOWN,
-  HB_SCRIPT_BALINESE,
-  HB_SCRIPT_CUNEIFORM,
-  HB_SCRIPT_PHOENICIAN,
-  HB_SCRIPT_PHAGS_PA,
-  HB_SCRIPT_NKO,
-
-  /* Unicode-5.1 additions */
-  HB_SCRIPT_KAYAH_LI,
-  HB_SCRIPT_LEPCHA,
-  HB_SCRIPT_REJANG,
-  HB_SCRIPT_SUNDANESE,
-  HB_SCRIPT_SAURASHTRA,
-  HB_SCRIPT_CHAM,
-  HB_SCRIPT_OL_CHIKI,
-  HB_SCRIPT_VAI,
-  HB_SCRIPT_CARIAN,
-  HB_SCRIPT_LYCIAN,
-  HB_SCRIPT_LYDIAN,
-
-  /* Unicode-5.2 additions */
-  HB_SCRIPT_AVESTAN,
-  HB_SCRIPT_BAMUM,
-  HB_SCRIPT_EGYPTIAN_HIEROGLYPHS,
-  HB_SCRIPT_IMPERIAL_ARAMAIC,
-  HB_SCRIPT_INSCRIPTIONAL_PAHLAVI,
-  HB_SCRIPT_INSCRIPTIONAL_PARTHIAN,
-  HB_SCRIPT_JAVANESE,
-  HB_SCRIPT_KAITHI,
-  HB_SCRIPT_TAI_THAM,
-  HB_SCRIPT_LISU,
-  HB_SCRIPT_MEETEI_MAYEK,
-  HB_SCRIPT_OLD_SOUTH_ARABIAN,
-  HB_SCRIPT_OLD_TURKIC,
-  HB_SCRIPT_SAMARITAN,
-  HB_SCRIPT_TAI_VIET,
-
-  /* Unicode-6.0 additions */
-  HB_SCRIPT_BATAK,
-  HB_SCRIPT_BRAHMI,
-  HB_SCRIPT_MANDAIC,
-
-  /* Unicode-6.1 additions */
-  HB_SCRIPT_CHAKMA,
-  HB_SCRIPT_MEROITIC_CURSIVE,
-  HB_SCRIPT_MEROITIC_HIEROGLYPHS,
-  HB_SCRIPT_MIAO,
-  HB_SCRIPT_SHARADA,
-  HB_SCRIPT_SORA_SOMPENG,
-  HB_SCRIPT_TAKRI
-};
-#endif
-
-hb_script_t
-hb_glib_script_to_script (GUnicodeScript script)
-{
-#if GLIB_CHECK_VERSION(2,29,14)
-  return (hb_script_t) g_unicode_script_to_iso15924 (script);
-#else
-  if (likely ((unsigned int) script < ARRAY_LENGTH (glib_script_to_script)))
-    return glib_script_to_script[script];
-
-  if (unlikely (script == G_UNICODE_SCRIPT_INVALID_CODE))
-    return HB_SCRIPT_INVALID;
-
-  return HB_SCRIPT_UNKNOWN;
-#endif
-}
-
-GUnicodeScript
-hb_glib_script_from_script (hb_script_t script)
-{
-#if GLIB_CHECK_VERSION(2,29,14)
-  return g_unicode_script_from_iso15924 (script);
-#else
-  unsigned int count = ARRAY_LENGTH (glib_script_to_script);
-  for (unsigned int i = 0; i < count; i++)
-    if (glib_script_to_script[i] == script)
-      return (GUnicodeScript) i;
-
-  if (unlikely (script == HB_SCRIPT_INVALID))
-    return G_UNICODE_SCRIPT_INVALID_CODE;
-
-  return G_UNICODE_SCRIPT_UNKNOWN;
-#endif
-}
-
-
-static hb_unicode_combining_class_t
-hb_glib_unicode_combining_class (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-				 hb_codepoint_t      unicode,
-				 void               *user_data HB_UNUSED)
-
-{
-  return (hb_unicode_combining_class_t) g_unichar_combining_class (unicode);
-}
-
-static unsigned int
-hb_glib_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-				 hb_codepoint_t      unicode,
-				 void               *user_data HB_UNUSED)
-{
-  return g_unichar_iswide (unicode) ? 2 : 1;
-}
-
-static hb_unicode_general_category_t
-hb_glib_unicode_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-				  hb_codepoint_t      unicode,
-				  void               *user_data HB_UNUSED)
-
-{
-  /* hb_unicode_general_category_t and GUnicodeType are identical */
-  return (hb_unicode_general_category_t) g_unichar_type (unicode);
-}
-
-static hb_codepoint_t
-hb_glib_unicode_mirroring (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-			   hb_codepoint_t      unicode,
-			   void               *user_data HB_UNUSED)
-{
-  g_unichar_get_mirror_char (unicode, &unicode);
-  return unicode;
-}
-
-static hb_script_t
-hb_glib_unicode_script (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-			hb_codepoint_t      unicode,
-			void               *user_data HB_UNUSED)
-{
-  return hb_glib_script_to_script (g_unichar_get_script (unicode));
-}
-
-static hb_bool_t
-hb_glib_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-			 hb_codepoint_t      a,
-			 hb_codepoint_t      b,
-			 hb_codepoint_t     *ab,
-			 void               *user_data HB_UNUSED)
-{
-#if GLIB_CHECK_VERSION(2,29,12)
-  return g_unichar_compose (a, b, ab);
-#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
-hb_glib_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-			   hb_codepoint_t      ab,
-			   hb_codepoint_t     *a,
-			   hb_codepoint_t     *b,
-			   void               *user_data HB_UNUSED)
-{
-#if GLIB_CHECK_VERSION(2,29,12)
-  return g_unichar_decompose (ab, a, b);
-#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;
-}
-
-static unsigned int
-hb_glib_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-					 hb_codepoint_t      u,
-					 hb_codepoint_t     *decomposed,
-					 void               *user_data HB_UNUSED)
-{
-#if GLIB_CHECK_VERSION(2,29,12)
-  return g_unichar_fully_decompose (u, true, decomposed, HB_UNICODE_MAX_DECOMPOSITION_LEN);
-#endif
-
-  /* If the user doesn't have GLib >= 2.29.12 we have to perform
-   * a round trip to UTF-8 and the associated memory management dance. */
-  gchar utf8[6];
-  gchar *utf8_decomposed, *c;
-  gsize utf8_len, utf8_decomposed_len, i;
-
-  /* Convert @u to UTF-8 and normalise it in NFKD mode. This performs the compatibility decomposition. */
-  utf8_len = g_unichar_to_utf8 (u, utf8);
-  utf8_decomposed = g_utf8_normalize (utf8, utf8_len, G_NORMALIZE_NFKD);
-  utf8_decomposed_len = g_utf8_strlen (utf8_decomposed, -1);
-
-  assert (utf8_decomposed_len <= HB_UNICODE_MAX_DECOMPOSITION_LEN);
-
-  for (i = 0, c = utf8_decomposed; i < utf8_decomposed_len; i++, c = g_utf8_next_char (c))
-    *decomposed++ = g_utf8_get_char (c);
-
-  g_free (utf8_decomposed);
-
-  return utf8_decomposed_len;
-}
-
-static hb_unicode_funcs_t *static_glib_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_glib_funcs (void)
-{
-  hb_unicode_funcs_destroy (static_glib_funcs);
-}
-#endif
-
-hb_unicode_funcs_t *
-hb_glib_get_unicode_funcs (void)
-{
-retry:
-  hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_glib_funcs);
-
-  if (unlikely (!funcs))
-  {
-    funcs = hb_unicode_funcs_create (nullptr);
-
-#define HB_UNICODE_FUNC_IMPLEMENT(name) \
-    hb_unicode_funcs_set_##name##_func (funcs, hb_glib_unicode_##name, nullptr, nullptr);
-      HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-
-    hb_unicode_funcs_make_immutable (funcs);
-
-    if (!hb_atomic_ptr_cmpexch (&static_glib_funcs, nullptr, funcs)) {
-      hb_unicode_funcs_destroy (funcs);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_glib_funcs); /* First person registers atexit() callback. */
-#endif
-  };
-
-  return hb_unicode_funcs_reference (funcs);
-}
-
-#if GLIB_CHECK_VERSION(2,31,10)
-
-static void
-_hb_g_bytes_unref (void *data)
-{
-  g_bytes_unref ((GBytes *) data);
-}
-
-/**
- * hb_glib_blob_create:
- *
- * Since: 0.9.38
- **/
-hb_blob_t *
-hb_glib_blob_create (GBytes *gbytes)
-{
-  gsize size = 0;
-  gconstpointer data = g_bytes_get_data (gbytes, &size);
-  return hb_blob_create ((const char *) data,
-			 size,
-			 HB_MEMORY_MODE_READONLY,
-			 g_bytes_ref (gbytes),
-			 _hb_g_bytes_unref);
-}
-#endif
diff --git a/third_party/harfbuzz-ng/src/hb-glib.h b/third_party/harfbuzz-ng/src/hb-glib.h
deleted file mode 100644
index 5f04183..0000000
--- a/third_party/harfbuzz-ng/src/hb-glib.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_GLIB_H
-#define HB_GLIB_H
-
-#include "hb.h"
-
-#include <glib.h>
-
-HB_BEGIN_DECLS
-
-
-HB_EXTERN hb_script_t
-hb_glib_script_to_script (GUnicodeScript script);
-
-HB_EXTERN GUnicodeScript
-hb_glib_script_from_script (hb_script_t script);
-
-
-HB_EXTERN hb_unicode_funcs_t *
-hb_glib_get_unicode_funcs (void);
-
-#if GLIB_CHECK_VERSION(2,31,10)
-HB_EXTERN hb_blob_t *
-hb_glib_blob_create (GBytes *gbytes);
-#endif
-
-HB_END_DECLS
-
-#endif /* HB_GLIB_H */
diff --git a/third_party/harfbuzz-ng/src/hb-gobject-structs.cc b/third_party/harfbuzz-ng/src/hb-gobject-structs.cc
deleted file mode 100644
index a96c3580..0000000
--- a/third_party/harfbuzz-ng/src/hb-gobject-structs.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-
-/* g++ didn't like older gtype.h gcc-only code path. */
-#include <glib.h>
-#if !GLIB_CHECK_VERSION(2,29,16)
-#undef __GNUC__
-#undef __GNUC_MINOR__
-#define __GNUC__ 2
-#define __GNUC_MINOR__ 6
-#endif
-
-#include "hb-gobject.h"
-
-#define HB_DEFINE_BOXED_TYPE(name,copy_func,free_func) \
-GType \
-hb_gobject_##name##_get_type (void) \
-{ \
-   static gsize type_id = 0; \
-   if (g_once_init_enter (&type_id)) { \
-      GType id = g_boxed_type_register_static (g_intern_static_string ("hb_" #name "_t"), \
-					       (GBoxedCopyFunc) copy_func, \
-					       (GBoxedFreeFunc) free_func); \
-      g_once_init_leave (&type_id, id); \
-   } \
-   return type_id; \
-}
-
-#define HB_DEFINE_OBJECT_TYPE(name) \
-	HB_DEFINE_BOXED_TYPE (name, hb_##name##_reference, hb_##name##_destroy);
-
-#define HB_DEFINE_VALUE_TYPE(name) \
-	static hb_##name##_t *_hb_##name##_reference (const hb_##name##_t *l) \
-	{ \
-	  hb_##name##_t *c = (hb_##name##_t *) calloc (1, sizeof (hb_##name##_t)); \
-	  if (unlikely (!c)) return nullptr; \
-	  *c = *l; \
-	  return c; \
-	} \
-	static void _hb_##name##_destroy (hb_##name##_t *l) { free (l); } \
-	HB_DEFINE_BOXED_TYPE (name, _hb_##name##_reference, _hb_##name##_destroy);
-
-HB_DEFINE_OBJECT_TYPE (buffer)
-HB_DEFINE_OBJECT_TYPE (blob)
-HB_DEFINE_OBJECT_TYPE (face)
-HB_DEFINE_OBJECT_TYPE (font)
-HB_DEFINE_OBJECT_TYPE (font_funcs)
-HB_DEFINE_OBJECT_TYPE (set)
-HB_DEFINE_OBJECT_TYPE (shape_plan)
-HB_DEFINE_OBJECT_TYPE (unicode_funcs)
-HB_DEFINE_VALUE_TYPE (feature)
-HB_DEFINE_VALUE_TYPE (glyph_info)
-HB_DEFINE_VALUE_TYPE (glyph_position)
-HB_DEFINE_VALUE_TYPE (segment_properties)
-HB_DEFINE_VALUE_TYPE (user_data_key)
-
-HB_DEFINE_VALUE_TYPE (ot_math_glyph_variant)
-HB_DEFINE_VALUE_TYPE (ot_math_glyph_part)
diff --git a/third_party/harfbuzz-ng/src/hb-gobject-structs.h b/third_party/harfbuzz-ng/src/hb-gobject-structs.h
deleted file mode 100644
index 302dc95..0000000
--- a/third_party/harfbuzz-ng/src/hb-gobject-structs.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_GOBJECT_H_IN
-#error "Include <hb-gobject.h> instead."
-#endif
-
-#ifndef HB_GOBJECT_STRUCTS_H
-#define HB_GOBJECT_STRUCTS_H
-
-#include "hb.h"
-
-#include <glib-object.h>
-
-HB_BEGIN_DECLS
-
-
-/* Object types */
-
-/**
- * hb_gobject_blob_get_type:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN GType
-hb_gobject_blob_get_type (void);
-#define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ())
-
-/**
- * hb_gobject_buffer_get_type:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN GType
-hb_gobject_buffer_get_type (void);
-#define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ())
-
-/**
- * hb_gobject_face_get_type:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN GType
-hb_gobject_face_get_type (void);
-#define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ())
-
-/**
- * hb_gobject_font_get_type:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN GType
-hb_gobject_font_get_type (void);
-#define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ())
-
-/**
- * hb_gobject_font_funcs_get_type:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN GType
-hb_gobject_font_funcs_get_type (void);
-#define HB_GOBJECT_TYPE_FONT_FUNCS (hb_gobject_font_funcs_get_type ())
-
-HB_EXTERN GType
-hb_gobject_set_get_type (void);
-#define HB_GOBJECT_TYPE_SET (hb_gobject_set_get_type ())
-
-HB_EXTERN GType
-hb_gobject_shape_plan_get_type (void);
-#define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ())
-
-/**
- * hb_gobject_unicode_funcs_get_type:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN GType
-hb_gobject_unicode_funcs_get_type (void);
-#define HB_GOBJECT_TYPE_UNICODE_FUNCS (hb_gobject_unicode_funcs_get_type ())
-
-/* Value types */
-
-HB_EXTERN GType
-hb_gobject_feature_get_type (void);
-#define HB_GOBJECT_TYPE_FEATURE (hb_gobject_feature_get_type ())
-
-HB_EXTERN GType
-hb_gobject_glyph_info_get_type (void);
-#define HB_GOBJECT_TYPE_GLYPH_INFO (hb_gobject_glyph_info_get_type ())
-
-HB_EXTERN GType
-hb_gobject_glyph_position_get_type (void);
-#define HB_GOBJECT_TYPE_GLYPH_POSITION (hb_gobject_glyph_position_get_type ())
-
-HB_EXTERN GType
-hb_gobject_segment_properties_get_type (void);
-#define HB_GOBJECT_TYPE_SEGMENT_PROPERTIES (hb_gobject_segment_properties_get_type ())
-
-HB_EXTERN GType
-hb_gobject_user_data_key_get_type (void);
-#define HB_GOBJECT_TYPE_USER_DATA_KEY (hb_gobject_user_data_key_get_type ())
-
-HB_EXTERN GType
-hb_gobject_ot_math_glyph_variant_get_type (void);
-#define HB_GOBJECT_TYPE_OT_MATH_GLYPH_VARIANT (hb_gobject_ot_math_glyph_variant_get_type ())
-
-HB_EXTERN GType
-hb_gobject_ot_math_glyph_part_get_type (void);
-#define HB_GOBJECT_TYPE_OT_MATH_GLYPH_PART (hb_gobject_ot_math_glyph_part_get_type ())
-
-
-HB_END_DECLS
-
-#endif /* HB_GOBJECT_H */
diff --git a/third_party/harfbuzz-ng/src/hb-gobject.h b/third_party/harfbuzz-ng/src/hb-gobject.h
deleted file mode 100644
index ea1bd25..0000000
--- a/third_party/harfbuzz-ng/src/hb-gobject.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_GOBJECT_H
-#define HB_GOBJECT_H
-#define HB_GOBJECT_H_IN
-
-#include "hb.h"
-
-#include "hb-gobject-enums.h"
-#include "hb-gobject-structs.h"
-
-HB_BEGIN_DECLS
-HB_END_DECLS
-
-#undef HB_GOBJECT_H_IN
-#endif /* HB_GOBJECT_H */
diff --git a/third_party/harfbuzz-ng/src/hb-graphite2.cc b/third_party/harfbuzz-ng/src/hb-graphite2.cc
deleted file mode 100644
index 46fe139..0000000
--- a/third_party/harfbuzz-ng/src/hb-graphite2.cc
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright © 2011  Martin Hosken
- * Copyright © 2011  SIL International
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#define HB_SHAPER graphite2
-#include "hb-shaper-impl-private.hh"
-
-#include "hb-graphite2.h"
-
-#include <graphite2/Segment.h>
-
-
-HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, face)
-HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, font)
-
-
-/*
- * shaper face data
- */
-
-typedef struct hb_graphite2_tablelist_t {
-  struct hb_graphite2_tablelist_t *next;
-  hb_blob_t *blob;
-  unsigned int tag;
-} hb_graphite2_tablelist_t;
-
-struct hb_graphite2_shaper_face_data_t {
-  hb_face_t *face;
-  gr_face   *grface;
-  hb_graphite2_tablelist_t *tlist;
-};
-
-static const void *hb_graphite2_get_table (const void *data, unsigned int tag, size_t *len)
-{
-  hb_graphite2_shaper_face_data_t *face_data = (hb_graphite2_shaper_face_data_t *) data;
-  hb_graphite2_tablelist_t *tlist = face_data->tlist;
-
-  hb_blob_t *blob = nullptr;
-
-  for (hb_graphite2_tablelist_t *p = tlist; p; p = p->next)
-    if (p->tag == tag) {
-      blob = p->blob;
-      break;
-    }
-
-  if (unlikely (!blob))
-  {
-    blob = face_data->face->reference_table (tag);
-
-    hb_graphite2_tablelist_t *p = (hb_graphite2_tablelist_t *) calloc (1, sizeof (hb_graphite2_tablelist_t));
-    if (unlikely (!p)) {
-      hb_blob_destroy (blob);
-      return nullptr;
-    }
-    p->blob = blob;
-    p->tag = tag;
-
-    /* TODO Not thread-safe, but fairly harmless.
-     * We can do the double-checked pointer cmpexch thing here. */
-    p->next = face_data->tlist;
-    face_data->tlist = p;
-  }
-
-  unsigned int tlen;
-  const char *d = hb_blob_get_data (blob, &tlen);
-  *len = tlen;
-  return d;
-}
-
-hb_graphite2_shaper_face_data_t *
-_hb_graphite2_shaper_face_data_create (hb_face_t *face)
-{
-  hb_blob_t *silf_blob = face->reference_table (HB_GRAPHITE2_TAG_SILF);
-  /* Umm, we just reference the table to check whether it exists.
-   * Maybe add better API for this? */
-  if (!hb_blob_get_length (silf_blob))
-  {
-    hb_blob_destroy (silf_blob);
-    return nullptr;
-  }
-  hb_blob_destroy (silf_blob);
-
-  hb_graphite2_shaper_face_data_t *data = (hb_graphite2_shaper_face_data_t *) calloc (1, sizeof (hb_graphite2_shaper_face_data_t));
-  if (unlikely (!data))
-    return nullptr;
-
-  data->face = face;
-  data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll);
-
-  if (unlikely (!data->grface)) {
-    free (data);
-    return nullptr;
-  }
-
-  return data;
-}
-
-void
-_hb_graphite2_shaper_face_data_destroy (hb_graphite2_shaper_face_data_t *data)
-{
-  hb_graphite2_tablelist_t *tlist = data->tlist;
-
-  while (tlist)
-  {
-    hb_graphite2_tablelist_t *old = tlist;
-    hb_blob_destroy (tlist->blob);
-    tlist = tlist->next;
-    free (old);
-  }
-
-  gr_face_destroy (data->grface);
-
-  free (data);
-}
-
-/*
- * Since: 0.9.10
- */
-gr_face *
-hb_graphite2_face_get_gr_face (hb_face_t *face)
-{
-  if (unlikely (!hb_graphite2_shaper_face_data_ensure (face))) return nullptr;
-  return HB_SHAPER_DATA_GET (face)->grface;
-}
-
-
-/*
- * shaper font data
- */
-
-struct hb_graphite2_shaper_font_data_t {};
-
-hb_graphite2_shaper_font_data_t *
-_hb_graphite2_shaper_font_data_create (hb_font_t *font HB_UNUSED)
-{
-  return (hb_graphite2_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data HB_UNUSED)
-{
-}
-
-/*
- * Since: 0.9.10
- */
-gr_font *
-hb_graphite2_font_get_gr_font (hb_font_t *font)
-{
-  return nullptr;
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_graphite2_shaper_shape_plan_data_t {};
-
-hb_graphite2_shaper_shape_plan_data_t *
-_hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-					     const hb_feature_t *user_features HB_UNUSED,
-					     unsigned int        num_user_features HB_UNUSED,
-					     const int          *coords HB_UNUSED,
-					     unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_graphite2_shaper_shape_plan_data_destroy (hb_graphite2_shaper_shape_plan_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
- * shaper
- */
-
-struct hb_graphite2_cluster_t {
-  unsigned int base_char;
-  unsigned int num_chars;
-  unsigned int base_glyph;
-  unsigned int num_glyphs;
-  unsigned int cluster;
-  float advance;
-};
-
-hb_bool_t
-_hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
-		     hb_font_t          *font,
-		     hb_buffer_t        *buffer,
-		     const hb_feature_t *features,
-		     unsigned int        num_features)
-{
-  hb_face_t *face = font->face;
-  gr_face *grface = HB_SHAPER_DATA_GET (face)->grface;
-
-  const char *lang = hb_language_to_string (hb_buffer_get_language (buffer));
-  const char *lang_end = lang ? strchr (lang, '-') : nullptr;
-  int lang_len = lang_end ? lang_end - lang : -1;
-  gr_feature_val *feats = gr_face_featureval_for_lang (grface, lang ? hb_tag_from_string (lang, lang_len) : 0);
-
-  for (unsigned int i = 0; i < num_features; i++)
-  {
-    const gr_feature_ref *fref = gr_face_find_fref (grface, features[i].tag);
-    if (fref)
-      gr_fref_set_feature_value (fref, features[i].value, feats);
-  }
-
-  gr_segment *seg = nullptr;
-  const gr_slot *is;
-  unsigned int ci = 0, ic = 0;
-  float curradvx = 0., curradvy = 0.;
-
-  unsigned int scratch_size;
-  hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
-
-  uint32_t *chars = (uint32_t *) scratch;
-
-  for (unsigned int i = 0; i < buffer->len; ++i)
-    chars[i] = buffer->info[i].codepoint;
-
-  /* TODO ensure_native_direction. */
-
-  hb_tag_t script_tag[2];
-  hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]);
-
-  seg = gr_make_seg (nullptr, grface,
-		     script_tag[1] == HB_TAG_NONE ? script_tag[0] : script_tag[1],
-		     feats,
-		     gr_utf32, chars, buffer->len,
-		     2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0));
-
-  if (unlikely (!seg)) {
-    if (feats) gr_featureval_destroy (feats);
-    return false;
-  }
-
-  unsigned int glyph_count = gr_seg_n_slots (seg);
-  if (unlikely (!glyph_count)) {
-    if (feats) gr_featureval_destroy (feats);
-    gr_seg_destroy (seg);
-    buffer->len = 0;
-    return true;
-  }
-
-  buffer->ensure (glyph_count);
-  scratch = buffer->get_scratch_buffer (&scratch_size);
-  while ((DIV_CEIL (sizeof (hb_graphite2_cluster_t) * buffer->len, sizeof (*scratch)) +
-	  DIV_CEIL (sizeof (hb_codepoint_t) * glyph_count, sizeof (*scratch))) > scratch_size)
-  {
-    if (unlikely (!buffer->ensure (buffer->allocated * 2)))
-    {
-      if (feats) gr_featureval_destroy (feats);
-      gr_seg_destroy (seg);
-      return false;
-    }
-    scratch = buffer->get_scratch_buffer (&scratch_size);
-  }
-
-#define ALLOCATE_ARRAY(Type, name, len) \
-  Type *name = (Type *) scratch; \
-  { \
-    unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
-    assert (_consumed <= scratch_size); \
-    scratch += _consumed; \
-    scratch_size -= _consumed; \
-  }
-
-  ALLOCATE_ARRAY (hb_graphite2_cluster_t, clusters, buffer->len);
-  ALLOCATE_ARRAY (hb_codepoint_t, gids, glyph_count);
-
-#undef ALLOCATE_ARRAY
-
-  memset (clusters, 0, sizeof (clusters[0]) * buffer->len);
-
-  hb_codepoint_t *pg = gids;
-  clusters[0].cluster = buffer->info[0].cluster;
-  float curradv = 0.;
-  if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
-  {
-    curradv = gr_slot_origin_X(gr_seg_first_slot(seg));
-    clusters[0].advance = gr_seg_advance_X(seg) - curradv;
-  }
-  else
-    clusters[0].advance = 0;
-  for (is = gr_seg_first_slot (seg), ic = 0; is; is = gr_slot_next_in_segment (is), ic++)
-  {
-    unsigned int before = gr_slot_before (is);
-    unsigned int after = gr_slot_after (is);
-    *pg = gr_slot_gid (is);
-    pg++;
-    while (clusters[ci].base_char > before && ci)
-    {
-      clusters[ci-1].num_chars += clusters[ci].num_chars;
-      clusters[ci-1].num_glyphs += clusters[ci].num_glyphs;
-      clusters[ci-1].advance += clusters[ci].advance;
-      ci--;
-    }
-
-    if (gr_slot_can_insert_before (is) && clusters[ci].num_chars && before >= clusters[ci].base_char + clusters[ci].num_chars)
-    {
-      hb_graphite2_cluster_t *c = clusters + ci + 1;
-      c->base_char = clusters[ci].base_char + clusters[ci].num_chars;
-      c->cluster = buffer->info[c->base_char].cluster;
-      c->num_chars = before - c->base_char;
-      c->base_glyph = ic;
-      c->num_glyphs = 0;
-      if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
-        c->advance = curradv - gr_slot_origin_X(is);
-      else
-      {
-        c->advance = 0;
-        clusters[ci].advance += gr_slot_origin_X(is) - curradv;
-      }
-      ci++;
-      curradv = gr_slot_origin_X(is);
-    }
-    clusters[ci].num_glyphs++;
-
-    if (clusters[ci].base_char + clusters[ci].num_chars < after + 1)
-	clusters[ci].num_chars = after + 1 - clusters[ci].base_char;
-  }
-
-  if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
-    clusters[ci].advance += curradv;
-  else
-    clusters[ci].advance += gr_seg_advance_X(seg) - curradv;
-  ci++;
-
-  for (unsigned int i = 0; i < ci; ++i)
-  {
-    for (unsigned int j = 0; j < clusters[i].num_glyphs; ++j)
-    {
-      hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j];
-      info->codepoint = gids[clusters[i].base_glyph + j];
-      info->cluster = clusters[i].cluster;
-      info->var1.i32 = clusters[i].advance;     // all glyphs in the cluster get the same advance
-    }
-  }
-  buffer->len = glyph_count;
-
-  unsigned int upem = hb_face_get_upem (face);
-  float xscale = (float) font->x_scale / upem;
-  float yscale = (float) font->y_scale / upem;
-  yscale *= yscale / xscale;
-  /* Positioning. */
-  unsigned int currclus = (unsigned int) -1;
-  const hb_glyph_info_t *info = buffer->info;
-  hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, nullptr);
-  if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
-  {
-    curradvx = 0;
-    for (is = gr_seg_first_slot (seg); is; pPos++, ++info, is = gr_slot_next_in_segment (is))
-    {
-      pPos->x_offset = gr_slot_origin_X (is) * xscale - curradvx;
-      pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy;
-      if (info->cluster != currclus) {
-        pPos->x_advance = info->var1.i32 * xscale;
-        curradvx += pPos->x_advance;
-        currclus = info->cluster;
-      } else
-        pPos->x_advance = 0.;
-
-      pPos->y_advance = gr_slot_advance_Y (is, grface, nullptr) * yscale;
-      curradvy += pPos->y_advance;
-    }
-  }
-  else
-  {
-    curradvx = gr_seg_advance_X(seg) * xscale;
-    for (is = gr_seg_first_slot (seg); is; pPos++, info++, is = gr_slot_next_in_segment (is))
-    {
-      if (info->cluster != currclus)
-      {
-        pPos->x_advance = info->var1.i32 * xscale;
-        curradvx -= pPos->x_advance;
-        currclus = info->cluster;
-      } else
-        pPos->x_advance = 0.;
-
-      pPos->y_advance = gr_slot_advance_Y (is, grface, nullptr) * yscale;
-      curradvy -= pPos->y_advance;
-      pPos->x_offset = (gr_slot_origin_X (is) - info->var1.i32) * xscale - curradvx + pPos->x_advance;
-      pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy;
-    }
-    hb_buffer_reverse_clusters (buffer);
-  }
-
-  if (feats) gr_featureval_destroy (feats);
-  gr_seg_destroy (seg);
-
-  buffer->unsafe_to_break_all ();
-
-  return true;
-}
diff --git a/third_party/harfbuzz-ng/src/hb-graphite2.h b/third_party/harfbuzz-ng/src/hb-graphite2.h
deleted file mode 100644
index 82b1e64..0000000
--- a/third_party/harfbuzz-ng/src/hb-graphite2.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011  Martin Hosken
- * Copyright (C) 2011  SIL International
- *
- *  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_GRAPHITE2_H
-#define HB_GRAPHITE2_H
-
-#include "hb.h"
-
-#include <graphite2/Font.h>
-
-HB_BEGIN_DECLS
-
-
-#define HB_GRAPHITE2_TAG_SILF HB_TAG('S','i','l','f')
-
-
-HB_EXTERN gr_face *
-hb_graphite2_face_get_gr_face (hb_face_t *face);
-
-#ifndef HB_DISABLE_DEPRECATED
-
-HB_EXTERN gr_font *
-hb_graphite2_font_get_gr_font (hb_font_t *font);
-
-#endif
-
-
-HB_END_DECLS
-
-#endif /* HB_GRAPHITE2_H */
diff --git a/third_party/harfbuzz-ng/src/hb-icu.cc b/third_party/harfbuzz-ng/src/hb-icu.cc
deleted file mode 100644
index 552eaec..0000000
--- a/third_party/harfbuzz-ng/src/hb-icu.cc
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2009  Keith Stribley
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-
-#include "hb-icu.h"
-
-#include "hb-unicode-private.hh"
-
-#include <unicode/uchar.h>
-#include <unicode/unorm2.h>
-#include <unicode/ustring.h>
-#include <unicode/utf16.h>
-#include <unicode/uversion.h>
-
-
-hb_script_t
-hb_icu_script_to_script (UScriptCode script)
-{
-  if (unlikely (script == USCRIPT_INVALID_CODE))
-    return HB_SCRIPT_INVALID;
-
-  return hb_script_from_string (uscript_getShortName (script), -1);
-}
-
-UScriptCode
-hb_icu_script_from_script (hb_script_t script)
-{
-  if (unlikely (script == HB_SCRIPT_INVALID))
-    return USCRIPT_INVALID_CODE;
-
-  for (unsigned int i = 0; i < USCRIPT_CODE_LIMIT; i++)
-    if (unlikely (hb_icu_script_to_script ((UScriptCode) i) == script))
-      return (UScriptCode) i;
-
-  return USCRIPT_UNKNOWN;
-}
-
-
-static hb_unicode_combining_class_t
-hb_icu_unicode_combining_class (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-				hb_codepoint_t      unicode,
-				void               *user_data HB_UNUSED)
-
-{
-  return (hb_unicode_combining_class_t) u_getCombiningClass (unicode);
-}
-
-static unsigned int
-hb_icu_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-				hb_codepoint_t      unicode,
-				void               *user_data HB_UNUSED)
-{
-  switch (u_getIntPropertyValue(unicode, UCHAR_EAST_ASIAN_WIDTH))
-  {
-  case U_EA_WIDE:
-  case U_EA_FULLWIDTH:
-    return 2;
-  case U_EA_NEUTRAL:
-  case U_EA_AMBIGUOUS:
-  case U_EA_HALFWIDTH:
-  case U_EA_NARROW:
-    return 1;
-  }
-  return 1;
-}
-
-static hb_unicode_general_category_t
-hb_icu_unicode_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-				 hb_codepoint_t      unicode,
-				 void               *user_data HB_UNUSED)
-{
-  switch (u_getIntPropertyValue(unicode, UCHAR_GENERAL_CATEGORY))
-  {
-  case U_UNASSIGNED:			return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
-
-  case U_UPPERCASE_LETTER:		return HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER;
-  case U_LOWERCASE_LETTER:		return HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER;
-  case U_TITLECASE_LETTER:		return HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER;
-  case U_MODIFIER_LETTER:		return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER;
-  case U_OTHER_LETTER:			return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
-
-  case U_NON_SPACING_MARK:		return HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK;
-  case U_ENCLOSING_MARK:		return HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
-  case U_COMBINING_SPACING_MARK:	return HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK;
-
-  case U_DECIMAL_DIGIT_NUMBER:		return HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER;
-  case U_LETTER_NUMBER:			return HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER;
-  case U_OTHER_NUMBER:			return HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER;
-
-  case U_SPACE_SEPARATOR:		return HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
-  case U_LINE_SEPARATOR:		return HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR;
-  case U_PARAGRAPH_SEPARATOR:		return HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR;
-
-  case U_CONTROL_CHAR:			return HB_UNICODE_GENERAL_CATEGORY_CONTROL;
-  case U_FORMAT_CHAR:			return HB_UNICODE_GENERAL_CATEGORY_FORMAT;
-  case U_PRIVATE_USE_CHAR:		return HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE;
-  case U_SURROGATE:			return HB_UNICODE_GENERAL_CATEGORY_SURROGATE;
-
-
-  case U_DASH_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION;
-  case U_START_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION;
-  case U_END_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION;
-  case U_CONNECTOR_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION;
-  case U_OTHER_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION;
-
-  case U_MATH_SYMBOL:			return HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL;
-  case U_CURRENCY_SYMBOL:		return HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL;
-  case U_MODIFIER_SYMBOL:		return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL;
-  case U_OTHER_SYMBOL:			return HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL;
-
-  case U_INITIAL_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION;
-  case U_FINAL_PUNCTUATION:		return HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION;
-  }
-
-  return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
-}
-
-static hb_codepoint_t
-hb_icu_unicode_mirroring (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-			  hb_codepoint_t      unicode,
-			  void               *user_data HB_UNUSED)
-{
-  return u_charMirror(unicode);
-}
-
-static hb_script_t
-hb_icu_unicode_script (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-		       hb_codepoint_t      unicode,
-		       void               *user_data HB_UNUSED)
-{
-  UErrorCode status = U_ZERO_ERROR;
-  UScriptCode scriptCode = uscript_getScript(unicode, &status);
-
-  if (unlikely (U_FAILURE (status)))
-    return HB_SCRIPT_UNKNOWN;
-
-  return hb_icu_script_to_script (scriptCode);
-}
-
-#if U_ICU_VERSION_MAJOR_NUM >= 49
-static const UNormalizer2 *normalizer;
-#endif
-
-static hb_bool_t
-hb_icu_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-			hb_codepoint_t      a,
-			hb_codepoint_t      b,
-			hb_codepoint_t     *ab,
-			void               *user_data HB_UNUSED)
-{
-#if U_ICU_VERSION_MAJOR_NUM >= 49
-  {
-    UChar32 ret = unorm2_composePair (normalizer, a, b);
-    if (ret < 0) return false;
-    *ab = ret;
-    return true;
-  }
-#endif
-
-  /* We don't ifdef-out the fallback code such that compiler always
-   * sees it and makes sure it's compilable. */
-
-  UChar utf16[4], normalized[5];
-  unsigned int len;
-  hb_bool_t ret, err;
-  UErrorCode icu_err;
-
-  len = 0;
-  err = false;
-  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), a, err);
-  if (err) return false;
-  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), b, err);
-  if (err) return false;
-
-  icu_err = U_ZERO_ERROR;
-  len = unorm2_normalize (unorm2_getNFCInstance (&icu_err), utf16, len, normalized, ARRAY_LENGTH (normalized), &icu_err);
-  if (U_FAILURE (icu_err))
-    return false;
-  if (u_countChar32 (normalized, len) == 1) {
-    U16_GET_UNSAFE (normalized, 0, *ab);
-    ret = true;
-  } else {
-    ret = false;
-  }
-
-  return ret;
-}
-
-static hb_bool_t
-hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-			  hb_codepoint_t      ab,
-			  hb_codepoint_t     *a,
-			  hb_codepoint_t     *b,
-			  void               *user_data HB_UNUSED)
-{
-#if U_ICU_VERSION_MAJOR_NUM >= 49
-  {
-    UChar decomposed[4];
-    int len;
-    UErrorCode icu_err = U_ZERO_ERROR;
-    len = unorm2_getRawDecomposition (normalizer, ab, decomposed,
-				      ARRAY_LENGTH (decomposed), &icu_err);
-    if (U_FAILURE (icu_err) || len < 0) return false;
-
-    len = u_countChar32 (decomposed, len);
-    if (len == 1) {
-      U16_GET_UNSAFE (decomposed, 0, *a);
-      *b = 0;
-      return *a != ab;
-    } else if (len == 2) {
-      len =0;
-      U16_NEXT_UNSAFE (decomposed, len, *a);
-      U16_NEXT_UNSAFE (decomposed, len, *b);
-    }
-    return true;
-  }
-#endif
-
-  /* We don't ifdef-out the fallback code such that compiler always
-   * sees it and makes sure it's compilable. */
-
-  UChar utf16[2], normalized[2 * HB_UNICODE_MAX_DECOMPOSITION_LEN + 1];
-  unsigned int len;
-  hb_bool_t ret, err;
-  UErrorCode icu_err;
-
-  /* This function is a monster! Maybe it wasn't a good idea adding a
-   * pairwise decompose API... */
-  /* Watchout for the dragons.  Err, watchout for macros changing len. */
-
-  len = 0;
-  err = false;
-  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), ab, err);
-  if (err) return false;
-
-  icu_err = U_ZERO_ERROR;
-  len = unorm2_normalize (unorm2_getNFDInstance (&icu_err), utf16, len, normalized, ARRAY_LENGTH (normalized), &icu_err);
-  if (U_FAILURE (icu_err))
-    return false;
-
-  len = u_countChar32 (normalized, len);
-
-  if (len == 1) {
-    U16_GET_UNSAFE (normalized, 0, *a);
-    *b = 0;
-    ret = *a != ab;
-  } else if (len == 2) {
-    len =0;
-    U16_NEXT_UNSAFE (normalized, len, *a);
-    U16_NEXT_UNSAFE (normalized, len, *b);
-
-    /* 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 :-(. */
-    UChar recomposed[20];
-    icu_err = U_ZERO_ERROR;
-    unorm2_normalize (unorm2_getNFCInstance (&icu_err), normalized, len, recomposed, ARRAY_LENGTH (recomposed), &icu_err);
-    if (U_FAILURE (icu_err))
-      return false;
-    hb_codepoint_t c;
-    U16_GET_UNSAFE (recomposed, 0, c);
-    if (c != *a && c != ab) {
-      *a = c;
-      *b = 0;
-    }
-    ret = true;
-  } else {
-    /* If decomposed to more than two characters, take the last one,
-     * and recompose the rest to get the first component. */
-    U16_PREV_UNSAFE (normalized, len, *b); /* Changes len in-place. */
-    UChar recomposed[18 * 2];
-    icu_err = U_ZERO_ERROR;
-    len = unorm2_normalize (unorm2_getNFCInstance (&icu_err), normalized, len, recomposed, ARRAY_LENGTH (recomposed), &icu_err);
-    if (U_FAILURE (icu_err))
-      return false;
-    /* We expect that recomposed has exactly one character now. */
-    if (unlikely (u_countChar32 (recomposed, len) != 1))
-      return false;
-    U16_GET_UNSAFE (recomposed, 0, *a);
-    ret = true;
-  }
-
-  return ret;
-}
-
-static unsigned int
-hb_icu_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-					hb_codepoint_t      u,
-					hb_codepoint_t     *decomposed,
-					void               *user_data HB_UNUSED)
-{
-  UChar utf16[2], normalized[2 * HB_UNICODE_MAX_DECOMPOSITION_LEN + 1];
-  unsigned int len;
-  int32_t utf32_len;
-  hb_bool_t err;
-  UErrorCode icu_err;
-
-  /* Copy @u into a UTF-16 array to be passed to ICU. */
-  len = 0;
-  err = false;
-  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), u, err);
-  if (err)
-    return 0;
-
-  /* Normalise the codepoint using NFKD mode. */
-  icu_err = U_ZERO_ERROR;
-  len = unorm2_normalize (unorm2_getNFKDInstance (&icu_err), utf16, len, normalized, ARRAY_LENGTH (normalized), &icu_err);
-  if (U_FAILURE (icu_err))
-    return 0;
-
-  /* Convert the decomposed form from UTF-16 to UTF-32. */
-  icu_err = U_ZERO_ERROR;
-  u_strToUTF32 ((UChar32*) decomposed, HB_UNICODE_MAX_DECOMPOSITION_LEN, &utf32_len, normalized, len, &icu_err);
-  if (U_FAILURE (icu_err))
-    return 0;
-
-  return utf32_len;
-}
-
-
-static hb_unicode_funcs_t *static_icu_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_icu_funcs (void)
-{
-  hb_unicode_funcs_destroy (static_icu_funcs);
-}
-#endif
-
-hb_unicode_funcs_t *
-hb_icu_get_unicode_funcs (void)
-{
-retry:
-  hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_icu_funcs);
-
-  if (unlikely (!funcs))
-  {
-#if U_ICU_VERSION_MAJOR_NUM >= 49
-    if (!hb_atomic_ptr_get (&normalizer)) {
-      UErrorCode icu_err = U_ZERO_ERROR;
-      /* We ignore failure in getNFCInstace(). */
-      (void) hb_atomic_ptr_cmpexch (&normalizer, nullptr, unorm2_getNFCInstance (&icu_err));
-    }
-#endif
-
-    funcs = hb_unicode_funcs_create (nullptr);
-
-#define HB_UNICODE_FUNC_IMPLEMENT(name) \
-    hb_unicode_funcs_set_##name##_func (funcs, hb_icu_unicode_##name, nullptr, nullptr);
-      HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-
-    hb_unicode_funcs_make_immutable (funcs);
-
-    if (!hb_atomic_ptr_cmpexch (&static_icu_funcs, nullptr, funcs)) {
-      hb_unicode_funcs_destroy (funcs);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_icu_funcs); /* First person registers atexit() callback. */
-#endif
-  };
-
-  return hb_unicode_funcs_reference (funcs);
-}
diff --git a/third_party/harfbuzz-ng/src/hb-icu.h b/third_party/harfbuzz-ng/src/hb-icu.h
deleted file mode 100644
index 2db6a7b..0000000
--- a/third_party/harfbuzz-ng/src/hb-icu.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_ICU_H
-#define HB_ICU_H
-
-#include "hb.h"
-
-#include <unicode/uscript.h>
-
-HB_BEGIN_DECLS
-
-
-HB_EXTERN hb_script_t
-hb_icu_script_to_script (UScriptCode script);
-
-HB_EXTERN UScriptCode
-hb_icu_script_from_script (hb_script_t script);
-
-
-HB_EXTERN hb_unicode_funcs_t *
-hb_icu_get_unicode_funcs (void);
-
-
-HB_END_DECLS
-
-#endif /* HB_ICU_H */
diff --git a/third_party/harfbuzz-ng/src/hb-mutex-private.hh b/third_party/harfbuzz-ng/src/hb-mutex-private.hh
deleted file mode 100644
index 49ed10e..0000000
--- a/third_party/harfbuzz-ng/src/hb-mutex-private.hh
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright © 2007  Chris Wilson
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Contributor(s):
- *	Chris Wilson <chris@chris-wilson.co.uk>
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_MUTEX_PRIVATE_HH
-#define HB_MUTEX_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-/* mutex */
-
-/* We need external help for these */
-
-#if defined(HB_MUTEX_IMPL_INIT) \
- && defined(hb_mutex_impl_init) \
- && defined(hb_mutex_impl_lock) \
- && defined(hb_mutex_impl_unlock) \
- && defined(hb_mutex_impl_finish)
-
-/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */
-
-
-#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
-
-#include <windows.h>
-typedef CRITICAL_SECTION hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT	{0}
-#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
-#define hb_mutex_impl_init(M)	InitializeCriticalSectionEx (M, 0, 0)
-#else
-#define hb_mutex_impl_init(M)	InitializeCriticalSection (M)
-#endif
-#define hb_mutex_impl_lock(M)	EnterCriticalSection (M)
-#define hb_mutex_impl_unlock(M)	LeaveCriticalSection (M)
-#define hb_mutex_impl_finish(M)	DeleteCriticalSection (M)
-
-
-#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
-
-#include <pthread.h>
-typedef pthread_mutex_t hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT	PTHREAD_MUTEX_INITIALIZER
-#define hb_mutex_impl_init(M)	pthread_mutex_init (M, nullptr)
-#define hb_mutex_impl_lock(M)	pthread_mutex_lock (M)
-#define hb_mutex_impl_unlock(M)	pthread_mutex_unlock (M)
-#define hb_mutex_impl_finish(M)	pthread_mutex_destroy (M)
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
-
-#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
-# include <sched.h>
-# define HB_SCHED_YIELD() sched_yield ()
-#else
-# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
-#endif
-
-/* This actually is not a totally awful implementation. */
-typedef volatile int hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT	0
-#define hb_mutex_impl_init(M)	*(M) = 0
-#define hb_mutex_impl_lock(M)	HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END
-#define hb_mutex_impl_unlock(M)	__sync_lock_release (M)
-#define hb_mutex_impl_finish(M)	HB_STMT_START {} HB_STMT_END
-
-
-#elif !defined(HB_NO_MT)
-
-#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
-# include <sched.h>
-# define HB_SCHED_YIELD() sched_yield ()
-#else
-# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
-#endif
-
-#define HB_MUTEX_INT_NIL 1 /* Warn that fallback implementation is in use. */
-typedef volatile int hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT	0
-#define hb_mutex_impl_init(M)	*(M) = 0
-#define hb_mutex_impl_lock(M)	HB_STMT_START { while (*(M)) HB_SCHED_YIELD (); (*(M))++; } HB_STMT_END
-#define hb_mutex_impl_unlock(M)	(*(M))--;
-#define hb_mutex_impl_finish(M)	HB_STMT_START {} HB_STMT_END
-
-
-#else /* HB_NO_MT */
-
-typedef int hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT	0
-#define hb_mutex_impl_init(M)	HB_STMT_START {} HB_STMT_END
-#define hb_mutex_impl_lock(M)	HB_STMT_START {} HB_STMT_END
-#define hb_mutex_impl_unlock(M)	HB_STMT_START {} HB_STMT_END
-#define hb_mutex_impl_finish(M)	HB_STMT_START {} HB_STMT_END
-
-
-#endif
-
-
-#define HB_MUTEX_INIT		{HB_MUTEX_IMPL_INIT}
-
-struct hb_mutex_t
-{
-  /* TODO Add tracing. */
-
-  hb_mutex_impl_t m;
-
-  inline void init   (void) { hb_mutex_impl_init   (&m); }
-  inline void lock   (void) { hb_mutex_impl_lock   (&m); }
-  inline void unlock (void) { hb_mutex_impl_unlock (&m); }
-  inline void finish (void) { hb_mutex_impl_finish (&m); }
-};
-
-
-#endif /* HB_MUTEX_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-object-private.hh b/third_party/harfbuzz-ng/src/hb-object-private.hh
deleted file mode 100644
index baa1f8f..0000000
--- a/third_party/harfbuzz-ng/src/hb-object-private.hh
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright © 2007  Chris Wilson
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Contributor(s):
- *	Chris Wilson <chris@chris-wilson.co.uk>
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OBJECT_PRIVATE_HH
-#define HB_OBJECT_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-
-#include "hb-atomic-private.hh"
-#include "hb-mutex-private.hh"
-
-
-/* reference_count */
-
-#define HB_REFERENCE_COUNT_INERT_VALUE -1
-#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
-#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT(HB_REFERENCE_COUNT_INERT_VALUE)}
-
-struct hb_reference_count_t
-{
-  hb_atomic_int_t ref_count;
-
-  inline void init (int v) { ref_count.set_unsafe (v); }
-  inline int get_unsafe (void) const { return ref_count.get_unsafe (); }
-  inline int inc (void) { return ref_count.inc (); }
-  inline int dec (void) { return ref_count.dec (); }
-  inline void finish (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); }
-
-  inline bool is_inert (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; }
-  inline bool is_valid (void) const { return ref_count.get_unsafe () > 0; }
-};
-
-
-/* user_data */
-
-#define HB_USER_DATA_ARRAY_INIT {HB_MUTEX_INIT, HB_LOCKABLE_SET_INIT}
-struct hb_user_data_array_t
-{
-  struct hb_user_data_item_t {
-    hb_user_data_key_t *key;
-    void *data;
-    hb_destroy_func_t destroy;
-
-    inline bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; }
-    inline bool operator == (hb_user_data_item_t &other) const { return key == other.key; }
-
-    void finish (void) { if (destroy) destroy (data); }
-  };
-
-  hb_mutex_t lock;
-  hb_lockable_set_t<hb_user_data_item_t, hb_mutex_t> items;
-
-  inline void init (void) { lock.init (); items.init (); }
-
-  HB_INTERNAL bool set (hb_user_data_key_t *key,
-			void *              data,
-			hb_destroy_func_t   destroy,
-			hb_bool_t           replace);
-
-  HB_INTERNAL void *get (hb_user_data_key_t *key);
-
-  inline void finish (void) { items.finish (lock); lock.finish (); }
-};
-
-
-/* object_header */
-
-struct hb_object_header_t
-{
-  hb_reference_count_t ref_count;
-  hb_user_data_array_t user_data;
-
-#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, HB_USER_DATA_ARRAY_INIT}
-
-  private:
-  ASSERT_POD ();
-};
-
-
-/* object */
-
-template <typename Type>
-static inline void hb_object_trace (const Type *obj, const char *function)
-{
-  DEBUG_MSG (OBJECT, (void *) obj,
-	     "%s refcount=%d",
-	     function,
-	     obj ? obj->header.ref_count.get_unsafe () : 0);
-}
-
-template <typename Type>
-static inline Type *hb_object_create (void)
-{
-  Type *obj = (Type *) calloc (1, sizeof (Type));
-
-  if (unlikely (!obj))
-    return obj;
-
-  hb_object_init (obj);
-  hb_object_trace (obj, HB_FUNC);
-  return obj;
-}
-template <typename Type>
-static inline void hb_object_init (Type *obj)
-{
-  obj->header.ref_count.init (1);
-  obj->header.user_data.init ();
-}
-template <typename Type>
-static inline bool hb_object_is_inert (const Type *obj)
-{
-  return unlikely (obj->header.ref_count.is_inert ());
-}
-template <typename Type>
-static inline bool hb_object_is_valid (const Type *obj)
-{
-  return likely (obj->header.ref_count.is_valid ());
-}
-template <typename Type>
-static inline Type *hb_object_reference (Type *obj)
-{
-  hb_object_trace (obj, HB_FUNC);
-  if (unlikely (!obj || hb_object_is_inert (obj)))
-    return obj;
-  assert (hb_object_is_valid (obj));
-  obj->header.ref_count.inc ();
-  return obj;
-}
-template <typename Type>
-static inline bool hb_object_destroy (Type *obj)
-{
-  hb_object_trace (obj, HB_FUNC);
-  if (unlikely (!obj || hb_object_is_inert (obj)))
-    return false;
-  assert (hb_object_is_valid (obj));
-  if (obj->header.ref_count.dec () != 1)
-    return false;
-
-  obj->header.ref_count.finish (); /* Do this before user_data */
-  obj->header.user_data.finish ();
-  return true;
-}
-template <typename Type>
-static inline bool hb_object_set_user_data (Type               *obj,
-					    hb_user_data_key_t *key,
-					    void *              data,
-					    hb_destroy_func_t   destroy,
-					    hb_bool_t           replace)
-{
-  if (unlikely (!obj || hb_object_is_inert (obj)))
-    return false;
-  assert (hb_object_is_valid (obj));
-  return obj->header.user_data.set (key, data, destroy, replace);
-}
-
-template <typename Type>
-static inline void *hb_object_get_user_data (Type               *obj,
-					     hb_user_data_key_t *key)
-{
-  if (unlikely (!obj || hb_object_is_inert (obj)))
-    return nullptr;
-  assert (hb_object_is_valid (obj));
-  return obj->header.user_data.get (key);
-}
-
-
-#endif /* HB_OBJECT_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-open-file-private.hh b/third_party/harfbuzz-ng/src/hb-open-file-private.hh
deleted file mode 100644
index e2644ea..0000000
--- a/third_party/harfbuzz-ng/src/hb-open-file-private.hh
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OPEN_FILE_PRIVATE_HH
-#define HB_OPEN_FILE_PRIVATE_HH
-
-#include "hb-open-type-private.hh"
-#include "hb-ot-head-table.hh"
-
-
-namespace OT {
-
-
-/*
- *
- * The OpenType Font File
- *
- */
-
-
-/*
- * Organization of an OpenType Font
- */
-
-struct OpenTypeFontFile;
-struct OffsetTable;
-struct TTCHeader;
-
-
-typedef struct TableRecord
-{
-  int cmp (Tag t) const
-  { return -t.cmp (tag); }
-
-  static int cmp (const void *pa, const void *pb)
-  {
-    const TableRecord *a = (const TableRecord *) pa;
-    const TableRecord *b = (const TableRecord *) pb;
-    return b->cmp (a->tag);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  Tag		tag;		/* 4-byte identifier. */
-  CheckSum	checkSum;	/* CheckSum for this table. */
-  Offset32	offset;		/* Offset from beginning of TrueType font
-				 * file. */
-  HBUINT32	length;		/* Length of this table. */
-  public:
-  DEFINE_SIZE_STATIC (16);
-} OpenTypeTable;
-
-typedef struct OffsetTable
-{
-  friend struct OpenTypeFontFile;
-
-  inline unsigned int get_table_count (void) const
-  { return tables.len; }
-  inline const TableRecord& get_table (unsigned int i) const
-  {
-    return tables[i];
-  }
-  inline unsigned int get_table_tags (unsigned int  start_offset,
-				      unsigned int *table_count, /* IN/OUT */
-				      hb_tag_t     *table_tags /* OUT */) const
-  {
-    if (table_count)
-    {
-      if (start_offset >= tables.len)
-        *table_count = 0;
-      else
-        *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);
-
-      const TableRecord *sub_tables = tables.array + start_offset;
-      unsigned int count = *table_count;
-      for (unsigned int i = 0; i < count; i++)
-	table_tags[i] = sub_tables[i].tag;
-    }
-    return tables.len;
-  }
-  inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
-  {
-    Tag t;
-    t.set (tag);
-    /* Linear-search for small tables to work around fonts with unsorted
-     * table list. */
-    int i = tables.len < 64 ? tables.lsearch (t) : tables.bsearch (t);
-    if (table_index)
-      *table_index = i == -1 ? Index::NOT_FOUND_INDEX : (unsigned int) i;
-    return i != -1;
-  }
-  inline const TableRecord& get_table_by_tag (hb_tag_t tag) const
-  {
-    unsigned int table_index;
-    find_table_index (tag, &table_index);
-    return get_table (table_index);
-  }
-
-  public:
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 hb_tag_t sfnt_tag,
-			 Supplier<hb_tag_t> &tags,
-			 Supplier<hb_blob_t *> &blobs,
-			 unsigned int table_count)
-  {
-    TRACE_SERIALIZE (this);
-    /* Alloc 12 for the OTHeader. */
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    /* Write sfntVersion (bytes 0..3). */
-    sfnt_version.set (sfnt_tag);
-    /* Take space for numTables, searchRange, entrySelector, RangeShift
-     * and the TableRecords themselves.  */
-    if (unlikely (!tables.serialize (c, table_count))) return_trace (false);
-
-    const char *dir_end = (const char *) c->head;
-    HBUINT32 *checksum_adjustment = nullptr;
-
-    /* Write OffsetTables, alloc for and write actual table blobs. */
-    for (unsigned int i = 0; i < table_count; i++)
-    {
-      TableRecord &rec = tables.array[i];
-      hb_blob_t *blob = blobs[i];
-      rec.tag.set (tags[i]);
-      rec.length.set (hb_blob_get_length (blob));
-      rec.offset.serialize (c, this);
-
-      /* Allocate room for the table and copy it. */
-      char *start = (char *) c->allocate_size<void> (rec.length);
-      if (unlikely (!start)) {return false;}
-
-      memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
-
-      /* 4-byte allignment. */
-      if (rec.length % 4)
-	c->allocate_size<void> (4 - rec.length % 4);
-      const char *end = (const char *) c->head;
-
-      if (tags[i] == HB_OT_TAG_head && end - start >= head::static_size)
-      {
-	head *h = (head *) start;
-	checksum_adjustment = &h->checkSumAdjustment;
-	checksum_adjustment->set (0);
-      }
-
-      rec.checkSum.set_for_data (start, end - start);
-    }
-    tags += table_count;
-    blobs += table_count;
-
-    tables.qsort ();
-
-    if (checksum_adjustment)
-    {
-      CheckSum checksum;
-
-      /* The following line is a slower version of the following block. */
-      //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
-      checksum.set_for_data (this, dir_end - (const char *) this);
-      for (unsigned int i = 0; i < table_count; i++)
-      {
-	TableRecord &rec = tables.array[i];
-	checksum.set (checksum + rec.checkSum);
-      }
-
-      checksum_adjustment->set (0xB1B0AFBAu - checksum);
-    }
-
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && tables.sanitize (c));
-  }
-
-  protected:
-  Tag		sfnt_version;	/* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
-  BinSearchArrayOf<TableRecord>
-		tables;
-  public:
-  DEFINE_SIZE_ARRAY (12, tables);
-} OpenTypeFontFace;
-
-
-/*
- * TrueType Collections
- */
-
-struct TTCHeaderVersion1
-{
-  friend struct TTCHeader;
-
-  inline unsigned int get_face_count (void) const { return table.len; }
-  inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (table.sanitize (c, this));
-  }
-
-  protected:
-  Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
-  FixedVersion<>version;	/* Version of the TTC Header (1.0),
-				 * 0x00010000u */
-  ArrayOf<LOffsetTo<OffsetTable>, HBUINT32>
-		table;		/* Array of offsets to the OffsetTable for each font
-				 * from the beginning of the file */
-  public:
-  DEFINE_SIZE_ARRAY (12, table);
-};
-
-struct TTCHeader
-{
-  friend struct OpenTypeFontFile;
-
-  private:
-
-  inline unsigned int get_face_count (void) const
-  {
-    switch (u.header.version.major) {
-    case 2: /* version 2 is compatible with version 1 */
-    case 1: return u.version1.get_face_count ();
-    default:return 0;
-    }
-  }
-  inline const OpenTypeFontFace& get_face (unsigned int i) const
-  {
-    switch (u.header.version.major) {
-    case 2: /* version 2 is compatible with version 1 */
-    case 1: return u.version1.get_face (i);
-    default:return Null(OpenTypeFontFace);
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
-    switch (u.header.version.major) {
-    case 2: /* version 2 is compatible with version 1 */
-    case 1: return_trace (u.version1.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  struct {
-  Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
-  FixedVersion<>version;	/* Version of the TTC Header (1.0 or 2.0),
-				 * 0x00010000u or 0x00020000u */
-  }			header;
-  TTCHeaderVersion1	version1;
-  } u;
-};
-
-
-/*
- * OpenType Font File
- */
-
-struct OpenTypeFontFile
-{
-  static const hb_tag_t tableTag	= HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */
-
-  static const hb_tag_t CFFTag		= HB_TAG ('O','T','T','O'); /* OpenType with Postscript outlines */
-  static const hb_tag_t TrueTypeTag	= HB_TAG ( 0 , 1 , 0 , 0 ); /* OpenType with TrueType outlines */
-  static const hb_tag_t TTCTag		= HB_TAG ('t','t','c','f'); /* TrueType Collection */
-  static const hb_tag_t TrueTag		= HB_TAG ('t','r','u','e'); /* Obsolete Apple TrueType */
-  static const hb_tag_t Typ1Tag		= HB_TAG ('t','y','p','1'); /* Obsolete Apple Type1 font in SFNT container */
-
-  inline hb_tag_t get_tag (void) const { return u.tag; }
-
-  inline unsigned int get_face_count (void) const
-  {
-    switch (u.tag) {
-    case CFFTag:	/* All the non-collection tags */
-    case TrueTag:
-    case Typ1Tag:
-    case TrueTypeTag:	return 1;
-    case TTCTag:	return u.ttcHeader.get_face_count ();
-    default:		return 0;
-    }
-  }
-  inline const OpenTypeFontFace& get_face (unsigned int i) const
-  {
-    switch (u.tag) {
-    /* Note: for non-collection SFNT data we ignore index.  This is because
-     * Apple dfont container is a container of SFNT's.  So each SFNT is a
-     * non-TTC, but the index is more than zero. */
-    case CFFTag:	/* All the non-collection tags */
-    case TrueTag:
-    case Typ1Tag:
-    case TrueTypeTag:	return u.fontFace;
-    case TTCTag:	return u.ttcHeader.get_face (i);
-    default:		return Null(OpenTypeFontFace);
-    }
-  }
-
-  inline bool serialize_single (hb_serialize_context_t *c,
-				hb_tag_t sfnt_tag,
-			        Supplier<hb_tag_t> &tags,
-			        Supplier<hb_blob_t *> &blobs,
-			        unsigned int table_count)
-  {
-    TRACE_SERIALIZE (this);
-    assert (sfnt_tag != TTCTag);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    return_trace (u.fontFace.serialize (c, sfnt_tag, tags, blobs, table_count));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!u.tag.sanitize (c))) return_trace (false);
-    switch (u.tag) {
-    case CFFTag:	/* All the non-collection tags */
-    case TrueTag:
-    case Typ1Tag:
-    case TrueTypeTag:	return_trace (u.fontFace.sanitize (c));
-    case TTCTag:	return_trace (u.ttcHeader.sanitize (c));
-    default:		return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  Tag			tag;		/* 4-byte identifier. */
-  OpenTypeFontFace	fontFace;
-  TTCHeader		ttcHeader;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (4, tag);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OPEN_FILE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-open-type-private.hh b/third_party/harfbuzz-ng/src/hb-open-type-private.hh
deleted file mode 100644
index 5d33199e..0000000
--- a/third_party/harfbuzz-ng/src/hb-open-type-private.hh
+++ /dev/null
@@ -1,1238 +0,0 @@
-/*
- * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OPEN_TYPE_PRIVATE_HH
-#define HB_OPEN_TYPE_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-face-private.hh"
-
-
-namespace OT {
-
-
-
-/*
- * Casts
- */
-
-/* Cast to struct T, reference to reference */
-template<typename Type, typename TObject>
-static inline const Type& CastR(const TObject &X)
-{ return reinterpret_cast<const Type&> (X); }
-template<typename Type, typename TObject>
-static inline Type& CastR(TObject &X)
-{ return reinterpret_cast<Type&> (X); }
-
-/* Cast to struct T, pointer to pointer */
-template<typename Type, typename TObject>
-static inline const Type* CastP(const TObject *X)
-{ return reinterpret_cast<const Type*> (X); }
-template<typename Type, typename TObject>
-static inline Type* CastP(TObject *X)
-{ return reinterpret_cast<Type*> (X); }
-
-/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
- * location pointed to by P plus Ofs bytes. */
-template<typename Type>
-static inline const Type& StructAtOffset(const void *P, unsigned int offset)
-{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
-template<typename Type>
-static inline Type& StructAtOffset(void *P, unsigned int offset)
-{ return * reinterpret_cast<Type*> ((char *) P + offset); }
-
-/* StructAfter<T>(X) returns the struct T& that is placed after X.
- * Works with X of variable size also.  X must implement get_size() */
-template<typename Type, typename TObject>
-static inline const Type& StructAfter(const TObject &X)
-{ return StructAtOffset<Type>(&X, X.get_size()); }
-template<typename Type, typename TObject>
-static inline Type& StructAfter(TObject &X)
-{ return StructAtOffset<Type>(&X, X.get_size()); }
-
-
-
-/*
- * Size checking
- */
-
-/* Check _assertion in a method environment */
-#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
-  inline void _instance_assertion_on_line_##_line (void) const \
-  { \
-    static_assert ((_assertion), ""); \
-    ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
-  }
-# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
-# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
-
-/* Check that _code compiles in a method environment */
-#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
-  inline void _compiles_assertion_on_line_##_line (void) const \
-  { _code; }
-# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
-# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
-
-
-#define DEFINE_SIZE_STATIC(size) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
-  static const unsigned int static_size = (size); \
-  static const unsigned int min_size = (size); \
-  inline unsigned int get_size (void) const { return (size); }
-
-#define DEFINE_SIZE_UNION(size, _member) \
-  DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
-  static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_MIN(size) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
-  static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_ARRAY(size, array) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
-  DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
-  static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
-  DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
-  static const unsigned int min_size = (size)
-
-
-
-/*
- * Null objects
- */
-
-/* Global nul-content Null pool.  Enlarge as necessary. */
-
-#define HB_NULL_POOL_SIZE 264
-static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE.");
-
-#ifdef HB_NO_VISIBILITY
-static
-#else
-extern HB_INTERNAL
-#endif
-const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)]
-#ifdef HB_NO_VISIBILITY
-= {}
-#endif
-;
-
-/* Generic nul-content Null objects. */
-template <typename Type>
-static inline const Type& Null (void) {
-  static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-  return *CastP<Type> (_hb_NullPool);
-}
-
-/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
-#define DEFINE_NULL_DATA(Type, data) \
-static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \
-template <> \
-/*static*/ inline const Type& Null<Type> (void) { \
-  return *CastP<Type> (_Null##Type); \
-} /* The following line really exists such that we end in a place needing semicolon */ \
-static_assert (Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small.  Enlarge.")
-
-/* Accessor macro. */
-#define Null(Type) Null<Type>()
-
-
-/*
- * Dispatch
- */
-
-template <typename Context, typename Return, unsigned int MaxDebugDepth>
-struct hb_dispatch_context_t
-{
-  static const unsigned int max_debug_depth = MaxDebugDepth;
-  typedef Return return_t;
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
-  static return_t no_dispatch_return_value (void) { return Context::default_return_value (); }
-};
-
-
-/*
- * Sanitize
- */
-
-/* This limits sanitizing time on really broken fonts. */
-#ifndef HB_SANITIZE_MAX_EDITS
-#define HB_SANITIZE_MAX_EDITS 32
-#endif
-#ifndef HB_SANITIZE_MAX_OPS_FACTOR
-#define HB_SANITIZE_MAX_OPS_FACTOR 8
-#endif
-#ifndef HB_SANITIZE_MAX_OPS_MIN
-#define HB_SANITIZE_MAX_OPS_MIN 16384
-#endif
-
-struct hb_sanitize_context_t :
-       hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
-{
-  inline hb_sanitize_context_t (void) :
-	debug_depth (0),
-	start (nullptr), end (nullptr),
-	writable (false), edit_count (0), max_ops (0),
-	blob (nullptr),
-	num_glyphs (0) {}
-
-  inline const char *get_name (void) { return "SANITIZE"; }
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format)
-  { return format->sanitize (this); }
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
-  static return_t default_return_value (void) { return true; }
-  static return_t no_dispatch_return_value (void) { return false; }
-  bool stop_sublookup_iteration (const return_t r) const { return !r; }
-
-  inline void init (hb_blob_t *b)
-  {
-    this->blob = hb_blob_reference (b);
-    this->writable = false;
-  }
-
-  inline void start_processing (void)
-  {
-    this->start = hb_blob_get_data (this->blob, nullptr);
-    this->end = this->start + hb_blob_get_length (this->blob);
-    assert (this->start <= this->end); /* Must not overflow. */
-    this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
-			 (unsigned) HB_SANITIZE_MAX_OPS_MIN);
-    this->edit_count = 0;
-    this->debug_depth = 0;
-
-    DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
-		     "start [%p..%p] (%lu bytes)",
-		     this->start, this->end,
-		     (unsigned long) (this->end - this->start));
-  }
-
-  inline void end_processing (void)
-  {
-    DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
-		     "end [%p..%p] %u edit requests",
-		     this->start, this->end, this->edit_count);
-
-    hb_blob_destroy (this->blob);
-    this->blob = nullptr;
-    this->start = this->end = nullptr;
-  }
-
-  inline bool check_range (const void *base, unsigned int len) const
-  {
-    const char *p = (const char *) base;
-    bool ok = this->max_ops-- > 0 &&
-	      this->start <= p &&
-	      p <= this->end &&
-	      (unsigned int) (this->end - p) >= len;
-
-    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-       "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
-       p, p + len, len,
-       this->start, this->end,
-       ok ? "OK" : "OUT-OF-RANGE");
-
-    return likely (ok);
-  }
-
-  inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
-  {
-    const char *p = (const char *) base;
-    bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
-    unsigned int array_size = record_size * len;
-    bool ok = !overflows && this->check_range (base, array_size);
-
-    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-       "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s",
-       p, p + (record_size * len), record_size, len, (unsigned int) array_size,
-       this->start, this->end,
-       overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE");
-
-    return likely (ok);
-  }
-
-  template <typename Type>
-  inline bool check_struct (const Type *obj) const
-  {
-    return likely (this->check_range (obj, obj->min_size));
-  }
-
-  inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED)
-  {
-    if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
-      return false;
-
-    const char *p = (const char *) base;
-    this->edit_count++;
-
-    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-       "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
-       this->edit_count,
-       p, p + len, len,
-       this->start, this->end,
-       this->writable ? "GRANTED" : "DENIED");
-
-    return this->writable;
-  }
-
-  template <typename Type, typename ValueType>
-  inline bool try_set (const Type *obj, const ValueType &v) {
-    if (this->may_edit (obj, obj->static_size)) {
-      const_cast<Type *> (obj)->set (v);
-      return true;
-    }
-    return false;
-  }
-
-  mutable unsigned int debug_depth;
-  const char *start, *end;
-  bool writable;
-  unsigned int edit_count;
-  mutable int max_ops;
-  hb_blob_t *blob;
-  unsigned int num_glyphs;
-};
-
-
-
-/* Template to sanitize an object. */
-template <typename Type>
-struct Sanitizer
-{
-  inline Sanitizer (void) {}
-
-  inline hb_blob_t *sanitize (hb_blob_t *blob) {
-    bool sane;
-
-    /* TODO is_sane() stuff */
-
-    c->init (blob);
-
-  retry:
-    DEBUG_MSG_FUNC (SANITIZE, c->start, "start");
-
-    c->start_processing ();
-
-    if (unlikely (!c->start)) {
-      c->end_processing ();
-      return blob;
-    }
-
-    Type *t = CastP<Type> (const_cast<char *> (c->start));
-
-    sane = t->sanitize (c);
-    if (sane) {
-      if (c->edit_count) {
-	DEBUG_MSG_FUNC (SANITIZE, c->start, "passed first round with %d edits; going for second round", c->edit_count);
-
-        /* sanitize again to ensure no toe-stepping */
-        c->edit_count = 0;
-	sane = t->sanitize (c);
-	if (c->edit_count) {
-	  DEBUG_MSG_FUNC (SANITIZE, c->start, "requested %d edits in second round; FAILLING", c->edit_count);
-	  sane = false;
-	}
-      }
-    } else {
-      unsigned int edit_count = c->edit_count;
-      if (edit_count && !c->writable) {
-        c->start = hb_blob_get_data_writable (blob, nullptr);
-	c->end = c->start + hb_blob_get_length (blob);
-
-	if (c->start) {
-	  c->writable = true;
-	  /* ok, we made it writable by relocating.  try again */
-	  DEBUG_MSG_FUNC (SANITIZE, c->start, "retry");
-	  goto retry;
-	}
-      }
-    }
-
-    c->end_processing ();
-
-    DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED");
-    if (sane)
-      return blob;
-    else {
-      hb_blob_destroy (blob);
-      return hb_blob_get_empty ();
-    }
-  }
-
-  static const Type* lock_instance (hb_blob_t *blob) {
-    hb_blob_make_immutable (blob);
-    const char *base = hb_blob_get_data (blob, nullptr);
-    return unlikely (!base) ? &Null(Type) : CastP<Type> (base);
-  }
-
-  inline void set_num_glyphs (unsigned int num_glyphs) { c->num_glyphs = num_glyphs; }
-
-  private:
-  hb_sanitize_context_t c[1];
-};
-
-
-
-/*
- * Serialize
- */
-
-
-struct hb_serialize_context_t
-{
-  inline hb_serialize_context_t (void *start_, unsigned int size)
-  {
-    this->start = (char *) start_;
-    this->end = this->start + size;
-
-    this->ran_out_of_room = false;
-    this->head = this->start;
-    this->debug_depth = 0;
-  }
-
-  template <typename Type>
-  inline Type *start_serialize (void)
-  {
-    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
-		     "start [%p..%p] (%lu bytes)",
-		     this->start, this->end,
-		     (unsigned long) (this->end - this->start));
-
-    return start_embed<Type> ();
-  }
-
-  inline void end_serialize (void)
-  {
-    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
-		     "end [%p..%p] serialized %d bytes; %s",
-		     this->start, this->end,
-		     (int) (this->head - this->start),
-		     this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
-
-  }
-
-  template <typename Type>
-  inline Type *copy (void)
-  {
-    assert (!this->ran_out_of_room);
-    unsigned int len = this->head - this->start;
-    void *p = malloc (len);
-    if (p)
-      memcpy (p, this->start, len);
-    return reinterpret_cast<Type *> (p);
-  }
-
-  template <typename Type>
-  inline Type *allocate_size (unsigned int size)
-  {
-    if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) {
-      this->ran_out_of_room = true;
-      return nullptr;
-    }
-    memset (this->head, 0, size);
-    char *ret = this->head;
-    this->head += size;
-    return reinterpret_cast<Type *> (ret);
-  }
-
-  template <typename Type>
-  inline Type *allocate_min (void)
-  {
-    return this->allocate_size<Type> (Type::min_size);
-  }
-
-  template <typename Type>
-  inline Type *start_embed (void)
-  {
-    Type *ret = reinterpret_cast<Type *> (this->head);
-    return ret;
-  }
-
-  template <typename Type>
-  inline Type *embed (const Type &obj)
-  {
-    unsigned int size = obj.get_size ();
-    Type *ret = this->allocate_size<Type> (size);
-    if (unlikely (!ret)) return nullptr;
-    memcpy (ret, obj, size);
-    return ret;
-  }
-
-  template <typename Type>
-  inline Type *extend_min (Type &obj)
-  {
-    unsigned int size = obj.min_size;
-    assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
-    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
-    return reinterpret_cast<Type *> (&obj);
-  }
-
-  template <typename Type>
-  inline Type *extend (Type &obj)
-  {
-    unsigned int size = obj.get_size ();
-    assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
-    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
-    return reinterpret_cast<Type *> (&obj);
-  }
-
-  inline void truncate (void *new_head)
-  {
-    assert (this->start < new_head && new_head <= this->head);
-    this->head = (char *) new_head;
-  }
-
-  unsigned int debug_depth;
-  char *start, *end, *head;
-  bool ran_out_of_room;
-};
-
-template <typename Type>
-struct Supplier
-{
-  inline Supplier (const Type *array, unsigned int len_, unsigned int stride_=sizeof(Type))
-  {
-    head = array;
-    len = len_;
-    stride = stride_;
-  }
-  inline const Type operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len)) return Type ();
-    return * (const Type *) (const void *) ((const char *) head + stride * i);
-  }
-
-  inline Supplier<Type> & operator += (unsigned int count)
-  {
-    if (unlikely (count > len))
-      count = len;
-    len -= count;
-    head = (const Type *) (const void *) ((const char *) head + stride * count);
-    return *this;
-  }
-
-  private:
-  inline Supplier (const Supplier<Type> &); /* Disallow copy */
-  inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
-
-  unsigned int len;
-  unsigned int stride;
-  const Type *head;
-};
-
-
-/*
- *
- * The OpenType Font File: Data Types
- */
-
-
-/* "The following data types are used in the OpenType font file.
- *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
-
-/*
- * Int types
- */
-
-
-template <typename Type, int Bytes> struct BEInt;
-
-template <typename Type>
-struct BEInt<Type, 1>
-{
-  public:
-  inline void set (Type V)
-  {
-    v = V;
-  }
-  inline operator Type (void) const
-  {
-    return v;
-  }
-  private: uint8_t v;
-};
-template <typename Type>
-struct BEInt<Type, 2>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[0] = (V >>  8) & 0xFF;
-    v[1] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[0] <<  8)
-         + (v[1]      );
-  }
-  private: uint8_t v[2];
-};
-template <typename Type>
-struct BEInt<Type, 3>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[0] = (V >> 16) & 0xFF;
-    v[1] = (V >>  8) & 0xFF;
-    v[2] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[0] << 16)
-         + (v[1] <<  8)
-         + (v[2]      );
-  }
-  private: uint8_t v[3];
-};
-template <typename Type>
-struct BEInt<Type, 4>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[0] = (V >> 24) & 0xFF;
-    v[1] = (V >> 16) & 0xFF;
-    v[2] = (V >>  8) & 0xFF;
-    v[3] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[0] << 24)
-         + (v[1] << 16)
-         + (v[2] <<  8)
-         + (v[3]      );
-  }
-  private: uint8_t v[4];
-};
-
-/* Integer types in big-endian order and no alignment requirement */
-template <typename Type, unsigned int Size>
-struct IntType
-{
-  inline void set (Type i) { v.set (i); }
-  inline operator Type(void) const { return v; }
-  inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
-  inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
-  static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
-  template <typename Type2>
-  inline int cmp (Type2 a) const
-  {
-    Type b = v;
-    if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
-      return (int) a - (int) b;
-    else
-      return a < b ? -1 : a == b ? 0 : +1;
-  }
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)));
-  }
-  protected:
-  BEInt<Type, Size> v;
-  public:
-  DEFINE_SIZE_STATIC (Size);
-};
-
-typedef IntType<uint8_t,  1> HBUINT8;	/* 8-bit unsigned integer. */
-typedef IntType<int8_t,   1> HBINT8;	/* 8-bit signed integer. */
-typedef IntType<uint16_t, 2> HBUINT16;	/* 16-bit unsigned integer. */
-typedef IntType<int16_t,  2> HBINT16;	/* 16-bit signed integer. */
-typedef IntType<uint32_t, 4> HBUINT32;	/* 32-bit unsigned integer. */
-typedef IntType<int32_t,  4> HBINT32;	/* 32-bit signed integer. */
-typedef IntType<uint32_t, 3> UINT24;	/* 24-bit unsigned integer. */
-
-/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
-typedef HBINT16 FWORD;
-
-/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
-typedef HBUINT16 UFWORD;
-
-/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
-struct F2DOT14 : HBINT16
-{
-  //inline float to_float (void) const { return ???; }
-  //inline void set_float (float f) { v.set (f * ???); }
-  public:
-  DEFINE_SIZE_STATIC (2);
-};
-
-/* 32-bit signed fixed-point number (16.16). */
-struct Fixed: HBINT32
-{
-  inline float to_float (void) const { return ((int32_t) v) / 65536.0; }
-  inline void set_float (float f) { v.set (round (f * 65536.0)); }
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-/* Date represented in number of seconds since 12:00 midnight, January 1,
- * 1904. The value is represented as a signed 64-bit integer. */
-struct LONGDATETIME
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)));
-  }
-  protected:
-  HBINT32 major;
-  HBUINT32 minor;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-/* Array of four uint8s (length = 32 bits) used to identify a script, language
- * system, feature, or baseline */
-struct Tag : HBUINT32
-{
-  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
-  inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
-  inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-DEFINE_NULL_DATA (Tag, "    ");
-
-/* Glyph index number, same as uint16 (length = 16 bits) */
-typedef HBUINT16 GlyphID;
-
-/* Script/language-system/feature index */
-struct Index : HBUINT16 {
-  static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
-};
-DEFINE_NULL_DATA (Index, "\xff\xff");
-
-/* Offset, Null offset = 0 */
-template <typename Type>
-struct Offset : Type
-{
-  inline bool is_null (void) const { return 0 == *this; }
-
-  inline void *serialize (hb_serialize_context_t *c, const void *base)
-  {
-    void *t = c->start_embed<void> ();
-    this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
-    return t;
-  }
-
-  public:
-  DEFINE_SIZE_STATIC (sizeof(Type));
-};
-
-typedef Offset<HBUINT16> Offset16;
-typedef Offset<HBUINT32> Offset32;
-
-
-/* CheckSum */
-struct CheckSum : HBUINT32
-{
-  /* This is reference implementation from the spec. */
-  static inline uint32_t CalcTableChecksum (const HBUINT32 *Table, uint32_t Length)
-  {
-    uint32_t Sum = 0L;
-    assert (0 == (Length & 3));
-    const HBUINT32 *EndPtr = Table + Length / HBUINT32::static_size;
-
-    while (Table < EndPtr)
-      Sum += *Table++;
-    return Sum;
-  }
-
-  /* Note: data should be 4byte aligned and have 4byte padding at the end. */
-  inline void set_for_data (const void *data, unsigned int length)
-  { set (CalcTableChecksum ((const HBUINT32 *) data, length)); }
-
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-
-/*
- * Version Numbers
- */
-
-template <typename FixedType=HBUINT16>
-struct FixedVersion
-{
-  inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  FixedType major;
-  FixedType minor;
-  public:
-  DEFINE_SIZE_STATIC (2 * sizeof(FixedType));
-};
-
-
-
-/*
- * Template subclasses of Offset that do the dereferencing.
- * Use: (base+offset)
- */
-
-template <typename Type, typename OffsetType=HBUINT16>
-struct OffsetTo : Offset<OffsetType>
-{
-  inline const Type& operator () (const void *base) const
-  {
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return Null(Type);
-    return StructAtOffset<Type> (base, offset);
-  }
-
-  inline Type& serialize (hb_serialize_context_t *c, const void *base)
-  {
-    return * (Type *) Offset<OffsetType>::serialize (c, base);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return_trace (false);
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return_trace (true);
-    if (unlikely (!c->check_range (base, offset))) return_trace (false);
-    const Type &obj = StructAtOffset<Type> (base, offset);
-    return_trace (likely (obj.sanitize (c)) || neuter (c));
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return_trace (false);
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return_trace (true);
-    if (unlikely (!c->check_range (base, offset))) return_trace (false);
-    const Type &obj = StructAtOffset<Type> (base, offset);
-    return_trace (likely (obj.sanitize (c, user_data)) || neuter (c));
-  }
-
-  /* Set the offset to Null */
-  inline bool neuter (hb_sanitize_context_t *c) const {
-    return c->try_set (this, 0);
-  }
-  DEFINE_SIZE_STATIC (sizeof(OffsetType));
-};
-template <typename Type> struct LOffsetTo : OffsetTo<Type, HBUINT32> {};
-template <typename Base, typename OffsetType, typename Type>
-static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
-template <typename Base, typename OffsetType, typename Type>
-static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
-
-
-/*
- * Array Types
- */
-
-/* An array with a number of elements. */
-template <typename Type, typename LenType=HBUINT16>
-struct ArrayOf
-{
-  const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
-  {
-    unsigned int count = len;
-    if (unlikely (start_offset > count))
-      count = 0;
-    else
-      count -= start_offset;
-    count = MIN (count, *pcount);
-    *pcount = count;
-    return array + start_offset;
-  }
-
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len)) return Null(Type);
-    return array[i];
-  }
-  inline Type& operator [] (unsigned int i)
-  {
-    return array[i];
-  }
-  inline unsigned int get_size (void) const
-  { return len.static_size + len * Type::static_size; }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 unsigned int items_len)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    len.set (items_len); /* TODO(serialize) Overflow? */
-    if (unlikely (!c->extend (*this))) return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<Type> &items,
-			 unsigned int items_len)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!serialize (c, items_len))) return_trace (false);
-    for (unsigned int i = 0; i < items_len; i++)
-      array[i] = items[i];
-    items += items_len;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize(), ie. they do not
-     * reference other structs via offsets.
-     */
-    (void) (false && array[0].sanitize (c));
-
-    return_trace (true);
-  }
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!array[i].sanitize (c, base)))
-        return_trace (false);
-    return_trace (true);
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!array[i].sanitize (c, base, user_data)))
-        return_trace (false);
-    return_trace (true);
-  }
-
-  template <typename SearchType>
-  inline int lsearch (const SearchType &x) const
-  {
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!this->array[i].cmp (x))
-        return i;
-    return -1;
-  }
-
-  inline void qsort (void)
-  {
-    ::qsort (array, len, sizeof (Type), Type::cmp);
-  }
-
-  private:
-  inline bool sanitize_shallow (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (len.sanitize (c) && c->check_array (array, Type::static_size, len));
-  }
-
-  public:
-  LenType len;
-  Type array[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (sizeof (LenType), array);
-};
-template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {};
-
-/* Array of Offset's */
-template <typename Type, typename OffsetType=HBUINT16>
-struct OffsetArrayOf : ArrayOf<OffsetTo<Type, OffsetType> > {};
-
-/* Array of offsets relative to the beginning of the array itself. */
-template <typename Type>
-struct OffsetListOf : OffsetArrayOf<Type>
-{
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= this->len)) return Null(Type);
-    return this+this->array[i];
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (OffsetArrayOf<Type>::sanitize (c, this));
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
-  }
-};
-
-
-/* An array starting at second element. */
-template <typename Type, typename LenType=HBUINT16>
-struct HeadlessArrayOf
-{
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len || !i)) return Null(Type);
-    return array[i-1];
-  }
-  inline unsigned int get_size (void) const
-  { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<Type> &items,
-			 unsigned int items_len)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    len.set (items_len); /* TODO(serialize) Overflow? */
-    if (unlikely (!items_len)) return_trace (true);
-    if (unlikely (!c->extend (*this))) return_trace (false);
-    for (unsigned int i = 0; i < items_len - 1; i++)
-      array[i] = items[i];
-    items += items_len - 1;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize(), ie. they do not
-     * reference other structs via offsets.
-     */
-    (void) (false && array[0].sanitize (c));
-
-    return_trace (true);
-  }
-
-  private:
-  inline bool sanitize_shallow (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (len.sanitize (c) &&
-		  (!len || c->check_array (array, Type::static_size, len - 1)));
-  }
-
-  public:
-  LenType len;
-  Type array[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (sizeof (LenType), array);
-};
-
-
-/*
- * An array with sorted elements.  Supports binary searching.
- */
-template <typename Type, typename LenType=HBUINT16>
-struct SortedArrayOf : ArrayOf<Type, LenType>
-{
-  template <typename SearchType>
-  inline int bsearch (const SearchType &x) const
-  {
-    /* Hand-coded bsearch here since this is in the hot inner loop. */
-    const Type *arr = this->array;
-    int min = 0, max = (int) this->len - 1;
-    while (min <= max)
-    {
-      int mid = (min + max) / 2;
-      int c = arr[mid].cmp (x);
-      if (c < 0)
-        max = mid - 1;
-      else if (c > 0)
-        min = mid + 1;
-      else
-        return mid;
-    }
-    return -1;
-  }
-};
-
-/*
- * Binary-search arrays
- */
-
-struct BinSearchHeader
-{
-  inline operator uint32_t (void) const { return len; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  inline void set (unsigned int v)
-  {
-    len.set (v);
-    assert (len == v);
-    entrySelectorZ.set (MAX (1u, _hb_bit_storage (v)) - 1);
-    searchRangeZ.set (16 * (1u << entrySelectorZ));
-    rangeShiftZ.set (v * 16 > searchRangeZ
-                     ? 16 * v - searchRangeZ
-                     : 0);
-  }
-
-  protected:
-  HBUINT16	len;
-  HBUINT16	searchRangeZ;
-  HBUINT16	entrySelectorZ;
-  HBUINT16	rangeShiftZ;
-
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-template <typename Type>
-struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader> {};
-
-
-/* Lazy struct and blob loaders. */
-
-/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */
-template <typename T>
-struct hb_lazy_loader_t
-{
-  inline void init (hb_face_t *face_)
-  {
-    face = face_;
-    instance = nullptr;
-  }
-
-  inline void fini (void)
-  {
-    if (instance && instance != &OT::Null(T))
-    {
-      instance->fini();
-      free (instance);
-    }
-  }
-
-  inline const T* get (void) const
-  {
-  retry:
-    T *p = (T *) hb_atomic_ptr_get (&instance);
-    if (unlikely (!p))
-    {
-      p = (T *) calloc (1, sizeof (T));
-      if (unlikely (!p))
-        p = const_cast<T *> (&OT::Null(T));
-      else
-	p->init (face);
-      if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p)))
-      {
-	if (p != &OT::Null(T))
-	  p->fini ();
-	goto retry;
-      }
-    }
-    return p;
-  }
-
-  inline const T* operator-> (void) const
-  {
-    return get ();
-  }
-
-  private:
-  hb_face_t *face;
-  T *instance;
-};
-
-/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */
-template <typename T>
-struct hb_lazy_table_loader_t
-{
-  inline void init (hb_face_t *face_)
-  {
-    face = face_;
-    blob = nullptr;
-    instance = nullptr;
-  }
-
-  inline void fini (void)
-  {
-    hb_blob_destroy (blob);
-  }
-
-  inline const T* get (void) const
-  {
-  retry:
-    T *p = (T *) hb_atomic_ptr_get (&instance);
-    if (unlikely (!p))
-    {
-      hb_blob_t *blob_ = OT::Sanitizer<T>().sanitize (face->reference_table (T::tableTag));
-      p = const_cast<T *>(OT::Sanitizer<T>::lock_instance (blob_));
-      if (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p))
-      {
-	hb_blob_destroy (blob_);
-	goto retry;
-      }
-      blob = blob_;
-    }
-    return p;
-  }
-
-  inline const T* operator-> (void) const
-  {
-    return get();
-  }
-
-  hb_face_t *face;
-  mutable hb_blob_t *blob;
-  private:
-  mutable T *instance;
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OPEN_TYPE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-cmap-table.hh b/third_party/harfbuzz-ng/src/hb-ot-cmap-table.hh
deleted file mode 100644
index 02079898..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-cmap-table.hh
+++ /dev/null
@@ -1,789 +0,0 @@
-/*
- * Copyright © 2014  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_CMAP_TABLE_HH
-#define HB_OT_CMAP_TABLE_HH
-
-#include "hb-open-type-private.hh"
-#include "hb-subset-plan.hh"
-
-namespace OT {
-
-
-/*
- * cmap -- Character To Glyph Index Mapping Table
- */
-
-#define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
-
-
-struct CmapSubtableFormat0
-{
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
-  {
-    hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0;
-    if (!gid)
-      return false;
-    *glyph = gid;
-    return true;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16	format;		/* Format number is set to 0. */
-  HBUINT16	lengthZ;	/* Byte length of this subtable. */
-  HBUINT16	languageZ;	/* Ignore. */
-  HBUINT8	glyphIdArray[256];/* An array that maps character
-				 * code to glyph index values. */
-  public:
-  DEFINE_SIZE_STATIC (6 + 256);
-};
-
-struct CmapSubtableFormat4
-{
-  struct accelerator_t
-  {
-    inline void init (const CmapSubtableFormat4 *subtable)
-    {
-      segCount = subtable->segCountX2 / 2;
-      endCount = subtable->values;
-      startCount = endCount + segCount + 1;
-      idDelta = startCount + segCount;
-      idRangeOffset = idDelta + segCount;
-      glyphIdArray = idRangeOffset + segCount;
-      glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2;
-    }
-
-    static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
-    {
-      const accelerator_t *thiz = (const accelerator_t *) obj;
-
-      /* Custom two-array bsearch. */
-      int min = 0, max = (int) thiz->segCount - 1;
-      const HBUINT16 *startCount = thiz->startCount;
-      const HBUINT16 *endCount = thiz->endCount;
-      unsigned int i;
-      while (min <= max)
-      {
-	int mid = (min + max) / 2;
-	if (codepoint < startCount[mid])
-	  max = mid - 1;
-	else if (codepoint > endCount[mid])
-	  min = mid + 1;
-	else
-	{
-	  i = mid;
-	  goto found;
-	}
-      }
-      return false;
-
-    found:
-      hb_codepoint_t gid;
-      unsigned int rangeOffset = thiz->idRangeOffset[i];
-      if (rangeOffset == 0)
-	gid = codepoint + thiz->idDelta[i];
-      else
-      {
-	/* Somebody has been smoking... */
-	unsigned int index = rangeOffset / 2 + (codepoint - thiz->startCount[i]) + i - thiz->segCount;
-	if (unlikely (index >= thiz->glyphIdArrayLength))
-	  return false;
-	gid = thiz->glyphIdArray[index];
-	if (unlikely (!gid))
-	  return false;
-	gid += thiz->idDelta[i];
-      }
-
-      *glyph = gid & 0xFFFFu;
-      return true;
-    }
-
-    const HBUINT16 *endCount;
-    const HBUINT16 *startCount;
-    const HBUINT16 *idDelta;
-    const HBUINT16 *idRangeOffset;
-    const HBUINT16 *glyphIdArray;
-    unsigned int segCount;
-    unsigned int glyphIdArrayLength;
-  };
-
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
-  {
-    accelerator_t accel;
-    accel.init (this);
-    return accel.get_glyph_func (&accel, codepoint, glyph);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this)))
-      return_trace (false);
-
-    if (unlikely (!c->check_range (this, length)))
-    {
-      /* Some broken fonts have too long of a "length" value.
-       * If that is the case, just change the value to truncate
-       * the subtable at the end of the blob. */
-      uint16_t new_length = (uint16_t) MIN ((uintptr_t) 65535,
-					    (uintptr_t) (c->end -
-							 (char *) this));
-      if (!c->try_set (&length, new_length))
-	return_trace (false);
-    }
-
-    return_trace (16 + 4 * (unsigned int) segCountX2 <= length);
-  }
-
-  protected:
-  HBUINT16	format;		/* Format number is set to 4. */
-  HBUINT16	length;		/* This is the length in bytes of the
-				 * subtable. */
-  HBUINT16	languageZ;	/* Ignore. */
-  HBUINT16	segCountX2;	/* 2 x segCount. */
-  HBUINT16	searchRangeZ;	/* 2 * (2**floor(log2(segCount))) */
-  HBUINT16	entrySelectorZ;	/* log2(searchRange/2) */
-  HBUINT16	rangeShiftZ;	/* 2 x segCount - searchRange */
-
-  HBUINT16	values[VAR];
-#if 0
-  HBUINT16	endCount[segCount];	/* End characterCode for each segment,
-					 * last=0xFFFFu. */
-  HBUINT16	reservedPad;		/* Set to 0. */
-  HBUINT16	startCount[segCount];	/* Start character code for each segment. */
-  HBINT16		idDelta[segCount];	/* Delta for all character codes in segment. */
-  HBUINT16	idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
-  HBUINT16	glyphIdArray[VAR];	/* Glyph index array (arbitrary length) */
-#endif
-
-  public:
-  DEFINE_SIZE_ARRAY (14, values);
-};
-
-struct CmapSubtableLongGroup
-{
-  friend struct CmapSubtableFormat12;
-  friend struct CmapSubtableFormat13;
-  friend struct cmap;
-
-  int cmp (hb_codepoint_t codepoint) const
-  {
-    if (codepoint < startCharCode) return -1;
-    if (codepoint > endCharCode)   return +1;
-    return 0;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  private:
-  HBUINT32		startCharCode;	/* First character code in this group. */
-  HBUINT32		endCharCode;	/* Last character code in this group. */
-  HBUINT32		glyphID;	/* Glyph index; interpretation depends on
-				 * subtable format. */
-  public:
-  DEFINE_SIZE_STATIC (12);
-};
-
-template <typename UINT>
-struct CmapSubtableTrimmed
-{
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
-  {
-    /* Rely on our implicit array bound-checking. */
-    hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
-    if (!gid)
-      return false;
-    *glyph = gid;
-    return true;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && glyphIdArray.sanitize (c));
-  }
-
-  protected:
-  UINT		formatReserved;	/* Subtable format and (maybe) padding. */
-  UINT		lengthZ;	/* Byte length of this subtable. */
-  UINT		languageZ;	/* Ignore. */
-  UINT		startCharCode;	/* First character code covered. */
-  ArrayOf<GlyphID, UINT>
-		glyphIdArray;	/* Array of glyph index values for character
-				 * codes in the range. */
-  public:
-  DEFINE_SIZE_ARRAY (5 * sizeof (UINT), glyphIdArray);
-};
-
-struct CmapSubtableFormat6  : CmapSubtableTrimmed<HBUINT16> {};
-struct CmapSubtableFormat10 : CmapSubtableTrimmed<HBUINT32 > {};
-
-template <typename T>
-struct CmapSubtableLongSegmented
-{
-  friend struct cmap;
-
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
-  {
-    int i = groups.bsearch (codepoint);
-    if (i == -1)
-      return false;
-    *glyph = T::group_get_glyph (groups[i], codepoint);
-    return true;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && groups.sanitize (c));
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         hb_prealloced_array_t<CmapSubtableLongGroup> &group_data)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    Supplier<CmapSubtableLongGroup> supplier (group_data.array, group_data.len);
-    if (unlikely (!groups.serialize (c, supplier, group_data.len))) return_trace (false);
-    return true;
-  }
-
-  protected:
-  HBUINT16	format;		/* Subtable format; set to 12. */
-  HBUINT16	reservedZ;	/* Reserved; set to 0. */
-  HBUINT32		lengthZ;	/* Byte length of this subtable. */
-  HBUINT32		languageZ;	/* Ignore. */
-  SortedArrayOf<CmapSubtableLongGroup, HBUINT32>
-		groups;		/* Groupings. */
-  public:
-  DEFINE_SIZE_ARRAY (16, groups);
-};
-
-struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
-{
-  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
-						hb_codepoint_t u)
-  { return group.glyphID + (u - group.startCharCode); }
-};
-
-struct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
-{
-  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
-						hb_codepoint_t u HB_UNUSED)
-  { return group.glyphID; }
-};
-
-typedef enum
-{
-  GLYPH_VARIANT_NOT_FOUND = 0,
-  GLYPH_VARIANT_FOUND = 1,
-  GLYPH_VARIANT_USE_DEFAULT = 2
-} glyph_variant_t;
-
-struct UnicodeValueRange
-{
-  inline int cmp (const hb_codepoint_t &codepoint) const
-  {
-    if (codepoint < startUnicodeValue) return -1;
-    if (codepoint > startUnicodeValue + additionalCount) return +1;
-    return 0;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  UINT24	startUnicodeValue;	/* First value in this range. */
-  HBUINT8		additionalCount;	/* Number of additional values in this
-					 * range. */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-typedef SortedArrayOf<UnicodeValueRange, HBUINT32> DefaultUVS;
-
-struct UVSMapping
-{
-  inline int cmp (const hb_codepoint_t &codepoint) const
-  {
-    return unicodeValue.cmp (codepoint);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  UINT24	unicodeValue;	/* Base Unicode value of the UVS */
-  GlyphID	glyphID;	/* Glyph ID of the UVS */
-  public:
-  DEFINE_SIZE_STATIC (5);
-};
-
-typedef SortedArrayOf<UVSMapping, HBUINT32> NonDefaultUVS;
-
-struct VariationSelectorRecord
-{
-  inline glyph_variant_t get_glyph (hb_codepoint_t codepoint,
-				    hb_codepoint_t *glyph,
-				    const void *base) const
-  {
-    int i;
-    const DefaultUVS &defaults = base+defaultUVS;
-    i = defaults.bsearch (codepoint);
-    if (i != -1)
-      return GLYPH_VARIANT_USE_DEFAULT;
-    const NonDefaultUVS &nonDefaults = base+nonDefaultUVS;
-    i = nonDefaults.bsearch (codepoint);
-    if (i != -1)
-    {
-      *glyph = nonDefaults[i].glyphID;
-       return GLYPH_VARIANT_FOUND;
-    }
-    return GLYPH_VARIANT_NOT_FOUND;
-  }
-
-  inline int cmp (const hb_codepoint_t &variation_selector) const
-  {
-    return varSelector.cmp (variation_selector);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  defaultUVS.sanitize (c, base) &&
-		  nonDefaultUVS.sanitize (c, base));
-  }
-
-  UINT24	varSelector;	/* Variation selector. */
-  LOffsetTo<DefaultUVS>
-		defaultUVS;	/* Offset to Default UVS Table. May be 0. */
-  LOffsetTo<NonDefaultUVS>
-		nonDefaultUVS;	/* Offset to Non-Default UVS Table. May be 0. */
-  public:
-  DEFINE_SIZE_STATIC (11);
-};
-
-struct CmapSubtableFormat14
-{
-  inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
-					    hb_codepoint_t variation_selector,
-					    hb_codepoint_t *glyph) const
-  {
-    return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  record.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16	format;		/* Format number is set to 14. */
-  HBUINT32		lengthZ;	/* Byte length of this subtable. */
-  SortedArrayOf<VariationSelectorRecord, HBUINT32>
-		record;		/* Variation selector records; sorted
-				 * in increasing order of `varSelector'. */
-  public:
-  DEFINE_SIZE_ARRAY (10, record);
-};
-
-struct CmapSubtable
-{
-  /* Note: We intentionally do NOT implement subtable formats 2 and 8. */
-
-  inline bool get_glyph (hb_codepoint_t codepoint,
-			 hb_codepoint_t *glyph) const
-  {
-    switch (u.format) {
-    case  0: return u.format0 .get_glyph (codepoint, glyph);
-    case  4: return u.format4 .get_glyph (codepoint, glyph);
-    case  6: return u.format6 .get_glyph (codepoint, glyph);
-    case 10: return u.format10.get_glyph (codepoint, glyph);
-    case 12: return u.format12.get_glyph (codepoint, glyph);
-    case 13: return u.format13.get_glyph (codepoint, glyph);
-    case 14:
-    default: return false;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case  0: return_trace (u.format0 .sanitize (c));
-    case  4: return_trace (u.format4 .sanitize (c));
-    case  6: return_trace (u.format6 .sanitize (c));
-    case 10: return_trace (u.format10.sanitize (c));
-    case 12: return_trace (u.format12.sanitize (c));
-    case 13: return_trace (u.format13.sanitize (c));
-    case 14: return_trace (u.format14.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  public:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  CmapSubtableFormat0	format0;
-  CmapSubtableFormat4	format4;
-  CmapSubtableFormat6	format6;
-  CmapSubtableFormat10	format10;
-  CmapSubtableFormat12	format12;
-  CmapSubtableFormat13	format13;
-  CmapSubtableFormat14	format14;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-
-struct EncodingRecord
-{
-  inline int cmp (const EncodingRecord &other) const
-  {
-    int ret;
-    ret = platformID.cmp (other.platformID);
-    if (ret) return ret;
-    ret = encodingID.cmp (other.encodingID);
-    if (ret) return ret;
-    return 0;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  subtable.sanitize (c, base));
-  }
-
-  HBUINT16	platformID;	/* Platform ID. */
-  HBUINT16	encodingID;	/* Platform-specific encoding ID. */
-  LOffsetTo<CmapSubtable>
-		subtable;	/* Byte offset from beginning of table to the subtable for this encoding. */
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct cmap
-{
-  static const hb_tag_t tableTag	= HB_OT_TAG_cmap;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  likely (version == 0) &&
-		  encodingRecord.sanitize (c, this));
-  }
-
-  inline bool populate_groups (hb_subset_plan_t *plan,
-			       hb_prealloced_array_t<CmapSubtableLongGroup> *groups) const
-  {
-    CmapSubtableLongGroup *group = nullptr;
-    for (unsigned int i = 0; i < plan->codepoints.len; i++) {
-
-      hb_codepoint_t cp = plan->codepoints[i];
-      if (!group || cp - 1 != group->endCharCode)
-      {
-        group = groups->push ();
-        group->startCharCode.set (cp);
-        group->endCharCode.set (cp);
-        hb_codepoint_t new_gid;
-        if (unlikely (!hb_subset_plan_new_gid_for_codepoint (plan, cp, &new_gid)))
-        {
-          DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
-          return false;
-        }
-        group->glyphID.set (new_gid);
-      } else
-      {
-        group->endCharCode.set (cp);
-      }
-    }
-
-    DEBUG_MSG(SUBSET, nullptr, "cmap");
-    for (unsigned int i = 0; i < groups->len; i++) {
-      CmapSubtableLongGroup& group = (*groups)[i];
-      DEBUG_MSG(SUBSET, nullptr, "  %d: U+%04X-U+%04X, gid %d-%d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID, (uint32_t) group.glyphID + ((uint32_t) group.endCharCode - (uint32_t) group.startCharCode));
-    }
-
-    return true;
-  }
-
-  inline bool _subset (hb_prealloced_array_t<CmapSubtableLongGroup> &groups,
-		       size_t dest_sz,
-		       void *dest) const
-  {
-    hb_serialize_context_t c (dest, dest_sz);
-
-    OT::cmap *cmap = c.start_serialize<OT::cmap> ();
-    if (unlikely (!c.extend_min (*cmap)))
-    {
-      return false;
-    }
-
-    cmap->version.set (0);
-
-    if (unlikely (!cmap->encodingRecord.serialize (&c, /* numTables */ 1))) return false;
-
-    EncodingRecord &rec = cmap->encodingRecord[0];
-    rec.platformID.set (3); // Windows
-    rec.encodingID.set (10); // Unicode UCS-4
-
-    /* capture offset to subtable */
-    CmapSubtable &subtable = rec.subtable.serialize (&c, cmap);
-
-    subtable.u.format.set (12);
-
-    CmapSubtableFormat12 &format12 = subtable.u.format12;
-    if (unlikely (!c.extend_min (format12))) return false;
-
-    format12.format.set (12);
-    format12.reservedZ.set (0);
-    format12.lengthZ.set (16 + 12 * groups.len);
-
-    if (unlikely (!format12.serialize (&c, groups))) return false;
-
-    c.end_serialize ();
-
-    return true;
-  }
-
-  inline bool subset (hb_subset_plan_t *plan) const
-  {
-    hb_auto_array_t<CmapSubtableLongGroup> groups;
-
-    if (unlikely (!populate_groups (plan, &groups))) return false;
-
-    // We now know how big our blob needs to be
-    // TODO use APIs from the structs to get size?
-    size_t dest_sz = 4 // header
-                   + 8 // 1 EncodingRecord
-                   + 16 // Format 12 header
-                   + 12 * groups.len; // SequentialMapGroup records
-    void *dest = malloc (dest_sz);
-    if (unlikely (!dest)) {
-      DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for cmap subset output", (unsigned long) dest_sz);
-      return false;
-    }
-
-    if (unlikely (!_subset (groups, dest_sz, dest)))
-    {
-      free (dest);
-      return false;
-    }
-
-    // all done, write the blob into dest
-    hb_blob_t *cmap_prime = hb_blob_create ((const char *)dest,
-                                            dest_sz,
-                                            HB_MEMORY_MODE_READONLY,
-                                            dest,
-                                            free);
-    bool result =  hb_subset_plan_add_table (plan, HB_OT_TAG_cmap, cmap_prime);
-    hb_blob_destroy (cmap_prime);
-    return result;
-  }
-
-  struct accelerator_t
-  {
-    inline void init (hb_face_t *face)
-    {
-      this->blob = OT::Sanitizer<OT::cmap>().sanitize (face->reference_table (HB_OT_TAG_cmap));
-      const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
-      const OT::CmapSubtable *subtable = nullptr;
-      const OT::CmapSubtableFormat14 *subtable_uvs = nullptr;
-
-      bool symbol = false;
-      /* 32-bit subtables. */
-      if (!subtable) subtable = cmap->find_subtable (3, 10);
-      if (!subtable) subtable = cmap->find_subtable (0, 6);
-      if (!subtable) subtable = cmap->find_subtable (0, 4);
-      /* 16-bit subtables. */
-      if (!subtable) subtable = cmap->find_subtable (3, 1);
-      if (!subtable) subtable = cmap->find_subtable (0, 3);
-      if (!subtable) subtable = cmap->find_subtable (0, 2);
-      if (!subtable) subtable = cmap->find_subtable (0, 1);
-      if (!subtable) subtable = cmap->find_subtable (0, 0);
-      if (!subtable)
-      {
-	subtable = cmap->find_subtable (3, 0);
-	if (subtable) symbol = true;
-      }
-      /* Meh. */
-      if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
-
-      /* UVS subtable. */
-      if (!subtable_uvs)
-      {
-	const OT::CmapSubtable *st = cmap->find_subtable (0, 5);
-	if (st && st->u.format == 14)
-	  subtable_uvs = &st->u.format14;
-      }
-      /* Meh. */
-      if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtableFormat14);
-
-      this->uvs_table = subtable_uvs;
-
-      this->get_glyph_data = subtable;
-      if (unlikely (symbol))
-	this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>;
-      else
-	switch (subtable->u.format) {
-	/* Accelerate format 4 and format 12. */
-	default: this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;		break;
-	case 12: this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;	break;
-	case  4:
-	  {
-	    this->format4_accel.init (&subtable->u.format4);
-	    this->get_glyph_data = &this->format4_accel;
-	    this->get_glyph_func = this->format4_accel.get_glyph_func;
-	  }
-	  break;
-	}
-    }
-
-    inline void fini (void)
-    {
-      hb_blob_destroy (this->blob);
-    }
-
-    inline bool get_nominal_glyph (hb_codepoint_t  unicode,
-				   hb_codepoint_t *glyph) const
-    {
-      return this->get_glyph_func (this->get_glyph_data, unicode, glyph);
-    }
-
-    inline bool get_variation_glyph (hb_codepoint_t  unicode,
-				     hb_codepoint_t  variation_selector,
-				     hb_codepoint_t *glyph) const
-    {
-      switch (this->uvs_table->get_glyph_variant (unicode,
-						  variation_selector,
-						  glyph))
-      {
-	case OT::GLYPH_VARIANT_NOT_FOUND:		return false;
-	case OT::GLYPH_VARIANT_FOUND:		return true;
-	case OT::GLYPH_VARIANT_USE_DEFAULT:	break;
-      }
-
-      return get_nominal_glyph (unicode, glyph);
-    }
-
-    protected:
-    typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
-					      hb_codepoint_t codepoint,
-					      hb_codepoint_t *glyph);
-
-    template <typename Type>
-    static inline bool get_glyph_from (const void *obj,
-				       hb_codepoint_t codepoint,
-				       hb_codepoint_t *glyph)
-    {
-      const Type *typed_obj = (const Type *) obj;
-      return typed_obj->get_glyph (codepoint, glyph);
-    }
-
-    template <typename Type>
-    static inline bool get_glyph_from_symbol (const void *obj,
-					      hb_codepoint_t codepoint,
-					      hb_codepoint_t *glyph)
-    {
-      const Type *typed_obj = (const Type *) obj;
-      if (likely (typed_obj->get_glyph (codepoint, glyph)))
-	return true;
-
-      if (codepoint <= 0x00FFu)
-      {
-	/* For symbol-encoded OpenType fonts, we duplicate the
-	 * U+F000..F0FF range at U+0000..U+00FF.  That's what
-	 * Windows seems to do, and that's hinted about at:
-	 * http://www.microsoft.com/typography/otspec/recom.htm
-	 * under "Non-Standard (Symbol) Fonts". */
-	return typed_obj->get_glyph (0xF000u + codepoint, glyph);
-      }
-
-      return false;
-    }
-
-    private:
-    hb_cmap_get_glyph_func_t get_glyph_func;
-    const void *get_glyph_data;
-    OT::CmapSubtableFormat4::accelerator_t format4_accel;
-
-    const OT::CmapSubtableFormat14 *uvs_table;
-    hb_blob_t *blob;
-  };
-
-  protected:
-
-  inline const CmapSubtable *find_subtable (unsigned int platform_id,
-					    unsigned int encoding_id) const
-  {
-    EncodingRecord key;
-    key.platformID.set (platform_id);
-    key.encodingID.set (encoding_id);
-
-    /* Note: We can use bsearch, but since it has no performance
-     * implications, we use lsearch and as such accept fonts with
-     * unsorted subtable list. */
-    int result = encodingRecord./*bsearch*/lsearch (key);
-    if (result == -1 || !encodingRecord[result].subtable)
-      return nullptr;
-
-    return &(this+encodingRecord[result].subtable);
-  }
-
-  protected:
-  HBUINT16		version;	/* Table version number (0). */
-  SortedArrayOf<EncodingRecord>
-			encodingRecord;	/* Encoding tables. */
-  public:
-  DEFINE_SIZE_ARRAY (4, encodingRecord);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_CMAP_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-color-cbdt-table.hh b/third_party/harfbuzz-ng/src/hb-ot-color-cbdt-table.hh
deleted file mode 100644
index e7ab917..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-color-cbdt-table.hh
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Copyright © 2016  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Seigo Nonaka
- */
-
-#ifndef HB_OT_COLOR_CBDT_TABLE_HH
-#define HB_OT_COLOR_CBDT_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-namespace OT {
-
-struct SmallGlyphMetrics
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  inline void get_extents (hb_glyph_extents_t *extents) const
-  {
-    extents->x_bearing = bearingX;
-    extents->y_bearing = bearingY;
-    extents->width = width;
-    extents->height = -height;
-  }
-
-  HBUINT8 height;
-  HBUINT8 width;
-  HBINT8 bearingX;
-  HBINT8 bearingY;
-  HBUINT8 advance;
-
-  DEFINE_SIZE_STATIC(5);
-};
-
-struct BigGlyphMetrics : SmallGlyphMetrics
-{
-  HBINT8 vertBearingX;
-  HBINT8 vertBearingY;
-  HBUINT8 vertAdvance;
-
-  DEFINE_SIZE_STATIC(8);
-};
-
-struct SBitLineMetrics
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  HBINT8 ascender;
-  HBINT8 decender;
-  HBUINT8 widthMax;
-  HBINT8 caretSlopeNumerator;
-  HBINT8 caretSlopeDenominator;
-  HBINT8 caretOffset;
-  HBINT8 minOriginSB;
-  HBINT8 minAdvanceSB;
-  HBINT8 maxBeforeBL;
-  HBINT8 minAfterBL;
-  HBINT8 padding1;
-  HBINT8 padding2;
-
-  DEFINE_SIZE_STATIC(12);
-};
-
-
-/*
- * Index Subtables.
- */
-
-struct IndexSubtableHeader
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  HBUINT16 indexFormat;
-  HBUINT16 imageFormat;
-  HBUINT32 imageDataOffset;
-
-  DEFINE_SIZE_STATIC(8);
-};
-
-template <typename OffsetType>
-struct IndexSubtableFormat1Or3
-{
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  c->check_array (offsetArrayZ, offsetArrayZ[0].static_size, glyph_count + 1));
-  }
-
-  bool get_image_data (unsigned int idx,
-		       unsigned int *offset,
-		       unsigned int *length) const
-  {
-    if (unlikely (offsetArrayZ[idx + 1] <= offsetArrayZ[idx]))
-      return false;
-
-    *offset = header.imageDataOffset + offsetArrayZ[idx];
-    *length = offsetArrayZ[idx + 1] - offsetArrayZ[idx];
-    return true;
-  }
-
-  IndexSubtableHeader header;
-  Offset<OffsetType> offsetArrayZ[VAR];
-
-  DEFINE_SIZE_ARRAY(8, offsetArrayZ);
-};
-
-struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<HBUINT32> {};
-struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<HBUINT16> {};
-
-struct IndexSubtable
-{
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.header.sanitize (c)) return_trace (false);
-    switch (u.header.indexFormat) {
-    case 1: return_trace (u.format1.sanitize (c, glyph_count));
-    case 3: return_trace (u.format3.sanitize (c, glyph_count));
-    default:return_trace (true);
-    }
-  }
-
-  inline bool get_extents (hb_glyph_extents_t *extents) const
-  {
-    switch (u.header.indexFormat) {
-    case 2: case 5: /* TODO */
-    case 1: case 3: case 4: /* Variable-metrics formats do not have metrics here. */
-    default:return (false);
-    }
-  }
-
-  bool get_image_data (unsigned int idx,
-		       unsigned int *offset,
-		       unsigned int *length,
-		       unsigned int *format) const
-  {
-    *format = u.header.imageFormat;
-    switch (u.header.indexFormat) {
-    case 1: return u.format1.get_image_data (idx, offset, length);
-    case 3: return u.format3.get_image_data (idx, offset, length);
-    default: return false;
-    }
-  }
-
-  protected:
-  union {
-  IndexSubtableHeader	header;
-  IndexSubtableFormat1	format1;
-  IndexSubtableFormat3	format3;
-  /* TODO: Format 2, 4, 5. */
-  } u;
-  public:
-  DEFINE_SIZE_UNION (8, header);
-};
-
-struct IndexSubtableRecord
-{
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  firstGlyphIndex <= lastGlyphIndex &&
-		  offsetToSubtable.sanitize (c, this, lastGlyphIndex - firstGlyphIndex + 1));
-  }
-
-  inline bool get_extents (hb_glyph_extents_t *extents) const
-  {
-    return (this+offsetToSubtable).get_extents (extents);
-  }
-
-  bool get_image_data (unsigned int gid,
-		       unsigned int *offset,
-		       unsigned int *length,
-		       unsigned int *format) const
-  {
-    if (gid < firstGlyphIndex || gid > lastGlyphIndex)
-    {
-      return false;
-    }
-    return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
-						   offset, length, format);
-  }
-
-  HBUINT16 firstGlyphIndex;
-  HBUINT16 lastGlyphIndex;
-  LOffsetTo<IndexSubtable> offsetToSubtable;
-
-  DEFINE_SIZE_STATIC(8);
-};
-
-struct IndexSubtableArray
-{
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, count)))
-      return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!indexSubtablesZ[i].sanitize (c, this)))
-	return_trace (false);
-    return_trace (true);
-  }
-
-  public:
-  const IndexSubtableRecord* find_table (hb_codepoint_t glyph, unsigned int numTables) const
-  {
-    for (unsigned int i = 0; i < numTables; ++i)
-    {
-      unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex;
-      unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex;
-      if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) {
-        return &indexSubtablesZ[i];
-      }
-    }
-    return nullptr;
-  }
-
-  protected:
-  IndexSubtableRecord indexSubtablesZ[VAR];
-
-  public:
-  DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
-};
-
-struct BitmapSizeTable
-{
-  friend struct CBLC;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) &&
-		  c->check_range (&(base+indexSubtableArrayOffset), indexTablesSize) &&
-		  horizontal.sanitize (c) &&
-		  vertical.sanitize (c));
-  }
-
-  const IndexSubtableRecord *find_table (hb_codepoint_t glyph, const void *base) const
-  {
-    return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables);
-  }
-
-  protected:
-  LOffsetTo<IndexSubtableArray> indexSubtableArrayOffset;
-  HBUINT32 indexTablesSize;
-  HBUINT32 numberOfIndexSubtables;
-  HBUINT32 colorRef;
-  SBitLineMetrics horizontal;
-  SBitLineMetrics vertical;
-  HBUINT16 startGlyphIndex;
-  HBUINT16 endGlyphIndex;
-  HBUINT8 ppemX;
-  HBUINT8 ppemY;
-  HBUINT8 bitDepth;
-  HBINT8 flags;
-
-  public:
-  DEFINE_SIZE_STATIC(48);
-};
-
-
-/*
- * Glyph Bitmap Data Formats.
- */
-
-struct GlyphBitmapDataFormat17
-{
-  SmallGlyphMetrics glyphMetrics;
-  HBUINT32 dataLen;
-  HBUINT8 dataZ[VAR];
-
-  DEFINE_SIZE_ARRAY(9, dataZ);
-};
-
-
-/*
- * CBLC -- Color Bitmap Location Table
- */
-
-#define HB_OT_TAG_CBLC HB_TAG('C','B','L','C')
-
-struct CBLC
-{
-  friend struct CBDT;
-
-  static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  likely (version.major == 2 || version.major == 3) &&
-		  sizeTables.sanitize (c, this));
-  }
-
-  protected:
-  const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
-					 unsigned int *x_ppem, unsigned int *y_ppem) const
-  {
-    /* TODO: Make it possible to select strike. */
-
-    unsigned int count = sizeTables.len;
-    for (uint32_t i = 0; i < count; ++i)
-    {
-      unsigned int startGlyphIndex = sizeTables.array[i].startGlyphIndex;
-      unsigned int endGlyphIndex = sizeTables.array[i].endGlyphIndex;
-      if (startGlyphIndex <= glyph && glyph <= endGlyphIndex)
-      {
-	*x_ppem = sizeTables[i].ppemX;
-	*y_ppem = sizeTables[i].ppemY;
-	return sizeTables[i].find_table (glyph, this);
-      }
-    }
-
-    return nullptr;
-  }
-
-  protected:
-  FixedVersion<>		version;
-  LArrayOf<BitmapSizeTable>	sizeTables;
-
-  public:
-  DEFINE_SIZE_ARRAY(8, sizeTables);
-};
-
-/*
- * CBDT -- Color Bitmap Data Table
- */
-#define HB_OT_TAG_CBDT HB_TAG('C','B','D','T')
-
-struct CBDT
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  likely (version.major == 2 || version.major == 3));
-  }
-
-  struct accelerator_t
-  {
-    inline void init (hb_face_t *face)
-    {
-      upem = hb_face_get_upem (face);
-
-      cblc_blob = Sanitizer<CBLC>().sanitize (face->reference_table (HB_OT_TAG_CBLC));
-      cbdt_blob = Sanitizer<CBDT>().sanitize (face->reference_table (HB_OT_TAG_CBDT));
-      cbdt_len = hb_blob_get_length (cbdt_blob);
-
-      if (hb_blob_get_length (cblc_blob) == 0) {
-	cblc = nullptr;
-	cbdt = nullptr;
-	return;  /* Not a bitmap font. */
-      }
-      cblc = Sanitizer<CBLC>::lock_instance (cblc_blob);
-      cbdt = Sanitizer<CBDT>::lock_instance (cbdt_blob);
-
-    }
-
-    inline void fini (void)
-    {
-      hb_blob_destroy (this->cblc_blob);
-      hb_blob_destroy (this->cbdt_blob);
-    }
-
-    inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
-    {
-      unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */
-
-      if (!cblc)
-	return false;  // Not a color bitmap font.
-
-      const IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem);
-      if (!subtable_record || !x_ppem || !y_ppem)
-	return false;
-
-      if (subtable_record->get_extents (extents))
-	return true;
-
-      unsigned int image_offset = 0, image_length = 0, image_format = 0;
-      if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format))
-	return false;
-
-      {
-	if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
-	  return false;
-
-	switch (image_format)
-	{
-	  case 17: {
-	    if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
-	      return false;
-
-	    const GlyphBitmapDataFormat17& glyphFormat17 =
-		StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
-	    glyphFormat17.glyphMetrics.get_extents (extents);
-	  }
-	  break;
-	  default:
-	    // TODO: Support other image formats.
-	    return false;
-	}
-      }
-
-      /* Convert to the font units. */
-      extents->x_bearing *= upem / (float) x_ppem;
-      extents->y_bearing *= upem / (float) y_ppem;
-      extents->width *= upem / (float) x_ppem;
-      extents->height *= upem / (float) y_ppem;
-
-      return true;
-    }
-
-    private:
-    hb_blob_t *cblc_blob;
-    hb_blob_t *cbdt_blob;
-    const CBLC *cblc;
-    const CBDT *cbdt;
-
-    unsigned int cbdt_len;
-    unsigned int upem;
-  };
-
-
-  protected:
-  FixedVersion<>version;
-  HBUINT8 dataZ[VAR];
-
-  public:
-  DEFINE_SIZE_ARRAY(4, dataZ);
-};
-
-} /* namespace OT */
-
-#endif /* HB_OT_COLOR_CBDT_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-color-colr-table.hh b/third_party/harfbuzz-ng/src/hb-ot-color-colr-table.hh
deleted file mode 100644
index 2c3b1ccc..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-color-colr-table.hh
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright © 2018  Ebrahim Byagowi
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
-
-#ifndef HB_OT_COLOR_COLR_TABLE_HH
-#define HB_OT_COLOR_COLR_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-/*
- * Color Palette
- * http://www.microsoft.com/typography/otspec/colr.htm
- */
-
-#define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
-
-namespace OT {
-
-
-struct LayerRecord
-{
-  friend struct COLR;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  GlyphID gID;			/* Glyph ID of layer glyph */
-  HBUINT16 paletteIndex;	/* Index value to use with a selected color palette */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-struct BaseGlyphRecord
-{
-  friend struct COLR;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  GlyphID gID;			/* Glyph ID of reference glyph */
-  HBUINT16 firstLayerIndex;	/* Index to the layer record */
-  HBUINT16 numLayers;		/* Number of color layers associated with this glyph */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct COLR
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_COLR;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!(c->check_struct (this) &&
-        c->check_array ((const void*) &layerRecordsOffsetZ, sizeof (LayerRecord), numLayerRecords) &&
-        c->check_array ((const void*) &baseGlyphRecordsZ, sizeof (BaseGlyphRecord), numBaseGlyphRecords)))
-      return_trace (false);
-
-    const BaseGlyphRecord* base_glyph_records = &baseGlyphRecordsZ (this);
-    for (unsigned int i = 0; i < numBaseGlyphRecords; ++i)
-      if (base_glyph_records[i].firstLayerIndex +
-          base_glyph_records[i].numLayers > numLayerRecords)
-        return_trace (false);
-
-    return_trace (true);
-  }
-
-  inline bool get_base_glyph_record (
-    hb_codepoint_t glyph_id, unsigned int &first_layer, unsigned int &num_layers) const
-  {
-    const BaseGlyphRecord* base_glyph_records = &baseGlyphRecordsZ (this);
-    unsigned int min = 0, max = numBaseGlyphRecords - 1;
-    while (min <= max)
-    {
-      unsigned int mid = (min + max) / 2;
-      hb_codepoint_t gID = base_glyph_records[mid].gID;
-      if (gID > glyph_id)
-        max = mid - 1;
-      else if (gID < glyph_id)
-        min = mid + 1;
-      else
-      {
-        first_layer = base_glyph_records[mid].firstLayerIndex;
-        num_layers = base_glyph_records[mid].numLayers;
-        return true;
-      }
-    }
-    return false;
-  }
-
-  inline void get_layer_record (int layer,
-    hb_codepoint_t &glyph_id, unsigned int &palette_index) const
-  {
-    const LayerRecord* records = &layerRecordsOffsetZ (this);
-    glyph_id = records[layer].gID;
-    palette_index = records[layer].paletteIndex;
-  }
-
-  protected:
-  HBUINT16	version;		/* Table version number */
-  HBUINT16	numBaseGlyphRecords;	/* Number of Base Glyph Records */
-  LOffsetTo<BaseGlyphRecord>
-		baseGlyphRecordsZ;	/* Offset to Base Glyph records. */
-  LOffsetTo<LayerRecord>
-		layerRecordsOffsetZ;	/* Offset to Layer Records */
-  HBUINT16	numLayerRecords;	/* Number of Layer Records */
-  public:
-  DEFINE_SIZE_STATIC (14);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_COLOR_COLR_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-color-cpal-table.hh b/third_party/harfbuzz-ng/src/hb-ot-color-cpal-table.hh
deleted file mode 100644
index e364c8a..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-color-cpal-table.hh
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright © 2016  Google, Inc.
- * Copyright © 2018  Ebrahim Byagowi
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Sascha Brawer
- */
-
-#ifndef HB_OT_COLOR_CPAL_TABLE_HH
-#define HB_OT_COLOR_CPAL_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-
-/*
- * Following parts to be moved to a public header.
- */
-
-/**
- * hb_ot_color_t:
- * ARGB data type for holding color values.
- *
- * Since: REPLACEME
- */
-typedef uint32_t hb_ot_color_t;
-
-
-/**
- * hb_ot_color_palette_flags_t:
- * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special to note about a color palette.
- * @HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND: flag indicating that the color palette is suitable for rendering text on light background.
- * @HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND: flag indicating that the color palette is suitable for rendering text on dark background.
- *
- * Since: REPLACEME
- */
-typedef enum { /*< flags >*/
-  HB_OT_COLOR_PALETTE_FLAG_DEFAULT = 0x00000000u,
-  HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND = 0x00000001u,
-  HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND = 0x00000002u,
-} hb_ot_color_palette_flags_t;
-
-// HB_EXTERN unsigned int
-// hb_ot_color_get_palette_count (hb_face_t *face);
-
-// HB_EXTERN unsigned int
-// hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette);
-
-// HB_EXTERN hb_ot_color_palette_flags_t
-// hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette);
-
-// HB_EXTERN unsigned int
-// hb_ot_color_get_palette_colors (hb_face_t       *face,
-// 				unsigned int     palette, /* default=0 */
-// 				unsigned int     start_offset,
-// 				unsigned int    *color_count /* IN/OUT */,
-// 				hb_ot_color_t   *colors /* OUT */);
-
-
-
-
-
-/*
- * Color Palette
- * http://www.microsoft.com/typography/otspec/cpal.htm
- */
-
-#define HB_OT_TAG_CPAL HB_TAG('C','P','A','L')
-
-namespace OT {
-
-
-struct CPALV1Tail
-{
-  friend struct CPAL;
-
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int palettes) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (
-      c->check_struct (this) &&
-      c->check_array ((const void*) &paletteFlags, sizeof (HBUINT32), palettes) &&
-      c->check_array ((const void*) &paletteLabel, sizeof (HBUINT16), palettes) &&
-      c->check_array ((const void*) &paletteEntryLabel, sizeof (HBUINT16), palettes));
-  }
-
-  private:
-  inline hb_ot_color_palette_flags_t
-  get_palette_flags (const void *base, unsigned int palette) const
-  {
-    const HBUINT32* flags = &paletteFlags (base);
-    return (hb_ot_color_palette_flags_t) (uint32_t) flags[palette];
-  }
-
-  inline unsigned int
-  get_palette_name_id (const void *base, unsigned int palette) const
-  {
-    const HBUINT16* name_ids = &paletteLabel (base);
-    return name_ids[palette];
-  }
-
-  protected:
-  LOffsetTo<HBUINT32> paletteFlags;
-  LOffsetTo<HBUINT16> paletteLabel;
-  LOffsetTo<HBUINT16> paletteEntryLabel;
-  public:
-  DEFINE_SIZE_STATIC (12);
-};
-
-typedef HBUINT32 BGRAColor;
-
-struct CPAL
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_CPAL;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!(c->check_struct (this) && // This checks colorRecordIndicesX sanity also, see #get_size
-        c->check_array ((const void*) &colorRecordsZ, sizeof (BGRAColor), numColorRecords)))
-      return_trace (false);
-
-    // Check for indices sanity so no need for doing it runtime
-    for (unsigned int i = 0; i < numPalettes; ++i)
-      if (colorRecordIndicesX[i] + numPaletteEntries > numColorRecords)
-        return_trace (false);
-
-    // If version is zero, we are done here; otherwise we need to check tail also
-    if (version == 0)
-      return_trace (true);
-
-    const CPALV1Tail &v1 = StructAfter<CPALV1Tail> (*this);
-    return_trace (v1.sanitize (c, numPalettes));
-  }
-
-  inline unsigned int get_size (void) const
-  {
-    return min_size + numPalettes * sizeof (HBUINT16);
-  }
-
-  inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette) const
-  {
-    if (version == 0 || palette >= numPalettes)
-      return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
-
-    const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
-    return cpal1.get_palette_flags (this, palette);
-  }
-
-  inline unsigned int get_palette_name_id (unsigned int palette) const
-  {
-    if (version == 0 || palette >= numPalettes)
-      return 0xFFFF;
-
-    const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
-    return cpal1.get_palette_name_id (this, palette);
-  }
-
-  inline unsigned int get_palette_count () const
-  {
-    return numPalettes;
-  }
-
-  inline hb_ot_color_t get_color_record_argb (unsigned int color_index, unsigned int palette) const
-  {
-    if (color_index >= numPaletteEntries || palette >= numPalettes)
-      return 0;
-
-    const BGRAColor* records = &colorRecordsZ(this);
-    // No need for more range check as it is already done on #sanitize
-    return records[colorRecordIndicesX[palette] + color_index];
-  }
-
-  protected:
-  HBUINT16	version;
-  /* Version 0 */
-  HBUINT16	numPaletteEntries;
-  HBUINT16	numPalettes;
-  HBUINT16	numColorRecords;
-  LOffsetTo<HBUINT32>	colorRecordsZ;
-  HBUINT16	colorRecordIndicesX[VAR];  // VAR=numPalettes
-/*CPALV1Tail	v1[VAR];*/
-  public:
-  DEFINE_SIZE_ARRAY (12, colorRecordIndicesX);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_COLOR_CPAL_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-font.cc b/third_party/harfbuzz-ng/src/hb-ot-font.cc
deleted file mode 100644
index 0e373d30..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-font.cc
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright © 2011,2014  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
- */
-
-#include "hb-private.hh"
-
-#include "hb-ot.h"
-
-#include "hb-font-private.hh"
-
-#include "hb-ot-cmap-table.hh"
-#include "hb-ot-glyf-table.hh"
-#include "hb-ot-hmtx-table.hh"
-#include "hb-ot-kern-table.hh"
-#include "hb-ot-post-table.hh"
-
-#include "hb-ot-color-cbdt-table.hh"
-
-
-struct hb_ot_font_t
-{
-  OT::cmap::accelerator_t cmap;
-  OT::hmtx::accelerator_t h_metrics;
-  OT::vmtx::accelerator_t v_metrics;
-  OT::hb_lazy_loader_t<OT::glyf::accelerator_t> glyf;
-  OT::hb_lazy_loader_t<OT::CBDT::accelerator_t> cbdt;
-  OT::hb_lazy_loader_t<OT::post::accelerator_t> post;
-  OT::hb_lazy_loader_t<OT::kern::accelerator_t> kern;
-};
-
-
-static hb_ot_font_t *
-_hb_ot_font_create (hb_face_t *face)
-{
-  hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
-
-  if (unlikely (!ot_font))
-    return nullptr;
-
-  ot_font->cmap.init (face);
-  ot_font->h_metrics.init (face);
-  ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
-  ot_font->glyf.init (face);
-  ot_font->cbdt.init (face);
-  ot_font->post.init (face);
-  ot_font->kern.init (face);
-
-  return ot_font;
-}
-
-static void
-_hb_ot_font_destroy (void *data)
-{
-  hb_ot_font_t *ot_font = (hb_ot_font_t *) data;
-
-  ot_font->cmap.fini ();
-  ot_font->h_metrics.fini ();
-  ot_font->v_metrics.fini ();
-  ot_font->glyf.fini ();
-  ot_font->cbdt.fini ();
-  ot_font->post.fini ();
-  ot_font->kern.fini ();
-
-  free (ot_font);
-}
-
-
-static hb_bool_t
-hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
-			 void *font_data,
-			 hb_codepoint_t unicode,
-			 hb_codepoint_t *glyph,
-			 void *user_data HB_UNUSED)
-
-{
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->cmap.get_nominal_glyph (unicode, glyph);
-}
-
-static hb_bool_t
-hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
-			   void *font_data,
-			   hb_codepoint_t unicode,
-			   hb_codepoint_t variation_selector,
-			   hb_codepoint_t *glyph,
-			   void *user_data HB_UNUSED)
-{
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph);
-}
-
-static hb_position_t
-hb_ot_get_glyph_h_advance (hb_font_t *font,
-			   void *font_data,
-			   hb_codepoint_t glyph,
-			   void *user_data HB_UNUSED)
-{
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_x (ot_font->h_metrics.get_advance (glyph, font));
-}
-
-static hb_position_t
-hb_ot_get_glyph_v_advance (hb_font_t *font,
-			   void *font_data,
-			   hb_codepoint_t glyph,
-			   void *user_data HB_UNUSED)
-{
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font));
-}
-
-static hb_position_t
-hb_ot_get_glyph_h_kerning (hb_font_t *font,
-			   void *font_data,
-			   hb_codepoint_t left_glyph,
-			   hb_codepoint_t right_glyph,
-			   void *user_data HB_UNUSED)
-{
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_x (ot_font->kern->get_h_kerning (left_glyph, right_glyph));
-}
-
-static hb_bool_t
-hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
-			 void *font_data,
-			 hb_codepoint_t glyph,
-			 hb_glyph_extents_t *extents,
-			 void *user_data HB_UNUSED)
-{
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  bool ret = ot_font->glyf->get_extents (glyph, extents);
-  if (!ret)
-    ret = ot_font->cbdt->get_extents (glyph, extents);
-  // TODO Hook up side-bearings variations.
-  extents->x_bearing = font->em_scale_x (extents->x_bearing);
-  extents->y_bearing = font->em_scale_y (extents->y_bearing);
-  extents->width     = font->em_scale_x (extents->width);
-  extents->height    = font->em_scale_y (extents->height);
-  return ret;
-}
-
-static hb_bool_t
-hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
-                      void *font_data,
-                      hb_codepoint_t glyph,
-                      char *name, unsigned int size,
-                      void *user_data HB_UNUSED)
-{
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->post->get_glyph_name (glyph, name, size);
-}
-
-static hb_bool_t
-hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
-                           void *font_data,
-                           const char *name, int len,
-                           hb_codepoint_t *glyph,
-                           void *user_data HB_UNUSED)
-{
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->post->get_glyph_from_name (name, len, glyph);
-}
-
-static hb_bool_t
-hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED,
-			  void *font_data,
-			  hb_font_extents_t *metrics,
-			  void *user_data HB_UNUSED)
-{
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender);
-  metrics->descender = font->em_scale_y (ot_font->h_metrics.descender);
-  metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap);
-  // TODO Hook up variations.
-  return ot_font->h_metrics.has_font_extents;
-}
-
-static hb_bool_t
-hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED,
-			  void *font_data,
-			  hb_font_extents_t *metrics,
-			  void *user_data HB_UNUSED)
-{
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender);
-  metrics->descender = font->em_scale_x (ot_font->v_metrics.descender);
-  metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap);
-  // TODO Hook up variations.
-  return ot_font->v_metrics.has_font_extents;
-}
-
-static hb_font_funcs_t *static_ot_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_ot_funcs (void)
-{
-  hb_font_funcs_destroy (static_ot_funcs);
-}
-#endif
-
-static hb_font_funcs_t *
-_hb_ot_get_font_funcs (void)
-{
-retry:
-  hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs);
-
-  if (unlikely (!funcs))
-  {
-    funcs = hb_font_funcs_create ();
-
-    hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
-    hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
-    hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
-    hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, nullptr, nullptr);
-    hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, nullptr, nullptr);
-    hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
-    hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
-    hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr);
-
-    hb_font_funcs_make_immutable (funcs);
-
-    if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, nullptr, funcs)) {
-      hb_font_funcs_destroy (funcs);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_ot_funcs); /* First person registers atexit() callback. */
-#endif
-  };
-
-  return funcs;
-}
-
-
-/**
- * hb_ot_font_set_funcs:
- *
- * Since: 0.9.28
- **/
-void
-hb_ot_font_set_funcs (hb_font_t *font)
-{
-  hb_ot_font_t *ot_font = _hb_ot_font_create (font->face);
-  if (unlikely (!ot_font))
-    return;
-
-  hb_font_set_funcs (font,
-		     _hb_ot_get_font_funcs (),
-		     ot_font,
-		     _hb_ot_font_destroy);
-}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-font.h b/third_party/harfbuzz-ng/src/hb-ot-font.h
deleted file mode 100644
index 80eaa54b..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-font.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright © 2014  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
- */
-
-#ifndef HB_OT_H_IN
-#error "Include <hb-ot.h> instead."
-#endif
-
-#ifndef HB_OT_FONT_H
-#define HB_OT_FONT_H
-
-#include "hb.h"
-
-HB_BEGIN_DECLS
-
-
-HB_EXTERN void
-hb_ot_font_set_funcs (hb_font_t *font);
-
-
-HB_END_DECLS
-
-#endif /* HB_OT_FONT_H */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-glyf-table.hh b/third_party/harfbuzz-ng/src/hb-ot-glyf-table.hh
deleted file mode 100644
index d62f24bd..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-glyf-table.hh
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * Copyright © 2015  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_GLYF_TABLE_HH
-#define HB_OT_GLYF_TABLE_HH
-
-#include "hb-open-type-private.hh"
-#include "hb-ot-head-table.hh"
-#include "hb-subset-glyf.hh"
-#include "hb-subset-plan.hh"
-#include "hb-subset-private.hh"
-
-namespace OT {
-
-
-/*
- * loca -- Index to Location
- */
-
-#define HB_OT_TAG_loca HB_TAG('l','o','c','a')
-
-
-struct loca
-{
-  friend struct glyf;
-
-  static const hb_tag_t tableTag = HB_OT_TAG_loca;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (true);
-  }
-
-  protected:
-  HBUINT8		dataX[VAR];		/* Location data. */
-  DEFINE_SIZE_ARRAY (0, dataX);
-};
-
-
-/*
- * glyf -- TrueType Glyph Data
- */
-
-#define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
-
-
-struct glyf
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_glyf;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    /* We don't check for anything specific here.  The users of the
-     * struct do all the hard work... */
-    return_trace (true);
-  }
-
-  inline bool subset (hb_subset_plan_t *plan) const
-  {
-    hb_blob_t *glyf_prime = nullptr;
-    hb_blob_t *loca_prime = nullptr;
-
-    bool success = true;
-    bool use_short_loca = false;
-    if (hb_subset_glyf_and_loca (plan, &use_short_loca, &glyf_prime, &loca_prime)) {
-      success = success && hb_subset_plan_add_table (plan, HB_OT_TAG_glyf, glyf_prime);
-      success = success && hb_subset_plan_add_table (plan, HB_OT_TAG_loca, loca_prime);
-      success = success && _add_head_and_set_loca_version (plan->source, use_short_loca, plan->dest);
-    } else {
-      success = false;
-    }
-    hb_blob_destroy (loca_prime);
-    hb_blob_destroy (glyf_prime);
-
-    return success;
-  }
-
-  static bool
-  _add_head_and_set_loca_version (hb_face_t *source, bool use_short_loca, hb_face_t *dest)
-  {
-    hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (hb_face_reference_table (source, HB_OT_TAG_head));
-    hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
-    hb_blob_destroy (head_blob);
-
-    if (unlikely (!head_prime_blob))
-      return false;
-
-    OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
-    head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1);
-    bool success = hb_subset_face_add_table (dest, HB_OT_TAG_head, head_prime_blob);
-
-    hb_blob_destroy (head_prime_blob);
-    return success;
-  }
-
-  struct GlyphHeader
-  {
-    HBINT16		numberOfContours;	/* If the number of contours is
-                                                 * greater than or equal to zero,
-                                                 * this is a simple glyph; if negative,
-                                                 * this is a composite glyph. */
-    FWORD		xMin;			/* Minimum x for coordinate data. */
-    FWORD		yMin;			/* Minimum y for coordinate data. */
-    FWORD		xMax;			/* Maximum x for coordinate data. */
-    FWORD		yMax;			/* Maximum y for coordinate data. */
-
-    DEFINE_SIZE_STATIC (10);
-  };
-
-  struct CompositeGlyphHeader
-  {
-    static const uint16_t ARG_1_AND_2_ARE_WORDS =      0x0001;
-    static const uint16_t ARGS_ARE_XY_VALUES =         0x0002;
-    static const uint16_t ROUND_XY_TO_GRID =           0x0004;
-    static const uint16_t WE_HAVE_A_SCALE =            0x0008;
-    static const uint16_t MORE_COMPONENTS =            0x0020;
-    static const uint16_t WE_HAVE_AN_X_AND_Y_SCALE =   0x0040;
-    static const uint16_t WE_HAVE_A_TWO_BY_TWO =       0x0080;
-    static const uint16_t WE_HAVE_INSTRUCTIONS =       0x0100;
-    static const uint16_t USE_MY_METRICS =             0x0200;
-    static const uint16_t OVERLAP_COMPOUND =           0x0400;
-    static const uint16_t SCALED_COMPONENT_OFFSET =    0x0800;
-    static const uint16_t UNSCALED_COMPONENT_OFFSET =  0x1000;
-
-    HBUINT16 flags;
-    HBUINT16 glyphIndex;
-
-    inline unsigned int get_size (void) const
-    {
-      unsigned int size = min_size;
-      if (flags & ARG_1_AND_2_ARE_WORDS) {
-        // arg1 and 2 are int16
-        size += 4;
-      } else {
-        // arg1 and 2 are int8
-        size += 2;
-      }
-      if (flags & WE_HAVE_A_SCALE) {
-        // One x 16 bit (scale)
-        size += 2;
-      } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
-        // Two x 16 bit (xscale, yscale)
-        size += 4;
-      } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
-        // Four x 16 bit (xscale, scale01, scale10, yscale)
-        size += 8;
-      }
-      return size;
-    }
-
-    struct Iterator
-    {
-      const char *glyph_start;
-      const char *glyph_end;
-      const CompositeGlyphHeader *current;
-
-      inline bool move_to_next ()
-      {
-	if (current->flags & CompositeGlyphHeader::MORE_COMPONENTS)
-	{
-	  const CompositeGlyphHeader *possible =
-	    &StructAfter<CompositeGlyphHeader, CompositeGlyphHeader> (*current);
-	  if (!in_range (possible))
-	    return false;
-	  current = possible;
-	  return true;
-	}
-	return false;
-      }
-
-      inline bool in_range (const CompositeGlyphHeader *composite) const
-      {
-	return (const char *) composite >= glyph_start
-	  && ((const char *) composite + CompositeGlyphHeader::min_size) <= glyph_end
-	  && ((const char *) composite + composite->get_size()) <= glyph_end;
-      }
-    };
-
-    static inline bool get_iterator (const char * glyph_data,
-				     unsigned int length,
-				     CompositeGlyphHeader::Iterator *iterator /* OUT */)
-    {
-      if (length < GlyphHeader::static_size)
-	return false; /* Empty glyph; zero extents. */
-
-      const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyph_data, 0);
-      if (glyph_header.numberOfContours < 0)
-      {
-        const CompositeGlyphHeader *possible =
-	  &StructAfter<CompositeGlyphHeader, GlyphHeader> (glyph_header);
-
-	iterator->glyph_start = glyph_data;
-	iterator->glyph_end = (const char *) glyph_data + length;
-	if (!iterator->in_range (possible))
-          return false;
-        iterator->current = possible;
-        return true;
-      }
-
-      return false;
-    }
-
-    DEFINE_SIZE_MIN (4);
-  };
-
-  struct accelerator_t
-  {
-    inline void init (hb_face_t *face)
-    {
-      hb_blob_t *head_blob = Sanitizer<head>().sanitize (face->reference_table (HB_OT_TAG_head));
-      const head *head_table = Sanitizer<head>::lock_instance (head_blob);
-      if ((unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
-      {
-	/* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
-	hb_blob_destroy (head_blob);
-	return;
-      }
-      short_offset = 0 == head_table->indexToLocFormat;
-      hb_blob_destroy (head_blob);
-
-      loca_blob = Sanitizer<loca>().sanitize (face->reference_table (HB_OT_TAG_loca));
-      loca_table = Sanitizer<loca>::lock_instance (loca_blob);
-      glyf_blob = Sanitizer<glyf>().sanitize (face->reference_table (HB_OT_TAG_glyf));
-      glyf_table = Sanitizer<glyf>::lock_instance (glyf_blob);
-
-      num_glyphs = MAX (1u, hb_blob_get_length (loca_blob) / (short_offset ? 2 : 4)) - 1;
-      glyf_len = hb_blob_get_length (glyf_blob);
-    }
-
-    inline void fini (void)
-    {
-      hb_blob_destroy (loca_blob);
-      hb_blob_destroy (glyf_blob);
-    }
-
-    /*
-     * Returns true if the referenced glyph is a valid glyph and a composite glyph.
-     * If true is returned a pointer to the composite glyph will be written into
-     * composite.
-     */
-    inline bool get_composite (hb_codepoint_t glyph,
-			       CompositeGlyphHeader::Iterator *composite /* OUT */) const
-    {
-      unsigned int start_offset, end_offset;
-      if (!get_offsets (glyph, &start_offset, &end_offset))
-        return false; /* glyph not found */
-
-      return CompositeGlyphHeader::get_iterator ((const char*) this->glyf_table + start_offset,
-						 end_offset - start_offset,
-						 composite);
-    }
-
-    /* based on FontTools _g_l_y_f.py::trim */
-    inline bool remove_padding(unsigned int start_offset,
-                               unsigned int *end_offset) const
-    {
-      static const int FLAG_X_SHORT = 0x02;
-      static const int FLAG_Y_SHORT = 0x04;
-      static const int FLAG_REPEAT = 0x08;
-      static const int FLAG_X_SAME = 0x10;
-      static const int FLAG_Y_SAME = 0x20;
-
-      if (*end_offset - start_offset < GlyphHeader::static_size)
-        return true;
-
-      const char *glyph = ((const char *) glyf_table) + start_offset;
-      const char * const glyph_end = glyph + (*end_offset - start_offset);
-      const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyph, 0);
-      int16_t num_contours = (int16_t) glyph_header.numberOfContours;
-
-      if (num_contours < 0)
-        /* Trimming for composites not implemented.
-         * If removing hints it falls out of that. */
-        return true;
-      else if (num_contours > 0)
-      {
-        /* simple glyph w/contours, possibly trimmable */
-        glyph += GlyphHeader::static_size + 2 * num_contours;
-
-        if (unlikely (glyph + 2 >= glyph_end)) return false;
-        uint16_t nCoordinates = (uint16_t) StructAtOffset<HBUINT16>(glyph - 2, 0) + 1;
-        uint16_t nInstructions = (uint16_t) StructAtOffset<HBUINT16>(glyph, 0);
-
-        glyph += 2 + nInstructions;
-        if (unlikely (glyph + 2 >= glyph_end)) return false;
-
-        unsigned int coordBytes = 0;
-        unsigned int coordsWithFlags = 0;
-        while (glyph < glyph_end)
-        {
-          uint8_t flag = (uint8_t) *glyph;
-          glyph++;
-
-          unsigned int repeat = 1;
-          if (flag & FLAG_REPEAT)
-          {
-            if (glyph >= glyph_end)
-            {
-              DEBUG_MSG(SUBSET, nullptr, "Bad flag");
-              return false;
-            }
-            repeat = ((uint8_t) *glyph) + 1;
-            glyph++;
-          }
-
-          unsigned int xBytes, yBytes;
-          xBytes = yBytes = 0;
-          if (flag & FLAG_X_SHORT)
-            xBytes = 1;
-          else if ((flag & FLAG_X_SAME) == 0)
-            xBytes = 2;
-
-          if (flag & FLAG_Y_SHORT)
-            yBytes = 1;
-          else if ((flag & FLAG_Y_SAME) == 0)
-            yBytes = 2;
-
-          coordBytes += (xBytes + yBytes) * repeat;
-          coordsWithFlags += repeat;
-          if (coordsWithFlags >= nCoordinates)
-            break;
-        }
-
-        if (coordsWithFlags != nCoordinates)
-        {
-          DEBUG_MSG(SUBSET, nullptr, "Expect %d coords to have flags, got flags for %d", nCoordinates, coordsWithFlags);
-          return false;
-        }
-        glyph += coordBytes;
-
-        if (glyph < glyph_end)
-          *end_offset -= glyph_end - glyph;
-      }
-      return true;
-    }
-
-    inline bool get_offsets (hb_codepoint_t  glyph,
-                             unsigned int   *start_offset /* OUT */,
-                             unsigned int   *end_offset   /* OUT */) const
-    {
-      if (unlikely (glyph >= num_glyphs))
-	return false;
-
-      if (short_offset)
-      {
-        const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataX;
-	*start_offset = 2 * offsets[glyph];
-	*end_offset   = 2 * offsets[glyph + 1];
-      }
-      else
-      {
-        const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataX;
-
-	*start_offset = offsets[glyph];
-	*end_offset   = offsets[glyph + 1];
-      }
-
-      if (*start_offset > *end_offset || *end_offset > glyf_len)
-	return false;
-
-      return true;
-    }
-
-    inline bool get_instruction_offsets(unsigned int start_offset,
-                                        unsigned int end_offset,
-                                        unsigned int *instruction_start /* OUT */,
-                                        unsigned int *instruction_end /* OUT */) const
-    {
-      if (end_offset - start_offset < GlyphHeader::static_size)
-      {
-        *instruction_start = 0;
-        *instruction_end = 0;
-        return true; /* Empty glyph; no instructions. */
-      }
-      const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset);
-      int16_t num_contours = (int16_t) glyph_header.numberOfContours;
-      if (num_contours < 0)
-      {
-        CompositeGlyphHeader::Iterator composite_it;
-        if (unlikely (!CompositeGlyphHeader::get_iterator (
-            (const char*) this->glyf_table + start_offset,
-             end_offset - start_offset, &composite_it))) return false;
-        const CompositeGlyphHeader *last;
-        do {
-          last = composite_it.current;
-        } while (composite_it.move_to_next());
-
-        if ( (uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
-          *instruction_start = ((char *) last - (char *) glyf_table->dataX) + last->get_size();
-        else
-          *instruction_start = end_offset;
-        *instruction_end = end_offset;
-        if (unlikely (*instruction_start > *instruction_end))
-        {
-          DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside [%d, %d]", *instruction_start, start_offset, end_offset);
-          return false;
-        }
-      }
-      else
-      {
-        unsigned int instruction_length_offset = start_offset + GlyphHeader::static_size + 2 * num_contours;
-        const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (glyf_table, instruction_length_offset);
-        *instruction_start = instruction_length_offset + 2;
-        *instruction_end = *instruction_start + (uint16_t) instruction_length;
-      }
-      return true;
-    }
-
-    inline bool get_extents (hb_codepoint_t glyph,
-			     hb_glyph_extents_t *extents) const
-    {
-      unsigned int start_offset, end_offset;
-      if (!get_offsets (glyph, &start_offset, &end_offset))
-        return false;
-
-      if (end_offset - start_offset < GlyphHeader::static_size)
-	return true; /* Empty glyph; zero extents. */
-
-      const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset);
-
-      extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax);
-      extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax);
-      extents->width     = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing;
-      extents->height    = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing;
-
-      return true;
-    }
-
-    private:
-    bool short_offset;
-    unsigned int num_glyphs;
-    const loca *loca_table;
-    const glyf *glyf_table;
-    hb_blob_t *loca_blob;
-    hb_blob_t *glyf_blob;
-    unsigned int glyf_len;
-  };
-
-  protected:
-  HBUINT8		dataX[VAR];		/* Glyphs data. */
-
-  DEFINE_SIZE_ARRAY (0, dataX);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_GLYF_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-hdmx-table.hh b/third_party/harfbuzz-ng/src/hb-ot-hdmx-table.hh
deleted file mode 100644
index f08fe39d8..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-hdmx-table.hh
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger
- */
-
-#ifndef HB_OT_HDMX_TABLE_HH
-#define HB_OT_HDMX_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-namespace OT {
-
-
-/*
- * hdmx - Horizontal Device Metric
- */
-
-#define HB_OT_TAG_hdmx HB_TAG('h','d','m','x')
-
-struct DeviceRecord
-{
-  struct SubsetView
-  {
-    const DeviceRecord *source_device_record;
-    hb_subset_plan_t *subset_plan;
-
-    inline void init(const DeviceRecord *source_device_record,
-		     hb_subset_plan_t   *subset_plan)
-    {
-      this->source_device_record = source_device_record;
-      this->subset_plan = subset_plan;
-    }
-
-    inline unsigned int len () const
-    {
-      return this->subset_plan->gids_to_retain_sorted.len;
-    }
-
-    inline const HBUINT8& operator [] (unsigned int i) const
-    {
-      if (unlikely (i >= len())) return Null(HBUINT8);
-      hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [i];
-      return this->source_device_record->widths[gid];
-    }
-  };
-
-  static inline unsigned int get_size (unsigned int count)
-  {
-    unsigned int raw_size = min_size + count * HBUINT8::static_size;
-    if (raw_size % 4)
-      /* Align to 32 bits */
-      return raw_size + (4 - (raw_size % 4));
-    return raw_size;
-  }
-
-  inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view)
-  {
-    TRACE_SERIALIZE (this);
-
-    if (unlikely (!c->allocate_size<DeviceRecord> (get_size (subset_view.len()))))
-      return_trace (false);
-
-    this->pixel_size.set (subset_view.source_device_record->pixel_size);
-    this->max_width.set (subset_view.source_device_record->max_width);
-
-    for (unsigned int i = 0; i < subset_view.len(); i++)
-      widths[i].set (subset_view[i]);
-
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int size_device_record) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-			  c->check_range (this, size_device_record)));
-  }
-
-  HBUINT8 pixel_size;   /* Pixel size for following widths (as ppem). */
-  HBUINT8 max_width;    /* Maximum width. */
-  HBUINT8 widths[VAR];  /* Array of widths (numGlyphs is from the 'maxp' table). */
-  public:
-  DEFINE_SIZE_ARRAY (2, widths);
-};
-
-
-struct hdmx
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_hdmx;
-
-  inline unsigned int get_size (void) const
-  {
-    return min_size + num_records * size_device_record;
-  }
-
-  inline const DeviceRecord& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= num_records)) return Null(DeviceRecord);
-    return StructAtOffset<DeviceRecord> (this, min_size + i * size_device_record);
-  }
-
-  inline bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan)
-  {
-    TRACE_SERIALIZE (this);
-
-    if (unlikely (!c->extend_min ((*this))))  return_trace (false);
-
-    this->version.set (source_hdmx->version);
-    this->num_records.set (source_hdmx->num_records);
-    this->size_device_record.set (DeviceRecord::get_size (plan->gids_to_retain_sorted.len));
-
-    for (unsigned int i = 0; i < source_hdmx->num_records; i++)
-    {
-      DeviceRecord::SubsetView subset_view;
-      subset_view.init (&(*source_hdmx)[i], plan);
-
-      c->start_embed<DeviceRecord> ()->serialize (c, subset_view);
-    }
-
-    return_trace (true);
-  }
-
-  static inline size_t get_subsetted_size (hb_subset_plan_t *plan)
-  {
-    return min_size + DeviceRecord::get_size (plan->gids_to_retain_sorted.len);
-  }
-
-  inline bool subset (hb_subset_plan_t *plan) const
-  {
-    size_t dest_size = get_subsetted_size (plan);
-    hdmx *dest = (hdmx *) malloc (dest_size);
-    if (unlikely (!dest))
-    {
-      DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for hdmx subset output.", (unsigned long) dest_size);
-      return false;
-    }
-
-    hb_serialize_context_t c (dest, dest_size);
-    hdmx *hdmx_prime = c.start_serialize<hdmx> ();
-    if (!hdmx_prime || !hdmx_prime->serialize (&c, this, plan)) {
-      free (dest);
-      return false;
-    }
-    c.end_serialize ();
-
-    hb_blob_t *hdmx_prime_blob = hb_blob_create ((const char *) dest,
-						 dest_size,
-						 HB_MEMORY_MODE_READONLY,
-						 dest,
-						 free);
-    bool result = hb_subset_plan_add_table (plan, HB_OT_TAG_hdmx, hdmx_prime_blob);
-    hb_blob_destroy (hdmx_prime_blob);
-
-    return result;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && version == 0 &&
-		  !_hb_unsigned_int_mul_overflows (num_records, size_device_record) &&
-		  c->check_range (this, get_size()));
-  }
-
-  protected:
-  HBUINT16	version;		/* Table version number (0) */
-  HBUINT16	num_records;		/* Number of device records. */
-  HBUINT32	size_device_record;	/* Size of a device record, 32-bit aligned. */
-  HBUINT8	data[VAR];		/* Array of device records. */
-  public:
-  DEFINE_SIZE_ARRAY (8, data);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_HDMX_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-head-table.hh b/third_party/harfbuzz-ng/src/hb-ot-head-table.hh
deleted file mode 100644
index 1d45840..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-head-table.hh
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright © 2010  Red Hat, Inc.
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_HEAD_TABLE_HH
-#define HB_OT_HEAD_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-
-namespace OT {
-
-
-/*
- * head -- Font Header
- */
-
-#define HB_OT_TAG_head HB_TAG('h','e','a','d')
-
-struct head
-{
-  friend struct OffsetTable;
-
-  static const hb_tag_t tableTag	= HB_OT_TAG_head;
-
-  inline unsigned int get_upem (void) const
-  {
-    unsigned int upem = unitsPerEm;
-    /* If no valid head table found, assume 1000, which matches typical Type1 usage. */
-    return 16 <= upem && upem <= 16384 ? upem : 1000;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  version.major == 1 &&
-		  magicNumber == 0x5F0F3CF5u);
-  }
-
-  protected:
-  FixedVersion<>version;		/* Version of the head table--currently
-					 * 0x00010000u for version 1.0. */
-  FixedVersion<>fontRevision;		/* Set by font manufacturer. */
-  HBUINT32	checkSumAdjustment;	/* To compute: set it to 0, sum the
-					 * entire font as HBUINT32, then store
-					 * 0xB1B0AFBAu - sum. */
-  HBUINT32	magicNumber;		/* Set to 0x5F0F3CF5u. */
-  HBUINT16	flags;			/* Bit 0: Baseline for font at y=0;
-					 * Bit 1: Left sidebearing point at x=0;
-					 * Bit 2: Instructions may depend on point size;
-					 * Bit 3: Force ppem to integer values for all
-					 *   internal scaler math; may use fractional
-					 *   ppem sizes if this bit is clear;
-					 * Bit 4: Instructions may alter advance width
-					 *   (the advance widths might not scale linearly);
-					 * Bits 5-10: These should be set according to
-					 *   Apple's specification. However, they are not
-					 *   implemented in OpenType.
-					 * Bit 5: This bit should be set in fonts that are
-					 *   intended to e laid out vertically, and in
-					 *   which the glyphs have been drawn such that an
-					 *   x-coordinate of 0 corresponds to the desired
-					 *   vertical baseline.
-					 * Bit 6: This bit must be set to zero.
-					 * Bit 7: This bit should be set if the font
-					 *   requires layout for correct linguistic
-					 *   rendering (e.g. Arabic fonts).
-					 * Bit 8: This bit should be set for a GX font
-					 *   which has one or more metamorphosis effects
-					 *   designated as happening by default.
-					 * Bit 9: This bit should be set if the font
-					 *   contains any strong right-to-left glyphs.
-					 * Bit 10: This bit should be set if the font
-					 *   contains Indic-style rearrangement effects.
-					 * Bit 11: Font data is 'lossless,' as a result
-					 *   of having been compressed and decompressed
-					 *   with the Agfa MicroType Express engine.
-					 * Bit 12: Font converted (produce compatible metrics)
-					 * Bit 13: Font optimized for ClearType™.
-					 *   Note, fonts that rely on embedded bitmaps (EBDT)
-					 *   for rendering should not be considered optimized
-					 *   for ClearType, and therefore should keep this bit
-					 *   cleared.
-					 * Bit 14: Last Resort font. If set, indicates that
-					 * the glyphs encoded in the cmap subtables are simply
-					 * generic symbolic representations of code point
-					 * ranges and don’t truly represent support for those
-					 * code points. If unset, indicates that the glyphs
-					 * encoded in the cmap subtables represent proper
-					 * support for those code points.
-					 * Bit 15: Reserved, set to 0. */
-  HBUINT16	unitsPerEm;		/* Valid range is from 16 to 16384. This value
-					 * should be a power of 2 for fonts that have
-					 * TrueType outlines. */
-  LONGDATETIME	created;		/* Number of seconds since 12:00 midnight,
-					   January 1, 1904. 64-bit integer */
-  LONGDATETIME	modified;		/* Number of seconds since 12:00 midnight,
-					   January 1, 1904. 64-bit integer */
-  HBINT16	xMin;			/* For all glyph bounding boxes. */
-  HBINT16	yMin;			/* For all glyph bounding boxes. */
-  HBINT16	xMax;			/* For all glyph bounding boxes. */
-  HBINT16	yMax;			/* For all glyph bounding boxes. */
-  HBUINT16	macStyle;		/* Bit 0: Bold (if set to 1);
-					 * Bit 1: Italic (if set to 1)
-					 * Bit 2: Underline (if set to 1)
-					 * Bit 3: Outline (if set to 1)
-					 * Bit 4: Shadow (if set to 1)
-					 * Bit 5: Condensed (if set to 1)
-					 * Bit 6: Extended (if set to 1)
-					 * Bits 7-15: Reserved (set to 0). */
-  HBUINT16	lowestRecPPEM;		/* Smallest readable size in pixels. */
-  HBINT16	fontDirectionHint;	/* Deprecated (Set to 2).
-					 * 0: Fully mixed directional glyphs;
-					 * 1: Only strongly left to right;
-					 * 2: Like 1 but also contains neutrals;
-					 * -1: Only strongly right to left;
-					 * -2: Like -1 but also contains neutrals. */
-  public:
-  HBINT16	indexToLocFormat;	/* 0 for short offsets, 1 for long. */
-  HBINT16	glyphDataFormat;	/* 0 for current format. */
-
-  DEFINE_SIZE_STATIC (54);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_HEAD_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh b/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh
deleted file mode 100644
index 97952b4..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_HHEA_TABLE_HH
-#define HB_OT_HHEA_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-
-namespace OT {
-
-
-/*
- * hhea -- The Horizontal Header Table
- * vhea -- The Vertical Header Table
- */
-
-#define HB_OT_TAG_hhea HB_TAG('h','h','e','a')
-#define HB_OT_TAG_vhea HB_TAG('v','h','e','a')
-
-template <typename T>
-struct _hea
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && likely (version.major == 1));
-  }
-
-  public:
-  FixedVersion<>version;		/* 0x00010000u for version 1.0. */
-  FWORD		ascender;		/* Typographic ascent. */
-  FWORD		descender;		/* Typographic descent. */
-  FWORD		lineGap;		/* Typographic line gap. */
-  UFWORD	advanceMax;		/* Maximum advance width/height value in
-					 * metrics table. */
-  FWORD		minLeadingBearing;	/* Minimum left/top sidebearing value in
-					 * metrics table. */
-  FWORD		minTrailingBearing;	/* Minimum right/bottom sidebearing value;
-					 * calculated as Min(aw - lsb -
-					 * (xMax - xMin)) for horizontal. */
-  FWORD		maxExtent;		/* horizontal: Max(lsb + (xMax - xMin)),
-					 * vertical: minLeadingBearing+(yMax-yMin). */
-  HBINT16		caretSlopeRise;		/* Used to calculate the slope of the
-					 * cursor (rise/run); 1 for vertical caret,
-					 * 0 for horizontal.*/
-  HBINT16		caretSlopeRun;		/* 0 for vertical caret, 1 for horizontal. */
-  HBINT16		caretOffset;		/* The amount by which a slanted
-					 * highlight on a glyph needs
-					 * to be shifted to produce the
-					 * best appearance. Set to 0 for
-					 * non-slanted fonts. */
-  HBINT16		reserved1;		/* Set to 0. */
-  HBINT16		reserved2;		/* Set to 0. */
-  HBINT16		reserved3;		/* Set to 0. */
-  HBINT16		reserved4;		/* Set to 0. */
-  HBINT16		metricDataFormat;	/* 0 for current format. */
-  HBUINT16	numberOfLongMetrics;	/* Number of LongMetric entries in metric
-					 * table. */
-  public:
-  DEFINE_SIZE_STATIC (36);
-};
-
-struct hhea : _hea<hhea> {
-  static const hb_tag_t tableTag	= HB_OT_TAG_hhea;
-};
-struct vhea : _hea<vhea> {
-  static const hb_tag_t tableTag	= HB_OT_TAG_vhea;
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_HHEA_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh
deleted file mode 100644
index 3cd48a6..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod, Roderick Sheeter
- */
-
-#ifndef HB_OT_HMTX_TABLE_HH
-#define HB_OT_HMTX_TABLE_HH
-
-#include "hb-open-type-private.hh"
-#include "hb-ot-hhea-table.hh"
-#include "hb-ot-os2-table.hh"
-#include "hb-ot-var-hvar-table.hh"
-
-
-namespace OT {
-
-
-/*
- * hmtx -- The Horizontal Metrics Table
- * vmtx -- The Vertical Metrics Table
- */
-
-#define HB_OT_TAG_hmtx HB_TAG('h','m','t','x')
-#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
-
-
-struct LongMetric
-{
-  UFWORD	advance; /* Advance width/height. */
-  FWORD		lsb; /* Leading (left/top) side bearing. */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-template <typename T, typename H>
-struct hmtxvmtx
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    /* We don't check for anything specific here.  The users of the
-     * struct do all the hard work... */
-    return_trace (true);
-  }
-
-
-  inline bool subset_update_header (hb_subset_plan_t *plan,
-                                    unsigned int num_hmetrics) const
-  {
-    hb_blob_t *src_blob = OT::Sanitizer<H> ().sanitize (plan->source->reference_table (H::tableTag));
-    hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail(src_blob);
-    hb_blob_destroy (src_blob);
-
-    if (unlikely (!dest_blob)) {
-      return false;
-    }
-
-    unsigned int length;
-    H *table = (H *) hb_blob_get_data (dest_blob, &length);
-    table->numberOfLongMetrics.set (num_hmetrics);
-
-    bool result = hb_subset_plan_add_table (plan, H::tableTag, dest_blob);
-    hb_blob_destroy (dest_blob);
-
-    return result;
-  }
-
-  inline bool subset (hb_subset_plan_t *plan) const
-  {
-    typename T::accelerator_t _mtx;
-    _mtx.init (plan->source);
-
-    /* All the trailing glyphs with the same advance can use one LongMetric
-     * and just keep LSB */
-    hb_prealloced_array_t<hb_codepoint_t> &gids = plan->gids_to_retain_sorted;
-    unsigned int num_advances = gids.len;
-    unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]);
-    while (num_advances > 1
-        && last_advance == _mtx.get_advance (gids[num_advances - 2]))
-    {
-      num_advances--;
-    }
-
-    /* alloc the new table */
-    size_t dest_sz = num_advances * 4
-                  + (gids.len - num_advances) * 2;
-    void *dest = (void *) malloc (dest_sz);
-    if (unlikely (!dest))
-    {
-      return false;
-    }
-    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in src has %d advances, %d lsbs", HB_UNTAG(T::tableTag), _mtx.num_advances, _mtx.num_metrics - _mtx.num_advances);
-    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", HB_UNTAG(T::tableTag), num_advances, gids.len - num_advances, (unsigned int) dest_sz);
-
-    const char *source_table = hb_blob_get_data (_mtx.blob, nullptr);
-    // Copy everything over
-    LongMetric * old_metrics = (LongMetric *) source_table;
-    FWORD *lsbs = (FWORD *) (old_metrics + _mtx.num_advances);
-    char * dest_pos = (char *) dest;
-    for (unsigned int i = 0; i < gids.len; i++)
-    {
-      /* the last metric or the one for gids[i] */
-      LongMetric *src_metric = old_metrics + MIN ((hb_codepoint_t) _mtx.num_advances - 1, gids[i]);
-      if (gids[i] < _mtx.num_advances)
-      {
-        /* src is a LongMetric */
-        if (i < num_advances)
-        {
-          /* dest is a LongMetric, copy it */
-          *((LongMetric *) dest_pos) = *src_metric;
-        }
-        else
-        {
-          /* dest just lsb */
-          *((FWORD *) dest_pos) = src_metric->lsb;
-        }
-      }
-      else
-      {
-        FWORD src_lsb = *(lsbs + gids[i] - _mtx.num_advances);
-        if (i < num_advances)
-        {
-          /* dest needs a full LongMetric */
-          LongMetric *metric = (LongMetric *)dest_pos;
-          metric->advance = src_metric->advance;
-          metric->lsb = src_lsb;
-        }
-        else
-        {
-          /* dest just needs an lsb */
-          *((FWORD *) dest_pos) = src_lsb;
-        }
-      }
-      dest_pos += (i < num_advances ? 4 : 2);
-    }
-    _mtx.fini ();
-
-    // Amend header num hmetrics
-    if (unlikely (!subset_update_header (plan, num_advances)))
-    {
-      free (dest);
-      return false;
-    }
-
-    hb_blob_t *result = hb_blob_create ((const char *)dest,
-                                        dest_sz,
-                                        HB_MEMORY_MODE_READONLY,
-                                        dest,
-                                        free);
-    bool success = hb_subset_plan_add_table (plan, T::tableTag, result);
-    hb_blob_destroy (result);
-    return success;
-  }
-
-  struct accelerator_t
-  {
-    friend struct hmtxvmtx;
-
-    inline void init (hb_face_t *face,
-		      unsigned int default_advance_ = 0)
-    {
-      default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
-
-      bool got_font_extents = false;
-      if (T::os2Tag)
-      {
-	hb_blob_t *os2_blob = Sanitizer<os2> ().sanitize (face->reference_table (T::os2Tag));
-	const os2 *os2_table = Sanitizer<os2>::lock_instance (os2_blob);
-#define USE_TYPO_METRICS (1u<<7)
-	if (0 != (os2_table->fsSelection & USE_TYPO_METRICS))
-	{
-	  ascender = os2_table->sTypoAscender;
-	  descender = os2_table->sTypoDescender;
-	  line_gap = os2_table->sTypoLineGap;
-	  got_font_extents = (ascender | descender) != 0;
-	}
-	hb_blob_destroy (os2_blob);
-      }
-
-      hb_blob_t *_hea_blob = Sanitizer<H> ().sanitize (face->reference_table (H::tableTag));
-      const H *_hea_table = Sanitizer<H>::lock_instance (_hea_blob);
-      num_advances = _hea_table->numberOfLongMetrics;
-      if (!got_font_extents)
-      {
-	ascender = _hea_table->ascender;
-	descender = _hea_table->descender;
-	line_gap = _hea_table->lineGap;
-	got_font_extents = (ascender | descender) != 0;
-      }
-      hb_blob_destroy (_hea_blob);
-
-      has_font_extents = got_font_extents;
-
-      blob = Sanitizer<hmtxvmtx> ().sanitize (face->reference_table (T::tableTag));
-
-      /* Cap num_metrics() and num_advances() based on table length. */
-      unsigned int len = hb_blob_get_length (blob);
-      if (unlikely (num_advances * 4 > len))
-	num_advances = len / 4;
-      num_metrics = num_advances + (len - 4 * num_advances) / 2;
-
-      /* We MUST set num_metrics to zero if num_advances is zero.
-       * Our get_advance() depends on that. */
-      if (unlikely (!num_advances))
-      {
-	num_metrics = num_advances = 0;
-	hb_blob_destroy (blob);
-	blob = hb_blob_get_empty ();
-      }
-      table = Sanitizer<hmtxvmtx>::lock_instance (blob);
-
-      var_blob = Sanitizer<HVARVVAR> ().sanitize (face->reference_table (T::variationsTag));
-      var_table = Sanitizer<HVARVVAR>::lock_instance (var_blob);
-    }
-
-    inline void fini (void)
-    {
-      hb_blob_destroy (blob);
-      hb_blob_destroy (var_blob);
-    }
-
-    inline unsigned int get_advance (hb_codepoint_t  glyph) const
-    {
-      if (unlikely (glyph >= num_metrics))
-      {
-        /* If num_metrics is zero, it means we don't have the metrics table
-         * for this direction: return default advance.  Otherwise, it means that the
-         * glyph index is out of bound: return zero. */
-        if (num_metrics)
-          return 0;
-        else
-          return default_advance;
-      }
-
-      return table->longMetric[MIN (glyph, (uint32_t) num_advances - 1)].advance;
-    }
-
-    inline unsigned int get_advance (hb_codepoint_t  glyph,
-                                     hb_font_t      *font) const
-    {
-      unsigned int advance = get_advance (glyph);
-      if (likely(glyph < num_metrics))
-      {
-        advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?!
-      }
-      return advance;	        
-    }
-
-    public:
-    bool has_font_extents;
-    unsigned short ascender;
-    unsigned short descender;
-    unsigned short line_gap;
-
-    protected:
-    unsigned int num_metrics;
-    unsigned int num_advances;
-    unsigned int default_advance;
-
-    private:
-    const hmtxvmtx *table;
-    hb_blob_t *blob;
-    const HVARVVAR *var_table;
-    hb_blob_t *var_blob;
-  };
-
-  protected:
-  LongMetric	longMetric[VAR];	/* Paired advance width and leading
-					 * bearing values for each glyph. The
-					 * value numOfHMetrics comes from
-					 * the 'hhea' table. If the font is
-					 * monospaced, only one entry need
-					 * be in the array, but that entry is
-					 * required. The last entry applies to
-					 * all subsequent glyphs. */
-/*FWORD		leadingBearingX[VAR];*/	/* Here the advance is assumed
-					 * to be the same as the advance
-					 * for the last entry above. The
-					 * number of entries in this array is
-					 * derived from numGlyphs (from 'maxp'
-					 * table) minus numberOfLongMetrics.
-					 * This generally is used with a run
-					 * of monospaced glyphs (e.g., Kanji
-					 * fonts or Courier fonts). Only one
-					 * run is allowed and it must be at
-					 * the end. This allows a monospaced
-					 * font to vary the side bearing
-					 * values for each glyph. */
-  public:
-  DEFINE_SIZE_ARRAY (0, longMetric);
-};
-
-struct hmtx : hmtxvmtx<hmtx, hhea> {
-  static const hb_tag_t tableTag	= HB_OT_TAG_hmtx;
-  static const hb_tag_t variationsTag	= HB_OT_TAG_HVAR;
-  static const hb_tag_t os2Tag		= HB_OT_TAG_os2;
-};
-struct vmtx : hmtxvmtx<vmtx, vhea> {
-  static const hb_tag_t tableTag	= HB_OT_TAG_vmtx;
-  static const hb_tag_t variationsTag	= HB_OT_TAG_VVAR;
-  static const hb_tag_t os2Tag		= HB_TAG_NONE;
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_HMTX_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-kern-table.hh b/third_party/harfbuzz-ng/src/hb-ot-kern-table.hh
deleted file mode 100644
index 368f547..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-kern-table.hh
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_KERN_TABLE_HH
-#define HB_OT_KERN_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-namespace OT {
-
-
-/*
- * kern -- Kerning
- */
-
-#define HB_OT_TAG_kern HB_TAG('k','e','r','n')
-
-struct hb_glyph_pair_t
-{
-  hb_codepoint_t left;
-  hb_codepoint_t right;
-};
-
-struct KernPair
-{
-  inline int get_kerning (void) const
-  { return value; }
-
-  inline int cmp (const hb_glyph_pair_t &o) const
-  {
-    int ret = left.cmp (o.left);
-    if (ret) return ret;
-    return right.cmp (o.right);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  GlyphID	left;
-  GlyphID	right;
-  FWORD		value;
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct KernSubTableFormat0
-{
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-  {
-    hb_glyph_pair_t pair = {left, right};
-    int i = pairs.bsearch (pair);
-    if (i == -1)
-      return 0;
-    return pairs[i].get_kerning ();
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (pairs.sanitize (c));
-  }
-
-  protected:
-  BinSearchArrayOf<KernPair> pairs;	/* Array of kerning pairs. */
-  public:
-  DEFINE_SIZE_ARRAY (8, pairs);
-};
-
-struct KernClassTable
-{
-  inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (firstGlyph.sanitize (c) && classes.sanitize (c));
-  }
-
-  protected:
-  HBUINT16		firstGlyph;	/* First glyph in class range. */
-  ArrayOf<HBUINT16>	classes;	/* Glyph classes. */
-  public:
-  DEFINE_SIZE_ARRAY (4, classes);
-};
-
-struct KernSubTableFormat2
-{
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
-  {
-    unsigned int l = (this+leftClassTable).get_class (left);
-    unsigned int r = (this+rightClassTable).get_class (right);
-    unsigned int offset = l * rowWidth + r * sizeof (FWORD);
-    const FWORD *arr = &(this+array);
-    if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end))
-      return 0;
-    const FWORD *v = &StructAtOffset<FWORD> (arr, offset);
-    if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end))
-      return 0;
-    return *v;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rowWidth.sanitize (c) &&
-		  leftClassTable.sanitize (c, this) &&
-		  rightClassTable.sanitize (c, this) &&
-		  array.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16	rowWidth;	/* The width, in bytes, of a row in the table. */
-  OffsetTo<KernClassTable>
-		leftClassTable;	/* Offset from beginning of this subtable to
-				 * left-hand class table. */
-  OffsetTo<KernClassTable>
-		rightClassTable;/* Offset from beginning of this subtable to
-				 * right-hand class table. */
-  OffsetTo<FWORD>
-		array;		/* Offset from beginning of this subtable to
-				 * the start of the kerning array. */
-  public:
-  DEFINE_SIZE_MIN (8);
-};
-
-struct KernSubTable
-{
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const
-  {
-    switch (format) {
-    case 0: return u.format0.get_kerning (left, right);
-    case 2: return u.format2.get_kerning (left, right, end);
-    default:return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const
-  {
-    TRACE_SANITIZE (this);
-    switch (format) {
-    case 0: return_trace (u.format0.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  KernSubTableFormat0	format0;
-  KernSubTableFormat2	format2;
-  } u;
-  public:
-  DEFINE_SIZE_MIN (0);
-};
-
-
-template <typename T>
-struct KernSubTableWrapper
-{
-  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
-  inline const T* thiz (void) const { return static_cast<const T *> (this); }
-
-  inline bool is_horizontal (void) const
-  { return (thiz()->coverage & T::COVERAGE_CHECK_FLAGS) == T::COVERAGE_CHECK_HORIZONTAL; }
-
-  inline bool is_override (void) const
-  { return bool (thiz()->coverage & T::COVERAGE_OVERRIDE_FLAG); }
-
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
-  { return thiz()->subtable.get_kerning (left, right, end, thiz()->format); }
-
-  inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
-  { return is_horizontal () ? get_kerning (left, right, end) : 0; }
-
-  inline unsigned int get_size (void) const { return thiz()->length; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (thiz()) &&
-		  thiz()->length >= thiz()->min_size &&
-		  c->check_array (thiz(), 1, thiz()->length) &&
-		  thiz()->subtable.sanitize (c, thiz()->format));
-  }
-};
-
-template <typename T>
-struct KernTable
-{
-  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
-  inline const T* thiz (void) const { return static_cast<const T *> (this); }
-
-  inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
-  {
-    int v = 0;
-    const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
-    unsigned int count = thiz()->nTables;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (st->is_override ())
-        v = 0;
-      v += st->get_h_kerning (left, right, table_length + (const char *) this);
-      st = &StructAfter<typename T::SubTableWrapper> (*st);
-    }
-    return v;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (thiz()) ||
-		  thiz()->version != T::VERSION))
-      return_trace (false);
-
-    const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
-    unsigned int count = thiz()->nTables;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (unlikely (!st->sanitize (c)))
-	return_trace (false);
-      st = &StructAfter<typename T::SubTableWrapper> (*st);
-    }
-
-    return_trace (true);
-  }
-};
-
-struct KernOT : KernTable<KernOT>
-{
-  friend struct KernTable<KernOT>;
-
-  static const uint16_t VERSION = 0x0000u;
-
-  struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
-  {
-    friend struct KernSubTableWrapper<SubTableWrapper>;
-
-    enum coverage_flags_t {
-      COVERAGE_DIRECTION_FLAG	= 0x01u,
-      COVERAGE_MINIMUM_FLAG	= 0x02u,
-      COVERAGE_CROSSSTREAM_FLAG	= 0x04u,
-      COVERAGE_OVERRIDE_FLAG	= 0x08u,
-
-      COVERAGE_VARIATION_FLAG	= 0x00u, /* Not supported. */
-
-      COVERAGE_CHECK_FLAGS	= 0x07u,
-      COVERAGE_CHECK_HORIZONTAL	= 0x01u
-    };
-
-    protected:
-    HBUINT16	versionZ;	/* Unused. */
-    HBUINT16	length;		/* Length of the subtable (including this header). */
-    HBUINT8	format;		/* Subtable format. */
-    HBUINT8	coverage;	/* Coverage bits. */
-    KernSubTable subtable;	/* Subtable data. */
-    public:
-    DEFINE_SIZE_MIN (6);
-  };
-
-  protected:
-  HBUINT16	version;	/* Version--0x0000u */
-  HBUINT16	nTables;	/* Number of subtables in the kerning table. */
-  HBUINT8		data[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (4, data);
-};
-
-struct KernAAT : KernTable<KernAAT>
-{
-  friend struct KernTable<KernAAT>;
-
-  static const uint32_t VERSION = 0x00010000u;
-
-  struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
-  {
-    friend struct KernSubTableWrapper<SubTableWrapper>;
-
-    enum coverage_flags_t {
-      COVERAGE_DIRECTION_FLAG	= 0x80u,
-      COVERAGE_CROSSSTREAM_FLAG	= 0x40u,
-      COVERAGE_VARIATION_FLAG	= 0x20u,
-
-      COVERAGE_OVERRIDE_FLAG	= 0x00u, /* Not supported. */
-
-      COVERAGE_CHECK_FLAGS	= 0xE0u,
-      COVERAGE_CHECK_HORIZONTAL	= 0x00u
-    };
-
-    protected:
-    HBUINT32	length;		/* Length of the subtable (including this header). */
-    HBUINT8	coverage;	/* Coverage bits. */
-    HBUINT8	format;		/* Subtable format. */
-    HBUINT16	tupleIndex;	/* The tuple index (used for variations fonts).
-				 * This value specifies which tuple this subtable covers. */
-    KernSubTable subtable;	/* Subtable data. */
-    public:
-    DEFINE_SIZE_MIN (8);
-  };
-
-  protected:
-  HBUINT32		version;	/* Version--0x00010000u */
-  HBUINT32		nTables;	/* Number of subtables in the kerning table. */
-  HBUINT8		data[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (8, data);
-};
-
-struct kern
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_kern;
-
-  inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
-  {
-    switch (u.major) {
-    case 0: return u.ot.get_h_kerning (left, right, table_length);
-    case 1: return u.aat.get_h_kerning (left, right, table_length);
-    default:return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.major.sanitize (c)) return_trace (false);
-    switch (u.major) {
-    case 0: return_trace (u.ot.sanitize (c));
-    case 1: return_trace (u.aat.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  struct accelerator_t
-  {
-    inline void init (hb_face_t *face)
-    {
-      blob = Sanitizer<kern>().sanitize (face->reference_table (HB_OT_TAG_kern));
-      table = Sanitizer<kern>::lock_instance (blob);
-      table_length = hb_blob_get_length (blob);
-    }
-    inline void fini (void)
-    {
-      hb_blob_destroy (blob);
-    }
-
-    inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-    { return table->get_h_kerning (left, right, table_length); }
-
-    private:
-    hb_blob_t *blob;
-    const kern *table;
-    unsigned int table_length;
-  };
-
-  protected:
-  union {
-  HBUINT16		major;
-  KernOT		ot;
-  KernAAT		aat;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, major);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_KERN_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-base-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-base-table.hh
deleted file mode 100644
index 20b8bd76..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-base-table.hh
+++ /dev/null
@@ -1,655 +0,0 @@
-/*
- * Copyright © 2016 Elie Roux <elie.roux@telecom-bretagne.eu>
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_LAYOUT_BASE_TABLE_HH
-#define HB_OT_LAYOUT_BASE_TABLE_HH
-
-#include "hb-open-type-private.hh"
-#include "hb-ot-layout-common-private.hh"
-
-namespace OT {
-
-#define NOT_INDEXED   ((unsigned int) -1)
-
-/*
- * BASE -- The BASE Table
- */
-
-struct BaseCoordFormat1
-{
-  inline int get_coord (void) const { return coordinate; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16	format;		/* Format identifier--format = 1 */
-  HBINT16	coordinate;	/* X or Y value, in design units */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-struct BaseCoordFormat2
-{
-  inline int get_coord (void) const
-  {
-    /* TODO */
-    return coordinate;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16	format;		/* Format identifier--format = 2 */
-  HBINT16	coordinate;	/* X or Y value, in design units */
-  GlyphID	referenceGlyph;	/* Glyph ID of control glyph */
-  HBUINT16	coordPoint;	/* Index of contour point on the
-				 * reference glyph */
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct BaseCoordFormat3
-{
-  inline int get_coord (void) const
-  {
-    /* TODO */
-    return coordinate;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16		format;		/* Format identifier--format = 3 */
-  HBINT16		coordinate;	/* X or Y value, in design units */
-  OffsetTo<Device>	deviceTable;	/* Offset to Device table for X or
-					 * Y value, from beginning of
-					 * BaseCoord table (may be NULL). */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct BaseCoord
-{
-  inline int get_coord (void) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_coord ();
-    case 2: return u.format2.get_coord ();
-    case 3: return u.format3.get_coord ();
-    default:return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    case 3: return_trace (u.format3.sanitize (c));
-    default:return_trace (false);
-    }
-  }
-
-  protected:
-  union {
-    HBUINT16		format;
-    BaseCoordFormat1	format1;
-    BaseCoordFormat2	format2;
-    BaseCoordFormat3	format3;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-struct FeatMinMaxRecord
-{
-  inline int get_min_value (void) const
-  { return (this+minCoord).get_coord(); }
-
-  inline int get_max_value (void) const
-  { return (this+maxCoord).get_coord(); }
-
-  inline const Tag &get_tag () const
-  { return tag; }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  minCoord.sanitize (c, base) &&
-		  maxCoord.sanitize (c, base));
-  }
-
-  protected:
-  Tag                   tag;		/* 4-byte feature identification tag--must
-					 * match feature tag in FeatureList */
-  OffsetTo<BaseCoord>   minCoord;	/* Offset to BaseCoord table that defines
-					 * the minimum extent value, from beginning
-					 * of MinMax table (may be NULL) */
-  OffsetTo<BaseCoord>   maxCoord;	/* Offset to BaseCoord table that defines
-					 * the maximum extent value, from beginning
-					 * of MinMax table (may be NULL) */
-  public:
-  DEFINE_SIZE_STATIC (8);
-
-};
-
-struct MinMax
-{
-  inline unsigned int get_feature_tag_index (Tag featureTableTag) const
-  {
-    /* TODO bsearch */
-    unsigned int count = featMinMaxRecords.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      Tag tag = featMinMaxRecords[i].get_tag();
-      int cmp = tag.cmp(featureTableTag);
-      if (cmp == 0) return i;
-      if (cmp > 0)  return NOT_INDEXED;
-    }
-    return NOT_INDEXED;
-  }
-
-  inline int get_min_value (unsigned int featureTableTagIndex) const
-  {
-    if (featureTableTagIndex == NOT_INDEXED)
-      return (this+minCoord).get_coord();
-    return featMinMaxRecords[featureTableTagIndex].get_min_value();
-  }
-
-  inline int get_max_value (unsigned int featureTableTagIndex) const
-  {
-    if (featureTableTagIndex == NOT_INDEXED)
-      return (this+maxCoord).get_coord();
-    return featMinMaxRecords[featureTableTagIndex].get_max_value();
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  minCoord.sanitize (c, this) &&
-		  maxCoord.sanitize (c, this) &&
-		  featMinMaxRecords.sanitize (c, this));
-  }
-
-  protected:
-  OffsetTo<BaseCoord>	minCoord;	/* Offset to BaseCoord table that defines
-					 * minimum extent value, from the beginning
-					 * of MinMax table (may be NULL) */
-  OffsetTo<BaseCoord>	maxCoord;	/* Offset to BaseCoord table that defines
-					 * maximum extent value, from the beginning
-					 * of MinMax table (may be NULL) */
-  ArrayOf<FeatMinMaxRecord>
-		featMinMaxRecords;	/* Array of FeatMinMaxRecords, in alphabetical
-					 * order by featureTableTag */
-  public:
-  DEFINE_SIZE_ARRAY (6, featMinMaxRecords);
-};
-
-/* TODO... */
-struct BaseLangSysRecord
-{
-  inline const Tag& get_tag(void) const
-  { return baseLangSysTag; }
-
-  inline unsigned int get_feature_tag_index (Tag featureTableTag) const
-  { return (this+minMax).get_feature_tag_index(featureTableTag); }
-
-  inline int get_min_value (unsigned int featureTableTagIndex) const
-  { return (this+minMax).get_min_value(featureTableTagIndex); }
-
-  inline int get_max_value (unsigned int featureTableTagIndex) const
-  { return (this+minMax).get_max_value(featureTableTagIndex); }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  minMax.sanitize (c, base));
-  }
-
-  protected:
-  Tag			baseLangSysTag;
-  OffsetTo<MinMax>	minMax;
-  public:
-  DEFINE_SIZE_STATIC (6);
-
-};
-
-struct BaseValues
-{
-  inline unsigned int get_default_base_tag_index (void) const
-  { return defaultIndex; }
-
-  inline int get_base_coord (unsigned int baselineTagIndex) const
-  {
-    return (this+baseCoords[baselineTagIndex]).get_coord();
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      defaultIndex <= baseCoordCount &&
-      baseCoords.sanitize (c, this));
-  }
-
-  protected:
-  Index				defaultIndex;
-  HBUINT16			baseCoordCount;
-  OffsetArrayOf<BaseCoord>	baseCoords;
-  public:
-  DEFINE_SIZE_ARRAY (6, baseCoords);
-
-};
-
-struct BaseScript {
-
-  inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
-  {
-    Tag tag;
-    int cmp;
-    for (unsigned int i = 0; i < baseLangSysCount; i++) {
-      tag = baseLangSysRecords[i].get_tag();
-      // taking advantage of alphabetical order
-      cmp = tag.cmp(baseLangSysTag);
-      if (cmp == 0) return i;
-      if (cmp > 0)  return NOT_INDEXED;
-    }
-    return NOT_INDEXED;
-  }
-
-  inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (baseLangSysIndex == NOT_INDEXED) {
-      if (unlikely(defaultMinMax)) return NOT_INDEXED;
-      return (this+defaultMinMax).get_feature_tag_index(featureTableTag);
-    }
-    if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED;
-    return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag);
-  }
-
-  inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    if (baseLangSysIndex == NOT_INDEXED)
-      return (this+defaultMinMax).get_min_value(featureTableTagIndex);
-    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
-  }
-
-  inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    if (baseLangSysIndex == NOT_INDEXED)
-      return (this+defaultMinMax).get_min_value(featureTableTagIndex);
-    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
-  }
-
-  inline unsigned int get_default_base_tag_index (void) const
-  { return (this+baseValues).get_default_base_tag_index(); }
-
-  inline int get_base_coord (unsigned int baselineTagIndex) const
-  { return (this+baseValues).get_base_coord(baselineTagIndex); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseValues.sanitize (c, this) &&
-      defaultMinMax.sanitize (c, this) &&
-      baseLangSysRecords.sanitize (c, this));
-  }
-
-  protected:
-  OffsetTo<BaseValues>        baseValues;
-  OffsetTo<MinMax>            defaultMinMax;
-  HBUINT16                      baseLangSysCount;
-  ArrayOf<BaseLangSysRecord>  baseLangSysRecords;
-
-  public:
-    DEFINE_SIZE_ARRAY (8, baseLangSysRecords);
-};
-
-
-struct BaseScriptRecord {
-
-  inline const Tag& get_tag (void) const
-  { return baseScriptTag; }
-
-  inline unsigned int get_default_base_tag_index(void) const
-  { return (this+baseScript).get_default_base_tag_index(); }
-
-  inline int get_base_coord(unsigned int baselineTagIndex) const
-  { return (this+baseScript).get_base_coord(baselineTagIndex); }
-
-  inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
-  { return (this+baseScript).get_lang_tag_index(baseLangSysTag); }
-
-  inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
-  { return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); }
-
-  inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); }
-
-  inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseScript != Null(OffsetTo<BaseScript>) &&
-      baseScript.sanitize (c, base));
-  }
-
-  protected:
-  Tag                   baseScriptTag;
-  OffsetTo<BaseScript>  baseScript;
-
-  public:
-    DEFINE_SIZE_STATIC (6);
-};
-
-struct BaseScriptList {
-
-  inline unsigned int get_base_script_index (Tag baseScriptTag) const
-  {
-    for (unsigned int i = 0; i < baseScriptCount; i++)
-      if (baseScriptRecords[i].get_tag() == baseScriptTag)
-        return i;
-    return NOT_INDEXED;
-  }
-
-  inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
-    return baseScriptRecords[baseScriptIndex].get_default_base_tag_index();
-  }
-
-  inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return baseScriptRecords[baseScriptIndex].get_base_coord(baselineTagIndex);
-  }
-
-  inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
-  {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
-    return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag);
-  }
-
-  inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
-    return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag);
-  }
-
-  inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return baseScriptRecords[baseScriptIndex].get_max_value(baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return baseScriptRecords[baseScriptIndex].get_min_value(baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseScriptRecords.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16                    baseScriptCount;
-  ArrayOf<BaseScriptRecord> baseScriptRecords;
-
-  public:
-  DEFINE_SIZE_ARRAY (4, baseScriptRecords);
-
-};
-
-struct BaseTagList
-{
-
-  inline unsigned int get_tag_index(Tag baselineTag) const
-  {
-    for (unsigned int i = 0; i < baseTagCount; i++)
-      if (baselineTags[i] == baselineTag)
-        return i;
-    return NOT_INDEXED;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16        baseTagCount;
-  SortedArrayOf<Tag>  baselineTags;
-
-  public:
-  DEFINE_SIZE_ARRAY (4, baselineTags);
-};
-
-struct Axis
-{
-
-  inline unsigned int get_base_tag_index(Tag baselineTag) const
-  {
-    if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return NOT_INDEXED;
-    return (this+baseTagList).get_tag_index(baselineTag);
-  }
-
-  inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
-    return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex);
-  }
-
-  inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex);
-  }
-
-  inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
-  {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
-    return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag);
-  }
-
-  inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
-    return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag);
-  }
-
-  inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+baseScriptList).get_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+baseScriptList).get_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseTagList.sanitize (c, this) &&
-      baseScriptList.sanitize (c, this));
-  }
-
-  protected:
-  OffsetTo<BaseTagList>     baseTagList;
-  OffsetTo<BaseScriptList>  baseScriptList;
-
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-struct BASE
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_BASE;
-
-  inline bool has_vert_axis(void)
-  { return vertAxis != Null(OffsetTo<Axis>); }
-
-  inline bool has_horiz_axis(void)
-  { return horizAxis != Null(OffsetTo<Axis>); }
-
-  // horizontal axis base coords:
-
-  inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
-  {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_base_tag_index(baselineTag);
-  }
-
-  inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
-  }
-
-  inline int get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
-  }
-
-  // vertical axis base coords:
-
-  inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_base_tag_index(baselineTag);
-  }
-
-  inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
-  }
-
-  inline int get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
-  }
-
-  // horizontal axis min/max coords:
-
-  inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
-  {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
-  }
-
-  inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
-  }
-
-  inline int get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline int get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-    // vertical axis min/max coords:
-
-  inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
-  }
-
-  inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
-  }
-
-  inline int get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline int get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  likely (version.major == 1) &&
-		  horizAxis.sanitize (c, this) &&
-		  vertAxis.sanitize (c, this) &&
-		  (version.to_int () < 0x00010001u || varStore.sanitize (c, this)));
-  }
-
-  protected:
-  FixedVersion<>  version;
-  OffsetTo<Axis>  horizAxis;
-  OffsetTo<Axis>  vertAxis;
-  LOffsetTo<VariationStore>
-		varStore;		/* Offset to the table of Item Variation
-					 * Store--from beginning of BASE
-					 * header (may be NULL).  Introduced
-					 * in version 0x00010001. */
-  public:
-  DEFINE_SIZE_MIN (8);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_LAYOUT_BASE_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh
deleted file mode 100644
index c5e7f521..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh
+++ /dev/null
@@ -1,1773 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2010,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH
-#define HB_OT_LAYOUT_COMMON_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-ot-layout-private.hh"
-#include "hb-open-type-private.hh"
-#include "hb-set-private.hh"
-
-
-#ifndef HB_MAX_NESTING_LEVEL
-#define HB_MAX_NESTING_LEVEL	6
-#endif
-#ifndef HB_MAX_CONTEXT_LENGTH
-#define HB_MAX_CONTEXT_LENGTH	64
-#endif
-
-
-namespace OT {
-
-
-#define NOT_COVERED		((unsigned int) -1)
-
-
-
-/*
- *
- * OpenType Layout Common Table Formats
- *
- */
-
-
-/*
- * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
- */
-
-template <typename Type>
-struct Record
-{
-  inline int cmp (hb_tag_t a) const {
-    return tag.cmp (a);
-  }
-
-  struct sanitize_closure_t {
-    hb_tag_t tag;
-    const void *list_base;
-  };
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    const sanitize_closure_t closure = {tag, base};
-    return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
-  }
-
-  Tag		tag;		/* 4-byte Tag identifier */
-  OffsetTo<Type>
-		offset;		/* Offset from beginning of object holding
-				 * the Record */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-template <typename Type>
-struct RecordArrayOf : SortedArrayOf<Record<Type> > {
-  inline const Tag& get_tag (unsigned int i) const
-  {
-    /* We cheat slightly and don't define separate Null objects
-     * for Record types.  Instead, we return the correct Null(Tag)
-     * here. */
-    if (unlikely (i >= this->len)) return Null(Tag);
-    return (*this)[i].tag;
-  }
-  inline unsigned int get_tags (unsigned int start_offset,
-				unsigned int *record_count /* IN/OUT */,
-				hb_tag_t     *record_tags /* OUT */) const
-  {
-    if (record_count) {
-      const Record<Type> *arr = this->sub_array (start_offset, record_count);
-      unsigned int count = *record_count;
-      for (unsigned int i = 0; i < count; i++)
-	record_tags[i] = arr[i].tag;
-    }
-    return this->len;
-  }
-  inline bool find_index (hb_tag_t tag, unsigned int *index) const
-  {
-    /* If we want to allow non-sorted data, we can lsearch(). */
-    int i = this->/*lsearch*/bsearch (tag);
-    if (i != -1) {
-        if (index) *index = i;
-        return true;
-    } else {
-      if (index) *index = Index::NOT_FOUND_INDEX;
-      return false;
-    }
-  }
-};
-
-template <typename Type>
-struct RecordListOf : RecordArrayOf<Type>
-{
-  inline const Type& operator [] (unsigned int i) const
-  { return this+RecordArrayOf<Type>::operator [](i).offset; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (RecordArrayOf<Type>::sanitize (c, this));
-  }
-};
-
-
-struct RangeRecord
-{
-  inline int cmp (hb_codepoint_t g) const {
-    return g < start ? -1 : g <= end ? 0 : +1 ;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  inline bool intersects (const hb_set_t *glyphs) const {
-    return glyphs->intersects (start, end);
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    return glyphs->add_range (start, end);
-  }
-
-  GlyphID	start;		/* First GlyphID in the range */
-  GlyphID	end;		/* Last GlyphID in the range */
-  HBUINT16	value;		/* Value */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-DEFINE_NULL_DATA (RangeRecord, "\000\001");
-
-
-struct IndexArray : ArrayOf<Index>
-{
-  inline unsigned int get_indexes (unsigned int start_offset,
-				   unsigned int *_count /* IN/OUT */,
-				   unsigned int *_indexes /* OUT */) const
-  {
-    if (_count) {
-      const HBUINT16 *arr = this->sub_array (start_offset, _count);
-      unsigned int count = *_count;
-      for (unsigned int i = 0; i < count; i++)
-	_indexes[i] = arr[i];
-    }
-    return this->len;
-  }
-};
-
-
-struct Script;
-struct LangSys;
-struct Feature;
-
-
-struct LangSys
-{
-  inline unsigned int get_feature_count (void) const
-  { return featureIndex.len; }
-  inline hb_tag_t get_feature_index (unsigned int i) const
-  { return featureIndex[i]; }
-  inline unsigned int get_feature_indexes (unsigned int start_offset,
-					   unsigned int *feature_count /* IN/OUT */,
-					   unsigned int *feature_indexes /* OUT */) const
-  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
-
-  inline bool has_required_feature (void) const { return reqFeatureIndex != 0xFFFFu; }
-  inline unsigned int get_required_feature_index (void) const
-  {
-    if (reqFeatureIndex == 0xFFFFu)
-      return Index::NOT_FOUND_INDEX;
-   return reqFeatureIndex;;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-			const Record<LangSys>::sanitize_closure_t * = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && featureIndex.sanitize (c));
-  }
-
-  Offset16	lookupOrderZ;	/* = Null (reserved for an offset to a
-				 * reordering table) */
-  HBUINT16	reqFeatureIndex;/* Index of a feature required for this
-				 * language system--if no required features
-				 * = 0xFFFFu */
-  IndexArray	featureIndex;	/* Array of indices into the FeatureList */
-  public:
-  DEFINE_SIZE_ARRAY (6, featureIndex);
-};
-DEFINE_NULL_DATA (LangSys, "\0\0\xFF\xFF");
-
-
-struct Script
-{
-  inline unsigned int get_lang_sys_count (void) const
-  { return langSys.len; }
-  inline const Tag& get_lang_sys_tag (unsigned int i) const
-  { return langSys.get_tag (i); }
-  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
-					 unsigned int *lang_sys_count /* IN/OUT */,
-					 hb_tag_t     *lang_sys_tags /* OUT */) const
-  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
-  inline const LangSys& get_lang_sys (unsigned int i) const
-  {
-    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
-    return this+langSys[i].offset;
-  }
-  inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
-  { return langSys.find_index (tag, index); }
-
-  inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
-  inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-			const Record<Script>::sanitize_closure_t * = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
-  }
-
-  protected:
-  OffsetTo<LangSys>
-		defaultLangSys;	/* Offset to DefaultLangSys table--from
-				 * beginning of Script table--may be Null */
-  RecordArrayOf<LangSys>
-		langSys;	/* Array of LangSysRecords--listed
-				 * alphabetically by LangSysTag */
-  public:
-  DEFINE_SIZE_ARRAY (4, langSys);
-};
-
-typedef RecordListOf<Script> ScriptList;
-
-
-/* http://www.microsoft.com/typography/otspec/features_pt.htm#size */
-struct FeatureParamsSize
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return_trace (false);
-
-    /* This subtable has some "history", if you will.  Some earlier versions of
-     * Adobe tools calculated the offset of the FeatureParams sutable from the
-     * beginning of the FeatureList table!  Now, that is dealt with in the
-     * Feature implementation.  But we still need to be able to tell junk from
-     * real data.  Note: We don't check that the nameID actually exists.
-     *
-     * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
-     *
-     * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
-     * coming out soon, and that the makeotf program will build a font with a
-     * 'size' feature that is correct by the specification.
-     *
-     * The specification for this feature tag is in the "OpenType Layout Tag
-     * Registry". You can see a copy of this at:
-     * http://partners.adobe.com/public/developer/opentype/index_tag8.html#size
-     *
-     * Here is one set of rules to determine if the 'size' feature is built
-     * correctly, or as by the older versions of MakeOTF. You may be able to do
-     * better.
-     *
-     * Assume that the offset to the size feature is according to specification,
-     * and make the following value checks. If it fails, assume the size
-     * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
-     * If this fails, reject the 'size' feature. The older makeOTF's calculated the
-     * offset from the beginning of the FeatureList table, rather than from the
-     * beginning of the 'size' Feature table.
-     *
-     * If "design size" == 0:
-     *     fails check
-     *
-     * Else if ("subfamily identifier" == 0 and
-     *     "range start" == 0 and
-     *     "range end" == 0 and
-     *     "range start" == 0 and
-     *     "menu name ID" == 0)
-     *     passes check: this is the format used when there is a design size
-     * specified, but there is no recommended size range.
-     *
-     * Else if ("design size" <  "range start" or
-     *     "design size" >   "range end" or
-     *     "range end" <= "range start" or
-     *     "menu name ID"  < 256 or
-     *     "menu name ID"  > 32767 or
-     *     menu name ID is not a name ID which is actually in the name table)
-     *     fails test
-     * Else
-     *     passes test.
-     */
-
-    if (!designSize)
-      return_trace (false);
-    else if (subfamilyID == 0 &&
-	     subfamilyNameID == 0 &&
-	     rangeStart == 0 &&
-	     rangeEnd == 0)
-      return_trace (true);
-    else if (designSize < rangeStart ||
-	     designSize > rangeEnd ||
-	     subfamilyNameID < 256 ||
-	     subfamilyNameID > 32767)
-      return_trace (false);
-    else
-      return_trace (true);
-  }
-
-  HBUINT16	designSize;	/* Represents the design size in 720/inch
-				 * units (decipoints).  The design size entry
-				 * must be non-zero.  When there is a design
-				 * size but no recommended size range, the
-				 * rest of the array will consist of zeros. */
-  HBUINT16	subfamilyID;	/* Has no independent meaning, but serves
-				 * as an identifier that associates fonts
-				 * in a subfamily. All fonts which share a
-				 * Preferred or Font Family name and which
-				 * differ only by size range shall have the
-				 * same subfamily value, and no fonts which
-				 * differ in weight or style shall have the
-				 * same subfamily value. If this value is
-				 * zero, the remaining fields in the array
-				 * will be ignored. */
-  HBUINT16	subfamilyNameID;/* If the preceding value is non-zero, this
-				 * value must be set in the range 256 - 32767
-				 * (inclusive). It records the value of a
-				 * field in the name table, which must
-				 * contain English-language strings encoded
-				 * in Windows Unicode and Macintosh Roman,
-				 * and may contain additional strings
-				 * localized to other scripts and languages.
-				 * Each of these strings is the name an
-				 * application should use, in combination
-				 * with the family name, to represent the
-				 * subfamily in a menu.  Applications will
-				 * choose the appropriate version based on
-				 * their selection criteria. */
-  HBUINT16	rangeStart;	/* Large end of the recommended usage range
-				 * (inclusive), stored in 720/inch units
-				 * (decipoints). */
-  HBUINT16	rangeEnd;	/* Small end of the recommended usage range
-				   (exclusive), stored in 720/inch units
-				 * (decipoints). */
-  public:
-  DEFINE_SIZE_STATIC (10);
-};
-
-/* http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx */
-struct FeatureParamsStylisticSet
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    /* Right now minorVersion is at zero.  Which means, any table supports
-     * the uiNameID field. */
-    return_trace (c->check_struct (this));
-  }
-
-  HBUINT16	version;	/* (set to 0): This corresponds to a “minor”
-				 * version number. Additional data may be
-				 * added to the end of this Feature Parameters
-				 * table in the future. */
-
-  HBUINT16	uiNameID;	/* The 'name' table name ID that specifies a
-				 * string (or strings, for multiple languages)
-				 * for a user-interface label for this
-				 * feature.  The values of uiLabelNameId and
-				 * sampleTextNameId are expected to be in the
-				 * font-specific name ID range (256-32767),
-				 * though that is not a requirement in this
-				 * Feature Parameters specification. The
-				 * user-interface label for the feature can
-				 * be provided in multiple languages. An
-				 * English string should be included as a
-				 * fallback. The string should be kept to a
-				 * minimal length to fit comfortably with
-				 * different application interfaces. */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-/* http://www.microsoft.com/typography/otspec/features_ae.htm#cv01-cv99 */
-struct FeatureParamsCharacterVariants
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  characters.sanitize (c));
-  }
-
-  HBUINT16	format;			/* Format number is set to 0. */
-  HBUINT16	featUILableNameID;	/* The ‘name’ table name ID that
-					 * specifies a string (or strings,
-					 * for multiple languages) for a
-					 * user-interface label for this
-					 * feature. (May be nullptr.) */
-  HBUINT16	featUITooltipTextNameID;/* The ‘name’ table name ID that
-					 * specifies a string (or strings,
-					 * for multiple languages) that an
-					 * application can use for tooltip
-					 * text for this feature. (May be
-					 * nullptr.) */
-  HBUINT16	sampleTextNameID;	/* The ‘name’ table name ID that
-					 * specifies sample text that
-					 * illustrates the effect of this
-					 * feature. (May be nullptr.) */
-  HBUINT16	numNamedParameters;	/* Number of named parameters. (May
-					 * be zero.) */
-  HBUINT16	firstParamUILabelNameID;/* The first ‘name’ table name ID
-					 * used to specify strings for
-					 * user-interface labels for the
-					 * feature parameters. (Must be zero
-					 * if numParameters is zero.) */
-  ArrayOf<UINT24>
-		characters;		/* Array of the Unicode Scalar Value
-					 * of the characters for which this
-					 * feature provides glyph variants.
-					 * (May be zero.) */
-  public:
-  DEFINE_SIZE_ARRAY (14, characters);
-};
-
-struct FeatureParams
-{
-  inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
-  {
-    TRACE_SANITIZE (this);
-    if (tag == HB_TAG ('s','i','z','e'))
-      return_trace (u.size.sanitize (c));
-    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
-      return_trace (u.stylisticSet.sanitize (c));
-    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
-      return_trace (u.characterVariants.sanitize (c));
-    return_trace (true);
-  }
-
-  inline const FeatureParamsSize& get_size_params (hb_tag_t tag) const
-  {
-    if (tag == HB_TAG ('s','i','z','e'))
-      return u.size;
-    return Null(FeatureParamsSize);
-  }
-
-  private:
-  union {
-  FeatureParamsSize			size;
-  FeatureParamsStylisticSet		stylisticSet;
-  FeatureParamsCharacterVariants	characterVariants;
-  } u;
-  DEFINE_SIZE_STATIC (17);
-};
-
-struct Feature
-{
-  inline unsigned int get_lookup_count (void) const
-  { return lookupIndex.len; }
-  inline hb_tag_t get_lookup_index (unsigned int i) const
-  { return lookupIndex[i]; }
-  inline unsigned int get_lookup_indexes (unsigned int start_index,
-					  unsigned int *lookup_count /* IN/OUT */,
-					  unsigned int *lookup_tags /* OUT */) const
-  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
-
-  inline const FeatureParams &get_feature_params (void) const
-  { return this+featureParams; }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-			const Record<Feature>::sanitize_closure_t *closure = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
-      return_trace (false);
-
-    /* Some earlier versions of Adobe tools calculated the offset of the
-     * FeatureParams subtable from the beginning of the FeatureList table!
-     *
-     * If sanitizing "failed" for the FeatureParams subtable, try it with the
-     * alternative location.  We would know sanitize "failed" if old value
-     * of the offset was non-zero, but it's zeroed now.
-     *
-     * Only do this for the 'size' feature, since at the time of the faulty
-     * Adobe tools, only the 'size' feature had FeatureParams defined.
-     */
-
-    OffsetTo<FeatureParams> orig_offset = featureParams;
-    if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
-      return_trace (false);
-
-    if (likely (orig_offset.is_null ()))
-      return_trace (true);
-
-    if (featureParams == 0 && closure &&
-	closure->tag == HB_TAG ('s','i','z','e') &&
-	closure->list_base && closure->list_base < this)
-    {
-      unsigned int new_offset_int = (unsigned int) orig_offset -
-				    (((char *) this) - ((char *) closure->list_base));
-
-      OffsetTo<FeatureParams> new_offset;
-      /* Check that it did not overflow. */
-      new_offset.set (new_offset_int);
-      if (new_offset == new_offset_int &&
-	  c->try_set (&featureParams, new_offset) &&
-	  !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
-	return_trace (false);
-
-      if (c->edit_count > 1)
-        c->edit_count--; /* This was a "legitimate" edit; don't contribute to error count. */
-    }
-
-    return_trace (true);
-  }
-
-  OffsetTo<FeatureParams>
-		 featureParams;	/* Offset to Feature Parameters table (if one
-				 * has been defined for the feature), relative
-				 * to the beginning of the Feature Table; = Null
-				 * if not required */
-  IndexArray	 lookupIndex;	/* Array of LookupList indices */
-  public:
-  DEFINE_SIZE_ARRAY (4, lookupIndex);
-};
-
-typedef RecordListOf<Feature> FeatureList;
-
-
-struct LookupFlag : HBUINT16
-{
-  enum Flags {
-    RightToLeft		= 0x0001u,
-    IgnoreBaseGlyphs	= 0x0002u,
-    IgnoreLigatures	= 0x0004u,
-    IgnoreMarks		= 0x0008u,
-    IgnoreFlags		= 0x000Eu,
-    UseMarkFilteringSet	= 0x0010u,
-    Reserved		= 0x00E0u,
-    MarkAttachmentType	= 0xFF00u
-  };
-  public:
-  DEFINE_SIZE_STATIC (2);
-};
-
-} /* namespace OT */
-/* This has to be outside the namespace. */
-HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags);
-namespace OT {
-
-struct Lookup
-{
-  inline unsigned int get_subtable_count (void) const { return subTable.len; }
-
-  template <typename SubTableType>
-  inline const SubTableType& get_subtable (unsigned int i) const
-  { return this+CastR<OffsetArrayOf<SubTableType> > (subTable)[i]; }
-
-  template <typename SubTableType>
-  inline const OffsetArrayOf<SubTableType>& get_subtables (void) const
-  { return CastR<OffsetArrayOf<SubTableType> > (subTable); }
-  template <typename SubTableType>
-  inline OffsetArrayOf<SubTableType>& get_subtables (void)
-  { return CastR<OffsetArrayOf<SubTableType> > (subTable); }
-
-  inline unsigned int get_type (void) const { return lookupType; }
-
-  /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
-   * higher 16-bit is mark-filtering-set if the lookup uses one.
-   * Not to be confused with glyph_props which is very similar. */
-  inline uint32_t get_props (void) const
-  {
-    unsigned int flag = lookupFlag;
-    if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
-    {
-      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-      flag += (markFilteringSet << 16);
-    }
-    return flag;
-  }
-
-  template <typename SubTableType, typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    unsigned int lookup_type = get_type ();
-    TRACE_DISPATCH (this, lookup_type);
-    unsigned int count = get_subtable_count ();
-    for (unsigned int i = 0; i < count; i++) {
-      typename context_t::return_t r = get_subtable<SubTableType> (i).dispatch (c, lookup_type);
-      if (c->stop_sublookup_iteration (r))
-        return_trace (r);
-    }
-    return_trace (c->default_return_value ());
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 unsigned int lookup_type,
-			 uint32_t lookup_props,
-			 unsigned int num_subtables)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    lookupType.set (lookup_type);
-    lookupFlag.set (lookup_props & 0xFFFFu);
-    if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
-    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
-    {
-      HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-      markFilteringSet.set (lookup_props >> 16);
-    }
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    /* Real sanitize of the subtables is done by GSUB/GPOS/... */
-    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
-    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
-    {
-      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-      if (!markFilteringSet.sanitize (c)) return_trace (false);
-    }
-    return_trace (true);
-  }
-
-  private:
-  HBUINT16	lookupType;		/* Different enumerations for GSUB and GPOS */
-  HBUINT16	lookupFlag;		/* Lookup qualifiers */
-  ArrayOf<Offset16>
-		subTable;		/* Array of SubTables */
-  HBUINT16	markFilteringSetX[VAR];	/* Index (base 0) into GDEF mark glyph sets
-					 * structure. This field is only present if bit
-					 * UseMarkFilteringSet of lookup flags is set. */
-  public:
-  DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
-};
-
-typedef OffsetListOf<Lookup> LookupList;
-
-
-/*
- * Coverage Table
- */
-
-struct CoverageFormat1
-{
-  friend struct Coverage;
-
-  private:
-  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
-  {
-    int i = glyphArray.bsearch (glyph_id);
-    static_assert ((((unsigned int) -1) == NOT_COVERED), "");
-    return i;
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &glyphs,
-			 unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    glyphArray.len.set (num_glyphs);
-    if (unlikely (!c->extend (glyphArray))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      glyphArray[i] = glyphs[i];
-    glyphs += num_glyphs;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (glyphArray.sanitize (c));
-  }
-
-  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
-    return glyphs->has (glyphArray[index]);
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    return glyphs->add_sorted_array (glyphArray.array, glyphArray.len);
-  }
-
-  public:
-  /* Older compilers need this to be public. */
-  struct Iter {
-    inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
-    inline bool more (void) { return i < c->glyphArray.len; }
-    inline void next (void) { i++; }
-    inline hb_codepoint_t get_glyph (void) { return c->glyphArray[i]; }
-    inline unsigned int get_coverage (void) { return i; }
-
-    private:
-    const struct CoverageFormat1 *c;
-    unsigned int i;
-  };
-  private:
-
-  protected:
-  HBUINT16	coverageFormat;	/* Format identifier--format = 1 */
-  SortedArrayOf<GlyphID>
-		glyphArray;	/* Array of GlyphIDs--in numerical order */
-  public:
-  DEFINE_SIZE_ARRAY (4, glyphArray);
-};
-
-struct CoverageFormat2
-{
-  friend struct Coverage;
-
-  private:
-  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
-  {
-    int i = rangeRecord.bsearch (glyph_id);
-    if (i != -1) {
-      const RangeRecord &range = rangeRecord[i];
-      return (unsigned int) range.value + (glyph_id - range.start);
-    }
-    return NOT_COVERED;
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &glyphs,
-			 unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-
-    if (unlikely (!num_glyphs))
-    {
-      rangeRecord.len.set (0);
-      return_trace (true);
-    }
-
-    unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < num_glyphs; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i])
-        num_ranges++;
-    rangeRecord.len.set (num_ranges);
-    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
-
-    unsigned int range = 0;
-    rangeRecord[range].start = glyphs[0];
-    rangeRecord[range].value.set (0);
-    for (unsigned int i = 1; i < num_glyphs; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i]) {
-	range++;
-	rangeRecord[range].start = glyphs[i];
-	rangeRecord[range].value.set (i);
-        rangeRecord[range].end = glyphs[i];
-      } else {
-        rangeRecord[range].end = glyphs[i];
-      }
-    glyphs += num_glyphs;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rangeRecord.sanitize (c));
-  }
-
-  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
-    unsigned int i;
-    unsigned int count = rangeRecord.len;
-    for (i = 0; i < count; i++) {
-      const RangeRecord &range = rangeRecord[i];
-      if (range.value <= index &&
-	  index < (unsigned int) range.value + (range.end - range.start) &&
-	  range.intersects (glyphs))
-        return true;
-      else if (index < range.value)
-        return false;
-    }
-    return false;
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
-        return false;
-    return true;
-  }
-
-  public:
-  /* Older compilers need this to be public. */
-  struct Iter
-  {
-    inline void init (const CoverageFormat2 &c_)
-    {
-      c = &c_;
-      coverage = 0;
-      i = 0;
-      j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
-    }
-    inline bool more (void) { return i < c->rangeRecord.len; }
-    inline void next (void)
-    {
-      if (j >= c->rangeRecord[i].end)
-      {
-        i++;
-	if (more ())
-	{
-	  j = c->rangeRecord[i].start;
-	  coverage = c->rangeRecord[i].value;
-	}
-	return;
-      }
-      coverage++;
-      j++;
-    }
-    inline hb_codepoint_t get_glyph (void) { return j; }
-    inline unsigned int get_coverage (void) { return coverage; }
-
-    private:
-    const struct CoverageFormat2 *c;
-    unsigned int i, j, coverage;
-  };
-  private:
-
-  protected:
-  HBUINT16	coverageFormat;	/* Format identifier--format = 2 */
-  SortedArrayOf<RangeRecord>
-		rangeRecord;	/* Array of glyph ranges--ordered by
-				 * Start GlyphID. rangeCount entries
-				 * long */
-  public:
-  DEFINE_SIZE_ARRAY (4, rangeRecord);
-};
-
-struct Coverage
-{
-  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_coverage (glyph_id);
-    case 2: return u.format2.get_coverage (glyph_id);
-    default:return NOT_COVERED;
-    }
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &glyphs,
-			 unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < num_glyphs; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i])
-        num_ranges++;
-    u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2);
-    switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs));
-    case 2: return_trace (u.format2.serialize (c, glyphs, num_glyphs));
-    default:return_trace (false);
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  inline bool intersects (const hb_set_t *glyphs) const {
-    /* TODO speed this up */
-    Coverage::Iter iter;
-    for (iter.init (*this); iter.more (); iter.next ()) {
-      if (glyphs->has (iter.get_glyph ()))
-        return true;
-    }
-    return false;
-  }
-
-  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
-    switch (u.format) {
-    case 1: return u.format1.intersects_coverage (glyphs, index);
-    case 2: return u.format2.intersects_coverage (glyphs, index);
-    default:return false;
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    switch (u.format) {
-    case 1: return u.format1.add_coverage (glyphs);
-    case 2: return u.format2.add_coverage (glyphs);
-    default:return false;
-    }
-  }
-
-  struct Iter {
-    Iter (void) : format (0), u () {};
-    inline void init (const Coverage &c_) {
-      format = c_.u.format;
-      switch (format) {
-      case 1: u.format1.init (c_.u.format1); return;
-      case 2: u.format2.init (c_.u.format2); return;
-      default:                               return;
-      }
-    }
-    inline bool more (void) {
-      switch (format) {
-      case 1: return u.format1.more ();
-      case 2: return u.format2.more ();
-      default:return false;
-      }
-    }
-    inline void next (void) {
-      switch (format) {
-      case 1: u.format1.next (); break;
-      case 2: u.format2.next (); break;
-      default:                   break;
-      }
-    }
-    inline hb_codepoint_t get_glyph (void) {
-      switch (format) {
-      case 1: return u.format1.get_glyph ();
-      case 2: return u.format2.get_glyph ();
-      default:return 0;
-      }
-    }
-    inline unsigned int get_coverage (void) {
-      switch (format) {
-      case 1: return u.format1.get_coverage ();
-      case 2: return u.format2.get_coverage ();
-      default:return -1;
-      }
-    }
-
-    private:
-    unsigned int format;
-    union {
-    CoverageFormat2::Iter	format2; /* Put this one first since it's larger; helps shut up compiler. */
-    CoverageFormat1::Iter	format1;
-    } u;
-  };
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  CoverageFormat1	format1;
-  CoverageFormat2	format2;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-
-/*
- * Class Definition Table
- */
-
-struct ClassDefFormat1
-{
-  friend struct ClassDef;
-
-  private:
-  inline unsigned int get_class (hb_codepoint_t glyph_id) const
-  {
-    unsigned int i = (unsigned int) (glyph_id - startGlyph);
-    if (unlikely (i < classValue.len))
-      return classValue[i];
-    return 0;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && classValue.sanitize (c));
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    unsigned int start = 0;
-    unsigned int count = classValue.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (classValue[i])
-        continue;
-
-      if (start != i)
-	if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + i)))
-	  return false;
-
-      start = i + 1;
-    }
-    if (start != count)
-      if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + count)))
-	return false;
-
-    return true;
-  }
-
-  template <typename set_t>
-  inline bool add_class (set_t *glyphs, unsigned int klass) const {
-    unsigned int count = classValue.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (classValue[i] == klass)
-        glyphs->add (startGlyph + i);
-    }
-    return true;
-  }
-
-  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
-    unsigned int count = classValue.len;
-    if (klass == 0)
-    {
-      /* 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 (g < startGlyph)
-        return true;
-      g = startGlyph + count - 1;
-      if (hb_set_next (glyphs, &g))
-        return true;
-      /* Fall through. */
-    }
-    for (unsigned int i = 0; i < count; i++)
-      if (classValue[i] == klass && glyphs->has (startGlyph + i))
-        return true;
-    return false;
-  }
-
-  protected:
-  HBUINT16	classFormat;		/* Format identifier--format = 1 */
-  GlyphID	startGlyph;		/* First GlyphID of the classValueArray */
-  ArrayOf<HBUINT16>
-		classValue;		/* Array of Class Values--one per GlyphID */
-  public:
-  DEFINE_SIZE_ARRAY (6, classValue);
-};
-
-struct ClassDefFormat2
-{
-  friend struct ClassDef;
-
-  private:
-  inline unsigned int get_class (hb_codepoint_t glyph_id) const
-  {
-    int i = rangeRecord.bsearch (glyph_id);
-    if (unlikely (i != -1))
-      return rangeRecord[i].value;
-    return 0;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rangeRecord.sanitize (c));
-  }
-
-  template <typename set_t>
-  inline bool add_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].add_coverage (glyphs)))
-	  return false;
-    return true;
-  }
-
-  template <typename set_t>
-  inline bool add_class (set_t *glyphs, unsigned int klass) const {
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (rangeRecord[i].value == klass)
-        if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
-	  return false;
-    }
-    return true;
-  }
-
-  inline bool intersects_class (const hb_set_t *glyphs, unsigned int 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++)
-      {
-	if (!hb_set_next (glyphs, &g))
-	  break;
-	if (g < rangeRecord[i].start)
-	  return true;
-	g = rangeRecord[i].end;
-      }
-      if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
-        return true;
-      /* Fall through. */
-    }
-    for (unsigned int i = 0; i < count; i++)
-      if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
-        return true;
-    return false;
-  }
-
-  protected:
-  HBUINT16	classFormat;	/* Format identifier--format = 2 */
-  SortedArrayOf<RangeRecord>
-		rangeRecord;	/* Array of glyph ranges--ordered by
-				 * Start GlyphID */
-  public:
-  DEFINE_SIZE_ARRAY (4, rangeRecord);
-};
-
-struct ClassDef
-{
-  inline unsigned int get_class (hb_codepoint_t glyph_id) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_class (glyph_id);
-    case 2: return u.format2.get_class (glyph_id);
-    default:return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    switch (u.format) {
-    case 1: return u.format1.add_coverage (glyphs);
-    case 2: return u.format2.add_coverage (glyphs);
-    default:return false;
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename set_t>
-  inline bool add_class (set_t *glyphs, unsigned int klass) const {
-    switch (u.format) {
-    case 1: return u.format1.add_class (glyphs, klass);
-    case 2: return u.format2.add_class (glyphs, klass);
-    default:return false;
-    }
-  }
-
-  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
-    switch (u.format) {
-    case 1: return u.format1.intersects_class (glyphs, klass);
-    case 2: return u.format2.intersects_class (glyphs, klass);
-    default:return false;
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  ClassDefFormat1	format1;
-  ClassDefFormat2	format2;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-
-/*
- * Item Variation Store
- */
-
-struct VarRegionAxis
-{
-  inline float evaluate (int coord) const
-  {
-    int start = startCoord, peak = peakCoord, end = endCoord;
-
-    /* TODO Move these to sanitize(). */
-    if (unlikely (start > peak || peak > end))
-      return 1.;
-    if (unlikely (start < 0 && end > 0 && peak != 0))
-      return 1.;
-
-    if (peak == 0 || coord == peak)
-      return 1.;
-
-    if (coord <= start || end <= coord)
-      return 0.;
-
-    /* Interpolate */
-    if (coord < peak)
-      return float (coord - start) / (peak - start);
-    else
-      return float (end - coord) / (end - peak);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-    /* TODO Handle invalid start/peak/end configs, so we don't
-     * have to do that at runtime. */
-  }
-
-  public:
-  F2DOT14	startCoord;
-  F2DOT14	peakCoord;
-  F2DOT14	endCoord;
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct VarRegionList
-{
-  inline float evaluate (unsigned int region_index,
-			 int *coords, unsigned int coord_len) const
-  {
-    if (unlikely (region_index >= regionCount))
-      return 0.;
-
-    const VarRegionAxis *axes = axesZ + (region_index * axisCount);
-
-    float v = 1.;
-    unsigned int count = axisCount;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      int coord = i < coord_len ? coords[i] : 0;
-      float factor = axes[i].evaluate (coord);
-      if (factor == 0.)
-        return 0.;
-      v *= factor;
-    }
-    return v;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  c->check_array (axesZ, axesZ[0].static_size,
-				  (unsigned int) axisCount * (unsigned int) regionCount));
-  }
-
-  protected:
-  HBUINT16	axisCount;
-  HBUINT16	regionCount;
-  VarRegionAxis	axesZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (4, axesZ);
-};
-
-struct VarData
-{
-  inline unsigned int get_row_size (void) const
-  { return shortCount + regionIndices.len; }
-
-  inline unsigned int get_size (void) const
-  { return itemCount * get_row_size (); }
-
-  inline float get_delta (unsigned int inner,
-			  int *coords, unsigned int coord_count,
-			  const VarRegionList &regions) const
-  {
-    if (unlikely (inner >= itemCount))
-      return 0.;
-
-   unsigned int count = regionIndices.len;
-   unsigned int scount = shortCount;
-
-   const HBUINT8 *bytes = &StructAfter<HBUINT8> (regionIndices);
-   const HBUINT8 *row = bytes + inner * (scount + count);
-
-   float delta = 0.;
-   unsigned int i = 0;
-
-   const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row);
-   for (; i < scount; i++)
-   {
-     float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count);
-     delta += scalar * *scursor++;
-   }
-   const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
-   for (; i < count; i++)
-   {
-     float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count);
-     delta += scalar * *bcursor++;
-   }
-
-   return delta;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  regionIndices.sanitize(c) &&
-		  shortCount <= regionIndices.len &&
-		  c->check_array (&StructAfter<HBUINT8> (regionIndices),
-				  get_row_size (), itemCount));
-  }
-
-  protected:
-  HBUINT16		itemCount;
-  HBUINT16		shortCount;
-  ArrayOf<HBUINT16>	regionIndices;
-  HBUINT8			bytesX[VAR];
-  public:
-  DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX);
-};
-
-struct VariationStore
-{
-  inline float get_delta (unsigned int outer, unsigned int inner,
-			  int *coords, unsigned int coord_count) const
-  {
-    if (unlikely (outer >= dataSets.len))
-      return 0.;
-
-    return (this+dataSets[outer]).get_delta (inner,
-					     coords, coord_count,
-					     this+regions);
-  }
-
-  inline float get_delta (unsigned int index,
-			  int *coords, unsigned int coord_count) const
-  {
-    unsigned int outer = index >> 16;
-    unsigned int inner = index & 0xFFFF;
-    return get_delta (outer, inner, coords, coord_count);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  format == 1 &&
-		  regions.sanitize (c, this) &&
-		  dataSets.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16				format;
-  LOffsetTo<VarRegionList>		regions;
-  OffsetArrayOf<VarData, HBUINT32>	dataSets;
-  public:
-  DEFINE_SIZE_ARRAY (8, dataSets);
-};
-
-/*
- * Feature Variations
- */
-
-struct ConditionFormat1
-{
-  friend struct Condition;
-
-  private:
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
-    return filterRangeMinValue <= coord && coord <= filterRangeMaxValue;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16	format;		/* Format identifier--format = 1 */
-  HBUINT16	axisIndex;
-  F2DOT14	filterRangeMinValue;
-  F2DOT14	filterRangeMaxValue;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct Condition
-{
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.evaluate (coords, coord_len);
-    default:return false;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  ConditionFormat1	format1;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-struct ConditionSet
-{
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    unsigned int count = conditions.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!(this+conditions.array[i]).evaluate (coords, coord_len))
-        return false;
-    return true;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (conditions.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<Condition, HBUINT32> conditions;
-  public:
-  DEFINE_SIZE_ARRAY (2, conditions);
-};
-
-struct FeatureTableSubstitutionRecord
-{
-  friend struct FeatureTableSubstitution;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && feature.sanitize (c, base));
-  }
-
-  protected:
-  HBUINT16		featureIndex;
-  LOffsetTo<Feature>	feature;
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct FeatureTableSubstitution
-{
-  inline const Feature *find_substitute (unsigned int feature_index) const
-  {
-    unsigned int count = substitutions.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      const FeatureTableSubstitutionRecord &record = substitutions.array[i];
-      if (record.featureIndex == feature_index)
-	return &(this+record.feature);
-    }
-    return nullptr;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  substitutions.sanitize (c, this));
-  }
-
-  protected:
-  FixedVersion<>	version;	/* Version--0x00010000u */
-  ArrayOf<FeatureTableSubstitutionRecord>
-			substitutions;
-  public:
-  DEFINE_SIZE_ARRAY (6, substitutions);
-};
-
-struct FeatureVariationRecord
-{
-  friend struct FeatureVariations;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (conditions.sanitize (c, base) &&
-		  substitutions.sanitize (c, base));
-  }
-
-  protected:
-  LOffsetTo<ConditionSet>
-			conditions;
-  LOffsetTo<FeatureTableSubstitution>
-			substitutions;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct FeatureVariations
-{
-  static const unsigned int NOT_FOUND_INDEX = 0xFFFFFFFFu;
-
-  inline bool find_index (const int *coords, unsigned int coord_len,
-			  unsigned int *index) const
-  {
-    unsigned int count = varRecords.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      const FeatureVariationRecord &record = varRecords.array[i];
-      if ((this+record.conditions).evaluate (coords, coord_len))
-      {
-	*index = i;
-	return true;
-      }
-    }
-    *index = NOT_FOUND_INDEX;
-    return false;
-  }
-
-  inline const Feature *find_substitute (unsigned int variations_index,
-					 unsigned int feature_index) const
-  {
-    const FeatureVariationRecord &record = varRecords[variations_index];
-    return (this+record.substitutions).find_substitute (feature_index);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  varRecords.sanitize (c, this));
-  }
-
-  protected:
-  FixedVersion<>	version;	/* Version--0x00010000u */
-  LArrayOf<FeatureVariationRecord>
-			varRecords;
-  public:
-  DEFINE_SIZE_ARRAY (8, varRecords);
-};
-
-
-/*
- * Device Tables
- */
-
-struct HintingDevice
-{
-  friend struct Device;
-
-  private:
-
-  inline hb_position_t get_x_delta (hb_font_t *font) const
-  { return get_delta (font->x_ppem, font->x_scale); }
-
-  inline hb_position_t get_y_delta (hb_font_t *font) const
-  { return get_delta (font->y_ppem, font->y_scale); }
-
-  inline unsigned int get_size (void) const
-  {
-    unsigned int f = deltaFormat;
-    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * HBUINT16::static_size;
-    return HBUINT16::static_size * (4 + ((endSize - startSize) >> (4 - f)));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
-  }
-
-  private:
-
-  inline int get_delta (unsigned int ppem, int scale) const
-  {
-    if (!ppem) return 0;
-
-    int pixels = get_delta_pixels (ppem);
-
-    if (!pixels) return 0;
-
-    return (int) (pixels * (int64_t) scale / ppem);
-  }
-  inline int get_delta_pixels (unsigned int ppem_size) const
-  {
-    unsigned int f = deltaFormat;
-    if (unlikely (f < 1 || f > 3))
-      return 0;
-
-    if (ppem_size < startSize || ppem_size > endSize)
-      return 0;
-
-    unsigned int s = ppem_size - startSize;
-
-    unsigned int byte = deltaValue[s >> (4 - f)];
-    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
-    unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
-
-    int delta = bits & mask;
-
-    if ((unsigned int) delta >= ((mask + 1) >> 1))
-      delta -= mask + 1;
-
-    return delta;
-  }
-
-  protected:
-  HBUINT16	startSize;		/* Smallest size to correct--in ppem */
-  HBUINT16	endSize;		/* Largest size to correct--in ppem */
-  HBUINT16	deltaFormat;		/* Format of DeltaValue array data: 1, 2, or 3
-					 * 1	Signed 2-bit value, 8 values per uint16
-					 * 2	Signed 4-bit value, 4 values per uint16
-					 * 3	Signed 8-bit value, 2 values per uint16
-					 */
-  HBUINT16	deltaValue[VAR];	/* Array of compressed data */
-  public:
-  DEFINE_SIZE_ARRAY (6, deltaValue);
-};
-
-struct VariationDevice
-{
-  friend struct Device;
-
-  private:
-
-  inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
-  { return font->em_scalef_x (get_delta (font, store)); }
-
-  inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
-  { return font->em_scalef_y (get_delta (font, store)); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  private:
-
-  inline float get_delta (hb_font_t *font, const VariationStore &store) const
-  {
-    return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords);
-  }
-
-  protected:
-  HBUINT16	outerIndex;
-  HBUINT16	innerIndex;
-  HBUINT16	deltaFormat;	/* Format identifier for this table: 0x0x8000 */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct DeviceHeader
-{
-  protected:
-  HBUINT16		reserved1;
-  HBUINT16		reserved2;
-  public:
-  HBUINT16		format;		/* Format identifier */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct Device
-{
-  inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const
-  {
-    switch (u.b.format)
-    {
-    case 1: case 2: case 3:
-      return u.hinting.get_x_delta (font);
-    case 0x8000:
-      return u.variation.get_x_delta (font, store);
-    default:
-      return 0;
-    }
-  }
-  inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const
-  {
-    switch (u.b.format)
-    {
-    case 1: case 2: case 3:
-      return u.hinting.get_y_delta (font);
-    case 0x8000:
-      return u.variation.get_y_delta (font, store);
-    default:
-      return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.b.format.sanitize (c)) return_trace (false);
-    switch (u.b.format) {
-    case 1: case 2: case 3:
-      return_trace (u.hinting.sanitize (c));
-    case 0x8000:
-      return_trace (u.variation.sanitize (c));
-    default:
-      return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  DeviceHeader		b;
-  HintingDevice		hinting;
-  VariationDevice	variation;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (6, b);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
deleted file mode 100644
index 2d6c66e..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2010,2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_LAYOUT_GDEF_TABLE_HH
-#define HB_OT_LAYOUT_GDEF_TABLE_HH
-
-#include "hb-ot-layout-common-private.hh"
-
-#include "hb-font-private.hh"
-
-
-namespace OT {
-
-
-/*
- * Attachment List Table
- */
-
-typedef ArrayOf<HBUINT16> AttachPoint;	/* Array of contour point indices--in
-					 * increasing numerical order */
-
-struct AttachList
-{
-  inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
-					 unsigned int start_offset,
-					 unsigned int *point_count /* IN/OUT */,
-					 unsigned int *point_array /* OUT */) const
-  {
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
-    if (index == NOT_COVERED)
-    {
-      if (point_count)
-	*point_count = 0;
-      return 0;
-    }
-
-    const AttachPoint &points = this+attachPoint[index];
-
-    if (point_count) {
-      const HBUINT16 *array = points.sub_array (start_offset, point_count);
-      unsigned int count = *point_count;
-      for (unsigned int i = 0; i < count; i++)
-	point_array[i] = array[i];
-    }
-
-    return points.len;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this));
-  }
-
-  protected:
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table -- from
-					 * beginning of AttachList table */
-  OffsetArrayOf<AttachPoint>
-		attachPoint;		/* Array of AttachPoint tables
-					 * in Coverage Index order */
-  public:
-  DEFINE_SIZE_ARRAY (4, attachPoint);
-};
-
-/*
- * Ligature Caret Table
- */
-
-struct CaretValueFormat1
-{
-  friend struct CaretValue;
-
-  private:
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
-  {
-    return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16	caretValueFormat;	/* Format identifier--format = 1 */
-  FWORD		coordinate;		/* X or Y value, in design units */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-struct CaretValueFormat2
-{
-  friend struct CaretValue;
-
-  private:
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
-  {
-    hb_position_t x, y;
-    if (font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y))
-      return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
-    else
-      return 0;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16	caretValueFormat;	/* Format identifier--format = 2 */
-  HBUINT16	caretValuePoint;	/* Contour point index on glyph */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-struct CaretValueFormat3
-{
-  friend struct CaretValue;
-
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, const VariationStore &var_store) const
-  {
-    return HB_DIRECTION_IS_HORIZONTAL (direction) ?
-           font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) :
-           font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16	caretValueFormat;	/* Format identifier--format = 3 */
-  FWORD		coordinate;		/* X or Y value, in design units */
-  OffsetTo<Device>
-		deviceTable;		/* Offset to Device table for X or Y
-					 * value--from beginning of CaretValue
-					 * table */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct CaretValue
-{
-  inline hb_position_t get_caret_value (hb_font_t *font,
-					hb_direction_t direction,
-					hb_codepoint_t glyph_id,
-					const VariationStore &var_store) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_caret_value (font, direction);
-    case 2: return u.format2.get_caret_value (font, direction, glyph_id);
-    case 3: return u.format3.get_caret_value (font, direction, var_store);
-    default:return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    case 3: return_trace (u.format3.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  CaretValueFormat1	format1;
-  CaretValueFormat2	format2;
-  CaretValueFormat3	format3;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-struct LigGlyph
-{
-  inline unsigned int get_lig_carets (hb_font_t *font,
-				      hb_direction_t direction,
-				      hb_codepoint_t glyph_id,
-				      const VariationStore &var_store,
-				      unsigned int start_offset,
-				      unsigned int *caret_count /* IN/OUT */,
-				      hb_position_t *caret_array /* OUT */) const
-  {
-    if (caret_count) {
-      const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_count);
-      unsigned int count = *caret_count;
-      for (unsigned int i = 0; i < count; i++)
-	caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store);
-    }
-
-    return carets.len;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (carets.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<CaretValue>
-		carets;			/* Offset array of CaretValue tables
-					 * --from beginning of LigGlyph table
-					 * --in increasing coordinate order */
-  public:
-  DEFINE_SIZE_ARRAY (2, carets);
-};
-
-struct LigCaretList
-{
-  inline unsigned int get_lig_carets (hb_font_t *font,
-				      hb_direction_t direction,
-				      hb_codepoint_t glyph_id,
-				      const VariationStore &var_store,
-				      unsigned int start_offset,
-				      unsigned int *caret_count /* IN/OUT */,
-				      hb_position_t *caret_array /* OUT */) const
-  {
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
-    if (index == NOT_COVERED)
-    {
-      if (caret_count)
-	*caret_count = 0;
-      return 0;
-    }
-    const LigGlyph &lig_glyph = this+ligGlyph[index];
-    return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
-  }
-
-  protected:
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of LigCaretList table */
-  OffsetArrayOf<LigGlyph>
-		ligGlyph;		/* Array of LigGlyph tables
-					 * in Coverage Index order */
-  public:
-  DEFINE_SIZE_ARRAY (4, ligGlyph);
-};
-
-
-struct MarkGlyphSetsFormat1
-{
-  inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
-  { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  ArrayOf<LOffsetTo<Coverage> >
-		coverage;		/* Array of long offsets to mark set
-					 * coverage tables */
-  public:
-  DEFINE_SIZE_ARRAY (4, coverage);
-};
-
-struct MarkGlyphSets
-{
-  inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.covers (set_index, glyph_id);
-    default:return false;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  MarkGlyphSetsFormat1	format1;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-
-/*
- * GDEF -- The Glyph Definition Table
- */
-
-struct GDEF
-{
-  static const hb_tag_t tableTag	= HB_OT_TAG_GDEF;
-
-  enum GlyphClasses {
-    UnclassifiedGlyph	= 0,
-    BaseGlyph		= 1,
-    LigatureGlyph	= 2,
-    MarkGlyph		= 3,
-    ComponentGlyph	= 4
-  };
-
-  inline bool has_glyph_classes (void) const { return glyphClassDef != 0; }
-  inline unsigned int get_glyph_class (hb_codepoint_t glyph) const
-  { return (this+glyphClassDef).get_class (glyph); }
-  inline void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
-  { (this+glyphClassDef).add_class (glyphs, klass); }
-
-  inline bool has_mark_attachment_types (void) const { return markAttachClassDef != 0; }
-  inline unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
-  { return (this+markAttachClassDef).get_class (glyph); }
-
-  inline bool has_attach_points (void) const { return attachList != 0; }
-  inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
-					 unsigned int start_offset,
-					 unsigned int *point_count /* IN/OUT */,
-					 unsigned int *point_array /* OUT */) const
-  { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); }
-
-  inline bool has_lig_carets (void) const { return ligCaretList != 0; }
-  inline unsigned int get_lig_carets (hb_font_t *font,
-				      hb_direction_t direction,
-				      hb_codepoint_t glyph_id,
-				      unsigned int start_offset,
-				      unsigned int *caret_count /* IN/OUT */,
-				      hb_position_t *caret_array /* OUT */) const
-  { return (this+ligCaretList).get_lig_carets (font,
-					       direction, glyph_id, get_var_store(),
-					       start_offset, caret_count, caret_array); }
-
-  inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; }
-  inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
-  { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); }
-
-  inline bool has_var_store (void) const { return version.to_int () >= 0x00010003u && varStore != 0; }
-  inline const VariationStore &get_var_store (void) const
-  { return version.to_int () >= 0x00010003u ? this+varStore : Null(VariationStore); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  glyphClassDef.sanitize (c, this) &&
-		  attachList.sanitize (c, this) &&
-		  ligCaretList.sanitize (c, this) &&
-		  markAttachClassDef.sanitize (c, this) &&
-		  (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
-		  (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
-  }
-
-  /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
-   * glyph class and other bits, and high 8-bit gthe mark attachment type (if any).
-   * Not to be confused with lookup_props which is very similar. */
-  inline unsigned int get_glyph_props (hb_codepoint_t glyph) const
-  {
-    unsigned int klass = get_glyph_class (glyph);
-
-    static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs), "");
-    static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures), "");
-    static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), "");
-
-    switch (klass) {
-    default:			return 0;
-    case BaseGlyph:		return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH;
-    case LigatureGlyph:		return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
-    case MarkGlyph:
-	  klass = get_mark_attachment_type (glyph);
-	  return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8);
-    }
-  }
-
-
-  protected:
-  FixedVersion<>version;		/* Version of the GDEF table--currently
-					 * 0x00010003u */
-  OffsetTo<ClassDef>
-		glyphClassDef;		/* Offset to class definition table
-					 * for glyph type--from beginning of
-					 * GDEF header (may be Null) */
-  OffsetTo<AttachList>
-		attachList;		/* Offset to list of glyphs with
-					 * attachment points--from beginning
-					 * of GDEF header (may be Null) */
-  OffsetTo<LigCaretList>
-		ligCaretList;		/* Offset to list of positioning points
-					 * for ligature carets--from beginning
-					 * of GDEF header (may be Null) */
-  OffsetTo<ClassDef>
-		markAttachClassDef;	/* Offset to class definition table for
-					 * mark attachment type--from beginning
-					 * of GDEF header (may be Null) */
-  OffsetTo<MarkGlyphSets>
-		markGlyphSetsDef;	/* Offset to the table of mark set
-					 * definitions--from beginning of GDEF
-					 * header (may be NULL).  Introduced
-					 * in version 0x00010002. */
-  LOffsetTo<VariationStore>
-		varStore;		/* Offset to the table of Item Variation
-					 * Store--from beginning of GDEF
-					 * header (may be NULL).  Introduced
-					 * in version 0x00010003. */
-  public:
-  DEFINE_SIZE_MIN (12);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_LAYOUT_GDEF_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
deleted file mode 100644
index 46ffcc6..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
+++ /dev/null
@@ -1,1654 +0,0 @@
-/*
- * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 2010,2012,2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_LAYOUT_GPOS_TABLE_HH
-#define HB_OT_LAYOUT_GPOS_TABLE_HH
-
-#include "hb-ot-layout-gsubgpos-private.hh"
-
-
-namespace OT {
-
-
-/* buffer **position** var allocations */
-#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
-#define attach_type() var.u8[2] /* attachment type */
-/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
-
-enum attach_type_t {
-  ATTACH_TYPE_NONE	= 0X00,
-
-  /* Each attachment should be either a mark or a cursive; can't be both. */
-  ATTACH_TYPE_MARK	= 0X01,
-  ATTACH_TYPE_CURSIVE	= 0X02,
-};
-
-
-/* Shared Tables: ValueRecord, Anchor Table, and MarkArray */
-
-typedef HBUINT16 Value;
-
-typedef Value ValueRecord[VAR];
-
-struct ValueFormat : HBUINT16
-{
-  enum Flags {
-    xPlacement	= 0x0001u,	/* Includes horizontal adjustment for placement */
-    yPlacement	= 0x0002u,	/* Includes vertical adjustment for placement */
-    xAdvance	= 0x0004u,	/* Includes horizontal adjustment for advance */
-    yAdvance	= 0x0008u,	/* Includes vertical adjustment for advance */
-    xPlaDevice	= 0x0010u,	/* Includes horizontal Device table for placement */
-    yPlaDevice	= 0x0020u,	/* Includes vertical Device table for placement */
-    xAdvDevice	= 0x0040u,	/* Includes horizontal Device table for advance */
-    yAdvDevice	= 0x0080u,	/* Includes vertical Device table for advance */
-    ignored	= 0x0F00u,	/* Was used in TrueType Open for MM fonts */
-    reserved	= 0xF000u,	/* For future use */
-
-    devices	= 0x00F0u	/* Mask for having any Device table */
-  };
-
-/* All fields are options.  Only those available advance the value pointer. */
-#if 0
-  HBINT16		xPlacement;		/* Horizontal adjustment for
-					 * placement--in design units */
-  HBINT16		yPlacement;		/* Vertical adjustment for
-					 * placement--in design units */
-  HBINT16		xAdvance;		/* Horizontal adjustment for
-					 * advance--in design units (only used
-					 * for horizontal writing) */
-  HBINT16		yAdvance;		/* Vertical adjustment for advance--in
-					 * design units (only used for vertical
-					 * writing) */
-  Offset	xPlaDevice;		/* Offset to Device table for
-					 * horizontal placement--measured from
-					 * beginning of PosTable (may be NULL) */
-  Offset	yPlaDevice;		/* Offset to Device table for vertical
-					 * placement--measured from beginning
-					 * of PosTable (may be NULL) */
-  Offset	xAdvDevice;		/* Offset to Device table for
-					 * horizontal advance--measured from
-					 * beginning of PosTable (may be NULL) */
-  Offset	yAdvDevice;		/* Offset to Device table for vertical
-					 * advance--measured from beginning of
-					 * PosTable (may be NULL) */
-#endif
-
-  inline unsigned int get_len (void) const
-  { return _hb_popcount ((unsigned int) *this); }
-  inline unsigned int get_size (void) const
-  { return get_len () * Value::static_size; }
-
-  void apply_value (hb_ot_apply_context_t   *c,
-		    const void           *base,
-		    const Value          *values,
-		    hb_glyph_position_t  &glyph_pos) const
-  {
-    unsigned int format = *this;
-    if (!format) return;
-
-    hb_font_t *font = c->font;
-    hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
-
-    if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short (values++));
-    if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short (values++));
-    if (format & xAdvance) {
-      if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values));
-      values++;
-    }
-    /* y_advance values grow downward but font-space grows upward, hence negation */
-    if (format & yAdvance) {
-      if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values));
-      values++;
-    }
-
-    if (!has_device ()) return;
-
-    bool use_x_device = font->x_ppem || font->num_coords;
-    bool use_y_device = font->y_ppem || font->num_coords;
-
-    if (!use_x_device && !use_y_device) return;
-
-    const VariationStore &store = c->var_store;
-
-    /* pixel -> fractional pixel */
-    if (format & xPlaDevice) {
-      if (use_x_device) glyph_pos.x_offset  += (base + get_device (values)).get_x_delta (font, store);
-      values++;
-    }
-    if (format & yPlaDevice) {
-      if (use_y_device) glyph_pos.y_offset  += (base + get_device (values)).get_y_delta (font, store);
-      values++;
-    }
-    if (format & xAdvDevice) {
-      if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font, store);
-      values++;
-    }
-    if (format & yAdvDevice) {
-      /* y_advance values grow downward but font-space grows upward, hence negation */
-      if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font, store);
-      values++;
-    }
-  }
-
-  private:
-  inline bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
-  {
-    unsigned int format = *this;
-
-    if (format & xPlacement) values++;
-    if (format & yPlacement) values++;
-    if (format & xAdvance)   values++;
-    if (format & yAdvance)   values++;
-
-    if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
-    if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
-    if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
-    if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
-
-    return true;
-  }
-
-  static inline OffsetTo<Device>& get_device (Value* value)
-  { return *CastP<OffsetTo<Device> > (value); }
-  static inline const OffsetTo<Device>& get_device (const Value* value)
-  { return *CastP<OffsetTo<Device> > (value); }
-
-  static inline const HBINT16& get_short (const Value* value)
-  { return *CastP<HBINT16> (value); }
-
-  public:
-
-  inline bool has_device (void) const {
-    unsigned int format = *this;
-    return (format & devices) != 0;
-  }
-
-  inline bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
-  }
-
-  inline bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    unsigned int len = get_len ();
-
-    if (!c->check_array (values, get_size (), count)) return_trace (false);
-
-    if (!has_device ()) return_trace (true);
-
-    for (unsigned int i = 0; i < count; i++) {
-      if (!sanitize_value_devices (c, base, values))
-        return_trace (false);
-      values += len;
-    }
-
-    return_trace (true);
-  }
-
-  /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */
-  inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
-  {
-    TRACE_SANITIZE (this);
-
-    if (!has_device ()) return_trace (true);
-
-    for (unsigned int i = 0; i < count; i++) {
-      if (!sanitize_value_devices (c, base, values))
-        return_trace (false);
-      values += stride;
-    }
-
-    return_trace (true);
-  }
-};
-
-
-struct AnchorFormat1
-{
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
-			  float *x, float *y) const
-  {
-    hb_font_t *font = c->font;
-    *x = font->em_fscale_x (xCoordinate);
-    *y = font->em_fscale_y (yCoordinate);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  FWORD		xCoordinate;		/* Horizontal value--in design units */
-  FWORD		yCoordinate;		/* Vertical value--in design units */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct AnchorFormat2
-{
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
-			  float *x, float *y) const
-  {
-    hb_font_t *font = c->font;
-    unsigned int x_ppem = font->x_ppem;
-    unsigned int y_ppem = font->y_ppem;
-    hb_position_t cx, cy;
-    hb_bool_t ret;
-
-    ret = (x_ppem || y_ppem) &&
-	   font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
-    *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
-    *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 2 */
-  FWORD		xCoordinate;		/* Horizontal value--in design units */
-  FWORD		yCoordinate;		/* Vertical value--in design units */
-  HBUINT16	anchorPoint;		/* Index to glyph contour point */
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct AnchorFormat3
-{
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
-			  float *x, float *y) const
-  {
-    hb_font_t *font = c->font;
-    *x = font->em_fscale_x (xCoordinate);
-    *y = font->em_fscale_y (yCoordinate);
-
-    if (font->x_ppem || font->num_coords)
-      *x += (this+xDeviceTable).get_x_delta (font, c->var_store);
-    if (font->y_ppem || font->num_coords)
-      *y += (this+yDeviceTable).get_y_delta (font, c->var_store);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 3 */
-  FWORD		xCoordinate;		/* Horizontal value--in design units */
-  FWORD		yCoordinate;		/* Vertical value--in design units */
-  OffsetTo<Device>
-		xDeviceTable;		/* Offset to Device table for X
-					 * coordinate-- from beginning of
-					 * Anchor table (may be NULL) */
-  OffsetTo<Device>
-		yDeviceTable;		/* Offset to Device table for Y
-					 * coordinate-- from beginning of
-					 * Anchor table (may be NULL) */
-  public:
-  DEFINE_SIZE_STATIC (10);
-};
-
-struct Anchor
-{
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
-			  float *x, float *y) const
-  {
-    *x = *y = 0;
-    switch (u.format) {
-    case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
-    case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
-    case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
-    default:					      return;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    case 3: return_trace (u.format3.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  AnchorFormat1		format1;
-  AnchorFormat2		format2;
-  AnchorFormat3		format3;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-
-struct AnchorMatrix
-{
-  inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const {
-    *found = false;
-    if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
-    *found = !matrixZ[row * cols + col].is_null ();
-    return this+matrixZ[row * cols + col];
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
-  {
-    TRACE_SANITIZE (this);
-    if (!c->check_struct (this)) return_trace (false);
-    if (unlikely (_hb_unsigned_int_mul_overflows (rows, cols))) return_trace (false);
-    unsigned int count = rows * cols;
-    if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (!matrixZ[i].sanitize (c, this)) return_trace (false);
-    return_trace (true);
-  }
-
-  HBUINT16	rows;			/* Number of rows */
-  protected:
-  OffsetTo<Anchor>
-		matrixZ[VAR];		/* Matrix of offsets to Anchor tables--
-					 * from beginning of AnchorMatrix table */
-  public:
-  DEFINE_SIZE_ARRAY (2, matrixZ);
-};
-
-
-struct MarkRecord
-{
-  friend struct MarkArray;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
-  }
-
-  protected:
-  HBUINT16	klass;			/* Class defined for this mark */
-  OffsetTo<Anchor>
-		markAnchor;		/* Offset to Anchor table--from
-					 * beginning of MarkArray table */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-struct MarkArray : ArrayOf<MarkRecord>	/* Array of MarkRecords--in Coverage order */
-{
-  inline bool apply (hb_ot_apply_context_t *c,
-		     unsigned int mark_index, unsigned int glyph_index,
-		     const AnchorMatrix &anchors, unsigned int class_count,
-		     unsigned int glyph_pos) const
-  {
-    TRACE_APPLY (this);
-    hb_buffer_t *buffer = c->buffer;
-    const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index);
-    unsigned int mark_class = record.klass;
-
-    const Anchor& mark_anchor = this + record.markAnchor;
-    bool found;
-    const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
-    /* If this subtable doesn't have an anchor for this base and this class,
-     * return false such that the subsequent subtables have a chance at it. */
-    if (unlikely (!found)) return_trace (false);
-
-    float mark_x, mark_y, base_x, base_y;
-
-    buffer->unsafe_to_break (glyph_pos, buffer->idx);
-    mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
-    glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
-
-    hb_glyph_position_t &o = buffer->cur_pos();
-    o.x_offset = round (base_x - mark_x);
-    o.y_offset = round (base_y - mark_y);
-    o.attach_type() = ATTACH_TYPE_MARK;
-    o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
-    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
-
-    buffer->idx++;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (ArrayOf<MarkRecord>::sanitize (c, this));
-  }
-};
-
-
-/* Lookups */
-
-struct SinglePosFormat1
-{
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    hb_buffer_t *buffer = c->buffer;
-    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    valueFormat.apply_value (c, this, values, buffer->cur_pos());
-
-    buffer->idx++;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  coverage.sanitize (c, this) &&
-		  valueFormat.sanitize_value (c, this, values));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of subtable */
-  ValueFormat	valueFormat;		/* Defines the types of data in the
-					 * ValueRecord */
-  ValueRecord	values;			/* Defines positioning
-					 * value(s)--applied to all glyphs in
-					 * the Coverage table */
-  public:
-  DEFINE_SIZE_ARRAY (6, values);
-};
-
-struct SinglePosFormat2
-{
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    hb_buffer_t *buffer = c->buffer;
-    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    if (likely (index >= valueCount)) return_trace (false);
-
-    valueFormat.apply_value (c, this,
-			     &values[index * valueFormat.get_len ()],
-			     buffer->cur_pos());
-
-    buffer->idx++;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  coverage.sanitize (c, this) &&
-		  valueFormat.sanitize_values (c, this, values, valueCount));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 2 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of subtable */
-  ValueFormat	valueFormat;		/* Defines the types of data in the
-					 * ValueRecord */
-  HBUINT16	valueCount;		/* Number of ValueRecords */
-  ValueRecord	values;			/* Array of ValueRecords--positioning
-					 * values applied to glyphs */
-  public:
-  DEFINE_SIZE_ARRAY (8, values);
-};
-
-struct SinglePos
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    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));
-    case 2: return_trace (c->dispatch (u.format2));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  SinglePosFormat1	format1;
-  SinglePosFormat2	format2;
-  } u;
-};
-
-
-struct PairValueRecord
-{
-  friend struct PairSet;
-
-  protected:
-  GlyphID	secondGlyph;		/* GlyphID of second glyph in the
-					 * pair--first glyph is listed in the
-					 * Coverage table */
-  ValueRecord	values;			/* Positioning data for the first glyph
-					 * followed by for second glyph */
-  public:
-  DEFINE_SIZE_ARRAY (2, values);
-};
-
-struct PairSet
-{
-  friend struct PairPosFormat1;
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c,
-			      const ValueFormat *valueFormats) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    unsigned int len1 = valueFormats[0].get_len ();
-    unsigned int len2 = valueFormats[1].get_len ();
-    unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
-
-    const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
-    c->input->add_array (&record->secondGlyph, len, record_size);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c,
-		     const ValueFormat *valueFormats,
-		     unsigned int pos) const
-  {
-    TRACE_APPLY (this);
-    hb_buffer_t *buffer = c->buffer;
-    unsigned int len1 = valueFormats[0].get_len ();
-    unsigned int len2 = valueFormats[1].get_len ();
-    unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
-
-    const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
-    unsigned int count = len;
-
-    /* Hand-coded bsearch. */
-    if (unlikely (!count))
-      return_trace (false);
-    hb_codepoint_t x = buffer->info[pos].codepoint;
-    int min = 0, max = (int) count - 1;
-    while (min <= max)
-    {
-      int mid = (min + max) / 2;
-      const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid);
-      hb_codepoint_t mid_x = record->secondGlyph;
-      if (x < mid_x)
-        max = mid - 1;
-      else if (x > mid_x)
-        min = mid + 1;
-      else
-      {
-        buffer->unsafe_to_break (buffer->idx, pos + 1);
-	valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
-	valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
-	if (len2)
-	  pos++;
-	buffer->idx = pos;
-	return_trace (true);
-      }
-    }
-
-    return_trace (false);
-  }
-
-  struct sanitize_closure_t {
-    const void *base;
-    const ValueFormat *valueFormats;
-    unsigned int len1; /* valueFormats[0].get_len() */
-    unsigned int stride; /* 1 + len1 + len2 */
-  };
-
-  inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
-  {
-    TRACE_SANITIZE (this);
-    if (!(c->check_struct (this)
-       && c->check_array (arrayZ, HBUINT16::static_size * closure->stride, len))) return_trace (false);
-
-    unsigned int count = len;
-    const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
-    return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) &&
-		  closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
-  }
-
-  protected:
-  HBUINT16	len;			/* Number of PairValueRecords */
-  HBUINT16	arrayZ[VAR];		/* Array of PairValueRecords--ordered
-					 * by GlyphID of the second glyph */
-  public:
-  DEFINE_SIZE_ARRAY (2, arrayZ);
-};
-
-struct PairPosFormat1
-{
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    unsigned int count = pairSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+pairSet[i]).collect_glyphs (c, valueFormat);
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    hb_buffer_t *buffer = c->buffer;
-    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
-    skippy_iter.reset (buffer->idx, 1);
-    if (!skippy_iter.next ()) return_trace (false);
-
-    return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-
-    if (!c->check_struct (this)) return_trace (false);
-
-    unsigned int len1 = valueFormat[0].get_len ();
-    unsigned int len2 = valueFormat[1].get_len ();
-    PairSet::sanitize_closure_t closure = {
-      this,
-      valueFormat,
-      len1,
-      1 + len1 + len2
-    };
-
-    return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of subtable */
-  ValueFormat	valueFormat[2];		/* [0] Defines the types of data in
-					 * ValueRecord1--for the first glyph
-					 * in the pair--may be zero (0) */
-					/* [1] Defines the types of data in
-					 * ValueRecord2--for the second glyph
-					 * in the pair--may be zero (0) */
-  OffsetArrayOf<PairSet>
-		pairSet;		/* Array of PairSet tables
-					 * ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_ARRAY (10, pairSet);
-};
-
-struct PairPosFormat2
-{
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    if (unlikely (!(this+classDef2).add_coverage (c->input))) return;
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    hb_buffer_t *buffer = c->buffer;
-    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
-    skippy_iter.reset (buffer->idx, 1);
-    if (!skippy_iter.next ()) return_trace (false);
-
-    unsigned int len1 = valueFormat1.get_len ();
-    unsigned int len2 = valueFormat2.get_len ();
-    unsigned int record_len = len1 + len2;
-
-    unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
-    unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
-    if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
-
-    buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
-    const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
-    valueFormat1.apply_value (c, this, v, buffer->cur_pos());
-    valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
-
-    buffer->idx = skippy_iter.idx;
-    if (len2)
-      buffer->idx++;
-
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!(c->check_struct (this)
-       && coverage.sanitize (c, this)
-       && classDef1.sanitize (c, this)
-       && classDef2.sanitize (c, this))) return_trace (false);
-
-    unsigned int len1 = valueFormat1.get_len ();
-    unsigned int len2 = valueFormat2.get_len ();
-    unsigned int stride = len1 + len2;
-    unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
-    unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
-    return_trace (c->check_array (values, record_size, count) &&
-		  valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
-		  valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 2 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of subtable */
-  ValueFormat	valueFormat1;		/* ValueRecord definition--for the
-					 * first glyph of the pair--may be zero
-					 * (0) */
-  ValueFormat	valueFormat2;		/* ValueRecord definition--for the
-					 * second glyph of the pair--may be
-					 * zero (0) */
-  OffsetTo<ClassDef>
-		classDef1;		/* Offset to ClassDef table--from
-					 * beginning of PairPos subtable--for
-					 * the first glyph of the pair */
-  OffsetTo<ClassDef>
-		classDef2;		/* Offset to ClassDef table--from
-					 * beginning of PairPos subtable--for
-					 * the second glyph of the pair */
-  HBUINT16	class1Count;		/* Number of classes in ClassDef1
-					 * table--includes Class0 */
-  HBUINT16	class2Count;		/* Number of classes in ClassDef2
-					 * table--includes Class0 */
-  ValueRecord	values;			/* Matrix of value pairs:
-					 * class1-major, class2-minor,
-					 * Each entry has value1 and value2 */
-  public:
-  DEFINE_SIZE_ARRAY (16, values);
-};
-
-struct PairPos
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    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));
-    case 2: return_trace (c->dispatch (u.format2));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  PairPosFormat1	format1;
-  PairPosFormat2	format2;
-  } u;
-};
-
-
-struct EntryExitRecord
-{
-  friend struct CursivePosFormat1;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
-  }
-
-  protected:
-  OffsetTo<Anchor>
-		entryAnchor;		/* Offset to EntryAnchor table--from
-					 * beginning of CursivePos
-					 * subtable--may be NULL */
-  OffsetTo<Anchor>
-		exitAnchor;		/* Offset to ExitAnchor table--from
-					 * beginning of CursivePos
-					 * subtable--may be NULL */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-static void
-reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent);
-
-struct CursivePosFormat1
-{
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    hb_buffer_t *buffer = c->buffer;
-
-    const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
-    if (!this_record.exitAnchor) return_trace (false);
-
-    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
-    skippy_iter.reset (buffer->idx, 1);
-    if (!skippy_iter.next ()) return_trace (false);
-
-    const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint)];
-    if (!next_record.entryAnchor) return_trace (false);
-
-    unsigned int i = buffer->idx;
-    unsigned int j = skippy_iter.idx;
-
-    buffer->unsafe_to_break (i, j);
-    float entry_x, entry_y, exit_x, exit_y;
-    (this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
-    (this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
-
-    hb_glyph_position_t *pos = buffer->pos;
-
-    hb_position_t d;
-    /* Main-direction adjustment */
-    switch (c->direction) {
-      case HB_DIRECTION_LTR:
-	pos[i].x_advance  = round (exit_x) + pos[i].x_offset;
-
-	d = round (entry_x) + pos[j].x_offset;
-	pos[j].x_advance -= d;
-	pos[j].x_offset  -= d;
-	break;
-      case HB_DIRECTION_RTL:
-	d = round (exit_x) + pos[i].x_offset;
-	pos[i].x_advance -= d;
-	pos[i].x_offset  -= d;
-
-	pos[j].x_advance  = round (entry_x) + pos[j].x_offset;
-	break;
-      case HB_DIRECTION_TTB:
-	pos[i].y_advance  = round (exit_y) + pos[i].y_offset;
-
-	d = round (entry_y) + pos[j].y_offset;
-	pos[j].y_advance -= d;
-	pos[j].y_offset  -= d;
-	break;
-      case HB_DIRECTION_BTT:
-	d = round (exit_y) + pos[i].y_offset;
-	pos[i].y_advance -= d;
-	pos[i].y_offset  -= d;
-
-	pos[j].y_advance  = round (entry_y);
-	break;
-      case HB_DIRECTION_INVALID:
-      default:
-	break;
-    }
-
-    /* Cross-direction adjustment */
-
-    /* We attach child to parent (think graph theory and rooted trees whereas
-     * the root stays on baseline and each node aligns itself against its
-     * parent.
-     *
-     * Optimize things for the case of RightToLeft, as that's most common in
-     * Arabinc. */
-    unsigned int child  = i;
-    unsigned int parent = j;
-    hb_position_t x_offset = entry_x - exit_x;
-    hb_position_t y_offset = entry_y - exit_y;
-    if  (!(c->lookup_props & LookupFlag::RightToLeft))
-    {
-      unsigned int k = child;
-      child = parent;
-      parent = k;
-      x_offset = -x_offset;
-      y_offset = -y_offset;
-    }
-
-    /* If child was already connected to someone else, walk through its old
-     * chain and reverse the link direction, such that the whole tree of its
-     * previous connection now attaches to new parent.  Watch out for case
-     * where new parent is on the path from old chain...
-     */
-    reverse_cursive_minor_offset (pos, child, c->direction, parent);
-
-    pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
-    pos[child].attach_chain() = (int) parent - (int) child;
-    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
-      pos[child].y_offset = y_offset;
-    else
-      pos[child].x_offset = x_offset;
-
-    buffer->idx = j;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of subtable */
-  ArrayOf<EntryExitRecord>
-		entryExitRecord;	/* Array of EntryExit records--in
-					 * Coverage Index order */
-  public:
-  DEFINE_SIZE_ARRAY (6, entryExitRecord);
-};
-
-struct CursivePos
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    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));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  CursivePosFormat1	format1;
-  } u;
-};
-
-
-typedef AnchorMatrix BaseArray;		/* base-major--
-					 * in order of BaseCoverage Index--,
-					 * mark-minor--
-					 * ordered by class--zero-based. */
-
-struct MarkBasePosFormat1
-{
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
-    if (unlikely (!(this+baseCoverage).add_coverage (c->input))) return;
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+markCoverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    hb_buffer_t *buffer = c->buffer;
-    unsigned int mark_index = (this+markCoverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (mark_index == NOT_COVERED)) return_trace (false);
-
-    /* Now we search backwards for a non-mark glyph */
-    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
-    skippy_iter.reset (buffer->idx, 1);
-    skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
-    do {
-      if (!skippy_iter.prev ()) return_trace (false);
-      /* We only want to attach to the first of a MultipleSubst sequence.
-       * https://github.com/harfbuzz/harfbuzz/issues/740
-       * Reject others. */
-      if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
-	  0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
-	  (skippy_iter.idx == 0 ||
-	   _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
-	   _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
-	   _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
-	   _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1
-	   ))
-	break;
-      skippy_iter.reject ();
-    } while (1);
-
-    /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
-    //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
-
-    unsigned int base_index = (this+baseCoverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint);
-    if (base_index == NOT_COVERED) return_trace (false);
-
-    return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  markCoverage.sanitize (c, this) &&
-		  baseCoverage.sanitize (c, this) &&
-		  markArray.sanitize (c, this) &&
-		  baseArray.sanitize (c, this, (unsigned int) classCount));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-		markCoverage;		/* Offset to MarkCoverage table--from
-					 * beginning of MarkBasePos subtable */
-  OffsetTo<Coverage>
-		baseCoverage;		/* Offset to BaseCoverage table--from
-					 * beginning of MarkBasePos subtable */
-  HBUINT16	classCount;		/* Number of classes defined for marks */
-  OffsetTo<MarkArray>
-		markArray;		/* Offset to MarkArray table--from
-					 * beginning of MarkBasePos subtable */
-  OffsetTo<BaseArray>
-		baseArray;		/* Offset to BaseArray table--from
-					 * beginning of MarkBasePos subtable */
-  public:
-  DEFINE_SIZE_STATIC (12);
-};
-
-struct MarkBasePos
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    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));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  MarkBasePosFormat1	format1;
-  } u;
-};
-
-
-typedef AnchorMatrix LigatureAttach;	/* component-major--
-					 * in order of writing direction--,
-					 * mark-minor--
-					 * ordered by class--zero-based. */
-
-typedef OffsetListOf<LigatureAttach> LigatureArray;
-					/* Array of LigatureAttach
-					 * tables ordered by
-					 * LigatureCoverage Index */
-
-struct MarkLigPosFormat1
-{
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
-    if (unlikely (!(this+ligatureCoverage).add_coverage (c->input))) return;
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+markCoverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    hb_buffer_t *buffer = c->buffer;
-    unsigned int mark_index = (this+markCoverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (mark_index == NOT_COVERED)) return_trace (false);
-
-    /* Now we search backwards for a non-mark glyph */
-    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
-    skippy_iter.reset (buffer->idx, 1);
-    skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
-    if (!skippy_iter.prev ()) return_trace (false);
-
-    /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
-    //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
-
-    unsigned int j = skippy_iter.idx;
-    unsigned int lig_index = (this+ligatureCoverage).get_coverage  (buffer->info[j].codepoint);
-    if (lig_index == NOT_COVERED) return_trace (false);
-
-    const LigatureArray& lig_array = this+ligatureArray;
-    const LigatureAttach& lig_attach = lig_array[lig_index];
-
-    /* Find component to attach to */
-    unsigned int comp_count = lig_attach.rows;
-    if (unlikely (!comp_count)) return_trace (false);
-
-    /* We must now check whether the ligature ID of the current mark glyph
-     * is identical to the ligature ID of the found ligature.  If yes, we
-     * can directly use the component index.  If not, we attach the mark
-     * glyph to the last component of the ligature. */
-    unsigned int comp_index;
-    unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
-    unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-    unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
-    if (lig_id && lig_id == mark_id && mark_comp > 0)
-      comp_index = MIN (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
-    else
-      comp_index = comp_count - 1;
-
-    return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  markCoverage.sanitize (c, this) &&
-		  ligatureCoverage.sanitize (c, this) &&
-		  markArray.sanitize (c, this) &&
-		  ligatureArray.sanitize (c, this, (unsigned int) classCount));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-		markCoverage;		/* Offset to Mark Coverage table--from
-					 * beginning of MarkLigPos subtable */
-  OffsetTo<Coverage>
-		ligatureCoverage;	/* Offset to Ligature Coverage
-					 * table--from beginning of MarkLigPos
-					 * subtable */
-  HBUINT16	classCount;		/* Number of defined mark classes */
-  OffsetTo<MarkArray>
-		markArray;		/* Offset to MarkArray table--from
-					 * beginning of MarkLigPos subtable */
-  OffsetTo<LigatureArray>
-		ligatureArray;		/* Offset to LigatureArray table--from
-					 * beginning of MarkLigPos subtable */
-  public:
-  DEFINE_SIZE_STATIC (12);
-};
-
-struct MarkLigPos
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    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));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  MarkLigPosFormat1	format1;
-  } u;
-};
-
-
-typedef AnchorMatrix Mark2Array;	/* mark2-major--
-					 * in order of Mark2Coverage Index--,
-					 * mark1-minor--
-					 * ordered by class--zero-based. */
-
-struct MarkMarkPosFormat1
-{
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+mark1Coverage).add_coverage (c->input))) return;
-    if (unlikely (!(this+mark2Coverage).add_coverage (c->input))) return;
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+mark1Coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    hb_buffer_t *buffer = c->buffer;
-    unsigned int mark1_index = (this+mark1Coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (mark1_index == NOT_COVERED)) return_trace (false);
-
-    /* now we search backwards for a suitable mark glyph until a non-mark glyph */
-    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
-    skippy_iter.reset (buffer->idx, 1);
-    skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
-    if (!skippy_iter.prev ()) return_trace (false);
-
-    if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) { return_trace (false); }
-
-    unsigned int j = skippy_iter.idx;
-
-    unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
-    unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
-    unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
-    unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
-
-    if (likely (id1 == id2)) {
-      if (id1 == 0) /* Marks belonging to the same base. */
-	goto good;
-      else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
-        goto good;
-    } else {
-      /* If ligature ids don't match, it may be the case that one of the marks
-       * itself is a ligature.  In which case match. */
-      if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
-	goto good;
-    }
-
-    /* Didn't match. */
-    return_trace (false);
-
-    good:
-    unsigned int mark2_index = (this+mark2Coverage).get_coverage  (buffer->info[j].codepoint);
-    if (mark2_index == NOT_COVERED) return_trace (false);
-
-    return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  mark1Coverage.sanitize (c, this) &&
-		  mark2Coverage.sanitize (c, this) &&
-		  mark1Array.sanitize (c, this) &&
-		  mark2Array.sanitize (c, this, (unsigned int) classCount));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-		mark1Coverage;		/* Offset to Combining Mark1 Coverage
-					 * table--from beginning of MarkMarkPos
-					 * subtable */
-  OffsetTo<Coverage>
-		mark2Coverage;		/* Offset to Combining Mark2 Coverage
-					 * table--from beginning of MarkMarkPos
-					 * subtable */
-  HBUINT16	classCount;		/* Number of defined mark classes */
-  OffsetTo<MarkArray>
-		mark1Array;		/* Offset to Mark1Array table--from
-					 * beginning of MarkMarkPos subtable */
-  OffsetTo<Mark2Array>
-		mark2Array;		/* Offset to Mark2Array table--from
-					 * beginning of MarkMarkPos subtable */
-  public:
-  DEFINE_SIZE_STATIC (12);
-};
-
-struct MarkMarkPos
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    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));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  MarkMarkPosFormat1	format1;
-  } u;
-};
-
-
-struct ContextPos : Context {};
-
-struct ChainContextPos : ChainContext {};
-
-struct ExtensionPos : Extension<ExtensionPos>
-{
-  typedef struct PosLookupSubTable LookupSubTable;
-};
-
-
-
-/*
- * PosLookup
- */
-
-
-struct PosLookupSubTable
-{
-  friend struct PosLookup;
-
-  enum Type {
-    Single		= 1,
-    Pair		= 2,
-    Cursive		= 3,
-    MarkBase		= 4,
-    MarkLig		= 5,
-    MarkMark		= 6,
-    Context		= 7,
-    ChainContext	= 8,
-    Extension		= 9
-  };
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
-  {
-    TRACE_DISPATCH (this, lookup_type);
-    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ());
-    switch (lookup_type) {
-    case Single:		return_trace (u.single.dispatch (c));
-    case Pair:			return_trace (u.pair.dispatch (c));
-    case Cursive:		return_trace (u.cursive.dispatch (c));
-    case MarkBase:		return_trace (u.markBase.dispatch (c));
-    case MarkLig:		return_trace (u.markLig.dispatch (c));
-    case MarkMark:		return_trace (u.markMark.dispatch (c));
-    case Context:		return_trace (u.context.dispatch (c));
-    case ChainContext:		return_trace (u.chainContext.dispatch (c));
-    case Extension:		return_trace (u.extension.dispatch (c));
-    default:			return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		sub_format;
-  SinglePos		single;
-  PairPos		pair;
-  CursivePos		cursive;
-  MarkBasePos		markBase;
-  MarkLigPos		markLig;
-  MarkMarkPos		markMark;
-  ContextPos		context;
-  ChainContextPos	chainContext;
-  ExtensionPos		extension;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, sub_format);
-};
-
-
-struct PosLookup : Lookup
-{
-  inline const PosLookupSubTable& get_subtable (unsigned int i) const
-  { return Lookup::get_subtable<PosLookupSubTable> (i); }
-
-  inline bool is_reverse (void) const
-  {
-    return false;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    return_trace (dispatch (c));
-  }
-
-  inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    return_trace (dispatch (c));
-  }
-
-  template <typename set_t>
-  inline void add_coverage (set_t *glyphs) const
-  {
-    hb_add_coverage_context_t<set_t> c (glyphs);
-    dispatch (&c);
-  }
-
-  static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
-
-  template <typename context_t>
-  static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  { return Lookup::dispatch<PosLookupSubTable> (c); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!Lookup::sanitize (c))) return_trace (false);
-    return_trace (dispatch (c));
-  }
-};
-
-typedef OffsetListOf<PosLookup> PosLookupList;
-
-/*
- * GPOS -- The Glyph Positioning Table
- */
-
-struct GPOS : GSUBGPOS
-{
-  static const hb_tag_t tableTag	= HB_OT_TAG_GPOS;
-
-  inline const PosLookup& get_lookup (unsigned int i) const
-  { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
-
-  static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
-  static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
-  static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false);
-    const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
-    return_trace (list.sanitize (c, this));
-  }
-};
-
-
-static void
-reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent)
-{
-  int chain = pos[i].attach_chain(), type = pos[i].attach_type();
-  if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
-    return;
-
-  pos[i].attach_chain() = 0;
-
-  unsigned int j = (int) i + chain;
-
-  /* Stop if we see new parent in the chain. */
-  if (j == new_parent)
-    return;
-
-  reverse_cursive_minor_offset (pos, j, direction, new_parent);
-
-  if (HB_DIRECTION_IS_HORIZONTAL (direction))
-    pos[j].y_offset = -pos[i].y_offset;
-  else
-    pos[j].x_offset = -pos[i].x_offset;
-
-  pos[j].attach_chain() = -chain;
-  pos[j].attach_type() = type;
-}
-static void
-propagate_attachment_offsets (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction)
-{
-  /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
-   * offset of glyph they are attached to. */
-  int chain = pos[i].attach_chain(), type = pos[i].attach_type();
-  if (likely (!chain))
-    return;
-
-  unsigned int j = (int) i + chain;
-
-  pos[i].attach_chain() = 0;
-
-  propagate_attachment_offsets (pos, j, direction);
-
-  assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE));
-
-  if (type & ATTACH_TYPE_CURSIVE)
-  {
-    if (HB_DIRECTION_IS_HORIZONTAL (direction))
-      pos[i].y_offset += pos[j].y_offset;
-    else
-      pos[i].x_offset += pos[j].x_offset;
-  }
-  else /*if (type & ATTACH_TYPE_MARK)*/
-  {
-    pos[i].x_offset += pos[j].x_offset;
-    pos[i].y_offset += pos[j].y_offset;
-
-    assert (j < i);
-    if (HB_DIRECTION_IS_FORWARD (direction))
-      for (unsigned int k = j; k < i; k++) {
-	pos[i].x_offset -= pos[k].x_advance;
-	pos[i].y_offset -= pos[k].y_advance;
-      }
-    else
-      for (unsigned int k = j + 1; k < i + 1; k++) {
-	pos[i].x_offset += pos[k].x_advance;
-	pos[i].y_offset += pos[k].y_advance;
-      }
-  }
-}
-
-void
-GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
-{
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-    buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0;
-}
-
-void
-GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
-{
-  //_hb_buffer_assert_gsubgpos_vars (buffer);
-}
-
-void
-GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
-{
-  _hb_buffer_assert_gsubgpos_vars (buffer);
-
-  unsigned int len;
-  hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
-  hb_direction_t direction = buffer->props.direction;
-
-  /* Handle attachments */
-  if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
-    for (unsigned int i = 0; i < len; i++)
-      propagate_attachment_offsets (pos, i, direction);
-}
-
-
-/* Out-of-class implementation for methods recursing */
-
-template <typename context_t>
-/*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
-{
-  const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
-  const PosLookup &l = gpos.get_lookup (lookup_index);
-  return l.dispatch (c);
-}
-
-/*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
-{
-  const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
-  const PosLookup &l = gpos.get_lookup (lookup_index);
-  unsigned int saved_lookup_props = c->lookup_props;
-  unsigned int saved_lookup_index = c->lookup_index;
-  c->set_lookup_index (lookup_index);
-  c->set_lookup_props (l.get_props ());
-  bool ret = l.dispatch (c);
-  c->set_lookup_index (saved_lookup_index);
-  c->set_lookup_props (saved_lookup_props);
-  return ret;
-}
-
-
-#undef attach_chain
-#undef attach_type
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_LAYOUT_GPOS_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
deleted file mode 100644
index 5f67aed..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
+++ /dev/null
@@ -1,1364 +0,0 @@
-/*
- * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 2010,2012,2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_LAYOUT_GSUB_TABLE_HH
-#define HB_OT_LAYOUT_GSUB_TABLE_HH
-
-#include "hb-ot-layout-gsubgpos-private.hh"
-
-
-namespace OT {
-
-
-struct SingleSubstFormat1
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      /* TODO Switch to range-based API to work around malicious fonts.
-       * https://github.com/harfbuzz/harfbuzz/issues/363 */
-      hb_codepoint_t glyph_id = iter.get_glyph ();
-      if (c->glyphs->has (glyph_id))
-	c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
-    }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      /* TODO Switch to range-based API to work around malicious fonts.
-       * https://github.com/harfbuzz/harfbuzz/issues/363 */
-      hb_codepoint_t glyph_id = iter.get_glyph ();
-      c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
-    }
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    /* According to the Adobe Annotated OpenType Suite, result is always
-     * limited to 16bit. */
-    glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu;
-    c->replace_glyph (glyph_id);
-
-    return_trace (true);
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &glyphs,
-			 unsigned int num_glyphs,
-			 int delta)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of Substitution table */
-  HBINT16	deltaGlyphID;		/* Add to original GlyphID to get
-					 * substitute GlyphID */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct SingleSubstFormat2
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
-    unsigned int count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      if (c->glyphs->has (iter.get_glyph ()))
-	c->glyphs->add (substitute[iter.get_coverage ()]);
-    }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
-    unsigned int count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      c->output->add (substitute[iter.get_coverage ()]);
-    }
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    if (unlikely (index >= substitute.len)) return_trace (false);
-
-    glyph_id = substitute[index];
-    c->replace_glyph (glyph_id);
-
-    return_trace (true);
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &glyphs,
-			 Supplier<GlyphID> &substitutes,
-			 unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return_trace (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 2 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of Substitution table */
-  ArrayOf<GlyphID>
-		substitute;		/* Array of substitute
-					 * GlyphIDs--ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_ARRAY (6, substitute);
-};
-
-struct SingleSubst
-{
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &glyphs,
-			 Supplier<GlyphID> &substitutes,
-			 unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (u.format))) return_trace (false);
-    unsigned int format = 2;
-    int delta = 0;
-    if (num_glyphs) {
-      format = 1;
-      /* TODO(serialize) check for wrap-around */
-      delta = substitutes[0] - glyphs[0];
-      for (unsigned int i = 1; i < num_glyphs; i++)
-	if (delta != substitutes[i] - glyphs[i]) {
-	  format = 2;
-	  break;
-	}
-    }
-    u.format.set (format);
-    switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs, delta));
-    case 2: return_trace (u.format2.serialize (c, glyphs, substitutes, num_glyphs));
-    default:return_trace (false);
-    }
-  }
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    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));
-    case 2: return_trace (c->dispatch (u.format2));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  SingleSubstFormat1	format1;
-  SingleSubstFormat2	format2;
-  } u;
-};
-
-
-struct Sequence
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    unsigned int count = substitute.len;
-    for (unsigned int i = 0; i < count; i++)
-      c->glyphs->add (substitute[i]);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    c->output->add_array (substitute.array, substitute.len);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int count = substitute.len;
-
-    /* Special-case to make it in-place and not consider this
-     * as a "multiplied" substitution. */
-    if (unlikely (count == 1))
-    {
-      c->replace_glyph (substitute.array[0]);
-      return_trace (true);
-    }
-    /* Spec disallows this, but Uniscribe allows it.
-     * https://github.com/harfbuzz/harfbuzz/issues/253 */
-    else if (unlikely (count == 0))
-    {
-      c->buffer->delete_glyph ();
-      return_trace (true);
-    }
-
-    unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
-			 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
-
-    for (unsigned int i = 0; i < count; i++) {
-      _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
-      c->output_glyph_for_component (substitute.array[i], klass);
-    }
-    c->buffer->skip_glyph ();
-
-    return_trace (true);
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &glyphs,
-			 unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (substitute.sanitize (c));
-  }
-
-  protected:
-  ArrayOf<GlyphID>
-		substitute;		/* String of GlyphIDs to substitute */
-  public:
-  DEFINE_SIZE_ARRAY (2, substitute);
-};
-
-struct MultipleSubstFormat1
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
-    unsigned int count = sequence.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      if (c->glyphs->has (iter.get_glyph ()))
-	(this+sequence[iter.get_coverage ()]).closure (c);
-    }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    unsigned int count = sequence.len;
-    for (unsigned int i = 0; i < count; i++)
-	(this+sequence[i]).collect_glyphs (c);
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    return_trace ((this+sequence[index]).apply (c));
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &glyphs,
-			 Supplier<unsigned int> &substitute_len_list,
-			 unsigned int num_glyphs,
-			 Supplier<GlyphID> &substitute_glyphs_list)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!sequence.serialize (c, num_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      if (unlikely (!sequence[i].serialize (c, this).serialize (c,
-								substitute_glyphs_list,
-								substitute_len_list[i]))) return_trace (false);
-    substitute_len_list += num_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of Substitution table */
-  OffsetArrayOf<Sequence>
-		sequence;		/* Array of Sequence tables
-					 * ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_ARRAY (6, sequence);
-};
-
-struct MultipleSubst
-{
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &glyphs,
-			 Supplier<unsigned int> &substitute_len_list,
-			 unsigned int num_glyphs,
-			 Supplier<GlyphID> &substitute_glyphs_list)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (u.format))) return_trace (false);
-    unsigned int format = 1;
-    u.format.set (format);
-    switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, num_glyphs, substitute_glyphs_list));
-    default:return_trace (false);
-    }
-  }
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    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));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  MultipleSubstFormat1	format1;
-  } u;
-};
-
-
-typedef ArrayOf<GlyphID> AlternateSet;	/* Array of alternate GlyphIDs--in
-					 * arbitrary order */
-
-struct AlternateSubstFormat1
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
-    unsigned int count = alternateSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      if (c->glyphs->has (iter.get_glyph ())) {
-	const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
-	unsigned int count = alt_set.len;
-	for (unsigned int i = 0; i < count; i++)
-	  c->glyphs->add (alt_set[i]);
-      }
-    }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
-    unsigned int count = alternateSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
-      c->output->add_array (alt_set.array, alt_set.len);
-    }
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
-
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const AlternateSet &alt_set = this+alternateSet[index];
-
-    if (unlikely (!alt_set.len)) return_trace (false);
-
-    hb_mask_t glyph_mask = c->buffer->cur().mask;
-    hb_mask_t lookup_mask = c->lookup_mask;
-
-    /* Note: This breaks badly if two features enabled this lookup together. */
-    unsigned int shift = _hb_ctz (lookup_mask);
-    unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
-
-    if (unlikely (alt_index > alt_set.len || alt_index == 0)) return_trace (false);
-
-    glyph_id = alt_set[alt_index - 1];
-
-    c->replace_glyph (glyph_id);
-
-    return_trace (true);
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &glyphs,
-			 Supplier<unsigned int> &alternate_len_list,
-			 unsigned int num_glyphs,
-			 Supplier<GlyphID> &alternate_glyphs_list)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!alternateSet.serialize (c, num_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      if (unlikely (!alternateSet[i].serialize (c, this).serialize (c,
-								    alternate_glyphs_list,
-								    alternate_len_list[i]))) return_trace (false);
-    alternate_len_list += num_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of Substitution table */
-  OffsetArrayOf<AlternateSet>
-		alternateSet;		/* Array of AlternateSet tables
-					 * ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_ARRAY (6, alternateSet);
-};
-
-struct AlternateSubst
-{
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &glyphs,
-			 Supplier<unsigned int> &alternate_len_list,
-			 unsigned int num_glyphs,
-			 Supplier<GlyphID> &alternate_glyphs_list)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (u.format))) return_trace (false);
-    unsigned int format = 1;
-    u.format.set (format);
-    switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, num_glyphs, alternate_glyphs_list));
-    default:return_trace (false);
-    }
-  }
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    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));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  AlternateSubstFormat1	format1;
-  } u;
-};
-
-
-struct Ligature
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    unsigned int count = component.len;
-    for (unsigned int i = 1; i < count; i++)
-      if (!c->glyphs->has (component[i]))
-        return;
-    c->glyphs->add (ligGlyph);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    c->input->add_array (component.array, component.len ? component.len - 1 : 0);
-    c->output->add (ligGlyph);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-    if (c->len != component.len)
-      return_trace (false);
-
-    for (unsigned int i = 1; i < c->len; i++)
-      if (likely (c->glyphs[i] != component[i]))
-	return_trace (false);
-
-    return_trace (true);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int count = component.len;
-
-    if (unlikely (!count)) return_trace (false);
-
-    /* Special-case to make it in-place and not consider this
-     * as a "ligated" substitution. */
-    if (unlikely (count == 1))
-    {
-      c->replace_glyph (ligGlyph);
-      return_trace (true);
-    }
-
-    bool is_mark_ligature = false;
-    unsigned int total_component_count = 0;
-
-    unsigned int match_length = 0;
-    unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
-
-    if (likely (!match_input (c, count,
-			      &component[1],
-			      match_glyph,
-			      nullptr,
-			      &match_length,
-			      match_positions,
-			      &is_mark_ligature,
-			      &total_component_count)))
-      return_trace (false);
-
-    ligate_input (c,
-		  count,
-		  match_positions,
-		  match_length,
-		  ligGlyph,
-		  is_mark_ligature,
-		  total_component_count);
-
-    return_trace (true);
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 GlyphID ligature,
-			 Supplier<GlyphID> &components, /* Starting from second */
-			 unsigned int num_components /* Including first component */)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    ligGlyph = ligature;
-    if (unlikely (!component.serialize (c, components, num_components))) return_trace (false);
-    return_trace (true);
-  }
-
-  public:
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (ligGlyph.sanitize (c) && component.sanitize (c));
-  }
-
-  protected:
-  GlyphID	ligGlyph;		/* GlyphID of ligature to substitute */
-  HeadlessArrayOf<GlyphID>
-		component;		/* Array of component GlyphIDs--start
-					 * with the second  component--ordered
-					 * in writing direction */
-  public:
-  DEFINE_SIZE_ARRAY (4, component);
-};
-
-struct LigatureSet
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    unsigned int num_ligs = ligature.len;
-    for (unsigned int i = 0; i < num_ligs; i++)
-      (this+ligature[i]).closure (c);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    unsigned int num_ligs = ligature.len;
-    for (unsigned int i = 0; i < num_ligs; i++)
-      (this+ligature[i]).collect_glyphs (c);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-    unsigned int num_ligs = ligature.len;
-    for (unsigned int i = 0; i < num_ligs; i++)
-    {
-      const Ligature &lig = this+ligature[i];
-      if (lig.would_apply (c))
-        return_trace (true);
-    }
-    return_trace (false);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int num_ligs = ligature.len;
-    for (unsigned int i = 0; i < num_ligs; i++)
-    {
-      const Ligature &lig = this+ligature[i];
-      if (lig.apply (c)) return_trace (true);
-    }
-
-    return_trace (false);
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &ligatures,
-			 Supplier<unsigned int> &component_count_list,
-			 unsigned int num_ligatures,
-			 Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!ligature.serialize (c, num_ligatures))) return_trace (false);
-    for (unsigned int i = 0; i < num_ligatures; i++)
-      if (unlikely (!ligature[i].serialize (c, this).serialize (c,
-								ligatures[i],
-								component_list,
-								component_count_list[i]))) return_trace (false);
-    ligatures += num_ligatures;
-    component_count_list += num_ligatures;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (ligature.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<Ligature>
-		ligature;		/* Array LigatureSet tables
-					 * ordered by preference */
-  public:
-  DEFINE_SIZE_ARRAY (2, ligature);
-};
-
-struct LigatureSubstFormat1
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
-    unsigned int count = ligatureSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      if (c->glyphs->has (iter.get_glyph ()))
-	(this+ligatureSet[iter.get_coverage ()]).closure (c);
-    }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
-    unsigned int count = ligatureSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      (this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c);
-    }
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const LigatureSet &lig_set = this+ligatureSet[index];
-    return_trace (lig_set.would_apply (c));
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
-
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const LigatureSet &lig_set = this+ligatureSet[index];
-    return_trace (lig_set.apply (c));
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &first_glyphs,
-			 Supplier<unsigned int> &ligature_per_first_glyph_count_list,
-			 unsigned int num_first_glyphs,
-			 Supplier<GlyphID> &ligatures_list,
-			 Supplier<unsigned int> &component_count_list,
-			 Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_first_glyphs; i++)
-      if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c,
-								   ligatures_list,
-								   component_count_list,
-								   ligature_per_first_glyph_count_list[i],
-								   component_list))) return_trace (false);
-    ligature_per_first_glyph_count_list += num_first_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of Substitution table */
-  OffsetArrayOf<LigatureSet>
-		ligatureSet;		/* Array LigatureSet tables
-					 * ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_ARRAY (6, ligatureSet);
-};
-
-struct LigatureSubst
-{
-  inline bool serialize (hb_serialize_context_t *c,
-			 Supplier<GlyphID> &first_glyphs,
-			 Supplier<unsigned int> &ligature_per_first_glyph_count_list,
-			 unsigned int num_first_glyphs,
-			 Supplier<GlyphID> &ligatures_list,
-			 Supplier<unsigned int> &component_count_list,
-			 Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (u.format))) return_trace (false);
-    unsigned int format = 1;
-    u.format.set (format);
-    switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c,
-					       first_glyphs,
-					       ligature_per_first_glyph_count_list,
-					       num_first_glyphs,
-					       ligatures_list,
-					       component_count_list,
-					       component_list));
-    default:return_trace (false);
-    }
-  }
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    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));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  LigatureSubstFormat1	format1;
-  } u;
-};
-
-
-struct ContextSubst : Context {};
-
-struct ChainContextSubst : ChainContext {};
-
-struct ExtensionSubst : Extension<ExtensionSubst>
-{
-  typedef struct SubstLookupSubTable LookupSubTable;
-
-  inline bool is_reverse (void) const;
-};
-
-
-struct ReverseChainSingleSubstFormat1
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-
-    unsigned int count;
-
-    count = backtrack.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!(this+backtrack[i]).intersects (c->glyphs))
-        return;
-
-    count = lookahead.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!(this+lookahead[i]).intersects (c->glyphs))
-        return;
-
-    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
-    Coverage::Iter iter;
-    count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
-    {
-      if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      if (c->glyphs->has (iter.get_glyph ()))
-	c->glyphs->add (substitute[iter.get_coverage ()]);
-    }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-
-    unsigned int count;
-
-    count = backtrack.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!(this+backtrack[i]).add_coverage (c->before))) return;
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    count = lookahead.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!(this+lookahead[i]).add_coverage (c->after))) return;
-
-    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
-    count = substitute.len;
-    c->output->add_array (substitute.array, substitute.len);
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
-      return_trace (false); /* No chaining to this type */
-
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
-
-  unsigned int start_index = 0, end_index = 0;
-    if (match_backtrack (c,
-			 backtrack.len, (HBUINT16 *) backtrack.array,
-			 match_coverage, this,
-			 &start_index) &&
-        match_lookahead (c,
-			 lookahead.len, (HBUINT16 *) lookahead.array,
-			 match_coverage, this,
-			 1, &end_index))
-    {
-      c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
-      c->replace_glyph_inplace (substitute[index]);
-      /* Note: We DON'T decrease buffer->idx.  The main loop does it
-       * for us.  This is useful for preventing surprises if someone
-       * calls us through a Context lookup. */
-      return_trace (true);
-    }
-
-    return_trace (false);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
-      return_trace (false);
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    if (!lookahead.sanitize (c, this))
-      return_trace (false);
-    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
-    return_trace (substitute.sanitize (c));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of table */
-  OffsetArrayOf<Coverage>
-		backtrack;		/* Array of coverage tables
-					 * in backtracking sequence, in  glyph
-					 * sequence order */
-  OffsetArrayOf<Coverage>
-		lookaheadX;		/* Array of coverage tables
-					 * in lookahead sequence, in glyph
-					 * sequence order */
-  ArrayOf<GlyphID>
-		substituteX;		/* Array of substitute
-					 * GlyphIDs--ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_MIN (10);
-};
-
-struct ReverseChainSingleSubst
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    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));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16				format;		/* Format identifier */
-  ReverseChainSingleSubstFormat1	format1;
-  } u;
-};
-
-
-
-/*
- * SubstLookup
- */
-
-struct SubstLookupSubTable
-{
-  friend struct SubstLookup;
-
-  enum Type {
-    Single		= 1,
-    Multiple		= 2,
-    Alternate		= 3,
-    Ligature		= 4,
-    Context		= 5,
-    ChainContext	= 6,
-    Extension		= 7,
-    ReverseChainSingle	= 8
-  };
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
-  {
-    TRACE_DISPATCH (this, lookup_type);
-    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ());
-    switch (lookup_type) {
-    case Single:		return_trace (u.single.dispatch (c));
-    case Multiple:		return_trace (u.multiple.dispatch (c));
-    case Alternate:		return_trace (u.alternate.dispatch (c));
-    case Ligature:		return_trace (u.ligature.dispatch (c));
-    case Context:		return_trace (u.context.dispatch (c));
-    case ChainContext:		return_trace (u.chainContext.dispatch (c));
-    case Extension:		return_trace (u.extension.dispatch (c));
-    case ReverseChainSingle:	return_trace (u.reverseChainContextSingle.dispatch (c));
-    default:			return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16			sub_format;
-  SingleSubst			single;
-  MultipleSubst			multiple;
-  AlternateSubst		alternate;
-  LigatureSubst			ligature;
-  ContextSubst			context;
-  ChainContextSubst		chainContext;
-  ExtensionSubst		extension;
-  ReverseChainSingleSubst	reverseChainContextSingle;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, sub_format);
-};
-
-
-struct SubstLookup : Lookup
-{
-  inline const SubstLookupSubTable& get_subtable (unsigned int i) const
-  { return Lookup::get_subtable<SubstLookupSubTable> (i); }
-
-  inline static bool lookup_type_is_reverse (unsigned int lookup_type)
-  { return lookup_type == SubstLookupSubTable::ReverseChainSingle; }
-
-  inline bool is_reverse (void) const
-  {
-    unsigned int type = get_type ();
-    if (unlikely (type == SubstLookupSubTable::Extension))
-      return CastR<ExtensionSubst> (get_subtable(0)).is_reverse ();
-    return lookup_type_is_reverse (type);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    return_trace (dispatch (c));
-  }
-
-  inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    c->set_recurse_func (dispatch_recurse_func<hb_closure_context_t>);
-    return_trace (dispatch (c));
-  }
-
-  inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
-    return_trace (dispatch (c));
-  }
-
-  template <typename set_t>
-  inline void add_coverage (set_t *glyphs) const
-  {
-    hb_add_coverage_context_t<set_t> c (glyphs);
-    dispatch (&c);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c,
-			   const hb_ot_layout_lookup_accelerator_t *accel) const
-  {
-    TRACE_WOULD_APPLY (this);
-    if (unlikely (!c->len))  return_trace (false);
-    if (!accel->may_have (c->glyphs[0]))  return_trace (false);
-      return_trace (dispatch (c));
-  }
-
-  static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
-
-  inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c,
-						  unsigned int i)
-  { return get_subtables<SubstLookupSubTable> ()[i].serialize (c, this); }
-
-  inline bool serialize_single (hb_serialize_context_t *c,
-				uint32_t lookup_props,
-			        Supplier<GlyphID> &glyphs,
-			        Supplier<GlyphID> &substitutes,
-			        unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_props, 1))) return_trace (false);
-    return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs));
-  }
-
-  inline bool serialize_multiple (hb_serialize_context_t *c,
-				  uint32_t lookup_props,
-				  Supplier<GlyphID> &glyphs,
-				  Supplier<unsigned int> &substitute_len_list,
-				  unsigned int num_glyphs,
-				  Supplier<GlyphID> &substitute_glyphs_list)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return_trace (false);
-    return_trace (serialize_subtable (c, 0).u.multiple.serialize (c,
-								  glyphs,
-								  substitute_len_list,
-								  num_glyphs,
-								  substitute_glyphs_list));
-  }
-
-  inline bool serialize_alternate (hb_serialize_context_t *c,
-				   uint32_t lookup_props,
-				   Supplier<GlyphID> &glyphs,
-				   Supplier<unsigned int> &alternate_len_list,
-				   unsigned int num_glyphs,
-				   Supplier<GlyphID> &alternate_glyphs_list)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return_trace (false);
-    return_trace (serialize_subtable (c, 0).u.alternate.serialize (c,
-								   glyphs,
-								   alternate_len_list,
-								   num_glyphs,
-								   alternate_glyphs_list));
-  }
-
-  inline bool serialize_ligature (hb_serialize_context_t *c,
-				  uint32_t lookup_props,
-				  Supplier<GlyphID> &first_glyphs,
-				  Supplier<unsigned int> &ligature_per_first_glyph_count_list,
-				  unsigned int num_first_glyphs,
-				  Supplier<GlyphID> &ligatures_list,
-				  Supplier<unsigned int> &component_count_list,
-				  Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return_trace (false);
-    return_trace (serialize_subtable (c, 0).u.ligature.serialize (c,
-								  first_glyphs,
-								  ligature_per_first_glyph_count_list,
-								  num_first_glyphs,
-								  ligatures_list,
-								  component_count_list,
-								  component_list));
-  }
-
-  template <typename context_t>
-  static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  { return Lookup::dispatch<SubstLookupSubTable> (c); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!Lookup::sanitize (c))) return_trace (false);
-    if (unlikely (!dispatch (c))) return_trace (false);
-
-    if (unlikely (get_type () == SubstLookupSubTable::Extension))
-    {
-      /* The spec says all subtables of an Extension lookup should
-       * have the same type, which shall not be the Extension type
-       * itself (but we already checked for that).
-       * This is specially important if one has a reverse type! */
-      unsigned int type = get_subtable (0).u.extension.get_type ();
-      unsigned int count = get_subtable_count ();
-      for (unsigned int i = 1; i < count; i++)
-        if (get_subtable (i).u.extension.get_type () != type)
-	  return_trace (false);
-    }
-    return_trace (true);
-  }
-};
-
-typedef OffsetListOf<SubstLookup> SubstLookupList;
-
-/*
- * GSUB -- The Glyph Substitution Table
- */
-
-struct GSUB : GSUBGPOS
-{
-  static const hb_tag_t tableTag	= HB_OT_TAG_GSUB;
-
-  inline const SubstLookup& get_lookup (unsigned int i) const
-  { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
-
-  static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer);
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false);
-    const OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList);
-    return_trace (list.sanitize (c, this));
-  }
-};
-
-
-void
-GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
-{
-  _hb_buffer_assert_gsubgpos_vars (buffer);
-
-  const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
-    _hb_glyph_info_clear_lig_props (&buffer->info[i]);
-    buffer->info[i].syllable() = 0;
-  }
-}
-
-
-/* Out-of-class implementation for methods recursing */
-
-/*static*/ inline bool ExtensionSubst::is_reverse (void) const
-{
-  unsigned int type = get_type ();
-  if (unlikely (type == SubstLookupSubTable::Extension))
-    return CastR<ExtensionSubst> (get_subtable<LookupSubTable>()).is_reverse ();
-  return SubstLookup::lookup_type_is_reverse (type);
-}
-
-template <typename context_t>
-/*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
-{
-  const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
-  const SubstLookup &l = gsub.get_lookup (lookup_index);
-  return l.dispatch (c);
-}
-
-/*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
-{
-  const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
-  const SubstLookup &l = gsub.get_lookup (lookup_index);
-  unsigned int saved_lookup_props = c->lookup_props;
-  unsigned int saved_lookup_index = c->lookup_index;
-  c->set_lookup_index (lookup_index);
-  c->set_lookup_props (l.get_props ());
-  bool ret = l.dispatch (c);
-  c->set_lookup_index (saved_lookup_index);
-  c->set_lookup_props (saved_lookup_props);
-  return ret;
-}
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh
deleted file mode 100644
index 9054634..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh
+++ /dev/null
@@ -1,2374 +0,0 @@
-/*
- * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 2010,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
-#define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-buffer-private.hh"
-#include "hb-ot-layout-gdef-table.hh"
-#include "hb-set-private.hh"
-
-
-namespace OT {
-
-
-struct hb_closure_context_t :
-       hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE>
-{
-  inline const char *get_name (void) { return "CLOSURE"; }
-  typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
-  template <typename T>
-  inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
-  static return_t default_return_value (void) { return HB_VOID; }
-  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
-  return_t recurse (unsigned int lookup_index)
-  {
-    if (unlikely (nesting_level_left == 0 || !recurse_func))
-      return default_return_value ();
-
-    nesting_level_left--;
-    recurse_func (this, lookup_index);
-    nesting_level_left++;
-    return HB_VOID;
-  }
-
-  hb_face_t *face;
-  hb_set_t *glyphs;
-  recurse_func_t recurse_func;
-  unsigned int nesting_level_left;
-  unsigned int debug_depth;
-
-  hb_closure_context_t (hb_face_t *face_,
-			hb_set_t *glyphs_,
-		        unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
-			  face (face_),
-			  glyphs (glyphs_),
-			  recurse_func (nullptr),
-			  nesting_level_left (nesting_level_left_),
-			  debug_depth (0) {}
-
-  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
-};
-
-
-struct hb_would_apply_context_t :
-       hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
-{
-  inline const char *get_name (void) { return "WOULD_APPLY"; }
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.would_apply (this); }
-  static return_t default_return_value (void) { return false; }
-  bool stop_sublookup_iteration (return_t r) const { return r; }
-
-  hb_face_t *face;
-  const hb_codepoint_t *glyphs;
-  unsigned int len;
-  bool zero_context;
-  unsigned int debug_depth;
-
-  hb_would_apply_context_t (hb_face_t *face_,
-			    const hb_codepoint_t *glyphs_,
-			    unsigned int len_,
-			    bool zero_context_) :
-			      face (face_),
-			      glyphs (glyphs_),
-			      len (len_),
-			      zero_context (zero_context_),
-			      debug_depth (0) {}
-};
-
-
-struct hb_collect_glyphs_context_t :
-       hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, HB_DEBUG_COLLECT_GLYPHS>
-{
-  inline const char *get_name (void) { return "COLLECT_GLYPHS"; }
-  typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
-  template <typename T>
-  inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
-  static return_t default_return_value (void) { return HB_VOID; }
-  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
-  return_t recurse (unsigned int lookup_index)
-  {
-    if (unlikely (nesting_level_left == 0 || !recurse_func))
-      return default_return_value ();
-
-    /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
-     * past the previous check.  For GSUB, we only want to collect the output
-     * glyphs in the recursion.  If output is not requested, we can go home now.
-     *
-     * Note further, that the above is not exactly correct.  A recursed lookup
-     * is allowed to match input that is not matched in the context, but that's
-     * not how most fonts are built.  It's possible to relax that and recurse
-     * with all sets here if it proves to be an issue.
-     */
-
-    if (output == hb_set_get_empty ())
-      return HB_VOID;
-
-    /* Return if new lookup was recursed to before. */
-    if (recursed_lookups->has (lookup_index))
-      return HB_VOID;
-
-    hb_set_t *old_before = before;
-    hb_set_t *old_input  = input;
-    hb_set_t *old_after  = after;
-    before = input = after = hb_set_get_empty ();
-
-    nesting_level_left--;
-    recurse_func (this, lookup_index);
-    nesting_level_left++;
-
-    before = old_before;
-    input  = old_input;
-    after  = old_after;
-
-    recursed_lookups->add (lookup_index);
-
-    return HB_VOID;
-  }
-
-  hb_face_t *face;
-  hb_set_t *before;
-  hb_set_t *input;
-  hb_set_t *after;
-  hb_set_t *output;
-  recurse_func_t recurse_func;
-  hb_set_t *recursed_lookups;
-  unsigned int nesting_level_left;
-  unsigned int debug_depth;
-
-  hb_collect_glyphs_context_t (hb_face_t *face_,
-			       hb_set_t  *glyphs_before, /* OUT. May be nullptr */
-			       hb_set_t  *glyphs_input,  /* OUT. May be nullptr */
-			       hb_set_t  *glyphs_after,  /* OUT. May be nullptr */
-			       hb_set_t  *glyphs_output, /* OUT. May be nullptr */
-			       unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
-			      face (face_),
-			      before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
-			      input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
-			      after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
-			      output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
-			      recurse_func (nullptr),
-			      recursed_lookups (nullptr),
-			      nesting_level_left (nesting_level_left_),
-			      debug_depth (0)
-  {
-    recursed_lookups = hb_set_create ();
-  }
-  ~hb_collect_glyphs_context_t (void)
-  {
-    hb_set_destroy (recursed_lookups);
-  }
-
-  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
-};
-
-
-
-/* XXX Can we remove this? */
-
-template <typename set_t>
-struct hb_add_coverage_context_t :
-       hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
-{
-  inline const char *get_name (void) { return "GET_COVERAGE"; }
-  typedef const Coverage &return_t;
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
-  static return_t default_return_value (void) { return Null(Coverage); }
-  bool stop_sublookup_iteration (return_t r) const
-  {
-    r.add_coverage (set);
-    return false;
-  }
-
-  hb_add_coverage_context_t (set_t *set_) :
-			    set (set_),
-			    debug_depth (0) {}
-
-  set_t *set;
-  unsigned int debug_depth;
-};
-
-
-struct hb_ot_apply_context_t :
-       hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
-{
-  struct matcher_t
-  {
-    inline matcher_t (void) :
-	     lookup_props (0),
-	     ignore_zwnj (false),
-	     ignore_zwj (false),
-	     mask (-1),
-#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
-	     syllable arg1(0),
-#undef arg1
-	     match_func (nullptr),
-	     match_data (nullptr) {};
-
-    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
-
-    inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
-    inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
-    inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
-    inline void set_mask (hb_mask_t mask_) { mask = mask_; }
-    inline void set_syllable (uint8_t syllable_)  { syllable = syllable_; }
-    inline void set_match_func (match_func_t match_func_,
-				const void *match_data_)
-    { match_func = match_func_; match_data = match_data_; }
-
-    enum may_match_t {
-      MATCH_NO,
-      MATCH_YES,
-      MATCH_MAYBE
-    };
-
-    inline may_match_t may_match (const hb_glyph_info_t &info,
-				  const HBUINT16          *glyph_data) const
-    {
-      if (!(info.mask & mask) ||
-	  (syllable && syllable != info.syllable ()))
-	return MATCH_NO;
-
-      if (match_func)
-        return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
-
-      return MATCH_MAYBE;
-    }
-
-    enum may_skip_t {
-      SKIP_NO,
-      SKIP_YES,
-      SKIP_MAYBE
-    };
-
-    inline may_skip_t
-    may_skip (const hb_ot_apply_context_t *c,
-	      const hb_glyph_info_t    &info) const
-    {
-      if (!c->check_glyph_property (&info, lookup_props))
-	return SKIP_YES;
-
-      if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) &&
-		    (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
-		    (ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
-	return SKIP_MAYBE;
-
-      return SKIP_NO;
-    }
-
-    protected:
-    unsigned int lookup_props;
-    bool ignore_zwnj;
-    bool ignore_zwj;
-    hb_mask_t mask;
-    uint8_t syllable;
-    match_func_t match_func;
-    const void *match_data;
-  };
-
-  struct skipping_iterator_t
-  {
-    inline void init (hb_ot_apply_context_t *c_, bool context_match = false)
-    {
-      c = c_;
-      match_glyph_data = nullptr;
-      matcher.set_match_func (nullptr, nullptr);
-      matcher.set_lookup_props (c->lookup_props);
-      /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
-      matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
-      /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
-      matcher.set_ignore_zwj  (c->table_index == 1 || (context_match || c->auto_zwj));
-      matcher.set_mask (context_match ? -1 : c->lookup_mask);
-    }
-    inline void set_lookup_props (unsigned int lookup_props)
-    {
-      matcher.set_lookup_props (lookup_props);
-    }
-    inline void set_match_func (matcher_t::match_func_t match_func_,
-				const void *match_data_,
-				const HBUINT16 glyph_data[])
-    {
-      matcher.set_match_func (match_func_, match_data_);
-      match_glyph_data = glyph_data;
-    }
-
-    inline void reset (unsigned int start_index_,
-		       unsigned int num_items_)
-    {
-      idx = start_index_;
-      num_items = num_items_;
-      end = c->buffer->len;
-      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
-    }
-
-    inline void reject (void) { num_items++; match_glyph_data--; }
-
-    inline matcher_t::may_skip_t
-    may_skip (const hb_glyph_info_t    &info) const
-    {
-      return matcher.may_skip (c, info);
-    }
-
-    inline bool next (void)
-    {
-      assert (num_items > 0);
-      while (idx + num_items < end)
-      {
-	idx++;
-	const hb_glyph_info_t &info = c->buffer->info[idx];
-
-	matcher_t::may_skip_t skip = matcher.may_skip (c, info);
-	if (unlikely (skip == matcher_t::SKIP_YES))
-	  continue;
-
-	matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
-	if (match == matcher_t::MATCH_YES ||
-	    (match == matcher_t::MATCH_MAYBE &&
-	     skip == matcher_t::SKIP_NO))
-	{
-	  num_items--;
-	  match_glyph_data++;
-	  return true;
-	}
-
-	if (skip == matcher_t::SKIP_NO)
-	  return false;
-      }
-      return false;
-    }
-    inline bool prev (void)
-    {
-      assert (num_items > 0);
-      while (idx >= num_items)
-      {
-	idx--;
-	const hb_glyph_info_t &info = c->buffer->out_info[idx];
-
-	matcher_t::may_skip_t skip = matcher.may_skip (c, info);
-	if (unlikely (skip == matcher_t::SKIP_YES))
-	  continue;
-
-	matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
-	if (match == matcher_t::MATCH_YES ||
-	    (match == matcher_t::MATCH_MAYBE &&
-	     skip == matcher_t::SKIP_NO))
-	{
-	  num_items--;
-	  match_glyph_data++;
-	  return true;
-	}
-
-	if (skip == matcher_t::SKIP_NO)
-	  return false;
-      }
-      return false;
-    }
-
-    unsigned int idx;
-    protected:
-    hb_ot_apply_context_t *c;
-    matcher_t matcher;
-    const HBUINT16 *match_glyph_data;
-
-    unsigned int num_items;
-    unsigned int end;
-  };
-
-
-  inline const char *get_name (void) { return "APPLY"; }
-  typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.apply (this); }
-  static return_t default_return_value (void) { return false; }
-  bool stop_sublookup_iteration (return_t r) const { return r; }
-  return_t recurse (unsigned int sub_lookup_index)
-  {
-    if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
-      return default_return_value ();
-
-    nesting_level_left--;
-    bool ret = recurse_func (this, sub_lookup_index);
-    nesting_level_left++;
-    return ret;
-  }
-
-  skipping_iterator_t iter_input, iter_context;
-
-  hb_font_t *font;
-  hb_face_t *face;
-  hb_buffer_t *buffer;
-  recurse_func_t recurse_func;
-  const GDEF &gdef;
-  const VariationStore &var_store;
-
-  hb_direction_t direction;
-  hb_mask_t lookup_mask;
-  unsigned int table_index; /* GSUB/GPOS */
-  unsigned int lookup_index;
-  unsigned int lookup_props;
-  unsigned int nesting_level_left;
-  unsigned int debug_depth;
-
-  bool auto_zwnj;
-  bool auto_zwj;
-  bool has_glyph_classes;
-
-
-  hb_ot_apply_context_t (unsigned int table_index_,
-		      hb_font_t *font_,
-		      hb_buffer_t *buffer_) :
-			iter_input (), iter_context (),
-			font (font_), face (font->face), buffer (buffer_),
-			recurse_func (nullptr),
-			gdef (*hb_ot_layout_from_face (face)->gdef),
-			var_store (gdef.get_var_store ()),
-			direction (buffer_->props.direction),
-			lookup_mask (1),
-			table_index (table_index_),
-			lookup_index ((unsigned int) -1),
-			lookup_props (0),
-			nesting_level_left (HB_MAX_NESTING_LEVEL),
-			debug_depth (0),
-			auto_zwnj (true),
-			auto_zwj (true),
-			has_glyph_classes (gdef.has_glyph_classes ()) {}
-
-  inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
-  inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
-  inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; }
-  inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
-  inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
-  inline void set_lookup_props (unsigned int lookup_props_)
-  {
-    lookup_props = lookup_props_;
-    iter_input.init (this, false);
-    iter_context.init (this, true);
-  }
-
-  inline bool
-  match_properties_mark (hb_codepoint_t  glyph,
-			 unsigned int    glyph_props,
-			 unsigned int    match_props) const
-  {
-    /* If using mark filtering sets, the high short of
-     * match_props has the set index.
-     */
-    if (match_props & LookupFlag::UseMarkFilteringSet)
-      return gdef.mark_set_covers (match_props >> 16, glyph);
-
-    /* The second byte of match_props has the meaning
-     * "ignore marks of attachment type different than
-     * the attachment type specified."
-     */
-    if (match_props & LookupFlag::MarkAttachmentType)
-      return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
-
-    return true;
-  }
-
-  inline bool
-  check_glyph_property (const hb_glyph_info_t *info,
-			unsigned int  match_props) const
-  {
-    hb_codepoint_t glyph = info->codepoint;
-    unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
-
-    /* Not covered, if, for example, glyph class is ligature and
-     * match_props includes LookupFlags::IgnoreLigatures
-     */
-    if (glyph_props & match_props & LookupFlag::IgnoreFlags)
-      return false;
-
-    if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
-      return match_properties_mark (glyph, glyph_props, match_props);
-
-    return true;
-  }
-
-  inline void _set_glyph_props (hb_codepoint_t glyph_index,
-			  unsigned int class_guess = 0,
-			  bool ligature = false,
-			  bool component = false) const
-  {
-    unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
-			  HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
-    add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
-    if (ligature)
-    {
-      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
-      /* In the only place that the MULTIPLIED bit is used, Uniscribe
-       * seems to only care about the "last" transformation between
-       * Ligature and Multiple substitions.  Ie. if you ligate, expand,
-       * and ligate again, it forgives the multiplication and acts as
-       * if only ligation happened.  As such, clear MULTIPLIED bit.
-       */
-      add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
-    }
-    if (component)
-      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
-    if (likely (has_glyph_classes))
-      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
-    else if (class_guess)
-      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
-  }
-
-  inline void replace_glyph (hb_codepoint_t glyph_index) const
-  {
-    _set_glyph_props (glyph_index);
-    buffer->replace_glyph (glyph_index);
-  }
-  inline void replace_glyph_inplace (hb_codepoint_t glyph_index) const
-  {
-    _set_glyph_props (glyph_index);
-    buffer->cur().codepoint = glyph_index;
-  }
-  inline void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
-					   unsigned int class_guess) const
-  {
-    _set_glyph_props (glyph_index, class_guess, true);
-    buffer->replace_glyph (glyph_index);
-  }
-  inline void output_glyph_for_component (hb_codepoint_t glyph_index,
-					  unsigned int class_guess) const
-  {
-    _set_glyph_props (glyph_index, class_guess, false, true);
-    buffer->output_glyph (glyph_index);
-  }
-};
-
-
-
-typedef bool (*intersects_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
-typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
-typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
-
-struct ContextClosureFuncs
-{
-  intersects_func_t intersects;
-};
-struct ContextCollectGlyphsFuncs
-{
-  collect_glyphs_func_t collect;
-};
-struct ContextApplyFuncs
-{
-  match_func_t match;
-};
-
-
-static inline bool intersects_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
-{
-  return glyphs->has (value);
-}
-static inline bool intersects_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  return class_def.intersects_class (glyphs, value);
-}
-static inline bool intersects_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
-  return (data+coverage).intersects (glyphs);
-}
-
-static inline bool intersects_array (hb_closure_context_t *c,
-				     unsigned int count,
-				     const HBUINT16 values[],
-				     intersects_func_t intersects_func,
-				     const void *intersects_data)
-{
-  for (unsigned int i = 0; i < count; i++)
-    if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
-      return false;
-  return true;
-}
-
-
-static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
-{
-  glyphs->add (value);
-}
-static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  class_def.add_class (glyphs, value);
-}
-static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
-  (data+coverage).add_coverage (glyphs);
-}
-static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
-				  hb_set_t *glyphs,
-				  unsigned int count,
-				  const HBUINT16 values[],
-				  collect_glyphs_func_t collect_func,
-				  const void *collect_data)
-{
-  for (unsigned int i = 0; i < count; i++)
-    collect_func (glyphs, values[i], collect_data);
-}
-
-
-static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
-{
-  return glyph_id == value;
-}
-static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
-{
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  return class_def.get_class (glyph_id) == value;
-}
-static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
-{
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
-  return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
-}
-
-static inline bool would_match_input (hb_would_apply_context_t *c,
-				      unsigned int count, /* Including the first glyph (not matched) */
-				      const HBUINT16 input[], /* Array of input values--start with second glyph */
-				      match_func_t match_func,
-				      const void *match_data)
-{
-  if (count != c->len)
-    return false;
-
-  for (unsigned int i = 1; i < count; i++)
-    if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
-      return false;
-
-  return true;
-}
-static inline bool match_input (hb_ot_apply_context_t *c,
-				unsigned int count, /* Including the first glyph (not matched) */
-				const HBUINT16 input[], /* Array of input values--start with second glyph */
-				match_func_t match_func,
-				const void *match_data,
-				unsigned int *end_offset,
-				unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
-				bool *p_is_mark_ligature = nullptr,
-				unsigned int *p_total_component_count = nullptr)
-{
-  TRACE_APPLY (nullptr);
-
-  if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
-
-  hb_buffer_t *buffer = c->buffer;
-
-  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
-  skippy_iter.reset (buffer->idx, count - 1);
-  skippy_iter.set_match_func (match_func, match_data, input);
-
-  /*
-   * This is perhaps the trickiest part of OpenType...  Remarks:
-   *
-   * - If all components of the ligature were marks, we call this a mark ligature.
-   *
-   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
-   *   it as a ligature glyph.
-   *
-   * - Ligatures cannot be formed across glyphs attached to different components
-   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
-   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
-   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
-   *   There are a couple of exceptions to this:
-   *
-   *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
-   *     assuming that the font designer knows what they are doing (otherwise it can
-   *     break Indic stuff when a matra wants to ligate with a conjunct,
-   *
-   *   o If two marks want to ligate and they belong to different components of the
-   *     same ligature glyph, and said ligature glyph is to be ignored according to
-   *     mark-filtering rules, then allow.
-   *     https://github.com/harfbuzz/harfbuzz/issues/545
-   */
-
-  bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur());
-
-  unsigned int total_component_count = 0;
-  total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
-
-  unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-  unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
-
-  enum {
-    LIGBASE_NOT_CHECKED,
-    LIGBASE_MAY_NOT_SKIP,
-    LIGBASE_MAY_SKIP
-  } ligbase = LIGBASE_NOT_CHECKED;
-
-  match_positions[0] = buffer->idx;
-  for (unsigned int i = 1; i < count; i++)
-  {
-    if (!skippy_iter.next ()) return_trace (false);
-
-    match_positions[i] = skippy_iter.idx;
-
-    unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
-    unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
-
-    if (first_lig_id && first_lig_comp)
-    {
-      /* If first component was attached to a previous ligature component,
-       * all subsequent components should be attached to the same ligature
-       * component, otherwise we shouldn't ligate them... */
-      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
-      {
-        /* ...unless, we are attached to a base ligature and that base
-	 * ligature is ignorable. */
-        if (ligbase == LIGBASE_NOT_CHECKED)
-	{
-	  bool found = false;
-	  const hb_glyph_info_t *out = buffer->out_info;
-	  unsigned int j = buffer->out_len;
-	  while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
-	  {
-	    if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
-	    {
-	      j--;
-	      found = true;
-	      break;
-	    }
-	    j--;
-	  }
-
-	  if (found && skippy_iter.may_skip (out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES)
-	    ligbase = LIGBASE_MAY_SKIP;
-	  else
-	    ligbase = LIGBASE_MAY_NOT_SKIP;
-	}
-
-        if (ligbase == LIGBASE_MAY_NOT_SKIP)
-	  return_trace (false);
-      }
-    }
-    else
-    {
-      /* If first component was NOT attached to a previous ligature component,
-       * all subsequent components should also NOT be attached to any ligature
-       * component, unless they are attached to the first component itself! */
-      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
-	return_trace (false);
-    }
-
-    is_mark_ligature = is_mark_ligature && _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]);
-    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
-  }
-
-  *end_offset = skippy_iter.idx - buffer->idx + 1;
-
-  if (p_is_mark_ligature)
-    *p_is_mark_ligature = is_mark_ligature;
-
-  if (p_total_component_count)
-    *p_total_component_count = total_component_count;
-
-  return_trace (true);
-}
-static inline bool ligate_input (hb_ot_apply_context_t *c,
-				 unsigned int count, /* Including the first glyph */
-				 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
-				 unsigned int match_length,
-				 hb_codepoint_t lig_glyph,
-				 bool is_mark_ligature,
-				 unsigned int total_component_count)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_buffer_t *buffer = c->buffer;
-
-  buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
-
-  /*
-   * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave
-   *   the ligature to keep its old ligature id.  This will allow it to attach to
-   *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
-   *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a
-   *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
-   *   later, we don't want them to lose their ligature id/component, otherwise
-   *   GPOS will fail to correctly position the mark ligature on top of the
-   *   LAM,LAM,HEH ligature.  See:
-   *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
-   *
-   * - If a ligature is formed of components that some of which are also ligatures
-   *   themselves, and those ligature components had marks attached to *their*
-   *   components, we have to attach the marks to the new ligature component
-   *   positions!  Now *that*'s tricky!  And these marks may be following the
-   *   last component of the whole sequence, so we should loop forward looking
-   *   for them and update them.
-   *
-   *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
-   *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
-   *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
-   *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
-   *   the new ligature with a component value of 2.
-   *
-   *   This in fact happened to a font...  See:
-   *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
-   */
-
-  unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
-  unsigned int lig_id = is_mark_ligature ? 0 : _hb_allocate_lig_id (buffer);
-  unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-  unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
-  unsigned int components_so_far = last_num_components;
-
-  if (!is_mark_ligature)
-  {
-    _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
-    if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
-    {
-      _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
-    }
-  }
-  c->replace_glyph_with_ligature (lig_glyph, klass);
-
-  for (unsigned int i = 1; i < count; i++)
-  {
-    while (buffer->idx < match_positions[i] && !buffer->in_error)
-    {
-      if (!is_mark_ligature) {
-        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
-	if (this_comp == 0)
-	  this_comp = last_num_components;
-	unsigned int new_lig_comp = components_so_far - last_num_components +
-				    MIN (this_comp, last_num_components);
-	  _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
-      }
-      buffer->next_glyph ();
-    }
-
-    last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-    last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
-    components_so_far += last_num_components;
-
-    /* Skip the base glyph */
-    buffer->idx++;
-  }
-
-  if (!is_mark_ligature && last_lig_id) {
-    /* Re-adjust components for any marks following. */
-    for (unsigned int i = buffer->idx; i < buffer->len; i++) {
-      if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
-        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
-	if (!this_comp)
-	  break;
-	unsigned int new_lig_comp = components_so_far - last_num_components +
-				    MIN (this_comp, last_num_components);
-	_hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
-      } else
-	break;
-    }
-  }
-  return_trace (true);
-}
-
-static inline bool match_backtrack (hb_ot_apply_context_t *c,
-				    unsigned int count,
-				    const HBUINT16 backtrack[],
-				    match_func_t match_func,
-				    const void *match_data,
-				    unsigned int *match_start)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
-  skippy_iter.reset (c->buffer->backtrack_len (), count);
-  skippy_iter.set_match_func (match_func, match_data, backtrack);
-
-  for (unsigned int i = 0; i < count; i++)
-    if (!skippy_iter.prev ())
-      return_trace (false);
-
-  *match_start = skippy_iter.idx;
-
-  return_trace (true);
-}
-
-static inline bool match_lookahead (hb_ot_apply_context_t *c,
-				    unsigned int count,
-				    const HBUINT16 lookahead[],
-				    match_func_t match_func,
-				    const void *match_data,
-				    unsigned int offset,
-				    unsigned int *end_index)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
-  skippy_iter.reset (c->buffer->idx + offset - 1, count);
-  skippy_iter.set_match_func (match_func, match_data, lookahead);
-
-  for (unsigned int i = 0; i < count; i++)
-    if (!skippy_iter.next ())
-      return_trace (false);
-
-  *end_index = skippy_iter.idx + 1;
-
-  return_trace (true);
-}
-
-
-
-struct LookupRecord
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  HBUINT16	sequenceIndex;		/* Index into current glyph
-					 * sequence--first glyph = 0 */
-  HBUINT16	lookupListIndex;	/* Lookup to apply to that
-					 * position--zero--based */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-
-template <typename context_t>
-static inline void recurse_lookups (context_t *c,
-				    unsigned int lookupCount,
-				    const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
-{
-  for (unsigned int i = 0; i < lookupCount; i++)
-    c->recurse (lookupRecord[i].lookupListIndex);
-}
-
-static inline bool apply_lookup (hb_ot_apply_context_t *c,
-				 unsigned int count, /* Including the first glyph */
-				 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
-				 unsigned int lookupCount,
-				 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
-				 unsigned int match_length)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_buffer_t *buffer = c->buffer;
-  int end;
-
-  /* All positions are distance from beginning of *output* buffer.
-   * Adjust. */
-  {
-    unsigned int bl = buffer->backtrack_len ();
-    end = bl + match_length;
-
-    int delta = bl - buffer->idx;
-    /* Convert positions to new indexing. */
-    for (unsigned int j = 0; j < count; j++)
-      match_positions[j] += delta;
-  }
-
-  for (unsigned int i = 0; i < lookupCount && !buffer->in_error; i++)
-  {
-    unsigned int idx = lookupRecord[i].sequenceIndex;
-    if (idx >= count)
-      continue;
-
-    /* Don't recurse to ourself at same position.
-     * Note that this test is too naive, it doesn't catch longer loops. */
-    if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
-      continue;
-
-    if (unlikely (!buffer->move_to (match_positions[idx])))
-      break;
-
-    if (unlikely (buffer->max_ops <= 0))
-      break;
-
-    unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
-    if (!c->recurse (lookupRecord[i].lookupListIndex))
-      continue;
-
-    unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
-    int delta = new_len - orig_len;
-
-    if (!delta)
-        continue;
-
-    /* Recursed lookup changed buffer len.  Adjust.
-     *
-     * TODO:
-     *
-     * Right now, if buffer length increased by n, we assume n new glyphs
-     * were added right after the current position, and if buffer length
-     * was decreased by n, we assume n match positions after the current
-     * one where removed.  The former (buffer length increased) case is
-     * fine, but the decrease case can be improved in at least two ways,
-     * both of which are significant:
-     *
-     *   - If recursed-to lookup is MultipleSubst and buffer length
-     *     decreased, then it's current match position that was deleted,
-     *     NOT the one after it.
-     *
-     *   - If buffer length was decreased by n, it does not necessarily
-     *     mean that n match positions where removed, as there might
-     *     have been marks and default-ignorables in the sequence.  We
-     *     should instead drop match positions between current-position
-     *     and current-position + n instead.
-     *
-     * It should be possible to construct tests for both of these cases.
-     */
-
-    end += delta;
-    if (end <= int (match_positions[idx]))
-    {
-      /* End might end up being smaller than match_positions[idx] if the recursed
-       * lookup ended up removing many items, more than we have had matched.
-       * Just never rewind end back and get out of here.
-       * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
-      end = match_positions[idx];
-      /* There can't be any further changes. */
-      break;
-    }
-
-    unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
-
-    if (delta > 0)
-    {
-      if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
-	break;
-    }
-    else
-    {
-      /* NOTE: delta is negative. */
-      delta = MAX (delta, (int) next - (int) count);
-      next -= delta;
-    }
-
-    /* Shift! */
-    memmove (match_positions + next + delta, match_positions + next,
-	     (count - next) * sizeof (match_positions[0]));
-    next += delta;
-    count += delta;
-
-    /* Fill in new entries. */
-    for (unsigned int j = idx + 1; j < next; j++)
-      match_positions[j] = match_positions[j - 1] + 1;
-
-    /* And fixup the rest. */
-    for (; next < count; next++)
-      match_positions[next] += delta;
-  }
-
-  buffer->move_to (end);
-
-  return_trace (true);
-}
-
-
-
-/* Contextual lookups */
-
-struct ContextClosureLookupContext
-{
-  ContextClosureFuncs funcs;
-  const void *intersects_data;
-};
-
-struct ContextCollectGlyphsLookupContext
-{
-  ContextCollectGlyphsFuncs funcs;
-  const void *collect_data;
-};
-
-struct ContextApplyLookupContext
-{
-  ContextApplyFuncs funcs;
-  const void *match_data;
-};
-
-static inline void context_closure_lookup (hb_closure_context_t *c,
-					   unsigned int inputCount, /* Including the first glyph (not matched) */
-					   const HBUINT16 input[], /* Array of input values--start with second glyph */
-					   unsigned int lookupCount,
-					   const LookupRecord lookupRecord[],
-					   ContextClosureLookupContext &lookup_context)
-{
-  if (intersects_array (c,
-			inputCount ? inputCount - 1 : 0, input,
-			lookup_context.funcs.intersects, lookup_context.intersects_data))
-    recurse_lookups (c,
-		     lookupCount, lookupRecord);
-}
-
-static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
-						  unsigned int inputCount, /* Including the first glyph (not matched) */
-						  const HBUINT16 input[], /* Array of input values--start with second glyph */
-						  unsigned int lookupCount,
-						  const LookupRecord lookupRecord[],
-						  ContextCollectGlyphsLookupContext &lookup_context)
-{
-  collect_array (c, c->input,
-		 inputCount ? inputCount - 1 : 0, input,
-		 lookup_context.funcs.collect, lookup_context.collect_data);
-  recurse_lookups (c,
-		   lookupCount, lookupRecord);
-}
-
-static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
-					       unsigned int inputCount, /* Including the first glyph (not matched) */
-					       const HBUINT16 input[], /* Array of input values--start with second glyph */
-					       unsigned int lookupCount HB_UNUSED,
-					       const LookupRecord lookupRecord[] HB_UNUSED,
-					       ContextApplyLookupContext &lookup_context)
-{
-  return would_match_input (c,
-			    inputCount, input,
-			    lookup_context.funcs.match, lookup_context.match_data);
-}
-static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
-					 unsigned int inputCount, /* Including the first glyph (not matched) */
-					 const HBUINT16 input[], /* Array of input values--start with second glyph */
-					 unsigned int lookupCount,
-					 const LookupRecord lookupRecord[],
-					 ContextApplyLookupContext &lookup_context)
-{
-  unsigned int match_length = 0;
-  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
-  return match_input (c,
-		      inputCount, input,
-		      lookup_context.funcs.match, lookup_context.match_data,
-		      &match_length, match_positions)
-      && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length),
-	  apply_lookup (c,
-		       inputCount, match_positions,
-		       lookupCount, lookupRecord,
-		       match_length));
-}
-
-struct Rule
-{
-  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    context_closure_lookup (c,
-			    inputCount, inputZ,
-			    lookupCount, lookupRecord,
-			    lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    context_collect_glyphs_lookup (c,
-				   inputCount, inputZ,
-				   lookupCount, lookupRecord,
-				   lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    return_trace (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    return_trace (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
-  }
-
-  public:
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (inputCount.sanitize (c) &&
-		  lookupCount.sanitize (c) &&
-		  c->check_range (inputZ,
-				  inputZ[0].static_size * inputCount +
-				  LookupRecord::static_size * lookupCount));
-  }
-
-  protected:
-  HBUINT16	inputCount;		/* Total number of glyphs in input
-					 * glyph sequence--includes the first
-					 * glyph */
-  HBUINT16	lookupCount;		/* Number of LookupRecords */
-  HBUINT16	inputZ[VAR];		/* Array of match inputs--start with
-					 * second glyph */
-/*LookupRecord	lookupRecordX[VAR];*/	/* Array of LookupRecords--in
-					 * design order */
-  public:
-  DEFINE_SIZE_ARRAY (4, inputZ);
-};
-
-struct RuleSet
-{
-  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).closure (c, lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-    {
-      if ((this+rule[i]).would_apply (c, lookup_context))
-        return_trace (true);
-    }
-    return_trace (false);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-    {
-      if ((this+rule[i]).apply (c, lookup_context))
-        return_trace (true);
-    }
-    return_trace (false);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rule.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<Rule>
-		rule;			/* Array of Rule tables
-					 * ordered by preference */
-  public:
-  DEFINE_SIZE_ARRAY (2, rule);
-};
-
-
-struct ContextFormat1
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-
-    const Coverage &cov = (this+coverage);
-
-    struct ContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
-      nullptr
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (cov.intersects_coverage (c->glyphs, i)) {
-	const RuleSet &rule_set = this+ruleSet[i];
-	rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    struct ContextCollectGlyphsLookupContext lookup_context = {
-      {collect_glyph},
-      nullptr
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      nullptr
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED))
-      return_trace (false);
-
-    const RuleSet &rule_set = this+ruleSet[index];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      nullptr
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of table */
-  OffsetArrayOf<RuleSet>
-		ruleSet;		/* Array of RuleSet tables
-					 * ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_ARRAY (6, ruleSet);
-};
-
-
-struct ContextFormat2
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    if (!(this+coverage).intersects (c->glyphs))
-      return;
-
-    const ClassDef &class_def = this+classDef;
-
-    struct ContextClosureLookupContext lookup_context = {
-      {intersects_class},
-      &class_def
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (class_def.intersects_class (c->glyphs, i)) {
-	const RuleSet &rule_set = this+ruleSet[i];
-	rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    const ClassDef &class_def = this+classDef;
-    struct ContextCollectGlyphsLookupContext lookup_context = {
-      {collect_class},
-      &class_def
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const ClassDef &class_def = this+classDef;
-    unsigned int index = class_def.get_class (c->glyphs[0]);
-    const RuleSet &rule_set = this+ruleSet[index];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_class},
-      &class_def
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const ClassDef &class_def = this+classDef;
-    index = class_def.get_class (c->buffer->cur().codepoint);
-    const RuleSet &rule_set = this+ruleSet[index];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_class},
-      &class_def
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 2 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of table */
-  OffsetTo<ClassDef>
-		classDef;		/* Offset to glyph ClassDef table--from
-					 * beginning of table */
-  OffsetArrayOf<RuleSet>
-		ruleSet;		/* Array of RuleSet tables
-					 * ordered by class */
-  public:
-  DEFINE_SIZE_ARRAY (8, ruleSet);
-};
-
-
-struct ContextFormat3
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    if (!(this+coverageZ[0]).intersects (c->glyphs))
-      return;
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextClosureLookupContext lookup_context = {
-      {intersects_coverage},
-      this
-    };
-    context_closure_lookup (c,
-			    glyphCount, (const HBUINT16 *) (coverageZ + 1),
-			    lookupCount, lookupRecord,
-			    lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverageZ[0]).add_coverage (c->input);
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextCollectGlyphsLookupContext lookup_context = {
-      {collect_coverage},
-      this
-    };
-
-    context_collect_glyphs_lookup (c,
-				   glyphCount, (const HBUINT16 *) (coverageZ + 1),
-				   lookupCount, lookupRecord,
-				   lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      this
-    };
-    return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverageZ[0];
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      this
-    };
-    return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!c->check_struct (this)) return_trace (false);
-    unsigned int count = glyphCount;
-    if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
-    if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (!coverageZ[i].sanitize (c, this)) return_trace (false);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
-    return_trace (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 3 */
-  HBUINT16	glyphCount;		/* Number of glyphs in the input glyph
-					 * sequence */
-  HBUINT16	lookupCount;		/* Number of LookupRecords */
-  OffsetTo<Coverage>
-		coverageZ[VAR];		/* Array of offsets to Coverage
-					 * table in glyph sequence order */
-/*LookupRecord	lookupRecordX[VAR];*/	/* Array of LookupRecords--in
-					 * design order */
-  public:
-  DEFINE_SIZE_ARRAY (6, coverageZ);
-};
-
-struct Context
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    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));
-    case 2: return_trace (c->dispatch (u.format2));
-    case 3: return_trace (c->dispatch (u.format3));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  ContextFormat1	format1;
-  ContextFormat2	format2;
-  ContextFormat3	format3;
-  } u;
-};
-
-
-/* Chaining Contextual lookups */
-
-struct ChainContextClosureLookupContext
-{
-  ContextClosureFuncs funcs;
-  const void *intersects_data[3];
-};
-
-struct ChainContextCollectGlyphsLookupContext
-{
-  ContextCollectGlyphsFuncs funcs;
-  const void *collect_data[3];
-};
-
-struct ChainContextApplyLookupContext
-{
-  ContextApplyFuncs funcs;
-  const void *match_data[3];
-};
-
-static inline void chain_context_closure_lookup (hb_closure_context_t *c,
-						 unsigned int backtrackCount,
-						 const HBUINT16 backtrack[],
-						 unsigned int inputCount, /* Including the first glyph (not matched) */
-						 const HBUINT16 input[], /* Array of input values--start with second glyph */
-						 unsigned int lookaheadCount,
-						 const HBUINT16 lookahead[],
-						 unsigned int lookupCount,
-						 const LookupRecord lookupRecord[],
-						 ChainContextClosureLookupContext &lookup_context)
-{
-  if (intersects_array (c,
-			backtrackCount, backtrack,
-			lookup_context.funcs.intersects, lookup_context.intersects_data[0])
-   && intersects_array (c,
-			inputCount ? inputCount - 1 : 0, input,
-			lookup_context.funcs.intersects, lookup_context.intersects_data[1])
-   && intersects_array (c,
-		       lookaheadCount, lookahead,
-		       lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
-    recurse_lookups (c,
-		     lookupCount, lookupRecord);
-}
-
-static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
-						        unsigned int backtrackCount,
-						        const HBUINT16 backtrack[],
-						        unsigned int inputCount, /* Including the first glyph (not matched) */
-						        const HBUINT16 input[], /* Array of input values--start with second glyph */
-						        unsigned int lookaheadCount,
-						        const HBUINT16 lookahead[],
-						        unsigned int lookupCount,
-						        const LookupRecord lookupRecord[],
-						        ChainContextCollectGlyphsLookupContext &lookup_context)
-{
-  collect_array (c, c->before,
-		 backtrackCount, backtrack,
-		 lookup_context.funcs.collect, lookup_context.collect_data[0]);
-  collect_array (c, c->input,
-		 inputCount ? inputCount - 1 : 0, input,
-		 lookup_context.funcs.collect, lookup_context.collect_data[1]);
-  collect_array (c, c->after,
-		 lookaheadCount, lookahead,
-		 lookup_context.funcs.collect, lookup_context.collect_data[2]);
-  recurse_lookups (c,
-		   lookupCount, lookupRecord);
-}
-
-static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
-						     unsigned int backtrackCount,
-						     const HBUINT16 backtrack[] HB_UNUSED,
-						     unsigned int inputCount, /* Including the first glyph (not matched) */
-						     const HBUINT16 input[], /* Array of input values--start with second glyph */
-						     unsigned int lookaheadCount,
-						     const HBUINT16 lookahead[] HB_UNUSED,
-						     unsigned int lookupCount HB_UNUSED,
-						     const LookupRecord lookupRecord[] HB_UNUSED,
-						     ChainContextApplyLookupContext &lookup_context)
-{
-  return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
-      && would_match_input (c,
-			    inputCount, input,
-			    lookup_context.funcs.match, lookup_context.match_data[1]);
-}
-
-static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
-					       unsigned int backtrackCount,
-					       const HBUINT16 backtrack[],
-					       unsigned int inputCount, /* Including the first glyph (not matched) */
-					       const HBUINT16 input[], /* Array of input values--start with second glyph */
-					       unsigned int lookaheadCount,
-					       const HBUINT16 lookahead[],
-					       unsigned int lookupCount,
-					       const LookupRecord lookupRecord[],
-					       ChainContextApplyLookupContext &lookup_context)
-{
-  unsigned int start_index = 0, match_length = 0, end_index = 0;
-  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
-  return match_input (c,
-		      inputCount, input,
-		      lookup_context.funcs.match, lookup_context.match_data[1],
-		      &match_length, match_positions)
-      && match_backtrack (c,
-			  backtrackCount, backtrack,
-			  lookup_context.funcs.match, lookup_context.match_data[0],
-			  &start_index)
-      && match_lookahead (c,
-			  lookaheadCount, lookahead,
-			  lookup_context.funcs.match, lookup_context.match_data[2],
-			  match_length, &end_index)
-      && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
-          apply_lookup (c,
-		       inputCount, match_positions,
-		       lookupCount, lookupRecord,
-		       match_length));
-}
-
-struct ChainRule
-{
-  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    chain_context_closure_lookup (c,
-				  backtrack.len, backtrack.array,
-				  input.len, input.array,
-				  lookahead.len, lookahead.array,
-				  lookup.len, lookup.array,
-				  lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    chain_context_collect_glyphs_lookup (c,
-					 backtrack.len, backtrack.array,
-					 input.len, input.array,
-					 lookahead.len, lookahead.array,
-					 lookup.len, lookup.array,
-					 lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (chain_context_would_apply_lookup (c,
-						    backtrack.len, backtrack.array,
-						    input.len, input.array,
-						    lookahead.len, lookahead.array, lookup.len,
-						    lookup.array, lookup_context));
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (chain_context_apply_lookup (c,
-					      backtrack.len, backtrack.array,
-					      input.len, input.array,
-					      lookahead.len, lookahead.array, lookup.len,
-					      lookup.array, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!backtrack.sanitize (c)) return_trace (false);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    if (!input.sanitize (c)) return_trace (false);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    if (!lookahead.sanitize (c)) return_trace (false);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (lookup.sanitize (c));
-  }
-
-  protected:
-  ArrayOf<HBUINT16>
-		backtrack;		/* Array of backtracking values
-					 * (to be matched before the input
-					 * sequence) */
-  HeadlessArrayOf<HBUINT16>
-		inputX;			/* Array of input values (start with
-					 * second glyph) */
-  ArrayOf<HBUINT16>
-		lookaheadX;		/* Array of lookahead values's (to be
-					 * matched after the input sequence) */
-  ArrayOf<LookupRecord>
-		lookupX;		/* Array of LookupRecords--in
-					 * design order) */
-  public:
-  DEFINE_SIZE_MIN (8);
-};
-
-struct ChainRuleSet
-{
-  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).closure (c, lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      if ((this+rule[i]).would_apply (c, lookup_context))
-        return_trace (true);
-
-    return_trace (false);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      if ((this+rule[i]).apply (c, lookup_context))
-        return_trace (true);
-
-    return_trace (false);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rule.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<ChainRule>
-		rule;			/* Array of ChainRule tables
-					 * ordered by preference */
-  public:
-  DEFINE_SIZE_ARRAY (2, rule);
-};
-
-struct ChainContextFormat1
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    const Coverage &cov = (this+coverage);
-
-    struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (cov.intersects_coverage (c->glyphs, i)) {
-	const ChainRuleSet &rule_set = this+ruleSet[i];
-	rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    struct ChainContextCollectGlyphsLookupContext lookup_context = {
-      {collect_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const ChainRuleSet &rule_set = this+ruleSet[index];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of table */
-  OffsetArrayOf<ChainRuleSet>
-		ruleSet;		/* Array of ChainRuleSet tables
-					 * ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_ARRAY (6, ruleSet);
-};
-
-struct ChainContextFormat2
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    if (!(this+coverage).intersects (c->glyphs))
-      return;
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (input_class_def.intersects_class (c->glyphs, i)) {
-	const ChainRuleSet &rule_set = this+ruleSet[i];
-	rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    struct ChainContextCollectGlyphsLookupContext lookup_context = {
-      {collect_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    unsigned int index = input_class_def.get_class (c->glyphs[0]);
-    const ChainRuleSet &rule_set = this+ruleSet[index];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    index = input_class_def.get_class (c->buffer->cur().codepoint);
-    const ChainRuleSet &rule_set = this+ruleSet[index];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) &&
-		  backtrackClassDef.sanitize (c, this) &&
-		  inputClassDef.sanitize (c, this) &&
-		  lookaheadClassDef.sanitize (c, this) &&
-		  ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 2 */
-  OffsetTo<Coverage>
-		coverage;		/* Offset to Coverage table--from
-					 * beginning of table */
-  OffsetTo<ClassDef>
-		backtrackClassDef;	/* Offset to glyph ClassDef table
-					 * containing backtrack sequence
-					 * data--from beginning of table */
-  OffsetTo<ClassDef>
-		inputClassDef;		/* Offset to glyph ClassDef
-					 * table containing input sequence
-					 * data--from beginning of table */
-  OffsetTo<ClassDef>
-		lookaheadClassDef;	/* Offset to glyph ClassDef table
-					 * containing lookahead sequence
-					 * data--from beginning of table */
-  OffsetArrayOf<ChainRuleSet>
-		ruleSet;		/* Array of ChainRuleSet tables
-					 * ordered by class */
-  public:
-  DEFINE_SIZE_ARRAY (12, ruleSet);
-};
-
-struct ChainContextFormat3
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-
-    if (!(this+input[0]).intersects (c->glyphs))
-      return;
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_coverage},
-      {this, this, this}
-    };
-    chain_context_closure_lookup (c,
-				  backtrack.len, (const HBUINT16 *) backtrack.array,
-				  input.len, (const HBUINT16 *) input.array + 1,
-				  lookahead.len, (const HBUINT16 *) lookahead.array,
-				  lookup.len, lookup.array,
-				  lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-
-    (this+input[0]).add_coverage (c->input);
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextCollectGlyphsLookupContext lookup_context = {
-      {collect_coverage},
-      {this, this, this}
-    };
-    chain_context_collect_glyphs_lookup (c,
-					 backtrack.len, (const HBUINT16 *) backtrack.array,
-					 input.len, (const HBUINT16 *) input.array + 1,
-					 lookahead.len, (const HBUINT16 *) lookahead.array,
-					 lookup.len, lookup.array,
-					 lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      {this, this, this}
-    };
-    return_trace (chain_context_would_apply_lookup (c,
-						    backtrack.len, (const HBUINT16 *) backtrack.array,
-						    input.len, (const HBUINT16 *) input.array + 1,
-						    lookahead.len, (const HBUINT16 *) lookahead.array,
-						    lookup.len, lookup.array, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    return this+input[0];
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-
-    unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      {this, this, this}
-    };
-    return_trace (chain_context_apply_lookup (c,
-					      backtrack.len, (const HBUINT16 *) backtrack.array,
-					      input.len, (const HBUINT16 *) input.array + 1,
-					      lookahead.len, (const HBUINT16 *) lookahead.array,
-					      lookup.len, lookup.array, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!backtrack.sanitize (c, this)) return_trace (false);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    if (!input.sanitize (c, this)) return_trace (false);
-    if (!input.len) return_trace (false); /* To be consistent with Context. */
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    if (!lookahead.sanitize (c, this)) return_trace (false);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (lookup.sanitize (c));
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier--format = 3 */
-  OffsetArrayOf<Coverage>
-		backtrack;		/* Array of coverage tables
-					 * in backtracking sequence, in  glyph
-					 * sequence order */
-  OffsetArrayOf<Coverage>
-		inputX		;	/* Array of coverage
-					 * tables in input sequence, in glyph
-					 * sequence order */
-  OffsetArrayOf<Coverage>
-		lookaheadX;		/* Array of coverage tables
-					 * in lookahead sequence, in glyph
-					 * sequence order */
-  ArrayOf<LookupRecord>
-		lookupX;		/* Array of LookupRecords--in
-					 * design order) */
-  public:
-  DEFINE_SIZE_MIN (10);
-};
-
-struct ChainContext
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    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));
-    case 2: return_trace (c->dispatch (u.format2));
-    case 3: return_trace (c->dispatch (u.format3));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;	/* Format identifier */
-  ChainContextFormat1	format1;
-  ChainContextFormat2	format2;
-  ChainContextFormat3	format3;
-  } u;
-};
-
-
-template <typename T>
-struct ExtensionFormat1
-{
-  inline unsigned int get_type (void) const { return extensionLookupType; }
-
-  template <typename X>
-  inline const X& get_subtable (void) const
-  {
-    unsigned int offset = extensionOffset;
-    if (unlikely (!offset)) return Null(typename T::LookupSubTable);
-    return StructAtOffset<typename T::LookupSubTable> (this, offset);
-  }
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, format);
-    if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
-    return_trace (get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()));
-  }
-
-  /* This is called from may_dispatch() above with hb_sanitize_context_t. */
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  extensionOffset != 0 &&
-		  extensionLookupType != T::LookupSubTable::Extension);
-  }
-
-  protected:
-  HBUINT16	format;			/* Format identifier. Set to 1. */
-  HBUINT16	extensionLookupType;	/* Lookup type of subtable referenced
-					 * by ExtensionOffset (i.e. the
-					 * extension subtable). */
-  HBUINT32	extensionOffset;	/* Offset to the extension subtable,
-					 * of lookup type subtable. */
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-template <typename T>
-struct Extension
-{
-  inline unsigned int get_type (void) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_type ();
-    default:return 0;
-    }
-  }
-  template <typename X>
-  inline const X& get_subtable (void) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.template get_subtable<typename T::LookupSubTable> ();
-    default:return Null(typename T::LookupSubTable);
-    }
-  }
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-    switch (u.format) {
-    case 1: return_trace (u.format1.dispatch (c));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16		format;		/* Format identifier */
-  ExtensionFormat1<T>	format1;
-  } u;
-};
-
-
-/*
- * GSUB/GPOS Common
- */
-
-struct GSUBGPOS
-{
-  inline unsigned int get_script_count (void) const
-  { return (this+scriptList).len; }
-  inline const Tag& get_script_tag (unsigned int i) const
-  { return (this+scriptList).get_tag (i); }
-  inline unsigned int get_script_tags (unsigned int start_offset,
-				       unsigned int *script_count /* IN/OUT */,
-				       hb_tag_t     *script_tags /* OUT */) const
-  { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
-  inline const Script& get_script (unsigned int i) const
-  { return (this+scriptList)[i]; }
-  inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
-  { return (this+scriptList).find_index (tag, index); }
-
-  inline unsigned int get_feature_count (void) const
-  { return (this+featureList).len; }
-  inline hb_tag_t get_feature_tag (unsigned int i) const
-  { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
-  inline unsigned int get_feature_tags (unsigned int start_offset,
-					unsigned int *feature_count /* IN/OUT */,
-					hb_tag_t     *feature_tags /* OUT */) const
-  { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
-  inline const Feature& get_feature (unsigned int i) const
-  { return (this+featureList)[i]; }
-  inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
-  { return (this+featureList).find_index (tag, index); }
-
-  inline unsigned int get_lookup_count (void) const
-  { return (this+lookupList).len; }
-  inline const Lookup& get_lookup (unsigned int i) const
-  { return (this+lookupList)[i]; }
-
-  inline bool find_variations_index (const int *coords, unsigned int num_coords,
-				     unsigned int *index) const
-  { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
-	   .find_index (coords, num_coords, index); }
-  inline const Feature& get_feature_variation (unsigned int feature_index,
-					       unsigned int variations_index) const
-  {
-    if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
-	version.to_int () >= 0x00010001u)
-    {
-      const Feature *feature = (this+featureVars).find_substitute (variations_index,
-								   feature_index);
-      if (feature)
-        return *feature;
-    }
-    return get_feature (feature_index);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  scriptList.sanitize (c, this) &&
-		  featureList.sanitize (c, this) &&
-		  lookupList.sanitize (c, this) &&
-		  (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
-  }
-
-  protected:
-  FixedVersion<>version;	/* Version of the GSUB/GPOS table--initially set
-				 * to 0x00010000u */
-  OffsetTo<ScriptList>
-		scriptList;  	/* ScriptList table */
-  OffsetTo<FeatureList>
-		featureList; 	/* FeatureList table */
-  OffsetTo<LookupList>
-		lookupList; 	/* LookupList table */
-  LOffsetTo<FeatureVariations>
-		featureVars;	/* Offset to Feature Variations
-				   table--from beginning of table
-				 * (may be NULL).  Introduced
-				 * in version 0x00010001. */
-  public:
-  DEFINE_SIZE_MIN (10);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh
deleted file mode 100644
index adbaad64..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright © 2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_LAYOUT_JSTF_TABLE_HH
-#define HB_OT_LAYOUT_JSTF_TABLE_HH
-
-#include "hb-open-type-private.hh"
-#include "hb-ot-layout-gpos-table.hh"
-
-
-namespace OT {
-
-
-/*
- * JstfModList -- Justification Modification List Tables
- */
-
-typedef IndexArray JstfModList;
-
-
-/*
- * JstfMax -- Justification Maximum Table
- */
-
-typedef OffsetListOf<PosLookup> JstfMax;
-
-
-/*
- * JstfPriority -- Justification Priority Table
- */
-
-struct JstfPriority
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  shrinkageEnableGSUB.sanitize (c, this) &&
-		  shrinkageDisableGSUB.sanitize (c, this) &&
-		  shrinkageEnableGPOS.sanitize (c, this) &&
-		  shrinkageDisableGPOS.sanitize (c, this) &&
-		  shrinkageJstfMax.sanitize (c, this) &&
-		  extensionEnableGSUB.sanitize (c, this) &&
-		  extensionDisableGSUB.sanitize (c, this) &&
-		  extensionEnableGPOS.sanitize (c, this) &&
-		  extensionDisableGPOS.sanitize (c, this) &&
-		  extensionJstfMax.sanitize (c, this));
-  }
-
-  protected:
-  OffsetTo<JstfModList>
-		shrinkageEnableGSUB;	/* Offset to Shrinkage Enable GSUB
-					 * JstfModList table--from beginning of
-					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
-		shrinkageDisableGSUB;	/* Offset to Shrinkage Disable GSUB
-					 * JstfModList table--from beginning of
-					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
-		shrinkageEnableGPOS;	/* Offset to Shrinkage Enable GPOS
-					 * JstfModList table--from beginning of
-					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
-		shrinkageDisableGPOS;	/* Offset to Shrinkage Disable GPOS
-					 * JstfModList table--from beginning of
-					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfMax>
-		shrinkageJstfMax;	/* Offset to Shrinkage JstfMax table--
-					 * from beginning of JstfPriority table
-					 * --may be NULL */
-  OffsetTo<JstfModList>
-		extensionEnableGSUB;	/* Offset to Extension Enable GSUB
-					 * JstfModList table--from beginning of
-					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
-		extensionDisableGSUB;	/* Offset to Extension Disable GSUB
-					 * JstfModList table--from beginning of
-					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
-		extensionEnableGPOS;	/* Offset to Extension Enable GPOS
-					 * JstfModList table--from beginning of
-					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfModList>
-		extensionDisableGPOS;	/* Offset to Extension Disable GPOS
-					 * JstfModList table--from beginning of
-					 * JstfPriority table--may be NULL */
-  OffsetTo<JstfMax>
-		extensionJstfMax;	/* Offset to Extension JstfMax table--
-					 * from beginning of JstfPriority table
-					 * --may be NULL */
-
-  public:
-  DEFINE_SIZE_STATIC (20);
-};
-
-
-/*
- * JstfLangSys -- Justification Language System Table
- */
-
-struct JstfLangSys : OffsetListOf<JstfPriority>
-{
-  inline bool sanitize (hb_sanitize_context_t *c,
-			const Record<JstfLangSys>::sanitize_closure_t * = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (OffsetListOf<JstfPriority>::sanitize (c));
-  }
-};
-
-
-/*
- * ExtenderGlyphs -- Extender Glyph Table
- */
-
-typedef SortedArrayOf<GlyphID> ExtenderGlyphs;
-
-
-/*
- * JstfScript -- The Justification Table
- */
-
-struct JstfScript
-{
-  inline unsigned int get_lang_sys_count (void) const
-  { return langSys.len; }
-  inline const Tag& get_lang_sys_tag (unsigned int i) const
-  { return langSys.get_tag (i); }
-  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
-					 unsigned int *lang_sys_count /* IN/OUT */,
-					 hb_tag_t     *lang_sys_tags /* OUT */) const
-  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
-  inline const JstfLangSys& get_lang_sys (unsigned int i) const
-  {
-    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
-    return this+langSys[i].offset;
-  }
-  inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
-  { return langSys.find_index (tag, index); }
-
-  inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
-  inline const JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-			const Record<JstfScript>::sanitize_closure_t * = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (extenderGlyphs.sanitize (c, this) &&
-		  defaultLangSys.sanitize (c, this) &&
-		  langSys.sanitize (c, this));
-  }
-
-  protected:
-  OffsetTo<ExtenderGlyphs>
-		extenderGlyphs;	/* Offset to ExtenderGlyph table--from beginning
-				 * of JstfScript table-may be NULL */
-  OffsetTo<JstfLangSys>
-		defaultLangSys;	/* Offset to DefaultJstfLangSys table--from
-				 * beginning of JstfScript table--may be Null */
-  RecordArrayOf<JstfLangSys>
-		langSys;	/* Array of JstfLangSysRecords--listed
-				 * alphabetically by LangSysTag */
-  public:
-  DEFINE_SIZE_ARRAY (6, langSys);
-};
-
-
-/*
- * JSTF -- The Justification Table
- */
-
-struct JSTF
-{
-  static const hb_tag_t tableTag	= HB_OT_TAG_JSTF;
-
-  inline unsigned int get_script_count (void) const
-  { return scriptList.len; }
-  inline const Tag& get_script_tag (unsigned int i) const
-  { return scriptList.get_tag (i); }
-  inline unsigned int get_script_tags (unsigned int start_offset,
-				       unsigned int *script_count /* IN/OUT */,
-				       hb_tag_t     *script_tags /* OUT */) const
-  { return scriptList.get_tags (start_offset, script_count, script_tags); }
-  inline const JstfScript& get_script (unsigned int i) const
-  { return this+scriptList[i].offset; }
-  inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
-  { return scriptList.find_index (tag, index); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  scriptList.sanitize (c, this));
-  }
-
-  protected:
-  FixedVersion<>version;	/* Version of the JSTF table--initially set
-				 * to 0x00010000u */
-  RecordArrayOf<JstfScript>
-		scriptList;  	/* Array of JstfScripts--listed
-				 * alphabetically by ScriptTag */
-  public:
-  DEFINE_SIZE_ARRAY (6, scriptList);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_LAYOUT_JSTF_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
deleted file mode 100644
index 870ba73f..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2012,2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_LAYOUT_PRIVATE_HH
-#define HB_OT_LAYOUT_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
-#include "hb-set-digest-private.hh"
-#include "hb-open-type-private.hh"
-
-
-/* Private API corresponding to hb-ot-layout.h: */
-
-HB_INTERNAL hb_bool_t
-hb_ot_layout_table_find_feature (hb_face_t    *face,
-				 hb_tag_t      table_tag,
-				 hb_tag_t      feature_tag,
-				 unsigned int *feature_index);
-
-
-/*
- * GDEF
- */
-
-enum hb_ot_layout_glyph_props_flags_t
-{
-  /* The following three match LookupFlags::Ignore* numbers. */
-  HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH	= 0x02u,
-  HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE	= 0x04u,
-  HB_OT_LAYOUT_GLYPH_PROPS_MARK		= 0x08u,
-
-  /* The following are used internally; not derived from GDEF. */
-  HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED	= 0x10u,
-  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED	= 0x20u,
-  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED	= 0x40u,
-
-  HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
-					  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
-					  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
-};
-HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
-
-
-/*
- * GSUB/GPOS
- */
-
-HB_INTERNAL hb_bool_t
-hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
-					   unsigned int          lookup_index,
-					   const hb_codepoint_t *glyphs,
-					   unsigned int          glyphs_length,
-					   hb_bool_t             zero_context);
-
-
-/* Should be called before all the substitute_lookup's are done. */
-HB_INTERNAL void
-hb_ot_layout_substitute_start (hb_font_t    *font,
-			       hb_buffer_t  *buffer);
-
-
-struct hb_ot_layout_lookup_accelerator_t;
-
-namespace OT {
-  struct hb_ot_apply_context_t;
-  struct SubstLookup;
-}
-
-HB_INTERNAL void
-hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
-				const OT::SubstLookup &lookup,
-				const hb_ot_layout_lookup_accelerator_t &accel);
-
-
-/* Should be called before all the position_lookup's are done. */
-HB_INTERNAL void
-hb_ot_layout_position_start (hb_font_t    *font,
-			     hb_buffer_t  *buffer);
-
-/* Should be called after all the position_lookup's are done, to finish advances. */
-HB_INTERNAL void
-hb_ot_layout_position_finish_advances (hb_font_t    *font,
-				       hb_buffer_t  *buffer);
-
-/* Should be called after hb_ot_layout_position_finish_advances, to finish offsets. */
-HB_INTERNAL void
-hb_ot_layout_position_finish_offsets (hb_font_t    *font,
-				      hb_buffer_t  *buffer);
-
-
-
-/*
- * hb_ot_layout_t
- */
-
-namespace OT {
-  struct BASE;
-  struct COLR;
-  struct CPAL;
-  struct GDEF;
-  struct GSUB;
-  struct GPOS;
-  struct MATH;
-  struct fvar;
-  struct avar;
-}
-
-namespace AAT {
-  struct ankr;
-  struct kerx;
-  struct morx;
-  struct trak;
-}
-
-struct hb_ot_layout_lookup_accelerator_t
-{
-  template <typename TLookup>
-  inline void init (const TLookup &lookup)
-  {
-    digest.init ();
-    lookup.add_coverage (&digest);
-  }
-
-  inline void fini (void)
-  {
-  }
-
-  inline bool may_have (hb_codepoint_t g) const {
-    return digest.may_have (g);
-  }
-
-  private:
-  hb_set_digest_t digest;
-};
-
-struct hb_ot_layout_t
-{
-  hb_blob_t *gdef_blob;
-  hb_blob_t *gsub_blob;
-  hb_blob_t *gpos_blob;
-
-  const struct OT::GDEF *gdef;
-  const struct OT::GSUB *gsub;
-  const struct OT::GPOS *gpos;
-
-  /* TODO Move the following out of this struct. */
-  OT::hb_lazy_table_loader_t<struct OT::BASE> base;
-  OT::hb_lazy_table_loader_t<struct OT::COLR> colr;
-  OT::hb_lazy_table_loader_t<struct OT::CPAL> cpal;
-  OT::hb_lazy_table_loader_t<struct OT::MATH> math;
-  OT::hb_lazy_table_loader_t<struct OT::fvar> fvar;
-  OT::hb_lazy_table_loader_t<struct OT::avar> avar;
-  OT::hb_lazy_table_loader_t<struct AAT::ankr> ankr;
-  OT::hb_lazy_table_loader_t<struct AAT::kerx> kerx;
-  OT::hb_lazy_table_loader_t<struct AAT::morx> morx;
-  OT::hb_lazy_table_loader_t<struct AAT::trak> trak;
-
-  unsigned int gsub_lookup_count;
-  unsigned int gpos_lookup_count;
-
-  hb_ot_layout_lookup_accelerator_t *gsub_accels;
-  hb_ot_layout_lookup_accelerator_t *gpos_accels;
-};
-
-
-HB_INTERNAL hb_ot_layout_t *
-_hb_ot_layout_create (hb_face_t *face);
-
-HB_INTERNAL void
-_hb_ot_layout_destroy (hb_ot_layout_t *layout);
-
-
-#define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot)
-
-
-/*
- * Buffer var routines.
- */
-
-/* buffer var allocations, used during the entire shaping process */
-#define unicode_props()		var2.u16[0]
-
-/* buffer var allocations, used during the GSUB/GPOS processing */
-#define glyph_props()		var1.u16[0] /* GDEF glyph properties */
-#define lig_props()		var1.u8[2] /* GSUB/GPOS ligature tracking */
-#define syllable()		var1.u8[3] /* GSUB/GPOS shaping boundaries */
-
-
-/* Loop over syllables. Based on foreach_cluster(). */
-#define foreach_syllable(buffer, start, end) \
-  for (unsigned int \
-       _count = buffer->len, \
-       start = 0, end = _count ? _next_syllable (buffer, 0) : 0; \
-       start < _count; \
-       start = end, end = _next_syllable (buffer, start))
-
-static inline unsigned int
-_next_syllable (hb_buffer_t *buffer, unsigned int start)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  unsigned int syllable = info[start].syllable();
-  while (++start < count && syllable == info[start].syllable())
-    ;
-
-  return start;
-}
-
-
-/* unicode_props */
-
-/* Design:
- * unicode_props() is a two-byte number.  The low byte includes:
- * - General_Category: 5 bits.
- * - A bit each for:
- *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
- *   * Whether it's one of the three Mongolian Free Variation Selectors,
- *     CGJ, or other characters that are hidden but should not be ignored
- *     like most other Default_Ignorable()s do during matching.
- *   * One free bit right now.
- *
- * The high-byte has different meanings, switched by the Gen-Cat:
- * - For Mn,Mc,Me: the modified Combining_Class.
- * - For Cf: whether it's ZWJ, ZWNJ, or something else.
- * - For Ws: index of which space character this is, if space fallback
- *   is needed, ie. we don't set this by default, only if asked to.
- */
-
-enum hb_unicode_props_flags_t {
-  UPROPS_MASK_GEN_CAT	= 0x001Fu,
-  UPROPS_MASK_IGNORABLE	= 0x0020u,
-  UPROPS_MASK_HIDDEN	= 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3,
-                                    * or TAG characters */
-
-  /* If GEN_CAT=FORMAT, top byte masks: */
-  UPROPS_MASK_Cf_ZWJ	= 0x0100u,
-  UPROPS_MASK_Cf_ZWNJ	= 0x0200u
-};
-HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
-
-static inline void
-_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
-{
-  hb_unicode_funcs_t *unicode = buffer->unicode;
-  unsigned int u = info->codepoint;
-  unsigned int gen_cat = (unsigned int) unicode->general_category (u);
-  unsigned int props = gen_cat;
-
-  if (u >= 0x80)
-  {
-    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII;
-    if (unlikely (unicode->is_default_ignorable (u)))
-    {
-      buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
-      props |=  UPROPS_MASK_IGNORABLE;
-      if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ;
-      else if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
-      /* Mongolian Free Variation Selectors need to be remembered
-       * because although we need to hide them like default-ignorables,
-       * they need to non-ignorable during shaping.  This is similar to
-       * what we do for joiners in Indic-like shapers, but since the
-       * FVSes are GC=Mn, we have use a separate bit to remember them.
-       * Fixes:
-       * https://github.com/harfbuzz/harfbuzz/issues/234 */
-      else if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN;
-      /* TAG characters need similar treatment. Fixes:
-       * https://github.com/harfbuzz/harfbuzz/issues/463 */
-      else if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
-      /* COMBINING GRAPHEME JOINER should not be skipped; at least some times.
-       * https://github.com/harfbuzz/harfbuzz/issues/554 */
-      else if (unlikely (u == 0x034Fu))
-      {
-	buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CGJ;
-	props |= UPROPS_MASK_HIDDEN;
-      }
-    }
-    else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat)))
-    {
-      /* The above check is just an optimization to let in only things we need further
-       * processing on. */
-
-      /* Only Mn and Mc can have non-zero ccc:
-       * http://www.unicode.org/policies/stability_policy.html#Property_Value
-       * """
-       * Canonical_Combining_Class, General_Category
-       * All characters other than those with General_Category property values
-       * Spacing_Mark (Mc) and Nonspacing_Mark (Mn) have the Canonical_Combining_Class
-       * property value 0.
-       * 1.1.5+
-       * """
-       *
-       * Also, all Mn's that are Default_Ignorable, have ccc=0, hence
-       * the "else if".
-       */
-      props |= unicode->modified_combining_class (info->codepoint)<<8;
-
-      /* Recategorize emoji skin-tone modifiers as Unicode mark, so they
-       * behave correctly in non-native directionality.  They originally
-       * are MODIFIER_SYMBOL.  Fixes:
-       * https://github.com/harfbuzz/harfbuzz/issues/169
-       */
-      if (unlikely (hb_in_range (u, 0x1F3FBu, 0x1F3FFu)))
-      {
-	props = gen_cat = HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
-      }
-    }
-  }
-
-  info->unicode_props() = props;
-}
-
-static inline void
-_hb_glyph_info_set_general_category (hb_glyph_info_t *info,
-				     hb_unicode_general_category_t gen_cat)
-{
-  /* Clears top-byte. */
-  info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_GEN_CAT));
-}
-
-static inline hb_unicode_general_category_t
-_hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
-{
-  return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_GEN_CAT);
-}
-
-static inline bool
-_hb_glyph_info_is_unicode_mark (const hb_glyph_info_t *info)
-{
-  return HB_UNICODE_GENERAL_CATEGORY_IS_MARK (info->unicode_props() & UPROPS_MASK_GEN_CAT);
-}
-static inline void
-_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
-					     unsigned int modified_class)
-{
-  if (unlikely (!_hb_glyph_info_is_unicode_mark (info)))
-    return;
-  info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
-}
-static inline unsigned int
-_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
-}
-
-
-/* Loop over grapheme. Based on foreach_cluster(). */
-#define foreach_grapheme(buffer, start, end) \
-  for (unsigned int \
-       _count = buffer->len, \
-       start = 0, end = _count ? _next_grapheme (buffer, 0) : 0; \
-       start < _count; \
-       start = end, end = _next_grapheme (buffer, start))
-
-static inline unsigned int
-_next_grapheme (hb_buffer_t *buffer, unsigned int start)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  while (++start < count && _hb_glyph_info_is_unicode_mark (&info[start]))
-    ;
-
-  return start;
-}
-
-
-#define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info)))
-
-static inline bool
-_hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_get_general_category (info) ==
-	 HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
-}
-static inline void
-_hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s)
-{
-  if (unlikely (!_hb_glyph_info_is_unicode_space (info)))
-    return;
-  info->unicode_props() = (((unsigned int) s)<<8) | (info->unicode_props() & 0xFF);
-}
-static inline hb_unicode_funcs_t::space_t
-_hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_space (info) ?
-	 (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
-	 hb_unicode_funcs_t::NOT_SPACE;
-}
-
-static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
-
-static inline hb_bool_t
-_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
-{
-  return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
-	 !_hb_glyph_info_ligated (info);
-}
-static inline hb_bool_t
-_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
-{
-  return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
-	  == UPROPS_MASK_IGNORABLE) &&
-	 !_hb_glyph_info_ligated (info);
-}
-static inline void
-_hb_glyph_info_unhide (hb_glyph_info_t *info)
-{
-  info->unicode_props() &= ~ UPROPS_MASK_HIDDEN;
-}
-
-static inline bool
-_hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_get_general_category (info) ==
-	 HB_UNICODE_GENERAL_CATEGORY_FORMAT;
-}
-static inline hb_bool_t
-_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
-}
-static inline hb_bool_t
-_hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
-}
-static inline hb_bool_t
-_hb_glyph_info_is_joiner (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ));
-}
-static inline void
-_hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
-{
-  if (!_hb_glyph_info_is_unicode_format (info))
-    return;
-  info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
-}
-
-/* lig_props: aka lig_id / lig_comp
- *
- * When a ligature is formed:
- *
- *   - The ligature glyph and any marks in between all the same newly allocated
- *     lig_id,
- *   - The ligature glyph will get lig_num_comps set to the number of components
- *   - The marks get lig_comp > 0, reflecting which component of the ligature
- *     they were applied to.
- *   - This is used in GPOS to attach marks to the right component of a ligature
- *     in MarkLigPos,
- *   - Note that when marks are ligated together, much of the above is skipped
- *     and the current lig_id reused.
- *
- * When a multiple-substitution is done:
- *
- *   - All resulting glyphs will have lig_id = 0,
- *   - The resulting glyphs will have lig_comp = 0, 1, 2, ... respectively.
- *   - This is used in GPOS to attach marks to the first component of a
- *     multiple substitution in MarkBasePos.
- *
- * The numbers are also used in GPOS to do mark-to-mark positioning only
- * to marks that belong to the same component of the same ligature.
- */
-
-static inline void
-_hb_glyph_info_clear_lig_props (hb_glyph_info_t *info)
-{
-  info->lig_props() = 0;
-}
-
-#define IS_LIG_BASE 0x10
-
-static inline void
-_hb_glyph_info_set_lig_props_for_ligature (hb_glyph_info_t *info,
-					   unsigned int lig_id,
-					   unsigned int lig_num_comps)
-{
-  info->lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F);
-}
-
-static inline void
-_hb_glyph_info_set_lig_props_for_mark (hb_glyph_info_t *info,
-				       unsigned int lig_id,
-				       unsigned int lig_comp)
-{
-  info->lig_props() = (lig_id << 5) | (lig_comp & 0x0F);
-}
-
-static inline void
-_hb_glyph_info_set_lig_props_for_component (hb_glyph_info_t *info, unsigned int comp)
-{
-  _hb_glyph_info_set_lig_props_for_mark (info, 0, comp);
-}
-
-static inline unsigned int
-_hb_glyph_info_get_lig_id (const hb_glyph_info_t *info)
-{
-  return info->lig_props() >> 5;
-}
-
-static inline bool
-_hb_glyph_info_ligated_internal (const hb_glyph_info_t *info)
-{
-  return !!(info->lig_props() & IS_LIG_BASE);
-}
-
-static inline unsigned int
-_hb_glyph_info_get_lig_comp (const hb_glyph_info_t *info)
-{
-  if (_hb_glyph_info_ligated_internal (info))
-    return 0;
-  else
-    return info->lig_props() & 0x0F;
-}
-
-static inline unsigned int
-_hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info)
-{
-  if ((info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) &&
-      _hb_glyph_info_ligated_internal (info))
-    return info->lig_props() & 0x0F;
-  else
-    return 1;
-}
-
-static inline uint8_t
-_hb_allocate_lig_id (hb_buffer_t *buffer) {
-  uint8_t lig_id = buffer->next_serial () & 0x07;
-  if (unlikely (!lig_id))
-    lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
-  return lig_id;
-}
-
-/* glyph_props: */
-
-static inline void
-_hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props)
-{
-  info->glyph_props() = props;
-}
-
-static inline unsigned int
-_hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
-{
-  return info->glyph_props();
-}
-
-static inline bool
-_hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
-}
-
-static inline bool
-_hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
-}
-
-static inline bool
-_hb_glyph_info_is_mark (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
-}
-
-static inline bool
-_hb_glyph_info_substituted (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
-}
-
-static inline bool
-_hb_glyph_info_ligated (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
-}
-
-static inline bool
-_hb_glyph_info_multiplied (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
-}
-
-static inline bool
-_hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
-}
-
-static inline void
-_hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
-{
-  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
-			   HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
-}
-
-static inline void
-_hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
-{
-  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
-}
-
-
-/* Allocation / deallocation. */
-
-static inline void
-_hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props);
-}
-
-static inline void
-_hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props);
-}
-
-static inline void
-_hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ASSERT_VAR (buffer, unicode_props);
-}
-
-static inline void
-_hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
-  HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
-  HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
-}
-
-static inline void
-_hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
-}
-
-static inline void
-_hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
-  HB_BUFFER_ASSERT_VAR (buffer, lig_props);
-  HB_BUFFER_ASSERT_VAR (buffer, syllable);
-}
-
-/* Make sure no one directly touches our props... */
-#undef unicode_props0
-#undef unicode_props1
-#undef lig_props
-#undef glyph_props
-
-#endif /* HB_OT_LAYOUT_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout.cc b/third_party/harfbuzz-ng/src/hb-ot-layout.cc
deleted file mode 100644
index 1c9e950..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-layout.cc
+++ /dev/null
@@ -1,1313 +0,0 @@
-/*
- * Copyright © 1998-2004  David Turner and Werner Lemberg
- * Copyright © 2006  Behdad Esfahbod
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2012,2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-open-type-private.hh"
-#include "hb-ot-layout-private.hh"
-
-#include "hb-ot-layout-base-table.hh"
-#include "hb-ot-layout-gdef-table.hh"
-#include "hb-ot-layout-gsub-table.hh"
-#include "hb-ot-layout-gpos-table.hh"
-#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise.
-#include "hb-ot-name-table.hh" // Just so we compile it; unused otherwise.
-#include "hb-ot-color-colr-table.hh"
-#include "hb-ot-color-cpal-table.hh"
-
-#include "hb-ot-map-private.hh"
-
-
-#ifndef HB_NO_VISIBILITY
-const void * const OT::_hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
-#endif
-
-
-hb_ot_layout_t *
-_hb_ot_layout_create (hb_face_t *face)
-{
-  hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
-  if (unlikely (!layout))
-    return nullptr;
-
-  layout->gdef_blob = OT::Sanitizer<OT::GDEF>().sanitize (face->reference_table (HB_OT_TAG_GDEF));
-  layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob);
-
-  layout->gsub_blob = OT::Sanitizer<OT::GSUB>().sanitize (face->reference_table (HB_OT_TAG_GSUB));
-  layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob);
-
-  layout->gpos_blob = OT::Sanitizer<OT::GPOS>().sanitize (face->reference_table (HB_OT_TAG_GPOS));
-  layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
-
-  layout->base.init (face);
-  layout->colr.init (face);
-  layout->cpal.init (face);
-  layout->math.init (face);
-  layout->fvar.init (face);
-  layout->avar.init (face);
-  layout->ankr.init (face);
-  layout->kerx.init (face);
-  layout->morx.init (face);
-  layout->trak.init (face);
-
-  {
-    /*
-     * The ugly business of blacklisting individual fonts' tables happen here!
-     * See this thread for why we finally had to bend in and do this:
-     * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
-     */
-    unsigned int gdef_len = hb_blob_get_length (layout->gdef_blob);
-    unsigned int gsub_len = hb_blob_get_length (layout->gsub_blob);
-    unsigned int gpos_len = hb_blob_get_length (layout->gpos_blob);
-    if (0
-      /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
-      || (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
-      || (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
-      || (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
-      || (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
-      || (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len)
-      /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
-      || (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len)
-    )
-    {
-      /* In certain versions of Times New Roman Italic and Bold Italic,
-       * ASCII double quotation mark U+0022, mapped to glyph 5, has wrong
-       * glyph class 3 (mark) in GDEF.  Nuke the GDEF to avoid zero-width
-       * double-quote.  See:
-       * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
-       */
-     if (3 == layout->gdef->get_glyph_class (5))
-       layout->gdef = &OT::Null(OT::GDEF);
-    }
-    else if (0
-      /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c  tahoma.ttf from Windows 8 */
-      || (898 == gdef_len && 46470 == gpos_len && 12554 == gsub_len)
-      /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc  tahomabd.ttf from Windows 8 */
-      || (910 == gdef_len && 47732 == gpos_len && 12566 == gsub_len)
-      /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e  tahoma.ttf from Windows 8.1 */
-      || (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len)
-      /* sha1sum:6d400781948517c3c0441ba42acb309584b73033  tahomabd.ttf from Windows 8.1 */
-      || (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len)
-      /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (964 == gdef_len && 60072 == gpos_len && 23836 == gsub_len)
-      /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (976 == gdef_len && 61456 == gpos_len && 23832 == gsub_len)
-      /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846  tahoma.ttf from Windows 10 */
-      || (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len)
-      /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343  tahomabd.ttf from Windows 10 */
-      || (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len)
-      /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (1006 == gdef_len && 61346 == gpos_len && 24576 == gsub_len)
-      /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (1018 == gdef_len && 62828 == gpos_len && 24572 == gsub_len)
-      /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5  tahoma.ttf from Windows 10 AU */
-      || (1006 == gdef_len && 61352 == gpos_len && 24576 == gsub_len)
-      /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2  tahomabd.ttf from Windows 10 AU */
-      || (1018 == gdef_len && 62834 == gpos_len && 24572 == gsub_len)
-      /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7  Tahoma.ttf from Mac OS X 10.9 */
-      || (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len)
-      /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba  Tahoma Bold.ttf from Mac OS X 10.9 */
-      || (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len)
-      /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc  himalaya.ttf from Windows 7 */
-      || (180 == gdef_len && 7254 == gpos_len && 13054 == gsub_len)
-      /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0  himalaya.ttf from Windows 8 */
-      || (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len)
-      /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427  himalaya.ttf from Windows 8.1 */
-      || (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len)
-      /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44  cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
-      /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371  cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
-      || (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len)
-      /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f  cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
-      /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b  cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
-      || (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len)
-      /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
-      || (1058 == gdef_len && 11818 == gpos_len && 47032 == gsub_len)
-      /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
-      || (1046 == gdef_len && 12600 == gpos_len && 47030 == gsub_len)
-      /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
-      || (1058 == gdef_len && 16770 == gpos_len && 71796 == gsub_len)
-      /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
-      || (1046 == gdef_len && 17862 == gpos_len && 71790 == gsub_len)
-      /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
-      || (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len)
-      /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
-      || (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len)
-      /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
-      || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len)
-      /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
-      || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len)
-      /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85  Padauk.ttf
-       *  "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
-      || (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len)
-    )
-    {
-      /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks
-       * such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya,
-       * and the version of Cantarell shipped by Ubuntu 16.04.
-       * Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing.
-       * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
-       *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
-       *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
-       */
-      layout->gdef = &OT::Null(OT::GDEF);
-    }
-  }
-
-  layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
-  layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
-
-  layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
-  layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
-
-  if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
-		(layout->gpos_lookup_count && !layout->gpos_accels)))
-  {
-    _hb_ot_layout_destroy (layout);
-    return nullptr;
-  }
-
-  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
-    layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
-  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
-    layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
-
-  return layout;
-}
-
-void
-_hb_ot_layout_destroy (hb_ot_layout_t *layout)
-{
-  if (layout->gsub_accels)
-    for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
-      layout->gsub_accels[i].fini ();
-  if (layout->gpos_accels)
-    for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
-      layout->gpos_accels[i].fini ();
-
-  free (layout->gsub_accels);
-  free (layout->gpos_accels);
-
-  hb_blob_destroy (layout->gdef_blob);
-  hb_blob_destroy (layout->gsub_blob);
-  hb_blob_destroy (layout->gpos_blob);
-
-  layout->base.fini ();
-  layout->colr.fini ();
-  layout->cpal.fini ();
-  layout->math.fini ();
-  layout->fvar.fini ();
-  layout->avar.fini ();
-  layout->ankr.fini ();
-  layout->kerx.fini ();
-  layout->morx.fini ();
-  layout->trak.fini ();
-
-  free (layout);
-}
-
-// static inline const OT::BASE&
-// _get_base (hb_face_t *face)
-// {
-//   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::BASE);
-//   hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-//   return *(layout->base.get ());
-// }
-
-static inline const OT::GDEF&
-_get_gdef (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF);
-  return *hb_ot_layout_from_face (face)->gdef;
-}
-static inline const OT::GSUB&
-_get_gsub (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GSUB);
-  return *hb_ot_layout_from_face (face)->gsub;
-}
-static inline const OT::GPOS&
-_get_gpos (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS);
-  return *hb_ot_layout_from_face (face)->gpos;
-}
-
-/*
- * GDEF
- */
-
-hb_bool_t
-hb_ot_layout_has_glyph_classes (hb_face_t *face)
-{
-  return _get_gdef (face).has_glyph_classes ();
-}
-
-/**
- * hb_ot_layout_get_glyph_class:
- *
- * Since: 0.9.7
- **/
-hb_ot_layout_glyph_class_t
-hb_ot_layout_get_glyph_class (hb_face_t      *face,
-			      hb_codepoint_t  glyph)
-{
-  return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph);
-}
-
-/**
- * hb_ot_layout_get_glyphs_in_class:
- *
- * Since: 0.9.7
- **/
-void
-hb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
-				  hb_ot_layout_glyph_class_t  klass,
-				  hb_set_t                   *glyphs /* OUT */)
-{
-  return _get_gdef (face).get_glyphs_in_class (klass, glyphs);
-}
-
-unsigned int
-hb_ot_layout_get_attach_points (hb_face_t      *face,
-				hb_codepoint_t  glyph,
-				unsigned int    start_offset,
-				unsigned int   *point_count /* IN/OUT */,
-				unsigned int   *point_array /* OUT */)
-{
-  return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array);
-}
-
-unsigned int
-hb_ot_layout_get_ligature_carets (hb_font_t      *font,
-				  hb_direction_t  direction,
-				  hb_codepoint_t  glyph,
-				  unsigned int    start_offset,
-				  unsigned int   *caret_count /* IN/OUT */,
-				  hb_position_t  *caret_array /* OUT */)
-{
-  return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
-}
-
-
-/*
- * GSUB/GPOS
- */
-
-static const OT::GSUBGPOS&
-get_gsubgpos_table (hb_face_t *face,
-		    hb_tag_t   table_tag)
-{
-  switch (table_tag) {
-    case HB_OT_TAG_GSUB: return _get_gsub (face);
-    case HB_OT_TAG_GPOS: return _get_gpos (face);
-    default:             return OT::Null(OT::GSUBGPOS);
-  }
-}
-
-
-unsigned int
-hb_ot_layout_table_get_script_tags (hb_face_t    *face,
-				    hb_tag_t      table_tag,
-				    unsigned int  start_offset,
-				    unsigned int *script_count /* IN/OUT */,
-				    hb_tag_t     *script_tags /* OUT */)
-{
-  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-
-  return g.get_script_tags (start_offset, script_count, script_tags);
-}
-
-#define HB_OT_TAG_LATIN_SCRIPT		HB_TAG ('l', 'a', 't', 'n')
-
-hb_bool_t
-hb_ot_layout_table_find_script (hb_face_t    *face,
-				hb_tag_t      table_tag,
-				hb_tag_t      script_tag,
-				unsigned int *script_index)
-{
-  static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX), "");
-  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-
-  if (g.find_script_index (script_tag, script_index))
-    return true;
-
-  /* try finding 'DFLT' */
-  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index))
-    return false;
-
-  /* try with 'dflt'; MS site has had typos and many fonts use it now :(.
-   * including many versions of DejaVu Sans Mono! */
-  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index))
-    return false;
-
-  /* try with 'latn'; some old fonts put their features there even though
-     they're really trying to support Thai, for example :( */
-  if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index))
-    return false;
-
-  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
-  return false;
-}
-
-hb_bool_t
-hb_ot_layout_table_choose_script (hb_face_t      *face,
-				  hb_tag_t        table_tag,
-				  const hb_tag_t *script_tags,
-				  unsigned int   *script_index,
-				  hb_tag_t       *chosen_script)
-{
-  static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX), "");
-  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-
-  while (*script_tags)
-  {
-    if (g.find_script_index (*script_tags, script_index)) {
-      if (chosen_script)
-        *chosen_script = *script_tags;
-      return true;
-    }
-    script_tags++;
-  }
-
-  /* try finding 'DFLT' */
-  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) {
-    if (chosen_script)
-      *chosen_script = HB_OT_TAG_DEFAULT_SCRIPT;
-    return false;
-  }
-
-  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
-  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) {
-    if (chosen_script)
-      *chosen_script = HB_OT_TAG_DEFAULT_LANGUAGE;
-    return false;
-  }
-
-  /* try with 'latn'; some old fonts put their features there even though
-     they're really trying to support Thai, for example :( */
-  if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index)) {
-    if (chosen_script)
-      *chosen_script = HB_OT_TAG_LATIN_SCRIPT;
-    return false;
-  }
-
-  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
-  if (chosen_script)
-    *chosen_script = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
-  return false;
-}
-
-unsigned int
-hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
-				     hb_tag_t      table_tag,
-				     unsigned int  start_offset,
-				     unsigned int *feature_count /* IN/OUT */,
-				     hb_tag_t     *feature_tags /* OUT */)
-{
-  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-
-  return g.get_feature_tags (start_offset, feature_count, feature_tags);
-}
-
-hb_bool_t
-hb_ot_layout_table_find_feature (hb_face_t    *face,
-				 hb_tag_t      table_tag,
-				 hb_tag_t      feature_tag,
-				 unsigned int *feature_index)
-{
-  static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX), "");
-  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-
-  unsigned int num_features = g.get_feature_count ();
-  for (unsigned int i = 0; i < num_features; i++)
-  {
-    if (feature_tag == g.get_feature_tag (i)) {
-      if (feature_index) *feature_index = i;
-      return true;
-    }
-  }
-
-  if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
-  return false;
-}
-
-
-unsigned int
-hb_ot_layout_script_get_language_tags (hb_face_t    *face,
-				       hb_tag_t      table_tag,
-				       unsigned int  script_index,
-				       unsigned int  start_offset,
-				       unsigned int *language_count /* IN/OUT */,
-				       hb_tag_t     *language_tags /* OUT */)
-{
-  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
-
-  return s.get_lang_sys_tags (start_offset, language_count, language_tags);
-}
-
-hb_bool_t
-hb_ot_layout_script_find_language (hb_face_t    *face,
-				   hb_tag_t      table_tag,
-				   unsigned int  script_index,
-				   hb_tag_t      language_tag,
-				   unsigned int *language_index)
-{
-  static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX), "");
-  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
-
-  if (s.find_lang_sys_index (language_tag, language_index))
-    return true;
-
-  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
-  if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
-    return false;
-
-  if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
-  return false;
-}
-
-hb_bool_t
-hb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
-						  hb_tag_t      table_tag,
-						  unsigned int  script_index,
-						  unsigned int  language_index,
-						  unsigned int *feature_index)
-{
-  return hb_ot_layout_language_get_required_feature (face,
-						     table_tag,
-						     script_index,
-						     language_index,
-						     feature_index,
-						     nullptr);
-}
-
-/**
- * hb_ot_layout_language_get_required_feature:
- *
- * Since: 0.9.30
- **/
-hb_bool_t
-hb_ot_layout_language_get_required_feature (hb_face_t    *face,
-					    hb_tag_t      table_tag,
-					    unsigned int  script_index,
-					    unsigned int  language_index,
-					    unsigned int *feature_index,
-					    hb_tag_t     *feature_tag)
-{
-  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
-
-  unsigned int index = l.get_required_feature_index ();
-  if (feature_index) *feature_index = index;
-  if (feature_tag) *feature_tag = g.get_feature_tag (index);
-
-  return l.has_required_feature ();
-}
-
-unsigned int
-hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
-					   hb_tag_t      table_tag,
-					   unsigned int  script_index,
-					   unsigned int  language_index,
-					   unsigned int  start_offset,
-					   unsigned int *feature_count /* IN/OUT */,
-					   unsigned int *feature_indexes /* OUT */)
-{
-  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
-
-  return l.get_feature_indexes (start_offset, feature_count, feature_indexes);
-}
-
-unsigned int
-hb_ot_layout_language_get_feature_tags (hb_face_t    *face,
-					hb_tag_t      table_tag,
-					unsigned int  script_index,
-					unsigned int  language_index,
-					unsigned int  start_offset,
-					unsigned int *feature_count /* IN/OUT */,
-					hb_tag_t     *feature_tags /* OUT */)
-{
-  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
-
-  static_assert ((sizeof (unsigned int) == sizeof (hb_tag_t)), "");
-  unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags);
-
-  if (feature_tags) {
-    unsigned int count = *feature_count;
-    for (unsigned int i = 0; i < count; i++)
-      feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]);
-  }
-
-  return ret;
-}
-
-
-hb_bool_t
-hb_ot_layout_language_find_feature (hb_face_t    *face,
-				    hb_tag_t      table_tag,
-				    unsigned int  script_index,
-				    unsigned int  language_index,
-				    hb_tag_t      feature_tag,
-				    unsigned int *feature_index)
-{
-  static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX), "");
-  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
-
-  unsigned int num_features = l.get_feature_count ();
-  for (unsigned int i = 0; i < num_features; i++) {
-    unsigned int f_index = l.get_feature_index (i);
-
-    if (feature_tag == g.get_feature_tag (f_index)) {
-      if (feature_index) *feature_index = f_index;
-      return true;
-    }
-  }
-
-  if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
-  return false;
-}
-
-/**
- * hb_ot_layout_feature_get_lookups:
- *
- * Since: 0.9.7
- **/
-unsigned int
-hb_ot_layout_feature_get_lookups (hb_face_t    *face,
-				  hb_tag_t      table_tag,
-				  unsigned int  feature_index,
-				  unsigned int  start_offset,
-				  unsigned int *lookup_count /* IN/OUT */,
-				  unsigned int *lookup_indexes /* OUT */)
-{
-  return hb_ot_layout_feature_with_variations_get_lookups (face,
-							   table_tag,
-							   feature_index,
-							   HB_OT_LAYOUT_NO_VARIATIONS_INDEX,
-							   start_offset,
-							   lookup_count,
-							   lookup_indexes);
-}
-
-/**
- * hb_ot_layout_table_get_lookup_count:
- *
- * Since: 0.9.22
- **/
-unsigned int
-hb_ot_layout_table_get_lookup_count (hb_face_t    *face,
-				     hb_tag_t      table_tag)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return 0;
-  switch (table_tag)
-  {
-    case HB_OT_TAG_GSUB:
-    {
-      return hb_ot_layout_from_face (face)->gsub_lookup_count;
-    }
-    case HB_OT_TAG_GPOS:
-    {
-      return hb_ot_layout_from_face (face)->gpos_lookup_count;
-    }
-  }
-  return 0;
-}
-
-static void
-_hb_ot_layout_collect_lookups_lookups (hb_face_t      *face,
-				       hb_tag_t        table_tag,
-				       unsigned int    feature_index,
-				       hb_set_t       *lookup_indexes /* OUT */)
-{
-  unsigned int lookup_indices[32];
-  unsigned int offset, len;
-
-  offset = 0;
-  do {
-    len = ARRAY_LENGTH (lookup_indices);
-    hb_ot_layout_feature_get_lookups (face,
-				      table_tag,
-				      feature_index,
-				      offset, &len,
-				      lookup_indices);
-
-    for (unsigned int i = 0; i < len; i++)
-      lookup_indexes->add (lookup_indices[i]);
-
-    offset += len;
-  } while (len == ARRAY_LENGTH (lookup_indices));
-}
-
-static void
-_hb_ot_layout_collect_lookups_features (hb_face_t      *face,
-					hb_tag_t        table_tag,
-					unsigned int    script_index,
-					unsigned int    language_index,
-					const hb_tag_t *features,
-					hb_set_t       *lookup_indexes /* OUT */)
-{
-  if (!features)
-  {
-    unsigned int required_feature_index;
-    if (hb_ot_layout_language_get_required_feature (face,
-						    table_tag,
-						    script_index,
-						    language_index,
-						    &required_feature_index,
-						    nullptr))
-      _hb_ot_layout_collect_lookups_lookups (face,
-					     table_tag,
-					     required_feature_index,
-					     lookup_indexes);
-
-    /* All features */
-    unsigned int feature_indices[32];
-    unsigned int offset, len;
-
-    offset = 0;
-    do {
-      len = ARRAY_LENGTH (feature_indices);
-      hb_ot_layout_language_get_feature_indexes (face,
-						 table_tag,
-						 script_index,
-						 language_index,
-						 offset, &len,
-						 feature_indices);
-
-      for (unsigned int i = 0; i < len; i++)
-	_hb_ot_layout_collect_lookups_lookups (face,
-					       table_tag,
-					       feature_indices[i],
-					       lookup_indexes);
-
-      offset += len;
-    } while (len == ARRAY_LENGTH (feature_indices));
-  }
-  else
-  {
-    for (; *features; features++)
-    {
-      unsigned int feature_index;
-      if (hb_ot_layout_language_find_feature (face,
-					      table_tag,
-					      script_index,
-					      language_index,
-					      *features,
-					      &feature_index))
-        _hb_ot_layout_collect_lookups_lookups (face,
-					       table_tag,
-					       feature_index,
-					       lookup_indexes);
-    }
-  }
-}
-
-static void
-_hb_ot_layout_collect_lookups_languages (hb_face_t      *face,
-					 hb_tag_t        table_tag,
-					 unsigned int    script_index,
-					 const hb_tag_t *languages,
-					 const hb_tag_t *features,
-					 hb_set_t       *lookup_indexes /* OUT */)
-{
-  _hb_ot_layout_collect_lookups_features (face,
-					  table_tag,
-					  script_index,
-					  HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
-					  features,
-					  lookup_indexes);
-
-  if (!languages)
-  {
-    /* All languages */
-    unsigned int count = hb_ot_layout_script_get_language_tags (face,
-								table_tag,
-								script_index,
-								0, nullptr, nullptr);
-    for (unsigned int language_index = 0; language_index < count; language_index++)
-      _hb_ot_layout_collect_lookups_features (face,
-					      table_tag,
-					      script_index,
-					      language_index,
-					      features,
-					      lookup_indexes);
-  }
-  else
-  {
-    for (; *languages; languages++)
-    {
-      unsigned int language_index;
-      if (hb_ot_layout_script_find_language (face,
-					     table_tag,
-					     script_index,
-					     *languages,
-					     &language_index))
-        _hb_ot_layout_collect_lookups_features (face,
-						table_tag,
-						script_index,
-						language_index,
-						features,
-						lookup_indexes);
-    }
-  }
-}
-
-/**
- * hb_ot_layout_collect_lookups:
- *
- * Since: 0.9.8
- **/
-void
-hb_ot_layout_collect_lookups (hb_face_t      *face,
-			      hb_tag_t        table_tag,
-			      const hb_tag_t *scripts,
-			      const hb_tag_t *languages,
-			      const hb_tag_t *features,
-			      hb_set_t       *lookup_indexes /* OUT */)
-{
-  if (!scripts)
-  {
-    /* All scripts */
-    unsigned int count = hb_ot_layout_table_get_script_tags (face,
-							     table_tag,
-							     0, nullptr, nullptr);
-    for (unsigned int script_index = 0; script_index < count; script_index++)
-      _hb_ot_layout_collect_lookups_languages (face,
-					       table_tag,
-					       script_index,
-					       languages,
-					       features,
-					       lookup_indexes);
-  }
-  else
-  {
-    for (; *scripts; scripts++)
-    {
-      unsigned int script_index;
-      if (hb_ot_layout_table_find_script (face,
-					  table_tag,
-					  *scripts,
-					  &script_index))
-        _hb_ot_layout_collect_lookups_languages (face,
-						 table_tag,
-						 script_index,
-						 languages,
-						 features,
-						 lookup_indexes);
-    }
-  }
-}
-
-/**
- * hb_ot_layout_lookup_collect_glyphs:
- *
- * Since: 0.9.7
- **/
-void
-hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
-				    hb_tag_t      table_tag,
-				    unsigned int  lookup_index,
-				    hb_set_t     *glyphs_before, /* OUT. May be nullptr */
-				    hb_set_t     *glyphs_input,  /* OUT. May be nullptr */
-				    hb_set_t     *glyphs_after,  /* OUT. May be nullptr */
-				    hb_set_t     *glyphs_output  /* OUT. May be nullptr */)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
-
-  OT::hb_collect_glyphs_context_t c (face,
-				     glyphs_before,
-				     glyphs_input,
-				     glyphs_after,
-				     glyphs_output);
-
-  switch (table_tag)
-  {
-    case HB_OT_TAG_GSUB:
-    {
-      const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
-      l.collect_glyphs (&c);
-      return;
-    }
-    case HB_OT_TAG_GPOS:
-    {
-      const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
-      l.collect_glyphs (&c);
-      return;
-    }
-  }
-}
-
-
-/* Variations support */
-
-hb_bool_t
-hb_ot_layout_table_find_feature_variations (hb_face_t    *face,
-					    hb_tag_t      table_tag,
-					    const int    *coords,
-					    unsigned int  num_coords,
-					    unsigned int *variations_index /* out */)
-{
-  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-
-  return g.find_variations_index (coords, num_coords, variations_index);
-}
-
-unsigned int
-hb_ot_layout_feature_with_variations_get_lookups (hb_face_t    *face,
-						  hb_tag_t      table_tag,
-						  unsigned int  feature_index,
-						  unsigned int  variations_index,
-						  unsigned int  start_offset,
-						  unsigned int *lookup_count /* IN/OUT */,
-						  unsigned int *lookup_indexes /* OUT */)
-{
-  static_assert ((OT::FeatureVariations::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_VARIATIONS_INDEX), "");
-  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-
-  const OT::Feature &f = g.get_feature_variation (feature_index, variations_index);
-
-  return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
-}
-
-
-/*
- * OT::GSUB
- */
-
-hb_bool_t
-hb_ot_layout_has_substitution (hb_face_t *face)
-{
-  return &_get_gsub (face) != &OT::Null(OT::GSUB);
-}
-
-/**
- * hb_ot_layout_lookup_would_substitute:
- *
- * Since: 0.9.7
- **/
-hb_bool_t
-hb_ot_layout_lookup_would_substitute (hb_face_t            *face,
-				      unsigned int          lookup_index,
-				      const hb_codepoint_t *glyphs,
-				      unsigned int          glyphs_length,
-				      hb_bool_t             zero_context)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false;
-  return hb_ot_layout_lookup_would_substitute_fast (face, lookup_index, glyphs, glyphs_length, zero_context);
-}
-
-hb_bool_t
-hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
-					   unsigned int          lookup_index,
-					   const hb_codepoint_t *glyphs,
-					   unsigned int          glyphs_length,
-					   hb_bool_t             zero_context)
-{
-  if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
-  OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
-
-  const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
-
-  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]);
-}
-
-void
-hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
-{
-  OT::GSUB::substitute_start (font, buffer);
-}
-
-/**
- * hb_ot_layout_lookup_substitute_closure:
- *
- * Since: 0.9.7
- **/
-void
-hb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
-				        unsigned int  lookup_index,
-				        hb_set_t     *glyphs)
-{
-  OT::hb_closure_context_t c (face, glyphs);
-
-  const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index);
-
-  l.closure (&c);
-}
-
-/*
- * OT::GPOS
- */
-
-hb_bool_t
-hb_ot_layout_has_positioning (hb_face_t *face)
-{
-  return &_get_gpos (face) != &OT::Null(OT::GPOS);
-}
-
-void
-hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
-{
-  OT::GPOS::position_start (font, buffer);
-}
-
-void
-hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer)
-{
-  OT::GPOS::position_finish_advances (font, buffer);
-}
-
-void
-hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
-{
-  OT::GPOS::position_finish_offsets (font, buffer);
-}
-
-/**
- * hb_ot_layout_get_size_params:
- *
- * Since: 0.9.10
- **/
-hb_bool_t
-hb_ot_layout_get_size_params (hb_face_t    *face,
-			      unsigned int *design_size,       /* OUT.  May be nullptr */
-			      unsigned int *subfamily_id,      /* OUT.  May be nullptr */
-			      unsigned int *subfamily_name_id, /* OUT.  May be nullptr */
-			      unsigned int *range_start,       /* OUT.  May be nullptr */
-			      unsigned int *range_end          /* OUT.  May be nullptr */)
-{
-  const OT::GPOS &gpos = _get_gpos (face);
-  const hb_tag_t tag = HB_TAG ('s','i','z','e');
-
-  unsigned int num_features = gpos.get_feature_count ();
-  for (unsigned int i = 0; i < num_features; i++)
-  {
-    if (tag == gpos.get_feature_tag (i))
-    {
-      const OT::Feature &f = gpos.get_feature (i);
-      const OT::FeatureParamsSize &params = f.get_feature_params ().get_size_params (tag);
-
-      if (params.designSize)
-      {
-#define PARAM(a, A) if (a) *a = params.A
-	PARAM (design_size, designSize);
-	PARAM (subfamily_id, subfamilyID);
-	PARAM (subfamily_name_id, subfamilyNameID);
-	PARAM (range_start, rangeStart);
-	PARAM (range_end, rangeEnd);
-#undef PARAM
-
-	return true;
-      }
-    }
-  }
-
-#define PARAM(a, A) if (a) *a = 0
-  PARAM (design_size, designSize);
-  PARAM (subfamily_id, subfamilyID);
-  PARAM (subfamily_name_id, subfamilyNameID);
-  PARAM (range_start, rangeStart);
-  PARAM (range_end, rangeEnd);
-#undef PARAM
-
-  return false;
-}
-
-
-/*
- * Parts of different types are implemented here such that they have direct
- * access to GSUB/GPOS lookups.
- */
-
-
-struct GSUBProxy
-{
-  static const unsigned int table_index = 0;
-  static const bool inplace = false;
-  typedef OT::SubstLookup Lookup;
-
-  GSUBProxy (hb_face_t *face) :
-    table (*hb_ot_layout_from_face (face)->gsub),
-    accels (hb_ot_layout_from_face (face)->gsub_accels) {}
-
-  const OT::GSUB &table;
-  const hb_ot_layout_lookup_accelerator_t *accels;
-};
-
-struct GPOSProxy
-{
-  static const unsigned int table_index = 1;
-  static const bool inplace = true;
-  typedef OT::PosLookup Lookup;
-
-  GPOSProxy (hb_face_t *face) :
-    table (*hb_ot_layout_from_face (face)->gpos),
-    accels (hb_ot_layout_from_face (face)->gpos_accels) {}
-
-  const OT::GPOS &table;
-  const hb_ot_layout_lookup_accelerator_t *accels;
-};
-
-
-struct hb_get_subtables_context_t :
-       OT::hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
-{
-  template <typename Type>
-  static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
-  {
-    const Type *typed_obj = (const Type *) obj;
-    return typed_obj->apply (c);
-  }
-
-  typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
-
-  struct hb_applicable_t
-  {
-    inline void init (const void *obj_, hb_apply_func_t apply_func_)
-    {
-      obj = obj_;
-      apply_func = apply_func_;
-    }
-
-    inline bool apply (OT::hb_ot_apply_context_t *c) const { return apply_func (obj, c); }
-
-    private:
-    const void *obj;
-    hb_apply_func_t apply_func;
-  };
-
-  typedef hb_auto_array_t<hb_applicable_t> array_t;
-
-  /* Dispatch interface. */
-  inline const char *get_name (void) { return "GET_SUBTABLES"; }
-  template <typename T>
-  inline return_t dispatch (const T &obj)
-  {
-    hb_applicable_t *entry = array.push();
-    if (likely (entry))
-      entry->init (&obj, apply_to<T>);
-    return HB_VOID;
-  }
-  static return_t default_return_value (void) { return HB_VOID; }
-  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
-
-  hb_get_subtables_context_t (array_t &array_) :
-			      array (array_),
-			      debug_depth (0) {}
-
-  array_t &array;
-  unsigned int debug_depth;
-};
-
-static inline bool
-apply_forward (OT::hb_ot_apply_context_t *c,
-	       const hb_ot_layout_lookup_accelerator_t &accel,
-	       const hb_get_subtables_context_t::array_t &subtables)
-{
-  bool ret = false;
-  hb_buffer_t *buffer = c->buffer;
-  while (buffer->idx < buffer->len && !buffer->in_error)
-  {
-    bool applied = false;
-    if (accel.may_have (buffer->cur().codepoint) &&
-	(buffer->cur().mask & c->lookup_mask) &&
-	c->check_glyph_property (&buffer->cur(), c->lookup_props))
-     {
-       for (unsigned int i = 0; i < subtables.len; i++)
-         if (subtables[i].apply (c))
-	 {
-	   applied = true;
-	   break;
-	 }
-     }
-
-    if (applied)
-      ret = true;
-    else
-      buffer->next_glyph ();
-  }
-  return ret;
-}
-
-static inline bool
-apply_backward (OT::hb_ot_apply_context_t *c,
-	       const hb_ot_layout_lookup_accelerator_t &accel,
-	       const hb_get_subtables_context_t::array_t &subtables)
-{
-  bool ret = false;
-  hb_buffer_t *buffer = c->buffer;
-  do
-  {
-    if (accel.may_have (buffer->cur().codepoint) &&
-	(buffer->cur().mask & c->lookup_mask) &&
-	c->check_glyph_property (&buffer->cur(), c->lookup_props))
-    {
-     for (unsigned int i = 0; i < subtables.len; i++)
-       if (subtables[i].apply (c))
-       {
-	 ret = true;
-	 break;
-       }
-    }
-    /* The reverse lookup doesn't "advance" cursor (for good reason). */
-    buffer->idx--;
-
-  }
-  while ((int) buffer->idx >= 0);
-  return ret;
-}
-
-template <typename Proxy>
-static inline void
-apply_string (OT::hb_ot_apply_context_t *c,
-	      const typename Proxy::Lookup &lookup,
-	      const hb_ot_layout_lookup_accelerator_t &accel)
-{
-  hb_buffer_t *buffer = c->buffer;
-
-  if (unlikely (!buffer->len || !c->lookup_mask))
-    return;
-
-  c->set_lookup_props (lookup.get_props ());
-
-  hb_get_subtables_context_t::array_t subtables;
-  hb_get_subtables_context_t c_get_subtables (subtables);
-  lookup.dispatch (&c_get_subtables);
-
-  if (likely (!lookup.is_reverse ()))
-  {
-    /* in/out forward substitution/positioning */
-    if (Proxy::table_index == 0)
-      buffer->clear_output ();
-    buffer->idx = 0;
-
-    bool ret;
-    ret = apply_forward (c, accel, subtables);
-    if (ret)
-    {
-      if (!Proxy::inplace)
-	buffer->swap_buffers ();
-      else
-	assert (!buffer->has_separate_output ());
-    }
-  }
-  else
-  {
-    /* in-place backward substitution/positioning */
-    if (Proxy::table_index == 0)
-      buffer->remove_output ();
-    buffer->idx = buffer->len - 1;
-
-    apply_backward (c, accel, subtables);
-  }
-}
-
-template <typename Proxy>
-inline void hb_ot_map_t::apply (const Proxy &proxy,
-				const hb_ot_shape_plan_t *plan,
-				hb_font_t *font,
-				hb_buffer_t *buffer) const
-{
-  const unsigned int table_index = proxy.table_index;
-  unsigned int i = 0;
-  OT::hb_ot_apply_context_t c (table_index, font, buffer);
-  c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
-
-  for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
-    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);
-      apply_string<Proxy> (&c,
-			   proxy.table.get_lookup (lookup_index),
-			   proxy.accels[lookup_index]);
-      (void) buffer->message (font, "end lookup %d", lookup_index);
-    }
-
-    if (stage->pause_func)
-    {
-      buffer->clear_output ();
-      stage->pause_func (plan, font, buffer);
-    }
-  }
-}
-
-void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
-{
-  GSUBProxy proxy (font->face);
-  apply (proxy, plan, font, buffer);
-}
-
-void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
-{
-  GPOSProxy proxy (font->face);
-  apply (proxy, plan, font, buffer);
-}
-
-void
-hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
-				const OT::SubstLookup &lookup,
-				const hb_ot_layout_lookup_accelerator_t &accel)
-{
-  apply_string<GSUBProxy> (c, lookup, accel);
-}
-
-
-
-
-/*
- * OT::BASE
- */
-
-// /**
-//  * hb_ot_base_has_data:
-//  * @face: #hb_face_t to test
-//  *
-//  * This function allows to verify the presence of an OpenType BASE table on the
-//  * face.
-//  *
-//  * Return value: true if face has a BASE table, false otherwise
-//  *
-//  * Since: XXX
-//  **/
-// hb_bool_t
-// hb_ot_base_has_data (hb_face_t *face)
-// {
-//   return &_get_base (face) != &OT::Null(OT::BASE);
-// }
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout.h b/third_party/harfbuzz-ng/src/hb-ot-layout.h
deleted file mode 100644
index 85938ba..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-layout.h
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_H_IN
-#error "Include <hb-ot.h> instead."
-#endif
-
-#ifndef HB_OT_LAYOUT_H
-#define HB_OT_LAYOUT_H
-
-#include "hb.h"
-
-#include "hb-ot-tag.h"
-
-HB_BEGIN_DECLS
-
-
-#define HB_OT_TAG_BASE HB_TAG('B','A','S','E')
-#define HB_OT_TAG_GDEF HB_TAG('G','D','E','F')
-#define HB_OT_TAG_GSUB HB_TAG('G','S','U','B')
-#define HB_OT_TAG_GPOS HB_TAG('G','P','O','S')
-#define HB_OT_TAG_JSTF HB_TAG('J','S','T','F')
-
-
-/*
- * GDEF
- */
-
-HB_EXTERN hb_bool_t
-hb_ot_layout_has_glyph_classes (hb_face_t *face);
-
-typedef enum {
-  HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED	= 0,
-  HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH	= 1,
-  HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE	= 2,
-  HB_OT_LAYOUT_GLYPH_CLASS_MARK		= 3,
-  HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT	= 4
-} hb_ot_layout_glyph_class_t;
-
-HB_EXTERN hb_ot_layout_glyph_class_t
-hb_ot_layout_get_glyph_class (hb_face_t      *face,
-			      hb_codepoint_t  glyph);
-
-HB_EXTERN void
-hb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
-				  hb_ot_layout_glyph_class_t  klass,
-				  hb_set_t                   *glyphs /* OUT */);
-
-
-/* Not that useful.  Provides list of attach points for a glyph that a
- * client may want to cache */
-HB_EXTERN unsigned int
-hb_ot_layout_get_attach_points (hb_face_t      *face,
-				hb_codepoint_t  glyph,
-				unsigned int    start_offset,
-				unsigned int   *point_count /* IN/OUT */,
-				unsigned int   *point_array /* OUT */);
-
-/* Ligature caret positions */
-HB_EXTERN unsigned int
-hb_ot_layout_get_ligature_carets (hb_font_t      *font,
-				  hb_direction_t  direction,
-				  hb_codepoint_t  glyph,
-				  unsigned int    start_offset,
-				  unsigned int   *caret_count /* IN/OUT */,
-				  hb_position_t  *caret_array /* OUT */);
-
-
-/*
- * GSUB/GPOS feature query and enumeration interface
- */
-
-#define HB_OT_LAYOUT_NO_SCRIPT_INDEX		0xFFFFu
-#define HB_OT_LAYOUT_NO_FEATURE_INDEX		0xFFFFu
-#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX	0xFFFFu
-#define HB_OT_LAYOUT_NO_VARIATIONS_INDEX	0xFFFFFFFFu
-
-HB_EXTERN unsigned int
-hb_ot_layout_table_get_script_tags (hb_face_t    *face,
-				    hb_tag_t      table_tag,
-				    unsigned int  start_offset,
-				    unsigned int *script_count /* IN/OUT */,
-				    hb_tag_t     *script_tags /* OUT */);
-
-HB_EXTERN hb_bool_t
-hb_ot_layout_table_find_script (hb_face_t    *face,
-				hb_tag_t      table_tag,
-				hb_tag_t      script_tag,
-				unsigned int *script_index);
-
-/* Like find_script, but takes zero-terminated array of scripts to test */
-HB_EXTERN hb_bool_t
-hb_ot_layout_table_choose_script (hb_face_t      *face,
-				  hb_tag_t        table_tag,
-				  const hb_tag_t *script_tags,
-				  unsigned int   *script_index,
-				  hb_tag_t       *chosen_script);
-
-HB_EXTERN unsigned int
-hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
-				     hb_tag_t      table_tag,
-				     unsigned int  start_offset,
-				     unsigned int *feature_count /* IN/OUT */,
-				     hb_tag_t     *feature_tags /* OUT */);
-
-HB_EXTERN unsigned int
-hb_ot_layout_script_get_language_tags (hb_face_t    *face,
-				       hb_tag_t      table_tag,
-				       unsigned int  script_index,
-				       unsigned int  start_offset,
-				       unsigned int *language_count /* IN/OUT */,
-				       hb_tag_t     *language_tags /* OUT */);
-
-HB_EXTERN hb_bool_t
-hb_ot_layout_script_find_language (hb_face_t    *face,
-				   hb_tag_t      table_tag,
-				   unsigned int  script_index,
-				   hb_tag_t      language_tag,
-				   unsigned int *language_index);
-
-HB_EXTERN hb_bool_t
-hb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
-						  hb_tag_t      table_tag,
-						  unsigned int  script_index,
-						  unsigned int  language_index,
-						  unsigned int *feature_index);
-
-HB_EXTERN hb_bool_t
-hb_ot_layout_language_get_required_feature (hb_face_t    *face,
-					    hb_tag_t      table_tag,
-					    unsigned int  script_index,
-					    unsigned int  language_index,
-					    unsigned int *feature_index,
-					    hb_tag_t     *feature_tag);
-
-HB_EXTERN unsigned int
-hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
-					   hb_tag_t      table_tag,
-					   unsigned int  script_index,
-					   unsigned int  language_index,
-					   unsigned int  start_offset,
-					   unsigned int *feature_count /* IN/OUT */,
-					   unsigned int *feature_indexes /* OUT */);
-
-HB_EXTERN unsigned int
-hb_ot_layout_language_get_feature_tags (hb_face_t    *face,
-					hb_tag_t      table_tag,
-					unsigned int  script_index,
-					unsigned int  language_index,
-					unsigned int  start_offset,
-					unsigned int *feature_count /* IN/OUT */,
-					hb_tag_t     *feature_tags /* OUT */);
-
-HB_EXTERN hb_bool_t
-hb_ot_layout_language_find_feature (hb_face_t    *face,
-				    hb_tag_t      table_tag,
-				    unsigned int  script_index,
-				    unsigned int  language_index,
-				    hb_tag_t      feature_tag,
-				    unsigned int *feature_index);
-
-HB_EXTERN unsigned int
-hb_ot_layout_feature_get_lookups (hb_face_t    *face,
-				  hb_tag_t      table_tag,
-				  unsigned int  feature_index,
-				  unsigned int  start_offset,
-				  unsigned int *lookup_count /* IN/OUT */,
-				  unsigned int *lookup_indexes /* OUT */);
-
-HB_EXTERN unsigned int
-hb_ot_layout_table_get_lookup_count (hb_face_t    *face,
-				     hb_tag_t      table_tag);
-
-
-HB_EXTERN void
-hb_ot_layout_collect_lookups (hb_face_t      *face,
-			      hb_tag_t        table_tag,
-			      const hb_tag_t *scripts,
-			      const hb_tag_t *languages,
-			      const hb_tag_t *features,
-			      hb_set_t       *lookup_indexes /* OUT */);
-
-HB_EXTERN void
-hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
-				    hb_tag_t      table_tag,
-				    unsigned int  lookup_index,
-				    hb_set_t     *glyphs_before, /* OUT. May be NULL */
-				    hb_set_t     *glyphs_input,  /* OUT. May be NULL */
-				    hb_set_t     *glyphs_after,  /* OUT. May be NULL */
-				    hb_set_t     *glyphs_output  /* OUT. May be NULL */);
-
-#ifdef HB_NOT_IMPLEMENTED
-typedef struct
-{
-  const hb_codepoint_t *before,
-  unsigned int          before_length,
-  const hb_codepoint_t *input,
-  unsigned int          input_length,
-  const hb_codepoint_t *after,
-  unsigned int          after_length,
-} hb_ot_layout_glyph_sequence_t;
-
-typedef hb_bool_t
-(*hb_ot_layout_glyph_sequence_func_t) (hb_font_t    *font,
-				       hb_tag_t      table_tag,
-				       unsigned int  lookup_index,
-				       const hb_ot_layout_glyph_sequence_t *sequence,
-				       void         *user_data);
-
-HB_EXTERN void
-Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t    *face,
-					 hb_tag_t      table_tag,
-					 unsigned int  lookup_index,
-					 hb_ot_layout_glyph_sequence_func_t callback,
-					 void         *user_data);
-#endif
-
-/* Variations support */
-
-HB_EXTERN hb_bool_t
-hb_ot_layout_table_find_feature_variations (hb_face_t    *face,
-					    hb_tag_t      table_tag,
-					    const int    *coords,
-					    unsigned int  num_coords,
-					    unsigned int *variations_index /* out */);
-
-HB_EXTERN unsigned int
-hb_ot_layout_feature_with_variations_get_lookups (hb_face_t    *face,
-						  hb_tag_t      table_tag,
-						  unsigned int  feature_index,
-						  unsigned int  variations_index,
-						  unsigned int  start_offset,
-						  unsigned int *lookup_count /* IN/OUT */,
-						  unsigned int *lookup_indexes /* OUT */);
-
-
-/*
- * GSUB
- */
-
-HB_EXTERN hb_bool_t
-hb_ot_layout_has_substitution (hb_face_t *face);
-
-HB_EXTERN hb_bool_t
-hb_ot_layout_lookup_would_substitute (hb_face_t            *face,
-				      unsigned int          lookup_index,
-				      const hb_codepoint_t *glyphs,
-				      unsigned int          glyphs_length,
-				      hb_bool_t             zero_context);
-
-HB_EXTERN void
-hb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
-				        unsigned int  lookup_index,
-				        hb_set_t     *glyphs
-					/*TODO , hb_bool_t  inclusive */);
-
-#ifdef HB_NOT_IMPLEMENTED
-/* Note: You better have GDEF when using this API, or marks won't do much. */
-HB_EXTERN hb_bool_t
-Xhb_ot_layout_lookup_substitute (hb_font_t            *font,
-				unsigned int          lookup_index,
-				const hb_ot_layout_glyph_sequence_t *sequence,
-				unsigned int          out_size,
-				hb_codepoint_t       *glyphs_out,   /* OUT */
-				unsigned int         *clusters_out, /* OUT */
-				unsigned int         *out_length    /* OUT */);
-#endif
-
-
-/*
- * GPOS
- */
-
-HB_EXTERN hb_bool_t
-hb_ot_layout_has_positioning (hb_face_t *face);
-
-#ifdef HB_NOT_IMPLEMENTED
-/* Note: You better have GDEF when using this API, or marks won't do much. */
-HB_EXTERN hb_bool_t
-Xhb_ot_layout_lookup_position (hb_font_t            *font,
-			      unsigned int          lookup_index,
-			      const hb_ot_layout_glyph_sequence_t *sequence,
-			      hb_glyph_position_t  *positions /* IN / OUT */);
-#endif
-
-/* Optical 'size' feature info.  Returns true if found.
- * http://www.microsoft.com/typography/otspec/features_pt.htm#size */
-HB_EXTERN hb_bool_t
-hb_ot_layout_get_size_params (hb_face_t    *face,
-			      unsigned int *design_size,       /* OUT.  May be NULL */
-			      unsigned int *subfamily_id,      /* OUT.  May be NULL */
-			      unsigned int *subfamily_name_id, /* OUT.  May be NULL */
-			      unsigned int *range_start,       /* OUT.  May be NULL */
-			      unsigned int *range_end          /* OUT.  May be NULL */);
-
-
-/*
- * BASE
- */
-#if 0
-
-#define HB_OT_TAG_BASE_HANG HB_TAG('h','a','n','g')
-#define HB_OT_TAG_BASE_ICFB HB_TAG('i','c','f','b')
-#define HB_OT_TAG_BASE_ICFT HB_TAG('i','c','f','t')
-#define HB_OT_TAG_BASE_IDEO HB_TAG('i','d','e','o')
-#define HB_OT_TAG_BASE_IDTB HB_TAG('i','d','t','b')
-#define HB_OT_TAG_BASE_MATH HB_TAG('m','a','t','h')
-#define HB_OT_TAG_BASE_ROMN HB_TAG('r','o','m','n')
-
-#endif
-
-
-HB_END_DECLS
-
-#endif /* HB_OT_LAYOUT_H */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-map-private.hh b/third_party/harfbuzz-ng/src/hb-ot-map-private.hh
deleted file mode 100644
index e6bd8ea5..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-map-private.hh
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2010,2011,2012,2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_MAP_PRIVATE_HH
-#define HB_OT_MAP_PRIVATE_HH
-
-#include "hb-buffer-private.hh"
-
-
-struct hb_ot_shape_plan_t;
-
-static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
-
-struct hb_ot_map_t
-{
-  friend struct hb_ot_map_builder_t;
-
-  public:
-
-  struct feature_map_t {
-    hb_tag_t tag; /* should be first for our bsearch to work */
-    unsigned int index[2]; /* GSUB/GPOS */
-    unsigned int stage[2]; /* GSUB/GPOS */
-    unsigned int shift;
-    hb_mask_t mask;
-    hb_mask_t _1_mask; /* mask for value=1, for quick access */
-    unsigned int needs_fallback : 1;
-    unsigned int auto_zwnj : 1;
-    unsigned int auto_zwj : 1;
-
-    inline int cmp (const hb_tag_t *tag_) const
-    { return *tag_ < tag ? -1 : *tag_ > tag ? 1 : 0; }
-  };
-
-  struct lookup_map_t {
-    unsigned short index;
-    unsigned short auto_zwnj : 1;
-    unsigned short auto_zwj : 1;
-    hb_mask_t mask;
-
-    static int cmp (const void *pa, const void *pb)
-    {
-      const lookup_map_t *a = (const lookup_map_t *) pa;
-      const lookup_map_t *b = (const lookup_map_t *) pb;
-      return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
-    }
-  };
-
-  typedef void (*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 */
-    pause_func_t pause_func;
-  };
-
-
-  hb_ot_map_t (void) { memset (this, 0, sizeof (*this)); }
-
-  inline hb_mask_t get_global_mask (void) const { return global_mask; }
-
-  inline hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = nullptr) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    if (shift) *shift = map ? map->shift : 0;
-    return map ? map->mask : 0;
-  }
-
-  inline bool needs_fallback (hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->needs_fallback : false;
-  }
-
-  inline hb_mask_t get_1_mask (hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->_1_mask : 0;
-  }
-
-  inline unsigned int get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX;
-  }
-
-  inline unsigned int get_feature_stage (unsigned int table_index, hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->stage[table_index] : (unsigned int) -1;
-  }
-
-  inline void get_stage_lookups (unsigned int table_index, unsigned int stage,
-				 const struct lookup_map_t **plookups, unsigned int *lookup_count) const {
-    if (unlikely (stage == (unsigned int) -1)) {
-      *plookups = nullptr;
-      *lookup_count = 0;
-      return;
-    }
-    assert (stage <= stages[table_index].len);
-    unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0;
-    unsigned int end   = stage < stages[table_index].len ? stages[table_index][stage].last_lookup : lookups[table_index].len;
-    *plookups = end == start ? nullptr : &lookups[table_index][start];
-    *lookup_count = end - start;
-  }
-
-  HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
-  template <typename Proxy>
-  HB_INTERNAL inline void apply (const Proxy &proxy,
-				 const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
-  HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
-  HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
-
-  inline void finish (void) {
-    features.finish ();
-    for (unsigned int table_index = 0; table_index < 2; table_index++)
-    {
-      lookups[table_index].finish ();
-      stages[table_index].finish ();
-    }
-  }
-
-  public:
-  hb_tag_t chosen_script[2];
-  bool found_script[2];
-
-  private:
-
-  hb_mask_t global_mask;
-
-  hb_prealloced_array_t<feature_map_t, 8> features;
-  hb_prealloced_array_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */
-  hb_prealloced_array_t<stage_map_t, 4> stages[2]; /* GSUB/GPOS */
-};
-
-enum hb_ot_map_feature_flags_t {
-  F_NONE		= 0x0000u,
-  F_GLOBAL		= 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */
-  F_HAS_FALLBACK	= 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */
-  F_MANUAL_ZWNJ		= 0x0004u, /* Don't skip over ZWNJ when matching **context**. */
-  F_MANUAL_ZWJ		= 0x0008u, /* Don't skip over ZWJ when matching **input**. */
-  F_GLOBAL_SEARCH	= 0x0010u  /* If feature not found in LangSys, look for it in global feature list and pick one. */
-};
-HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
-/* Macro version for where const is desired. */
-#define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r)))
-
-
-struct hb_ot_map_builder_t
-{
-  public:
-
-  HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_,
-				   const hb_segment_properties_t *props_);
-
-  HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value,
-				hb_ot_map_feature_flags_t flags);
-
-  inline void add_global_bool_feature (hb_tag_t tag)
-  { add_feature (tag, 1, F_GLOBAL); }
-
-  inline void add_gsub_pause (hb_ot_map_t::pause_func_t pause_func)
-  { add_pause (0, pause_func); }
-  inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func)
-  { add_pause (1, pause_func); }
-
-  HB_INTERNAL void compile (hb_ot_map_t  &m,
-			    const int    *coords,
-			    unsigned int  num_coords);
-
-  inline void finish (void) {
-    feature_infos.finish ();
-    for (unsigned int table_index = 0; table_index < 2; table_index++)
-    {
-      stages[table_index].finish ();
-    }
-  }
-
-  private:
-
-  HB_INTERNAL void add_lookups (hb_ot_map_t  &m,
-				unsigned int  table_index,
-				unsigned int  feature_index,
-				unsigned int  variations_index,
-				hb_mask_t     mask,
-				bool          auto_zwnj = true,
-				bool          auto_zwj = true);
-
-  struct feature_info_t {
-    hb_tag_t tag;
-    unsigned int seq; /* sequence#, used for stable sorting only */
-    unsigned int max_value;
-    hb_ot_map_feature_flags_t flags;
-    unsigned int default_value; /* for non-global features, what should the unset glyphs take */
-    unsigned int stage[2]; /* GSUB/GPOS */
-
-    static int cmp (const void *pa, const void *pb)
-    {
-      const feature_info_t *a = (const feature_info_t *) pa;
-      const feature_info_t *b = (const feature_info_t *) pb;
-      return (a->tag != b->tag) ?  (a->tag < b->tag ? -1 : 1) :
-	     (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
-    }
-  };
-
-  struct stage_info_t {
-    unsigned int index;
-    hb_ot_map_t::pause_func_t pause_func;
-  };
-
-  HB_INTERNAL void add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func);
-
-  public:
-
-  hb_face_t *face;
-  hb_segment_properties_t props;
-
-  hb_tag_t chosen_script[2];
-  bool found_script[2];
-  unsigned int script_index[2], language_index[2];
-
-  private:
-
-  unsigned int current_stage[2]; /* GSUB/GPOS */
-  hb_prealloced_array_t<feature_info_t, 32> feature_infos;
-  hb_prealloced_array_t<stage_info_t, 8> stages[2]; /* GSUB/GPOS */
-};
-
-
-
-#endif /* HB_OT_MAP_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-map.cc b/third_party/harfbuzz-ng/src/hb-ot-map.cc
deleted file mode 100644
index 54b0ce377..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-map.cc
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2010,2011,2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-map-private.hh"
-
-#include "hb-ot-layout-private.hh"
-
-
-void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const
-{
-  for (unsigned int i = 0; i < lookups[table_index].len; i++)
-    hb_set_add (lookups_out, lookups[table_index][i].index);
-}
-
-
-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));
-
-  face = face_;
-  props = *props_;
-
-
-  /* Fetch script/language indices for GSUB/GPOS.  We need these later to skip
-   * features not available in either table and not waste precious bits for them. */
-
-  hb_tag_t script_tags[3] = {HB_TAG_NONE, HB_TAG_NONE, HB_TAG_NONE};
-  hb_tag_t language_tag;
-
-  hb_ot_tags_from_script (props.script, &script_tags[0], &script_tags[1]);
-  language_tag = hb_ot_tag_from_language (props.language);
-
-  for (unsigned int table_index = 0; table_index < 2; table_index++) {
-    hb_tag_t table_tag = table_tags[table_index];
-    found_script[table_index] = (bool) hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]);
-    hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
-  }
-}
-
-void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value,
-				       hb_ot_map_feature_flags_t flags)
-{
-  feature_info_t *info = feature_infos.push();
-  if (unlikely (!info)) return;
-  if (unlikely (!tag)) return;
-  info->tag = tag;
-  info->seq = feature_infos.len;
-  info->max_value = value;
-  info->flags = flags;
-  info->default_value = (flags & F_GLOBAL) ? value : 0;
-  info->stage[0] = current_stage[0];
-  info->stage[1] = current_stage[1];
-}
-
-void
-hb_ot_map_builder_t::add_lookups (hb_ot_map_t  &m,
-				  unsigned int  table_index,
-				  unsigned int  feature_index,
-				  unsigned int  variations_index,
-				  hb_mask_t     mask,
-				  bool          auto_zwnj,
-				  bool          auto_zwj)
-{
-  unsigned int lookup_indices[32];
-  unsigned int offset, len;
-  unsigned int table_lookup_count;
-
-  table_lookup_count = hb_ot_layout_table_get_lookup_count (face, table_tags[table_index]);
-
-  offset = 0;
-  do {
-    len = ARRAY_LENGTH (lookup_indices);
-    hb_ot_layout_feature_with_variations_get_lookups (face,
-						      table_tags[table_index],
-						      feature_index,
-						      variations_index,
-						      offset, &len,
-						      lookup_indices);
-
-    for (unsigned int i = 0; i < len; i++)
-    {
-      if (lookup_indices[i] >= table_lookup_count)
-	continue;
-      hb_ot_map_t::lookup_map_t *lookup = m.lookups[table_index].push ();
-      if (unlikely (!lookup))
-        return;
-      lookup->mask = mask;
-      lookup->index = lookup_indices[i];
-      lookup->auto_zwnj = auto_zwnj;
-      lookup->auto_zwj = auto_zwj;
-    }
-
-    offset += len;
-  } while (len == ARRAY_LENGTH (lookup_indices));
-}
-
-
-void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func)
-{
-  stage_info_t *s = stages[table_index].push ();
-  if (likely (s)) {
-    s->index = current_stage[table_index];
-    s->pause_func = pause_func;
-  }
-
-  current_stage[table_index]++;
-}
-
-void
-hb_ot_map_builder_t::compile (hb_ot_map_t  &m,
-			      const int    *coords,
-			      unsigned int  num_coords)
-{
-  static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
-  unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1;
-  unsigned int global_bit_shift = _hb_popcount (HB_GLYPH_FLAG_DEFINED);
-
-  m.global_mask = global_bit_mask;
-
-  unsigned int required_feature_index[2];
-  hb_tag_t required_feature_tag[2];
-  /* We default to applying required feature in stage 0.  If the required
-   * feature has a tag that is known to the shaper, we apply required feature
-   * in the stage for that tag.
-   */
-  unsigned int required_feature_stage[2] = {0, 0};
-
-  for (unsigned int table_index = 0; table_index < 2; table_index++)
-  {
-    m.chosen_script[table_index] = chosen_script[table_index];
-    m.found_script[table_index] = found_script[table_index];
-
-    hb_ot_layout_language_get_required_feature (face,
-						table_tags[table_index],
-						script_index[table_index],
-						language_index[table_index],
-						&required_feature_index[table_index],
-						&required_feature_tag[table_index]);
-  }
-
-  if (!feature_infos.len)
-    return;
-
-  /* Sort features and merge duplicates */
-  {
-    feature_infos.qsort ();
-    unsigned int j = 0;
-    for (unsigned int i = 1; i < feature_infos.len; i++)
-      if (feature_infos[i].tag != feature_infos[j].tag)
-	feature_infos[++j] = feature_infos[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;
-	} else {
-	  feature_infos[j].flags &= ~F_GLOBAL;
-	  feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_infos[i].max_value);
-	  /* Inherit default_value from j */
-	}
-	feature_infos[j].flags |= (feature_infos[i].flags & F_HAS_FALLBACK);
-	feature_infos[j].stage[0] = MIN (feature_infos[j].stage[0], feature_infos[i].stage[0]);
-	feature_infos[j].stage[1] = MIN (feature_infos[j].stage[1], feature_infos[i].stage[1]);
-      }
-    feature_infos.shrink (j + 1);
-  }
-
-
-  /* Allocate bits now */
-  unsigned int next_bit = global_bit_shift + 1;
-
-  for (unsigned int i = 0; i < feature_infos.len; i++)
-  {
-    const feature_info_t *info = &feature_infos[i];
-
-    unsigned int bits_needed;
-
-    if ((info->flags & F_GLOBAL) && info->max_value == 1)
-      /* Uses the global bit */
-      bits_needed = 0;
-    else
-      /* Limit to 8 bits per feature. */
-      bits_needed = MIN(8u, _hb_bit_storage (info->max_value));
-
-    if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
-      continue; /* Feature disabled, or not enough bits. */
-
-
-    hb_bool_t found = false;
-    unsigned int feature_index[2];
-    for (unsigned int table_index = 0; table_index < 2; table_index++)
-    {
-      if (required_feature_tag[table_index] == info->tag)
-	required_feature_stage[table_index] = info->stage[table_index];
-
-      found |= hb_ot_layout_language_find_feature (face,
-						   table_tags[table_index],
-						   script_index[table_index],
-						   language_index[table_index],
-						   info->tag,
-						   &feature_index[table_index]);
-    }
-    if (!found && (info->flags & F_GLOBAL_SEARCH))
-    {
-      for (unsigned int table_index = 0; table_index < 2; table_index++)
-      {
-	found |= hb_ot_layout_table_find_feature (face,
-						  table_tags[table_index],
-						  info->tag,
-						  &feature_index[table_index]);
-      }
-    }
-    if (!found && !(info->flags & F_HAS_FALLBACK))
-      continue;
-
-
-    hb_ot_map_t::feature_map_t *map = m.features.push ();
-    if (unlikely (!map))
-      break;
-
-    map->tag = info->tag;
-    map->index[0] = feature_index[0];
-    map->index[1] = feature_index[1];
-    map->stage[0] = info->stage[0];
-    map->stage[1] = info->stage[1];
-    map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ);
-    map->auto_zwj = !(info->flags & F_MANUAL_ZWJ);
-    if ((info->flags & F_GLOBAL) && info->max_value == 1) {
-      /* Uses the global bit */
-      map->shift = global_bit_shift;
-      map->mask = global_bit_mask;
-    } else {
-      map->shift = next_bit;
-      map->mask = (1u << (next_bit + bits_needed)) - (1u << next_bit);
-      next_bit += bits_needed;
-      m.global_mask |= (info->default_value << map->shift) & map->mask;
-    }
-    map->_1_mask = (1u << map->shift) & map->mask;
-    map->needs_fallback = !found;
-
-  }
-  feature_infos.shrink (0); /* Done with these */
-
-
-  add_gsub_pause (nullptr);
-  add_gpos_pause (nullptr);
-
-  for (unsigned int table_index = 0; table_index < 2; table_index++)
-  {
-    /* Collect lookup indices for features */
-
-    unsigned int variations_index;
-    hb_ot_layout_table_find_feature_variations (face,
-						table_tags[table_index],
-						coords,
-						num_coords,
-						&variations_index);
-
-    unsigned int stage_index = 0;
-    unsigned int last_num_lookups = 0;
-    for (unsigned stage = 0; stage < current_stage[table_index]; stage++)
-    {
-      if (required_feature_index[table_index] != HB_OT_LAYOUT_NO_FEATURE_INDEX &&
-	  required_feature_stage[table_index] == stage)
-	add_lookups (m, table_index,
-		     required_feature_index[table_index],
-		     variations_index,
-		     global_bit_mask);
-
-      for (unsigned i = 0; i < m.features.len; i++)
-        if (m.features[i].stage[table_index] == stage)
-	  add_lookups (m, table_index,
-		       m.features[i].index[table_index],
-		       variations_index,
-		       m.features[i].mask,
-		       m.features[i].auto_zwnj,
-		       m.features[i].auto_zwj);
-
-      /* Sort lookups and merge duplicates */
-      if (last_num_lookups < m.lookups[table_index].len)
-      {
-	m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].len);
-
-	unsigned int j = last_num_lookups;
-	for (unsigned int i = j + 1; i < m.lookups[table_index].len; i++)
-	  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);
-      }
-
-      last_num_lookups = m.lookups[table_index].len;
-
-      if (stage_index < stages[table_index].len && stages[table_index][stage_index].index == stage) {
-	hb_ot_map_t::stage_map_t *stage_map = m.stages[table_index].push ();
-	if (likely (stage_map)) {
-	  stage_map->last_lookup = last_num_lookups;
-	  stage_map->pause_func = stages[table_index][stage_index].pause_func;
-	}
-
-	stage_index++;
-      }
-    }
-  }
-}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-math-table.hh b/third_party/harfbuzz-ng/src/hb-ot-math-table.hh
deleted file mode 100644
index 571ce01b..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-math-table.hh
+++ /dev/null
@@ -1,722 +0,0 @@
-/*
- * Copyright © 2016  Igalia S.L.
- *
- *  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.
- *
- * Igalia Author(s): Frédéric Wang
- */
-
-#ifndef HB_OT_MATH_TABLE_HH
-#define HB_OT_MATH_TABLE_HH
-
-#include "hb-open-type-private.hh"
-#include "hb-ot-layout-common-private.hh"
-#include "hb-ot-math.h"
-
-namespace OT {
-
-
-struct MathValueRecord
-{
-  inline hb_position_t get_x_value (hb_font_t *font, const void *base) const
-  { return font->em_scale_x (value) + (base+deviceTable).get_x_delta (font); }
-  inline hb_position_t get_y_value (hb_font_t *font, const void *base) const
-  { return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && deviceTable.sanitize (c, base));
-  }
-
-  protected:
-  HBINT16			value;		/* The X or Y value in design units */
-  OffsetTo<Device>	deviceTable;	/* Offset to the device table - from the
-					 * beginning of parent table. May be nullptr.
-					 * Suggested format for device table is 1. */
-
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-struct MathConstants
-{
-  inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-
-    unsigned int count = ARRAY_LENGTH (mathValueRecords);
-    for (unsigned int i = 0; i < count; i++)
-      if (!mathValueRecords[i].sanitize (c, this))
-	return_trace (false);
-
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && sanitize_math_value_records(c));
-  }
-
-  inline hb_position_t get_value (hb_ot_math_constant_t constant,
-				  hb_font_t *font) const
-  {
-    switch (constant) {
-
-    case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN:
-    case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN:
-      return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN];
-
-    case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT:
-    case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT:
-      return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]);
-
-    case HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE:
-    case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE:
-    case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP:
-    case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT:
-      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value(font, this);
-
-    case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT:
-    case HB_OT_MATH_CONSTANT_AXIS_HEIGHT:
-    case HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT:
-    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN:
-    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN:
-    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN:
-    case HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN:
-    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP:
-    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN:
-    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP:
-    case HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN:
-    case HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS:
-    case HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN:
-    case HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN:
-    case HB_OT_MATH_CONSTANT_MATH_LEADING:
-    case HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER:
-    case HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS:
-    case HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP:
-    case HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP:
-    case HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER:
-    case HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS:
-    case HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP:
-    case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP:
-    case HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN:
-    case HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN:
-    case HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN:
-    case HB_OT_MATH_CONSTANT_STACK_GAP_MIN:
-    case HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP:
-    case HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP:
-    case HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN:
-    case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN:
-    case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN:
-    case HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP:
-    case HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN:
-    case HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN:
-    case HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX:
-    case HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN:
-    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX:
-    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT:
-    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN:
-    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP:
-    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED:
-    case HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER:
-    case HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS:
-    case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP:
-    case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN:
-    case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN:
-      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this);
-
-    case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT:
-      return radicalDegreeBottomRaisePercent;
-
-    default:
-      return 0;
-    }
-  }
-
-  protected:
-  HBINT16 percentScaleDown[2];
-  HBUINT16 minHeight[2];
-  MathValueRecord mathValueRecords[51];
-  HBINT16 radicalDegreeBottomRaisePercent;
-
-  public:
-  DEFINE_SIZE_STATIC (214);
-};
-
-struct MathItalicsCorrectionInfo
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  coverage.sanitize (c, this) &&
-		  italicsCorrection.sanitize (c, this));
-  }
-
-  inline hb_position_t get_value (hb_codepoint_t glyph,
-				  hb_font_t *font) const
-  {
-    unsigned int index = (this+coverage).get_coverage (glyph);
-    return italicsCorrection[index].get_x_value (font, this);
-  }
-
-  protected:
-  OffsetTo<Coverage>       coverage;		/* Offset to Coverage table -
-						 * from the beginning of
-						 * MathItalicsCorrectionInfo
-						 * table. */
-  ArrayOf<MathValueRecord> italicsCorrection;	/* Array of MathValueRecords
-						 * defining italics correction
-						 * values for each
-						 * covered glyph. */
-
-  public:
-  DEFINE_SIZE_ARRAY (4, italicsCorrection);
-};
-
-struct MathTopAccentAttachment
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  topAccentCoverage.sanitize (c, this) &&
-		  topAccentAttachment.sanitize (c, this));
-  }
-
-  inline hb_position_t get_value (hb_codepoint_t glyph,
-				  hb_font_t *font) const
-  {
-    unsigned int index = (this+topAccentCoverage).get_coverage (glyph);
-    if (index == NOT_COVERED)
-      return font->get_glyph_h_advance (glyph) / 2;
-    return topAccentAttachment[index].get_x_value(font, this);
-  }
-
-  protected:
-  OffsetTo<Coverage>       topAccentCoverage;   /* Offset to Coverage table -
-						 * from the beginning of
-						 * MathTopAccentAttachment
-						 * table. */
-  ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
-						 * defining top accent
-						 * attachment points for each
-						 * covered glyph. */
-
-  public:
-  DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment);
-};
-
-struct MathKern
-{
-  inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    unsigned int count = 2 * heightCount + 1;
-    for (unsigned int i = 0; i < count; i++)
-      if (!mathValueRecords[i].sanitize (c, this)) return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  c->check_array (mathValueRecords,
-				  mathValueRecords[0].static_size,
-				  2 * heightCount + 1) &&
-		  sanitize_math_value_records (c));
-  }
-
-  inline hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const
-  {
-    const MathValueRecord* correctionHeight = mathValueRecords;
-    const MathValueRecord* kernValue = mathValueRecords + heightCount;
-    int sign = font->y_scale < 0 ? -1 : +1;
-
-    /* The description of the MathKern table is a ambiguous, but interpreting
-     * "between the two heights found at those indexes" for 0 < i < len as
-     *
-     *   correctionHeight[i-1] < correction_height <= correctionHeight[i]
-     *
-     * makes the result consistent with the limit cases and we can just use the
-     * binary search algorithm of std::upper_bound:
-     */
-    unsigned int i = 0;
-    unsigned int count = heightCount;
-    while (count > 0)
-    {
-      unsigned int half = count / 2;
-      hb_position_t height = correctionHeight[i + half].get_y_value(font, this);
-      if (sign * height < sign * correction_height)
-      {
-	i += half + 1;
-	count -= half + 1;
-      } else
-	count = half;
-    }
-    return kernValue[i].get_x_value(font, this);
-  }
-
-  protected:
-  HBUINT16	  heightCount;
-  MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
-					  * which the kern value changes.
-					  * Sorted by the height value in
-					  * design units (heightCount entries),
-					  * Followed by:
-					  * Array of kern values corresponding
-					  * to heights. (heightCount+1 entries).
-					  */
-
-  public:
-  DEFINE_SIZE_ARRAY (2, mathValueRecords);
-};
-
-struct MathKernInfoRecord
-{
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-
-    unsigned int count = ARRAY_LENGTH (mathKern);
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!mathKern[i].sanitize (c, base)))
-	return_trace (false);
-
-    return_trace (true);
-  }
-
-  inline hb_position_t get_kerning (hb_ot_math_kern_t kern,
-				    hb_position_t correction_height,
-				    hb_font_t *font,
-				    const void *base) const
-  {
-    unsigned int idx = kern;
-    if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0;
-    return (base+mathKern[idx]).get_value (correction_height, font);
-  }
-
-  protected:
-  /* Offset to MathKern table for each corner -
-   * from the beginning of MathKernInfo table. May be nullptr. */
-  OffsetTo<MathKern> mathKern[4];
-
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct MathKernInfo
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  mathKernCoverage.sanitize (c, this) &&
-		  mathKernInfoRecords.sanitize (c, this));
-  }
-
-  inline hb_position_t get_kerning (hb_codepoint_t glyph,
-				    hb_ot_math_kern_t kern,
-				    hb_position_t correction_height,
-				    hb_font_t *font) const
-  {
-    unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
-    return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this);
-  }
-
-  protected:
-  OffsetTo<Coverage>		mathKernCoverage;    /* Offset to Coverage table -
-						      * from the beginning of the
-						      * MathKernInfo table. */
-  ArrayOf<MathKernInfoRecord>	mathKernInfoRecords; /* Array of
-						      * MathKernInfoRecords,
-						      * per-glyph information for
-						      * mathematical positioning
-						      * of subscripts and
-						      * superscripts. */
-
-  public:
-  DEFINE_SIZE_ARRAY (4, mathKernInfoRecords);
-};
-
-struct MathGlyphInfo
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  mathItalicsCorrectionInfo.sanitize (c, this) &&
-		  mathTopAccentAttachment.sanitize (c, this) &&
-		  extendedShapeCoverage.sanitize (c, this) &&
-		  mathKernInfo.sanitize(c, this));
-  }
-
-  inline hb_position_t
-  get_italics_correction (hb_codepoint_t  glyph, hb_font_t *font) const
-  { return (this+mathItalicsCorrectionInfo).get_value (glyph, font); }
-
-  inline hb_position_t
-  get_top_accent_attachment (hb_codepoint_t  glyph, hb_font_t *font) const
-  { return (this+mathTopAccentAttachment).get_value (glyph, font); }
-
-  inline bool is_extended_shape (hb_codepoint_t glyph) const
-  { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; }
-
-  inline hb_position_t get_kerning (hb_codepoint_t glyph,
-				    hb_ot_math_kern_t kern,
-				    hb_position_t correction_height,
-				    hb_font_t *font) const
-  { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); }
-
-  protected:
-  /* Offset to MathItalicsCorrectionInfo table -
-   * from the beginning of MathGlyphInfo table. */
-  OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
-
-  /* Offset to MathTopAccentAttachment table -
-   * from the beginning of MathGlyphInfo table. */
-  OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment;
-
-  /* Offset to coverage table for Extended Shape glyphs -
-   * from the beginning of MathGlyphInfo table. When the left or right glyph of
-   * a box is an extended shape variant, the (ink) box (and not the default
-   * position defined by values in MathConstants table) should be used for
-   * vertical positioning purposes. May be nullptr.. */
-  OffsetTo<Coverage> extendedShapeCoverage;
-
-   /* Offset to MathKernInfo table -
-    * from the beginning of MathGlyphInfo table. */
-  OffsetTo<MathKernInfo> mathKernInfo;
-
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct MathGlyphVariantRecord
-{
-  friend struct MathGlyphConstruction;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  GlyphID variantGlyph;       /* Glyph ID for the variant. */
-  HBUINT16  advanceMeasurement; /* Advance width/height, in design units, of the
-			       * variant, in the direction of requested
-			       * glyph extension. */
-
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-struct PartFlags : HBUINT16
-{
-  enum Flags {
-    Extender	= 0x0001u, /* If set, the part can be skipped or repeated. */
-
-    Defined	= 0x0001u, /* All defined flags. */
-  };
-
-  public:
-  DEFINE_SIZE_STATIC (2);
-};
-
-struct MathGlyphPartRecord
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  inline void extract (hb_ot_math_glyph_part_t &out,
-		       int scale,
-		       hb_font_t *font) const
-  {
-    out.glyph			= glyph;
-
-    out.start_connector_length	= font->em_scale (startConnectorLength, scale);
-    out.end_connector_length	= font->em_scale (endConnectorLength, scale);
-    out.full_advance		= font->em_scale (fullAdvance, scale);
-
-    static_assert ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER ==
-		   (unsigned int) PartFlags::Extender, "");
-
-    out.flags = (hb_ot_math_glyph_part_flags_t)
-		(unsigned int)
-		(partFlags & PartFlags::Defined);
-  }
-
-  protected:
-  GlyphID   glyph;		  /* Glyph ID for the part. */
-  HBUINT16    startConnectorLength; /* Advance width/ height of the straight bar
-				   * connector material, in design units, is at
-				   * the beginning of the glyph, in the
-				   * direction of the extension. */
-  HBUINT16    endConnectorLength;   /* Advance width/ height of the straight bar
-				   * connector material, in design units, is at
-				   * the end of the glyph, in the direction of
-				   * the extension. */
-  HBUINT16    fullAdvance;	  /* Full advance width/height for this part,
-				   * in the direction of the extension.
-				   * In design units. */
-  PartFlags partFlags;		  /* Part qualifiers. */
-
-  public:
-  DEFINE_SIZE_STATIC (10);
-};
-
-struct MathGlyphAssembly
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  italicsCorrection.sanitize(c, this) &&
-		  partRecords.sanitize(c));
-  }
-
-  inline unsigned int get_parts (hb_direction_t direction,
-				 hb_font_t *font,
-				 unsigned int start_offset,
-				 unsigned int *parts_count, /* IN/OUT */
-				 hb_ot_math_glyph_part_t *parts /* OUT */,
-				 hb_position_t *italics_correction /* OUT */) const
-  {
-    if (parts_count)
-    {
-      int scale = font->dir_scale (direction);
-      const MathGlyphPartRecord *arr =
-	    partRecords.sub_array (start_offset, parts_count);
-      unsigned int count = *parts_count;
-      for (unsigned int i = 0; i < count; i++)
-	arr[i].extract (parts[i], scale, font);
-    }
-
-    if (italics_correction)
-      *italics_correction = italicsCorrection.get_x_value (font, this);
-
-    return partRecords.len;
-  }
-
-  protected:
-  MathValueRecord	   italicsCorrection; /* Italics correction of this
-					       * MathGlyphAssembly. Should not
-					       * depend on the assembly size. */
-  ArrayOf<MathGlyphPartRecord> partRecords;   /* Array of part records, from
-					       * left to right and bottom to
-					       * top. */
-
-  public:
-  DEFINE_SIZE_ARRAY (6, partRecords);
-};
-
-struct MathGlyphConstruction
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  glyphAssembly.sanitize(c, this) &&
-		  mathGlyphVariantRecord.sanitize(c));
-  }
-
-  inline const MathGlyphAssembly &get_assembly (void) const
-  { return this+glyphAssembly; }
-
-  inline unsigned int get_variants (hb_direction_t direction,
-				    hb_font_t *font,
-				    unsigned int start_offset,
-				    unsigned int *variants_count, /* IN/OUT */
-				    hb_ot_math_glyph_variant_t *variants /* OUT */) const
-  {
-    if (variants_count)
-    {
-      int scale = font->dir_scale (direction);
-      const MathGlyphVariantRecord *arr =
-	    mathGlyphVariantRecord.sub_array (start_offset, variants_count);
-      unsigned int count = *variants_count;
-      for (unsigned int i = 0; i < count; i++)
-      {
-	variants[i].glyph = arr[i].variantGlyph;
-	variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale);
-      }
-    }
-    return mathGlyphVariantRecord.len;
-  }
-
-  protected:
-  /* Offset to MathGlyphAssembly table for this shape - from the beginning of
-     MathGlyphConstruction table. May be nullptr. */
-  OffsetTo<MathGlyphAssembly>	  glyphAssembly;
-
-  /* MathGlyphVariantRecords for alternative variants of the glyphs. */
-  ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord;
-
-  public:
-  DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord);
-};
-
-struct MathVariants
-{
-  inline bool sanitize_offsets (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    unsigned int count = vertGlyphCount + horizGlyphCount;
-    for (unsigned int i = 0; i < count; i++)
-      if (!glyphConstruction[i].sanitize (c, this)) return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  vertGlyphCoverage.sanitize (c, this) &&
-		  horizGlyphCoverage.sanitize (c, this) &&
-		  c->check_array (glyphConstruction,
-				  glyphConstruction[0].static_size,
-				  vertGlyphCount + horizGlyphCount) &&
-		  sanitize_offsets (c));
-  }
-
-  inline hb_position_t get_min_connector_overlap (hb_direction_t direction,
-						  hb_font_t *font) const
-  { return font->em_scale_dir (minConnectorOverlap, direction); }
-
-  inline unsigned int get_glyph_variants (hb_codepoint_t glyph,
-					  hb_direction_t direction,
-					  hb_font_t *font,
-					  unsigned int start_offset,
-					  unsigned int *variants_count, /* IN/OUT */
-					  hb_ot_math_glyph_variant_t *variants /* OUT */) const
-  { return get_glyph_construction (glyph, direction, font)
-	   .get_variants (direction, font, start_offset, variants_count, variants); }
-
-  inline unsigned int get_glyph_parts (hb_codepoint_t glyph,
-				       hb_direction_t direction,
-				       hb_font_t *font,
-				       unsigned int start_offset,
-				       unsigned int *parts_count, /* IN/OUT */
-				       hb_ot_math_glyph_part_t *parts /* OUT */,
-				       hb_position_t *italics_correction /* OUT */) const
-  { return get_glyph_construction (glyph, direction, font)
-	   .get_assembly ()
-	   .get_parts (direction, font,
-		       start_offset, parts_count, parts,
-		       italics_correction); }
-
-  private:
-  inline const MathGlyphConstruction &
-		get_glyph_construction (hb_codepoint_t glyph,
-					hb_direction_t direction,
-					hb_font_t *font) const
-  {
-    bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
-    unsigned int count = vertical ? vertGlyphCount : horizGlyphCount;
-    const OffsetTo<Coverage> &coverage = vertical ? vertGlyphCoverage
-						  : horizGlyphCoverage;
-
-    unsigned int index = (this+coverage).get_coverage (glyph);
-    if (unlikely (index >= count)) return Null(MathGlyphConstruction);
-
-    if (!vertical)
-      index += vertGlyphCount;
-
-    return this+glyphConstruction[index];
-  }
-
-  protected:
-  HBUINT16	     minConnectorOverlap; /* Minimum overlap of connecting
-					   * glyphs during glyph construction,
-					   * in design units. */
-  OffsetTo<Coverage> vertGlyphCoverage;   /* Offset to Coverage table -
-					   * from the beginning of MathVariants
-					   * table. */
-  OffsetTo<Coverage> horizGlyphCoverage;  /* Offset to Coverage table -
-					   * from the beginning of MathVariants
-					   * table. */
-  HBUINT16	     vertGlyphCount;      /* Number of glyphs for which
-					   * information is provided for
-					   * vertically growing variants. */
-  HBUINT16	     horizGlyphCount;     /* Number of glyphs for which
-					   * information is provided for
-					   * horizontally growing variants. */
-
-  /* Array of offsets to MathGlyphConstruction tables - from the beginning of
-     the MathVariants table, for shapes growing in vertical/horizontal
-     direction. */
-  OffsetTo<MathGlyphConstruction> glyphConstruction[VAR];
-
-  public:
-  DEFINE_SIZE_ARRAY (10, glyphConstruction);
-};
-
-
-/*
- * MATH -- The MATH Table
- */
-
-struct MATH
-{
-  static const hb_tag_t tableTag	= HB_OT_TAG_MATH;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  mathConstants.sanitize (c, this) &&
-		  mathGlyphInfo.sanitize (c, this) &&
-		  mathVariants.sanitize (c, this));
-  }
-
-  inline hb_position_t get_constant (hb_ot_math_constant_t  constant,
-				     hb_font_t		   *font) const
-  { return (this+mathConstants).get_value (constant, font); }
-
-  inline const MathGlyphInfo &get_math_glyph_info (void) const
-  { return this+mathGlyphInfo; }
-
-  inline const MathVariants &get_math_variants (void) const
-  { return this+mathVariants; }
-
-  protected:
-  FixedVersion<>version;		/* Version of the MATH table
-					 * initially set to 0x00010000u */
-  OffsetTo<MathConstants> mathConstants;/* MathConstants table */
-  OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */
-  OffsetTo<MathVariants>  mathVariants;	/* MathVariants table */
-
-  public:
-  DEFINE_SIZE_STATIC (10);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_MATH_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-math.cc b/third_party/harfbuzz-ng/src/hb-ot-math.cc
deleted file mode 100644
index f82a073..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-math.cc
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright © 2016  Igalia S.L.
- *
- *  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.
- *
- * Igalia Author(s): Frédéric Wang
- */
-
-#include "hb-open-type-private.hh"
-
-#include "hb-ot-layout-private.hh"
-#include "hb-ot-math-table.hh"
-
-static inline const OT::MATH&
-_get_math (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->math.get ());
-}
-
-/*
- * OT::MATH
- */
-
-/**
- * hb_ot_math_has_data:
- * @face: #hb_face_t to test
- *
- * This function allows to verify the presence of an OpenType MATH table on the
- * face.
- *
- * Return value: true if face has a MATH table, false otherwise
- *
- * Since: 1.3.3
- **/
-hb_bool_t
-hb_ot_math_has_data (hb_face_t *face)
-{
-  return &_get_math (face) != &OT::Null(OT::MATH);
-}
-
-/**
- * hb_ot_math_get_constant:
- * @font: #hb_font_t from which to retrieve the value
- * @constant: #hb_ot_math_constant_t the constant to retrieve
- *
- * This function returns the requested math constants as a #hb_position_t.
- * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN,
- * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or
- * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is
- * actually an integer between 0 and 100 representing that percentage.
- *
- * Return value: the requested constant or 0
- *
- * Since: 1.3.3
- **/
-hb_position_t
-hb_ot_math_get_constant (hb_font_t *font,
-			 hb_ot_math_constant_t constant)
-{
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_constant(constant, font);
-}
-
-/**
- * hb_ot_math_get_glyph_italics_correction:
- * @font: #hb_font_t from which to retrieve the value
- * @glyph: glyph index from which to retrieve the value
- *
- * Return value: the italics correction of the glyph or 0
- *
- * Since: 1.3.3
- **/
-hb_position_t
-hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
-					 hb_codepoint_t glyph)
-{
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_math_glyph_info().get_italics_correction (glyph, font);
-}
-
-/**
- * hb_ot_math_get_glyph_top_accent_attachment:
- * @font: #hb_font_t from which to retrieve the value
- * @glyph: glyph index from which to retrieve the value
- *
- * Return value: the top accent attachment of the glyph or 0
- *
- * Since: 1.3.3
- **/
-hb_position_t
-hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
-					    hb_codepoint_t glyph)
-{
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_math_glyph_info().get_top_accent_attachment (glyph, font);
-}
-
-/**
- * hb_ot_math_is_glyph_extended_shape:
- * @face: a #hb_face_t to test
- * @glyph: a glyph index to test
- *
- * Return value: true if the glyph is an extended shape, false otherwise
- *
- * Since: 1.3.3
- **/
-hb_bool_t
-hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
-				    hb_codepoint_t glyph)
-{
-  const OT::MATH &math = _get_math (face);
-  return math.get_math_glyph_info().is_extended_shape (glyph);
-}
-
-/**
- * hb_ot_math_get_glyph_kerning:
- * @font: #hb_font_t from which to retrieve the value
- * @glyph: glyph index from which to retrieve the value
- * @kern: the #hb_ot_math_kern_t from which to retrieve the value
- * @correction_height: the correction height to use to determine the kerning.
- *
- * This function tries to retrieve the MathKern table for the specified font,
- * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the
- * MathKern table to find one value that is greater or equal to specified
- * correction_height. If one is found the corresponding value from the list of
- * kerns is returned and otherwise the last kern value is returned.
- *
- * Return value: requested kerning or 0
- *
- * Since: 1.3.3
- **/
-hb_position_t
-hb_ot_math_get_glyph_kerning (hb_font_t *font,
-			      hb_codepoint_t glyph,
-			      hb_ot_math_kern_t kern,
-			      hb_position_t correction_height)
-{
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font);
-}
-
-/**
- * hb_ot_math_get_glyph_variants:
- * @font: #hb_font_t from which to retrieve the values
- * @glyph: index of the glyph to stretch
- * @direction: direction of the stretching
- * @start_offset: offset of the first variant to retrieve
- * @variants_count: maximum number of variants to retrieve after start_offset
- * (IN) and actual number of variants retrieved (OUT)
- * @variants: array of size at least @variants_count to store the result
- *
- * This function tries to retrieve the MathGlyphConstruction for the specified
- * font, glyph and direction. Note that only the value of
- * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list
- * of size variants as an array of hb_ot_math_glyph_variant_t structs.
- *
- * Return value: the total number of size variants available or 0
- *
- * Since: 1.3.3
- **/
-unsigned int
-hb_ot_math_get_glyph_variants (hb_font_t *font,
-			       hb_codepoint_t glyph,
-			       hb_direction_t direction,
-			       unsigned int start_offset,
-			       unsigned int *variants_count, /* IN/OUT */
-			       hb_ot_math_glyph_variant_t *variants /* OUT */)
-{
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_math_variants().get_glyph_variants (glyph, direction, font,
-						      start_offset,
-						      variants_count,
-						      variants);
-}
-
-/**
- * hb_ot_math_get_min_connector_overlap:
- * @font: #hb_font_t from which to retrieve the value
- * @direction: direction of the stretching
- *
- * This function tries to retrieve the MathVariants table for the specified
- * font and returns the minimum overlap of connecting glyphs to draw a glyph
- * assembly in the specified direction. Note that only the value of
- * #HB_DIRECTION_IS_HORIZONTAL is considered.
- *
- * Return value: requested min connector overlap or 0
- *
- * Since: 1.3.3
- **/
-hb_position_t
-hb_ot_math_get_min_connector_overlap (hb_font_t *font,
-				      hb_direction_t direction)
-{
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_math_variants().get_min_connector_overlap (direction, font);
-}
-
-/**
- * hb_ot_math_get_glyph_assembly:
- * @font: #hb_font_t from which to retrieve the values
- * @glyph: index of the glyph to stretch
- * @direction: direction of the stretching
- * @start_offset: offset of the first glyph part to retrieve
- * @parts_count: maximum number of glyph parts to retrieve after start_offset
- * (IN) and actual number of parts retrieved (OUT)
- * @parts: array of size at least @parts_count to store the result
- * @italics_correction: italic correction of the glyph assembly
- *
- * This function tries to retrieve the GlyphAssembly for the specified font,
- * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL
- * is considered. It provides the information necessary to draw the glyph
- * assembly as an array of #hb_ot_math_glyph_part_t.
- *
- * Return value: the total number of parts in the glyph assembly
- *
- * Since: 1.3.3
- **/
-unsigned int
-hb_ot_math_get_glyph_assembly (hb_font_t *font,
-			       hb_codepoint_t glyph,
-			       hb_direction_t direction,
-			       unsigned int start_offset,
-			       unsigned int *parts_count, /* IN/OUT */
-			       hb_ot_math_glyph_part_t *parts, /* OUT */
-			       hb_position_t *italics_correction /* OUT */)
-{
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_math_variants().get_glyph_parts (glyph, direction, font,
-						   start_offset,
-						   parts_count,
-						   parts,
-						   italics_correction);
-}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-math.h b/third_party/harfbuzz-ng/src/hb-ot-math.h
deleted file mode 100644
index 521a5ca..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-math.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright © 2016  Igalia S.L.
- *
- *  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.
- *
- * Igalia Author(s): Frédéric Wang
- */
-
-#ifndef HB_OT_H_IN
-#error "Include <hb-ot.h> instead."
-#endif
-
-#ifndef HB_OT_MATH_H
-#define HB_OT_MATH_H
-
-#include "hb.h"
-
-HB_BEGIN_DECLS
-
-
-/*
- * MATH
- */
-
-#define HB_OT_TAG_MATH HB_TAG('M','A','T','H')
-
-/* Use with hb_buffer_set_script() for math shaping. */
-#define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h')
-
-/* Types */
-
-/**
- * hb_ot_math_constant_t:
- *
- * Since: 1.3.3
- */
-typedef enum {
-  HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0,
-  HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1,
-  HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT = 2,
-  HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT = 3,
-  HB_OT_MATH_CONSTANT_MATH_LEADING = 4,
-  HB_OT_MATH_CONSTANT_AXIS_HEIGHT = 5,
-  HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT = 6,
-  HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT = 7,
-  HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN = 8,
-  HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX = 9,
-  HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN = 10,
-  HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP = 11,
-  HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED = 12,
-  HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN = 13,
-  HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX = 14,
-  HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN = 15,
-  HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT = 16,
-  HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT = 17,
-  HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN = 18,
-  HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN = 19,
-  HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN = 20,
-  HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN = 21,
-  HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP = 22,
-  HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP = 23,
-  HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN = 24,
-  HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN = 25,
-  HB_OT_MATH_CONSTANT_STACK_GAP_MIN = 26,
-  HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN = 27,
-  HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP = 28,
-  HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN = 29,
-  HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN = 30,
-  HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN = 31,
-  HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP = 32,
-  HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP = 33,
-  HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN = 34,
-  HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN = 35,
-  HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN = 36,
-  HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN = 37,
-  HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS = 38,
-  HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN = 39,
-  HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN = 40,
-  HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP = 41,
-  HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP = 42,
-  HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP = 43,
-  HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS = 44,
-  HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER = 45,
-  HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP = 46,
-  HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS = 47,
-  HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER = 48,
-  HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP = 49,
-  HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP = 50,
-  HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS = 51,
-  HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER = 52,
-  HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE = 53,
-  HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE = 54,
-  HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55
-} hb_ot_math_constant_t;
-
-/**
- * hb_ot_math_kern_t:
- *
- * Since: 1.3.3
- */
-typedef enum {
-  HB_OT_MATH_KERN_TOP_RIGHT = 0,
-  HB_OT_MATH_KERN_TOP_LEFT = 1,
-  HB_OT_MATH_KERN_BOTTOM_RIGHT = 2,
-  HB_OT_MATH_KERN_BOTTOM_LEFT = 3
-} hb_ot_math_kern_t;
-
-/**
- * hb_ot_math_glyph_variant_t:
- *
- * Since: 1.3.3
- */
-typedef struct hb_ot_math_glyph_variant_t {
-  hb_codepoint_t glyph;
-  hb_position_t advance;
-} hb_ot_math_glyph_variant_t;
-
-/**
- * hb_ot_math_glyph_part_flags_t:
- *
- * Since: 1.3.3
- */
-typedef enum { /*< flags >*/
-  HB_MATH_GLYPH_PART_FLAG_EXTENDER	= 0x00000001u  /* Extender glyph */
-} hb_ot_math_glyph_part_flags_t;
-
-/**
- * hb_ot_math_glyph_part_t:
- *
- * Since: 1.3.3
- */
-typedef struct hb_ot_math_glyph_part_t {
-  hb_codepoint_t glyph;
-  hb_position_t start_connector_length;
-  hb_position_t end_connector_length;
-  hb_position_t full_advance;
-  hb_ot_math_glyph_part_flags_t flags;
-} hb_ot_math_glyph_part_t;
-
-/* Methods */
-
-HB_EXTERN hb_bool_t
-hb_ot_math_has_data (hb_face_t *face);
-
-HB_EXTERN hb_position_t
-hb_ot_math_get_constant (hb_font_t *font,
-			 hb_ot_math_constant_t constant);
-
-HB_EXTERN hb_position_t
-hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
-					 hb_codepoint_t glyph);
-
-HB_EXTERN hb_position_t
-hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
-					    hb_codepoint_t glyph);
-
-HB_EXTERN hb_bool_t
-hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
-				    hb_codepoint_t glyph);
-
-HB_EXTERN hb_position_t
-hb_ot_math_get_glyph_kerning (hb_font_t *font,
-			      hb_codepoint_t glyph,
-			      hb_ot_math_kern_t kern,
-			      hb_position_t correction_height);
-
-HB_EXTERN unsigned int
-hb_ot_math_get_glyph_variants (hb_font_t *font,
-			       hb_codepoint_t glyph,
-			       hb_direction_t direction,
-			       unsigned int start_offset,
-			       unsigned int *variants_count, /* IN/OUT */
-			       hb_ot_math_glyph_variant_t *variants /* OUT */);
-
-HB_EXTERN hb_position_t
-hb_ot_math_get_min_connector_overlap (hb_font_t *font,
-				      hb_direction_t direction);
-
-HB_EXTERN unsigned int
-hb_ot_math_get_glyph_assembly (hb_font_t *font,
-			       hb_codepoint_t glyph,
-			       hb_direction_t direction,
-			       unsigned int start_offset,
-			       unsigned int *parts_count, /* IN/OUT */
-			       hb_ot_math_glyph_part_t *parts, /* OUT */
-			       hb_position_t *italics_correction /* OUT */);
-
-
-HB_END_DECLS
-
-#endif /* HB_OT_MATH_H */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh b/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh
deleted file mode 100644
index 881deda..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_MAXP_TABLE_HH
-#define HB_OT_MAXP_TABLE_HH
-
-#include "hb-open-type-private.hh"
-#include "hb-subset-plan.hh"
-
-namespace OT {
-
-
-/*
- * maxp -- The Maximum Profile Table
- */
-
-#define HB_OT_TAG_maxp HB_TAG('m','a','x','p')
-
-struct maxpV1Tail
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  HBUINT16 maxPoints;		  /* Maximum points in a non-composite glyph. */
-  HBUINT16 maxContours;		  /* Maximum contours in a non-composite glyph. */
-  HBUINT16 maxCompositePoints;	  /* Maximum points in a composite glyph. */
-  HBUINT16 maxCompositeContours;  /* Maximum contours in a composite glyph. */
-  HBUINT16 maxZones;		  /* 1 if instructions do not use the twilight zone (Z0),
-				   * or 2 if instructions do use Z0; should be set to 2 in
-				   * most cases. */
-  HBUINT16 maxTwilightPoints;	  /* Maximum points used in Z0. */
-  HBUINT16 maxStorage;		  /* Number of Storage Area locations. */
-  HBUINT16 maxFunctionDefs;	  /* Number of FDEFs, equal to the highest function number + 1. */
-  HBUINT16 maxInstructionDefs;	  /* Number of IDEFs. */
-  HBUINT16 maxStackElements;	  /* Maximum stack depth. (This includes Font and CVT
-				   * Programs, as well as the instructions for each glyph.) */
-  HBUINT16 maxSizeOfInstructions; /* Maximum byte count for glyph instructions. */
-  HBUINT16 maxComponentElements;  /* Maximum number of components referenced at
-				   * "top level" for any composite glyph. */
-  HBUINT16 maxComponentDepth;	  /* Maximum levels of recursion; 1 for simple components. */
- public:
-  DEFINE_SIZE_STATIC (26);
-};
-
-
-struct maxp
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_maxp;
-
-  inline unsigned int get_num_glyphs (void) const
-  {
-    return numGlyphs;
-  }
-
-  inline void set_num_glyphs (unsigned int count)
-  {
-    numGlyphs.set (count);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this)))
-      return_trace (false);
-
-    if (version.major == 1)
-    {
-      const maxpV1Tail &v1 = StructAfter<maxpV1Tail> (*this);
-      return v1.sanitize (c);
-    }
-    return_trace (likely (version.major == 0 && version.minor == 0x5000u));
-  }
-
-  inline bool subset (hb_subset_plan_t *plan) const
-  {
-    hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_maxp));
-    hb_blob_t *maxp_prime_blob = hb_blob_copy_writable_or_fail (maxp_blob);
-    hb_blob_destroy (maxp_blob);
-
-    if (unlikely (!maxp_prime_blob)) {
-      return false;
-    }
-    OT::maxp *maxp_prime = (OT::maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
-
-    maxp_prime->set_num_glyphs (plan->gids_to_retain_sorted.len);
-    if (plan->drop_hints)
-      drop_hint_fields (plan, maxp_prime);
-
-    bool result = hb_subset_plan_add_table(plan, HB_OT_TAG_maxp, maxp_prime_blob);
-    hb_blob_destroy (maxp_prime_blob);
-    return result;
-  }
-
-  static inline void drop_hint_fields (hb_subset_plan_t *plan, OT::maxp *maxp_prime)
-  {
-    if (maxp_prime->version.major == 1)
-    {
-      maxpV1Tail &v1 = StructAfter<maxpV1Tail> (*maxp_prime);
-      v1.maxZones.set (1);
-      v1.maxTwilightPoints.set (0);
-      v1.maxStorage.set (0);
-      v1.maxFunctionDefs.set (0);
-      v1.maxInstructionDefs.set (0);
-      v1.maxStackElements.set (0);
-      v1.maxSizeOfInstructions.set (0);
-    }
-  }
-
-  protected:
-  FixedVersion<>version;		/* Version of the maxp table (0.5 or 1.0),
-					 * 0x00005000u or 0x00010000u. */
-  HBUINT16	numGlyphs;		/* The number of glyphs in the font. */
-/*maxpV1Tail v1Tail[VAR]; */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_MAXP_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-name-table.hh b/third_party/harfbuzz-ng/src/hb-ot-name-table.hh
deleted file mode 100644
index eb013337..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-name-table.hh
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_NAME_TABLE_HH
-#define HB_OT_NAME_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-
-namespace OT {
-
-
-/*
- * name -- The Naming Table
- */
-
-#define HB_OT_TAG_name HB_TAG('n','a','m','e')
-
-
-struct NameRecord
-{
-  static int cmp (const void *pa, const void *pb)
-  {
-    const NameRecord *a = (const NameRecord *) pa;
-    const NameRecord *b = (const NameRecord *) pb;
-    int ret;
-    ret = b->platformID.cmp (a->platformID);
-    if (ret) return ret;
-    ret = b->encodingID.cmp (a->encodingID);
-    if (ret) return ret;
-    ret = b->languageID.cmp (a->languageID);
-    if (ret) return ret;
-    ret = b->nameID.cmp (a->nameID);
-    if (ret) return ret;
-    return 0;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    /* We can check from base all the way up to the end of string... */
-    return_trace (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset));
-  }
-
-  HBUINT16	platformID;	/* Platform ID. */
-  HBUINT16	encodingID;	/* Platform-specific encoding ID. */
-  HBUINT16	languageID;	/* Language ID. */
-  HBUINT16	nameID;		/* Name ID. */
-  HBUINT16	length;		/* String length (in bytes). */
-  HBUINT16	offset;		/* String offset from start of storage area (in bytes). */
-  public:
-  DEFINE_SIZE_STATIC (12);
-};
-
-struct name
-{
-  static const hb_tag_t tableTag	= HB_OT_TAG_name;
-
-  inline unsigned int get_name (unsigned int platform_id,
-				unsigned int encoding_id,
-				unsigned int language_id,
-				unsigned int name_id,
-				void *buffer,
-				unsigned int buffer_length) const
-  {
-    NameRecord key;
-    key.platformID.set (platform_id);
-    key.encodingID.set (encoding_id);
-    key.languageID.set (language_id);
-    key.nameID.set (name_id);
-    NameRecord *match = (NameRecord *) bsearch (&key, nameRecord, count, sizeof (nameRecord[0]), NameRecord::cmp);
-
-    if (!match)
-      return 0;
-
-    unsigned int length = MIN (buffer_length, (unsigned int) match->length);
-    memcpy (buffer, (char *) this + stringOffset + match->offset, length);
-    return length;
-  }
-
-  inline unsigned int get_size (void) const
-  { return min_size + count * nameRecord[0].min_size; }
-
-  inline bool sanitize_records (hb_sanitize_context_t *c) const {
-    TRACE_SANITIZE (this);
-    char *string_pool = (char *) this + stringOffset;
-    unsigned int _count = count;
-    for (unsigned int i = 0; i < _count; i++)
-      if (!nameRecord[i].sanitize (c, string_pool)) return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  likely (format == 0 || format == 1) &&
-		  c->check_array (nameRecord, nameRecord[0].static_size, count) &&
-		  sanitize_records (c));
-  }
-
-  /* We only implement format 0 for now. */
-  HBUINT16	format;			/* Format selector (=0/1). */
-  HBUINT16	count;			/* Number of name records. */
-  Offset16	stringOffset;		/* Offset to start of string storage (from start of table). */
-  NameRecord	nameRecord[VAR];	/* The name records where count is the number of records. */
-  public:
-  DEFINE_SIZE_ARRAY (6, nameRecord);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_NAME_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-os2-table.hh b/third_party/harfbuzz-ng/src/hb-ot-os2-table.hh
deleted file mode 100644
index 6cb8d494..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-os2-table.hh
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_OS2_TABLE_HH
-#define HB_OT_OS2_TABLE_HH
-
-#include "hb-open-type-private.hh"
-#include "hb-ot-os2-unicode-ranges.hh"
-
-namespace OT {
-
-/*
- * OS/2 and Windows Metrics
- * http://www.microsoft.com/typography/otspec/os2.htm
- */
-
-#define HB_OT_TAG_os2 HB_TAG('O','S','/','2')
-
-struct os2
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_os2;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  inline bool subset (hb_subset_plan_t *plan) const
-  {
-    hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_os2));
-    hb_blob_t *os2_prime_blob = hb_blob_create_sub_blob (os2_blob, 0, -1);
-    // TODO(grieger): move to hb_blob_copy_writable_or_fail
-    hb_blob_destroy (os2_blob);
-
-    OT::os2 *os2_prime = (OT::os2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
-    if (unlikely (!os2_prime)) {
-      hb_blob_destroy (os2_prime_blob);
-      return false;
-    }
-
-    uint16_t min_cp, max_cp;
-    find_min_and_max_codepoint (plan->codepoints, &min_cp, &max_cp);
-    os2_prime->usFirstCharIndex.set (min_cp);
-    os2_prime->usLastCharIndex.set (max_cp);
-
-    _update_unicode_ranges (plan->codepoints, os2_prime->ulUnicodeRange);
-    bool result = hb_subset_plan_add_table(plan, HB_OT_TAG_os2, os2_prime_blob);
-
-    hb_blob_destroy (os2_prime_blob);
-    return result;
-  }
-
-  inline void _update_unicode_ranges (const hb_prealloced_array_t<hb_codepoint_t> &codepoints,
-                                      HBUINT32 ulUnicodeRange[4]) const
-  {
-    for (unsigned int i = 0; i < 4; i++)
-      ulUnicodeRange[i].set (0);
-
-    for (unsigned int i = 0; i < codepoints.len; i++)
-    {
-      hb_codepoint_t cp = codepoints[i];
-      unsigned int bit = hb_get_unicode_range_bit (cp);
-      if (bit < 128)
-      {
-        unsigned int block = bit / 32;
-        unsigned int bit_in_block = bit % 32;
-        unsigned int mask = 1 << bit_in_block;
-        ulUnicodeRange[block].set (ulUnicodeRange[block] | mask);
-      }
-      if (cp >= 0x10000 && cp <= 0x110000)
-      {
-        /* the spec says that bit 57 ("Non Plane 0") implies that there's
-           at least one codepoint beyond the BMP; so I also include all
-           the non-BMP codepoints here */
-        ulUnicodeRange[1].set (ulUnicodeRange[1] | (1 << 25));
-      }
-    }
-  }
-
-  static inline void find_min_and_max_codepoint (const hb_prealloced_array_t<hb_codepoint_t> &codepoints,
-                                                 uint16_t *min_cp, /* OUT */
-                                                 uint16_t *max_cp  /* OUT */)
-  {
-    hb_codepoint_t min = -1, max = 0;
-
-    for (unsigned int i = 0; i < codepoints.len; i++)
-    {
-      hb_codepoint_t cp = codepoints[i];
-      if (cp < min)
-        min = cp;
-      if (cp > max)
-        max = cp;
-    }
-
-    if (min > 0xFFFF)
-      min = 0xFFFF;
-    if (max > 0xFFFF)
-      max = 0xFFFF;
-
-    *min_cp = min;
-    *max_cp = max;
-  }
-
-  public:
-  HBUINT16	version;
-
-  /* Version 0 */
-  HBINT16	xAvgCharWidth;
-  HBUINT16	usWeightClass;
-  HBUINT16	usWidthClass;
-  HBUINT16	fsType;
-  HBINT16	ySubscriptXSize;
-  HBINT16	ySubscriptYSize;
-  HBINT16	ySubscriptXOffset;
-  HBINT16	ySubscriptYOffset;
-  HBINT16	ySuperscriptXSize;
-  HBINT16	ySuperscriptYSize;
-  HBINT16	ySuperscriptXOffset;
-  HBINT16	ySuperscriptYOffset;
-  HBINT16	yStrikeoutSize;
-  HBINT16	yStrikeoutPosition;
-  HBINT16	sFamilyClass;
-  HBUINT8	panose[10];
-  HBUINT32	ulUnicodeRange[4];
-  Tag		achVendID;
-  HBUINT16	fsSelection;
-  HBUINT16	usFirstCharIndex;
-  HBUINT16	usLastCharIndex;
-  HBINT16	sTypoAscender;
-  HBINT16	sTypoDescender;
-  HBINT16	sTypoLineGap;
-  HBUINT16	usWinAscent;
-  HBUINT16	usWinDescent;
-
-  /* Version 1 */
-  //HBUINT32	ulCodePageRange1;
-  //HBUINT32	ulCodePageRange2;
-
-  /* Version 2 */
-  //HBINT16	sxHeight;
-  //HBINT16	sCapHeight;
-  //HBUINT16	usDefaultChar;
-  //HBUINT16	usBreakChar;
-  //HBUINT16	usMaxContext;
-
-  /* Version 5 */
-  //HBUINT16	usLowerOpticalPointSize;
-  //HBUINT16	usUpperOpticalPointSize;
-
-  public:
-  DEFINE_SIZE_STATIC (78);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_OS2_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-os2-unicode-ranges.hh b/third_party/harfbuzz-ng/src/hb-ot-os2-unicode-ranges.hh
deleted file mode 100644
index 2cf168f..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-os2-unicode-ranges.hh
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger
- */
-
-#ifndef HB_OT_OS2_UNICODE_RANGES_HH
-#define HB_OT_OS2_UNICODE_RANGES_HH
-
-#include "hb-private.hh"
-#include "hb-dsalgs.hh"
-
-namespace OT {
-
-struct Range {
-  hb_codepoint_t start;
-  hb_codepoint_t end;
-  unsigned int bit;
-};
-
-/* Note: The contents of this array was generated using src/gen-unicode-ranges.py. */
-static Range os2UnicodeRangesSorted[] =
-{
-  {     0x0,     0x7F,   0}, // Basic Latin
-  {    0x80,     0xFF,   1}, // Latin-1 Supplement
-  {   0x100,    0x17F,   2}, // Latin Extended-A
-  {   0x180,    0x24F,   3}, // Latin Extended-B
-  {   0x250,    0x2AF,   4}, // IPA Extensions
-  {   0x2B0,    0x2FF,   5}, // Spacing Modifier Letters
-  {   0x300,    0x36F,   6}, // Combining Diacritical Marks
-  {   0x370,    0x3FF,   7}, // Greek and Coptic
-  {   0x400,    0x4FF,   9}, // Cyrillic
-  {   0x500,    0x52F,   9}, // Cyrillic Supplement
-  {   0x530,    0x58F,  10}, // Armenian
-  {   0x590,    0x5FF,  11}, // Hebrew
-  {   0x600,    0x6FF,  13}, // Arabic
-  {   0x700,    0x74F,  71}, // Syriac
-  {   0x750,    0x77F,  13}, // Arabic Supplement
-  {   0x780,    0x7BF,  72}, // Thaana
-  {   0x7C0,    0x7FF,  14}, // NKo
-  {   0x900,    0x97F,  15}, // Devanagari
-  {   0x980,    0x9FF,  16}, // Bengali
-  {   0xA00,    0xA7F,  17}, // Gurmukhi
-  {   0xA80,    0xAFF,  18}, // Gujarati
-  {   0xB00,    0xB7F,  19}, // Oriya
-  {   0xB80,    0xBFF,  20}, // Tamil
-  {   0xC00,    0xC7F,  21}, // Telugu
-  {   0xC80,    0xCFF,  22}, // Kannada
-  {   0xD00,    0xD7F,  23}, // Malayalam
-  {   0xD80,    0xDFF,  73}, // Sinhala
-  {   0xE00,    0xE7F,  24}, // Thai
-  {   0xE80,    0xEFF,  25}, // Lao
-  {   0xF00,    0xFFF,  70}, // Tibetan
-  {  0x1000,   0x109F,  74}, // Myanmar
-  {  0x10A0,   0x10FF,  26}, // Georgian
-  {  0x1100,   0x11FF,  28}, // Hangul Jamo
-  {  0x1200,   0x137F,  75}, // Ethiopic
-  {  0x1380,   0x139F,  75}, // Ethiopic Supplement
-  {  0x13A0,   0x13FF,  76}, // Cherokee
-  {  0x1400,   0x167F,  77}, // Unified Canadian Aboriginal Syllabics
-  {  0x1680,   0x169F,  78}, // Ogham
-  {  0x16A0,   0x16FF,  79}, // Runic
-  {  0x1700,   0x171F,  84}, // Tagalog
-  {  0x1720,   0x173F,  84}, // Hanunoo
-  {  0x1740,   0x175F,  84}, // Buhid
-  {  0x1760,   0x177F,  84}, // Tagbanwa
-  {  0x1780,   0x17FF,  80}, // Khmer
-  {  0x1800,   0x18AF,  81}, // Mongolian
-  {  0x1900,   0x194F,  93}, // Limbu
-  {  0x1950,   0x197F,  94}, // Tai Le
-  {  0x1980,   0x19DF,  95}, // New Tai Lue
-  {  0x19E0,   0x19FF,  80}, // Khmer Symbols
-  {  0x1A00,   0x1A1F,  96}, // Buginese
-  {  0x1B00,   0x1B7F,  27}, // Balinese
-  {  0x1B80,   0x1BBF, 112}, // Sundanese
-  {  0x1C00,   0x1C4F, 113}, // Lepcha
-  {  0x1C50,   0x1C7F, 114}, // Ol Chiki
-  {  0x1D00,   0x1D7F,   4}, // Phonetic Extensions
-  {  0x1D80,   0x1DBF,   4}, // Phonetic Extensions Supplement
-  {  0x1DC0,   0x1DFF,   6}, // Combining Diacritical Marks Supplement
-  {  0x1E00,   0x1EFF,  29}, // Latin Extended Additional
-  {  0x1F00,   0x1FFF,  30}, // Greek Extended
-  {  0x2000,   0x206F,  31}, // General Punctuation
-  {  0x2070,   0x209F,  32}, // Superscripts And Subscripts
-  {  0x20A0,   0x20CF,  33}, // Currency Symbols
-  {  0x20D0,   0x20FF,  34}, // Combining Diacritical Marks For Symbols
-  {  0x2100,   0x214F,  35}, // Letterlike Symbols
-  {  0x2150,   0x218F,  36}, // Number Forms
-  {  0x2190,   0x21FF,  37}, // Arrows
-  {  0x2200,   0x22FF,  38}, // Mathematical Operators
-  {  0x2300,   0x23FF,  39}, // Miscellaneous Technical
-  {  0x2400,   0x243F,  40}, // Control Pictures
-  {  0x2440,   0x245F,  41}, // Optical Character Recognition
-  {  0x2460,   0x24FF,  42}, // Enclosed Alphanumerics
-  {  0x2500,   0x257F,  43}, // Box Drawing
-  {  0x2580,   0x259F,  44}, // Block Elements
-  {  0x25A0,   0x25FF,  45}, // Geometric Shapes
-  {  0x2600,   0x26FF,  46}, // Miscellaneous Symbols
-  {  0x2700,   0x27BF,  47}, // Dingbats
-  {  0x27C0,   0x27EF,  38}, // Miscellaneous Mathematical Symbols-A
-  {  0x27F0,   0x27FF,  37}, // Supplemental Arrows-A
-  {  0x2800,   0x28FF,  82}, // Braille Patterns
-  {  0x2900,   0x297F,  37}, // Supplemental Arrows-B
-  {  0x2980,   0x29FF,  38}, // Miscellaneous Mathematical Symbols-B
-  {  0x2A00,   0x2AFF,  38}, // Supplemental Mathematical Operators
-  {  0x2B00,   0x2BFF,  37}, // Miscellaneous Symbols and Arrows
-  {  0x2C00,   0x2C5F,  97}, // Glagolitic
-  {  0x2C60,   0x2C7F,  29}, // Latin Extended-C
-  {  0x2C80,   0x2CFF,   8}, // Coptic
-  {  0x2D00,   0x2D2F,  26}, // Georgian Supplement
-  {  0x2D30,   0x2D7F,  98}, // Tifinagh
-  {  0x2D80,   0x2DDF,  75}, // Ethiopic Extended
-  {  0x2DE0,   0x2DFF,   9}, // Cyrillic Extended-A
-  {  0x2E00,   0x2E7F,  31}, // Supplemental Punctuation
-  {  0x2E80,   0x2EFF,  59}, // CJK Radicals Supplement
-  {  0x2F00,   0x2FDF,  59}, // Kangxi Radicals
-  {  0x2FF0,   0x2FFF,  59}, // Ideographic Description Characters
-  {  0x3000,   0x303F,  48}, // CJK Symbols And Punctuation
-  {  0x3040,   0x309F,  49}, // Hiragana
-  {  0x30A0,   0x30FF,  50}, // Katakana
-  {  0x3100,   0x312F,  51}, // Bopomofo
-  {  0x3130,   0x318F,  52}, // Hangul Compatibility Jamo
-  {  0x3190,   0x319F,  59}, // Kanbun
-  {  0x31A0,   0x31BF,  51}, // Bopomofo Extended
-  {  0x31C0,   0x31EF,  61}, // CJK Strokes
-  {  0x31F0,   0x31FF,  50}, // Katakana Phonetic Extensions
-  {  0x3200,   0x32FF,  54}, // Enclosed CJK Letters And Months
-  {  0x3300,   0x33FF,  55}, // CJK Compatibility
-  {  0x3400,   0x4DBF,  59}, // CJK Unified Ideographs Extension A
-  {  0x4DC0,   0x4DFF,  99}, // Yijing Hexagram Symbols
-  {  0x4E00,   0x9FFF,  59}, // CJK Unified Ideographs
-  {  0xA000,   0xA48F,  83}, // Yi Syllables
-  {  0xA490,   0xA4CF,  83}, // Yi Radicals
-  {  0xA500,   0xA63F,  12}, // Vai
-  {  0xA640,   0xA69F,   9}, // Cyrillic Extended-B
-  {  0xA700,   0xA71F,   5}, // Modifier Tone Letters
-  {  0xA720,   0xA7FF,  29}, // Latin Extended-D
-  {  0xA800,   0xA82F, 100}, // Syloti Nagri
-  {  0xA840,   0xA87F,  53}, // Phags-pa
-  {  0xA880,   0xA8DF, 115}, // Saurashtra
-  {  0xA900,   0xA92F, 116}, // Kayah Li
-  {  0xA930,   0xA95F, 117}, // Rejang
-  {  0xAA00,   0xAA5F, 118}, // Cham
-  {  0xAC00,   0xD7AF,  56}, // Hangul Syllables
-  {  0xD800,   0xDFFF,  57}, // Non-Plane 0 *
-  {  0xE000,   0xF8FF,  60}, // Private Use Area (plane 0)
-  {  0xF900,   0xFAFF,  61}, // CJK Compatibility Ideographs
-  {  0xFB00,   0xFB4F,  62}, // Alphabetic Presentation Forms
-  {  0xFB50,   0xFDFF,  63}, // Arabic Presentation Forms-A
-  {  0xFE00,   0xFE0F,  91}, // Variation Selectors
-  {  0xFE10,   0xFE1F,  65}, // Vertical Forms
-  {  0xFE20,   0xFE2F,  64}, // Combining Half Marks
-  {  0xFE30,   0xFE4F,  65}, // CJK Compatibility Forms
-  {  0xFE50,   0xFE6F,  66}, // Small Form Variants
-  {  0xFE70,   0xFEFF,  67}, // Arabic Presentation Forms-B
-  {  0xFF00,   0xFFEF,  68}, // Halfwidth And Fullwidth Forms
-  {  0xFFF0,   0xFFFF,  69}, // Specials
-  { 0x10000,  0x1007F, 101}, // Linear B Syllabary
-  { 0x10080,  0x100FF, 101}, // Linear B Ideograms
-  { 0x10100,  0x1013F, 101}, // Aegean Numbers
-  { 0x10140,  0x1018F, 102}, // Ancient Greek Numbers
-  { 0x10190,  0x101CF, 119}, // Ancient Symbols
-  { 0x101D0,  0x101FF, 120}, // Phaistos Disc
-  { 0x10280,  0x1029F, 121}, // Lycian
-  { 0x102A0,  0x102DF, 121}, // Carian
-  { 0x10300,  0x1032F,  85}, // Old Italic
-  { 0x10330,  0x1034F,  86}, // Gothic
-  { 0x10380,  0x1039F, 103}, // Ugaritic
-  { 0x103A0,  0x103DF, 104}, // Old Persian
-  { 0x10400,  0x1044F,  87}, // Deseret
-  { 0x10450,  0x1047F, 105}, // Shavian
-  { 0x10480,  0x104AF, 106}, // Osmanya
-  { 0x10800,  0x1083F, 107}, // Cypriot Syllabary
-  { 0x10900,  0x1091F,  58}, // Phoenician
-  { 0x10920,  0x1093F, 121}, // Lydian
-  { 0x10A00,  0x10A5F, 108}, // Kharoshthi
-  { 0x12000,  0x123FF, 110}, // Cuneiform
-  { 0x12400,  0x1247F, 110}, // Cuneiform Numbers and Punctuation
-  { 0x1D000,  0x1D0FF,  88}, // Byzantine Musical Symbols
-  { 0x1D100,  0x1D1FF,  88}, // Musical Symbols
-  { 0x1D200,  0x1D24F,  88}, // Ancient Greek Musical Notation
-  { 0x1D300,  0x1D35F, 109}, // Tai Xuan Jing Symbols
-  { 0x1D360,  0x1D37F, 111}, // Counting Rod Numerals
-  { 0x1D400,  0x1D7FF,  89}, // Mathematical Alphanumeric Symbols
-  { 0x1F000,  0x1F02F, 122}, // Mahjong Tiles
-  { 0x1F030,  0x1F09F, 122}, // Domino Tiles
-  { 0x20000,  0x2A6DF,  59}, // CJK Unified Ideographs Extension B
-  { 0x2F800,  0x2FA1F,  61}, // CJK Compatibility Ideographs Supplement
-  { 0xE0000,  0xE007F,  92}, // Tags
-  { 0xE0100,  0xE01EF,  91}, // Variation Selectors Supplement
-  { 0xF0000,  0xFFFFD,  90}, // Private Use (plane 15)
-  {0x100000, 0x10FFFD,  90}, // Private Use (plane 16)
-};
-
-static int
-_compare_range (const void *_key, const void *_item, void *_arg)
-{
-  hb_codepoint_t cp = *((hb_codepoint_t *) _key);
-  const Range *range = (Range *) _item;
-
-  if (cp < range->start)
-    return -1;
-  else if (cp <= range->end)
-    return 0;
-  else
-    return 1;
-}
-
-/**
- * hb_get_unicode_range_bit:
- * Returns the bit to be set in os/2 ulUnicodeRange for a given codepoint.
- **/
-static unsigned int
-hb_get_unicode_range_bit (hb_codepoint_t cp)
-{
-  Range *range = (Range*) hb_bsearch_r (&cp, os2UnicodeRangesSorted,
-                                        sizeof (os2UnicodeRangesSorted) / sizeof(Range),
-                                        sizeof(Range),
-                                        _compare_range, nullptr);
-  if (range != NULL)
-    return range->bit;
-  return -1;
-}
-
-} /* namespace OT */
-
-#endif /* HB_OT_OS2_UNICODE_RANGES_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-post-macroman.hh b/third_party/harfbuzz-ng/src/hb-ot-post-macroman.hh
deleted file mode 100644
index dbbb97e..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-post-macroman.hh
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_POST_MACROMAN_HH
-#if 0 /* Make checks happy. */
-#define HB_OT_POST_MACROMAN_HH
-#include "hb-private.hh"
-#endif
-
-
-_S(".notdef")
-_S(".null")
-_S("nonmarkingreturn")
-_S("space")
-_S("exclam")
-_S("quotedbl")
-_S("numbersign")
-_S("dollar")
-_S("percent")
-_S("ampersand")
-_S("quotesingle")
-_S("parenleft")
-_S("parenright")
-_S("asterisk")
-_S("plus")
-_S("comma")
-_S("hyphen")
-_S("period")
-_S("slash")
-_S("zero")
-_S("one")
-_S("two")
-_S("three")
-_S("four")
-_S("five")
-_S("six")
-_S("seven")
-_S("eight")
-_S("nine")
-_S("colon")
-_S("semicolon")
-_S("less")
-_S("equal")
-_S("greater")
-_S("question")
-_S("at")
-_S("A")
-_S("B")
-_S("C")
-_S("D")
-_S("E")
-_S("F")
-_S("G")
-_S("H")
-_S("I")
-_S("J")
-_S("K")
-_S("L")
-_S("M")
-_S("N")
-_S("O")
-_S("P")
-_S("Q")
-_S("R")
-_S("S")
-_S("T")
-_S("U")
-_S("V")
-_S("W")
-_S("X")
-_S("Y")
-_S("Z")
-_S("bracketleft")
-_S("backslash")
-_S("bracketright")
-_S("asciicircum")
-_S("underscore")
-_S("grave")
-_S("a")
-_S("b")
-_S("c")
-_S("d")
-_S("e")
-_S("f")
-_S("g")
-_S("h")
-_S("i")
-_S("j")
-_S("k")
-_S("l")
-_S("m")
-_S("n")
-_S("o")
-_S("p")
-_S("q")
-_S("r")
-_S("s")
-_S("t")
-_S("u")
-_S("v")
-_S("w")
-_S("x")
-_S("y")
-_S("z")
-_S("braceleft")
-_S("bar")
-_S("braceright")
-_S("asciitilde")
-_S("Adieresis")
-_S("Aring")
-_S("Ccedilla")
-_S("Eacute")
-_S("Ntilde")
-_S("Odieresis")
-_S("Udieresis")
-_S("aacute")
-_S("agrave")
-_S("acircumflex")
-_S("adieresis")
-_S("atilde")
-_S("aring")
-_S("ccedilla")
-_S("eacute")
-_S("egrave")
-_S("ecircumflex")
-_S("edieresis")
-_S("iacute")
-_S("igrave")
-_S("icircumflex")
-_S("idieresis")
-_S("ntilde")
-_S("oacute")
-_S("ograve")
-_S("ocircumflex")
-_S("odieresis")
-_S("otilde")
-_S("uacute")
-_S("ugrave")
-_S("ucircumflex")
-_S("udieresis")
-_S("dagger")
-_S("degree")
-_S("cent")
-_S("sterling")
-_S("section")
-_S("bullet")
-_S("paragraph")
-_S("germandbls")
-_S("registered")
-_S("copyright")
-_S("trademark")
-_S("acute")
-_S("dieresis")
-_S("notequal")
-_S("AE")
-_S("Oslash")
-_S("infinity")
-_S("plusminus")
-_S("lessequal")
-_S("greaterequal")
-_S("yen")
-_S("mu")
-_S("partialdiff")
-_S("summation")
-_S("product")
-_S("pi")
-_S("integral")
-_S("ordfeminine")
-_S("ordmasculine")
-_S("Omega")
-_S("ae")
-_S("oslash")
-_S("questiondown")
-_S("exclamdown")
-_S("logicalnot")
-_S("radical")
-_S("florin")
-_S("approxequal")
-_S("Delta")
-_S("guillemotleft")
-_S("guillemotright")
-_S("ellipsis")
-_S("nonbreakingspace")
-_S("Agrave")
-_S("Atilde")
-_S("Otilde")
-_S("OE")
-_S("oe")
-_S("endash")
-_S("emdash")
-_S("quotedblleft")
-_S("quotedblright")
-_S("quoteleft")
-_S("quoteright")
-_S("divide")
-_S("lozenge")
-_S("ydieresis")
-_S("Ydieresis")
-_S("fraction")
-_S("currency")
-_S("guilsinglleft")
-_S("guilsinglright")
-_S("fi")
-_S("fl")
-_S("daggerdbl")
-_S("periodcentered")
-_S("quotesinglbase")
-_S("quotedblbase")
-_S("perthousand")
-_S("Acircumflex")
-_S("Ecircumflex")
-_S("Aacute")
-_S("Edieresis")
-_S("Egrave")
-_S("Iacute")
-_S("Icircumflex")
-_S("Idieresis")
-_S("Igrave")
-_S("Oacute")
-_S("Ocircumflex")
-_S("apple")
-_S("Ograve")
-_S("Uacute")
-_S("Ucircumflex")
-_S("Ugrave")
-_S("dotlessi")
-_S("circumflex")
-_S("tilde")
-_S("macron")
-_S("breve")
-_S("dotaccent")
-_S("ring")
-_S("cedilla")
-_S("hungarumlaut")
-_S("ogonek")
-_S("caron")
-_S("Lslash")
-_S("lslash")
-_S("Scaron")
-_S("scaron")
-_S("Zcaron")
-_S("zcaron")
-_S("brokenbar")
-_S("Eth")
-_S("eth")
-_S("Yacute")
-_S("yacute")
-_S("Thorn")
-_S("thorn")
-_S("minus")
-_S("multiply")
-_S("onesuperior")
-_S("twosuperior")
-_S("threesuperior")
-_S("onehalf")
-_S("onequarter")
-_S("threequarters")
-_S("franc")
-_S("Gbreve")
-_S("gbreve")
-_S("Idotaccent")
-_S("Scedilla")
-_S("scedilla")
-_S("Cacute")
-_S("cacute")
-_S("Ccaron")
-_S("ccaron")
-_S("dcroat")
-
-
-#endif /* HB_OT_POST_MACROMAN_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-post-table.hh b/third_party/harfbuzz-ng/src/hb-ot-post-table.hh
deleted file mode 100644
index 9e479211..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-post-table.hh
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright © 2016  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_POST_TABLE_HH
-#define HB_OT_POST_TABLE_HH
-
-#include "hb-open-type-private.hh"
-#include "hb-dsalgs.hh"
-
-#define HB_STRING_ARRAY_NAME format1_names
-#define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh"
-#include "hb-string-array.hh"
-#undef HB_STRING_ARRAY_LIST
-#undef HB_STRING_ARRAY_NAME
-
-#define NUM_FORMAT1_NAMES 258
-
-namespace OT {
-
-
-/*
- * post -- PostScript
- */
-
-#define HB_OT_TAG_post HB_TAG('p','o','s','t')
-
-
-struct postV2Tail
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (glyphNameIndex.sanitize (c));
-  }
-
-  ArrayOf<HBUINT16>glyphNameIndex;	/* This is not an offset, but is the
-					 * ordinal number of the glyph in 'post'
-					 * string tables. */
-  HBUINT8		namesX[VAR];		/* Glyph names with length bytes [variable]
-					 * (a Pascal string). */
-
-  DEFINE_SIZE_ARRAY2 (2, glyphNameIndex, namesX);
-};
-
-struct post
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_post;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this)))
-      return_trace (false);
-    if (version.to_int () == 0x00020000)
-    {
-      const postV2Tail &v2 = StructAfter<postV2Tail> (*this);
-      return_trace (v2.sanitize (c));
-    }
-    return_trace (true);
-  }
-
-  struct accelerator_t
-  {
-    inline void init (hb_face_t *face)
-    {
-      blob = Sanitizer<post>().sanitize (face->reference_table (HB_OT_TAG_post));
-      const post *table = Sanitizer<post>::lock_instance (blob);
-      unsigned int table_length = hb_blob_get_length (blob);
-
-      version = table->version.to_int ();
-      index_to_offset.init ();
-      if (version != 0x00020000)
-        return;
-
-      const postV2Tail &v2 = StructAfter<postV2Tail> (*table);
-
-      glyphNameIndex = &v2.glyphNameIndex;
-      pool = &StructAfter<uint8_t> (v2.glyphNameIndex);
-
-      const uint8_t *end = (uint8_t *) table + table_length;
-      for (const uint8_t *data = pool; data < end && data + *data <= end; data += 1 + *data)
-      {
-	uint32_t *offset = index_to_offset.push ();
-	if (unlikely (!offset))
-	  break;
-	*offset = data - pool;
-      }
-    }
-    inline void fini (void)
-    {
-      index_to_offset.finish ();
-      free (gids_sorted_by_name);
-    }
-
-    inline bool get_glyph_name (hb_codepoint_t glyph,
-				char *buf, unsigned int buf_len) const
-    {
-      hb_string_t s = find_glyph_name (glyph);
-      if (!s.len)
-        return false;
-      if (!buf_len)
-	return true;
-      if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */
-        return false;
-      strncpy (buf, s.bytes, s.len);
-      buf[s.len] = '\0';
-      return true;
-    }
-
-    inline bool get_glyph_from_name (const char *name, int len,
-				     hb_codepoint_t *glyph) const
-    {
-      unsigned int count = get_glyph_count ();
-      if (unlikely (!count))
-        return false;
-
-      if (len < 0)
-	len = strlen (name);
-
-      if (unlikely (!len))
-	return false;
-
-    retry:
-      uint16_t *gids = (uint16_t *) hb_atomic_ptr_get (&gids_sorted_by_name);
-
-      if (unlikely (!gids))
-      {
-	gids = (uint16_t *) malloc (count * sizeof (gids[0]));
-	if (unlikely (!gids))
-	  return false; /* Anything better?! */
-
-	for (unsigned int i = 0; i < count; i++)
-	  gids[i] = i;
-	hb_sort_r (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
-
-	if (!hb_atomic_ptr_cmpexch (&gids_sorted_by_name, nullptr, gids)) {
-	  free (gids);
-	  goto retry;
-	}
-      }
-
-      hb_string_t st (name, len);
-      const uint16_t *gid = (const uint16_t *) hb_bsearch_r (&st, gids, count, sizeof (gids[0]), cmp_key, (void *) this);
-      if (gid)
-      {
-	*glyph = *gid;
-	return true;
-      }
-
-      return false;
-    }
-
-    protected:
-
-    inline unsigned int get_glyph_count (void) const
-    {
-      if (version == 0x00010000)
-        return NUM_FORMAT1_NAMES;
-
-      if (version == 0x00020000)
-        return glyphNameIndex->len;
-
-      return 0;
-    }
-
-    static inline int cmp_gids (const void *pa, const void *pb, void *arg)
-    {
-      const accelerator_t *thiz = (const accelerator_t *) arg;
-      uint16_t a = * (const uint16_t *) pa;
-      uint16_t b = * (const uint16_t *) pb;
-      return thiz->find_glyph_name (b).cmp (thiz->find_glyph_name (a));
-    }
-
-    static inline int cmp_key (const void *pk, const void *po, void *arg)
-    {
-      const accelerator_t *thiz = (const accelerator_t *) arg;
-      const hb_string_t *key = (const hb_string_t *) pk;
-      uint16_t o = * (const uint16_t *) po;
-      return thiz->find_glyph_name (o).cmp (*key);
-    }
-
-    inline hb_string_t find_glyph_name (hb_codepoint_t glyph) const
-    {
-      if (version == 0x00010000)
-      {
-	if (glyph >= NUM_FORMAT1_NAMES)
-	  return hb_string_t ();
-
-	return format1_names (glyph);
-      }
-
-      if (version != 0x00020000 || glyph >= glyphNameIndex->len)
-	return hb_string_t ();
-
-      unsigned int index = glyphNameIndex->array[glyph];
-      if (index < NUM_FORMAT1_NAMES)
-	return format1_names (index);
-      index -= NUM_FORMAT1_NAMES;
-
-      if (index >= index_to_offset.len)
-	return hb_string_t ();
-      unsigned int offset = index_to_offset.array[index];
-
-      const uint8_t *data = pool + offset;
-      unsigned int name_length = *data;
-      data++;
-
-      return hb_string_t ((const char *) data, name_length);
-    }
-
-    private:
-    hb_blob_t *blob;
-    uint32_t version;
-    const ArrayOf<HBUINT16> *glyphNameIndex;
-    hb_prealloced_array_t<uint32_t, 1> index_to_offset;
-    const uint8_t *pool;
-    mutable uint16_t *gids_sorted_by_name;
-  };
-
-  public:
-  FixedVersion<>version;		/* 0x00010000 for version 1.0
-					 * 0x00020000 for version 2.0
-					 * 0x00025000 for version 2.5 (deprecated)
-					 * 0x00030000 for version 3.0 */
-  Fixed		italicAngle;		/* Italic angle in counter-clockwise degrees
-					 * from the vertical. Zero for upright text,
-					 * negative for text that leans to the right
-					 * (forward). */
-  FWORD		underlinePosition;	/* This is the suggested distance of the top
-					 * of the underline from the baseline
-					 * (negative values indicate below baseline).
-					 * The PostScript definition of this FontInfo
-					 * dictionary key (the y coordinate of the
-					 * center of the stroke) is not used for
-					 * historical reasons. The value of the
-					 * PostScript key may be calculated by
-					 * subtracting half the underlineThickness
-					 * from the value of this field. */
-  FWORD		underlineThickness;	/* Suggested values for the underline
-					   thickness. */
-  HBUINT32	isFixedPitch;		/* Set to 0 if the font is proportionally
-					 * spaced, non-zero if the font is not
-					 * proportionally spaced (i.e. monospaced). */
-  HBUINT32	minMemType42;		/* Minimum memory usage when an OpenType font
-					 * is downloaded. */
-  HBUINT32	maxMemType42;		/* Maximum memory usage when an OpenType font
-					 * is downloaded. */
-  HBUINT32	minMemType1;		/* Minimum memory usage when an OpenType font
-					 * is downloaded as a Type 1 font. */
-  HBUINT32	maxMemType1;		/* Maximum memory usage when an OpenType font
-					 * is downloaded as a Type 1 font. */
-/*postV2Tail	v2[VAR];*/
-  DEFINE_SIZE_STATIC (32);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_POST_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh
deleted file mode 100644
index 5a257f0..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-private.hh"
-#include "hb-ot-layout-gsub-table.hh"
-
-
-/* Features ordered the same as the entries in shaping_table rows,
- * followed by rlig.  Don't change. */
-static const hb_tag_t arabic_fallback_features[] =
-{
-  HB_TAG('i','n','i','t'),
-  HB_TAG('m','e','d','i'),
-  HB_TAG('f','i','n','a'),
-  HB_TAG('i','s','o','l'),
-  HB_TAG('r','l','i','g'),
-};
-
-static OT::SubstLookup *
-arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUSED,
-					  hb_font_t *font,
-					  unsigned int feature_index)
-{
-  OT::GlyphID glyphs[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
-  OT::GlyphID substitutes[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
-  unsigned int num_glyphs = 0;
-
-  /* Populate arrays */
-  for (hb_codepoint_t u = SHAPING_TABLE_FIRST; u < SHAPING_TABLE_LAST + 1; u++)
-  {
-    hb_codepoint_t s = shaping_table[u - SHAPING_TABLE_FIRST][feature_index];
-    hb_codepoint_t u_glyph, s_glyph;
-
-    if (!s ||
-	!hb_font_get_glyph (font, u, 0, &u_glyph) ||
-	!hb_font_get_glyph (font, s, 0, &s_glyph) ||
-	u_glyph == s_glyph ||
-	u_glyph > 0xFFFFu || s_glyph > 0xFFFFu)
-      continue;
-
-    glyphs[num_glyphs].set (u_glyph);
-    substitutes[num_glyphs].set (s_glyph);
-
-    num_glyphs++;
-  }
-
-  if (!num_glyphs)
-    return nullptr;
-
-  /* Bubble-sort or something equally good!
-   * May not be good-enough for presidential candidate interviews, but good-enough for us... */
-  hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]);
-
-  OT::Supplier<OT::GlyphID> glyphs_supplier      (glyphs, num_glyphs);
-  OT::Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
-
-  /* Each glyph takes four bytes max, and there's some overhead. */
-  char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128];
-  OT::hb_serialize_context_t c (buf, sizeof (buf));
-  OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
-  bool ret = lookup->serialize_single (&c,
-				       OT::LookupFlag::IgnoreMarks,
-				       glyphs_supplier,
-				       substitutes_supplier,
-				       num_glyphs);
-  c.end_serialize ();
-  /* TODO sanitize the results? */
-
-  return ret ? c.copy<OT::SubstLookup> () : nullptr;
-}
-
-static OT::SubstLookup *
-arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UNUSED,
-					    hb_font_t *font)
-{
-  OT::GlyphID first_glyphs[ARRAY_LENGTH_CONST (ligature_table)];
-  unsigned int first_glyphs_indirection[ARRAY_LENGTH_CONST (ligature_table)];
-  unsigned int ligature_per_first_glyph_count_list[ARRAY_LENGTH_CONST (first_glyphs)];
-  unsigned int num_first_glyphs = 0;
-
-  /* We know that all our ligatures are 2-component */
-  OT::GlyphID ligature_list[ARRAY_LENGTH_CONST (first_glyphs) * ARRAY_LENGTH_CONST(ligature_table[0].ligatures)];
-  unsigned int component_count_list[ARRAY_LENGTH_CONST (ligature_list)];
-  OT::GlyphID component_list[ARRAY_LENGTH_CONST (ligature_list) * 1/* One extra component per ligature */];
-  unsigned int num_ligatures = 0;
-
-  /* Populate arrays */
-
-  /* Sort out the first-glyphs */
-  for (unsigned int first_glyph_idx = 0; first_glyph_idx < ARRAY_LENGTH (first_glyphs); first_glyph_idx++)
-  {
-    hb_codepoint_t first_u = ligature_table[first_glyph_idx].first;
-    hb_codepoint_t first_glyph;
-    if (!hb_font_get_glyph (font, first_u, 0, &first_glyph))
-      continue;
-    first_glyphs[num_first_glyphs].set (first_glyph);
-    ligature_per_first_glyph_count_list[num_first_glyphs] = 0;
-    first_glyphs_indirection[num_first_glyphs] = first_glyph_idx;
-    num_first_glyphs++;
-  }
-  hb_stable_sort (&first_glyphs[0], num_first_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &first_glyphs_indirection[0]);
-
-  /* Now that the first-glyphs are sorted, walk again, populate ligatures. */
-  for (unsigned int i = 0; i < num_first_glyphs; i++)
-  {
-    unsigned int first_glyph_idx = first_glyphs_indirection[i];
-
-    for (unsigned int second_glyph_idx = 0; second_glyph_idx < ARRAY_LENGTH (ligature_table[0].ligatures); second_glyph_idx++)
-    {
-      hb_codepoint_t second_u   = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].second;
-      hb_codepoint_t ligature_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].ligature;
-      hb_codepoint_t second_glyph, ligature_glyph;
-      if (!second_u ||
-	  !hb_font_get_glyph (font, second_u,   0, &second_glyph) ||
-	  !hb_font_get_glyph (font, ligature_u, 0, &ligature_glyph))
-	continue;
-
-      ligature_per_first_glyph_count_list[i]++;
-
-      ligature_list[num_ligatures].set (ligature_glyph);
-      component_count_list[num_ligatures] = 2;
-      component_list[num_ligatures].set (second_glyph);
-      num_ligatures++;
-    }
-  }
-
-  if (!num_ligatures)
-    return nullptr;
-
-  OT::Supplier<OT::GlyphID>   first_glyphs_supplier                      (first_glyphs, num_first_glyphs);
-  OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier    (ligature_per_first_glyph_count_list, num_first_glyphs);
-  OT::Supplier<OT::GlyphID>   ligatures_supplier                         (ligature_list, num_ligatures);
-  OT::Supplier<unsigned int > component_count_supplier                   (component_count_list, num_ligatures);
-  OT::Supplier<OT::GlyphID>   component_supplier                         (component_list, num_ligatures);
-
-  /* 16 bytes per ligature ought to be enough... */
-  char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128];
-  OT::hb_serialize_context_t c (buf, sizeof (buf));
-  OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
-  bool ret = lookup->serialize_ligature (&c,
-					 OT::LookupFlag::IgnoreMarks,
-					 first_glyphs_supplier,
-					 ligature_per_first_glyph_count_supplier,
-					 num_first_glyphs,
-					 ligatures_supplier,
-					 component_count_supplier,
-					 component_supplier);
-
-  c.end_serialize ();
-  /* TODO sanitize the results? */
-
-  return ret ? c.copy<OT::SubstLookup> () : nullptr;
-}
-
-static OT::SubstLookup *
-arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan,
-				   hb_font_t *font,
-				   unsigned int feature_index)
-{
-  if (feature_index < 4)
-    return arabic_fallback_synthesize_lookup_single (plan, font, feature_index);
-  else
-    return arabic_fallback_synthesize_lookup_ligature (plan, font);
-}
-
-#define ARABIC_FALLBACK_MAX_LOOKUPS 5
-
-struct arabic_fallback_plan_t
-{
-  ASSERT_POD ();
-
-  unsigned int num_lookups;
-  bool free_lookups;
-
-  hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS];
-  OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS];
-  hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
-};
-
-static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
-
-#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256)
-#define HB_WITH_WIN1256
-#endif
-
-#ifdef HB_WITH_WIN1256
-#include "hb-ot-shape-complex-arabic-win1256.hh"
-#endif
-
-struct ManifestLookup {
-  OT::Tag tag;
-  OT::OffsetTo<OT::SubstLookup> lookupOffset;
-};
-typedef OT::ArrayOf<ManifestLookup> Manifest;
-
-static bool
-arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan,
-				   const hb_ot_shape_plan_t *plan,
-				   hb_font_t *font)
-{
-#ifdef HB_WITH_WIN1256
-  /* Does this font look like it's Windows-1256-encoded? */
-  hb_codepoint_t g;
-  if (!(hb_font_get_glyph (font, 0x0627u, 0, &g) && g == 199 /* ALEF */ &&
-	hb_font_get_glyph (font, 0x0644u, 0, &g) && g == 225 /* LAM */ &&
-	hb_font_get_glyph (font, 0x0649u, 0, &g) && g == 236 /* ALEF MAKSURA */ &&
-	hb_font_get_glyph (font, 0x064Au, 0, &g) && g == 237 /* YEH */ &&
-	hb_font_get_glyph (font, 0x0652u, 0, &g) && g == 250 /* SUKUN */))
-    return false;
-
-  const Manifest &manifest = reinterpret_cast<const Manifest&> (arabic_win1256_gsub_lookups.manifest);
-  static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) / sizeof (ManifestLookup)
-		 <= ARABIC_FALLBACK_MAX_LOOKUPS, "");
-  /* TODO sanitize the table? */
-
-  unsigned j = 0;
-  unsigned int count = manifest.len;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    fallback_plan->mask_array[j] = plan->map.get_1_mask (manifest[i].tag);
-    if (fallback_plan->mask_array[j])
-    {
-      fallback_plan->lookup_array[j] = const_cast<OT::SubstLookup*> (&(&manifest+manifest[i].lookupOffset));
-      if (fallback_plan->lookup_array[j])
-      {
-	fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
-	j++;
-      }
-    }
-  }
-
-  fallback_plan->num_lookups = j;
-  fallback_plan->free_lookups = false;
-
-  return j > 0;
-#else
-  return false;
-#endif
-}
-
-static bool
-arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan,
-				   const hb_ot_shape_plan_t *plan,
-				   hb_font_t *font)
-{
-  static_assert ((ARRAY_LENGTH_CONST(arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS), "");
-  unsigned int j = 0;
-  for (unsigned int i = 0; i < ARRAY_LENGTH(arabic_fallback_features) ; i++)
-  {
-    fallback_plan->mask_array[j] = plan->map.get_1_mask (arabic_fallback_features[i]);
-    if (fallback_plan->mask_array[j])
-    {
-      fallback_plan->lookup_array[j] = arabic_fallback_synthesize_lookup (plan, font, i);
-      if (fallback_plan->lookup_array[j])
-      {
-	fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
-	j++;
-      }
-    }
-  }
-
-  fallback_plan->num_lookups = j;
-  fallback_plan->free_lookups = true;
-
-  return j > 0;
-}
-
-static arabic_fallback_plan_t *
-arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
-			     hb_font_t *font)
-{
-  arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t));
-  if (unlikely (!fallback_plan))
-    return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
-
-  fallback_plan->num_lookups = 0;
-  fallback_plan->free_lookups = false;
-
-  /* Try synthesizing GSUB table using Unicode Arabic Presentation Forms,
-   * in case the font has cmap entries for the presentation-forms characters. */
-  if (arabic_fallback_plan_init_unicode (fallback_plan, plan, font))
-    return fallback_plan;
-
-  /* See if this looks like a Windows-1256-encoded font.  If it does, use a
-   * hand-coded GSUB table. */
-  if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font))
-    return fallback_plan;
-
-  free (fallback_plan);
-  return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
-}
-
-static void
-arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
-{
-  if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil)
-    return;
-
-  for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
-    if (fallback_plan->lookup_array[i])
-    {
-      fallback_plan->accel_array[i].fini ();
-      if (fallback_plan->free_lookups)
-	free (fallback_plan->lookup_array[i]);
-    }
-
-  free (fallback_plan);
-}
-
-static void
-arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
-			    hb_font_t *font,
-			    hb_buffer_t *buffer)
-{
-  OT::hb_ot_apply_context_t c (0, font, buffer);
-  for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
-    if (fallback_plan->lookup_array[i]) {
-      c.set_lookup_mask (fallback_plan->mask_array[i]);
-      hb_ot_layout_substitute_lookup (&c,
-				      *fallback_plan->lookup_array[i],
-				      fallback_plan->accel_array[i]);
-    }
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-private.hh
deleted file mode 100644
index fcedc7d..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-private.hh
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright © 2015  Mozilla Foundation.
- * Copyright © 2015  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-struct arabic_shape_plan_t;
-
-HB_INTERNAL void *
-data_create_arabic (const hb_ot_shape_plan_t *plan);
-
-HB_INTERNAL void
-data_destroy_arabic (void *data);
-
-HB_INTERNAL void
-setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
-			 hb_buffer_t               *buffer,
-			 hb_script_t                script);
-
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh
deleted file mode 100644
index cd6e405..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh
+++ /dev/null
@@ -1,398 +0,0 @@
-/* == Start of generated table == */
-/*
- * The following table is generated by running:
- *
- *   ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
- *
- * on files with these headers:
- *
- * # ArabicShaping-10.0.0.txt
- * # Date: 2017-02-16, 00:00:00 GMT [RP, KW]
- * # Blocks-10.0.0.txt
- * # Date: 2017-04-12, 17:30:00 GMT [KW]
- * UnicodeData.txt does not have a header.
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
-
-
-#define X	JOINING_TYPE_X
-#define R	JOINING_TYPE_R
-#define T	JOINING_TYPE_T
-#define U	JOINING_TYPE_U
-#define A	JOINING_GROUP_ALAPH
-#define DR	JOINING_GROUP_DALATH_RISH
-#define L	JOINING_TYPE_L
-#define C	JOINING_TYPE_C
-#define D	JOINING_TYPE_D
-
-static const uint8_t joining_table[] =
-{
-
-#define joining_offset_0x0600u 0
-
-  /* Arabic */
-
-  /* 0600 */ U,U,U,U,U,U,X,X,U,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-  /* 0620 */ D,U,R,R,R,R,D,R,D,R,D,D,D,D,D,R,R,R,R,D,D,D,D,D,D,D,D,D,D,D,D,D,
-  /* 0640 */ C,D,D,D,D,D,D,D,R,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-  /* 0660 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,D,D,X,R,R,R,U,R,R,R,D,D,D,D,D,D,D,D,
-  /* 0680 */ D,D,D,D,D,D,D,D,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,D,D,D,D,D,D,
-  /* 06A0 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
-  /* 06C0 */ R,D,D,R,R,R,R,R,R,R,R,R,D,R,D,R,D,D,R,R,X,R,X,X,X,X,X,X,X,U,X,X,
-  /* 06E0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,R,R,X,X,X,X,X,X,X,X,X,X,D,D,D,X,X,D,
-
-  /* Syriac */
-
-  /* 0700 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,A,X,D,D,D,DR,DR,R,R,R,D,D,D,D,R,D,
-  /* 0720 */ D,D,D,D,D,D,D,D,R,D,DR,D,R,D,D,DR,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-  /* 0740 */ X,X,X,X,X,X,X,X,X,X,X,X,X,R,D,D,
-
-  /* Arabic Supplement */
-
-  /* 0740 */                                 D,D,D,D,D,D,D,D,D,R,R,R,D,D,D,D,
-  /* 0760 */ D,D,D,D,D,D,D,D,D,D,D,R,R,D,D,D,D,R,D,R,R,D,D,D,R,R,D,D,D,D,D,D,
-
-  /* FILLER */
-
-  /* 0780 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-  /* 07A0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-
-  /* NKo */
-
-  /* 07C0 */ X,X,X,X,X,X,X,X,X,X,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
-  /* 07E0 */ D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,C,X,X,X,X,X,
-
-  /* FILLER */
-
-  /* 0800 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-  /* 0820 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-
-  /* Mandaic */
-
-  /* 0840 */ R,D,D,D,D,D,R,R,D,R,D,D,D,D,D,D,D,D,D,D,R,D,U,U,U,X,X,X,X,X,X,X,
-
-  /* Syriac Supplement */
-
-  /* 0860 */ D,U,D,D,D,D,U,R,D,R,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-  /* 0880 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-
-  /* Arabic Extended-A */
-
-  /* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,X,D,D,D,R,D,D,D,D,X,X,
-  /* 08C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-  /* 08E0 */ X,X,U,
-
-#define joining_offset_0x1806u 739
-
-  /* Mongolian */
-
-  /* 1800 */             U,D,X,X,C,X,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-  /* 1820 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
-  /* 1840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
-  /* 1860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,
-  /* 1880 */ U,U,U,U,U,T,T,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
-  /* 18A0 */ D,D,D,D,D,D,D,D,D,X,D,
-
-#define joining_offset_0x200cu 904
-
-  /* General Punctuation */
-
-  /* 2000 */                         U,C,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-  /* 2020 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-  /* 2040 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-  /* 2060 */ X,X,X,X,X,X,U,U,U,U,
-
-#define joining_offset_0xa840u 998
-
-  /* Phags-pa */
-
-  /* A840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
-  /* A860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,L,U,
-
-#define joining_offset_0x10ac0u 1050
-
-  /* Manichaean */
-
-  /* 10AC0 */ D,D,D,D,D,R,U,R,U,R,R,U,U,L,R,R,R,R,R,D,D,D,D,L,D,D,D,D,D,R,D,D,
-  /* 10AE0 */ D,R,U,U,R,X,X,X,X,X,X,D,D,D,D,R,
-
-#define joining_offset_0x10b80u 1098
-
-  /* Psalter Pahlavi */
-
-  /* 10B80 */ D,R,D,R,R,R,D,D,D,R,D,D,R,D,R,R,D,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-  /* 10BA0 */ X,X,X,X,X,X,X,X,X,R,R,R,R,D,D,U,
-
-#define joining_offset_0x1e900u 1146
-
-  /* Adlam */
-
-  /* 1E900 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
-  /* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
-  /* 1E940 */ D,D,D,D,
-
-}; /* Table items: 1214; occupancy: 55% */
-
-
-static unsigned int
-joining_type (hb_codepoint_t u)
-{
-  switch (u >> 12)
-  {
-    case 0x0u:
-      if (hb_in_range<hb_codepoint_t> (u, 0x0600u, 0x08E2u)) return joining_table[u - 0x0600u + joining_offset_0x0600u];
-      break;
-
-    case 0x1u:
-      if (hb_in_range<hb_codepoint_t> (u, 0x1806u, 0x18AAu)) return joining_table[u - 0x1806u + joining_offset_0x1806u];
-      break;
-
-    case 0x2u:
-      if (hb_in_range<hb_codepoint_t> (u, 0x200Cu, 0x2069u)) return joining_table[u - 0x200Cu + joining_offset_0x200cu];
-      break;
-
-    case 0xAu:
-      if (hb_in_range<hb_codepoint_t> (u, 0xA840u, 0xA873u)) return joining_table[u - 0xA840u + joining_offset_0xa840u];
-      break;
-
-    case 0x10u:
-      if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
-      break;
-
-    case 0x1Eu:
-      if (hb_in_range<hb_codepoint_t> (u, 0x1E900u, 0x1E943u)) return joining_table[u - 0x1E900u + joining_offset_0x1e900u];
-      break;
-
-    default:
-      break;
-  }
-  return X;
-}
-
-#undef X
-#undef R
-#undef T
-#undef U
-#undef A
-#undef DR
-#undef L
-#undef C
-#undef D
-
-
-static const uint16_t shaping_table[][4] =
-{
-  {0x0000u, 0x0000u, 0x0000u, 0xFE80u}, /* U+0621 ARABIC LETTER HAMZA ISOLATED FORM */
-  {0x0000u, 0x0000u, 0xFE82u, 0xFE81u}, /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */
-  {0x0000u, 0x0000u, 0xFE84u, 0xFE83u}, /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */
-  {0x0000u, 0x0000u, 0xFE86u, 0xFE85u}, /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */
-  {0x0000u, 0x0000u, 0xFE88u, 0xFE87u}, /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */
-  {0xFE8Bu, 0xFE8Cu, 0xFE8Au, 0xFE89u}, /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */
-  {0x0000u, 0x0000u, 0xFE8Eu, 0xFE8Du}, /* U+0627 ARABIC LETTER ALEF */
-  {0xFE91u, 0xFE92u, 0xFE90u, 0xFE8Fu}, /* U+0628 ARABIC LETTER BEH */
-  {0x0000u, 0x0000u, 0xFE94u, 0xFE93u}, /* U+0629 ARABIC LETTER TEH MARBUTA */
-  {0xFE97u, 0xFE98u, 0xFE96u, 0xFE95u}, /* U+062A ARABIC LETTER TEH */
-  {0xFE9Bu, 0xFE9Cu, 0xFE9Au, 0xFE99u}, /* U+062B ARABIC LETTER THEH */
-  {0xFE9Fu, 0xFEA0u, 0xFE9Eu, 0xFE9Du}, /* U+062C ARABIC LETTER JEEM */
-  {0xFEA3u, 0xFEA4u, 0xFEA2u, 0xFEA1u}, /* U+062D ARABIC LETTER HAH */
-  {0xFEA7u, 0xFEA8u, 0xFEA6u, 0xFEA5u}, /* U+062E ARABIC LETTER KHAH */
-  {0x0000u, 0x0000u, 0xFEAAu, 0xFEA9u}, /* U+062F ARABIC LETTER DAL */
-  {0x0000u, 0x0000u, 0xFEACu, 0xFEABu}, /* U+0630 ARABIC LETTER THAL */
-  {0x0000u, 0x0000u, 0xFEAEu, 0xFEADu}, /* U+0631 ARABIC LETTER REH */
-  {0x0000u, 0x0000u, 0xFEB0u, 0xFEAFu}, /* U+0632 ARABIC LETTER ZAIN */
-  {0xFEB3u, 0xFEB4u, 0xFEB2u, 0xFEB1u}, /* U+0633 ARABIC LETTER SEEN */
-  {0xFEB7u, 0xFEB8u, 0xFEB6u, 0xFEB5u}, /* U+0634 ARABIC LETTER SHEEN */
-  {0xFEBBu, 0xFEBCu, 0xFEBAu, 0xFEB9u}, /* U+0635 ARABIC LETTER SAD */
-  {0xFEBFu, 0xFEC0u, 0xFEBEu, 0xFEBDu}, /* U+0636 ARABIC LETTER DAD */
-  {0xFEC3u, 0xFEC4u, 0xFEC2u, 0xFEC1u}, /* U+0637 ARABIC LETTER TAH */
-  {0xFEC7u, 0xFEC8u, 0xFEC6u, 0xFEC5u}, /* U+0638 ARABIC LETTER ZAH */
-  {0xFECBu, 0xFECCu, 0xFECAu, 0xFEC9u}, /* U+0639 ARABIC LETTER AIN */
-  {0xFECFu, 0xFED0u, 0xFECEu, 0xFECDu}, /* U+063A ARABIC LETTER GHAIN */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063B  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063C  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063D  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063E  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063F  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0640  */
-  {0xFED3u, 0xFED4u, 0xFED2u, 0xFED1u}, /* U+0641 ARABIC LETTER FEH */
-  {0xFED7u, 0xFED8u, 0xFED6u, 0xFED5u}, /* U+0642 ARABIC LETTER QAF */
-  {0xFEDBu, 0xFEDCu, 0xFEDAu, 0xFED9u}, /* U+0643 ARABIC LETTER KAF */
-  {0xFEDFu, 0xFEE0u, 0xFEDEu, 0xFEDDu}, /* U+0644 ARABIC LETTER LAM */
-  {0xFEE3u, 0xFEE4u, 0xFEE2u, 0xFEE1u}, /* U+0645 ARABIC LETTER MEEM */
-  {0xFEE7u, 0xFEE8u, 0xFEE6u, 0xFEE5u}, /* U+0646 ARABIC LETTER NOON */
-  {0xFEEBu, 0xFEECu, 0xFEEAu, 0xFEE9u}, /* U+0647 ARABIC LETTER HEH */
-  {0x0000u, 0x0000u, 0xFEEEu, 0xFEEDu}, /* U+0648 ARABIC LETTER WAW */
-  {0xFBE8u, 0xFBE9u, 0xFEF0u, 0xFEEFu}, /* U+0649 ARABIC LETTER */
-  {0xFEF3u, 0xFEF4u, 0xFEF2u, 0xFEF1u}, /* U+064A ARABIC LETTER YEH */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064B  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064C  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064D  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064E  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064F  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0650  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0651  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0652  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0653  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0654  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0655  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0656  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0657  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0658  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0659  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065A  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065B  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065C  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065D  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065E  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065F  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0660  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0661  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0662  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0663  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0664  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0665  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0666  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0667  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0668  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0669  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066A  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066B  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066C  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066D  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066E  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066F  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0670  */
-  {0x0000u, 0x0000u, 0xFB51u, 0xFB50u}, /* U+0671 ARABIC LETTER ALEF WASLA */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0672  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0673  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0674  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0675  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0676  */
-  {0x0000u, 0x0000u, 0x0000u, 0xFBDDu}, /* U+0677 ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0678  */
-  {0xFB68u, 0xFB69u, 0xFB67u, 0xFB66u}, /* U+0679 ARABIC LETTER TTEH */
-  {0xFB60u, 0xFB61u, 0xFB5Fu, 0xFB5Eu}, /* U+067A ARABIC LETTER TTEHEH */
-  {0xFB54u, 0xFB55u, 0xFB53u, 0xFB52u}, /* U+067B ARABIC LETTER BEEH */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+067C  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+067D  */
-  {0xFB58u, 0xFB59u, 0xFB57u, 0xFB56u}, /* U+067E ARABIC LETTER PEH */
-  {0xFB64u, 0xFB65u, 0xFB63u, 0xFB62u}, /* U+067F ARABIC LETTER TEHEH */
-  {0xFB5Cu, 0xFB5Du, 0xFB5Bu, 0xFB5Au}, /* U+0680 ARABIC LETTER BEHEH */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0681  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0682  */
-  {0xFB78u, 0xFB79u, 0xFB77u, 0xFB76u}, /* U+0683 ARABIC LETTER NYEH */
-  {0xFB74u, 0xFB75u, 0xFB73u, 0xFB72u}, /* U+0684 ARABIC LETTER DYEH */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0685  */
-  {0xFB7Cu, 0xFB7Du, 0xFB7Bu, 0xFB7Au}, /* U+0686 ARABIC LETTER TCHEH */
-  {0xFB80u, 0xFB81u, 0xFB7Fu, 0xFB7Eu}, /* U+0687 ARABIC LETTER TCHEHEH */
-  {0x0000u, 0x0000u, 0xFB89u, 0xFB88u}, /* U+0688 ARABIC LETTER DDAL */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0689  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068A  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068B  */
-  {0x0000u, 0x0000u, 0xFB85u, 0xFB84u}, /* U+068C ARABIC LETTER DAHAL */
-  {0x0000u, 0x0000u, 0xFB83u, 0xFB82u}, /* U+068D ARABIC LETTER DDAHAL */
-  {0x0000u, 0x0000u, 0xFB87u, 0xFB86u}, /* U+068E ARABIC LETTER DUL */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068F  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0690  */
-  {0x0000u, 0x0000u, 0xFB8Du, 0xFB8Cu}, /* U+0691 ARABIC LETTER RREH */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0692  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0693  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0694  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0695  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0696  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0697  */
-  {0x0000u, 0x0000u, 0xFB8Bu, 0xFB8Au}, /* U+0698 ARABIC LETTER JEH */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0699  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069A  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069B  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069C  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069D  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069E  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069F  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A0  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A1  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A2  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A3  */
-  {0xFB6Cu, 0xFB6Du, 0xFB6Bu, 0xFB6Au}, /* U+06A4 ARABIC LETTER VEH */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A5  */
-  {0xFB70u, 0xFB71u, 0xFB6Fu, 0xFB6Eu}, /* U+06A6 ARABIC LETTER PEHEH */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A7  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A8  */
-  {0xFB90u, 0xFB91u, 0xFB8Fu, 0xFB8Eu}, /* U+06A9 ARABIC LETTER KEHEH */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AA  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AB  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AC  */
-  {0xFBD5u, 0xFBD6u, 0xFBD4u, 0xFBD3u}, /* U+06AD ARABIC LETTER NG */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AE  */
-  {0xFB94u, 0xFB95u, 0xFB93u, 0xFB92u}, /* U+06AF ARABIC LETTER GAF */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B0  */
-  {0xFB9Cu, 0xFB9Du, 0xFB9Bu, 0xFB9Au}, /* U+06B1 ARABIC LETTER NGOEH */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B2  */
-  {0xFB98u, 0xFB99u, 0xFB97u, 0xFB96u}, /* U+06B3 ARABIC LETTER GUEH */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B4  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B5  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B6  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B7  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B8  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B9  */
-  {0x0000u, 0x0000u, 0xFB9Fu, 0xFB9Eu}, /* U+06BA ARABIC LETTER NOON GHUNNA */
-  {0xFBA2u, 0xFBA3u, 0xFBA1u, 0xFBA0u}, /* U+06BB ARABIC LETTER RNOON */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BC  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BD  */
-  {0xFBACu, 0xFBADu, 0xFBABu, 0xFBAAu}, /* U+06BE ARABIC LETTER HEH DOACHASHMEE */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BF  */
-  {0x0000u, 0x0000u, 0xFBA5u, 0xFBA4u}, /* U+06C0 ARABIC LETTER HEH WITH YEH ABOVE */
-  {0xFBA8u, 0xFBA9u, 0xFBA7u, 0xFBA6u}, /* U+06C1 ARABIC LETTER HEH GOAL */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C2  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C3  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C4  */
-  {0x0000u, 0x0000u, 0xFBE1u, 0xFBE0u}, /* U+06C5 ARABIC LETTER KIRGHIZ OE */
-  {0x0000u, 0x0000u, 0xFBDAu, 0xFBD9u}, /* U+06C6 ARABIC LETTER OE */
-  {0x0000u, 0x0000u, 0xFBD8u, 0xFBD7u}, /* U+06C7 ARABIC LETTER U */
-  {0x0000u, 0x0000u, 0xFBDCu, 0xFBDBu}, /* U+06C8 ARABIC LETTER YU */
-  {0x0000u, 0x0000u, 0xFBE3u, 0xFBE2u}, /* U+06C9 ARABIC LETTER KIRGHIZ YU */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CA  */
-  {0x0000u, 0x0000u, 0xFBDFu, 0xFBDEu}, /* U+06CB ARABIC LETTER VE */
-  {0xFBFEu, 0xFBFFu, 0xFBFDu, 0xFBFCu}, /* U+06CC ARABIC LETTER FARSI YEH */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CD  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CE  */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CF  */
-  {0xFBE6u, 0xFBE7u, 0xFBE5u, 0xFBE4u}, /* U+06D0 ARABIC LETTER E */
-  {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06D1  */
-  {0x0000u, 0x0000u, 0xFBAFu, 0xFBAEu}, /* U+06D2 ARABIC LETTER YEH BARREE */
-  {0x0000u, 0x0000u, 0xFBB1u, 0xFBB0u}, /* U+06D3 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE */
-};
-
-#define SHAPING_TABLE_FIRST	0x0621u
-#define SHAPING_TABLE_LAST	0x06D3u
-
-
-static const struct ligature_set_t {
- uint16_t first;
- struct ligature_pairs_t {
-   uint16_t second;
-   uint16_t ligature;
- } ligatures[4];
-} ligature_table[] =
-{
-  { 0xFEDFu, {
-    { 0xFE88u, 0xFEF9u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */
-    { 0xFE82u, 0xFEF5u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */
-    { 0xFE8Eu, 0xFEFBu }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */
-    { 0xFE84u, 0xFEF7u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */
-  }},
-  { 0xFEE0u, {
-    { 0xFE88u, 0xFEFAu }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */
-    { 0xFE82u, 0xFEF6u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */
-    { 0xFE8Eu, 0xFEFCu }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */
-    { 0xFE84u, 0xFEF8u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */
-  }},
-};
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH */
-
-/* == End of generated table == */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh
deleted file mode 100644
index 54c6cdc2..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright © 2014  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH
-
-
-/*
- * The macros in the first part of this file are generic macros that can
- * be used to define the bytes for OpenType table data in code in a
- * readable manner.  We can move the macros to reside with their respective
- * struct types, but since we only use these to define one data table, the
- * Windows-1256 Arabic shaping table in this file, we keep them here.
- */
-
-
-/* First we measure, then we cut. */
-#ifndef OT_MEASURE
-#define OT_MEASURE
-#define OT_TABLE_START			static const struct TABLE_NAME {
-#define OT_TABLE_END			}
-#define OT_LABEL_START(Name)		unsigned char Name[
-#define OT_LABEL_END			];
-#define OT_UINT8(u8)			+1/*byte*/
-#define OT_UINT16(u16)			+2/*bytes*/
-#else
-#undef  OT_MEASURE
-#define OT_TABLE_START			TABLE_NAME = {
-#define OT_TABLE_END			};
-#define OT_LABEL_START(Name)		{
-#define OT_LABEL_END			},
-#define OT_UINT8(u8)			(u8),
-#define OT_UINT16(u16)			(unsigned char)((u16)>>8), (unsigned char)((u16)&0xFFu),
-#define OT_COUNT(Name, ItemSize)	((unsigned int) sizeof(((struct TABLE_NAME*)0)->Name) \
-					 / (unsigned int)(ItemSize) \
-					 /* OT_ASSERT it's divisible (and positive). */)
-#define OT_DISTANCE(From,To)		((unsigned int) \
-					 ((char*)(&((struct TABLE_NAME*)0)->To) - \
-					  (char*)(&((struct TABLE_NAME*)0)->From)) \
-					 /* OT_ASSERT it's positive. */)
-#endif
-
-
-#define OT_LABEL(Name) \
-	OT_LABEL_END \
-	OT_LABEL_START(Name)
-
-/* Whenever we receive an argument that is a list, it will expand to
- * contain commas.  That cannot be passed to another macro because the
- * commas will throw off the preprocessor.  The solution is to wrap
- * the passed-in argument in OT_LIST() before passing to the next macro.
- * Unfortunately this trick requires vararg macros. */
-#define OT_LIST(...) __VA_ARGS__
-
-
-/*
- * Basic Types
- */
-
-#define OT_TAG(a,b,c,d) \
-	OT_UINT8(a) OT_UINT8(b) OT_UINT8(c) OT_UINT8(d)
-
-#define OT_OFFSET(From, To) /* Offset from From to To in bytes */ \
-	OT_UINT16(OT_DISTANCE(From, To))
-
-#define OT_GLYPHID /* GlyphID */ \
-	OT_UINT16
-
-#define OT_UARRAY(Name, Items) \
-	OT_LABEL_START(Name) \
-	OT_UINT16(OT_COUNT(Name##Data, 2)) \
-	OT_LABEL(Name##Data) \
-	Items \
-	OT_LABEL_END
-
-#define OT_UHEADLESSARRAY(Name, Items) \
-	OT_LABEL_START(Name) \
-	OT_UINT16(OT_COUNT(Name##Data, 2) + 1) \
-	OT_LABEL(Name##Data) \
-	Items \
-	OT_LABEL_END
-
-
-/*
- * Common Types
- */
-
-#define OT_LOOKUP_FLAG_IGNORE_MARKS	0x08u
-
-#define OT_LOOKUP(Name, LookupType, LookupFlag, SubLookupOffsets) \
-	OT_LABEL_START(Name) \
-	OT_UINT16(LookupType) \
-	OT_UINT16(LookupFlag) \
-	OT_LABEL_END \
-	OT_UARRAY(Name##SubLookupOffsetsArray, OT_LIST(SubLookupOffsets))
-
-#define OT_SUBLOOKUP(Name, SubFormat, Items) \
-	OT_LABEL_START(Name) \
-	OT_UINT16(SubFormat) \
-	Items
-
-#define OT_COVERAGE1(Name, Items) \
-	OT_LABEL_START(Name) \
-	OT_UINT16(1) \
-	OT_LABEL_END \
-	OT_UARRAY(Name##Glyphs, OT_LIST(Items))
-
-
-/*
- * GSUB
- */
-
-#define OT_LOOKUP_TYPE_SUBST_SINGLE	1u
-#define OT_LOOKUP_TYPE_SUBST_LIGATURE	4u
-
-#define OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(Name, FromGlyphs, ToGlyphs) \
-	OT_SUBLOOKUP(Name, 2, \
-		OT_OFFSET(Name, Name##Coverage) \
-		OT_LABEL_END \
-		OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \
-	) \
-	OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \
-	/* ASSERT_STATIC_EXPR_ZERO (len(FromGlyphs) == len(ToGlyphs)) */
-
-#define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \
-	OT_SUBLOOKUP(Name, 1, \
-		OT_OFFSET(Name, Name##Coverage) \
-		OT_LABEL_END \
-		OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \
-	) \
-	OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \
-	/* ASSERT_STATIC_EXPR_ZERO (len(FirstGlyphs) == len(LigatureSetOffsets)) */
-
-#define OT_LIGATURE_SET(Name, LigatureSetOffsets) \
-	OT_UARRAY(Name, OT_LIST(LigatureSetOffsets))
-
-#define OT_LIGATURE(Name, Components, LigGlyph) \
-	OT_LABEL_START(Name) \
-	LigGlyph \
-	OT_LABEL_END \
-	OT_UHEADLESSARRAY(Name##ComponentsArray, OT_LIST(Components))
-
-/*
- *
- * Start of Windows-1256 shaping table.
- *
- */
-
-/* Table name. */
-#define TABLE_NAME arabic_win1256_gsub_lookups
-
-/* Table manifest. */
-#define MANIFEST(Items) \
-	OT_LABEL_START(manifest) \
-	OT_UINT16(OT_COUNT(manifestData, 6)) \
-	OT_LABEL(manifestData) \
-	Items \
-	OT_LABEL_END
-
-#define MANIFEST_LOOKUP(Tag, Name) \
-	Tag \
-	OT_OFFSET(manifest, Name)
-
-/* Shorthand. */
-#define G	OT_GLYPHID
-
-/*
- * Table Start
- */
-OT_TABLE_START
-
-
-/*
- * Manifest
- */
-MANIFEST(
-	MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligLookup)
-	MANIFEST_LOOKUP(OT_TAG('i','n','i','t'), initLookup)
-	MANIFEST_LOOKUP(OT_TAG('m','e','d','i'), mediLookup)
-	MANIFEST_LOOKUP(OT_TAG('f','i','n','a'), finaLookup)
-	MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligMarksLookup)
-)
-
-/*
- * Lookups
- */
-OT_LOOKUP(initLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
-	OT_OFFSET(initLookup, initmediSubLookup)
-	OT_OFFSET(initLookup, initSubLookup)
-)
-OT_LOOKUP(mediLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
-	OT_OFFSET(mediLookup, initmediSubLookup)
-	OT_OFFSET(mediLookup, mediSubLookup)
-	OT_OFFSET(mediLookup, medifinaLamAlefSubLookup)
-)
-OT_LOOKUP(finaLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
-	OT_OFFSET(finaLookup, finaSubLookup)
-	/* We don't need this one currently as the sequence inherits masks
-	 * from the first item.  Just in case we change that in the future
-	 * to be smart about Arabic masks when ligating... */
-	OT_OFFSET(finaLookup, medifinaLamAlefSubLookup)
-)
-OT_LOOKUP(rligLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, OT_LOOKUP_FLAG_IGNORE_MARKS,
-	OT_OFFSET(rligLookup, lamAlefLigaturesSubLookup)
-)
-OT_LOOKUP(rligMarksLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, 0,
-	OT_OFFSET(rligMarksLookup, shaddaLigaturesSubLookup)
-)
-
-/*
- * init/medi/fina forms
- */
-OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initmediSubLookup,
-	G(198)	G(200)	G(201)	G(202)	G(203)	G(204)	G(205)	G(206)	G(211)
-	G(212)	G(213)	G(214)	G(223)	G(225)	G(227)	G(228)	G(236)	G(237),
-	G(162)	G(4)	G(5)	G(5)	G(6)	G(7)	G(9)	G(11)	G(13)
-	G(14)	G(15)	G(26)	G(140)	G(141)	G(142)	G(143)	G(154)	G(154)
-)
-OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initSubLookup,
-	G(218)	G(219)	G(221)	G(222)	G(229),
-	G(27)	G(30)	G(128)	G(131)	G(144)
-)
-OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(mediSubLookup,
-	G(218)	G(219)	G(221)	G(222)	G(229),
-	G(28)	G(31)	G(129)	G(138)	G(149)
-)
-OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(finaSubLookup,
-	G(194)	G(195)	G(197)	G(198)	G(199)	G(201)	G(204)	G(205)	G(206)
-	G(218)	G(219)	G(229)	G(236)	G(237),
-	G(2)	G(1)	G(3)	G(181)	G(0)	G(159)	G(8)	G(10)	G(12)
-	G(29)	G(127)	G(152) G(160)	G(156)
-)
-OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(medifinaLamAlefSubLookup,
-	G(165)	G(178)	G(180)	G(252),
-	G(170)	G(179)	G(185)	G(255)
-)
-
-/*
- * Lam+Alef ligatures
- */
-OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(lamAlefLigaturesSubLookup,
-	G(225),
-	OT_OFFSET(lamAlefLigaturesSubLookup, lamLigatureSet)
-)
-OT_LIGATURE_SET(lamLigatureSet,
-	OT_OFFSET(lamLigatureSet, lamInitLigature1)
-	OT_OFFSET(lamLigatureSet, lamInitLigature2)
-	OT_OFFSET(lamLigatureSet, lamInitLigature3)
-	OT_OFFSET(lamLigatureSet, lamInitLigature4)
-)
-OT_LIGATURE(lamInitLigature1, G(199), G(165))
-OT_LIGATURE(lamInitLigature2, G(195), G(178))
-OT_LIGATURE(lamInitLigature3, G(194), G(180))
-OT_LIGATURE(lamInitLigature4, G(197), G(252))
-
-/*
- * Shadda ligatures
- */
-OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(shaddaLigaturesSubLookup,
-	G(248),
-	OT_OFFSET(shaddaLigaturesSubLookup, shaddaLigatureSet)
-)
-OT_LIGATURE_SET(shaddaLigatureSet,
-	OT_OFFSET(shaddaLigatureSet, shaddaLigature1)
-	OT_OFFSET(shaddaLigatureSet, shaddaLigature2)
-	OT_OFFSET(shaddaLigatureSet, shaddaLigature3)
-)
-OT_LIGATURE(shaddaLigature1, G(243), G(172))
-OT_LIGATURE(shaddaLigature2, G(245), G(173))
-OT_LIGATURE(shaddaLigature3, G(246), G(175))
-
-/*
- * Table end
- */
-OT_TABLE_END
-
-
-/*
- * Clean up
- */
-#undef OT_TABLE_START
-#undef OT_TABLE_END
-#undef OT_LABEL_START
-#undef OT_LABEL_END
-#undef OT_UINT8
-#undef OT_UINT16
-#undef OT_DISTANCE
-#undef OT_COUNT
-
-/*
- * Include a second time to get the table data...
- */
-#if 0
-#include "hb-private.hh" /* Make check-includes.sh happy. */
-#endif
-#ifdef OT_MEASURE
-#include "hb-ot-shape-complex-arabic-win1256.hh"
-#endif
-
-#define HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
deleted file mode 100644
index 47961bf..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
+++ /dev/null
@@ -1,721 +0,0 @@
-/*
- * Copyright © 2010,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-ot-shape-complex-arabic-private.hh"
-#include "hb-ot-shape-private.hh"
-
-
-/* buffer var allocations */
-#define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */
-
-#define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0
-
-/* See:
- * https://github.com/harfbuzz/harfbuzz/commit/6e6f82b6f3dde0fc6c3c7d991d9ec6cfff57823d#commitcomment-14248516 */
-#define HB_ARABIC_GENERAL_CATEGORY_IS_WORD(gen_cat) \
-	(FLAG_UNSAFE (gen_cat) & \
-	 (FLAG (HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE) | \
-	  /*FLAG (HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER) |*/ \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) | \
-	  /*FLAG (HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER) |*/ \
-	  /*FLAG (HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER) |*/ \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL)))
-
-
-/*
- * Joining types:
- */
-
-/*
- * Bits used in the joining tables
- */
-enum hb_arabic_joining_type_t {
-  JOINING_TYPE_U		= 0,
-  JOINING_TYPE_L		= 1,
-  JOINING_TYPE_R		= 2,
-  JOINING_TYPE_D		= 3,
-  JOINING_TYPE_C		= JOINING_TYPE_D,
-  JOINING_GROUP_ALAPH		= 4,
-  JOINING_GROUP_DALATH_RISH	= 5,
-  NUM_STATE_MACHINE_COLS	= 6,
-
-  JOINING_TYPE_T = 7,
-  JOINING_TYPE_X = 8  /* means: use general-category to choose between U or T. */
-};
-
-#include "hb-ot-shape-complex-arabic-table.hh"
-
-static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
-{
-  unsigned int j_type = joining_type(u);
-  if (likely (j_type != JOINING_TYPE_X))
-    return j_type;
-
-  return (FLAG_UNSAFE(gen_cat) &
-	  (FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) |
-	   FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
-	   FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT))
-	 ) ?  JOINING_TYPE_T : JOINING_TYPE_U;
-}
-
-#define FEATURE_IS_SYRIAC(tag) hb_in_range<unsigned char> ((unsigned char) (tag), '2', '3')
-
-static const hb_tag_t arabic_features[] =
-{
-  HB_TAG('i','s','o','l'),
-  HB_TAG('f','i','n','a'),
-  HB_TAG('f','i','n','2'),
-  HB_TAG('f','i','n','3'),
-  HB_TAG('m','e','d','i'),
-  HB_TAG('m','e','d','2'),
-  HB_TAG('i','n','i','t'),
-  HB_TAG_NONE
-};
-
-
-/* Same order as the feature array */
-enum arabic_action_t {
-  ISOL,
-  FINA,
-  FIN2,
-  FIN3,
-  MEDI,
-  MED2,
-  INIT,
-
-  NONE,
-
-  ARABIC_NUM_FEATURES = NONE,
-
-  /* We abuse the same byte for other things... */
-  STCH_FIXED,
-  STCH_REPEATING,
-};
-
-static const struct arabic_state_table_entry {
-	uint8_t prev_action;
-	uint8_t curr_action;
-	uint16_t next_state;
-} arabic_state_table[][NUM_STATE_MACHINE_COLS] =
-{
-  /*   jt_U,          jt_L,          jt_R,          jt_D,          jg_ALAPH,      jg_DALATH_RISH */
-
-  /* State 0: prev was U, not willing to join. */
-  { {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,6}, },
-
-  /* State 1: prev was R or ISOL/ALAPH, not willing to join. */
-  { {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN2,5}, {NONE,ISOL,6}, },
-
-  /* State 2: prev was D/L in ISOL form, willing to join. */
-  { {NONE,NONE,0}, {NONE,ISOL,2}, {INIT,FINA,1}, {INIT,FINA,3}, {INIT,FINA,4}, {INIT,FINA,6}, },
-
-  /* State 3: prev was D in FINA form, willing to join. */
-  { {NONE,NONE,0}, {NONE,ISOL,2}, {MEDI,FINA,1}, {MEDI,FINA,3}, {MEDI,FINA,4}, {MEDI,FINA,6}, },
-
-  /* State 4: prev was FINA ALAPH, not willing to join. */
-  { {NONE,NONE,0}, {NONE,ISOL,2}, {MED2,ISOL,1}, {MED2,ISOL,2}, {MED2,FIN2,5}, {MED2,ISOL,6}, },
-
-  /* State 5: prev was FIN2/FIN3 ALAPH, not willing to join. */
-  { {NONE,NONE,0}, {NONE,ISOL,2}, {ISOL,ISOL,1}, {ISOL,ISOL,2}, {ISOL,FIN2,5}, {ISOL,ISOL,6}, },
-
-  /* State 6: prev was DALATH/RISH, not willing to join. */
-  { {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN3,5}, {NONE,ISOL,6}, }
-};
-
-
-static void
-nuke_joiners (const hb_ot_shape_plan_t *plan,
-	      hb_font_t *font,
-	      hb_buffer_t *buffer);
-
-static void
-arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
-		       hb_font_t *font,
-		       hb_buffer_t *buffer);
-
-static void
-record_stch (const hb_ot_shape_plan_t *plan,
-	     hb_font_t *font,
-	     hb_buffer_t *buffer);
-
-static void
-collect_features_arabic (hb_ot_shape_planner_t *plan)
-{
-  hb_ot_map_builder_t *map = &plan->map;
-
-  /* We apply features according to the Arabic spec, with pauses
-   * in between most.
-   *
-   * The pause between init/medi/... and rlig is required.  See eg:
-   * https://bugzilla.mozilla.org/show_bug.cgi?id=644184
-   *
-   * The pauses between init/medi/... themselves are not necessarily
-   * needed as only one of those features is applied to any character.
-   * The only difference it makes is when fonts have contextual
-   * substitutions.  We now follow the order of the spec, which makes
-   * for better experience if that's what Uniscribe is doing.
-   *
-   * At least for Arabic, looks like Uniscribe has a pause between
-   * rlig and calt.  Otherwise the IranNastaliq's ALLAH ligature won't
-   * work.  However, testing shows that rlig and calt are applied
-   * together for Mongolian in Uniscribe.  As such, we only add a
-   * pause for Arabic, not other scripts.
-   *
-   * A pause after calt is required to make KFGQPC Uthmanic Script HAFS
-   * work correctly.  See https://github.com/harfbuzz/harfbuzz/issues/505
-   */
-
-  map->add_gsub_pause (nuke_joiners);
-
-  map->add_global_bool_feature (HB_TAG('s','t','c','h'));
-  map->add_gsub_pause (record_stch);
-
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
-
-  map->add_gsub_pause (nullptr);
-
-  for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++)
-  {
-    bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]);
-    map->add_feature (arabic_features[i], 1, has_fallback ? F_HAS_FALLBACK : F_NONE);
-    map->add_gsub_pause (nullptr);
-  }
-
-  map->add_feature (HB_TAG('r','l','i','g'), 1, F_GLOBAL|F_HAS_FALLBACK);
-  if (plan->props.script == HB_SCRIPT_ARABIC)
-    map->add_gsub_pause (arabic_fallback_shape);
-
-  /* No pause after rclt.  See 98460779bae19e4d64d29461ff154b3527bf8420. */
-  map->add_global_bool_feature (HB_TAG('r','c','l','t'));
-  map->add_global_bool_feature (HB_TAG('c','a','l','t'));
-  map->add_gsub_pause (nullptr);
-
-  /* The spec includes 'cswh'.  Earlier versions of Windows
-   * used to enable this by default, but testing suggests
-   * that Windows 8 and later do not enable it by default,
-   * and spec now says 'Off by default'.
-   * We disabled this in ae23c24c32.
-   * Note that IranNastaliq uses this feature extensively
-   * to fixup broken glyph sequences.  Oh well...
-   * Test case: U+0643,U+0640,U+0631. */
-  //map->add_global_bool_feature (HB_TAG('c','s','w','h'));
-  map->add_global_bool_feature (HB_TAG('m','s','e','t'));
-}
-
-#include "hb-ot-shape-complex-arabic-fallback.hh"
-
-struct arabic_shape_plan_t
-{
-  ASSERT_POD ();
-
-  /* The "+ 1" in the next array is to accommodate for the "NONE" command,
-   * which is not an OpenType feature, but this simplifies the code by not
-   * having to do a "if (... < NONE) ..." and just rely on the fact that
-   * mask_array[NONE] == 0. */
-  hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
-
-  arabic_fallback_plan_t *fallback_plan;
-
-  unsigned int do_fallback : 1;
-  unsigned int has_stch : 1;
-};
-
-void *
-data_create_arabic (const hb_ot_shape_plan_t *plan)
-{
-  arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) calloc (1, sizeof (arabic_shape_plan_t));
-  if (unlikely (!arabic_plan))
-    return nullptr;
-
-  arabic_plan->do_fallback = plan->props.script == HB_SCRIPT_ARABIC;
-  arabic_plan->has_stch = !!plan->map.get_1_mask (HB_TAG ('s','t','c','h'));
-  for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) {
-    arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]);
-    arabic_plan->do_fallback = arabic_plan->do_fallback &&
-			       (FEATURE_IS_SYRIAC (arabic_features[i]) ||
-			        plan->map.needs_fallback (arabic_features[i]));
-  }
-
-  return arabic_plan;
-}
-
-void
-data_destroy_arabic (void *data)
-{
-  arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) data;
-
-  arabic_fallback_plan_destroy (arabic_plan->fallback_plan);
-
-  free (data);
-}
-
-static void
-arabic_joining (hb_buffer_t *buffer)
-{
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int prev = (unsigned int) -1, state = 0;
-
-  /* Check pre-context */
-  for (unsigned int i = 0; i < buffer->context_len[0]; i++)
-  {
-    unsigned int this_type = get_joining_type (buffer->context[0][i], buffer->unicode->general_category (buffer->context[0][i]));
-
-    if (unlikely (this_type == JOINING_TYPE_T))
-      continue;
-
-    const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
-    state = entry->next_state;
-    break;
-  }
-
-  for (unsigned int i = 0; i < count; i++)
-  {
-    unsigned int this_type = get_joining_type (info[i].codepoint, _hb_glyph_info_get_general_category (&info[i]));
-
-    if (unlikely (this_type == JOINING_TYPE_T)) {
-      info[i].arabic_shaping_action() = NONE;
-      continue;
-    }
-
-    const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
-
-    if (entry->prev_action != NONE && prev != (unsigned int) -1)
-    {
-      info[prev].arabic_shaping_action() = entry->prev_action;
-      buffer->unsafe_to_break (prev, i + 1);
-    }
-
-    info[i].arabic_shaping_action() = entry->curr_action;
-
-    prev = i;
-    state = entry->next_state;
-  }
-
-  for (unsigned int i = 0; i < buffer->context_len[1]; i++)
-  {
-    unsigned int this_type = get_joining_type (buffer->context[1][i], buffer->unicode->general_category (buffer->context[1][i]));
-
-    if (unlikely (this_type == JOINING_TYPE_T))
-      continue;
-
-    const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
-    if (entry->prev_action != NONE && prev != (unsigned int) -1)
-      info[prev].arabic_shaping_action() = entry->prev_action;
-    break;
-  }
-}
-
-static void
-mongolian_variation_selectors (hb_buffer_t *buffer)
-{
-  /* Copy arabic_shaping_action() from base to Mongolian variation selectors. */
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 1; i < count; i++)
-    if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x180Bu, 0x180Du)))
-      info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action();
-}
-
-void
-setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
-			 hb_buffer_t               *buffer,
-			 hb_script_t                script)
-{
-  HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action);
-
-  arabic_joining (buffer);
-  if (script == HB_SCRIPT_MONGOLIAN)
-    mongolian_variation_selectors (buffer);
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    info[i].mask |= arabic_plan->mask_array[info[i].arabic_shaping_action()];
-}
-
-static void
-setup_masks_arabic (const hb_ot_shape_plan_t *plan,
-		    hb_buffer_t              *buffer,
-		    hb_font_t                *font HB_UNUSED)
-{
-  const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
-  setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script);
-}
-
-
-static void
-nuke_joiners (const hb_ot_shape_plan_t *plan HB_UNUSED,
-	      hb_font_t *font HB_UNUSED,
-	      hb_buffer_t *buffer)
-{
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    if (_hb_glyph_info_is_zwj (&info[i]))
-      _hb_glyph_info_flip_joiners (&info[i]);
-}
-
-static void
-arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
-		       hb_font_t *font,
-		       hb_buffer_t *buffer)
-{
-  const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
-
-  if (!arabic_plan->do_fallback)
-    return;
-
-retry:
-  arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) hb_atomic_ptr_get (&arabic_plan->fallback_plan);
-  if (unlikely (!fallback_plan))
-  {
-    /* This sucks.  We need a font to build the fallback plan... */
-    fallback_plan = arabic_fallback_plan_create (plan, font);
-    if (unlikely (!hb_atomic_ptr_cmpexch (&(const_cast<arabic_shape_plan_t *> (arabic_plan))->fallback_plan, nullptr, fallback_plan))) {
-      arabic_fallback_plan_destroy (fallback_plan);
-      goto retry;
-    }
-  }
-
-  arabic_fallback_plan_shape (fallback_plan, font, buffer);
-}
-
-/*
- * Stretch feature: "stch".
- * See example here:
- * https://www.microsoft.com/typography/OpenTypeDev/syriac/intro.htm
- * We implement this in a generic way, such that the Arabic subtending
- * marks can use it as well.
- */
-
-static void
-record_stch (const hb_ot_shape_plan_t *plan,
-	     hb_font_t *font,
-	     hb_buffer_t *buffer)
-{
-  const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
-  if (!arabic_plan->has_stch)
-    return;
-
-  /* 'stch' feature was just applied.  Look for anything that multiplied,
-   * and record it for stch treatment later.  Note that rtlm, frac, etc
-   * are applied before stch, but we assume that they didn't result in
-   * anything multiplying into 5 pieces, so it's safe-ish... */
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    if (unlikely (_hb_glyph_info_multiplied (&info[i])))
-    {
-      unsigned int comp = _hb_glyph_info_get_lig_comp (&info[i]);
-      info[i].arabic_shaping_action() = comp % 2 ? STCH_REPEATING : STCH_FIXED;
-      buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH;
-    }
-}
-
-static void
-apply_stch (const hb_ot_shape_plan_t *plan,
-	    hb_buffer_t              *buffer,
-	    hb_font_t                *font)
-{
-  if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH)))
-    return;
-
-  /* The Arabic shaper currently always processes in RTL mode, so we should
-   * stretch / position the stretched pieces to the left / preceding glyphs. */
-
-  /* We do a two pass implementation:
-   * First pass calculates the exact number of extra glyphs we need,
-   * We then enlarge buffer to have that much room,
-   * Second pass applies the stretch, copying things to the end of buffer.
-   */
-
-  int sign = font->x_scale < 0 ? -1 : +1;
-  unsigned int extra_glyphs_needed = 0; // Set during MEASURE, used during CUT
-  typedef enum { MEASURE, CUT } step_t;
-
-  for (step_t step = MEASURE; step <= CUT; step = (step_t) (step + 1))
-  {
-    unsigned int count = buffer->len;
-    hb_glyph_info_t *info = buffer->info;
-    hb_glyph_position_t *pos = buffer->pos;
-    unsigned int new_len = count + extra_glyphs_needed; // write head during CUT
-    unsigned int j = new_len;
-    for (unsigned int i = count; i; i--)
-    {
-      if (!hb_in_range<unsigned> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING))
-      {
-        if (step == CUT)
-	{
-	  --j;
-	  info[j] = info[i - 1];
-	  pos[j] = pos[i - 1];
-	}
-        continue;
-      }
-
-      /* Yay, justification! */
-
-      hb_position_t w_total = 0; // Total to be filled
-      hb_position_t w_fixed = 0; // Sum of fixed tiles
-      hb_position_t w_repeating = 0; // Sum of repeating tiles
-      int n_fixed = 0;
-      int n_repeating = 0;
-
-      unsigned int end = i;
-      while (i &&
-	     hb_in_range<unsigned> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING))
-      {
-	i--;
-	hb_position_t width = font->get_glyph_h_advance (info[i].codepoint);
-	if (info[i].arabic_shaping_action() == STCH_FIXED)
-	{
-	  w_fixed += width;
-	  n_fixed++;
-	}
-	else
-	{
-	  w_repeating += width;
-	  n_repeating++;
-	}
-      }
-      unsigned int start = i;
-      unsigned int context = i;
-      while (context &&
-	     !hb_in_range<unsigned> (info[context - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING) &&
-	     (_hb_glyph_info_is_default_ignorable (&info[context - 1]) ||
-	      HB_ARABIC_GENERAL_CATEGORY_IS_WORD (_hb_glyph_info_get_general_category (&info[context - 1]))))
-      {
-	context--;
-	w_total += pos[context].x_advance;
-      }
-      i++; // Don't touch i again.
-
-      DEBUG_MSG (ARABIC, nullptr, "%s stretch at (%d,%d,%d)",
-		 step == MEASURE ? "measuring" : "cutting", context, start, end);
-      DEBUG_MSG (ARABIC, nullptr, "rest of word:    count=%d width %d", start - context, w_total);
-      DEBUG_MSG (ARABIC, nullptr, "fixed tiles:     count=%d width=%d", n_fixed, w_fixed);
-      DEBUG_MSG (ARABIC, nullptr, "repeating tiles: count=%d width=%d", n_repeating, w_repeating);
-
-      /* Number of additional times to repeat each repeating tile. */
-      int n_copies = 0;
-
-      hb_position_t w_remaining = w_total - w_fixed;
-      if (sign * w_remaining > sign * w_repeating && sign * w_repeating > 0)
-	n_copies = (sign * w_remaining) / (sign * w_repeating) - 1;
-
-      /* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */
-      hb_position_t extra_repeat_overlap = 0;
-      hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1);
-      if (shortfall > 0 && n_repeating > 0)
-      {
-        ++n_copies;
-        hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining;
-        if (excess > 0)
-          extra_repeat_overlap = excess / (n_copies * n_repeating);
-      }
-
-      if (step == MEASURE)
-      {
-	extra_glyphs_needed += n_copies * n_repeating;
-	DEBUG_MSG (ARABIC, nullptr, "will add extra %d copies of repeating tiles", n_copies);
-      }
-      else
-      {
-	buffer->unsafe_to_break (context, end);
-	hb_position_t x_offset = 0;
-	for (unsigned int k = end; k > start; k--)
-	{
-	  hb_position_t width = font->get_glyph_h_advance (info[k - 1].codepoint);
-
-	  unsigned int repeat = 1;
-	  if (info[k - 1].arabic_shaping_action() == STCH_REPEATING)
-	    repeat += n_copies;
-
-	  DEBUG_MSG (ARABIC, nullptr, "appending %d copies of glyph %d; j=%d",
-		     repeat, info[k - 1].codepoint, j);
-	  for (unsigned int n = 0; n < repeat; n++)
-	  {
-	    x_offset -= width;
-	    if (n > 0)
-	      x_offset += extra_repeat_overlap;
-	    pos[k - 1].x_offset = x_offset;
-	    /* Append copy. */
-	    --j;
-	    info[j] = info[k - 1];
-	    pos[j] = pos[k - 1];
-	  }
-	}
-      }
-    }
-
-    if (step == MEASURE)
-    {
-      if (unlikely (!buffer->ensure (count + extra_glyphs_needed)))
-        break;
-    }
-    else
-    {
-      assert (j == 0);
-      buffer->len = new_len;
-    }
-  }
-}
-
-
-static void
-postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan,
-			   hb_buffer_t              *buffer,
-			   hb_font_t                *font)
-{
-  apply_stch (plan, buffer, font);
-
-  HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
-}
-
-/* http://www.unicode.org/reports/tr53/tr53-1.pdf */
-
-static hb_codepoint_t
-modifier_combining_marks[] =
-{
-  0x0654u, /* ARABIC HAMZA ABOVE */
-  0x0655u, /* ARABIC HAMZA BELOW */
-  0x0658u, /* ARABIC MARK NOON GHUNNA */
-  0x06DCu, /* ARABIC SMALL HIGH SEEN */
-  0x06E3u, /* ARABIC SMALL LOW SEEN */
-  0x06E7u, /* ARABIC SMALL HIGH YEH */
-  0x06E8u, /* ARABIC SMALL HIGH NOON */
-  0x08F3u, /* ARABIC SMALL HIGH WAW */
-};
-
-static inline bool
-info_is_mcm (const hb_glyph_info_t &info)
-{
-  hb_codepoint_t u = info.codepoint;
-  for (unsigned int i = 0; i < ARRAY_LENGTH (modifier_combining_marks); i++)
-    if (u == modifier_combining_marks[i])
-      return true;
-  return false;
-}
-
-static void
-reorder_marks_arabic (const hb_ot_shape_plan_t *plan,
-		      hb_buffer_t              *buffer,
-		      unsigned int              start,
-		      unsigned int              end)
-{
-  hb_glyph_info_t *info = buffer->info;
-
-  DEBUG_MSG (ARABIC, buffer, "Reordering marks from %d to %d", start, end);
-
-  unsigned int i = start;
-  for (unsigned int cc = 220; cc <= 230; cc += 10)
-  {
-    DEBUG_MSG (ARABIC, buffer, "Looking for %d's starting at %d", cc, i);
-    while (i < end && info_cc(info[i]) < cc)
-      i++;
-    DEBUG_MSG (ARABIC, buffer, "Looking for %d's stopped at %d", cc, i);
-
-    if (i == end)
-      break;
-
-    if (info_cc(info[i]) > cc)
-      continue;
-
-    unsigned int j = i;
-    while (j < end && info_cc(info[j]) == cc && info_is_mcm (info[j]))
-      j++;
-
-    if (i == j)
-      continue;
-
-    DEBUG_MSG (ARABIC, buffer, "Found %d's from %d to %d", cc, i, j);
-
-    /* Shift it! */
-    DEBUG_MSG (ARABIC, buffer, "Shifting %d's: %d %d", cc, i, j);
-    hb_glyph_info_t temp[HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS];
-    assert (j - i <= ARRAY_LENGTH (temp));
-    buffer->merge_clusters (start, j);
-    memmove (temp, &info[i], (j - i) * sizeof (hb_glyph_info_t));
-    memmove (&info[start + j - i], &info[start], (i - start) * sizeof (hb_glyph_info_t));
-    memmove (&info[start], temp, (j - i) * sizeof (hb_glyph_info_t));
-
-    /* Renumber CC such that the reordered sequence is still sorted.
-     * 22 and 26 are chosen because they are smaller than all Arabic categories,
-     * and are folded back to 220/230 respectively during fallback mark positioning.
-     *
-     * We do this because the CGJ-handling logic in the normalizer relies on
-     * mark sequences having an increasing order even after this reordering.
-     * https://github.com/harfbuzz/harfbuzz/issues/554
-     * This, however, does break some obscure sequences, where the normalizer
-     * might compose a sequence that it should not.  For example, in the seequence
-     * ALEF, HAMZAH, MADDAH, we should NOT try to compose ALEF+MADDAH, but with this
-     * renumbering, we will.
-     */
-    unsigned int new_start = start + j - i;
-    unsigned int new_cc = cc == 220 ? HB_MODIFIED_COMBINING_CLASS_CCC22 : HB_MODIFIED_COMBINING_CLASS_CCC26;
-    while (start < new_start)
-    {
-      _hb_glyph_info_set_modified_combining_class (&info[start], new_cc);
-      start++;
-    }
-
-    i = j;
-  }
-}
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
-{
-  collect_features_arabic,
-  nullptr, /* override_features */
-  data_create_arabic,
-  data_destroy_arabic,
-  nullptr, /* preprocess_text */
-  postprocess_glyphs_arabic,
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
-  nullptr, /* decompose */
-  nullptr, /* compose */
-  setup_masks_arabic,
-  nullptr, /* disable_otl */
-  reorder_marks_arabic,
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-  true, /* fallback_position */
-};
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc
deleted file mode 100644
index 68a62a1..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright © 2010,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
-{
-  nullptr, /* collect_features */
-  nullptr, /* override_features */
-  nullptr, /* data_create */
-  nullptr, /* data_destroy */
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
-  nullptr, /* decompose */
-  nullptr, /* compose */
-  nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-  true, /* fallback_position */
-};
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc
deleted file mode 100644
index 7508c223..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright © 2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-/* Hangul shaper */
-
-
-/* Same order as the feature array below */
-enum {
-  _JMO,
-
-  LJMO,
-  VJMO,
-  TJMO,
-
-  FIRST_HANGUL_FEATURE = LJMO,
-  HANGUL_FEATURE_COUNT = TJMO + 1
-};
-
-static const hb_tag_t hangul_features[HANGUL_FEATURE_COUNT] =
-{
-  HB_TAG_NONE,
-  HB_TAG('l','j','m','o'),
-  HB_TAG('v','j','m','o'),
-  HB_TAG('t','j','m','o')
-};
-
-static void
-collect_features_hangul (hb_ot_shape_planner_t *plan)
-{
-  hb_ot_map_builder_t *map = &plan->map;
-
-  for (unsigned int i = FIRST_HANGUL_FEATURE; i < HANGUL_FEATURE_COUNT; i++)
-    map->add_feature (hangul_features[i], 1, F_NONE);
-}
-
-static void
-override_features_hangul (hb_ot_shape_planner_t *plan)
-{
-  /* Uniscribe does not apply 'calt' for Hangul, and certain fonts
-   * (Noto Sans CJK, Source Sans Han, etc) apply all of jamo lookups
-   * in calt, which is not desirable. */
-  plan->map.add_feature (HB_TAG('c','a','l','t'), 0, F_GLOBAL);
-}
-
-struct hangul_shape_plan_t
-{
-  ASSERT_POD ();
-
-  hb_mask_t mask_array[HANGUL_FEATURE_COUNT];
-};
-
-static void *
-data_create_hangul (const hb_ot_shape_plan_t *plan)
-{
-  hangul_shape_plan_t *hangul_plan = (hangul_shape_plan_t *) calloc (1, sizeof (hangul_shape_plan_t));
-  if (unlikely (!hangul_plan))
-    return nullptr;
-
-  for (unsigned int i = 0; i < HANGUL_FEATURE_COUNT; i++)
-    hangul_plan->mask_array[i] = plan->map.get_1_mask (hangul_features[i]);
-
-  return hangul_plan;
-}
-
-static void
-data_destroy_hangul (void *data)
-{
-  free (data);
-}
-
-/* Constants for algorithmic hangul syllable [de]composition. */
-#define LBase 0x1100u
-#define VBase 0x1161u
-#define TBase 0x11A7u
-#define LCount 19u
-#define VCount 21u
-#define TCount 28u
-#define SBase 0xAC00u
-#define NCount (VCount * TCount)
-#define SCount (LCount * NCount)
-
-#define isCombiningL(u) (hb_in_range<hb_codepoint_t> ((u), LBase, LBase+LCount-1))
-#define isCombiningV(u) (hb_in_range<hb_codepoint_t> ((u), VBase, VBase+VCount-1))
-#define isCombiningT(u) (hb_in_range<hb_codepoint_t> ((u), TBase+1, TBase+TCount-1))
-#define isCombinedS(u) (hb_in_range<hb_codepoint_t> ((u), SBase, SBase+SCount-1))
-
-#define isL(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu))
-#define isV(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u))
-#define isT(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu))
-
-#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302Eu, 0x302Fu))
-
-/* buffer var allocations */
-#define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */
-
-static bool
-is_zero_width_char (hb_font_t *font,
-		    hb_codepoint_t unicode)
-{
-  hb_codepoint_t glyph;
-  return hb_font_get_glyph (font, unicode, 0, &glyph) && hb_font_get_glyph_h_advance (font, glyph) == 0;
-}
-
-static void
-preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
-			hb_buffer_t              *buffer,
-			hb_font_t                *font)
-{
-  HB_BUFFER_ALLOCATE_VAR (buffer, hangul_shaping_feature);
-
-  /* Hangul syllables come in two shapes: LV, and LVT.  Of those:
-   *
-   *   - LV can be precomposed, or decomposed.  Lets call those
-   *     <LV> and <L,V>,
-   *   - LVT can be fully precomposed, partically precomposed, or
-   *     fully decomposed.  Ie. <LVT>, <LV,T>, or <L,V,T>.
-   *
-   * The composition / decomposition is mechanical.  However, not
-   * all <L,V> sequences compose, and not all <LV,T> sequences
-   * compose.
-   *
-   * Here are the specifics:
-   *
-   *   - <L>: U+1100..115F, U+A960..A97F
-   *   - <V>: U+1160..11A7, U+D7B0..D7C7
-   *   - <T>: U+11A8..11FF, U+D7CB..D7FB
-   *
-   *   - Only the <L,V> sequences for the 11xx ranges combine.
-   *   - Only <LV,T> sequences for T in U+11A8..11C3 combine.
-   *
-   * Here is what we want to accomplish in this shaper:
-   *
-   *   - If the whole syllable can be precomposed, do that,
-   *   - Otherwise, fully decompose and apply ljmo/vjmo/tjmo features.
-   *   - If a valid syllable is followed by a Hangul tone mark, reorder the tone
-   *     mark to precede the whole syllable - unless it is a zero-width glyph, in
-   *     which case we leave it untouched, assuming it's designed to overstrike.
-   *
-   * That is, of the different possible syllables:
-   *
-   *   <L>
-   *   <L,V>
-   *   <L,V,T>
-   *   <LV>
-   *   <LVT>
-   *   <LV, T>
-   *
-   * - <L> needs no work.
-   *
-   * - <LV> and <LVT> can stay the way they are if the font supports them, otherwise we
-   *   should fully decompose them if font supports.
-   *
-   * - <L,V> and <L,V,T> we should compose if the whole thing can be composed.
-   *
-   * - <LV,T> we should compose if the whole thing can be composed, otherwise we should
-   *   decompose.
-   */
-
-  buffer->clear_output ();
-  unsigned int start = 0, end = 0; /* Extent of most recently seen syllable;
-				    * valid only if start < end
-				    */
-  unsigned int count = buffer->len;
-
-  for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;)
-  {
-    hb_codepoint_t u = buffer->cur().codepoint;
-
-    if (isHangulTone (u))
-    {
-      /*
-       * We could cache the width of the tone marks and the existence of dotted-circle,
-       * but the use of the Hangul tone mark characters seems to be rare enough that
-       * I didn't bother for now.
-       */
-      if (start < end && end == buffer->out_len)
-      {
-	/* Tone mark follows a valid syllable; move it in front, unless it's zero width. */
-        buffer->unsafe_to_break_from_outbuffer (start, buffer->idx);
-	buffer->next_glyph ();
-	if (!is_zero_width_char (font, u))
-	{
-	  buffer->merge_out_clusters (start, end + 1);
-	  hb_glyph_info_t *info = buffer->out_info;
-	  hb_glyph_info_t tone = info[end];
-	  memmove (&info[start + 1], &info[start], (end - start) * sizeof (hb_glyph_info_t));
-	  info[start] = tone;
-	}
-      }
-      else
-      {
-	/* No valid syllable as base for tone mark; try to insert dotted circle. */
-	if (font->has_glyph (0x25CCu))
-	{
-	  hb_codepoint_t chars[2];
-	  if (!is_zero_width_char (font, u)) {
-	    chars[0] = u;
-	    chars[1] = 0x25CCu;
-	  } else {
-	    chars[0] = 0x25CCu;
-	    chars[1] = u;
-	  }
-	  buffer->replace_glyphs (1, 2, chars);
-	}
-	else
-	{
-	  /* No dotted circle available in the font; just leave tone mark untouched. */
-	  buffer->next_glyph ();
-	}
-      }
-      start = end = buffer->out_len;
-      continue;
-    }
-
-    start = buffer->out_len; /* Remember current position as a potential syllable start;
-			      * will only be used if we set end to a later position.
-			      */
-
-    if (isL (u) && buffer->idx + 1 < count)
-    {
-      hb_codepoint_t l = u;
-      hb_codepoint_t v = buffer->cur(+1).codepoint;
-      if (isV (v))
-      {
-	/* Have <L,V> or <L,V,T>. */
-	hb_codepoint_t t = 0;
-	unsigned int tindex = 0;
-	if (buffer->idx + 2 < count)
-	{
-	  t = buffer->cur(+2).codepoint;
-	  if (isT (t))
-	    tindex = t - TBase; /* Only used if isCombiningT (t); otherwise invalid. */
-	  else
-	    t = 0; /* The next character was not a trailing jamo. */
-	}
-	buffer->unsafe_to_break (buffer->idx, buffer->idx + (t ? 3 : 2));
-
-	/* We've got a syllable <L,V,T?>; see if it can potentially be composed. */
-	if (isCombiningL (l) && isCombiningV (v) && (t == 0 || isCombiningT (t)))
-	{
-	  /* Try to compose; if this succeeds, end is set to start+1. */
-	  hb_codepoint_t s = SBase + (l - LBase) * NCount + (v - VBase) * TCount + tindex;
-	  if (font->has_glyph (s))
-	  {
-	    buffer->replace_glyphs (t ? 3 : 2, 1, &s);
-	    if (unlikely (buffer->in_error))
-	      return;
-	    end = start + 1;
-	    continue;
-	  }
-	}
-
-	/* We didn't compose, either because it's an Old Hangul syllable without a
-	 * precomposed character in Unicode, or because the font didn't support the
-	 * necessary precomposed glyph.
-	 * Set jamo features on the individual glyphs, and advance past them.
-	 */
-	buffer->cur().hangul_shaping_feature() = LJMO;
-	buffer->next_glyph ();
-	buffer->cur().hangul_shaping_feature() = VJMO;
-	buffer->next_glyph ();
-	if (t)
-	{
-	  buffer->cur().hangul_shaping_feature() = TJMO;
-	  buffer->next_glyph ();
-	  end = start + 3;
-	}
-	else
-	  end = start + 2;
-	if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
-	  buffer->merge_out_clusters (start, end);
-	continue;
-      }
-    }
-
-    else if (isCombinedS (u))
-    {
-      /* Have <LV>, <LVT>, or <LV,T> */
-      hb_codepoint_t s = u;
-      bool has_glyph = font->has_glyph (s);
-      unsigned int lindex = (s - SBase) / NCount;
-      unsigned int nindex = (s - SBase) % NCount;
-      unsigned int vindex = nindex / TCount;
-      unsigned int tindex = nindex % TCount;
-
-      if (!tindex &&
-	  buffer->idx + 1 < count &&
-	  isCombiningT (buffer->cur(+1).codepoint))
-      {
-	/* <LV,T>, try to combine. */
-	unsigned int new_tindex = buffer->cur(+1).codepoint - TBase;
-	hb_codepoint_t new_s = s + new_tindex;
-	if (font->has_glyph (new_s))
-	{
-	  buffer->replace_glyphs (2, 1, &new_s);
-	  if (unlikely (buffer->in_error))
-	    return;
-	  end = start + 1;
-	  continue;
-	}
-	else
-	  buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */
-      }
-
-      /* Otherwise, decompose if font doesn't support <LV> or <LVT>,
-       * or if having non-combining <LV,T>.  Note that we already handled
-       * combining <LV,T> above. */
-      if (!has_glyph ||
-	  (!tindex &&
-	   buffer->idx + 1 < count &&
-	   isT (buffer->cur(+1).codepoint)))
-      {
-	hb_codepoint_t decomposed[3] = {LBase + lindex,
-					VBase + vindex,
-					TBase + tindex};
-	if (font->has_glyph (decomposed[0]) &&
-	    font->has_glyph (decomposed[1]) &&
-	    (!tindex || font->has_glyph (decomposed[2])))
-	{
-	  unsigned int s_len = tindex ? 3 : 2;
-	  buffer->replace_glyphs (1, s_len, decomposed);
-	  if (unlikely (buffer->in_error))
-	    return;
-
-	  /* We decomposed S: apply jamo features to the individual glyphs
-	   * that are now in buffer->out_info.
-	   */
-	  hb_glyph_info_t *info = buffer->out_info;
-
-	  /* If we decomposed an LV because of a non-combining T following,
-	   * we want to include this T in the syllable.
-	   */
-	  if (has_glyph && !tindex)
-	  {
-            buffer->next_glyph ();
-            s_len++;
-          }
-          end = start + s_len;
-
-	  unsigned int i = start;
-	  info[i++].hangul_shaping_feature() = LJMO;
-	  info[i++].hangul_shaping_feature() = VJMO;
-	  if (i < end)
-	    info[i++].hangul_shaping_feature() = TJMO;
-	  if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
-	    buffer->merge_out_clusters (start, end);
-	  continue;
-	}
-	else if ((!tindex && buffer->idx + 1 < count && isT (buffer->cur(+1).codepoint)))
-	  buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */
-      }
-
-      if (has_glyph)
-      {
-        /* We didn't decompose the S, so just advance past it. */
-	end = start + 1;
-	buffer->next_glyph ();
-	continue;
-      }
-    }
-
-    /* Didn't find a recognizable syllable, so we leave end <= start;
-     * this will prevent tone-mark reordering happening.
-     */
-    buffer->next_glyph ();
-  }
-  buffer->swap_buffers ();
-}
-
-static void
-setup_masks_hangul (const hb_ot_shape_plan_t *plan,
-		    hb_buffer_t              *buffer,
-		    hb_font_t                *font HB_UNUSED)
-{
-  const hangul_shape_plan_t *hangul_plan = (const hangul_shape_plan_t *) plan->data;
-
-  if (likely (hangul_plan))
-  {
-    unsigned int count = buffer->len;
-    hb_glyph_info_t *info = buffer->info;
-    for (unsigned int i = 0; i < count; i++, info++)
-      info->mask |= hangul_plan->mask_array[info->hangul_shaping_feature()];
-  }
-
-  HB_BUFFER_DEALLOCATE_VAR (buffer, hangul_shaping_feature);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
-{
-  collect_features_hangul,
-  override_features_hangul,
-  data_create_hangul,
-  data_destroy_hangul,
-  preprocess_text_hangul,
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
-  nullptr, /* decompose */
-  nullptr, /* compose */
-  setup_masks_hangul,
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
-  false, /* fallback_position */
-};
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc
deleted file mode 100644
index 34cf28b..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright © 2010,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-static bool
-compose_hebrew (const hb_ot_shape_normalize_context_t *c,
-		hb_codepoint_t  a,
-		hb_codepoint_t  b,
-		hb_codepoint_t *ab)
-{
-  /* Hebrew presentation-form shaping.
-   * https://bugzilla.mozilla.org/show_bug.cgi?id=728866
-   * Hebrew presentation forms with dagesh, for characters U+05D0..05EA;
-   * Note that some letters do not have a dagesh presForm encoded.
-   */
-  static const hb_codepoint_t sDageshForms[0x05EAu - 0x05D0u + 1] = {
-    0xFB30u, /* ALEF */
-    0xFB31u, /* BET */
-    0xFB32u, /* GIMEL */
-    0xFB33u, /* DALET */
-    0xFB34u, /* HE */
-    0xFB35u, /* VAV */
-    0xFB36u, /* ZAYIN */
-    0x0000u, /* HET */
-    0xFB38u, /* TET */
-    0xFB39u, /* YOD */
-    0xFB3Au, /* FINAL KAF */
-    0xFB3Bu, /* KAF */
-    0xFB3Cu, /* LAMED */
-    0x0000u, /* FINAL MEM */
-    0xFB3Eu, /* MEM */
-    0x0000u, /* FINAL NUN */
-    0xFB40u, /* NUN */
-    0xFB41u, /* SAMEKH */
-    0x0000u, /* AYIN */
-    0xFB43u, /* FINAL PE */
-    0xFB44u, /* PE */
-    0x0000u, /* FINAL TSADI */
-    0xFB46u, /* TSADI */
-    0xFB47u, /* QOF */
-    0xFB48u, /* RESH */
-    0xFB49u, /* SHIN */
-    0xFB4Au /* TAV */
-  };
-
-  bool found = (bool) c->unicode->compose (a, b, ab);
-
-  if (!found && !c->plan->has_mark)
-  {
-      /* Special-case Hebrew presentation forms that are excluded from
-       * standard normalization, but wanted for old fonts. */
-      switch (b) {
-      case 0x05B4u: /* HIRIQ */
-	  if (a == 0x05D9u) { /* YOD */
-	      *ab = 0xFB1Du;
-	      found = true;
-	  }
-	  break;
-      case 0x05B7u: /* patah */
-	  if (a == 0x05F2u) { /* YIDDISH YOD YOD */
-	      *ab = 0xFB1Fu;
-	      found = true;
-	  } else if (a == 0x05D0u) { /* ALEF */
-	      *ab = 0xFB2Eu;
-	      found = true;
-	  }
-	  break;
-      case 0x05B8u: /* QAMATS */
-	  if (a == 0x05D0u) { /* ALEF */
-	      *ab = 0xFB2Fu;
-	      found = true;
-	  }
-	  break;
-      case 0x05B9u: /* HOLAM */
-	  if (a == 0x05D5u) { /* VAV */
-	      *ab = 0xFB4Bu;
-	      found = true;
-	  }
-	  break;
-      case 0x05BCu: /* DAGESH */
-	  if (a >= 0x05D0u && a <= 0x05EAu) {
-	      *ab = sDageshForms[a - 0x05D0u];
-	      found = (*ab != 0);
-	  } else if (a == 0xFB2Au) { /* SHIN WITH SHIN DOT */
-	      *ab = 0xFB2Cu;
-	      found = true;
-	  } else if (a == 0xFB2Bu) { /* SHIN WITH SIN DOT */
-	      *ab = 0xFB2Du;
-	      found = true;
-	  }
-	  break;
-      case 0x05BFu: /* RAFE */
-	  switch (a) {
-	  case 0x05D1u: /* BET */
-	      *ab = 0xFB4Cu;
-	      found = true;
-	      break;
-	  case 0x05DBu: /* KAF */
-	      *ab = 0xFB4Du;
-	      found = true;
-	      break;
-	  case 0x05E4u: /* PE */
-	      *ab = 0xFB4Eu;
-	      found = true;
-	      break;
-	  }
-	  break;
-      case 0x05C1u: /* SHIN DOT */
-	  if (a == 0x05E9u) { /* SHIN */
-	      *ab = 0xFB2Au;
-	      found = true;
-	  } else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
-	      *ab = 0xFB2Cu;
-	      found = true;
-	  }
-	  break;
-      case 0x05C2u: /* SIN DOT */
-	  if (a == 0x05E9u) { /* SHIN */
-	      *ab = 0xFB2Bu;
-	      found = true;
-	  } else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
-	      *ab = 0xFB2Du;
-	      found = true;
-	  }
-	  break;
-      }
-  }
-
-  return found;
-}
-
-static bool
-disable_otl_hebrew (const hb_ot_shape_plan_t *plan)
-{
-  /* For Hebrew shaper, use fallback if GPOS does not have 'hebr'
-   * script.  This matches Uniscribe better, and makes fonts like
-   * Arial that have GSUB/GPOS/GDEF but no data for Hebrew work.
-   * See:
-   * https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368
-   */
-  return plan->map.chosen_script[1] != HB_TAG ('h','e','b','r');
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
-{
-  nullptr, /* collect_features */
-  nullptr, /* override_features */
-  nullptr, /* data_create */
-  nullptr, /* data_destroy */
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
-  nullptr, /* decompose */
-  compose_hebrew,
-  nullptr, /* setup_masks */
-  disable_otl_hebrew,
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-  true, /* fallback_position */
-};
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh
deleted file mode 100644
index f3cea22..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh
+++ /dev/null
@@ -1,1319 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-indic-machine.rl"
-/*
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
-
-#include "hb-private.hh"
-
-
-#line 36 "hb-ot-shape-complex-indic-machine.hh"
-static const unsigned char _indic_syllable_machine_trans_keys[] = {
-	8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
-	5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 
-	4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
-	16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 
-	4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
-	5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 
-	4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
-	16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 
-	4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 8u, 
-	5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 
-	5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
-	16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 
-	4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 
-	8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
-	5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 
-	4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
-	16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 
-	4u, 13u, 4u, 8u, 4u, 13u, 4u, 13u, 5u, 8u, 5u, 8u, 5u, 7u, 5u, 8u, 
-	5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 
-	8u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 
-	6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 8u, 8u, 1u, 19u, 3u, 17u, 
-	3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 
-	3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 
-	3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 
-	5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
-	3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 
-	3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 
-	1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 
-	1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 
-	3u, 17u, 3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 
-	4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 
-	4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 
-	10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
-	3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 
-	5u, 10u, 3u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 
-	1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 
-	3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 
-	1u, 16u, 1u, 16u, 1u, 16u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 
-	3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 
-	3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 
-	5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u, 
-	4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
-	3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 
-	1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 
-	1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 
-	3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 13u, 3u, 17u, 4u, 8u, 
-	3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 
-	3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 
-	3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 
-	10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 
-	5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 
-	4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 
-	3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 
-	1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 
-	1u, 16u, 3u, 17u, 1u, 17u, 3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u, 
-	10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 
-	4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
-	3u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 
-	0
-};
-
-static const char _indic_syllable_machine_key_spans[] = {
-	1, 4, 3, 1, 4, 3, 1, 4, 
-	3, 1, 4, 3, 1, 5, 1, 1, 
-	5, 1, 1, 5, 1, 1, 5, 1, 
-	1, 5, 10, 5, 10, 5, 10, 5, 
-	10, 5, 10, 1, 4, 3, 1, 4, 
-	3, 1, 4, 3, 1, 4, 3, 1, 
-	5, 1, 1, 5, 1, 1, 5, 1, 
-	1, 5, 1, 1, 5, 10, 5, 10, 
-	5, 10, 5, 10, 5, 10, 1, 4, 
-	3, 1, 4, 3, 1, 4, 3, 1, 
-	4, 3, 1, 5, 1, 1, 5, 1, 
-	1, 5, 1, 1, 5, 1, 1, 5, 
-	10, 5, 10, 5, 10, 5, 10, 5, 
-	1, 4, 3, 1, 4, 3, 1, 4, 
-	3, 1, 4, 3, 1, 5, 1, 1, 
-	5, 1, 1, 5, 1, 1, 5, 1, 
-	1, 5, 10, 5, 10, 5, 10, 5, 
-	10, 5, 10, 10, 4, 4, 3, 4, 
-	3, 1, 4, 3, 1, 4, 3, 1, 
-	1, 5, 1, 1, 5, 1, 1, 5, 
-	1, 1, 5, 1, 1, 1, 19, 15, 
-	15, 14, 16, 15, 15, 14, 16, 15, 
-	15, 14, 16, 15, 15, 14, 16, 15, 
-	15, 14, 6, 6, 6, 1, 1, 1, 
-	6, 8, 8, 7, 6, 8, 7, 6, 
-	8, 7, 6, 8, 7, 6, 8, 7, 
-	15, 15, 16, 16, 16, 16, 15, 15, 
-	16, 16, 16, 16, 15, 15, 16, 16, 
-	16, 16, 15, 15, 16, 16, 16, 16, 
-	15, 15, 15, 15, 14, 16, 15, 15, 
-	14, 16, 15, 15, 14, 16, 15, 15, 
-	14, 16, 15, 15, 14, 6, 6, 6, 
-	1, 1, 1, 6, 8, 8, 7, 6, 
-	8, 7, 6, 8, 7, 6, 8, 7, 
-	6, 8, 7, 15, 15, 16, 16, 16, 
-	16, 15, 15, 16, 16, 16, 16, 15, 
-	15, 16, 16, 16, 16, 15, 15, 16, 
-	16, 16, 16, 5, 15, 15, 14, 16, 
-	15, 15, 14, 16, 15, 15, 14, 16, 
-	15, 15, 14, 16, 15, 15, 14, 6, 
-	6, 6, 1, 1, 1, 6, 8, 8, 
-	7, 6, 8, 7, 6, 8, 7, 6, 
-	8, 7, 6, 8, 7, 15, 15, 16, 
-	16, 16, 16, 15, 15, 16, 16, 16, 
-	16, 15, 15, 16, 16, 16, 16, 15, 
-	15, 16, 16, 16, 16, 10, 15, 5, 
-	15, 15, 14, 16, 15, 15, 14, 16, 
-	15, 15, 14, 16, 15, 15, 14, 16, 
-	15, 15, 14, 6, 6, 6, 1, 1, 
-	1, 6, 8, 8, 7, 6, 8, 7, 
-	6, 8, 7, 6, 8, 7, 6, 8, 
-	7, 15, 15, 16, 16, 16, 16, 15, 
-	15, 16, 16, 16, 16, 15, 15, 16, 
-	16, 16, 16, 15, 15, 16, 16, 16, 
-	16, 15, 17, 15, 17, 10, 6, 1, 
-	1, 1, 6, 16, 8, 7, 6, 8, 
-	7, 6, 8, 7, 6, 8, 7, 6, 
-	8, 6, 6, 1, 1, 1, 6, 16
-};
-
-static const short _indic_syllable_machine_index_offsets[] = {
-	0, 2, 7, 11, 13, 18, 22, 24, 
-	29, 33, 35, 40, 44, 46, 52, 54, 
-	56, 62, 64, 66, 72, 74, 76, 82, 
-	84, 86, 92, 103, 109, 120, 126, 137, 
-	143, 154, 160, 171, 173, 178, 182, 184, 
-	189, 193, 195, 200, 204, 206, 211, 215, 
-	217, 223, 225, 227, 233, 235, 237, 243, 
-	245, 247, 253, 255, 257, 263, 274, 280, 
-	291, 297, 308, 314, 325, 331, 342, 344, 
-	349, 353, 355, 360, 364, 366, 371, 375, 
-	377, 382, 386, 388, 394, 396, 398, 404, 
-	406, 408, 414, 416, 418, 424, 426, 428, 
-	434, 445, 451, 462, 468, 479, 485, 496, 
-	502, 504, 509, 513, 515, 520, 524, 526, 
-	531, 535, 537, 542, 546, 548, 554, 556, 
-	558, 564, 566, 568, 574, 576, 578, 584, 
-	586, 588, 594, 605, 611, 622, 628, 639, 
-	645, 656, 662, 673, 684, 689, 694, 698, 
-	703, 707, 709, 714, 718, 720, 725, 729, 
-	731, 733, 739, 741, 743, 749, 751, 753, 
-	759, 761, 763, 769, 771, 773, 775, 795, 
-	811, 827, 842, 859, 875, 891, 906, 923, 
-	939, 955, 970, 987, 1003, 1019, 1034, 1051, 
-	1067, 1083, 1098, 1105, 1112, 1119, 1121, 1123, 
-	1125, 1132, 1141, 1150, 1158, 1165, 1174, 1182, 
-	1189, 1198, 1206, 1213, 1222, 1230, 1237, 1246, 
-	1254, 1270, 1286, 1303, 1320, 1337, 1354, 1370, 
-	1386, 1403, 1420, 1437, 1454, 1470, 1486, 1503, 
-	1520, 1537, 1554, 1570, 1586, 1603, 1620, 1637, 
-	1654, 1670, 1686, 1702, 1718, 1733, 1750, 1766, 
-	1782, 1797, 1814, 1830, 1846, 1861, 1878, 1894, 
-	1910, 1925, 1942, 1958, 1974, 1989, 1996, 2003, 
-	2010, 2012, 2014, 2016, 2023, 2032, 2041, 2049, 
-	2056, 2065, 2073, 2080, 2089, 2097, 2104, 2113, 
-	2121, 2128, 2137, 2145, 2161, 2177, 2194, 2211, 
-	2228, 2245, 2261, 2277, 2294, 2311, 2328, 2345, 
-	2361, 2377, 2394, 2411, 2428, 2445, 2461, 2477, 
-	2494, 2511, 2528, 2545, 2551, 2567, 2583, 2598, 
-	2615, 2631, 2647, 2662, 2679, 2695, 2711, 2726, 
-	2743, 2759, 2775, 2790, 2807, 2823, 2839, 2854, 
-	2861, 2868, 2875, 2877, 2879, 2881, 2888, 2897, 
-	2906, 2914, 2921, 2930, 2938, 2945, 2954, 2962, 
-	2969, 2978, 2986, 2993, 3002, 3010, 3026, 3042, 
-	3059, 3076, 3093, 3110, 3126, 3142, 3159, 3176, 
-	3193, 3210, 3226, 3242, 3259, 3276, 3293, 3310, 
-	3326, 3342, 3359, 3376, 3393, 3410, 3421, 3437, 
-	3443, 3459, 3475, 3490, 3507, 3523, 3539, 3554, 
-	3571, 3587, 3603, 3618, 3635, 3651, 3667, 3682, 
-	3699, 3715, 3731, 3746, 3753, 3760, 3767, 3769, 
-	3771, 3773, 3780, 3789, 3798, 3806, 3813, 3822, 
-	3830, 3837, 3846, 3854, 3861, 3870, 3878, 3885, 
-	3894, 3902, 3918, 3934, 3951, 3968, 3985, 4002, 
-	4018, 4034, 4051, 4068, 4085, 4102, 4118, 4134, 
-	4151, 4168, 4185, 4202, 4218, 4234, 4251, 4268, 
-	4285, 4302, 4318, 4336, 4352, 4370, 4381, 4388, 
-	4390, 4392, 4394, 4401, 4418, 4427, 4435, 4442, 
-	4451, 4459, 4466, 4475, 4483, 4490, 4499, 4507, 
-	4514, 4523, 4530, 4537, 4539, 4541, 4543, 4550
-};
-
-static const short _indic_syllable_machine_indicies[] = {
-	1, 0, 2, 2, 3, 1, 0, 4, 
-	4, 3, 0, 3, 0, 5, 5, 6, 
-	1, 0, 7, 7, 6, 0, 6, 0, 
-	8, 8, 9, 1, 0, 10, 10, 9, 
-	0, 9, 0, 11, 11, 12, 1, 0, 
-	13, 13, 12, 0, 12, 0, 14, 0, 
-	0, 0, 1, 0, 15, 0, 16, 0, 
-	17, 11, 11, 12, 1, 0, 18, 0, 
-	19, 0, 20, 8, 8, 9, 1, 0, 
-	21, 0, 22, 0, 23, 5, 5, 6, 
-	1, 0, 24, 0, 25, 0, 26, 2, 
-	2, 3, 1, 0, 26, 2, 2, 3, 
-	1, 0, 0, 0, 0, 27, 0, 28, 
-	2, 2, 3, 1, 0, 28, 2, 2, 
-	3, 1, 0, 0, 0, 0, 29, 0, 
-	30, 2, 2, 3, 1, 0, 30, 2, 
-	2, 3, 1, 0, 0, 0, 0, 31, 
-	0, 32, 2, 2, 3, 1, 0, 32, 
-	2, 2, 3, 1, 0, 0, 0, 0, 
-	33, 0, 34, 2, 2, 3, 1, 0, 
-	34, 2, 2, 3, 1, 0, 0, 0, 
-	0, 35, 0, 37, 36, 38, 38, 39, 
-	37, 36, 40, 40, 39, 36, 39, 36, 
-	41, 41, 42, 37, 36, 43, 43, 42, 
-	36, 42, 36, 44, 44, 45, 37, 36, 
-	46, 46, 45, 36, 45, 36, 47, 47, 
-	48, 37, 36, 49, 49, 48, 36, 48, 
-	36, 50, 36, 36, 36, 37, 36, 51, 
-	36, 52, 36, 53, 47, 47, 48, 37, 
-	36, 54, 36, 55, 36, 56, 44, 44, 
-	45, 37, 36, 57, 36, 58, 36, 59, 
-	41, 41, 42, 37, 36, 60, 36, 61, 
-	36, 62, 38, 38, 39, 37, 36, 62, 
-	38, 38, 39, 37, 36, 36, 36, 36, 
-	63, 36, 64, 38, 38, 39, 37, 36, 
-	64, 38, 38, 39, 37, 36, 36, 36, 
-	36, 65, 36, 66, 38, 38, 39, 37, 
-	36, 66, 38, 38, 39, 37, 36, 36, 
-	36, 36, 67, 36, 68, 38, 38, 39, 
-	37, 36, 68, 38, 38, 39, 37, 36, 
-	36, 36, 36, 69, 36, 70, 38, 38, 
-	39, 37, 36, 70, 38, 38, 39, 37, 
-	36, 36, 36, 36, 71, 36, 73, 72, 
-	74, 74, 75, 73, 72, 77, 77, 75, 
-	76, 75, 76, 78, 78, 79, 73, 72, 
-	80, 80, 79, 72, 79, 72, 81, 81, 
-	82, 73, 72, 83, 83, 82, 72, 82, 
-	72, 84, 84, 85, 73, 72, 86, 86, 
-	85, 72, 85, 72, 87, 72, 72, 72, 
-	73, 72, 88, 72, 89, 72, 90, 84, 
-	84, 85, 73, 72, 91, 72, 92, 72, 
-	93, 81, 81, 82, 73, 72, 94, 72, 
-	95, 72, 96, 78, 78, 79, 73, 72, 
-	97, 72, 98, 72, 99, 74, 74, 75, 
-	73, 72, 99, 74, 74, 75, 73, 72, 
-	72, 72, 72, 100, 72, 101, 74, 74, 
-	75, 73, 72, 101, 74, 74, 75, 73, 
-	72, 72, 72, 72, 102, 72, 103, 74, 
-	74, 75, 73, 72, 103, 74, 74, 75, 
-	73, 72, 72, 72, 72, 104, 72, 105, 
-	74, 74, 75, 73, 72, 105, 74, 74, 
-	75, 73, 72, 72, 72, 72, 106, 72, 
-	107, 74, 74, 75, 73, 72, 109, 108, 
-	110, 110, 111, 109, 108, 112, 112, 111, 
-	108, 111, 108, 113, 113, 114, 109, 108, 
-	115, 115, 114, 108, 114, 108, 116, 116, 
-	117, 109, 108, 118, 118, 117, 108, 117, 
-	108, 119, 119, 120, 109, 108, 121, 121, 
-	120, 108, 120, 108, 122, 108, 108, 108, 
-	109, 108, 123, 108, 124, 108, 125, 119, 
-	119, 120, 109, 108, 126, 108, 127, 108, 
-	128, 116, 116, 117, 109, 108, 129, 108, 
-	130, 108, 131, 113, 113, 114, 109, 108, 
-	132, 108, 133, 108, 134, 110, 110, 111, 
-	109, 108, 134, 110, 110, 111, 109, 108, 
-	108, 108, 108, 135, 108, 136, 110, 110, 
-	111, 109, 108, 136, 110, 110, 111, 109, 
-	108, 108, 108, 108, 137, 108, 138, 110, 
-	110, 111, 109, 108, 138, 110, 110, 111, 
-	109, 108, 108, 108, 108, 139, 108, 140, 
-	110, 110, 111, 109, 108, 140, 110, 110, 
-	111, 109, 108, 108, 108, 108, 141, 108, 
-	142, 110, 110, 111, 109, 108, 142, 110, 
-	110, 111, 109, 108, 108, 108, 108, 143, 
-	108, 107, 74, 74, 75, 73, 72, 72, 
-	72, 72, 144, 72, 77, 77, 75, 1, 
-	0, 145, 145, 146, 1, 0, 4, 4, 
-	146, 0, 147, 147, 148, 149, 0, 150, 
-	150, 148, 0, 148, 0, 151, 151, 152, 
-	149, 0, 153, 153, 152, 0, 152, 0, 
-	154, 154, 155, 149, 0, 156, 156, 155, 
-	0, 155, 0, 149, 0, 157, 0, 0, 
-	0, 149, 0, 158, 0, 159, 0, 160, 
-	154, 154, 155, 149, 0, 161, 0, 162, 
-	0, 163, 151, 151, 152, 149, 0, 164, 
-	0, 165, 0, 166, 147, 147, 148, 149, 
-	0, 167, 0, 168, 0, 170, 169, 172, 
-	173, 174, 175, 176, 177, 75, 73, 171, 
-	178, 179, 179, 144, 171, 180, 181, 182, 
-	183, 184, 171, 186, 187, 188, 189, 3, 
-	1, 185, 190, 185, 185, 35, 185, 185, 
-	185, 191, 185, 192, 187, 193, 193, 3, 
-	1, 185, 190, 185, 185, 185, 185, 185, 
-	185, 191, 185, 187, 193, 193, 3, 1, 
-	185, 190, 185, 185, 185, 185, 185, 185, 
-	191, 185, 194, 185, 185, 185, 16, 195, 
-	185, 1, 185, 190, 185, 185, 185, 185, 
-	185, 194, 185, 196, 197, 198, 199, 3, 
-	1, 185, 190, 185, 185, 33, 185, 185, 
-	185, 191, 185, 200, 197, 201, 201, 3, 
-	1, 185, 190, 185, 185, 185, 185, 185, 
-	185, 191, 185, 197, 201, 201, 3, 1, 
-	185, 190, 185, 185, 185, 185, 185, 185, 
-	191, 185, 202, 185, 185, 185, 16, 203, 
-	185, 1, 185, 190, 185, 185, 185, 185, 
-	185, 202, 185, 204, 205, 206, 207, 3, 
-	1, 185, 190, 185, 185, 31, 185, 185, 
-	185, 191, 185, 208, 205, 209, 209, 3, 
-	1, 185, 190, 185, 185, 185, 185, 185, 
-	185, 191, 185, 205, 209, 209, 3, 1, 
-	185, 190, 185, 185, 185, 185, 185, 185, 
-	191, 185, 210, 185, 185, 185, 16, 211, 
-	185, 1, 185, 190, 185, 185, 185, 185, 
-	185, 210, 185, 212, 213, 214, 215, 3, 
-	1, 185, 190, 185, 185, 29, 185, 185, 
-	185, 191, 185, 216, 213, 217, 217, 3, 
-	1, 185, 190, 185, 185, 185, 185, 185, 
-	185, 191, 185, 213, 217, 217, 3, 1, 
-	185, 190, 185, 185, 185, 185, 185, 185, 
-	191, 185, 218, 185, 185, 185, 16, 219, 
-	185, 1, 185, 190, 185, 185, 185, 185, 
-	185, 218, 185, 220, 221, 222, 223, 3, 
-	1, 185, 190, 185, 185, 27, 185, 185, 
-	185, 191, 185, 224, 221, 225, 225, 3, 
-	1, 185, 190, 185, 185, 185, 185, 185, 
-	185, 191, 185, 221, 225, 225, 3, 1, 
-	185, 190, 185, 185, 185, 185, 185, 185, 
-	191, 185, 16, 226, 185, 1, 185, 190, 
-	185, 227, 227, 185, 1, 185, 190, 185, 
-	228, 185, 185, 229, 185, 190, 185, 190, 
-	185, 230, 185, 231, 185, 228, 185, 185, 
-	185, 185, 190, 185, 16, 185, 232, 232, 
-	3, 1, 185, 190, 185, 233, 25, 234, 
-	235, 6, 1, 185, 190, 185, 25, 234, 
-	235, 6, 1, 185, 190, 185, 234, 234, 
-	6, 1, 185, 190, 185, 236, 22, 237, 
-	238, 9, 1, 185, 190, 185, 22, 237, 
-	238, 9, 1, 185, 190, 185, 237, 237, 
-	9, 1, 185, 190, 185, 239, 19, 240, 
-	241, 12, 1, 185, 190, 185, 19, 240, 
-	241, 12, 1, 185, 190, 185, 240, 240, 
-	12, 1, 185, 190, 185, 242, 16, 227, 
-	243, 185, 1, 185, 190, 185, 16, 227, 
-	243, 185, 1, 185, 190, 185, 227, 244, 
-	185, 1, 185, 190, 185, 16, 185, 227, 
-	227, 185, 1, 185, 190, 185, 221, 225, 
-	225, 3, 1, 185, 190, 185, 220, 221, 
-	225, 225, 3, 1, 185, 190, 185, 185, 
-	185, 185, 185, 185, 191, 185, 220, 221, 
-	222, 225, 3, 1, 185, 190, 185, 185, 
-	27, 185, 185, 185, 191, 185, 218, 185, 
-	245, 185, 232, 232, 3, 1, 185, 190, 
-	185, 185, 185, 185, 185, 218, 185, 218, 
-	185, 185, 185, 227, 227, 185, 1, 185, 
-	190, 185, 185, 185, 185, 185, 218, 185, 
-	218, 185, 185, 185, 227, 246, 185, 1, 
-	185, 190, 185, 185, 185, 185, 185, 218, 
-	185, 218, 185, 245, 185, 227, 227, 185, 
-	1, 185, 190, 185, 185, 185, 185, 185, 
-	218, 185, 212, 213, 217, 217, 3, 1, 
-	185, 190, 185, 185, 185, 185, 185, 185, 
-	191, 185, 212, 213, 214, 217, 3, 1, 
-	185, 190, 185, 185, 29, 185, 185, 185, 
-	191, 185, 210, 185, 247, 185, 232, 232, 
-	3, 1, 185, 190, 185, 185, 185, 185, 
-	185, 210, 185, 210, 185, 185, 185, 227, 
-	227, 185, 1, 185, 190, 185, 185, 185, 
-	185, 185, 210, 185, 210, 185, 185, 185, 
-	227, 248, 185, 1, 185, 190, 185, 185, 
-	185, 185, 185, 210, 185, 210, 185, 247, 
-	185, 227, 227, 185, 1, 185, 190, 185, 
-	185, 185, 185, 185, 210, 185, 204, 205, 
-	209, 209, 3, 1, 185, 190, 185, 185, 
-	185, 185, 185, 185, 191, 185, 204, 205, 
-	206, 209, 3, 1, 185, 190, 185, 185, 
-	31, 185, 185, 185, 191, 185, 202, 185, 
-	249, 185, 232, 232, 3, 1, 185, 190, 
-	185, 185, 185, 185, 185, 202, 185, 202, 
-	185, 185, 185, 227, 227, 185, 1, 185, 
-	190, 185, 185, 185, 185, 185, 202, 185, 
-	202, 185, 185, 185, 227, 250, 185, 1, 
-	185, 190, 185, 185, 185, 185, 185, 202, 
-	185, 202, 185, 249, 185, 227, 227, 185, 
-	1, 185, 190, 185, 185, 185, 185, 185, 
-	202, 185, 196, 197, 201, 201, 3, 1, 
-	185, 190, 185, 185, 185, 185, 185, 185, 
-	191, 185, 196, 197, 198, 201, 3, 1, 
-	185, 190, 185, 185, 33, 185, 185, 185, 
-	191, 185, 194, 185, 251, 185, 232, 232, 
-	3, 1, 185, 190, 185, 185, 185, 185, 
-	185, 194, 185, 194, 185, 185, 185, 227, 
-	227, 185, 1, 185, 190, 185, 185, 185, 
-	185, 185, 194, 185, 194, 185, 185, 185, 
-	227, 252, 185, 1, 185, 190, 185, 185, 
-	185, 185, 185, 194, 185, 194, 185, 251, 
-	185, 227, 227, 185, 1, 185, 190, 185, 
-	185, 185, 185, 185, 194, 185, 186, 187, 
-	193, 193, 3, 1, 185, 190, 185, 185, 
-	185, 185, 185, 185, 191, 185, 186, 187, 
-	188, 193, 3, 1, 185, 190, 185, 185, 
-	35, 185, 185, 185, 191, 185, 254, 255, 
-	256, 257, 39, 37, 253, 258, 253, 253, 
-	71, 253, 253, 253, 259, 253, 260, 255, 
-	261, 257, 39, 37, 253, 258, 253, 253, 
-	253, 253, 253, 253, 259, 253, 255, 261, 
-	257, 39, 37, 253, 258, 253, 253, 253, 
-	253, 253, 253, 259, 253, 262, 253, 253, 
-	253, 52, 263, 253, 37, 253, 258, 253, 
-	253, 253, 253, 253, 262, 253, 264, 265, 
-	266, 267, 39, 37, 253, 258, 253, 253, 
-	69, 253, 253, 253, 259, 253, 268, 265, 
-	269, 269, 39, 37, 253, 258, 253, 253, 
-	253, 253, 253, 253, 259, 253, 265, 269, 
-	269, 39, 37, 253, 258, 253, 253, 253, 
-	253, 253, 253, 259, 253, 270, 253, 253, 
-	253, 52, 271, 253, 37, 253, 258, 253, 
-	253, 253, 253, 253, 270, 253, 272, 273, 
-	274, 275, 39, 37, 253, 258, 253, 253, 
-	67, 253, 253, 253, 259, 253, 276, 273, 
-	277, 277, 39, 37, 253, 258, 253, 253, 
-	253, 253, 253, 253, 259, 253, 273, 277, 
-	277, 39, 37, 253, 258, 253, 253, 253, 
-	253, 253, 253, 259, 253, 278, 253, 253, 
-	253, 52, 279, 253, 37, 253, 258, 253, 
-	253, 253, 253, 253, 278, 253, 280, 281, 
-	282, 283, 39, 37, 253, 258, 253, 253, 
-	65, 253, 253, 253, 259, 253, 284, 281, 
-	285, 285, 39, 37, 253, 258, 253, 253, 
-	253, 253, 253, 253, 259, 253, 281, 285, 
-	285, 39, 37, 253, 258, 253, 253, 253, 
-	253, 253, 253, 259, 253, 286, 253, 253, 
-	253, 52, 287, 253, 37, 253, 258, 253, 
-	253, 253, 253, 253, 286, 253, 288, 289, 
-	290, 291, 39, 37, 253, 258, 253, 253, 
-	63, 253, 253, 253, 259, 253, 292, 289, 
-	293, 293, 39, 37, 253, 258, 253, 253, 
-	253, 253, 253, 253, 259, 253, 289, 293, 
-	293, 39, 37, 253, 258, 253, 253, 253, 
-	253, 253, 253, 259, 253, 52, 294, 253, 
-	37, 253, 258, 253, 295, 295, 253, 37, 
-	253, 258, 253, 296, 253, 253, 297, 253, 
-	258, 253, 258, 253, 298, 253, 299, 253, 
-	296, 253, 253, 253, 253, 258, 253, 52, 
-	253, 300, 300, 39, 37, 253, 258, 253, 
-	301, 61, 302, 303, 42, 37, 253, 258, 
-	253, 61, 302, 303, 42, 37, 253, 258, 
-	253, 302, 302, 42, 37, 253, 258, 253, 
-	304, 58, 305, 306, 45, 37, 253, 258, 
-	253, 58, 305, 306, 45, 37, 253, 258, 
-	253, 305, 305, 45, 37, 253, 258, 253, 
-	307, 55, 308, 309, 48, 37, 253, 258, 
-	253, 55, 308, 309, 48, 37, 253, 258, 
-	253, 308, 308, 48, 37, 253, 258, 253, 
-	310, 52, 295, 311, 253, 37, 253, 258, 
-	253, 52, 295, 311, 253, 37, 253, 258, 
-	253, 295, 312, 253, 37, 253, 258, 253, 
-	52, 253, 295, 295, 253, 37, 253, 258, 
-	253, 289, 293, 293, 39, 37, 253, 258, 
-	253, 288, 289, 293, 293, 39, 37, 253, 
-	258, 253, 253, 253, 253, 253, 253, 259, 
-	253, 288, 289, 290, 293, 39, 37, 253, 
-	258, 253, 253, 63, 253, 253, 253, 259, 
-	253, 286, 253, 313, 253, 300, 300, 39, 
-	37, 253, 258, 253, 253, 253, 253, 253, 
-	286, 253, 286, 253, 253, 253, 295, 295, 
-	253, 37, 253, 258, 253, 253, 253, 253, 
-	253, 286, 253, 286, 253, 253, 253, 295, 
-	314, 253, 37, 253, 258, 253, 253, 253, 
-	253, 253, 286, 253, 286, 253, 313, 253, 
-	295, 295, 253, 37, 253, 258, 253, 253, 
-	253, 253, 253, 286, 253, 280, 281, 285, 
-	285, 39, 37, 253, 258, 253, 253, 253, 
-	253, 253, 253, 259, 253, 280, 281, 282, 
-	285, 39, 37, 253, 258, 253, 253, 65, 
-	253, 253, 253, 259, 253, 278, 253, 315, 
-	253, 300, 300, 39, 37, 253, 258, 253, 
-	253, 253, 253, 253, 278, 253, 278, 253, 
-	253, 253, 295, 295, 253, 37, 253, 258, 
-	253, 253, 253, 253, 253, 278, 253, 278, 
-	253, 253, 253, 295, 316, 253, 37, 253, 
-	258, 253, 253, 253, 253, 253, 278, 253, 
-	278, 253, 315, 253, 295, 295, 253, 37, 
-	253, 258, 253, 253, 253, 253, 253, 278, 
-	253, 272, 273, 277, 277, 39, 37, 253, 
-	258, 253, 253, 253, 253, 253, 253, 259, 
-	253, 272, 273, 274, 277, 39, 37, 253, 
-	258, 253, 253, 67, 253, 253, 253, 259, 
-	253, 270, 253, 317, 253, 300, 300, 39, 
-	37, 253, 258, 253, 253, 253, 253, 253, 
-	270, 253, 270, 253, 253, 253, 295, 295, 
-	253, 37, 253, 258, 253, 253, 253, 253, 
-	253, 270, 253, 270, 253, 253, 253, 295, 
-	318, 253, 37, 253, 258, 253, 253, 253, 
-	253, 253, 270, 253, 270, 253, 317, 253, 
-	295, 295, 253, 37, 253, 258, 253, 253, 
-	253, 253, 253, 270, 253, 264, 265, 269, 
-	269, 39, 37, 253, 258, 253, 253, 253, 
-	253, 253, 253, 259, 253, 264, 265, 266, 
-	269, 39, 37, 253, 258, 253, 253, 69, 
-	253, 253, 253, 259, 253, 262, 253, 319, 
-	253, 300, 300, 39, 37, 253, 258, 253, 
-	253, 253, 253, 253, 262, 253, 262, 253, 
-	253, 253, 295, 295, 253, 37, 253, 258, 
-	253, 253, 253, 253, 253, 262, 253, 262, 
-	253, 253, 253, 295, 320, 253, 37, 253, 
-	258, 253, 253, 253, 253, 253, 262, 253, 
-	262, 253, 319, 253, 295, 295, 253, 37, 
-	253, 258, 253, 253, 253, 253, 253, 262, 
-	253, 70, 38, 38, 39, 37, 253, 254, 
-	255, 261, 257, 39, 37, 253, 258, 253, 
-	253, 253, 253, 253, 253, 259, 253, 322, 
-	175, 323, 323, 75, 73, 321, 178, 321, 
-	321, 321, 321, 321, 321, 182, 321, 175, 
-	323, 323, 75, 73, 321, 178, 321, 321, 
-	321, 321, 321, 321, 182, 321, 324, 321, 
-	321, 321, 89, 325, 321, 73, 321, 178, 
-	321, 321, 321, 321, 321, 324, 321, 326, 
-	327, 328, 329, 75, 73, 321, 178, 321, 
-	321, 106, 321, 321, 321, 182, 321, 330, 
-	327, 331, 331, 75, 73, 321, 178, 321, 
-	321, 321, 321, 321, 321, 182, 321, 327, 
-	331, 331, 75, 73, 321, 178, 321, 321, 
-	321, 321, 321, 321, 182, 321, 332, 321, 
-	321, 321, 89, 333, 321, 73, 321, 178, 
-	321, 321, 321, 321, 321, 332, 321, 334, 
-	335, 336, 337, 75, 73, 321, 178, 321, 
-	321, 104, 321, 321, 321, 182, 321, 338, 
-	335, 339, 339, 75, 73, 321, 178, 321, 
-	321, 321, 321, 321, 321, 182, 321, 335, 
-	339, 339, 75, 73, 321, 178, 321, 321, 
-	321, 321, 321, 321, 182, 321, 340, 321, 
-	321, 321, 89, 341, 321, 73, 321, 178, 
-	321, 321, 321, 321, 321, 340, 321, 342, 
-	343, 344, 345, 75, 73, 321, 178, 321, 
-	321, 102, 321, 321, 321, 182, 321, 346, 
-	343, 347, 347, 75, 73, 321, 178, 321, 
-	321, 321, 321, 321, 321, 182, 321, 343, 
-	347, 347, 75, 73, 321, 178, 321, 321, 
-	321, 321, 321, 321, 182, 321, 348, 321, 
-	321, 321, 89, 349, 321, 73, 321, 178, 
-	321, 321, 321, 321, 321, 348, 321, 350, 
-	351, 352, 353, 75, 73, 321, 178, 321, 
-	321, 100, 321, 321, 321, 182, 321, 354, 
-	351, 355, 355, 75, 73, 321, 178, 321, 
-	321, 321, 321, 321, 321, 182, 321, 351, 
-	355, 355, 75, 73, 321, 178, 321, 321, 
-	321, 321, 321, 321, 182, 321, 89, 356, 
-	321, 73, 321, 178, 321, 357, 357, 321, 
-	73, 321, 178, 321, 358, 321, 321, 359, 
-	321, 178, 321, 178, 321, 360, 321, 361, 
-	321, 358, 321, 321, 321, 321, 178, 321, 
-	89, 321, 362, 362, 75, 73, 321, 178, 
-	321, 363, 98, 364, 365, 79, 73, 321, 
-	178, 321, 98, 364, 365, 79, 73, 321, 
-	178, 321, 364, 364, 79, 73, 321, 178, 
-	321, 366, 95, 367, 368, 82, 73, 321, 
-	178, 321, 95, 367, 368, 82, 73, 321, 
-	178, 321, 367, 367, 82, 73, 321, 178, 
-	321, 369, 92, 370, 371, 85, 73, 321, 
-	178, 321, 92, 370, 371, 85, 73, 321, 
-	178, 321, 370, 370, 85, 73, 321, 178, 
-	321, 372, 89, 357, 373, 321, 73, 321, 
-	178, 321, 89, 357, 373, 321, 73, 321, 
-	178, 321, 357, 374, 321, 73, 321, 178, 
-	321, 89, 321, 357, 357, 321, 73, 321, 
-	178, 321, 351, 355, 355, 75, 73, 321, 
-	178, 321, 350, 351, 355, 355, 75, 73, 
-	321, 178, 321, 321, 321, 321, 321, 321, 
-	182, 321, 350, 351, 352, 355, 75, 73, 
-	321, 178, 321, 321, 100, 321, 321, 321, 
-	182, 321, 348, 321, 375, 321, 362, 362, 
-	75, 73, 321, 178, 321, 321, 321, 321, 
-	321, 348, 321, 348, 321, 321, 321, 357, 
-	357, 321, 73, 321, 178, 321, 321, 321, 
-	321, 321, 348, 321, 348, 321, 321, 321, 
-	357, 376, 321, 73, 321, 178, 321, 321, 
-	321, 321, 321, 348, 321, 348, 321, 375, 
-	321, 357, 357, 321, 73, 321, 178, 321, 
-	321, 321, 321, 321, 348, 321, 342, 343, 
-	347, 347, 75, 73, 321, 178, 321, 321, 
-	321, 321, 321, 321, 182, 321, 342, 343, 
-	344, 347, 75, 73, 321, 178, 321, 321, 
-	102, 321, 321, 321, 182, 321, 340, 321, 
-	377, 321, 362, 362, 75, 73, 321, 178, 
-	321, 321, 321, 321, 321, 340, 321, 340, 
-	321, 321, 321, 357, 357, 321, 73, 321, 
-	178, 321, 321, 321, 321, 321, 340, 321, 
-	340, 321, 321, 321, 357, 378, 321, 73, 
-	321, 178, 321, 321, 321, 321, 321, 340, 
-	321, 340, 321, 377, 321, 357, 357, 321, 
-	73, 321, 178, 321, 321, 321, 321, 321, 
-	340, 321, 334, 335, 339, 339, 75, 73, 
-	321, 178, 321, 321, 321, 321, 321, 321, 
-	182, 321, 334, 335, 336, 339, 75, 73, 
-	321, 178, 321, 321, 104, 321, 321, 321, 
-	182, 321, 332, 321, 379, 321, 362, 362, 
-	75, 73, 321, 178, 321, 321, 321, 321, 
-	321, 332, 321, 332, 321, 321, 321, 357, 
-	357, 321, 73, 321, 178, 321, 321, 321, 
-	321, 321, 332, 321, 332, 321, 321, 321, 
-	357, 380, 321, 73, 321, 178, 321, 321, 
-	321, 321, 321, 332, 321, 332, 321, 379, 
-	321, 357, 357, 321, 73, 321, 178, 321, 
-	321, 321, 321, 321, 332, 321, 326, 327, 
-	331, 331, 75, 73, 321, 178, 321, 321, 
-	321, 321, 321, 321, 182, 321, 326, 327, 
-	328, 331, 75, 73, 321, 178, 321, 321, 
-	106, 321, 321, 321, 182, 321, 324, 321, 
-	381, 321, 362, 362, 75, 73, 321, 178, 
-	321, 321, 321, 321, 321, 324, 321, 324, 
-	321, 321, 321, 357, 357, 321, 73, 321, 
-	178, 321, 321, 321, 321, 321, 324, 321, 
-	324, 321, 321, 321, 357, 382, 321, 73, 
-	321, 178, 321, 321, 321, 321, 321, 324, 
-	321, 324, 321, 381, 321, 357, 357, 321, 
-	73, 321, 178, 321, 321, 321, 321, 321, 
-	324, 321, 107, 74, 74, 75, 73, 383, 
-	383, 383, 383, 144, 383, 174, 175, 323, 
-	323, 75, 73, 321, 178, 321, 321, 321, 
-	321, 321, 321, 182, 321, 107, 74, 74, 
-	75, 73, 383, 385, 386, 387, 388, 111, 
-	109, 384, 389, 384, 384, 143, 384, 384, 
-	384, 390, 384, 391, 386, 388, 388, 111, 
-	109, 384, 389, 384, 384, 384, 384, 384, 
-	384, 390, 384, 386, 388, 388, 111, 109, 
-	384, 389, 384, 384, 384, 384, 384, 384, 
-	390, 384, 392, 384, 384, 384, 124, 393, 
-	384, 109, 384, 389, 384, 384, 384, 384, 
-	384, 392, 384, 394, 395, 396, 397, 111, 
-	109, 384, 389, 384, 384, 141, 384, 384, 
-	384, 390, 384, 398, 395, 399, 399, 111, 
-	109, 384, 389, 384, 384, 384, 384, 384, 
-	384, 390, 384, 395, 399, 399, 111, 109, 
-	384, 389, 384, 384, 384, 384, 384, 384, 
-	390, 384, 400, 384, 384, 384, 124, 401, 
-	384, 109, 384, 389, 384, 384, 384, 384, 
-	384, 400, 384, 402, 403, 404, 405, 111, 
-	109, 384, 389, 384, 384, 139, 384, 384, 
-	384, 390, 384, 406, 403, 407, 407, 111, 
-	109, 384, 389, 384, 384, 384, 384, 384, 
-	384, 390, 384, 403, 407, 407, 111, 109, 
-	384, 389, 384, 384, 384, 384, 384, 384, 
-	390, 384, 408, 384, 384, 384, 124, 409, 
-	384, 109, 384, 389, 384, 384, 384, 384, 
-	384, 408, 384, 410, 411, 412, 413, 111, 
-	109, 384, 389, 384, 384, 137, 384, 384, 
-	384, 390, 384, 414, 411, 415, 415, 111, 
-	109, 384, 389, 384, 384, 384, 384, 384, 
-	384, 390, 384, 411, 415, 415, 111, 109, 
-	384, 389, 384, 384, 384, 384, 384, 384, 
-	390, 384, 416, 384, 384, 384, 124, 417, 
-	384, 109, 384, 389, 384, 384, 384, 384, 
-	384, 416, 384, 418, 419, 420, 421, 111, 
-	109, 384, 389, 384, 384, 135, 384, 384, 
-	384, 390, 384, 422, 419, 423, 423, 111, 
-	109, 384, 389, 384, 384, 384, 384, 384, 
-	384, 390, 384, 419, 423, 423, 111, 109, 
-	384, 389, 384, 384, 384, 384, 384, 384, 
-	390, 384, 124, 424, 384, 109, 384, 389, 
-	384, 425, 425, 384, 109, 384, 389, 384, 
-	426, 384, 384, 427, 384, 389, 384, 389, 
-	384, 428, 384, 429, 384, 426, 384, 384, 
-	384, 384, 389, 384, 124, 384, 430, 430, 
-	111, 109, 384, 389, 384, 431, 133, 432, 
-	433, 114, 109, 384, 389, 384, 133, 432, 
-	433, 114, 109, 384, 389, 384, 432, 432, 
-	114, 109, 384, 389, 384, 434, 130, 435, 
-	436, 117, 109, 384, 389, 384, 130, 435, 
-	436, 117, 109, 384, 389, 384, 435, 435, 
-	117, 109, 384, 389, 384, 437, 127, 438, 
-	439, 120, 109, 384, 389, 384, 127, 438, 
-	439, 120, 109, 384, 389, 384, 438, 438, 
-	120, 109, 384, 389, 384, 440, 124, 425, 
-	441, 384, 109, 384, 389, 384, 124, 425, 
-	441, 384, 109, 384, 389, 384, 425, 442, 
-	384, 109, 384, 389, 384, 124, 384, 425, 
-	425, 384, 109, 384, 389, 384, 419, 423, 
-	423, 111, 109, 384, 389, 384, 418, 419, 
-	423, 423, 111, 109, 384, 389, 384, 384, 
-	384, 384, 384, 384, 390, 384, 418, 419, 
-	420, 423, 111, 109, 384, 389, 384, 384, 
-	135, 384, 384, 384, 390, 384, 416, 384, 
-	443, 384, 430, 430, 111, 109, 384, 389, 
-	384, 384, 384, 384, 384, 416, 384, 416, 
-	384, 384, 384, 425, 425, 384, 109, 384, 
-	389, 384, 384, 384, 384, 384, 416, 384, 
-	416, 384, 384, 384, 425, 444, 384, 109, 
-	384, 389, 384, 384, 384, 384, 384, 416, 
-	384, 416, 384, 443, 384, 425, 425, 384, 
-	109, 384, 389, 384, 384, 384, 384, 384, 
-	416, 384, 410, 411, 415, 415, 111, 109, 
-	384, 389, 384, 384, 384, 384, 384, 384, 
-	390, 384, 410, 411, 412, 415, 111, 109, 
-	384, 389, 384, 384, 137, 384, 384, 384, 
-	390, 384, 408, 384, 445, 384, 430, 430, 
-	111, 109, 384, 389, 384, 384, 384, 384, 
-	384, 408, 384, 408, 384, 384, 384, 425, 
-	425, 384, 109, 384, 389, 384, 384, 384, 
-	384, 384, 408, 384, 408, 384, 384, 384, 
-	425, 446, 384, 109, 384, 389, 384, 384, 
-	384, 384, 384, 408, 384, 408, 384, 445, 
-	384, 425, 425, 384, 109, 384, 389, 384, 
-	384, 384, 384, 384, 408, 384, 402, 403, 
-	407, 407, 111, 109, 384, 389, 384, 384, 
-	384, 384, 384, 384, 390, 384, 402, 403, 
-	404, 407, 111, 109, 384, 389, 384, 384, 
-	139, 384, 384, 384, 390, 384, 400, 384, 
-	447, 384, 430, 430, 111, 109, 384, 389, 
-	384, 384, 384, 384, 384, 400, 384, 400, 
-	384, 384, 384, 425, 425, 384, 109, 384, 
-	389, 384, 384, 384, 384, 384, 400, 384, 
-	400, 384, 384, 384, 425, 448, 384, 109, 
-	384, 389, 384, 384, 384, 384, 384, 400, 
-	384, 400, 384, 447, 384, 425, 425, 384, 
-	109, 384, 389, 384, 384, 384, 384, 384, 
-	400, 384, 394, 395, 399, 399, 111, 109, 
-	384, 389, 384, 384, 384, 384, 384, 384, 
-	390, 384, 394, 395, 396, 399, 111, 109, 
-	384, 389, 384, 384, 141, 384, 384, 384, 
-	390, 384, 392, 384, 449, 384, 430, 430, 
-	111, 109, 384, 389, 384, 384, 384, 384, 
-	384, 392, 384, 392, 384, 384, 384, 425, 
-	425, 384, 109, 384, 389, 384, 384, 384, 
-	384, 384, 392, 384, 392, 384, 384, 384, 
-	425, 450, 384, 109, 384, 389, 384, 384, 
-	384, 384, 384, 392, 384, 392, 384, 449, 
-	384, 425, 425, 384, 109, 384, 389, 384, 
-	384, 384, 384, 384, 392, 384, 385, 386, 
-	388, 388, 111, 109, 384, 389, 384, 384, 
-	384, 384, 384, 384, 390, 384, 172, 173, 
-	174, 175, 451, 323, 75, 73, 321, 178, 
-	179, 179, 144, 321, 321, 172, 182, 321, 
-	186, 452, 188, 189, 3, 1, 185, 190, 
-	185, 185, 35, 185, 185, 185, 191, 185, 
-	194, 173, 174, 175, 453, 454, 75, 149, 
-	185, 455, 185, 179, 144, 185, 185, 194, 
-	182, 185, 107, 456, 456, 75, 149, 185, 
-	190, 185, 185, 144, 185, 457, 185, 185, 
-	458, 185, 455, 185, 455, 185, 459, 185, 
-	231, 185, 457, 185, 185, 185, 185, 455, 
-	185, 194, 185, 251, 107, 460, 460, 146, 
-	149, 185, 190, 185, 185, 185, 185, 185, 
-	194, 185, 461, 168, 462, 463, 148, 149, 
-	185, 455, 185, 168, 462, 463, 148, 149, 
-	185, 455, 185, 462, 462, 148, 149, 185, 
-	455, 185, 464, 165, 465, 466, 152, 149, 
-	185, 455, 185, 165, 465, 466, 152, 149, 
-	185, 455, 185, 465, 465, 152, 149, 185, 
-	455, 185, 467, 162, 468, 469, 155, 149, 
-	185, 455, 185, 162, 468, 469, 155, 149, 
-	185, 455, 185, 468, 468, 155, 149, 185, 
-	455, 185, 470, 159, 471, 472, 185, 149, 
-	185, 455, 185, 159, 471, 472, 185, 149, 
-	185, 455, 185, 471, 471, 185, 149, 185, 
-	455, 185, 474, 473, 475, 475, 473, 170, 
-	473, 476, 473, 475, 475, 473, 170, 473, 
-	476, 473, 477, 473, 473, 478, 473, 476, 
-	473, 476, 473, 479, 473, 480, 473, 477, 
-	473, 473, 473, 473, 476, 473, 172, 383, 
-	383, 383, 383, 383, 383, 383, 383, 383, 
-	179, 383, 383, 383, 383, 172, 383, 0
-};
-
-static const short _indic_syllable_machine_trans_targs[] = {
-	166, 188, 2, 194, 3, 5, 197, 6, 
-	8, 200, 9, 11, 203, 12, 14, 15, 
-	187, 17, 18, 202, 20, 21, 199, 23, 
-	24, 196, 205, 208, 212, 214, 218, 220, 
-	224, 226, 230, 232, 166, 255, 37, 261, 
-	38, 40, 264, 41, 43, 267, 44, 46, 
-	270, 47, 49, 50, 254, 52, 53, 269, 
-	55, 56, 266, 58, 59, 263, 272, 275, 
-	279, 281, 285, 287, 291, 293, 297, 300, 
-	166, 321, 72, 327, 166, 73, 75, 330, 
-	76, 78, 333, 79, 81, 336, 82, 84, 
-	85, 320, 87, 88, 335, 90, 91, 332, 
-	93, 94, 329, 338, 341, 345, 347, 351, 
-	353, 357, 359, 363, 166, 389, 106, 395, 
-	107, 109, 398, 110, 112, 401, 113, 115, 
-	404, 116, 118, 119, 388, 121, 122, 403, 
-	124, 125, 400, 127, 128, 397, 406, 409, 
-	413, 415, 419, 421, 425, 427, 431, 433, 
-	366, 142, 444, 144, 447, 438, 145, 147, 
-	450, 148, 150, 453, 151, 154, 155, 455, 
-	157, 158, 452, 160, 161, 449, 163, 164, 
-	446, 166, 458, 166, 167, 234, 301, 303, 
-	365, 367, 323, 368, 434, 435, 340, 456, 
-	463, 166, 168, 170, 34, 233, 190, 207, 
-	169, 33, 171, 228, 172, 174, 32, 227, 
-	173, 31, 175, 222, 176, 178, 30, 221, 
-	177, 29, 179, 216, 180, 182, 28, 215, 
-	181, 27, 183, 210, 184, 186, 26, 209, 
-	185, 25, 193, 0, 189, 192, 191, 166, 
-	1, 195, 4, 22, 198, 7, 19, 201, 
-	10, 16, 204, 13, 206, 211, 213, 217, 
-	219, 223, 225, 229, 231, 166, 235, 237, 
-	69, 299, 257, 274, 236, 68, 238, 295, 
-	239, 241, 67, 294, 240, 66, 242, 289, 
-	243, 245, 65, 288, 244, 64, 246, 283, 
-	247, 249, 63, 282, 248, 62, 250, 277, 
-	251, 253, 61, 276, 252, 60, 260, 35, 
-	256, 259, 258, 166, 36, 262, 39, 57, 
-	265, 42, 54, 268, 45, 51, 271, 48, 
-	273, 278, 280, 284, 286, 290, 292, 296, 
-	298, 166, 302, 103, 304, 361, 305, 307, 
-	102, 360, 306, 101, 308, 355, 309, 311, 
-	100, 354, 310, 99, 312, 349, 313, 315, 
-	98, 348, 314, 97, 316, 343, 317, 319, 
-	96, 342, 318, 95, 326, 70, 322, 325, 
-	324, 166, 71, 328, 74, 92, 331, 77, 
-	89, 334, 80, 86, 337, 83, 339, 344, 
-	346, 350, 352, 356, 358, 362, 364, 166, 
-	166, 369, 371, 138, 137, 391, 408, 370, 
-	372, 429, 373, 375, 136, 428, 374, 135, 
-	376, 423, 377, 379, 134, 422, 378, 133, 
-	380, 417, 381, 383, 132, 416, 382, 131, 
-	384, 411, 385, 387, 130, 410, 386, 129, 
-	394, 104, 390, 393, 392, 166, 105, 396, 
-	108, 126, 399, 111, 123, 402, 114, 120, 
-	405, 117, 407, 412, 414, 418, 420, 424, 
-	426, 430, 432, 139, 436, 437, 443, 440, 
-	140, 439, 442, 441, 141, 445, 143, 162, 
-	448, 146, 159, 451, 149, 156, 454, 152, 
-	153, 166, 457, 165, 460, 459, 462, 461, 
-	166
-};
-
-static const char _indic_syllable_machine_trans_actions[] = {
-	1, 0, 0, 2, 0, 0, 2, 0, 
-	0, 2, 0, 0, 2, 0, 0, 0, 
-	2, 0, 0, 2, 0, 0, 2, 0, 
-	0, 2, 2, 2, 2, 2, 2, 2, 
-	2, 2, 2, 2, 3, 0, 0, 2, 
-	0, 0, 2, 0, 0, 2, 0, 0, 
-	2, 0, 0, 0, 2, 0, 0, 2, 
-	0, 0, 2, 0, 0, 2, 2, 2, 
-	2, 2, 2, 2, 2, 2, 2, 2, 
-	4, 0, 0, 2, 5, 0, 0, 2, 
-	0, 0, 2, 0, 0, 2, 0, 0, 
-	0, 2, 0, 0, 2, 0, 0, 2, 
-	0, 0, 2, 2, 6, 2, 6, 2, 
-	6, 2, 6, 2, 7, 0, 0, 2, 
-	0, 0, 2, 0, 0, 2, 0, 0, 
-	2, 0, 0, 0, 2, 0, 0, 2, 
-	0, 0, 2, 0, 0, 2, 2, 2, 
-	2, 2, 2, 2, 2, 2, 2, 2, 
-	6, 0, 2, 0, 2, 0, 0, 0, 
-	2, 0, 0, 2, 0, 0, 0, 2, 
-	0, 0, 2, 0, 0, 2, 0, 0, 
-	2, 8, 0, 11, 2, 2, 6, 0, 
-	12, 12, 0, 2, 6, 2, 6, 2, 
-	0, 13, 2, 0, 0, 2, 0, 2, 
-	2, 0, 2, 2, 2, 0, 0, 2, 
-	2, 0, 2, 2, 2, 0, 0, 2, 
-	2, 0, 2, 2, 2, 0, 0, 2, 
-	2, 0, 2, 2, 2, 0, 0, 2, 
-	2, 0, 2, 0, 0, 0, 0, 14, 
-	0, 2, 0, 0, 2, 0, 0, 2, 
-	0, 0, 2, 0, 2, 2, 2, 2, 
-	2, 2, 2, 2, 2, 15, 2, 0, 
-	0, 2, 0, 2, 2, 0, 2, 2, 
-	2, 0, 0, 2, 2, 0, 2, 2, 
-	2, 0, 0, 2, 2, 0, 2, 2, 
-	2, 0, 0, 2, 2, 0, 2, 2, 
-	2, 0, 0, 2, 2, 0, 2, 0, 
-	0, 0, 0, 16, 0, 2, 0, 0, 
-	2, 0, 0, 2, 0, 0, 2, 0, 
-	2, 2, 2, 2, 2, 2, 2, 2, 
-	2, 17, 6, 0, 6, 6, 6, 0, 
-	0, 6, 6, 0, 6, 6, 6, 0, 
-	0, 6, 6, 0, 6, 6, 6, 0, 
-	0, 6, 6, 0, 6, 6, 6, 0, 
-	0, 6, 6, 0, 6, 0, 0, 0, 
-	0, 18, 0, 2, 0, 0, 2, 0, 
-	0, 2, 0, 0, 2, 0, 2, 2, 
-	2, 2, 2, 2, 2, 2, 2, 19, 
-	20, 2, 0, 0, 0, 0, 2, 2, 
-	2, 2, 2, 0, 0, 2, 2, 0, 
-	2, 2, 2, 0, 0, 2, 2, 0, 
-	2, 2, 2, 0, 0, 2, 2, 0, 
-	2, 2, 2, 0, 0, 2, 2, 0, 
-	2, 0, 0, 0, 0, 21, 0, 2, 
-	0, 0, 2, 0, 0, 2, 0, 0, 
-	2, 0, 2, 2, 2, 2, 2, 2, 
-	2, 2, 2, 0, 0, 22, 2, 0, 
-	0, 0, 0, 0, 0, 2, 0, 0, 
-	2, 0, 0, 2, 0, 0, 2, 0, 
-	0, 23, 2, 0, 0, 0, 0, 0, 
-	24
-};
-
-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, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	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, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	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, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 37, 73, 73, 
-	77, 77, 73, 73, 73, 73, 73, 73, 
-	73, 73, 73, 73, 73, 73, 73, 73, 
-	73, 73, 73, 73, 73, 73, 73, 73, 
-	73, 73, 73, 73, 73, 73, 73, 73, 
-	109, 109, 109, 109, 109, 109, 109, 109, 
-	109, 109, 109, 109, 109, 109, 109, 109, 
-	109, 109, 109, 109, 109, 109, 109, 109, 
-	109, 109, 109, 109, 109, 109, 109, 109, 
-	109, 109, 109, 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, 170, 0, 186, 
-	186, 186, 186, 186, 186, 186, 186, 186, 
-	186, 186, 186, 186, 186, 186, 186, 186, 
-	186, 186, 186, 186, 186, 186, 186, 186, 
-	186, 186, 186, 186, 186, 186, 186, 186, 
-	186, 186, 186, 186, 186, 186, 186, 186, 
-	186, 186, 186, 186, 186, 186, 186, 186, 
-	186, 186, 186, 186, 186, 186, 186, 186, 
-	186, 186, 186, 186, 186, 186, 186, 186, 
-	186, 186, 254, 254, 254, 254, 254, 254, 
-	254, 254, 254, 254, 254, 254, 254, 254, 
-	254, 254, 254, 254, 254, 254, 254, 254, 
-	254, 254, 254, 254, 254, 254, 254, 254, 
-	254, 254, 254, 254, 254, 254, 254, 254, 
-	254, 254, 254, 254, 254, 254, 254, 254, 
-	254, 254, 254, 254, 254, 254, 254, 254, 
-	254, 254, 254, 254, 254, 254, 254, 254, 
-	254, 254, 254, 254, 254, 322, 322, 322, 
-	322, 322, 322, 322, 322, 322, 322, 322, 
-	322, 322, 322, 322, 322, 322, 322, 322, 
-	322, 322, 322, 322, 322, 322, 322, 322, 
-	322, 322, 322, 322, 322, 322, 322, 322, 
-	322, 322, 322, 322, 322, 322, 322, 322, 
-	322, 322, 322, 322, 322, 322, 322, 322, 
-	322, 322, 322, 322, 322, 322, 322, 322, 
-	322, 322, 322, 322, 322, 384, 322, 384, 
-	385, 385, 385, 385, 385, 385, 385, 385, 
-	385, 385, 385, 385, 385, 385, 385, 385, 
-	385, 385, 385, 385, 385, 385, 385, 385, 
-	385, 385, 385, 385, 385, 385, 385, 385, 
-	385, 385, 385, 385, 385, 385, 385, 385, 
-	385, 385, 385, 385, 385, 385, 385, 385, 
-	385, 385, 385, 385, 385, 385, 385, 385, 
-	385, 385, 385, 385, 385, 385, 385, 385, 
-	385, 385, 322, 186, 186, 186, 186, 186, 
-	186, 186, 186, 186, 186, 186, 186, 186, 
-	186, 186, 186, 186, 186, 186, 186, 186, 
-	474, 474, 474, 474, 474, 474, 474, 384
-};
-
-static const int indic_syllable_machine_start = 166;
-static const int indic_syllable_machine_first_final = 166;
-static const int indic_syllable_machine_error = -1;
-
-static const int indic_syllable_machine_en_main = 166;
-
-
-#line 36 "hb-ot-shape-complex-indic-machine.rl"
-
-
-
-#line 92 "hb-ot-shape-complex-indic-machine.rl"
-
-
-#define found_syllable(syllable_type) \
-  HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
-      info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
-    syllable_serial++; \
-    if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
-  } HB_STMT_END
-
-static void
-find_syllables (hb_buffer_t *buffer)
-{
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
-  int cs;
-  hb_glyph_info_t *info = buffer->info;
-  
-#line 1137 "hb-ot-shape-complex-indic-machine.hh"
-	{
-	cs = indic_syllable_machine_start;
-	ts = 0;
-	te = 0;
-	act = 0;
-	}
-
-#line 113 "hb-ot-shape-complex-indic-machine.rl"
-
-
-  p = 0;
-  pe = eof = buffer->len;
-
-  unsigned int last = 0;
-  unsigned int syllable_serial = 1;
-  
-#line 1154 "hb-ot-shape-complex-indic-machine.hh"
-	{
-	int _slen;
-	int _trans;
-	const unsigned char *_keys;
-	const short *_inds;
-	if ( p == pe )
-		goto _test_eof;
-_resume:
-	switch ( _indic_syllable_machine_from_state_actions[cs] ) {
-	case 10:
-#line 1 "NONE"
-	{ts = p;}
-	break;
-#line 1168 "hb-ot-shape-complex-indic-machine.hh"
-	}
-
-	_keys = _indic_syllable_machine_trans_keys + (cs<<1);
-	_inds = _indic_syllable_machine_indicies + _indic_syllable_machine_index_offsets[cs];
-
-	_slen = _indic_syllable_machine_key_spans[cs];
-	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].indic_category()) &&
-		( info[p].indic_category()) <= _keys[1] ?
-		( info[p].indic_category()) - _keys[0] : _slen ];
-
-_eof_trans:
-	cs = _indic_syllable_machine_trans_targs[_trans];
-
-	if ( _indic_syllable_machine_trans_actions[_trans] == 0 )
-		goto _again;
-
-	switch ( _indic_syllable_machine_trans_actions[_trans] ) {
-	case 2:
-#line 1 "NONE"
-	{te = p+1;}
-	break;
-	case 14:
-#line 83 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p+1;{ found_syllable (consonant_syllable); }}
-	break;
-	case 16:
-#line 84 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p+1;{ found_syllable (vowel_syllable); }}
-	break;
-	case 21:
-#line 85 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p+1;{ found_syllable (standalone_cluster); }}
-	break;
-	case 24:
-#line 86 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p+1;{ found_syllable (symbol_cluster); }}
-	break;
-	case 18:
-#line 87 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p+1;{ found_syllable (broken_cluster); }}
-	break;
-	case 11:
-#line 88 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p+1;{ found_syllable (non_indic_cluster); }}
-	break;
-	case 13:
-#line 83 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p;p--;{ found_syllable (consonant_syllable); }}
-	break;
-	case 15:
-#line 84 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p;p--;{ found_syllable (vowel_syllable); }}
-	break;
-	case 20:
-#line 85 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p;p--;{ found_syllable (standalone_cluster); }}
-	break;
-	case 23:
-#line 86 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p;p--;{ found_syllable (symbol_cluster); }}
-	break;
-	case 17:
-#line 87 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p;p--;{ found_syllable (broken_cluster); }}
-	break;
-	case 19:
-#line 88 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p;p--;{ found_syllable (non_indic_cluster); }}
-	break;
-	case 1:
-#line 83 "hb-ot-shape-complex-indic-machine.rl"
-	{{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
-	break;
-	case 3:
-#line 84 "hb-ot-shape-complex-indic-machine.rl"
-	{{p = ((te))-1;}{ found_syllable (vowel_syllable); }}
-	break;
-	case 7:
-#line 85 "hb-ot-shape-complex-indic-machine.rl"
-	{{p = ((te))-1;}{ found_syllable (standalone_cluster); }}
-	break;
-	case 8:
-#line 86 "hb-ot-shape-complex-indic-machine.rl"
-	{{p = ((te))-1;}{ found_syllable (symbol_cluster); }}
-	break;
-	case 4:
-#line 87 "hb-ot-shape-complex-indic-machine.rl"
-	{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
-	break;
-	case 5:
-#line 1 "NONE"
-	{	switch( act ) {
-	case 1:
-	{{p = ((te))-1;} found_syllable (consonant_syllable); }
-	break;
-	case 5:
-	{{p = ((te))-1;} found_syllable (broken_cluster); }
-	break;
-	case 6:
-	{{p = ((te))-1;} found_syllable (non_indic_cluster); }
-	break;
-	}
-	}
-	break;
-	case 22:
-#line 1 "NONE"
-	{te = p+1;}
-#line 83 "hb-ot-shape-complex-indic-machine.rl"
-	{act = 1;}
-	break;
-	case 6:
-#line 1 "NONE"
-	{te = p+1;}
-#line 87 "hb-ot-shape-complex-indic-machine.rl"
-	{act = 5;}
-	break;
-	case 12:
-#line 1 "NONE"
-	{te = p+1;}
-#line 88 "hb-ot-shape-complex-indic-machine.rl"
-	{act = 6;}
-	break;
-#line 1291 "hb-ot-shape-complex-indic-machine.hh"
-	}
-
-_again:
-	switch ( _indic_syllable_machine_to_state_actions[cs] ) {
-	case 9:
-#line 1 "NONE"
-	{ts = 0;}
-	break;
-#line 1300 "hb-ot-shape-complex-indic-machine.hh"
-	}
-
-	if ( ++p != pe )
-		goto _resume;
-	_test_eof: {}
-	if ( p == eof )
-	{
-	if ( _indic_syllable_machine_eof_trans[cs] > 0 ) {
-		_trans = _indic_syllable_machine_eof_trans[cs] - 1;
-		goto _eof_trans;
-	}
-	}
-
-	}
-
-#line 122 "hb-ot-shape-complex-indic-machine.rl"
-
-}
-
-#endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh
deleted file mode 100644
index 867b9362..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-#include "hb-ot-shape-complex-private.hh"
-#include "hb-ot-shape-private.hh" /* XXX Remove */
-
-
-/* buffer var allocations */
-#define indic_category() complex_var_u8_0() /* indic_category_t */
-#define indic_position() complex_var_u8_1() /* indic_position_t */
-
-
-#define INDIC_TABLE_ELEMENT_TYPE uint16_t
-
-/* Cateories used in the OpenType spec:
- * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx
- */
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum indic_category_t {
-  OT_X = 0,
-  OT_C = 1,
-  OT_V = 2,
-  OT_N = 3,
-  OT_H = 4,
-  OT_ZWNJ = 5,
-  OT_ZWJ = 6,
-  OT_M = 7,
-  OT_SM = 8,
-  /* OT_VD = 9, UNUSED; we use OT_A instead. */
-  OT_A = 10,
-  OT_PLACEHOLDER = 11,
-  OT_DOTTEDCIRCLE = 12,
-  OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */
-  OT_Coeng = 14, /* Khmer-style Virama. */
-  OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
-  OT_Ra = 16,
-  OT_CM = 17,  /* Consonant-Medial. */
-  OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
-  OT_CS = 19
-};
-
-#define MEDIAL_FLAGS (FLAG (OT_CM))
-
-/* Note:
- *
- * We treat Vowels and placeholders as if they were consonants.  This is safe because Vowels
- * cannot happen in a consonant syllable.  The plus side however is, we can call the
- * consonant syllable logic from the vowel syllable function and get it all right! */
-#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CS) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
-#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
-
-
-/* Visual positions in a syllable from left to right. */
-enum indic_position_t {
-  POS_START = 0,
-
-  POS_RA_TO_BECOME_REPH = 1,
-  POS_PRE_M = 2,
-  POS_PRE_C = 3,
-
-  POS_BASE_C = 4,
-  POS_AFTER_MAIN = 5,
-
-  POS_ABOVE_C = 6,
-
-  POS_BEFORE_SUB = 7,
-  POS_BELOW_C = 8,
-  POS_AFTER_SUB = 9,
-
-  POS_BEFORE_POST = 10,
-  POS_POST_C = 11,
-  POS_AFTER_POST = 12,
-
-  POS_FINAL_C = 13,
-  POS_SMVD = 14,
-
-  POS_END = 15
-};
-
-/* Categories used in IndicSyllabicCategory.txt from UCD. */
-enum indic_syllabic_category_t {
-  INDIC_SYLLABIC_CATEGORY_OTHER				= OT_X,
-
-  INDIC_SYLLABIC_CATEGORY_AVAGRAHA			= OT_Symbol,
-  INDIC_SYLLABIC_CATEGORY_BINDU				= OT_SM,
-  INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER		= OT_PLACEHOLDER, /* Don't care. */
-  INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK		= OT_A,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT			= OT_C,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD		= OT_C,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL		= OT_CM,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER		= OT_C,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER		= OT_M, /* U+17CD only. */
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL		= OT_CM,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER		= OT_PLACEHOLDER,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA	= OT_Repha,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED		= OT_X, /* Don't care. */
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED		= OT_CM,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA	= OT_N,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER	= OT_CS,
-  INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK		= OT_SM, /* https://github.com/harfbuzz/harfbuzz/issues/552 */
-  INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER		= OT_Coeng,
-  INDIC_SYLLABIC_CATEGORY_JOINER			= OT_ZWJ,
-  INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER		= OT_X,
-  INDIC_SYLLABIC_CATEGORY_NON_JOINER			= OT_ZWNJ,
-  INDIC_SYLLABIC_CATEGORY_NUKTA				= OT_N,
-  INDIC_SYLLABIC_CATEGORY_NUMBER			= OT_PLACEHOLDER,
-  INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER			= OT_PLACEHOLDER, /* Don't care. */
-  INDIC_SYLLABIC_CATEGORY_PURE_KILLER			= OT_M, /* Is like a vowel matra. */
-  INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER		= OT_RS,
-  INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER		= OT_SM,
-  INDIC_SYLLABIC_CATEGORY_TONE_LETTER			= OT_X,
-  INDIC_SYLLABIC_CATEGORY_TONE_MARK			= OT_N,
-  INDIC_SYLLABIC_CATEGORY_VIRAMA			= OT_H,
-  INDIC_SYLLABIC_CATEGORY_VISARGA			= OT_SM,
-  INDIC_SYLLABIC_CATEGORY_VOWEL				= OT_V,
-  INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT		= OT_M,
-  INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT		= OT_V
-};
-
-/* Categories used in IndicSMatraCategory.txt from UCD */
-enum indic_matra_category_t {
-  INDIC_MATRA_CATEGORY_NOT_APPLICABLE			= POS_END,
-
-  INDIC_MATRA_CATEGORY_LEFT				= POS_PRE_C,
-  INDIC_MATRA_CATEGORY_TOP				= POS_ABOVE_C,
-  INDIC_MATRA_CATEGORY_BOTTOM				= POS_BELOW_C,
-  INDIC_MATRA_CATEGORY_RIGHT				= POS_POST_C,
-
-  /* These should resolve to the position of the last part of the split sequence. */
-  INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT			= INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT			= INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM			= INDIC_MATRA_CATEGORY_BOTTOM,
-  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT		= INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_TOP_AND_LEFT			= INDIC_MATRA_CATEGORY_TOP,
-  INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT		= INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_TOP_AND_RIGHT			= INDIC_MATRA_CATEGORY_RIGHT,
-
-  INDIC_MATRA_CATEGORY_OVERSTRUCK			= POS_AFTER_MAIN,
-  INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT		= POS_PRE_M
-};
-
-#define INDIC_COMBINE_CATEGORIES(S,M) \
-  ( \
-    ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
-    ( S | \
-     ( \
-      ( \
-       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
-       S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
-       S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
-       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
-       S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
-       S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
-       false \
-       ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \
-      ) << 8 \
-     ) \
-    ) \
-   )
-
-HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE
-hb_indic_get_categories (hb_codepoint_t u);
-
-
-static inline bool
-is_one_of (const hb_glyph_info_t &info, unsigned int flags)
-{
-  /* If it ligated, all bets are off. */
-  if (_hb_glyph_info_ligated (&info)) return false;
-  return !!(FLAG_UNSAFE (info.indic_category()) & flags);
-}
-
-static inline bool
-is_joiner (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, JOINER_FLAGS);
-}
-
-static inline bool
-is_consonant (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, CONSONANT_FLAGS);
-}
-
-static inline bool
-is_halant (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, FLAG (OT_H));
-}
-
-#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
-
-#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
-#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
-#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
-#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
-#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
-#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
-#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
-#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
-#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
-#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
-
-
-#define MATRA_POS_LEFT(u)	POS_PRE_M
-#define MATRA_POS_RIGHT(u)	( \
-				  IS_DEVA(u) ? POS_AFTER_SUB  : \
-				  IS_BENG(u) ? POS_AFTER_POST : \
-				  IS_GURU(u) ? POS_AFTER_POST : \
-				  IS_GUJR(u) ? POS_AFTER_POST : \
-				  IS_ORYA(u) ? POS_AFTER_POST : \
-				  IS_TAML(u) ? POS_AFTER_POST : \
-				  IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
-				  IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
-				  IS_MLYM(u) ? POS_AFTER_POST : \
-				  IS_SINH(u) ? POS_AFTER_SUB  : \
-				  /*default*/  POS_AFTER_SUB    \
-				)
-#define MATRA_POS_TOP(u)	( /* BENG and MLYM don't have top matras. */ \
-				  IS_DEVA(u) ? POS_AFTER_SUB  : \
-				  IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
-				  IS_GUJR(u) ? POS_AFTER_SUB  : \
-				  IS_ORYA(u) ? POS_AFTER_MAIN : \
-				  IS_TAML(u) ? POS_AFTER_SUB  : \
-				  IS_TELU(u) ? POS_BEFORE_SUB : \
-				  IS_KNDA(u) ? POS_BEFORE_SUB : \
-				  IS_SINH(u) ? POS_AFTER_SUB  : \
-				  /*default*/  POS_AFTER_SUB    \
-				)
-#define MATRA_POS_BOTTOM(u)	( \
-				  IS_DEVA(u) ? POS_AFTER_SUB  : \
-				  IS_BENG(u) ? POS_AFTER_SUB  : \
-				  IS_GURU(u) ? POS_AFTER_POST : \
-				  IS_GUJR(u) ? POS_AFTER_POST : \
-				  IS_ORYA(u) ? POS_AFTER_SUB  : \
-				  IS_TAML(u) ? POS_AFTER_POST : \
-				  IS_TELU(u) ? POS_BEFORE_SUB : \
-				  IS_KNDA(u) ? POS_BEFORE_SUB : \
-				  IS_MLYM(u) ? POS_AFTER_POST : \
-				  IS_SINH(u) ? POS_AFTER_SUB  : \
-				  /*default*/  POS_AFTER_SUB    \
-				)
-
-static inline indic_position_t
-matra_position_indic (hb_codepoint_t u, indic_position_t side)
-{
-  switch ((int) side)
-  {
-    case POS_PRE_C:	return MATRA_POS_LEFT (u);
-    case POS_POST_C:	return MATRA_POS_RIGHT (u);
-    case POS_ABOVE_C:	return MATRA_POS_TOP (u);
-    case POS_BELOW_C:	return MATRA_POS_BOTTOM (u);
-  };
-  return side;
-}
-
-/* XXX
- * This is a hack for now.  We should move this data into the main Indic table.
- * Or completely remove it and just check in the tables.
- */
-static const hb_codepoint_t ra_chars[] = {
-  0x0930u, /* Devanagari */
-  0x09B0u, /* Bengali */
-  0x09F0u, /* Bengali */
-  0x0A30u, /* Gurmukhi */	/* No Reph */
-  0x0AB0u, /* Gujarati */
-  0x0B30u, /* Oriya */
-  0x0BB0u, /* Tamil */		/* No Reph */
-  0x0C30u, /* Telugu */		/* Reph formed only with ZWJ */
-  0x0CB0u, /* Kannada */
-  0x0D30u, /* Malayalam */	/* No Reph, Logical Repha */
-
-  0x0DBBu, /* Sinhala */		/* Reph formed only with ZWJ */
-};
-
-static inline bool
-is_ra (hb_codepoint_t u)
-{
-  for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++)
-    if (u == ra_chars[i])
-      return true;
-  return false;
-}
-
-static inline void
-set_indic_properties (hb_glyph_info_t &info)
-{
-  hb_codepoint_t u = info.codepoint;
-  unsigned int type = hb_indic_get_categories (u);
-  indic_category_t cat = (indic_category_t) (type & 0x7Fu);
-  indic_position_t pos = (indic_position_t) (type >> 8);
-
-
-  /*
-   * Re-assign category
-   */
-
-  /* The following act more like the Bindus. */
-  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0953u, 0x0954u)))
-    cat = OT_SM;
-  /* The following act like consonants. */
-  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x0A72u, 0x0A73u,
-				      0x1CF5u, 0x1CF6u)))
-    cat = OT_C;
-  /* TODO: The following should only be allowed after a Visarga.
-   * For now, just treat them like regular tone marks. */
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1CE2u, 0x1CE8u)))
-    cat = OT_A;
-  /* TODO: The following should only be allowed after some of
-   * the nasalization marks, maybe only for U+1CE9..U+1CF1.
-   * For now, just treat them like tone marks. */
-  else if (unlikely (u == 0x1CEDu))
-    cat = OT_A;
-  /* The following take marks in standalone clusters, similar to Avagraha. */
-  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0xA8F2u, 0xA8F7u,
-				      0x1CE9u, 0x1CECu,
-				      0x1CEEu, 0x1CF1u)))
-  {
-    cat = OT_Symbol;
-    static_assert (((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol), "");
-  }
-  else if (unlikely (u == 0x0A51u))
-  {
-    /* https://github.com/harfbuzz/harfbuzz/issues/524 */
-    cat = OT_M;
-    pos = POS_BELOW_C;
-  }
-
-  /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
-   * so the Indic shaper needs to know their categories. */
-  else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM;
-  else if (unlikely (u == 0x1133cu)) cat = OT_N;
-
-  else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
-
-  else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
-  else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
-				    cat = OT_PLACEHOLDER;
-  else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
-
-
-  /*
-   * Re-assign position.
-   */
-
-  if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
-  {
-    pos = POS_BASE_C;
-    if (is_ra (u))
-      cat = OT_Ra;
-  }
-  else if (cat == OT_M)
-  {
-    pos = matra_position_indic (u, pos);
-  }
-  else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) /* | FLAG (OT_VD) */ | FLAG (OT_A) | FLAG (OT_Symbol))))
-  {
-    pos = POS_SMVD;
-  }
-
-  if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
-
-
-
-  info.indic_category() = cat;
-  info.indic_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc
deleted file mode 100644
index 867cfb3..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc
+++ /dev/null
@@ -1,486 +0,0 @@
-/* == Start of generated table == */
-/*
- * The following table is generated by running:
- *
- *   ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
- *
- * on files with these headers:
- *
- * # IndicSyllabicCategory-10.0.0.txt
- * # Date: 2017-05-31, 01:07:00 GMT [KW, RP]
- * # IndicPositionalCategory-10.0.0.txt
- * # Date: 2017-05-31, 01:07:00 GMT [RP]
- * # Blocks-10.0.0.txt
- * # Date: 2017-04-12, 17:30:00 GMT [KW]
- */
-
-#include "hb-ot-shape-complex-indic-private.hh"
-
-
-#define ISC_A	INDIC_SYLLABIC_CATEGORY_AVAGRAHA		/*  15 chars; Avagraha */
-#define ISC_Bi	INDIC_SYLLABIC_CATEGORY_BINDU			/*  80 chars; Bindu */
-#define ISC_BJN	INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER	/*  20 chars; Brahmi_Joining_Number */
-#define ISC_Ca	INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK	/*  57 chars; Cantillation_Mark */
-#define ISC_C	INDIC_SYLLABIC_CATEGORY_CONSONANT		/* 2024 chars; Consonant */
-#define ISC_CD	INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD		/*  10 chars; Consonant_Dead */
-#define ISC_CF	INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL		/*  68 chars; Consonant_Final */
-#define ISC_CHL	INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER	/*   5 chars; Consonant_Head_Letter */
-#define ISC_CK	INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER	/*   2 chars; Consonant_Killer */
-#define ISC_CM	INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL	/*  27 chars; Consonant_Medial */
-#define ISC_CP	INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER	/*  18 chars; Consonant_Placeholder */
-#define ISC_CPR	INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA	/*   2 chars; Consonant_Preceding_Repha */
-#define ISC_CPrf	INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED	/*   7 chars; Consonant_Prefixed */
-#define ISC_CS	INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED	/*  95 chars; Consonant_Subjoined */
-#define ISC_CSR	INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA	/*   5 chars; Consonant_Succeeding_Repha */
-#define ISC_CWS	INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER	/*   4 chars; Consonant_With_Stacker */
-#define ISC_GM	INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK		/*   3 chars; Gemination_Mark */
-#define ISC_IS	INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER	/*  10 chars; Invisible_Stacker */
-#define ISC_ZWJ	INDIC_SYLLABIC_CATEGORY_JOINER			/*   1 chars; Joiner */
-#define ISC_ML	INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER	/*   1 chars; Modifying_Letter */
-#define ISC_ZWNJ	INDIC_SYLLABIC_CATEGORY_NON_JOINER		/*   1 chars; Non_Joiner */
-#define ISC_N	INDIC_SYLLABIC_CATEGORY_NUKTA			/*  28 chars; Nukta */
-#define ISC_Nd	INDIC_SYLLABIC_CATEGORY_NUMBER			/* 469 chars; Number */
-#define ISC_NJ	INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER		/*   1 chars; Number_Joiner */
-#define ISC_x	INDIC_SYLLABIC_CATEGORY_OTHER			/*   1 chars; Other */
-#define ISC_PK	INDIC_SYLLABIC_CATEGORY_PURE_KILLER		/*  21 chars; Pure_Killer */
-#define ISC_RS	INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER	/*   2 chars; Register_Shifter */
-#define ISC_SM	INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER	/*  22 chars; Syllable_Modifier */
-#define ISC_TL	INDIC_SYLLABIC_CATEGORY_TONE_LETTER		/*   7 chars; Tone_Letter */
-#define ISC_TM	INDIC_SYLLABIC_CATEGORY_TONE_MARK		/*  42 chars; Tone_Mark */
-#define ISC_V	INDIC_SYLLABIC_CATEGORY_VIRAMA			/*  24 chars; Virama */
-#define ISC_Vs	INDIC_SYLLABIC_CATEGORY_VISARGA			/*  34 chars; Visarga */
-#define ISC_Vo	INDIC_SYLLABIC_CATEGORY_VOWEL			/*  30 chars; Vowel */
-#define ISC_M	INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT		/* 633 chars; Vowel_Dependent */
-#define ISC_VI	INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT	/* 443 chars; Vowel_Independent */
-
-#define IMC_B	INDIC_MATRA_CATEGORY_BOTTOM			/* 330 chars; Bottom */
-#define IMC_BL	INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT		/*   1 chars; Bottom_And_Left */
-#define IMC_BR	INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT		/*   2 chars; Bottom_And_Right */
-#define IMC_L	INDIC_MATRA_CATEGORY_LEFT			/*  57 chars; Left */
-#define IMC_LR	INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT		/*  21 chars; Left_And_Right */
-#define IMC_x	INDIC_MATRA_CATEGORY_NOT_APPLICABLE		/*   1 chars; Not_Applicable */
-#define IMC_O	INDIC_MATRA_CATEGORY_OVERSTRUCK			/*  10 chars; Overstruck */
-#define IMC_R	INDIC_MATRA_CATEGORY_RIGHT			/* 262 chars; Right */
-#define IMC_T	INDIC_MATRA_CATEGORY_TOP			/* 380 chars; Top */
-#define IMC_TB	INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM		/*  10 chars; Top_And_Bottom */
-#define IMC_TBR	INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT	/*   1 chars; Top_And_Bottom_And_Right */
-#define IMC_TL	INDIC_MATRA_CATEGORY_TOP_AND_LEFT		/*   6 chars; Top_And_Left */
-#define IMC_TLR	INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT	/*   4 chars; Top_And_Left_And_Right */
-#define IMC_TR	INDIC_MATRA_CATEGORY_TOP_AND_RIGHT		/*  13 chars; Top_And_Right */
-#define IMC_VOL	INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT		/*  19 chars; Visual_Order_Left */
-
-#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
-
-
-static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
-
-
-#define indic_offset_0x0028u 0
-
-
-  /* Basic Latin */
-
-  /* 0028 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(CP,x),  _(x,x),  _(x,x),
-  /* 0030 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 0038 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-
-#define indic_offset_0x00b0u 24
-
-
-  /* Latin-1 Supplement */
-
-  /* 00B0 */  _(x,x),  _(x,x), _(SM,x), _(SM,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 00B8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 00C0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 00C8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 00D0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(CP,x),
-
-#define indic_offset_0x0900u 64
-
-
-  /* Devanagari */
-
-  /* 0900 */ _(Bi,T), _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 0908 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 0910 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0918 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0920 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0928 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0930 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0938 */  _(C,x),  _(C,x),  _(M,T),  _(M,R),  _(N,B),  _(A,x),  _(M,R),  _(M,L),
-  /* 0940 */  _(M,R),  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(M,T),  _(M,T),  _(M,T),
-  /* 0948 */  _(M,T),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(V,B),  _(M,L),  _(M,R),
-  /* 0950 */  _(x,x), _(Ca,T), _(Ca,B),  _(x,T),  _(x,T),  _(M,T),  _(M,B),  _(M,B),
-  /* 0958 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0960 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
-  /* 0968 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 0970 */  _(x,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 0978 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-
-  /* Bengali */
-
-  /* 0980 */  _(x,x), _(Bi,T), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 0988 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x),  _(x,x), _(VI,x),
-  /* 0990 */ _(VI,x),  _(x,x),  _(x,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0998 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 09A0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 09A8 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 09B0 */  _(C,x),  _(x,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(C,x),  _(C,x),
-  /* 09B8 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,B),  _(A,x),  _(M,R),  _(M,L),
-  /* 09C0 */  _(M,R),  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(x,x),  _(x,x),  _(M,L),
-  /* 09C8 */  _(M,L),  _(x,x),  _(x,x), _(M,LR), _(M,LR),  _(V,B), _(CD,x),  _(x,x),
-  /* 09D0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),
-  /* 09D8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),
-  /* 09E0 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
-  /* 09E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 09F0 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 09F8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(Bi,x),  _(x,x),  _(x,x),  _(x,x),
-
-  /* Gurmukhi */
-
-  /* 0A00 */  _(x,x), _(Bi,T), _(Bi,T), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 0A08 */ _(VI,x), _(VI,x), _(VI,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(VI,x),
-  /* 0A10 */ _(VI,x),  _(x,x),  _(x,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0A18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0A20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0A28 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0A30 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(x,x),
-  /* 0A38 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,B),  _(x,x),  _(M,R),  _(M,L),
-  /* 0A40 */  _(M,R),  _(M,B),  _(M,B),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,T),
-  /* 0A48 */  _(M,T),  _(x,x),  _(x,x),  _(M,T),  _(M,T),  _(V,B),  _(x,x),  _(x,x),
-  /* 0A50 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0A58 */  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(x,x),
-  /* 0A60 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
-  /* 0A68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 0A70 */ _(Bi,T), _(GM,T), _(CP,x), _(CP,x),  _(x,x), _(CM,B),  _(x,x),  _(x,x),
-  /* 0A78 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-
-  /* Gujarati */
-
-  /* 0A80 */  _(x,x), _(Bi,T), _(Bi,T), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 0A88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x), _(VI,x),
-  /* 0A90 */ _(VI,x), _(VI,x),  _(x,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0A98 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0AA0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0AA8 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0AB0 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0AB8 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,B),  _(A,x),  _(M,R),  _(M,L),
-  /* 0AC0 */  _(M,R),  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(M,T),  _(x,x),  _(M,T),
-  /* 0AC8 */  _(M,T), _(M,TR),  _(x,x),  _(M,R),  _(M,R),  _(V,B),  _(x,x),  _(x,x),
-  /* 0AD0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0AD8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0AE0 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
-  /* 0AE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 0AF0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0AF8 */  _(x,x),  _(C,x), _(Ca,T), _(Ca,T), _(Ca,T),  _(N,T),  _(N,T),  _(N,T),
-
-  /* Oriya */
-
-  /* 0B00 */  _(x,x), _(Bi,T), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 0B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x),  _(x,x), _(VI,x),
-  /* 0B10 */ _(VI,x),  _(x,x),  _(x,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0B18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0B20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0B28 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0B30 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0B38 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,B),  _(A,x),  _(M,R),  _(M,T),
-  /* 0B40 */  _(M,R),  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(x,x),  _(x,x),  _(M,L),
-  /* 0B48 */ _(M,TL),  _(x,x),  _(x,x), _(M,LR),_(M,TLR),  _(V,B),  _(x,x),  _(x,x),
-  /* 0B50 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,T), _(M,TR),
-  /* 0B58 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),
-  /* 0B60 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
-  /* 0B68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 0B70 */  _(x,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0B78 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-
-  /* Tamil */
-
-  /* 0B80 */  _(x,x),  _(x,x), _(Bi,T), _(ML,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 0B88 */ _(VI,x), _(VI,x), _(VI,x),  _(x,x),  _(x,x),  _(x,x), _(VI,x), _(VI,x),
-  /* 0B90 */ _(VI,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(x,x),  _(x,x),
-  /* 0B98 */  _(x,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(x,x),  _(C,x),  _(C,x),
-  /* 0BA0 */  _(x,x),  _(x,x),  _(x,x),  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0BA8 */  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(C,x),  _(C,x),
-  /* 0BB0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0BB8 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),  _(M,R),
-  /* 0BC0 */  _(M,T),  _(M,R),  _(M,R),  _(x,x),  _(x,x),  _(x,x),  _(M,L),  _(M,L),
-  /* 0BC8 */  _(M,L),  _(x,x), _(M,LR), _(M,LR), _(M,LR),  _(V,T),  _(x,x),  _(x,x),
-  /* 0BD0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),
-  /* 0BD8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0BE0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
-  /* 0BE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 0BF0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0BF8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-
-  /* Telugu */
-
-  /* 0C00 */ _(Bi,T), _(Bi,R), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 0C08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x), _(VI,x), _(VI,x),
-  /* 0C10 */ _(VI,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0C18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0C20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0C28 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0C30 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0C38 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(A,x),  _(M,T),  _(M,T),
-  /* 0C40 */  _(M,T),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(x,x),  _(M,T),  _(M,T),
-  /* 0C48 */ _(M,TB),  _(x,x),  _(M,T),  _(M,T),  _(M,T),  _(V,T),  _(x,x),  _(x,x),
-  /* 0C50 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,T),  _(M,B),  _(x,x),
-  /* 0C58 */  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0C60 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
-  /* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 0C70 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0C78 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-
-  /* Kannada */
-
-  /* 0C80 */  _(x,x), _(Bi,T), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 0C88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x), _(VI,x), _(VI,x),
-  /* 0C90 */ _(VI,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0C98 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0CA0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0CA8 */  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0CB0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0CB8 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,B),  _(A,x),  _(M,R),  _(M,T),
-  /* 0CC0 */ _(M,TR),  _(M,R),  _(M,R),  _(M,R),  _(M,R),  _(x,x),  _(M,T), _(M,TR),
-  /* 0CC8 */ _(M,TR),  _(x,x), _(M,TR), _(M,TR),  _(M,T),  _(V,T),  _(x,x),  _(x,x),
-  /* 0CD0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),  _(M,R),  _(x,x),
-  /* 0CD8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(C,x),  _(x,x),
-  /* 0CE0 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
-  /* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 0CF0 */  _(x,x),_(CWS,x),_(CWS,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0CF8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-
-  /* Malayalam */
-
-  /* 0D00 */ _(Bi,T), _(Bi,T), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x), _(VI,x), _(VI,x),
-  /* 0D10 */ _(VI,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0D18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0D20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0D28 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0D30 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0D38 */  _(C,x),  _(C,x),  _(C,x), _(PK,T), _(PK,T),  _(A,x),  _(M,R),  _(M,R),
-  /* 0D40 */  _(M,R),  _(M,R),  _(M,R),  _(M,B),  _(M,B),  _(x,x),  _(M,L),  _(M,L),
-  /* 0D48 */  _(M,L),  _(x,x), _(M,LR), _(M,LR), _(M,LR),  _(V,T),_(CPR,x),  _(x,x),
-  /* 0D50 */  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(CD,x), _(CD,x), _(CD,x),  _(M,R),
-  /* 0D58 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(VI,x),
-  /* 0D60 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
-  /* 0D68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 0D70 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0D78 */  _(x,x),  _(x,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x),
-
-  /* Sinhala */
-
-  /* 0D80 */  _(x,x),  _(x,x), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 0D88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 0D90 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x),
-  /* 0D98 */  _(x,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0DA0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0DA8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0DB0 */  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0DB8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),  _(x,x),  _(x,x),
-  /* 0DC0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),
-  /* 0DC8 */  _(x,x),  _(x,x),  _(V,T),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),
-  /* 0DD0 */  _(M,R),  _(M,R),  _(M,T),  _(M,T),  _(M,B),  _(x,x),  _(M,B),  _(x,x),
-  /* 0DD8 */  _(M,R),  _(M,L), _(M,TL),  _(M,L), _(M,LR),_(M,TLR), _(M,LR),  _(M,R),
-  /* 0DE0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
-  /* 0DE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 0DF0 */  _(x,x),  _(x,x),  _(M,R),  _(M,R),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-
-#define indic_offset_0x1000u 1336
-
-
-  /* Myanmar */
-
-  /* 1000 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 1008 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 1010 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 1018 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 1020 */  _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 1028 */ _(VI,x), _(VI,x), _(VI,x),  _(M,R),  _(M,R),  _(M,T),  _(M,T),  _(M,B),
-  /* 1030 */  _(M,B),  _(M,L),  _(M,T),  _(M,T),  _(M,T),  _(M,T), _(Bi,T), _(TM,B),
-  /* 1038 */ _(Vs,R), _(IS,x), _(PK,T), _(CM,R), _(CM,x), _(CM,B), _(CM,B),  _(C,x),
-  /* 1040 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 1048 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(CP,x),  _(x,x),
-  /* 1050 */  _(C,x),  _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(M,R),  _(M,R),
-  /* 1058 */  _(M,B),  _(M,B),  _(C,x),  _(C,x),  _(C,x),  _(C,x), _(CM,B), _(CM,B),
-  /* 1060 */ _(CM,B),  _(C,x),  _(M,R), _(TM,R), _(TM,R),  _(C,x),  _(C,x),  _(M,R),
-  /* 1068 */  _(M,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R),  _(C,x),  _(C,x),
-  /* 1070 */  _(C,x),  _(M,T),  _(M,T),  _(M,T),  _(M,T),  _(C,x),  _(C,x),  _(C,x),
-  /* 1078 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 1080 */  _(C,x),  _(C,x), _(CM,B),  _(M,R),  _(M,L),  _(M,T),  _(M,T), _(TM,R),
-  /* 1088 */ _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,B),  _(C,x), _(TM,R),
-  /* 1090 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 1098 */ _(Nd,x), _(Nd,x), _(TM,R), _(TM,R),  _(M,R),  _(M,T),  _(x,x),  _(x,x),
-
-#define indic_offset_0x1780u 1496
-
-
-  /* Khmer */
-
-  /* 1780 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 1788 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 1790 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 1798 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 17A0 */  _(C,x),  _(C,x),  _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 17A8 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
-  /* 17B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x),  _(x,x),  _(M,R),  _(M,T),
-  /* 17B8 */  _(M,T),  _(M,T),  _(M,T),  _(M,B),  _(M,B),  _(M,B), _(M,TL),_(M,TLR),
-  /* 17C0 */ _(M,LR),  _(M,L),  _(M,L),  _(M,L), _(M,LR), _(M,LR), _(Bi,T), _(Vs,R),
-  /* 17C8 */  _(M,R), _(RS,T), _(RS,T), _(SM,T),_(CSR,T), _(CK,T), _(SM,T), _(SM,T),
-  /* 17D0 */ _(SM,T), _(PK,T), _(IS,x), _(SM,T),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 17D8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(A,x), _(SM,T),  _(x,x),  _(x,x),
-  /* 17E0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* 17E8 */ _(Nd,x), _(Nd,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-
-#define indic_offset_0x1cd0u 1608
-
-
-  /* Vedic Extensions */
-
-  /* 1CD0 */ _(Ca,T), _(Ca,T), _(Ca,T),  _(x,x), _(Ca,O), _(Ca,B), _(Ca,B), _(Ca,B),
-  /* 1CD8 */ _(Ca,B), _(Ca,B), _(Ca,T), _(Ca,T), _(Ca,B), _(Ca,B), _(Ca,B), _(Ca,B),
-  /* 1CE0 */ _(Ca,T), _(Ca,R),  _(x,O),  _(x,O),  _(x,O),  _(x,O),  _(x,O),  _(x,O),
-  /* 1CE8 */  _(x,O),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,B),  _(x,x),  _(x,x),
-  /* 1CF0 */  _(x,x),  _(x,x), _(Vs,x), _(Vs,x), _(Ca,T),  _(x,x),  _(x,x), _(Ca,R),
-  /* 1CF8 */ _(Ca,x), _(Ca,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-
-#define indic_offset_0x2008u 1656
-
-
-  /* General Punctuation */
-
-  /* 2008 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),_(ZWNJ,x),_(ZWJ,x),  _(x,x),  _(x,x),
-  /* 2010 */ _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(CP,x),  _(x,x),  _(x,x),  _(x,x),
-
-#define indic_offset_0x2070u 1672
-
-
-  /* Superscripts and Subscripts */
-
-  /* 2070 */  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(SM,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 2078 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 2080 */  _(x,x),  _(x,x), _(SM,x), _(SM,x), _(SM,x),  _(x,x),  _(x,x),  _(x,x),
-
-#define indic_offset_0xa8e0u 1696
-
-
-  /* Devanagari Extended */
-
-  /* A8E0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
-  /* A8E8 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
-  /* A8F0 */ _(Ca,T), _(Ca,T), _(Bi,x), _(Bi,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-
-#define indic_offset_0xa9e0u 1720
-
-
-  /* Myanmar Extended-B */
-
-  /* A9E0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(M,T),  _(x,x),  _(C,x),
-  /* A9E8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* A9F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
-  /* A9F8 */ _(Nd,x), _(Nd,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(x,x),
-
-#define indic_offset_0xaa60u 1752
-
-
-  /* Myanmar Extended-A */
-
-  /* AA60 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* AA68 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* AA70 */  _(x,x),  _(C,x),  _(C,x),  _(C,x), _(CP,x), _(CP,x), _(CP,x),  _(x,x),
-  /* AA78 */  _(x,x),  _(x,x),  _(C,x), _(TM,R), _(TM,T), _(TM,R),  _(C,x),  _(C,x),
-
-}; /* Table items: 1784; occupancy: 70% */
-
-INDIC_TABLE_ELEMENT_TYPE
-hb_indic_get_categories (hb_codepoint_t u)
-{
-  switch (u >> 12)
-  {
-    case 0x0u:
-      if (unlikely (u == 0x00A0u)) return _(CP,x);
-      if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
-      break;
-
-    case 0x1u:
-      if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x1780u, 0x17EFu)) return indic_table[u - 0x1780u + indic_offset_0x1780u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
-      break;
-
-    case 0x2u:
-      if (unlikely (u == 0x25CCu)) return _(CP,x);
-      if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u];
-      break;
-
-    case 0xAu:
-      if (hb_in_range<hb_codepoint_t> (u, 0xA8E0u, 0xA8F7u)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u];
-      if (hb_in_range<hb_codepoint_t> (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u];
-      if (hb_in_range<hb_codepoint_t> (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u];
-      break;
-
-    default:
-      break;
-  }
-  return _(x,x);
-}
-
-#undef _
-
-#undef ISC_A
-#undef ISC_Bi
-#undef ISC_BJN
-#undef ISC_Ca
-#undef ISC_C
-#undef ISC_CD
-#undef ISC_CF
-#undef ISC_CHL
-#undef ISC_CK
-#undef ISC_CM
-#undef ISC_CP
-#undef ISC_CPR
-#undef ISC_CPrf
-#undef ISC_CS
-#undef ISC_CSR
-#undef ISC_CWS
-#undef ISC_GM
-#undef ISC_IS
-#undef ISC_ZWJ
-#undef ISC_ML
-#undef ISC_ZWNJ
-#undef ISC_N
-#undef ISC_Nd
-#undef ISC_NJ
-#undef ISC_x
-#undef ISC_PK
-#undef ISC_RS
-#undef ISC_SM
-#undef ISC_TL
-#undef ISC_TM
-#undef ISC_V
-#undef ISC_Vs
-#undef ISC_Vo
-#undef ISC_M
-#undef ISC_VI
-
-#undef IMC_B
-#undef IMC_BL
-#undef IMC_BR
-#undef IMC_L
-#undef IMC_LR
-#undef IMC_x
-#undef IMC_O
-#undef IMC_R
-#undef IMC_T
-#undef IMC_TB
-#undef IMC_TBR
-#undef IMC_TL
-#undef IMC_TLR
-#undef IMC_TR
-#undef IMC_VOL
-
-/* == End of generated table == */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
deleted file mode 100644
index 32ad86a5..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
+++ /dev/null
@@ -1,1569 +0,0 @@
-/*
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-complex-indic-private.hh"
-#include "hb-ot-layout-private.hh"
-
-
-/*
- * Indic shaper.
- */
-
-
-/*
- * Indic configurations.  Note that we do not want to keep every single script-specific
- * behavior in these tables necessarily.  This should mainly be used for per-script
- * properties that are cheaper keeping here, than in the code.  Ie. if, say, one and
- * only one script has an exception, that one script can be if'ed directly in the code,
- * instead of adding a new flag in these structs.
- */
-
-enum base_position_t {
-  BASE_POS_LAST_SINHALA,
-  BASE_POS_LAST
-};
-enum reph_position_t {
-  REPH_POS_AFTER_MAIN  = POS_AFTER_MAIN,
-  REPH_POS_BEFORE_SUB  = POS_BEFORE_SUB,
-  REPH_POS_AFTER_SUB   = POS_AFTER_SUB,
-  REPH_POS_BEFORE_POST = POS_BEFORE_POST,
-  REPH_POS_AFTER_POST  = POS_AFTER_POST
-};
-enum reph_mode_t {
-  REPH_MODE_IMPLICIT,  /* Reph formed out of initial Ra,H sequence. */
-  REPH_MODE_EXPLICIT,  /* Reph formed out of initial Ra,H,ZWJ sequence. */
-  REPH_MODE_LOG_REPHA  /* Encoded Repha character, needs reordering. */
-};
-enum blwf_mode_t {
-  BLWF_MODE_PRE_AND_POST, /* Below-forms feature applied to pre-base and post-base. */
-  BLWF_MODE_POST_ONLY     /* Below-forms feature applied to post-base only. */
-};
-struct indic_config_t
-{
-  hb_script_t     script;
-  bool            has_old_spec;
-  hb_codepoint_t  virama;
-  base_position_t base_pos;
-  reph_position_t reph_pos;
-  reph_mode_t     reph_mode;
-  blwf_mode_t     blwf_mode;
-};
-
-static const indic_config_t indic_configs[] =
-{
-  /* Default.  Should be first. */
-  {HB_SCRIPT_INVALID,	false,      0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
-  {HB_SCRIPT_DEVANAGARI,true, 0x094Du,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
-  {HB_SCRIPT_BENGALI,	true, 0x09CDu,BASE_POS_LAST, REPH_POS_AFTER_SUB,  REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
-  {HB_SCRIPT_GURMUKHI,	true, 0x0A4Du,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
-  {HB_SCRIPT_GUJARATI,	true, 0x0ACDu,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
-  {HB_SCRIPT_ORIYA,	true, 0x0B4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
-  {HB_SCRIPT_TAMIL,	true, 0x0BCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
-  {HB_SCRIPT_TELUGU,	true, 0x0C4Du,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY},
-  {HB_SCRIPT_KANNADA,	true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY},
-  {HB_SCRIPT_MALAYALAM,	true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST},
-  {HB_SCRIPT_SINHALA,	false,0x0DCAu,BASE_POS_LAST_SINHALA,
-						     REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST},
-};
-
-
-
-/*
- * Indic shaper.
- */
-
-struct feature_list_t {
-  hb_tag_t tag;
-  hb_ot_map_feature_flags_t flags;
-};
-
-static const feature_list_t
-indic_features[] =
-{
-  /*
-   * Basic features.
-   * These features are applied in order, one at a time, after initial_reordering.
-   */
-  {HB_TAG('n','u','k','t'), F_GLOBAL},
-  {HB_TAG('a','k','h','n'), F_GLOBAL},
-  {HB_TAG('r','p','h','f'), F_NONE},
-  {HB_TAG('r','k','r','f'), F_GLOBAL},
-  {HB_TAG('p','r','e','f'), F_NONE},
-  {HB_TAG('b','l','w','f'), F_NONE},
-  {HB_TAG('a','b','v','f'), F_NONE},
-  {HB_TAG('h','a','l','f'), F_NONE},
-  {HB_TAG('p','s','t','f'), F_NONE},
-  {HB_TAG('v','a','t','u'), F_GLOBAL},
-  {HB_TAG('c','j','c','t'), F_GLOBAL},
-  /*
-   * Other features.
-   * These features are applied all at once, after final_reordering.
-   * Default Bengali font in Windows for example has intermixed
-   * lookups for init,pres,abvs,blws features.
-   */
-  {HB_TAG('i','n','i','t'), F_NONE},
-  {HB_TAG('p','r','e','s'), F_GLOBAL},
-  {HB_TAG('a','b','v','s'), F_GLOBAL},
-  {HB_TAG('b','l','w','s'), F_GLOBAL},
-  {HB_TAG('p','s','t','s'), F_GLOBAL},
-  {HB_TAG('h','a','l','n'), F_GLOBAL},
-  /* Positioning features, though we don't care about the types. */
-  {HB_TAG('d','i','s','t'), F_GLOBAL},
-  {HB_TAG('a','b','v','m'), F_GLOBAL},
-  {HB_TAG('b','l','w','m'), F_GLOBAL},
-};
-
-/*
- * Must be in the same order as the indic_features array.
- */
-enum {
-  _NUKT,
-  _AKHN,
-  RPHF,
-  _RKRF,
-  PREF,
-  BLWF,
-  ABVF,
-  HALF,
-  PSTF,
-  _VATU,
-  _CJCT,
-
-  INIT,
-  _PRES,
-  _ABVS,
-  _BLWS,
-  _PSTS,
-  _HALN,
-  _DIST,
-  _ABVM,
-  _BLWM,
-
-  INDIC_NUM_FEATURES,
-  INDIC_BASIC_FEATURES = INIT /* Don't forget to update this! */
-};
-
-static void
-setup_syllables (const hb_ot_shape_plan_t *plan,
-		 hb_font_t *font,
-		 hb_buffer_t *buffer);
-static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-		    hb_font_t *font,
-		    hb_buffer_t *buffer);
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-		  hb_font_t *font,
-		  hb_buffer_t *buffer);
-static void
-clear_syllables (const hb_ot_shape_plan_t *plan,
-		 hb_font_t *font,
-		 hb_buffer_t *buffer);
-
-static void
-collect_features_indic (hb_ot_shape_planner_t *plan)
-{
-  hb_ot_map_builder_t *map = &plan->map;
-
-  /* Do this before any lookups have been applied. */
-  map->add_gsub_pause (setup_syllables);
-
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
-  /* The Indic specs do not require ccmp, but we apply it here since if
-   * there is a use of it, it's typically at the beginning. */
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-
-
-  unsigned int i = 0;
-  map->add_gsub_pause (initial_reordering);
-  for (; i < INDIC_BASIC_FEATURES; i++) {
-    map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-    map->add_gsub_pause (nullptr);
-  }
-  map->add_gsub_pause (final_reordering);
-  for (; i < INDIC_NUM_FEATURES; i++) {
-    map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-  }
-
-  map->add_global_bool_feature (HB_TAG('c','a','l','t'));
-  map->add_global_bool_feature (HB_TAG('c','l','i','g'));
-
-  map->add_gsub_pause (clear_syllables);
-}
-
-static void
-override_features_indic (hb_ot_shape_planner_t *plan)
-{
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
-}
-
-
-struct would_substitute_feature_t
-{
-  inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
-  {
-    zero_context = zero_context_;
-    map->get_stage_lookups (0/*GSUB*/,
-			    map->get_feature_stage (0/*GSUB*/, feature_tag),
-			    &lookups, &count);
-  }
-
-  inline bool would_substitute (const hb_codepoint_t *glyphs,
-				unsigned int          glyphs_count,
-				hb_face_t            *face) const
-  {
-    for (unsigned int i = 0; i < count; i++)
-      if (hb_ot_layout_lookup_would_substitute_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context))
-	return true;
-    return false;
-  }
-
-  private:
-  const hb_ot_map_t::lookup_map_t *lookups;
-  unsigned int count;
-  bool zero_context;
-};
-
-struct indic_shape_plan_t
-{
-  ASSERT_POD ();
-
-  inline bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
-  {
-    hb_codepoint_t glyph = virama_glyph;
-    if (unlikely (virama_glyph == (hb_codepoint_t) -1))
-    {
-      if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph))
-	glyph = 0;
-      /* Technically speaking, the spec says we should apply 'locl' to virama too.
-       * Maybe one day... */
-
-      /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
-       * during shape planning...  Instead, overwrite it here.  It's safe.  Don't worry! */
-      virama_glyph = glyph;
-    }
-
-    *pglyph = glyph;
-    return glyph != 0;
-  }
-
-  const indic_config_t *config;
-
-  bool is_old_spec;
-  mutable hb_codepoint_t virama_glyph;
-
-  would_substitute_feature_t rphf;
-  would_substitute_feature_t pref;
-  would_substitute_feature_t blwf;
-  would_substitute_feature_t pstf;
-
-  hb_mask_t mask_array[INDIC_NUM_FEATURES];
-};
-
-static void *
-data_create_indic (const hb_ot_shape_plan_t *plan)
-{
-  indic_shape_plan_t *indic_plan = (indic_shape_plan_t *) calloc (1, sizeof (indic_shape_plan_t));
-  if (unlikely (!indic_plan))
-    return nullptr;
-
-  indic_plan->config = &indic_configs[0];
-  for (unsigned int i = 1; i < ARRAY_LENGTH (indic_configs); i++)
-    if (plan->props.script == indic_configs[i].script) {
-      indic_plan->config = &indic_configs[i];
-      break;
-    }
-
-  indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
-  indic_plan->virama_glyph = (hb_codepoint_t) -1;
-
-  /* Use zero-context would_substitute() matching for new-spec of the main
-   * Indic scripts, and scripts with one spec only, but not for old-specs.
-   * The new-spec for all dual-spec scripts says zero-context matching happens.
-   *
-   * However, testing with Malayalam shows that old and new spec both allow
-   * context.  Testing with Bengali new-spec however shows that it doesn't.
-   * So, the heuristic here is the way it is.  It should *only* be changed,
-   * as we discover more cases of what Windows does.  DON'T TOUCH OTHERWISE.
-   */
-  bool zero_context = !indic_plan->is_old_spec && plan->props.script != HB_SCRIPT_MALAYALAM;
-  indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f'), zero_context);
-  indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context);
-  indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context);
-  indic_plan->pstf.init (&plan->map, HB_TAG('p','s','t','f'), zero_context);
-
-  for (unsigned int i = 0; i < ARRAY_LENGTH (indic_plan->mask_array); i++)
-    indic_plan->mask_array[i] = (indic_features[i].flags & F_GLOBAL) ?
-				 0 : plan->map.get_1_mask (indic_features[i].tag);
-
-  return indic_plan;
-}
-
-static void
-data_destroy_indic (void *data)
-{
-  free (data);
-}
-
-static indic_position_t
-consonant_position_from_face (const indic_shape_plan_t *indic_plan,
-			      const hb_codepoint_t consonant,
-			      const hb_codepoint_t virama,
-			      hb_face_t *face)
-{
-  /* For old-spec, the order of glyphs is Consonant,Virama,
-   * whereas for new-spec, it's Virama,Consonant.  However,
-   * some broken fonts (like Free Sans) simply copied lookups
-   * from old-spec to new-spec without modification.
-   * And oddly enough, Uniscribe seems to respect those lookups.
-   * Eg. in the sequence U+0924,U+094D,U+0930, Uniscribe finds
-   * base at 0.  The font however, only has lookups matching
-   * 930,94D in 'blwf', not the expected 94D,930 (with new-spec
-   * table).  As such, we simply match both sequences.  Seems
-   * to work. */
-  hb_codepoint_t glyphs[3] = {virama, consonant, virama};
-  if (indic_plan->blwf.would_substitute (glyphs  , 2, face) ||
-      indic_plan->blwf.would_substitute (glyphs+1, 2, face))
-    return POS_BELOW_C;
-  if (indic_plan->pstf.would_substitute (glyphs  , 2, face) ||
-      indic_plan->pstf.would_substitute (glyphs+1, 2, face))
-    return POS_POST_C;
-  if (indic_plan->pref.would_substitute (glyphs  , 2, face) ||
-      indic_plan->pref.would_substitute (glyphs+1, 2, face))
-    return POS_POST_C;
-  return POS_BASE_C;
-}
-
-
-enum syllable_type_t {
-  consonant_syllable,
-  vowel_syllable,
-  standalone_cluster,
-  symbol_cluster,
-  broken_cluster,
-  non_indic_cluster,
-};
-
-#include "hb-ot-shape-complex-indic-machine.hh"
-
-
-static void
-setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		   hb_buffer_t              *buffer,
-		   hb_font_t                *font HB_UNUSED)
-{
-  HB_BUFFER_ALLOCATE_VAR (buffer, indic_category);
-  HB_BUFFER_ALLOCATE_VAR (buffer, indic_position);
-
-  /* We cannot setup masks here.  We save information about characters
-   * and setup masks later on in a pause-callback. */
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    set_indic_properties (info[i]);
-}
-
-static void
-setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		 hb_font_t *font HB_UNUSED,
-		 hb_buffer_t *buffer)
-{
-  find_syllables (buffer);
-  foreach_syllable (buffer, start, end)
-    buffer->unsafe_to_break (start, end);
-}
-
-static int
-compare_indic_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
-{
-  int a = pa->indic_position();
-  int b = pb->indic_position();
-
-  return a < b ? -1 : a == b ? 0 : +1;
-}
-
-
-
-static void
-update_consonant_positions (const hb_ot_shape_plan_t *plan,
-			    hb_font_t         *font,
-			    hb_buffer_t       *buffer)
-{
-  const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
-
-  if (indic_plan->config->base_pos != BASE_POS_LAST)
-    return;
-
-  hb_codepoint_t virama;
-  if (indic_plan->get_virama_glyph (font, &virama))
-  {
-    hb_face_t *face = font->face;
-    unsigned int count = buffer->len;
-    hb_glyph_info_t *info = buffer->info;
-    for (unsigned int i = 0; i < count; i++)
-      if (info[i].indic_position() == POS_BASE_C)
-      {
-	hb_codepoint_t consonant = info[i].codepoint;
-	info[i].indic_position() = consonant_position_from_face (indic_plan, consonant, virama, face);
-      }
-  }
-}
-
-
-/* Rules from:
- * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx */
-
-static void
-initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
-				       hb_face_t *face,
-				       hb_buffer_t *buffer,
-				       unsigned int start, unsigned int end)
-{
-  const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
-  hb_glyph_info_t *info = buffer->info;
-
-  /* https://github.com/harfbuzz/harfbuzz/issues/435#issuecomment-335560167
-   * // For compatibility with legacy usage in Kannada,
-   * // Ra+h+ZWJ must behave like Ra+ZWJ+h...
-   */
-  if (buffer->props.script == HB_SCRIPT_KANNADA &&
-      start + 3 <= end &&
-      is_one_of (info[start  ], FLAG (OT_Ra)) &&
-      is_one_of (info[start+1], FLAG (OT_H)) &&
-      is_one_of (info[start+2], FLAG (OT_ZWJ)))
-  {
-    buffer->merge_clusters (start+1, start+3);
-    hb_glyph_info_t tmp = info[start+1];
-    info[start+1] = info[start+2];
-    info[start+2] = tmp;
-  }
-
-  /* 1. Find base consonant:
-   *
-   * The shaping engine finds the base consonant of the syllable, using the
-   * following algorithm: starting from the end of the syllable, move backwards
-   * until a consonant is found that does not have a below-base or post-base
-   * form (post-base forms have to follow below-base forms), or that is not a
-   * pre-base-reordering Ra, or arrive at the first consonant. The consonant
-   * stopped at will be the base.
-   *
-   *   o If the syllable starts with Ra + Halant (in a script that has Reph)
-   *     and has more than one consonant, Ra is excluded from candidates for
-   *     base consonants.
-   */
-
-  unsigned int base = end;
-  bool has_reph = false;
-
-  {
-    /* -> If the syllable starts with Ra + Halant (in a script that has Reph)
-     *    and has more than one consonant, Ra is excluded from candidates for
-     *    base consonants. */
-    unsigned int limit = start;
-    if (indic_plan->mask_array[RPHF] &&
-	start + 3 <= end &&
-	(
-	 (indic_plan->config->reph_mode == REPH_MODE_IMPLICIT && !is_joiner (info[start + 2])) ||
-	 (indic_plan->config->reph_mode == REPH_MODE_EXPLICIT && info[start + 2].indic_category() == OT_ZWJ)
-	))
-    {
-      /* See if it matches the 'rphf' feature. */
-      hb_codepoint_t glyphs[3] = {info[start].codepoint,
-				  info[start + 1].codepoint,
-				  indic_plan->config->reph_mode == REPH_MODE_EXPLICIT ?
-				    info[start + 2].codepoint : 0};
-      if (indic_plan->rphf.would_substitute (glyphs, 2, face) ||
-	  (indic_plan->config->reph_mode == REPH_MODE_EXPLICIT &&
-	   indic_plan->rphf.would_substitute (glyphs, 3, face)))
-      {
-	limit += 2;
-	while (limit < end && is_joiner (info[limit]))
-	  limit++;
-	base = start;
-	has_reph = true;
-      }
-    } else if (indic_plan->config->reph_mode == REPH_MODE_LOG_REPHA && info[start].indic_category() == OT_Repha)
-    {
-	limit += 1;
-	while (limit < end && is_joiner (info[limit]))
-	  limit++;
-	base = start;
-	has_reph = true;
-    }
-
-    switch (indic_plan->config->base_pos)
-    {
-      case BASE_POS_LAST:
-      {
-	/* -> starting from the end of the syllable, move backwards */
-	unsigned int i = end;
-	bool seen_below = false;
-	do {
-	  i--;
-	  /* -> until a consonant is found */
-	  if (is_consonant (info[i]))
-	  {
-	    /* -> that does not have a below-base or post-base form
-	     * (post-base forms have to follow below-base forms), */
-	    if (info[i].indic_position() != POS_BELOW_C &&
-		(info[i].indic_position() != POS_POST_C || seen_below))
-	    {
-	      base = i;
-	      break;
-	    }
-	    if (info[i].indic_position() == POS_BELOW_C)
-	      seen_below = true;
-
-	    /* -> or that is not a pre-base-reordering Ra,
-	     *
-	     * IMPLEMENTATION NOTES:
-	     *
-	     * Our pre-base-reordering Ra's are marked POS_POST_C, so will be skipped
-	     * by the logic above already.
-	     */
-
-	    /* -> or arrive at the first consonant. The consonant stopped at will
-	     * be the base. */
-	    base = i;
-	  }
-	  else
-	  {
-	    /* A ZWJ after a Halant stops the base search, and requests an explicit
-	     * half form.
-	     * A ZWJ before a Halant, requests a subjoined form instead, and hence
-	     * search continues.  This is particularly important for Bengali
-	     * sequence Ra,H,Ya that should form Ya-Phalaa by subjoining Ya. */
-	    if (start < i &&
-		info[i].indic_category() == OT_ZWJ &&
-		info[i - 1].indic_category() == OT_H)
-	      break;
-	  }
-	} while (i > limit);
-      }
-      break;
-
-      case BASE_POS_LAST_SINHALA:
-      {
-        /* Sinhala base positioning is slightly different from main Indic, in that:
-	 * 1. Its ZWJ behavior is different,
-	 * 2. We don't need to look into the font for consonant positions.
-	 */
-
-	if (!has_reph)
-	  base = limit;
-
-	/* Find the last base consonant that is not blocked by ZWJ.  If there is
-	 * a ZWJ right before a base consonant, that would request a subjoined form. */
-	for (unsigned int i = limit; i < end; i++)
-	  if (is_consonant (info[i]))
-	  {
-	    if (limit < i && info[i - 1].indic_category() == OT_ZWJ)
-	      break;
-	    else
-	      base = i;
-	  }
-
-	/* Mark all subsequent consonants as below. */
-	for (unsigned int i = base + 1; i < end; i++)
-	  if (is_consonant (info[i]))
-	    info[i].indic_position() = POS_BELOW_C;
-      }
-      break;
-    }
-
-    /* -> If the syllable starts with Ra + Halant (in a script that has Reph)
-     *    and has more than one consonant, Ra is excluded from candidates for
-     *    base consonants.
-     *
-     *  Only do this for unforced Reph. (ie. not for Ra,H,ZWJ. */
-    if (has_reph && base == start && limit - base <= 2) {
-      /* Have no other consonant, so Reph is not formed and Ra becomes base. */
-      has_reph = false;
-    }
-  }
-
-
-  /* 2. Decompose and reorder Matras:
-   *
-   * Each matra and any syllable modifier sign in the syllable are moved to the
-   * appropriate position relative to the consonant(s) in the syllable. The
-   * shaping engine decomposes two- or three-part matras into their constituent
-   * parts before any repositioning. Matra characters are classified by which
-   * consonant in a conjunct they have affinity for and are reordered to the
-   * following positions:
-   *
-   *   o Before first half form in the syllable
-   *   o After subjoined consonants
-   *   o After post-form consonant
-   *   o After main consonant (for above marks)
-   *
-   * IMPLEMENTATION NOTES:
-   *
-   * The normalize() routine has already decomposed matras for us, so we don't
-   * need to worry about that.
-   */
-
-
-  /* 3.  Reorder marks to canonical order:
-   *
-   * Adjacent nukta and halant or nukta and vedic sign are always repositioned
-   * if necessary, so that the nukta is first.
-   *
-   * IMPLEMENTATION NOTES:
-   *
-   * We don't need to do this: the normalize() routine already did this for us.
-   */
-
-
-  /* Reorder characters */
-
-  for (unsigned int i = start; i < base; i++)
-    info[i].indic_position() = MIN (POS_PRE_C, (indic_position_t) info[i].indic_position());
-
-  if (base < end)
-    info[base].indic_position() = POS_BASE_C;
-
-  /* Mark final consonants.  A final consonant is one appearing after a matra.
-   * Happens in Sinhala. */
-  for (unsigned int i = base + 1; i < end; i++)
-    if (info[i].indic_category() == OT_M) {
-      for (unsigned int j = i + 1; j < end; j++)
-	if (is_consonant (info[j])) {
-	 info[j].indic_position() = POS_FINAL_C;
-	 break;
-       }
-      break;
-    }
-
-  /* Handle beginning Ra */
-  if (has_reph)
-    info[start].indic_position() = POS_RA_TO_BECOME_REPH;
-
-  /* For old-style Indic script tags, move the first post-base Halant after
-   * last consonant.
-   *
-   * Reports suggest that in some scripts Uniscribe does this only if there
-   * is *not* a Halant after last consonant already (eg. Kannada), while it
-   * does it unconditionally in other scripts (eg. Malayalam).  We don't
-   * currently know about other scripts, so we single out Malayalam for now.
-   *
-   * Kannada test case:
-   * U+0C9A,U+0CCD,U+0C9A,U+0CCD
-   * With some versions of Lohit Kannada.
-   * https://bugs.freedesktop.org/show_bug.cgi?id=59118
-   *
-   * Malayalam test case:
-   * U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D
-   * With lohit-ttf-20121122/Lohit-Malayalam.ttf
-   */
-  if (indic_plan->is_old_spec)
-  {
-    bool disallow_double_halants = buffer->props.script != HB_SCRIPT_MALAYALAM;
-    for (unsigned int i = base + 1; i < end; i++)
-      if (info[i].indic_category() == OT_H)
-      {
-        unsigned int j;
-        for (j = end - 1; j > i; j--)
-	  if (is_consonant (info[j]) ||
-	      (disallow_double_halants && info[j].indic_category() == OT_H))
-	    break;
-	if (info[j].indic_category() != OT_H && j > i) {
-	  /* Move Halant to after last consonant. */
-	  hb_glyph_info_t t = info[i];
-	  memmove (&info[i], &info[i + 1], (j - i) * sizeof (info[0]));
-	  info[j] = t;
-	}
-        break;
-      }
-  }
-
-  /* Attach misc marks to previous char to move with them. */
-  {
-    indic_position_t last_pos = POS_START;
-    for (unsigned int i = start; i < end; i++)
-    {
-      if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_H))))
-      {
-	info[i].indic_position() = last_pos;
-	if (unlikely (info[i].indic_category() == OT_H &&
-		      info[i].indic_position() == POS_PRE_M))
-	{
-	  /*
-	   * Uniscribe doesn't move the Halant with Left Matra.
-	   * TEST: U+092B,U+093F,U+094DE
-	   * We follow.  This is important for the Sinhala
-	   * U+0DDA split matra since it decomposes to U+0DD9,U+0DCA
-	   * where U+0DD9 is a left matra and U+0DCA is the virama.
-	   * We don't want to move the virama with the left matra.
-	   * TEST: U+0D9A,U+0DDA
-	   */
-	  for (unsigned int j = i; j > start; j--)
-	    if (info[j - 1].indic_position() != POS_PRE_M) {
-	      info[i].indic_position() = info[j - 1].indic_position();
-	      break;
-	    }
-	}
-      } else if (info[i].indic_position() != POS_SMVD) {
-        last_pos = (indic_position_t) info[i].indic_position();
-      }
-    }
-  }
-  /* For post-base consonants let them own anything before them
-   * since the last consonant or matra. */
-  {
-    unsigned int last = base;
-    for (unsigned int i = base + 1; i < end; i++)
-      if (is_consonant (info[i]))
-      {
-	for (unsigned int j = last + 1; j < i; j++)
-	  if (info[j].indic_position() < POS_SMVD)
-	    info[j].indic_position() = info[i].indic_position();
-	last = i;
-      } else if (info[i].indic_category() == OT_M)
-        last = i;
-  }
-
-
-  {
-    /* Use syllable() for sort accounting temporarily. */
-    unsigned int syllable = info[start].syllable();
-    for (unsigned int i = start; i < end; i++)
-      info[i].syllable() = i - start;
-
-    /* Sit tight, rock 'n roll! */
-    hb_stable_sort (info + start, end - start, compare_indic_order);
-    /* Find base again */
-    base = end;
-    for (unsigned int i = start; i < end; i++)
-      if (info[i].indic_position() == POS_BASE_C)
-      {
-	base = i;
-	break;
-      }
-    /* 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
-     * order and merge as needed.
-     * For pre-base stuff, we handle cluster issues in final reordering.
-     *
-     * We could use buffer->sort() for this, if there was no special
-     * reordering of pre-base stuff happening later...
-     */
-    if (indic_plan->is_old_spec || end - base > 127)
-      buffer->merge_clusters (base, end);
-    else
-    {
-      /* Note!  syllable() is a one-byte field. */
-      for (unsigned int i = base; i < end; i++)
-        if (info[i].syllable() != 255)
-	{
-	  unsigned int max = i;
-	  unsigned int j = start + info[i].syllable();
-	  while (j != i)
-	  {
-	    max = MAX (max, j);
-	    unsigned int next = start + info[j].syllable();
-	    info[j].syllable() = 255; /* So we don't process j later again. */
-	    j = next;
-	  }
-	  if (i != max)
-	    buffer->merge_clusters (i, max + 1);
-	}
-    }
-
-    /* Put syllable back in. */
-    for (unsigned int i = start; i < end; i++)
-      info[i].syllable() = syllable;
-  }
-
-  /* Setup masks now */
-
-  {
-    hb_mask_t mask;
-
-    /* Reph */
-    for (unsigned int i = start; i < end && info[i].indic_position() == POS_RA_TO_BECOME_REPH; i++)
-      info[i].mask |= indic_plan->mask_array[RPHF];
-
-    /* Pre-base */
-    mask = indic_plan->mask_array[HALF];
-    if (!indic_plan->is_old_spec &&
-	indic_plan->config->blwf_mode == BLWF_MODE_PRE_AND_POST)
-      mask |= indic_plan->mask_array[BLWF];
-    for (unsigned int i = start; i < base; i++)
-      info[i].mask  |= mask;
-    /* Base */
-    mask = 0;
-    if (base < end)
-      info[base].mask |= mask;
-    /* Post-base */
-    mask = indic_plan->mask_array[BLWF] | indic_plan->mask_array[ABVF] | indic_plan->mask_array[PSTF];
-    for (unsigned int i = base + 1; i < end; i++)
-      info[i].mask  |= mask;
-  }
-
-  if (indic_plan->is_old_spec &&
-      buffer->props.script == HB_SCRIPT_DEVANAGARI)
-  {
-    /* Old-spec eye-lash Ra needs special handling.  From the
-     * spec:
-     *
-     * "The feature 'below-base form' is applied to consonants
-     * having below-base forms and following the base consonant.
-     * The exception is vattu, which may appear below half forms
-     * as well as below the base glyph. The feature 'below-base
-     * form' will be applied to all such occurrences of Ra as well."
-     *
-     * Test case: U+0924,U+094D,U+0930,U+094d,U+0915
-     * with Sanskrit 2003 font.
-     *
-     * However, note that Ra,Halant,ZWJ is the correct way to
-     * request eyelash form of Ra, so we wouldbn't inhibit it
-     * in that sequence.
-     *
-     * Test case: U+0924,U+094D,U+0930,U+094d,U+200D,U+0915
-     */
-    for (unsigned int i = start; i + 1 < base; i++)
-      if (info[i  ].indic_category() == OT_Ra &&
-	  info[i+1].indic_category() == OT_H  &&
-	  (i + 2 == base ||
-	   info[i+2].indic_category() != OT_ZWJ))
-      {
-	info[i  ].mask |= indic_plan->mask_array[BLWF];
-	info[i+1].mask |= indic_plan->mask_array[BLWF];
-      }
-  }
-
-  unsigned int pref_len = 2;
-  if (indic_plan->mask_array[PREF] && base + pref_len < end)
-  {
-    /* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */
-    for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
-      hb_codepoint_t glyphs[2];
-      for (unsigned int j = 0; j < pref_len; j++)
-        glyphs[j] = info[i + j].codepoint;
-      if (indic_plan->pref.would_substitute (glyphs, pref_len, face))
-      {
-	for (unsigned int j = 0; j < pref_len; j++)
-	  info[i++].mask |= indic_plan->mask_array[PREF];
-	break;
-      }
-    }
-  }
-
-  /* Apply ZWJ/ZWNJ effects */
-  for (unsigned int i = start + 1; i < end; i++)
-    if (is_joiner (info[i])) {
-      bool non_joiner = info[i].indic_category() == OT_ZWNJ;
-      unsigned int j = i;
-
-      do {
-	j--;
-
-	/* ZWJ/ZWNJ should disable CJCT.  They do that by simply
-	 * being there, since we don't skip them for the CJCT
-	 * feature (ie. F_MANUAL_ZWJ) */
-
-	/* A ZWNJ disables HALF. */
-	if (non_joiner)
-	  info[j].mask &= ~indic_plan->mask_array[HALF];
-
-      } while (j > start && !is_consonant (info[j]));
-    }
-}
-
-static void
-initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
-				       hb_face_t *face,
-				       hb_buffer_t *buffer,
-				       unsigned int start, unsigned int end)
-{
-  /* We treat placeholder/dotted-circle as if they are consonants, so we
-   * should just chain.  Only if not in compatibility mode that is... */
-
-  if (hb_options ().uniscribe_bug_compatible)
-  {
-    /* For dotted-circle, this is what Uniscribe does:
-     * If dotted-circle is the last glyph, it just does nothing.
-     * Ie. It doesn't form Reph. */
-    if (buffer->info[end - 1].indic_category() == OT_DOTTEDCIRCLE)
-      return;
-  }
-
-  initial_reordering_consonant_syllable (plan, face, buffer, start, end);
-}
-
-static void
-initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
-			     hb_face_t *face,
-			     hb_buffer_t *buffer,
-			     unsigned int start, unsigned int end)
-{
-  syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
-  switch (syllable_type)
-  {
-    case vowel_syllable: /* We made the vowels look like consonants.  So let's call the consonant logic! */
-    case consonant_syllable:
-     initial_reordering_consonant_syllable (plan, face, buffer, start, end);
-     break;
-
-    case broken_cluster: /* We already inserted dotted-circles, so just call the standalone_cluster. */
-    case standalone_cluster:
-     initial_reordering_standalone_cluster (plan, face, buffer, start, end);
-     break;
-
-    case symbol_cluster:
-    case non_indic_cluster:
-      break;
-  }
-}
-
-static inline void
-insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		       hb_font_t *font,
-		       hb_buffer_t *buffer)
-{
-  /* Note: This loop is extra overhead, but should not be measurable. */
-  bool has_broken_syllables = false;
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    if ((info[i].syllable() & 0x0F) == broken_cluster)
-    {
-      has_broken_syllables = true;
-      break;
-    }
-  if (likely (!has_broken_syllables))
-    return;
-
-
-  hb_codepoint_t dottedcircle_glyph;
-  if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
-    return;
-
-  hb_glyph_info_t dottedcircle = {0};
-  dottedcircle.codepoint = 0x25CCu;
-  set_indic_properties (dottedcircle);
-  dottedcircle.codepoint = dottedcircle_glyph;
-
-  buffer->clear_output ();
-
-  buffer->idx = 0;
-  unsigned int last_syllable = 0;
-  while (buffer->idx < buffer->len && !buffer->in_error)
-  {
-    unsigned int syllable = buffer->cur().syllable();
-    syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
-    if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
-    {
-      last_syllable = syllable;
-
-      hb_glyph_info_t ginfo = dottedcircle;
-      ginfo.cluster = buffer->cur().cluster;
-      ginfo.mask = buffer->cur().mask;
-      ginfo.syllable() = buffer->cur().syllable();
-      /* TODO Set glyph_props? */
-
-      /* Insert dottedcircle after possible Repha. */
-      while (buffer->idx < buffer->len && !buffer->in_error &&
-	     last_syllable == buffer->cur().syllable() &&
-	     buffer->cur().indic_category() == OT_Repha)
-        buffer->next_glyph ();
-
-      buffer->output_info (ginfo);
-    }
-    else
-      buffer->next_glyph ();
-  }
-
-  buffer->swap_buffers ();
-}
-
-static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-		    hb_font_t *font,
-		    hb_buffer_t *buffer)
-{
-  update_consonant_positions (plan, font, buffer);
-  insert_dotted_circles (plan, font, buffer);
-
-  foreach_syllable (buffer, start, end)
-    initial_reordering_syllable (plan, font->face, buffer, start, end);
-}
-
-static void
-final_reordering_syllable (const hb_ot_shape_plan_t *plan,
-			   hb_buffer_t *buffer,
-			   unsigned int start, unsigned int end)
-{
-  const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
-  hb_glyph_info_t *info = buffer->info;
-
-
-  /* This function relies heavily on halant glyphs.  Lots of ligation
-   * and possibly multiple substitutions happened prior to this
-   * phase, and that might have messed up our properties.  Recover
-   * from a particular case of that where we're fairly sure that a
-   * class of OT_H is desired but has been lost. */
-  if (indic_plan->virama_glyph)
-  {
-    unsigned int virama_glyph = indic_plan->virama_glyph;
-    for (unsigned int i = start; i < end; i++)
-      if (info[i].codepoint == virama_glyph &&
-	  _hb_glyph_info_ligated (&info[i]) &&
-	  _hb_glyph_info_multiplied (&info[i]))
-      {
-        /* This will make sure that this glyph passes is_halant() test. */
-	info[i].indic_category() = OT_H;
-	_hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
-      }
-  }
-
-
-  /* 4. Final reordering:
-   *
-   * After the localized forms and basic shaping forms GSUB features have been
-   * applied (see below), the shaping engine performs some final glyph
-   * reordering before applying all the remaining font features to the entire
-   * syllable.
-   */
-
-  bool try_pref = !!indic_plan->mask_array[PREF];
-
-  /* Find base again */
-  unsigned int base;
-  for (base = start; base < end; base++)
-    if (info[base].indic_position() >= POS_BASE_C)
-    {
-      if (try_pref && base + 1 < end)
-      {
-	for (unsigned int i = base + 1; i < end; i++)
-	  if ((info[i].mask & indic_plan->mask_array[PREF]) != 0)
-	  {
-	    if (!(_hb_glyph_info_substituted (&info[i]) &&
-		  _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
-	    {
-	      /* Ok, this was a 'pref' candidate but didn't form any.
-	       * Base is around here... */
-	      base = i;
-	      while (base < end && is_halant (info[base]))
-		base++;
-	      info[base].indic_position() = POS_BASE_C;
-
-	      try_pref = false;
-	    }
-	    break;
-	  }
-      }
-      /* For Malayalam, skip over unformed below- (but NOT post-) forms. */
-      if (buffer->props.script == HB_SCRIPT_MALAYALAM)
-      {
-	for (unsigned int i = base + 1; i < end; i++)
-	{
-	  while (i < end && is_joiner (info[i]))
-	    i++;
-	  if (i == end || !is_halant (info[i]))
-	    break;
-	  i++; /* Skip halant. */
-	  while (i < end && is_joiner (info[i]))
-	    i++;
-	  if (i < end && is_consonant (info[i]) && info[i].indic_position() == POS_BELOW_C)
-	  {
-	    base = i;
-	    info[base].indic_position() = POS_BASE_C;
-	  }
-	}
-      }
-
-      if (start < base && info[base].indic_position() > POS_BASE_C)
-        base--;
-      break;
-    }
-  if (base == end && start < base &&
-      is_one_of (info[base - 1], FLAG (OT_ZWJ)))
-    base--;
-  if (base < end)
-    while (start < base &&
-	   is_one_of (info[base], (FLAG (OT_N) | FLAG (OT_H))))
-      base--;
-
-
-  /*   o Reorder matras:
-   *
-   *     If a pre-base matra character had been reordered before applying basic
-   *     features, the glyph can be moved closer to the main consonant based on
-   *     whether half-forms had been formed. Actual position for the matra is
-   *     defined as “after last standalone halant glyph, after initial matra
-   *     position and before the main consonant”. If ZWJ or ZWNJ follow this
-   *     halant, position is moved after it.
-   */
-
-  if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */
-  {
-    /* If we lost track of base, alas, position before last thingy. */
-    unsigned int new_pos = base == end ? base - 2 : base - 1;
-
-    /* Malayalam / Tamil do not have "half" forms or explicit virama forms.
-     * The glyphs formed by 'half' are Chillus or ligated explicit viramas.
-     * We want to position matra after them.
-     */
-    if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL)
-    {
-      while (new_pos > start &&
-	     !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_H)))))
-	new_pos--;
-
-      /* If we found no Halant we are done.
-       * Otherwise only proceed if the Halant does
-       * not belong to the Matra itself! */
-      if (is_halant (info[new_pos]) &&
-	  info[new_pos].indic_position() != POS_PRE_M)
-      {
-	/* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
-	if (new_pos + 1 < end && is_joiner (info[new_pos + 1]))
-	  new_pos++;
-      }
-      else
-        new_pos = start; /* No move. */
-    }
-
-    if (start < new_pos && info[new_pos].indic_position () != POS_PRE_M)
-    {
-      /* Now go see if there's actually any matras... */
-      for (unsigned int i = new_pos; i > start; i--)
-	if (info[i - 1].indic_position () == POS_PRE_M)
-	{
-	  unsigned int old_pos = i - 1;
-	  if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */
-	    base--;
-
-	  hb_glyph_info_t tmp = info[old_pos];
-	  memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0]));
-	  info[new_pos] = tmp;
-
-	  /* Note: this merge_clusters() is intentionally *after* the reordering.
-	   * Indic matra reordering is special and tricky... */
-	  buffer->merge_clusters (new_pos, MIN (end, base + 1));
-
-	  new_pos--;
-	}
-    } else {
-      for (unsigned int i = start; i < base; i++)
-	if (info[i].indic_position () == POS_PRE_M) {
-	  buffer->merge_clusters (i, MIN (end, base + 1));
-	  break;
-	}
-    }
-  }
-
-
-  /*   o Reorder reph:
-   *
-   *     Reph’s original position is always at the beginning of the syllable,
-   *     (i.e. it is not reordered at the character reordering stage). However,
-   *     it will be reordered according to the basic-forms shaping results.
-   *     Possible positions for reph, depending on the script, are; after main,
-   *     before post-base consonant forms, and after post-base consonant forms.
-   */
-
-  /* Two cases:
-   *
-   * - If repha is encoded as a sequence of characters (Ra,H or Ra,H,ZWJ), then
-   *   we should only move it if the sequence ligated to the repha form.
-   *
-   * - If repha is encoded separately and in the logical position, we should only
-   *   move it if it did NOT ligate.  If it ligated, it's probably the font trying
-   *   to make it work without the reordering.
-   */
-  if (start + 1 < end &&
-      info[start].indic_position() == POS_RA_TO_BECOME_REPH &&
-      ((info[start].indic_category() == OT_Repha) ^
-       _hb_glyph_info_ligated_and_didnt_multiply (&info[start])))
-  {
-    unsigned int new_reph_pos;
-    reph_position_t reph_pos = indic_plan->config->reph_pos;
-
-    /*       1. If reph should be positioned after post-base consonant forms,
-     *          proceed to step 5.
-     */
-    if (reph_pos == REPH_POS_AFTER_POST)
-    {
-      goto reph_step_5;
-    }
-
-    /*       2. If the reph repositioning class is not after post-base: target
-     *          position is after the first explicit halant glyph between the
-     *          first post-reph consonant and last main consonant. If ZWJ or ZWNJ
-     *          are following this halant, position is moved after it. If such
-     *          position is found, this is the target position. Otherwise,
-     *          proceed to the next step.
-     *
-     *          Note: in old-implementation fonts, where classifications were
-     *          fixed in shaping engine, there was no case where reph position
-     *          will be found on this step.
-     */
-    {
-      new_reph_pos = start + 1;
-      while (new_reph_pos < base && !is_halant (info[new_reph_pos]))
-	new_reph_pos++;
-
-      if (new_reph_pos < base && is_halant (info[new_reph_pos]))
-      {
-	/* ->If ZWJ or ZWNJ are following this halant, position is moved after it. */
-	if (new_reph_pos + 1 < base && is_joiner (info[new_reph_pos + 1]))
-	  new_reph_pos++;
-	goto reph_move;
-      }
-    }
-
-    /*       3. If reph should be repositioned after the main consonant: find the
-     *          first consonant not ligated with main, or find the first
-     *          consonant that is not a potential pre-base-reordering Ra.
-     */
-    if (reph_pos == REPH_POS_AFTER_MAIN)
-    {
-      new_reph_pos = base;
-      while (new_reph_pos + 1 < end && info[new_reph_pos + 1].indic_position() <= POS_AFTER_MAIN)
-	new_reph_pos++;
-      if (new_reph_pos < end)
-        goto reph_move;
-    }
-
-    /*       4. If reph should be positioned before post-base consonant, find
-     *          first post-base classified consonant not ligated with main. If no
-     *          consonant is found, the target position should be before the
-     *          first matra, syllable modifier sign or vedic sign.
-     */
-    /* This is our take on what step 4 is trying to say (and failing, BADLY). */
-    if (reph_pos == REPH_POS_AFTER_SUB)
-    {
-      new_reph_pos = base;
-      while (new_reph_pos + 1 < end &&
-	     !( FLAG_UNSAFE (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD))))
-	new_reph_pos++;
-      if (new_reph_pos < end)
-        goto reph_move;
-    }
-
-    /*       5. If no consonant is found in steps 3 or 4, move reph to a position
-     *          immediately before the first post-base matra, syllable modifier
-     *          sign or vedic sign that has a reordering class after the intended
-     *          reph position. For example, if the reordering position for reph
-     *          is post-main, it will skip above-base matras that also have a
-     *          post-main position.
-     */
-    reph_step_5:
-    {
-      /* Copied from step 2. */
-      new_reph_pos = start + 1;
-      while (new_reph_pos < base && !is_halant (info[new_reph_pos]))
-	new_reph_pos++;
-
-      if (new_reph_pos < base && is_halant (info[new_reph_pos]))
-      {
-	/* ->If ZWJ or ZWNJ are following this halant, position is moved after it. */
-	if (new_reph_pos + 1 < base && is_joiner (info[new_reph_pos + 1]))
-	  new_reph_pos++;
-	goto reph_move;
-      }
-    }
-
-    /*       6. Otherwise, reorder reph to the end of the syllable.
-     */
-    {
-      new_reph_pos = end - 1;
-      while (new_reph_pos > start && info[new_reph_pos].indic_position() == POS_SMVD)
-	new_reph_pos--;
-
-      /*
-       * If the Reph is to be ending up after a Matra,Halant sequence,
-       * position it before that Halant so it can interact with the Matra.
-       * However, if it's a plain Consonant,Halant we shouldn't do that.
-       * Uniscribe doesn't do this.
-       * TEST: U+0930,U+094D,U+0915,U+094B,U+094D
-       */
-      if (!hb_options ().uniscribe_bug_compatible &&
-	  unlikely (is_halant (info[new_reph_pos]))) {
-	for (unsigned int i = base + 1; i < new_reph_pos; i++)
-	  if (info[i].indic_category() == OT_M) {
-	    /* Ok, got it. */
-	    new_reph_pos--;
-	  }
-      }
-      goto reph_move;
-    }
-
-    reph_move:
-    {
-      /* Move */
-      buffer->merge_clusters (start, new_reph_pos + 1);
-      hb_glyph_info_t reph = info[start];
-      memmove (&info[start], &info[start + 1], (new_reph_pos - start) * sizeof (info[0]));
-      info[new_reph_pos] = reph;
-
-      if (start < base && base <= new_reph_pos)
-	base--;
-    }
-  }
-
-
-  /*   o Reorder pre-base-reordering consonants:
-   *
-   *     If a pre-base-reordering consonant is found, reorder it according to
-   *     the following rules:
-   */
-
-  if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */
-  {
-    for (unsigned int i = base + 1; i < end; i++)
-      if ((info[i].mask & indic_plan->mask_array[PREF]) != 0)
-      {
-	/*       1. Only reorder a glyph produced by substitution during application
-	 *          of the <pref> feature. (Note that a font may shape a Ra consonant with
-	 *          the feature generally but block it in certain contexts.)
-	 */
-        /* Note: We just check that something got substituted.  We don't check that
-	 * the <pref> feature actually did it...
-	 *
-	 * Reorder pref only if it ligated. */
-	if (_hb_glyph_info_ligated_and_didnt_multiply (&info[i]))
-	{
-	  /*
-	   *       2. Try to find a target position the same way as for pre-base matra.
-	   *          If it is found, reorder pre-base consonant glyph.
-	   *
-	   *       3. If position is not found, reorder immediately before main
-	   *          consonant.
-	   */
-
-	  unsigned int new_pos = base;
-	  /* Malayalam / Tamil do not have "half" forms or explicit virama forms.
-	   * The glyphs formed by 'half' are Chillus or ligated explicit viramas.
-	   * We want to position matra after them.
-	   */
-	  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(OT_M) | FLAG (OT_H))))
-	      new_pos--;
-	  }
-
-	  if (new_pos > start && is_halant (info[new_pos - 1]))
-	  {
-	    /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
-	    if (new_pos < end && is_joiner (info[new_pos]))
-	      new_pos++;
-	  }
-
-	  {
-	    unsigned int old_pos = i;
-
-	    buffer->merge_clusters (new_pos, old_pos + 1);
-	    hb_glyph_info_t tmp = info[old_pos];
-	    memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
-	    info[new_pos] = tmp;
-
-	    if (new_pos <= base && base < old_pos)
-	      base++;
-	  }
-	}
-
-        break;
-      }
-  }
-
-
-  /* Apply 'init' to the Left Matra if it's a word start. */
-  if (info[start].indic_position () == POS_PRE_M)
-  {
-    if (!start ||
-	!(FLAG_UNSAFE (_hb_glyph_info_get_general_category (&info[start - 1])) &
-	 FLAG_RANGE (HB_UNICODE_GENERAL_CATEGORY_FORMAT, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
-      info[start].mask |= indic_plan->mask_array[INIT];
-    else
-      buffer->unsafe_to_break (start - 1, start + 1);
-  }
-
-
-  /*
-   * Finish off the clusters and go home!
-   */
-  if (hb_options ().uniscribe_bug_compatible)
-  {
-    switch ((hb_tag_t) plan->props.script)
-    {
-      case HB_SCRIPT_TAMIL:
-      case HB_SCRIPT_SINHALA:
-        break;
-
-      default:
-	/* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala.
-	 * This means, half forms are submerged into the main consonant's cluster.
-	 * This is unnecessary, and makes cursor positioning harder, but that's what
-	 * Uniscribe does. */
-	buffer->merge_clusters (start, end);
-	break;
-    }
-  }
-}
-
-
-static void
-final_reordering (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;
-
-  foreach_syllable (buffer, start, end)
-    final_reordering_syllable (plan, buffer, start, end);
-
-  HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);
-}
-
-
-static void
-clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		 hb_font_t *font HB_UNUSED,
-		 hb_buffer_t *buffer)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-    info[i].syllable() = 0;
-}
-
-
-static bool
-decompose_indic (const hb_ot_shape_normalize_context_t *c,
-		 hb_codepoint_t  ab,
-		 hb_codepoint_t *a,
-		 hb_codepoint_t *b)
-{
-  switch (ab)
-  {
-    /* Don't decompose these. */
-    case 0x0931u  : return false; /* DEVANAGARI LETTER RRA */
-    case 0x0B94u  : return false; /* TAMIL LETTER AU */
-
-
-    /*
-     * Decompose split matras that don't have Unicode decompositions.
-     */
-
-#if 0
-    /* Gujarati */
-    /* This one has no decomposition in Unicode, but needs no decomposition either. */
-    /* case 0x0AC9u  : return false; */
-
-    /* Oriya */
-    case 0x0B57u  : *a = no decomp, -> RIGHT; return true;
-#endif
-  }
-
-  if ((ab == 0x0DDAu || hb_in_range<hb_codepoint_t> (ab, 0x0DDCu, 0x0DDEu)))
-  {
-    /*
-     * Sinhala split matras...  Let the fun begin.
-     *
-     * These four characters have Unicode decompositions.  However, Uniscribe
-     * decomposes them "Khmer-style", that is, it uses the character itself to
-     * get the second half.  The first half of all four decompositions is always
-     * U+0DD9.
-     *
-     * Now, there are buggy fonts, namely, the widely used lklug.ttf, that are
-     * broken with Uniscribe.  But we need to support them.  As such, we only
-     * do the Uniscribe-style decomposition if the character is transformed into
-     * its "sec.half" form by the 'pstf' feature.  Otherwise, we fall back to
-     * Unicode decomposition.
-     *
-     * Note that we can't unconditionally use Unicode decomposition.  That would
-     * break some other fonts, that are designed to work with Uniscribe, and
-     * don't have positioning features for the Unicode-style decomposition.
-     *
-     * Argh...
-     *
-     * The Uniscribe behavior is now documented in the newly published Sinhala
-     * spec in 2012:
-     *
-     *   http://www.microsoft.com/typography/OpenTypeDev/sinhala/intro.htm#shaping
-     */
-
-    const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) c->plan->data;
-
-    hb_codepoint_t glyph;
-
-    if (hb_options ().uniscribe_bug_compatible ||
-	(c->font->get_nominal_glyph (ab, &glyph) &&
-	 indic_plan->pstf.would_substitute (&glyph, 1, c->font->face)))
-    {
-      /* Ok, safe to use Uniscribe-style decomposition. */
-      *a = 0x0DD9u;
-      *b = ab;
-      return true;
-    }
-  }
-
-  return (bool) c->unicode->decompose (ab, a, b);
-}
-
-static bool
-compose_indic (const hb_ot_shape_normalize_context_t *c,
-	       hb_codepoint_t  a,
-	       hb_codepoint_t  b,
-	       hb_codepoint_t *ab)
-{
-  /* Avoid recomposing split matras. */
-  if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a)))
-    return false;
-
-  /* Composition-exclusion exceptions that we want to recompose. */
-  if (a == 0x09AFu && b == 0x09BCu) { *ab = 0x09DFu; return true; }
-
-  return (bool) c->unicode->compose (a, b, ab);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
-{
-  collect_features_indic,
-  override_features_indic,
-  data_create_indic,
-  data_destroy_indic,
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
-  decompose_indic,
-  compose_indic,
-  setup_masks_indic,
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
-  false, /* fallback_position */
-};
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-khmer-machine.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-khmer-machine.hh
deleted file mode 100644
index 380705a5..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-khmer-machine.hh
+++ /dev/null
@@ -1,294 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-khmer-machine.rl"
-/*
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
-
-#include "hb-private.hh"
-
-
-#line 36 "hb-ot-shape-complex-khmer-machine.hh"
-static const unsigned char _khmer_syllable_machine_trans_keys[] = {
-	7u, 7u, 1u, 16u, 13u, 13u, 1u, 16u, 7u, 13u, 7u, 7u, 1u, 16u, 13u, 13u, 
-	1u, 16u, 7u, 13u, 1u, 16u, 3u, 14u, 3u, 14u, 5u, 14u, 3u, 14u, 5u, 14u, 
-	8u, 8u, 3u, 13u, 3u, 8u, 8u, 8u, 3u, 8u, 3u, 14u, 3u, 14u, 5u, 14u, 
-	3u, 14u, 5u, 14u, 8u, 8u, 3u, 13u, 3u, 8u, 8u, 8u, 3u, 8u, 3u, 14u, 
-	3u, 14u, 7u, 13u, 7u, 7u, 1u, 16u, 0
-};
-
-static const char _khmer_syllable_machine_key_spans[] = {
-	1, 16, 1, 16, 7, 1, 16, 1, 
-	16, 7, 16, 12, 12, 10, 12, 10, 
-	1, 11, 6, 1, 6, 12, 12, 10, 
-	12, 10, 1, 11, 6, 1, 6, 12, 
-	12, 7, 1, 16
-};
-
-static const short _khmer_syllable_machine_index_offsets[] = {
-	0, 2, 19, 21, 38, 46, 48, 65, 
-	67, 84, 92, 109, 122, 135, 146, 159, 
-	170, 172, 184, 191, 193, 200, 213, 226, 
-	237, 250, 261, 263, 275, 282, 284, 291, 
-	304, 317, 325, 327
-};
-
-static const char _khmer_syllable_machine_indicies[] = {
-	1, 0, 2, 2, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 2, 0, 3, 0, 4, 4, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 4, 0, 1, 0, 
-	0, 0, 0, 0, 5, 0, 7, 6, 
-	8, 8, 6, 6, 6, 6, 6, 6, 
-	6, 6, 6, 6, 6, 6, 6, 8, 
-	6, 9, 6, 10, 10, 6, 6, 6, 
-	6, 6, 6, 6, 6, 6, 6, 6, 
-	6, 6, 10, 6, 7, 6, 6, 6, 
-	6, 6, 11, 6, 4, 4, 13, 12, 
-	14, 15, 7, 16, 12, 12, 4, 4, 
-	11, 17, 12, 4, 12, 19, 18, 20, 
-	21, 1, 22, 18, 18, 18, 18, 5, 
-	23, 18, 24, 18, 21, 21, 1, 22, 
-	18, 18, 18, 18, 18, 23, 18, 21, 
-	21, 1, 22, 18, 18, 18, 18, 18, 
-	23, 18, 25, 18, 21, 21, 1, 22, 
-	18, 18, 18, 18, 18, 26, 18, 21, 
-	21, 1, 22, 18, 18, 18, 18, 18, 
-	26, 18, 27, 18, 28, 18, 29, 18, 
-	18, 22, 18, 18, 18, 18, 3, 18, 
-	30, 18, 18, 18, 18, 22, 18, 22, 
-	18, 28, 18, 18, 18, 18, 22, 18, 
-	19, 18, 21, 21, 1, 22, 18, 18, 
-	18, 18, 18, 23, 18, 32, 31, 33, 
-	33, 7, 16, 31, 31, 31, 31, 31, 
-	34, 31, 33, 33, 7, 16, 31, 31, 
-	31, 31, 31, 34, 31, 35, 31, 33, 
-	33, 7, 16, 31, 31, 31, 31, 31, 
-	36, 31, 33, 33, 7, 16, 31, 31, 
-	31, 31, 31, 36, 31, 37, 31, 38, 
-	31, 39, 31, 31, 16, 31, 31, 31, 
-	31, 9, 31, 40, 31, 31, 31, 31, 
-	16, 31, 16, 31, 38, 31, 31, 31, 
-	31, 16, 31, 13, 31, 41, 33, 7, 
-	16, 31, 31, 31, 31, 11, 34, 31, 
-	13, 31, 33, 33, 7, 16, 31, 31, 
-	31, 31, 31, 34, 31, 7, 42, 42, 
-	42, 42, 42, 11, 42, 7, 42, 10, 
-	10, 42, 42, 42, 42, 42, 42, 42, 
-	42, 42, 42, 42, 42, 42, 10, 42, 
-	0
-};
-
-static const char _khmer_syllable_machine_trans_targs[] = {
-	10, 14, 17, 20, 11, 21, 10, 24, 
-	27, 30, 31, 32, 10, 22, 33, 34, 
-	26, 35, 10, 12, 4, 0, 16, 3, 
-	13, 15, 1, 10, 18, 2, 19, 10, 
-	23, 5, 8, 25, 6, 10, 28, 7, 
-	29, 9, 10
-};
-
-static const char _khmer_syllable_machine_trans_actions[] = {
-	1, 2, 2, 0, 2, 2, 3, 2, 
-	2, 0, 2, 2, 6, 2, 0, 0, 
-	0, 0, 7, 2, 0, 0, 0, 0, 
-	2, 2, 0, 8, 0, 0, 0, 9, 
-	2, 0, 0, 2, 0, 10, 0, 0, 
-	0, 0, 11
-};
-
-static const char _khmer_syllable_machine_to_state_actions[] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 4, 0, 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 _khmer_syllable_machine_from_state_actions[] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 5, 0, 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 unsigned char _khmer_syllable_machine_eof_trans[] = {
-	1, 1, 1, 1, 1, 7, 7, 7, 
-	7, 7, 0, 19, 19, 19, 19, 19, 
-	19, 19, 19, 19, 19, 19, 32, 32, 
-	32, 32, 32, 32, 32, 32, 32, 32, 
-	32, 43, 43, 43
-};
-
-static const int khmer_syllable_machine_start = 10;
-static const int khmer_syllable_machine_first_final = 10;
-static const int khmer_syllable_machine_error = -1;
-
-static const int khmer_syllable_machine_en_main = 10;
-
-
-#line 36 "hb-ot-shape-complex-khmer-machine.rl"
-
-
-
-#line 74 "hb-ot-shape-complex-khmer-machine.rl"
-
-
-#define found_syllable(syllable_type) \
-  HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
-      info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
-    syllable_serial++; \
-    if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
-  } HB_STMT_END
-
-static void
-find_syllables (hb_buffer_t *buffer)
-{
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
-  int cs;
-  hb_glyph_info_t *info = buffer->info;
-  
-#line 181 "hb-ot-shape-complex-khmer-machine.hh"
-	{
-	cs = khmer_syllable_machine_start;
-	ts = 0;
-	te = 0;
-	act = 0;
-	}
-
-#line 95 "hb-ot-shape-complex-khmer-machine.rl"
-
-
-  p = 0;
-  pe = eof = buffer->len;
-
-  unsigned int last = 0;
-  unsigned int syllable_serial = 1;
-  
-#line 198 "hb-ot-shape-complex-khmer-machine.hh"
-	{
-	int _slen;
-	int _trans;
-	const unsigned char *_keys;
-	const char *_inds;
-	if ( p == pe )
-		goto _test_eof;
-_resume:
-	switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
-	case 5:
-#line 1 "NONE"
-	{ts = p;}
-	break;
-#line 212 "hb-ot-shape-complex-khmer-machine.hh"
-	}
-
-	_keys = _khmer_syllable_machine_trans_keys + (cs<<1);
-	_inds = _khmer_syllable_machine_indicies + _khmer_syllable_machine_index_offsets[cs];
-
-	_slen = _khmer_syllable_machine_key_spans[cs];
-	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].khmer_category()) &&
-		( info[p].khmer_category()) <= _keys[1] ?
-		( info[p].khmer_category()) - _keys[0] : _slen ];
-
-_eof_trans:
-	cs = _khmer_syllable_machine_trans_targs[_trans];
-
-	if ( _khmer_syllable_machine_trans_actions[_trans] == 0 )
-		goto _again;
-
-	switch ( _khmer_syllable_machine_trans_actions[_trans] ) {
-	case 2:
-#line 1 "NONE"
-	{te = p+1;}
-	break;
-	case 8:
-#line 68 "hb-ot-shape-complex-khmer-machine.rl"
-	{te = p+1;{ found_syllable (consonant_syllable); }}
-	break;
-	case 10:
-#line 69 "hb-ot-shape-complex-khmer-machine.rl"
-	{te = p+1;{ found_syllable (broken_cluster); }}
-	break;
-	case 6:
-#line 70 "hb-ot-shape-complex-khmer-machine.rl"
-	{te = p+1;{ found_syllable (non_khmer_cluster); }}
-	break;
-	case 7:
-#line 68 "hb-ot-shape-complex-khmer-machine.rl"
-	{te = p;p--;{ found_syllable (consonant_syllable); }}
-	break;
-	case 9:
-#line 69 "hb-ot-shape-complex-khmer-machine.rl"
-	{te = p;p--;{ found_syllable (broken_cluster); }}
-	break;
-	case 11:
-#line 70 "hb-ot-shape-complex-khmer-machine.rl"
-	{te = p;p--;{ found_syllable (non_khmer_cluster); }}
-	break;
-	case 1:
-#line 68 "hb-ot-shape-complex-khmer-machine.rl"
-	{{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
-	break;
-	case 3:
-#line 69 "hb-ot-shape-complex-khmer-machine.rl"
-	{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
-	break;
-#line 266 "hb-ot-shape-complex-khmer-machine.hh"
-	}
-
-_again:
-	switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
-	case 4:
-#line 1 "NONE"
-	{ts = 0;}
-	break;
-#line 275 "hb-ot-shape-complex-khmer-machine.hh"
-	}
-
-	if ( ++p != pe )
-		goto _resume;
-	_test_eof: {}
-	if ( p == eof )
-	{
-	if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
-		_trans = _khmer_syllable_machine_eof_trans[cs] - 1;
-		goto _eof_trans;
-	}
-	}
-
-	}
-
-#line 104 "hb-ot-shape-complex-khmer-machine.rl"
-
-}
-
-#endif /* HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-khmer-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-khmer-private.hh
deleted file mode 100644
index f90ef96..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-khmer-private.hh
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-complex-indic-private.hh"
-
-
-/* buffer var allocations */
-#define khmer_category() indic_category() /* khmer_category_t */
-#define khmer_position() indic_position() /* khmer_position_t */
-
-
-typedef indic_category_t khmer_category_t;
-typedef indic_position_t khmer_position_t;
-
-
-static inline khmer_position_t
-matra_position_khmer (khmer_position_t side)
-{
-  switch ((int) side)
-  {
-    case POS_PRE_C:
-      return POS_PRE_M;
-
-    case POS_POST_C:
-    case POS_ABOVE_C:
-    case POS_BELOW_C:
-      return POS_AFTER_POST;
-
-    default:
-      return side;
-  };
-}
-
-static inline bool
-is_consonant_or_vowel (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, CONSONANT_FLAGS | FLAG (OT_V));
-}
-
-static inline bool
-is_coeng (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, FLAG (OT_Coeng));
-}
-
-static inline void
-set_khmer_properties (hb_glyph_info_t &info)
-{
-  hb_codepoint_t u = info.codepoint;
-  unsigned int type = hb_indic_get_categories (u);
-  khmer_category_t cat = (khmer_category_t) (type & 0x7Fu);
-  khmer_position_t pos = (khmer_position_t) (type >> 8);
-
-
-  /*
-   * Re-assign category
-   */
-
-  if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CDu, 0x17D1u) ||
-		     u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */
-  {
-    /* These can occur mid-syllable (eg. before matras), even though Unicode marks them as Syllable_Modifier.
-     * https://github.com/roozbehp/unicode-data/issues/5 */
-    cat = OT_M;
-    pos = POS_ABOVE_C;
-  }
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u))) cat = OT_PLACEHOLDER;
-  else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
-
-
-  /*
-   * Re-assign position.
-   */
-
-  if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
-  {
-    pos = POS_BASE_C;
-    if (u == 0x179Au)
-      cat = OT_Ra;
-  }
-  else if (cat == OT_M)
-  {
-    pos = matra_position_khmer (pos);
-  }
-  else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) | FLAG (OT_A) | FLAG (OT_Symbol))))
-  {
-    pos = POS_SMVD;
-  }
-
-  info.khmer_category() = cat;
-  info.khmer_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-khmer.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-khmer.cc
deleted file mode 100644
index 304879d8..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-khmer.cc
+++ /dev/null
@@ -1,835 +0,0 @@
-/*
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-complex-khmer-private.hh"
-#include "hb-ot-layout-private.hh"
-
-
-/*
- * Khmer shaper.
- */
-
-struct feature_list_t {
-  hb_tag_t tag;
-  hb_ot_map_feature_flags_t flags;
-};
-
-static const feature_list_t
-khmer_features[] =
-{
-  /*
-   * Basic features.
-   * These features are applied in order, one at a time, after initial_reordering.
-   */
-  {HB_TAG('p','r','e','f'), F_NONE},
-  {HB_TAG('b','l','w','f'), F_NONE},
-  {HB_TAG('a','b','v','f'), F_NONE},
-  {HB_TAG('p','s','t','f'), F_NONE},
-  {HB_TAG('c','f','a','r'), F_NONE},
-  /*
-   * Other features.
-   * These features are applied all at once, after final_reordering.
-   * Default Bengali font in Windows for example has intermixed
-   * lookups for init,pres,abvs,blws features.
-   */
-  {HB_TAG('p','r','e','s'), F_GLOBAL},
-  {HB_TAG('a','b','v','s'), F_GLOBAL},
-  {HB_TAG('b','l','w','s'), F_GLOBAL},
-  {HB_TAG('p','s','t','s'), F_GLOBAL},
-  /* Positioning features, though we don't care about the types. */
-  {HB_TAG('d','i','s','t'), F_GLOBAL},
-  {HB_TAG('a','b','v','m'), F_GLOBAL},
-  {HB_TAG('b','l','w','m'), F_GLOBAL},
-};
-
-/*
- * Must be in the same order as the khmer_features array.
- */
-enum {
-  PREF,
-  BLWF,
-  ABVF,
-  PSTF,
-  CFAR,
-
-  _PRES,
-  _ABVS,
-  _BLWS,
-  _PSTS,
-  _DIST,
-  _ABVM,
-  _BLWM,
-
-  KHMER_NUM_FEATURES,
-  KHMER_BASIC_FEATURES = _PRES /* Don't forget to update this! */
-};
-
-static void
-setup_syllables (const hb_ot_shape_plan_t *plan,
-		 hb_font_t *font,
-		 hb_buffer_t *buffer);
-static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-		    hb_font_t *font,
-		    hb_buffer_t *buffer);
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-		  hb_font_t *font,
-		  hb_buffer_t *buffer);
-static void
-clear_syllables (const hb_ot_shape_plan_t *plan,
-		 hb_font_t *font,
-		 hb_buffer_t *buffer);
-
-static void
-collect_features_khmer (hb_ot_shape_planner_t *plan)
-{
-  hb_ot_map_builder_t *map = &plan->map;
-
-  /* Do this before any lookups have been applied. */
-  map->add_gsub_pause (setup_syllables);
-
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
-  /* The Indic specs do not require ccmp, but we apply it here since if
-   * there is a use of it, it's typically at the beginning. */
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-
-
-  unsigned int i = 0;
-  map->add_gsub_pause (initial_reordering);
-  for (; i < KHMER_BASIC_FEATURES; i++) {
-    map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-    map->add_gsub_pause (nullptr);
-  }
-  map->add_gsub_pause (final_reordering);
-  for (; i < KHMER_NUM_FEATURES; i++) {
-    map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-  }
-
-  map->add_global_bool_feature (HB_TAG('c','a','l','t'));
-  map->add_global_bool_feature (HB_TAG('c','l','i','g'));
-
-  map->add_gsub_pause (clear_syllables);
-}
-
-static void
-override_features_khmer (hb_ot_shape_planner_t *plan)
-{
-  /* Uniscribe does not apply 'kern' in Khmer. */
-  if (hb_options ().uniscribe_bug_compatible)
-  {
-    plan->map.add_feature (HB_TAG('k','e','r','n'), 0, F_GLOBAL);
-  }
-
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
-}
-
-
-struct would_substitute_feature_t
-{
-  inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
-  {
-    zero_context = zero_context_;
-    map->get_stage_lookups (0/*GSUB*/,
-			    map->get_feature_stage (0/*GSUB*/, feature_tag),
-			    &lookups, &count);
-  }
-
-  inline bool would_substitute (const hb_codepoint_t *glyphs,
-				unsigned int          glyphs_count,
-				hb_face_t            *face) const
-  {
-    for (unsigned int i = 0; i < count; i++)
-      if (hb_ot_layout_lookup_would_substitute_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context))
-	return true;
-    return false;
-  }
-
-  private:
-  const hb_ot_map_t::lookup_map_t *lookups;
-  unsigned int count;
-  bool zero_context;
-};
-
-struct khmer_shape_plan_t
-{
-  ASSERT_POD ();
-
-  inline bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
-  {
-    hb_codepoint_t glyph = virama_glyph;
-    if (unlikely (virama_glyph == (hb_codepoint_t) -1))
-    {
-      if (!font->get_nominal_glyph (0x17D2u, &glyph))
-	glyph = 0;
-      /* Technically speaking, the spec says we should apply 'locl' to virama too.
-       * Maybe one day... */
-
-      /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
-       * during shape planning...  Instead, overwrite it here.  It's safe.  Don't worry! */
-      virama_glyph = glyph;
-    }
-
-    *pglyph = glyph;
-    return glyph != 0;
-  }
-
-  mutable hb_codepoint_t virama_glyph;
-
-  would_substitute_feature_t pref;
-
-  hb_mask_t mask_array[KHMER_NUM_FEATURES];
-};
-
-static void *
-data_create_khmer (const hb_ot_shape_plan_t *plan)
-{
-  khmer_shape_plan_t *khmer_plan = (khmer_shape_plan_t *) calloc (1, sizeof (khmer_shape_plan_t));
-  if (unlikely (!khmer_plan))
-    return nullptr;
-
-  khmer_plan->virama_glyph = (hb_codepoint_t) -1;
-
-  khmer_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), true);
-
-  for (unsigned int i = 0; i < ARRAY_LENGTH (khmer_plan->mask_array); i++)
-    khmer_plan->mask_array[i] = (khmer_features[i].flags & F_GLOBAL) ?
-				 0 : plan->map.get_1_mask (khmer_features[i].tag);
-
-  return khmer_plan;
-}
-
-static void
-data_destroy_khmer (void *data)
-{
-  free (data);
-}
-
-
-enum syllable_type_t {
-  consonant_syllable,
-  broken_cluster,
-  non_khmer_cluster,
-};
-
-#include "hb-ot-shape-complex-khmer-machine.hh"
-
-static void
-setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		   hb_buffer_t              *buffer,
-		   hb_font_t                *font HB_UNUSED)
-{
-  HB_BUFFER_ALLOCATE_VAR (buffer, khmer_category);
-  HB_BUFFER_ALLOCATE_VAR (buffer, khmer_position);
-
-  /* We cannot setup masks here.  We save information about characters
-   * and setup masks later on in a pause-callback. */
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    set_khmer_properties (info[i]);
-}
-
-static void
-setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		 hb_font_t *font HB_UNUSED,
-		 hb_buffer_t *buffer)
-{
-  find_syllables (buffer);
-  foreach_syllable (buffer, start, end)
-    buffer->unsafe_to_break (start, end);
-}
-
-static int
-compare_khmer_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
-{
-  int a = pa->khmer_position();
-  int b = pb->khmer_position();
-
-  return a < b ? -1 : a == b ? 0 : +1;
-}
-
-
-/* Rules from:
- * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx */
-
-static void
-initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
-				       hb_face_t *face,
-				       hb_buffer_t *buffer,
-				       unsigned int start, unsigned int end)
-{
-  const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
-  hb_glyph_info_t *info = buffer->info;
-
-  /* 1. Khmer shaping assumes that a syllable will begin with a Cons, IndV, or Number. */
-
-  /* The first consonant is always the base. */
-  unsigned int base = start;
-  info[base].khmer_position() = POS_BASE_C;
-
-  /* Mark all subsequent consonants as below. */
-  for (unsigned int i = base + 1; i < end; i++)
-    if (is_consonant_or_vowel (info[i]))
-      info[i].khmer_position() = POS_BELOW_C;
-
-  /* Mark final consonants.  A final consonant is one appearing after a matra,
-   * like in Khmer. */
-  for (unsigned int i = base + 1; i < end; i++)
-    if (info[i].khmer_category() == OT_M) {
-      for (unsigned int j = i + 1; j < end; j++)
-        if (is_consonant_or_vowel (info[j])) {
-	  info[j].khmer_position() = POS_FINAL_C;
-	  break;
-	}
-      break;
-    }
-
-  /* Attach misc marks to previous char to move with them. */
-  {
-    khmer_position_t last_pos = POS_START;
-    for (unsigned int i = start; i < end; i++)
-    {
-      if ((FLAG_UNSAFE (info[i].khmer_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_Coeng))))
-      {
-	info[i].khmer_position() = last_pos;
-	if (unlikely (info[i].khmer_category() == OT_H &&
-		      info[i].khmer_position() == POS_PRE_M))
-	{
-	  /*
-	   * Uniscribe doesn't move the Halant with Left Matra.
-	   * TEST: U+092B,U+093F,U+094DE
-	   * We follow.  This is important for the Sinhala
-	   * U+0DDA split matra since it decomposes to U+0DD9,U+0DCA
-	   * where U+0DD9 is a left matra and U+0DCA is the virama.
-	   * We don't want to move the virama with the left matra.
-	   * TEST: U+0D9A,U+0DDA
-	   */
-	  for (unsigned int j = i; j > start; j--)
-	    if (info[j - 1].khmer_position() != POS_PRE_M) {
-	      info[i].khmer_position() = info[j - 1].khmer_position();
-	      break;
-	    }
-	}
-      } else if (info[i].khmer_position() != POS_SMVD) {
-        last_pos = (khmer_position_t) info[i].khmer_position();
-      }
-    }
-  }
-  /* For post-base consonants let them own anything before them
-   * since the last consonant or matra. */
-  {
-    unsigned int last = base;
-    for (unsigned int i = base + 1; i < end; i++)
-      if (is_consonant_or_vowel (info[i]))
-      {
-	for (unsigned int j = last + 1; j < i; j++)
-	  if (info[j].khmer_position() < POS_SMVD)
-	    info[j].khmer_position() = info[i].khmer_position();
-	last = i;
-      } else if (info[i].khmer_category() == OT_M)
-        last = i;
-  }
-
-  {
-    /* Use syllable() for sort accounting temporarily. */
-    unsigned int syllable = info[start].syllable();
-    for (unsigned int i = start; i < end; i++)
-      info[i].syllable() = i - start;
-
-    /* Sit tight, rock 'n roll! */
-    hb_stable_sort (info + start, end - start, compare_khmer_order);
-    /* Find base again */
-    base = end;
-    for (unsigned int i = start; i < end; i++)
-      if (info[i].khmer_position() == POS_BASE_C)
-      {
-	base = i;
-	break;
-      }
-
-    /* Note!  syllable() is a one-byte field. */
-    for (unsigned int i = base; i < end; i++)
-      if (info[i].syllable() != 255)
-      {
-	unsigned int max = i;
-	unsigned int j = start + info[i].syllable();
-	while (j != i)
-	{
-	  max = MAX (max, j);
-	  unsigned int next = start + info[j].syllable();
-	  info[j].syllable() = 255; /* So we don't process j later again. */
-	  j = next;
-	}
-	if (i != max)
-	  buffer->merge_clusters (i, max + 1);
-      }
-
-    /* Put syllable back in. */
-    for (unsigned int i = start; i < end; i++)
-      info[i].syllable() = syllable;
-  }
-
-  /* Setup masks now */
-
-  {
-    hb_mask_t mask;
-
-    /* Post-base */
-    mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF];
-    for (unsigned int i = base + 1; i < end; i++)
-      info[i].mask  |= mask;
-  }
-
-  unsigned int pref_len = 2;
-  if (khmer_plan->mask_array[PREF] && base + pref_len < end)
-  {
-    /* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */
-    for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
-      hb_codepoint_t glyphs[2];
-      for (unsigned int j = 0; j < pref_len; j++)
-        glyphs[j] = info[i + j].codepoint;
-      if (khmer_plan->pref.would_substitute (glyphs, pref_len, face))
-      {
-	for (unsigned int j = 0; j < pref_len; j++)
-	  info[i++].mask |= khmer_plan->mask_array[PREF];
-
-	/* Mark the subsequent stuff with 'cfar'.  Used in Khmer.
-	 * Read the feature spec.
-	 * This allows distinguishing the following cases with MS Khmer fonts:
-	 * U+1784,U+17D2,U+179A,U+17D2,U+1782
-	 * U+1784,U+17D2,U+1782,U+17D2,U+179A
-	 */
-	if (khmer_plan->mask_array[CFAR])
-	  for (; i < end; i++)
-	    info[i].mask |= khmer_plan->mask_array[CFAR];
-
-	break;
-      }
-    }
-  }
-}
-
-static void
-initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
-			     hb_face_t *face,
-			     hb_buffer_t *buffer,
-			     unsigned int start, unsigned int end)
-{
-  syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
-  switch (syllable_type)
-  {
-    case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
-    case consonant_syllable:
-     initial_reordering_consonant_syllable (plan, face, buffer, start, end);
-     break;
-
-    case non_khmer_cluster:
-      break;
-  }
-}
-
-static inline void
-insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		       hb_font_t *font,
-		       hb_buffer_t *buffer)
-{
-  /* Note: This loop is extra overhead, but should not be measurable. */
-  bool has_broken_syllables = false;
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    if ((info[i].syllable() & 0x0F) == broken_cluster)
-    {
-      has_broken_syllables = true;
-      break;
-    }
-  if (likely (!has_broken_syllables))
-    return;
-
-
-  hb_codepoint_t dottedcircle_glyph;
-  if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
-    return;
-
-  hb_glyph_info_t dottedcircle = {0};
-  dottedcircle.codepoint = 0x25CCu;
-  set_khmer_properties (dottedcircle);
-  dottedcircle.codepoint = dottedcircle_glyph;
-
-  buffer->clear_output ();
-
-  buffer->idx = 0;
-  unsigned int last_syllable = 0;
-  while (buffer->idx < buffer->len && !buffer->in_error)
-  {
-    unsigned int syllable = buffer->cur().syllable();
-    syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
-    if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
-    {
-      last_syllable = syllable;
-
-      hb_glyph_info_t ginfo = dottedcircle;
-      ginfo.cluster = buffer->cur().cluster;
-      ginfo.mask = buffer->cur().mask;
-      ginfo.syllable() = buffer->cur().syllable();
-      /* TODO Set glyph_props? */
-
-      /* Insert dottedcircle after possible Repha. */
-      while (buffer->idx < buffer->len && !buffer->in_error &&
-	     last_syllable == buffer->cur().syllable() &&
-	     buffer->cur().khmer_category() == OT_Repha)
-        buffer->next_glyph ();
-
-      buffer->output_info (ginfo);
-    }
-    else
-      buffer->next_glyph ();
-  }
-
-  buffer->swap_buffers ();
-}
-
-static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-		    hb_font_t *font,
-		    hb_buffer_t *buffer)
-{
-  insert_dotted_circles (plan, font, buffer);
-
-  foreach_syllable (buffer, start, end)
-    initial_reordering_syllable (plan, font->face, buffer, start, end);
-}
-
-static void
-final_reordering_syllable (const hb_ot_shape_plan_t *plan,
-			   hb_buffer_t *buffer,
-			   unsigned int start, unsigned int end)
-{
-  const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
-  hb_glyph_info_t *info = buffer->info;
-
-
-  /* This function relies heavily on halant glyphs.  Lots of ligation
-   * and possibly multiple substitutions happened prior to this
-   * phase, and that might have messed up our properties.  Recover
-   * from a particular case of that where we're fairly sure that a
-   * class of OT_H is desired but has been lost. */
-  if (khmer_plan->virama_glyph)
-  {
-    unsigned int virama_glyph = khmer_plan->virama_glyph;
-    for (unsigned int i = start; i < end; i++)
-      if (info[i].codepoint == virama_glyph &&
-	  _hb_glyph_info_ligated (&info[i]) &&
-	  _hb_glyph_info_multiplied (&info[i]))
-      {
-        /* This will make sure that this glyph passes is_coeng() test. */
-	info[i].khmer_category() = OT_H;
-	_hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
-      }
-  }
-
-
-  /* 4. Final reordering:
-   *
-   * After the localized forms and basic shaping forms GSUB features have been
-   * applied (see below), the shaping engine performs some final glyph
-   * reordering before applying all the remaining font features to the entire
-   * syllable.
-   */
-
-  bool try_pref = !!khmer_plan->mask_array[PREF];
-
-  /* Find base again */
-  unsigned int base;
-  for (base = start; base < end; base++)
-    if (info[base].khmer_position() >= POS_BASE_C)
-    {
-      if (try_pref && base + 1 < end)
-      {
-	for (unsigned int i = base + 1; i < end; i++)
-	  if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0)
-	  {
-	    if (!(_hb_glyph_info_substituted (&info[i]) &&
-		  _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
-	    {
-	      /* Ok, this was a 'pref' candidate but didn't form any.
-	       * Base is around here... */
-	      base = i;
-	      while (base < end && is_coeng (info[base]))
-		base++;
-	      info[base].khmer_position() = POS_BASE_C;
-
-	      try_pref = false;
-	    }
-	    break;
-	  }
-      }
-
-      if (start < base && info[base].khmer_position() > POS_BASE_C)
-        base--;
-      break;
-    }
-  if (base == end && start < base &&
-      is_one_of (info[base - 1], FLAG (OT_ZWJ)))
-    base--;
-  if (base < end)
-    while (start < base &&
-	   is_one_of (info[base], (FLAG (OT_N) | FLAG (OT_Coeng))))
-      base--;
-
-
-  /*   o Reorder matras:
-   *
-   *     If a pre-base matra character had been reordered before applying basic
-   *     features, the glyph can be moved closer to the main consonant based on
-   *     whether half-forms had been formed. Actual position for the matra is
-   *     defined as “after last standalone halant glyph, after initial matra
-   *     position and before the main consonant”. If ZWJ or ZWNJ follow this
-   *     halant, position is moved after it.
-   */
-
-  if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */
-  {
-    /* If we lost track of base, alas, position before last thingy. */
-    unsigned int new_pos = base == end ? base - 2 : base - 1;
-
-    while (new_pos > start &&
-	   !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_Coeng)))))
-      new_pos--;
-
-    /* If we found no Halant we are done.
-     * Otherwise only proceed if the Halant does
-     * not belong to the Matra itself! */
-    if (is_coeng (info[new_pos]) &&
-	info[new_pos].khmer_position() != POS_PRE_M)
-    {
-      /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
-      if (new_pos + 1 < end && is_joiner (info[new_pos + 1]))
-	new_pos++;
-    }
-    else
-      new_pos = start; /* No move. */
-
-    if (start < new_pos && info[new_pos].khmer_position () != POS_PRE_M)
-    {
-      /* Now go see if there's actually any matras... */
-      for (unsigned int i = new_pos; i > start; i--)
-	if (info[i - 1].khmer_position () == POS_PRE_M)
-	{
-	  unsigned int old_pos = i - 1;
-	  if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */
-	    base--;
-
-	  hb_glyph_info_t tmp = info[old_pos];
-	  memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0]));
-	  info[new_pos] = tmp;
-
-	  /* Note: this merge_clusters() is intentionally *after* the reordering.
-	   * Indic matra reordering is special and tricky... */
-	  buffer->merge_clusters (new_pos, MIN (end, base + 1));
-
-	  new_pos--;
-	}
-    } else {
-      for (unsigned int i = start; i < base; i++)
-	if (info[i].khmer_position () == POS_PRE_M) {
-	  buffer->merge_clusters (i, MIN (end, base + 1));
-	  break;
-	}
-    }
-  }
-
-
-  /*   o Reorder pre-base-reordering consonants:
-   *
-   *     If a pre-base-reordering consonant is found, reorder it according to
-   *     the following rules:
-   */
-
-  if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */
-  {
-    for (unsigned int i = base + 1; i < end; i++)
-      if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0)
-      {
-	/*       1. Only reorder a glyph produced by substitution during application
-	 *          of the <pref> feature. (Note that a font may shape a Ra consonant with
-	 *          the feature generally but block it in certain contexts.)
-	 */
-        /* Note: We just check that something got substituted.  We don't check that
-	 * the <pref> feature actually did it...
-	 *
-	 * Reorder pref only if it ligated. */
-	if (_hb_glyph_info_ligated_and_didnt_multiply (&info[i]))
-	{
-	  /*
-	   *       2. Try to find a target position the same way as for pre-base matra.
-	   *          If it is found, reorder pre-base consonant glyph.
-	   *
-	   *       3. If position is not found, reorder immediately before main
-	   *          consonant.
-	   */
-
-	  unsigned int new_pos = base;
-	  while (new_pos > start &&
-		 !(is_one_of (info[new_pos - 1], FLAG(OT_M) | FLAG (OT_Coeng))))
-	    new_pos--;
-
-	  /* In Khmer coeng model, a H,Ra can go *after* matras.  If it goes after a
-	   * split matra, it should be reordered to *before* the left part of such matra. */
-	  if (new_pos > start && info[new_pos - 1].khmer_category() == OT_M)
-	  {
-	    unsigned int old_pos = i;
-	    for (unsigned int j = base + 1; j < old_pos; j++)
-	      if (info[j].khmer_category() == OT_M)
-	      {
-		new_pos--;
-		break;
-	      }
-	  }
-
-	  if (new_pos > start && is_coeng (info[new_pos - 1]))
-	  {
-	    /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
-	    if (new_pos < end && is_joiner (info[new_pos]))
-	      new_pos++;
-	  }
-
-	  {
-	    unsigned int old_pos = i;
-
-	    buffer->merge_clusters (new_pos, old_pos + 1);
-	    hb_glyph_info_t tmp = info[old_pos];
-	    memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
-	    info[new_pos] = tmp;
-
-	    if (new_pos <= base && base < old_pos)
-	      base++;
-	  }
-	}
-
-        break;
-      }
-  }
-
-
-  /*
-   * Finish off the clusters and go home!
-   */
-  if (hb_options ().uniscribe_bug_compatible)
-  {
-    /* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala.
-     * This means, half forms are submerged into the main consonant's cluster.
-     * This is unnecessary, and makes cursor positioning harder, but that's what
-     * Uniscribe does. */
-    buffer->merge_clusters (start, end);
-  }
-}
-
-
-static void
-final_reordering (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;
-
-  foreach_syllable (buffer, start, end)
-    final_reordering_syllable (plan, buffer, start, end);
-
-  HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_position);
-}
-
-
-static void
-clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		 hb_font_t *font HB_UNUSED,
-		 hb_buffer_t *buffer)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-    info[i].syllable() = 0;
-}
-
-
-static bool
-decompose_khmer (const hb_ot_shape_normalize_context_t *c,
-		 hb_codepoint_t  ab,
-		 hb_codepoint_t *a,
-		 hb_codepoint_t *b)
-{
-  switch (ab)
-  {
-    /*
-     * Decompose split matras that don't have Unicode decompositions.
-     */
-
-    /* Khmer */
-    case 0x17BEu  : *a = 0x17C1u; *b= 0x17BEu; return true;
-    case 0x17BFu  : *a = 0x17C1u; *b= 0x17BFu; return true;
-    case 0x17C0u  : *a = 0x17C1u; *b= 0x17C0u; return true;
-    case 0x17C4u  : *a = 0x17C1u; *b= 0x17C4u; return true;
-    case 0x17C5u  : *a = 0x17C1u; *b= 0x17C5u; return true;
-  }
-
-  return (bool) c->unicode->decompose (ab, a, b);
-}
-
-static bool
-compose_khmer (const hb_ot_shape_normalize_context_t *c,
-	       hb_codepoint_t  a,
-	       hb_codepoint_t  b,
-	       hb_codepoint_t *ab)
-{
-  /* Avoid recomposing split matras. */
-  if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a)))
-    return false;
-
-  return (bool) c->unicode->compose (a, b, ab);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_khmer =
-{
-  collect_features_khmer,
-  override_features_khmer,
-  data_create_khmer,
-  data_destroy_khmer,
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
-  decompose_khmer,
-  compose_khmer,
-  setup_masks_khmer,
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
-  false, /* fallback_position */
-};
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh
deleted file mode 100644
index fb67dd4..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh
+++ /dev/null
@@ -1,413 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-myanmar-machine.rl"
-/*
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
-
-#include "hb-private.hh"
-
-
-#line 36 "hb-ot-shape-complex-myanmar-machine.hh"
-static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
-	1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 
-	3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, 
-	3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 5u, 29u, 
-	5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 
-	3u, 29u, 3u, 30u, 3u, 29u, 1u, 32u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
-	3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 32u, 8u, 8u, 
-	0
-};
-
-static const char _myanmar_syllable_machine_key_spans[] = {
-	32, 28, 25, 4, 25, 23, 21, 21, 
-	27, 27, 27, 27, 16, 27, 27, 27, 
-	27, 27, 28, 27, 27, 27, 27, 25, 
-	4, 25, 23, 21, 21, 27, 27, 27, 
-	27, 28, 27, 32, 27, 27, 27, 27, 
-	27, 28, 27, 27, 27, 27, 32, 1
-};
-
-static const short _myanmar_syllable_machine_index_offsets[] = {
-	0, 33, 62, 88, 93, 119, 143, 165, 
-	187, 215, 243, 271, 299, 316, 344, 372, 
-	400, 428, 456, 485, 513, 541, 569, 597, 
-	623, 628, 654, 678, 700, 722, 750, 778, 
-	806, 834, 863, 891, 924, 952, 980, 1008, 
-	1036, 1064, 1093, 1121, 1149, 1177, 1205, 1238
-};
-
-static const char _myanmar_syllable_machine_indicies[] = {
-	1, 1, 2, 3, 4, 4, 0, 5, 
-	0, 6, 1, 0, 0, 0, 0, 7, 
-	0, 8, 9, 0, 10, 11, 12, 13, 
-	14, 15, 16, 17, 18, 19, 20, 1, 
-	0, 22, 23, 24, 24, 21, 25, 21, 
-	26, 21, 21, 21, 21, 21, 21, 21, 
-	27, 21, 21, 28, 29, 30, 31, 32, 
-	33, 34, 35, 36, 37, 21, 24, 24, 
-	21, 25, 21, 21, 21, 21, 21, 21, 
-	21, 21, 21, 38, 21, 21, 21, 21, 
-	21, 21, 32, 21, 21, 21, 36, 21, 
-	24, 24, 21, 25, 21, 24, 24, 21, 
-	25, 21, 21, 21, 21, 21, 21, 21, 
-	21, 21, 21, 21, 21, 21, 21, 21, 
-	21, 32, 21, 21, 21, 36, 21, 39, 
-	21, 24, 24, 21, 25, 21, 32, 21, 
-	21, 21, 21, 21, 21, 21, 40, 21, 
-	21, 21, 21, 21, 21, 32, 21, 24, 
-	24, 21, 25, 21, 21, 21, 21, 21, 
-	21, 21, 21, 21, 40, 21, 21, 21, 
-	21, 21, 21, 32, 21, 24, 24, 21, 
-	25, 21, 21, 21, 21, 21, 21, 21, 
-	21, 21, 21, 21, 21, 21, 21, 21, 
-	21, 32, 21, 22, 21, 24, 24, 21, 
-	25, 21, 26, 21, 21, 21, 21, 21, 
-	21, 21, 41, 21, 21, 41, 21, 21, 
-	21, 32, 42, 21, 21, 36, 21, 22, 
-	21, 24, 24, 21, 25, 21, 26, 21, 
-	21, 21, 21, 21, 21, 21, 21, 21, 
-	21, 21, 21, 21, 21, 32, 21, 21, 
-	21, 36, 21, 22, 21, 24, 24, 21, 
-	25, 21, 26, 21, 21, 21, 21, 21, 
-	21, 21, 41, 21, 21, 21, 21, 21, 
-	21, 32, 42, 21, 21, 36, 21, 22, 
-	21, 24, 24, 21, 25, 21, 26, 21, 
-	21, 21, 21, 21, 21, 21, 21, 21, 
-	21, 21, 21, 21, 21, 32, 42, 21, 
-	21, 36, 21, 1, 1, 21, 21, 21, 
-	21, 21, 21, 21, 21, 21, 21, 21, 
-	21, 21, 1, 21, 22, 21, 24, 24, 
-	21, 25, 21, 26, 21, 21, 21, 21, 
-	21, 21, 21, 27, 21, 21, 28, 29, 
-	30, 31, 32, 33, 34, 35, 36, 21, 
-	22, 21, 24, 24, 21, 25, 21, 26, 
-	21, 21, 21, 21, 21, 21, 21, 43, 
-	21, 21, 21, 21, 21, 21, 32, 33, 
-	34, 35, 36, 21, 22, 21, 24, 24, 
-	21, 25, 21, 26, 21, 21, 21, 21, 
-	21, 21, 21, 21, 21, 21, 21, 21, 
-	21, 21, 32, 33, 34, 35, 36, 21, 
-	22, 21, 24, 24, 21, 25, 21, 26, 
-	21, 21, 21, 21, 21, 21, 21, 21, 
-	21, 21, 21, 21, 21, 21, 32, 33, 
-	34, 21, 36, 21, 22, 21, 24, 24, 
-	21, 25, 21, 26, 21, 21, 21, 21, 
-	21, 21, 21, 21, 21, 21, 21, 21, 
-	21, 21, 32, 21, 34, 21, 36, 21, 
-	22, 21, 24, 24, 21, 25, 21, 26, 
-	21, 21, 21, 21, 21, 21, 21, 21, 
-	21, 21, 21, 21, 21, 21, 32, 33, 
-	34, 35, 36, 43, 21, 22, 21, 24, 
-	24, 21, 25, 21, 26, 21, 21, 21, 
-	21, 21, 21, 21, 43, 21, 21, 28, 
-	21, 30, 21, 32, 33, 34, 35, 36, 
-	21, 22, 21, 24, 24, 21, 25, 21, 
-	26, 21, 21, 21, 21, 21, 21, 21, 
-	43, 21, 21, 28, 21, 21, 21, 32, 
-	33, 34, 35, 36, 21, 22, 21, 24, 
-	24, 21, 25, 21, 26, 21, 21, 21, 
-	21, 21, 21, 21, 43, 21, 21, 28, 
-	29, 30, 21, 32, 33, 34, 35, 36, 
-	21, 22, 23, 24, 24, 21, 25, 21, 
-	26, 21, 21, 21, 21, 21, 21, 21, 
-	27, 21, 21, 28, 29, 30, 31, 32, 
-	33, 34, 35, 36, 21, 3, 3, 44, 
-	5, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 45, 44, 44, 44, 44, 44, 
-	44, 14, 44, 44, 44, 18, 44, 3, 
-	3, 44, 5, 44, 3, 3, 44, 5, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	14, 44, 44, 44, 18, 44, 46, 44, 
-	3, 3, 44, 5, 44, 14, 44, 44, 
-	44, 44, 44, 44, 44, 47, 44, 44, 
-	44, 44, 44, 44, 14, 44, 3, 3, 
-	44, 5, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 47, 44, 44, 44, 44, 
-	44, 44, 14, 44, 3, 3, 44, 5, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	14, 44, 2, 44, 3, 3, 44, 5, 
-	44, 6, 44, 44, 44, 44, 44, 44, 
-	44, 48, 44, 44, 48, 44, 44, 44, 
-	14, 49, 44, 44, 18, 44, 2, 44, 
-	3, 3, 44, 5, 44, 6, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 14, 44, 44, 44, 
-	18, 44, 2, 44, 3, 3, 44, 5, 
-	44, 6, 44, 44, 44, 44, 44, 44, 
-	44, 48, 44, 44, 44, 44, 44, 44, 
-	14, 49, 44, 44, 18, 44, 2, 44, 
-	3, 3, 44, 5, 44, 6, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 14, 49, 44, 44, 
-	18, 44, 22, 23, 24, 24, 21, 25, 
-	21, 26, 21, 21, 21, 21, 21, 21, 
-	21, 50, 21, 21, 28, 29, 30, 31, 
-	32, 33, 34, 35, 36, 37, 21, 22, 
-	51, 24, 24, 21, 25, 21, 26, 21, 
-	21, 21, 21, 21, 21, 21, 27, 21, 
-	21, 28, 29, 30, 31, 32, 33, 34, 
-	35, 36, 21, 1, 1, 2, 3, 3, 
-	3, 44, 5, 44, 6, 1, 44, 44, 
-	44, 44, 1, 44, 8, 44, 44, 10, 
-	11, 12, 13, 14, 15, 16, 17, 18, 
-	19, 44, 1, 44, 2, 44, 3, 3, 
-	44, 5, 44, 6, 44, 44, 44, 44, 
-	44, 44, 44, 8, 44, 44, 10, 11, 
-	12, 13, 14, 15, 16, 17, 18, 44, 
-	2, 44, 3, 3, 44, 5, 44, 6, 
-	44, 44, 44, 44, 44, 44, 44, 52, 
-	44, 44, 44, 44, 44, 44, 14, 15, 
-	16, 17, 18, 44, 2, 44, 3, 3, 
-	44, 5, 44, 6, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 14, 15, 16, 17, 18, 44, 
-	2, 44, 3, 3, 44, 5, 44, 6, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 14, 15, 
-	16, 44, 18, 44, 2, 44, 3, 3, 
-	44, 5, 44, 6, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 14, 44, 16, 44, 18, 44, 
-	2, 44, 3, 3, 44, 5, 44, 6, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 14, 15, 
-	16, 17, 18, 52, 44, 2, 44, 3, 
-	3, 44, 5, 44, 6, 44, 44, 44, 
-	44, 44, 44, 44, 52, 44, 44, 10, 
-	44, 12, 44, 14, 15, 16, 17, 18, 
-	44, 2, 44, 3, 3, 44, 5, 44, 
-	6, 44, 44, 44, 44, 44, 44, 44, 
-	52, 44, 44, 10, 44, 44, 44, 14, 
-	15, 16, 17, 18, 44, 2, 44, 3, 
-	3, 44, 5, 44, 6, 44, 44, 44, 
-	44, 44, 44, 44, 52, 44, 44, 10, 
-	11, 12, 44, 14, 15, 16, 17, 18, 
-	44, 2, 3, 3, 3, 44, 5, 44, 
-	6, 44, 44, 44, 44, 44, 44, 44, 
-	8, 44, 44, 10, 11, 12, 13, 14, 
-	15, 16, 17, 18, 44, 1, 1, 53, 
-	53, 53, 53, 53, 53, 53, 53, 1, 
-	53, 53, 53, 53, 1, 53, 53, 53, 
-	53, 53, 53, 53, 53, 53, 53, 53, 
-	53, 53, 53, 53, 1, 53, 54, 53, 
-	0
-};
-
-static const char _myanmar_syllable_machine_trans_targs[] = {
-	0, 1, 23, 0, 0, 24, 30, 33, 
-	36, 46, 37, 42, 43, 44, 26, 39, 
-	40, 41, 29, 45, 47, 0, 2, 12, 
-	0, 3, 9, 13, 14, 19, 20, 21, 
-	5, 16, 17, 18, 8, 22, 4, 6, 
-	7, 10, 11, 15, 0, 25, 27, 28, 
-	31, 32, 34, 35, 38, 0, 0
-};
-
-static const char _myanmar_syllable_machine_trans_actions[] = {
-	3, 0, 0, 4, 5, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 6, 0, 0, 
-	7, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 8, 0, 0, 0, 
-	0, 0, 0, 0, 0, 9, 10
-};
-
-static const char _myanmar_syllable_machine_to_state_actions[] = {
-	1, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const char _myanmar_syllable_machine_from_state_actions[] = {
-	2, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const short _myanmar_syllable_machine_eof_trans[] = {
-	0, 22, 22, 22, 22, 22, 22, 22, 
-	22, 22, 22, 22, 22, 22, 22, 22, 
-	22, 22, 22, 22, 22, 22, 22, 45, 
-	45, 45, 45, 45, 45, 45, 45, 45, 
-	45, 22, 22, 45, 45, 45, 45, 45, 
-	45, 45, 45, 45, 45, 45, 54, 54
-};
-
-static const int myanmar_syllable_machine_start = 0;
-static const int myanmar_syllable_machine_first_final = 0;
-static const int myanmar_syllable_machine_error = -1;
-
-static const int myanmar_syllable_machine_en_main = 0;
-
-
-#line 36 "hb-ot-shape-complex-myanmar-machine.rl"
-
-
-
-#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
-
-
-#define found_syllable(syllable_type) \
-  HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
-      info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
-    syllable_serial++; \
-    if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
-  } HB_STMT_END
-
-static void
-find_syllables (hb_buffer_t *buffer)
-{
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
-  int cs;
-  hb_glyph_info_t *info = buffer->info;
-  
-#line 302 "hb-ot-shape-complex-myanmar-machine.hh"
-	{
-	cs = myanmar_syllable_machine_start;
-	ts = 0;
-	te = 0;
-	act = 0;
-	}
-
-#line 115 "hb-ot-shape-complex-myanmar-machine.rl"
-
-
-  p = 0;
-  pe = eof = buffer->len;
-
-  unsigned int last = 0;
-  unsigned int syllable_serial = 1;
-  
-#line 319 "hb-ot-shape-complex-myanmar-machine.hh"
-	{
-	int _slen;
-	int _trans;
-	const unsigned char *_keys;
-	const char *_inds;
-	if ( p == pe )
-		goto _test_eof;
-_resume:
-	switch ( _myanmar_syllable_machine_from_state_actions[cs] ) {
-	case 2:
-#line 1 "NONE"
-	{ts = p;}
-	break;
-#line 333 "hb-ot-shape-complex-myanmar-machine.hh"
-	}
-
-	_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
-	_inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs];
-
-	_slen = _myanmar_syllable_machine_key_spans[cs];
-	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) &&
-		( info[p].myanmar_category()) <= _keys[1] ?
-		( info[p].myanmar_category()) - _keys[0] : _slen ];
-
-_eof_trans:
-	cs = _myanmar_syllable_machine_trans_targs[_trans];
-
-	if ( _myanmar_syllable_machine_trans_actions[_trans] == 0 )
-		goto _again;
-
-	switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
-	case 7:
-#line 86 "hb-ot-shape-complex-myanmar-machine.rl"
-	{te = p+1;{ found_syllable (consonant_syllable); }}
-	break;
-	case 5:
-#line 87 "hb-ot-shape-complex-myanmar-machine.rl"
-	{te = p+1;{ found_syllable (non_myanmar_cluster); }}
-	break;
-	case 10:
-#line 88 "hb-ot-shape-complex-myanmar-machine.rl"
-	{te = p+1;{ found_syllable (punctuation_cluster); }}
-	break;
-	case 4:
-#line 89 "hb-ot-shape-complex-myanmar-machine.rl"
-	{te = p+1;{ found_syllable (broken_cluster); }}
-	break;
-	case 3:
-#line 90 "hb-ot-shape-complex-myanmar-machine.rl"
-	{te = p+1;{ found_syllable (non_myanmar_cluster); }}
-	break;
-	case 6:
-#line 86 "hb-ot-shape-complex-myanmar-machine.rl"
-	{te = p;p--;{ found_syllable (consonant_syllable); }}
-	break;
-	case 8:
-#line 89 "hb-ot-shape-complex-myanmar-machine.rl"
-	{te = p;p--;{ found_syllable (broken_cluster); }}
-	break;
-	case 9:
-#line 90 "hb-ot-shape-complex-myanmar-machine.rl"
-	{te = p;p--;{ found_syllable (non_myanmar_cluster); }}
-	break;
-#line 383 "hb-ot-shape-complex-myanmar-machine.hh"
-	}
-
-_again:
-	switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
-	case 1:
-#line 1 "NONE"
-	{ts = 0;}
-	break;
-#line 392 "hb-ot-shape-complex-myanmar-machine.hh"
-	}
-
-	if ( ++p != pe )
-		goto _resume;
-	_test_eof: {}
-	if ( p == eof )
-	{
-	if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) {
-		_trans = _myanmar_syllable_machine_eof_trans[cs] - 1;
-		goto _eof_trans;
-	}
-	}
-
-	}
-
-#line 124 "hb-ot-shape-complex-myanmar-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-private.hh
deleted file mode 100644
index 04f81bd1..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-private.hh
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-complex-indic-private.hh"
-
-
-/* buffer var allocations */
-#define myanmar_category() indic_category() /* myanmar_category_t */
-#define myanmar_position() indic_position() /* myanmar_position_t */
-
-
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum myanmar_category_t {
-  OT_As  = 18,  /* Asat */
-  OT_D0  = 20, /* Digit zero */
-  OT_DB  = OT_N, /* Dot below */
-  OT_GB  = OT_PLACEHOLDER,
-  OT_MH  = 21, /* Various consonant medial types */
-  OT_MR  = 22, /* Various consonant medial types */
-  OT_MW  = 23, /* Various consonant medial types */
-  OT_MY  = 24, /* Various consonant medial types */
-  OT_PT  = 25, /* Pwo and other tones */
-  OT_VAbv = 26,
-  OT_VBlw = 27,
-  OT_VPre = 28,
-  OT_VPst = 29,
-  OT_VS   = 30, /* Variation selectors */
-  OT_P    = 31, /* Punctuation */
-  OT_D    = 32, /* Digits except zero */
-};
-
-
-static inline void
-set_myanmar_properties (hb_glyph_info_t &info)
-{
-  hb_codepoint_t u = info.codepoint;
-  unsigned int type = hb_indic_get_categories (u);
-  indic_category_t cat = (indic_category_t) (type & 0x7Fu);
-  indic_position_t pos = (indic_position_t) (type >> 8);
-
-  /* Myanmar
-   * http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm#analyze
-   */
-  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)))
-    cat = (indic_category_t) OT_VS;
-
-  switch (u)
-  {
-    case 0x104Eu:
-      cat = (indic_category_t) OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
-      break;
-
-    case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
-    case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
-    case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
-    case 0x25FEu:
-      cat = (indic_category_t) OT_GB;
-      break;
-
-    case 0x1004u: case 0x101Bu: case 0x105Au:
-      cat = (indic_category_t) OT_Ra;
-      break;
-
-    case 0x1032u: case 0x1036u:
-      cat = (indic_category_t) OT_A;
-      break;
-
-    case 0x1039u:
-      cat = (indic_category_t) OT_H;
-      break;
-
-    case 0x103Au:
-      cat = (indic_category_t) OT_As;
-      break;
-
-    case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
-    case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
-    case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
-    case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
-    case 0x1097u: case 0x1098u: case 0x1099u:
-      cat = (indic_category_t) OT_D;
-      break;
-
-    case 0x1040u:
-      cat = (indic_category_t) OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
-      break;
-
-    case 0x103Eu: case 0x1060u:
-      cat = (indic_category_t) OT_MH;
-      break;
-
-    case 0x103Cu:
-      cat = (indic_category_t) OT_MR;
-      break;
-
-    case 0x103Du: case 0x1082u:
-      cat = (indic_category_t) OT_MW;
-      break;
-
-    case 0x103Bu: case 0x105Eu: case 0x105Fu:
-      cat = (indic_category_t) OT_MY;
-      break;
-
-    case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
-    case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
-      cat = (indic_category_t) OT_PT;
-      break;
-
-    case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
-    case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
-    case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
-      cat = (indic_category_t) OT_SM;
-      break;
-
-    case 0x104Au: case 0x104Bu:
-      cat = (indic_category_t) OT_P;
-      break;
-
-    case 0xAA74u: case 0xAA75u: case 0xAA76u:
-      /* https://github.com/roozbehp/unicode-data/issues/3 */
-      cat = (indic_category_t) OT_C;
-      break;
-  }
-
-  if (cat == OT_M)
-  {
-    switch ((int) pos)
-    {
-      case POS_PRE_C:	cat = (indic_category_t) OT_VPre;
-			pos = POS_PRE_M;                  break;
-      case POS_ABOVE_C:	cat = (indic_category_t) OT_VAbv; break;
-      case POS_BELOW_C:	cat = (indic_category_t) OT_VBlw; break;
-      case POS_POST_C:	cat = (indic_category_t) OT_VPst; break;
-    }
-  }
-
-  info.myanmar_category() = (myanmar_category_t) cat;
-  info.myanmar_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc
deleted file mode 100644
index 3c57bc1..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Copyright © 2011,2012,2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-complex-myanmar-private.hh"
-
-
-/*
- * Myanmar shaper.
- */
-
-static const hb_tag_t
-basic_features[] =
-{
-  /*
-   * Basic features.
-   * These features are applied in order, one at a time, after initial_reordering.
-   */
-  HB_TAG('r','p','h','f'),
-  HB_TAG('p','r','e','f'),
-  HB_TAG('b','l','w','f'),
-  HB_TAG('p','s','t','f'),
-};
-static const hb_tag_t
-other_features[] =
-{
-  /*
-   * Other features.
-   * These features are applied all at once, after final_reordering.
-   */
-  HB_TAG('p','r','e','s'),
-  HB_TAG('a','b','v','s'),
-  HB_TAG('b','l','w','s'),
-  HB_TAG('p','s','t','s'),
-  /* Positioning features, though we don't care about the types. */
-  HB_TAG('d','i','s','t'),
-  /* Pre-release version of Windows 8 Myanmar font had abvm,blwm
-   * features.  The released Windows 8 version of the font (as well
-   * as the released spec) used 'mark' instead.  The Windows 8
-   * shaper however didn't apply 'mark' but did apply 'mkmk'.
-   * Perhaps it applied abvm/blwm.  This was fixed in a Windows 8
-   * update, so now it applies mark/mkmk.  We are guessing that
-   * it still applies abvm/blwm too.
-   */
-  HB_TAG('a','b','v','m'),
-  HB_TAG('b','l','w','m'),
-};
-
-static void
-setup_syllables (const hb_ot_shape_plan_t *plan,
-		 hb_font_t *font,
-		 hb_buffer_t *buffer);
-static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-		    hb_font_t *font,
-		    hb_buffer_t *buffer);
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-		  hb_font_t *font,
-		  hb_buffer_t *buffer);
-
-static void
-collect_features_myanmar (hb_ot_shape_planner_t *plan)
-{
-  hb_ot_map_builder_t *map = &plan->map;
-
-  /* Do this before any lookups have been applied. */
-  map->add_gsub_pause (setup_syllables);
-
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
-  /* The Indic specs do not require ccmp, but we apply it here since if
-   * there is a use of it, it's typically at the beginning. */
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-
-
-  map->add_gsub_pause (initial_reordering);
-  for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
-  {
-    map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
-    map->add_gsub_pause (nullptr);
-  }
-  map->add_gsub_pause (final_reordering);
-  for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
-    map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
-}
-
-static void
-override_features_myanmar (hb_ot_shape_planner_t *plan)
-{
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
-}
-
-
-enum syllable_type_t {
-  consonant_syllable,
-  punctuation_cluster,
-  broken_cluster,
-  non_myanmar_cluster,
-};
-
-#include "hb-ot-shape-complex-myanmar-machine.hh"
-
-
-static void
-setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		   hb_buffer_t              *buffer,
-		   hb_font_t                *font HB_UNUSED)
-{
-  HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_category);
-  HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_position);
-
-  /* We cannot setup masks here.  We save information about characters
-   * and setup masks later on in a pause-callback. */
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    set_myanmar_properties (info[i]);
-}
-
-static void
-setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		 hb_font_t *font HB_UNUSED,
-		 hb_buffer_t *buffer)
-{
-  find_syllables (buffer);
-  foreach_syllable (buffer, start, end)
-    buffer->unsafe_to_break (start, end);
-}
-
-static int
-compare_myanmar_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
-{
-  int a = pa->myanmar_position();
-  int b = pb->myanmar_position();
-
-  return a < b ? -1 : a == b ? 0 : +1;
-}
-
-
-/* Rules from:
- * http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm */
-
-static void
-initial_reordering_consonant_syllable (hb_buffer_t *buffer,
-				       unsigned int start, unsigned int end)
-{
-  hb_glyph_info_t *info = buffer->info;
-
-  unsigned int base = end;
-  bool has_reph = false;
-
-  {
-    unsigned int limit = start;
-    if (start + 3 <= end &&
-	info[start  ].myanmar_category() == OT_Ra &&
-	info[start+1].myanmar_category() == OT_As &&
-	info[start+2].myanmar_category() == OT_H)
-    {
-      limit += 3;
-      base = start;
-      has_reph = true;
-    }
-
-    {
-      if (!has_reph)
-	base = limit;
-
-      for (unsigned int i = limit; i < end; i++)
-	if (is_consonant (info[i]))
-	{
-	  base = i;
-	  break;
-	}
-    }
-  }
-
-  /* Reorder! */
-  {
-    unsigned int i = start;
-    for (; i < start + (has_reph ? 3 : 0); i++)
-      info[i].myanmar_position() = POS_AFTER_MAIN;
-    for (; i < base; i++)
-      info[i].myanmar_position() = POS_PRE_C;
-    if (i < end)
-    {
-      info[i].myanmar_position() = POS_BASE_C;
-      i++;
-    }
-    indic_position_t pos = POS_AFTER_MAIN;
-    /* The following loop may be ugly, but it implements all of
-     * Myanmar reordering! */
-    for (; i < end; i++)
-    {
-      if (info[i].myanmar_category() == OT_MR) /* Pre-base reordering */
-      {
-	info[i].myanmar_position() = POS_PRE_C;
-	continue;
-      }
-      if (info[i].myanmar_position() < POS_BASE_C) /* Left matra */
-      {
-	continue;
-      }
-      if (info[i].myanmar_category() == OT_VS)
-      {
-	info[i].myanmar_position() = info[i - 1].myanmar_position();
-	continue;
-      }
-
-      if (pos == POS_AFTER_MAIN && info[i].myanmar_category() == OT_VBlw)
-      {
-	pos = POS_BELOW_C;
-	info[i].myanmar_position() = pos;
-	continue;
-      }
-
-      if (pos == POS_BELOW_C && info[i].myanmar_category() == OT_A)
-      {
-	info[i].myanmar_position() = POS_BEFORE_SUB;
-	continue;
-      }
-      if (pos == POS_BELOW_C && info[i].myanmar_category() == OT_VBlw)
-      {
-	info[i].myanmar_position() = pos;
-	continue;
-      }
-      if (pos == POS_BELOW_C && info[i].myanmar_category() != OT_A)
-      {
-        pos = POS_AFTER_SUB;
-	info[i].myanmar_position() = pos;
-	continue;
-      }
-      info[i].myanmar_position() = pos;
-    }
-  }
-
-  /* Sit tight, rock 'n roll! */
-  buffer->sort (start, end, compare_myanmar_order);
-}
-
-static void
-initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
-			     hb_face_t *face,
-			     hb_buffer_t *buffer,
-			     unsigned int start, unsigned int end)
-{
-  syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
-  switch (syllable_type) {
-
-    case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
-    case consonant_syllable:
-      initial_reordering_consonant_syllable  (buffer, start, end);
-      break;
-
-    case punctuation_cluster:
-    case non_myanmar_cluster:
-      break;
-  }
-}
-
-static inline void
-insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		       hb_font_t *font,
-		       hb_buffer_t *buffer)
-{
-  /* Note: This loop is extra overhead, but should not be measurable. */
-  bool has_broken_syllables = false;
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    if ((info[i].syllable() & 0x0F) == broken_cluster)
-    {
-      has_broken_syllables = true;
-      break;
-    }
-  if (likely (!has_broken_syllables))
-    return;
-
-
-  hb_codepoint_t dottedcircle_glyph;
-  if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
-    return;
-
-  hb_glyph_info_t dottedcircle = {0};
-  dottedcircle.codepoint = 0x25CCu;
-  set_myanmar_properties (dottedcircle);
-  dottedcircle.codepoint = dottedcircle_glyph;
-
-  buffer->clear_output ();
-
-  buffer->idx = 0;
-  unsigned int last_syllable = 0;
-  while (buffer->idx < buffer->len && !buffer->in_error)
-  {
-    unsigned int syllable = buffer->cur().syllable();
-    syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
-    if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
-    {
-      last_syllable = syllable;
-
-      hb_glyph_info_t ginfo = dottedcircle;
-      ginfo.cluster = buffer->cur().cluster;
-      ginfo.mask = buffer->cur().mask;
-      ginfo.syllable() = buffer->cur().syllable();
-
-      buffer->output_info (ginfo);
-    }
-    else
-      buffer->next_glyph ();
-  }
-
-  buffer->swap_buffers ();
-}
-
-static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-		    hb_font_t *font,
-		    hb_buffer_t *buffer)
-{
-  insert_dotted_circles (plan, font, buffer);
-
-  foreach_syllable (buffer, start, end)
-    initial_reordering_syllable (plan, font->face, buffer, start, end);
-}
-
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-		  hb_font_t *font HB_UNUSED,
-		  hb_buffer_t *buffer)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  /* Zero syllables now... */
-  for (unsigned int i = 0; i < count; i++)
-    info[i].syllable() = 0;
-
-  HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position);
-}
-
-
-/* Uniscribe seems to have a shaper for 'mymr' that is like the
- * generic shaper, except that it zeros mark advances GDEF_LATE. */
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old =
-{
-  nullptr, /* collect_features */
-  nullptr, /* override_features */
-  nullptr, /* data_create */
-  nullptr, /* data_destroy */
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
-  nullptr, /* decompose */
-  nullptr, /* compose */
-  nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-  true, /* fallback_position */
-};
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
-{
-  collect_features_myanmar,
-  override_features_myanmar,
-  nullptr, /* data_create */
-  nullptr, /* data_destroy */
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
-  nullptr, /* decompose */
-  nullptr, /* compose */
-  setup_masks_myanmar,
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
-  false, /* fallback_position */
-};
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
deleted file mode 100644
index 08b6fe96..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright © 2010,2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-private.hh"
-#include "hb-ot-shape-normalize-private.hh"
-
-
-
-/* buffer var allocations, used by complex shapers */
-#define complex_var_u8_0()	var2.u8[2]
-#define complex_var_u8_1()	var2.u8[3]
-
-
-#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32
-
-enum hb_ot_shape_zero_width_marks_type_t {
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
-};
-
-
-/* Master OT shaper list */
-#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
-  HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \
-  HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (khmer) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_old) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (tibetan) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (use) \
-  /* ^--- Add new shapers here */
-
-
-struct hb_ot_complex_shaper_t
-{
-  /* collect_features()
-   * Called during shape_plan().
-   * Shapers should use plan->map to add their features and callbacks.
-   * May be nullptr.
-   */
-  void (*collect_features) (hb_ot_shape_planner_t *plan);
-
-  /* override_features()
-   * Called during shape_plan().
-   * Shapers should use plan->map to override features and add callbacks after
-   * common features are added.
-   * May be nullptr.
-   */
-  void (*override_features) (hb_ot_shape_planner_t *plan);
-
-
-  /* data_create()
-   * Called at the end of shape_plan().
-   * Whatever shapers return will be accessible through plan->data later.
-   * If nullptr is returned, means a plan failure.
-   */
-  void *(*data_create) (const hb_ot_shape_plan_t *plan);
-
-  /* data_destroy()
-   * Called when the shape_plan is being destroyed.
-   * plan->data is passed here for destruction.
-   * If nullptr is returned, means a plan failure.
-   * May be nullptr.
-   */
-  void (*data_destroy) (void *data);
-
-
-  /* preprocess_text()
-   * Called during shape().
-   * Shapers can use to modify text before shaping starts.
-   * May be nullptr.
-   */
-  void (*preprocess_text) (const hb_ot_shape_plan_t *plan,
-			   hb_buffer_t              *buffer,
-			   hb_font_t                *font);
-
-  /* postprocess_glyphs()
-   * Called during shape().
-   * Shapers can use to modify glyphs after shaping ends.
-   * May be nullptr.
-   */
-  void (*postprocess_glyphs) (const hb_ot_shape_plan_t *plan,
-			      hb_buffer_t              *buffer,
-			      hb_font_t                *font);
-
-
-  hb_ot_shape_normalization_mode_t normalization_preference;
-
-  /* decompose()
-   * Called during shape()'s normalization.
-   * May be nullptr.
-   */
-  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
-		     hb_codepoint_t  ab,
-		     hb_codepoint_t *a,
-		     hb_codepoint_t *b);
-
-  /* compose()
-   * Called during shape()'s normalization.
-   * May be nullptr.
-   */
-  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
-		   hb_codepoint_t  a,
-		   hb_codepoint_t  b,
-		   hb_codepoint_t *ab);
-
-  /* setup_masks()
-   * Called during shape().
-   * Shapers should use map to get feature masks and set on buffer.
-   * Shapers may NOT modify characters.
-   * May be nullptr.
-   */
-  void (*setup_masks) (const hb_ot_shape_plan_t *plan,
-		       hb_buffer_t              *buffer,
-		       hb_font_t                *font);
-
-  /* disable_otl()
-   * Called during shape().
-   * If set and returns true, GDEF/GSUB/GPOS of the font are ignored
-   * and fallback operations used.
-   * May be nullptr.
-   */
-  bool (*disable_otl) (const hb_ot_shape_plan_t *plan);
-
-  /* reorder_marks()
-   * Called during shape().
-   * Shapers can use to modify ordering of combining marks.
-   * May be nullptr.
-   */
-  void (*reorder_marks) (const hb_ot_shape_plan_t *plan,
-			 hb_buffer_t              *buffer,
-			 unsigned int              start,
-			 unsigned int              end);
-
-  hb_ot_shape_zero_width_marks_type_t zero_width_marks;
-
-  bool fallback_position;
-};
-
-#define HB_COMPLEX_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_complex_shaper_t _hb_ot_complex_shaper_##name;
-HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
-#undef HB_COMPLEX_SHAPER_IMPLEMENT
-
-
-static inline const hb_ot_complex_shaper_t *
-hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
-{
-  switch ((hb_tag_t) planner->props.script)
-  {
-    default:
-      return &_hb_ot_complex_shaper_default;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_ARABIC:
-
-    /* Unicode-3.0 additions */
-    case HB_SCRIPT_MONGOLIAN:
-    case HB_SCRIPT_SYRIAC:
-
-    /* Unicode-5.0 additions */
-    case HB_SCRIPT_NKO:
-    case HB_SCRIPT_PHAGS_PA:
-
-    /* Unicode-6.0 additions */
-    case HB_SCRIPT_MANDAIC:
-
-    /* Unicode-7.0 additions */
-    case HB_SCRIPT_MANICHAEAN:
-    case HB_SCRIPT_PSALTER_PAHLAVI:
-
-    /* Unicode-9.0 additions */
-    case HB_SCRIPT_ADLAM:
-
-      /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
-       * This is because we do fallback shaping for Arabic script (and not others).
-       * But note that Arabic shaping is applicable only to horizontal layout; for
-       * vertical text, just use the generic shaper instead. */
-      if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
-	   planner->props.script == HB_SCRIPT_ARABIC) &&
-	  HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
-	return &_hb_ot_complex_shaper_arabic;
-      else
-	return &_hb_ot_complex_shaper_default;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_THAI:
-    case HB_SCRIPT_LAO:
-
-      return &_hb_ot_complex_shaper_thai;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_HANGUL:
-
-      return &_hb_ot_complex_shaper_hangul;
-
-
-    /* Unicode-2.0 additions */
-    case HB_SCRIPT_TIBETAN:
-
-      return &_hb_ot_complex_shaper_tibetan;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_HEBREW:
-
-      return &_hb_ot_complex_shaper_hebrew;
-
-
-    /* ^--- Add new shapers here */
-
-#if 0
-    /* Unicode-4.1 additions */
-    case HB_SCRIPT_NEW_TAI_LUE:
-#endif
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_BENGALI:
-    case HB_SCRIPT_DEVANAGARI:
-    case HB_SCRIPT_GUJARATI:
-    case HB_SCRIPT_GURMUKHI:
-    case HB_SCRIPT_KANNADA:
-    case HB_SCRIPT_MALAYALAM:
-    case HB_SCRIPT_ORIYA:
-    case HB_SCRIPT_TAMIL:
-    case HB_SCRIPT_TELUGU:
-
-    /* Unicode-3.0 additions */
-    case HB_SCRIPT_SINHALA:
-
-      /* If the designer designed the font for the 'DFLT' script,
-       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
-       * Otherwise, use the specific shaper.
-       * Note that for some simple scripts, there may not be *any*
-       * GSUB/GPOS needed, so there may be no scripts found! */
-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
-	  planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
-	return &_hb_ot_complex_shaper_default;
-      else
-	return &_hb_ot_complex_shaper_indic;
-
-    case HB_SCRIPT_KHMER:
-      /* A number of Khmer fonts in the wild don't have a 'pref' feature,
-       * and as such won't shape properly via the Indic shaper;
-       * however, they typically have 'liga' / 'clig' features that implement
-       * the necessary "reordering" by means of ligature substitutions.
-       * So we send such pref-less fonts through the generic shaper instead. */
-      if (planner->map.found_script[0] &&
-	  hb_ot_layout_language_find_feature (planner->face, HB_OT_TAG_GSUB,
-					      planner->map.script_index[0],
-					      planner->map.language_index[0],
-					      HB_TAG ('p','r','e','f'),
-					      nullptr))
-	return &_hb_ot_complex_shaper_khmer;
-      else
-	return &_hb_ot_complex_shaper_default;
-
-    case HB_SCRIPT_MYANMAR:
-      if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','2'))
-	return &_hb_ot_complex_shaper_myanmar;
-      else if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
-	return &_hb_ot_complex_shaper_myanmar_old;
-      else
-	return &_hb_ot_complex_shaper_default;
-
-
-    /* Unicode-2.0 additions */
-    //case HB_SCRIPT_TIBETAN:
-
-    /* Unicode-3.0 additions */
-    //case HB_SCRIPT_MONGOLIAN:
-    //case HB_SCRIPT_SINHALA:
-
-    /* Unicode-3.2 additions */
-    case HB_SCRIPT_BUHID:
-    case HB_SCRIPT_HANUNOO:
-    case HB_SCRIPT_TAGALOG:
-    case HB_SCRIPT_TAGBANWA:
-
-    /* Unicode-4.0 additions */
-    case HB_SCRIPT_LIMBU:
-    case HB_SCRIPT_TAI_LE:
-
-    /* Unicode-4.1 additions */
-    case HB_SCRIPT_BUGINESE:
-    case HB_SCRIPT_KHAROSHTHI:
-    case HB_SCRIPT_SYLOTI_NAGRI:
-    case HB_SCRIPT_TIFINAGH:
-
-    /* Unicode-5.0 additions */
-    case HB_SCRIPT_BALINESE:
-    //case HB_SCRIPT_NKO:
-    //case HB_SCRIPT_PHAGS_PA:
-
-    /* Unicode-5.1 additions */
-    case HB_SCRIPT_CHAM:
-    case HB_SCRIPT_KAYAH_LI:
-    case HB_SCRIPT_LEPCHA:
-    case HB_SCRIPT_REJANG:
-    case HB_SCRIPT_SAURASHTRA:
-    case HB_SCRIPT_SUNDANESE:
-
-    /* Unicode-5.2 additions */
-    case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS:
-    case HB_SCRIPT_JAVANESE:
-    case HB_SCRIPT_KAITHI:
-    case HB_SCRIPT_MEETEI_MAYEK:
-    case HB_SCRIPT_TAI_THAM:
-    case HB_SCRIPT_TAI_VIET:
-
-    /* Unicode-6.0 additions */
-    case HB_SCRIPT_BATAK:
-    case HB_SCRIPT_BRAHMI:
-    //case HB_SCRIPT_MANDAIC:
-
-    /* Unicode-6.1 additions */
-    case HB_SCRIPT_CHAKMA:
-    case HB_SCRIPT_SHARADA:
-    case HB_SCRIPT_TAKRI:
-
-    /* Unicode-7.0 additions */
-    case HB_SCRIPT_DUPLOYAN:
-    case HB_SCRIPT_GRANTHA:
-    case HB_SCRIPT_KHOJKI:
-    case HB_SCRIPT_KHUDAWADI:
-    case HB_SCRIPT_MAHAJANI:
-    //case HB_SCRIPT_MANICHAEAN:
-    case HB_SCRIPT_MODI:
-    case HB_SCRIPT_PAHAWH_HMONG:
-    //case HB_SCRIPT_PSALTER_PAHLAVI:
-    case HB_SCRIPT_SIDDHAM:
-    case HB_SCRIPT_TIRHUTA:
-
-    /* Unicode-8.0 additions */
-    case HB_SCRIPT_AHOM:
-    //case HB_SCRIPT_MULTANI:
-
-    /* Unicode-9.0 additions */
-    case HB_SCRIPT_BHAIKSUKI:
-    case HB_SCRIPT_MARCHEN:
-    case HB_SCRIPT_NEWA:
-
-    /* Unicode-10.0 additions */
-    case HB_SCRIPT_MASARAM_GONDI:
-    case HB_SCRIPT_SOYOMBO:
-    case HB_SCRIPT_ZANABAZAR_SQUARE:
-
-      /* If the designer designed the font for the 'DFLT' script,
-       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
-       * Otherwise, use the specific shaper.
-       * Note that for some simple scripts, there may not be *any*
-       * GSUB/GPOS needed, so there may be no scripts found! */
-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
-	  planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
-	return &_hb_ot_complex_shaper_default;
-      else
-	return &_hb_ot_complex_shaper_use;
-  }
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc
deleted file mode 100644
index 6ba925c6..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright © 2010,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-/* Thai / Lao shaper */
-
-
-/* PUA shaping */
-
-
-enum thai_consonant_type_t
-{
-  NC,
-  AC,
-  RC,
-  DC,
-  NOT_CONSONANT,
-  NUM_CONSONANT_TYPES = NOT_CONSONANT
-};
-
-static thai_consonant_type_t
-get_consonant_type (hb_codepoint_t u)
-{
-  if (u == 0x0E1Bu || u == 0x0E1Du || u == 0x0E1Fu/* || u == 0x0E2Cu*/)
-    return AC;
-  if (u == 0x0E0Du || u == 0x0E10u)
-    return RC;
-  if (u == 0x0E0Eu || u == 0x0E0Fu)
-    return DC;
-  if (hb_in_range<hb_codepoint_t> (u, 0x0E01u, 0x0E2Eu))
-    return NC;
-  return NOT_CONSONANT;
-}
-
-
-enum thai_mark_type_t
-{
-  AV,
-  BV,
-  T,
-  NOT_MARK,
-  NUM_MARK_TYPES = NOT_MARK
-};
-
-static thai_mark_type_t
-get_mark_type (hb_codepoint_t u)
-{
-  if (u == 0x0E31u || hb_in_range<hb_codepoint_t> (u, 0x0E34u, 0x0E37u) ||
-      u == 0x0E47u || hb_in_range<hb_codepoint_t> (u, 0x0E4Du, 0x0E4Eu))
-    return AV;
-  if (hb_in_range<hb_codepoint_t> (u, 0x0E38u, 0x0E3Au))
-    return BV;
-  if (hb_in_range<hb_codepoint_t> (u, 0x0E48u, 0x0E4Cu))
-    return T;
-  return NOT_MARK;
-}
-
-
-enum thai_action_t
-{
-  NOP,
-  SD,  /* Shift combining-mark down */
-  SL,  /* Shift combining-mark left */
-  SDL, /* Shift combining-mark down-left */
-  RD   /* Remove descender from base */
-};
-
-static hb_codepoint_t
-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;
-  } const *pua_mappings = nullptr;
-  static const thai_pua_mapping_t SD_mappings[] = {
-    {0x0E48u, 0xF70Au, 0xF88Bu}, /* MAI EK */
-    {0x0E49u, 0xF70Bu, 0xF88Eu}, /* MAI THO */
-    {0x0E4Au, 0xF70Cu, 0xF891u}, /* MAI TRI */
-    {0x0E4Bu, 0xF70Du, 0xF894u}, /* MAI CHATTAWA */
-    {0x0E4Cu, 0xF70Eu, 0xF897u}, /* THANTHAKHAT */
-    {0x0E38u, 0xF718u, 0xF89Bu}, /* SARA U */
-    {0x0E39u, 0xF719u, 0xF89Cu}, /* SARA UU */
-    {0x0E3Au, 0xF71Au, 0xF89Du}, /* PHINTHU */
-    {0x0000u, 0x0000u, 0x0000u}
-  };
-  static const thai_pua_mapping_t SDL_mappings[] = {
-    {0x0E48u, 0xF705u, 0xF88Cu}, /* MAI EK */
-    {0x0E49u, 0xF706u, 0xF88Fu}, /* MAI THO */
-    {0x0E4Au, 0xF707u, 0xF892u}, /* MAI TRI */
-    {0x0E4Bu, 0xF708u, 0xF895u}, /* MAI CHATTAWA */
-    {0x0E4Cu, 0xF709u, 0xF898u}, /* THANTHAKHAT */
-    {0x0000u, 0x0000u, 0x0000u}
-  };
-  static const thai_pua_mapping_t SL_mappings[] = {
-    {0x0E48u, 0xF713u, 0xF88Au}, /* MAI EK */
-    {0x0E49u, 0xF714u, 0xF88Du}, /* MAI THO */
-    {0x0E4Au, 0xF715u, 0xF890u}, /* MAI TRI */
-    {0x0E4Bu, 0xF716u, 0xF893u}, /* MAI CHATTAWA */
-    {0x0E4Cu, 0xF717u, 0xF896u}, /* THANTHAKHAT */
-    {0x0E31u, 0xF710u, 0xF884u}, /* MAI HAN-AKAT */
-    {0x0E34u, 0xF701u, 0xF885u}, /* SARA I */
-    {0x0E35u, 0xF702u, 0xF886u}, /* SARA II */
-    {0x0E36u, 0xF703u, 0xF887u}, /* SARA UE */
-    {0x0E37u, 0xF704u, 0xF888u}, /* SARA UEE */
-    {0x0E47u, 0xF712u, 0xF889u}, /* MAITAIKHU */
-    {0x0E4Du, 0xF711u, 0xF899u}, /* NIKHAHIT */
-    {0x0000u, 0x0000u, 0x0000u}
-  };
-  static const thai_pua_mapping_t RD_mappings[] = {
-    {0x0E0Du, 0xF70Fu, 0xF89Au}, /* YO YING */
-    {0x0E10u, 0xF700u, 0xF89Eu}, /* THO THAN */
-    {0x0000u, 0x0000u, 0x0000u}
-  };
-
-  switch (action) {
-    case NOP: return u;
-    case SD:  pua_mappings = SD_mappings; break;
-    case SDL: pua_mappings = SDL_mappings; break;
-    case SL:  pua_mappings = SL_mappings; break;
-    case RD:  pua_mappings = RD_mappings; break;
-  }
-  for (; pua_mappings->u; pua_mappings++)
-    if (pua_mappings->u == u)
-    {
-      hb_codepoint_t glyph;
-      if (hb_font_get_glyph (font, pua_mappings->win_pua, 0, &glyph))
-	return pua_mappings->win_pua;
-      if (hb_font_get_glyph (font, pua_mappings->mac_pua, 0, &glyph))
-	return pua_mappings->mac_pua;
-      break;
-    }
-  return u;
-}
-
-
-static enum thai_above_state_t
-{     /* Cluster above looks like: */
-  T0, /*  ⣤                      */
-  T1, /*     ⣼                   */
-  T2, /*        ⣾                */
-  T3, /*           ⣿             */
-  NUM_ABOVE_STATES
-} thai_above_start_state[NUM_CONSONANT_TYPES + 1/* For NOT_CONSONANT */] =
-{
-  T0, /* NC */
-  T1, /* AC */
-  T0, /* RC */
-  T0, /* DC */
-  T3, /* NOT_CONSONANT */
-};
-
-static const struct thai_above_state_machine_edge_t {
-  thai_action_t action;
-  thai_above_state_t next_state;
-} thai_above_state_machine[NUM_ABOVE_STATES][NUM_MARK_TYPES] =
-{        /*AV*/    /*BV*/    /*T*/
-/*T0*/ {{NOP,T3}, {NOP,T0}, {SD, T3}},
-/*T1*/ {{SL, T2}, {NOP,T1}, {SDL,T2}},
-/*T2*/ {{NOP,T3}, {NOP,T2}, {SL, T3}},
-/*T3*/ {{NOP,T3}, {NOP,T3}, {NOP,T3}},
-};
-
-
-static enum thai_below_state_t
-{
-  B0, /* No descender */
-  B1, /* Removable descender */
-  B2, /* Strict descender */
-  NUM_BELOW_STATES
-} thai_below_start_state[NUM_CONSONANT_TYPES + 1/* For NOT_CONSONANT */] =
-{
-  B0, /* NC */
-  B0, /* AC */
-  B1, /* RC */
-  B2, /* DC */
-  B2, /* NOT_CONSONANT */
-};
-
-static const struct thai_below_state_machine_edge_t {
-  thai_action_t action;
-  thai_below_state_t next_state;
-} thai_below_state_machine[NUM_BELOW_STATES][NUM_MARK_TYPES] =
-{        /*AV*/    /*BV*/    /*T*/
-/*B0*/ {{NOP,B0}, {NOP,B2}, {NOP, B0}},
-/*B1*/ {{NOP,B1}, {RD, B2}, {NOP, B1}},
-/*B2*/ {{NOP,B2}, {SD, B2}, {NOP, B2}},
-};
-
-
-static void
-do_thai_pua_shaping (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		     hb_buffer_t              *buffer,
-		     hb_font_t                *font)
-{
-  thai_above_state_t above_state = thai_above_start_state[NOT_CONSONANT];
-  thai_below_state_t below_state = thai_below_start_state[NOT_CONSONANT];
-  unsigned int base = 0;
-
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    thai_mark_type_t mt = get_mark_type (info[i].codepoint);
-
-    if (mt == NOT_MARK) {
-      thai_consonant_type_t ct = get_consonant_type (info[i].codepoint);
-      above_state = thai_above_start_state[ct];
-      below_state = thai_below_start_state[ct];
-      base = i;
-      continue;
-    }
-
-    const thai_above_state_machine_edge_t &above_edge = thai_above_state_machine[above_state][mt];
-    const thai_below_state_machine_edge_t &below_edge = thai_below_state_machine[below_state][mt];
-    above_state = above_edge.next_state;
-    below_state = below_edge.next_state;
-
-    /* At least one of the above/below actions is NOP. */
-    thai_action_t action = above_edge.action != NOP ? above_edge.action : below_edge.action;
-
-    buffer->unsafe_to_break (base, i);
-    if (action == RD)
-      info[base].codepoint = thai_pua_shape (info[base].codepoint, action, font);
-    else
-      info[i].codepoint = thai_pua_shape (info[i].codepoint, action, font);
-  }
-}
-
-
-static void
-preprocess_text_thai (const hb_ot_shape_plan_t *plan,
-		      hb_buffer_t              *buffer,
-		      hb_font_t                *font)
-{
-  /* This function implements the shaping logic documented here:
-   *
-   *   http://linux.thai.net/~thep/th-otf/shaping.html
-   *
-   * The first shaping rule listed there is needed even if the font has Thai
-   * OpenType tables.  The rest do fallback positioning based on PUA codepoints.
-   * We implement that only if there exist no Thai GSUB in the font.
-   */
-
-  /* The following is NOT specified in the MS OT Thai spec, however, it seems
-   * to be what Uniscribe and other engines implement.  According to Eric Muller:
-   *
-   * When you have a SARA AM, decompose it in NIKHAHIT + SARA AA, *and* move the
-   * NIKHAHIT backwards over any tone mark (0E48-0E4B).
-   *
-   * <0E14, 0E4B, 0E33> -> <0E14, 0E4D, 0E4B, 0E32>
-   *
-   * This reordering is legit only when the NIKHAHIT comes from a SARA AM, not
-   * when it's there to start with. The string <0E14, 0E4B, 0E4D> is probably
-   * not what a user wanted, but the rendering is nevertheless nikhahit above
-   * chattawa.
-   *
-   * Same for Lao.
-   *
-   * Note:
-   *
-   * Uniscribe also does some below-marks reordering.  Namely, it positions U+0E3A
-   * after U+0E38 and U+0E39.  We do that by modifying the ccc for U+0E3A.
-   * See unicode->modified_combining_class ().  Lao does NOT have a U+0E3A
-   * equivalent.
-   */
-
-
-  /*
-   * Here are the characters of significance:
-   *
-   *			Thai	Lao
-   * SARA AM:		U+0E33	U+0EB3
-   * SARA AA:		U+0E32	U+0EB2
-   * Nikhahit:		U+0E4D	U+0ECD
-   *
-   * Testing shows that Uniscribe reorder the following marks:
-   * Thai:	<0E31,0E34..0E37,0E47..0E4E>
-   * Lao:	<0EB1,0EB4..0EB7,0EC7..0ECE>
-   *
-   * Note how the Lao versions are the same as Thai + 0x80.
-   */
-
-  /* We only get one script at a time, so a script-agnostic implementation
-   * is adequate here. */
-#define IS_SARA_AM(x) (((x) & ~0x0080u) == 0x0E33u)
-#define NIKHAHIT_FROM_SARA_AM(x) ((x) - 0x0E33u + 0x0E4Du)
-#define SARA_AA_FROM_SARA_AM(x) ((x) - 1)
-#define IS_TONE_MARK(x) (hb_in_ranges<hb_codepoint_t> ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u))
-
-  buffer->clear_output ();
-  unsigned int count = buffer->len;
-  for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;)
-  {
-    hb_codepoint_t u = buffer->cur().codepoint;
-    if (likely (!IS_SARA_AM (u))) {
-      buffer->next_glyph ();
-      continue;
-    }
-
-    /* Is SARA AM. Decompose and reorder. */
-    hb_codepoint_t decomposed[2] = {hb_codepoint_t (NIKHAHIT_FROM_SARA_AM (u)),
-				    hb_codepoint_t (SARA_AA_FROM_SARA_AM (u))};
-    buffer->replace_glyphs (1, 2, decomposed);
-    if (unlikely (buffer->in_error))
-      return;
-
-    /* Make Nikhahit be recognized as a ccc=0 mark when zeroing widths. */
-    unsigned int end = buffer->out_len;
-    _hb_glyph_info_set_general_category (&buffer->out_info[end - 2], HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK);
-
-    /* Ok, let's see... */
-    unsigned int start = end - 2;
-    while (start > 0 && IS_TONE_MARK (buffer->out_info[start - 1].codepoint))
-      start--;
-
-    if (start + 2 < end)
-    {
-      /* Move Nikhahit (end-2) to the beginning */
-      buffer->merge_out_clusters (start, end);
-      hb_glyph_info_t t = buffer->out_info[end - 2];
-      memmove (buffer->out_info + start + 1,
-	       buffer->out_info + start,
-	       sizeof (buffer->out_info[0]) * (end - start - 2));
-      buffer->out_info[start] = t;
-    }
-    else
-    {
-      /* Since we decomposed, and NIKHAHIT is combining, merge clusters with the
-       * previous cluster. */
-      if (start && buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
-	buffer->merge_out_clusters (start - 1, end);
-    }
-  }
-  buffer->swap_buffers ();
-
-  /* If font has Thai GSUB, we are done. */
-  if (plan->props.script == HB_SCRIPT_THAI && !plan->map.found_script[0])
-    do_thai_pua_shaping (plan, buffer, font);
-}
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
-{
-  nullptr, /* collect_features */
-  nullptr, /* override_features */
-  nullptr, /* data_create */
-  nullptr, /* data_destroy */
-  preprocess_text_thai,
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
-  nullptr, /* decompose */
-  nullptr, /* compose */
-  nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-  false,/* fallback_position */
-};
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc
deleted file mode 100644
index eaac0bf..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright © 2010,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-static const hb_tag_t tibetan_features[] =
-{
-  HB_TAG('a','b','v','s'),
-  HB_TAG('b','l','w','s'),
-  HB_TAG('a','b','v','m'),
-  HB_TAG('b','l','w','m'),
-  HB_TAG_NONE
-};
-
-static void
-collect_features_tibetan (hb_ot_shape_planner_t *plan)
-{
-  for (const hb_tag_t *script_features = tibetan_features; script_features && *script_features; script_features++)
-    plan->map.add_global_bool_feature (*script_features);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan =
-{
-  collect_features_tibetan,
-  nullptr, /* override_features */
-  nullptr, /* data_create */
-  nullptr, /* data_destroy */
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
-  nullptr, /* decompose */
-  nullptr, /* compose */
-  nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-  true, /* fallback_position */
-};
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh
deleted file mode 100644
index 0bf3ad3..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh
+++ /dev/null
@@ -1,502 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-use-machine.rl"
-/*
- * Copyright © 2015  Mozilla Foundation.
- * Copyright © 2015  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
-
-#include "hb-private.hh"
-
-
-#line 38 "hb-ot-shape-complex-use-machine.hh"
-static const unsigned char _use_syllable_machine_trans_keys[] = {
-	12u, 12u, 1u, 15u, 1u, 1u, 12u, 12u, 0u, 43u, 21u, 21u, 8u, 39u, 8u, 39u, 
-	1u, 15u, 1u, 1u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 
-	8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 
-	8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 13u, 21u, 4u, 4u, 13u, 13u, 8u, 39u, 
-	8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 
-	8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 
-	8u, 39u, 1u, 15u, 12u, 12u, 1u, 39u, 8u, 39u, 21u, 42u, 41u, 42u, 42u, 42u, 
-	1u, 5u, 0
-};
-
-static const char _use_syllable_machine_key_spans[] = {
-	1, 15, 1, 1, 44, 1, 32, 32, 
-	15, 1, 32, 32, 32, 19, 19, 19, 
-	32, 32, 32, 32, 32, 32, 32, 32, 
-	32, 32, 32, 32, 9, 1, 1, 32, 
-	32, 32, 32, 19, 19, 19, 32, 32, 
-	32, 32, 32, 32, 32, 32, 32, 32, 
-	32, 15, 1, 39, 32, 22, 2, 1, 
-	5
-};
-
-static const short _use_syllable_machine_index_offsets[] = {
-	0, 2, 18, 20, 22, 67, 69, 102, 
-	135, 151, 153, 186, 219, 252, 272, 292, 
-	312, 345, 378, 411, 444, 477, 510, 543, 
-	576, 609, 642, 675, 708, 718, 720, 722, 
-	755, 788, 821, 854, 874, 894, 914, 947, 
-	980, 1013, 1046, 1079, 1112, 1145, 1178, 1211, 
-	1244, 1277, 1293, 1295, 1335, 1368, 1391, 1394, 
-	1396
-};
-
-static const char _use_syllable_machine_indicies[] = {
-	1, 0, 3, 2, 2, 2, 2, 2, 
-	2, 2, 2, 2, 2, 2, 2, 2, 
-	4, 2, 3, 2, 6, 5, 7, 8, 
-	9, 7, 10, 8, 9, 9, 11, 9, 
-	9, 3, 12, 9, 9, 13, 7, 7, 
-	14, 15, 9, 9, 16, 17, 18, 19, 
-	20, 21, 22, 16, 23, 24, 25, 26, 
-	27, 28, 9, 29, 30, 31, 9, 9, 
-	9, 32, 9, 34, 33, 36, 35, 35, 
-	37, 1, 35, 35, 38, 35, 35, 35, 
-	35, 35, 39, 40, 41, 42, 43, 44, 
-	45, 46, 40, 47, 39, 48, 49, 50, 
-	51, 35, 52, 53, 54, 35, 36, 35, 
-	35, 37, 1, 35, 35, 38, 35, 35, 
-	35, 35, 35, 55, 40, 41, 42, 43, 
-	44, 45, 46, 40, 47, 48, 48, 49, 
-	50, 51, 35, 52, 53, 54, 35, 37, 
-	56, 56, 56, 56, 56, 56, 56, 56, 
-	56, 56, 56, 56, 56, 57, 56, 37, 
-	56, 36, 35, 35, 37, 1, 35, 35, 
-	38, 35, 35, 35, 35, 35, 35, 40, 
-	41, 42, 43, 44, 45, 46, 40, 47, 
-	48, 48, 49, 50, 51, 35, 52, 53, 
-	54, 35, 36, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	40, 41, 42, 43, 44, 35, 35, 35, 
-	35, 35, 35, 49, 50, 51, 35, 52, 
-	53, 54, 35, 36, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	35, 35, 41, 42, 43, 44, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	52, 53, 54, 35, 36, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 42, 43, 44, 35, 
-	36, 35, 35, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	35, 43, 44, 35, 36, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 44, 35, 
-	36, 35, 35, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	42, 43, 44, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 52, 53, 54, 
-	35, 36, 35, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	35, 42, 43, 44, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 53, 
-	54, 35, 36, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	35, 35, 42, 43, 44, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	35, 54, 35, 36, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	35, 35, 41, 42, 43, 44, 35, 35, 
-	35, 35, 35, 35, 49, 50, 51, 35, 
-	52, 53, 54, 35, 36, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	35, 35, 35, 41, 42, 43, 44, 35, 
-	35, 35, 35, 35, 35, 35, 50, 51, 
-	35, 52, 53, 54, 35, 36, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 41, 42, 43, 44, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	51, 35, 52, 53, 54, 35, 36, 35, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 40, 41, 42, 43, 
-	44, 35, 46, 40, 35, 35, 35, 49, 
-	50, 51, 35, 52, 53, 54, 35, 36, 
-	35, 35, 35, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 40, 41, 42, 
-	43, 44, 35, 58, 40, 35, 35, 35, 
-	49, 50, 51, 35, 52, 53, 54, 35, 
-	36, 35, 35, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 40, 41, 
-	42, 43, 44, 35, 35, 40, 35, 35, 
-	35, 49, 50, 51, 35, 52, 53, 54, 
-	35, 36, 35, 35, 35, 35, 35, 35, 
-	35, 35, 35, 35, 35, 35, 35, 40, 
-	41, 42, 43, 44, 45, 46, 40, 35, 
-	35, 35, 49, 50, 51, 35, 52, 53, 
-	54, 35, 36, 35, 35, 37, 1, 35, 
-	35, 38, 35, 35, 35, 35, 35, 35, 
-	40, 41, 42, 43, 44, 45, 46, 40, 
-	47, 35, 48, 49, 50, 51, 35, 52, 
-	53, 54, 35, 36, 35, 35, 37, 1, 
-	35, 35, 38, 35, 35, 35, 35, 35, 
-	35, 40, 41, 42, 43, 44, 45, 46, 
-	40, 47, 39, 48, 49, 50, 51, 35, 
-	52, 53, 54, 35, 60, 59, 59, 59, 
-	59, 59, 59, 59, 61, 59, 10, 62, 
-	60, 59, 11, 63, 63, 3, 6, 63, 
-	63, 64, 63, 63, 63, 63, 63, 65, 
-	16, 17, 18, 19, 20, 21, 22, 16, 
-	23, 25, 25, 26, 27, 28, 63, 29, 
-	30, 31, 63, 11, 63, 63, 3, 6, 
-	63, 63, 64, 63, 63, 63, 63, 63, 
-	63, 16, 17, 18, 19, 20, 21, 22, 
-	16, 23, 25, 25, 26, 27, 28, 63, 
-	29, 30, 31, 63, 11, 63, 63, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 16, 17, 18, 19, 20, 63, 
-	63, 63, 63, 63, 63, 26, 27, 28, 
-	63, 29, 30, 31, 63, 11, 63, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 63, 63, 17, 18, 19, 20, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 29, 30, 31, 63, 11, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 63, 63, 63, 63, 18, 19, 
-	20, 63, 11, 63, 63, 63, 63, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 63, 19, 20, 63, 11, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	20, 63, 11, 63, 63, 63, 63, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 18, 19, 20, 63, 63, 63, 
-	63, 63, 63, 63, 63, 63, 63, 29, 
-	30, 31, 63, 11, 63, 63, 63, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 63, 18, 19, 20, 63, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 30, 31, 63, 11, 63, 63, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 63, 63, 18, 19, 20, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 63, 31, 63, 11, 63, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 63, 63, 17, 18, 19, 20, 
-	63, 63, 63, 63, 63, 63, 26, 27, 
-	28, 63, 29, 30, 31, 63, 11, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 63, 63, 63, 17, 18, 19, 
-	20, 63, 63, 63, 63, 63, 63, 63, 
-	27, 28, 63, 29, 30, 31, 63, 11, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 63, 63, 63, 63, 17, 18, 
-	19, 20, 63, 63, 63, 63, 63, 63, 
-	63, 63, 28, 63, 29, 30, 31, 63, 
-	11, 63, 63, 63, 63, 63, 63, 63, 
-	63, 63, 63, 63, 63, 63, 16, 17, 
-	18, 19, 20, 63, 22, 16, 63, 63, 
-	63, 26, 27, 28, 63, 29, 30, 31, 
-	63, 11, 63, 63, 63, 63, 63, 63, 
-	63, 63, 63, 63, 63, 63, 63, 16, 
-	17, 18, 19, 20, 63, 66, 16, 63, 
-	63, 63, 26, 27, 28, 63, 29, 30, 
-	31, 63, 11, 63, 63, 63, 63, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	16, 17, 18, 19, 20, 63, 63, 16, 
-	63, 63, 63, 26, 27, 28, 63, 29, 
-	30, 31, 63, 11, 63, 63, 63, 63, 
-	63, 63, 63, 63, 63, 63, 63, 63, 
-	63, 16, 17, 18, 19, 20, 21, 22, 
-	16, 63, 63, 63, 26, 27, 28, 63, 
-	29, 30, 31, 63, 11, 63, 63, 3, 
-	6, 63, 63, 64, 63, 63, 63, 63, 
-	63, 63, 16, 17, 18, 19, 20, 21, 
-	22, 16, 23, 63, 25, 26, 27, 28, 
-	63, 29, 30, 31, 63, 3, 67, 67, 
-	67, 67, 67, 67, 67, 67, 67, 67, 
-	67, 67, 67, 4, 67, 6, 67, 8, 
-	63, 63, 63, 8, 63, 63, 11, 63, 
-	63, 3, 6, 63, 63, 64, 63, 63, 
-	63, 63, 63, 63, 16, 17, 18, 19, 
-	20, 21, 22, 16, 23, 24, 25, 26, 
-	27, 28, 63, 29, 30, 31, 63, 11, 
-	63, 63, 3, 6, 63, 63, 64, 63, 
-	63, 63, 63, 63, 63, 16, 17, 18, 
-	19, 20, 21, 22, 16, 23, 24, 25, 
-	26, 27, 28, 63, 29, 30, 31, 63, 
-	69, 68, 68, 68, 68, 68, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 68, 
-	68, 68, 68, 68, 69, 70, 68, 69, 
-	70, 68, 70, 68, 8, 67, 67, 67, 
-	8, 67, 0
-};
-
-static const char _use_syllable_machine_trans_targs[] = {
-	4, 8, 4, 31, 2, 4, 1, 5, 
-	6, 4, 28, 4, 49, 50, 51, 53, 
-	33, 34, 35, 36, 37, 44, 45, 47, 
-	52, 48, 41, 42, 43, 38, 39, 40, 
-	56, 4, 4, 4, 4, 7, 0, 27, 
-	11, 12, 13, 14, 15, 22, 23, 25, 
-	26, 19, 20, 21, 16, 17, 18, 10, 
-	4, 9, 24, 4, 29, 30, 4, 4, 
-	3, 32, 46, 4, 4, 54, 55
-};
-
-static const char _use_syllable_machine_trans_actions[] = {
-	1, 0, 2, 3, 0, 4, 0, 0, 
-	7, 8, 0, 9, 10, 10, 3, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	3, 3, 0, 0, 0, 0, 0, 0, 
-	0, 11, 12, 13, 14, 7, 0, 7, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	7, 0, 0, 0, 0, 0, 0, 7, 
-	15, 0, 0, 16, 0, 0, 17, 18, 
-	0, 3, 0, 19, 20, 0, 0
-};
-
-static const char _use_syllable_machine_to_state_actions[] = {
-	0, 0, 0, 0, 5, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 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 _use_syllable_machine_from_state_actions[] = {
-	0, 0, 0, 0, 6, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 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 _use_syllable_machine_eof_trans[] = {
-	1, 3, 3, 6, 0, 34, 36, 36, 
-	57, 57, 36, 36, 36, 36, 36, 36, 
-	36, 36, 36, 36, 36, 36, 36, 36, 
-	36, 36, 36, 36, 60, 63, 60, 64, 
-	64, 64, 64, 64, 64, 64, 64, 64, 
-	64, 64, 64, 64, 64, 64, 64, 64, 
-	64, 68, 68, 64, 64, 69, 69, 69, 
-	68
-};
-
-static const int use_syllable_machine_start = 4;
-static const int use_syllable_machine_first_final = 4;
-static const int use_syllable_machine_error = -1;
-
-static const int use_syllable_machine_en_main = 4;
-
-
-#line 38 "hb-ot-shape-complex-use-machine.rl"
-
-
-
-#line 141 "hb-ot-shape-complex-use-machine.rl"
-
-
-#define found_syllable(syllable_type) \
-  HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
-      info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
-    syllable_serial++; \
-    if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
-  } HB_STMT_END
-
-static void
-find_syllables (hb_buffer_t *buffer)
-{
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
-  int cs;
-  hb_glyph_info_t *info = buffer->info;
-  
-#line 339 "hb-ot-shape-complex-use-machine.hh"
-	{
-	cs = use_syllable_machine_start;
-	ts = 0;
-	te = 0;
-	act = 0;
-	}
-
-#line 162 "hb-ot-shape-complex-use-machine.rl"
-
-
-  p = 0;
-  pe = eof = buffer->len;
-
-  unsigned int last = 0;
-  unsigned int syllable_serial = 1;
-  
-#line 356 "hb-ot-shape-complex-use-machine.hh"
-	{
-	int _slen;
-	int _trans;
-	const unsigned char *_keys;
-	const char *_inds;
-	if ( p == pe )
-		goto _test_eof;
-_resume:
-	switch ( _use_syllable_machine_from_state_actions[cs] ) {
-	case 6:
-#line 1 "NONE"
-	{ts = p;}
-	break;
-#line 370 "hb-ot-shape-complex-use-machine.hh"
-	}
-
-	_keys = _use_syllable_machine_trans_keys + (cs<<1);
-	_inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs];
-
-	_slen = _use_syllable_machine_key_spans[cs];
-	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].use_category()) &&
-		( info[p].use_category()) <= _keys[1] ?
-		( info[p].use_category()) - _keys[0] : _slen ];
-
-_eof_trans:
-	cs = _use_syllable_machine_trans_targs[_trans];
-
-	if ( _use_syllable_machine_trans_actions[_trans] == 0 )
-		goto _again;
-
-	switch ( _use_syllable_machine_trans_actions[_trans] ) {
-	case 7:
-#line 1 "NONE"
-	{te = p+1;}
-	break;
-	case 12:
-#line 130 "hb-ot-shape-complex-use-machine.rl"
-	{te = p+1;{ found_syllable (independent_cluster); }}
-	break;
-	case 14:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
-	{te = p+1;{ found_syllable (standard_cluster); }}
-	break;
-	case 9:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
-	{te = p+1;{ found_syllable (broken_cluster); }}
-	break;
-	case 8:
-#line 137 "hb-ot-shape-complex-use-machine.rl"
-	{te = p+1;{ found_syllable (non_cluster); }}
-	break;
-	case 11:
-#line 130 "hb-ot-shape-complex-use-machine.rl"
-	{te = p;p--;{ found_syllable (independent_cluster); }}
-	break;
-	case 15:
-#line 131 "hb-ot-shape-complex-use-machine.rl"
-	{te = p;p--;{ found_syllable (virama_terminated_cluster); }}
-	break;
-	case 13:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
-	{te = p;p--;{ found_syllable (standard_cluster); }}
-	break;
-	case 17:
-#line 133 "hb-ot-shape-complex-use-machine.rl"
-	{te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }}
-	break;
-	case 16:
-#line 134 "hb-ot-shape-complex-use-machine.rl"
-	{te = p;p--;{ found_syllable (numeral_cluster); }}
-	break;
-	case 20:
-#line 135 "hb-ot-shape-complex-use-machine.rl"
-	{te = p;p--;{ found_syllable (symbol_cluster); }}
-	break;
-	case 18:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
-	{te = p;p--;{ found_syllable (broken_cluster); }}
-	break;
-	case 19:
-#line 137 "hb-ot-shape-complex-use-machine.rl"
-	{te = p;p--;{ found_syllable (non_cluster); }}
-	break;
-	case 1:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
-	{{p = ((te))-1;}{ found_syllable (standard_cluster); }}
-	break;
-	case 4:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
-	{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
-	break;
-	case 2:
-#line 1 "NONE"
-	{	switch( act ) {
-	case 7:
-	{{p = ((te))-1;} found_syllable (broken_cluster); }
-	break;
-	case 8:
-	{{p = ((te))-1;} found_syllable (non_cluster); }
-	break;
-	}
-	}
-	break;
-	case 3:
-#line 1 "NONE"
-	{te = p+1;}
-#line 136 "hb-ot-shape-complex-use-machine.rl"
-	{act = 7;}
-	break;
-	case 10:
-#line 1 "NONE"
-	{te = p+1;}
-#line 137 "hb-ot-shape-complex-use-machine.rl"
-	{act = 8;}
-	break;
-#line 472 "hb-ot-shape-complex-use-machine.hh"
-	}
-
-_again:
-	switch ( _use_syllable_machine_to_state_actions[cs] ) {
-	case 5:
-#line 1 "NONE"
-	{ts = 0;}
-	break;
-#line 481 "hb-ot-shape-complex-use-machine.hh"
-	}
-
-	if ( ++p != pe )
-		goto _resume;
-	_test_eof: {}
-	if ( p == eof )
-	{
-	if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
-		_trans = _use_syllable_machine_eof_trans[cs] - 1;
-		goto _eof_trans;
-	}
-	}
-
-	}
-
-#line 171 "hb-ot-shape-complex-use-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use-private.hh
deleted file mode 100644
index f7ded133..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use-private.hh
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright © 2015  Mozilla Foundation.
- * Copyright © 2015  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-#define USE_TABLE_ELEMENT_TYPE uint8_t
-
-/* Cateories used in the Universal Shaping Engine spec:
- * https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm
- */
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum use_category_t {
-  USE_O		= 0,	/* OTHER */
-
-  USE_B		= 1,	/* BASE */
-  USE_IND	= 3,	/* BASE_IND */
-  USE_N		= 4,	/* BASE_NUM */
-  USE_GB	= 5,	/* BASE_OTHER */
-  USE_CGJ	= 6,	/* CGJ */
-//  USE_F		= 7,	/* CONS_FINAL */
-  USE_FM	= 8,	/* CONS_FINAL_MOD */
-//  USE_M		= 9,	/* CONS_MED */
-//  USE_CM	= 10,	/* CONS_MOD */
-  USE_SUB	= 11,	/* CONS_SUB */
-  USE_H		= 12,	/* HALANT */
-
-  USE_HN	= 13,	/* HALANT_NUM */
-  USE_ZWNJ	= 14,	/* Zero width non-joiner */
-  USE_ZWJ	= 15,	/* Zero width joiner */
-  USE_WJ	= 16,	/* Word joiner */
-  USE_Rsv	= 17,	/* Reserved characters */
-  USE_R		= 18,	/* REPHA */
-  USE_S		= 19,	/* SYM */
-//  USE_SM	= 20,	/* SYM_MOD */
-  USE_VS	= 21,	/* VARIATION_SELECTOR */
-//  USE_V	= 36,	/* VOWEL */
-//  USE_VM	= 40,	/* VOWEL_MOD */
-
-  USE_FAbv	= 24,	/* CONS_FINAL_ABOVE */
-  USE_FBlw	= 25,	/* CONS_FINAL_BELOW */
-  USE_FPst	= 26,	/* CONS_FINAL_POST */
-  USE_MAbv	= 27,	/* CONS_MED_ABOVE */
-  USE_MBlw	= 28,	/* CONS_MED_BELOW */
-  USE_MPst	= 29,	/* CONS_MED_POST */
-  USE_MPre	= 30,	/* CONS_MED_PRE */
-  USE_CMAbv	= 31,	/* CONS_MOD_ABOVE */
-  USE_CMBlw	= 32,	/* CONS_MOD_BELOW */
-  USE_VAbv	= 33,	/* VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST */
-  USE_VBlw	= 34,	/* VOWEL_BELOW / VOWEL_BELOW_POST */
-  USE_VPst	= 35,	/* VOWEL_POST	UIPC = Right */
-  USE_VPre	= 22,	/* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */
-  USE_VMAbv	= 37,	/* VOWEL_MOD_ABOVE */
-  USE_VMBlw	= 38,	/* VOWEL_MOD_BELOW */
-  USE_VMPst	= 39,	/* VOWEL_MOD_POST */
-  USE_VMPre	= 23,	/* VOWEL_MOD_PRE */
-  USE_SMAbv	= 41,	/* SYM_MOD_ABOVE */
-  USE_SMBlw	= 42,	/* SYM_MOD_BELOW */
-  USE_CS	= 43	/* CONS_WITH_STACKER */
-};
-
-HB_INTERNAL USE_TABLE_ELEMENT_TYPE
-hb_use_get_category (hb_codepoint_t u);
-
-#endif /* HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use-table.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use-table.cc
deleted file mode 100644
index 6823392f4..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use-table.cc
+++ /dev/null
@@ -1,788 +0,0 @@
-/* == Start of generated table == */
-/*
- * The following table is generated by running:
- *
- *   ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt
- *
- * on files with these headers:
- *
- * # IndicSyllabicCategory-10.0.0.txt
- * # Date: 2017-05-31, 01:07:00 GMT [KW, RP]
- * # IndicPositionalCategory-10.0.0.txt
- * # Date: 2017-05-31, 01:07:00 GMT [RP]
- * # Blocks-10.0.0.txt
- * # Date: 2017-04-12, 17:30:00 GMT [KW]
- * UnicodeData.txt does not have a header.
- */
-
-#include "hb-ot-shape-complex-use-private.hh"
-
-#define B	USE_B	/* BASE */
-#define CGJ	USE_CGJ	/* CGJ */
-#define CS	USE_CS	/* CONS_WITH_STACKER */
-#define FM	USE_FM	/* CONS_FINAL_MOD */
-#define GB	USE_GB	/* BASE_OTHER */
-#define H	USE_H	/* HALANT */
-#define HN	USE_HN	/* HALANT_NUM */
-#define IND	USE_IND	/* BASE_IND */
-#define N	USE_N	/* BASE_NUM */
-#define O	USE_O	/* OTHER */
-#define R	USE_R	/* REPHA */
-#define Rsv	USE_Rsv	/* Reserved */
-#define S	USE_S	/* SYM */
-#define SUB	USE_SUB	/* CONS_SUB */
-#define VS	USE_VS	/* VARIATION_SELECTOR */
-#define WJ	USE_WJ	/* Word_Joiner */
-#define ZWJ	USE_ZWJ	/* ZWJ */
-#define ZWNJ	USE_ZWNJ	/* ZWNJ */
-#define CMBlw	USE_CMBlw
-#define CMAbv	USE_CMAbv
-#define FBlw	USE_FBlw
-#define FPst	USE_FPst
-#define FAbv	USE_FAbv
-#define MPre	USE_MPre
-#define MBlw	USE_MBlw
-#define MPst	USE_MPst
-#define MAbv	USE_MAbv
-#define SMBlw	USE_SMBlw
-#define SMAbv	USE_SMAbv
-#define VPre	USE_VPre
-#define VBlw	USE_VBlw
-#define VPst	USE_VPst
-#define VAbv	USE_VAbv
-#define VMPre	USE_VMPre
-#define VMBlw	USE_VMBlw
-#define VMPst	USE_VMPst
-#define VMAbv	USE_VMAbv
-
-static const USE_TABLE_ELEMENT_TYPE use_table[] = {
-
-
-#define use_offset_0x0028u 0
-
-
-  /* Basic Latin */
-                                                                         O,     O,     O,     O,     O,    GB,     O,     O,
-  /* 0030 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-
-#define use_offset_0x00a0u 24
-
-
-  /* Latin-1 Supplement */
-
-  /* 00A0 */    GB,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 00B0 */     O,     O,    FM,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 00C0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 00D0 */     O,     O,     O,     O,     O,     O,     O,    GB,
-
-#define use_offset_0x0348u 80
-
-
-  /* Combining Diacritical Marks */
-                                                                         O,     O,     O,     O,     O,     O,     O,   CGJ,
-
-#define use_offset_0x0900u 88
-
-
-  /* Devanagari */
-
-  /* 0900 */ VMAbv, VMAbv, VMAbv, VMPst,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0910 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0920 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0930 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VAbv,  VPst, CMBlw,     B,  VPst,  VPre,
-  /* 0940 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,  VPst,  VPst,  VPst,  VPst,     H,  VPre,  VPst,
-  /* 0950 */     O, VMAbv, VMBlw,     O,     O,  VAbv,  VBlw,  VBlw,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0960 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0970 */     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-
-  /* Bengali */
-
-  /* 0980 */     O, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,
-  /* 0990 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 09A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
-  /* 09B0 */     B,     O,     B,     O,     O,     O,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VPre,
-  /* 09C0 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,   IND,     O,
-  /* 09D0 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     B,     B,     O,     B,
-  /* 09E0 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 09F0 */     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     B,     O,     O,     O,
-
-  /* Gurmukhi */
-
-  /* 0A00 */     O, VMAbv, VMAbv, VMPst,     O,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     B,
-  /* 0A10 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
-  /* 0A30 */     B,     O,     B,     B,     O,     B,     B,     O,     B,     B,     O,     O, CMBlw,     O,  VPst,  VPre,
-  /* 0A40 */  VPst,  VBlw,  VBlw,     O,     O,     O,     O,  VAbv,  VAbv,     O,     O,  VAbv,  VAbv,     H,     O,     O,
-  /* 0A50 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     O,     B,     O,
-  /* 0A60 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0A70 */ VMAbv, CMAbv,    GB,    GB,     O,  MBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Gujarati */
-
-  /* 0A80 */     O, VMAbv, VMAbv, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,
-  /* 0A90 */     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0AA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
-  /* 0AB0 */     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VPre,
-  /* 0AC0 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,     O,  VAbv,  VAbv,  VAbv,     O,  VPst,  VPst,     H,     O,     O,
-  /* 0AD0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 0AE0 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0AF0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     B, VMAbv, VMAbv, VMAbv, CMAbv, CMAbv, CMAbv,
-
-  /* Oriya */
-
-  /* 0B00 */     O, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,
-  /* 0B10 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0B20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
-  /* 0B30 */     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VAbv,
-  /* 0B40 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,     O,     O,
-  /* 0B50 */     O,     O,     O,     O,     O,     O,  VAbv,  VAbv,     O,     O,     O,     O,     B,     B,     O,     B,
-  /* 0B60 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0B70 */     O,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Tamil */
-
-  /* 0B80 */     O,     O, VMAbv,   IND,     O,     B,     B,     B,     B,     B,     B,     O,     O,     O,     B,     B,
-  /* 0B90 */     B,     O,     B,     B,     B,     B,     O,     O,     O,     B,     B,     O,     B,     O,     B,     B,
-  /* 0BA0 */     O,     O,     O,     B,     B,     O,     O,     O,     B,     B,     B,     O,     O,     O,     B,     B,
-  /* 0BB0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,  VPst,  VPst,
-  /* 0BC0 */  VAbv,  VPst,  VPst,     O,     O,     O,  VPre,  VPre,  VPre,     O,  VPre,  VPre,  VPre,     H,     O,     O,
-  /* 0BD0 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 0BE0 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0BF0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Telugu */
-
-  /* 0C00 */ VMAbv, VMPst, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,
-  /* 0C10 */     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0C20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
-  /* 0C30 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     B,  VAbv,  VAbv,
-  /* 0C40 */  VAbv,  VPst,  VPst,  VPst,  VPst,     O,  VAbv,  VAbv,  VAbv,     O,  VAbv,  VAbv,  VAbv,     H,     O,     O,
-  /* 0C50 */     O,     O,     O,     O,     O,  VAbv,  VBlw,     O,     B,     B,     B,     O,     O,     O,     O,     O,
-  /* 0C60 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0C70 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Kannada */
-
-  /* 0C80 */     O, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,
-  /* 0C90 */     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0CA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
-  /* 0CB0 */     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VAbv,
-  /* 0CC0 */  VAbv,  VPst,  VPst,  VPst,  VPst,     O,  VAbv,  VAbv,  VAbv,     O,  VAbv,  VAbv,  VAbv,     H,     O,     O,
-  /* 0CD0 */     O,     O,     O,     O,     O,  VPst,  VPst,     O,     O,     O,     O,     O,     O,     O,     B,     O,
-  /* 0CE0 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0CF0 */     O,    CS,    CS,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Malayalam */
-
-  /* 0D00 */ VMAbv, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,
-  /* 0D10 */     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0D20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0D30 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,     B,  VPst,  VPst,
-  /* 0D40 */  VPst,  VPst,  VPst,  VBlw,  VBlw,     O,  VPre,  VPre,  VPre,     O,  VPre,  VPre,  VPre,     H,     R,     O,
-  /* 0D50 */     O,     O,     O,     O,   IND,   IND,   IND,  VPst,     O,     O,     O,     O,     O,     O,     O,     B,
-  /* 0D60 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0D70 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,   IND,   IND,   IND,   IND,   IND,   IND,
-
-  /* Sinhala */
-
-  /* 0D80 */     O,     O, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0D90 */     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     B,     B,     B,     B,     B,     B,
-  /* 0DA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0DB0 */     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     O,     O,
-  /* 0DC0 */     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     H,     O,     O,     O,     O,  VPst,
-  /* 0DD0 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,     O,  VBlw,     O,  VPst,  VPre,  VPre,  VPre,  VPre,  VPre,  VPre,  VPst,
-  /* 0DE0 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0DF0 */     O,     O,  VPst,  VPst,     O,     O,     O,     O,
-
-#define use_offset_0x1000u 1360
-
-
-  /* Myanmar */
-
-  /* 1000 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1010 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1020 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,  VPst,  VAbv,  VAbv,  VBlw,
-  /* 1030 */  VBlw,  VPre,  VAbv,  VAbv,  VAbv,  VAbv, VMAbv, VMBlw, VMPst,     H,  VAbv,  MPst,  MPre,  MBlw,  MBlw,     B,
-  /* 1040 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,    GB,     O,
-  /* 1050 */     B,     B,     B,     B,     B,     B,  VPst,  VPst,  VBlw,  VBlw,     B,     B,     B,     B,  MBlw,  MBlw,
-  /* 1060 */  MBlw,     B,  VPst, VMPst, VMPst,     B,     B,  VPst,  VPst, VMPst, VMPst, VMPst, VMPst, VMPst,     B,     B,
-  /* 1070 */     B,  VAbv,  VAbv,  VAbv,  VAbv,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1080 */     B,     B,  MBlw,  VPst,  VPre,  VAbv,  VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw,     B, VMPst,
-  /* 1090 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B, VMPst, VMPst,  VPst,  VAbv,     O,     O,
-
-#define use_offset_0x1700u 1520
-
-
-  /* Tagalog */
-
-  /* 1700 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,
-  /* 1710 */     B,     B,  VAbv,  VBlw,  VBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Hanunoo */
-
-  /* 1720 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1730 */     B,     B,  VAbv,  VBlw,  VBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Buhid */
-
-  /* 1740 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1750 */     B,     B,  VAbv,  VBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Tagbanwa */
-
-  /* 1760 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,
-  /* 1770 */     B,     O,  VAbv,  VBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Khmer */
-
-  /* 1780 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1790 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 17A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 17B0 */     B,     B,     B,     B,     O,     O,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VPre,  VPre,
-  /* 17C0 */  VPre,  VPre,  VPre,  VPre,  VPre,  VPre, VMAbv, VMPst,  VPst, VMAbv, VMAbv,    FM,  FAbv, CMAbv,    FM,    FM,
-  /* 17D0 */    FM,  VAbv,     H,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     B,  VAbv,     O,     O,
-  /* 17E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-
-#define use_offset_0x1900u 1760
-
-
-  /* Limbu */
-
-  /* 1900 */    GB,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1910 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,
-  /* 1920 */  VAbv,  VAbv,  VBlw,  VPst,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,   SUB,   SUB,   SUB,     O,     O,     O,     O,
-  /* 1930 */  FPst,  FPst, VMBlw,  FPst,  FPst,  FPst,  FPst,  FPst,  FPst,  FBlw,  VAbv,    FM,     O,     O,     O,     O,
-  /* 1940 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-
-  /* Tai Le */
-
-  /* 1950 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1960 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,
-  /* 1970 */     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* New Tai Lue */
-
-  /* 1980 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1990 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 19A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
-  /* 19B0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 19C0 */     B,     B,     B,     B,     B,     B,     B,     B, VMPst, VMPst,     O,     O,     O,     O,     O,     O,
-  /* 19D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-  /* 19E0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 19F0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Buginese */
-
-  /* 1A00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1A10 */     B,     B,     B,     B,     B,     B,     B,  VAbv,  VBlw,  VPre,  VPst,  VAbv,     O,     O,     O,     O,
-
-  /* Tai Tham */
-
-  /* 1A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1A30 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1A40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1A50 */     B,     B,     B,     B,     B,  MPre,  MBlw,   SUB,  FAbv,  FAbv,  FAbv,   SUB,   SUB,   SUB,   SUB,     O,
-  /* 1A60 */     H,  VPst,  VAbv,  VPst,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VAbv,  VBlw,  VPst,  VPre,  VPre,
-  /* 1A70 */  VPre,  VPre,  VPre,  VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,  VAbv,    FM,    FM,     O,     O,  FBlw,
-  /* 1A80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-  /* 1A90 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-
-#define use_offset_0x1b00u 2176
-
-
-  /* Balinese */
-
-  /* 1B00 */ VMAbv, VMAbv, VMAbv,  FAbv, VMPst,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1B10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1B20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1B30 */     B,     B,     B,     B, CMAbv,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VPre,  VPre,
-  /* 1B40 */  VPre,  VPre,  VAbv,  VAbv,     H,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
-  /* 1B50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-  /* 1B60 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
-  /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Sundanese */
-
-  /* 1B80 */ VMAbv,  FAbv, VMPst,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1B90 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1BA0 */     B,   SUB,   SUB,   SUB,  VAbv,  VBlw,  VPre,  VPst,  VAbv,  VAbv,  VPst,     H,   SUB,   SUB,     B,     B,
-  /* 1BB0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-
-  /* Batak */
-
-  /* 1BC0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1BD0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1BE0 */     B,     B,     B,     B,     B,     B, CMAbv,  VPst,  VAbv,  VAbv,  VPst,  VPst,  VPst,  VAbv,  VPst,  VAbv,
-  /* 1BF0 */  FAbv,  FAbv, CMBlw, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Lepcha */
-
-  /* 1C00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1C10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1C20 */     B,     B,     B,     B,   SUB,   SUB,  VPst,  VPre,  VPre,  VPre,  VPst,  VPst,  VBlw,  FAbv,  FAbv,  FAbv,
-  /* 1C30 */  FAbv,  FAbv,  FAbv,  FAbv, VMPre, VMPre,    FM, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 1C40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     B,     B,     B,
-
-#define use_offset_0x1cd0u 2512
-
-
-  /* Vedic Extensions */
-
-  /* 1CD0 */ VMAbv, VMAbv, VMAbv,     O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw,
-  /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw,     O,     O,     O,     O, VMBlw,     O,     O,
-  /* 1CF0 */     O,     O, VMPst, VMPst, VMAbv,     O,     O, VMPst, VMAbv, VMAbv,     O,     O,     O,     O,     O,     O,
-
-#define use_offset_0x1df8u 2560
-
-
-  /* Combining Diacritical Marks Supplement */
-                                                                         O,     O,     O,    FM,     O,     O,     O,     O,
-
-#define use_offset_0x2008u 2568
-
-
-  /* General Punctuation */
-                                                                         O,     O,     O,     O,  ZWNJ,   ZWJ,     O,     O,
-  /* 2010 */    GB,    GB,    GB,    GB,    GB,     O,     O,     O,
-
-#define use_offset_0x2060u 2584
-
-  /* 2060 */    WJ,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Superscripts and Subscripts */
-
-  /* 2070 */     O,     O,     O,     O,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 2080 */     O,     O,    FM,    FM,    FM,     O,     O,     O,
-
-#define use_offset_0x20f0u 2624
-
-
-  /* Combining Diacritical Marks for Symbols */
-
-  /* 20F0 */ VMAbv,     O,     O,     O,     O,     O,     O,     O,
-
-#define use_offset_0x25c8u 2632
-
-
-  /* Geometric Shapes */
-                                                                         O,     O,     O,     O,    GB,     O,     O,     O,
-
-#define use_offset_0xa800u 2640
-
-
-  /* Syloti Nagri */
-
-  /* A800 */     B,     B,     O,     B,     B,     B,  VAbv,     B,     B,     B,     B, VMAbv,     B,     B,     B,     B,
-  /* A810 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A820 */     B,     B,     B,  VPst,  VPst,  VBlw,  VAbv,  VPst,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* A830 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Phags-pa */
-
-  /* A840 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A850 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A860 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A870 */     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Saurashtra */
-
-  /* A880 */ VMPst, VMPst,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A890 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A8A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A8B0 */     B,     B,     B,     B,  MPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,
-  /* A8C0 */  VPst,  VPst,  VPst,  VPst,     H, VMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* A8D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-
-  /* Devanagari Extended */
-
-  /* A8E0 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,
-  /* A8F0 */ VMAbv, VMAbv,     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Kayah Li */
-
-  /* A900 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A910 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A920 */     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv, VMBlw, VMBlw, VMBlw,     O,     O,
-
-  /* Rejang */
-
-  /* A930 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A940 */     B,     B,     B,     B,     B,     B,     B,  VBlw,  VBlw,  VBlw,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  FAbv,
-  /* A950 */  FAbv,  FAbv,  FPst,  VPst,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* A960 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* A970 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Javanese */
-
-  /* A980 */ VMAbv, VMAbv,  FAbv, VMPst,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A990 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A9A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A9B0 */     B,     B,     B, CMAbv,  VPst,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VPre,  VAbv,   SUB,  MPst,  MBlw,
-  /* A9C0 */     H,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* A9D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-
-  /* Myanmar Extended-B */
-
-  /* A9E0 */     B,     B,     B,     B,     B,  VAbv,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A9F0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,
-
-  /* Cham */
-
-  /* AA00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* AA10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* AA20 */     B,     B,     B,     B,     B,     B,     B,     B,     B, VMAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VAbv,  VPre,
-  /* AA30 */  VPre,  VAbv,  VBlw,  MPst,  MPre,  MBlw,  MBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* AA40 */     B,     B,     B,  FAbv,     B,     B,     B,     B,     B,     B,     B,     B,  FAbv,  FPst,     O,     O,
-  /* AA50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-
-  /* Myanmar Extended-A */
-
-  /* AA60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* AA70 */     O,     B,     B,     B,    GB,    GB,    GB,     O,     O,     O,     B, VMPst, VMAbv, VMPst,     B,     B,
-
-  /* Tai Viet */
-
-  /* AA80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* AA90 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* AAA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* AAB0 */  VAbv,     B,  VAbv,  VAbv,  VBlw,     B,     B,  VAbv,  VAbv,     B,     B,     B,     B,     B,  VAbv, VMAbv,
-  /* AAC0 */     B, VMAbv,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* AAD0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Meetei Mayek Extensions */
-
-  /* AAE0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPre,  VBlw,  VAbv,  VPre,  VPst,
-  /* AAF0 */     O,     O,     O,     O,     O, VMPst,     H,     O,
-
-#define use_offset_0xabc0u 3400
-
-
-  /* Meetei Mayek */
-
-  /* ABC0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* ABD0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* ABE0 */     B,     B,     B,  VPst,  VPst,  VAbv,  VPst,  VPst,  VBlw,  VPst,  VPst,     O, VMPst,  VBlw,     O,     O,
-  /* ABF0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-
-#define use_offset_0xfe00u 3464
-
-
-  /* Variation Selectors */
-
-  /* FE00 */    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,
-
-#define use_offset_0x10a00u 3480
-
-
-  /* Kharoshthi */
-
-  /* 10A00 */     B,  VBlw,  VBlw,  VBlw,     O,  VAbv,  VBlw,     O,     O,     O,     O,     O,  VBlw,  VBlw, VMBlw, VMAbv,
-  /* 10A10 */     B,     B,     B,     B,     O,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,
-  /* 10A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 10A30 */     B,     B,     B,     B,     O,     O,     O,     O, CMAbv, CMBlw, CMBlw,     O,     O,     O,     O,     H,
-  /* 10A40 */     B,     B,     B,     B,     B,     B,     B,     B,
-
-#define use_offset_0x11000u 3552
-
-
-  /* Brahmi */
-
-  /* 11000 */ VMPst, VMAbv, VMPst,    CS,    CS,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11010 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11020 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11030 */     B,     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,
-  /* 11040 */  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,     H,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 11050 */     O,     O,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,
-  /* 11060 */     N,     N,     N,     N,     N,     N,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11070 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,    HN,
-
-  /* Kaithi */
-
-  /* 11080 */ VMAbv, VMAbv, VMPst,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11090 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 110A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 110B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VAbv,  VAbv,  VPst,  VPst,     H, CMBlw,     O,     O,     O,     O,     O,
-
-#define use_offset_0x11100u 3744
-
-
-  /* Chakma */
-
-  /* 11100 */ VMAbv, VMAbv, VMAbv,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11110 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11120 */     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VAbv,  VAbv,  VAbv,
-  /* 11130 */  VAbv,  VBlw,  VBlw,     H,  VAbv,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11140 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Mahajani */
-
-  /* 11150 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11160 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11170 */     B,     B,     B, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Sharada */
-
-  /* 11180 */ VMAbv, VMAbv, VMPst,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11190 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 111A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 111B0 */     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,
-  /* 111C0 */     H,     B,     R,     R,     O,     O,     O,     O,     O,     O, CMBlw,  VAbv,  VBlw,     O,     O,     O,
-  /* 111D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-
-  /* Sinhala Archaic Numbers */
-
-  /* 111E0 */     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 111F0 */     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Khojki */
-
-  /* 11200 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11210 */     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11220 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,  VPst,  VPst,  VBlw,
-  /* 11230 */  VAbv,  VAbv,  VAbv,  VAbv, VMAbv,     H, CMAbv, CMAbv,     O,     O,     O,     O,     O,     O, VMAbv,     O,
-
-#define use_offset_0x11280u 4064
-
-
-  /* Multani */
-
-  /* 11280 */     B,     B,     B,     B,     B,     B,     B,     O,     B,     O,     B,     B,     B,     B,     O,     B,
-  /* 11290 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,
-  /* 112A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Khudawadi */
-
-  /* 112B0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 112C0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 112D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B, VMAbv,
-  /* 112E0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv, CMBlw,  VBlw,     O,     O,     O,     O,     O,
-  /* 112F0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-
-  /* Grantha */
-
-  /* 11300 */ VMAbv, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,
-  /* 11310 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11320 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
-  /* 11330 */     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VPst,
-  /* 11340 */  VAbv,  VPst,  VPst,  VPst,  VPst,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,     O,     O,
-  /* 11350 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     O,     O,     B,     B,
-  /* 11360 */     B,     B,  VPst,  VPst,     O,     O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
-  /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
-
-#define use_offset_0x11400u 4312
-
-
-  /* Newa */
-
-  /* 11400 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11410 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11420 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11430 */     B,     B,     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,
-  /* 11440 */  VPst,  VPst,     H, VMAbv, VMAbv, VMPst, CMBlw,     B,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 11450 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-  /* 11460 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 11470 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Tirhuta */
-
-  /* 11480 */     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11490 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 114A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 114B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VPre,  VAbv,  VPre,  VPre,  VPst,  VPre, VMAbv,
-  /* 114C0 */ VMAbv, VMPst,     H, CMBlw,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 114D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-
-#define use_offset_0x11580u 4536
-
-
-  /* Siddham */
-
-  /* 11580 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11590 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 115A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,
-  /* 115B0 */  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,  VPre,  VPre, VMAbv, VMAbv, VMPst,     H,
-  /* 115C0 */ CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 115D0 */     O,     O,     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,  VBlw,  VBlw,     O,     O,
-  /* 115E0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 115F0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Modi */
-
-  /* 11600 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11610 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11620 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11630 */  VPst,  VPst,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VPst,  VPst, VMAbv, VMPst,     H,
-  /* 11640 */  VAbv,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 11650 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-  /* 11660 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 11670 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Takri */
-
-  /* 11680 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11690 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 116A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B, VMAbv, VMPst,  VAbv,  VPre,  VPst,
-  /* 116B0 */  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,     H, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 116C0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-  /* 116D0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 116E0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 116F0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Ahom */
-
-  /* 11700 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11710 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,  MBlw,  MPre,  MAbv,
-  /* 11720 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VAbv,  VBlw,  VAbv,  VAbv,  VAbv,     O,     O,     O,     O,
-  /* 11730 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
-
-#define use_offset_0x11a00u 4984
-
-
-  /* Zanabazar Square */
-
-  /* 11A00 */     B,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,     B,     B,     B,     B,     B,
-  /* 11A10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11A30 */     B,     B,     B,    FM,  VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst,     R,  MBlw,  MBlw,  MBlw,  MBlw,    GB,
-  /* 11A40 */     O,     O,     O,     O,     O,    GB,     O,     H,     O,     O,     O,     O,     O,     O,     O,     O,
-
-  /* Soyombo */
-
-  /* 11A50 */     B,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VPst,  VPst,  VBlw,  VBlw,  VBlw,     B,     B,     B,     B,
-  /* 11A60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11A70 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11A80 */     B,     B,     B,     B,     O,     O,     R,     R,     R,     R,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,
-  /* 11A90 */  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw, VMAbv, VMPst, CMAbv,     H,     O,     O,     O,     O,     O,     O,
-
-#define use_offset_0x11c00u 5144
-
-
-  /* Bhaiksuki */
-
-  /* 11C00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
-  /* 11C10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11C20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,
-  /* 11C30 */  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,     O,  VAbv,  VAbv,  VAbv,  VAbv, VMAbv, VMAbv, VMPst,     H,
-  /* 11C40 */     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 11C50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11C60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,
-
-  /* Marchen */
-
-  /* 11C70 */     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11C80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11C90 */     O,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
-  /* 11CA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
-  /* 11CB0 */  VBlw,  VPre,  VBlw,  VAbv,  VPst, VMAbv, VMAbv,     O,
-
-#define use_offset_0x11d00u 5328
-
-
-  /* Masaram Gondi */
-
-  /* 11D00 */     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,
-  /* 11D10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11D20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11D30 */     B,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,     O,     O,     O,  VAbv,     O,  VAbv,  VAbv,     O,  VAbv,
-  /* 11D40 */ VMAbv, VMAbv, CMBlw,  VAbv,  VBlw,     H,     R,  MBlw,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 11D50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-
-}; /* Table items: 5424; occupancy: 73% */
-
-USE_TABLE_ELEMENT_TYPE
-hb_use_get_category (hb_codepoint_t u)
-{
-  switch (u >> 12)
-  {
-    case 0x0u:
-      if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x0348u, 0x034Fu)) return use_table[u - 0x0348u + use_offset_0x0348u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u];
-      break;
-
-    case 0x1u:
-      if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return use_table[u - 0x1000u + use_offset_0x1000u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x1700u, 0x17EFu)) return use_table[u - 0x1700u + use_offset_0x1700u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x1DF8u, 0x1DFFu)) return use_table[u - 0x1DF8u + use_offset_0x1df8u];
-      break;
-
-    case 0x2u:
-      if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2017u)) return use_table[u - 0x2008u + use_offset_0x2008u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x2060u, 0x2087u)) return use_table[u - 0x2060u + use_offset_0x2060u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x20F0u, 0x20F7u)) return use_table[u - 0x20F0u + use_offset_0x20f0u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x25C8u, 0x25CFu)) return use_table[u - 0x25C8u + use_offset_0x25c8u];
-      break;
-
-    case 0xAu:
-      if (hb_in_range<hb_codepoint_t> (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u];
-      if (hb_in_range<hb_codepoint_t> (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u];
-      break;
-
-    case 0xFu:
-      if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u];
-      break;
-
-    case 0x10u:
-      if (hb_in_range<hb_codepoint_t> (u, 0x10A00u, 0x10A47u)) return use_table[u - 0x10A00u + use_offset_0x10a00u];
-      break;
-
-    case 0x11u:
-      if (hb_in_range<hb_codepoint_t> (u, 0x11000u, 0x110BFu)) return use_table[u - 0x11000u + use_offset_0x11000u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x11580u, 0x1173Fu)) return use_table[u - 0x11580u + use_offset_0x11580u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x11A00u, 0x11A9Fu)) return use_table[u - 0x11A00u + use_offset_0x11a00u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x11D00u, 0x11D5Fu)) return use_table[u - 0x11D00u + use_offset_0x11d00u];
-      break;
-
-    default:
-      break;
-  }
-  return USE_O;
-}
-
-#undef B
-#undef CGJ
-#undef CS
-#undef FM
-#undef GB
-#undef H
-#undef HN
-#undef IND
-#undef N
-#undef O
-#undef R
-#undef Rsv
-#undef S
-#undef SUB
-#undef VS
-#undef WJ
-#undef ZWJ
-#undef ZWNJ
-#undef CMBlw
-#undef CMAbv
-#undef FBlw
-#undef FPst
-#undef FAbv
-#undef MPre
-#undef MBlw
-#undef MPst
-#undef MAbv
-#undef SMBlw
-#undef SMAbv
-#undef VPre
-#undef VBlw
-#undef VPst
-#undef VAbv
-#undef VMPre
-#undef VMBlw
-#undef VMPst
-#undef VMAbv
-
-/* == End of generated table == */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use.cc
deleted file mode 100644
index ee7653b..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use.cc
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * Copyright © 2015  Mozilla Foundation.
- * Copyright © 2015  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-complex-use-private.hh"
-#include "hb-ot-shape-complex-arabic-private.hh"
-
-/* buffer var allocations */
-#define use_category() complex_var_u8_0()
-
-
-/*
- * Universal Shaping Engine.
- * https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm
- */
-
-static const hb_tag_t
-basic_features[] =
-{
-  /*
-   * Basic features.
-   * These features are applied all at once, before reordering.
-   */
-  HB_TAG('r','k','r','f'),
-  HB_TAG('a','b','v','f'),
-  HB_TAG('b','l','w','f'),
-  HB_TAG('h','a','l','f'),
-  HB_TAG('p','s','t','f'),
-  HB_TAG('v','a','t','u'),
-  HB_TAG('c','j','c','t'),
-};
-static const hb_tag_t
-arabic_features[] =
-{
-  HB_TAG('i','s','o','l'),
-  HB_TAG('i','n','i','t'),
-  HB_TAG('m','e','d','i'),
-  HB_TAG('f','i','n','a'),
-  /* The spec doesn't specify these but we apply anyway, since our Arabic shaper
-   * does.  These are only used in Syriac spec. */
-  HB_TAG('m','e','d','2'),
-  HB_TAG('f','i','n','2'),
-  HB_TAG('f','i','n','3'),
-};
-/* Same order as arabic_features.  Don't need Syriac stuff.*/
-enum joining_form_t {
-  ISOL,
-  INIT,
-  MEDI,
-  FINA,
-  _NONE
-};
-static const hb_tag_t
-other_features[] =
-{
-  /*
-   * Other features.
-   * These features are applied all at once, after reordering.
-   */
-  HB_TAG('a','b','v','s'),
-  HB_TAG('b','l','w','s'),
-  HB_TAG('h','a','l','n'),
-  HB_TAG('p','r','e','s'),
-  HB_TAG('p','s','t','s'),
-  /* Positioning features, though we don't care about the types. */
-  HB_TAG('d','i','s','t'),
-  HB_TAG('a','b','v','m'),
-  HB_TAG('b','l','w','m'),
-};
-
-static void
-setup_syllables (const hb_ot_shape_plan_t *plan,
-		 hb_font_t *font,
-		 hb_buffer_t *buffer);
-static void
-clear_substitution_flags (const hb_ot_shape_plan_t *plan,
-			  hb_font_t *font,
-			  hb_buffer_t *buffer);
-static void
-record_rphf (const hb_ot_shape_plan_t *plan,
-	     hb_font_t *font,
-	     hb_buffer_t *buffer);
-static void
-record_pref (const hb_ot_shape_plan_t *plan,
-	     hb_font_t *font,
-	     hb_buffer_t *buffer);
-static void
-reorder (const hb_ot_shape_plan_t *plan,
-	 hb_font_t *font,
-	 hb_buffer_t *buffer);
-
-static void
-collect_features_use (hb_ot_shape_planner_t *plan)
-{
-  hb_ot_map_builder_t *map = &plan->map;
-
-  /* Do this before any lookups have been applied. */
-  map->add_gsub_pause (setup_syllables);
-
-  /* "Default glyph pre-processing group" */
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-  map->add_global_bool_feature (HB_TAG('n','u','k','t'));
-  map->add_global_bool_feature (HB_TAG('a','k','h','n'));
-
-  /* "Reordering group" */
-  map->add_gsub_pause (clear_substitution_flags);
-  map->add_feature (HB_TAG('r','p','h','f'), 1, F_MANUAL_ZWJ);
-  map->add_gsub_pause (record_rphf);
-  map->add_gsub_pause (clear_substitution_flags);
-  map->add_feature (HB_TAG('p','r','e','f'), 1, F_GLOBAL | F_MANUAL_ZWJ);
-  map->add_gsub_pause (record_pref);
-
-  /* "Orthographic unit shaping group" */
-  for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
-    map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
-
-  map->add_gsub_pause (reorder);
-
-  /* "Topographical features" */
-  for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++)
-    map->add_feature (arabic_features[i], 1, F_NONE);
-  map->add_gsub_pause (nullptr);
-
-  /* "Standard typographic presentation" and "Positional feature application" */
-  for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
-    map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
-}
-
-struct use_shape_plan_t
-{
-  ASSERT_POD ();
-
-  hb_mask_t rphf_mask;
-
-  arabic_shape_plan_t *arabic_plan;
-};
-
-static bool
-has_arabic_joining (hb_script_t script)
-{
-  /* List of scripts that have data in arabic-table. */
-  switch ((int) script)
-  {
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_ARABIC:
-
-    /* Unicode-3.0 additions */
-    case HB_SCRIPT_MONGOLIAN:
-    case HB_SCRIPT_SYRIAC:
-
-    /* Unicode-5.0 additions */
-    case HB_SCRIPT_NKO:
-    case HB_SCRIPT_PHAGS_PA:
-
-    /* Unicode-6.0 additions */
-    case HB_SCRIPT_MANDAIC:
-
-    /* Unicode-7.0 additions */
-    case HB_SCRIPT_MANICHAEAN:
-    case HB_SCRIPT_PSALTER_PAHLAVI:
-
-    /* Unicode-9.0 additions */
-    case HB_SCRIPT_ADLAM:
-
-      return true;
-
-    default:
-      return false;
-  }
-}
-
-static void *
-data_create_use (const hb_ot_shape_plan_t *plan)
-{
-  use_shape_plan_t *use_plan = (use_shape_plan_t *) calloc (1, sizeof (use_shape_plan_t));
-  if (unlikely (!use_plan))
-    return nullptr;
-
-  use_plan->rphf_mask = plan->map.get_1_mask (HB_TAG('r','p','h','f'));
-
-  if (has_arabic_joining (plan->props.script))
-  {
-    use_plan->arabic_plan = (arabic_shape_plan_t *) data_create_arabic (plan);
-    if (unlikely (!use_plan->arabic_plan))
-    {
-      free (use_plan);
-      return nullptr;
-    }
-  }
-
-  return use_plan;
-}
-
-static void
-data_destroy_use (void *data)
-{
-  use_shape_plan_t *use_plan = (use_shape_plan_t *) data;
-
-  if (use_plan->arabic_plan)
-    data_destroy_arabic (use_plan->arabic_plan);
-
-  free (data);
-}
-
-enum syllable_type_t {
-  independent_cluster,
-  virama_terminated_cluster,
-  standard_cluster,
-  number_joiner_terminated_cluster,
-  numeral_cluster,
-  symbol_cluster,
-  broken_cluster,
-  non_cluster,
-};
-
-#include "hb-ot-shape-complex-use-machine.hh"
-
-
-static void
-setup_masks_use (const hb_ot_shape_plan_t *plan,
-		 hb_buffer_t              *buffer,
-		 hb_font_t                *font HB_UNUSED)
-{
-  const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
-
-  /* Do this before allocating use_category(). */
-  if (use_plan->arabic_plan)
-  {
-    setup_masks_arabic_plan (use_plan->arabic_plan, buffer, plan->props.script);
-  }
-
-  HB_BUFFER_ALLOCATE_VAR (buffer, use_category);
-
-  /* We cannot setup masks here.  We save information about characters
-   * and setup masks later on in a pause-callback. */
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    info[i].use_category() = hb_use_get_category (info[i].codepoint);
-}
-
-static void
-setup_rphf_mask (const hb_ot_shape_plan_t *plan,
-		 hb_buffer_t *buffer)
-{
-  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;
-
-  hb_glyph_info_t *info = buffer->info;
-
-  foreach_syllable (buffer, start, end)
-  {
-    unsigned int limit = info[start].use_category() == USE_R ? 1 : MIN (3u, end - start);
-    for (unsigned int i = start; i < start + limit; i++)
-      info[i].mask |= mask;
-  }
-}
-
-static void
-setup_topographical_masks (const hb_ot_shape_plan_t *plan,
-			   hb_buffer_t *buffer)
-{
-  const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
-  if (use_plan->arabic_plan)
-    return;
-
-  static_assert ((INIT < 4 && ISOL < 4 && MEDI < 4 && FINA < 4), "");
-  hb_mask_t masks[4], all_masks = 0;
-  for (unsigned int i = 0; i < 4; i++)
-  {
-    masks[i] = plan->map.get_1_mask (arabic_features[i]);
-    if (masks[i] == plan->map.get_global_mask ())
-      masks[i] = 0;
-    all_masks |= masks[i];
-  }
-  if (!all_masks)
-    return;
-  hb_mask_t other_masks = ~all_masks;
-
-  unsigned int last_start = 0;
-  joining_form_t last_form = _NONE;
-  hb_glyph_info_t *info = buffer->info;
-  foreach_syllable (buffer, start, end)
-  {
-    syllable_type_t syllable_type = (syllable_type_t) (info[start].syllable() & 0x0F);
-    switch (syllable_type)
-    {
-      case independent_cluster:
-      case symbol_cluster:
-      case non_cluster:
-	/* These don't join.  Nothing to do. */
-	last_form = _NONE;
-	break;
-
-      case virama_terminated_cluster:
-      case standard_cluster:
-      case number_joiner_terminated_cluster:
-      case numeral_cluster:
-      case broken_cluster:
-
-	bool join = last_form == FINA || last_form == ISOL;
-
-	if (join)
-	{
-	  /* Fixup previous syllable's form. */
-	  last_form = last_form == FINA ? MEDI : INIT;
-	  for (unsigned int i = last_start; i < start; i++)
-	    info[i].mask = (info[i].mask & other_masks) | masks[last_form];
-	}
-
-	/* Form for this syllable. */
-	last_form = join ? FINA : ISOL;
-	for (unsigned int i = start; i < end; i++)
-	  info[i].mask = (info[i].mask & other_masks) | masks[last_form];
-
-	break;
-    }
-
-    last_start = start;
-  }
-}
-
-static void
-setup_syllables (const hb_ot_shape_plan_t *plan,
-		 hb_font_t *font HB_UNUSED,
-		 hb_buffer_t *buffer)
-{
-  find_syllables (buffer);
-  foreach_syllable (buffer, start, end)
-    buffer->unsafe_to_break (start, end);
-  setup_rphf_mask (plan, buffer);
-  setup_topographical_masks (plan, buffer);
-}
-
-static void
-clear_substitution_flags (const hb_ot_shape_plan_t *plan,
-			  hb_font_t *font HB_UNUSED,
-			  hb_buffer_t *buffer)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-    _hb_glyph_info_clear_substituted (&info[i]);
-}
-
-static void
-record_rphf (const hb_ot_shape_plan_t *plan,
-	     hb_font_t *font,
-	     hb_buffer_t *buffer)
-{
-  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;
-  hb_glyph_info_t *info = buffer->info;
-
-  foreach_syllable (buffer, start, end)
-  {
-    /* Mark a substituted repha as USE_R. */
-    for (unsigned int i = start; i < end && (info[i].mask & mask); i++)
-      if (_hb_glyph_info_substituted (&info[i]))
-      {
-	info[i].use_category() = USE_R;
-	break;
-      }
-  }
-}
-
-static void
-record_pref (const hb_ot_shape_plan_t *plan,
-	     hb_font_t *font,
-	     hb_buffer_t *buffer)
-{
-  hb_glyph_info_t *info = buffer->info;
-
-  foreach_syllable (buffer, start, end)
-  {
-    /* Mark a substituted pref as VPre, as they behave the same way. */
-    for (unsigned int i = start; i < end; i++)
-      if (_hb_glyph_info_substituted (&info[i]))
-      {
-	info[i].use_category() = USE_VPre;
-	break;
-      }
-  }
-}
-
-static inline bool
-is_halant (const hb_glyph_info_t &info)
-{
-  return info.use_category() == USE_H && !_hb_glyph_info_ligated (&info);
-}
-
-static void
-reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
-{
-  syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
-  /* Only a few syllable types need reordering. */
-  if (unlikely (!(FLAG_UNSAFE (syllable_type) &
-		  (FLAG (virama_terminated_cluster) |
-		   FLAG (standard_cluster) |
-		   FLAG (broken_cluster) |
-		   0))))
-    return;
-
-  hb_glyph_info_t *info = buffer->info;
-
-#define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB))
-
-  /* Move things forward. */
-  if (info[start].use_category() == USE_R && end - start > 1)
-  {
-    /* Got a repha.  Reorder it to after first base, before first halant. */
-    for (unsigned int i = start + 1; i < end; i++)
-      if ((FLAG_UNSAFE (info[i].use_category()) & (BASE_FLAGS)) || is_halant (info[i]))
-      {
-	/* If we hit a halant, move before it; otherwise it's a base: move to it's
-	 * place, and shift things in between backward. */
-
-	if (is_halant (info[i]))
-	  i--;
-
-	buffer->merge_clusters (start, i + 1);
-	hb_glyph_info_t t = info[start];
-	memmove (&info[start], &info[start + 1], (i - start) * sizeof (info[0]));
-	info[i] = t;
-
-	break;
-      }
-  }
-
-  /* Move things back. */
-  unsigned int j = end;
-  for (unsigned int i = start; i < end; i++)
-  {
-    uint32_t flag = FLAG_UNSAFE (info[i].use_category());
-    if ((flag & (BASE_FLAGS)) || is_halant (info[i]))
-    {
-      /* If we hit a halant, move after it; otherwise it's a base: move to it's
-       * place, and shift things in between backward. */
-      if (is_halant (info[i]))
-	j = i + 1;
-      else
-	j = i;
-    }
-    else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) &&
-	     /* Only move the first component of a MultipleSubst. */
-	     0 == _hb_glyph_info_get_lig_comp (&info[i]) &&
-	     j < i)
-    {
-      buffer->merge_clusters (j, i + 1);
-      hb_glyph_info_t t = info[i];
-      memmove (&info[j + 1], &info[j], (i - j) * sizeof (info[0]));
-      info[j] = t;
-    }
-  }
-}
-
-static inline void
-insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
-		       hb_font_t *font,
-		       hb_buffer_t *buffer)
-{
-  /* Note: This loop is extra overhead, but should not be measurable. */
-  bool has_broken_syllables = false;
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    if ((info[i].syllable() & 0x0F) == broken_cluster)
-    {
-      has_broken_syllables = true;
-      break;
-    }
-  if (likely (!has_broken_syllables))
-    return;
-
-  hb_glyph_info_t dottedcircle = {0};
-  if (!font->get_nominal_glyph (0x25CCu, &dottedcircle.codepoint))
-    return;
-  dottedcircle.use_category() = hb_use_get_category (0x25CC);
-
-  buffer->clear_output ();
-
-  buffer->idx = 0;
-  unsigned int last_syllable = 0;
-  while (buffer->idx < buffer->len && !buffer->in_error)
-  {
-    unsigned int syllable = buffer->cur().syllable();
-    syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
-    if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
-    {
-      last_syllable = syllable;
-
-      hb_glyph_info_t ginfo = dottedcircle;
-      ginfo.cluster = buffer->cur().cluster;
-      ginfo.mask = buffer->cur().mask;
-      ginfo.syllable() = buffer->cur().syllable();
-      /* TODO Set glyph_props? */
-
-      /* Insert dottedcircle after possible Repha. */
-      while (buffer->idx < buffer->len && !buffer->in_error &&
-	     last_syllable == buffer->cur().syllable() &&
-	     buffer->cur().use_category() == USE_R)
-        buffer->next_glyph ();
-
-      buffer->output_info (ginfo);
-    }
-    else
-      buffer->next_glyph ();
-  }
-
-  buffer->swap_buffers ();
-}
-
-static void
-reorder (const hb_ot_shape_plan_t *plan,
-	 hb_font_t *font,
-	 hb_buffer_t *buffer)
-{
-  insert_dotted_circles (plan, font, buffer);
-
-  hb_glyph_info_t *info = buffer->info;
-
-  foreach_syllable (buffer, start, end)
-    reorder_syllable (buffer, start, end);
-
-  /* Zero syllables now... */
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-    info[i].syllable() = 0;
-
-  HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
-}
-
-static bool
-decompose_use (const hb_ot_shape_normalize_context_t *c,
-                hb_codepoint_t  ab,
-                hb_codepoint_t *a,
-                hb_codepoint_t *b)
-{
-  switch (ab)
-  {
-    /* Chakma:
-     * Special case where the Unicode decomp gives matras in the wrong order
-     * for cluster validation.
-     */
-    case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true;
-    case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true;
-  }
-
-  return (bool) c->unicode->decompose (ab, a, b);
-}
-
-static bool
-compose_use (const hb_ot_shape_normalize_context_t *c,
-	     hb_codepoint_t  a,
-	     hb_codepoint_t  b,
-	     hb_codepoint_t *ab)
-{
-  /* Avoid recomposing split matras. */
-  if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a)))
-    return false;
-
-  return (bool)c->unicode->compose (a, b, ab);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
-{
-  collect_features_use,
-  nullptr, /* override_features */
-  data_create_use,
-  data_destroy_use,
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
-  decompose_use,
-  compose_use,
-  setup_masks_use,
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
-  false, /* fallback_position */
-};
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-fallback-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-fallback-private.hh
deleted file mode 100644
index e134224d..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-fallback-private.hh
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_FALLBACK_PRIVATE_HH
-#define HB_OT_SHAPE_FALLBACK_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-private.hh"
-
-
-HB_INTERNAL void _hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
-						 hb_font_t *font,
-						 hb_buffer_t  *buffer);
-
-HB_INTERNAL void _hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan,
-								    hb_font_t *font,
-								    hb_buffer_t  *buffer);
-
-
-HB_INTERNAL void _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
-					     hb_font_t *font,
-					     hb_buffer_t  *buffer);
-
-HB_INTERNAL void _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
-					       hb_font_t *font,
-					       hb_buffer_t  *buffer);
-
-
-#endif /* HB_OT_SHAPE_FALLBACK_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc
deleted file mode 100644
index c7b4605..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-fallback-private.hh"
-#include "hb-ot-layout-gsubgpos-private.hh"
-
-static unsigned int
-recategorize_combining_class (hb_codepoint_t u,
-			      unsigned int klass)
-{
-  if (klass >= 200)
-    return klass;
-
-  /* Thai / Lao need some per-character work. */
-  if ((u & ~0xFF) == 0x0E00u)
-  {
-    if (unlikely (klass == 0))
-    {
-      switch (u)
-      {
-        case 0x0E31u:
-        case 0x0E34u:
-        case 0x0E35u:
-        case 0x0E36u:
-        case 0x0E37u:
-        case 0x0E47u:
-        case 0x0E4Cu:
-        case 0x0E4Du:
-        case 0x0E4Eu:
-	  klass = HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
-	  break;
-
-        case 0x0EB1u:
-        case 0x0EB4u:
-        case 0x0EB5u:
-        case 0x0EB6u:
-        case 0x0EB7u:
-        case 0x0EBBu:
-        case 0x0ECCu:
-        case 0x0ECDu:
-	  klass = HB_UNICODE_COMBINING_CLASS_ABOVE;
-	  break;
-
-        case 0x0EBCu:
-	  klass = HB_UNICODE_COMBINING_CLASS_BELOW;
-	  break;
-      }
-    } else {
-      /* Thai virama is below-right */
-      if (u == 0x0E3Au)
-	klass = HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT;
-    }
-  }
-
-  switch (klass)
-  {
-
-    /* Hebrew */
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC10: /* sheva */
-    case HB_MODIFIED_COMBINING_CLASS_CCC11: /* hataf segol */
-    case HB_MODIFIED_COMBINING_CLASS_CCC12: /* hataf patah */
-    case HB_MODIFIED_COMBINING_CLASS_CCC13: /* hataf qamats */
-    case HB_MODIFIED_COMBINING_CLASS_CCC14: /* hiriq */
-    case HB_MODIFIED_COMBINING_CLASS_CCC15: /* tsere */
-    case HB_MODIFIED_COMBINING_CLASS_CCC16: /* segol */
-    case HB_MODIFIED_COMBINING_CLASS_CCC17: /* patah */
-    case HB_MODIFIED_COMBINING_CLASS_CCC18: /* qamats */
-    case HB_MODIFIED_COMBINING_CLASS_CCC20: /* qubuts */
-    case HB_MODIFIED_COMBINING_CLASS_CCC22: /* meteg */
-      return HB_UNICODE_COMBINING_CLASS_BELOW;
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC23: /* rafe */
-      return HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE;
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC24: /* shin dot */
-      return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC25: /* sin dot */
-    case HB_MODIFIED_COMBINING_CLASS_CCC19: /* holam */
-      return HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT;
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC26: /* point varika */
-      return HB_UNICODE_COMBINING_CLASS_ABOVE;
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC21: /* dagesh */
-      break;
-
-
-    /* Arabic and Syriac */
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC27: /* fathatan */
-    case HB_MODIFIED_COMBINING_CLASS_CCC28: /* dammatan */
-    case HB_MODIFIED_COMBINING_CLASS_CCC30: /* fatha */
-    case HB_MODIFIED_COMBINING_CLASS_CCC31: /* damma */
-    case HB_MODIFIED_COMBINING_CLASS_CCC33: /* shadda */
-    case HB_MODIFIED_COMBINING_CLASS_CCC34: /* sukun */
-    case HB_MODIFIED_COMBINING_CLASS_CCC35: /* superscript alef */
-    case HB_MODIFIED_COMBINING_CLASS_CCC36: /* superscript alaph */
-      return HB_UNICODE_COMBINING_CLASS_ABOVE;
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC29: /* kasratan */
-    case HB_MODIFIED_COMBINING_CLASS_CCC32: /* kasra */
-      return HB_UNICODE_COMBINING_CLASS_BELOW;
-
-
-    /* Thai */
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC103: /* sara u / sara uu */
-      return HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT;
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC107: /* mai */
-      return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
-
-
-    /* Lao */
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC118: /* sign u / sign uu */
-      return HB_UNICODE_COMBINING_CLASS_BELOW;
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC122: /* mai */
-      return HB_UNICODE_COMBINING_CLASS_ABOVE;
-
-
-    /* Tibetan */
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC129: /* sign aa */
-      return HB_UNICODE_COMBINING_CLASS_BELOW;
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC130: /* sign i*/
-      return HB_UNICODE_COMBINING_CLASS_ABOVE;
-
-    case HB_MODIFIED_COMBINING_CLASS_CCC132: /* sign u */
-      return HB_UNICODE_COMBINING_CLASS_BELOW;
-
-  }
-
-  return klass;
-}
-
-void
-_hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
-						   hb_font_t *font HB_UNUSED,
-						   hb_buffer_t  *buffer)
-{
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) {
-      unsigned int combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]);
-      combining_class = recategorize_combining_class (info[i].codepoint, combining_class);
-      _hb_glyph_info_set_modified_combining_class (&info[i], combining_class);
-    }
-}
-
-
-static void
-zero_mark_advances (hb_buffer_t *buffer,
-		    unsigned int start,
-		    unsigned int end)
-{
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = start; i < end; i++)
-    if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
-    {
-      buffer->pos[i].x_advance = 0;
-      buffer->pos[i].y_advance = 0;
-    }
-}
-
-static inline void
-position_mark (const hb_ot_shape_plan_t *plan,
-	       hb_font_t *font,
-	       hb_buffer_t  *buffer,
-	       hb_glyph_extents_t &base_extents,
-	       unsigned int i,
-	       unsigned int combining_class)
-{
-  hb_glyph_extents_t mark_extents;
-  if (!font->get_glyph_extents (buffer->info[i].codepoint, &mark_extents))
-    return;
-
-  hb_position_t y_gap = font->y_scale / 16;
-
-  hb_glyph_position_t &pos = buffer->pos[i];
-  pos.x_offset = pos.y_offset = 0;
-
-
-  /* We don't position LEFT and RIGHT marks. */
-
-  /* X positioning */
-  switch (combining_class)
-  {
-    case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
-    case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
-      if (buffer->props.direction == HB_DIRECTION_LTR) {
-	pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing;
-        break;
-      } else if (buffer->props.direction == HB_DIRECTION_RTL) {
-	pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 - mark_extents.x_bearing;
-        break;
-      }
-      HB_FALLTHROUGH;
-
-    default:
-    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
-    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
-    case HB_UNICODE_COMBINING_CLASS_BELOW:
-    case HB_UNICODE_COMBINING_CLASS_ABOVE:
-      /* Center align. */
-      pos.x_offset += base_extents.x_bearing + (base_extents.width - mark_extents.width) / 2 - mark_extents.x_bearing;
-      break;
-
-    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
-    case HB_UNICODE_COMBINING_CLASS_BELOW_LEFT:
-    case HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT:
-      /* Left align. */
-      pos.x_offset += base_extents.x_bearing - mark_extents.x_bearing;
-      break;
-
-    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
-    case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
-    case HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT:
-      /* Right align. */
-      pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width - mark_extents.x_bearing;
-      break;
-  }
-
-  /* Y positioning */
-  switch (combining_class)
-  {
-    case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
-    case HB_UNICODE_COMBINING_CLASS_BELOW_LEFT:
-    case HB_UNICODE_COMBINING_CLASS_BELOW:
-    case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
-      /* Add gap, fall-through. */
-      base_extents.height -= y_gap;
-      HB_FALLTHROUGH;
-
-    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
-    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
-      pos.y_offset = base_extents.y_bearing + base_extents.height - mark_extents.y_bearing;
-      /* Never shift up "below" marks. */
-      if ((y_gap > 0) == (pos.y_offset > 0))
-      {
-	base_extents.height -= pos.y_offset;
-	pos.y_offset = 0;
-      }
-      base_extents.height += mark_extents.height;
-      break;
-
-    case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
-    case HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT:
-    case HB_UNICODE_COMBINING_CLASS_ABOVE:
-    case HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT:
-      /* Add gap, fall-through. */
-      base_extents.y_bearing += y_gap;
-      base_extents.height -= y_gap;
-      HB_FALLTHROUGH;
-
-    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
-    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
-      pos.y_offset = base_extents.y_bearing - (mark_extents.y_bearing + mark_extents.height);
-      /* Don't shift down "above" marks too much. */
-      if ((y_gap > 0) != (pos.y_offset > 0))
-      {
-	unsigned int correction = -pos.y_offset / 2;
-	base_extents.y_bearing += correction;
-	base_extents.height -= correction;
-	pos.y_offset += correction;
-      }
-      base_extents.y_bearing -= mark_extents.height;
-      base_extents.height += mark_extents.height;
-      break;
-  }
-}
-
-static inline void
-position_around_base (const hb_ot_shape_plan_t *plan,
-		      hb_font_t *font,
-		      hb_buffer_t  *buffer,
-		      unsigned int base,
-		      unsigned int end)
-{
-  hb_direction_t horiz_dir = HB_DIRECTION_INVALID;
-
-  buffer->unsafe_to_break (base, end);
-
-  hb_glyph_extents_t base_extents;
-  if (!font->get_glyph_extents (buffer->info[base].codepoint,
-				&base_extents))
-  {
-    /* If extents don't work, zero marks and go home. */
-    zero_mark_advances (buffer, base + 1, end);
-    return;
-  }
-  base_extents.x_bearing += buffer->pos[base].x_offset;
-  base_extents.y_bearing += buffer->pos[base].y_offset;
-
-  unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[base]);
-  /* Use integer for num_lig_components such that it doesn't convert to unsigned
-   * when we divide or multiply by it. */
-  int num_lig_components = _hb_glyph_info_get_lig_num_comps (&buffer->info[base]);
-
-  hb_position_t x_offset = 0, y_offset = 0;
-  if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
-    x_offset -= buffer->pos[base].x_advance;
-    y_offset -= buffer->pos[base].y_advance;
-  }
-
-  hb_glyph_extents_t component_extents = base_extents;
-  int last_lig_component = -1;
-  unsigned int last_combining_class = 255;
-  hb_glyph_extents_t cluster_extents = base_extents; /* Initialization is just to shut gcc up. */
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = base + 1; i < end; i++)
-    if (_hb_glyph_info_get_modified_combining_class (&info[i]))
-    {
-      if (num_lig_components > 1) {
-	unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&info[i]);
-	int this_lig_component = _hb_glyph_info_get_lig_comp (&info[i]) - 1;
-	/* Conditions for attaching to the last component. */
-	if (!lig_id || lig_id != this_lig_id || this_lig_component >= num_lig_components)
-	  this_lig_component = num_lig_components - 1;
-	if (last_lig_component != this_lig_component)
-	{
-	  last_lig_component = this_lig_component;
-	  last_combining_class = 255;
-	  component_extents = base_extents;
-	  if (unlikely (horiz_dir == HB_DIRECTION_INVALID)) {
-	    if (HB_DIRECTION_IS_HORIZONTAL (plan->props.direction))
-	      horiz_dir = plan->props.direction;
-	    else
-	      horiz_dir = hb_script_get_horizontal_direction (plan->props.script);
-	  }
-	  if (horiz_dir == HB_DIRECTION_LTR)
-	    component_extents.x_bearing += (this_lig_component * component_extents.width) / num_lig_components;
-	  else
-	    component_extents.x_bearing += ((num_lig_components - 1 - this_lig_component) * component_extents.width) / num_lig_components;
-	  component_extents.width /= num_lig_components;
-	}
-      }
-
-      unsigned int this_combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]);
-      if (last_combining_class != this_combining_class)
-      {
-	last_combining_class = this_combining_class;
-        cluster_extents = component_extents;
-      }
-
-      position_mark (plan, font, buffer, cluster_extents, i, this_combining_class);
-
-      buffer->pos[i].x_advance = 0;
-      buffer->pos[i].y_advance = 0;
-      buffer->pos[i].x_offset += x_offset;
-      buffer->pos[i].y_offset += y_offset;
-
-    } else {
-      if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
-	x_offset -= buffer->pos[i].x_advance;
-	y_offset -= buffer->pos[i].y_advance;
-      } else {
-	x_offset += buffer->pos[i].x_advance;
-	y_offset += buffer->pos[i].y_advance;
-      }
-    }
-}
-
-static inline void
-position_cluster (const hb_ot_shape_plan_t *plan,
-		  hb_font_t *font,
-		  hb_buffer_t  *buffer,
-		  unsigned int start,
-		  unsigned int end)
-{
-  if (end - start < 2)
-    return;
-
-  /* Find the base glyph */
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = start; i < end; i++)
-    if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))
-    {
-      /* Find mark glyphs */
-      unsigned int j;
-      for (j = i + 1; j < end; j++)
-	if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[j])))
-	  break;
-
-      position_around_base (plan, font, buffer, i, j);
-
-      i = j - 1;
-    }
-}
-
-void
-_hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
-				hb_font_t *font,
-				hb_buffer_t  *buffer)
-{
-  _hb_buffer_assert_gsubgpos_vars (buffer);
-
-  unsigned int start = 0;
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 1; i < count; i++)
-    if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) {
-      position_cluster (plan, font, buffer, start, i);
-      start = i;
-    }
-  position_cluster (plan, font, buffer, start, count);
-}
-
-
-/* Performs old-style TrueType kerning. */
-void
-_hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
-			    hb_font_t *font,
-			    hb_buffer_t  *buffer)
-{
-  if (!plan->has_kern) return;
-
-  OT::hb_ot_apply_context_t c (1, font, buffer);
-  c.set_lookup_mask (plan->kern_mask);
-  c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
-  OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
-  skippy_iter.init (&c);
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  hb_glyph_position_t *pos = buffer->pos;
-  for (unsigned int idx = 0; idx < count;)
-  {
-    skippy_iter.reset (idx, 1);
-    if (!skippy_iter.next ())
-    {
-      idx++;
-      continue;
-    }
-
-    hb_position_t x_kern, y_kern;
-    font->get_glyph_kerning_for_direction (info[idx].codepoint,
-					   info[skippy_iter.idx].codepoint,
-					   buffer->props.direction,
-					   &x_kern, &y_kern);
-
-    if (x_kern)
-    {
-      hb_position_t kern1 = x_kern >> 1;
-      hb_position_t kern2 = x_kern - kern1;
-      pos[idx].x_advance += kern1;
-      pos[skippy_iter.idx].x_advance += kern2;
-      pos[skippy_iter.idx].x_offset += kern2;
-      buffer->unsafe_to_break (idx, skippy_iter.idx + 1);
-    }
-
-    if (y_kern)
-    {
-      hb_position_t kern1 = y_kern >> 1;
-      hb_position_t kern2 = y_kern - kern1;
-      pos[idx].y_advance += kern1;
-      pos[skippy_iter.idx].y_advance += kern2;
-      pos[skippy_iter.idx].y_offset += kern2;
-      buffer->unsafe_to_break (idx, skippy_iter.idx + 1);
-    }
-
-    idx = skippy_iter.idx;
-  }
-}
-
-
-/* Adjusts width of various spaces. */
-void
-_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
-			      hb_font_t *font,
-			      hb_buffer_t  *buffer)
-{
-  if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
-    return;
-
-  hb_glyph_info_t *info = buffer->info;
-  hb_glyph_position_t *pos = buffer->pos;
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-    if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i]))
-    {
-      hb_unicode_funcs_t::space_t space_type = _hb_glyph_info_get_unicode_space_fallback_type (&info[i]);
-      hb_codepoint_t glyph;
-      typedef hb_unicode_funcs_t t;
-      switch (space_type)
-      {
-	case t::NOT_SPACE: /* Shouldn't happen. */
-	case t::SPACE:
-	  break;
-
-	case t::SPACE_EM:
-	case t::SPACE_EM_2:
-	case t::SPACE_EM_3:
-	case t::SPACE_EM_4:
-	case t::SPACE_EM_5:
-	case t::SPACE_EM_6:
-	case t::SPACE_EM_16:
-	  pos[i].x_advance = (font->x_scale + ((int) space_type)/2) / (int) space_type;
-	  break;
-
-	case t::SPACE_4_EM_18:
-	  pos[i].x_advance = (int64_t) font->x_scale * 4 / 18;
-	  break;
-
-	case t::SPACE_FIGURE:
-	  for (char u = '0'; u <= '9'; u++)
-	    if (font->get_nominal_glyph (u, &glyph))
-	    {
-	      pos[i].x_advance = font->get_glyph_h_advance (glyph);
-	      break;
-	    }
-	  break;
-
-	case t::SPACE_PUNCTUATION:
-	  if (font->get_nominal_glyph ('.', &glyph))
-	    pos[i].x_advance = font->get_glyph_h_advance (glyph);
-	  else if (font->get_nominal_glyph (',', &glyph))
-	    pos[i].x_advance = font->get_glyph_h_advance (glyph);
-	  break;
-
-	case t::SPACE_NARROW:
-	  /* Half-space?
-	   * Unicode doc http://www.unicode.org/charts/PDF/U2000.pdf says ~1/4 or 1/5 of EM.
-	   * However, in my testing, many fonts have their regular space being about that
-	   * size.  To me, a percentage of the space width makes more sense.  Half is as
-	   * good as any. */
-	  pos[i].x_advance /= 2;
-	  break;
-      }
-    }
-}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh
deleted file mode 100644
index c744e26..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_NORMALIZE_PRIVATE_HH
-#define HB_OT_SHAPE_NORMALIZE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-/* buffer var allocations, used during the normalization process */
-#define glyph_index()	var1.u32
-
-struct hb_ot_shape_plan_t;
-
-enum hb_ot_shape_normalization_mode_t {
-  HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
-  HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED,
-  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* never composes base-to-base */
-  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* always fully decomposes and then recompose back */
-
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS
-};
-
-HB_INTERNAL void _hb_ot_shape_normalize (const hb_ot_shape_plan_t *shaper,
-					 hb_buffer_t *buffer,
-					 hb_font_t *font);
-
-
-struct hb_ot_shape_normalize_context_t
-{
-  const hb_ot_shape_plan_t *plan;
-  hb_buffer_t *buffer;
-  hb_font_t *font;
-  hb_unicode_funcs_t *unicode;
-  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
-		     hb_codepoint_t  ab,
-		     hb_codepoint_t *a,
-		     hb_codepoint_t *b);
-  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
-		   hb_codepoint_t  a,
-		   hb_codepoint_t  b,
-		   hb_codepoint_t *ab);
-};
-
-
-#endif /* HB_OT_SHAPE_NORMALIZE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc
deleted file mode 100644
index 62cbb9d..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-normalize-private.hh"
-#include "hb-ot-shape-complex-private.hh"
-#include "hb-ot-shape-private.hh"
-
-
-/*
- * HIGHLEVEL DESIGN:
- *
- * This file exports one main function: _hb_ot_shape_normalize().
- *
- * This function closely reflects the Unicode Normalization Algorithm,
- * yet it's different.
- *
- * Each shaper specifies whether it prefers decomposed (NFD) or composed (NFC).
- * The logic however tries to use whatever the font can support.
- *
- * In general what happens is that: each grapheme is decomposed in a chain
- * of 1:2 decompositions, marks reordered, and then recomposed if desired,
- * so far it's like Unicode Normalization.  However, the decomposition and
- * recomposition only happens if the font supports the resulting characters.
- *
- * The goals are:
- *
- *   - Try to render all canonically equivalent strings similarly.  To really
- *     achieve this we have to always do the full decomposition and then
- *     selectively recompose from there.  It's kinda too expensive though, so
- *     we skip some cases.  For example, if composed is desired, we simply
- *     don't touch 1-character clusters that are supported by the font, even
- *     though their NFC may be different.
- *
- *   - When a font has a precomposed character for a sequence but the 'ccmp'
- *     feature in the font is not adequate, use the precomposed character
- *     which typically has better mark positioning.
- *
- *   - When a font does not support a combining mark, but supports it precomposed
- *     with previous base, use that.  This needs the itemizer to have this
- *     knowledge too.  We need to provide assistance to the itemizer.
- *
- *   - When a font does not support a character but supports its canonical
- *     decomposition, well, use the decomposition.
- *
- *   - The complex shapers can customize the compose and decompose functions to
- *     offload some of their requirements to the normalizer.  For example, the
- *     Indic shaper may want to disallow recomposing of two matras.
- */
-
-static bool
-decompose_unicode (const hb_ot_shape_normalize_context_t *c,
-		   hb_codepoint_t  ab,
-		   hb_codepoint_t *a,
-		   hb_codepoint_t *b)
-{
-  return (bool) c->unicode->decompose (ab, a, b);
-}
-
-static bool
-compose_unicode (const hb_ot_shape_normalize_context_t *c,
-		 hb_codepoint_t  a,
-		 hb_codepoint_t  b,
-		 hb_codepoint_t *ab)
-{
-  return (bool) c->unicode->compose (a, b, ab);
-}
-
-static inline void
-set_glyph (hb_glyph_info_t &info, hb_font_t *font)
-{
-  (void) font->get_nominal_glyph (info.codepoint, &info.glyph_index());
-}
-
-static inline void
-output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph)
-{
-  buffer->cur().glyph_index() = glyph;
-  buffer->output_glyph (unichar); /* This is very confusing indeed. */
-  _hb_glyph_info_set_unicode_props (&buffer->prev(), buffer);
-}
-
-static inline void
-next_char (hb_buffer_t *buffer, hb_codepoint_t glyph)
-{
-  buffer->cur().glyph_index() = glyph;
-  buffer->next_glyph ();
-}
-
-static inline void
-skip_char (hb_buffer_t *buffer)
-{
-  buffer->skip_glyph ();
-}
-
-/* Returns 0 if didn't decompose, number of resulting characters otherwise. */
-static inline unsigned int
-decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint_t ab)
-{
-  hb_codepoint_t a, b, a_glyph, b_glyph;
-  hb_buffer_t * const buffer = c->buffer;
-  hb_font_t * const font = c->font;
-
-  if (!c->decompose (c, ab, &a, &b) ||
-      (b && !font->get_nominal_glyph (b, &b_glyph)))
-    return 0;
-
-  bool has_a = (bool) font->get_nominal_glyph (a, &a_glyph);
-  if (shortest && has_a) {
-    /* Output a and b */
-    output_char (buffer, a, a_glyph);
-    if (likely (b)) {
-      output_char (buffer, b, b_glyph);
-      return 2;
-    }
-    return 1;
-  }
-
-  unsigned int ret;
-  if ((ret = decompose (c, shortest, a))) {
-    if (b) {
-      output_char (buffer, b, b_glyph);
-      return ret + 1;
-    }
-    return ret;
-  }
-
-  if (has_a) {
-    output_char (buffer, a, a_glyph);
-    if (likely (b)) {
-      output_char (buffer, b, b_glyph);
-      return 2;
-    }
-    return 1;
-  }
-
-  return 0;
-}
-
-static inline void
-decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shortest)
-{
-  hb_buffer_t * const buffer = c->buffer;
-  hb_codepoint_t u = buffer->cur().codepoint;
-  hb_codepoint_t glyph;
-
-  if (shortest && c->font->get_nominal_glyph (u, &glyph))
-  {
-    next_char (buffer, glyph);
-    return;
-  }
-
-  if (decompose (c, shortest, u))
-  {
-    skip_char (buffer);
-    return;
-  }
-
-  if (!shortest && c->font->get_nominal_glyph (u, &glyph))
-  {
-    next_char (buffer, glyph);
-    return;
-  }
-
-  if (_hb_glyph_info_is_unicode_space (&buffer->cur()))
-  {
-    hb_codepoint_t space_glyph;
-    hb_unicode_funcs_t::space_t space_type = buffer->unicode->space_fallback_type (u);
-    if (space_type != hb_unicode_funcs_t::NOT_SPACE && c->font->get_nominal_glyph (0x0020u, &space_glyph))
-    {
-      _hb_glyph_info_set_unicode_space_fallback_type (&buffer->cur(), space_type);
-      next_char (buffer, space_glyph);
-      buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK;
-      return;
-    }
-  }
-
-  if (u == 0x2011u)
-  {
-    /* U+2011 is the only sensible character that is a no-break version of another character
-     * and not a space.  The space ones are handled already.  Handle this lone one. */
-    hb_codepoint_t other_glyph;
-    if (c->font->get_nominal_glyph (0x2010u, &other_glyph))
-    {
-      next_char (buffer, other_glyph);
-      return;
-    }
-  }
-
-  next_char (buffer, glyph); /* glyph is initialized in earlier branches. */
-}
-
-static inline void
-handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit)
-{
-  /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
-  hb_buffer_t * const buffer = c->buffer;
-  hb_font_t * const font = c->font;
-  for (; buffer->idx < end - 1 && !buffer->in_error;) {
-    if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) {
-      /* The next two lines are some ugly lines... But work. */
-      if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
-      {
-	buffer->replace_glyphs (2, 1, &buffer->cur().codepoint);
-      }
-      else
-      {
-        /* Just pass on the two characters separately, let GSUB do its magic. */
-	set_glyph (buffer->cur(), font);
-	buffer->next_glyph ();
-	set_glyph (buffer->cur(), font);
-	buffer->next_glyph ();
-      }
-      /* Skip any further variation selectors. */
-      while (buffer->idx < end && unlikely (buffer->unicode->is_variation_selector (buffer->cur().codepoint)))
-      {
-	set_glyph (buffer->cur(), font);
-	buffer->next_glyph ();
-      }
-    } else {
-      set_glyph (buffer->cur(), font);
-      buffer->next_glyph ();
-    }
-  }
-  if (likely (buffer->idx < end)) {
-    set_glyph (buffer->cur(), font);
-    buffer->next_glyph ();
-  }
-}
-
-static inline void
-decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit)
-{
-  hb_buffer_t * const buffer = c->buffer;
-  for (unsigned int i = buffer->idx; i < end && !buffer->in_error; i++)
-    if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) {
-      handle_variation_selector_cluster (c, end, short_circuit);
-      return;
-    }
-
-  while (buffer->idx < end && !buffer->in_error)
-    decompose_current_character (c, short_circuit);
-}
-
-static inline void
-decompose_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool might_short_circuit, bool always_short_circuit)
-{
-  if (likely (c->buffer->idx + 1 == end))
-    decompose_current_character (c, might_short_circuit);
-  else
-    decompose_multi_char_cluster (c, end, always_short_circuit);
-}
-
-
-static int
-compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
-{
-  unsigned int a = _hb_glyph_info_get_modified_combining_class (pa);
-  unsigned int b = _hb_glyph_info_get_modified_combining_class (pb);
-
-  return a < b ? -1 : a == b ? 0 : +1;
-}
-
-
-void
-_hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
-			hb_buffer_t *buffer,
-			hb_font_t *font)
-{
-  if (unlikely (!buffer->len)) return;
-
-  _hb_buffer_assert_unicode_vars (buffer);
-
-  hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference;
-  const hb_ot_shape_normalize_context_t c = {
-    plan,
-    buffer,
-    font,
-    buffer->unicode,
-    plan->shaper->decompose ? plan->shaper->decompose : decompose_unicode,
-    plan->shaper->compose   ? plan->shaper->compose   : compose_unicode
-  };
-
-  bool always_short_circuit = mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE;
-  bool might_short_circuit = always_short_circuit ||
-			     (mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED &&
-			      mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT);
-  unsigned int count;
-
-  /* We do a fairly straightforward yet custom normalization process in three
-   * separate rounds: decompose, reorder, recompose (if desired).  Currently
-   * this makes two buffer swaps.  We can make it faster by moving the last
-   * two rounds into the inner loop for the first round, but it's more readable
-   * this way. */
-
-
-  /* First round, decompose */
-
-  buffer->clear_output ();
-  count = buffer->len;
-  for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;)
-  {
-    unsigned int end;
-    for (end = buffer->idx + 1; end < count; end++)
-      if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))))
-        break;
-
-    decompose_cluster (&c, end, might_short_circuit, always_short_circuit);
-  }
-  buffer->swap_buffers ();
-
-
-  /* Second round, reorder (inplace) */
-
-  count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0)
-      continue;
-
-    unsigned int end;
-    for (end = i + 1; end < count; end++)
-      if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
-        break;
-
-    /* We are going to do a O(n^2).  Only do this if the sequence is short. */
-    if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
-      i = end;
-      continue;
-    }
-
-    buffer->sort (i, end, compare_combining_class);
-
-    if (plan->shaper->reorder_marks)
-      plan->shaper->reorder_marks (plan, buffer, i, end);
-
-    i = end;
-  }
-
-
-  if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE ||
-      mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED)
-    return;
-
-  /* Third round, recompose */
-
-  /* As noted in the comment earlier, we don't try to combine
-   * ccc=0 chars with their previous Starter. */
-
-  buffer->clear_output ();
-  count = buffer->len;
-  unsigned int starter = 0;
-  buffer->next_glyph ();
-  while (buffer->idx < count && !buffer->in_error)
-  {
-    hb_codepoint_t composed, glyph;
-    if (/* We don't try to compose a non-mark character with it's preceding starter.
-	 * This is both an optimization to avoid trying to compose every two neighboring
-	 * glyphs in most scripts AND a desired feature for Hangul.  Apparently Hangul
-	 * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */
-	HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())))
-    {
-      if (/* If there's anything between the starter and this char, they should have CCC
-	   * smaller than this character's. */
-	  (starter == buffer->out_len - 1 ||
-	   info_cc (buffer->prev()) < info_cc (buffer->cur())) &&
-	  /* And compose. */
-	  c.compose (&c,
-		     buffer->out_info[starter].codepoint,
-		     buffer->cur().codepoint,
-		     &composed) &&
-	  /* And the font has glyph for the composite. */
-	  font->get_nominal_glyph (composed, &glyph))
-      {
-	/* Composes. */
-	buffer->next_glyph (); /* Copy to out-buffer. */
-	if (unlikely (buffer->in_error))
-	  return;
-	buffer->merge_out_clusters (starter, buffer->out_len);
-	buffer->out_len--; /* Remove the second composable. */
-	/* Modify starter and carry on. */
-	buffer->out_info[starter].codepoint = composed;
-	buffer->out_info[starter].glyph_index() = glyph;
-	_hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer);
-
-	continue;
-      }
-    }
-
-    /* Blocked, or doesn't compose. */
-    buffer->next_glyph ();
-
-    if (info_cc (buffer->prev()) == 0)
-      starter = buffer->out_len - 1;
-  }
-  buffer->swap_buffers ();
-
-  if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_CGJ)
-  {
-    /* For all CGJ, check if it prevented any reordering at all.
-     * If it did NOT, then make it skippable.
-     * https://github.com/harfbuzz/harfbuzz/issues/554
-     */
-    for (unsigned int i = 1; i + 1 < buffer->len; i++)
-      if (buffer->info[i].codepoint == 0x034Fu/*CGJ*/ &&
-	  info_cc(buffer->info[i-1]) <= info_cc(buffer->info[i+1]))
-      {
-	_hb_glyph_info_unhide (&buffer->info[i]);
-      }
-  }
-}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh
deleted file mode 100644
index fe5d2b7f..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright © 2010  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_PRIVATE_HH
-#define HB_OT_SHAPE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-map-private.hh"
-#include "hb-ot-layout-private.hh"
-
-
-
-struct hb_ot_shape_plan_t
-{
-  hb_segment_properties_t props;
-  const struct hb_ot_complex_shaper_t *shaper;
-  hb_ot_map_t map;
-  const void *data;
-  hb_mask_t rtlm_mask, frac_mask, numr_mask, dnom_mask;
-  hb_mask_t kern_mask;
-  unsigned int has_frac : 1;
-  unsigned int has_kern : 1;
-  unsigned int has_mark : 1;
-
-  inline void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
-  {
-    unsigned int table_index;
-    switch (table_tag) {
-      case HB_OT_TAG_GSUB: table_index = 0; break;
-      case HB_OT_TAG_GPOS: table_index = 1; break;
-      default: return;
-    }
-    map.collect_lookups (table_index, lookups);
-  }
-  inline void substitute (hb_font_t *font, hb_buffer_t *buffer) const { map.substitute (this, font, buffer); }
-  inline void position (hb_font_t *font, hb_buffer_t *buffer) const { map.position (this, font, buffer); }
-
-  void finish (void) { map.finish (); }
-};
-
-struct hb_ot_shape_planner_t
-{
-  /* In the order that they are filled in. */
-  hb_face_t *face;
-  hb_segment_properties_t props;
-  const struct hb_ot_complex_shaper_t *shaper;
-  hb_ot_map_builder_t map;
-
-  hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan) :
-			 face (master_plan->face_unsafe),
-			 props (master_plan->props),
-			 shaper (nullptr),
-			 map (face, &props) {}
-  ~hb_ot_shape_planner_t (void) { map.finish (); }
-
-  inline void compile (hb_ot_shape_plan_t &plan,
-		       const int          *coords,
-		       unsigned int        num_coords)
-  {
-    plan.props = props;
-    plan.shaper = shaper;
-    map.compile (plan.map, coords, num_coords);
-
-    plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
-    plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
-    plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
-    plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
-
-    plan.kern_mask = plan.map.get_mask (HB_DIRECTION_IS_HORIZONTAL (plan.props.direction) ?
-					HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'));
-
-    plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
-    plan.has_kern = !!plan.kern_mask;
-    plan.has_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
-  }
-
-  private:
-  /* No copy. */
-  hb_ot_shape_planner_t (const hb_ot_shape_planner_t &);
-  hb_ot_shape_planner_t &operator = (const hb_ot_shape_planner_t &);
-};
-
-
-#endif /* HB_OT_SHAPE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape.cc b/third_party/harfbuzz-ng/src/hb-ot-shape.cc
deleted file mode 100644
index 263d65c..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape.cc
+++ /dev/null
@@ -1,970 +0,0 @@
-/*
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2010,2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#define HB_SHAPER ot
-#define hb_ot_shaper_face_data_t hb_ot_layout_t
-#define hb_ot_shaper_shape_plan_data_t hb_ot_shape_plan_t
-#include "hb-shaper-impl-private.hh"
-
-#include "hb-ot-shape-private.hh"
-#include "hb-ot-shape-complex-private.hh"
-#include "hb-ot-shape-fallback-private.hh"
-#include "hb-ot-shape-normalize-private.hh"
-
-#include "hb-ot-layout-private.hh"
-#include "hb-unicode-private.hh"
-#include "hb-set-private.hh"
-
-#include "hb-ot-layout-gsubgpos-private.hh"
-//#include "hb-aat-layout-private.hh"
-
-static hb_tag_t common_features[] = {
-  HB_TAG('c','c','m','p'),
-  HB_TAG('l','o','c','l'),
-  HB_TAG('m','a','r','k'),
-  HB_TAG('m','k','m','k'),
-  HB_TAG('r','l','i','g'),
-};
-
-
-static hb_tag_t horizontal_features[] = {
-  HB_TAG('c','a','l','t'),
-  HB_TAG('c','l','i','g'),
-  HB_TAG('c','u','r','s'),
-  HB_TAG('k','e','r','n'),
-  HB_TAG('l','i','g','a'),
-  HB_TAG('r','c','l','t'),
-};
-
-
-
-static void
-hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
-			      const hb_segment_properties_t  *props,
-			      const hb_feature_t             *user_features,
-			      unsigned int                    num_user_features)
-{
-  hb_ot_map_builder_t *map = &planner->map;
-
-  map->add_global_bool_feature (HB_TAG('r','v','r','n'));
-  map->add_gsub_pause (nullptr);
-
-  switch (props->direction) {
-    case HB_DIRECTION_LTR:
-      map->add_global_bool_feature (HB_TAG ('l','t','r','a'));
-      map->add_global_bool_feature (HB_TAG ('l','t','r','m'));
-      break;
-    case HB_DIRECTION_RTL:
-      map->add_global_bool_feature (HB_TAG ('r','t','l','a'));
-      map->add_feature (HB_TAG ('r','t','l','m'), 1, F_NONE);
-      break;
-    case HB_DIRECTION_TTB:
-    case HB_DIRECTION_BTT:
-    case HB_DIRECTION_INVALID:
-    default:
-      break;
-  }
-
-  map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE);
-  map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE);
-  map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE);
-
-  if (planner->shaper->collect_features)
-    planner->shaper->collect_features (planner);
-
-  for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++)
-    map->add_global_bool_feature (common_features[i]);
-
-  if (HB_DIRECTION_IS_HORIZONTAL (props->direction))
-    for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++)
-      map->add_feature (horizontal_features[i], 1, F_GLOBAL |
-			(horizontal_features[i] == HB_TAG('k','e','r','n') ?
-			 F_HAS_FALLBACK : F_NONE));
-  else
-  {
-    /* We really want to find a 'vert' feature if there's any in the font, no
-     * matter which script/langsys it is listed (or not) under.
-     * See various bugs referenced from:
-     * https://github.com/harfbuzz/harfbuzz/issues/63 */
-    map->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL | F_GLOBAL_SEARCH);
-  }
-
-  if (planner->shaper->override_features)
-    planner->shaper->override_features (planner);
-
-  for (unsigned int i = 0; i < num_user_features; i++) {
-    const hb_feature_t *feature = &user_features[i];
-    map->add_feature (feature->tag, feature->value,
-		      (feature->start == 0 && feature->end == (unsigned int) -1) ?
-		       F_GLOBAL : F_NONE);
-  }
-}
-
-
-/*
- * shaper face data
- */
-
-HB_SHAPER_DATA_ENSURE_DEFINE(ot, face)
-
-hb_ot_shaper_face_data_t *
-_hb_ot_shaper_face_data_create (hb_face_t *face)
-{
-  return _hb_ot_layout_create (face);
-}
-
-void
-_hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
-{
-  _hb_ot_layout_destroy (data);
-}
-
-
-/*
- * shaper font data
- */
-
-HB_SHAPER_DATA_ENSURE_DEFINE(ot, font)
-
-struct hb_ot_shaper_font_data_t {};
-
-hb_ot_shaper_font_data_t *
-_hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED)
-{
-  return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data)
-{
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-hb_ot_shaper_shape_plan_data_t *
-_hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan,
-				      const hb_feature_t *user_features,
-				      unsigned int        num_user_features,
-				      const int          *coords,
-				      unsigned int        num_coords)
-{
-  hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t));
-  if (unlikely (!plan))
-    return nullptr;
-
-  hb_ot_shape_planner_t planner (shape_plan);
-
-  planner.shaper = hb_ot_shape_complex_categorize (&planner);
-
-  hb_ot_shape_collect_features (&planner, &shape_plan->props,
-				user_features, num_user_features);
-
-  planner.compile (*plan, coords, num_coords);
-
-  if (plan->shaper->data_create) {
-    plan->data = plan->shaper->data_create (plan);
-    if (unlikely (!plan->data))
-      return nullptr;
-  }
-
-  return plan;
-}
-
-void
-_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan)
-{
-  if (plan->shaper->data_destroy)
-    plan->shaper->data_destroy (const_cast<void *> (plan->data));
-
-  plan->finish ();
-
-  free (plan);
-}
-
-
-/*
- * shaper
- */
-
-struct hb_ot_shape_context_t
-{
-  hb_ot_shape_plan_t *plan;
-  hb_font_t *font;
-  hb_face_t *face;
-  hb_buffer_t  *buffer;
-  const hb_feature_t *user_features;
-  unsigned int        num_user_features;
-
-  /* Transient stuff */
-  bool fallback_positioning;
-  bool fallback_glyph_classes;
-  hb_direction_t target_direction;
-};
-
-
-
-/* Main shaper */
-
-
-/* Prepare */
-
-static void
-hb_set_unicode_props (hb_buffer_t *buffer)
-{
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    _hb_glyph_info_set_unicode_props (&info[i], buffer);
-}
-
-static void
-hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
-{
-  if (!(buffer->flags & HB_BUFFER_FLAG_BOT) ||
-      buffer->context_len[0] ||
-      _hb_glyph_info_get_general_category (&buffer->info[0]) !=
-      HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
-    return;
-
-  if (!font->has_glyph (0x25CCu))
-    return;
-
-  hb_glyph_info_t dottedcircle = {0};
-  dottedcircle.codepoint = 0x25CCu;
-  _hb_glyph_info_set_unicode_props (&dottedcircle, buffer);
-
-  buffer->clear_output ();
-
-  buffer->idx = 0;
-  hb_glyph_info_t info = dottedcircle;
-  info.cluster = buffer->cur().cluster;
-  info.mask = buffer->cur().mask;
-  buffer->output_info (info);
-  while (buffer->idx < buffer->len && !buffer->in_error)
-    buffer->next_glyph ();
-
-  buffer->swap_buffers ();
-}
-
-static void
-hb_form_clusters (hb_buffer_t *buffer)
-{
-  if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII))
-    return;
-
-  /* Loop duplicated in hb_ensure_native_direction(), and in _hb-coretext.cc */
-  unsigned int base = 0;
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 1; i < count; i++)
-  {
-    if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])) &&
-		!_hb_glyph_info_is_joiner (&info[i])))
-    {
-      if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
-	buffer->merge_clusters (base, i);
-      else
-	buffer->unsafe_to_break (base, i);
-      base = i;
-    }
-  }
-  if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
-    buffer->merge_clusters (base, count);
-  else
-    buffer->unsafe_to_break (base, count);
-}
-
-static void
-hb_ensure_native_direction (hb_buffer_t *buffer)
-{
-  hb_direction_t direction = buffer->props.direction;
-
-  /* TODO vertical:
-   * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType
-   * Ogham fonts are supposed to be implemented BTT or not.  Need to research that
-   * first. */
-  if ((HB_DIRECTION_IS_HORIZONTAL (direction) && direction != hb_script_get_horizontal_direction (buffer->props.script)) ||
-      (HB_DIRECTION_IS_VERTICAL   (direction) && direction != HB_DIRECTION_TTB))
-  {
-    /* Same loop as hb_form_clusters().
-     * Since form_clusters() merged clusters already, we don't merge. */
-    unsigned int base = 0;
-    unsigned int count = buffer->len;
-    hb_glyph_info_t *info = buffer->info;
-    for (unsigned int i = 1; i < count; i++)
-    {
-      if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
-      {
-	if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
-	  buffer->merge_clusters (base, i);
-	buffer->reverse_range (base, i);
-
-	base = i;
-      }
-    }
-    if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
-      buffer->merge_clusters (base, count);
-    buffer->reverse_range (base, count);
-
-    buffer->reverse ();
-
-    buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
-  }
-}
-
-
-/* Substitute */
-
-static inline void
-hb_ot_mirror_chars (hb_ot_shape_context_t *c)
-{
-  if (HB_DIRECTION_IS_FORWARD (c->target_direction))
-    return;
-
-  hb_buffer_t *buffer = c->buffer;
-  hb_unicode_funcs_t *unicode = buffer->unicode;
-  hb_mask_t rtlm_mask = c->plan->rtlm_mask;
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++) {
-    hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint);
-    if (likely (codepoint == info[i].codepoint || !c->font->has_glyph (codepoint)))
-      info[i].mask |= rtlm_mask;
-    else
-      info[i].codepoint = codepoint;
-  }
-}
-
-static inline void
-hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
-{
-  if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
-      !c->plan->has_frac)
-    return;
-
-  hb_buffer_t *buffer = c->buffer;
-
-  hb_mask_t pre_mask, post_mask;
-  if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
-  {
-    pre_mask = c->plan->numr_mask | c->plan->frac_mask;
-    post_mask = c->plan->frac_mask | c->plan->dnom_mask;
-  }
-  else
-  {
-    pre_mask = c->plan->frac_mask | c->plan->dnom_mask;
-    post_mask = c->plan->numr_mask | c->plan->frac_mask;
-  }
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    if (info[i].codepoint == 0x2044u) /* FRACTION SLASH */
-    {
-      unsigned int start = i, end = i + 1;
-      while (start &&
-	     _hb_glyph_info_get_general_category (&info[start - 1]) ==
-	     HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
-        start--;
-      while (end < count &&
-	     _hb_glyph_info_get_general_category (&info[end]) ==
-	     HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
-        end++;
-
-      buffer->unsafe_to_break (start, end);
-
-      for (unsigned int j = start; j < i; j++)
-        info[j].mask |= pre_mask;
-      info[i].mask |= c->plan->frac_mask;
-      for (unsigned int j = i + 1; j < end; j++)
-        info[j].mask |= post_mask;
-
-      i = end - 1;
-    }
-  }
-}
-
-static inline void
-hb_ot_shape_initialize_masks (hb_ot_shape_context_t *c)
-{
-  hb_ot_map_t *map = &c->plan->map;
-  hb_buffer_t *buffer = c->buffer;
-
-  hb_mask_t global_mask = map->get_global_mask ();
-  buffer->reset_masks (global_mask);
-}
-
-static inline void
-hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
-{
-  hb_ot_map_t *map = &c->plan->map;
-  hb_buffer_t *buffer = c->buffer;
-
-  hb_ot_shape_setup_masks_fraction (c);
-
-  if (c->plan->shaper->setup_masks)
-    c->plan->shaper->setup_masks (c->plan, buffer, c->font);
-
-  for (unsigned int i = 0; i < c->num_user_features; i++)
-  {
-    const hb_feature_t *feature = &c->user_features[i];
-    if (!(feature->start == 0 && feature->end == (unsigned int)-1)) {
-      unsigned int shift;
-      hb_mask_t mask = map->get_mask (feature->tag, &shift);
-      buffer->set_masks (feature->value << shift, mask, feature->start, feature->end);
-    }
-  }
-}
-
-static void
-hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t *c)
-{
-  hb_buffer_t *buffer = c->buffer;
-
-  if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
-      (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) ||
-      (buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES))
-    return;
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  hb_glyph_position_t *pos = buffer->pos;
-  unsigned int i = 0;
-  for (i = 0; i < count; i++)
-    if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
-      pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
-}
-
-static void
-hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
-{
-  hb_buffer_t *buffer = c->buffer;
-
-  if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
-      (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES))
-    return;
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  hb_glyph_position_t *pos = buffer->pos;
-  unsigned int i = 0;
-  for (i = 0; i < count; i++)
-  {
-    if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
-      break;
-  }
-
-  /* No default-ignorables found; return. */
-  if (i == count)
-    return;
-
-  hb_codepoint_t space;
-  if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) &&
-      c->font->get_nominal_glyph (' ', &space))
-  {
-    /* Replace default-ignorables with a zero-advance space glyph. */
-    for (/*continue*/; i < count; i++)
-    {
-      if (_hb_glyph_info_is_default_ignorable (&info[i]))
-	info[i].codepoint = space;
-    }
-  }
-  else
-  {
-    /* Merge clusters and delete default-ignorables.
-     * NOTE! We can't use out-buffer as we have positioning data. */
-    unsigned int j = i;
-    for (; i < count; i++)
-    {
-      if (_hb_glyph_info_is_default_ignorable (&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;
-  }
-}
-
-
-static inline void
-hb_ot_map_glyphs_fast (hb_buffer_t  *buffer)
-{
-  /* Normalization process sets up glyph_index(), we just copy it. */
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    info[i].codepoint = info[i].glyph_index();
-
-  buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
-}
-
-static inline void
-hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
-{
-  unsigned int count = c->buffer->len;
-  hb_glyph_info_t *info = c->buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    hb_ot_layout_glyph_props_flags_t klass;
-
-    /* Never mark default-ignorables as marks.
-     * They won't get in the way of lookups anyway,
-     * but having them as mark will cause them to be skipped
-     * over if the lookup-flag says so, but at least for the
-     * Mongolian variation selectors, looks like Uniscribe
-     * marks them as non-mark.  Some Mongolian fonts without
-     * GDEF rely on this.  Another notable character that
-     * this applies to is COMBINING GRAPHEME JOINER. */
-    klass = (_hb_glyph_info_get_general_category (&info[i]) !=
-	     HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
-	     _hb_glyph_info_is_default_ignorable (&info[i])) ?
-	    HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
-	    HB_OT_LAYOUT_GLYPH_PROPS_MARK;
-    _hb_glyph_info_set_glyph_props (&info[i], klass);
-  }
-}
-
-static inline void
-hb_ot_substitute_default (hb_ot_shape_context_t *c)
-{
-  hb_buffer_t *buffer = c->buffer;
-
-  hb_ot_mirror_chars (c);
-
-  HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index);
-
-  _hb_ot_shape_normalize (c->plan, buffer, c->font);
-
-  hb_ot_shape_setup_masks (c);
-
-  /* This is unfortunate to go here, but necessary... */
-  if (c->fallback_positioning)
-    _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer);
-
-  hb_ot_map_glyphs_fast (buffer);
-
-  HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_index);
-}
-
-static inline void
-hb_ot_substitute_complex (hb_ot_shape_context_t *c)
-{
-  hb_buffer_t *buffer = c->buffer;
-
-  hb_ot_layout_substitute_start (c->font, buffer);
-
-  if (!hb_ot_layout_has_glyph_classes (c->face))
-    hb_synthesize_glyph_classes (c);
-
-  c->plan->substitute (c->font, buffer);
-
-  /* XXX Call morx instead. */
-  //hb_aat_layout_substitute (c->font, c->buffer);
-}
-
-static inline void
-hb_ot_substitute (hb_ot_shape_context_t *c)
-{
-  hb_ot_substitute_default (c);
-
-  _hb_buffer_allocate_gsubgpos_vars (c->buffer);
-
-  hb_ot_substitute_complex (c);
-}
-
-/* Position */
-
-static inline void
-adjust_mark_offsets (hb_glyph_position_t *pos)
-{
-  pos->x_offset -= pos->x_advance;
-  pos->y_offset -= pos->y_advance;
-}
-
-static inline void
-zero_mark_width (hb_glyph_position_t *pos)
-{
-  pos->x_advance = 0;
-  pos->y_advance = 0;
-}
-
-static inline void
-zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets)
-{
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    if (_hb_glyph_info_is_mark (&info[i]))
-    {
-      if (adjust_offsets)
-        adjust_mark_offsets (&buffer->pos[i]);
-      zero_mark_width (&buffer->pos[i]);
-    }
-}
-
-static inline void
-hb_ot_position_default (hb_ot_shape_context_t *c)
-{
-  hb_direction_t direction = c->buffer->props.direction;
-  unsigned int count = c->buffer->len;
-  hb_glyph_info_t *info = c->buffer->info;
-  hb_glyph_position_t *pos = c->buffer->pos;
-
-  if (HB_DIRECTION_IS_HORIZONTAL (direction))
-  {
-    for (unsigned int i = 0; i < count; i++)
-      pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint);
-    /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
-    if (c->font->has_glyph_h_origin_func ())
-      for (unsigned int i = 0; i < count; i++)
-	c->font->subtract_glyph_h_origin (info[i].codepoint,
-					  &pos[i].x_offset,
-					  &pos[i].y_offset);
-  }
-  else
-  {
-    for (unsigned int i = 0; i < count; i++)
-    {
-      pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint);
-      c->font->subtract_glyph_v_origin (info[i].codepoint,
-					&pos[i].x_offset,
-					&pos[i].y_offset);
-    }
-  }
-  if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
-    _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
-}
-
-static inline void
-hb_ot_position_complex (hb_ot_shape_context_t *c)
-{
-  unsigned int count = c->buffer->len;
-  hb_glyph_info_t *info = c->buffer->info;
-  hb_glyph_position_t *pos = c->buffer->pos;
-
-  /* If the font has no GPOS, AND, no fallback positioning will
-   * happen, AND, direction is forward, then when zeroing mark
-   * widths, we shift the mark with it, such that the mark
-   * is positioned hanging over the previous glyph.  When
-   * direction is backward we don't shift and it will end up
-   * hanging over the next glyph after the final reordering.
-   * If fallback positinoing happens or GPOS is present, we don't
-   * care.
-   */
-  bool adjust_offsets_when_zeroing = c->fallback_positioning &&
-				     !c->plan->shaper->fallback_position &&
-				     HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
-
-  /* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
-
-  /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
-  if (c->font->has_glyph_h_origin_func ())
-    for (unsigned int i = 0; i < count; i++)
-      c->font->add_glyph_h_origin (info[i].codepoint,
-				   &pos[i].x_offset,
-				   &pos[i].y_offset);
-
-  hb_ot_layout_position_start (c->font, c->buffer);
-
-  switch (c->plan->shaper->zero_width_marks)
-  {
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
-      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
-      break;
-
-    default:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
-      break;
-  }
-
-  if (likely (!c->fallback_positioning))
-    c->plan->position (c->font, c->buffer);
-
-  switch (c->plan->shaper->zero_width_marks)
-  {
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
-      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
-      break;
-
-    default:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
-      break;
-  }
-
-  /* Finishing off GPOS has to follow a certain order. */
-  hb_ot_layout_position_finish_advances (c->font, c->buffer);
-  hb_ot_zero_width_default_ignorables (c);
-  hb_ot_layout_position_finish_offsets (c->font, c->buffer);
-
-  /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
-  if (c->font->has_glyph_h_origin_func ())
-    for (unsigned int i = 0; i < count; i++)
-      c->font->subtract_glyph_h_origin (info[i].codepoint,
-					&pos[i].x_offset,
-					&pos[i].y_offset);
-}
-
-static inline void
-hb_ot_position (hb_ot_shape_context_t *c)
-{
-  c->buffer->clear_positions ();
-
-  hb_ot_position_default (c);
-
-  hb_ot_position_complex (c);
-
-  if (c->fallback_positioning && c->plan->shaper->fallback_position)
-    _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
-
-  if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
-    hb_buffer_reverse (c->buffer);
-
-  /* Visual fallback goes here. */
-
-  if (c->fallback_positioning)
-    _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
-
-  _hb_buffer_deallocate_gsubgpos_vars (c->buffer);
-
-  //hb_aat_layout_position (c->font, c->buffer);
-}
-
-static inline void
-hb_propagate_flags (hb_buffer_t *buffer)
-{
-  /* Propagate cluster-level glyph flags to be the same on all cluster glyphs.
-   * Simplifies using them. */
-
-  if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK))
-    return;
-
-  hb_glyph_info_t *info = buffer->info;
-
-  foreach_cluster (buffer, start, end)
-  {
-    unsigned int mask = 0;
-    for (unsigned int i = start; i < end; i++)
-      if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
-      {
-	 mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-	 break;
-      }
-    if (mask)
-      for (unsigned int i = start; i < end; i++)
-	info[i].mask |= mask;
-  }
-}
-
-/* Pull it all together! */
-
-static void
-hb_ot_shape_internal (hb_ot_shape_context_t *c)
-{
-  c->buffer->deallocate_var_all ();
-  c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
-  if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
-  {
-    c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR,
-			      (unsigned) HB_BUFFER_MAX_LEN_MIN);
-  }
-  if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
-  {
-    c->buffer->max_ops = MAX (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR,
-			      (unsigned) HB_BUFFER_MAX_OPS_MIN);
-  }
-
-  bool disable_otl = c->plan->shaper->disable_otl && c->plan->shaper->disable_otl (c->plan);
-  //c->fallback_substitute     = disable_otl || !hb_ot_layout_has_substitution (c->face);
-  c->fallback_positioning    = disable_otl || !hb_ot_layout_has_positioning (c->face);
-  c->fallback_glyph_classes  = disable_otl || !hb_ot_layout_has_glyph_classes (c->face);
-
-  /* Save the original direction, we use it later. */
-  c->target_direction = c->buffer->props.direction;
-
-  _hb_buffer_allocate_unicode_vars (c->buffer);
-
-  c->buffer->clear_output ();
-
-  hb_ot_shape_initialize_masks (c);
-  hb_set_unicode_props (c->buffer);
-  hb_insert_dotted_circle (c->buffer, c->font);
-
-  hb_form_clusters (c->buffer);
-
-  hb_ensure_native_direction (c->buffer);
-
-  if (c->plan->shaper->preprocess_text)
-    c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
-
-  hb_ot_substitute (c);
-  hb_ot_position (c);
-
-  hb_ot_hide_default_ignorables (c);
-
-  if (c->plan->shaper->postprocess_glyphs)
-    c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
-
-  hb_propagate_flags (c->buffer);
-
-  _hb_buffer_deallocate_unicode_vars (c->buffer);
-
-  c->buffer->props.direction = c->target_direction;
-
-  c->buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
-  c->buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
-  c->buffer->deallocate_var_all ();
-}
-
-
-hb_bool_t
-_hb_ot_shape (hb_shape_plan_t    *shape_plan,
-	      hb_font_t          *font,
-	      hb_buffer_t        *buffer,
-	      const hb_feature_t *features,
-	      unsigned int        num_features)
-{
-  hb_ot_shape_context_t c = {HB_SHAPER_DATA_GET (shape_plan), font, font->face, buffer, features, num_features};
-  hb_ot_shape_internal (&c);
-
-  return true;
-}
-
-
-/**
- * hb_ot_shape_plan_collect_lookups:
- *
- * Since: 0.9.7
- **/
-void
-hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
-				  hb_tag_t         table_tag,
-				  hb_set_t        *lookup_indexes /* OUT */)
-{
-  /* XXX Does the first part always succeed? */
-  HB_SHAPER_DATA_GET (shape_plan)->collect_lookups (table_tag, lookup_indexes);
-}
-
-
-/* TODO Move this to hb-ot-shape-normalize, make it do decompose, and make it public. */
-static void
-add_char (hb_font_t          *font,
-	  hb_unicode_funcs_t *unicode,
-	  hb_bool_t           mirror,
-	  hb_codepoint_t      u,
-	  hb_set_t           *glyphs)
-{
-  hb_codepoint_t glyph;
-  if (font->get_nominal_glyph (u, &glyph))
-    glyphs->add (glyph);
-  if (mirror)
-  {
-    hb_codepoint_t m = unicode->mirroring (u);
-    if (m != u && font->get_nominal_glyph (m, &glyph))
-      glyphs->add (glyph);
-  }
-}
-
-
-/**
- * hb_ot_shape_glyphs_closure:
- *
- * Since: 0.9.2
- **/
-void
-hb_ot_shape_glyphs_closure (hb_font_t          *font,
-			    hb_buffer_t        *buffer,
-			    const hb_feature_t *features,
-			    unsigned int        num_features,
-			    hb_set_t           *glyphs)
-{
-  hb_ot_shape_plan_t plan;
-
-  const char *shapers[] = {"ot", nullptr};
-  hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props,
-							     features, num_features, shapers);
-
-  bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_DIRECTION_RTL;
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs);
-
-  hb_set_t *lookups = hb_set_create ();
-  hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, lookups);
-
-  /* And find transitive closure. */
-  hb_set_t *copy = hb_set_create ();
-  do {
-    copy->set (glyphs);
-    for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID; hb_set_next (lookups, &lookup_index);)
-      hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs);
-  } while (!copy->is_equal (glyphs));
-  hb_set_destroy (copy);
-
-  hb_set_destroy (lookups);
-
-  hb_shape_plan_destroy (shape_plan);
-}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape.h b/third_party/harfbuzz-ng/src/hb-ot-shape.h
deleted file mode 100644
index 7b1bcc0..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-shape.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright © 2013  Red Hat, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_H_IN
-#error "Include <hb-ot.h> instead."
-#endif
-
-#ifndef HB_OT_SHAPE_H
-#define HB_OT_SHAPE_H
-
-#include "hb.h"
-
-HB_BEGIN_DECLS
-
-/* TODO port to shape-plan / set. */
-HB_EXTERN void
-hb_ot_shape_glyphs_closure (hb_font_t          *font,
-			    hb_buffer_t        *buffer,
-			    const hb_feature_t *features,
-			    unsigned int        num_features,
-			    hb_set_t           *glyphs);
-
-HB_EXTERN void
-hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
-				  hb_tag_t         table_tag,
-				  hb_set_t        *lookup_indexes /* OUT */);
-
-HB_END_DECLS
-
-#endif /* HB_OT_SHAPE_H */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-tag.cc b/third_party/harfbuzz-ng/src/hb-ot-tag.cc
deleted file mode 100644
index 1338c31..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-tag.cc
+++ /dev/null
@@ -1,1094 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
- */
-
-#include "hb-private.hh"
-
-
-/* hb_script_t */
-
-static hb_tag_t
-hb_ot_old_tag_from_script (hb_script_t script)
-{
-  /* This seems to be accurate as of end of 2012. */
-
-  switch ((hb_tag_t) script) {
-    case HB_SCRIPT_INVALID:		return HB_OT_TAG_DEFAULT_SCRIPT;
-
-    /* KATAKANA and HIRAGANA both map to 'kana' */
-    case HB_SCRIPT_HIRAGANA:		return HB_TAG('k','a','n','a');
-
-    /* Spaces at the end are preserved, unlike ISO 15924 */
-    case HB_SCRIPT_LAO:			return HB_TAG('l','a','o',' ');
-    case HB_SCRIPT_YI:			return HB_TAG('y','i',' ',' ');
-    /* Unicode-5.0 additions */
-    case HB_SCRIPT_NKO:			return HB_TAG('n','k','o',' ');
-    /* Unicode-5.1 additions */
-    case HB_SCRIPT_VAI:			return HB_TAG('v','a','i',' ');
-    /* Unicode-5.2 additions */
-    /* Unicode-6.0 additions */
-  }
-
-  /* Else, just change first char to lowercase and return */
-  return ((hb_tag_t) script) | 0x20000000u;
-}
-
-static hb_script_t
-hb_ot_old_tag_to_script (hb_tag_t tag)
-{
-  if (unlikely (tag == HB_OT_TAG_DEFAULT_SCRIPT))
-    return HB_SCRIPT_INVALID;
-
-  /* This side of the conversion is fully algorithmic. */
-
-  /* Any spaces at the end of the tag are replaced by repeating the last
-   * letter.  Eg 'nko ' -> 'Nkoo' */
-  if (unlikely ((tag & 0x0000FF00u) == 0x00002000u))
-    tag |= (tag >> 8) & 0x0000FF00u; /* Copy second letter to third */
-  if (unlikely ((tag & 0x000000FFu) == 0x00000020u))
-    tag |= (tag >> 8) & 0x000000FFu; /* Copy third letter to fourth */
-
-  /* Change first char to uppercase and return */
-  return (hb_script_t) (tag & ~0x20000000u);
-}
-
-static hb_tag_t
-hb_ot_new_tag_from_script (hb_script_t script)
-{
-  switch ((hb_tag_t) script) {
-    case HB_SCRIPT_BENGALI:		return HB_TAG('b','n','g','2');
-    case HB_SCRIPT_DEVANAGARI:		return HB_TAG('d','e','v','2');
-    case HB_SCRIPT_GUJARATI:		return HB_TAG('g','j','r','2');
-    case HB_SCRIPT_GURMUKHI:		return HB_TAG('g','u','r','2');
-    case HB_SCRIPT_KANNADA:		return HB_TAG('k','n','d','2');
-    case HB_SCRIPT_MALAYALAM:		return HB_TAG('m','l','m','2');
-    case HB_SCRIPT_ORIYA:		return HB_TAG('o','r','y','2');
-    case HB_SCRIPT_TAMIL:		return HB_TAG('t','m','l','2');
-    case HB_SCRIPT_TELUGU:		return HB_TAG('t','e','l','2');
-    case HB_SCRIPT_MYANMAR:		return HB_TAG('m','y','m','2');
-  }
-
-  return HB_OT_TAG_DEFAULT_SCRIPT;
-}
-
-static hb_script_t
-hb_ot_new_tag_to_script (hb_tag_t tag)
-{
-  switch (tag) {
-    case HB_TAG('b','n','g','2'):	return HB_SCRIPT_BENGALI;
-    case HB_TAG('d','e','v','2'):	return HB_SCRIPT_DEVANAGARI;
-    case HB_TAG('g','j','r','2'):	return HB_SCRIPT_GUJARATI;
-    case HB_TAG('g','u','r','2'):	return HB_SCRIPT_GURMUKHI;
-    case HB_TAG('k','n','d','2'):	return HB_SCRIPT_KANNADA;
-    case HB_TAG('m','l','m','2'):	return HB_SCRIPT_MALAYALAM;
-    case HB_TAG('o','r','y','2'):	return HB_SCRIPT_ORIYA;
-    case HB_TAG('t','m','l','2'):	return HB_SCRIPT_TAMIL;
-    case HB_TAG('t','e','l','2'):	return HB_SCRIPT_TELUGU;
-    case HB_TAG('m','y','m','2'):	return HB_SCRIPT_MYANMAR;
-  }
-
-  return HB_SCRIPT_UNKNOWN;
-}
-
-/*
- * Complete list at:
- * https://www.microsoft.com/typography/otspec/scripttags.htm
- * https://www.microsoft.com/typography/otspec160/scripttagsProposed.htm
- *
- * Most of the script tags are the same as the ISO 15924 tag but lowercased.
- * So we just do that, and handle the exceptional cases in a switch.
- */
-
-void
-hb_ot_tags_from_script (hb_script_t  script,
-			hb_tag_t    *script_tag_1,
-			hb_tag_t    *script_tag_2)
-{
-  hb_tag_t new_tag;
-
-  *script_tag_2 = HB_OT_TAG_DEFAULT_SCRIPT;
-  *script_tag_1 = hb_ot_old_tag_from_script (script);
-
-  new_tag = hb_ot_new_tag_from_script (script);
-  if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT)) {
-    *script_tag_2 = *script_tag_1;
-    *script_tag_1 = new_tag;
-  }
-}
-
-hb_script_t
-hb_ot_tag_to_script (hb_tag_t tag)
-{
-  if (unlikely ((tag & 0x000000FFu) == '2'))
-    return hb_ot_new_tag_to_script (tag);
-
-  return hb_ot_old_tag_to_script (tag);
-}
-
-
-/* hb_language_t */
-
-typedef struct {
-  char language[4];
-  hb_tag_t tag;
-} LangTag;
-
-/*
- * Complete list at:
- * http://www.microsoft.com/typography/otspec/languagetags.htm
- *
- * Generated by intersecting the OpenType language tag list from
- * Draft OpenType 1.5 spec, with with the ISO 639-3 codes from
- * 2008-08-04, matching on name, and finally adjusted manually.
- *
- * Updated on 2012-12-07 with more research into remaining codes.
- *
- * Updated on 2013-11-23 based on usage in SIL and Microsoft fonts,
- * the new proposal from Microsoft, and latest ISO 639-3 names.
- *
- * Some items still missing.  Those are commented out at the end.
- * Keep sorted for bsearch.
- *
- * Updated as of 2015-05-06: OT1.7 on MS website has some newer
- * items that we don't have here, eg. Zazaki.  This is the new
- * items in OpenType 1.7 (red items), most of which we have:
- * http://www.microsoft.com/typography/otspec170/languagetags.htm
- */
-
-static const LangTag ot_languages[] = {
-  {"aa",	HB_TAG('A','F','R',' ')},	/* Afar */
-  {"ab",	HB_TAG('A','B','K',' ')},	/* Abkhazian */
-  {"abq",	HB_TAG('A','B','A',' ')},	/* Abaza */
-  {"acf",	HB_TAG('F','A','N',' ')},	/* French Antillean */
-  {"ach",	HB_TAG('A','C','H',' ')},	/* Acoli */
-  {"acr",	HB_TAG('A','C','R',' ')},	/* Achi */
-  {"ada",	HB_TAG('D','N','G',' ')},	/* Dangme */
-  {"ady",	HB_TAG('A','D','Y',' ')},	/* Adyghe */
-  {"af",	HB_TAG('A','F','K',' ')},	/* Afrikaans */
-  {"ahg",	HB_TAG('A','G','W',' ')},	/* Agaw */
-  {"aii",	HB_TAG('S','W','A',' ')},	/* Swadaya Aramaic */
-  {"aio",	HB_TAG('A','I','O',' ')},	/* Aiton */
-  {"aiw",	HB_TAG('A','R','I',' ')},	/* Aari */
-  {"ak",	HB_TAG('T','W','I',' ')},	/* Akan [macrolanguage] */
-  {"aka",	HB_TAG('A','K','A',' ')},	/* Akan */
-  {"alt",	HB_TAG('A','L','T',' ')},	/* [Southern] Altai */
-  {"am",	HB_TAG('A','M','H',' ')},	/* Amharic */
-  {"amf",	HB_TAG('H','B','N',' ')},	/* Hammer-Banna */
-  {"amw",	HB_TAG('S','Y','R',' ')},	/* Western Neo-Aramaic */
-  {"an",	HB_TAG('A','R','G',' ')},	/* Aragonese */
-  {"ang",	HB_TAG('A','N','G',' ')},	/* Old English (ca. 450-1100) */
-  {"ar",	HB_TAG('A','R','A',' ')},	/* Arabic [macrolanguage] */
-  {"arb",	HB_TAG('A','R','A',' ')},	/* Standard Arabic */
-  {"arn",	HB_TAG('M','A','P',' ')},	/* Mapudungun */
-  {"ary",	HB_TAG('M','O','R',' ')},	/* Moroccan Arabic */
-  {"as",	HB_TAG('A','S','M',' ')},	/* Assamese */
-  {"ast",	HB_TAG('A','S','T',' ')},	/* Asturian/Asturleonese/Bable/Leonese */
-  {"ath",	HB_TAG('A','T','H',' ')},	/* Athapaskan [family] */
-  {"atj",	HB_TAG('R','C','R',' ')},	/* R-Cree */
-  {"atv",	HB_TAG('A','L','T',' ')},	/* [Northern] Altai */
-  {"av",	HB_TAG('A','V','R',' ')},	/* Avaric */
-  {"awa",	HB_TAG('A','W','A',' ')},	/* Awadhi */
-  {"ay",	HB_TAG('A','Y','M',' ')},	/* Aymara [macrolanguage] */
-  {"az",	HB_TAG('A','Z','E',' ')},	/* Azerbaijani [macrolanguage] */
-  {"azb",	HB_TAG('A','Z','B',' ')},	/* South Azerbaijani */
-  {"azj",	HB_TAG('A','Z','E',' ')},	/* North Azerbaijani */
-  {"ba",	HB_TAG('B','S','H',' ')},	/* Bashkir */
-  {"bad",	HB_TAG('B','A','D','0')},	/* Banda */
-  {"bai",	HB_TAG('B','M','L',' ')},	/* Bamileke [family] */
-  {"bal",	HB_TAG('B','L','I',' ')},	/* Baluchi [macrolangauge] */
-  {"ban",	HB_TAG('B','A','N',' ')},	/* Balinese */
-  {"bar",	HB_TAG('B','A','R',' ')},	/* Bavarian */
-  {"bbc",	HB_TAG('B','B','C',' ')},	/* Batak Toba */
-  {"bci",	HB_TAG('B','A','U',' ')},	/* Baoulé */
-  {"bcl",	HB_TAG('B','I','K',' ')},	/* Central Bikol */
-  {"bcq",	HB_TAG('B','C','H',' ')},	/* Bench */
-  {"bdy",	HB_TAG('B','D','Y',' ')},	/* Bandjalang */
-  {"be",	HB_TAG('B','E','L',' ')},	/* Belarusian */
-  {"bem",	HB_TAG('B','E','M',' ')},	/* Bemba (Zambia) */
-  {"ber",	HB_TAG('B','E','R',' ')},	/* Berber [family] */
-  {"bfq",	HB_TAG('B','A','D',' ')},	/* Badaga */
-  {"bft",	HB_TAG('B','L','T',' ')},	/* Balti */
-  {"bfu",	HB_TAG('L','A','H',' ')},	/* Lahuli */
-  {"bfy",	HB_TAG('B','A','G',' ')},	/* Baghelkhandi */
-  {"bg",	HB_TAG('B','G','R',' ')},	/* Bulgarian */
-  {"bgc",	HB_TAG('B','G','C',' ')},	/* Haryanvi */
-  {"bgq",	HB_TAG('B','G','Q',' ')},	/* Bagri */
-  {"bgr",	HB_TAG('Q','I','N',' ')},	/* Bawm Chin */
-  {"bhb",	HB_TAG('B','H','I',' ')},	/* Bhili */
-  {"bhk",	HB_TAG('B','I','K',' ')},	/* Albay Bicolano (retired code) */
-  {"bho",	HB_TAG('B','H','O',' ')},	/* Bhojpuri */
-  {"bi",	HB_TAG('B','I','S',' ')},	/* Bislama */
-  {"bik",	HB_TAG('B','I','K',' ')},	/* Bikol [macrolanguage] */
-  {"bin",	HB_TAG('E','D','O',' ')},	/* Bini */
-  {"bjj",	HB_TAG('B','J','J',' ')},	/* Kanauji */
-  {"bjt",	HB_TAG('B','L','N',' ')},	/* Balanta-Ganja */
-  {"bla",	HB_TAG('B','K','F',' ')},	/* Blackfoot */
-  {"ble",	HB_TAG('B','L','N',' ')},	/* Balanta-Kentohe */
-  {"blk",	HB_TAG('B','L','K',' ')},	/* Pa'O/Pa'o Karen */
-  {"bln",	HB_TAG('B','I','K',' ')},	/* Southern Catanduanes Bikol */
-  {"bm",	HB_TAG('B','M','B',' ')},	/* Bambara */
-  {"bn",	HB_TAG('B','E','N',' ')},	/* Bengali */
-  {"bo",	HB_TAG('T','I','B',' ')},	/* Tibetan */
-  {"bpy",	HB_TAG('B','P','Y',' ')},	/* Bishnupriya */
-  {"bqi",	HB_TAG('L','R','C',' ')},	/* Bakhtiari */
-  {"br",	HB_TAG('B','R','E',' ')},	/* Breton */
-  {"bra",	HB_TAG('B','R','I',' ')},	/* Braj Bhasha */
-  {"brh",	HB_TAG('B','R','H',' ')},	/* Brahui */
-  {"brx",	HB_TAG('B','R','X',' ')},	/* Bodo (India) */
-  {"bs",	HB_TAG('B','O','S',' ')},	/* Bosnian */
-  {"btb",	HB_TAG('B','T','I',' ')},	/* Beti (Cameroon) */
-  {"bto",	HB_TAG('B','I','K',' ')},	/* Rinconada Bikol */
-  {"bts",	HB_TAG('B','T','S',' ')},	/* Batak Simalungun */
-  {"bug",	HB_TAG('B','U','G',' ')},	/* Buginese */
-  {"bxr",	HB_TAG('R','B','U',' ')},	/* Russian Buriat */
-  {"byn",	HB_TAG('B','I','L',' ')},	/* Bilen */
-  {"ca",	HB_TAG('C','A','T',' ')},	/* Catalan */
-  {"cak",	HB_TAG('C','A','K',' ')},	/* Kaqchikel */
-  {"cbk",	HB_TAG('C','B','K',' ')},	/* Chavacano */
-  {"cbl",	HB_TAG('Q','I','N',' ')},	/* Bualkhaw Chin */
-  {"cco",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"ce",	HB_TAG('C','H','E',' ')},	/* Chechen */
-  {"ceb",	HB_TAG('C','E','B',' ')},	/* Cebuano */
-  {"cfm",	HB_TAG('H','A','L',' ')},	/* Halam/Falam Chin */
-  {"cgg",	HB_TAG('C','G','G',' ')},	/* Chiga */
-  {"ch",	HB_TAG('C','H','A',' ')},	/* Chamorro */
-  {"chj",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"chk",	HB_TAG('C','H','K','0')},	/* Chuukese */
-  {"cho",	HB_TAG('C','H','O',' ')},	/* Choctaw */
-  {"chp",	HB_TAG('C','H','P',' ')},	/* Chipewyan */
-  {"chq",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"chr",	HB_TAG('C','H','R',' ')},	/* Cherokee */
-  {"chy",	HB_TAG('C','H','Y',' ')},	/* Cheyenne */
-  {"chz",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"cja",	HB_TAG('C','J','A',' ')},	/* Western Cham */
-  {"cjm",	HB_TAG('C','J','M',' ')},	/* Eastern Cham */
-  {"cka",	HB_TAG('Q','I','N',' ')},	/* Khumi Awa Chin */
-  {"ckb",	HB_TAG('K','U','R',' ')},	/* Central Kurdish (Sorani) */
-  {"ckt",	HB_TAG('C','H','K',' ')},	/* Chukchi */
-  {"cld",	HB_TAG('S','Y','R',' ')},	/* Chaldean Neo-Aramaic */
-  {"cle",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"cmr",	HB_TAG('Q','I','N',' ')},	/* Mro-Khimi Chin */
-  {"cnb",	HB_TAG('Q','I','N',' ')},	/* Chinbon Chin */
-  {"cnh",	HB_TAG('Q','I','N',' ')},	/* Hakha Chin */
-  {"cnk",	HB_TAG('Q','I','N',' ')},	/* Khumi Chin */
-  {"cnl",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"cnt",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"cnw",	HB_TAG('Q','I','N',' ')},	/* Ngawn Chin */
-  {"cop",	HB_TAG('C','O','P',' ')},	/* Coptic */
-  {"cpa",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"cpp",	HB_TAG('C','P','P',' ')},	/* Creoles */
-  {"cr",	HB_TAG('C','R','E',' ')},	/* Cree */
-  {"cre",	HB_TAG('Y','C','R',' ')},	/* Y-Cree */
-  {"crh",	HB_TAG('C','R','T',' ')},	/* Crimean Tatar */
-  {"crj",	HB_TAG('E','C','R',' ')},	/* [Southern] East Cree */
-  {"crk",	HB_TAG('W','C','R',' ')},	/* West-Cree */
-  {"crl",	HB_TAG('E','C','R',' ')},	/* [Northern] East Cree */
-  {"crm",	HB_TAG('M','C','R',' ')},	/* Moose Cree */
-  {"crx",	HB_TAG('C','R','R',' ')},	/* Carrier */
-  {"cs",	HB_TAG('C','S','Y',' ')},	/* Czech */
-  {"csa",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"csb",	HB_TAG('C','S','B',' ')},	/* Kashubian */
-  {"csh",	HB_TAG('Q','I','N',' ')},	/* Asho Chin */
-  {"cso",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"csy",	HB_TAG('Q','I','N',' ')},	/* Siyin Chin */
-  {"ctd",	HB_TAG('Q','I','N',' ')},	/* Tedim Chin */
-  {"cte",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"ctg",	HB_TAG('C','T','G',' ')},	/* Chittagonian */
-  {"ctl",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"cts",	HB_TAG('B','I','K',' ')},	/* Northern Catanduanes Bikol */
-  {"cu",	HB_TAG('C','S','L',' ')},	/* Church Slavic */
-  {"cuc",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"cuk",	HB_TAG('C','U','K',' ')},	/* San Blas Kuna */
-  {"cv",	HB_TAG('C','H','U',' ')},	/* Chuvash */
-  {"cvn",	HB_TAG('C','C','H','N')},	/* Chinantec */
-  {"cwd",	HB_TAG('D','C','R',' ')},	/* Woods Cree */
-  {"cy",	HB_TAG('W','E','L',' ')},	/* Welsh */
-  {"czt",	HB_TAG('Q','I','N',' ')},	/* Zotung Chin */
-  {"da",	HB_TAG('D','A','N',' ')},	/* Danish */
-  {"dao",	HB_TAG('Q','I','N',' ')},	/* Daai Chin */
-  {"dap",	HB_TAG('N','I','S',' ')},	/* Nisi (India) */
-  {"dar",	HB_TAG('D','A','R',' ')},	/* Dargwa */
-  {"dax",	HB_TAG('D','A','X',' ')},	/* Dayi */
-  {"de",	HB_TAG('D','E','U',' ')},	/* German */
-  {"dgo",	HB_TAG('D','G','O',' ')},	/* Dogri */
-  {"dhd",	HB_TAG('M','A','W',' ')},	/* Dhundari */
-  {"dhg",	HB_TAG('D','H','G',' ')},	/* Dhangu */
-  {"din",	HB_TAG('D','N','K',' ')},	/* Dinka [macrolanguage] */
-  {"diq",	HB_TAG('D','I','Q',' ')},	/* Dimli */
-  {"dje",	HB_TAG('D','J','R',' ')},	/* Zarma */
-  {"djr",	HB_TAG('D','J','R','0')},	/* Djambarrpuyngu */
-  {"dng",	HB_TAG('D','U','N',' ')},	/* Dungan */
-  {"dnj",	HB_TAG('D','N','J',' ')},	/* Dan */
-  {"doi",	HB_TAG('D','G','R',' ')},	/* Dogri [macrolanguage] */
-  {"dsb",	HB_TAG('L','S','B',' ')},	/* Lower Sorbian */
-  {"duj",	HB_TAG('D','U','J',' ')},	/* Dhuwal */
-  {"dv",	HB_TAG('D','I','V',' ')},	/* Dhivehi/Divehi/Maldivian */
-  {"dyu",	HB_TAG('J','U','L',' ')},	/* Jula */
-  {"dz",	HB_TAG('D','Z','N',' ')},	/* Dzongkha */
-  {"ee",	HB_TAG('E','W','E',' ')},	/* Ewe */
-  {"efi",	HB_TAG('E','F','I',' ')},	/* Efik */
-  {"ekk",	HB_TAG('E','T','I',' ')},	/* Standard Estonian */
-  {"el",	HB_TAG('E','L','L',' ')},	/* Modern Greek (1453-) */
-  {"emk",	HB_TAG('M','N','K',' ')},	/* Eastern Maninkakan */
-  {"en",	HB_TAG('E','N','G',' ')},	/* English */
-  {"enf",	HB_TAG('F','N','E',' ')},	/* Forest Nenets */
-  {"enh",	HB_TAG('T','N','E',' ')},	/* Tundra Nenets */
-  {"eo",	HB_TAG('N','T','O',' ')},	/* Esperanto */
-  {"eot",	HB_TAG('B','T','I',' ')},	/* Beti (Côte d'Ivoire) */
-  {"es",	HB_TAG('E','S','P',' ')},	/* Spanish */
-  {"esu",	HB_TAG('E','S','U',' ')},	/* Central Yupik */
-  {"et",	HB_TAG('E','T','I',' ')},	/* Estonian [macrolanguage] */
-  {"eu",	HB_TAG('E','U','Q',' ')},	/* Basque */
-  {"eve",	HB_TAG('E','V','N',' ')},	/* Even */
-  {"evn",	HB_TAG('E','V','K',' ')},	/* Evenki */
-  {"fa",	HB_TAG('F','A','R',' ')},	/* Persian [macrolanguage] */
-  {"fan",	HB_TAG('F','A','N','0')},	/* Fang */
-  {"fat",	HB_TAG('F','A','T',' ')},	/* Fanti */
-  {"ff",	HB_TAG('F','U','L',' ')},	/* Fulah [macrolanguage] */
-  {"fi",	HB_TAG('F','I','N',' ')},	/* Finnish */
-  {"fil",	HB_TAG('P','I','L',' ')},	/* Filipino */
-  {"fj",	HB_TAG('F','J','I',' ')},	/* Fijian */
-  {"flm",	HB_TAG('H','A','L',' ')},	/* Halam/Falam Chin [retired ISO639 code] */
-  {"fo",	HB_TAG('F','O','S',' ')},	/* Faroese */
-  {"fon",	HB_TAG('F','O','N',' ')},	/* Fon */
-  {"fr",	HB_TAG('F','R','A',' ')},	/* French */
-  {"frc",	HB_TAG('F','R','C',' ')},	/* Cajun French */
-  {"frp",	HB_TAG('F','R','P',' ')},	/* Arpitan/Francoprovençal */
-  {"fuf",	HB_TAG('F','T','A',' ')},	/* Futa */
-  {"fur",	HB_TAG('F','R','L',' ')},	/* Friulian */
-  {"fuv",	HB_TAG('F','U','V',' ')},	/* Nigerian Fulfulde */
-  {"fy",	HB_TAG('F','R','I',' ')},	/* Western Frisian */
-  {"ga",	HB_TAG('I','R','I',' ')},	/* Irish */
-  {"gaa",	HB_TAG('G','A','D',' ')},	/* Ga */
-  {"gag",	HB_TAG('G','A','G',' ')},	/* Gagauz */
-  {"gbm",	HB_TAG('G','A','W',' ')},	/* Garhwali */
-  {"gd",	HB_TAG('G','A','E',' ')},	/* Scottish Gaelic */
-  {"gez",	HB_TAG('G','E','Z',' ')},	/* Ge'ez */
-  {"ggo",	HB_TAG('G','O','N',' ')},	/* Southern Gondi */
-  {"gih",	HB_TAG('G','I','H',' ')},	/* Githabul */
-  {"gil",	HB_TAG('G','I','L','0')},	/* Kiribati (Gilbertese) */
-  {"gkp",	HB_TAG('G','K','P',' ')},	/* Kpelle (Guinea) */
-  {"gl",	HB_TAG('G','A','L',' ')},	/* Galician */
-  {"gld",	HB_TAG('N','A','N',' ')},	/* Nanai */
-  {"glk",	HB_TAG('G','L','K',' ')},	/* Gilaki */
-  {"gn",	HB_TAG('G','U','A',' ')},	/* Guarani [macrolanguage] */
-  {"gnn",	HB_TAG('G','N','N',' ')},	/* Gumatj */
-  {"gno",	HB_TAG('G','O','N',' ')},	/* Northern Gondi */
-  {"gog",	HB_TAG('G','O','G',' ')},	/* Gogo */
-  {"gon",	HB_TAG('G','O','N',' ')},	/* Gondi [macrolanguage] */
-  {"grt",	HB_TAG('G','R','O',' ')},	/* Garo */
-  {"gru",	HB_TAG('S','O','G',' ')},	/* Sodo Gurage */
-  {"gsw",	HB_TAG('A','L','S',' ')},	/* Alsatian */
-  {"gu",	HB_TAG('G','U','J',' ')},	/* Gujarati */
-  {"guc",	HB_TAG('G','U','C',' ')},	/* Wayuu */
-  {"guf",	HB_TAG('G','U','F',' ')},	/* Gupapuyngu */
-  {"guk",	HB_TAG('G','M','Z',' ')},	/* Gumuz */
-/*{"guk",	HB_TAG('G','U','K',' ')},*/	/* Gumuz (in SIL fonts) */
-  {"guz",	HB_TAG('G','U','Z',' ')},	/* Ekegusii/Gusii */
-  {"gv",	HB_TAG('M','N','X',' ')},	/* Manx */
-  {"ha",	HB_TAG('H','A','U',' ')},	/* Hausa */
-  {"har",	HB_TAG('H','R','I',' ')},	/* Harari */
-  {"haw",	HB_TAG('H','A','W',' ')},	/* Hawaiian */
-  {"hay",	HB_TAG('H','A','Y',' ')},	/* Haya */
-  {"haz",	HB_TAG('H','A','Z',' ')},	/* Hazaragi */
-  {"he",	HB_TAG('I','W','R',' ')},	/* Hebrew */
-  {"hi",	HB_TAG('H','I','N',' ')},	/* Hindi */
-  {"hil",	HB_TAG('H','I','L',' ')},	/* Hiligaynon */
-  {"hlt",	HB_TAG('Q','I','N',' ')},	/* Matu Chin */
-  {"hmn",	HB_TAG('H','M','N',' ')},	/* Hmong */
-  {"hnd",	HB_TAG('H','N','D',' ')},	/* [Southern] Hindko */
-  {"hne",	HB_TAG('C','H','H',' ')},	/* Chattisgarhi */
-  {"hno",	HB_TAG('H','N','D',' ')},	/* [Northern] Hindko */
-  {"ho",	HB_TAG('H','M','O',' ')},	/* Hiri Motu */
-  {"hoc",	HB_TAG('H','O',' ',' ')},	/* Ho */
-  {"hoj",	HB_TAG('H','A','R',' ')},	/* Harauti */
-  {"hr",	HB_TAG('H','R','V',' ')},	/* Croatian */
-  {"hsb",	HB_TAG('U','S','B',' ')},	/* Upper Sorbian */
-  {"ht",	HB_TAG('H','A','I',' ')},	/* Haitian/Haitian Creole */
-  {"hu",	HB_TAG('H','U','N',' ')},	/* Hungarian */
-  {"hy",	HB_TAG('H','Y','E',' ')},	/* Armenian */
-  {"hz",	HB_TAG('H','E','R',' ')},	/* Herero */
-  {"ia",	HB_TAG('I','N','A',' ')},	/* Interlingua (International Auxiliary Language Association) */
-  {"iba",	HB_TAG('I','B','A',' ')},	/* Iban */
-  {"ibb",	HB_TAG('I','B','B',' ')},	/* Ibibio */
-  {"id",	HB_TAG('I','N','D',' ')},	/* Indonesian */
-  {"ie",	HB_TAG('I','L','E',' ')},	/* Interlingue/Occidental */
-  {"ig",	HB_TAG('I','B','O',' ')},	/* Igbo */
-  {"igb",	HB_TAG('E','B','I',' ')},	/* Ebira */
-  {"ii",	HB_TAG('Y','I','M',' ')},	/* Yi Modern */
-  {"ijc",	HB_TAG('I','J','O',' ')},	/* Izon */
-  {"ijo",	HB_TAG('I','J','O',' ')},	/* Ijo [family] */
-  {"ik",	HB_TAG('I','P','K',' ')},	/* Inupiaq [macrolanguage] */
-  {"ilo",	HB_TAG('I','L','O',' ')},	/* Ilokano */
-  {"inh",	HB_TAG('I','N','G',' ')},	/* Ingush */
-  {"io",	HB_TAG('I','D','O',' ')},	/* Ido */
-  {"is",	HB_TAG('I','S','L',' ')},	/* Icelandic */
-  {"it",	HB_TAG('I','T','A',' ')},	/* Italian */
-  {"iu",	HB_TAG('I','N','U',' ')},	/* Inuktitut [macrolanguage] */
-  {"ja",	HB_TAG('J','A','N',' ')},	/* Japanese */
-  {"jam",	HB_TAG('J','A','M',' ')},	/* Jamaican Creole English */
-  {"jbo",	HB_TAG('J','B','O',' ')},	/* Lojban */
-  {"jv",	HB_TAG('J','A','V',' ')},	/* Javanese */
-  {"ka",	HB_TAG('K','A','T',' ')},	/* Georgian */
-  {"kaa",	HB_TAG('K','R','K',' ')},	/* Karakalpak */
-  {"kab",	HB_TAG('K','A','B','0')},	/* Kabyle */
-  {"kam",	HB_TAG('K','M','B',' ')},	/* Kamba (Kenya) */
-  {"kar",	HB_TAG('K','R','N',' ')},	/* Karen [family] */
-  {"kat",	HB_TAG('K','G','E',' ')},	/* Khutsuri Georgian */
-  {"kbd",	HB_TAG('K','A','B',' ')},	/* Kabardian */
-  {"kde",	HB_TAG('K','D','E',' ')},	/* Makonde */
-  {"kdr",	HB_TAG('K','R','M',' ')},	/* Karaim */
-  {"kdt",	HB_TAG('K','U','Y',' ')},	/* Kuy */
-  {"kea",	HB_TAG('K','E','A',' ')},	/* Kabuverdianu (Crioulo) */
-  {"kek",	HB_TAG('K','E','K',' ')},	/* Kekchi */
-  {"kex",	HB_TAG('K','K','N',' ')},	/* Kokni */
-  {"kfa",	HB_TAG('K','O','D',' ')},	/* Kodagu */
-  {"kfr",	HB_TAG('K','A','C',' ')},	/* Kachchi */
-  {"kfx",	HB_TAG('K','U','L',' ')},	/* Kulvi */
-  {"kfy",	HB_TAG('K','M','N',' ')},	/* Kumaoni */
-  {"kg",	HB_TAG('K','O','N',' ')},	/* Kongo [macrolanguage] */
-  {"kha",	HB_TAG('K','S','I',' ')},	/* Khasi */
-  {"khb",	HB_TAG('X','B','D',' ')},	/* Lü */
-  {"kht",	HB_TAG('K','H','N',' ')},	/* Khamti (Microsoft fonts) */
-/*{"kht",	HB_TAG('K','H','T',' ')},*/	/* Khamti (OpenType spec and SIL fonts) */
-  {"khw",	HB_TAG('K','H','W',' ')},	/* Khowar */
-  {"ki",	HB_TAG('K','I','K',' ')},	/* Gikuyu/Kikuyu */
-  {"kiu",	HB_TAG('K','I','U',' ')},	/* Kirmanjki */
-  {"kj",	HB_TAG('K','U','A',' ')},	/* Kuanyama/Kwanyama */
-  {"kjd",	HB_TAG('K','J','D',' ')},	/* Southern Kiwai */
-  {"kjh",	HB_TAG('K','H','A',' ')},	/* Khakass */
-  {"kjp",	HB_TAG('K','J','P',' ')},	/* Pwo Eastern Karen */
-  {"kk",	HB_TAG('K','A','Z',' ')},	/* Kazakh */
-  {"kl",	HB_TAG('G','R','N',' ')},	/* Kalaallisut */
-  {"kln",	HB_TAG('K','A','L',' ')},	/* Kalenjin */
-  {"km",	HB_TAG('K','H','M',' ')},	/* Central Khmer */
-  {"kmb",	HB_TAG('M','B','N',' ')},	/* Kimbundu */
-  {"kmw",	HB_TAG('K','M','O',' ')},	/* Komo (Democratic Republic of Congo) */
-  {"kn",	HB_TAG('K','A','N',' ')},	/* Kannada */
-  {"knn",	HB_TAG('K','O','K',' ')},	/* Konkani */
-  {"ko",	HB_TAG('K','O','R',' ')},	/* Korean */
-  {"koi",	HB_TAG('K','O','P',' ')},	/* Komi-Permyak */
-  {"kok",	HB_TAG('K','O','K',' ')},	/* Konkani [macrolanguage] */
-  {"kon",	HB_TAG('K','O','N','0')},	/* Kongo */
-  {"kos",	HB_TAG('K','O','S',' ')},	/* Kosraean */
-  {"kpe",	HB_TAG('K','P','L',' ')},	/* Kpelle [macrolanguage] */
-  {"kpv",	HB_TAG('K','O','Z',' ')},	/* Komi-Zyrian */
-  {"kpy",	HB_TAG('K','Y','K',' ')},	/* Koryak */
-  {"kqy",	HB_TAG('K','R','T',' ')},	/* Koorete */
-  {"kr",	HB_TAG('K','N','R',' ')},	/* Kanuri [macrolanguage] */
-  {"kri",	HB_TAG('K','R','I',' ')},	/* Krio */
-  {"krl",	HB_TAG('K','R','L',' ')},	/* Karelian */
-  {"kru",	HB_TAG('K','U','U',' ')},	/* Kurukh */
-  {"ks",	HB_TAG('K','S','H',' ')},	/* Kashmiri */
-  {"ksh",	HB_TAG('K','S','H','0')},	/* Ripuarian, Kölsch */
-/*{"ksw",	HB_TAG('K','R','N',' ')},*/	/* S'gaw Karen (Microsoft fonts?) */
-  {"ksw",	HB_TAG('K','S','W',' ')},	/* S'gaw Karen (OpenType spec and SIL fonts) */
-  {"ktb",	HB_TAG('K','E','B',' ')},	/* Kebena */
-  {"ktu",	HB_TAG('K','O','N',' ')},	/* Kikongo */
-  {"ku",	HB_TAG('K','U','R',' ')},	/* Kurdish [macrolanguage] */
-  {"kum",	HB_TAG('K','U','M',' ')},	/* Kumyk */
-  {"kv",	HB_TAG('K','O','M',' ')},	/* Komi [macrolanguage] */
-  {"kvd",	HB_TAG('K','U','I',' ')},	/* Kui (Indonesia) */
-  {"kw",	HB_TAG('C','O','R',' ')},	/* Cornish */
-  {"kxc",	HB_TAG('K','M','S',' ')},	/* Komso */
-  {"kxu",	HB_TAG('K','U','I',' ')},	/* Kui (India) */
-  {"ky",	HB_TAG('K','I','R',' ')},	/* Kirghiz/Kyrgyz */
-  {"kyu",	HB_TAG('K','Y','U',' ')},	/* Western Kayah */
-  {"la",	HB_TAG('L','A','T',' ')},	/* Latin */
-  {"lad",	HB_TAG('J','U','D',' ')},	/* Ladino */
-  {"lb",	HB_TAG('L','T','Z',' ')},	/* Luxembourgish */
-  {"lbe",	HB_TAG('L','A','K',' ')},	/* Lak */
-  {"lbj",	HB_TAG('L','D','K',' ')},	/* Ladakhi */
-  {"lez",	HB_TAG('L','E','Z',' ')},	/* Lezgi */
-  {"lg",	HB_TAG('L','U','G',' ')},	/* Ganda */
-  {"li",	HB_TAG('L','I','M',' ')},	/* Limburgan/Limburger/Limburgish */
-  {"lif",	HB_TAG('L','M','B',' ')},	/* Limbu */
-  {"lij",	HB_TAG('L','I','J',' ')},	/* Ligurian */
-  {"lis",	HB_TAG('L','I','S',' ')},	/* Lisu */
-  {"ljp",	HB_TAG('L','J','P',' ')},	/* Lampung Api */
-  {"lki",	HB_TAG('L','K','I',' ')},	/* Laki */
-  {"lld",	HB_TAG('L','A','D',' ')},	/* Ladin */
-  {"lmn",	HB_TAG('L','A','M',' ')},	/* Lambani */
-  {"lmo",	HB_TAG('L','M','O',' ')},	/* Lombard */
-  {"ln",	HB_TAG('L','I','N',' ')},	/* Lingala */
-  {"lo",	HB_TAG('L','A','O',' ')},	/* Lao */
-  {"lom",	HB_TAG('L','O','M',' ')},	/* Loma */
-  {"lrc",	HB_TAG('L','R','C',' ')},	/* Northern Luri */
-  {"lt",	HB_TAG('L','T','H',' ')},	/* Lithuanian */
-  {"lu",	HB_TAG('L','U','B',' ')},	/* Luba-Katanga */
-  {"lua",	HB_TAG('L','U','B',' ')},	/* Luba-Kasai */
-  {"luo",	HB_TAG('L','U','O',' ')},	/* Luo (Kenya and Tanzania) */
-  {"lus",	HB_TAG('M','I','Z',' ')},	/* Mizo */
-  {"luy",	HB_TAG('L','U','H',' ')},	/* Luyia/Oluluyia [macrolanguage] */
-  {"luz",	HB_TAG('L','R','C',' ')},	/* Southern Luri */
-  {"lv",	HB_TAG('L','V','I',' ')},	/* Latvian */
-  {"lzz",	HB_TAG('L','A','Z',' ')},	/* Laz */
-  {"mad",	HB_TAG('M','A','D',' ')},	/* Madurese */
-  {"mag",	HB_TAG('M','A','G',' ')},	/* Magahi */
-  {"mai",	HB_TAG('M','T','H',' ')},	/* Maithili */
-  {"mak",	HB_TAG('M','K','R',' ')},	/* Makasar */
-  {"mam",	HB_TAG('M','A','M',' ')},	/* Mam */
-  {"man",	HB_TAG('M','N','K',' ')},	/* Manding/Mandingo [macrolanguage] */
-  {"mdc",	HB_TAG('M','L','E',' ')},	/* Male (Papua New Guinea) */
-  {"mdf",	HB_TAG('M','O','K',' ')},	/* Moksha */
-  {"mdr",	HB_TAG('M','D','R',' ')},	/* Mandar */
-  {"mdy",	HB_TAG('M','L','E',' ')},	/* Male (Ethiopia) */
-  {"men",	HB_TAG('M','D','E',' ')},	/* Mende (Sierra Leone) */
-  {"mer",	HB_TAG('M','E','R',' ')},	/* Meru */
-  {"mfe",	HB_TAG('M','F','E',' ')},	/* Morisyen */
-  {"mg",	HB_TAG('M','L','G',' ')},	/* Malagasy [macrolanguage] */
-  {"mh",	HB_TAG('M','A','H',' ')},	/* Marshallese */
-  {"mhr",	HB_TAG('L','M','A',' ')},	/* Low Mari */
-  {"mi",	HB_TAG('M','R','I',' ')},	/* Maori */
-  {"min",	HB_TAG('M','I','N',' ')},	/* Minangkabau */
-  {"mk",	HB_TAG('M','K','D',' ')},	/* Macedonian */
-  {"mku",	HB_TAG('M','N','K',' ')},	/* Konyanka Maninka */
-  {"mkw",	HB_TAG('M','K','W',' ')},	/* Kituba (Congo) */
-  {"ml",	HB_TAG('M','L','R',' ')},	/* Malayalam */
-  {"mlq",	HB_TAG('M','N','K',' ')},	/* Western Maninkakan */
-  {"mn",	HB_TAG('M','N','G',' ')},	/* Mongolian [macrolanguage] */
-  {"mnc",	HB_TAG('M','C','H',' ')},	/* Manchu */
-  {"mni",	HB_TAG('M','N','I',' ')},	/* Manipuri */
-  {"mnk",	HB_TAG('M','N','D',' ')},	/* Mandinka */
-  {"mns",	HB_TAG('M','A','N',' ')},	/* Mansi */
-  {"mnw",	HB_TAG('M','O','N',' ')},	/* Mon */
-  {"mo",	HB_TAG('M','O','L',' ')},	/* Moldavian */
-  {"moh",	HB_TAG('M','O','H',' ')},	/* Mohawk */
-  {"mos",	HB_TAG('M','O','S',' ')},	/* Mossi */
-  {"mpe",	HB_TAG('M','A','J',' ')},	/* Majang */
-  {"mr",	HB_TAG('M','A','R',' ')},	/* Marathi */
-  {"mrh",	HB_TAG('Q','I','N',' ')},	/* Mara Chin */
-  {"mrj",	HB_TAG('H','M','A',' ')},	/* High Mari */
-  {"ms",	HB_TAG('M','L','Y',' ')},	/* Malay [macrolanguage] */
-  {"msc",	HB_TAG('M','N','K',' ')},	/* Sankaran Maninka */
-  {"mt",	HB_TAG('M','T','S',' ')},	/* Maltese */
-  {"mtr",	HB_TAG('M','A','W',' ')},	/* Mewari */
-  {"mus",	HB_TAG('M','U','S',' ')},	/* Creek */
-  {"mve",	HB_TAG('M','A','W',' ')},	/* Marwari (Pakistan) */
-  {"mwk",	HB_TAG('M','N','K',' ')},	/* Kita Maninkakan */
-  {"mwl",	HB_TAG('M','W','L',' ')},	/* Mirandese */
-  {"mwr",	HB_TAG('M','A','W',' ')},	/* Marwari [macrolanguage] */
-  {"mww",	HB_TAG('M','W','W',' ')},	/* Hmong Daw */
-  {"my",	HB_TAG('B','R','M',' ')},	/* Burmese */
-  {"mym",	HB_TAG('M','E','N',' ')},	/* Me'en */
-  {"myn",	HB_TAG('M','Y','N',' ')},	/* Mayan */
-  {"myq",	HB_TAG('M','N','K',' ')},	/* Forest Maninka (retired code) */
-  {"myv",	HB_TAG('E','R','Z',' ')},	/* Erzya */
-  {"mzn",	HB_TAG('M','Z','N',' ')},	/* Mazanderani */
-  {"na",	HB_TAG('N','A','U',' ')},	/* Nauru */
-  {"nag",	HB_TAG('N','A','G',' ')},	/* Naga-Assamese */
-  {"nah",	HB_TAG('N','A','H',' ')},	/* Nahuatl [family] */
-  {"nap",	HB_TAG('N','A','P',' ')},	/* Neapolitan */
-  {"nb",	HB_TAG('N','O','R',' ')},	/* Norwegian Bokmål */
-  {"nco",	HB_TAG('S','I','B',' ')},	/* Sibe */
-  {"nd",	HB_TAG('N','D','B',' ')},	/* [North] Ndebele */
-  {"ndc",	HB_TAG('N','D','C',' ')},	/* Ndau */
-  {"nds",	HB_TAG('N','D','S',' ')},	/* Low German/Low Saxon */
-  {"ne",	HB_TAG('N','E','P',' ')},	/* Nepali */
-  {"new",	HB_TAG('N','E','W',' ')},	/* Newari */
-  {"ng",	HB_TAG('N','D','G',' ')},	/* Ndonga */
-  {"nga",	HB_TAG('N','G','A',' ')},	/* Ngabaka */
-  {"ngl",	HB_TAG('L','M','W',' ')},	/* Lomwe */
-  {"ngo",	HB_TAG('S','X','T',' ')},	/* Sutu */
-  {"niu",	HB_TAG('N','I','U',' ')},	/* Niuean */
-  {"niv",	HB_TAG('G','I','L',' ')},	/* Gilyak */
-  {"nl",	HB_TAG('N','L','D',' ')},	/* Dutch */
-  {"nn",	HB_TAG('N','Y','N',' ')},	/* Norwegian Nynorsk */
-  {"no",	HB_TAG('N','O','R',' ')},	/* Norwegian [macrolanguage] */
-  {"nod",	HB_TAG('N','T','A',' ')},	/* Northern Thai */
-  {"noe",	HB_TAG('N','O','E',' ')},	/* Nimadi */
-  {"nog",	HB_TAG('N','O','G',' ')},	/* Nogai */
-  {"nov",	HB_TAG('N','O','V',' ')},	/* Novial */
-  {"nqo",	HB_TAG('N','K','O',' ')},	/* N'Ko */
-  {"nr",	HB_TAG('N','D','B',' ')},	/* [South] Ndebele */
-  {"nsk",	HB_TAG('N','A','S',' ')},	/* Naskapi */
-  {"nso",	HB_TAG('S','O','T',' ')},	/* [Northern] Sotho */
-  {"nv",	HB_TAG('N','A','V',' ')},	/* Navajo */
-  {"ny",	HB_TAG('C','H','I',' ')},	/* Chewa/Chichwa/Nyanja */
-  {"nym",	HB_TAG('N','Y','M',' ')},	/* Nyamwezi */
-  {"nyn",	HB_TAG('N','K','L',' ')},	/* Nyankole */
-  {"oc",	HB_TAG('O','C','I',' ')},	/* Occitan (post 1500) */
-  {"oj",	HB_TAG('O','J','B',' ')},	/* Ojibwa [macrolanguage] */
-  {"ojs",	HB_TAG('O','C','R',' ')},	/* Oji-Cree */
-  {"okm",	HB_TAG('K','O','H',' ')},	/* Korean Old Hangul */
-  {"om",	HB_TAG('O','R','O',' ')},	/* Oromo [macrolanguage] */
-  {"or",	HB_TAG('O','R','I',' ')},	/* Oriya */
-  {"os",	HB_TAG('O','S','S',' ')},	/* Ossetian */
-  {"pa",	HB_TAG('P','A','N',' ')},	/* Panjabi */
-  {"pag",	HB_TAG('P','A','G',' ')},	/* Pangasinan */
-  {"pam",	HB_TAG('P','A','M',' ')},	/* Kapampangan/Pampanga */
-  {"pap",	HB_TAG('P','A','P','0')},	/* Papiamento */
-  {"pau",	HB_TAG('P','A','U',' ')},	/* Palauan */
-  {"pcc",	HB_TAG('P','C','C',' ')},	/* Bouyei */
-  {"pcd",	HB_TAG('P','C','D',' ')},	/* Picard */
-  {"pce",	HB_TAG('P','L','G',' ')},	/* [Ruching] Palaung */
-  {"pck",	HB_TAG('Q','I','N',' ')},	/* Paite Chin */
-  {"pdc",	HB_TAG('P','D','C',' ')},	/* Pennsylvania German */
-  {"pes",	HB_TAG('F','A','R',' ')},	/* Iranian Persian */
-  {"phk",	HB_TAG('P','H','K',' ')},	/* Phake */
-  {"pi",	HB_TAG('P','A','L',' ')},	/* Pali */
-  {"pih",	HB_TAG('P','I','H',' ')},	/* Pitcairn-Norfolk */
-  {"pl",	HB_TAG('P','L','K',' ')},	/* Polish */
-  {"pll",	HB_TAG('P','L','G',' ')},	/* [Shwe] Palaung */
-  {"plp",	HB_TAG('P','A','P',' ')},	/* Palpa */
-  {"pms",	HB_TAG('P','M','S',' ')},	/* Piemontese */
-  {"pnb",	HB_TAG('P','N','B',' ')},	/* Western Panjabi */
-  {"poh",	HB_TAG('P','O','H',' ')},	/* Pocomchi */
-  {"pon",	HB_TAG('P','O','N',' ')},	/* Pohnpeian */
-  {"prs",	HB_TAG('D','R','I',' ')},	/* Afghan Persian/Dari */
-  {"ps",	HB_TAG('P','A','S',' ')},	/* Pashto/Pushto [macrolanguage] */
-  {"pt",	HB_TAG('P','T','G',' ')},	/* Portuguese */
-  {"pwo",	HB_TAG('P','W','O',' ')},	/* Pwo Western Karen */
-  {"qu",	HB_TAG('Q','U','Z',' ')},	/* Quechua [macrolanguage] */
-  {"quc",	HB_TAG('Q','U','C',' ')},	/* K'iche'/Quiché */
-  {"quh",	HB_TAG('Q','U','H',' ')},	/* Quechua (Bolivia) */
-  {"quz",	HB_TAG('Q','U','Z',' ')},	/* Cusco Quechua */
-  {"qvi",	HB_TAG('Q','V','I',' ')},	/* Quechua (Ecuador) */
-  {"qwh",	HB_TAG('Q','W','H',' ')},	/* Quechua (Peru) */
-  {"raj",	HB_TAG('R','A','J',' ')},	/* Rajasthani [macrolanguage] */
-  {"rar",	HB_TAG('R','A','R',' ')},	/* Rarotongan */
-  {"rbb",	HB_TAG('P','L','G',' ')},	/* Rumai Palaung */
-  {"rej",	HB_TAG('R','E','J',' ')},	/* Rejang */
-  {"ria",	HB_TAG('R','I','A',' ')},	/* Riang (India) */
-  {"rif",	HB_TAG('R','I','F',' ')},	/* Tarifit */
-  {"ril",	HB_TAG('R','I','A',' ')},	/* Riang (Myanmar) */
-  {"rit",	HB_TAG('R','I','T',' ')},	/* Ritarungo */
-  {"rki",	HB_TAG('A','R','K',' ')},	/* Rakhine */
-  {"rkw",	HB_TAG('R','K','W',' ')},	/* Arakwal */
-  {"rm",	HB_TAG('R','M','S',' ')},	/* Romansh */
-  {"rmy",	HB_TAG('R','M','Y',' ')},	/* Vlax Romani */
-  {"rn",	HB_TAG('R','U','N',' ')},	/* Rundi */
-  {"ro",	HB_TAG('R','O','M',' ')},	/* Romanian */
-  {"rom",	HB_TAG('R','O','Y',' ')},	/* Romany [macrolanguage] */
-  {"rtm",	HB_TAG('R','T','M',' ')},	/* Rotuman */
-  {"ru",	HB_TAG('R','U','S',' ')},	/* Russian */
-  {"rue",	HB_TAG('R','S','Y',' ')},	/* Rusyn */
-  {"rup",	HB_TAG('R','U','P',' ')},	/* Aromanian/Arumanian/Macedo-Romanian */
-  {"rw",	HB_TAG('R','U','A',' ')},	/* Kinyarwanda */
-  {"rwr",	HB_TAG('M','A','W',' ')},	/* Marwari (India) */
-  {"sa",	HB_TAG('S','A','N',' ')},	/* Sanskrit */
-  {"sah",	HB_TAG('Y','A','K',' ')},	/* Yakut */
-  {"sam",	HB_TAG('P','A','A',' ')},	/* Palestinian Aramaic */
-  {"sas",	HB_TAG('S','A','S',' ')},	/* Sasak */
-  {"sat",	HB_TAG('S','A','T',' ')},	/* Santali */
-  {"sc",	HB_TAG('S','R','D',' ')},	/* Sardinian [macrolanguage] */
-  {"sck",	HB_TAG('S','A','D',' ')},	/* Sadri */
-  {"scn",	HB_TAG('S','C','N',' ')},	/* Sicilian */
-  {"sco",	HB_TAG('S','C','O',' ')},	/* Scots */
-  {"scs",	HB_TAG('S','L','A',' ')},	/* [North] Slavey */
-  {"sd",	HB_TAG('S','N','D',' ')},	/* Sindhi */
-  {"se",	HB_TAG('N','S','M',' ')},	/* Northern Sami */
-  {"seh",	HB_TAG('S','N','A',' ')},	/* Sena */
-  {"sel",	HB_TAG('S','E','L',' ')},	/* Selkup */
-  {"sez",	HB_TAG('Q','I','N',' ')},	/* Senthang Chin */
-  {"sg",	HB_TAG('S','G','O',' ')},	/* Sango */
-  {"sga",	HB_TAG('S','G','A',' ')},	/* Old Irish (to 900) */
-  {"sgs",	HB_TAG('S','G','S',' ')},	/* Samogitian */
-  {"sgw",	HB_TAG('C','H','G',' ')},	/* Sebat Bet Gurage */
-/*{"sgw",	HB_TAG('S','G','W',' ')},*/	/* Sebat Bet Gurage (in SIL fonts) */
-  {"shi",	HB_TAG('S','H','I',' ')},	/* Tachelhit */
-  {"shn",	HB_TAG('S','H','N',' ')},	/* Shan */
-  {"si",	HB_TAG('S','N','H',' ')},	/* Sinhala */
-  {"sid",	HB_TAG('S','I','D',' ')},	/* Sidamo */
-  {"sjd",	HB_TAG('K','S','M',' ')},	/* Kildin Sami */
-  {"sk",	HB_TAG('S','K','Y',' ')},	/* Slovak */
-  {"skr",	HB_TAG('S','R','K',' ')},	/* Seraiki */
-  {"sl",	HB_TAG('S','L','V',' ')},	/* Slovenian */
-  {"sm",	HB_TAG('S','M','O',' ')},	/* Samoan */
-  {"sma",	HB_TAG('S','S','M',' ')},	/* Southern Sami */
-  {"smj",	HB_TAG('L','S','M',' ')},	/* Lule Sami */
-  {"smn",	HB_TAG('I','S','M',' ')},	/* Inari Sami */
-  {"sms",	HB_TAG('S','K','S',' ')},	/* Skolt Sami */
-  {"sn",	HB_TAG('S','N','A','0')},	/* Shona */
-  {"snk",	HB_TAG('S','N','K',' ')},	/* Soninke */
-  {"so",	HB_TAG('S','M','L',' ')},	/* Somali */
-  {"sop",	HB_TAG('S','O','P',' ')},	/* Songe */
-  {"sq",	HB_TAG('S','Q','I',' ')},	/* Albanian [macrolanguage] */
-  {"sr",	HB_TAG('S','R','B',' ')},	/* Serbian */
-  {"srr",	HB_TAG('S','R','R',' ')},	/* Serer */
-  {"ss",	HB_TAG('S','W','Z',' ')},	/* Swati */
-  {"st",	HB_TAG('S','O','T',' ')},	/* [Southern] Sotho */
-  {"stq",	HB_TAG('S','T','Q',' ')},	/* Saterfriesisch */
-  {"stv",	HB_TAG('S','I','G',' ')},	/* Silt'e */
-  {"su",	HB_TAG('S','U','N',' ')},	/* Sundanese */
-  {"suk",	HB_TAG('S','U','K',' ')},	/* Sukama */
-  {"suq",	HB_TAG('S','U','R',' ')},	/* Suri */
-  {"sv",	HB_TAG('S','V','E',' ')},	/* Swedish */
-  {"sva",	HB_TAG('S','V','A',' ')},	/* Svan */
-  {"sw",	HB_TAG('S','W','K',' ')},	/* Swahili [macrolanguage] */
-  {"swb",	HB_TAG('C','M','R',' ')},	/* Comorian */
-  {"swh",	HB_TAG('S','W','K',' ')},	/* Kiswahili/Swahili */
-  {"swv",	HB_TAG('M','A','W',' ')},	/* Shekhawati */
-  {"sxu",	HB_TAG('S','X','U',' ')},	/* Upper Saxon */
-  {"syc",	HB_TAG('S','Y','R',' ')},	/* Classical Syriac */
-  {"syl",	HB_TAG('S','Y','L',' ')},	/* Sylheti */
-  {"syr",	HB_TAG('S','Y','R',' ')},	/* Syriac [macrolanguage] */
-  {"szl",	HB_TAG('S','Z','L',' ')},	/* Silesian */
-  {"ta",	HB_TAG('T','A','M',' ')},	/* Tamil */
-  {"tab",	HB_TAG('T','A','B',' ')},	/* Tabasaran */
-  {"tcp",	HB_TAG('Q','I','N',' ')},	/* Tawr Chin */
-  {"tcy",	HB_TAG('T','U','L',' ')},	/* Tulu */
-  {"tcz",	HB_TAG('Q','I','N',' ')},	/* Thado Chin */
-  {"tdd",	HB_TAG('T','D','D',' ')},	/* Tai Nüa */
-  {"te",	HB_TAG('T','E','L',' ')},	/* Telugu */
-  {"tem",	HB_TAG('T','M','N',' ')},	/* Temne */
-  {"tet",	HB_TAG('T','E','T',' ')},	/* Tetum */
-  {"tg",	HB_TAG('T','A','J',' ')},	/* Tajik */
-  {"th",	HB_TAG('T','H','A',' ')},	/* Thai */
-  {"ti",	HB_TAG('T','G','Y',' ')},	/* Tigrinya */
-  {"tig",	HB_TAG('T','G','R',' ')},	/* Tigre */
-  {"tiv",	HB_TAG('T','I','V',' ')},	/* Tiv */
-  {"tk",	HB_TAG('T','K','M',' ')},	/* Turkmen */
-  {"tl",	HB_TAG('T','G','L',' ')},	/* Tagalog */
-  {"tmh",	HB_TAG('T','M','H',' ')},	/* Tamashek */
-  {"tn",	HB_TAG('T','N','A',' ')},	/* Tswana */
-  {"to",	HB_TAG('T','G','N',' ')},	/* Tonga (Tonga Islands) */
-  {"tod",	HB_TAG('T','O','D','0')},	/* Toma */
-  {"toi",	HB_TAG('T','N','G',' ')},	/* Tonga */
-  {"tpi",	HB_TAG('T','P','I',' ')},	/* Tok Pisin */
-  {"tr",	HB_TAG('T','R','K',' ')},	/* Turkish */
-  {"tru",	HB_TAG('T','U','A',' ')},	/* Turoyo Aramaic */
-  {"ts",	HB_TAG('T','S','G',' ')},	/* Tsonga */
-  {"tt",	HB_TAG('T','A','T',' ')},	/* Tatar */
-  {"tum",	HB_TAG('T','U','M',' ')},	/* Tumbuka */
-  {"tvl",	HB_TAG('T','V','L',' ')},	/* Tuvalu */
-  {"tw",	HB_TAG('T','W','I',' ')},	/* Twi */
-  {"ty",	HB_TAG('T','H','T',' ')},	/* Tahitian */
-  {"tyv",	HB_TAG('T','U','V',' ')},	/* Tuvin */
-  {"tyz",	HB_TAG('T','Y','Z',' ')},	/* Tày */
-  {"tzm",	HB_TAG('T','Z','M',' ')},	/* Central Atlas Tamazight */
-  {"tzo",	HB_TAG('T','Z','O',' ')},	/* Tzotzil */
-  {"udm",	HB_TAG('U','D','M',' ')},	/* Udmurt */
-  {"ug",	HB_TAG('U','Y','G',' ')},	/* Uighur */
-  {"uk",	HB_TAG('U','K','R',' ')},	/* Ukrainian */
-  {"umb",	HB_TAG('U','M','B',' ')},	/* Umbundu */
-  {"unr",	HB_TAG('M','U','N',' ')},	/* Mundari */
-  {"ur",	HB_TAG('U','R','D',' ')},	/* Urdu */
-  {"uz",	HB_TAG('U','Z','B',' ')},	/* Uzbek [macrolanguage] */
-  {"uzn",	HB_TAG('U','Z','B',' ')},	/* Northern Uzbek */
-  {"uzs",	HB_TAG('U','Z','B',' ')},	/* Southern Uzbek */
-  {"ve",	HB_TAG('V','E','N',' ')},	/* Venda */
-  {"vec",	HB_TAG('V','E','C',' ')},	/* Venetian */
-  {"vi",	HB_TAG('V','I','T',' ')},	/* Vietnamese */
-  {"vls",	HB_TAG('F','L','E',' ')},	/* Vlaams */
-  {"vmw",	HB_TAG('M','A','K',' ')},	/* Makhuwa */
-  {"vo",	HB_TAG('V','O','L',' ')},	/* Volapük */
-  {"vro",	HB_TAG('V','R','O',' ')},	/* Võro */
-  {"wa",	HB_TAG('W','L','N',' ')},	/* Walloon */
-  {"war",	HB_TAG('W','A','R',' ')},	/* Waray (Philippines) */
-  {"wbm",	HB_TAG('W','A',' ',' ')},	/* Wa */
-  {"wbr",	HB_TAG('W','A','G',' ')},	/* Wagdi */
-  {"wle",	HB_TAG('S','I','G',' ')},	/* Wolane */
-  {"wo",	HB_TAG('W','L','F',' ')},	/* Wolof */
-  {"wry",	HB_TAG('M','A','W',' ')},	/* Merwari */
-  {"wtm",	HB_TAG('W','T','M',' ')},	/* Mewati */
-  {"xal",	HB_TAG('K','L','M',' ')},	/* Kalmyk */
-  {"xan",	HB_TAG('S','E','K',' ')},	/* Sekota */
-  {"xh",	HB_TAG('X','H','S',' ')},	/* Xhosa */
-  {"xjb",	HB_TAG('X','J','B',' ')},	/* Minjangbal */
-  {"xog",	HB_TAG('X','O','G',' ')},	/* Soga */
-  {"xom",	HB_TAG('K','M','O',' ')},	/* Komo (Sudan) */
-  {"xpe",	HB_TAG('X','P','E',' ')},	/* Kpelle (Liberia) */
-  {"xsl",	HB_TAG('S','S','L',' ')},	/* South Slavey */
-  {"xst",	HB_TAG('S','I','G',' ')},	/* Silt'e (retired code) */
-  {"xwo",	HB_TAG('T','O','D',' ')},	/* Written Oirat (Todo) */
-  {"yao",	HB_TAG('Y','A','O',' ')},	/* Yao */
-  {"yap",	HB_TAG('Y','A','P',' ')},	/* Yapese */
-  {"yi",	HB_TAG('J','I','I',' ')},	/* Yiddish [macrolanguage] */
-  {"yo",	HB_TAG('Y','B','A',' ')},	/* Yoruba */
-  {"yos",	HB_TAG('Q','I','N',' ')},	/* Yos, deprecated by IANA in favor of Zou [zom] */
-  {"yso",	HB_TAG('N','I','S',' ')},	/* Nisi (China) */
-  {"za",	HB_TAG('Z','H','A',' ')},	/* Chuang/Zhuang [macrolanguage] */
-  {"zea",	HB_TAG('Z','E','A',' ')},	/* Zeeuws */
-  {"zgh",	HB_TAG('Z','G','H',' ')},	/* Standard Morrocan Tamazigh */
-  {"zne",	HB_TAG('Z','N','D',' ')},	/* Zande */
-  {"zom",	HB_TAG('Q','I','N',' ')},	/* Zou */
-  {"zu",	HB_TAG('Z','U','L',' ')}, 	/* Zulu */
-  {"zum",	HB_TAG('L','R','C',' ')},	/* Kumzari */
-  {"zza",	HB_TAG('Z','Z','A',' ')},	/* Zazaki */
-
-  /* The corresponding languages IDs for the following IDs are unclear,
-   * overlap, or are architecturally weird. Needs more research. */
-
-/*{"chp",	HB_TAG('S','A','Y',' ')},*/	/* Sayisi */
-/*{"cwd",	HB_TAG('T','C','R',' ')},*/	/* TH-Cree */
-/*{"emk",	HB_TAG('E','M','K',' ')},*/	/* Eastern Maninkakan */
-/*{"krc",	HB_TAG('B','A','L',' ')},*/	/* Balkar */
-/*{"??",	HB_TAG('B','C','R',' ')},*/	/* Bible Cree */
-/*{"zh?",	HB_TAG('C','H','N',' ')},*/	/* Chinese (seen in Microsoft fonts) */
-/*{"ar-Syrc?",	HB_TAG('G','A','R',' ')},*/	/* Garshuni */
-/*{"hy?",	HB_TAG('H','Y','E','0')},*/	/* Armenian East (ISO 639-3 hye according to Microsoft, but that’s equivalent to ISO 639-1 hy) */
-/*{"ga-Latg?/"	HB_TAG('I','R','T',' ')},*/	/* Irish Traditional */
-/*{"krc",	HB_TAG('K','A','R',' ')},*/	/* Karachay */
-/*{"ka-Geok?",	HB_TAG('K','G','E',' ')},*/	/* Khutsuri Georgian */
-/*{"kca",	HB_TAG('K','H','K',' ')},*/	/* Khanty-Kazim */
-/*{"kca",	HB_TAG('K','H','S',' ')},*/	/* Khanty-Shurishkar */
-/*{"kca",	HB_TAG('K','H','V',' ')},*/	/* Khanty-Vakhi */
-/*{"kqs, kss",	HB_TAG('K','I','S',' ')},*/	/* Kisii */
-/*{"lua",	HB_TAG('L','U','A',' ')},*/	/* Luba-Lulua */
-/*{"mlq",	HB_TAG('M','L','N',' ')},*/	/* Malinke */
-/*{"nso",	HB_TAG('N','S','O',' ')},*/	/* Sotho, Northern */
-/*{"??",	HB_TAG('M','A','L',' ')},*/	/* Malayalam Traditional */
-/*{"csw",	HB_TAG('N','C','R',' ')},*/	/* N-Cree */
-/*{"csw",	HB_TAG('N','H','C',' ')},*/	/* Norway House Cree */
-/*{"el-polyton",	HB_TAG('P','G','R',' ')},*/	/* Polytonic Greek */
-/*{"bgr, cnh, cnw, czt, sez, tcp, csy, ctd, flm, pck, tcz, zom, cmr, dao, hlt, cka, cnk, mrh, mwg, cbl, cnb, csh",	HB_TAG('Q','I','N',' ')},*/	/* Chin */
-/*{"??",	HB_TAG('Y','I','C',' ')},*/	/* Yi Classic */
-/*{"zh-Latn-pinyin",	HB_TAG('Z','H','P',' ')},*/	/* Chinese Phonetic */
-};
-
-typedef struct {
-  char language[11];
-  hb_tag_t tag;
-} LangTagLong;
-static const LangTagLong ot_languages_zh[] = {
-  /* Store longest-first, if one is a prefix of another. */
-  {"zh-cn",	HB_TAG('Z','H','S',' ')},	/* Chinese (China) */
-  {"zh-hk",	HB_TAG('Z','H','H',' ')},	/* Chinese (Hong Kong) */
-  {"zh-mo",	HB_TAG('Z','H','H',' ')},	/* Chinese (Macao) */
-  {"zh-sg",	HB_TAG('Z','H','S',' ')},	/* Chinese (Singapore) */
-  {"zh-tw",	HB_TAG('Z','H','T',' ')},	/* Chinese (Taiwan) */
-  {"zh-hans",	HB_TAG('Z','H','S',' ')},	/* Chinese (Simplified) */
-  {"zh-hant-hk",HB_TAG('Z','H','H',' ')},	/* Chinese (Hong Kong) */
-  {"zh-hant-mo",HB_TAG('Z','H','H',' ')},	/* Chinese (Macao) */
-  {"zh-hant",	HB_TAG('Z','H','T',' ')},	/* Chinese (Traditional) */
-};
-
-static int
-lang_compare_first_component (const void *pa,
-			      const void *pb)
-{
-  const char *a = (const char *) pa;
-  const char *b = (const char *) pb;
-  unsigned int da, db;
-  const char *p;
-
-  p = strchr (a, '-');
-  da = p ? (unsigned int) (p - a) : strlen (a);
-
-  p = strchr (b, '-');
-  db = p ? (unsigned int) (p - b) : strlen (b);
-
-  return strncmp (a, b, MAX (da, db));
-}
-
-static hb_bool_t
-lang_matches (const char *lang_str, const char *spec)
-{
-  unsigned int len = strlen (spec);
-
-  return strncmp (lang_str, spec, len) == 0 &&
-	 (lang_str[len] == '\0' || lang_str[len] == '-');
-}
-
-hb_tag_t
-hb_ot_tag_from_language (hb_language_t language)
-{
-  const char *lang_str, *s;
-
-  if (language == HB_LANGUAGE_INVALID)
-    return HB_OT_TAG_DEFAULT_LANGUAGE;
-
-  lang_str = hb_language_to_string (language);
-
-  s = strstr (lang_str, "x-hbot");
-  if (s) {
-    char tag[4];
-    int i;
-    s += 6;
-    for (i = 0; i < 4 && ISALNUM (s[i]); i++)
-      tag[i] = TOUPPER (s[i]);
-    if (i) {
-      for (; i < 4; i++)
-	tag[i] = ' ';
-      return HB_TAG (tag[0], tag[1], tag[2], tag[3]);
-    }
-  }
-
-  /*
-   * "fonipa" is a variant tag in BCP-47, meaning the International Phonetic Alphabet.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-fonipa")) {
-    return HB_TAG('I','P','P','H');  /* Phonetic transcription—IPA conventions */
-  }
-
-  /*
-   * "fonnapa" is a variant tag in BCP-47, meaning the North American Phonetic Alphabet
-   * also known as Americanist Phonetic Notation.  It can be applied to any language.
-   */
-  if (strstr (lang_str, "-fonnapa")) {
-    return HB_TAG('A','P','P','H');  /* Phonetic transcription—Americanist conventions */
-  }
-
-  /*
-   * "Syre" is a BCP-47 script tag, meaning the Estrangela variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syre")) {
-    return HB_TAG('S','Y','R','E');  /* Estrangela Syriac */
-  }
-
-  /*
-   * "Syrj" is a BCP-47 script tag, meaning the Western variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syrj")) {
-    return HB_TAG('S','Y','R','J');  /* Western Syriac */
-  }
-
-  /*
-   * "Syrn" is a BCP-47 script tag, meaning the Eastern variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syrn")) {
-    return HB_TAG('S','Y','R','N');  /* Eastern Syriac */
-  }
-
-  /* Find a language matching in the first component */
-  {
-    const LangTag *lang_tag;
-    lang_tag = (LangTag *) bsearch (lang_str, ot_languages,
-				    ARRAY_LENGTH (ot_languages), sizeof (LangTag),
-				    lang_compare_first_component);
-    if (lang_tag)
-      return lang_tag->tag;
-  }
-
-  /* Otherwise, check the Chinese ones */
-  if (0 == lang_compare_first_component (lang_str, "zh"))
-  {
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_LENGTH (ot_languages_zh); i++)
-    {
-      const LangTagLong *lang_tag;
-      lang_tag = &ot_languages_zh[i];
-      if (lang_matches (lang_str, lang_tag->language))
-	return lang_tag->tag;
-    }
-
-    /* Otherwise just return 'ZHS ' */
-    return HB_TAG('Z','H','S',' ');
-  }
-
-  s = strchr (lang_str, '-');
-  if (!s)
-    s = lang_str + strlen (lang_str);
-  if (s - lang_str == 3) {
-    /* Assume it's ISO-639-3 and upper-case and use it. */
-    return hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000u;
-  }
-
-  return HB_OT_TAG_DEFAULT_LANGUAGE;
-}
-
-/**
- * hb_ot_tag_to_language:
- *
- * 
- *
- * Return value: (transfer none):
- *
- * Since: 0.9.2
- **/
-hb_language_t
-hb_ot_tag_to_language (hb_tag_t tag)
-{
-  unsigned int i;
-
-  if (tag == HB_OT_TAG_DEFAULT_LANGUAGE)
-    return nullptr;
-
-  /* struct LangTag has only room for 3-letter language tags. */
-  switch (tag) {
-  case HB_TAG('A','P','P','H'):  /* Phonetic transcription—Americanist conventions */
-    return hb_language_from_string ("und-fonnapa", -1);
-  case HB_TAG('I','P','P','H'):  /* Phonetic transcription—IPA conventions */
-    return hb_language_from_string ("und-fonipa", -1);
-  case HB_TAG('S','Y','R',' '):  /* Syriac [macrolanguage] */
-    return hb_language_from_string ("syr", -1);
-  case HB_TAG('S','Y','R','E'):  /* Estrangela Syriac */
-    return hb_language_from_string ("und-Syre", -1);
-  case HB_TAG('S','Y','R','J'):  /* Western Syriac */
-    return hb_language_from_string ("und-Syrj", -1);
-  case HB_TAG('S','Y','R','N'):  /* Eastern Syriac */
-    return hb_language_from_string ("und-Syrn", -1);
-  }
-
-  for (i = 0; i < ARRAY_LENGTH (ot_languages); i++)
-    if (ot_languages[i].tag == tag)
-      return hb_language_from_string (ot_languages[i].language, -1);
-
-  /* If tag starts with ZH, it's Chinese */
-  if ((tag & 0xFFFF0000u)  == 0x5A480000u) {
-    switch (tag) {
-      case HB_TAG('Z','H','H',' '): return hb_language_from_string ("zh-hk", -1); /* Hong Kong */
-      case HB_TAG('Z','H','S',' '): return hb_language_from_string ("zh-Hans", -1); /* Simplified */
-      case HB_TAG('Z','H','T',' '): return hb_language_from_string ("zh-Hant", -1); /* Traditional */
-      default: break; /* Fall through */
-    }
-  }
-
-  /* Else return a custom language in the form of "x-hbotABCD" */
-  {
-    unsigned char buf[11] = "x-hbot";
-    buf[6] = tag >> 24;
-    buf[7] = (tag >> 16) & 0xFF;
-    buf[8] = (tag >> 8) & 0xFF;
-    buf[9] = tag & 0xFF;
-    if (buf[9] == 0x20)
-      buf[9] = '\0';
-    buf[10] = '\0';
-    return hb_language_from_string ((char *) buf, -1);
-  }
-}
-
-#ifdef MAIN
-static inline void
-test_langs_sorted (void)
-{
-  for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++)
-  {
-    int c = lang_compare_first_component (ot_languages[i-1].language, ot_languages[i].language);
-    if (c >= 0)
-    {
-      fprintf (stderr, "ot_languages not sorted at index %d: %s %d %s\n",
-	       i, ot_languages[i-1].language, c, ot_languages[i].language);
-      abort();
-    }
-  }
-}
-
-int
-main (void)
-{
-  test_langs_sorted ();
-  return 0;
-}
-
-#endif
diff --git a/third_party/harfbuzz-ng/src/hb-ot-tag.h b/third_party/harfbuzz-ng/src/hb-ot-tag.h
deleted file mode 100644
index 54fb747..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-tag.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_H_IN
-#error "Include <hb-ot.h> instead."
-#endif
-
-#ifndef HB_OT_TAG_H
-#define HB_OT_TAG_H
-
-#include "hb.h"
-
-HB_BEGIN_DECLS
-
-
-#define HB_OT_TAG_DEFAULT_SCRIPT	HB_TAG ('D', 'F', 'L', 'T')
-#define HB_OT_TAG_DEFAULT_LANGUAGE	HB_TAG ('d', 'f', 'l', 't')
-
-HB_EXTERN void
-hb_ot_tags_from_script (hb_script_t  script,
-			hb_tag_t    *script_tag_1,
-			hb_tag_t    *script_tag_2);
-
-HB_EXTERN hb_script_t
-hb_ot_tag_to_script (hb_tag_t tag);
-
-HB_EXTERN hb_tag_t
-hb_ot_tag_from_language (hb_language_t language);
-
-HB_EXTERN hb_language_t
-hb_ot_tag_to_language (hb_tag_t tag);
-
-
-HB_END_DECLS
-
-#endif /* HB_OT_TAG_H */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-var-avar-table.hh b/third_party/harfbuzz-ng/src/hb-ot-var-avar-table.hh
deleted file mode 100644
index e305a67..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-var-avar-table.hh
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_VAR_AVAR_TABLE_HH
-#define HB_OT_VAR_AVAR_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-namespace OT {
-
-
-struct AxisValueMap
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  public:
-  F2DOT14	fromCoord;	/* A normalized coordinate value obtained using
-				 * default normalization. */
-  F2DOT14	toCoord;	/* The modified, normalized coordinate value. */
-
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-struct SegmentMaps : ArrayOf<AxisValueMap>
-{
-  inline int map (int value) const
-  {
-    /* The following special-cases are not part of OpenType, which requires
-     * that at least -1, 0, and +1 must be mapped. But we include these as
-     * part of a better error recovery scheme. */
-
-    if (len < 2)
-    {
-      if (!len)
-	return value;
-      else /* len == 1*/
-	return value - array[0].fromCoord + array[0].toCoord;
-    }
-
-    if (value <= array[0].fromCoord)
-      return value - array[0].fromCoord + array[0].toCoord;
-
-    unsigned int i;
-    unsigned int count = len;
-    for (i = 1; i < count && value > array[i].fromCoord; i++)
-      ;
-
-    if (value >= array[i].fromCoord)
-      return value - array[i].fromCoord + array[i].toCoord;
-
-    if (unlikely (array[i-1].fromCoord == array[i].fromCoord))
-      return array[i-1].toCoord;
-
-    int denom = array[i].fromCoord - array[i-1].fromCoord;
-    return array[i-1].toCoord +
-	   ((array[i].toCoord - array[i-1].toCoord) *
-	    (value - array[i-1].fromCoord) + denom/2) / denom;
-  }
-
-  DEFINE_SIZE_ARRAY (2, array);
-};
-
-/*
- * avar — Axis Variations Table
- */
-
-#define HB_OT_TAG_avar HB_TAG('a','v','a','r')
-
-struct avar
-{
-  static const hb_tag_t tableTag	= HB_OT_TAG_avar;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!(version.sanitize (c) &&
-		    version.major == 1 &&
-		    c->check_struct (this))))
-      return_trace (false);
-
-    const SegmentMaps *map = &axisSegmentMapsZ;
-    unsigned int count = axisCount;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (unlikely (!map->sanitize (c)))
-        return_trace (false);
-      map = &StructAfter<SegmentMaps> (*map);
-    }
-
-    return_trace (true);
-  }
-
-  inline void map_coords (int *coords, unsigned int coords_length) const
-  {
-    unsigned int count = MIN<unsigned int> (coords_length, axisCount);
-
-    const SegmentMaps *map = &axisSegmentMapsZ;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      coords[i] = map->map (coords[i]);
-      map = &StructAfter<SegmentMaps> (*map);
-    }
-  }
-
-  protected:
-  FixedVersion<>version;	/* Version of the avar table
-				 * initially set to 0x00010000u */
-  HBUINT16	reserved;	/* This field is permanently reserved. Set to 0. */
-  HBUINT16	axisCount;	/* The number of variation axes in the font. This
-				 * must be the same number as axisCount in the
-				 * 'fvar' table. */
-  SegmentMaps	axisSegmentMapsZ;
-
-  public:
-  DEFINE_SIZE_MIN (8);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_VAR_AVAR_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-var-fvar-table.hh b/third_party/harfbuzz-ng/src/hb-ot-var-fvar-table.hh
deleted file mode 100644
index 999b723..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-var-fvar-table.hh
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_VAR_FVAR_TABLE_HH
-#define HB_OT_VAR_FVAR_TABLE_HH
-
-#include "hb-open-type-private.hh"
-
-namespace OT {
-
-
-struct InstanceRecord
-{
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  c->check_array (coordinates, coordinates[0].static_size, axis_count));
-  }
-
-  protected:
-  HBUINT16	subfamilyNameID;/* The name ID for entries in the 'name' table
-				 * that provide subfamily names for this instance. */
-  HBUINT16	reserved;	/* Reserved for future use — set to 0. */
-  Fixed		coordinates[VAR];/* The coordinates array for this instance. */
-  //HBUINT16	postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
-  //				  * table that provide PostScript names for this
-  //				  * instance. */
-
-  public:
-  DEFINE_SIZE_ARRAY (4, coordinates);
-};
-
-struct AxisRecord
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  public:
-  Tag		axisTag;	/* Tag identifying the design variation for the axis. */
-  Fixed		minValue;	/* The minimum coordinate value for the axis. */
-  Fixed		defaultValue;	/* The default coordinate value for the axis. */
-  Fixed		maxValue;	/* The maximum coordinate value for the axis. */
-  HBUINT16	reserved;	/* Reserved for future use — set to 0. */
-  HBUINT16	axisNameID;	/* The name ID for entries in the 'name' table that
-				 * provide a display name for this axis. */
-
-  public:
-  DEFINE_SIZE_STATIC (20);
-};
-
-
-/*
- * fvar — Font Variations Table
- */
-
-#define HB_OT_TAG_fvar HB_TAG('f','v','a','r')
-
-struct fvar
-{
-  static const hb_tag_t tableTag	= HB_OT_TAG_fvar;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  c->check_struct (this) &&
-		  instanceSize >= axisCount * 4 + 4 &&
-		  axisSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */
-		  instanceSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */
-		  c->check_range (this, things) &&
-		  c->check_range (&StructAtOffset<char> (this, things),
-				  axisCount * axisSize + instanceCount * instanceSize));
-  }
-
-  inline unsigned int get_axis_count (void) const
-  { return axisCount; }
-
-  inline bool get_axis (unsigned int index, hb_ot_var_axis_t *info) const
-  {
-    if (unlikely (index >= axisCount))
-      return false;
-
-    if (info)
-    {
-      const AxisRecord &axis = get_axes ()[index];
-      info->tag = axis.axisTag;
-      info->name_id =  axis.axisNameID;
-      info->default_value = axis.defaultValue / 65536.;
-      /* Ensure order, to simplify client math. */
-      info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
-      info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
-    }
-
-    return true;
-  }
-
-  inline unsigned int get_axis_infos (unsigned int      start_offset,
-				      unsigned int     *axes_count /* IN/OUT */,
-				      hb_ot_var_axis_t *axes_array /* OUT */) const
-  {
-    if (axes_count)
-    {
-      unsigned int count = axisCount;
-      start_offset = MIN (start_offset, count);
-
-      count -= start_offset;
-      axes_array += start_offset;
-
-      count = MIN (count, *axes_count);
-      *axes_count = count;
-
-      for (unsigned int i = 0; i < count; i++)
-	get_axis (start_offset + i, axes_array + i);
-    }
-    return axisCount;
-  }
-
-  inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const
-  {
-    const AxisRecord *axes = get_axes ();
-    unsigned int count = get_axis_count ();
-    for (unsigned int i = 0; i < count; i++)
-      if (axes[i].axisTag == tag)
-      {
-        if (index)
-	  *index = i;
-	return get_axis (i, info);
-      }
-    if (index)
-      *index = HB_OT_VAR_NO_AXIS_INDEX;
-    return false;
-  }
-
-  inline int normalize_axis_value (unsigned int axis_index, float v) const
-  {
-    hb_ot_var_axis_t axis;
-    if (!get_axis (axis_index, &axis))
-      return 0;
-
-    v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */
-
-    if (v == axis.default_value)
-      return 0;
-    else if (v < axis.default_value)
-      v = (v - axis.default_value) / (axis.default_value - axis.min_value);
-    else
-      v = (v - axis.default_value) / (axis.max_value - axis.default_value);
-    return (int) (v * 16384. + (v >= 0. ? .5 : -.5));
-  }
-
-  protected:
-  inline const AxisRecord * get_axes (void) const
-  { return &StructAtOffset<AxisRecord> (this, things); }
-
-  inline const InstanceRecord * get_instances (void) const
-  { return &StructAtOffset<InstanceRecord> (get_axes () + axisCount, 0); }
-
-  protected:
-  FixedVersion<>version;	/* Version of the fvar table
-				 * initially set to 0x00010000u */
-  Offset16	things;		/* Offset in bytes from the beginning of the table
-				 * to the start of the AxisRecord array. */
-  HBUINT16	reserved;	/* This field is permanently reserved. Set to 2. */
-  HBUINT16	axisCount;	/* The number of variation axes in the font (the
-				 * number of records in the axes array). */
-  HBUINT16	axisSize;	/* The size in bytes of each VariationAxisRecord —
-				 * set to 20 (0x0014) for this version. */
-  HBUINT16	instanceCount;	/* The number of named instances defined in the font
-				 * (the number of records in the instances array). */
-  HBUINT16	instanceSize;	/* The size in bytes of each InstanceRecord — set
-				 * to either axisCount * sizeof(Fixed) + 4, or to
-				 * axisCount * sizeof(Fixed) + 6. */
-
-  public:
-  DEFINE_SIZE_STATIC (16);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_VAR_FVAR_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-var-hvar-table.hh b/third_party/harfbuzz-ng/src/hb-ot-var-hvar-table.hh
deleted file mode 100644
index e20131b..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-var-hvar-table.hh
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_VAR_HVAR_TABLE_HH
-#define HB_OT_VAR_HVAR_TABLE_HH
-
-#include "hb-ot-layout-common-private.hh"
-
-
-namespace OT {
-
-
-struct DeltaSetIndexMap
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  c->check_array (mapData, get_width (), mapCount));
-  }
-
-  unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */
-  {
-    /* If count is zero, pass value unchanged.  This takes
-     * care of direct mapping for advance map. */
-    if (!mapCount)
-      return v;
-
-    if (v >= mapCount)
-      v = mapCount - 1;
-
-    unsigned int u = 0;
-    { /* Fetch it. */
-      unsigned int w = get_width ();
-      const HBUINT8 *p = mapData + w * v;
-      for (; w; w--)
-	u = (u << 8) + *p++;
-    }
-
-    { /* Repack it. */
-      unsigned int n = get_inner_bitcount ();
-      unsigned int outer = u >> n;
-      unsigned int inner = u & ((1 << n) - 1);
-      u = (outer<<16) | inner;
-    }
-
-    return u;
-  }
-
-  protected:
-  inline unsigned int get_width (void) const
-  { return ((format >> 4) & 3) + 1; }
-
-  inline unsigned int get_inner_bitcount (void) const
-  { return (format & 0xF) + 1; }
-
-  protected:
-  HBUINT16	format;		/* A packed field that describes the compressed
-				 * representation of delta-set indices. */
-  HBUINT16	mapCount;	/* The number of mapping entries. */
-  HBUINT8		mapData[VAR];	/* The delta-set index mapping data. */
-
-  public:
-  DEFINE_SIZE_ARRAY (4, mapData);
-};
-
-
-/*
- * HVAR -- The Horizontal Metrics Variations Table
- * VVAR -- The Vertical Metrics Variations Table
- */
-
-#define HB_OT_TAG_HVAR HB_TAG('H','V','A','R')
-#define HB_OT_TAG_VVAR HB_TAG('V','V','A','R')
-
-struct HVARVVAR
-{
-  static const hb_tag_t HVARTag	= HB_OT_TAG_HVAR;
-  static const hb_tag_t VVARTag	= HB_OT_TAG_VVAR;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  varStore.sanitize (c, this) &&
-		  advMap.sanitize (c, this) &&
-		  lsbMap.sanitize (c, this) &&
-		  rsbMap.sanitize (c, this));
-  }
-
-  inline float get_advance_var (hb_codepoint_t glyph,
-				int *coords, unsigned int coord_count) const
-  {
-    unsigned int varidx = (this+advMap).map (glyph);
-    return (this+varStore).get_delta (varidx, coords, coord_count);
-  }
-
-  inline bool has_sidebearing_deltas (void) const
-  { return lsbMap && rsbMap; }
-
-  protected:
-  FixedVersion<>version;	/* Version of the metrics variation table
-				 * initially set to 0x00010000u */
-  LOffsetTo<VariationStore>
-		varStore;	/* Offset to item variation store table. */
-  LOffsetTo<DeltaSetIndexMap>
-		advMap;		/* Offset to advance var-idx mapping. */
-  LOffsetTo<DeltaSetIndexMap>
-		lsbMap;		/* Offset to lsb/tsb var-idx mapping. */
-  LOffsetTo<DeltaSetIndexMap>
-		rsbMap;		/* Offset to rsb/bsb var-idx mapping. */
-
-  public:
-  DEFINE_SIZE_STATIC (20);
-};
-
-struct HVAR : HVARVVAR {
-  static const hb_tag_t tableTag	= HB_OT_TAG_HVAR;
-};
-struct VVAR : HVARVVAR {
-  static const hb_tag_t tableTag	= HB_OT_TAG_VVAR;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (static_cast<const HVARVVAR *> (this)->sanitize (c) &&
-		  vorgMap.sanitize (c, this));
-  }
-
-  protected:
-  LOffsetTo<DeltaSetIndexMap>
-		vorgMap;	/* Offset to vertical-origin var-idx mapping. */
-
-  public:
-  DEFINE_SIZE_STATIC (24);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_VAR_HVAR_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-var-mvar-table.hh b/third_party/harfbuzz-ng/src/hb-ot-var-mvar-table.hh
deleted file mode 100644
index e835768..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-var-mvar-table.hh
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_VAR_MVAR_TABLE_HH
-#define HB_OT_VAR_MVAR_TABLE_HH
-
-#include "hb-ot-layout-common-private.hh"
-
-
-namespace OT {
-
-
-struct VariationValueRecord
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  public:
-  Tag		valueTag;	/* Four-byte tag identifying a font-wide measure. */
-  HBUINT32		varIdx;		/* Outer/inner index into VariationStore item. */
-
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-
-/*
- * MVAR -- Metrics Variations Table
- */
-
-#define HB_OT_TAG_MVAR HB_TAG('M','V','A','R')
-
-struct MVAR
-{
-  static const hb_tag_t tableTag	= HB_OT_TAG_MVAR;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-		  likely (version.major == 1) &&
-		  c->check_struct (this) &&
-		  valueRecordSize >= VariationValueRecord::static_size &&
-		  varStore.sanitize (c, this) &&
-		  c->check_array (values, valueRecordSize, valueRecordCount));
-  }
-
-  inline float get_var (hb_tag_t tag,
-			int *coords, unsigned int coord_count) const
-  {
-    const VariationValueRecord *record;
-    record = (VariationValueRecord *) bsearch (&tag, values,
-					       valueRecordCount, valueRecordSize,
-					       tag_compare);
-    if (!record)
-      return 0.;
-
-    return (this+varStore).get_delta (record->varIdx, coords, coord_count);
-  }
-
-protected:
-  static inline int tag_compare (const void *pa, const void *pb)
-  {
-    const hb_tag_t *a = (const hb_tag_t *) pa;
-    const Tag *b = (const Tag *) pb;
-    return b->cmp (*a);
-  }
-
-  protected:
-  FixedVersion<>version;	/* Version of the metrics variation table
-				 * initially set to 0x00010000u */
-  HBUINT16	reserved;	/* Not used; set to 0. */
-  HBUINT16	valueRecordSize;/* The size in bytes of each value record —
-				 * must be greater than zero. */
-  HBUINT16	valueRecordCount;/* The number of value records — may be zero. */
-  OffsetTo<VariationStore>
-		varStore;	/* Offset to item variation store table. */
-  HBUINT8		values[VAR];	/* Array of value records. The records must be
-				 * in binary order of their valueTag field. */
-
-  public:
-  DEFINE_SIZE_ARRAY (12, values);
-};
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_VAR_MVAR_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-var.cc b/third_party/harfbuzz-ng/src/hb-ot-var.cc
deleted file mode 100644
index 90ba0bd..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-var.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-open-type-private.hh"
-
-#include "hb-ot-layout-private.hh"
-#include "hb-ot-var-avar-table.hh"
-#include "hb-ot-var-fvar-table.hh"
-#include "hb-ot-var-mvar-table.hh"
-#include "hb-ot-var.h"
-
-/*
- * fvar/avar
- */
-
-static inline const OT::fvar&
-_get_fvar (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::fvar);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->fvar.get ());
-}
-static inline const OT::avar&
-_get_avar (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::avar);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->avar.get ());
-}
-
-/**
- * hb_ot_var_has_data:
- * @face: #hb_face_t to test
- *
- * This function allows to verify the presence of OpenType variation data on the face.
- * Alternatively, use hb_ot_var_get_axis_count().
- *
- * Return value: true if face has a `fvar' table and false otherwise
- *
- * Since: 1.4.2
- **/
-hb_bool_t
-hb_ot_var_has_data (hb_face_t *face)
-{
-  return &_get_fvar (face) != &OT::Null(OT::fvar);
-}
-
-/**
- * hb_ot_var_get_axis_count:
- *
- * Since: 1.4.2
- **/
-unsigned int
-hb_ot_var_get_axis_count (hb_face_t *face)
-{
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.get_axis_count ();
-}
-
-/**
- * hb_ot_var_get_axes:
- *
- * Since: 1.4.2
- **/
-unsigned int
-hb_ot_var_get_axes (hb_face_t        *face,
-		    unsigned int      start_offset,
-		    unsigned int     *axes_count /* IN/OUT */,
-		    hb_ot_var_axis_t *axes_array /* OUT */)
-{
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.get_axis_infos (start_offset, axes_count, axes_array);
-}
-
-/**
- * hb_ot_var_find_axis:
- *
- * Since: 1.4.2
- **/
-hb_bool_t
-hb_ot_var_find_axis (hb_face_t        *face,
-		     hb_tag_t          axis_tag,
-		     unsigned int     *axis_index,
-		     hb_ot_var_axis_t *axis_info)
-{
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.find_axis (axis_tag, axis_index, axis_info);
-}
-
-
-/**
- * hb_ot_var_normalize_variations:
- *
- * Since: 1.4.2
- **/
-void
-hb_ot_var_normalize_variations (hb_face_t            *face,
-				const hb_variation_t *variations, /* IN */
-				unsigned int          variations_length,
-				int                  *coords, /* OUT */
-				unsigned int          coords_length)
-{
-  for (unsigned int i = 0; i < coords_length; i++)
-    coords[i] = 0;
-
-  const OT::fvar &fvar = _get_fvar (face);
-  for (unsigned int i = 0; i < variations_length; i++)
-  {
-    unsigned int axis_index;
-    if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, nullptr) &&
-	axis_index < coords_length)
-      coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value);
-  }
-
-  const OT::avar &avar = _get_avar (face);
-  avar.map_coords (coords, coords_length);
-}
-
-/**
- * hb_ot_var_normalize_coords:
- *
- * Since: 1.4.2
- **/
-void
-hb_ot_var_normalize_coords (hb_face_t    *face,
-			    unsigned int coords_length,
-			    const float *design_coords, /* IN */
-			    int *normalized_coords /* OUT */)
-{
-  const OT::fvar &fvar = _get_fvar (face);
-  for (unsigned int i = 0; i < coords_length; i++)
-    normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]);
-
-  const OT::avar &avar = _get_avar (face);
-  avar.map_coords (normalized_coords, coords_length);
-}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-var.h b/third_party/harfbuzz-ng/src/hb-ot-var.h
deleted file mode 100644
index a2c0c5f2..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot-var.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_H_IN
-#error "Include <hb-ot.h> instead."
-#endif
-
-#ifndef HB_OT_VAR_H
-#define HB_OT_VAR_H
-
-#include "hb.h"
-
-HB_BEGIN_DECLS
-
-
-#define HB_OT_TAG_VAR_AXIS_ITALIC	HB_TAG('i','t','a','l')
-#define HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE	HB_TAG('o','p','s','z')
-#define HB_OT_TAG_VAR_AXIS_SLANT	HB_TAG('s','l','n','t')
-#define HB_OT_TAG_VAR_AXIS_WIDTH	HB_TAG('w','d','t','h')
-#define HB_OT_TAG_VAR_AXIS_WEIGHT	HB_TAG('w','g','h','t')
-
-
-/*
- * fvar / avar
- */
-
-/**
- * hb_ot_var_axis_t:
- *
- * Since: 1.4.2
- */
-typedef struct hb_ot_var_axis_t {
-  hb_tag_t tag;
-  unsigned int name_id;
-  float min_value;
-  float default_value;
-  float max_value;
-} hb_ot_var_axis_t;
-
-HB_EXTERN hb_bool_t
-hb_ot_var_has_data (hb_face_t *face);
-
-/**
- * HB_OT_VAR_NO_AXIS_INDEX:
- *
- * Since: 1.4.2
- */
-#define HB_OT_VAR_NO_AXIS_INDEX		0xFFFFFFFFu
-
-HB_EXTERN unsigned int
-hb_ot_var_get_axis_count (hb_face_t *face);
-
-HB_EXTERN unsigned int
-hb_ot_var_get_axes (hb_face_t        *face,
-		    unsigned int      start_offset,
-		    unsigned int     *axes_count /* IN/OUT */,
-		    hb_ot_var_axis_t *axes_array /* OUT */);
-
-HB_EXTERN hb_bool_t
-hb_ot_var_find_axis (hb_face_t        *face,
-		     hb_tag_t          axis_tag,
-		     unsigned int     *axis_index,
-		     hb_ot_var_axis_t *axis_info);
-
-
-HB_EXTERN void
-hb_ot_var_normalize_variations (hb_face_t            *face,
-				const hb_variation_t *variations, /* IN */
-				unsigned int          variations_length,
-				int                  *coords, /* OUT */
-				unsigned int          coords_length);
-
-HB_EXTERN void
-hb_ot_var_normalize_coords (hb_face_t    *face,
-			    unsigned int coords_length,
-			    const float *design_coords, /* IN */
-			    int *normalized_coords /* OUT */);
-
-
-HB_END_DECLS
-
-#endif /* HB_OT_VAR_H */
diff --git a/third_party/harfbuzz-ng/src/hb-ot.h b/third_party/harfbuzz-ng/src/hb-ot.h
deleted file mode 100644
index 2120a3e..0000000
--- a/third_party/harfbuzz-ng/src/hb-ot.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_H
-#define HB_OT_H
-#define HB_OT_H_IN
-
-#include "hb.h"
-
-#include "hb-ot-font.h"
-#include "hb-ot-layout.h"
-#include "hb-ot-math.h"
-#include "hb-ot-tag.h"
-#include "hb-ot-shape.h"
-#include "hb-ot-var.h"
-
-HB_BEGIN_DECLS
-
-HB_END_DECLS
-
-#undef HB_OT_H_IN
-#endif /* HB_OT_H */
diff --git a/third_party/harfbuzz-ng/src/hb-private.hh b/third_party/harfbuzz-ng/src/hb-private.hh
deleted file mode 100644
index daa496e..0000000
--- a/third_party/harfbuzz-ng/src/hb-private.hh
+++ /dev/null
@@ -1,1073 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_PRIVATE_HH
-#define HB_PRIVATE_HH
-
-#define _GNU_SOURCE 1
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "hb.h"
-#define HB_H_IN
-#ifdef HAVE_OT
-#include "hb-ot.h"
-#define HB_OT_H_IN
-#endif
-
-#include <math.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#if defined(_MSC_VER) || defined(__MINGW32__)
-#include <intrin.h>
-#endif
-
-#define HB_PASTE1(a,b) a##b
-#define HB_PASTE(a,b) HB_PASTE1(a,b)
-
-/* Compile-time custom allocator support. */
-
-#if defined(hb_malloc_impl) \
- && defined(hb_calloc_impl) \
- && defined(hb_realloc_impl) \
- && defined(hb_free_impl)
-extern "C" void* hb_malloc_impl(size_t size);
-extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
-extern "C" void* hb_realloc_impl(void *ptr, size_t size);
-extern "C" void  hb_free_impl(void *ptr);
-#define malloc hb_malloc_impl
-#define calloc hb_calloc_impl
-#define realloc hb_realloc_impl
-#define free hb_free_impl
-#endif
-
-
-/* Compiler attributes */
-
-
-#if __cplusplus < 201103L
-
-#ifndef nullptr
-#define nullptr NULL
-#endif
-
-// Static assertions
-#ifndef static_assert
-#define static_assert(e, msg) \
-	HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
-#endif // static_assert
-
-#endif // __cplusplus < 201103L
-
-#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
-#define likely(expr) (__builtin_expect (!!(expr), 1))
-#define unlikely(expr) (__builtin_expect (!!(expr), 0))
-#else
-#define likely(expr) (expr)
-#define unlikely(expr) (expr)
-#endif
-
-#if !defined(__GNUC__) && !defined(__clang__)
-#undef __attribute__
-#define __attribute__(x)
-#endif
-
-#if __GNUC__ >= 3
-#define HB_PURE_FUNC	__attribute__((pure))
-#define HB_CONST_FUNC	__attribute__((const))
-#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
-#else
-#define HB_PURE_FUNC
-#define HB_CONST_FUNC
-#define HB_PRINTF_FUNC(format_idx, arg_idx)
-#endif
-#if __GNUC__ >= 4
-#define HB_UNUSED	__attribute__((unused))
-#elif defined(_MSC_VER) /* https://github.com/harfbuzz/harfbuzz/issues/635 */
-#define HB_UNUSED __pragma(warning(suppress: 4100 4101))
-#else
-#define HB_UNUSED
-#endif
-
-#ifndef HB_INTERNAL
-# if !defined(HB_NO_VISIBILITY) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_MSC_VER) && !defined(__SUNPRO_CC)
-#  define HB_INTERNAL __attribute__((__visibility__("hidden")))
-# else
-#  define HB_INTERNAL
-#  define HB_NO_VISIBILITY 1
-# endif
-#endif
-
-#if __GNUC__ >= 3
-#define HB_FUNC __PRETTY_FUNCTION__
-#elif defined(_MSC_VER)
-#define HB_FUNC __FUNCSIG__
-#else
-#define HB_FUNC __func__
-#endif
-
-#ifdef __SUNPRO_CC
-/* https://github.com/harfbuzz/harfbuzz/issues/630 */
-#define __restrict
-#endif
-
-/*
- * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
- * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
- * cases that fall through without a break or return statement. HB_FALLTHROUGH
- * is only needed on cases that have code:
- *
- * switch (foo) {
- *   case 1: // These cases have no code. No fallthrough annotations are needed.
- *   case 2:
- *   case 3:
- *     foo = 4; // This case has code, so a fallthrough annotation is needed:
- *     HB_FALLTHROUGH;
- *   default:
- *     return foo;
- * }
- */
-#if defined(__clang__) && __cplusplus >= 201103L
-   /* clang's fallthrough annotations are only available starting in C++11. */
-#  define HB_FALLTHROUGH [[clang::fallthrough]]
-#elif __GNUC__ >= 7
-   /* GNU fallthrough attribute is available from GCC7 */
-#  define HB_FALLTHROUGH __attribute__((fallthrough))
-#elif defined(_MSC_VER)
-   /*
-    * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
-    * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
-    */
-#  include <sal.h>
-#  define HB_FALLTHROUGH __fallthrough
-#else
-#  define HB_FALLTHROUGH /* FALLTHROUGH */
-#endif
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-   /* We need Windows Vista for both Uniscribe backend and for
-    * MemoryBarrier.  We don't support compiling on Windows XP,
-    * though we run on it fine. */
-#  if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
-#    undef _WIN32_WINNT
-#  endif
-#  ifndef _WIN32_WINNT
-#    define _WIN32_WINNT 0x0600
-#  endif
-#  ifndef WIN32_LEAN_AND_MEAN
-#    define WIN32_LEAN_AND_MEAN 1
-#  endif
-#  ifndef STRICT
-#    define STRICT 1
-#  endif
-
-#  if defined(_WIN32_WCE)
-     /* Some things not defined on Windows CE. */
-#    define vsnprintf _vsnprintf
-#    define getenv(Name) nullptr
-#    if _WIN32_WCE < 0x800
-#      define setlocale(Category, Locale) "C"
-static int errno = 0; /* Use something better? */
-#    endif
-#  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
-#    define getenv(Name) nullptr
-#  endif
-#  if defined(_MSC_VER) && _MSC_VER < 1900
-#    define snprintf _snprintf
-#  endif
-#endif
-
-#if HAVE_ATEXIT
-/* atexit() is only safe to be called from shared libraries on certain
- * platforms.  Whitelist.
- * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
-#  if defined(__linux) && defined(__GLIBC_PREREQ)
-#    if __GLIBC_PREREQ(2,3)
-/* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
-#      define HB_USE_ATEXIT 1
-#    endif
-#  elif defined(_MSC_VER) || defined(__MINGW32__)
-/* For MSVC:
- * http://msdn.microsoft.com/en-ca/library/tze57ck3.aspx
- * http://msdn.microsoft.com/en-ca/library/zk17ww08.aspx
- * mingw32 headers say atexit is safe to use in shared libraries.
- */
-#    define HB_USE_ATEXIT 1
-#  elif defined(__ANDROID__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
-/* This was fixed in Android NKD r8 or r8b:
- * https://code.google.com/p/android/issues/detail?id=6455
- * which introduced GCC 4.6:
- * https://developer.android.com/tools/sdk/ndk/index.html
- */
-#    define HB_USE_ATEXIT 1
-#  elif defined(__APPLE__)
-/* For macOS and related platforms, the atexit man page indicates
- * that it will be invoked when the library is unloaded, not only
- * at application exit.
- */
-#    define HB_USE_ATEXIT 1
-#  endif
-#endif
-
-/* Basics */
-
-#undef MIN
-template <typename Type>
-static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
-
-#undef MAX
-template <typename Type>
-static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
-
-static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
-{ return (a + (b - 1)) / b; }
-
-
-#undef  ARRAY_LENGTH
-template <typename Type, unsigned int n>
-static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
-/* A const version, but does not detect erratically being called on pointers. */
-#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
-
-#define HB_STMT_START do
-#define HB_STMT_END   while (0)
-
-template <unsigned int cond> class hb_assert_constant_t;
-template <> class hb_assert_constant_t<1> {};
-
-#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
-
-/* Lets assert int types.  Saves trouble down the road. */
-
-static_assert ((sizeof (int8_t) == 1), "");
-static_assert ((sizeof (uint8_t) == 1), "");
-static_assert ((sizeof (int16_t) == 2), "");
-static_assert ((sizeof (uint16_t) == 2), "");
-static_assert ((sizeof (int32_t) == 4), "");
-static_assert ((sizeof (uint32_t) == 4), "");
-static_assert ((sizeof (int64_t) == 8), "");
-static_assert ((sizeof (uint64_t) == 8), "");
-
-static_assert ((sizeof (hb_codepoint_t) == 4), "");
-static_assert ((sizeof (hb_position_t) == 4), "");
-static_assert ((sizeof (hb_mask_t) == 4), "");
-static_assert ((sizeof (hb_var_int_t) == 4), "");
-
-
-/* We like our types POD */
-
-#define _ASSERT_TYPE_POD1(_line, _type)	union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; }
-#define _ASSERT_TYPE_POD0(_line, _type)	_ASSERT_TYPE_POD1 (_line, _type)
-#define ASSERT_TYPE_POD(_type)		_ASSERT_TYPE_POD0 (__LINE__, _type)
-
-#ifdef __GNUC__
-# define _ASSERT_INSTANCE_POD1(_line, _instance) \
-	HB_STMT_START { \
-		typedef __typeof__(_instance) _type_##_line; \
-		_ASSERT_TYPE_POD1 (_line, _type_##_line); \
-	} HB_STMT_END
-#else
-# define _ASSERT_INSTANCE_POD1(_line, _instance)	typedef int _assertion_on_line_##_line##_not_tested
-#endif
-# define _ASSERT_INSTANCE_POD0(_line, _instance)	_ASSERT_INSTANCE_POD1 (_line, _instance)
-# define ASSERT_INSTANCE_POD(_instance)			_ASSERT_INSTANCE_POD0 (__LINE__, _instance)
-
-/* Check _assertion in a method environment */
-#define _ASSERT_POD1(_line) \
-	HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \
-	{ _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
-# define _ASSERT_POD0(_line)	_ASSERT_POD1 (_line)
-# define ASSERT_POD()		_ASSERT_POD0 (__LINE__)
-
-
-
-/* Misc */
-
-/*
- * Void!
- */
-typedef const struct _hb_void_t *hb_void_t;
-#define HB_VOID ((const _hb_void_t *) nullptr)
-
-/* Return the number of 1 bits in v. */
-template <typename T>
-static inline HB_CONST_FUNC unsigned int
-_hb_popcount (T v)
-{
-#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined(__OPTIMIZE__)
-  if (sizeof (T) <= sizeof (unsigned int))
-    return __builtin_popcount (v);
-
-  if (sizeof (T) <= sizeof (unsigned long))
-    return __builtin_popcountl (v);
-
-  if (sizeof (T) <= sizeof (unsigned long long))
-    return __builtin_popcountll (v);
-#endif
-
-  if (sizeof (T) <= 4)
-  {
-    /* "HACKMEM 169" */
-    uint32_t y;
-    y = (v >> 1) &033333333333;
-    y = v - y - ((y >>1) & 033333333333);
-    return (((y + (y >> 3)) & 030707070707) % 077);
-  }
-
-  if (sizeof (T) == 8)
-  {
-    unsigned int shift = 32;
-    return _hb_popcount<uint32_t> ((uint32_t) v) + _hb_popcount ((uint32_t) (v >> shift));
-  }
-
-  if (sizeof (T) == 16)
-  {
-    unsigned int shift = 64;
-    return _hb_popcount<uint64_t> ((uint64_t) v) + _hb_popcount ((uint64_t) (v >> shift));
-  }
-
-  assert (0);
-}
-
-/* Returns the number of bits needed to store number */
-template <typename T>
-static inline HB_CONST_FUNC unsigned int
-_hb_bit_storage (T v)
-{
-  if (unlikely (!v)) return 0;
-
-#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
-  if (sizeof (T) <= sizeof (unsigned int))
-    return sizeof (unsigned int) * 8 - __builtin_clz (v);
-
-  if (sizeof (T) <= sizeof (unsigned long))
-    return sizeof (unsigned long) * 8 - __builtin_clzl (v);
-
-  if (sizeof (T) <= sizeof (unsigned long long))
-    return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
-#endif
-
-#if defined(_MSC_VER) || defined(__MINGW32__)
-  if (sizeof (T) <= sizeof (unsigned int))
-  {
-    unsigned long where;
-    _BitScanReverse (&where, v);
-    return 1 + where;
-  }
-# if _WIN64
-  if (sizeof (T) <= 8)
-  {
-    unsigned long where;
-    _BitScanReverse64 (&where, v);
-    return 1 + where;
-  }
-# endif
-#endif
-
-  if (sizeof (T) <= 4)
-  {
-    /* "bithacks" */
-    const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
-    const unsigned int S[] = {1, 2, 4, 8, 16};
-    unsigned int r = 0;
-    for (int i = 4; i >= 0; i--)
-      if (v & b[i])
-      {
-	v >>= S[i];
-	r |= S[i];
-      }
-    return r + 1;
-  }
-  if (sizeof (T) <= 8)
-  {
-    /* "bithacks" */
-    const uint64_t b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000};
-    const unsigned int S[] = {1, 2, 4, 8, 16, 32};
-    unsigned int r = 0;
-    for (int i = 5; i >= 0; i--)
-      if (v & b[i])
-      {
-	v >>= S[i];
-	r |= S[i];
-      }
-    return r + 1;
-  }
-  if (sizeof (T) == 16)
-  {
-    unsigned int shift = 64;
-    return (v >> shift) ? _hb_bit_storage<uint64_t> ((uint64_t) v >> shift) + shift :
-			  _hb_bit_storage<uint64_t> ((uint64_t) v);
-  }
-
-  assert (0);
-}
-
-/* Returns the number of zero bits in the least significant side of v */
-template <typename T>
-static inline HB_CONST_FUNC unsigned int
-_hb_ctz (T v)
-{
-  if (unlikely (!v)) return 0;
-
-#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
-  if (sizeof (T) <= sizeof (unsigned int))
-    return __builtin_ctz (v);
-
-  if (sizeof (T) <= sizeof (unsigned long))
-    return __builtin_ctzl (v);
-
-  if (sizeof (T) <= sizeof (unsigned long long))
-    return __builtin_ctzll (v);
-#endif
-
-#if defined(_MSC_VER) || defined(__MINGW32__)
-  if (sizeof (T) <= sizeof (unsigned int))
-  {
-    unsigned long where;
-    _BitScanForward (&where, v);
-    return where;
-  }
-# if _WIN64
-  if (sizeof (T) <= 8)
-  {
-    unsigned long where;
-    _BitScanForward64 (&where, v);
-    return where;
-  }
-# endif
-#endif
-
-  if (sizeof (T) <= 4)
-  {
-    /* "bithacks" */
-    unsigned int c = 32;
-    v &= - (int32_t) v;
-    if (v) c--;
-    if (v & 0x0000FFFF) c -= 16;
-    if (v & 0x00FF00FF) c -= 8;
-    if (v & 0x0F0F0F0F) c -= 4;
-    if (v & 0x33333333) c -= 2;
-    if (v & 0x55555555) c -= 1;
-    return c;
-  }
-  if (sizeof (T) <= 8)
-  {
-    /* "bithacks" */
-    unsigned int c = 64;
-    v &= - (int64_t) (v);
-    if (v) c--;
-    if (v & 0x00000000FFFFFFFF) c -= 32;
-    if (v & 0x0000FFFF0000FFFF) c -= 16;
-    if (v & 0x00FF00FF00FF00FF) c -= 8;
-    if (v & 0x0F0F0F0F0F0F0F0F) c -= 4;
-    if (v & 0x3333333333333333) c -= 2;
-    if (v & 0x5555555555555555) c -= 1;
-    return c;
-  }
-  if (sizeof (T) == 16)
-  {
-    unsigned int shift = 64;
-    return (uint64_t) v ? _hb_bit_storage<uint64_t> ((uint64_t) v) :
-			  _hb_bit_storage<uint64_t> ((uint64_t) v >> shift) + shift;
-  }
-
-  assert (0);
-}
-
-static inline bool
-_hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
-{
-  return (size > 0) && (count >= ((unsigned int) -1) / size);
-}
-
-static inline unsigned int
-_hb_ceil_to_4 (unsigned int v)
-{
-  return ((v - 1) | 3) + 1;
-}
-
-
-
-/* arrays and maps */
-
-
-#define HB_PREALLOCED_ARRAY_INIT {0, 0, nullptr}
-template <typename Type, unsigned int StaticSize=16>
-struct hb_prealloced_array_t
-{
-  unsigned int len;
-  unsigned int allocated;
-  Type *array;
-  Type static_array[StaticSize];
-
-  void init (void)
-  {
-    len = 0;
-    allocated = ARRAY_LENGTH (static_array);
-    array = static_array;
-  }
-
-  inline Type& operator [] (unsigned int i) { return array[i]; }
-  inline const Type& operator [] (unsigned int i) const { return array[i]; }
-
-  inline Type *push (void)
-  {
-    if (unlikely (!resize (len + 1)))
-      return nullptr;
-
-    return &array[len - 1];
-  }
-
-  /* Allocate for size but don't adjust len. */
-  inline bool alloc(unsigned int size)
-  {
-    if (likely (size <= allocated))
-      return true;
-
-    /* Reallocate */
-
-    unsigned int new_allocated = allocated;
-    while (size >= new_allocated)
-      new_allocated += (new_allocated >> 1) + 8;
-
-    Type *new_array = nullptr;
-
-    if (array == static_array) {
-      new_array = (Type *) calloc (new_allocated, sizeof (Type));
-      if (new_array)
-        memcpy (new_array, array, len * sizeof (Type));
-          } else {
-      bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
-      if (likely (!overflows)) {
-        new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
-      }
-    }
-
-    if (unlikely (!new_array))
-      return false;
-
-    array = new_array;
-    allocated = new_allocated;
-
-    return true;
-  }
-
-  inline bool resize (unsigned int size)
-  {
-    if (!alloc (size))
-      return false;
-
-    len = size;
-    return true;
-  }
-
-  inline void pop (void)
-  {
-    len--;
-  }
-
-  inline void remove (unsigned int i)
-  {
-     if (unlikely (i >= len))
-       return;
-     memmove (static_cast<void *> (&array[i]),
-	      static_cast<void *> (&array[i + 1]),
-	      (len - i - 1) * sizeof (Type));
-     len--;
-  }
-
-  inline void shrink (unsigned int l)
-  {
-     if (l < len)
-       len = l;
-  }
-
-  template <typename T>
-  inline Type *find (T v) {
-    for (unsigned int i = 0; i < len; i++)
-      if (array[i] == v)
-	return &array[i];
-    return nullptr;
-  }
-  template <typename T>
-  inline const Type *find (T v) const {
-    for (unsigned int i = 0; i < len; i++)
-      if (array[i] == v)
-	return &array[i];
-    return nullptr;
-  }
-
-  inline void qsort (int (*cmp)(const void*, const void*))
-  {
-    ::qsort (array, len, sizeof (Type), cmp);
-  }
-
-  inline void qsort (void)
-  {
-    ::qsort (array, len, sizeof (Type), Type::cmp);
-  }
-
-  inline void qsort (unsigned int start, unsigned int end)
-  {
-    ::qsort (array + start, end - start, sizeof (Type), Type::cmp);
-  }
-
-  template <typename T>
-  inline Type *lsearch (const T &x)
-  {
-    for (unsigned int i = 0; i < len; i++)
-      if (0 == this->array[i].cmp (&x))
-	return &array[i];
-    return nullptr;
-  }
-
-  template <typename T>
-  inline Type *bsearch (const T &x)
-  {
-    unsigned int i;
-    return bfind (x, &i) ? &array[i] : nullptr;
-  }
-  template <typename T>
-  inline const Type *bsearch (const T &x) const
-  {
-    unsigned int i;
-    return bfind (x, &i) ? &array[i] : nullptr;
-  }
-  template <typename T>
-  inline bool bfind (const T &x, unsigned int *i) const
-  {
-    int min = 0, max = (int) this->len - 1;
-    while (min <= max)
-    {
-      int mid = (min + max) / 2;
-      int c = this->array[mid].cmp (&x);
-      if (c < 0)
-        max = mid - 1;
-      else if (c > 0)
-        min = mid + 1;
-      else
-      {
-        *i = mid;
-	return true;
-      }
-    }
-    if (max < 0 || (max < (int) this->len && this->array[max].cmp (&x) > 0))
-      max++;
-    *i = max;
-    return false;
-  }
-
-  inline void finish (void)
-  {
-    if (array != static_array)
-      free (array);
-    array = nullptr;
-    allocated = len = 0;
-  }
-};
-
-template <typename Type>
-struct hb_auto_array_t : hb_prealloced_array_t <Type>
-{
-  hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); }
-  ~hb_auto_array_t (void) { hb_prealloced_array_t<Type>::finish (); }
-};
-
-
-#define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT}
-template <typename item_t, typename lock_t>
-struct hb_lockable_set_t
-{
-  hb_prealloced_array_t <item_t, 1> items;
-
-  inline void init (void) { items.init (); }
-
-  template <typename T>
-  inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item) {
-      if (replace) {
-	item_t old = *item;
-	*item = v;
-	l.unlock ();
-	old.finish ();
-      }
-      else {
-        item = nullptr;
-	l.unlock ();
-      }
-    } else {
-      item = items.push ();
-      if (likely (item))
-	*item = v;
-      l.unlock ();
-    }
-    return item;
-  }
-
-  template <typename T>
-  inline void remove (T v, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item) {
-      item_t old = *item;
-      *item = items[items.len - 1];
-      items.pop ();
-      l.unlock ();
-      old.finish ();
-    } else {
-      l.unlock ();
-    }
-  }
-
-  template <typename T>
-  inline bool find (T v, item_t *i, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item)
-      *i = *item;
-    l.unlock ();
-    return !!item;
-  }
-
-  template <typename T>
-  inline item_t *find_or_insert (T v, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (!item) {
-      item = items.push ();
-      if (likely (item))
-        *item = v;
-    }
-    l.unlock ();
-    return item;
-  }
-
-  inline void finish (lock_t &l)
-  {
-    if (!items.len) {
-      /* No need for locking. */
-      items.finish ();
-      return;
-    }
-    l.lock ();
-    while (items.len) {
-      item_t old = items[items.len - 1];
-	items.pop ();
-	l.unlock ();
-	old.finish ();
-	l.lock ();
-    }
-    items.finish ();
-    l.unlock ();
-  }
-
-};
-
-
-/* ASCII tag/character handling */
-
-static inline bool ISALPHA (unsigned char c)
-{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
-static inline bool ISALNUM (unsigned char c)
-{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
-static inline bool ISSPACE (unsigned char c)
-{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
-static inline unsigned char TOUPPER (unsigned char c)
-{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
-static inline unsigned char TOLOWER (unsigned char c)
-{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
-
-
-/* HB_NDEBUG disables some sanity checks that are very safe to disable and
- * should be disabled in production systems.  If NDEBUG is defined, enable
- * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
- * light-weight) to be enabled, then HB_DEBUG can be defined to disable
- * the costlier checks. */
-#ifdef NDEBUG
-#define HB_NDEBUG
-#endif
-
-
-/* Misc */
-
-template <typename T> class hb_assert_unsigned_t;
-template <> class hb_assert_unsigned_t<unsigned char> {};
-template <> class hb_assert_unsigned_t<unsigned short> {};
-template <> class hb_assert_unsigned_t<unsigned int> {};
-template <> class hb_assert_unsigned_t<unsigned long> {};
-
-template <typename T> static inline bool
-hb_in_range (T u, T lo, T hi)
-{
-  /* The sizeof() is here to force template instantiation.
-   * I'm sure there are better ways to do this but can't think of
-   * one right now.  Declaring a variable won't work as HB_UNUSED
-   * is unusable on some platforms and unused types are less likely
-   * to generate a warning than unused variables. */
-  static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), "");
-
-  /* The casts below are important as if T is smaller than int,
-   * the subtract results will become a signed int! */
-  return (T)(u - lo) <= (T)(hi - lo);
-}
-
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
-{
-  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
-}
-
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
-{
-  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
-}
-
-
-/* Enable bitwise ops on enums marked as flags_t */
-/* To my surprise, looks like the function resolver is happy to silently cast
- * one enum to another...  So this doesn't provide the type-checking that I
- * originally had in mind... :(.
- *
- * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
- */
-#ifdef _MSC_VER
-# pragma warning(disable:4200)
-# pragma warning(disable:4800)
-#endif
-#define HB_MARK_AS_FLAG_T(T) \
-	extern "C++" { \
-	  static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
-	  static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
-	  static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
-	  static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
-	  static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
-	  static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
-	  static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
-	}
-
-
-/* Useful for set-operations on small enums.
- * For example, for testing "x ∈ {x1, x2, x3}" use:
- * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
- */
-#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned int)(x) < 32) + (1U << (unsigned int)(x)))
-#define FLAG_UNSAFE(x) ((unsigned int)(x) < 32 ? (1U << (unsigned int)(x)) : 0)
-#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
-
-
-template <typename T, typename T2> static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
-{
-  for (unsigned int i = 1; i < len; i++)
-  {
-    unsigned int j = i;
-    while (j && compar (&array[j - 1], &array[i]) > 0)
-      j--;
-    if (i == j)
-      continue;
-    /* Move item i to occupy place for item j, shift what's in between. */
-    {
-      T t = array[i];
-      memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
-      array[j] = t;
-    }
-    if (array2)
-    {
-      T2 t = array2[i];
-      memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
-      array2[j] = t;
-    }
-  }
-}
-
-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)
-{
-  /* Pain because we don't know whether s is nul-terminated. */
-  char buf[64];
-  len = MIN (ARRAY_LENGTH (buf) - 1, len);
-  strncpy (buf, s, len);
-  buf[len] = '\0';
-
-  char *end;
-  errno = 0;
-  unsigned long v = strtoul (buf, &end, base);
-  if (errno) return false;
-  if (*end) return false;
-  *out = v;
-  return true;
-}
-
-
-/* Vectorization */
-
-struct HbOpOr
-{
-  static const bool passthru_left = true;
-  static const bool passthru_right = true;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
-};
-struct HbOpAnd
-{
-  static const bool passthru_left = false;
-  static const bool passthru_right = false;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
-};
-struct HbOpMinus
-{
-  static const bool passthru_left = true;
-  static const bool passthru_right = false;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
-};
-struct HbOpXor
-{
-  static const bool passthru_left = true;
-  static const bool passthru_right = true;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
-};
-
-/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))). */
-template <typename elt_t, unsigned int byte_size>
-struct hb_vector_size_t
-{
-  elt_t& operator [] (unsigned int i) { return v[i]; }
-  const elt_t& operator [] (unsigned int i) const { return v[i]; }
-
-  template <class Op>
-  inline hb_vector_size_t process (const hb_vector_size_t &o) const
-  {
-    hb_vector_size_t r;
-    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
-      Op::process (r.v[i], v[i], o.v[i]);
-    return r;
-  }
-  inline hb_vector_size_t operator | (const hb_vector_size_t &o) const
-  { return process<HbOpOr> (o); }
-  inline hb_vector_size_t operator & (const hb_vector_size_t &o) const
-  { return process<HbOpAnd> (o); }
-  inline hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
-  { return process<HbOpXor> (o); }
-  inline hb_vector_size_t operator ~ () const
-  {
-    hb_vector_size_t r;
-    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
-      r.v[i] = ~v[i];
-    return r;
-  }
-
-  private:
-  static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
-  elt_t v[byte_size / sizeof (elt_t)];
-};
-
-/* The `vector_size' attribute was introduced in gcc 3.1. */
-#if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
-#define HAVE_VECTOR_SIZE 1
-#endif
-
-
-/* Global runtime options. */
-
-struct hb_options_t
-{
-  unsigned int initialized : 1;
-  unsigned int uniscribe_bug_compatible : 1;
-};
-
-union hb_options_union_t {
-  unsigned int i;
-  hb_options_t opts;
-};
-static_assert ((sizeof (int) == sizeof (hb_options_union_t)), "");
-
-HB_INTERNAL void
-_hb_options_init (void);
-
-extern HB_INTERNAL hb_options_union_t _hb_options;
-
-static inline hb_options_t
-hb_options (void)
-{
-  if (unlikely (!_hb_options.i))
-    _hb_options_init ();
-
-  return _hb_options.opts;
-}
-
-/* Size signifying variable-sized array */
-#define VAR 1
-
-
-/* String type. */
-
-struct hb_string_t
-{
-  inline hb_string_t (void) : bytes (nullptr), len (0) {}
-  inline hb_string_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {}
-
-  inline int cmp (const hb_string_t &a) const
-  {
-    if (len != a.len)
-      return (int) a.len - (int) len;
-
-    return memcmp (a.bytes, bytes, len);
-  }
-  static inline int cmp (const void *pa, const void *pb)
-  {
-    hb_string_t *a = (hb_string_t *) pa;
-    hb_string_t *b = (hb_string_t *) pb;
-    return b->cmp (*a);
-  }
-
-  const char *bytes;
-  unsigned int len;
-};
-
-
-#endif /* HB_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-set-digest-private.hh b/third_party/harfbuzz-ng/src/hb-set-digest-private.hh
deleted file mode 100644
index e099a82..0000000
--- a/third_party/harfbuzz-ng/src/hb-set-digest-private.hh
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SET_DIGEST_PRIVATE_HH
-#define HB_SET_DIGEST_PRIVATE_HH
-
-#include "hb-private.hh"
-
-/*
- * The set digests here implement various "filters" that support
- * "approximate member query".  Conceptually these are like Bloom
- * Filter and Quotient Filter, however, much smaller, faster, and
- * designed to fit the requirements of our uses for glyph coverage
- * queries.
- *
- * Our filters are highly accurate if the lookup covers fairly local
- * set of glyphs, but fully flooded and ineffective if coverage is
- * all over the place.
- *
- * The frozen-set can be used instead of a digest, to trade more
- * memory for 100% accuracy, but in practice, that doesn't look like
- * an attractive trade-off.
- */
-
-template <typename mask_t, unsigned int shift>
-struct hb_set_digest_lowest_bits_t
-{
-  ASSERT_POD ();
-
-  static const unsigned int mask_bytes = sizeof (mask_t);
-  static const unsigned int mask_bits = sizeof (mask_t) * 8;
-  static const unsigned int num_bits = 0
-				     + (mask_bytes >= 1 ? 3 : 0)
-				     + (mask_bytes >= 2 ? 1 : 0)
-				     + (mask_bytes >= 4 ? 1 : 0)
-				     + (mask_bytes >= 8 ? 1 : 0)
-				     + (mask_bytes >= 16? 1 : 0)
-				     + 0;
-
-  static_assert ((shift < sizeof (hb_codepoint_t) * 8), "");
-  static_assert ((shift + num_bits <= sizeof (hb_codepoint_t) * 8), "");
-
-  inline void init (void) {
-    mask = 0;
-  }
-
-  inline void add (hb_codepoint_t g) {
-    mask |= mask_for (g);
-  }
-
-  inline bool add_range (hb_codepoint_t a, hb_codepoint_t b) {
-    if ((b >> shift) - (a >> shift) >= mask_bits - 1)
-      mask = (mask_t) -1;
-    else {
-      mask_t ma = mask_for (a);
-      mask_t mb = mask_for (b);
-      mask |= mb + (mb - ma) - (mb < ma);
-    }
-    return true;
-  }
-
-  template <typename T>
-  inline void add_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);
-    }
-  }
-  template <typename T>
-  inline 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);
-    }
-    return true;
-  }
-
-  inline bool may_have (hb_codepoint_t g) const {
-    return !!(mask & mask_for (g));
-  }
-
-  private:
-
-  static inline mask_t mask_for (hb_codepoint_t g) {
-    return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1));
-  }
-  mask_t mask;
-};
-
-template <typename head_t, typename tail_t>
-struct hb_set_digest_combiner_t
-{
-  ASSERT_POD ();
-
-  inline void init (void) {
-    head.init ();
-    tail.init ();
-  }
-
-  inline void add (hb_codepoint_t g) {
-    head.add (g);
-    tail.add (g);
-  }
-
-  inline bool add_range (hb_codepoint_t a, hb_codepoint_t b) {
-    head.add_range (a, b);
-    tail.add_range (a, b);
-    return true;
-  }
-  template <typename T>
-  inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    head.add_array (array, count, stride);
-    tail.add_array (array, count, stride);
-  }
-  template <typename T>
-  inline 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;
-  }
-
-  inline bool may_have (hb_codepoint_t g) const {
-    return head.may_have (g) && tail.may_have (g);
-  }
-
-  private:
-  head_t head;
-  tail_t tail;
-};
-
-
-/*
- * hb_set_digest_t
- *
- * This is a combination of digests that performs "best".
- * There is not much science to this: it's a result of intuition
- * and testing.
- */
-typedef hb_set_digest_combiner_t
-<
-  hb_set_digest_lowest_bits_t<unsigned long, 4>,
-  hb_set_digest_combiner_t
-  <
-    hb_set_digest_lowest_bits_t<unsigned long, 0>,
-    hb_set_digest_lowest_bits_t<unsigned long, 9>
-  >
-> hb_set_digest_t;
-
-
-#endif /* HB_SET_DIGEST_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-set-private.hh b/third_party/harfbuzz-ng/src/hb-set-private.hh
deleted file mode 100644
index 3615c50e..0000000
--- a/third_party/harfbuzz-ng/src/hb-set-private.hh
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * Copyright © 2012,2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SET_PRIVATE_HH
-#define HB_SET_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-
-
-/*
- * hb_set_t
- */
-
-/* TODO Keep a free-list so we can free pages that are completely zeroed.  At that
- * point maybe also use a sentinel value for "all-1" pages? */
-
-struct hb_set_t
-{
-  struct page_map_t
-  {
-    inline int cmp (const page_map_t *o) const { return (int) o->major - (int) major; }
-
-    uint32_t major;
-    uint32_t index;
-  };
-
-  struct page_t
-  {
-    inline void init0 (void) { memset (&v, 0, sizeof (v)); }
-    inline void init1 (void) { memset (&v, 0xff, sizeof (v)); }
-
-    inline unsigned int len (void) const
-    { return ARRAY_LENGTH_CONST (v); }
-
-    inline bool is_empty (void) const
-    {
-      for (unsigned int i = 0; i < len (); i++)
-        if (v[i])
-	  return false;
-      return true;
-    }
-
-    inline void add (hb_codepoint_t g) { elt (g) |= mask (g); }
-    inline void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
-    inline bool has (hb_codepoint_t g) const { return !!(elt (g) & mask (g)); }
-
-    inline void add_range (hb_codepoint_t a, hb_codepoint_t b)
-    {
-      elt_t *la = &elt (a);
-      elt_t *lb = &elt (b);
-      if (la == lb)
-        *la |= (mask (b) << 1) - mask(a);
-      else
-      {
-	*la |= ~(mask (a) - 1);
-	la++;
-
-	memset (la, 0xff, (char *) lb - (char *) la);
-
-	*lb |= ((mask (b) << 1) - 1);
-      }
-    }
-
-    inline bool is_equal (const page_t *other) const
-    {
-      return 0 == memcmp (&v, &other->v, sizeof (v));
-    }
-
-    inline unsigned int get_population (void) const
-    {
-      unsigned int pop = 0;
-      for (unsigned int i = 0; i < len (); i++)
-        pop += _hb_popcount (v[i]);
-      return pop;
-    }
-
-    inline bool next (hb_codepoint_t *codepoint) const
-    {
-      unsigned int m = (*codepoint + 1) & MASK;
-      if (!m)
-      {
-	*codepoint = INVALID;
-	return false;
-      }
-      unsigned int i = m / ELT_BITS;
-      unsigned int j = m & ELT_MASK;
-
-      const elt_t vv = v[i] & ~((elt_t (1) << j) - 1);
-      for (const elt_t *p = &vv; i < len (); p = &v[++i])
-	if (*p)
-	{
-	  *codepoint = i * ELT_BITS + elt_get_min (*p);
-	  return true;
-	}
-
-      *codepoint = INVALID;
-      return false;
-    }
-    inline bool previous (hb_codepoint_t *codepoint) const
-    {
-      unsigned int m = (*codepoint - 1) & MASK;
-      if (m == MASK)
-      {
-	*codepoint = INVALID;
-	return false;
-      }
-      unsigned int i = m / ELT_BITS;
-      unsigned int j = m & ELT_MASK;
-
-      const elt_t vv = v[i] & ((elt_t (1) << (j + 1)) - 1);
-      for (const elt_t *p = &vv; (int) i >= 0; p = &v[--i])
-	if (*p)
-	{
-	  *codepoint = i * ELT_BITS + elt_get_max (*p);
-	  return true;
-	}
-
-      *codepoint = INVALID;
-      return false;
-    }
-    inline hb_codepoint_t get_min (void) const
-    {
-      for (unsigned int i = 0; i < len (); i++)
-        if (v[i])
-	  return i * ELT_BITS + elt_get_min (v[i]);
-      return INVALID;
-    }
-    inline hb_codepoint_t get_max (void) const
-    {
-      for (int i = len () - 1; i >= 0; i--)
-        if (v[i])
-	  return i * ELT_BITS + elt_get_max (v[i]);
-      return 0;
-    }
-
-    typedef unsigned long long elt_t;
-    static const unsigned int PAGE_BITS = 1024;
-    static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
-
-    static inline unsigned int elt_get_min (const elt_t &elt) { return _hb_ctz (elt); }
-    static inline unsigned int elt_get_max (const elt_t &elt) { return _hb_bit_storage (elt) - 1; }
-
-#if 0 && HAVE_VECTOR_SIZE
-    /* The vectorized version does not work with clang as non-const
-     * elt() errs "non-const reference cannot bind to vector element". */
-    typedef elt_t vector_t __attribute__((vector_size (PAGE_BITS / 8)));
-#else
-    typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
-#endif
-
-    vector_t v;
-
-    static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
-    static const unsigned int ELT_MASK = ELT_BITS - 1;
-    static const unsigned int BITS = sizeof (vector_t) * 8;
-    static const unsigned int MASK = BITS - 1;
-    static_assert (PAGE_BITS == BITS, "");
-
-    elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; }
-    elt_t const &elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
-    elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & ELT_MASK); }
-  };
-  static_assert (page_t::PAGE_BITS == sizeof (page_t) * 8, "");
-
-  hb_object_header_t header;
-  ASSERT_POD ();
-  bool in_error;
-  hb_prealloced_array_t<page_map_t, 8> page_map;
-  hb_prealloced_array_t<page_t, 1> pages;
-
-  inline void init (void)
-  {
-    in_error = false;
-    page_map.init ();
-    pages.init ();
-  }
-  inline void finish (void)
-  {
-    page_map.finish ();
-    pages.finish ();
-  }
-
-  inline bool resize (unsigned int count)
-  {
-    if (unlikely (in_error)) return false;
-    if (!pages.resize (count) || !page_map.resize (count))
-    {
-      pages.resize (page_map.len);
-      in_error = true;
-      return false;
-    }
-    return true;
-  }
-
-  inline void clear (void) {
-    if (unlikely (hb_object_is_inert (this)))
-      return;
-    in_error = false;
-    page_map.resize (0);
-    pages.resize (0);
-  }
-  inline bool is_empty (void) const {
-    unsigned int count = pages.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!pages[i].is_empty ())
-        return false;
-    return true;
-  }
-
-  inline void add (hb_codepoint_t g)
-  {
-    if (unlikely (in_error)) return;
-    if (unlikely (g == INVALID)) return;
-    page_t *page = page_for_insert (g); if (unlikely (!page)) return;
-    page->add (g);
-  }
-  inline bool add_range (hb_codepoint_t a, hb_codepoint_t b)
-  {
-    if (unlikely (in_error)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
-    if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
-    unsigned int ma = get_major (a);
-    unsigned int mb = get_major (b);
-    if (ma == mb)
-    {
-      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
-      page->add_range (a, b);
-    }
-    else
-    {
-      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
-      page->add_range (a, major_start (ma + 1) - 1);
-
-      for (unsigned int m = ma + 1; m < mb; m++)
-      {
-	page = page_for_insert (major_start (m)); if (unlikely (!page)) return false;
-	page->init1 ();
-      }
-
-      page = page_for_insert (b); if (unlikely (!page)) return false;
-      page->add_range (major_start (mb), b);
-    }
-    return true;
-  }
-
-  template <typename T>
-  inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    if (unlikely (in_error)) return;
-    if (!count) return;
-    hb_codepoint_t g = *array;
-    while (count)
-    {
-      unsigned int m = get_major (g);
-      page_t *page = page_for_insert (g); if (unlikely (!page)) return;
-      unsigned int start = major_start (m);
-      unsigned int end = major_start (m + 1);
-      do
-      {
-	page->add (g);
-
-	array = (const T *) ((const char *) array + stride);
-	count--;
-      }
-      while (count && (g = *array, start <= g && g < end));
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename T>
-  inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    if (unlikely (in_error)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
-    if (!count) return true;
-    hb_codepoint_t g = *array;
-    hb_codepoint_t last_g = g;
-    while (count)
-    {
-      unsigned int m = get_major (g);
-      page_t *page = page_for_insert (g); if (unlikely (!page)) return false;
-      unsigned int end = major_start (m + 1);
-      do
-      {
-        /* If we try harder we can change the following comparison to <=;
-	 * Not sure if it's worth it. */
-        if (g < last_g) return false;
-	last_g = g;
-	page->add (g);
-
-	array = (const T *) ((const char *) array + stride);
-	count--;
-      }
-      while (count && (g = *array, g < end));
-    }
-    return true;
-  }
-
-  inline void del (hb_codepoint_t g)
-  {
-    if (unlikely (in_error)) return;
-    page_t *p = page_for (g);
-    if (!p)
-      return;
-    p->del (g);
-  }
-  inline void del_range (hb_codepoint_t a, hb_codepoint_t b)
-  {
-    /* TODO Optimize, like add_range(). */
-    if (unlikely (in_error)) return;
-    for (unsigned int i = a; i < b + 1; i++)
-      del (i);
-  }
-  inline bool has (hb_codepoint_t g) const
-  {
-    const page_t *p = page_for (g);
-    if (!p)
-      return false;
-    return p->has (g);
-  }
-  inline bool intersects (hb_codepoint_t first,
-			  hb_codepoint_t last) const
-  {
-    hb_codepoint_t c = first - 1;
-    return next (&c) && c <= last;
-  }
-  inline void set (const hb_set_t *other)
-  {
-    if (unlikely (in_error)) return;
-    unsigned int count = other->pages.len;
-    if (!resize (count))
-      return;
-
-    memcpy (pages.array, other->pages.array, count * sizeof (pages.array[0]));
-    memcpy (page_map.array, other->page_map.array, count * sizeof (page_map.array[0]));
-  }
-
-  inline bool is_equal (const hb_set_t *other) const
-  {
-    unsigned int na = pages.len;
-    unsigned int nb = other->pages.len;
-
-    unsigned int a = 0, b = 0;
-    for (; a < na && b < nb; )
-    {
-      if (page_at (a).is_empty ()) { a++; continue; }
-      if (other->page_at (b).is_empty ()) { b++; continue; }
-      if (page_map[a].major != other->page_map[b].major ||
-	  !page_at (a).is_equal (&other->page_at (b)))
-        return false;
-      a++;
-      b++;
-    }
-    for (; a < na; a++)
-      if (!page_at (a).is_empty ()) { return false; }
-    for (; b < nb; b++)
-      if (!other->page_at (b).is_empty ()) { return false; }
-
-    return true;
-  }
-
-  template <class Op>
-  inline void process (const hb_set_t *other)
-  {
-    if (unlikely (in_error)) return;
-
-    unsigned int na = pages.len;
-    unsigned int nb = other->pages.len;
-    unsigned int next_page = na;
-
-    unsigned int count = 0;
-    unsigned int a = 0, b = 0;
-    for (; a < na && b < nb; )
-    {
-      if (page_map[a].major == other->page_map[b].major)
-      {
-        count++;
-	a++;
-	b++;
-      }
-      else if (page_map[a].major < other->page_map[b].major)
-      {
-        if (Op::passthru_left)
-	  count++;
-        a++;
-      }
-      else
-      {
-        if (Op::passthru_right)
-	  count++;
-        b++;
-      }
-    }
-    if (Op::passthru_left)
-      count += na - a;
-    if (Op::passthru_right)
-      count += nb - b;
-
-    if (!resize (count))
-      return;
-
-    /* Process in-place backward. */
-    a = na;
-    b = nb;
-    for (; a && b; )
-    {
-      if (page_map[a - 1].major == other->page_map[b - 1].major)
-      {
-	a--;
-	b--;
-	count--;
-	page_map[count] = page_map[a];
-	Op::process (page_at (count).v, page_at (a).v, other->page_at (b).v);
-      }
-      else if (page_map[a - 1].major > other->page_map[b - 1].major)
-      {
-	a--;
-	if (Op::passthru_left)
-	{
-	  count--;
-	  page_map[count] = page_map[a];
-	}
-      }
-      else
-      {
-	b--;
-	if (Op::passthru_right)
-	{
-	  count--;
-	  page_map[count].major = other->page_map[b].major;
-	  page_map[count].index = next_page++;
-	  page_at (count).v = other->page_at (b).v;
-	}
-      }
-    }
-    if (Op::passthru_left)
-      while (a)
-      {
-	a--;
-	count--;
-	page_map[count] = page_map [a];
-      }
-    if (Op::passthru_right)
-      while (b)
-      {
-	b--;
-	count--;
-	page_map[count].major = other->page_map[b].major;
-	page_map[count].index = next_page++;
-	page_at (count).v = other->page_at (b).v;
-      }
-    assert (!count);
-  }
-
-  inline void union_ (const hb_set_t *other)
-  {
-    process<HbOpOr> (other);
-  }
-  inline void intersect (const hb_set_t *other)
-  {
-    process<HbOpAnd> (other);
-  }
-  inline void subtract (const hb_set_t *other)
-  {
-    process<HbOpMinus> (other);
-  }
-  inline void symmetric_difference (const hb_set_t *other)
-  {
-    process<HbOpXor> (other);
-  }
-  inline bool next (hb_codepoint_t *codepoint) const
-  {
-    if (unlikely (*codepoint == INVALID)) {
-      *codepoint = get_min ();
-      return *codepoint != INVALID;
-    }
-
-    page_map_t map = {get_major (*codepoint), 0};
-    unsigned int i;
-    page_map.bfind (map, &i);
-    if (i < page_map.len && page_map[i].major == map.major)
-    {
-      if (pages[page_map[i].index].next (codepoint))
-      {
-	*codepoint += page_map[i].major * page_t::PAGE_BITS;
-	return true;
-      }
-      i++;
-    }
-    for (; i < page_map.len; i++)
-    {
-      hb_codepoint_t m = pages[page_map[i].index].get_min ();
-      if (m != INVALID)
-      {
-	*codepoint = page_map[i].major * page_t::PAGE_BITS + m;
-	return true;
-      }
-    }
-    *codepoint = INVALID;
-    return false;
-  }
-  inline bool previous (hb_codepoint_t *codepoint) const
-  {
-    if (unlikely (*codepoint == INVALID)) {
-      *codepoint = get_max ();
-      return *codepoint != INVALID;
-    }
-
-    page_map_t map = {get_major (*codepoint), 0};
-    unsigned int i;
-    page_map.bfind (map, &i);
-    if (i < page_map.len && page_map[i].major == map.major)
-    {
-      if (pages[page_map[i].index].previous (codepoint))
-      {
-	*codepoint += page_map[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 ();
-      if (m != INVALID)
-      {
-	*codepoint = page_map[i].major * page_t::PAGE_BITS + m;
-	return true;
-      }
-    }
-    *codepoint = INVALID;
-    return false;
-  }
-  inline bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
-  {
-    hb_codepoint_t i;
-
-    i = *last;
-    if (!next (&i))
-    {
-      *last = *first = INVALID;
-      return false;
-    }
-
-    /* TODO Speed up. */
-    *last = *first = i;
-    while (next (&i) && i == *last + 1)
-      (*last)++;
-
-    return true;
-  }
-  inline bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
-  {
-    hb_codepoint_t i;
-
-    i = *first;
-    if (!previous (&i))
-    {
-      *last = *first = INVALID;
-      return false;
-    }
-
-    /* TODO Speed up. */
-    *last = *first = i;
-    while (previous (&i) && i == *first - 1)
-      (*first)--;
-
-    return true;
-  }
-
-  inline unsigned int get_population (void) const
-  {
-    unsigned int pop = 0;
-    unsigned int count = pages.len;
-    for (unsigned int i = 0; i < count; i++)
-      pop += pages[i].get_population ();
-    return pop;
-  }
-  inline hb_codepoint_t get_min (void) const
-  {
-    unsigned int count = pages.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!page_at (i).is_empty ())
-        return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_min ();
-    return INVALID;
-  }
-  inline hb_codepoint_t get_max (void) const
-  {
-    unsigned int count = pages.len;
-    for (int i = count - 1; i >= 0; i++)
-      if (!page_at (i).is_empty ())
-        return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_max ();
-    return INVALID;
-  }
-
-  static  const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
-
-  inline page_t *page_for_insert (hb_codepoint_t g)
-  {
-    page_map_t map = {get_major (g), pages.len};
-    unsigned int i;
-    if (!page_map.bfind (map, &i))
-    {
-      if (!resize (pages.len + 1))
-	return nullptr;
-
-      pages[map.index].init0 ();
-      memmove (&page_map[i + 1], &page_map[i], (page_map.len - 1 - i) * sizeof (page_map[0]));
-      page_map[i] = map;
-    }
-    return &pages[page_map[i].index];
-  }
-  inline page_t *page_for (hb_codepoint_t g)
-  {
-    page_map_t key = {get_major (g)};
-    const page_map_t *found = page_map.bsearch (key);
-    if (found)
-      return &pages[found->index];
-    return nullptr;
-  }
-  inline const page_t *page_for (hb_codepoint_t g) const
-  {
-    page_map_t key = {get_major (g)};
-    const page_map_t *found = page_map.bsearch (key);
-    if (found)
-      return &pages[found->index];
-    return nullptr;
-  }
-  inline page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
-  inline const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
-  inline unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
-  inline hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
-};
-
-
-#endif /* HB_SET_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-set.cc b/third_party/harfbuzz-ng/src/hb-set.cc
deleted file mode 100644
index 07cf9d09..0000000
--- a/third_party/harfbuzz-ng/src/hb-set.cc
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-set-private.hh"
-
-
-/* Public API */
-
-
-/**
- * hb_set_create: (Xconstructor)
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.2
- **/
-hb_set_t *
-hb_set_create (void)
-{
-  hb_set_t *set;
-
-  if (!(set = hb_object_create<hb_set_t> ()))
-    return hb_set_get_empty ();
-
-  set->init ();
-
-  return set;
-}
-
-static const hb_set_t _hb_set_nil = {
-  HB_OBJECT_HEADER_STATIC,
-  true, /* in_error */
-
-  {0} /* elts */
-};
-
-/**
- * hb_set_get_empty:
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.2
- **/
-hb_set_t *
-hb_set_get_empty (void)
-{
-  return const_cast<hb_set_t *> (&_hb_set_nil);
-}
-
-/**
- * hb_set_reference: (skip)
- * @set: a set.
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.2
- **/
-hb_set_t *
-hb_set_reference (hb_set_t *set)
-{
-  return hb_object_reference (set);
-}
-
-/**
- * hb_set_destroy: (skip)
- * @set: a set.
- *
- * Since: 0.9.2
- **/
-void
-hb_set_destroy (hb_set_t *set)
-{
-  if (!hb_object_destroy (set)) return;
-
-  set->finish ();
-
-  free (set);
-}
-
-/**
- * hb_set_set_user_data: (skip)
- * @set: a set.
- * @key:
- * @data:
- * @destroy:
- * @replace:
- *
- * Return value:
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_set_set_user_data (hb_set_t           *set,
-		      hb_user_data_key_t *key,
-		      void *              data,
-		      hb_destroy_func_t   destroy,
-		      hb_bool_t           replace)
-{
-  return hb_object_set_user_data (set, key, data, destroy, replace);
-}
-
-/**
- * hb_set_get_user_data: (skip)
- * @set: a set.
- * @key:
- *
- * Return value: (transfer none):
- *
- * Since: 0.9.2
- **/
-void *
-hb_set_get_user_data (hb_set_t           *set,
-		      hb_user_data_key_t *key)
-{
-  return hb_object_get_user_data (set, key);
-}
-
-
-/**
- * hb_set_allocation_successful:
- * @set: a set.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_set_allocation_successful (const hb_set_t  *set HB_UNUSED)
-{
-  return !set->in_error;
-}
-
-/**
- * hb_set_clear:
- * @set: a set.
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_set_clear (hb_set_t *set)
-{
-  set->clear ();
-}
-
-/**
- * hb_set_is_empty:
- * @set: a set.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.7
- **/
-hb_bool_t
-hb_set_is_empty (const hb_set_t *set)
-{
-  return set->is_empty ();
-}
-
-/**
- * hb_set_has:
- * @set: a set.
- * @codepoint: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_set_has (const hb_set_t *set,
-	    hb_codepoint_t  codepoint)
-{
-  return set->has (codepoint);
-}
-
-/**
- * hb_set_add:
- * @set: a set.
- * @codepoint: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_set_add (hb_set_t       *set,
-	    hb_codepoint_t  codepoint)
-{
-  set->add (codepoint);
-}
-
-/**
- * hb_set_add_range:
- * @set: a set.
- * @first: 
- * @last: 
- *
- * 
- *
- * Since: 0.9.7
- **/
-void
-hb_set_add_range (hb_set_t       *set,
-		  hb_codepoint_t  first,
-		  hb_codepoint_t  last)
-{
-  set->add_range (first, last);
-}
-
-/**
- * hb_set_del:
- * @set: a set.
- * @codepoint: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_set_del (hb_set_t       *set,
-	    hb_codepoint_t  codepoint)
-{
-  set->del (codepoint);
-}
-
-/**
- * hb_set_del_range:
- * @set: a set.
- * @first: 
- * @last: 
- *
- * 
- *
- * Since: 0.9.7
- **/
-void
-hb_set_del_range (hb_set_t       *set,
-		  hb_codepoint_t  first,
-		  hb_codepoint_t  last)
-{
-  set->del_range (first, last);
-}
-
-/**
- * hb_set_is_equal:
- * @set: a set.
- * @other: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.7
- **/
-hb_bool_t
-hb_set_is_equal (const hb_set_t *set,
-		 const hb_set_t *other)
-{
-  return set->is_equal (other);
-}
-
-/**
- * hb_set_set:
- * @set: a set.
- * @other: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_set_set (hb_set_t       *set,
-	    const hb_set_t *other)
-{
-  set->set (other);
-}
-
-/**
- * hb_set_union:
- * @set: a set.
- * @other: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_set_union (hb_set_t       *set,
-	      const hb_set_t *other)
-{
-  set->union_ (other);
-}
-
-/**
- * hb_set_intersect:
- * @set: a set.
- * @other: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_set_intersect (hb_set_t       *set,
-		  const hb_set_t *other)
-{
-  set->intersect (other);
-}
-
-/**
- * hb_set_subtract:
- * @set: a set.
- * @other: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_set_subtract (hb_set_t       *set,
-		 const hb_set_t *other)
-{
-  set->subtract (other);
-}
-
-/**
- * hb_set_symmetric_difference:
- * @set: a set.
- * @other: 
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_set_symmetric_difference (hb_set_t       *set,
-			     const hb_set_t *other)
-{
-  set->symmetric_difference (other);
-}
-
-/**
- * hb_set_invert:
- * @set: a set.
- *
- * 
- *
- * Since: 0.9.10
- *
- * Deprecated: 1.6.1
- **/
-void
-hb_set_invert (hb_set_t *set)
-{
-}
-
-/**
- * hb_set_get_population:
- * @set: a set.
- *
- * Returns the number of numbers in the set.
- *
- * Return value: set population.
- *
- * Since: 0.9.7
- **/
-unsigned int
-hb_set_get_population (const hb_set_t *set)
-{
-  return set->get_population ();
-}
-
-/**
- * hb_set_get_min:
- * @set: a set.
- *
- * Finds the minimum number in the set.
- *
- * Return value: minimum of the set, or %HB_SET_VALUE_INVALID if set is empty.
- *
- * Since: 0.9.7
- **/
-hb_codepoint_t
-hb_set_get_min (const hb_set_t *set)
-{
-  return set->get_min ();
-}
-
-/**
- * hb_set_get_max:
- * @set: a set.
- *
- * Finds the maximum number in the set.
- *
- * Return value: minimum of the set, or %HB_SET_VALUE_INVALID if set is empty.
- *
- * Since: 0.9.7
- **/
-hb_codepoint_t
-hb_set_get_max (const hb_set_t *set)
-{
-  return set->get_max ();
-}
-
-/**
- * hb_set_next:
- * @set: a set.
- * @codepoint: (inout):
- *
- * Gets the next number in @set that is greater than current value of @codepoint.
- *
- * Set @codepoint to %HB_SET_VALUE_INVALID to get started.
- *
- * Return value: whether there was a next value.
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_set_next (const hb_set_t *set,
-	     hb_codepoint_t *codepoint)
-{
-  return set->next (codepoint);
-}
-
-/**
- * hb_set_previous:
- * @set: a set.
- * @codepoint: (inout):
- *
- * Gets the previous number in @set that is slower than current value of @codepoint.
- *
- * Set @codepoint to %HB_SET_VALUE_INVALID to get started.
- *
- * Return value: whether there was a previous value.
- *
- * Since: 1.8.0
- **/
-hb_bool_t
-hb_set_previous (const hb_set_t *set,
-		 hb_codepoint_t *codepoint)
-{
-  return set->previous (codepoint);
-}
-
-/**
- * hb_set_next_range:
- * @set: a set.
- * @first: (out): output first codepoint in the range.
- * @last: (inout): input current last and output last codepoint in the range.
- *
- * Gets the next consecutive range of numbers in @set that
- * are greater than current value of @last.
- *
- * Set @last to %HB_SET_VALUE_INVALID to get started.
- *
- * Return value: whether there was a next range.
- *
- * Since: 0.9.7
- **/
-hb_bool_t
-hb_set_next_range (const hb_set_t *set,
-		   hb_codepoint_t *first,
-		   hb_codepoint_t *last)
-{
-  return set->next_range (first, last);
-}
-
-/**
- * hb_set_previous_range:
- * @set: a set.
- * @first: (inout): input current first and output first codepoint in the range.
- * @last: (out): output last codepoint in the range.
- *
- * Gets the previous consecutive range of numbers in @set that
- * are greater than current value of @last.
- *
- * Set @first to %HB_SET_VALUE_INVALID to get started.
- *
- * Return value: whether there was a previous range.
- *
- * Since: 1.8.0
- **/
-hb_bool_t
-hb_set_previous_range (const hb_set_t *set,
-		       hb_codepoint_t *first,
-		       hb_codepoint_t *last)
-{
-  return set->previous_range (first, last);
-}
diff --git a/third_party/harfbuzz-ng/src/hb-set.h b/third_party/harfbuzz-ng/src/hb-set.h
deleted file mode 100644
index b0f82f8..0000000
--- a/third_party/harfbuzz-ng/src/hb-set.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_H_IN
-#error "Include <hb.h> instead."
-#endif
-
-#ifndef HB_SET_H
-#define HB_SET_H
-
-#include "hb-common.h"
-
-HB_BEGIN_DECLS
-
-
-/*
- * Since: 0.9.21
- */
-#define HB_SET_VALUE_INVALID ((hb_codepoint_t) -1)
-
-typedef struct hb_set_t hb_set_t;
-
-
-HB_EXTERN hb_set_t *
-hb_set_create (void);
-
-HB_EXTERN hb_set_t *
-hb_set_get_empty (void);
-
-HB_EXTERN hb_set_t *
-hb_set_reference (hb_set_t *set);
-
-HB_EXTERN void
-hb_set_destroy (hb_set_t *set);
-
-HB_EXTERN hb_bool_t
-hb_set_set_user_data (hb_set_t           *set,
-		      hb_user_data_key_t *key,
-		      void *              data,
-		      hb_destroy_func_t   destroy,
-		      hb_bool_t           replace);
-
-HB_EXTERN void *
-hb_set_get_user_data (hb_set_t           *set,
-		      hb_user_data_key_t *key);
-
-
-/* Returns false if allocation has failed before */
-HB_EXTERN hb_bool_t
-hb_set_allocation_successful (const hb_set_t *set);
-
-HB_EXTERN void
-hb_set_clear (hb_set_t *set);
-
-HB_EXTERN hb_bool_t
-hb_set_is_empty (const hb_set_t *set);
-
-HB_EXTERN hb_bool_t
-hb_set_has (const hb_set_t *set,
-	    hb_codepoint_t  codepoint);
-
-/* Right now limited to 16-bit integers.  Eventually will do full codepoint range, sans -1
- * which we will use as a sentinel. */
-HB_EXTERN void
-hb_set_add (hb_set_t       *set,
-	    hb_codepoint_t  codepoint);
-
-HB_EXTERN void
-hb_set_add_range (hb_set_t       *set,
-		  hb_codepoint_t  first,
-		  hb_codepoint_t  last);
-
-HB_EXTERN void
-hb_set_del (hb_set_t       *set,
-	    hb_codepoint_t  codepoint);
-
-HB_EXTERN void
-hb_set_del_range (hb_set_t       *set,
-		  hb_codepoint_t  first,
-		  hb_codepoint_t  last);
-
-HB_EXTERN hb_bool_t
-hb_set_is_equal (const hb_set_t *set,
-		 const hb_set_t *other);
-
-HB_EXTERN void
-hb_set_set (hb_set_t       *set,
-	    const hb_set_t *other);
-
-HB_EXTERN void
-hb_set_union (hb_set_t       *set,
-	      const hb_set_t *other);
-
-HB_EXTERN void
-hb_set_intersect (hb_set_t       *set,
-		  const hb_set_t *other);
-
-HB_EXTERN void
-hb_set_subtract (hb_set_t       *set,
-		 const hb_set_t *other);
-
-HB_EXTERN void
-hb_set_symmetric_difference (hb_set_t       *set,
-			     const hb_set_t *other);
-
-HB_EXTERN unsigned int
-hb_set_get_population (const hb_set_t *set);
-
-/* Returns HB_SET_VALUE_INVALID if set empty. */
-HB_EXTERN hb_codepoint_t
-hb_set_get_min (const hb_set_t *set);
-
-/* Returns HB_SET_VALUE_INVALID if set empty. */
-HB_EXTERN hb_codepoint_t
-hb_set_get_max (const hb_set_t *set);
-
-/* Pass HB_SET_VALUE_INVALID in to get started. */
-HB_EXTERN hb_bool_t
-hb_set_next (const hb_set_t *set,
-	     hb_codepoint_t *codepoint);
-
-/* Pass HB_SET_VALUE_INVALID in to get started. */
-HB_EXTERN hb_bool_t
-hb_set_previous (const hb_set_t *set,
-		 hb_codepoint_t *codepoint);
-
-/* Pass HB_SET_VALUE_INVALID for first and last to get started. */
-HB_EXTERN hb_bool_t
-hb_set_next_range (const hb_set_t *set,
-		   hb_codepoint_t *first,
-		   hb_codepoint_t *last);
-
-/* Pass HB_SET_VALUE_INVALID for first and last to get started. */
-HB_EXTERN hb_bool_t
-hb_set_previous_range (const hb_set_t *set,
-		       hb_codepoint_t *first,
-		       hb_codepoint_t *last);
-
-
-HB_END_DECLS
-
-#endif /* HB_SET_H */
diff --git a/third_party/harfbuzz-ng/src/hb-shape-plan-private.hh b/third_party/harfbuzz-ng/src/hb-shape-plan-private.hh
deleted file mode 100644
index aa0413a..0000000
--- a/third_party/harfbuzz-ng/src/hb-shape-plan-private.hh
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SHAPE_PLAN_PRIVATE_HH
-#define HB_SHAPE_PLAN_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-#include "hb-shaper-private.hh"
-
-
-struct hb_shape_plan_t
-{
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t default_shaper_list;
-  hb_face_t *face_unsafe; /* We don't carry a reference to face. */
-  hb_segment_properties_t props;
-
-  hb_shape_func_t *shaper_func;
-  const char *shaper_name;
-
-  hb_feature_t *user_features;
-  unsigned int num_user_features;
-
-  int *coords;
-  unsigned int num_coords;
-
-  struct hb_shaper_data_t shaper_data;
-};
-
-#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \
-	, const hb_feature_t *user_features \
-	, unsigned int        num_user_features \
-	, const int          *coords \
-	, unsigned int        num_coords
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, shape_plan);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
-
-#endif /* HB_SHAPE_PLAN_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-shape-plan.cc b/third_party/harfbuzz-ng/src/hb-shape-plan.cc
deleted file mode 100644
index 6eeba2b..0000000
--- a/third_party/harfbuzz-ng/src/hb-shape-plan.cc
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-shape-plan-private.hh"
-#include "hb-shaper-private.hh"
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
-
-
-static void
-hb_shape_plan_plan (hb_shape_plan_t    *shape_plan,
-		    const hb_feature_t *user_features,
-		    unsigned int        num_user_features,
-		    const int          *coords,
-		    unsigned int        num_coords,
-		    const char * const *shaper_list)
-{
-  DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
-		  "num_features=%d num_coords=%d shaper_list=%p",
-		  num_user_features,
-		  num_coords,
-		  shaper_list);
-
-  const hb_shaper_pair_t *shapers = _hb_shapers_get ();
-
-#define HB_SHAPER_PLAN(shaper) \
-	HB_STMT_START { \
-	  if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \
-	    HB_SHAPER_DATA (shaper, shape_plan) = \
-	      HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, \
-							       user_features, num_user_features, \
-							       coords, num_coords); \
-	    shape_plan->shaper_func = _hb_##shaper##_shape; \
-	    shape_plan->shaper_name = #shaper; \
-	    return; \
-	  } \
-	} HB_STMT_END
-
-  if (likely (!shaper_list)) {
-    for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
-      if (0)
-	;
-#define HB_SHAPER_IMPLEMENT(shaper) \
-      else if (shapers[i].func == _hb_##shaper##_shape) \
-	HB_SHAPER_PLAN (shaper);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-  } else {
-    for (; *shaper_list; shaper_list++)
-      if (0)
-	;
-#define HB_SHAPER_IMPLEMENT(shaper) \
-      else if (0 == strcmp (*shaper_list, #shaper)) \
-	HB_SHAPER_PLAN (shaper);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-  }
-
-#undef HB_SHAPER_PLAN
-}
-
-
-/*
- * hb_shape_plan_t
- */
-
-/**
- * hb_shape_plan_create: (Xconstructor)
- * @face: 
- * @props: 
- * @user_features: (array length=num_user_features):
- * @num_user_features: 
- * @shaper_list: (array zero-terminated=1):
- *
- * 
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.7
- **/
-hb_shape_plan_t *
-hb_shape_plan_create (hb_face_t                     *face,
-		      const hb_segment_properties_t *props,
-		      const hb_feature_t            *user_features,
-		      unsigned int                   num_user_features,
-		      const char * const            *shaper_list)
-{
-  return hb_shape_plan_create2 (face, props,
-				user_features, num_user_features,
-				nullptr, 0,
-				shaper_list);
-}
-
-hb_shape_plan_t *
-hb_shape_plan_create2 (hb_face_t                     *face,
-		       const hb_segment_properties_t *props,
-		       const hb_feature_t            *user_features,
-		       unsigned int                   num_user_features,
-		       const int                     *orig_coords,
-		       unsigned int                   num_coords,
-		       const char * const            *shaper_list)
-{
-  DEBUG_MSG_FUNC (SHAPE_PLAN, nullptr,
-		  "face=%p num_features=%d num_coords=%d shaper_list=%p",
-		  face,
-		  num_user_features,
-		  num_coords,
-		  shaper_list);
-
-  hb_shape_plan_t *shape_plan;
-  hb_feature_t *features = nullptr;
-  int *coords = nullptr;
-
-  if (unlikely (!face))
-    face = hb_face_get_empty ();
-  if (unlikely (!props))
-    return hb_shape_plan_get_empty ();
-  if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
-    return hb_shape_plan_get_empty ();
-  if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int))))
-  {
-    free (features);
-    return hb_shape_plan_get_empty ();
-  }
-  if (!(shape_plan = hb_object_create<hb_shape_plan_t> ()))
-  {
-    free (coords);
-    free (features);
-    return hb_shape_plan_get_empty ();
-  }
-
-  assert (props->direction != HB_DIRECTION_INVALID);
-
-  hb_face_make_immutable (face);
-  shape_plan->default_shaper_list = !shaper_list;
-  shape_plan->face_unsafe = face;
-  shape_plan->props = *props;
-  shape_plan->num_user_features = num_user_features;
-  shape_plan->user_features = features;
-  if (num_user_features)
-    memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
-  shape_plan->num_coords = num_coords;
-  shape_plan->coords = coords;
-  if (num_coords)
-    memcpy (coords, orig_coords, num_coords * sizeof (int));
-
-  hb_shape_plan_plan (shape_plan,
-		      user_features, num_user_features,
-		      coords, num_coords,
-		      shaper_list);
-
-  return shape_plan;
-}
-
-/**
- * hb_shape_plan_get_empty:
- *
- * 
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.7
- **/
-hb_shape_plan_t *
-hb_shape_plan_get_empty (void)
-{
-  static const hb_shape_plan_t _hb_shape_plan_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* default_shaper_list */
-    nullptr, /* face */
-    HB_SEGMENT_PROPERTIES_DEFAULT, /* props */
-
-    nullptr, /* shaper_func */
-    nullptr, /* shaper_name */
-
-    nullptr, /* user_features */
-    0,    /* num_user_featurs */
-
-    nullptr, /* coords */
-    0,    /* num_coords */
-
-    {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-    }
-  };
-
-  return const_cast<hb_shape_plan_t *> (&_hb_shape_plan_nil);
-}
-
-/**
- * hb_shape_plan_reference: (skip)
- * @shape_plan: a shape plan.
- *
- * 
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.7
- **/
-hb_shape_plan_t *
-hb_shape_plan_reference (hb_shape_plan_t *shape_plan)
-{
-  return hb_object_reference (shape_plan);
-}
-
-/**
- * hb_shape_plan_destroy: (skip)
- * @shape_plan: a shape plan.
- *
- * 
- *
- * Since: 0.9.7
- **/
-void
-hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
-{
-  if (!hb_object_destroy (shape_plan)) return;
-
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, shape_plan);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-  free (shape_plan->user_features);
-  free (shape_plan->coords);
-
-  free (shape_plan);
-}
-
-/**
- * hb_shape_plan_set_user_data: (skip)
- * @shape_plan: a shape plan.
- * @key: 
- * @data: 
- * @destroy: 
- * @replace: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.7
- **/
-hb_bool_t
-hb_shape_plan_set_user_data (hb_shape_plan_t    *shape_plan,
-			     hb_user_data_key_t *key,
-			     void *              data,
-			     hb_destroy_func_t   destroy,
-			     hb_bool_t           replace)
-{
-  return hb_object_set_user_data (shape_plan, key, data, destroy, replace);
-}
-
-/**
- * hb_shape_plan_get_user_data: (skip)
- * @shape_plan: a shape plan.
- * @key: 
- *
- * 
- *
- * Return value: (transfer none):
- *
- * Since: 0.9.7
- **/
-void *
-hb_shape_plan_get_user_data (hb_shape_plan_t    *shape_plan,
-			     hb_user_data_key_t *key)
-{
-  return hb_object_get_user_data (shape_plan, key);
-}
-
-
-/**
- * hb_shape_plan_execute:
- * @shape_plan: a shape plan.
- * @font: a font.
- * @buffer: a buffer.
- * @features: (array length=num_features):
- * @num_features: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.7
- **/
-hb_bool_t
-hb_shape_plan_execute (hb_shape_plan_t    *shape_plan,
-		       hb_font_t          *font,
-		       hb_buffer_t        *buffer,
-		       const hb_feature_t *features,
-		       unsigned int        num_features)
-{
-  DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
-		  "num_features=%d shaper_func=%p, shaper_name=%s",
-		  num_features,
-		  shape_plan->shaper_func,
-		  shape_plan->shaper_name);
-
-  if (unlikely (!buffer->len))
-    return true;
-
-  assert (!hb_object_is_inert (buffer));
-  assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
-
-  if (unlikely (hb_object_is_inert (shape_plan)))
-    return false;
-
-  assert (shape_plan->face_unsafe == font->face);
-  assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props));
-
-#define HB_SHAPER_EXECUTE(shaper) \
-	HB_STMT_START { \
-	  return HB_SHAPER_DATA (shaper, shape_plan) && \
-		 hb_##shaper##_shaper_font_data_ensure (font) && \
-		 _hb_##shaper##_shape (shape_plan, font, buffer, features, num_features); \
-	} HB_STMT_END
-
-  if (0)
-    ;
-#define HB_SHAPER_IMPLEMENT(shaper) \
-  else if (shape_plan->shaper_func == _hb_##shaper##_shape) \
-    HB_SHAPER_EXECUTE (shaper);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-#undef HB_SHAPER_EXECUTE
-
-  return false;
-}
-
-
-/*
- * caching
- */
-
-#if 0
-static unsigned int
-hb_shape_plan_hash (const hb_shape_plan_t *shape_plan)
-{
-  return hb_segment_properties_hash (&shape_plan->props) +
-	 shape_plan->default_shaper_list ? 0 : (intptr_t) shape_plan->shaper_func;
-}
-#endif
-
-/* User-feature caching is currently somewhat dumb:
- * it only finds matches where the feature array is identical,
- * not cases where the feature lists would be compatible for plan purposes
- * but have different ranges, for example.
- */
-struct hb_shape_plan_proposal_t
-{
-  const hb_segment_properties_t  props;
-  const char * const            *shaper_list;
-  const hb_feature_t            *user_features;
-  unsigned int                   num_user_features;
-  const int                     *coords;
-  unsigned int                   num_coords;
-  hb_shape_func_t               *shaper_func;
-};
-
-static inline hb_bool_t
-hb_shape_plan_user_features_match (const hb_shape_plan_t          *shape_plan,
-				   const hb_shape_plan_proposal_t *proposal)
-{
-  if (proposal->num_user_features != shape_plan->num_user_features)
-    return false;
-  for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++)
-    if (proposal->user_features[i].tag   != shape_plan->user_features[i].tag   ||
-        proposal->user_features[i].value != shape_plan->user_features[i].value ||
-        proposal->user_features[i].start != shape_plan->user_features[i].start ||
-        proposal->user_features[i].end   != shape_plan->user_features[i].end)
-      return false;
-  return true;
-}
-
-static inline hb_bool_t
-hb_shape_plan_coords_match (const hb_shape_plan_t          *shape_plan,
-			    const hb_shape_plan_proposal_t *proposal)
-{
-  if (proposal->num_coords != shape_plan->num_coords)
-    return false;
-  for (unsigned int i = 0, n = proposal->num_coords; i < n; i++)
-    if (proposal->coords[i] != shape_plan->coords[i])
-      return false;
-  return true;
-}
-
-static hb_bool_t
-hb_shape_plan_matches (const hb_shape_plan_t          *shape_plan,
-		       const hb_shape_plan_proposal_t *proposal)
-{
-  return hb_segment_properties_equal (&shape_plan->props, &proposal->props) &&
-	 hb_shape_plan_user_features_match (shape_plan, proposal) &&
-	 hb_shape_plan_coords_match (shape_plan, proposal) &&
-	 ((shape_plan->default_shaper_list && !proposal->shaper_list) ||
-	  (shape_plan->shaper_func == proposal->shaper_func));
-}
-
-static inline hb_bool_t
-hb_non_global_user_features_present (const hb_feature_t *user_features,
-				     unsigned int        num_user_features)
-{
-  while (num_user_features) {
-    if (user_features->start != 0 || user_features->end != (unsigned int) -1)
-      return true;
-    num_user_features--;
-    user_features++;
-  }
-  return false;
-}
-
-static inline hb_bool_t
-hb_coords_present (const int *coords,
-		   unsigned int num_coords)
-{
-  return num_coords != 0;
-}
-
-/**
- * hb_shape_plan_create_cached:
- * @face: 
- * @props: 
- * @user_features: (array length=num_user_features):
- * @num_user_features: 
- * @shaper_list: (array zero-terminated=1):
- *
- * 
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.7
- **/
-hb_shape_plan_t *
-hb_shape_plan_create_cached (hb_face_t                     *face,
-			     const hb_segment_properties_t *props,
-			     const hb_feature_t            *user_features,
-			     unsigned int                   num_user_features,
-			     const char * const            *shaper_list)
-{
-  return hb_shape_plan_create_cached2 (face, props,
-				       user_features, num_user_features,
-				       nullptr, 0,
-				       shaper_list);
-}
-
-hb_shape_plan_t *
-hb_shape_plan_create_cached2 (hb_face_t                     *face,
-			      const hb_segment_properties_t *props,
-			      const hb_feature_t            *user_features,
-			      unsigned int                   num_user_features,
-			      const int                     *coords,
-			      unsigned int                   num_coords,
-			      const char * const            *shaper_list)
-{
-  DEBUG_MSG_FUNC (SHAPE_PLAN, nullptr,
-		  "face=%p num_features=%d shaper_list=%p",
-		  face,
-		  num_user_features,
-		  shaper_list);
-
-  hb_shape_plan_proposal_t proposal = {
-    *props,
-    shaper_list,
-    user_features,
-    num_user_features,
-    nullptr
-  };
-
-  if (shaper_list) {
-    /* Choose shaper.  Adapted from hb_shape_plan_plan().
-     * Must choose shaper exactly the same way as that function. */
-    for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_item++)
-      if (0)
-	;
-#define HB_SHAPER_IMPLEMENT(shaper) \
-      else if (0 == strcmp (*shaper_item, #shaper) && \
-	       hb_##shaper##_shaper_face_data_ensure (face)) \
-      { \
-	proposal.shaper_func = _hb_##shaper##_shape; \
-	break; \
-      }
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-    if (unlikely (!proposal.shaper_func))
-      return hb_shape_plan_get_empty ();
-  }
-
-
-retry:
-  hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atomic_ptr_get (&face->shape_plans);
-
-  /* Don't look for plan in the cache if there were variation coordinates XXX Fix me. */
-  if (!hb_coords_present (coords, num_coords))
-    for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next)
-      if (hb_shape_plan_matches (node->shape_plan, &proposal))
-      {
-        DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache");
-        return hb_shape_plan_reference (node->shape_plan);
-      }
-
-  /* Not found. */
-  hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props,
-						       user_features, num_user_features,
-						       coords, num_coords,
-						       shaper_list);
-
-  /* Don't add to the cache if face is inert. */
-  if (unlikely (hb_object_is_inert (face)))
-    return shape_plan;
-
-  /* Don't add the plan to the cache if there were user features with non-global ranges */
-  if (hb_non_global_user_features_present (user_features, num_user_features))
-    return shape_plan;
-  /* Don't add the plan to the cache if there were variation coordinates XXX Fix me. */
-  if (hb_coords_present (coords, num_coords))
-    return shape_plan;
-
-  hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t));
-  if (unlikely (!node))
-    return shape_plan;
-
-  node->shape_plan = shape_plan;
-  node->next = cached_plan_nodes;
-
-  if (!hb_atomic_ptr_cmpexch (&face->shape_plans, cached_plan_nodes, node)) {
-    hb_shape_plan_destroy (shape_plan);
-    free (node);
-    goto retry;
-  }
-  DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, "inserted into cache");
-
-  return hb_shape_plan_reference (shape_plan);
-}
-
-/**
- * hb_shape_plan_get_shaper:
- * @shape_plan: a shape plan.
- *
- * 
- *
- * Return value: (transfer none):
- *
- * Since: 0.9.7
- **/
-const char *
-hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan)
-{
-  return shape_plan->shaper_name;
-}
diff --git a/third_party/harfbuzz-ng/src/hb-shape-plan.h b/third_party/harfbuzz-ng/src/hb-shape-plan.h
deleted file mode 100644
index b62ae7c..0000000
--- a/third_party/harfbuzz-ng/src/hb-shape-plan.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_H_IN
-#error "Include <hb.h> instead."
-#endif
-
-#ifndef HB_SHAPE_PLAN_H
-#define HB_SHAPE_PLAN_H
-
-#include "hb-common.h"
-#include "hb-font.h"
-
-HB_BEGIN_DECLS
-
-typedef struct hb_shape_plan_t hb_shape_plan_t;
-
-HB_EXTERN hb_shape_plan_t *
-hb_shape_plan_create (hb_face_t                     *face,
-		      const hb_segment_properties_t *props,
-		      const hb_feature_t            *user_features,
-		      unsigned int                   num_user_features,
-		      const char * const            *shaper_list);
-
-HB_EXTERN hb_shape_plan_t *
-hb_shape_plan_create_cached (hb_face_t                     *face,
-			     const hb_segment_properties_t *props,
-			     const hb_feature_t            *user_features,
-			     unsigned int                   num_user_features,
-			     const char * const            *shaper_list);
-
-HB_EXTERN hb_shape_plan_t *
-hb_shape_plan_create2 (hb_face_t                     *face,
-		       const hb_segment_properties_t *props,
-		       const hb_feature_t            *user_features,
-		       unsigned int                   num_user_features,
-		       const int                     *coords,
-		       unsigned int                   num_coords,
-		       const char * const            *shaper_list);
-
-HB_EXTERN hb_shape_plan_t *
-hb_shape_plan_create_cached2 (hb_face_t                     *face,
-			      const hb_segment_properties_t *props,
-			      const hb_feature_t            *user_features,
-			      unsigned int                   num_user_features,
-			      const int                     *coords,
-			      unsigned int                   num_coords,
-			      const char * const            *shaper_list);
-
-
-HB_EXTERN hb_shape_plan_t *
-hb_shape_plan_get_empty (void);
-
-HB_EXTERN hb_shape_plan_t *
-hb_shape_plan_reference (hb_shape_plan_t *shape_plan);
-
-HB_EXTERN void
-hb_shape_plan_destroy (hb_shape_plan_t *shape_plan);
-
-HB_EXTERN hb_bool_t
-hb_shape_plan_set_user_data (hb_shape_plan_t    *shape_plan,
-			     hb_user_data_key_t *key,
-			     void *              data,
-			     hb_destroy_func_t   destroy,
-			     hb_bool_t           replace);
-
-HB_EXTERN void *
-hb_shape_plan_get_user_data (hb_shape_plan_t    *shape_plan,
-			     hb_user_data_key_t *key);
-
-
-HB_EXTERN hb_bool_t
-hb_shape_plan_execute (hb_shape_plan_t    *shape_plan,
-		       hb_font_t          *font,
-		       hb_buffer_t        *buffer,
-		       const hb_feature_t *features,
-		       unsigned int        num_features);
-
-HB_EXTERN const char *
-hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan);
-
-
-HB_END_DECLS
-
-#endif /* HB_SHAPE_PLAN_H */
diff --git a/third_party/harfbuzz-ng/src/hb-shape.cc b/third_party/harfbuzz-ng/src/hb-shape.cc
deleted file mode 100644
index 39355b3..0000000
--- a/third_party/harfbuzz-ng/src/hb-shape.cc
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-
-#include "hb-shaper-private.hh"
-#include "hb-shape-plan-private.hh"
-#include "hb-buffer-private.hh"
-#include "hb-font-private.hh"
-
-/**
- * SECTION:hb-shape
- * @title: Shaping
- * @short_description: Conversion of text strings into positioned glyphs
- * @include: hb.h
- *
- * Shaping is the central operation of HarfBuzz. Shaping operates on buffers,
- * which are sequences of Unicode characters that use the same font and have
- * the same text direction, script and language. After shaping the buffer
- * contains the output glyphs and their positions.
- **/
-
-static const char **static_shaper_list;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_shaper_list (void)
-{
-  free (static_shaper_list);
-}
-#endif
-
-/**
- * hb_shape_list_shapers:
- *
- * Retrieves the list of shapers supported by HarfBuzz.
- *
- * Return value: (transfer none) (array zero-terminated=1): an array of
- *    constant strings
- *
- * Since: 0.9.2
- **/
-const char **
-hb_shape_list_shapers (void)
-{
-retry:
-  const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
-
-  if (unlikely (!shaper_list))
-  {
-    /* Not found; allocate one. */
-    shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
-    if (unlikely (!shaper_list)) {
-      static const char *nil_shaper_list[] = {nullptr};
-      return nil_shaper_list;
-    }
-
-    const hb_shaper_pair_t *shapers = _hb_shapers_get ();
-    unsigned int i;
-    for (i = 0; i < HB_SHAPERS_COUNT; i++)
-      shaper_list[i] = shapers[i].name;
-    shaper_list[i] = nullptr;
-
-    if (!hb_atomic_ptr_cmpexch (&static_shaper_list, nullptr, shaper_list)) {
-      free (shaper_list);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_shaper_list); /* First person registers atexit() callback. */
-#endif
-  }
-
-  return shaper_list;
-}
-
-
-/**
- * hb_shape_full:
- * @font: an #hb_font_t to use for shaping
- * @buffer: an #hb_buffer_t to shape
- * @features: (array length=num_features) (allow-none): an array of user
- *    specified #hb_feature_t or %NULL
- * @num_features: the length of @features array
- * @shaper_list: (array zero-terminated=1) (allow-none): a %NULL-terminated
- *    array of shapers to use or %NULL
- *
- * See hb_shape() for details. If @shaper_list is not %NULL, the specified
- * shapers will be used in the given order, otherwise the default shapers list
- * will be used.
- *
- * Return value: false if all shapers failed, true otherwise
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_shape_full (hb_font_t          *font,
-	       hb_buffer_t        *buffer,
-	       const hb_feature_t *features,
-	       unsigned int        num_features,
-	       const char * const *shaper_list)
-{
-  hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached2 (font->face, &buffer->props,
-							      features, num_features,
-							      font->coords, font->num_coords,
-							      shaper_list);
-  hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
-  hb_shape_plan_destroy (shape_plan);
-
-  if (res)
-    buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
-  return res;
-}
-
-/**
- * hb_shape:
- * @font: an #hb_font_t to use for shaping
- * @buffer: an #hb_buffer_t to shape
- * @features: (array length=num_features) (allow-none): an array of user
- *    specified #hb_feature_t or %NULL
- * @num_features: the length of @features array
- *
- * Shapes @buffer using @font turning its Unicode characters content to
- * positioned glyphs. If @features is not %NULL, it will be used to control the
- * features applied during shaping.
- *
- * Since: 0.9.2
- **/
-void
-hb_shape (hb_font_t           *font,
-	  hb_buffer_t         *buffer,
-	  const hb_feature_t  *features,
-	  unsigned int         num_features)
-{
-  hb_shape_full (font, buffer, features, num_features, nullptr);
-}
diff --git a/third_party/harfbuzz-ng/src/hb-shape.h b/third_party/harfbuzz-ng/src/hb-shape.h
deleted file mode 100644
index 39507ff74..0000000
--- a/third_party/harfbuzz-ng/src/hb-shape.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_H_IN
-#error "Include <hb.h> instead."
-#endif
-
-#ifndef HB_SHAPE_H
-#define HB_SHAPE_H
-
-#include "hb-common.h"
-#include "hb-buffer.h"
-#include "hb-font.h"
-
-HB_BEGIN_DECLS
-
-
-HB_EXTERN void
-hb_shape (hb_font_t           *font,
-	  hb_buffer_t         *buffer,
-	  const hb_feature_t  *features,
-	  unsigned int         num_features);
-
-HB_EXTERN hb_bool_t
-hb_shape_full (hb_font_t          *font,
-	       hb_buffer_t        *buffer,
-	       const hb_feature_t *features,
-	       unsigned int        num_features,
-	       const char * const *shaper_list);
-
-HB_EXTERN const char **
-hb_shape_list_shapers (void);
-
-
-HB_END_DECLS
-
-#endif /* HB_SHAPE_H */
diff --git a/third_party/harfbuzz-ng/src/hb-shaper-impl-private.hh b/third_party/harfbuzz-ng/src/hb-shaper-impl-private.hh
deleted file mode 100644
index 7844081..0000000
--- a/third_party/harfbuzz-ng/src/hb-shaper-impl-private.hh
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SHAPER_IMPL_PRIVATE_HH
-#define HB_SHAPER_IMPL_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-shaper-private.hh"
-#include "hb-shape-plan-private.hh"
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
-
-
-#ifdef HB_SHAPER
-#define HB_SHAPER_DATA_GET(object) HB_SHAPER_DATA (HB_SHAPER, object)
-#endif
-
-
-#endif /* HB_SHAPER_IMPL_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-shaper-list.hh b/third_party/harfbuzz-ng/src/hb-shaper-list.hh
deleted file mode 100644
index b0835d31..0000000
--- a/third_party/harfbuzz-ng/src/hb-shaper-list.hh
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SHAPER_LIST_HH
-#define HB_SHAPER_LIST_HH
-#endif /* HB_SHAPER_LIST_HH */ /* Dummy header guards */
-
-/* v--- Add new shapers in the right place here. */
-
-#ifdef HAVE_GRAPHITE2
-/* Only picks up fonts that have a "Silf" table. */
-HB_SHAPER_IMPLEMENT (graphite2)
-#endif
-#ifdef HAVE_CORETEXT
-/* Only picks up fonts that have a "mort" or "morx" table. */
-HB_SHAPER_IMPLEMENT (coretext_aat)
-#endif
-
-#ifdef HAVE_OT
-HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */
-#endif
-
-#ifdef HAVE_UNISCRIBE
-HB_SHAPER_IMPLEMENT (uniscribe)
-#endif
-#ifdef HAVE_DIRECTWRITE
-HB_SHAPER_IMPLEMENT (directwrite)
-#endif
-#ifdef HAVE_CORETEXT
-HB_SHAPER_IMPLEMENT (coretext)
-#endif
-
-#ifdef HAVE_FALLBACK
-HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */
-#endif
diff --git a/third_party/harfbuzz-ng/src/hb-shaper-private.hh b/third_party/harfbuzz-ng/src/hb-shaper-private.hh
deleted file mode 100644
index ce2d9f28..0000000
--- a/third_party/harfbuzz-ng/src/hb-shaper-private.hh
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SHAPER_PRIVATE_HH
-#define HB_SHAPER_PRIVATE_HH
-
-#include "hb-private.hh"
-
-typedef hb_bool_t hb_shape_func_t (hb_shape_plan_t    *shape_plan,
-				   hb_font_t          *font,
-				   hb_buffer_t        *buffer,
-				   const hb_feature_t *features,
-				   unsigned int        num_features);
-
-#define HB_SHAPER_IMPLEMENT(name) \
-	extern "C" HB_INTERNAL hb_shape_func_t _hb_##name##_shape;
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-struct hb_shaper_pair_t {
-  char name[16];
-  hb_shape_func_t *func;
-};
-
-HB_INTERNAL const hb_shaper_pair_t *
-_hb_shapers_get (void);
-
-
-/* For embedding in face / font / ... */
-struct hb_shaper_data_t {
-#define HB_SHAPER_IMPLEMENT(shaper) void *shaper;
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-};
-
-#define HB_SHAPERS_COUNT (sizeof (hb_shaper_data_t) / sizeof (void *))
-
-/* Means: succeeded, but don't need to keep any data. */
-#define HB_SHAPER_DATA_SUCCEEDED ((void *) +1)
-
-/* Means: tried but failed to create. */
-#define HB_SHAPER_DATA_INVALID ((void *) -1)
-#define HB_SHAPER_DATA_IS_INVALID(data) ((void *) (data) == HB_SHAPER_DATA_INVALID)
-
-#define HB_SHAPER_DATA_TYPE_NAME(shaper, object)	hb_##shaper##_shaper_##object##_data_t
-#define HB_SHAPER_DATA_TYPE(shaper, object)		struct HB_SHAPER_DATA_TYPE_NAME(shaper, object)
-#define HB_SHAPER_DATA_INSTANCE(shaper, object, instance)	(* (HB_SHAPER_DATA_TYPE(shaper, object) **) &(instance)->shaper_data.shaper)
-#define HB_SHAPER_DATA(shaper, object)			HB_SHAPER_DATA_INSTANCE(shaper, object, object)
-#define HB_SHAPER_DATA_CREATE_FUNC(shaper, object)	_hb_##shaper##_shaper_##object##_data_create
-#define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object)	_hb_##shaper##_shaper_##object##_data_destroy
-#define HB_SHAPER_DATA_ENSURE_FUNC(shaper, object)	hb_##shaper##_shaper_##object##_data_ensure
-
-#define HB_SHAPER_DATA_PROTOTYPE(shaper, object) \
-	HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \
-	extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \
-	HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS); \
-	extern "C" HB_INTERNAL void \
-	HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data); \
-	extern "C" HB_INTERNAL bool \
-	HB_SHAPER_DATA_ENSURE_FUNC (shaper, object) (hb_##object##_t *object)
-
-#define HB_SHAPER_DATA_DESTROY(shaper, object) \
-    if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \
-      if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \
-        HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data);
-
-#define HB_SHAPER_DATA_ENSURE_DEFINE(shaper, object) \
-	HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, true)
-
-#define HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, condition) \
-bool \
-HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \
-{\
-  retry: \
-  HB_SHAPER_DATA_TYPE (shaper, object) *data = (HB_SHAPER_DATA_TYPE (shaper, object) *) hb_atomic_ptr_get (&HB_SHAPER_DATA (shaper, object)); \
-  if (likely (data) && !(condition)) { \
-    /* Drop and recreate. */ \
-    /* If someone dropped it in the mean time, throw it away and don't touch it. \
-     * Otherwise, destruct it. */ \
-    if (hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), data, nullptr)) { \
-      HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \
-    } \
-    goto retry; \
-  } \
-  if (unlikely (!data)) { \
-    data = HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (object); \
-    if (unlikely (!data)) \
-      data = (HB_SHAPER_DATA_TYPE (shaper, object) *) HB_SHAPER_DATA_INVALID; \
-    if (!hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), nullptr, data)) { \
-      if (data && \
-	  data != HB_SHAPER_DATA_INVALID && \
-	  data != HB_SHAPER_DATA_SUCCEEDED) \
-	HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \
-      goto retry; \
-    } \
-  } \
-  return data != nullptr && !HB_SHAPER_DATA_IS_INVALID (data); \
-}
-
-
-#endif /* HB_SHAPER_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-shaper.cc b/third_party/harfbuzz-ng/src/hb-shaper.cc
deleted file mode 100644
index 2c44cf26..0000000
--- a/third_party/harfbuzz-ng/src/hb-shaper.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-#include "hb-shaper-private.hh"
-#include "hb-atomic-private.hh"
-
-
-static const hb_shaper_pair_t all_shapers[] = {
-#define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape},
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-};
-
-
-/* Thread-safe, lock-free, shapers */
-
-static const hb_shaper_pair_t *static_shapers;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_shapers (void)
-{
-  if (unlikely (static_shapers != all_shapers))
-    free ((void *) static_shapers);
-}
-#endif
-
-const hb_shaper_pair_t *
-_hb_shapers_get (void)
-{
-retry:
-  hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_shapers);
-
-  if (unlikely (!shapers))
-  {
-    char *env = getenv ("HB_SHAPER_LIST");
-    if (!env || !*env) {
-      (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]);
-      return (const hb_shaper_pair_t *) all_shapers;
-    }
-
-    /* Not found; allocate one. */
-    shapers = (hb_shaper_pair_t *) calloc (1, sizeof (all_shapers));
-    if (unlikely (!shapers)) {
-      (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]);
-      return (const hb_shaper_pair_t *) all_shapers;
-    }
-
-    memcpy (shapers, all_shapers, sizeof (all_shapers));
-
-     /* Reorder shaper list to prefer requested shapers. */
-    unsigned int i = 0;
-    char *end, *p = env;
-    for (;;) {
-      end = strchr (p, ',');
-      if (!end)
-	end = p + strlen (p);
-
-      for (unsigned int j = i; j < ARRAY_LENGTH (all_shapers); j++)
-	if (end - p == (int) strlen (shapers[j].name) &&
-	    0 == strncmp (shapers[j].name, p, end - p))
-	{
-	  /* Reorder this shaper to position i */
-	 struct hb_shaper_pair_t t = shapers[j];
-	 memmove (&shapers[i + 1], &shapers[i], sizeof (shapers[i]) * (j - i));
-	 shapers[i] = t;
-	 i++;
-	}
-
-      if (!*end)
-	break;
-      else
-	p = end + 1;
-    }
-
-    if (!hb_atomic_ptr_cmpexch (&static_shapers, nullptr, shapers)) {
-      free (shapers);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_shapers); /* First person registers atexit() callback. */
-#endif
-  }
-
-  return shapers;
-}
diff --git a/third_party/harfbuzz-ng/src/hb-string-array.hh b/third_party/harfbuzz-ng/src/hb-string-array.hh
deleted file mode 100644
index ba829b0c..0000000
--- a/third_party/harfbuzz-ng/src/hb-string-array.hh
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_STRING_ARRAY_HH
-#if 0 /* Make checks happy. */
-#define HB_STRING_ARRAY_HH
-#endif
-
-#include "hb-private.hh"
-
-/* Based on Bruno Haible's code in Appendix B of Ulrich Drepper's dsohowto.pdf:
- * https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf */
-
-#define HB_STRING_ARRAY_TYPE_NAME	HB_PASTE(HB_STRING_ARRAY_NAME, _msgstr_t)
-#define HB_STRING_ARRAY_POOL_NAME	HB_PASTE(HB_STRING_ARRAY_NAME, _msgstr)
-#define HB_STRING_ARRAY_OFFS_NAME	HB_PASTE(HB_STRING_ARRAY_NAME, _msgidx)
-
-static const union HB_STRING_ARRAY_TYPE_NAME {
-  struct {
-/* I like to avoid storing the nul-termination byte since we don't need it,
- * but C++ does not allow that.
- * https://stackoverflow.com/questions/28433862/why-initializer-string-for-array-of-chars-is-too-long-compiles-fine-in-c-not
- */
-#define _S(s) char HB_PASTE (str, __LINE__)[sizeof (s)];
-#include HB_STRING_ARRAY_LIST
-#undef _S
-  } st;
-  char str[VAR];
-}
-HB_STRING_ARRAY_POOL_NAME =
-{
-  {
-#define _S(s) s,
-#include HB_STRING_ARRAY_LIST
-#undef _S
-  }
-};
-static const unsigned int HB_STRING_ARRAY_OFFS_NAME[] =
-{
-#define _S(s) offsetof (union HB_STRING_ARRAY_TYPE_NAME, st.HB_PASTE(str, __LINE__)),
-#include HB_STRING_ARRAY_LIST
-#undef _S
-  sizeof (HB_STRING_ARRAY_TYPE_NAME)
-};
-
-static inline hb_string_t
-HB_STRING_ARRAY_NAME (unsigned int i)
-{
-  assert (i < ARRAY_LENGTH (HB_STRING_ARRAY_OFFS_NAME) - 1);
-  return hb_string_t (HB_STRING_ARRAY_POOL_NAME.str + HB_STRING_ARRAY_OFFS_NAME[i],
-		      HB_STRING_ARRAY_OFFS_NAME[i + 1] - HB_STRING_ARRAY_OFFS_NAME[i] - 1);
-}
-
-#undef HB_STRING_ARRAY_TYPE_NAME
-#undef HB_STRING_ARRAY_POOL_NAME
-#undef HB_STRING_ARRAY_OFFS_NAME
-
-#endif /* HB_STRING_ARRAY_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-subset-glyf.hh b/third_party/harfbuzz-ng/src/hb-subset-glyf.hh
deleted file mode 100644
index 99b76db9..0000000
--- a/third_party/harfbuzz-ng/src/hb-subset-glyf.hh
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger
- */
-
-#ifndef HB_SUBSET_GLYF_HH
-#define HB_SUBSET_GLYF_HH
-
-#include "hb-private.hh"
-
-#include "hb-subset-plan.hh"
-
-HB_INTERNAL bool
-hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
-                         bool             *use_short_loca, /* OUT */
-                         hb_blob_t       **glyf_prime /* OUT */,
-                         hb_blob_t       **loca_prime /* OUT */);
-
-#endif /* HB_SUBSET_GLYF_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-subset-plan.hh b/third_party/harfbuzz-ng/src/hb-subset-plan.hh
deleted file mode 100644
index d1b66b4..0000000
--- a/third_party/harfbuzz-ng/src/hb-subset-plan.hh
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger, Roderick Sheeter
- */
-
-#ifndef HB_SUBSET_PLAN_HH
-#define HB_SUBSET_PLAN_HH
-
-#include "hb-private.hh"
-
-#include "hb-subset.h"
-
-#include "hb-object-private.hh"
-
-struct hb_subset_plan_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t drop_hints;
-
-  // TODO(Q1) actual map, drop this crap
-  // Look at me ma, I'm a poor mans map codepoint : new gid
-  // codepoints is sorted and aligned with gids_to_retain.
-
-  // These first two lists provide a mapping from cp -> gid
-  // As a result it does not list the full set of glyphs to retain.
-  hb_prealloced_array_t<hb_codepoint_t> codepoints;
-  hb_prealloced_array_t<hb_codepoint_t> gids_to_retain;
-
-  // This list contains the complete set of glyphs to retain and may contain
-  // more glyphs then the lists above.
-  hb_prealloced_array_t<hb_codepoint_t> gids_to_retain_sorted;
-
-  // Plan is only good for a specific source/dest so keep them with it
-  hb_face_t *source;
-  hb_face_t *dest;
-};
-
-typedef struct hb_subset_plan_t hb_subset_plan_t;
-
-HB_INTERNAL hb_subset_plan_t *
-hb_subset_plan_create (hb_face_t           *face,
-                       hb_subset_profile_t *profile,
-                       hb_subset_input_t   *input);
-
-HB_INTERNAL hb_bool_t
-hb_subset_plan_new_gid_for_old_id(hb_subset_plan_t *plan,
-                                  hb_codepoint_t old_gid,
-                                  hb_codepoint_t *new_gid /* OUT */);
-
-HB_INTERNAL hb_bool_t
-hb_subset_plan_new_gid_for_codepoint(hb_subset_plan_t *plan,
-                                     hb_codepoint_t codepont,
-                                     hb_codepoint_t *new_gid /* OUT */);
-
-HB_INTERNAL hb_bool_t
-hb_subset_plan_add_table(hb_subset_plan_t *plan,
-                         hb_tag_t tag,
-                         hb_blob_t *contents);
-
-HB_INTERNAL void
-hb_subset_plan_destroy (hb_subset_plan_t *plan);
-
-#endif /* HB_SUBSET_PLAN_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-subset-private.hh b/third_party/harfbuzz-ng/src/hb-subset-private.hh
deleted file mode 100644
index 5fa7252..0000000
--- a/third_party/harfbuzz-ng/src/hb-subset-private.hh
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger, Roderick Sheeter
- */
-
-#ifndef HB_SUBSET_PRIVATE_HH
-#define HB_SUBSET_PRIVATE_HH
-
-
-#include "hb-private.hh"
-
-#include "hb-subset.h"
-
-#include "hb-font-private.hh"
-
-typedef struct hb_subset_face_data_t hb_subset_face_data_t;
-
-struct hb_subset_input_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_set_t *unicodes;
-  hb_set_t *glyphs;
-
-  hb_bool_t drop_hints;
-  /* TODO
-   *
-   * features
-   * lookups
-   * nameIDs
-   * ...
-   */
-};
-
-HB_INTERNAL hb_face_t *
-hb_subset_face_create (void);
-
-HB_INTERNAL hb_bool_t
-hb_subset_face_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob);
-
-#endif /* HB_SUBSET_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-subset.h b/third_party/harfbuzz-ng/src/hb-subset.h
deleted file mode 100644
index 55ce25b..0000000
--- a/third_party/harfbuzz-ng/src/hb-subset.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Rod Sheeter
- */
-
-#ifndef HB_SUBSET_H
-#define HB_SUBSET_H
-
-#include "hb.h"
-
-HB_BEGIN_DECLS
-
-/*
- * hb_subset_profile_t
- * Things that change based on target environment, e.g. OS.
- * Threadsafe for multiple concurrent subset operations.
- */
-
-typedef struct hb_subset_profile_t hb_subset_profile_t;
-
-HB_EXTERN hb_subset_profile_t *
-hb_subset_profile_create (void);
-
-HB_EXTERN void
-hb_subset_profile_destroy (hb_subset_profile_t *profile);
-
-/*
- * hb_subset_input_t
- *
- * Things that change based on the input. Characters to keep, etc.
- */
-
-typedef struct hb_subset_input_t hb_subset_input_t;
-
-HB_EXTERN hb_subset_input_t *
-hb_subset_input_create_or_fail (void);
-
-HB_EXTERN hb_subset_input_t *
-hb_subset_input_reference (hb_subset_input_t *subset_input);
-
-HB_EXTERN void
-hb_subset_input_destroy (hb_subset_input_t *subset_input);
-
-HB_EXTERN hb_set_t *
-hb_subset_input_unicode_set (hb_subset_input_t *subset_input);
-
-HB_EXTERN hb_set_t *
-hb_subset_input_glyph_set (hb_subset_input_t *subset_input);
-
-HB_EXTERN hb_bool_t *
-hb_subset_input_drop_hints (hb_subset_input_t *subset_input);
-
-/* hb_subset() */
-
-HB_EXTERN hb_face_t *
-hb_subset (hb_face_t *source,
-	   hb_subset_profile_t *profile,
-           hb_subset_input_t *input);
-
-HB_END_DECLS
-
-#endif /* HB_SUBSET_H */
diff --git a/third_party/harfbuzz-ng/src/hb-ucdn.cc b/third_party/harfbuzz-ng/src/hb-ucdn.cc
deleted file mode 100644
index 9515bda..0000000
--- a/third_party/harfbuzz-ng/src/hb-ucdn.cc
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (C) 2012 Grigori Goronzy <greg@kinoho.net>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "hb-private.hh"
-
-#include "hb-unicode-private.hh"
-
-#include "ucdn.h"
-
-static const hb_script_t ucdn_script_translate[] =
-{
-    HB_SCRIPT_COMMON,
-    HB_SCRIPT_LATIN,
-    HB_SCRIPT_GREEK,
-    HB_SCRIPT_CYRILLIC,
-    HB_SCRIPT_ARMENIAN,
-    HB_SCRIPT_HEBREW,
-    HB_SCRIPT_ARABIC,
-    HB_SCRIPT_SYRIAC,
-    HB_SCRIPT_THAANA,
-    HB_SCRIPT_DEVANAGARI,
-    HB_SCRIPT_BENGALI,
-    HB_SCRIPT_GURMUKHI,
-    HB_SCRIPT_GUJARATI,
-    HB_SCRIPT_ORIYA,
-    HB_SCRIPT_TAMIL,
-    HB_SCRIPT_TELUGU,
-    HB_SCRIPT_KANNADA,
-    HB_SCRIPT_MALAYALAM,
-    HB_SCRIPT_SINHALA,
-    HB_SCRIPT_THAI,
-    HB_SCRIPT_LAO,
-    HB_SCRIPT_TIBETAN,
-    HB_SCRIPT_MYANMAR,
-    HB_SCRIPT_GEORGIAN,
-    HB_SCRIPT_HANGUL,
-    HB_SCRIPT_ETHIOPIC,
-    HB_SCRIPT_CHEROKEE,
-    HB_SCRIPT_CANADIAN_SYLLABICS,
-    HB_SCRIPT_OGHAM,
-    HB_SCRIPT_RUNIC,
-    HB_SCRIPT_KHMER,
-    HB_SCRIPT_MONGOLIAN,
-    HB_SCRIPT_HIRAGANA,
-    HB_SCRIPT_KATAKANA,
-    HB_SCRIPT_BOPOMOFO,
-    HB_SCRIPT_HAN,
-    HB_SCRIPT_YI,
-    HB_SCRIPT_OLD_ITALIC,
-    HB_SCRIPT_GOTHIC,
-    HB_SCRIPT_DESERET,
-    HB_SCRIPT_INHERITED,
-    HB_SCRIPT_TAGALOG,
-    HB_SCRIPT_HANUNOO,
-    HB_SCRIPT_BUHID,
-    HB_SCRIPT_TAGBANWA,
-    HB_SCRIPT_LIMBU,
-    HB_SCRIPT_TAI_LE,
-    HB_SCRIPT_LINEAR_B,
-    HB_SCRIPT_UGARITIC,
-    HB_SCRIPT_SHAVIAN,
-    HB_SCRIPT_OSMANYA,
-    HB_SCRIPT_CYPRIOT,
-    HB_SCRIPT_BRAILLE,
-    HB_SCRIPT_BUGINESE,
-    HB_SCRIPT_COPTIC,
-    HB_SCRIPT_NEW_TAI_LUE,
-    HB_SCRIPT_GLAGOLITIC,
-    HB_SCRIPT_TIFINAGH,
-    HB_SCRIPT_SYLOTI_NAGRI,
-    HB_SCRIPT_OLD_PERSIAN,
-    HB_SCRIPT_KHAROSHTHI,
-    HB_SCRIPT_BALINESE,
-    HB_SCRIPT_CUNEIFORM,
-    HB_SCRIPT_PHOENICIAN,
-    HB_SCRIPT_PHAGS_PA,
-    HB_SCRIPT_NKO,
-    HB_SCRIPT_SUNDANESE,
-    HB_SCRIPT_LEPCHA,
-    HB_SCRIPT_OL_CHIKI,
-    HB_SCRIPT_VAI,
-    HB_SCRIPT_SAURASHTRA,
-    HB_SCRIPT_KAYAH_LI,
-    HB_SCRIPT_REJANG,
-    HB_SCRIPT_LYCIAN,
-    HB_SCRIPT_CARIAN,
-    HB_SCRIPT_LYDIAN,
-    HB_SCRIPT_CHAM,
-    HB_SCRIPT_TAI_THAM,
-    HB_SCRIPT_TAI_VIET,
-    HB_SCRIPT_AVESTAN,
-    HB_SCRIPT_EGYPTIAN_HIEROGLYPHS,
-    HB_SCRIPT_SAMARITAN,
-    HB_SCRIPT_LISU,
-    HB_SCRIPT_BAMUM,
-    HB_SCRIPT_JAVANESE,
-    HB_SCRIPT_MEETEI_MAYEK,
-    HB_SCRIPT_IMPERIAL_ARAMAIC,
-    HB_SCRIPT_OLD_SOUTH_ARABIAN,
-    HB_SCRIPT_INSCRIPTIONAL_PARTHIAN,
-    HB_SCRIPT_INSCRIPTIONAL_PAHLAVI,
-    HB_SCRIPT_OLD_TURKIC,
-    HB_SCRIPT_KAITHI,
-    HB_SCRIPT_BATAK,
-    HB_SCRIPT_BRAHMI,
-    HB_SCRIPT_MANDAIC,
-    HB_SCRIPT_CHAKMA,
-    HB_SCRIPT_MEROITIC_CURSIVE,
-    HB_SCRIPT_MEROITIC_HIEROGLYPHS,
-    HB_SCRIPT_MIAO,
-    HB_SCRIPT_SHARADA,
-    HB_SCRIPT_SORA_SOMPENG,
-    HB_SCRIPT_TAKRI,
-    HB_SCRIPT_UNKNOWN,
-    HB_SCRIPT_BASSA_VAH,
-    HB_SCRIPT_CAUCASIAN_ALBANIAN,
-    HB_SCRIPT_DUPLOYAN,
-    HB_SCRIPT_ELBASAN,
-    HB_SCRIPT_GRANTHA,
-    HB_SCRIPT_KHOJKI,
-    HB_SCRIPT_KHUDAWADI,
-    HB_SCRIPT_LINEAR_A,
-    HB_SCRIPT_MAHAJANI,
-    HB_SCRIPT_MANICHAEAN,
-    HB_SCRIPT_MENDE_KIKAKUI,
-    HB_SCRIPT_MODI,
-    HB_SCRIPT_MRO,
-    HB_SCRIPT_NABATAEAN,
-    HB_SCRIPT_OLD_NORTH_ARABIAN,
-    HB_SCRIPT_OLD_PERMIC,
-    HB_SCRIPT_PAHAWH_HMONG,
-    HB_SCRIPT_PALMYRENE,
-    HB_SCRIPT_PAU_CIN_HAU,
-    HB_SCRIPT_PSALTER_PAHLAVI,
-    HB_SCRIPT_SIDDHAM,
-    HB_SCRIPT_TIRHUTA,
-    HB_SCRIPT_WARANG_CITI,
-    HB_SCRIPT_AHOM,
-    HB_SCRIPT_ANATOLIAN_HIEROGLYPHS,
-    HB_SCRIPT_HATRAN,
-    HB_SCRIPT_MULTANI,
-    HB_SCRIPT_OLD_HUNGARIAN,
-    HB_SCRIPT_SIGNWRITING,
-    HB_SCRIPT_ADLAM,
-    HB_SCRIPT_BHAIKSUKI,
-    HB_SCRIPT_MARCHEN,
-    HB_SCRIPT_NEWA,
-    HB_SCRIPT_OSAGE,
-    HB_SCRIPT_TANGUT,
-    HB_SCRIPT_MASARAM_GONDI,
-    HB_SCRIPT_NUSHU,
-    HB_SCRIPT_SOYOMBO,
-    HB_SCRIPT_ZANABAZAR_SQUARE,
-};
-
-static hb_unicode_combining_class_t
-hb_ucdn_combining_class(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-			hb_codepoint_t unicode,
-			void *user_data HB_UNUSED)
-{
-    return (hb_unicode_combining_class_t) ucdn_get_combining_class(unicode);
-}
-
-static unsigned int
-hb_ucdn_eastasian_width(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-			hb_codepoint_t unicode,
-			void *user_data HB_UNUSED)
-{
-    int w = ucdn_get_east_asian_width(unicode);
-    return (w == UCDN_EAST_ASIAN_F || w == UCDN_EAST_ASIAN_W) ? 2 : 1;
-}
-
-static hb_unicode_general_category_t
-hb_ucdn_general_category(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-			 hb_codepoint_t unicode,
-			 void *user_data HB_UNUSED)
-{
-    return (hb_unicode_general_category_t)ucdn_get_general_category(unicode);
-}
-
-static hb_codepoint_t
-hb_ucdn_mirroring(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-		  hb_codepoint_t unicode,
-		  void *user_data HB_UNUSED)
-{
-    return ucdn_mirror(unicode);
-}
-
-static hb_script_t
-hb_ucdn_script(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-	       hb_codepoint_t unicode,
-	       void *user_data HB_UNUSED)
-{
-    return ucdn_script_translate[ucdn_get_script(unicode)];
-}
-
-static hb_bool_t
-hb_ucdn_compose(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-		hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab,
-		void *user_data HB_UNUSED)
-{
-    return ucdn_compose(ab, a, b);
-}
-
-static hb_bool_t
-hb_ucdn_decompose(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-		  hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b,
-		  void *user_data HB_UNUSED)
-{
-    return ucdn_decompose(ab, a, b);
-}
-
-static unsigned int
-hb_ucdn_decompose_compatibility(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-				hb_codepoint_t u, hb_codepoint_t *decomposed,
-				void *user_data HB_UNUSED)
-{
-    return ucdn_compat_decompose(u, decomposed);
-}
-
-static hb_unicode_funcs_t *static_ucdn_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_ucdn_funcs (void)
-{
-  hb_unicode_funcs_destroy (static_ucdn_funcs);
-}
-#endif
-
-extern "C" HB_INTERNAL
-hb_unicode_funcs_t *
-hb_ucdn_get_unicode_funcs (void)
-{
-retry:
-  hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs);
-
-  if (unlikely (!funcs))
-  {
-    funcs = hb_unicode_funcs_create (nullptr);
-
-#define HB_UNICODE_FUNC_IMPLEMENT(name) \
-    hb_unicode_funcs_set_##name##_func (funcs, hb_ucdn_##name, nullptr, nullptr);
-      HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-
-    hb_unicode_funcs_make_immutable (funcs);
-
-    if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, nullptr, funcs)) {
-      hb_unicode_funcs_destroy (funcs);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_ucdn_funcs); /* First person registers atexit() callback. */
-#endif
-  };
-
-  return hb_unicode_funcs_reference (funcs);
-}
diff --git a/third_party/harfbuzz-ng/src/hb-unicode-private.hh b/third_party/harfbuzz-ng/src/hb-unicode-private.hh
deleted file mode 100644
index 82bb9a4..0000000
--- a/third_party/harfbuzz-ng/src/hb-unicode-private.hh
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Codethink Limited
- * Copyright © 2010,2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Codethink Author(s): Ryan Lortie
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_UNICODE_PRIVATE_HH
-#define HB_UNICODE_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-
-
-extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256];
-
-/*
- * hb_unicode_funcs_t
- */
-
-#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS \
-  HB_UNICODE_FUNC_IMPLEMENT (combining_class) \
-  HB_UNICODE_FUNC_IMPLEMENT (eastasian_width) \
-  HB_UNICODE_FUNC_IMPLEMENT (general_category) \
-  HB_UNICODE_FUNC_IMPLEMENT (mirroring) \
-  HB_UNICODE_FUNC_IMPLEMENT (script) \
-  HB_UNICODE_FUNC_IMPLEMENT (compose) \
-  HB_UNICODE_FUNC_IMPLEMENT (decompose) \
-  HB_UNICODE_FUNC_IMPLEMENT (decompose_compatibility) \
-  /* ^--- Add new callbacks here */
-
-/* Simple callbacks are those taking a hb_codepoint_t and returning a hb_codepoint_t */
-#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_combining_class_t, combining_class) \
-  HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width) \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_general_category_t, general_category) \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_codepoint_t, mirroring) \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \
-  /* ^--- Add new simple callbacks here */
-
-struct hb_unicode_funcs_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_unicode_funcs_t *parent;
-
-  bool immutable;
-
-#define HB_UNICODE_FUNC_IMPLEMENT(return_type, name) \
-  inline return_type name (hb_codepoint_t unicode) { return func.name (this, unicode, user_data.name); }
-HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
-#undef HB_UNICODE_FUNC_IMPLEMENT
-
-  inline hb_bool_t compose (hb_codepoint_t a, hb_codepoint_t b,
-			    hb_codepoint_t *ab)
-  {
-    *ab = 0;
-    if (unlikely (!a || !b)) return false;
-    return func.compose (this, a, b, ab, user_data.compose);
-  }
-
-  inline hb_bool_t decompose (hb_codepoint_t ab,
-			      hb_codepoint_t *a, hb_codepoint_t *b)
-  {
-    *a = ab; *b = 0;
-    return func.decompose (this, ab, a, b, user_data.decompose);
-  }
-
-  inline unsigned int decompose_compatibility (hb_codepoint_t  u,
-					       hb_codepoint_t *decomposed)
-  {
-    unsigned int ret = func.decompose_compatibility (this, u, decomposed, user_data.decompose_compatibility);
-    if (ret == 1 && u == decomposed[0]) {
-      decomposed[0] = 0;
-      return 0;
-    }
-    decomposed[ret] = 0;
-    return ret;
-  }
-
-
-  inline unsigned int
-  modified_combining_class (hb_codepoint_t unicode)
-  {
-    /* XXX This hack belongs to the Myanmar shaper. */
-    if (unlikely (unicode == 0x1037u)) unicode = 0x103Au;
-
-    /* XXX This hack belongs to the USE shaper (for Tai Tham):
-     * Reorder SAKOT to ensure it comes after any tone marks. */
-    if (unlikely (unicode == 0x1A60u)) return 254;
-
-    /* XXX This hack belongs to the Tibetan shaper:
-     * Reorder PADMA to ensure it comes after any vowel marks. */
-    if (unlikely (unicode == 0x0FC6u)) return 254;
-    /* Reorder TSA -PHRU to reorder before U+0F74 */
-    if (unlikely (unicode == 0x0F39u)) return 127;
-
-    return _hb_modified_combining_class[combining_class (unicode)];
-  }
-
-  static inline hb_bool_t
-  is_variation_selector (hb_codepoint_t unicode)
-  {
-    /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the
-     * Arabic shaper.  No need to match them here. */
-    return unlikely (hb_in_ranges<hb_codepoint_t> (unicode,
-				   0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */
-				   0xE0100u, 0xE01EFu));  /* VARIATION SELECTOR-17..256 */
-  }
-
-  /* Default_Ignorable codepoints:
-   *
-   * Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable,
-   * we do NOT want to hide them, as the way Uniscribe has implemented them
-   * is with regular spacing glyphs, and that's the way fonts are made to work.
-   * As such, we make exceptions for those four.
-   * Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503
-   *
-   * Unicode 7.0:
-   * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
-   * 00AD          # Cf       SOFT HYPHEN
-   * 034F          # Mn       COMBINING GRAPHEME JOINER
-   * 061C          # Cf       ARABIC LETTER MARK
-   * 115F..1160    # Lo   [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
-   * 17B4..17B5    # Mn   [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
-   * 180B..180D    # Mn   [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
-   * 180E          # Cf       MONGOLIAN VOWEL SEPARATOR
-   * 200B..200F    # Cf   [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
-   * 202A..202E    # Cf   [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
-   * 2060..2064    # Cf   [5] WORD JOINER..INVISIBLE PLUS
-   * 2065          # Cn       <reserved-2065>
-   * 2066..206F    # Cf  [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
-   * 3164          # Lo       HANGUL FILLER
-   * FE00..FE0F    # Mn  [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
-   * FEFF          # Cf       ZERO WIDTH NO-BREAK SPACE
-   * FFA0          # Lo       HALFWIDTH HANGUL FILLER
-   * FFF0..FFF8    # Cn   [9] <reserved-FFF0>..<reserved-FFF8>
-   * 1BCA0..1BCA3  # Cf   [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
-   * 1D173..1D17A  # Cf   [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
-   * E0000         # Cn       <reserved-E0000>
-   * E0001         # Cf       LANGUAGE TAG
-   * E0002..E001F  # Cn  [30] <reserved-E0002>..<reserved-E001F>
-   * E0020..E007F  # Cf  [96] TAG SPACE..CANCEL TAG
-   * E0080..E00FF  # Cn [128] <reserved-E0080>..<reserved-E00FF>
-   * E0100..E01EF  # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
-   * E01F0..E0FFF  # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
-   */
-  static inline hb_bool_t
-  is_default_ignorable (hb_codepoint_t ch)
-  {
-    hb_codepoint_t plane = ch >> 16;
-    if (likely (plane == 0))
-    {
-      /* BMP */
-      hb_codepoint_t page = ch >> 8;
-      switch (page) {
-	case 0x00: return unlikely (ch == 0x00ADu);
-	case 0x03: return unlikely (ch == 0x034Fu);
-	case 0x06: return unlikely (ch == 0x061Cu);
-	case 0x17: return hb_in_range<hb_codepoint_t> (ch, 0x17B4u, 0x17B5u);
-	case 0x18: return hb_in_range<hb_codepoint_t> (ch, 0x180Bu, 0x180Eu);
-	case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200Bu, 0x200Fu,
-					    0x202Au, 0x202Eu,
-					    0x2060u, 0x206Fu);
-	case 0xFE: return hb_in_range<hb_codepoint_t> (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu;
-	case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0u, 0xFFF8u);
-	default: return false;
-      }
-    }
-    else
-    {
-      /* Other planes */
-      switch (plane) {
-	case 0x01: return hb_in_range<hb_codepoint_t> (ch, 0x1D173u, 0x1D17Au);
-	case 0x0E: return hb_in_range<hb_codepoint_t> (ch, 0xE0000u, 0xE0FFFu);
-	default: return false;
-      }
-    }
-  }
-
-  /* Space estimates based on:
-   * http://www.unicode.org/charts/PDF/U2000.pdf
-   * https://www.microsoft.com/typography/developers/fdsspec/spaces.aspx
-   */
-  enum space_t {
-    NOT_SPACE = 0,
-    SPACE_EM   = 1,
-    SPACE_EM_2 = 2,
-    SPACE_EM_3 = 3,
-    SPACE_EM_4 = 4,
-    SPACE_EM_5 = 5,
-    SPACE_EM_6 = 6,
-    SPACE_EM_16 = 16,
-    SPACE_4_EM_18,	/* 4/18th of an EM! */
-    SPACE,
-    SPACE_FIGURE,
-    SPACE_PUNCTUATION,
-    SPACE_NARROW,
-  };
-  static inline space_t
-  space_fallback_type (hb_codepoint_t u)
-  {
-    switch (u)
-    {
-      /* All GC=Zs chars that can use a fallback. */
-      default:	    return NOT_SPACE;	/* U+1680 OGHAM SPACE MARK */
-      case 0x0020u: return SPACE;	/* U+0020 SPACE */
-      case 0x00A0u: return SPACE;	/* U+00A0 NO-BREAK SPACE */
-      case 0x2000u: return SPACE_EM_2;	/* U+2000 EN QUAD */
-      case 0x2001u: return SPACE_EM;	/* U+2001 EM QUAD */
-      case 0x2002u: return SPACE_EM_2;	/* U+2002 EN SPACE */
-      case 0x2003u: return SPACE_EM;	/* U+2003 EM SPACE */
-      case 0x2004u: return SPACE_EM_3;	/* U+2004 THREE-PER-EM SPACE */
-      case 0x2005u: return SPACE_EM_4;	/* U+2005 FOUR-PER-EM SPACE */
-      case 0x2006u: return SPACE_EM_6;	/* U+2006 SIX-PER-EM SPACE */
-      case 0x2007u: return SPACE_FIGURE;	/* U+2007 FIGURE SPACE */
-      case 0x2008u: return SPACE_PUNCTUATION;	/* U+2008 PUNCTUATION SPACE */
-      case 0x2009u: return SPACE_EM_5;		/* U+2009 THIN SPACE */
-      case 0x200Au: return SPACE_EM_16;		/* U+200A HAIR SPACE */
-      case 0x202Fu: return SPACE_NARROW;	/* U+202F NARROW NO-BREAK SPACE */
-      case 0x205Fu: return SPACE_4_EM_18;	/* U+205F MEDIUM MATHEMATICAL SPACE */
-      case 0x3000u: return SPACE_EM;		/* U+3000 IDEOGRAPHIC SPACE */
-    }
-  }
-
-  struct {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_func_t name;
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-  } func;
-
-  struct {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) void *name;
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-  } user_data;
-
-  struct {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-  } destroy;
-};
-
-
-extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
-
-
-/* Modified combining marks */
-
-/* Hebrew
- *
- * We permute the "fixed-position" classes 10-26 into the order
- * described in the SBL Hebrew manual:
- *
- * http://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf
- *
- * (as recommended by:
- *  http://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering-t6751.0.html)
- *
- * More details here:
- * https://bugzilla.mozilla.org/show_bug.cgi?id=662055
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC10 22 /* sheva */
-#define HB_MODIFIED_COMBINING_CLASS_CCC11 15 /* hataf segol */
-#define HB_MODIFIED_COMBINING_CLASS_CCC12 16 /* hataf patah */
-#define HB_MODIFIED_COMBINING_CLASS_CCC13 17 /* hataf qamats */
-#define HB_MODIFIED_COMBINING_CLASS_CCC14 23 /* hiriq */
-#define HB_MODIFIED_COMBINING_CLASS_CCC15 18 /* tsere */
-#define HB_MODIFIED_COMBINING_CLASS_CCC16 19 /* segol */
-#define HB_MODIFIED_COMBINING_CLASS_CCC17 20 /* patah */
-#define HB_MODIFIED_COMBINING_CLASS_CCC18 21 /* qamats */
-#define HB_MODIFIED_COMBINING_CLASS_CCC19 14 /* holam */
-#define HB_MODIFIED_COMBINING_CLASS_CCC20 24 /* qubuts */
-#define HB_MODIFIED_COMBINING_CLASS_CCC21 12 /* dagesh */
-#define HB_MODIFIED_COMBINING_CLASS_CCC22 25 /* meteg */
-#define HB_MODIFIED_COMBINING_CLASS_CCC23 13 /* rafe */
-#define HB_MODIFIED_COMBINING_CLASS_CCC24 10 /* shin dot */
-#define HB_MODIFIED_COMBINING_CLASS_CCC25 11 /* sin dot */
-#define HB_MODIFIED_COMBINING_CLASS_CCC26 26 /* point varika */
-
-/*
- * Arabic
- *
- * Modify to move Shadda (ccc=33) before other marks.  See:
- * http://unicode.org/faq/normalization.html#8
- * http://unicode.org/faq/normalization.html#9
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC27 28 /* fathatan */
-#define HB_MODIFIED_COMBINING_CLASS_CCC28 29 /* dammatan */
-#define HB_MODIFIED_COMBINING_CLASS_CCC29 30 /* kasratan */
-#define HB_MODIFIED_COMBINING_CLASS_CCC30 31 /* fatha */
-#define HB_MODIFIED_COMBINING_CLASS_CCC31 32 /* damma */
-#define HB_MODIFIED_COMBINING_CLASS_CCC32 33 /* kasra */
-#define HB_MODIFIED_COMBINING_CLASS_CCC33 27 /* shadda */
-#define HB_MODIFIED_COMBINING_CLASS_CCC34 34 /* sukun */
-#define HB_MODIFIED_COMBINING_CLASS_CCC35 35 /* superscript alef */
-
-/* Syriac */
-#define HB_MODIFIED_COMBINING_CLASS_CCC36 36 /* superscript alaph */
-
-/* Telugu
- *
- * Modify Telugu length marks (ccc=84, ccc=91).
- * These are the only matras in the main Indic scripts range that have
- * a non-zero ccc.  That makes them reorder with the Halant that is
- * ccc=9.  Just zero them, we don't need them in our Indic shaper.
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC84 0 /* length mark */
-#define HB_MODIFIED_COMBINING_CLASS_CCC91 0 /* ai length mark */
-
-/* Thai
- *
- * Modify U+0E38 and U+0E39 (ccc=103) to be reordered before U+0E3A (ccc=9).
- * Assign 3, which is unassigned otherwise.
- * Uniscribe does this reordering too.
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC103 3 /* sara u / sara uu */
-#define HB_MODIFIED_COMBINING_CLASS_CCC107 107 /* mai * */
-
-/* Lao */
-#define HB_MODIFIED_COMBINING_CLASS_CCC118 118 /* sign u / sign uu */
-#define HB_MODIFIED_COMBINING_CLASS_CCC122 122 /* mai * */
-
-/* Tibetan
- * 
- * In case of multiple vowel-signs, use u first (but after achung) 
- * this allows Dzongkha multi-vowel shortcuts to render correctly 
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC129 129 /* sign aa */
-#define HB_MODIFIED_COMBINING_CLASS_CCC130 132 /* sign i */
-#define HB_MODIFIED_COMBINING_CLASS_CCC132 131 /* sign u */
-
-/* Misc */
-
-#define HB_UNICODE_GENERAL_CATEGORY_IS_MARK(gen_cat) \
-	(FLAG_UNSAFE (gen_cat) & \
-	 (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
-
-#define HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL(gen_cat) \
-	(FLAG_UNSAFE (gen_cat) & \
-	 (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \
-	  FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL)))
-
-#endif /* HB_UNICODE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-unicode.cc b/third_party/harfbuzz-ng/src/hb-unicode.cc
deleted file mode 100644
index 726baeb..0000000
--- a/third_party/harfbuzz-ng/src/hb-unicode.cc
+++ /dev/null
@@ -1,563 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Codethink Limited
- * Copyright © 2010,2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Codethink Author(s): Ryan Lortie
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-
-#include "hb-unicode-private.hh"
-
-
-
-/*
- * hb_unicode_funcs_t
- */
-
-static hb_unicode_combining_class_t
-hb_unicode_combining_class_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
-				hb_codepoint_t      unicode   HB_UNUSED,
-				void               *user_data HB_UNUSED)
-{
-  return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED;
-}
-
-static unsigned int
-hb_unicode_eastasian_width_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
-				hb_codepoint_t      unicode   HB_UNUSED,
-				void               *user_data HB_UNUSED)
-{
-  return 1;
-}
-
-static hb_unicode_general_category_t
-hb_unicode_general_category_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
-				 hb_codepoint_t      unicode   HB_UNUSED,
-				 void               *user_data HB_UNUSED)
-{
-  return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
-}
-
-static hb_codepoint_t
-hb_unicode_mirroring_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
-			  hb_codepoint_t      unicode   HB_UNUSED,
-			  void               *user_data HB_UNUSED)
-{
-  return unicode;
-}
-
-static hb_script_t
-hb_unicode_script_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
-		       hb_codepoint_t      unicode   HB_UNUSED,
-		       void               *user_data HB_UNUSED)
-{
-  return HB_SCRIPT_UNKNOWN;
-}
-
-static hb_bool_t
-hb_unicode_compose_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
-			hb_codepoint_t      a         HB_UNUSED,
-			hb_codepoint_t      b         HB_UNUSED,
-			hb_codepoint_t     *ab        HB_UNUSED,
-			void               *user_data HB_UNUSED)
-{
-  return false;
-}
-
-static hb_bool_t
-hb_unicode_decompose_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
-			  hb_codepoint_t      ab        HB_UNUSED,
-			  hb_codepoint_t     *a         HB_UNUSED,
-			  hb_codepoint_t     *b         HB_UNUSED,
-			  void               *user_data HB_UNUSED)
-{
-  return false;
-}
-
-
-static unsigned int
-hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs     HB_UNUSED,
-					hb_codepoint_t      u          HB_UNUSED,
-					hb_codepoint_t     *decomposed HB_UNUSED,
-					void               *user_data  HB_UNUSED)
-{
-  return 0;
-}
-
-
-#define HB_UNICODE_FUNCS_IMPLEMENT_SET \
-  HB_UNICODE_FUNCS_IMPLEMENT (glib) \
-  HB_UNICODE_FUNCS_IMPLEMENT (icu) \
-  HB_UNICODE_FUNCS_IMPLEMENT (ucdn) \
-  HB_UNICODE_FUNCS_IMPLEMENT (nil) \
-  /* ^--- Add new callbacks before nil */
-
-#define hb_nil_get_unicode_funcs hb_unicode_funcs_get_empty
-
-/* Prototype them all */
-#define HB_UNICODE_FUNCS_IMPLEMENT(set) \
-extern "C" hb_unicode_funcs_t *hb_##set##_get_unicode_funcs (void);
-HB_UNICODE_FUNCS_IMPLEMENT_SET
-#undef HB_UNICODE_FUNCS_IMPLEMENT
-
-
-hb_unicode_funcs_t *
-hb_unicode_funcs_get_default (void)
-{
-#define HB_UNICODE_FUNCS_IMPLEMENT(set) \
-  return hb_##set##_get_unicode_funcs ();
-
-#if defined(HAVE_UCDN)
-  HB_UNICODE_FUNCS_IMPLEMENT(ucdn)
-#elif defined(HAVE_GLIB)
-  HB_UNICODE_FUNCS_IMPLEMENT(glib)
-#elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
-  HB_UNICODE_FUNCS_IMPLEMENT(icu)
-#else
-#define HB_UNICODE_FUNCS_NIL 1
-  HB_UNICODE_FUNCS_IMPLEMENT(nil)
-#endif
-
-#undef HB_UNICODE_FUNCS_IMPLEMENT
-}
-
-#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
-#error "Could not find any Unicode functions implementation, you have to provide your own"
-#error "Consider building hb-ucdn.c.  If you absolutely want to build without any, check the code."
-#endif
-
-/**
- * hb_unicode_funcs_create: (Xconstructor)
- * @parent: (nullable):
- *
- * 
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.2
- **/
-hb_unicode_funcs_t *
-hb_unicode_funcs_create (hb_unicode_funcs_t *parent)
-{
-  hb_unicode_funcs_t *ufuncs;
-
-  if (!(ufuncs = hb_object_create<hb_unicode_funcs_t> ()))
-    return hb_unicode_funcs_get_empty ();
-
-  if (!parent)
-    parent = hb_unicode_funcs_get_empty ();
-
-  hb_unicode_funcs_make_immutable (parent);
-  ufuncs->parent = hb_unicode_funcs_reference (parent);
-
-  ufuncs->func = parent->func;
-
-  /* We can safely copy user_data from parent since we hold a reference
-   * onto it and it's immutable.  We should not copy the destroy notifiers
-   * though. */
-  ufuncs->user_data = parent->user_data;
-
-  return ufuncs;
-}
-
-
-const hb_unicode_funcs_t _hb_unicode_funcs_nil = {
-  HB_OBJECT_HEADER_STATIC,
-
-  nullptr, /* parent */
-  true, /* immutable */
-  {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_nil,
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-  }
-};
-
-/**
- * hb_unicode_funcs_get_empty:
- *
- * 
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.2
- **/
-hb_unicode_funcs_t *
-hb_unicode_funcs_get_empty (void)
-{
-  return const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil);
-}
-
-/**
- * hb_unicode_funcs_reference: (skip)
- * @ufuncs: Unicode functions.
- *
- * 
- *
- * Return value: (transfer full):
- *
- * Since: 0.9.2
- **/
-hb_unicode_funcs_t *
-hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs)
-{
-  return hb_object_reference (ufuncs);
-}
-
-/**
- * hb_unicode_funcs_destroy: (skip)
- * @ufuncs: Unicode functions.
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
-{
-  if (!hb_object_destroy (ufuncs)) return;
-
-#define HB_UNICODE_FUNC_IMPLEMENT(name) \
-  if (ufuncs->destroy.name) ufuncs->destroy.name (ufuncs->user_data.name);
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-
-  hb_unicode_funcs_destroy (ufuncs->parent);
-
-  free (ufuncs);
-}
-
-/**
- * hb_unicode_funcs_set_user_data: (skip)
- * @ufuncs: Unicode functions.
- * @key: 
- * @data: 
- * @destroy: 
- * @replace: 
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
-			        hb_user_data_key_t *key,
-			        void *              data,
-			        hb_destroy_func_t   destroy,
-				hb_bool_t           replace)
-{
-  return hb_object_set_user_data (ufuncs, key, data, destroy, replace);
-}
-
-/**
- * hb_unicode_funcs_get_user_data: (skip)
- * @ufuncs: Unicode functions.
- * @key: 
- *
- * 
- *
- * Return value: (transfer none):
- *
- * Since: 0.9.2
- **/
-void *
-hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
-			        hb_user_data_key_t *key)
-{
-  return hb_object_get_user_data (ufuncs, key);
-}
-
-
-/**
- * hb_unicode_funcs_make_immutable:
- * @ufuncs: Unicode functions.
- *
- * 
- *
- * Since: 0.9.2
- **/
-void
-hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
-{
-  if (unlikely (hb_object_is_inert (ufuncs)))
-    return;
-
-  ufuncs->immutable = true;
-}
-
-/**
- * hb_unicode_funcs_is_immutable:
- * @ufuncs: Unicode functions.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs)
-{
-  return ufuncs->immutable;
-}
-
-/**
- * hb_unicode_funcs_get_parent:
- * @ufuncs: Unicode functions.
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_unicode_funcs_t *
-hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs)
-{
-  return ufuncs->parent ? ufuncs->parent : hb_unicode_funcs_get_empty ();
-}
-
-
-#define HB_UNICODE_FUNC_IMPLEMENT(name)						\
-										\
-void										\
-hb_unicode_funcs_set_##name##_func (hb_unicode_funcs_t		   *ufuncs,	\
-				    hb_unicode_##name##_func_t	    func,	\
-				    void			   *user_data,	\
-				    hb_destroy_func_t		    destroy)	\
-{										\
-  if (ufuncs->immutable)							\
-    return;									\
-										\
-  if (ufuncs->destroy.name)							\
-    ufuncs->destroy.name (ufuncs->user_data.name);				\
-										\
-  if (func) {									\
-    ufuncs->func.name = func;							\
-    ufuncs->user_data.name = user_data;						\
-    ufuncs->destroy.name = destroy;						\
-  } else {									\
-    ufuncs->func.name = ufuncs->parent->func.name;				\
-    ufuncs->user_data.name = ufuncs->parent->user_data.name;			\
-    ufuncs->destroy.name = nullptr;						\
-  }										\
-}
-
-HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-
-
-#define HB_UNICODE_FUNC_IMPLEMENT(return_type, name)				\
-										\
-return_type									\
-hb_unicode_##name (hb_unicode_funcs_t *ufuncs,					\
-		   hb_codepoint_t      unicode)					\
-{										\
-  return ufuncs->name (unicode);						\
-}
-HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
-#undef HB_UNICODE_FUNC_IMPLEMENT
-
-/**
- * hb_unicode_compose:
- * @ufuncs: Unicode functions.
- * @a: 
- * @b: 
- * @ab: (out):
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
-		    hb_codepoint_t      a,
-		    hb_codepoint_t      b,
-		    hb_codepoint_t     *ab)
-{
-  return ufuncs->compose (a, b, ab);
-}
-
-/**
- * hb_unicode_decompose:
- * @ufuncs: Unicode functions.
- * @ab: 
- * @a: (out):
- * @b: (out):
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-hb_bool_t
-hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
-		      hb_codepoint_t      ab,
-		      hb_codepoint_t     *a,
-		      hb_codepoint_t     *b)
-{
-  return ufuncs->decompose (ab, a, b);
-}
-
-/**
- * hb_unicode_decompose_compatibility:
- * @ufuncs: Unicode functions.
- * @u: 
- * @decomposed: (out):
- *
- * 
- *
- * Return value: 
- *
- * Since: 0.9.2
- **/
-unsigned int
-hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
-				    hb_codepoint_t      u,
-				    hb_codepoint_t     *decomposed)
-{
-  return ufuncs->decompose_compatibility (u, decomposed);
-}
-
-
-/* See hb-unicode-private.hh for details. */
-const uint8_t
-_hb_modified_combining_class[256] =
-{
-  0, /* HB_UNICODE_COMBINING_CLASS_NOT_REORDERED */
-  1, /* HB_UNICODE_COMBINING_CLASS_OVERLAY */
-  2, 3, 4, 5, 6,
-  7, /* HB_UNICODE_COMBINING_CLASS_NUKTA */
-  8, /* HB_UNICODE_COMBINING_CLASS_KANA_VOICING */
-  9, /* HB_UNICODE_COMBINING_CLASS_VIRAMA */
-
-  /* Hebrew */
-  HB_MODIFIED_COMBINING_CLASS_CCC10,
-  HB_MODIFIED_COMBINING_CLASS_CCC11,
-  HB_MODIFIED_COMBINING_CLASS_CCC12,
-  HB_MODIFIED_COMBINING_CLASS_CCC13,
-  HB_MODIFIED_COMBINING_CLASS_CCC14,
-  HB_MODIFIED_COMBINING_CLASS_CCC15,
-  HB_MODIFIED_COMBINING_CLASS_CCC16,
-  HB_MODIFIED_COMBINING_CLASS_CCC17,
-  HB_MODIFIED_COMBINING_CLASS_CCC18,
-  HB_MODIFIED_COMBINING_CLASS_CCC19,
-  HB_MODIFIED_COMBINING_CLASS_CCC20,
-  HB_MODIFIED_COMBINING_CLASS_CCC21,
-  HB_MODIFIED_COMBINING_CLASS_CCC22,
-  HB_MODIFIED_COMBINING_CLASS_CCC23,
-  HB_MODIFIED_COMBINING_CLASS_CCC24,
-  HB_MODIFIED_COMBINING_CLASS_CCC25,
-  HB_MODIFIED_COMBINING_CLASS_CCC26,
-
-  /* Arabic */
-  HB_MODIFIED_COMBINING_CLASS_CCC27,
-  HB_MODIFIED_COMBINING_CLASS_CCC28,
-  HB_MODIFIED_COMBINING_CLASS_CCC29,
-  HB_MODIFIED_COMBINING_CLASS_CCC30,
-  HB_MODIFIED_COMBINING_CLASS_CCC31,
-  HB_MODIFIED_COMBINING_CLASS_CCC32,
-  HB_MODIFIED_COMBINING_CLASS_CCC33,
-  HB_MODIFIED_COMBINING_CLASS_CCC34,
-  HB_MODIFIED_COMBINING_CLASS_CCC35,
-
-  /* Syriac */
-  HB_MODIFIED_COMBINING_CLASS_CCC36,
-
-  37, 38, 39,
-  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, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
-  80, 81, 82, 83,
-
-  /* Telugu */
-  HB_MODIFIED_COMBINING_CLASS_CCC84,
-  85, 86, 87, 88, 89, 90,
-  HB_MODIFIED_COMBINING_CLASS_CCC91,
-  92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
-
-  /* Thai */
-  HB_MODIFIED_COMBINING_CLASS_CCC103,
-  104, 105, 106,
-  HB_MODIFIED_COMBINING_CLASS_CCC107,
-  108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
-
-  /* Lao */
-  HB_MODIFIED_COMBINING_CLASS_CCC118,
-  119, 120, 121,
-  HB_MODIFIED_COMBINING_CLASS_CCC122,
-  123, 124, 125, 126, 127, 128,
-
-  /* Tibetan */
-  HB_MODIFIED_COMBINING_CLASS_CCC129,
-  HB_MODIFIED_COMBINING_CLASS_CCC130,
-  131,
-  HB_MODIFIED_COMBINING_CLASS_CCC132,
-  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, 158, 159,
-  160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
-  170, 171, 172, 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, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT */
-  201,
-  202, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW */
-  203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
-  214, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE */
-  215,
-  216, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT */
-  217,
-  218, /* HB_UNICODE_COMBINING_CLASS_BELOW_LEFT */
-  219,
-  220, /* HB_UNICODE_COMBINING_CLASS_BELOW */
-  221,
-  222, /* HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT */
-  223,
-  224, /* HB_UNICODE_COMBINING_CLASS_LEFT */
-  225,
-  226, /* HB_UNICODE_COMBINING_CLASS_RIGHT */
-  227,
-  228, /* HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT */
-  229,
-  230, /* HB_UNICODE_COMBINING_CLASS_ABOVE */
-  231,
-  232, /* HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT */
-  233, /* HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW */
-  234, /* HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE */
-  235, 236, 237, 238, 239,
-  240, /* HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT */
-  241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
-  255, /* HB_UNICODE_COMBINING_CLASS_INVALID */
-};
diff --git a/third_party/harfbuzz-ng/src/hb-unicode.h b/third_party/harfbuzz-ng/src/hb-unicode.h
deleted file mode 100644
index 2657f48..0000000
--- a/third_party/harfbuzz-ng/src/hb-unicode.h
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Codethink Limited
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Codethink Author(s): Ryan Lortie
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_H_IN
-#error "Include <hb.h> instead."
-#endif
-
-#ifndef HB_UNICODE_H
-#define HB_UNICODE_H
-
-#include "hb-common.h"
-
-HB_BEGIN_DECLS
-
-
-/* hb_unicode_general_category_t */
-
-/* Unicode Character Database property: General_Category (gc) */
-typedef enum
-{
-  HB_UNICODE_GENERAL_CATEGORY_CONTROL,			/* Cc */
-  HB_UNICODE_GENERAL_CATEGORY_FORMAT,			/* Cf */
-  HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED,		/* Cn */
-  HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE,		/* Co */
-  HB_UNICODE_GENERAL_CATEGORY_SURROGATE,		/* Cs */
-  HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER,		/* Ll */
-  HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER,		/* Lm */
-  HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER,		/* Lo */
-  HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER,		/* Lt */
-  HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER,		/* Lu */
-  HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK,		/* Mc */
-  HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK,		/* Me */
-  HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK,		/* Mn */
-  HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER,		/* Nd */
-  HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER,		/* Nl */
-  HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER,		/* No */
-  HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION,	/* Pc */
-  HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION,		/* Pd */
-  HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION,	/* Pe */
-  HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION,	/* Pf */
-  HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION,	/* Pi */
-  HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION,	/* Po */
-  HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION,		/* Ps */
-  HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL,		/* Sc */
-  HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL,		/* Sk */
-  HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL,		/* Sm */
-  HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL,		/* So */
-  HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR,		/* Zl */
-  HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR,	/* Zp */
-  HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR		/* Zs */
-} hb_unicode_general_category_t;
-
-/* hb_unicode_combining_class_t */
-
-/* Note: newer versions of Unicode may add new values.  Clients should be ready to handle
- * any value in the 0..254 range being returned from hb_unicode_combining_class().
- */
-
-/* Unicode Character Database property: Canonical_Combining_Class (ccc) */
-typedef enum
-{
-  HB_UNICODE_COMBINING_CLASS_NOT_REORDERED	= 0,
-  HB_UNICODE_COMBINING_CLASS_OVERLAY		= 1,
-  HB_UNICODE_COMBINING_CLASS_NUKTA		= 7,
-  HB_UNICODE_COMBINING_CLASS_KANA_VOICING	= 8,
-  HB_UNICODE_COMBINING_CLASS_VIRAMA		= 9,
-
-  /* Hebrew */
-  HB_UNICODE_COMBINING_CLASS_CCC10	=  10,
-  HB_UNICODE_COMBINING_CLASS_CCC11	=  11,
-  HB_UNICODE_COMBINING_CLASS_CCC12	=  12,
-  HB_UNICODE_COMBINING_CLASS_CCC13	=  13,
-  HB_UNICODE_COMBINING_CLASS_CCC14	=  14,
-  HB_UNICODE_COMBINING_CLASS_CCC15	=  15,
-  HB_UNICODE_COMBINING_CLASS_CCC16	=  16,
-  HB_UNICODE_COMBINING_CLASS_CCC17	=  17,
-  HB_UNICODE_COMBINING_CLASS_CCC18	=  18,
-  HB_UNICODE_COMBINING_CLASS_CCC19	=  19,
-  HB_UNICODE_COMBINING_CLASS_CCC20	=  20,
-  HB_UNICODE_COMBINING_CLASS_CCC21	=  21,
-  HB_UNICODE_COMBINING_CLASS_CCC22	=  22,
-  HB_UNICODE_COMBINING_CLASS_CCC23	=  23,
-  HB_UNICODE_COMBINING_CLASS_CCC24	=  24,
-  HB_UNICODE_COMBINING_CLASS_CCC25	=  25,
-  HB_UNICODE_COMBINING_CLASS_CCC26	=  26,
-
-  /* Arabic */
-  HB_UNICODE_COMBINING_CLASS_CCC27	=  27,
-  HB_UNICODE_COMBINING_CLASS_CCC28	=  28,
-  HB_UNICODE_COMBINING_CLASS_CCC29	=  29,
-  HB_UNICODE_COMBINING_CLASS_CCC30	=  30,
-  HB_UNICODE_COMBINING_CLASS_CCC31	=  31,
-  HB_UNICODE_COMBINING_CLASS_CCC32	=  32,
-  HB_UNICODE_COMBINING_CLASS_CCC33	=  33,
-  HB_UNICODE_COMBINING_CLASS_CCC34	=  34,
-  HB_UNICODE_COMBINING_CLASS_CCC35	=  35,
-
-  /* Syriac */
-  HB_UNICODE_COMBINING_CLASS_CCC36	=  36,
-
-  /* Telugu */
-  HB_UNICODE_COMBINING_CLASS_CCC84	=  84,
-  HB_UNICODE_COMBINING_CLASS_CCC91	=  91,
-
-  /* Thai */
-  HB_UNICODE_COMBINING_CLASS_CCC103	= 103,
-  HB_UNICODE_COMBINING_CLASS_CCC107	= 107,
-
-  /* Lao */
-  HB_UNICODE_COMBINING_CLASS_CCC118	= 118,
-  HB_UNICODE_COMBINING_CLASS_CCC122	= 122,
-
-  /* Tibetan */
-  HB_UNICODE_COMBINING_CLASS_CCC129	= 129,
-  HB_UNICODE_COMBINING_CLASS_CCC130	= 130,
-  HB_UNICODE_COMBINING_CLASS_CCC133	= 132,
-
-
-  HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT	= 200,
-  HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW		= 202,
-  HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE		= 214,
-  HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT	= 216,
-  HB_UNICODE_COMBINING_CLASS_BELOW_LEFT			= 218,
-  HB_UNICODE_COMBINING_CLASS_BELOW			= 220,
-  HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT		= 222,
-  HB_UNICODE_COMBINING_CLASS_LEFT			= 224,
-  HB_UNICODE_COMBINING_CLASS_RIGHT			= 226,
-  HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT			= 228,
-  HB_UNICODE_COMBINING_CLASS_ABOVE			= 230,
-  HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT		= 232,
-  HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW		= 233,
-  HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE		= 234,
-
-  HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT		= 240,
-
-  HB_UNICODE_COMBINING_CLASS_INVALID	= 255
-} hb_unicode_combining_class_t;
-
-
-/*
- * hb_unicode_funcs_t
- */
-
-typedef struct hb_unicode_funcs_t hb_unicode_funcs_t;
-
-
-/*
- * just give me the best implementation you've got there.
- */
-HB_EXTERN hb_unicode_funcs_t *
-hb_unicode_funcs_get_default (void);
-
-
-HB_EXTERN hb_unicode_funcs_t *
-hb_unicode_funcs_create (hb_unicode_funcs_t *parent);
-
-HB_EXTERN hb_unicode_funcs_t *
-hb_unicode_funcs_get_empty (void);
-
-HB_EXTERN hb_unicode_funcs_t *
-hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs);
-
-HB_EXTERN void
-hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs);
-
-HB_EXTERN hb_bool_t
-hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
-			        hb_user_data_key_t *key,
-			        void *              data,
-			        hb_destroy_func_t   destroy,
-				hb_bool_t           replace);
-
-
-HB_EXTERN void *
-hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
-			        hb_user_data_key_t *key);
-
-
-HB_EXTERN void
-hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs);
-
-HB_EXTERN hb_bool_t
-hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs);
-
-HB_EXTERN hb_unicode_funcs_t *
-hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs);
-
-
-/*
- * funcs
- */
-
-/* typedefs */
-
-typedef hb_unicode_combining_class_t	(*hb_unicode_combining_class_func_t)	(hb_unicode_funcs_t *ufuncs,
-										 hb_codepoint_t      unicode,
-										 void               *user_data);
-typedef unsigned int			(*hb_unicode_eastasian_width_func_t)	(hb_unicode_funcs_t *ufuncs,
-										 hb_codepoint_t      unicode,
-										 void               *user_data);
-typedef hb_unicode_general_category_t	(*hb_unicode_general_category_func_t)	(hb_unicode_funcs_t *ufuncs,
-										 hb_codepoint_t      unicode,
-										 void               *user_data);
-typedef hb_codepoint_t			(*hb_unicode_mirroring_func_t)		(hb_unicode_funcs_t *ufuncs,
-										 hb_codepoint_t      unicode,
-										 void               *user_data);
-typedef hb_script_t			(*hb_unicode_script_func_t)		(hb_unicode_funcs_t *ufuncs,
-										 hb_codepoint_t      unicode,
-										 void               *user_data);
-
-typedef hb_bool_t			(*hb_unicode_compose_func_t)		(hb_unicode_funcs_t *ufuncs,
-										 hb_codepoint_t      a,
-										 hb_codepoint_t      b,
-										 hb_codepoint_t     *ab,
-										 void               *user_data);
-typedef hb_bool_t			(*hb_unicode_decompose_func_t)		(hb_unicode_funcs_t *ufuncs,
-										 hb_codepoint_t      ab,
-										 hb_codepoint_t     *a,
-										 hb_codepoint_t     *b,
-										 void               *user_data);
-
-/**
- * hb_unicode_decompose_compatibility_func_t:
- * @ufuncs: a Unicode function structure
- * @u: codepoint to decompose
- * @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into
- * @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func()
- *
- * Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed.
- * The complete length of the decomposition will be returned.
- *
- * If @u has no compatibility decomposition, zero should be returned.
- *
- * The Unicode standard guarantees that a buffer of length %HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any
- * compatibility decomposition plus an terminating value of 0.  Consequently, @decompose must be allocated by the caller to be at least this length.  Implementations
- * of this function type must ensure that they do not write past the provided array.
- *
- * Return value: number of codepoints in the full compatibility decomposition of @u, or 0 if no decomposition available.
- */
-typedef unsigned int			(*hb_unicode_decompose_compatibility_func_t)	(hb_unicode_funcs_t *ufuncs,
-											 hb_codepoint_t      u,
-											 hb_codepoint_t     *decomposed,
-											 void               *user_data);
-
-/* See Unicode 6.1 for details on the maximum decomposition length. */
-#define HB_UNICODE_MAX_DECOMPOSITION_LEN (18+1) /* codepoints */
-
-/* setters */
-
-/**
- * hb_unicode_funcs_set_combining_class_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs,
-					   hb_unicode_combining_class_func_t func,
-					   void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_unicode_funcs_set_eastasian_width_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
-					   hb_unicode_eastasian_width_func_t func,
-					   void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_unicode_funcs_set_general_category_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs,
-					    hb_unicode_general_category_func_t func,
-					    void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_unicode_funcs_set_mirroring_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs,
-				     hb_unicode_mirroring_func_t func,
-				     void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_unicode_funcs_set_script_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs,
-				  hb_unicode_script_func_t func,
-				  void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_unicode_funcs_set_compose_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs,
-				   hb_unicode_compose_func_t func,
-				   void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_unicode_funcs_set_decompose_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs,
-				     hb_unicode_decompose_func_t func,
-				     void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_unicode_funcs_set_decompose_compatibility_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs,
-						   hb_unicode_decompose_compatibility_func_t func,
-						   void *user_data, hb_destroy_func_t destroy);
-
-/* accessors */
-
-/**
- * hb_unicode_combining_class:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN hb_unicode_combining_class_t
-hb_unicode_combining_class (hb_unicode_funcs_t *ufuncs,
-			    hb_codepoint_t unicode);
-
-/**
- * hb_unicode_eastasian_width:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN unsigned int
-hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
-			    hb_codepoint_t unicode);
-
-/**
- * hb_unicode_general_category:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN hb_unicode_general_category_t
-hb_unicode_general_category (hb_unicode_funcs_t *ufuncs,
-			     hb_codepoint_t unicode);
-
-/**
- * hb_unicode_mirroring:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN hb_codepoint_t
-hb_unicode_mirroring (hb_unicode_funcs_t *ufuncs,
-		      hb_codepoint_t unicode);
-
-/**
- * hb_unicode_script:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN hb_script_t
-hb_unicode_script (hb_unicode_funcs_t *ufuncs,
-		   hb_codepoint_t unicode);
-
-HB_EXTERN hb_bool_t
-hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
-		    hb_codepoint_t      a,
-		    hb_codepoint_t      b,
-		    hb_codepoint_t     *ab);
-
-HB_EXTERN hb_bool_t
-hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
-		      hb_codepoint_t      ab,
-		      hb_codepoint_t     *a,
-		      hb_codepoint_t     *b);
-
-HB_EXTERN unsigned int
-hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
-				    hb_codepoint_t      u,
-				    hb_codepoint_t     *decomposed);
-
-HB_END_DECLS
-
-#endif /* HB_UNICODE_H */
diff --git a/third_party/harfbuzz-ng/src/hb-utf-private.hh b/third_party/harfbuzz-ng/src/hb-utf-private.hh
deleted file mode 100644
index 211eb4d..0000000
--- a/third_party/harfbuzz-ng/src/hb-utf-private.hh
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright © 2011,2012,2014  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_UTF_PRIVATE_HH
-#define HB_UTF_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-struct hb_utf8_t
-{
-  typedef uint8_t codepoint_t;
-
-  static inline const uint8_t *
-  next (const uint8_t *text,
-	const uint8_t *end,
-	hb_codepoint_t *unicode,
-	hb_codepoint_t replacement)
-  {
-    /* Written to only accept well-formed sequences.
-     * Based on ideas from ICU's U8_NEXT.
-     * Generates one "replacement" for each ill-formed byte. */
-
-    hb_codepoint_t c = *text++;
-
-    if (c > 0x7Fu)
-    {
-      if (hb_in_range<hb_codepoint_t> (c, 0xC2u, 0xDFu)) /* Two-byte */
-      {
-	unsigned int t1;
-	if (likely (text < end &&
-		    (t1 = text[0] - 0x80u) <= 0x3Fu))
-	{
-	  c = ((c&0x1Fu)<<6) | t1;
-	  text++;
-	}
-	else
-	  goto error;
-      }
-      else if (hb_in_range<hb_codepoint_t> (c, 0xE0u, 0xEFu)) /* Three-byte */
-      {
-	unsigned int t1, t2;
-	if (likely (1 < end - text &&
-		    (t1 = text[0] - 0x80u) <= 0x3Fu &&
-		    (t2 = text[1] - 0x80u) <= 0x3Fu))
-	{
-	  c = ((c&0xFu)<<12) | (t1<<6) | t2;
-	  if (unlikely (c < 0x0800u || hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
-	    goto error;
-	  text += 2;
-	}
-	else
-	  goto error;
-      }
-      else if (hb_in_range<hb_codepoint_t> (c, 0xF0u, 0xF4u)) /* Four-byte */
-      {
-	unsigned int t1, t2, t3;
-	if (likely (2 < end - text &&
-		    (t1 = text[0] - 0x80u) <= 0x3Fu &&
-		    (t2 = text[1] - 0x80u) <= 0x3Fu &&
-		    (t3 = text[2] - 0x80u) <= 0x3Fu))
-	{
-	  c = ((c&0x7u)<<18) | (t1<<12) | (t2<<6) | t3;
-	  if (unlikely (!hb_in_range<hb_codepoint_t> (c, 0x10000u, 0x10FFFFu)))
-	    goto error;
-	  text += 3;
-	}
-	else
-	  goto error;
-      }
-      else
-	goto error;
-    }
-
-    *unicode = c;
-    return text;
-
-  error:
-    *unicode = replacement;
-    return text;
-  }
-
-  static inline const uint8_t *
-  prev (const uint8_t *text,
-	const uint8_t *start,
-	hb_codepoint_t *unicode,
-	hb_codepoint_t replacement)
-  {
-    const uint8_t *end = text--;
-    while (start < text && (*text & 0xc0) == 0x80 && end - text < 4)
-      text--;
-
-    if (likely (next (text, end, unicode, replacement) == end))
-      return text;
-
-    *unicode = replacement;
-    return end - 1;
-  }
-
-  static inline unsigned int
-  strlen (const uint8_t *text)
-  {
-    return ::strlen ((const char *) text);
-  }
-};
-
-
-struct hb_utf16_t
-{
-  typedef uint16_t codepoint_t;
-
-  static inline const uint16_t *
-  next (const uint16_t *text,
-	const uint16_t *end,
-	hb_codepoint_t *unicode,
-	hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *text++;
-
-    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
-    {
-      *unicode = c;
-      return text;
-    }
-
-    if (likely (c <= 0xDBFFu && text < end))
-    {
-      /* High-surrogate in c */
-      hb_codepoint_t l = *text;
-      if (likely (hb_in_range<hb_codepoint_t> (l, 0xDC00u, 0xDFFFu)))
-      {
-	/* Low-surrogate in l */
-	*unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u);
-	 text++;
-	 return text;
-      }
-    }
-
-    /* Lonely / out-of-order surrogate. */
-    *unicode = replacement;
-    return text;
-  }
-
-  static inline const uint16_t *
-  prev (const uint16_t *text,
-	const uint16_t *start,
-	hb_codepoint_t *unicode,
-	hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *--text;
-
-    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
-    {
-      *unicode = c;
-      return text;
-    }
-
-    if (likely (c >= 0xDC00u && start < text))
-    {
-      /* Low-surrogate in c */
-      hb_codepoint_t h = text[-1];
-      if (likely (hb_in_range<hb_codepoint_t> (h, 0xD800u, 0xDBFFu)))
-      {
-        /* High-surrogate in h */
-        *unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u);
-        text--;
-        return text;
-      }
-    }
-
-    /* Lonely / out-of-order surrogate. */
-    *unicode = replacement;
-    return text;
-  }
-
-
-  static inline unsigned int
-  strlen (const uint16_t *text)
-  {
-    unsigned int l = 0;
-    while (*text++) l++;
-    return l;
-  }
-};
-
-
-template <bool validate=true>
-struct hb_utf32_t
-{
-  typedef uint32_t codepoint_t;
-
-  static inline const uint32_t *
-  next (const uint32_t *text,
-	const uint32_t *end HB_UNUSED,
-	hb_codepoint_t *unicode,
-	hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *unicode = *text++;
-    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
-      *unicode = replacement;
-    return text;
-  }
-
-  static inline const uint32_t *
-  prev (const uint32_t *text,
-	const uint32_t *start HB_UNUSED,
-	hb_codepoint_t *unicode,
-	hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *unicode = *--text;
-    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
-      *unicode = replacement;
-    return text;
-  }
-
-  static inline unsigned int
-  strlen (const uint32_t *text)
-  {
-    unsigned int l = 0;
-    while (*text++) l++;
-    return l;
-  }
-};
-
-
-struct hb_latin1_t
-{
-  typedef uint8_t codepoint_t;
-
-  static inline const uint8_t *
-  next (const uint8_t *text,
-	const uint8_t *end HB_UNUSED,
-	hb_codepoint_t *unicode,
-	hb_codepoint_t replacement HB_UNUSED)
-  {
-    *unicode = *text++;
-    return text;
-  }
-
-  static inline const uint8_t *
-  prev (const uint8_t *text,
-	const uint8_t *start HB_UNUSED,
-	hb_codepoint_t *unicode,
-	hb_codepoint_t replacement)
-  {
-    *unicode = *--text;
-    return text;
-  }
-
-  static inline unsigned int
-  strlen (const uint8_t *text)
-  {
-    unsigned int l = 0;
-    while (*text++) l++;
-    return l;
-  }
-};
-
-#endif /* HB_UTF_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-version.h b/third_party/harfbuzz-ng/src/hb-version.h
deleted file mode 100644
index 27509326..0000000
--- a/third_party/harfbuzz-ng/src/hb-version.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_H_IN
-#error "Include <hb.h> instead."
-#endif
-
-#ifndef HB_VERSION_H
-#define HB_VERSION_H
-
-#include "hb-common.h"
-
-HB_BEGIN_DECLS
-
-
-#define HB_VERSION_MAJOR 1
-#define HB_VERSION_MINOR 7
-#define HB_VERSION_MICRO 6
-
-#define HB_VERSION_STRING "1.7.6"
-
-#define HB_VERSION_ATLEAST(major,minor,micro) \
-	((major)*10000+(minor)*100+(micro) <= \
-	 HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
-
-
-HB_EXTERN void
-hb_version (unsigned int *major,
-	    unsigned int *minor,
-	    unsigned int *micro);
-
-HB_EXTERN const char *
-hb_version_string (void);
-
-HB_EXTERN hb_bool_t
-hb_version_atleast (unsigned int major,
-		    unsigned int minor,
-		    unsigned int micro);
-
-
-HB_END_DECLS
-
-#endif /* HB_VERSION_H */
diff --git a/third_party/harfbuzz-ng/src/hb-warning.cc b/third_party/harfbuzz-ng/src/hb-warning.cc
deleted file mode 100644
index 8f322bc..0000000
--- a/third_party/harfbuzz-ng/src/hb-warning.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-atomic-private.hh"
-#include "hb-mutex-private.hh"
-
-
-#if defined(HB_ATOMIC_INT_NIL)
-#error "Could not find any system to define atomic_int macros, library WILL NOT be thread-safe"
-#error "Check hb-atomic-private.hh for possible resolutions."
-#endif
-
-#if defined(HB_MUTEX_IMPL_NIL)
-#error "Could not find any system to define mutex macros, library WILL NOT be thread-safe"
-#error "Check hb-mutex-private.hh for possible resolutions."
-#endif
diff --git a/third_party/harfbuzz-ng/src/hb.h b/third_party/harfbuzz-ng/src/hb.h
deleted file mode 100644
index 7402034f..0000000
--- a/third_party/harfbuzz-ng/src/hb.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_H
-#define HB_H
-#define HB_H_IN
-
-#ifndef HB_EXTERN
-#define HB_EXTERN extern
-#endif
-
-#include "hb-blob.h"
-#include "hb-buffer.h"
-#include "hb-common.h"
-#include "hb-deprecated.h"
-#include "hb-face.h"
-#include "hb-font.h"
-#include "hb-set.h"
-#include "hb-shape.h"
-#include "hb-shape-plan.h"
-#include "hb-unicode.h"
-#include "hb-version.h"
-
-HB_BEGIN_DECLS
-HB_END_DECLS
-
-#undef HB_H_IN
-#endif /* HB_H */
diff --git a/third_party/harfbuzz-ng/src/main.cc b/third_party/harfbuzz-ng/src/main.cc
deleted file mode 100644
index d221e9d..0000000
--- a/third_party/harfbuzz-ng/src/main.cc
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#include "hb-open-file-private.hh"
-#include "hb-ot-layout-gdef-table.hh"
-#include "hb-ot-layout-gsubgpos-private.hh"
-
-#ifdef HAVE_GLIB
-#include <glib.h>
-#endif
-#include <stdlib.h>
-#include <stdio.h>
-
-
-using namespace OT;
-
-#ifndef HB_NO_VISIBILITY
-const void * const OT::_hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
-#endif
-
-int
-main (int argc, char **argv)
-{
-  if (argc != 2) {
-    fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]);
-    exit (1);
-  }
-
-  const char *font_data = nullptr;
-  int len = 0;
-
-#ifdef HAVE_GLIB
-  GMappedFile *mf = g_mapped_file_new (argv[1], false, nullptr);
-  font_data = g_mapped_file_get_contents (mf);
-  len = g_mapped_file_get_length (mf);
-#else
-  FILE *f = fopen (argv[1], "rb");
-  fseek (f, 0, SEEK_END);
-  len = ftell (f);
-  fseek (f, 0, SEEK_SET);
-  font_data = (const char *) malloc (len);
-  len = fread ((char *) font_data, 1, len, f);
-#endif
-
-  printf ("Opened font file %s: %d bytes long\n", argv[1], len);
-
-  const OpenTypeFontFile &ot = *CastP<OpenTypeFontFile> (font_data);
-
-  switch (ot.get_tag ()) {
-  case OpenTypeFontFile::TrueTypeTag:
-    printf ("OpenType font with TrueType outlines\n");
-    break;
-  case OpenTypeFontFile::CFFTag:
-    printf ("OpenType font with CFF (Type1) outlines\n");
-    break;
-  case OpenTypeFontFile::TTCTag:
-    printf ("TrueType Collection of OpenType fonts\n");
-    break;
-  case OpenTypeFontFile::TrueTag:
-    printf ("Obsolete Apple TrueType font\n");
-    break;
-  case OpenTypeFontFile::Typ1Tag:
-    printf ("Obsolete Apple Type1 font in SFNT container\n");
-    break;
-  default:
-    printf ("Unknown font format\n");
-    break;
-  }
-
-  int num_fonts = ot.get_face_count ();
-  printf ("%d font(s) found in file\n", num_fonts);
-  for (int n_font = 0; n_font < num_fonts; n_font++) {
-    const OpenTypeFontFace &font = ot.get_face (n_font);
-    printf ("Font %d of %d:\n", n_font, num_fonts);
-
-    int num_tables = font.get_table_count ();
-    printf ("  %d table(s) found in font\n", num_tables);
-    for (int n_table = 0; n_table < num_tables; n_table++) {
-      const OpenTypeTable &table = font.get_table (n_table);
-      printf ("  Table %2d of %2d: %.4s (0x%08x+0x%08x)\n", n_table, num_tables,
-	      (const char *)table.tag,
-	      (unsigned int) table.offset,
-	      (unsigned int) table.length);
-
-      switch (table.tag) {
-
-      case HB_OT_TAG_GSUB:
-      case HB_OT_TAG_GPOS:
-	{
-
-	const GSUBGPOS &g = *CastP<GSUBGPOS> (font_data + table.offset);
-
-	int num_scripts = g.get_script_count ();
-	printf ("    %d script(s) found in table\n", num_scripts);
-	for (int n_script = 0; n_script < num_scripts; n_script++) {
-	  const Script &script = g.get_script (n_script);
-	  printf ("    Script %2d of %2d: %.4s\n", n_script, num_scripts,
-	          (const char *)g.get_script_tag(n_script));
-
-	  if (!script.has_default_lang_sys())
-	    printf ("      No default language system\n");
-	  int num_langsys = script.get_lang_sys_count ();
-	  printf ("      %d language system(s) found in script\n", num_langsys);
-	  for (int n_langsys = script.has_default_lang_sys() ? -1 : 0; n_langsys < num_langsys; n_langsys++) {
-	    const LangSys &langsys = n_langsys == -1
-				   ? script.get_default_lang_sys ()
-				   : script.get_lang_sys (n_langsys);
-	    if (n_langsys == -1)
-	      printf ("      Default Language System\n");
-	    else
-	      printf ("      Language System %2d of %2d: %.4s\n", n_langsys, num_langsys,
-		      (const char *)script.get_lang_sys_tag (n_langsys));
-	    if (!langsys.has_required_feature ())
-	      printf ("        No required feature\n");
-	    else
-	      printf ("        Required feature index: %d\n",
-		      langsys.get_required_feature_index ());
-
-	    int num_features = langsys.get_feature_count ();
-	    printf ("        %d feature(s) found in language system\n", num_features);
-	    for (int n_feature = 0; n_feature < num_features; n_feature++) {
-	      printf ("        Feature index %2d of %2d: %d\n", n_feature, num_features,
-	              langsys.get_feature_index (n_feature));
-	    }
-	  }
-	}
-
-	int num_features = g.get_feature_count ();
-	printf ("    %d feature(s) found in table\n", num_features);
-	for (int n_feature = 0; n_feature < num_features; n_feature++) {
-	  const Feature &feature = g.get_feature (n_feature);
-	  int num_lookups = feature.get_lookup_count ();
-	  printf ("    Feature %2d of %2d: %c%c%c%c\n", n_feature, num_features,
-	          HB_UNTAG(g.get_feature_tag(n_feature)));
-
-	  printf ("        %d lookup(s) found in feature\n", num_lookups);
-	  for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) {
-	    printf ("        Lookup index %2d of %2d: %d\n", n_lookup, num_lookups,
-	            feature.get_lookup_index (n_lookup));
-	  }
-	}
-
-	int num_lookups = g.get_lookup_count ();
-	printf ("    %d lookup(s) found in table\n", num_lookups);
-	for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) {
-	  const Lookup &lookup = g.get_lookup (n_lookup);
-	  printf ("    Lookup %2d of %2d: type %d, props 0x%04X\n", n_lookup, num_lookups,
-	          lookup.get_type(), lookup.get_props());
-	}
-
-	}
-	break;
-
-      case GDEF::tableTag:
-	{
-
-	const GDEF &gdef = *CastP<GDEF> (font_data + table.offset);
-
-	printf ("    Has %sglyph classes\n",
-		  gdef.has_glyph_classes () ? "" : "no ");
-	printf ("    Has %smark attachment types\n",
-		  gdef.has_mark_attachment_types () ? "" : "no ");
-	printf ("    Has %sattach points\n",
-		  gdef.has_attach_points () ? "" : "no ");
-	printf ("    Has %slig carets\n",
-		  gdef.has_lig_carets () ? "" : "no ");
-	printf ("    Has %smark sets\n",
-		  gdef.has_mark_sets () ? "" : "no ");
-	break;
-	}
-      }
-    }
-  }
-
-  return 0;
-}
-
-
diff --git a/third_party/harfbuzz-ng/src/test-buffer-serialize.cc b/third_party/harfbuzz-ng/src/test-buffer-serialize.cc
deleted file mode 100644
index 636b003..0000000
--- a/third_party/harfbuzz-ng/src/test-buffer-serialize.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright © 2010,2011,2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-
-#include "hb.h"
-#include "hb-ot.h"
-#ifdef HAVE_FREETYPE
-#include "hb-ft.h"
-#endif
-
-#ifdef HAVE_GLIB
-# include <glib.h>
-# if !GLIB_CHECK_VERSION (2, 22, 0)
-#  define g_mapped_file_unref g_mapped_file_free
-# endif
-#endif
-#include <stdlib.h>
-#include <stdio.h>
-
-int
-main (int argc, char **argv)
-{
-  hb_blob_t *blob = nullptr;
-
-  if (argc != 2) {
-    fprintf (stderr, "usage: %s font-file\n", argv[0]);
-    exit (1);
-  }
-
-  /* Create the blob */
-  {
-    const char *font_data;
-    unsigned int len;
-    hb_destroy_func_t destroy;
-    void *user_data;
-    hb_memory_mode_t mm;
-
-#ifdef HAVE_GLIB
-    GMappedFile *mf = g_mapped_file_new (argv[1], false, nullptr);
-    font_data = g_mapped_file_get_contents (mf);
-    len = g_mapped_file_get_length (mf);
-    destroy = (hb_destroy_func_t) g_mapped_file_unref;
-    user_data = (void *) mf;
-    mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
-#else
-    FILE *f = fopen (argv[1], "rb");
-    fseek (f, 0, SEEK_END);
-    len = ftell (f);
-    fseek (f, 0, SEEK_SET);
-    font_data = (const char *) malloc (len);
-    if (!font_data) len = 0;
-    len = fread ((char *) font_data, 1, len, f);
-    destroy = free;
-    user_data = (void *) font_data;
-    fclose (f);
-    mm = HB_MEMORY_MODE_WRITABLE;
-#endif
-
-    blob = hb_blob_create (font_data, len, mm, user_data, destroy);
-  }
-
-  hb_face_t *face = hb_face_create (blob, 0 /* first face */);
-  hb_blob_destroy (blob);
-  blob = nullptr;
-
-  unsigned int upem = hb_face_get_upem (face);
-  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);
-#ifdef HAVE_FREETYPE
-  //hb_ft_font_set_funcs (font);
-#endif
-
-  hb_buffer_t *buf;
-  buf = hb_buffer_create ();
-
-  bool ret = true;
-  char line[BUFSIZ], out[BUFSIZ];
-  while (fgets (line, sizeof(line), stdin) != nullptr)
-  {
-    hb_buffer_clear_contents (buf);
-
-    const char *p = line;
-    while (hb_buffer_deserialize_glyphs (buf,
-					 p, -1, &p,
-					 font,
-					 HB_BUFFER_SERIALIZE_FORMAT_JSON))
-      ;
-    if (*p && *p != '\n')
-      ret = false;
-
-    hb_buffer_serialize_glyphs (buf, 0, hb_buffer_get_length (buf),
-				out, sizeof (out), nullptr,
-				font, HB_BUFFER_SERIALIZE_FORMAT_JSON,
-				HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
-    puts (out);
-  }
-
-  hb_buffer_destroy (buf);
-
-  hb_font_destroy (font);
-
-  return !ret;
-}
diff --git a/third_party/harfbuzz-ng/src/test-size-params.cc b/third_party/harfbuzz-ng/src/test-size-params.cc
deleted file mode 100644
index 9741b87..0000000
--- a/third_party/harfbuzz-ng/src/test-size-params.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright © 2010,2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-
-#include "hb.h"
-#include "hb-ot.h"
-
-#ifdef HAVE_GLIB
-# include <glib.h>
-# if !GLIB_CHECK_VERSION (2, 22, 0)
-#  define g_mapped_file_unref g_mapped_file_free
-# endif
-#endif
-#include <stdlib.h>
-#include <stdio.h>
-
-int
-main (int argc, char **argv)
-{
-  hb_blob_t *blob = nullptr;
-
-  if (argc != 2) {
-    fprintf (stderr, "usage: %s font-file\n", argv[0]);
-    exit (1);
-  }
-
-  /* Create the blob */
-  {
-    const char *font_data;
-    unsigned int len;
-    hb_destroy_func_t destroy;
-    void *user_data;
-    hb_memory_mode_t mm;
-
-#ifdef HAVE_GLIB
-    GMappedFile *mf = g_mapped_file_new (argv[1], false, nullptr);
-    font_data = g_mapped_file_get_contents (mf);
-    len = g_mapped_file_get_length (mf);
-    destroy = (hb_destroy_func_t) g_mapped_file_unref;
-    user_data = (void *) mf;
-    mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
-#else
-    FILE *f = fopen (argv[1], "rb");
-    fseek (f, 0, SEEK_END);
-    len = ftell (f);
-    fseek (f, 0, SEEK_SET);
-    font_data = (const char *) malloc (len);
-    if (!font_data) len = 0;
-    len = fread ((char *) font_data, 1, len, f);
-    destroy = free;
-    user_data = (void *) font_data;
-    fclose (f);
-    mm = HB_MEMORY_MODE_WRITABLE;
-#endif
-
-    blob = hb_blob_create (font_data, len, mm, user_data, destroy);
-  }
-
-  /* Create the face */
-  hb_face_t *face = hb_face_create (blob, 0 /* first face */);
-  hb_blob_destroy (blob);
-  blob = nullptr;
-
-  unsigned int p[5];
-  bool ret = hb_ot_layout_get_size_params (face, p, p+1, p+2, p+3, p+4);
-
-  printf ("%g %u %u %g %g\n", p[0]/10., p[1], p[2], p[3]/10., p[4]/10.);
-
-  return !ret;
-}
diff --git a/third_party/harfbuzz-ng/src/test-would-substitute.cc b/third_party/harfbuzz-ng/src/test-would-substitute.cc
deleted file mode 100644
index efebf2d0..0000000
--- a/third_party/harfbuzz-ng/src/test-would-substitute.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright © 2010,2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-
-#include "hb.h"
-#include "hb-ot.h"
-
-#ifdef HAVE_GLIB
-# include <glib.h>
-# if !GLIB_CHECK_VERSION (2, 22, 0)
-#  define g_mapped_file_unref g_mapped_file_free
-# endif
-#endif
-#include <stdlib.h>
-#include <stdio.h>
-
-#ifdef HAVE_FREETYPE
-#include "hb-ft.h"
-#endif
-
-int
-main (int argc, char **argv)
-{
-  hb_blob_t *blob = nullptr;
-
-  if (argc != 4 && argc != 5) {
-    fprintf (stderr, "usage: %s font-file lookup-index first-glyph [second-glyph]\n", argv[0]);
-    exit (1);
-  }
-
-  /* Create the blob */
-  {
-    const char *font_data;
-    unsigned int len;
-    hb_destroy_func_t destroy;
-    void *user_data;
-    hb_memory_mode_t mm;
-
-#ifdef HAVE_GLIB
-    GMappedFile *mf = g_mapped_file_new (argv[1], false, nullptr);
-    font_data = g_mapped_file_get_contents (mf);
-    len = g_mapped_file_get_length (mf);
-    destroy = (hb_destroy_func_t) g_mapped_file_unref;
-    user_data = (void *) mf;
-    mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
-#else
-    FILE *f = fopen (argv[1], "rb");
-    fseek (f, 0, SEEK_END);
-    len = ftell (f);
-    fseek (f, 0, SEEK_SET);
-    font_data = (const char *) malloc (len);
-    if (!font_data) len = 0;
-    len = fread ((char *) font_data, 1, len, f);
-    destroy = free;
-    user_data = (void *) font_data;
-    fclose (f);
-    mm = HB_MEMORY_MODE_WRITABLE;
-#endif
-
-    blob = hb_blob_create (font_data, len, mm, user_data, destroy);
-  }
-
-  /* Create the face */
-  hb_face_t *face = hb_face_create (blob, 0 /* first face */);
-  hb_blob_destroy (blob);
-  blob = nullptr;
-
-  hb_font_t *font = hb_font_create (face);
-#ifdef HAVE_FREETYPE
-  hb_ft_font_set_funcs (font);
-#endif
-
-  unsigned int len = argc - 3;
-  hb_codepoint_t glyphs[2];
-  if (!hb_font_glyph_from_string (font, argv[3], -1, &glyphs[0]) ||
-      (argc > 4 &&
-       !hb_font_glyph_from_string (font, argv[4], -1, &glyphs[1])))
-    return 2;
-  return !hb_ot_layout_lookup_would_substitute (face, strtol (argv[2], nullptr, 0), glyphs, len, false);
-}
diff --git a/third_party/harfbuzz-ng/src/test.cc b/third_party/harfbuzz-ng/src/test.cc
deleted file mode 100644
index 9592b37..0000000
--- a/third_party/harfbuzz-ng/src/test.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright © 2010,2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.hh"
-
-#include "hb.h"
-
-#ifdef HAVE_GLIB
-# include <glib.h>
-# if !GLIB_CHECK_VERSION (2, 22, 0)
-#  define g_mapped_file_unref g_mapped_file_free
-# endif
-#endif
-#include <stdlib.h>
-#include <stdio.h>
-
-#ifdef HAVE_FREETYPE
-#include "hb-ft.h"
-#endif
-
-int
-main (int argc, char **argv)
-{
-  hb_blob_t *blob = nullptr;
-
-  if (argc != 2) {
-    fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]);
-    exit (1);
-  }
-
-  /* Create the blob */
-  {
-    const char *font_data;
-    unsigned int len;
-    hb_destroy_func_t destroy;
-    void *user_data;
-    hb_memory_mode_t mm;
-
-#ifdef HAVE_GLIB
-    GMappedFile *mf = g_mapped_file_new (argv[1], false, nullptr);
-    font_data = g_mapped_file_get_contents (mf);
-    len = g_mapped_file_get_length (mf);
-    destroy = (hb_destroy_func_t) g_mapped_file_unref;
-    user_data = (void *) mf;
-    mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
-#else
-    FILE *f = fopen (argv[1], "rb");
-    fseek (f, 0, SEEK_END);
-    len = ftell (f);
-    fseek (f, 0, SEEK_SET);
-    font_data = (const char *) malloc (len);
-    if (!font_data) len = 0;
-    len = fread ((char *) font_data, 1, len, f);
-    destroy = free;
-    user_data = (void *) font_data;
-    fclose (f);
-    mm = HB_MEMORY_MODE_WRITABLE;
-#endif
-
-    blob = hb_blob_create (font_data, len, mm, user_data, destroy);
-  }
-
-  printf ("Opened font file %s: %u bytes long\n", argv[1], hb_blob_get_length (blob));
-
-  /* Create the face */
-  hb_face_t *face = hb_face_create (blob, 0 /* first face */);
-  hb_blob_destroy (blob);
-  blob = nullptr;
-  unsigned int upem = hb_face_get_upem (face);
-
-  hb_font_t *font = hb_font_create (face);
-  hb_font_set_scale (font, upem, upem);
-
-#ifdef HAVE_FREETYPE
-  hb_ft_font_set_funcs (font);
-#endif
-
-  hb_buffer_t *buffer = hb_buffer_create ();
-
-  hb_buffer_add_utf8 (buffer, "\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x8d\xe0\xa4\x95", -1, 0, -1);
-  hb_buffer_guess_segment_properties (buffer);
-
-  hb_shape (font, buffer, nullptr, 0);
-
-  unsigned int count = hb_buffer_get_length (buffer);
-  hb_glyph_info_t *infos = hb_buffer_get_glyph_infos (buffer, nullptr);
-  hb_glyph_position_t *positions = hb_buffer_get_glyph_positions (buffer, nullptr);
-
-  for (unsigned int i = 0; i < count; i++)
-  {
-    hb_glyph_info_t *info = &infos[i];
-    hb_glyph_position_t *pos = &positions[i];
-
-    printf ("cluster %d	glyph 0x%x at	(%d,%d)+(%d,%d)\n",
-	    info->cluster,
-	    info->codepoint,
-	    pos->x_offset,
-	    pos->y_offset,
-	    pos->x_advance,
-	    pos->y_advance);
-
-  }
-
-  hb_buffer_destroy (buffer);
-  hb_font_destroy (font);
-  hb_face_destroy (face);
-
-  return 0;
-}
-
-
diff --git a/third_party/webrtc_overrides/BUILD.gn b/third_party/webrtc_overrides/BUILD.gn
index c734324..f4814475 100644
--- a/third_party/webrtc_overrides/BUILD.gn
+++ b/third_party/webrtc_overrides/BUILD.gn
@@ -143,6 +143,7 @@
     "rtc_base/task_queue.cc",
   ]
   deps = [
+    "//base",
     "//third_party/webrtc/rtc_base:rtc_task_queue_api",
   ]
 }
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 8934a44d..899a1f9 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -40380,6 +40380,18 @@
   <int value="1" label="Sync account switcher"/>
 </enum>
 
+<enum name="SigninTokenStateTransition">
+  <int value="0" label="None to Invalid"/>
+  <int value="1" label="None to Regular"/>
+  <int value="2" label="Invalid to Regular"/>
+  <int value="3" label="Regular to Invalid"/>
+  <int value="4" label="Regular to Regular"/>
+  <int value="5" label="Invalid to None"/>
+  <int value="6" label="Regular to None"/>
+  <int value="7" label="Load Regular"/>
+  <int value="8" label="Load Invalid"/>
+</enum>
+
 <enum name="SigninTokenTableReadTokenFromDBResult">
   <int value="0" label="Success"/>
   <int value="1" label="Decrypt failed"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 408266a..e564e12 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -84281,6 +84281,16 @@
   </summary>
 </histogram>
 
+<histogram name="Signin.TokenStateTransition" enum="SigninTokenStateTransition">
+  <owner>droger@chromium.org</owner>
+  <summary>
+    Tracks the changes of refresh token states for all accounts. Tokens can have
+    three states: Regular (retrieved from Gaia), Invalid (created by Chrome and
+    known to be invalid) or None (no token). Recorded when a token is loaded or
+    changed.
+  </summary>
+</histogram>
+
 <histogram name="Signin.TokenTable.GetAllTokensSqlStatementValidity"
     enum="BooleanValid">
   <owner>msarda@chromium.org</owner>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index df99d2f..e149fd996 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -138,7 +138,7 @@
          ('media_perftests', 'build74-b1--device7'),
        ],
        'perf_tests_with_args': [
-         ('angle_perftests', 'build73-b1--device4', ['--shard-timeout=180'],
+         ('angle_perftests', 'build73-b1--device4', ['--shard-timeout=300'],
            'angle_perftests'),
        ]
       }
diff --git a/ui/base/accelerators/mojo/BUILD.gn b/ui/base/accelerators/mojo/BUILD.gn
index 7682b707..4e02828 100644
--- a/ui/base/accelerators/mojo/BUILD.gn
+++ b/ui/base/accelerators/mojo/BUILD.gn
@@ -9,7 +9,7 @@
     "accelerator.mojom",
   ]
   public_deps = [
-    "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//ui/events/mojo:interfaces",
   ]
 }
@@ -20,6 +20,7 @@
   ]
   public_deps = [
     ":interfaces",
+    "//mojo/public/mojom/base",
     "//ui/base",
     "//ui/events",
   ]
diff --git a/ui/base/accelerators/mojo/DEPS b/ui/base/accelerators/mojo/DEPS
index 6cfa565..6cbc2015 100644
--- a/ui/base/accelerators/mojo/DEPS
+++ b/ui/base/accelerators/mojo/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
   "+mojo/common",
+  "+mojo/public/cpp/base",
 ]
diff --git a/ui/base/accelerators/mojo/accelerator.mojom b/ui/base/accelerators/mojo/accelerator.mojom
index d54cbf8..77a4029b 100644
--- a/ui/base/accelerators/mojo/accelerator.mojom
+++ b/ui/base/accelerators/mojo/accelerator.mojom
@@ -4,7 +4,7 @@
 
 module ui.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "ui/events/mojo/event_constants.mojom";
 import "ui/events/mojo/keyboard_codes.mojom";
 
@@ -21,5 +21,5 @@
   int32 key_code;
   AcceleratorKeyState key_state;
   int32 modifiers;
-  mojo.common.mojom.TimeTicks time_stamp;
+  mojo_base.mojom.TimeTicks time_stamp;
 };
diff --git a/ui/base/accelerators/mojo/accelerator_struct_traits.h b/ui/base/accelerators/mojo/accelerator_struct_traits.h
index 02f2da1..c0dc969 100644
--- a/ui/base/accelerators/mojo/accelerator_struct_traits.h
+++ b/ui/base/accelerators/mojo/accelerator_struct_traits.h
@@ -5,7 +5,7 @@
 #ifndef UI_BASE_ACCELERATORS_MOJO_ACCELERATOR_STRUCT_TRAITS_H_
 #define UI_BASE_ACCELERATORS_MOJO_ACCELERATOR_STRUCT_TRAITS_H_
 
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/accelerators/mojo/accelerator.mojom.h"
 #include "ui/events/keycodes/keyboard_codes.h"
diff --git a/ui/events/mojo/BUILD.gn b/ui/events/mojo/BUILD.gn
index 49165b3..9515ba4 100644
--- a/ui/events/mojo/BUILD.gn
+++ b/ui/events/mojo/BUILD.gn
@@ -12,7 +12,7 @@
   ]
 
   public_deps = [
-    "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//ui/gfx/mojo",
     "//ui/latency/mojo:interfaces",
   ]
diff --git a/ui/events/mojo/event.mojom b/ui/events/mojo/event.mojom
index 39e37b1..6ec6d7cb 100644
--- a/ui/events/mojo/event.mojom
+++ b/ui/events/mojo/event.mojom
@@ -4,7 +4,7 @@
 
 module ui.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "ui/events/mojo/event_constants.mojom";
 import "ui/events/mojo/keyboard_codes.mojom";
 import "ui/latency/mojo/latency_info.mojom";
@@ -151,7 +151,7 @@
   // This value accurately orders events w.r.t. to each other but does not
   // position them at an absolute time since the TimeTicks origin is only
   // guaranteed to be fixed during one instance of the application.
-  mojo.common.mojom.TimeTicks time_stamp;
+  mojo_base.mojom.TimeTicks time_stamp;
   LatencyInfo latency;
   KeyData? key_data;
   PointerData? pointer_data;
diff --git a/ui/events/mojo/event_struct_traits.cc b/ui/events/mojo/event_struct_traits.cc
index 05ce3df1..1dd08b6 100644
--- a/ui/events/mojo/event_struct_traits.cc
+++ b/ui/events/mojo/event_struct_traits.cc
@@ -4,7 +4,7 @@
 
 #include "ui/events/mojo/event_struct_traits.h"
 
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "ui/events/event.h"
 #include "ui/events/gesture_event_details.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
diff --git a/ui/events/mojo/struct_traits_unittest.cc b/ui/events/mojo/struct_traits_unittest.cc
index 782d5375..5e2a491 100644
--- a/ui/events/mojo/struct_traits_unittest.cc
+++ b/ui/events/mojo/struct_traits_unittest.cc
@@ -5,7 +5,7 @@
 #include <utility>
 
 #include "base/message_loop/message_loop.h"
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/event.h"
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
index 8af1fd60..c86da3e 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -348,8 +348,8 @@
       this.updateAvailability.bind(this));
 
   chrome.commandLinePrivate.hasSwitch(
-      'enable-zip-archiver-packer', function(enabled) {
-        CommandHandler.IS_ZIP_ARCHIVER_PACKER_ENABLED_ = enabled;
+      'disable-zip-archiver-packer', function(disabled) {
+        CommandHandler.IS_ZIP_ARCHIVER_PACKER_ENABLED_ = !disabled;
       }.bind(this));
 };
 
diff --git a/ui/latency/mojo/BUILD.gn b/ui/latency/mojo/BUILD.gn
index 0840e693..61d3975 100644
--- a/ui/latency/mojo/BUILD.gn
+++ b/ui/latency/mojo/BUILD.gn
@@ -11,6 +11,7 @@
 
   public_deps = [
     "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//ui/gfx/geometry/mojo",
   ]
 }
diff --git a/ui/latency/mojo/latency_info.mojom b/ui/latency/mojo/latency_info.mojom
index 9ebb386..1b0e5e8 100644
--- a/ui/latency/mojo/latency_info.mojom
+++ b/ui/latency/mojo/latency_info.mojom
@@ -4,7 +4,7 @@
 
 module ui.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
 enum LatencyComponentType {
@@ -104,13 +104,13 @@
   // component.
   int64 sequence_number;
   // Average time of events that happened in this component.
-  mojo.common.mojom.TimeTicks event_time;
+  mojo_base.mojom.TimeTicks event_time;
   // Count of events that happened in this component
   uint32 event_count;
   // Time of the oldest event that happened in this component.
-  mojo.common.mojom.TimeTicks first_event_time;
+  mojo_base.mojom.TimeTicks first_event_time;
   // Time of the most recent event that happened in this component.
-  mojo.common.mojom.TimeTicks last_event_time;
+  mojo_base.mojom.TimeTicks last_event_time;
 };
 
 struct LatencyComponentPair {
@@ -128,5 +128,5 @@
   bool began;
   bool terminated;
   SourceEventType source_event_type;
-  mojo.common.mojom.TimeDelta expected_queueing_time_on_dispatch;
+  mojo_base.mojom.TimeDelta expected_queueing_time_on_dispatch;
 };
diff --git a/ui/latency/mojo/latency_info_struct_traits.cc b/ui/latency/mojo/latency_info_struct_traits.cc
index 4f4d231..2e44de6 100644
--- a/ui/latency/mojo/latency_info_struct_traits.cc
+++ b/ui/latency/mojo/latency_info_struct_traits.cc
@@ -4,7 +4,7 @@
 
 #include "ui/latency/mojo/latency_info_struct_traits.h"
 
-#include "mojo/common/time_struct_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 
 namespace mojo {
 
diff --git a/ui/message_center/public/mojo/notification.mojom b/ui/message_center/public/mojo/notification.mojom
index 9d05a98b..823517c 100644
--- a/ui/message_center/public/mojo/notification.mojom
+++ b/ui/message_center/public/mojo/notification.mojom
@@ -4,7 +4,7 @@
 
 module message_center.mojom;
 
-import "mojo/common/time.mojom";
+import "mojo/public/mojom/base/time.mojom";
 import "mojo/public/mojom/base/string16.mojom";
 import "ui/gfx/image/mojo/image.mojom";
 import "ui/message_center/public/mojo/notifier_id.mojom";
@@ -51,7 +51,7 @@
 struct RichNotificationData {
   int32 priority;
   bool never_time_out;
-  mojo.common.mojom.Time timestamp;
+  mojo_base.mojom.Time timestamp;
   // |context_message| intentionally omitted. See https://crbug.com/797084
   gfx.mojom.ImageSkia? image;
   gfx.mojom.ImageSkia? small_image;
diff --git a/ui/message_center/public/mojo/notification_struct_traits.cc b/ui/message_center/public/mojo/notification_struct_traits.cc
index 1cf0faf2..3534b53a 100644
--- a/ui/message_center/public/mojo/notification_struct_traits.cc
+++ b/ui/message_center/public/mojo/notification_struct_traits.cc
@@ -4,8 +4,8 @@
 
 #include "ui/message_center/public/mojo/notification_struct_traits.h"
 
-#include "mojo/common/time_struct_traits.h"
 #include "mojo/public/cpp/base/string16_mojom_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "ui/gfx/image/mojo/image_skia_struct_traits.h"
 #include "ui/message_center/public/mojo/notifier_id_struct_traits.h"
 #include "url/mojom/url_gurl_mojom_traits.h"