diff --git a/DEPS b/DEPS
index fc0213b..f7fa9d2 100644
--- a/DEPS
+++ b/DEPS
@@ -78,7 +78,7 @@
   # 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': 'f5d857d30b6d37becadd73b3cb046b86b8d0cfb9',
+  'v8_revision': 'b88605f7468d01c269bda1d4d79bbd4f3d38e8a8',
   # 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.
@@ -130,7 +130,7 @@
   # 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': '4ba80741d0fc5fc87ea925177727fe58bd679fdd',
+  'catapult_revision': 'e0dc203974cdbdd9eb69a3afb213cfd0dcf400e7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/chrome/browser/autocomplete/autocomplete_classifier_factory.cc b/chrome/browser/autocomplete/autocomplete_classifier_factory.cc
index 6bf3210..d0816f3 100644
--- a/chrome/browser/autocomplete/autocomplete_classifier_factory.cc
+++ b/chrome/browser/autocomplete/autocomplete_classifier_factory.cc
@@ -4,7 +4,8 @@
 
 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
 
-#include "base/memory/ptr_util.h"
+#include <memory>
+
 #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h"
 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
 #include "chrome/browser/autocomplete/contextual_suggestions_service_factory.h"
@@ -39,14 +40,11 @@
 std::unique_ptr<KeyedService> AutocompleteClassifierFactory::BuildInstanceFor(
     content::BrowserContext* context) {
   Profile* profile = static_cast<Profile*>(context);
-  auto provider_client =
-      base::MakeUnique<ChromeAutocompleteProviderClient>(profile);
-  auto controller = base::MakeUnique<AutocompleteController>(
-      std::move(provider_client), nullptr,
-      AutocompleteClassifier::DefaultOmniboxProviders());
-  return base::MakeUnique<AutocompleteClassifier>(
-      std::move(controller),
-      base::MakeUnique<ChromeAutocompleteSchemeClassifier>(profile));
+  return std::make_unique<AutocompleteClassifier>(
+      std::make_unique<AutocompleteController>(
+          std::make_unique<ChromeAutocompleteProviderClient>(profile), nullptr,
+          AutocompleteClassifier::DefaultOmniboxProviders()),
+      std::make_unique<ChromeAutocompleteSchemeClassifier>(profile));
 }
 
 AutocompleteClassifierFactory::AutocompleteClassifierFactory()
diff --git a/chrome/browser/ui/views/accessibility/navigation_accessibility_uitest_win.cc b/chrome/browser/ui/views/accessibility/navigation_accessibility_uitest_win.cc
index 7f48628..372e906 100644
--- a/chrome/browser/ui/views/accessibility/navigation_accessibility_uitest_win.cc
+++ b/chrome/browser/ui/views/accessibility/navigation_accessibility_uitest_win.cc
@@ -203,7 +203,10 @@
 
 // Tests that when focus is in the omnibox and the user types a url and
 // presses enter, no focus events are sent on the old document.
-IN_PROC_BROWSER_TEST_F(NavigationAccessibilityTest, TestNavigateToNewUrl) {
+// Disabled due to flaky CHECK failures in
+// WinAccessibilityEventMonitor::WaitForNextEvent; see https://crbug.com/791981.
+IN_PROC_BROWSER_TEST_F(NavigationAccessibilityTest,
+                       DISABLED_TestNavigateToNewUrl) {
   content::BrowserAccessibilityState::GetInstance()->EnableAccessibility();
 
   ui_test_utils::NavigateToURL(browser(),
diff --git a/chrome/browser/ui/views/frame/test_with_browser_view.cc b/chrome/browser/ui/views/frame/test_with_browser_view.cc
index c179d20..f028f99 100644
--- a/chrome/browser/ui/views/frame/test_with_browser_view.cc
+++ b/chrome/browser/ui/views/frame/test_with_browser_view.cc
@@ -4,7 +4,8 @@
 
 #include "chrome/browser/ui/views/frame/test_with_browser_view.h"
 
-#include "base/memory/ptr_util.h"
+#include <memory>
+
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "build/build_config.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
@@ -35,28 +36,24 @@
 std::unique_ptr<KeyedService> CreateTemplateURLService(
     content::BrowserContext* context) {
   Profile* profile = static_cast<Profile*>(context);
-  return base::MakeUnique<TemplateURLService>(
-      profile->GetPrefs(),
-      std::unique_ptr<SearchTermsData>(new UIThreadSearchTermsData(profile)),
+  return std::make_unique<TemplateURLService>(
+      profile->GetPrefs(), std::make_unique<UIThreadSearchTermsData>(profile),
       WebDataServiceFactory::GetKeywordWebDataForProfile(
           profile, ServiceAccessType::EXPLICIT_ACCESS),
-      std::unique_ptr<TemplateURLServiceClient>(
-          new ChromeTemplateURLServiceClient(
-              HistoryServiceFactory::GetForProfile(
-                  profile, ServiceAccessType::EXPLICIT_ACCESS))),
+      std::make_unique<ChromeTemplateURLServiceClient>(
+          HistoryServiceFactory::GetForProfile(
+              profile, ServiceAccessType::EXPLICIT_ACCESS)),
       nullptr, nullptr, base::Closure());
 }
 
 std::unique_ptr<KeyedService> CreateAutocompleteClassifier(
     content::BrowserContext* context) {
   Profile* profile = static_cast<Profile*>(context);
-  return base::MakeUnique<AutocompleteClassifier>(
-      base::WrapUnique(new AutocompleteController(
-          base::WrapUnique(new ChromeAutocompleteProviderClient(profile)),
-
-          nullptr, AutocompleteClassifier::DefaultOmniboxProviders())),
-      std::unique_ptr<AutocompleteSchemeClassifier>(
-          new TestSchemeClassifier()));
+  return std::make_unique<AutocompleteClassifier>(
+      std::make_unique<AutocompleteController>(
+          std::make_unique<ChromeAutocompleteProviderClient>(profile), nullptr,
+          AutocompleteClassifier::DefaultOmniboxProviders()),
+      std::make_unique<TestSchemeClassifier>());
 }
 
 }  // namespace
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc
index f254d59..bc2f41f 100644
--- a/components/omnibox/browser/autocomplete_controller.cc
+++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -5,6 +5,8 @@
 #include "components/omnibox/browser/autocomplete_controller.h"
 
 #include <stddef.h>
+
+#include <memory>
 #include <set>
 #include <string>
 #include <utility>
@@ -12,7 +14,6 @@
 #include "base/feature_list.h"
 #include "base/format_macros.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
@@ -245,7 +246,7 @@
     // that would come with it.
     if (!ClipboardRecentContent::GetInstance()) {
       ClipboardRecentContent::SetInstance(
-          base::MakeUnique<ClipboardRecentContentGeneric>());
+          std::make_unique<ClipboardRecentContentGeneric>());
     }
 #endif
     // ClipboardRecentContent can be null in iOS tests.  For non-iOS, we
diff --git a/components/omnibox/browser/autocomplete_provider_unittest.cc b/components/omnibox/browser/autocomplete_provider_unittest.cc
index d3da554..05fb984 100644
--- a/components/omnibox/browser/autocomplete_provider_unittest.cc
+++ b/components/omnibox/browser/autocomplete_provider_unittest.cc
@@ -288,7 +288,7 @@
     : client_(new AutocompleteProviderClientWithClosure()),
       client_owned_(false) {
   client_->set_template_url_service(
-      base::MakeUnique<TemplateURLService>(nullptr, 0));
+      std::make_unique<TemplateURLService>(nullptr, 0));
 }
 
 AutocompleteProviderTest::~AutocompleteProviderTest() {
@@ -304,7 +304,7 @@
   data.SetKeyword(keyword);
   TemplateURLService* turl_model = client_->GetTemplateURLService();
   TemplateURL* default_turl =
-      turl_model->Add(base::MakeUnique<TemplateURL>(data));
+      turl_model->Add(std::make_unique<TemplateURL>(data));
   turl_model->SetUserSelectedDefaultSearchProvider(default_turl);
   turl_model->Load();
   TemplateURLID default_provider_id = default_turl->id();
@@ -369,7 +369,7 @@
   data.SetURL("http://defaultturl/{searchTerms}");
   TemplateURLService* turl_model = client_->GetTemplateURLService();
   TemplateURL* default_turl =
-      turl_model->Add(base::MakeUnique<TemplateURL>(data));
+      turl_model->Add(std::make_unique<TemplateURL>(data));
   turl_model->SetUserSelectedDefaultSearchProvider(default_turl);
   TemplateURLID default_provider_id = default_turl->id();
   ASSERT_NE(0, default_provider_id);
@@ -380,7 +380,7 @@
   data2.SetKeyword(base::ASCIIToUTF16("k"));
   data2.SetURL("http://keyword/{searchTerms}");
   TemplateURL* keyword_turl =
-      turl_model->Add(base::MakeUnique<TemplateURL>(data2));
+      turl_model->Add(std::make_unique<TemplateURL>(data2));
   ASSERT_NE(0, keyword_turl->id());
 
   ResetControllerWithType(AutocompleteProvider::TYPE_KEYWORD |
@@ -396,7 +396,7 @@
   data.SetKeyword(base::ASCIIToUTF16("foo.com"));
   data.SetURL("http://foo.com/{searchTerms}");
   TemplateURL* keyword_turl =
-      turl_model->Add(base::MakeUnique<TemplateURL>(data));
+      turl_model->Add(std::make_unique<TemplateURL>(data));
   ASSERT_NE(0, keyword_turl->id());
 
   // Make a TemplateURL for KeywordProvider that a shorter version of the
@@ -404,14 +404,14 @@
   data.SetShortName(base::ASCIIToUTF16("f"));
   data.SetKeyword(base::ASCIIToUTF16("f"));
   data.SetURL("http://f.com/{searchTerms}");
-  keyword_turl = turl_model->Add(base::MakeUnique<TemplateURL>(data));
+  keyword_turl = turl_model->Add(std::make_unique<TemplateURL>(data));
   ASSERT_NE(0, keyword_turl->id());
 
   // Create another TemplateURL for KeywordProvider.
   data.SetShortName(base::ASCIIToUTF16("bar.com"));
   data.SetKeyword(base::ASCIIToUTF16("bar.com"));
   data.SetURL("http://bar.com/{searchTerms}");
-  keyword_turl = turl_model->Add(base::MakeUnique<TemplateURL>(data));
+  keyword_turl = turl_model->Add(std::make_unique<TemplateURL>(data));
   ASSERT_NE(0, keyword_turl->id());
 
   ResetControllerWithType(AutocompleteProvider::TYPE_KEYWORD);
diff --git a/components/omnibox/browser/autocomplete_result_unittest.cc b/components/omnibox/browser/autocomplete_result_unittest.cc
index 6211592f..544ad83 100644
--- a/components/omnibox/browser/autocomplete_result_unittest.cc
+++ b/components/omnibox/browser/autocomplete_result_unittest.cc
@@ -11,7 +11,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -104,7 +103,7 @@
     // a DCHECK.
     field_trial_list_.reset();
     field_trial_list_.reset(new base::FieldTrialList(
-        base::MakeUnique<metrics::SHA1EntropyProvider>("foo")));
+        std::make_unique<metrics::SHA1EntropyProvider>("foo")));
     variations::testing::ClearAllVariationParams();
 
     // Create the list of mock providers.  5 is enough.
@@ -542,7 +541,7 @@
   url_data.SetShortName(base::ASCIIToUTF16("unittest"));
   url_data.SetKeyword(base::ASCIIToUTF16("foo"));
   url_data.SetURL("http://www.foo.com/s?q={searchTerms}");
-  template_url_service_.get()->Add(base::MakeUnique<TemplateURL>(url_data));
+  template_url_service_.get()->Add(std::make_unique<TemplateURL>(url_data));
 
   TestData data[] = {
     { 0, 1, 1300, true },
@@ -586,7 +585,7 @@
   url_data.SetShortName(base::ASCIIToUTF16("unittest"));
   url_data.SetKeyword(base::ASCIIToUTF16("foo"));
   url_data.SetURL("http://www.foo.com/s?q={searchTerms}");
-  template_url_service_.get()->Add(base::MakeUnique<TemplateURL>(url_data));
+  template_url_service_.get()->Add(std::make_unique<TemplateURL>(url_data));
 
   AutocompleteMatch dup_match;
   dup_match.destination_url = GURL("http://www.foo.com/s?q=foo&oq=dup");
diff --git a/components/omnibox/browser/base_search_provider.cc b/components/omnibox/browser/base_search_provider.cc
index 784dc80..e6fb1e6 100644
--- a/components/omnibox/browser/base_search_provider.cc
+++ b/components/omnibox/browser/base_search_provider.cc
@@ -8,11 +8,11 @@
 #include <stdint.h>
 
 #include <algorithm>
+#include <memory>
 
 #include "base/feature_list.h"
 #include "base/i18n/case_conversion.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/data_use_measurement/core/data_use_user_data.h"
@@ -161,7 +161,7 @@
 void BaseSearchProvider::DeleteMatch(const AutocompleteMatch& match) {
   DCHECK(match.deletable);
   if (!match.GetAdditionalInfo(BaseSearchProvider::kDeletionUrlKey).empty()) {
-    deletion_handlers_.push_back(base::MakeUnique<SuggestionDeletionHandler>(
+    deletion_handlers_.push_back(std::make_unique<SuggestionDeletionHandler>(
         match.GetAdditionalInfo(BaseSearchProvider::kDeletionUrlKey),
         client_->GetRequestContext(),
         base::Bind(&BaseSearchProvider::OnDeletionComplete,
diff --git a/components/omnibox/browser/base_search_provider_unittest.cc b/components/omnibox/browser/base_search_provider_unittest.cc
index b32062a9..0387a0a 100644
--- a/components/omnibox/browser/base_search_provider_unittest.cc
+++ b/components/omnibox/browser/base_search_provider_unittest.cc
@@ -5,6 +5,7 @@
 #include "components/omnibox/browser/base_search_provider.h"
 
 #include <algorithm>
+#include <memory>
 #include <utility>
 
 #include "base/macros.h"
@@ -92,7 +93,7 @@
 TEST_F(BaseSearchProviderTest, PreserveAnswersWhenDeduplicating) {
   TemplateURLData data;
   data.SetURL("http://foo.com/url?bar={searchTerms}");
-  auto template_url = base::MakeUnique<TemplateURL>(data);
+  auto template_url = std::make_unique<TemplateURL>(data);
 
   TestBaseSearchProvider::MatchMap map;
   base::string16 query = base::ASCIIToUTF16("weather los angeles");
@@ -178,7 +179,7 @@
 TEST_F(BaseSearchProviderTest, MatchTailSuggestionProperly) {
   TemplateURLData data;
   data.SetURL("http://foo.com/url?bar={searchTerms}");
-  auto template_url = base::MakeUnique<TemplateURL>(data);
+  auto template_url = std::make_unique<TemplateURL>(data);
 
   AutocompleteInput autocomplete_input(
       base::ASCIIToUTF16("weather"), 7, metrics::OmniboxEventProto::BLANK,
diff --git a/components/omnibox/browser/contextual_suggestions_service.cc b/components/omnibox/browser/contextual_suggestions_service.cc
index 7d6a9820..b81ef9b 100644
--- a/components/omnibox/browser/contextual_suggestions_service.cc
+++ b/components/omnibox/browser/contextual_suggestions_service.cc
@@ -4,11 +4,11 @@
 
 #include "components/omnibox/browser/contextual_suggestions_service.h"
 
+#include <memory>
 #include <utility>
 
 #include "base/feature_list.h"
 #include "base/json/json_writer.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
@@ -64,9 +64,9 @@
 //
 std::string FormatRequestBodyExperimentalService(
     const std::string& current_url) {
-  auto request = base::MakeUnique<base::DictionaryValue>();
-  auto url_list = base::MakeUnique<base::ListValue>();
-  auto url_entry = base::MakeUnique<base::DictionaryValue>();
+  auto request = std::make_unique<base::DictionaryValue>();
+  auto url_list = std::make_unique<base::ListValue>();
+  auto url_entry = std::make_unique<base::DictionaryValue>();
   url_entry->SetString("url", current_url);
   url_list->Append(std::move(url_entry));
   request->Set("urls", std::move(url_list));
@@ -298,7 +298,7 @@
   // Create the oauth2 token fetcher.
   const OAuth2TokenService::ScopeSet scopes{
       "https://www.googleapis.com/auth/cusco-chrome-extension"};
-  token_fetcher_ = base::MakeUnique<AccessTokenFetcher>(
+  token_fetcher_ = std::make_unique<AccessTokenFetcher>(
       "contextual_suggestions_service", signin_manager_, token_service_, scopes,
       base::BindOnce(&ContextualSuggestionsService::AccessTokenAvailable,
                      base::Unretained(this), std::move(fetcher),
diff --git a/components/omnibox/browser/fake_autocomplete_provider_client.cc b/components/omnibox/browser/fake_autocomplete_provider_client.cc
index 1787801..6d14963 100644
--- a/components/omnibox/browser/fake_autocomplete_provider_client.cc
+++ b/components/omnibox/browser/fake_autocomplete_provider_client.cc
@@ -4,8 +4,9 @@
 
 #include "components/omnibox/browser/fake_autocomplete_provider_client.h"
 
+#include <memory>
+
 #include "base/files/file_path.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/test/test_bookmark_client.h"
diff --git a/components/omnibox/browser/history_url_provider_unittest.cc b/components/omnibox/browser/history_url_provider_unittest.cc
index 2d876490..69c16ad 100644
--- a/components/omnibox/browser/history_url_provider_unittest.cc
+++ b/components/omnibox/browser/history_url_provider_unittest.cc
@@ -11,7 +11,6 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -964,7 +963,7 @@
   data.SetURL("http://testsearch.com/?q={searchTerms}");
   TemplateURLService* template_url_service = client_->GetTemplateURLService();
   TemplateURL* template_url =
-      template_url_service->Add(base::MakeUnique<TemplateURL>(data));
+      template_url_service->Add(std::make_unique<TemplateURL>(data));
   template_url_service->SetUserSelectedDefaultSearchProvider(template_url);
   template_url_service->Load();
 
@@ -1194,7 +1193,7 @@
   ExpectFormattedFullMatch("abc", L"https://www.abc.def.com/path", 12, 3);
   ExpectFormattedFullMatch("hij", L"https://www.hij.com/path", 12, 3);
 
-  auto feature_list = base::MakeUnique<base::test::ScopedFeatureList>();
+  auto feature_list = std::make_unique<base::test::ScopedFeatureList>();
   feature_list->InitWithFeatures(
       {omnibox::kUIExperimentHideSuggestionUrlScheme,
        omnibox::kUIExperimentHideSuggestionUrlTrivialSubdomains,
diff --git a/components/omnibox/browser/in_memory_url_index_unittest.cc b/components/omnibox/browser/in_memory_url_index_unittest.cc
index bd4a730..ac058edb 100644
--- a/components/omnibox/browser/in_memory_url_index_unittest.cc
+++ b/components/omnibox/browser/in_memory_url_index_unittest.cc
@@ -17,7 +17,6 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/i18n/case_conversion.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
@@ -278,7 +277,7 @@
   }
 
   // Set up a simple template URL service with a default search engine.
-  template_url_service_ = base::MakeUnique<TemplateURLService>(
+  template_url_service_ = std::make_unique<TemplateURLService>(
       kTemplateURLData, arraysize(kTemplateURLData));
   TemplateURL* template_url = template_url_service_->GetTemplateURLForKeyword(
       base::ASCIIToUTF16(kDefaultTemplateURLKeyword));
diff --git a/components/omnibox/browser/keyword_provider_unittest.cc b/components/omnibox/browser/keyword_provider_unittest.cc
index 43c36be..620edb0 100644
--- a/components/omnibox/browser/keyword_provider_unittest.cc
+++ b/components/omnibox/browser/keyword_provider_unittest.cc
@@ -7,11 +7,11 @@
 #include <stddef.h>
 
 #include <map>
+#include <memory>
 #include <utility>
 
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/strings/utf_string_conversions.h"
@@ -66,7 +66,7 @@
     // a DCHECK.
     field_trial_list_.reset();
     field_trial_list_.reset(new base::FieldTrialList(
-        base::MakeUnique<metrics::SHA1EntropyProvider>("foo")));
+        std::make_unique<metrics::SHA1EntropyProvider>("foo")));
     variations::testing::ClearAllVariationParams();
   }
   ~KeywordProviderTest() override {}
@@ -465,7 +465,7 @@
   data.SetKeyword(keyword);
   data.SetURL("http://www.google.com/foo?q={searchTerms}");
   TemplateURL* template_url = client_->GetTemplateURLService()->Add(
-      base::MakeUnique<TemplateURL>(data));
+      std::make_unique<TemplateURL>(data));
   ASSERT_TRUE(
       template_url ==
       client_->GetTemplateURLService()->GetTemplateURLForKeyword(keyword));
diff --git a/components/omnibox/browser/mock_autocomplete_provider_client.cc b/components/omnibox/browser/mock_autocomplete_provider_client.cc
index 02f5d94..e793441 100644
--- a/components/omnibox/browser/mock_autocomplete_provider_client.cc
+++ b/components/omnibox/browser/mock_autocomplete_provider_client.cc
@@ -4,11 +4,11 @@
 
 #include "components/omnibox/browser/mock_autocomplete_provider_client.h"
 
-#include "base/memory/ptr_util.h"
+#include <memory>
 
 MockAutocompleteProviderClient::MockAutocompleteProviderClient() {
   contextual_suggestions_service_ =
-      base::MakeUnique<ContextualSuggestionsService>(
+      std::make_unique<ContextualSuggestionsService>(
           /*signin_manager=*/nullptr, /*token_service=*/nullptr,
           GetRequestContext());
 }
diff --git a/components/omnibox/browser/omnibox_edit_model_unittest.cc b/components/omnibox/browser/omnibox_edit_model_unittest.cc
index 6523032..de33410 100644
--- a/components/omnibox/browser/omnibox_edit_model_unittest.cc
+++ b/components/omnibox/browser/omnibox_edit_model_unittest.cc
@@ -5,9 +5,9 @@
 #include "components/omnibox/browser/omnibox_edit_model.h"
 
 #include <stddef.h>
+
 #include <memory>
 
-#include "base/memory/ptr_util.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/omnibox_view.h"
 #include "components/omnibox/browser/search_provider.h"
@@ -19,10 +19,10 @@
 class OmniboxEditModelTest : public testing::Test {
  public:
   void SetUp() override {
-    controller_ = base::MakeUnique<TestOmniboxEditController>();
-    view_ = base::MakeUnique<TestOmniboxView>(controller_.get());
-    model_ = base::MakeUnique<OmniboxEditModel>(
-        view_.get(), controller_.get(), base::MakeUnique<TestOmniboxClient>());
+    controller_ = std::make_unique<TestOmniboxEditController>();
+    view_ = std::make_unique<TestOmniboxView>(controller_.get());
+    model_ = std::make_unique<OmniboxEditModel>(
+        view_.get(), controller_.get(), std::make_unique<TestOmniboxClient>());
   }
 
   const TestOmniboxView& view() { return *view_; }
diff --git a/components/omnibox/browser/omnibox_field_trial_unittest.cc b/components/omnibox/browser/omnibox_field_trial_unittest.cc
index f0bb4f0..39834fd 100644
--- a/components/omnibox/browser/omnibox_field_trial_unittest.cc
+++ b/components/omnibox/browser/omnibox_field_trial_unittest.cc
@@ -9,7 +9,6 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/strings/string16.h"
 #include "build/build_config.h"
@@ -45,7 +44,7 @@
     // a DCHECK.
     field_trial_list_.reset();
     field_trial_list_.reset(new base::FieldTrialList(
-        base::MakeUnique<metrics::SHA1EntropyProvider>("foo")));
+        std::make_unique<metrics::SHA1EntropyProvider>("foo")));
     variations::testing::ClearAllVariationParams();
   }
 
diff --git a/components/omnibox/browser/omnibox_popup_model_unittest.cc b/components/omnibox/browser/omnibox_popup_model_unittest.cc
index 083650a..e03e79a 100644
--- a/components/omnibox/browser/omnibox_popup_model_unittest.cc
+++ b/components/omnibox/browser/omnibox_popup_model_unittest.cc
@@ -6,8 +6,9 @@
 
 #include <stddef.h>
 
+#include <memory>
+
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/omnibox/browser/autocomplete_controller.h"
 #include "components/omnibox/browser/autocomplete_match.h"
@@ -41,7 +42,7 @@
  public:
   OmniboxPopupModelTest()
       : view_(&controller_),
-        model_(&view_, &controller_, base::MakeUnique<TestOmniboxClient>()),
+        model_(&view_, &controller_, std::make_unique<TestOmniboxClient>()),
         popup_model_(&popup_view_, &model_) {}
 
   OmniboxEditModel* model() { return &model_; }
diff --git a/components/omnibox/browser/physical_web_provider.cc b/components/omnibox/browser/physical_web_provider.cc
index ce8b0ee..d3d18ef 100644
--- a/components/omnibox/browser/physical_web_provider.cc
+++ b/components/omnibox/browser/physical_web_provider.cc
@@ -9,7 +9,6 @@
 #include <utility>
 
 #include "base/feature_list.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -267,7 +266,7 @@
   bookmarks::TitledUrlIndex index(nullptr);
   std::vector<std::unique_ptr<PhysicalWebNode>> nodes;
   for (const auto& metadata_item : *metadata_list) {
-    nodes.push_back(base::MakeUnique<PhysicalWebNode>(metadata_item));
+    nodes.push_back(std::make_unique<PhysicalWebNode>(metadata_item));
     index.Add(nodes.back().get());
   }
 
diff --git a/components/omnibox/browser/physical_web_provider_unittest.cc b/components/omnibox/browser/physical_web_provider_unittest.cc
index 08f0e92..ea1308f2c 100644
--- a/components/omnibox/browser/physical_web_provider_unittest.cc
+++ b/components/omnibox/browser/physical_web_provider_unittest.cc
@@ -9,7 +9,6 @@
 #include <string>
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -43,7 +42,7 @@
  public:
   FakeAutocompleteProviderClient()
       : physical_web_data_source_(
-            base::MakeUnique<FakePhysicalWebDataSource>()),
+            std::make_unique<FakePhysicalWebDataSource>()),
         is_off_the_record_(false) {}
 
   const AutocompleteSchemeClassifier& GetSchemeClassifier() const override {
@@ -96,7 +95,7 @@
     // DCHECK.
     field_trial_list_.reset();
     field_trial_list_.reset(new base::FieldTrialList(
-        base::MakeUnique<metrics::SHA1EntropyProvider>("foo")));
+        std::make_unique<metrics::SHA1EntropyProvider>("foo")));
     variations::testing::ClearAllVariationParams();
   }
 
@@ -114,7 +113,7 @@
   // populated with a unique scanned URL and page metadata.
   static std::unique_ptr<physical_web::MetadataList> CreateMetadata(
       size_t metadata_count) {
-    auto metadata_list = base::MakeUnique<physical_web::MetadataList>();
+    auto metadata_list = std::make_unique<physical_web::MetadataList>();
     for (size_t i = 0; i < metadata_count; ++i) {
       std::string item_id = base::NumberToString(i);
       std::string url = "https://example.com/" + item_id;
diff --git a/components/omnibox/browser/scored_history_match_unittest.cc b/components/omnibox/browser/scored_history_match_unittest.cc
index 2c978b9..2f4b67bf 100644
--- a/components/omnibox/browser/scored_history_match_unittest.cc
+++ b/components/omnibox/browser/scored_history_match_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/auto_reset.h"
 #include "base/bind.h"
 #include "base/i18n/break_iterator.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
diff --git a/components/omnibox/browser/shortcuts_backend_unittest.cc b/components/omnibox/browser/shortcuts_backend_unittest.cc
index 4026d4f..ada12d0 100644
--- a/components/omnibox/browser/shortcuts_backend_unittest.cc
+++ b/components/omnibox/browser/shortcuts_backend_unittest.cc
@@ -6,9 +6,10 @@
 
 #include <stddef.h>
 
+#include <memory>
+
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -101,7 +102,7 @@
   data.SetKeyword(base::UTF8ToUTF16("foo"));
 
   TemplateURL* template_url =
-      template_url_service_->Add(base::MakeUnique<TemplateURL>(data));
+      template_url_service_->Add(std::make_unique<TemplateURL>(data));
   template_url_service_->SetUserSelectedDefaultSearchProvider(template_url);
 }
 
@@ -115,7 +116,7 @@
   base::FilePath shortcuts_database_path =
       profile_dir_.GetPath().Append(kShortcutsDatabaseName);
   backend_ = new ShortcutsBackend(
-      template_url_service_.get(), base::MakeUnique<SearchTermsData>(),
+      template_url_service_.get(), std::make_unique<SearchTermsData>(),
       history_service_.get(), shortcuts_database_path, false);
   ASSERT_TRUE(backend_.get());
   backend_->AddObserver(this);
diff --git a/components/omnibox/browser/shortcuts_provider_unittest.cc b/components/omnibox/browser/shortcuts_provider_unittest.cc
index ad94806..9e5477c6 100644
--- a/components/omnibox/browser/shortcuts_provider_unittest.cc
+++ b/components/omnibox/browser/shortcuts_provider_unittest.cc
@@ -16,7 +16,6 @@
 
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
diff --git a/components/omnibox/browser/suggestion_answer.cc b/components/omnibox/browser/suggestion_answer.cc
index 00d3c666..5bf8d85 100644
--- a/components/omnibox/browser/suggestion_answer.cc
+++ b/components/omnibox/browser/suggestion_answer.cc
@@ -6,8 +6,9 @@
 
 #include <stddef.h>
 
+#include <memory>
+
 #include "base/i18n/rtl.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -195,7 +196,7 @@
 // static
 std::unique_ptr<SuggestionAnswer> SuggestionAnswer::ParseAnswer(
     const base::DictionaryValue* answer_json) {
-  auto result = base::MakeUnique<SuggestionAnswer>();
+  auto result = std::make_unique<SuggestionAnswer>();
 
   const base::ListValue* lines_json;
   if (!answer_json->GetList(kAnswerJsonLines, &lines_json) ||
diff --git a/components/omnibox/browser/suggestion_answer_unittest.cc b/components/omnibox/browser/suggestion_answer_unittest.cc
index 5f154a2..7552c23 100644
--- a/components/omnibox/browser/suggestion_answer_unittest.cc
+++ b/components/omnibox/browser/suggestion_answer_unittest.cc
@@ -5,9 +5,9 @@
 #include "components/omnibox/browser/suggestion_answer.h"
 
 #include <algorithm>
+#include <memory>
 
 #include "base/json/json_reader.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -35,7 +35,7 @@
   SuggestionAnswer answer1;
   EXPECT_TRUE(answer1.Equals(SuggestionAnswer(answer1)));
 
-  auto answer2 = base::MakeUnique<SuggestionAnswer>();
+  auto answer2 = std::make_unique<SuggestionAnswer>();
   answer2->set_type(832345);
   EXPECT_TRUE(answer2->Equals(SuggestionAnswer(*answer2)));
 
diff --git a/components/omnibox/browser/test_omnibox_client.cc b/components/omnibox/browser/test_omnibox_client.cc
index b8f86ba..c747b37 100644
--- a/components/omnibox/browser/test_omnibox_client.cc
+++ b/components/omnibox/browser/test_omnibox_client.cc
@@ -4,10 +4,10 @@
 
 #include "components/omnibox/browser/test_omnibox_client.h"
 
+#include <memory>
 #include <utility>
 #include <vector>
 
-#include "base/memory/ptr_util.h"
 #include "components/omnibox/browser/autocomplete_controller.h"
 #include "components/omnibox/browser/autocomplete_scheme_classifier.h"
 #include "components/omnibox/browser/mock_autocomplete_provider_client.h"
@@ -19,11 +19,11 @@
 
 TestOmniboxClient::TestOmniboxClient()
     : autocomplete_classifier_(
-          base::MakeUnique<AutocompleteController>(
+          std::make_unique<AutocompleteController>(
               CreateAutocompleteProviderClient(),
               nullptr,
               AutocompleteClassifier::DefaultOmniboxProviders()),
-          base::MakeUnique<TestSchemeClassifier>()) {}
+          std::make_unique<TestSchemeClassifier>()) {}
 
 TestOmniboxClient::~TestOmniboxClient() {
   autocomplete_classifier_.Shutdown();
diff --git a/components/omnibox/browser/titled_url_match_utils_unittest.cc b/components/omnibox/browser/titled_url_match_utils_unittest.cc
index 5085933..4b5095d 100644
--- a/components/omnibox/browser/titled_url_match_utils_unittest.cc
+++ b/components/omnibox/browser/titled_url_match_utils_unittest.cc
@@ -4,7 +4,8 @@
 
 #include "components/omnibox/browser/titled_url_match_utils.h"
 
-#include "base/memory/ptr_util.h"
+#include <memory>
+
 #include "base/strings/utf_string_conversions.h"
 #include "components/bookmarks/browser/titled_url_match.h"
 #include "components/bookmarks/browser/titled_url_node.h"
diff --git a/components/omnibox/browser/zero_suggest_provider_unittest.cc b/components/omnibox/browser/zero_suggest_provider_unittest.cc
index 18edadbd..662b9bcda 100644
--- a/components/omnibox/browser/zero_suggest_provider_unittest.cc
+++ b/components/omnibox/browser/zero_suggest_provider_unittest.cc
@@ -5,9 +5,9 @@
 #include "components/omnibox/browser/zero_suggest_provider.h"
 
 #include <map>
+#include <memory>
 #include <string>
 
-#include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
@@ -199,7 +199,7 @@
   data.SetShortName(base::ASCIIToUTF16("t"));
   data.SetURL("https://www.google.com/?q={searchTerms}");
   data.suggestions_url = "https://www.google.com/complete/?q={searchTerms}";
-  default_t_url_ = turl_model->Add(base::MakeUnique<TemplateURL>(data));
+  default_t_url_ = turl_model->Add(std::make_unique<TemplateURL>(data));
   turl_model->SetUserSelectedDefaultSearchProvider(default_t_url_);
 
   provider_ = ZeroSuggestProvider::Create(client_.get(), nullptr, this);
@@ -213,7 +213,7 @@
   // a DCHECK.
   field_trial_list_.reset();
   field_trial_list_.reset(new base::FieldTrialList(
-      base::MakeUnique<metrics::SHA1EntropyProvider>("foo")));
+      std::make_unique<metrics::SHA1EntropyProvider>("foo")));
   variations::testing::ClearAllVariationParams();
 }
 
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index ce43af6..4e1f6938 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -203,8 +203,8 @@
   } else if (base::SysInfo::AmountOfPhysicalMemoryMB() <= 512) {
     // In this case we prefer to use RGB565 format instead of RGBA8888 if
     // possible.
-    // TODO(danakj): GpuCommandBufferStub constructor checks for alpha == 0 in
-    // order to enable 565, but it should avoid using 565 when -1s are
+    // TODO(danakj): CommandBufferStub constructor checks for alpha == 0
+    // in order to enable 565, but it should avoid using 565 when -1s are
     // specified
     // (IOW check that a <= 0 && rgb > 0 && rgb <= 565) then alpha should be
     // -1.
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
index 4e32865..95ea27d5 100644
--- a/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
-#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/renderer_host/media/in_process_video_capture_provider.h"
@@ -52,9 +51,7 @@
 const char kNoFormatsVideoDeviceID[] = "/dev/video1";
 const char kZeroResolutionVideoDeviceID[] = "/dev/video2";
 const char* const kDefaultVideoDeviceID = kZeroResolutionVideoDeviceID;
-const char kUserDefaultAudioInputDeviceID[] = "fake_audio_input_2";
-const char kSystemDefaultAudioInputLabel[] = "Fake Audio Input 1";
-const char kSystemDefaultAudioOutputLabel[] = "Fake Audio Output 1";
+const char kDefaultAudioDeviceID[] = "fake_audio_input_2";
 
 const auto kIgnoreLogMessageCB = base::BindRepeating([](const std::string&) {});
 
@@ -95,8 +92,7 @@
         switches::kUseFakeDeviceForMediaStream,
         base::StringPrintf("video-input-default-id=%s, "
                            "audio-input-default-id=%s",
-                           kDefaultVideoDeviceID,
-                           kUserDefaultAudioInputDeviceID));
+                           kDefaultVideoDeviceID, kDefaultAudioDeviceID));
     audio_manager_ = std::make_unique<media::MockAudioManager>(
         std::make_unique<media::TestAudioThread>());
     audio_system_ =
@@ -202,7 +198,7 @@
     EXPECT_EQ(kNumExpectedEntries, capabilities.size());
     std::string expected_first_device_id =
         GetHMACForMediaDeviceID(browser_context_->GetMediaDeviceIDSalt(),
-                                origin_, kUserDefaultAudioInputDeviceID);
+                                origin_, kDefaultAudioDeviceID);
     EXPECT_EQ(expected_first_device_id, capabilities[0]->device_id);
     for (const auto& capability : capabilities)
       EXPECT_TRUE(capability->parameters.IsValid());
@@ -308,15 +304,8 @@
   }
 
   // Returns true if all devices have labels, false otherwise.
-  bool DoesContainLabels(
-      const MediaDeviceInfoArray& device_infos,
-      const std::string& system_default_label = std::string()) {
+  bool DoesContainLabels(const MediaDeviceInfoArray& device_infos) {
     for (const auto& device_info : device_infos) {
-      if (media::AudioDeviceDescription::IsDefaultDevice(
-              device_info.device_id)) {
-        EXPECT_TRUE(base::EndsWith(device_info.label, system_default_label,
-                                   base::CompareCase::SENSITIVE));
-      }
       if (device_info.label.empty())
         return false;
     }
@@ -325,13 +314,8 @@
 
   // Returns true if all devices have labels, false otherwise.
   bool DoesContainLabels(const std::vector<MediaDeviceInfoArray>& enumeration) {
-    for (int i = 0; i < NUM_MEDIA_DEVICE_TYPES; i++) {
-      std::string default_label;
-      if (i == MEDIA_DEVICE_TYPE_AUDIO_INPUT)
-        default_label = kSystemDefaultAudioInputLabel;
-      else if (i == MEDIA_DEVICE_TYPE_AUDIO_OUTPUT)
-        default_label = kSystemDefaultAudioOutputLabel;
-      if (!DoesContainLabels(enumeration[i], default_label))
+    for (const auto& device_infos : enumeration) {
+      if (!DoesContainLabels(device_infos))
         return false;
     }
     return true;
diff --git a/content/browser/renderer_host/media/media_devices_manager.cc b/content/browser/renderer_host/media/media_devices_manager.cc
index 50435cd..5ad8bf2 100644
--- a/content/browser/renderer_host/media/media_devices_manager.cc
+++ b/content/browser/renderer_host/media/media_devices_manager.cc
@@ -49,23 +49,23 @@
   return output_string;
 }
 
-media::AudioDeviceDescriptions GetFakeAudioDevices(bool is_input) {
-  media::AudioDeviceDescriptions result;
+MediaDeviceInfoArray GetFakeAudioDevices(bool is_input) {
+  MediaDeviceInfoArray result;
   if (is_input) {
-    result.emplace_back("Fake Default Audio Input",
-                        media::AudioDeviceDescription::kDefaultDeviceId,
-                        "fake_group_audio_1");
-    result.emplace_back("Fake Audio Input 1", "fake_audio_input_1",
-                        "fake_group_audio_1");
-    result.emplace_back("Fake Audio Input 2", "fake_audio_input_2",
+    result.emplace_back(media::AudioDeviceDescription::kDefaultDeviceId,
+                        "Fake Default Audio Input",
+                        "fake_group_audio_input_default");
+    result.emplace_back("fake_audio_input_1", "Fake Audio Input 1",
+                        "fake_group_audio_input_1");
+    result.emplace_back("fake_audio_input_2", "Fake Audio Input 2",
                         "fake_group_audio_input_2");
   } else {
-    result.emplace_back("Fake Default Audio Output",
-                        media::AudioDeviceDescription::kDefaultDeviceId,
-                        "fake_group_audio_1");
-    result.emplace_back("Fake Audio Output 1", "fake_audio_output_1",
-                        "fake_group_audio_1");
-    result.emplace_back("Fake Audio Output 2", "fake_audio_output_2",
+    result.emplace_back(media::AudioDeviceDescription::kDefaultDeviceId,
+                        "Fake Default Audio Output",
+                        "fake_group_audio_output_default");
+    result.emplace_back("fake_audio_output_1", "Fake Audio Output 1",
+                        "fake_group_audio_output_1");
+    result.emplace_back("fake_audio_output_2", "Fake Audio Output 2",
                         "fake_group_audio_output_2");
   }
 
@@ -339,7 +339,7 @@
       is_input ? MEDIA_DEVICE_TYPE_AUDIO_INPUT : MEDIA_DEVICE_TYPE_AUDIO_OUTPUT;
   if (use_fake_devices_) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(&MediaDevicesManager::AudioDevicesEnumerated,
+        FROM_HERE, base::BindOnce(&MediaDevicesManager::DevicesEnumerated,
                                   weak_factory_.GetWeakPtr(), type,
                                   GetFakeAudioDevices(is_input)));
     return;
@@ -365,56 +365,10 @@
     media::AudioDeviceDescriptions device_descriptions) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  auto it_default_device =
-      std::find_if(device_descriptions.begin(), device_descriptions.end(),
-                   [](const media::AudioDeviceDescription& description) {
-                     return media::AudioDeviceDescription::IsDefaultDevice(
-                         description.unique_id);
-                   });
-
-  auto it_real_default_device = device_descriptions.end();
-  if (it_default_device != device_descriptions.end()) {
-    // Find the real device that maps to the default device by finding
-    // coincidence in the group ID.
-    // This approach works only when the following is true:
-    // * group ID is properly supported so that the default device has the
-    //   same group ID as some real device.
-    // * For input devices, the default device has an associated output device.
-    // * There is only one device with the same group ID of the default device.
-    // TODO(guidou): Get the real ID of the default input device from
-    // media::AudioSystem when the functionality becomes available.
-    // http://crbug.com/788758
-    for (auto it = device_descriptions.begin(); it != device_descriptions.end();
-         ++it) {
-      if (it->group_id == it_default_device->group_id &&
-          !media::AudioDeviceDescription::IsDefaultDevice(it->unique_id)) {
-        if (it_real_default_device != device_descriptions.end()) {
-          // If there is more than one real device with the same group ID as the
-          // default device, the exact mapping cannot be found.
-          it_real_default_device = device_descriptions.end();
-          break;
-        } else {
-          it_real_default_device = it;
-        }
-      }
-    }
-  }
-
   MediaDeviceInfoArray snapshot;
   for (const media::AudioDeviceDescription& description : device_descriptions) {
-    if (it_real_default_device != device_descriptions.end() &&
-        media::AudioDeviceDescription::IsDefaultDevice(description.unique_id)) {
-      // TODO(guidou): Make the concatenation of the default and real device
-      // labels in a properly localized manner. http://crbug.com/788767
-      snapshot.emplace_back(
-          description.unique_id,
-          description.device_name + " - " + it_real_default_device->device_name,
-          description.group_id);
-    } else {
-      snapshot.emplace_back(description);
-    }
+    snapshot.emplace_back(description);
   }
-
   DevicesEnumerated(type, snapshot);
 }
 
diff --git a/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc b/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc
index 034b29d..1b0abc10c 100644
--- a/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc
+++ b/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc
@@ -93,9 +93,8 @@
 #if defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
 // Renderer crashes under Android ASAN: https://crbug.com/408496.
 #define MAYBE_CallWithAudioDebugRecordings DISABLED_CallWithAudioDebugRecordings
-#elif (defined(OS_ANDROID) || defined(OS_WIN))
+#elif defined(OS_ANDROID)
 // Renderer crashes on Android M. https://crbug.com/535728.
-// Flaky on Windows. https://crbug.com/783790
 #define MAYBE_CallWithAudioDebugRecordings DISABLED_CallWithAudioDebugRecordings
 #else
 #define MAYBE_CallWithAudioDebugRecordings CallWithAudioDebugRecordings
diff --git a/gpu/ipc/common/gpu_messages.h b/gpu/ipc/common/gpu_messages.h
index 1f9806f..e634f79 100644
--- a/gpu/ipc/common/gpu_messages.h
+++ b/gpu/ipc/common/gpu_messages.h
@@ -76,10 +76,10 @@
 // These are messages from a renderer process to the GPU process.
 
 // Tells the GPU process to create a new command buffer. A corresponding
-// GpuCommandBufferStub is created.  if |surface_handle| is non-null, |size| is
-// ignored, and it will render directly to the native surface (only the browser
-// process is allowed to create those). Otherwise it will create an offscreen
-// backbuffer of dimensions |size|.
+// CommandBufferStub is created.  If |surface_handle| is non-null, |size|
+// is ignored, and it will render directly to the native surface (only the
+// browser process is allowed to create those). Otherwise it will create an
+// offscreen backbuffer of dimensions |size|.
 IPC_SYNC_MESSAGE_CONTROL3_2(GpuChannelMsg_CreateCommandBuffer,
                             GPUCreateCommandBufferConfig /* init_params */,
                             int32_t /* route_id */,
@@ -87,7 +87,7 @@
                             gpu::ContextResult,
                             gpu::Capabilities /* capabilities */)
 
-// The CommandBufferProxy sends this to the GpuCommandBufferStub in its
+// The CommandBufferProxy sends this to the CommandBufferStub in its
 // destructor, so that the stub deletes the actual CommandBufferService
 // object that it's hosting.
 IPC_SYNC_MESSAGE_CONTROL1_0(GpuChannelMsg_DestroyCommandBuffer,
diff --git a/gpu/ipc/service/BUILD.gn b/gpu/ipc/service/BUILD.gn
index 3397fbf..100d5629 100644
--- a/gpu/ipc/service/BUILD.gn
+++ b/gpu/ipc/service/BUILD.gn
@@ -28,13 +28,13 @@
 target(link_target_type, "ipc_service_sources") {
   visibility = [ "//gpu/*" ]
   sources = [
+    "command_buffer_stub.cc",
+    "command_buffer_stub.h",
     "gpu_channel.cc",
     "gpu_channel.h",
     "gpu_channel_manager.cc",
     "gpu_channel_manager.h",
     "gpu_channel_manager_delegate.h",
-    "gpu_command_buffer_stub.cc",
-    "gpu_command_buffer_stub.h",
     "gpu_config.h",
     "gpu_init.cc",
     "gpu_init.h",
diff --git a/gpu/ipc/service/gpu_command_buffer_stub.cc b/gpu/ipc/service/command_buffer_stub.cc
similarity index 88%
rename from gpu/ipc/service/gpu_command_buffer_stub.cc
rename to gpu/ipc/service/command_buffer_stub.cc
index fe38265..14c52b9 100644
--- a/gpu/ipc/service/gpu_command_buffer_stub.cc
+++ b/gpu/ipc/service/command_buffer_stub.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 "gpu/ipc/service/gpu_command_buffer_stub.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
 
 #include <utility>
 
@@ -218,7 +218,7 @@
 
 }  // namespace
 
-GpuCommandBufferStub::GpuCommandBufferStub(
+CommandBufferStub::CommandBufferStub(
     GpuChannel* channel,
     const GPUCreateCommandBufferConfig& init_params,
     CommandBufferId command_buffer_id,
@@ -240,15 +240,15 @@
       active_url_hash_(base::Hash(active_url_.possibly_invalid_spec())),
       wait_set_get_buffer_count_(0) {}
 
-GpuCommandBufferStub::~GpuCommandBufferStub() {
+CommandBufferStub::~CommandBufferStub() {
   Destroy();
 }
 
-GpuMemoryManager* GpuCommandBufferStub::GetMemoryManager() const {
+GpuMemoryManager* CommandBufferStub::GetMemoryManager() const {
   return channel()->gpu_channel_manager()->gpu_memory_manager();
 }
 
-bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
+bool CommandBufferStub::OnMessageReceived(const IPC::Message& message) {
   TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "GPUTask",
                "data", DevToolsChannelData::CreateForChannel(channel()));
   FastSetActiveURL(active_url_, active_url_hash_, channel_);
@@ -277,7 +277,7 @@
   // Always use IPC_MESSAGE_HANDLER_DELAY_REPLY for synchronous message handlers
   // here. This is so the reply can be delayed if the scheduler is unscheduled.
   bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(GpuCommandBufferStub, message)
+  IPC_BEGIN_MESSAGE_MAP(CommandBufferStub, message)
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetGetBuffer, OnSetGetBuffer);
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_TakeFrontBuffer, OnTakeFrontBuffer);
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ReturnFrontBuffer,
@@ -314,12 +314,12 @@
   return handled;
 }
 
-bool GpuCommandBufferStub::Send(IPC::Message* message) {
+bool CommandBufferStub::Send(IPC::Message* message) {
   return channel_->Send(message);
 }
 
 #if defined(OS_WIN)
-void GpuCommandBufferStub::DidCreateAcceleratedSurfaceChildWindow(
+void CommandBufferStub::DidCreateAcceleratedSurfaceChildWindow(
     SurfaceHandle parent_window,
     SurfaceHandle child_window) {
   GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
@@ -328,56 +328,56 @@
 }
 #endif
 
-void GpuCommandBufferStub::DidSwapBuffersComplete(
+void CommandBufferStub::DidSwapBuffersComplete(
     SwapBuffersCompleteParams params) {
   Send(new GpuCommandBufferMsg_SwapBuffersCompleted(route_id_, params));
 }
 
-const gles2::FeatureInfo* GpuCommandBufferStub::GetFeatureInfo() const {
+const gles2::FeatureInfo* CommandBufferStub::GetFeatureInfo() const {
   return context_group_->feature_info();
 }
 
-const GpuPreferences& GpuCommandBufferStub::GetGpuPreferences() const {
+const GpuPreferences& CommandBufferStub::GetGpuPreferences() const {
   return context_group_->gpu_preferences();
 }
 
-void GpuCommandBufferStub::SetSnapshotRequestedCallback(
+void CommandBufferStub::SetSnapshotRequestedCallback(
     const base::Closure& callback) {
   snapshot_requested_callback_ = callback;
 }
 
-void GpuCommandBufferStub::UpdateVSyncParameters(base::TimeTicks timebase,
-                                                 base::TimeDelta interval) {
+void CommandBufferStub::UpdateVSyncParameters(base::TimeTicks timebase,
+                                              base::TimeDelta interval) {
   Send(new GpuCommandBufferMsg_UpdateVSyncParameters(route_id_, timebase,
                                                      interval));
 }
 
-void GpuCommandBufferStub::BufferPresented(
+void CommandBufferStub::BufferPresented(
     uint64_t swap_id,
     const gfx::PresentationFeedback& feedback) {
   Send(new GpuCommandBufferMsg_BufferPresented(route_id_, swap_id, feedback));
 }
 
-void GpuCommandBufferStub::AddFilter(IPC::MessageFilter* message_filter) {
+void CommandBufferStub::AddFilter(IPC::MessageFilter* message_filter) {
   return channel_->AddFilter(message_filter);
 }
 
-int32_t GpuCommandBufferStub::GetRouteID() const {
+int32_t CommandBufferStub::GetRouteID() const {
   return route_id_;
 }
 
-bool GpuCommandBufferStub::IsScheduled() {
+bool CommandBufferStub::IsScheduled() {
   return (!command_buffer_.get() || command_buffer_->scheduled());
 }
 
-void GpuCommandBufferStub::PollWork() {
+void CommandBufferStub::PollWork() {
   // Post another delayed task if we have not yet reached the time at which
   // we should process delayed work.
   base::TimeTicks current_time = base::TimeTicks::Now();
   DCHECK(!process_delayed_work_time_.is_null());
   if (process_delayed_work_time_ > current_time) {
     channel_->task_runner()->PostDelayedTask(
-        FROM_HERE, base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()),
+        FROM_HERE, base::Bind(&CommandBufferStub::PollWork, AsWeakPtr()),
         process_delayed_work_time_ - current_time);
     return;
   }
@@ -386,8 +386,8 @@
   PerformWork();
 }
 
-void GpuCommandBufferStub::PerformWork() {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::PerformWork");
+void CommandBufferStub::PerformWork() {
+  TRACE_EVENT0("gpu", "CommandBufferStub::PerformWork");
   FastSetActiveURL(active_url_, active_url_hash_, channel_);
   // TODO(sunnyps): Should this use ScopedCrashKey instead?
   base::debug::SetCrashKeyValue(crash_keys::kGPUGLContextIsVirtual,
@@ -424,7 +424,7 @@
       base::TimeDelta::FromMilliseconds(kHandleMoreWorkPeriodBusyMs));
 }
 
-bool GpuCommandBufferStub::HasUnprocessedCommands() {
+bool CommandBufferStub::HasUnprocessedCommands() {
   if (command_buffer_) {
     CommandBuffer::State state = command_buffer_->GetState();
     return command_buffer_->put_offset() != state.get_offset &&
@@ -433,7 +433,7 @@
   return false;
 }
 
-void GpuCommandBufferStub::ScheduleDelayedWork(base::TimeDelta delay) {
+void CommandBufferStub::ScheduleDelayedWork(base::TimeDelta delay) {
   bool has_more_work = decoder_.get() && (decoder_->HasPendingQueries() ||
                                           decoder_->HasMoreIdleWork() ||
                                           decoder_->HasPollingWork());
@@ -469,11 +469,10 @@
 
   process_delayed_work_time_ = current_time + delay;
   channel_->task_runner()->PostDelayedTask(
-      FROM_HERE, base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()),
-      delay);
+      FROM_HERE, base::Bind(&CommandBufferStub::PollWork, AsWeakPtr()), delay);
 }
 
-bool GpuCommandBufferStub::MakeCurrent() {
+bool CommandBufferStub::MakeCurrent() {
   if (decoder_->MakeCurrent())
     return true;
   DLOG(ERROR) << "Context lost because MakeCurrent failed.";
@@ -482,7 +481,7 @@
   return false;
 }
 
-void GpuCommandBufferStub::Destroy() {
+void CommandBufferStub::Destroy() {
   FastSetActiveURL(active_url_, active_url_hash_, channel_);
   // TODO(sunnyps): Should this use ScopedCrashKey instead?
   base::debug::SetCrashKeyValue(crash_keys::kGPUGLContextIsVirtual,
@@ -538,8 +537,8 @@
   command_buffer_.reset();
 }
 
-gpu::ContextResult GpuCommandBufferStub::Initialize(
-    GpuCommandBufferStub* share_command_buffer_stub,
+gpu::ContextResult CommandBufferStub::Initialize(
+    CommandBufferStub* share_command_buffer_stub,
     const GPUCreateCommandBufferConfig& init_params,
     std::unique_ptr<base::SharedMemory> shared_state_shm) {
 #if defined(OS_FUCHSIA)
@@ -548,7 +547,7 @@
   LOG(ERROR) << "ContextResult::kFatalFailure: no fuchsia support";
   return gpu::ContextResult::kFatalFailure;
 #else
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::Initialize");
+  TRACE_EVENT0("gpu", "CommandBufferStub::Initialize");
   FastSetActiveURL(active_url_, active_url_hash_, channel_);
 
   GpuChannelManager* manager = channel_->gpu_channel_manager();
@@ -840,9 +839,9 @@
 #endif  // defined(OS_FUCHSIA)
 }
 
-void GpuCommandBufferStub::OnCreateStreamTexture(uint32_t texture_id,
-                                                 int32_t stream_id,
-                                                 bool* succeeded) {
+void CommandBufferStub::OnCreateStreamTexture(uint32_t texture_id,
+                                              int32_t stream_id,
+                                              bool* succeeded) {
 #if defined(OS_ANDROID)
   *succeeded = StreamTexture::Create(this, texture_id, stream_id);
 #else
@@ -850,14 +849,14 @@
 #endif
 }
 
-void GpuCommandBufferStub::OnSetGetBuffer(int32_t shm_id) {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSetGetBuffer");
+void CommandBufferStub::OnSetGetBuffer(int32_t shm_id) {
+  TRACE_EVENT0("gpu", "CommandBufferStub::OnSetGetBuffer");
   if (command_buffer_)
     command_buffer_->SetGetBuffer(shm_id);
 }
 
-void GpuCommandBufferStub::OnTakeFrontBuffer(const Mailbox& mailbox) {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnTakeFrontBuffer");
+void CommandBufferStub::OnTakeFrontBuffer(const Mailbox& mailbox) {
+  TRACE_EVENT0("gpu", "CommandBufferStub::OnTakeFrontBuffer");
   if (!decoder_) {
     LOG(ERROR) << "Can't take front buffer before initialization.";
     return;
@@ -866,13 +865,13 @@
   decoder_->TakeFrontBuffer(mailbox);
 }
 
-void GpuCommandBufferStub::OnReturnFrontBuffer(const Mailbox& mailbox,
-                                               bool is_lost) {
+void CommandBufferStub::OnReturnFrontBuffer(const Mailbox& mailbox,
+                                            bool is_lost) {
   decoder_->ReturnFrontBuffer(mailbox, is_lost);
 }
 
 CommandBufferServiceClient::CommandBatchProcessedResult
-GpuCommandBufferStub::OnCommandBatchProcessed() {
+CommandBufferStub::OnCommandBatchProcessed() {
   GpuWatchdogThread* watchdog = channel_->gpu_channel_manager()->watchdog();
   if (watchdog)
     watchdog->CheckArmed();
@@ -880,8 +879,8 @@
   return pause ? kPauseExecution : kContinueExecution;
 }
 
-void GpuCommandBufferStub::OnParseError() {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnParseError");
+void CommandBufferStub::OnParseError() {
+  TRACE_EVENT0("gpu", "CommandBufferStub::OnParseError");
   DCHECK(command_buffer_.get());
   CommandBuffer::State state = command_buffer_->GetState();
   IPC::Message* msg = new GpuCommandBufferMsg_Destroyed(
@@ -900,10 +899,10 @@
   CheckContextLost();
 }
 
-void GpuCommandBufferStub::OnWaitForTokenInRange(int32_t start,
-                                                 int32_t end,
-                                                 IPC::Message* reply_message) {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnWaitForTokenInRange");
+void CommandBufferStub::OnWaitForTokenInRange(int32_t start,
+                                              int32_t end,
+                                              IPC::Message* reply_message) {
+  TRACE_EVENT0("gpu", "CommandBufferStub::OnWaitForTokenInRange");
   DCHECK(command_buffer_.get());
   CheckContextLost();
   if (wait_for_token_)
@@ -915,12 +914,11 @@
   CheckCompleteWaits();
 }
 
-void GpuCommandBufferStub::OnWaitForGetOffsetInRange(
-    uint32_t set_get_buffer_count,
-    int32_t start,
-    int32_t end,
-    IPC::Message* reply_message) {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnWaitForGetOffsetInRange");
+void CommandBufferStub::OnWaitForGetOffsetInRange(uint32_t set_get_buffer_count,
+                                                  int32_t start,
+                                                  int32_t end,
+                                                  IPC::Message* reply_message) {
+  TRACE_EVENT0("gpu", "CommandBufferStub::OnWaitForGetOffsetInRange");
   DCHECK(command_buffer_.get());
   CheckContextLost();
   if (wait_for_get_offset_) {
@@ -935,7 +933,7 @@
   CheckCompleteWaits();
 }
 
-void GpuCommandBufferStub::CheckCompleteWaits() {
+void CommandBufferStub::CheckCompleteWaits() {
   bool has_wait = wait_for_token_ || wait_for_get_offset_;
   if (has_wait) {
     CommandBuffer::State state = command_buffer_->GetState();
@@ -968,11 +966,11 @@
   }
 }
 
-void GpuCommandBufferStub::OnAsyncFlush(int32_t put_offset,
-                                        uint32_t flush_id,
-                                        bool snapshot_requested) {
-  TRACE_EVENT1(
-      "gpu", "GpuCommandBufferStub::OnAsyncFlush", "put_offset", put_offset);
+void CommandBufferStub::OnAsyncFlush(int32_t put_offset,
+                                     uint32_t flush_id,
+                                     bool snapshot_requested) {
+  TRACE_EVENT1("gpu", "CommandBufferStub::OnAsyncFlush", "put_offset",
+               put_offset);
   DCHECK(command_buffer_);
 
   // We received this message out-of-order. This should not happen but is here
@@ -998,11 +996,11 @@
 #endif
 }
 
-void GpuCommandBufferStub::OnRegisterTransferBuffer(
+void CommandBufferStub::OnRegisterTransferBuffer(
     int32_t id,
     base::SharedMemoryHandle transfer_buffer,
     uint32_t size) {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnRegisterTransferBuffer");
+  TRACE_EVENT0("gpu", "CommandBufferStub::OnRegisterTransferBuffer");
 
   // Take ownership of the memory and map it into this process.
   // This validates the size.
@@ -1019,41 +1017,40 @@
   }
 }
 
-void GpuCommandBufferStub::OnDestroyTransferBuffer(int32_t id) {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnDestroyTransferBuffer");
+void CommandBufferStub::OnDestroyTransferBuffer(int32_t id) {
+  TRACE_EVENT0("gpu", "CommandBufferStub::OnDestroyTransferBuffer");
 
   if (command_buffer_)
     command_buffer_->DestroyTransferBuffer(id);
 }
 
-void GpuCommandBufferStub::ReportState() {
+void CommandBufferStub::ReportState() {
   command_buffer_->UpdateState();
 }
 
-void GpuCommandBufferStub::OnSignalSyncToken(const SyncToken& sync_token,
-                                             uint32_t id) {
+void CommandBufferStub::OnSignalSyncToken(const SyncToken& sync_token,
+                                          uint32_t id) {
   if (!sync_point_client_state_->WaitNonThreadSafe(
           sync_token, channel_->task_runner(),
-          base::Bind(&GpuCommandBufferStub::OnSignalAck, this->AsWeakPtr(),
-                     id))) {
+          base::Bind(&CommandBufferStub::OnSignalAck, this->AsWeakPtr(), id))) {
     OnSignalAck(id);
   }
 }
 
-void GpuCommandBufferStub::OnSignalAck(uint32_t id) {
+void CommandBufferStub::OnSignalAck(uint32_t id) {
   CommandBuffer::State state = command_buffer_->GetState();
   ReportState();
   Send(new GpuCommandBufferMsg_SignalAck(route_id_, id, state));
 }
 
-void GpuCommandBufferStub::OnSignalQuery(uint32_t query_id, uint32_t id) {
+void CommandBufferStub::OnSignalQuery(uint32_t query_id, uint32_t id) {
   if (decoder_) {
     gles2::QueryManager* query_manager = decoder_->GetQueryManager();
     if (query_manager) {
       gles2::QueryManager::Query* query = query_manager->GetQuery(query_id);
       if (query) {
-        query->AddCallback(base::Bind(&GpuCommandBufferStub::OnSignalAck,
-                                      this->AsWeakPtr(), id));
+        query->AddCallback(
+            base::Bind(&CommandBufferStub::OnSignalAck, this->AsWeakPtr(), id));
         return;
       }
     }
@@ -1062,7 +1059,7 @@
   OnSignalAck(id);
 }
 
-void GpuCommandBufferStub::OnFenceSyncRelease(uint64_t release) {
+void CommandBufferStub::OnFenceSyncRelease(uint64_t release) {
   SyncToken sync_token(CommandBufferNamespace::GPU_IO, 0, command_buffer_id_,
                        release);
   gles2::MailboxManager* mailbox_manager = context_group_->mailbox_manager();
@@ -1073,7 +1070,7 @@
   sync_point_client_state_->ReleaseFenceSync(release);
 }
 
-void GpuCommandBufferStub::OnDescheduleUntilFinished() {
+void CommandBufferStub::OnDescheduleUntilFinished() {
   DCHECK(command_buffer_->scheduled());
   DCHECK(decoder_->HasPollingWork());
 
@@ -1081,22 +1078,22 @@
   channel_->OnCommandBufferDescheduled(this);
 }
 
-void GpuCommandBufferStub::OnRescheduleAfterFinished() {
+void CommandBufferStub::OnRescheduleAfterFinished() {
   DCHECK(!command_buffer_->scheduled());
 
   command_buffer_->SetScheduled(true);
   channel_->OnCommandBufferScheduled(this);
 }
 
-bool GpuCommandBufferStub::OnWaitSyncToken(const SyncToken& sync_token) {
+bool CommandBufferStub::OnWaitSyncToken(const SyncToken& sync_token) {
   DCHECK(!waiting_for_sync_point_);
   DCHECK(command_buffer_->scheduled());
-  TRACE_EVENT_ASYNC_BEGIN1("gpu", "WaitSyncToken", this, "GpuCommandBufferStub",
+  TRACE_EVENT_ASYNC_BEGIN1("gpu", "WaitSyncToken", this, "CommandBufferStub",
                            this);
 
   waiting_for_sync_point_ = sync_point_client_state_->WaitNonThreadSafe(
       sync_token, channel_->task_runner(),
-      base::Bind(&GpuCommandBufferStub::OnWaitSyncTokenCompleted, AsWeakPtr(),
+      base::Bind(&CommandBufferStub::OnWaitSyncTokenCompleted, AsWeakPtr(),
                  sync_token));
 
   if (waiting_for_sync_point_) {
@@ -1111,11 +1108,10 @@
   return false;
 }
 
-void GpuCommandBufferStub::OnWaitSyncTokenCompleted(
-    const SyncToken& sync_token) {
+void CommandBufferStub::OnWaitSyncTokenCompleted(const SyncToken& sync_token) {
   DCHECK(waiting_for_sync_point_);
   TRACE_EVENT_ASYNC_END1("gpu", "WaitSyncTokenCompleted", this,
-                         "GpuCommandBufferStub", this);
+                         "CommandBufferStub", this);
   // Don't call PullTextureUpdates here because we can't MakeCurrent if we're
   // executing commands on another context. The WaitSyncToken command will run
   // again and call PullTextureUpdates once this command buffer gets scheduled.
@@ -1124,9 +1120,9 @@
   channel_->OnCommandBufferScheduled(this);
 }
 
-void GpuCommandBufferStub::OnCreateImage(
+void CommandBufferStub::OnCreateImage(
     const GpuCommandBufferMsg_CreateImage_Params& params) {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnCreateImage");
+  TRACE_EVENT0("gpu", "CommandBufferStub::OnCreateImage");
   const int32_t id = params.id;
   const gfx::GpuMemoryBufferHandle& handle = params.gpu_memory_buffer;
   const gfx::Size& size = params.size;
@@ -1168,8 +1164,8 @@
     sync_point_client_state_->ReleaseFenceSync(image_release_count);
 }
 
-void GpuCommandBufferStub::OnDestroyImage(int32_t id) {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnDestroyImage");
+void CommandBufferStub::OnDestroyImage(int32_t id) {
+  TRACE_EVENT0("gpu", "CommandBufferStub::OnDestroyImage");
 
   gles2::ImageManager* image_manager = channel_->image_manager();
   DCHECK(image_manager);
@@ -1181,8 +1177,8 @@
   image_manager->RemoveImage(id);
 }
 
-void GpuCommandBufferStub::OnConsoleMessage(int32_t id,
-                                            const std::string& message) {
+void CommandBufferStub::OnConsoleMessage(int32_t id,
+                                         const std::string& message) {
   GPUCommandBufferConsoleMessage console_message;
   console_message.id = id;
   console_message.message = message;
@@ -1192,26 +1188,25 @@
   Send(msg);
 }
 
-void GpuCommandBufferStub::CacheShader(const std::string& key,
-                                       const std::string& shader) {
+void CommandBufferStub::CacheShader(const std::string& key,
+                                    const std::string& shader) {
   channel_->CacheShader(key, shader);
 }
 
-void GpuCommandBufferStub::AddDestructionObserver(
-    DestructionObserver* observer) {
+void CommandBufferStub::AddDestructionObserver(DestructionObserver* observer) {
   destruction_observers_.AddObserver(observer);
 }
 
-void GpuCommandBufferStub::RemoveDestructionObserver(
+void CommandBufferStub::RemoveDestructionObserver(
     DestructionObserver* observer) {
   destruction_observers_.RemoveObserver(observer);
 }
 
-gles2::MemoryTracker* GpuCommandBufferStub::GetMemoryTracker() const {
+gles2::MemoryTracker* CommandBufferStub::GetMemoryTracker() const {
   return context_group_->memory_tracker();
 }
 
-bool GpuCommandBufferStub::CheckContextLost() {
+bool CommandBufferStub::CheckContextLost() {
   DCHECK(command_buffer_);
   CommandBuffer::State state = command_buffer_->GetState();
   bool was_lost = state.error == error::kLostContext;
@@ -1239,7 +1234,7 @@
   return was_lost;
 }
 
-void GpuCommandBufferStub::MarkContextLost() {
+void CommandBufferStub::MarkContextLost() {
   if (!command_buffer_ ||
       command_buffer_->GetState().error == error::kLostContext)
     return;
diff --git a/gpu/ipc/service/gpu_command_buffer_stub.h b/gpu/ipc/service/command_buffer_stub.h
similarity index 90%
rename from gpu/ipc/service/gpu_command_buffer_stub.h
rename to gpu/ipc/service/command_buffer_stub.h
index 9dfb89ac..4dd9f1e 100644
--- a/gpu/ipc/service/gpu_command_buffer_stub.h
+++ b/gpu/ipc/service/command_buffer_stub.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 GPU_IPC_SERVICE_GPU_COMMAND_BUFFER_STUB_H_
-#define GPU_IPC_SERVICE_GPU_COMMAND_BUFFER_STUB_H_
+#ifndef GPU_IPC_SERVICE_COMMAND_BUFFER_STUB_H_
+#define GPU_IPC_SERVICE_COMMAND_BUFFER_STUB_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -16,6 +16,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "gpu/command_buffer/common/command_buffer_id.h"
 #include "gpu/command_buffer/common/constants.h"
 #include "gpu/command_buffer/common/gpu_memory_allocation.h"
@@ -50,13 +51,13 @@
 class GpuChannel;
 class SyncPointClientState;
 
-class GPU_EXPORT GpuCommandBufferStub
+class GPU_EXPORT CommandBufferStub
     : public IPC::Listener,
       public IPC::Sender,
       public CommandBufferServiceClient,
       public gles2::GLES2DecoderClient,
       public ImageTransportSurfaceDelegate,
-      public base::SupportsWeakPtr<GpuCommandBufferStub> {
+      public base::SupportsWeakPtr<CommandBufferStub> {
  public:
   class DestructionObserver {
    public:
@@ -67,20 +68,20 @@
     virtual ~DestructionObserver() {}
   };
 
-  GpuCommandBufferStub(GpuChannel* channel,
-                       const GPUCreateCommandBufferConfig& init_params,
-                       CommandBufferId command_buffer_id,
-                       SequenceId sequence_id,
-                       int32_t stream_id,
-                       int32_t route_id);
+  CommandBufferStub(GpuChannel* channel,
+                    const GPUCreateCommandBufferConfig& init_params,
+                    CommandBufferId command_buffer_id,
+                    SequenceId sequence_id,
+                    int32_t stream_id,
+                    int32_t route_id);
 
-  ~GpuCommandBufferStub() override;
+  ~CommandBufferStub() override;
 
   // This must leave the GL context associated with the newly-created
-  // GpuCommandBufferStub current, so the GpuChannel can initialize
+  // CommandBufferStub current, so the GpuChannel can initialize
   // the gpu::Capabilities.
   gpu::ContextResult Initialize(
-      GpuCommandBufferStub* share_group,
+      CommandBufferStub* share_group,
       const GPUCreateCommandBufferConfig& init_params,
       std::unique_ptr<base::SharedMemory> shared_state_shm);
 
@@ -207,8 +208,8 @@
                                        const GpuFeatureInfo& gpu_feature_info);
 
   // The lifetime of objects of this class is managed by a GpuChannel. The
-  // GpuChannels destroy all the GpuCommandBufferStubs that they own when they
-  // are destroyed. So a raw pointer is safe.
+  // GpuChannels destroy all the CommandBufferStubs that they own when
+  // they are destroyed. So a raw pointer is safe.
   GpuChannel* const channel_;
 
   // The group of contexts that share namespaces with this context.
@@ -246,9 +247,9 @@
   std::unique_ptr<WaitForCommandState> wait_for_get_offset_;
   uint32_t wait_set_get_buffer_count_;
 
-  DISALLOW_COPY_AND_ASSIGN(GpuCommandBufferStub);
+  DISALLOW_COPY_AND_ASSIGN(CommandBufferStub);
 };
 
 }  // namespace gpu
 
-#endif  // GPU_IPC_SERVICE_GPU_COMMAND_BUFFER_STUB_H_
+#endif  // GPU_IPC_SERVICE_COMMAND_BUFFER_STUB_H_
diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc
index fbfcbf59..e422107d 100644
--- a/gpu/ipc/service/gpu_channel.cc
+++ b/gpu/ipc/service/gpu_channel.cc
@@ -421,15 +421,15 @@
   return channel_->Send(message);
 }
 
-void GpuChannel::OnCommandBufferScheduled(GpuCommandBufferStub* stub) {
+void GpuChannel::OnCommandBufferScheduled(CommandBufferStub* stub) {
   scheduler_->EnableSequence(stub->sequence_id());
 }
 
-void GpuChannel::OnCommandBufferDescheduled(GpuCommandBufferStub* stub) {
+void GpuChannel::OnCommandBufferDescheduled(CommandBufferStub* stub) {
   scheduler_->DisableSequence(stub->sequence_id());
 }
 
-GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32_t route_id) {
+CommandBufferStub* GpuChannel::LookupCommandBuffer(int32_t route_id) {
   auto it = stubs_.find(route_id);
   if (it == stubs_.end())
     return nullptr;
@@ -486,7 +486,7 @@
 
 void GpuChannel::HandleMessage(const IPC::Message& msg) {
   int32_t routing_id = msg.routing_id();
-  GpuCommandBufferStub* stub = LookupCommandBuffer(routing_id);
+  CommandBufferStub* stub = LookupCommandBuffer(routing_id);
 
   DCHECK(!stub || stub->IsScheduled());
 
@@ -536,9 +536,9 @@
 }
 
 #if defined(OS_ANDROID)
-const GpuCommandBufferStub* GpuChannel::GetOneStub() const {
+const CommandBufferStub* GpuChannel::GetOneStub() const {
   for (const auto& kv : stubs_) {
-    const GpuCommandBufferStub* stub = kv.second.get();
+    const CommandBufferStub* stub = kv.second.get();
     if (stub->decoder() && !stub->decoder()->WasContextLost())
       return stub;
   }
@@ -570,7 +570,7 @@
   }
 
   int32_t share_group_id = init_params.share_group_id;
-  GpuCommandBufferStub* share_group = LookupCommandBuffer(share_group_id);
+  CommandBufferStub* share_group = LookupCommandBuffer(share_group_id);
 
   if (!share_group && share_group_id != MSG_ROUTING_NONE) {
     LOG(ERROR) << "ContextResult::kFatalFailure: invalid share group id";
@@ -621,13 +621,13 @@
            << (gpu_channel_manager_->gpu_preferences().enable_raster_decoder &&
                init_params.attribs.enable_oop_rasterization);
 
-  auto stub = std::make_unique<GpuCommandBufferStub>(
+  auto stub = std::make_unique<CommandBufferStub>(
       this, init_params, command_buffer_id, sequence_id, stream_id, route_id);
   auto stub_result =
       stub->Initialize(share_group, init_params, std::move(shared_state_shm));
   if (stub_result != gpu::ContextResult::kSuccess) {
     DLOG(ERROR) << "GpuChannel::CreateCommandBuffer(): failed to initialize "
-                   "GpuCommandBufferStub";
+                   "CommandBufferStub";
     *result = stub_result;
     return;
   }
@@ -646,7 +646,7 @@
   TRACE_EVENT1("gpu", "GpuChannel::OnDestroyCommandBuffer", "route_id",
                route_id);
 
-  std::unique_ptr<GpuCommandBufferStub> stub;
+  std::unique_ptr<CommandBufferStub> stub;
   auto it = stubs_.find(route_id);
   if (it != stubs_.end()) {
     stub = std::move(it->second);
diff --git a/gpu/ipc/service/gpu_channel.h b/gpu/ipc/service/gpu_channel.h
index 78fb770..9e27b4f 100644
--- a/gpu/ipc/service/gpu_channel.h
+++ b/gpu/ipc/service/gpu_channel.h
@@ -22,7 +22,7 @@
 #include "gpu/command_buffer/common/context_result.h"
 #include "gpu/command_buffer/service/sync_point_manager.h"
 #include "gpu/gpu_export.h"
-#include "gpu/ipc/service/gpu_command_buffer_stub.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
 #include "gpu/ipc/service/gpu_memory_manager.h"
 #include "ipc/ipc_sender.h"
 #include "ipc/ipc_sync_channel.h"
@@ -134,12 +134,12 @@
   void AddFilter(IPC::MessageFilter* filter) override;
   void RemoveFilter(IPC::MessageFilter* filter) override;
 
-  void OnCommandBufferScheduled(GpuCommandBufferStub* stub);
-  void OnCommandBufferDescheduled(GpuCommandBufferStub* stub);
+  void OnCommandBufferScheduled(CommandBufferStub* stub);
+  void OnCommandBufferDescheduled(CommandBufferStub* stub);
 
   gl::GLShareGroup* share_group() const { return share_group_.get(); }
 
-  GpuCommandBufferStub* LookupCommandBuffer(int32_t route_id);
+  CommandBufferStub* LookupCommandBuffer(int32_t route_id);
 
   bool HasActiveWebGLContext() const;
   void LoseAllContexts();
@@ -175,7 +175,7 @@
   void HandleMessageForTesting(const IPC::Message& msg);
 
 #if defined(OS_ANDROID)
-  const GpuCommandBufferStub* GetOneStub() const;
+  const CommandBufferStub* GetOneStub() const;
 #endif
 
  private:
@@ -199,7 +199,7 @@
   scoped_refptr<GpuChannelMessageFilter> filter_;
 
   // Map of routing id to command buffer stub.
-  base::flat_map<int32_t, std::unique_ptr<GpuCommandBufferStub>> stubs_;
+  base::flat_map<int32_t, std::unique_ptr<CommandBufferStub>> stubs_;
 
   // Map of stream id to scheduler sequence id.
   base::flat_map<int32_t, SequenceId> stream_sequences_;
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc
index 34aff72..d7306d2 100644
--- a/gpu/ipc/service/gpu_channel_manager.cc
+++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -249,7 +249,7 @@
 }
 
 void GpuChannelManager::DoWakeUpGpu() {
-  const GpuCommandBufferStub* stub = nullptr;
+  const CommandBufferStub* stub = nullptr;
   for (const auto& kv : gpu_channels_) {
     const GpuChannel* channel = kv.second.get();
     stub = channel->GetOneStub();
diff --git a/gpu/ipc/service/gpu_channel_manager_unittest.cc b/gpu/ipc/service/gpu_channel_manager_unittest.cc
index 67c1e46..d7ef95c 100644
--- a/gpu/ipc/service/gpu_channel_manager_unittest.cc
+++ b/gpu/ipc/service/gpu_channel_manager_unittest.cc
@@ -45,7 +45,7 @@
                                &result, &capabilities));
     EXPECT_EQ(result, gpu::ContextResult::kSuccess);
 
-    GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
+    CommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
     EXPECT_TRUE(stub);
 
     channel_manager()->OnApplicationBackgroundedForTesting();
diff --git a/gpu/ipc/service/gpu_channel_unittest.cc b/gpu/ipc/service/gpu_channel_unittest.cc
index c73b8298..36d4325 100644
--- a/gpu/ipc/service/gpu_channel_unittest.cc
+++ b/gpu/ipc/service/gpu_channel_unittest.cc
@@ -42,7 +42,7 @@
                              &capabilities));
   EXPECT_EQ(result, gpu::ContextResult::kSuccess);
 
-  GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
+  CommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
   ASSERT_TRUE(stub);
 }
 
@@ -70,7 +70,7 @@
                              &capabilities));
   EXPECT_EQ(result, gpu::ContextResult::kFatalFailure);
 
-  GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
+  CommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
   EXPECT_FALSE(stub);
 }
 
@@ -94,7 +94,7 @@
                              &capabilities));
   EXPECT_EQ(result, gpu::ContextResult::kSuccess);
 
-  GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
+  CommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
   EXPECT_TRUE(stub);
 }
 
@@ -120,7 +120,7 @@
                              &capabilities));
   EXPECT_EQ(result, gpu::ContextResult::kSuccess);
 
-  GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId1);
+  CommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId1);
   EXPECT_TRUE(stub);
 
   // Create second context in same share group but different stream.
diff --git a/gpu/ipc/service/image_transport_surface_overlay_mac.h b/gpu/ipc/service/image_transport_surface_overlay_mac.h
index 1150ad4..3838521 100644
--- a/gpu/ipc/service/image_transport_surface_overlay_mac.h
+++ b/gpu/ipc/service/image_transport_surface_overlay_mac.h
@@ -11,7 +11,7 @@
 
 #import "base/mac/scoped_nsobject.h"
 #include "base/timer/timer.h"
-#include "gpu/ipc/service/gpu_command_buffer_stub.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
 #include "gpu/ipc/service/image_transport_surface.h"
 #include "ui/base/cocoa/remote_layer_api.h"
 #include "ui/gl/gl_surface.h"
diff --git a/gpu/ipc/service/stream_texture_android.cc b/gpu/ipc/service/stream_texture_android.cc
index 7633286..8b905d1 100644
--- a/gpu/ipc/service/stream_texture_android.cc
+++ b/gpu/ipc/service/stream_texture_android.cc
@@ -26,7 +26,7 @@
 using gles2::TextureRef;
 
 // static
-bool StreamTexture::Create(GpuCommandBufferStub* owner_stub,
+bool StreamTexture::Create(CommandBufferStub* owner_stub,
                            uint32_t client_texture_id,
                            int stream_id) {
   GLES2Decoder* decoder = owner_stub->decoder();
@@ -55,7 +55,7 @@
   return false;
 }
 
-StreamTexture::StreamTexture(GpuCommandBufferStub* owner_stub,
+StreamTexture::StreamTexture(CommandBufferStub* owner_stub,
                              int32_t route_id,
                              uint32_t texture_id)
     : surface_texture_(gl::SurfaceTexture::Create(texture_id)),
diff --git a/gpu/ipc/service/stream_texture_android.h b/gpu/ipc/service/stream_texture_android.h
index e94537e..728e8a86 100644
--- a/gpu/ipc/service/stream_texture_android.h
+++ b/gpu/ipc/service/stream_texture_android.h
@@ -13,7 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/unguessable_token.h"
 #include "gpu/command_buffer/service/gl_stream_texture_image.h"
-#include "gpu/ipc/service/gpu_command_buffer_stub.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
 #include "ipc/ipc_listener.h"
 #include "ui/gl/android/surface_texture.h"
 #include "ui/gl/gl_image.h"
@@ -30,14 +30,14 @@
 
 class StreamTexture : public gpu::gles2::GLStreamTextureImage,
                       public IPC::Listener,
-                      public GpuCommandBufferStub::DestructionObserver {
+                      public CommandBufferStub::DestructionObserver {
  public:
-  static bool Create(GpuCommandBufferStub* owner_stub,
+  static bool Create(CommandBufferStub* owner_stub,
                      uint32_t client_texture_id,
                      int stream_id);
 
  private:
-  StreamTexture(GpuCommandBufferStub* owner_stub,
+  StreamTexture(CommandBufferStub* owner_stub,
                 int32_t route_id,
                 uint32_t texture_id);
   ~StreamTexture() override;
@@ -70,7 +70,7 @@
                            int display_width,
                            int display_height) override {}
 
-  // GpuCommandBufferStub::DestructionObserver implementation.
+  // CommandBufferStub::DestructionObserver implementation.
   void OnWillDestroyStub() override;
 
   std::unique_ptr<ui::ScopedMakeCurrent> MakeStubCurrent();
@@ -99,7 +99,7 @@
   // Whether a new frame is available that we should update to.
   bool has_pending_frame_;
 
-  GpuCommandBufferStub* owner_stub_;
+  CommandBufferStub* owner_stub_;
   int32_t route_id_;
   bool has_listener_;
   uint32_t texture_id_;
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_popup_view_controller.mm b/ios/chrome/browser/ui/omnibox/omnibox_popup_view_controller.mm
index 84986c56..4021fbe 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_popup_view_controller.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_popup_view_controller.mm
@@ -231,8 +231,10 @@
   [detailTextLabel setTextAlignment:_alignment];
 
   // The width must be positive for CGContextRef to be valid.
-  CGFloat labelWidth =
-      MAX(40, floorf(row.frame.size.width) - kTextCellLeadingPadding);
+  UIEdgeInsets safeAreaInsets = SafeAreaInsetsForView(row);
+  CGFloat labelWidth = MAX(
+      40, floorf(UIEdgeInsetsInsetRect(row.bounds, safeAreaInsets).size.width) -
+              kTextCellLeadingPadding);
   CGFloat labelHeight =
       match.hasAnswer ? kAnswerLabelHeight : kTextDetailLabelHeight;
   CGFloat answerImagePadding = kAnswerImageWidth + kAnswerImageRightPadding;
diff --git a/media/audio/audio_device_description.cc b/media/audio/audio_device_description.cc
index 613c9f4d..dafe34b 100644
--- a/media/audio/audio_device_description.cc
+++ b/media/audio/audio_device_description.cc
@@ -2,8 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/logging.h"
 #include "media/audio/audio_device_description.h"
+
+#include <utility>
+
+#include "base/logging.h"
 #include "media/base/localized_strings.h"
 
 namespace media {
@@ -20,6 +23,12 @@
 }
 
 // static
+bool AudioDeviceDescription::IsCommunicationsDevice(
+    const std::string& device_id) {
+  return device_id == AudioDeviceDescription::kCommunicationsDeviceId;
+}
+
+// static
 bool AudioDeviceDescription::IsLoopbackDevice(const std::string& device_id) {
   return device_id.compare(kLoopbackInputDeviceId) == 0 ||
          device_id.compare(kLoopbackWithMuteDeviceId) == 0;
@@ -52,9 +61,29 @@
 #endif
 }
 
-AudioDeviceDescription::AudioDeviceDescription(const std::string& device_name,
-                                               const std::string& unique_id,
-                                               const std::string& group_id)
-    : device_name(device_name), unique_id(unique_id), group_id(group_id) {}
+// static
+std::string AudioDeviceDescription::GetDefaultDeviceName(
+    const std::string& real_device_name) {
+  DCHECK(!real_device_name.empty());
+  // TODO(guidou): Put the names together in a localized manner.
+  // http://crbug.com/788767
+  return GetDefaultDeviceName() + " - " + real_device_name;
+}
+
+// static
+std::string AudioDeviceDescription::GetCommunicationsDeviceName(
+    const std::string& real_device_name) {
+  DCHECK(!real_device_name.empty());
+  // TODO(guidou): Put the names together in a localized manner.
+  // http://crbug.com/788767
+  return GetCommunicationsDeviceName() + " - " + real_device_name;
+}
+
+AudioDeviceDescription::AudioDeviceDescription(std::string device_name,
+                                               std::string unique_id,
+                                               std::string group_id)
+    : device_name(std::move(device_name)),
+      unique_id(std::move(unique_id)),
+      group_id(std::move(group_id)) {}
 
 }  // namespace media
diff --git a/media/audio/audio_device_description.h b/media/audio/audio_device_description.h
index b9780ba..1a383f4 100644
--- a/media/audio/audio_device_description.h
+++ b/media/audio/audio_device_description.h
@@ -38,6 +38,9 @@
   // Returns true if |device_id| represents the default device.
   static bool IsDefaultDevice(const std::string& device_id);
 
+  // Returns true if |device_id| represents the communications device.
+  static bool IsCommunicationsDevice(const std::string& device_id);
+
   // Returns true if |device_id| represents a loopback audio capture device.
   static bool IsLoopbackDevice(const std::string& device_id);
 
@@ -52,14 +55,23 @@
   // Returns the localized name of the generic "default" device.
   static std::string GetDefaultDeviceName();
 
+  // Returns a localized version of name of the generic "default" device that
+  // includes the given |real_device_name|.
+  static std::string GetDefaultDeviceName(const std::string& real_device_name);
+
   // Returns the localized name of the generic default communications device.
   // This device is not supported on all platforms.
   static std::string GetCommunicationsDeviceName();
 
+  // Returns a localized version of name of the generic communications device
+  // that includes the given |real_device_name|.
+  static std::string GetCommunicationsDeviceName(
+      const std::string& real_device_name);
+
   AudioDeviceDescription(const AudioDeviceDescription& other) = default;
-  AudioDeviceDescription(const std::string& device_name,
-                         const std::string& unique_id,
-                         const std::string& group_id);
+  AudioDeviceDescription(std::string device_name,
+                         std::string unique_id,
+                         std::string group_id);
 
   ~AudioDeviceDescription() = default;
 
diff --git a/media/audio/audio_device_info_accessor_for_tests.cc b/media/audio/audio_device_info_accessor_for_tests.cc
index e77771c..6c0a9d6ed 100644
--- a/media/audio/audio_device_info_accessor_for_tests.cc
+++ b/media/audio/audio_device_info_accessor_for_tests.cc
@@ -61,4 +61,24 @@
   return audio_manager_->GetAssociatedOutputDeviceID(input_device_id);
 }
 
+std::string AudioDeviceInfoAccessorForTests::GetDefaultInputDeviceID() {
+  DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
+  return audio_manager_->GetDefaultInputDeviceID();
+}
+
+std::string AudioDeviceInfoAccessorForTests::GetDefaultOutputDeviceID() {
+  DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
+  return audio_manager_->GetDefaultOutputDeviceID();
+}
+
+std::string AudioDeviceInfoAccessorForTests::GetCommunicationsInputDeviceID() {
+  DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
+  return audio_manager_->GetCommunicationsInputDeviceID();
+}
+
+std::string AudioDeviceInfoAccessorForTests::GetCommunicationsOutputDeviceID() {
+  DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
+  return audio_manager_->GetCommunicationsOutputDeviceID();
+}
+
 }  // namespace media
diff --git a/media/audio/audio_device_info_accessor_for_tests.h b/media/audio/audio_device_info_accessor_for_tests.h
index 65f0cab..79bedf7 100644
--- a/media/audio/audio_device_info_accessor_for_tests.h
+++ b/media/audio/audio_device_info_accessor_for_tests.h
@@ -38,6 +38,14 @@
 
   std::string GetAssociatedOutputDeviceID(const std::string& input_device_id);
 
+  std::string GetDefaultInputDeviceID();
+
+  std::string GetDefaultOutputDeviceID();
+
+  std::string GetCommunicationsInputDeviceID();
+
+  std::string GetCommunicationsOutputDeviceID();
+
  private:
   AudioManager* const audio_manager_;
 
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h
index 40c22b8..135f83ad 100644
--- a/media/audio/audio_manager.h
+++ b/media/audio/audio_manager.h
@@ -252,6 +252,15 @@
   virtual std::string GetAssociatedOutputDeviceID(
       const std::string& input_device_id) = 0;
 
+  // These functions return the ID of the default/communications audio
+  // input/output devices respectively.
+  // Implementations that do not support this functionality should return an
+  // empty string.
+  virtual std::string GetDefaultInputDeviceID() = 0;
+  virtual std::string GetDefaultOutputDeviceID() = 0;
+  virtual std::string GetCommunicationsInputDeviceID() = 0;
+  virtual std::string GetCommunicationsOutputDeviceID() = 0;
+
  private:
   friend class AudioSystemHelper;
 
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index c00f901..4d57573 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -124,24 +124,68 @@
 void AudioManagerBase::GetAudioInputDeviceDescriptions(
     AudioDeviceDescriptions* device_descriptions) {
   CHECK(GetTaskRunner()->BelongsToCurrentThread());
-  AudioDeviceNames device_names;
-  GetAudioInputDeviceNames(&device_names);
-
-  for (const media::AudioDeviceName& name : device_names) {
-    device_descriptions->emplace_back(name.device_name, name.unique_id,
-                                      GetGroupIDInput(name.unique_id));
-  }
+  GetAudioDeviceDescriptions(device_descriptions,
+                             &AudioManagerBase::GetAudioInputDeviceNames,
+                             &AudioManagerBase::GetDefaultInputDeviceID,
+                             &AudioManagerBase::GetCommunicationsInputDeviceID,
+                             &AudioManagerBase::GetGroupIDInput);
 }
 
 void AudioManagerBase::GetAudioOutputDeviceDescriptions(
     AudioDeviceDescriptions* device_descriptions) {
   CHECK(GetTaskRunner()->BelongsToCurrentThread());
-  AudioDeviceNames device_names;
-  GetAudioOutputDeviceNames(&device_names);
+  GetAudioDeviceDescriptions(device_descriptions,
+                             &AudioManagerBase::GetAudioOutputDeviceNames,
+                             &AudioManagerBase::GetDefaultOutputDeviceID,
+                             &AudioManagerBase::GetCommunicationsOutputDeviceID,
+                             &AudioManagerBase::GetGroupIDOutput);
+}
 
-  for (const media::AudioDeviceName& name : device_names) {
-    device_descriptions->emplace_back(name.device_name, name.unique_id,
-                                      GetGroupIDOutput(name.unique_id));
+void AudioManagerBase::GetAudioDeviceDescriptions(
+    AudioDeviceDescriptions* device_descriptions,
+    void (AudioManagerBase::*get_device_names)(AudioDeviceNames*),
+    std::string (AudioManagerBase::*get_default_device_id)(),
+    std::string (AudioManagerBase::*get_communications_device_id)(),
+    std::string (AudioManagerBase::*get_group_id)(const std::string&)) {
+  CHECK(GetTaskRunner()->BelongsToCurrentThread());
+  AudioDeviceNames device_names;
+  (this->*get_device_names)(&device_names);
+  std::string real_default_device_id = (this->*get_default_device_id)();
+  std::string real_communications_device_id =
+      (this->*get_communications_device_id)();
+  std::string real_default_name;
+  std::string real_communications_name;
+
+  // Find the names for the real devices that are mapped to the default and
+  // communications devices.
+  for (const auto& name : device_names) {
+    if (name.unique_id == real_default_device_id)
+      real_default_name = name.device_name;
+    else if (name.unique_id == real_communications_device_id)
+      real_communications_name = name.device_name;
+  }
+
+  for (auto& name : device_names) {
+    // The |device_name| field as returned by get_device_names() contains a
+    // a generic string such as "Default" or "Communications" for the default
+    // and communications devices. If the names of the real devices mapped to
+    // the default or communications devices were found, append the name of
+    // the real devices to the corresponding entries.
+    // It is possible that the real names were not found if a new device was
+    // plugged in and designated as default/communications device after
+    // get_device_names() returns and before get_default_device_id() or
+    // get_communications_device_id() is called.
+    std::string device_name = std::move(name.device_name);
+    if (AudioDeviceDescription::IsDefaultDevice(name.unique_id) &&
+        !real_default_name.empty()) {
+      device_name += " - " + real_default_name;
+    } else if (AudioDeviceDescription::IsCommunicationsDevice(name.unique_id) &&
+               !real_communications_name.empty()) {
+      device_name += " - " + real_communications_name;
+    }
+    std::string group_id = (this->*get_group_id)(name.unique_id);
+    device_descriptions->emplace_back(
+        std::move(device_name), std::move(name.unique_id), std::move(group_id));
   }
 }
 
@@ -456,7 +500,7 @@
 
 std::string AudioManagerBase::GetAssociatedOutputDeviceID(
     const std::string& input_device_id) {
-  return "";
+  return std::string();
 }
 
 std::string AudioManagerBase::GetGroupIDOutput(
@@ -481,8 +525,20 @@
   return GetGroupIDOutput(output_device_id);
 }
 
+std::string AudioManagerBase::GetDefaultInputDeviceID() {
+  return std::string();
+}
+
 std::string AudioManagerBase::GetDefaultOutputDeviceID() {
-  return "";
+  return std::string();
+}
+
+std::string AudioManagerBase::GetCommunicationsInputDeviceID() {
+  return std::string();
+}
+
+std::string AudioManagerBase::GetCommunicationsOutputDeviceID() {
+  return std::string();
 }
 
 // static
diff --git a/media/audio/audio_manager_base.h b/media/audio/audio_manager_base.h
index 98d4f35..5ead83e3 100644
--- a/media/audio/audio_manager_base.h
+++ b/media/audio/audio_manager_base.h
@@ -151,9 +151,10 @@
   // which must initially be empty.
   virtual void GetAudioOutputDeviceNames(AudioDeviceNames* device_names);
 
-  // Returns the ID of the default audio output device.
-  // Implementations that don't yet support this should return an empty string.
-  virtual std::string GetDefaultOutputDeviceID();
+  std::string GetDefaultInputDeviceID() override;
+  std::string GetDefaultOutputDeviceID() override;
+  std::string GetCommunicationsInputDeviceID() override;
+  std::string GetCommunicationsOutputDeviceID() override;
 
   virtual std::unique_ptr<AudioDebugRecordingManager>
   CreateAudioDebugRecordingManager(
@@ -178,6 +179,13 @@
   // AudioManager:
   void InitializeDebugRecording() final;
 
+  void GetAudioDeviceDescriptions(
+      AudioDeviceDescriptions* descriptions,
+      void (AudioManagerBase::*get_device_names)(AudioDeviceNames*),
+      std::string (AudioManagerBase::*get_default_device_id)(),
+      std::string (AudioManagerBase::*get_communications_device_id)(),
+      std::string (AudioManagerBase::*get_group_id)(const std::string&));
+
   // Max number of open output streams, modified by
   // SetMaxOutputStreamsAllowed().
   int max_num_output_streams_;
diff --git a/media/audio/audio_manager_unittest.cc b/media/audio/audio_manager_unittest.cc
index 4cbd427..ee01d46a 100644
--- a/media/audio/audio_manager_unittest.cc
+++ b/media/audio/audio_manager_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/test_message_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -180,6 +181,36 @@
                               0);
 #endif  // defined(USE_CRAS)
 
+const char kRealDefaultInputDeviceID[] = "input3";
+const char kRealDefaultOutputDeviceID[] = "output4";
+const char kRealCommunicationsInputDeviceID[] = "input2";
+const char kRealCommunicationsOutputDeviceID[] = "output2";
+
+void CheckDescriptionLabels(const AudioDeviceDescriptions& descriptions,
+                            const std::string& real_default_id,
+                            const std::string& real_communications_id) {
+  std::string real_default_label;
+  std::string real_communications_label;
+  for (const auto& description : descriptions) {
+    if (description.unique_id == real_default_id)
+      real_default_label = description.device_name;
+    else if (description.unique_id == real_communications_id)
+      real_communications_label = description.device_name;
+  }
+
+  for (const auto& description : descriptions) {
+    if (AudioDeviceDescription::IsDefaultDevice(description.unique_id)) {
+      EXPECT_TRUE(base::EndsWith(description.device_name, real_default_label,
+                                 base::CompareCase::SENSITIVE));
+    } else if (description.unique_id ==
+               AudioDeviceDescription::kCommunicationsDeviceId) {
+      EXPECT_TRUE(base::EndsWith(description.device_name,
+                                 real_communications_label,
+                                 base::CompareCase::SENSITIVE));
+    }
+  }
+}
+
 }  // namespace
 
 // Test fixture which allows us to override the default enumeration API on
@@ -258,8 +289,9 @@
       AudioDeviceDescriptions::const_iterator it = device_descriptions.begin();
 
       // The first device in the list should always be the default device.
-      EXPECT_EQ(AudioDeviceDescription::GetDefaultDeviceName(),
-                it->device_name);
+      EXPECT_TRUE(base::StartsWith(
+          it->device_name, AudioDeviceDescription::GetDefaultDeviceName(),
+          base::CompareCase::SENSITIVE));
       EXPECT_EQ(std::string(AudioDeviceDescription::kDefaultDeviceId),
                 it->unique_id);
       ++it;
@@ -600,7 +632,18 @@
                    AudioLogFactory* audio_log_factory)
       : FakeAudioManager(std::move(audio_thread), audio_log_factory) {}
 
-  std::string GetDefaultOutputDeviceID() override { return "output4"; }
+  std::string GetDefaultInputDeviceID() override {
+    return kRealDefaultInputDeviceID;
+  }
+  std::string GetDefaultOutputDeviceID() override {
+    return kRealDefaultOutputDeviceID;
+  }
+  std::string GetCommunicationsInputDeviceID() override {
+    return kRealCommunicationsInputDeviceID;
+  }
+  std::string GetCommunicationsOutputDeviceID() override {
+    return kRealCommunicationsOutputDeviceID;
+  }
 
   std::string GetAssociatedOutputDeviceID(
       const std::string& input_id) override {
@@ -659,6 +702,29 @@
   EXPECT_NE(inputs[1].group_id, outputs[3].group_id);
 }
 
+TEST_F(AudioManagerTest, DefaultCommunicationsLabelsContainRealLabels) {
+  CreateAudioManagerForTesting<TestAudioManager>();
+  std::string default_input_id =
+      device_info_accessor_->GetDefaultInputDeviceID();
+  EXPECT_EQ(default_input_id, kRealDefaultInputDeviceID);
+  std::string default_output_id =
+      device_info_accessor_->GetDefaultOutputDeviceID();
+  EXPECT_EQ(default_output_id, kRealDefaultOutputDeviceID);
+  std::string communications_input_id =
+      device_info_accessor_->GetCommunicationsInputDeviceID();
+  EXPECT_EQ(communications_input_id, kRealCommunicationsInputDeviceID);
+  std::string communications_output_id =
+      device_info_accessor_->GetCommunicationsOutputDeviceID();
+  EXPECT_EQ(communications_output_id, kRealCommunicationsOutputDeviceID);
+  AudioDeviceDescriptions inputs;
+  device_info_accessor_->GetAudioInputDeviceDescriptions(&inputs);
+  CheckDescriptionLabels(inputs, default_input_id, communications_input_id);
+
+  AudioDeviceDescriptions outputs;
+  device_info_accessor_->GetAudioOutputDeviceDescriptions(&outputs);
+  CheckDescriptionLabels(outputs, default_output_id, communications_output_id);
+}
+
 TEST_F(AudioManagerTest, AudioDebugRecording) {
   CreateAudioManagerForTesting<TestAudioManager>();
 
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc
index a0abdad..a35a02e 100644
--- a/media/audio/mac/audio_manager_mac.cc
+++ b/media/audio/mac/audio_manager_mac.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <limits>
+#include <utility>
 #include <vector>
 
 #include "base/bind.h"
@@ -790,8 +791,18 @@
 
 std::string AudioManagerMac::GetDefaultOutputDeviceID() {
   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  return GetDefaultDeviceID(false /* is_input */);
+}
+
+std::string AudioManagerMac::GetDefaultInputDeviceID() {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  return GetDefaultDeviceID(true /* is_input */);
+}
+
+std::string AudioManagerMac::GetDefaultDeviceID(bool is_input) {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
   AudioDeviceID device_id = kAudioObjectUnknown;
-  if (!GetDefaultOutputDevice(&device_id))
+  if (!GetDefaultDevice(&device_id, is_input))
     return std::string();
 
   const AudioObjectPropertyAddress property_address = {
diff --git a/media/audio/mac/audio_manager_mac.h b/media/audio/mac/audio_manager_mac.h
index 77c7be74..c642ace 100644
--- a/media/audio/mac/audio_manager_mac.h
+++ b/media/audio/mac/audio_manager_mac.h
@@ -60,6 +60,8 @@
       const AudioParameters& params,
       const std::string& device_id,
       const LogCallback& log_callback) override;
+
+  std::string GetDefaultInputDeviceID() override;
   std::string GetDefaultOutputDeviceID() override;
 
   // Used to track destruction of input and output streams.
@@ -178,6 +180,8 @@
   // account.
   bool IncreaseIOBufferSizeIfPossible(AudioDeviceID device_id);
 
+  std::string GetDefaultDeviceID(bool is_input);
+
   std::unique_ptr<AudioDeviceListenerMac> output_device_listener_;
 
   // Track the output sample-rate and the default output device
diff --git a/media/audio/mock_audio_manager.cc b/media/audio/mock_audio_manager.cc
index 562d9ae..f10b5b1 100644
--- a/media/audio/mock_audio_manager.cc
+++ b/media/audio/mock_audio_manager.cc
@@ -103,6 +103,19 @@
              : get_associated_output_device_id_cb_.Run(input_device_id);
 }
 
+std::string MockAudioManager::GetDefaultInputDeviceID() {
+  return std::string();
+}
+std::string MockAudioManager::GetDefaultOutputDeviceID() {
+  return std::string();
+}
+std::string MockAudioManager::GetCommunicationsInputDeviceID() {
+  return std::string();
+}
+std::string MockAudioManager::GetCommunicationsOutputDeviceID() {
+  return std::string();
+}
+
 std::unique_ptr<AudioLog> MockAudioManager::CreateAudioLog(
     AudioLogFactory::AudioComponent component) {
   return nullptr;
diff --git a/media/audio/mock_audio_manager.h b/media/audio/mock_audio_manager.h
index 5ee6b2e8..693befe 100644
--- a/media/audio/mock_audio_manager.h
+++ b/media/audio/mock_audio_manager.h
@@ -99,6 +99,10 @@
       const std::string& device_id) override;
   std::string GetAssociatedOutputDeviceID(
       const std::string& input_device_id) override;
+  std::string GetDefaultInputDeviceID() override;
+  std::string GetDefaultOutputDeviceID() override;
+  std::string GetCommunicationsInputDeviceID() override;
+  std::string GetCommunicationsOutputDeviceID() override;
 
  private:
   AudioParameters input_params_;
diff --git a/media/gpu/android/video_frame_factory.h b/media/gpu/android/video_frame_factory.h
index 6a84042..43a01584 100644
--- a/media/gpu/android/video_frame_factory.h
+++ b/media/gpu/android/video_frame_factory.h
@@ -15,7 +15,7 @@
 #include "ui/gfx/geometry/size.h"
 
 namespace gpu {
-class GpuCommandBufferStub;
+class CommandBufferStub;
 struct SyncToken;
 }  // namespace gpu
 
@@ -30,7 +30,7 @@
 // safe. Virtual for testing; see VideoFrameFactoryImpl.
 class MEDIA_GPU_EXPORT VideoFrameFactory {
  public:
-  using GetStubCb = base::Callback<gpu::GpuCommandBufferStub*()>;
+  using GetStubCb = base::Callback<gpu::CommandBufferStub*()>;
   using InitCb = base::Callback<void(scoped_refptr<SurfaceTextureGLOwner>)>;
 
   // These mirror types from MojoVideoDecoderService.
diff --git a/media/gpu/android/video_frame_factory_impl.cc b/media/gpu/android/video_frame_factory_impl.cc
index d001931..75a8daf1 100644
--- a/media/gpu/android/video_frame_factory_impl.cc
+++ b/media/gpu/android/video_frame_factory_impl.cc
@@ -14,8 +14,8 @@
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/texture_manager.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
 #include "gpu/ipc/service/gpu_channel.h"
-#include "gpu/ipc/service/gpu_command_buffer_stub.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/scoped_callback_runner.h"
 #include "media/base/video_frame.h"
@@ -28,7 +28,7 @@
 namespace media {
 namespace {
 
-bool MakeContextCurrent(gpu::GpuCommandBufferStub* stub) {
+bool MakeContextCurrent(gpu::CommandBufferStub* stub) {
   return stub && stub->decoder()->MakeCurrent();
 }
 
diff --git a/media/gpu/android/video_frame_factory_impl.h b/media/gpu/android/video_frame_factory_impl.h
index f072b5a..2b1cfc1 100644
--- a/media/gpu/android/video_frame_factory_impl.h
+++ b/media/gpu/android/video_frame_factory_impl.h
@@ -8,7 +8,7 @@
 #include "base/optional.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/texture_manager.h"
-#include "gpu/ipc/service/gpu_command_buffer_stub.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
 #include "media/base/video_frame.h"
 #include "media/gpu/android/codec_image.h"
 #include "media/gpu/android/codec_wrapper.h"
@@ -62,7 +62,7 @@
 // GpuVideoFrameFactory is an implementation detail of VideoFrameFactoryImpl. It
 // may be created on any thread but only accessed on the gpu thread thereafter.
 class GpuVideoFrameFactory
-    : public gpu::GpuCommandBufferStub::DestructionObserver {
+    : public gpu::CommandBufferStub::DestructionObserver {
  public:
   GpuVideoFrameFactory();
   ~GpuVideoFrameFactory() override;
@@ -117,7 +117,7 @@
   // destructed).
   std::map<gpu::gles2::TextureRef*, scoped_refptr<gpu::gles2::TextureRef>>
       texture_refs_;
-  gpu::GpuCommandBufferStub* stub_;
+  gpu::CommandBufferStub* stub_;
 
   // Callback to notify us that an image has been destroyed.
   CodecImage::DestructionCb destruction_cb_;
diff --git a/media/gpu/ipc/service/gpu_video_decode_accelerator.cc b/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
index 515e4c6..edd8020 100644
--- a/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
+++ b/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
@@ -34,7 +34,7 @@
 
 namespace {
 static gl::GLContext* GetGLContext(
-    const base::WeakPtr<gpu::GpuCommandBufferStub>& stub) {
+    const base::WeakPtr<gpu::CommandBufferStub>& stub) {
   if (!stub) {
     DLOG(ERROR) << "Stub is gone; no GLContext.";
     return nullptr;
@@ -44,7 +44,7 @@
 }
 
 static bool MakeDecoderContextCurrent(
-    const base::WeakPtr<gpu::GpuCommandBufferStub>& stub) {
+    const base::WeakPtr<gpu::CommandBufferStub>& stub) {
   if (!stub) {
     DLOG(ERROR) << "Stub is gone; won't MakeCurrent().";
     return false;
@@ -58,7 +58,7 @@
   return true;
 }
 
-static bool BindImage(const base::WeakPtr<gpu::GpuCommandBufferStub>& stub,
+static bool BindImage(const base::WeakPtr<gpu::CommandBufferStub>& stub,
                       uint32_t client_texture_id,
                       uint32_t texture_target,
                       const scoped_refptr<gl::GLImage>& image,
@@ -75,7 +75,7 @@
 }
 
 static base::WeakPtr<gpu::gles2::GLES2Decoder> GetGLES2Decoder(
-    const base::WeakPtr<gpu::GpuCommandBufferStub>& stub) {
+    const base::WeakPtr<gpu::CommandBufferStub>& stub) {
   if (!stub) {
     DLOG(ERROR) << "Stub is gone; no GLES2Decoder.";
     return base::WeakPtr<gpu::gles2::GLES2Decoder>();
@@ -145,7 +145,7 @@
 
 GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(
     int32_t host_route_id,
-    gpu::GpuCommandBufferStub* stub,
+    gpu::CommandBufferStub* stub,
     const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
     const AndroidOverlayMojoFactoryCB& overlay_factory_cb)
     : host_route_id_(host_route_id),
diff --git a/media/gpu/ipc/service/gpu_video_decode_accelerator.h b/media/gpu/ipc/service/gpu_video_decode_accelerator.h
index 53ce55b..027ef01 100644
--- a/media/gpu/ipc/service/gpu_video_decode_accelerator.h
+++ b/media/gpu/ipc/service/gpu_video_decode_accelerator.h
@@ -18,7 +18,7 @@
 #include "base/synchronization/waitable_event.h"
 #include "gpu/command_buffer/service/texture_manager.h"
 #include "gpu/config/gpu_info.h"
-#include "gpu/ipc/service/gpu_command_buffer_stub.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
 #include "ipc/ipc_listener.h"
 #include "ipc/ipc_sender.h"
 #include "media/base/android_overlay_mojo_factory.h"
@@ -37,14 +37,14 @@
     : public IPC::Listener,
       public IPC::Sender,
       public VideoDecodeAccelerator::Client,
-      public gpu::GpuCommandBufferStub::DestructionObserver {
+      public gpu::CommandBufferStub::DestructionObserver {
  public:
   // Each of the arguments to the constructor must outlive this object.
   // |stub->decoder()| will be made current around any operation that touches
   // the underlying VDA so that it can make GL calls safely.
   GpuVideoDecodeAccelerator(
       int32_t host_route_id,
-      gpu::GpuCommandBufferStub* stub,
+      gpu::CommandBufferStub* stub,
       const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
       const AndroidOverlayMojoFactoryCB& factory);
 
@@ -72,7 +72,7 @@
   void NotifyResetDone() override;
   void NotifyError(VideoDecodeAccelerator::Error error) override;
 
-  // GpuCommandBufferStub::DestructionObserver implementation.
+  // CommandBufferStub::DestructionObserver implementation.
   void OnWillDestroyStub() override;
 
   // Function to delegate sending to actual sender.
@@ -80,7 +80,7 @@
 
   // Initialize VDAs from the set of VDAs supported for current platform until
   // one of them succeeds for given |config|. Send the |init_done_msg| when
-  // done. filter_ is passed to gpu::GpuCommandBufferStub channel only if the
+  // done. filter_ is passed to gpu::CommandBufferStub channel only if the
   // chosen VDA can decode on IO thread.
   bool Initialize(const VideoDecodeAccelerator::Config& config);
 
@@ -110,10 +110,10 @@
   // Route ID to communicate with the host.
   const int32_t host_route_id_;
 
-  // Unowned pointer to the underlying gpu::GpuCommandBufferStub.  |this| is
+  // Unowned pointer to the underlying gpu::CommandBufferStub.  |this| is
   // registered as a DestuctionObserver of |stub_| and will self-delete when
   // |stub_| is destroyed.
-  gpu::GpuCommandBufferStub* const stub_;
+  gpu::CommandBufferStub* const stub_;
 
   // The underlying VideoDecodeAccelerator.
   std::unique_ptr<VideoDecodeAccelerator> video_decode_accelerator_;
diff --git a/media/gpu/ipc/service/gpu_video_encode_accelerator.cc b/media/gpu/ipc/service/gpu_video_encode_accelerator.cc
index 8108649..03353ab 100644
--- a/media/gpu/ipc/service/gpu_video_encode_accelerator.cc
+++ b/media/gpu/ipc/service/gpu_video_encode_accelerator.cc
@@ -91,7 +91,7 @@
 
 GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator(
     int32_t host_route_id,
-    gpu::GpuCommandBufferStub* stub,
+    gpu::CommandBufferStub* stub,
     const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
     : host_route_id_(host_route_id),
       stub_(stub),
diff --git a/media/gpu/ipc/service/gpu_video_encode_accelerator.h b/media/gpu/ipc/service/gpu_video_encode_accelerator.h
index 37e126d..249fd7e 100644
--- a/media/gpu/ipc/service/gpu_video_encode_accelerator.h
+++ b/media/gpu/ipc/service/gpu_video_encode_accelerator.h
@@ -16,7 +16,7 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
 #include "gpu/config/gpu_info.h"
-#include "gpu/ipc/service/gpu_command_buffer_stub.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
 #include "ipc/ipc_listener.h"
 #include "media/video/video_encode_accelerator.h"
 #include "ui/gfx/geometry/size.h"
@@ -36,11 +36,11 @@
     : public IPC::Listener,
       public IPC::Sender,
       public VideoEncodeAccelerator::Client,
-      public gpu::GpuCommandBufferStub::DestructionObserver {
+      public gpu::CommandBufferStub::DestructionObserver {
  public:
   GpuVideoEncodeAccelerator(
       int32_t host_route_id,
-      gpu::GpuCommandBufferStub* stub,
+      gpu::CommandBufferStub* stub,
       const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
   ~GpuVideoEncodeAccelerator() override;
 
@@ -67,7 +67,7 @@
                             base::TimeDelta timestamp) override;
   void NotifyError(VideoEncodeAccelerator::Error error) override;
 
-  // gpu::GpuCommandBufferStub::DestructionObserver implementation.
+  // gpu::CommandBufferStub::DestructionObserver implementation.
   void OnWillDestroyStub() override;
 
   // Static query for supported profiles.  This query calls the appropriate
@@ -120,10 +120,10 @@
   // Route ID to communicate with the host.
   const uint32_t host_route_id_;
 
-  // Unowned pointer to the underlying gpu::GpuCommandBufferStub.  |this| is
+  // Unowned pointer to the underlying gpu::CommandBufferStub.  |this| is
   // registered as a DestuctionObserver of |stub_| and will self-delete when
   // |stub_| is destroyed.
-  gpu::GpuCommandBufferStub* const stub_;
+  gpu::CommandBufferStub* const stub_;
 
   // Owned pointer to the underlying VideoEncodeAccelerator.
   std::unique_ptr<VideoEncodeAccelerator> encoder_;
diff --git a/media/gpu/ipc/service/media_gpu_channel.cc b/media/gpu/ipc/service/media_gpu_channel.cc
index f6023c3..f12ed3b 100644
--- a/media/gpu/ipc/service/media_gpu_channel.cc
+++ b/media/gpu/ipc/service/media_gpu_channel.cc
@@ -115,7 +115,7 @@
     int32_t decoder_route_id,
     IPC::Message* reply_message) {
   TRACE_EVENT0("gpu", "MediaGpuChannel::OnCreateVideoDecoder");
-  gpu::GpuCommandBufferStub* stub =
+  gpu::CommandBufferStub* stub =
       channel_->LookupCommandBuffer(command_buffer_route_id);
   if (!stub) {
     reply_message->set_reply_error();
@@ -139,7 +139,7 @@
     const CreateVideoEncoderParams& params,
     IPC::Message* reply_message) {
   TRACE_EVENT0("gpu", "MediaGpuChannel::OnCreateVideoEncoder");
-  gpu::GpuCommandBufferStub* stub =
+  gpu::CommandBufferStub* stub =
       channel_->LookupCommandBuffer(command_buffer_route_id);
   if (!stub) {
     reply_message->set_reply_error();
diff --git a/media/gpu/windows/d3d11_video_decoder.cc b/media/gpu/windows/d3d11_video_decoder.cc
index 5d632046..33f0740 100644
--- a/media/gpu/windows/d3d11_video_decoder.cc
+++ b/media/gpu/windows/d3d11_video_decoder.cc
@@ -46,7 +46,7 @@
 
 D3D11VideoDecoder::D3D11VideoDecoder(
     scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
-    base::Callback<gpu::GpuCommandBufferStub*()> get_stub_cb,
+    base::Callback<gpu::CommandBufferStub*()> get_stub_cb,
     OutputWithReleaseMailboxCB output_cb)
     : impl_task_runner_(std::move(gpu_task_runner)), weak_factory_(this) {
   // We create |impl_| on the wrong thread, but we never use it here.
diff --git a/media/gpu/windows/d3d11_video_decoder.h b/media/gpu/windows/d3d11_video_decoder.h
index c489c467..ad82c7f 100644
--- a/media/gpu/windows/d3d11_video_decoder.h
+++ b/media/gpu/windows/d3d11_video_decoder.h
@@ -13,7 +13,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
-#include "gpu/ipc/service/gpu_command_buffer_stub.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
 #include "media/base/video_decoder.h"
 #include "media/gpu/media_gpu_export.h"
 #include "media/gpu/windows/d3d11_video_decoder_impl.h"
@@ -30,7 +30,7 @@
 class MEDIA_GPU_EXPORT D3D11VideoDecoder : public VideoDecoder {
  public:
   D3D11VideoDecoder(scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
-                    base::Callback<gpu::GpuCommandBufferStub*()> get_stub_cb,
+                    base::Callback<gpu::CommandBufferStub*()> get_stub_cb,
                     OutputWithReleaseMailboxCB output_cb);
   ~D3D11VideoDecoder() override;
 
diff --git a/media/gpu/windows/d3d11_video_decoder_impl.cc b/media/gpu/windows/d3d11_video_decoder_impl.cc
index 9dd155ce..35a8112 100644
--- a/media/gpu/windows/d3d11_video_decoder_impl.cc
+++ b/media/gpu/windows/d3d11_video_decoder_impl.cc
@@ -19,14 +19,14 @@
 
 namespace {
 
-static bool MakeContextCurrent(gpu::GpuCommandBufferStub* stub) {
+static bool MakeContextCurrent(gpu::CommandBufferStub* stub) {
   return stub && stub->decoder()->MakeCurrent();
 }
 
 }  // namespace
 
 D3D11VideoDecoderImpl::D3D11VideoDecoderImpl(
-    base::Callback<gpu::GpuCommandBufferStub*()> get_stub_cb,
+    base::Callback<gpu::CommandBufferStub*()> get_stub_cb,
     OutputWithReleaseMailboxCB output_cb)
     : get_stub_cb_(get_stub_cb),
       output_cb_(std::move(output_cb)),
diff --git a/media/gpu/windows/d3d11_video_decoder_impl.h b/media/gpu/windows/d3d11_video_decoder_impl.h
index 1e75bd8..abd9e130 100644
--- a/media/gpu/windows/d3d11_video_decoder_impl.h
+++ b/media/gpu/windows/d3d11_video_decoder_impl.h
@@ -15,7 +15,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "gpu/ipc/service/gpu_command_buffer_stub.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
 #include "media/base/video_decoder.h"
 #include "media/gpu/d3d11_h264_accelerator.h"
 #include "media/gpu/gles2_decoder_helper.h"
@@ -27,9 +27,8 @@
 class MEDIA_GPU_EXPORT D3D11VideoDecoderImpl : public VideoDecoder,
                                                public D3D11VideoDecoderClient {
  public:
-  D3D11VideoDecoderImpl(
-      base::Callback<gpu::GpuCommandBufferStub*()> get_stub_cb,
-      OutputWithReleaseMailboxCB output_cb);
+  D3D11VideoDecoderImpl(base::Callback<gpu::CommandBufferStub*()> get_stub_cb,
+                        OutputWithReleaseMailboxCB output_cb);
   ~D3D11VideoDecoderImpl() override;
 
   // VideoDecoder implementation:
@@ -62,8 +61,8 @@
   void OnMailboxReleased(D3D11PictureBuffer* buffer,
                          const gpu::SyncToken& sync_token);
 
-  base::Callback<gpu::GpuCommandBufferStub*()> get_stub_cb_;
-  gpu::GpuCommandBufferStub* stub_ = nullptr;
+  base::Callback<gpu::CommandBufferStub*()> get_stub_cb_;
+  gpu::CommandBufferStub* stub_ = nullptr;
   // A helper for creating textures. Only valid while |stub_| is valid.
   std::unique_ptr<GLES2DecoderHelper> decoder_helper_;
 
diff --git a/media/mojo/interfaces/video_decoder.mojom b/media/mojo/interfaces/video_decoder.mojom
index c34426b..77ab8a4 100644
--- a/media/mojo/interfaces/video_decoder.mojom
+++ b/media/mojo/interfaces/video_decoder.mojom
@@ -9,7 +9,7 @@
 import "media/mojo/interfaces/media_types.mojom";
 import "mojo/common/unguessable_token.mojom";
 
-// Identifies a GpuCommandBufferStub. MediaGpuChannelManager is responsible
+// Identifies a CommandBufferStub. MediaGpuChannelManager is responsible
 // for minting |channel_token| objects.
 struct CommandBufferId {
   mojo.common.mojom.UnguessableToken channel_token;
@@ -22,7 +22,7 @@
 interface VideoDecoder {
   // Initialize the decoder. This must be called before any other method.
   //
-  // |command_buffer_id|, when present, identifies a GpuCommandBufferStub that
+  // |command_buffer_id|, when present, identifies a CommandBufferStub that
   // the decoder can use for GL operations. Implementations that require GL will
   // fail Initialize() if |command_buffer_id| is not provided.
   //
diff --git a/media/mojo/services/gpu_mojo_media_client.cc b/media/mojo/services/gpu_mojo_media_client.cc
index d48a0a9e..4c1e24c 100644
--- a/media/mojo/services/gpu_mojo_media_client.cc
+++ b/media/mojo/services/gpu_mojo_media_client.cc
@@ -62,7 +62,7 @@
 
 #if BUILDFLAG(ENABLE_MEDIA_CODEC_VIDEO_DECODER) || \
     BUILDFLAG(ENABLE_D3D11_VIDEO_DECODER)
-gpu::GpuCommandBufferStub* GetGpuCommandBufferStub(
+gpu::CommandBufferStub* GetCommandBufferStub(
     base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,
     base::UnguessableToken channel_token,
     int32_t route_id) {
@@ -111,7 +111,7 @@
     RequestOverlayInfoCB request_overlay_info_cb) {
 #if BUILDFLAG(ENABLE_MEDIA_CODEC_VIDEO_DECODER)
   auto get_stub_cb =
-      base::Bind(&GetGpuCommandBufferStub, media_gpu_channel_manager_,
+      base::Bind(&GetCommandBufferStub, media_gpu_channel_manager_,
                  command_buffer_id->channel_token, command_buffer_id->route_id);
   return base::MakeUnique<MediaCodecVideoDecoder>(
       gpu_preferences_, std::move(output_cb), DeviceInfo::GetInstance(),
@@ -124,7 +124,7 @@
 #elif BUILDFLAG(ENABLE_D3D11_VIDEO_DECODER)
   return base::MakeUnique<D3D11VideoDecoder>(
       gpu_task_runner_,
-      base::Bind(&GetGpuCommandBufferStub, media_gpu_channel_manager_,
+      base::Bind(&GetCommandBufferStub, media_gpu_channel_manager_,
                  command_buffer_id->channel_token, command_buffer_id->route_id),
       std::move(output_cb));
 #else
diff --git a/services/resource_coordinator/memory_instrumentation/graph.cc b/services/resource_coordinator/memory_instrumentation/graph.cc
index b8b7854..364b000b 100644
--- a/services/resource_coordinator/memory_instrumentation/graph.cc
+++ b/services/resource_coordinator/memory_instrumentation/graph.cc
@@ -48,6 +48,16 @@
   return &*all_nodes_.begin();
 }
 
+PostOrderIterator GlobalDumpGraph::VisitInDepthFirstPostOrder() {
+  std::vector<Node*> roots;
+  for (auto it = process_dump_graphs_.rbegin();
+       it != process_dump_graphs_.rend(); it++) {
+    roots.push_back(it->second->root());
+  }
+  roots.push_back(shared_memory_graph_->root());
+  return PostOrderIterator(std::move(roots));
+}
+
 Process::Process(base::ProcessId pid, GlobalDumpGraph* global_graph)
     : pid_(pid),
       global_graph_(global_graph),
@@ -102,10 +112,6 @@
   return current;
 }
 
-PostOrderIterator Process::VisitInDepthFirstPostOrder() {
-  return PostOrderIterator(root_);
-}
-
 Node::Node(Process* dump_graph, Node* parent)
     : dump_graph_(dump_graph), parent_(parent), owns_edge_(nullptr) {}
 Node::~Node() {}
@@ -171,9 +177,8 @@
 Edge::Edge(Node* source, Node* target, int priority)
     : source_(source), target_(target), priority_(priority) {}
 
-PostOrderIterator::PostOrderIterator(Node* root) {
-  to_visit_.push_back(root);
-}
+PostOrderIterator::PostOrderIterator(std::vector<Node*> roots)
+    : to_visit_(std::move(roots)) {}
 PostOrderIterator::PostOrderIterator(PostOrderIterator&& other) = default;
 PostOrderIterator::~PostOrderIterator() = default;
 
diff --git a/services/resource_coordinator/memory_instrumentation/graph.h b/services/resource_coordinator/memory_instrumentation/graph.h
index a2a8b4ba..2523afe 100644
--- a/services/resource_coordinator/memory_instrumentation/graph.h
+++ b/services/resource_coordinator/memory_instrumentation/graph.h
@@ -42,11 +42,6 @@
     // if no such node exists in the provided |graph|.
     GlobalDumpGraph::Node* FindNode(base::StringPiece path);
 
-    // Returns an iterator which yields nodes in the nodes in this graph in
-    // post-order. That is, children and owners of nodes are returned before the
-    // node itself.
-    GlobalDumpGraph::PostOrderIterator VisitInDepthFirstPostOrder();
-
     base::ProcessId pid() const { return pid_; }
     GlobalDumpGraph* global_graph() const { return global_graph_; }
     GlobalDumpGraph::Node* root() const { return root_; }
@@ -179,7 +174,7 @@
   // An iterator-esque class which yields nodes in a depth-first post order.
   class PostOrderIterator {
    public:
-    PostOrderIterator(Node* root);
+    PostOrderIterator(std::vector<Node*> root_nodes);
     PostOrderIterator(PostOrderIterator&& other);
     ~PostOrderIterator();
 
@@ -208,6 +203,11 @@
   // and edge priority.
   void AddNodeOwnershipEdge(Node* owner, Node* owned, int priority);
 
+  // Returns an iterator which yields nodes in the nodes in this graph in
+  // post-order. That is, children and owners of nodes are returned before the
+  // node itself.
+  PostOrderIterator VisitInDepthFirstPostOrder();
+
   const GuidNodeMap& nodes_by_guid() const { return nodes_by_guid_; }
   GlobalDumpGraph::Process* shared_memory_graph() const {
     return shared_memory_graph_.get();
diff --git a/services/resource_coordinator/memory_instrumentation/graph_processor.cc b/services/resource_coordinator/memory_instrumentation/graph_processor.cc
index 54a732c..f3f9e06 100644
--- a/services/resource_coordinator/memory_instrumentation/graph_processor.cc
+++ b/services/resource_coordinator/memory_instrumentation/graph_processor.cc
@@ -136,32 +136,18 @@
   // Eighth pass: calculate the size field for nodes by considering the sizes
   // of their children and owners.
   {
-    auto it = global_graph->shared_memory_graph()->VisitInDepthFirstPostOrder();
+    auto it = global_graph->VisitInDepthFirstPostOrder();
     while (Node* node = it.next()) {
       CalculateSizeForNode(node);
     }
-
-    for (auto& pid_to_process : global_graph->process_dump_graphs()) {
-      auto it = pid_to_process.second->VisitInDepthFirstPostOrder();
-      while (Node* node = it.next()) {
-        CalculateSizeForNode(node);
-      }
-    }
   }
 
   // Ninth pass: Calculate not-owned and not-owning sub-sizes of all nodes.
   {
-    auto it = global_graph->shared_memory_graph()->VisitInDepthFirstPostOrder();
+    auto it = global_graph->VisitInDepthFirstPostOrder();
     while (Node* node = it.next()) {
       CalculateDumpSubSizes(node);
     }
-
-    for (auto& pid_to_process : global_graph->process_dump_graphs()) {
-      auto it = pid_to_process.second->VisitInDepthFirstPostOrder();
-      while (Node* node = it.next()) {
-        CalculateDumpSubSizes(node);
-      }
-    }
   }
 }
 
diff --git a/services/resource_coordinator/memory_instrumentation/graph_unittest.cc b/services/resource_coordinator/memory_instrumentation/graph_unittest.cc
index f289782..36331fe 100644
--- a/services/resource_coordinator/memory_instrumentation/graph_unittest.cc
+++ b/services/resource_coordinator/memory_instrumentation/graph_unittest.cc
@@ -9,10 +9,16 @@
 
 namespace memory_instrumentation {
 
+namespace {
+
 using base::trace_event::MemoryAllocatorDumpGuid;
 using Node = memory_instrumentation::GlobalDumpGraph::Node;
 using Process = memory_instrumentation::GlobalDumpGraph::Process;
 
+const MemoryAllocatorDumpGuid kEmptyGuid;
+
+}  // namespace
+
 TEST(GlobalDumpGraphTest, CreateContainerForProcess) {
   GlobalDumpGraph global_dump_graph;
 
@@ -41,39 +47,34 @@
 
 TEST(GlobalDumpGraphTest, VisitInDepthFirstPostOrder) {
   GlobalDumpGraph graph;
-  Process* process = graph.shared_memory_graph();
-  Node* root = process->root();
+  Process* process_1 = graph.CreateGraphForProcess(1);
+  Process* process_2 = graph.CreateGraphForProcess(2);
 
-  Node c1(process, root);
-  Node c2(process, root);
-  Node c2_c1(process, &c2);
-  Node c2_c2(process, &c2);
-  Node c3(process, root);
-  Node c3_c1(process, &c3);
-  Node c3_c2(process, &c3);
+  Node* c1 = process_1->CreateNode(kEmptyGuid, "c1", false);
+  Node* c2 = process_1->CreateNode(kEmptyGuid, "c2", false);
+  Node* c2_c1 = process_1->CreateNode(kEmptyGuid, "c2/c1", false);
+  Node* c2_c2 = process_1->CreateNode(kEmptyGuid, "c2/c2", false);
 
-  root->InsertChild("c1", &c1);
-  root->InsertChild("c2", &c2);
-  root->InsertChild("c3", &c3);
-  c2.InsertChild("c1", &c2_c1);
-  c2.InsertChild("c2", &c2_c2);
-  c3.InsertChild("c1", &c3_c1);
-  c3.InsertChild("c2", &c3_c2);
+  Node* c3 = process_2->CreateNode(kEmptyGuid, "c3", false);
+  Node* c3_c1 = process_2->CreateNode(kEmptyGuid, "c3/c1", false);
+  Node* c3_c2 = process_2->CreateNode(kEmptyGuid, "c3/c2", false);
 
   // |c3_c2| owns |c2_c2|.
-  graph.AddNodeOwnershipEdge(&c3_c2, &c2_c2, 1);
+  graph.AddNodeOwnershipEdge(c3_c2, c2_c2, 1);
 
   // This method should always call owners and then children before the node
   // itself.
-  auto iterator = process->VisitInDepthFirstPostOrder();
-  ASSERT_EQ(iterator.next(), &c1);
-  ASSERT_EQ(iterator.next(), &c2_c1);
-  ASSERT_EQ(iterator.next(), &c3_c2);
-  ASSERT_EQ(iterator.next(), &c2_c2);
-  ASSERT_EQ(iterator.next(), &c2);
-  ASSERT_EQ(iterator.next(), &c3_c1);
-  ASSERT_EQ(iterator.next(), &c3);
-  ASSERT_EQ(iterator.next(), root);
+  auto iterator = graph.VisitInDepthFirstPostOrder();
+  ASSERT_EQ(iterator.next(), graph.shared_memory_graph()->root());
+  ASSERT_EQ(iterator.next(), c1);
+  ASSERT_EQ(iterator.next(), c2_c1);
+  ASSERT_EQ(iterator.next(), c3_c2);
+  ASSERT_EQ(iterator.next(), c2_c2);
+  ASSERT_EQ(iterator.next(), c2);
+  ASSERT_EQ(iterator.next(), process_1->root());
+  ASSERT_EQ(iterator.next(), c3_c1);
+  ASSERT_EQ(iterator.next(), c3);
+  ASSERT_EQ(iterator.next(), process_2->root());
   ASSERT_EQ(iterator.next(), nullptr);
 }
 
diff --git a/third_party/WebKit/LayoutTests/fast/peerconnection/RTCPeerConnection-garbagecollected.html b/third_party/WebKit/LayoutTests/fast/peerconnection/RTCPeerConnection-garbagecollected.html
new file mode 100644
index 0000000..7dd7111
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/peerconnection/RTCPeerConnection-garbagecollected.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+
+const limit = 10;
+
+function waitAndGc() {
+  return new Promise(function(resolve, reject) {
+    setTimeout(function() {
+      gc();
+      resolve();
+    }, 0);
+  });
+}
+
+promise_test(function(t) {
+  const baseline = internals.peerConnectionCount();
+  let pc;
+  for (let count = 0; count < limit; count++) {
+    pc = new RTCPeerConnection();
+    pc.close();
+  }
+  return waitAndGc().then(function() {
+    // All the non-referenced PCs should now be collected.
+    assert_equals(internals.peerConnectionCount(), baseline + 1);
+    pc = null;
+    return waitAndGc();
+  }).then(function() {
+    gc();
+    assert_equals(internals.peerConnectionCount(), baseline);
+  });
+}, 'Closed Peerconnections are garbage collected');
+
+
+promise_test(function(t) {
+  const baseline = internals.peerConnectionCount();
+  for (let count = 0; count < limit; count++) {
+    pc = new RTCPeerConnection();
+  }
+  pc = null;
+  return waitAndGc().then(function() {
+    assert_equals(baseline + limit, internals.peerConnectionCount());
+  });
+}, 'Non-closed Peerconnections are NOT garbage collected');
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/Source/modules/BUILD.gn b/third_party/WebKit/Source/modules/BUILD.gn
index 64eb7f33..af2f13c 100644
--- a/third_party/WebKit/Source/modules/BUILD.gn
+++ b/third_party/WebKit/Source/modules/BUILD.gn
@@ -190,6 +190,8 @@
     "navigatorcontentutils/testing/NavigatorContentUtilsClientMock.h",
     "peerconnection/testing/InternalsRTCCertificate.cpp",
     "peerconnection/testing/InternalsRTCCertificate.h",
+    "peerconnection/testing/InternalsRTCPeerConnection.cpp",
+    "peerconnection/testing/InternalsRTCPeerConnection.h",
     "serviceworkers/testing/InternalsServiceWorker.cpp",
     "serviceworkers/testing/InternalsServiceWorker.h",
     "speech/testing/InternalsSpeechSynthesis.cpp",
diff --git a/third_party/WebKit/Source/modules/modules_idl_files.gni b/third_party/WebKit/Source/modules/modules_idl_files.gni
index ad0eeac..ae504e3 100644
--- a/third_party/WebKit/Source/modules/modules_idl_files.gni
+++ b/third_party/WebKit/Source/modules/modules_idl_files.gni
@@ -741,6 +741,7 @@
           "mediastream/testing/InternalsMediaStream.idl",
           "navigatorcontentutils/testing/InternalsNavigatorContentUtils.idl",
           "peerconnection/testing/InternalsRTCCertificate.idl",
+          "peerconnection/testing/InternalsRTCPeerConnection.idl",
           "serviceworkers/testing/InternalsServiceWorker.idl",
           "speech/testing/InternalsSpeechSynthesis.idl",
           "vibration/testing/InternalsVibration.idl",
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
index aff42d2..5d79b704 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
@@ -81,6 +81,7 @@
 #include "modules/peerconnection/RTCTrackEvent.h"
 #include "modules/peerconnection/RTCVoidRequestImpl.h"
 #include "modules/peerconnection/RTCVoidRequestPromiseImpl.h"
+#include "modules/peerconnection/testing/InternalsRTCPeerConnection.h"
 #include "platform/bindings/Microtask.h"
 #include "platform/bindings/ScriptState.h"
 #include "platform/bindings/V8ThrowException.h"
@@ -114,6 +115,9 @@
 const char kSignalingStateClosedMessage[] =
     "The RTCPeerConnection's signalingState is 'closed'.";
 
+// For testing: Keep track of number of existing PeerConnections.
+int g_peer_connection_counter = 0;
+
 bool ThrowExceptionIfSignalingStateClosed(
     RTCPeerConnection::SignalingState state,
     ExceptionState& exception_state) {
@@ -500,6 +504,7 @@
   // If we fail, set |m_closed| and |m_stopped| to true, to avoid hitting the
   // assert in the destructor.
 
+  g_peer_connection_counter++;
   if (!document->GetFrame()) {
     closed_ = true;
     stopped_ = true;
@@ -539,6 +544,7 @@
   // We are assuming that a wrapper is always created when RTCPeerConnection is
   // created.
   DCHECK(closed_ || stopped_);
+  g_peer_connection_counter--;
 }
 
 void RTCPeerConnection::Dispose() {
@@ -1769,4 +1775,8 @@
   MediaStreamObserver::Trace(visitor);
 }
 
+int RTCPeerConnection::PeerConnectionCount() {
+  return g_peer_connection_counter;
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.h b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.h
index 19d9edd..d88ef48 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.h
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.h
@@ -214,6 +214,9 @@
   // We keep the this object alive until either stopped or closed.
   bool HasPendingActivity() const final { return !closed_ && !stopped_; }
 
+  // For testing; exported to testing/InternalWebRTCPeerConnection
+  static int PeerConnectionCount();
+
   virtual void Trace(blink::Visitor*);
 
  private:
diff --git a/third_party/WebKit/Source/modules/peerconnection/testing/InternalsRTCPeerConnection.cpp b/third_party/WebKit/Source/modules/peerconnection/testing/InternalsRTCPeerConnection.cpp
new file mode 100644
index 0000000..05ff3de
--- /dev/null
+++ b/third_party/WebKit/Source/modules/peerconnection/testing/InternalsRTCPeerConnection.cpp
@@ -0,0 +1,13 @@
+// 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 "modules/peerconnection/testing/InternalsRTCPeerConnection.h"
+
+namespace blink {
+
+int InternalsRTCPeerConnection::peerConnectionCount(Internals& internals) {
+  return RTCPeerConnection::PeerConnectionCount();
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/peerconnection/testing/InternalsRTCPeerConnection.h b/third_party/WebKit/Source/modules/peerconnection/testing/InternalsRTCPeerConnection.h
new file mode 100644
index 0000000..11f4d26
--- /dev/null
+++ b/third_party/WebKit/Source/modules/peerconnection/testing/InternalsRTCPeerConnection.h
@@ -0,0 +1,24 @@
+// 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 InternalsRTCPeerConnection_h
+#define InternalsRTCPeerConnection_h
+
+#include "modules/peerconnection/RTCPeerConnection.h"
+#include "platform/wtf/Allocator.h"
+
+namespace blink {
+
+class Internals;
+
+class InternalsRTCPeerConnection {
+  STATIC_ONLY(InternalsRTCPeerConnection);
+
+ public:
+  static int peerConnectionCount(Internals&);
+};
+
+}  // namespace blink
+
+#endif  // InternalsRTCPeerConnection_h
diff --git a/third_party/WebKit/Source/modules/peerconnection/testing/InternalsRTCPeerConnection.idl b/third_party/WebKit/Source/modules/peerconnection/testing/InternalsRTCPeerConnection.idl
new file mode 100644
index 0000000..37fe749
--- /dev/null
+++ b/third_party/WebKit/Source/modules/peerconnection/testing/InternalsRTCPeerConnection.idl
@@ -0,0 +1,9 @@
+// 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.
+
+[
+    ImplementedAs=InternalsRTCPeerConnection
+] partial interface Internals {
+    long peerConnectionCount();
+};
diff --git a/third_party/harfbuzz-ng/BUILD.gn b/third_party/harfbuzz-ng/BUILD.gn
index 371af47..dcb7452 100644
--- a/third_party/harfbuzz-ng/BUILD.gn
+++ b/third_party/harfbuzz-ng/BUILD.gn
@@ -57,7 +57,9 @@
       "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",
@@ -77,6 +79,7 @@
       "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-common-private.hh",
       "src/hb-ot-layout-gdef-table.hh",
       "src/hb-ot-layout-gpos-table.hh",
@@ -92,6 +95,7 @@
       "src/hb-ot-math.h",
       "src/hb-ot-maxp-table.hh",
       "src/hb-ot-name-table.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",
@@ -142,6 +146,7 @@
       "src/hb-shaper-list.hh",
       "src/hb-shaper-private.hh",
       "src/hb-shaper.cc",
+      "src/hb-string-array.hh",
       "src/hb-unicode-private.hh",
       "src/hb-unicode.cc",
       "src/hb-unicode.h",
diff --git a/third_party/harfbuzz-ng/NEWS b/third_party/harfbuzz-ng/NEWS
index 51cec0d3..0599596 100644
--- a/third_party/harfbuzz-ng/NEWS
+++ b/third_party/harfbuzz-ng/NEWS
@@ -1,3 +1,42 @@
+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
 ====================================
diff --git a/third_party/harfbuzz-ng/README.chromium b/third_party/harfbuzz-ng/README.chromium
index b440acb1..5f6534db 100644
--- a/third_party/harfbuzz-ng/README.chromium
+++ b/third_party/harfbuzz-ng/README.chromium
@@ -1,8 +1,8 @@
 Name: harfbuzz-ng
 Short Name: harfbuzz-ng
 URL: http://harfbuzz.org
-Version: 1.6.3
-Date: 20171026
+Version: 1.7.2
+Date: 20171204
 Security Critical: yes
 License: MIT
 License File: COPYING
@@ -19,12 +19,4 @@
 harfbuzz.gyp accordingly, update the NEWS file from HarfBuzz' release notes, and
 bump the version numbers in README.chromium.
 
-Locally added #undef PAGE_SIZE to hb-set-private.hh to avoid a collision with
-#usr/include/asm/page.h as part of the Android NDK.
-
-Temporarily patched to original CoreText default font size 36.f that was used
-before to ease Blink reabaselining.
-
-Locally patching hb_set implementation back to the pre 1.6.1 implemention to see
-whether this addresses reports of performance regressions in issues 781794,
-782220.
+Locally patch hb-private.hh to silence unusued variable warnings in MSVC.
\ No newline at end of file
diff --git a/third_party/harfbuzz-ng/src/hb-atomic-private.hh b/third_party/harfbuzz-ng/src/hb-atomic-private.hh
index 2d56757..9343840 100644
--- a/third_party/harfbuzz-ng/src/hb-atomic-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-atomic-private.hh
@@ -89,9 +89,9 @@
 #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) (O), (int64_t) (N), (int64_t*) (P))
+#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) (O), (int32_t) (N), (int32_t*) (P))
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)	OSAtomicCompareAndSwap32Barrier ((int32_t) (void *) (O), (int32_t) (void *) (N), (int32_t*) (P))
 #endif
 #endif
 
diff --git a/third_party/harfbuzz-ng/src/hb-blob.cc b/third_party/harfbuzz-ng/src/hb-blob.cc
index e390d752..ceeb18d 100644
--- a/third_party/harfbuzz-ng/src/hb-blob.cc
+++ b/third_party/harfbuzz-ng/src/hb-blob.cc
@@ -29,6 +29,7 @@
 #define _POSIX_C_SOURCE 199309L
 #endif
 
+#include "hb-debug.hh"
 #include "hb-private.hh"
 
 #include "hb-object-private.hh"
@@ -44,12 +45,6 @@
 #include <errno.h>
 
 
-
-#ifndef HB_DEBUG_BLOB
-#define HB_DEBUG_BLOB (HB_DEBUG+0)
-#endif
-
-
 struct hb_blob_t {
   hb_object_header_t header;
   ASSERT_POD ();
diff --git a/third_party/harfbuzz-ng/src/hb-buffer-private.hh b/third_party/harfbuzz-ng/src/hb-buffer-private.hh
index 1aa87b6..97bdc1be 100644
--- a/third_party/harfbuzz-ng/src/hb-buffer-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-buffer-private.hh
@@ -35,8 +35,8 @@
 #include "hb-unicode-private.hh"
 
 
-#ifndef HB_BUFFER_MAX_EXPANSION_FACTOR
-#define HB_BUFFER_MAX_EXPANSION_FACTOR 32
+#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
@@ -45,6 +45,16 @@
 #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)), "");
 
@@ -84,6 +94,7 @@
   hb_codepoint_t replacement; /* U+FFFD or something else. */
   hb_buffer_scratch_flags_t scratch_flags; /* Have space-flallback, etc. */
   unsigned int max_len; /* Maximum allowed len. */
+  int max_ops; /* Maximum allowed operations. */
 
   /* Buffer contents */
   hb_buffer_content_type_t content_type;
@@ -102,17 +113,6 @@
   hb_glyph_info_t     *out_info;
   hb_glyph_position_t *pos;
 
-  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; }
-
   unsigned int serial;
 
   /* Text before / after the main buffer contents.
@@ -132,6 +132,10 @@
 #ifndef HB_NDEBUG
   uint8_t allocated_var_bits;
 #endif
+
+
+  /* Methods */
+
   inline void allocate_var (unsigned int start, unsigned int count)
   {
 #ifndef HB_NDEBUG
@@ -168,8 +172,17 @@
 #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]; }
 
-  /* Methods */
+  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);
@@ -305,16 +318,16 @@
     info.cluster = cluster;
   }
 
-  int
+  inline int
   _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *info,
 				     unsigned int start, unsigned int end,
 				     unsigned int cluster) const
   {
     for (unsigned int i = start; i < end; i++)
-      cluster = MIN (cluster, info[i].cluster);
+      cluster = MIN<unsigned int> (cluster, info[i].cluster);
     return cluster;
   }
-  void
+  inline void
   _unsafe_to_break_set_mask (hb_glyph_info_t *info,
 			     unsigned int start, unsigned int end,
 			     unsigned int cluster)
@@ -326,6 +339,19 @@
 	info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
       }
   }
+
+  inline void
+  unsafe_to_break_all (void)
+  {
+    for (unsigned int i = 0; i < len; i++)
+      info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+  }
+  inline void
+  safe_to_break_all (void)
+  {
+    for (unsigned int i = 0; i < len; i++)
+      info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+  }
 };
 
 
diff --git a/third_party/harfbuzz-ng/src/hb-buffer.cc b/third_party/harfbuzz-ng/src/hb-buffer.cc
index 73b3e4b..ef70002 100644
--- a/third_party/harfbuzz-ng/src/hb-buffer.cc
+++ b/third_party/harfbuzz-ng/src/hb-buffer.cc
@@ -554,7 +554,7 @@
   unsigned int cluster = info[start].cluster;
 
   for (unsigned int i = start + 1; i < end; i++)
-    cluster = MIN (cluster, info[i].cluster);
+    cluster = MIN<unsigned int>(cluster, info[i].cluster);
 
   /* Extend end */
   while (end < len && info[end - 1].cluster == info[end].cluster)
@@ -585,7 +585,7 @@
   unsigned int cluster = out_info[start].cluster;
 
   for (unsigned int i = start + 1; i < end; i++)
-    cluster = MIN (cluster, out_info[i].cluster);
+    cluster = MIN<unsigned int>(cluster, out_info[i].cluster);
 
   /* Extend start */
   while (start && out_info[start - 1].cluster == out_info[start].cluster)
@@ -722,6 +722,7 @@
     return hb_buffer_get_empty ();
 
   buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
+  buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
 
   buffer->reset ();
 
@@ -741,22 +742,23 @@
 hb_buffer_get_empty (void)
 {
   static const hb_buffer_t _hb_buffer_nil = {
-    HB_OBJECT_HEADER_STATIC,
+      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,
+      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 */
+      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. */
+      /* Zero is good enough for everything else. */
   };
 
   return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
diff --git a/third_party/harfbuzz-ng/src/hb-common.cc b/third_party/harfbuzz-ng/src/hb-common.cc
index 2f9b3b8..c8e3d60 100644
--- a/third_party/harfbuzz-ng/src/hb-common.cc
+++ b/third_party/harfbuzz-ng/src/hb-common.cc
@@ -85,7 +85,7 @@
   for (; i < 4; i++)
     tag[i] = ' ';
 
-  return HB_TAG_CHAR4 (tag);
+  return HB_TAG(tag[0], tag[1], tag[2], tag[3]);
 }
 
 /**
@@ -699,34 +699,41 @@
 
 #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 locale_t C_locale;
+static HB_LOCALE_T C_locale;
 
 #ifdef HB_USE_ATEXIT
 static void
 free_C_locale (void)
 {
   if (C_locale)
-    freelocale (C_locale);
+    HB_FREE_LOCALE(C_locale);
 }
 #endif
 
-static locale_t
-get_C_locale (void)
-{
+static HB_LOCALE_T get_C_locale(void) {
 retry:
-  locale_t C = (locale_t) hb_atomic_ptr_get (&C_locale);
+  HB_LOCALE_T C = (HB_LOCALE_T)hb_atomic_ptr_get(&C_locale);
 
   if (unlikely (!C))
   {
-    C = newlocale (LC_ALL_MASK, "C", nullptr);
+    C = HB_CREATE_LOCALE("C");
 
     if (!hb_atomic_ptr_cmpexch (&C_locale, nullptr, C))
     {
-      freelocale (C_locale);
+      HB_FREE_LOCALE(C_locale);
       goto retry;
     }
 
diff --git a/third_party/harfbuzz-ng/src/hb-coretext.cc b/third_party/harfbuzz-ng/src/hb-coretext.cc
index be08373..62b79da 100644
--- a/third_party/harfbuzz-ng/src/hb-coretext.cc
+++ b/third_party/harfbuzz-ng/src/hb-coretext.cc
@@ -27,19 +27,16 @@
  */
 
 #define HB_SHAPER coretext
+
+#include "hb-debug.hh"
+#include "hb-private.hh"
 #include "hb-shaper-impl-private.hh"
 
 #include "hb-coretext.h"
 #include <math.h>
 
-
-#ifndef HB_DEBUG_CORETEXT
-#define HB_DEBUG_CORETEXT (HB_DEBUG+0)
-#endif
-
 /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
-/* Temporarily patched to original size 36.f that was used before to ease Blink reabaselining. */
-#define HB_CORETEXT_DEFAULT_FONT_SIZE 36.f
+#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
 
 static CGFloat
 coretext_font_size (float ptem)
@@ -84,21 +81,12 @@
   CGFontRelease ((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);
-}
 
 HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
 HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
 	fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size (font->ptem)) <= .5
 )
 
-/*
- * shaper face data
- */
-
 static CTFontDescriptorRef
 get_last_resort_font_desc (void)
 {
@@ -270,6 +258,11 @@
   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
  */
@@ -281,10 +274,6 @@
 }
 
 
-/*
- * shaper font data
- */
-
 hb_coretext_shaper_font_data_t *
 _hb_coretext_shaper_font_data_create (hb_font_t *font)
 {
@@ -309,6 +298,30 @@
   CFRelease ((CTFontRef) data);
 }
 
+/*
+ * Since: 1.7.2
+ */
+hb_font_t* hb_coretext_font_create(CTFontRef ct_font) {
+  CGFontRef cg_font = CTFontCopyGraphicsFont(ct_font, 0);
+  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;
+
+  /* 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
@@ -331,13 +344,6 @@
 {
 }
 
-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
@@ -352,7 +358,9 @@
   feature_record_t rec;
   unsigned int order;
 
-  static int cmp (const active_feature_t *a, const active_feature_t *b) {
+  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 :
@@ -368,7 +376,9 @@
   bool start;
   active_feature_t feature;
 
-  static int cmp (const feature_event_t *a, const feature_event_t *b) {
+  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);
@@ -979,32 +989,34 @@
       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/behdad/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++)
+        /* 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;
@@ -1261,6 +1273,8 @@
     }
   }
 
+  buffer->unsafe_to_break_all();
+
 #undef FAIL
 
 fail:
diff --git a/third_party/harfbuzz-ng/src/hb-coretext.h b/third_party/harfbuzz-ng/src/hb-coretext.h
index c9136ff4..67eeccbc 100644
--- a/third_party/harfbuzz-ng/src/hb-coretext.h
+++ b/third_party/harfbuzz-ng/src/hb-coretext.h
@@ -48,6 +48,7 @@
 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);
diff --git a/third_party/harfbuzz-ng/src/hb-debug.hh b/third_party/harfbuzz-ng/src/hb-debug.hh
new file mode 100644
index 0000000..20dead65
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-debug.hh
@@ -0,0 +1,421 @@
+/*
+ * 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, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) 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>;
+
+/* 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_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_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-dsalgs.hh b/third_party/harfbuzz-ng/src/hb-dsalgs.hh
new file mode 100644
index 0000000..e4138475
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-dsalgs.hh
@@ -0,0 +1,161 @@
+/*
+ * 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-ft.cc b/third_party/harfbuzz-ng/src/hb-ft.cc
index f578e9d..16a4a840 100644
--- a/third_party/harfbuzz-ng/src/hb-ft.cc
+++ b/third_party/harfbuzz-ng/src/hb-ft.cc
@@ -27,6 +27,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
+#include "hb-debug.hh"
 #include "hb-private.hh"
 
 #include "hb-ft.h"
@@ -38,12 +39,6 @@
 #include FT_TRUETYPE_TABLES_H
 
 
-
-#ifndef HB_DEBUG_FT
-#define HB_DEBUG_FT (HB_DEBUG+0)
-#endif
-
-
 /* TODO:
  *
  * In general, this file does a fine job of what it's supposed to do.
diff --git a/third_party/harfbuzz-ng/src/hb-glib.cc b/third_party/harfbuzz-ng/src/hb-glib.cc
index 5b0a1eb..aca8df7 100644
--- a/third_party/harfbuzz-ng/src/hb-glib.cc
+++ b/third_party/harfbuzz-ng/src/hb-glib.cc
@@ -364,22 +364,44 @@
   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)
 {
-  static const hb_unicode_funcs_t _hb_glib_unicode_funcs = {
-    HB_OBJECT_HEADER_STATIC,
+retry:
+  hb_unicode_funcs_t* funcs =
+      (hb_unicode_funcs_t*)hb_atomic_ptr_get(&static_glib_funcs);
 
-    nullptr, /* parent */
-    true, /* immutable */
-    {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_glib_unicode_##name,
-      HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+  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 const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
+  return hb_unicode_funcs_reference(funcs);
 }
 
 #if GLIB_CHECK_VERSION(2,31,10)
diff --git a/third_party/harfbuzz-ng/src/hb-graphite2.cc b/third_party/harfbuzz-ng/src/hb-graphite2.cc
index 6f0598d..3e4a523 100644
--- a/third_party/harfbuzz-ng/src/hb-graphite2.cc
+++ b/third_party/harfbuzz-ng/src/hb-graphite2.cc
@@ -306,7 +306,8 @@
   {
     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);
@@ -331,8 +332,10 @@
       c->num_glyphs = 0;
       if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
         c->advance = curradv - gr_slot_origin_X(is);
-      else
-        clusters[ci].advance = gr_slot_origin_X(is) - curradv;
+      else {
+        c->advance = 0;
+        clusters[ci].advance += gr_slot_origin_X(is) - curradv;
+      }
       ci++;
       curradv = gr_slot_origin_X(is);
     }
@@ -345,7 +348,7 @@
   if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
     clusters[ci].advance += curradv;
   else
-    clusters[ci].advance = gr_seg_advance_X(seg) - curradv;
+    clusters[ci].advance += gr_seg_advance_X(seg) - curradv;
   ci++;
 
   for (unsigned int i = 0; i < ci; ++i)
@@ -411,5 +414,7 @@
   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-icu.cc b/third_party/harfbuzz-ng/src/hb-icu.cc
index 01d15f4..6c54a61 100644
--- a/third_party/harfbuzz-ng/src/hb-icu.cc
+++ b/third_party/harfbuzz-ng/src/hb-icu.cc
@@ -344,28 +344,51 @@
   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)
 {
-  static const hb_unicode_funcs_t _hb_icu_unicode_funcs = {
-    HB_OBJECT_HEADER_STATIC,
+retry:
+  hb_unicode_funcs_t* funcs =
+      (hb_unicode_funcs_t*)hb_atomic_ptr_get(&static_icu_funcs);
 
-    nullptr, /* parent */
-    true, /* immutable */
-    {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_icu_unicode_##name,
-      HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
+  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
   };
 
-#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
-  return const_cast<hb_unicode_funcs_t *> (&_hb_icu_unicode_funcs);
+  return hb_unicode_funcs_reference(funcs);
 }
diff --git a/third_party/harfbuzz-ng/src/hb-object-private.hh b/third_party/harfbuzz-ng/src/hb-object-private.hh
index d678ae3..baa1f8f 100644
--- a/third_party/harfbuzz-ng/src/hb-object-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-object-private.hh
@@ -33,18 +33,12 @@
 #define HB_OBJECT_PRIVATE_HH
 
 #include "hb-private.hh"
+#include "hb-debug.hh"
 
 #include "hb-atomic-private.hh"
 #include "hb-mutex-private.hh"
 
 
-/* Debug */
-
-#ifndef HB_DEBUG_OBJECT
-#define HB_DEBUG_OBJECT (HB_DEBUG+0)
-#endif
-
-
 /* reference_count */
 
 #define HB_REFERENCE_COUNT_INERT_VALUE -1
diff --git a/third_party/harfbuzz-ng/src/hb-open-file-private.hh b/third_party/harfbuzz-ng/src/hb-open-file-private.hh
index dcfdfd6..644e0b4 100644
--- a/third_party/harfbuzz-ng/src/hb-open-file-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-open-file-private.hh
@@ -53,6 +53,9 @@
 
 typedef struct TableRecord
 {
+  int cmp (Tag t) const
+  { return t.cmp (tag); }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -61,9 +64,9 @@
 
   Tag		tag;		/* 4-byte identifier. */
   CheckSum	checkSum;	/* CheckSum for this table. */
-  ULONG		offset;		/* Offset from beginning of TrueType font
+  UINT32		offset;		/* Offset from beginning of TrueType font
 				 * file. */
-  ULONG		length;		/* Length of this table. */
+  UINT32		length;		/* Length of this table. */
   public:
   DEFINE_SIZE_STATIC (16);
 } OpenTypeTable;
@@ -73,10 +76,9 @@
   friend struct OpenTypeFontFile;
 
   inline unsigned int get_table_count (void) const
-  { return numTables; }
+  { return tables.len; }
   inline const TableRecord& get_table (unsigned int i) const
   {
-    if (unlikely (i >= numTables)) return Null(TableRecord);
     return tables[i];
   }
   inline unsigned int get_table_tags (unsigned int start_offset,
@@ -85,33 +87,28 @@
   {
     if (table_count)
     {
-      if (start_offset >= numTables)
+      if (start_offset >= tables.len)
         *table_count = 0;
       else
-        *table_count = MIN (*table_count, numTables - start_offset);
+        *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);
 
-      const TableRecord *sub_tables = tables + 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 numTables;
+    return tables.len;
   }
   inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
   {
     Tag t;
     t.set (tag);
-    unsigned int count = numTables;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (t == tables[i].tag)
-      {
-        if (table_index) *table_index = i;
-        return true;
-      }
-    }
-    if (table_index) *table_index = Index::NOT_FOUND_INDEX;
-    return false;
+    /* 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
   {
@@ -124,16 +121,13 @@
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables));
+    return_trace (c->check_struct (this) && tables.sanitize (c));
   }
 
   protected:
   Tag		sfnt_version;	/* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
-  USHORT	numTables;	/* Number of tables. */
-  USHORT	searchRangeZ;	/* (Maximum power of 2 <= numTables) x 16 */
-  USHORT	entrySelectorZ;	/* Log2(maximum power of 2 <= numTables). */
-  USHORT	rangeShiftZ;	/* NumTables x 16-searchRange. */
-  TableRecord	tables[VAR];	/* TableRecord entries. numTables items */
+  BinSearchArrayOf<TableRecord>
+		tables;
   public:
   DEFINE_SIZE_ARRAY (12, tables);
 } OpenTypeFontFace;
@@ -160,7 +154,7 @@
   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
   FixedVersion<>version;	/* Version of the TTC Header (1.0),
 				 * 0x00010000u */
-  ArrayOf<LOffsetTo<OffsetTable>, ULONG>
+  ArrayOf<LOffsetTo<OffsetTable>, UINT32>
 		table;		/* Array of offsets to the OffsetTable for each font
 				 * from the beginning of the file */
   public:
diff --git a/third_party/harfbuzz-ng/src/hb-open-type-private.hh b/third_party/harfbuzz-ng/src/hb-open-type-private.hh
index f25341a..2f4e1b9e 100644
--- a/third_party/harfbuzz-ng/src/hb-open-type-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-open-type-private.hh
@@ -30,6 +30,7 @@
 #define HB_OPEN_TYPE_PRIVATE_HH
 
 #include "hb-private.hh"
+#include "hb-debug.hh"
 #include "hb-face-private.hh"
 
 
@@ -130,14 +131,16 @@
  */
 
 /* Global nul-content Null pool.  Enlarge as necessary. */
-/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */
-static const void *_NullPool[(256+8) / sizeof (void *)];
+
+#define HB_NULL_POOL_SIZE 264
+static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE.");
+extern HB_INTERNAL const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)];
 
 /* Generic nul-content Null objects. */
 template <typename Type>
 static inline const Type& Null (void) {
-  static_assert ((sizeof (Type) <= sizeof (_NullPool)), "");
-  return *CastP<Type> (_NullPool);
+  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. */
@@ -172,16 +175,6 @@
  * Sanitize
  */
 
-#ifndef HB_DEBUG_SANITIZE
-#define HB_DEBUG_SANITIZE (HB_DEBUG+0)
-#endif
-
-
-#define TRACE_SANITIZE(this) \
-	hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
-	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 "");
-
 /* This limits sanitizing time on really broken fonts. */
 #ifndef HB_SANITIZE_MAX_EDITS
 #define HB_SANITIZE_MAX_EDITS 32
@@ -385,16 +378,6 @@
  * Serialize
  */
 
-#ifndef HB_DEBUG_SERIALIZE
-#define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
-#endif
-
-
-#define TRACE_SERIALIZE(this) \
-	hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
-	(&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
-	 "");
-
 
 struct hb_serialize_context_t
 {
@@ -632,10 +615,11 @@
   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); }
-  inline int cmp (Type a) const
+  template <typename Type2>
+  inline int cmp (Type2 a) const
   {
     Type b = v;
-    if (sizeof (Type) < sizeof (int))
+    if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
       return (int) a - (int) b;
     else
       return a < b ? -1 : a == b ? 0 : +1;
@@ -651,23 +635,22 @@
   DEFINE_SIZE_STATIC (Size);
 };
 
-typedef	IntType<int8_t	, 1> CHAR;	/* 8-bit signed integer. */
-typedef	IntType<uint8_t	, 1> BYTE;	/* 8-bit unsigned integer. */
-typedef	IntType<int8_t	, 1> INT8;	/* 8-bit signed integer. */
-typedef IntType<uint16_t, 2> USHORT;	/* 16-bit unsigned integer. */
-typedef IntType<int16_t,  2> SHORT;	/* 16-bit signed integer. */
-typedef IntType<uint32_t, 4> ULONG;	/* 32-bit unsigned integer. */
-typedef IntType<int32_t,  4> LONG;	/* 32-bit signed integer. */
+typedef IntType<uint8_t,  1> UINT8;	/* 8-bit unsigned integer. */
+typedef IntType<int8_t,   1> INT8;	/* 8-bit signed integer. */
+typedef IntType<uint16_t, 2> UINT16;	/* 16-bit unsigned integer. */
+typedef IntType<int16_t,  2> INT16;	/* 16-bit signed integer. */
+typedef IntType<uint32_t, 4> UINT32;	/* 32-bit unsigned integer. */
+typedef IntType<int32_t,  4> INT32;	/* 32-bit signed integer. */
 typedef IntType<uint32_t, 3> UINT24;	/* 24-bit unsigned integer. */
 
-/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
-typedef SHORT FWORD;
+/* 16-bit signed integer (INT16) that describes a quantity in FUnits. */
+typedef INT16 FWORD;
 
-/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
-typedef USHORT UFWORD;
+/* 16-bit unsigned integer (UINT16) that describes a quantity in FUnits. */
+typedef UINT16 UFWORD;
 
 /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
-struct F2DOT14 : SHORT
+struct F2DOT14 : INT16
 {
   //inline float to_float (void) const { return ???; }
   //inline void set_float (float f) { v.set (f * ???); }
@@ -676,7 +659,7 @@
 };
 
 /* 32-bit signed fixed-point number (16.16). */
-struct Fixed: LONG
+struct Fixed: INT32
 {
   //inline float to_float (void) const { return ???; }
   //inline void set_float (float f) { v.set (f * ???); }
@@ -694,15 +677,15 @@
     return_trace (likely (c->check_struct (this)));
   }
   protected:
-  LONG major;
-  ULONG minor;
+  INT32 major;
+  UINT32 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 : ULONG
+struct Tag : UINT32
 {
   /* 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); }
@@ -713,19 +696,16 @@
 DEFINE_NULL_DATA (Tag, "    ");
 
 /* Glyph index number, same as uint16 (length = 16 bits) */
-struct GlyphID : USHORT {
-  static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT::cmp (*a); }
-  inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; }
-};
+typedef UINT16 GlyphID;
 
 /* Script/language-system/feature index */
-struct Index : USHORT {
+struct Index : UINT16 {
   static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
 };
 DEFINE_NULL_DATA (Index, "\xff\xff");
 
 /* Offset, Null offset = 0 */
-template <typename Type=USHORT>
+template <typename Type>
 struct Offset : Type
 {
   inline bool is_null (void) const { return 0 == *this; }
@@ -733,15 +713,18 @@
   DEFINE_SIZE_STATIC (sizeof(Type));
 };
 
+typedef Offset<UINT16> Offset16;
+typedef Offset<UINT32> Offset32;
+
 
 /* CheckSum */
-struct CheckSum : ULONG
+struct CheckSum : UINT32
 {
   /* This is reference implementation from the spec. */
-  static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length)
+  static inline uint32_t CalcTableChecksum (const UINT32 *Table, uint32_t Length)
   {
     uint32_t Sum = 0L;
-    const ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size;
+    const UINT32 *EndPtr = Table+((Length+3) & ~3) / UINT32::static_size;
 
     while (Table < EndPtr)
       Sum += *Table++;
@@ -750,7 +733,7 @@
 
   /* 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 ULONG *) data, length)); }
+  { set (CalcTableChecksum ((const UINT32 *) data, length)); }
 
   public:
   DEFINE_SIZE_STATIC (4);
@@ -761,7 +744,7 @@
  * Version Numbers
  */
 
-template <typename FixedType=USHORT>
+template <typename FixedType=UINT16>
 struct FixedVersion
 {
   inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; }
@@ -785,7 +768,7 @@
  * Use: (base+offset)
  */
 
-template <typename Type, typename OffsetType=USHORT>
+template <typename Type, typename OffsetType=UINT16>
 struct OffsetTo : Offset<OffsetType>
 {
   inline const Type& operator () (const void *base) const
@@ -830,7 +813,7 @@
   }
   DEFINE_SIZE_STATIC (sizeof(OffsetType));
 };
-template <typename Type> struct LOffsetTo : OffsetTo<Type, ULONG> {};
+template <typename Type> struct LOffsetTo : OffsetTo<Type, UINT32> {};
 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>
@@ -842,7 +825,7 @@
  */
 
 /* An array with a number of elements. */
-template <typename Type, typename LenType=USHORT>
+template <typename Type, typename LenType=UINT16>
 struct ArrayOf
 {
   const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
@@ -943,7 +926,7 @@
   inline bool sanitize_shallow (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && c->check_array (array, Type::static_size, len));
+    return_trace (len.sanitize (c) && c->check_array (array, Type::static_size, len));
   }
 
   public:
@@ -952,10 +935,10 @@
   public:
   DEFINE_SIZE_ARRAY (sizeof (LenType), array);
 };
-template <typename Type> struct LArrayOf : ArrayOf<Type, ULONG> {};
+template <typename Type> struct LArrayOf : ArrayOf<Type, UINT32> {};
 
 /* Array of Offset's */
-template <typename Type, typename OffsetType=USHORT>
+template <typename Type, typename OffsetType=UINT16>
 struct OffsetArrayOf : ArrayOf<OffsetTo<Type, OffsetType> > {};
 
 /* Array of offsets relative to the beginning of the array itself. */
@@ -983,7 +966,7 @@
 
 
 /* An array starting at second element. */
-template <typename Type, typename LenType=USHORT>
+template <typename Type, typename LenType=UINT16>
 struct HeadlessArrayOf
 {
   inline const Type& operator [] (unsigned int i) const
@@ -1009,12 +992,6 @@
     return_trace (true);
   }
 
-  inline bool sanitize_shallow (hb_sanitize_context_t *c) const
-  {
-    return c->check_struct (this)
-	&& c->check_array (this, Type::static_size, len);
-  }
-
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -1032,6 +1009,15 @@
     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:
@@ -1039,8 +1025,10 @@
 };
 
 
-/* An array with sorted elements.  Supports binary searching. */
-template <typename Type, typename LenType=USHORT>
+/*
+ * An array with sorted elements.  Supports binary searching.
+ */
+template <typename Type, typename LenType=UINT16>
 struct SortedArrayOf : ArrayOf<Type, LenType>
 {
   template <typename SearchType>
@@ -1064,6 +1052,33 @@
   }
 };
 
+/*
+ * 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));
+  }
+
+  protected:
+  UINT16	len;
+  UINT16	searchRangeZ;
+  UINT16	entrySelectorZ;
+  UINT16	rangeShiftZ;
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+template <typename Type>
+struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader> {};
+
 
 /* Lazy struct and blob loaders. */
 
diff --git a/third_party/harfbuzz-ng/src/hb-ot-cbdt-table.hh b/third_party/harfbuzz-ng/src/hb-ot-cbdt-table.hh
index 3c6855b0..415625e 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-cbdt-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-cbdt-table.hh
@@ -47,20 +47,20 @@
     extents->height = -height;
   }
 
-  BYTE height;
-  BYTE width;
-  CHAR bearingX;
-  CHAR bearingY;
-  BYTE advance;
+  UINT8 height;
+  UINT8 width;
+  INT8 bearingX;
+  INT8 bearingY;
+  UINT8 advance;
 
   DEFINE_SIZE_STATIC(5);
 };
 
 struct BigGlyphMetrics : SmallGlyphMetrics
 {
-  CHAR vertBearingX;
-  CHAR vertBearingY;
-  BYTE vertAdvance;
+  INT8 vertBearingX;
+  INT8 vertBearingY;
+  UINT8 vertAdvance;
 
   DEFINE_SIZE_STATIC(8);
 };
@@ -73,18 +73,18 @@
     return_trace (c->check_struct (this));
   }
 
-  CHAR ascender;
-  CHAR decender;
-  BYTE widthMax;
-  CHAR caretSlopeNumerator;
-  CHAR caretSlopeDenominator;
-  CHAR caretOffset;
-  CHAR minOriginSB;
-  CHAR minAdvanceSB;
-  CHAR maxBeforeBL;
-  CHAR minAfterBL;
-  CHAR padding1;
-  CHAR padding2;
+  INT8 ascender;
+  INT8 decender;
+  UINT8 widthMax;
+  INT8 caretSlopeNumerator;
+  INT8 caretSlopeDenominator;
+  INT8 caretOffset;
+  INT8 minOriginSB;
+  INT8 minAdvanceSB;
+  INT8 maxBeforeBL;
+  INT8 minAfterBL;
+  INT8 padding1;
+  INT8 padding2;
 
   DEFINE_SIZE_STATIC(12);
 };
@@ -102,9 +102,9 @@
     return_trace (c->check_struct (this));
   }
 
-  USHORT indexFormat;
-  USHORT imageFormat;
-  ULONG imageDataOffset;
+  UINT16 indexFormat;
+  UINT16 imageFormat;
+  UINT32 imageDataOffset;
 
   DEFINE_SIZE_STATIC(8);
 };
@@ -137,8 +137,8 @@
   DEFINE_SIZE_ARRAY(8, offsetArrayZ);
 };
 
-struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<ULONG> {};
-struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<USHORT> {};
+struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<UINT32> {};
+struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<UINT16> {};
 
 struct IndexSubtable
 {
@@ -214,8 +214,8 @@
 						   offset, length, format);
   }
 
-  USHORT firstGlyphIndex;
-  USHORT lastGlyphIndex;
+  UINT16 firstGlyphIndex;
+  UINT16 lastGlyphIndex;
   LOffsetTo<IndexSubtable> offsetToSubtable;
 
   DEFINE_SIZE_STATIC(8);
@@ -276,19 +276,19 @@
 
   protected:
   LOffsetTo<IndexSubtableArray> indexSubtableArrayOffset;
-  ULONG indexTablesSize;
-  ULONG numberOfIndexSubtables;
-  ULONG colorRef;
+  UINT32 indexTablesSize;
+  UINT32 numberOfIndexSubtables;
+  UINT32 colorRef;
   SBitLineMetrics horizontal;
   SBitLineMetrics vertical;
-  USHORT startGlyphIndex;
-  USHORT endGlyphIndex;
-  BYTE ppemX;
-  BYTE ppemY;
-  BYTE bitDepth;
-  CHAR flags;
+  UINT16 startGlyphIndex;
+  UINT16 endGlyphIndex;
+  UINT8 ppemX;
+  UINT8 ppemY;
+  UINT8 bitDepth;
+  INT8 flags;
 
-public:
+  public:
   DEFINE_SIZE_STATIC(48);
 };
 
@@ -300,8 +300,8 @@
 struct GlyphBitmapDataFormat17
 {
   SmallGlyphMetrics glyphMetrics;
-  ULONG dataLen;
-  BYTE dataZ[VAR];
+  UINT32 dataLen;
+  UINT8 dataZ[VAR];
 
   DEFINE_SIZE_ARRAY(9, dataZ);
 };
@@ -315,6 +315,8 @@
 
 struct CBLC
 {
+  friend struct CBDT;
+
   static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -325,7 +327,7 @@
 		  sizeTables.sanitize (c, this));
   }
 
-  public:
+  protected:
   const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
 					 unsigned int *x_ppem, unsigned int *y_ppem) const
   {
@@ -371,9 +373,94 @@
 		  likely (version.major == 2 || version.major == 3));
   }
 
+  struct accelerator_t
+  {
+    inline void init (hb_face_t *face)
+    {
+      upem = face->get_upem();
+
+      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;
-  BYTE dataZ[VAR];
+  UINT8 dataZ[VAR];
 
   public:
   DEFINE_SIZE_ARRAY(4, dataZ);
diff --git a/third_party/harfbuzz-ng/src/hb-ot-cmap-table.hh b/third_party/harfbuzz-ng/src/hb-ot-cmap-table.hh
index 93f38c56..883d7b3 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-cmap-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-cmap-table.hh
@@ -58,10 +58,10 @@
   }
 
   protected:
-  USHORT	format;		/* Format number is set to 0. */
-  USHORT	lengthZ;	/* Byte length of this subtable. */
-  USHORT	languageZ;	/* Ignore. */
-  BYTE		glyphIdArray[256];/* An array that maps character
+  UINT16	format;		/* Format number is set to 0. */
+  UINT16	lengthZ;	/* Byte length of this subtable. */
+  UINT16	languageZ;	/* Ignore. */
+  UINT8		glyphIdArray[256];/* An array that maps character
 				 * code to glyph index values. */
   public:
   DEFINE_SIZE_STATIC (6 + 256);
@@ -88,8 +88,8 @@
 
       /* Custom two-array bsearch. */
       int min = 0, max = (int) thiz->segCount - 1;
-      const USHORT *startCount = thiz->startCount;
-      const USHORT *endCount = thiz->endCount;
+      const UINT16 *startCount = thiz->startCount;
+      const UINT16 *endCount = thiz->endCount;
       unsigned int i;
       while (min <= max)
       {
@@ -127,11 +127,11 @@
       return true;
     }
 
-    const USHORT *endCount;
-    const USHORT *startCount;
-    const USHORT *idDelta;
-    const USHORT *idRangeOffset;
-    const USHORT *glyphIdArray;
+    const UINT16 *endCount;
+    const UINT16 *startCount;
+    const UINT16 *idDelta;
+    const UINT16 *idRangeOffset;
+    const UINT16 *glyphIdArray;
     unsigned int segCount;
     unsigned int glyphIdArrayLength;
   };
@@ -165,24 +165,24 @@
   }
 
   protected:
-  USHORT	format;		/* Format number is set to 4. */
-  USHORT	length;		/* This is the length in bytes of the
+  UINT16	format;		/* Format number is set to 4. */
+  UINT16	length;		/* This is the length in bytes of the
 				 * subtable. */
-  USHORT	languageZ;	/* Ignore. */
-  USHORT	segCountX2;	/* 2 x segCount. */
-  USHORT	searchRangeZ;	/* 2 * (2**floor(log2(segCount))) */
-  USHORT	entrySelectorZ;	/* log2(searchRange/2) */
-  USHORT	rangeShiftZ;	/* 2 x segCount - searchRange */
+  UINT16	languageZ;	/* Ignore. */
+  UINT16	segCountX2;	/* 2 x segCount. */
+  UINT16	searchRangeZ;	/* 2 * (2**floor(log2(segCount))) */
+  UINT16	entrySelectorZ;	/* log2(searchRange/2) */
+  UINT16	rangeShiftZ;	/* 2 x segCount - searchRange */
 
-  USHORT	values[VAR];
+  UINT16	values[VAR];
 #if 0
-  USHORT	endCount[segCount];	/* End characterCode for each segment,
+  UINT16	endCount[segCount];	/* End characterCode for each segment,
 					 * last=0xFFFFu. */
-  USHORT	reservedPad;		/* Set to 0. */
-  USHORT	startCount[segCount];	/* Start character code for each segment. */
-  SHORT		idDelta[segCount];	/* Delta for all character codes in segment. */
-  USHORT	idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
-  USHORT	glyphIdArray[VAR];	/* Glyph index array (arbitrary length) */
+  UINT16	reservedPad;		/* Set to 0. */
+  UINT16	startCount[segCount];	/* Start character code for each segment. */
+  INT16		idDelta[segCount];	/* Delta for all character codes in segment. */
+  UINT16	idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
+  UINT16	glyphIdArray[VAR];	/* Glyph index array (arbitrary length) */
 #endif
 
   public:
@@ -208,9 +208,9 @@
   }
 
   private:
-  ULONG		startCharCode;	/* First character code in this group. */
-  ULONG		endCharCode;	/* Last character code in this group. */
-  ULONG		glyphID;	/* Glyph index; interpretation depends on
+  UINT32		startCharCode;	/* First character code in this group. */
+  UINT32		endCharCode;	/* Last character code in this group. */
+  UINT32		glyphID;	/* Glyph index; interpretation depends on
 				 * subtable format. */
   public:
   DEFINE_SIZE_STATIC (12);
@@ -247,8 +247,8 @@
   DEFINE_SIZE_ARRAY (5 * sizeof (UINT), glyphIdArray);
 };
 
-struct CmapSubtableFormat6  : CmapSubtableTrimmed<USHORT> {};
-struct CmapSubtableFormat10 : CmapSubtableTrimmed<ULONG > {};
+struct CmapSubtableFormat6  : CmapSubtableTrimmed<UINT16> {};
+struct CmapSubtableFormat10 : CmapSubtableTrimmed<UINT32 > {};
 
 template <typename T>
 struct CmapSubtableLongSegmented
@@ -269,11 +269,11 @@
   }
 
   protected:
-  USHORT	format;		/* Subtable format; set to 12. */
-  USHORT	reservedZ;	/* Reserved; set to 0. */
-  ULONG		lengthZ;	/* Byte length of this subtable. */
-  ULONG		languageZ;	/* Ignore. */
-  SortedArrayOf<CmapSubtableLongGroup, ULONG>
+  UINT16	format;		/* Subtable format; set to 12. */
+  UINT16	reservedZ;	/* Reserved; set to 0. */
+  UINT32		lengthZ;	/* Byte length of this subtable. */
+  UINT32		languageZ;	/* Ignore. */
+  SortedArrayOf<CmapSubtableLongGroup, UINT32>
 		groups;		/* Groupings. */
   public:
   DEFINE_SIZE_ARRAY (16, groups);
@@ -316,13 +316,13 @@
   }
 
   UINT24	startUnicodeValue;	/* First value in this range. */
-  BYTE		additionalCount;	/* Number of additional values in this
+  UINT8		additionalCount;	/* Number of additional values in this
 					 * range. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
-typedef SortedArrayOf<UnicodeValueRange, ULONG> DefaultUVS;
+typedef SortedArrayOf<UnicodeValueRange, UINT32> DefaultUVS;
 
 struct UVSMapping
 {
@@ -343,7 +343,7 @@
   DEFINE_SIZE_STATIC (5);
 };
 
-typedef SortedArrayOf<UVSMapping, ULONG> NonDefaultUVS;
+typedef SortedArrayOf<UVSMapping, UINT32> NonDefaultUVS;
 
 struct VariationSelectorRecord
 {
@@ -405,9 +405,9 @@
   }
 
   protected:
-  USHORT	format;		/* Format number is set to 14. */
-  ULONG		lengthZ;	/* Byte length of this subtable. */
-  SortedArrayOf<VariationSelectorRecord, ULONG>
+  UINT16	format;		/* Format number is set to 14. */
+  UINT32		lengthZ;	/* Byte length of this subtable. */
+  SortedArrayOf<VariationSelectorRecord, UINT32>
 		record;		/* Variation selector records; sorted
 				 * in increasing order of `varSelector'. */
   public:
@@ -451,7 +451,7 @@
 
   public:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   CmapSubtableFormat0	format0;
   CmapSubtableFormat4	format4;
   CmapSubtableFormat6	format6;
@@ -484,8 +484,8 @@
 		  subtable.sanitize (c, base));
   }
 
-  USHORT	platformID;	/* Platform ID. */
-  USHORT	encodingID;	/* Platform-specific encoding ID. */
+  UINT16	platformID;	/* Platform ID. */
+  UINT16	encodingID;	/* Platform-specific encoding ID. */
   LOffsetTo<CmapSubtable>
 		subtable;	/* Byte offset from beginning of table to the subtable for this encoding. */
   public:
@@ -496,6 +496,146 @@
 {
   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));
+  }
+
+  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
   {
@@ -513,15 +653,8 @@
     return &(this+encodingRecord[result].subtable);
   }
 
-  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));
-  }
-
-  USHORT		version;	/* Table version number (0). */
+  protected:
+  UINT16		version;	/* Table version number (0). */
   SortedArrayOf<EncodingRecord>
 			encodingRecord;	/* Encoding tables. */
   public:
diff --git a/third_party/harfbuzz-ng/src/hb-ot-font.cc b/third_party/harfbuzz-ng/src/hb-ot-font.cc
index c0ce89d..c818a07 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-font.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-font.cc
@@ -30,447 +30,22 @@
 
 #include "hb-font-private.hh"
 
-#include "hb-ot-cmap-table.hh"
 #include "hb-ot-cbdt-table.hh"
+#include "hb-ot-cmap-table.hh"
 #include "hb-ot-glyf-table.hh"
-#include "hb-ot-head-table.hh"
-#include "hb-ot-hhea-table.hh"
 #include "hb-ot-hmtx-table.hh"
-#include "hb-ot-os2-table.hh"
-#include "hb-ot-var-hvar-table.hh"
+#include "hb-ot-kern-table.hh"
 #include "hb-ot-post-table.hh"
 
-
-struct hb_ot_face_metrics_accelerator_t
-{
-  unsigned int num_metrics;
-  unsigned int num_advances;
-  unsigned int default_advance;
-  unsigned short ascender;
-  unsigned short descender;
-  unsigned short line_gap;
-  bool has_font_extents;
-
-  const OT::hmtxvmtx *table;
-  hb_blob_t *blob;
-
-  const OT::HVARVVAR *var;
-  hb_blob_t *var_blob;
-
-  inline void init (hb_face_t *face,
-		    hb_tag_t _hea_tag,
-		    hb_tag_t _mtx_tag,
-		    hb_tag_t _var_tag,
-		    hb_tag_t os2_tag,
-		    unsigned int default_advance = 0)
-  {
-    this->default_advance = default_advance ? default_advance : face->get_upem ();
-
-    bool got_font_extents = false;
-    if (os2_tag)
-    {
-      hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>::sanitize (face->reference_table (os2_tag));
-      const OT::os2 *os2 = OT::Sanitizer<OT::os2>::lock_instance (os2_blob);
-#define USE_TYPO_METRICS (1u<<7)
-      if (0 != (os2->fsSelection & USE_TYPO_METRICS))
-      {
-	this->ascender = os2->sTypoAscender;
-	this->descender = os2->sTypoDescender;
-	this->line_gap = os2->sTypoLineGap;
-	got_font_extents = (this->ascender | this->descender) != 0;
-      }
-      hb_blob_destroy (os2_blob);
-    }
-
-    hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag));
-    const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob);
-    this->num_advances = _hea->numberOfLongMetrics;
-    if (!got_font_extents)
-    {
-      this->ascender = _hea->ascender;
-      this->descender = _hea->descender;
-      this->line_gap = _hea->lineGap;
-      got_font_extents = (this->ascender | this->descender) != 0;
-    }
-    hb_blob_destroy (_hea_blob);
-
-    this->has_font_extents = got_font_extents;
-
-    this->blob = OT::Sanitizer<OT::hmtxvmtx>::sanitize (face->reference_table (_mtx_tag));
-
-    /* Cap num_metrics() and num_advances() based on table length. */
-    unsigned int len = hb_blob_get_length (this->blob);
-    if (unlikely (this->num_advances * 4 > len))
-      this->num_advances = len / 4;
-    this->num_metrics = this->num_advances + (len - 4 * this->num_advances) / 2;
-
-    /* We MUST set num_metrics to zero if num_advances is zero.
-     * Our get_advance() depends on that. */
-    if (unlikely (!this->num_advances))
-    {
-      this->num_metrics = this->num_advances = 0;
-      hb_blob_destroy (this->blob);
-      this->blob = hb_blob_get_empty ();
-    }
-    this->table = OT::Sanitizer<OT::hmtxvmtx>::lock_instance (this->blob);
-
-    this->var_blob = OT::Sanitizer<OT::HVARVVAR>::sanitize (face->reference_table (_var_tag));
-    this->var = OT::Sanitizer<OT::HVARVVAR>::lock_instance (this->var_blob);
-  }
-
-  inline void fini (void)
-  {
-    hb_blob_destroy (this->blob);
-    hb_blob_destroy (this->var_blob);
-  }
-
-  inline unsigned int get_advance (hb_codepoint_t  glyph,
-				   hb_font_t      *font) const
-  {
-    if (unlikely (glyph >= this->num_metrics))
-    {
-      /* If this->num_metrics is zero, it means we don't have the metrics table
-       * for this direction: return default advance.  Otherwise, it means that the
-       * glyph index is out of bound: return zero. */
-      if (this->num_metrics)
-	return 0;
-      else
-	return this->default_advance;
-    }
-
-    return this->table->longMetric[MIN (glyph, (uint32_t) this->num_advances - 1)].advance
-	 + this->var->get_advance_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
-  }
-};
-
-struct hb_ot_face_glyf_accelerator_t
-{
-  bool short_offset;
-  unsigned int num_glyphs;
-  const OT::loca *loca;
-  const OT::glyf *glyf;
-  hb_blob_t *loca_blob;
-  hb_blob_t *glyf_blob;
-  unsigned int glyf_len;
-
-  inline void init (hb_face_t *face)
-  {
-    hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (face->reference_table (HB_OT_TAG_head));
-    const OT::head *head = OT::Sanitizer<OT::head>::lock_instance (head_blob);
-    if ((unsigned int) head->indexToLocFormat > 1 || head->glyphDataFormat != 0)
-    {
-      /* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
-      hb_blob_destroy (head_blob);
-      return;
-    }
-    this->short_offset = 0 == head->indexToLocFormat;
-    hb_blob_destroy (head_blob);
-
-    this->loca_blob = OT::Sanitizer<OT::loca>::sanitize (face->reference_table (HB_OT_TAG_loca));
-    this->loca = OT::Sanitizer<OT::loca>::lock_instance (this->loca_blob);
-    this->glyf_blob = OT::Sanitizer<OT::glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf));
-    this->glyf = OT::Sanitizer<OT::glyf>::lock_instance (this->glyf_blob);
-
-    this->num_glyphs = MAX (1u, hb_blob_get_length (this->loca_blob) / (this->short_offset ? 2 : 4)) - 1;
-    this->glyf_len = hb_blob_get_length (this->glyf_blob);
-  }
-
-  inline void fini (void)
-  {
-    hb_blob_destroy (this->loca_blob);
-    hb_blob_destroy (this->glyf_blob);
-  }
-
-  inline bool get_extents (hb_codepoint_t glyph,
-			   hb_glyph_extents_t *extents) const
-  {
-    if (unlikely (glyph >= this->num_glyphs))
-      return false;
-
-    unsigned int start_offset, end_offset;
-    if (this->short_offset)
-    {
-      start_offset = 2 * this->loca->u.shortsZ[glyph];
-      end_offset   = 2 * this->loca->u.shortsZ[glyph + 1];
-    }
-    else
-    {
-      start_offset = this->loca->u.longsZ[glyph];
-      end_offset   = this->loca->u.longsZ[glyph + 1];
-    }
-
-    if (start_offset > end_offset || end_offset > this->glyf_len)
-      return false;
-
-    if (end_offset - start_offset < OT::glyfGlyphHeader::static_size)
-      return true; /* Empty glyph; zero extents. */
-
-    const OT::glyfGlyphHeader &glyph_header = OT::StructAtOffset<OT::glyfGlyphHeader> (this->glyf, 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;
-  }
-};
-
-struct hb_ot_face_cbdt_accelerator_t
-{
-  hb_blob_t *cblc_blob;
-  hb_blob_t *cbdt_blob;
-  const OT::CBLC *cblc;
-  const OT::CBDT *cbdt;
-
-  unsigned int cbdt_len;
-  unsigned int upem;
-
-  inline void init (hb_face_t *face)
-  {
-    upem = face->get_upem();
-
-    cblc_blob = OT::Sanitizer<OT::CBLC>::sanitize (face->reference_table (HB_OT_TAG_CBLC));
-    cbdt_blob = OT::Sanitizer<OT::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 = OT::Sanitizer<OT::CBLC>::lock_instance (cblc_blob);
-    cbdt = OT::Sanitizer<OT::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 OT::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;
-
-    {
-      /* TODO Move the following into CBDT struct when adding more formats. */
-
-      if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
-	return false;
-
-      switch (image_format)
-      {
-	case 17: {
-	  if (unlikely (image_length < OT::GlyphBitmapDataFormat17::min_size))
-	    return false;
-
-	  const OT::GlyphBitmapDataFormat17& glyphFormat17 =
-	      OT::StructAtOffset<OT::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;
-  }
-};
-
-struct hb_ot_face_post_accelerator_t
-{
-  hb_blob_t *post_blob;
-  unsigned int post_len;
-  const OT::post *post;
-
-  inline void init (hb_face_t *face)
-  {
-    this->post_blob = OT::Sanitizer<OT::post>::sanitize (face->reference_table (HB_OT_TAG_post));
-    this->post = OT::Sanitizer<OT::post>::lock_instance (this->post_blob);
-    this->post_len = hb_blob_get_length (this->post_blob);
-  }
-
-  inline void fini (void)
-  {
-    hb_blob_destroy (this->post_blob);
-  }
-
-  inline bool get_glyph_name (hb_codepoint_t glyph,
-			      char *name, unsigned int size) const
-  {
-    return this->post->get_glyph_name (glyph, name, size, this->post_len);
-  }
-
-  inline bool get_glyph_from_name (const char *name, int len,
-				   hb_codepoint_t *glyph) const
-  {
-    if (unlikely (!len))
-      return false;
-
-    return this->post->get_glyph_from_name (name, len, glyph, this->post_len);
-  }
-};
-
-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;
-}
-
-struct hb_ot_face_cmap_accelerator_t
-{
-  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;
-
-  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);
-  }
-};
-
 struct hb_ot_font_t
 {
-  hb_ot_face_cmap_accelerator_t cmap;
-  hb_ot_face_metrics_accelerator_t h_metrics;
-  hb_ot_face_metrics_accelerator_t v_metrics;
-  OT::hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf;
-  OT::hb_lazy_loader_t<hb_ot_face_cbdt_accelerator_t> cbdt;
-  OT::hb_lazy_loader_t<hb_ot_face_post_accelerator_t> post;
+  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;
 };
 
 
@@ -483,12 +58,14 @@
     return nullptr;
 
   ot_font->cmap.init (face);
-  ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_HVAR, HB_OT_TAG_os2);
-  ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_OT_TAG_VVAR, HB_TAG_NONE,
-			   ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
+  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;
 }
@@ -504,6 +81,7 @@
   ot_font->glyf.fini ();
   ot_font->cbdt.fini ();
   ot_font->post.fini ();
+  ot_font->kern.fini();
 
   free (ot_font);
 }
@@ -553,6 +131,16 @@
   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,
@@ -650,10 +238,12 @@
     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); TODO
+    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); TODO
+    // 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);
 
diff --git a/third_party/harfbuzz-ng/src/hb-ot-glyf-table.hh b/third_party/harfbuzz-ng/src/hb-ot-glyf-table.hh
index dc7aa8469..88d3850b 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-glyf-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-glyf-table.hh
@@ -28,6 +28,7 @@
 #define HB_OT_GLYF_TABLE_HH
 
 #include "hb-open-type-private.hh"
+#include "hb-ot-head-table.hh"
 
 
 namespace OT {
@@ -42,6 +43,8 @@
 
 struct loca
 {
+  friend struct glyf;
+
   static const hb_tag_t tableTag = HB_OT_TAG_loca;
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -50,12 +53,9 @@
     return_trace (true);
   }
 
-  public:
-  union {
-    USHORT	shortsZ[VAR];		/* Location offset divided by 2. */
-    ULONG	longsZ[VAR];		/* Location offset. */
-  } u;
-  DEFINE_SIZE_ARRAY (0, u.longsZ);
+  protected:
+  UINT8		dataX[VAR];		/* Location data. */
+  DEFINE_SIZE_ARRAY (0, dataX);
 };
 
 
@@ -78,26 +78,102 @@
     return_trace (true);
   }
 
-  public:
-  BYTE		dataX[VAR];		/* Glyphs data. */
+  struct GlyphHeader
+  {
+    INT16		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 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);
+    }
+
+    inline bool get_extents (hb_codepoint_t glyph,
+			     hb_glyph_extents_t *extents) const
+    {
+      if (unlikely (glyph >= num_glyphs))
+	return false;
+
+      unsigned int start_offset, end_offset;
+      if (short_offset)
+      {
+        const UINT16 *offsets = (const UINT16 *) loca_table->dataX;
+	start_offset = 2 * offsets[glyph];
+	end_offset   = 2 * offsets[glyph + 1];
+      }
+      else
+      {
+        const UINT32 *offsets = (const UINT32 *) loca_table->dataX;
+	start_offset = offsets[glyph];
+	end_offset   = offsets[glyph + 1];
+      }
+
+      if (start_offset > end_offset || end_offset > glyf_len)
+	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:
+  UINT8		dataX[VAR];		/* Glyphs data. */
 
   DEFINE_SIZE_ARRAY (0, dataX);
 };
 
-struct glyfGlyphHeader
-{
-  SHORT		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);
-};
-
 } /* namespace OT */
 
 
diff --git a/third_party/harfbuzz-ng/src/hb-ot-head-table.hh b/third_party/harfbuzz-ng/src/hb-ot-head-table.hh
index 9c3e51eb..dd4349ef8 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-head-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-head-table.hh
@@ -64,11 +64,11 @@
   FixedVersion<>version;		/* Version of the head table--currently
 					 * 0x00010000u for version 1.0. */
   FixedVersion<>fontRevision;		/* Set by font manufacturer. */
-  ULONG		checkSumAdjustment;	/* To compute: set it to 0, sum the
-					 * entire font as ULONG, then store
+  UINT32		checkSumAdjustment;	/* To compute: set it to 0, sum the
+					 * entire font as UINT32, then store
 					 * 0xB1B0AFBAu - sum. */
-  ULONG		magicNumber;		/* Set to 0x5F0F3CF5u. */
-  USHORT	flags;			/* Bit 0: Baseline for font at y=0;
+  UINT32		magicNumber;		/* Set to 0x5F0F3CF5u. */
+  UINT16	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
@@ -114,18 +114,18 @@
 					 * encoded in the cmap subtables represent proper
 					 * support for those code points.
 					 * Bit 15: Reserved, set to 0. */
-  USHORT	unitsPerEm;		/* Valid range is from 16 to 16384. This value
+  UINT16	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 */
-  SHORT		xMin;			/* For all glyph bounding boxes. */
-  SHORT		yMin;			/* For all glyph bounding boxes. */
-  SHORT		xMax;			/* For all glyph bounding boxes. */
-  SHORT		yMax;			/* For all glyph bounding boxes. */
-  USHORT	macStyle;		/* Bit 0: Bold (if set to 1);
+  INT16		xMin;			/* For all glyph bounding boxes. */
+  INT16		yMin;			/* For all glyph bounding boxes. */
+  INT16		xMax;			/* For all glyph bounding boxes. */
+  INT16		yMax;			/* For all glyph bounding boxes. */
+  UINT16	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)
@@ -133,16 +133,16 @@
 					 * Bit 5: Condensed (if set to 1)
 					 * Bit 6: Extended (if set to 1)
 					 * Bits 7-15: Reserved (set to 0). */
-  USHORT	lowestRecPPEM;		/* Smallest readable size in pixels. */
-  SHORT		fontDirectionHint;	/* Deprecated (Set to 2).
+  UINT16	lowestRecPPEM;		/* Smallest readable size in pixels. */
+  INT16		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:
-  SHORT		indexToLocFormat;	/* 0 for short offsets, 1 for long. */
-  SHORT		glyphDataFormat;	/* 0 for current format. */
+  INT16		indexToLocFormat;	/* 0 for short offsets, 1 for long. */
+  INT16		glyphDataFormat;	/* 0 for current format. */
 
   DEFINE_SIZE_STATIC (54);
 };
diff --git a/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh b/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh
index c8e9536..dca0141 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh
@@ -44,11 +44,6 @@
 
 struct _hea
 {
-  static const hb_tag_t tableTag = HB_TAG('_','h','e','a');
-
-  static const hb_tag_t hheaTag	= HB_OT_TAG_hhea;
-  static const hb_tag_t vheaTag	= HB_OT_TAG_vhea;
-
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -69,21 +64,21 @@
 					 * (xMax - xMin)) for horizontal. */
   FWORD		maxExtent;		/* horizontal: Max(lsb + (xMax - xMin)),
 					 * vertical: minLeadingBearing+(yMax-yMin). */
-  SHORT		caretSlopeRise;		/* Used to calculate the slope of the
+  INT16		caretSlopeRise;		/* Used to calculate the slope of the
 					 * cursor (rise/run); 1 for vertical caret,
 					 * 0 for horizontal.*/
-  SHORT		caretSlopeRun;		/* 0 for vertical caret, 1 for horizontal. */
-  SHORT		caretOffset;		/* The amount by which a slanted
+  INT16		caretSlopeRun;		/* 0 for vertical caret, 1 for horizontal. */
+  INT16		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. */
-  SHORT		reserved1;		/* Set to 0. */
-  SHORT		reserved2;		/* Set to 0. */
-  SHORT		reserved3;		/* Set to 0. */
-  SHORT		reserved4;		/* Set to 0. */
-  SHORT		metricDataFormat;	/* 0 for current format. */
-  USHORT	numberOfLongMetrics;	/* Number of LongMetric entries in metric
+  INT16		reserved1;		/* Set to 0. */
+  INT16		reserved2;		/* Set to 0. */
+  INT16		reserved3;		/* Set to 0. */
+  INT16		reserved4;		/* Set to 0. */
+  INT16		metricDataFormat;	/* 0 for current format. */
+  UINT16	numberOfLongMetrics;	/* Number of LongMetric entries in metric
 					 * table. */
   public:
   DEFINE_SIZE_STATIC (36);
diff --git a/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh
index 30aa625..e710aee4 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh
@@ -28,6 +28,9 @@
 #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 {
@@ -50,11 +53,9 @@
   DEFINE_SIZE_STATIC (4);
 };
 
+template <typename T>
 struct hmtxvmtx
 {
-  static const hb_tag_t hmtxTag	= HB_OT_TAG_hmtx;
-  static const hb_tag_t vmtxTag	= HB_OT_TAG_vmtx;
-
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -63,7 +64,107 @@
     return_trace (true);
   }
 
-  public:
+  struct accelerator_t
+  {
+    inline void init (hb_face_t *face,
+		      unsigned int default_advance_ = 0)
+    {
+      default_advance = default_advance_ ? default_advance_ : face->get_upem ();
+
+      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<_hea>::sanitize (face->reference_table (T::headerTag));
+      const _hea *_hea_table = Sanitizer<_hea>::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,
+				     hb_font_t      *font) 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
+	   + var_table->get_advance_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
+    }
+
+    public:
+    bool has_font_extents;
+    unsigned short ascender;
+    unsigned short descender;
+    unsigned short line_gap;
+
+    private:
+    unsigned int num_metrics;
+    unsigned int num_advances;
+    unsigned int default_advance;
+
+    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
@@ -89,11 +190,17 @@
   DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX);
 };
 
-struct hmtx : hmtxvmtx {
+struct hmtx : hmtxvmtx<hmtx> {
   static const hb_tag_t tableTag	= HB_OT_TAG_hmtx;
+  static const hb_tag_t headerTag	= HB_OT_TAG_hhea;
+  static const hb_tag_t variationsTag	= HB_OT_TAG_HVAR;
+  static const hb_tag_t os2Tag		= HB_OT_TAG_os2;
 };
-struct vmtx : hmtxvmtx {
+struct vmtx : hmtxvmtx<vmtx> {
   static const hb_tag_t tableTag	= HB_OT_TAG_vmtx;
+  static const hb_tag_t headerTag	= HB_OT_TAG_vhea;
+  static const hb_tag_t variationsTag	= HB_OT_TAG_VVAR;
+  static const hb_tag_t os2Tag		= HB_TAG_NONE;
 };
 
 } /* namespace OT */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-kern-table.hh b/third_party/harfbuzz-ng/src/hb-ot-kern-table.hh
new file mode 100644
index 0000000..e07faca6
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-kern-table.hh
@@ -0,0 +1,394 @@
+/*
+ * 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:
+  UINT16		firstGlyph;	/* First glyph in class range. */
+  ArrayOf<UINT16>	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+leftClassTable).get_class (left);
+    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:
+  UINT16	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:
+    UINT16	versionZ;	/* Unused. */
+    UINT16	length;		/* Length of the subtable (including this header). */
+    UINT8	format;		/* Subtable format. */
+    UINT8	coverage;	/* Coverage bits. */
+    KernSubTable subtable;	/* Subtable data. */
+    public:
+    DEFINE_SIZE_MIN (6);
+  };
+
+  protected:
+  UINT16	version;	/* Version--0x0000u */
+  UINT16	nTables;	/* Number of subtables in the kerning table. */
+  UINT8		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:
+    UINT32	length;		/* Length of the subtable (including this header). */
+    UINT8	coverage;	/* Coverage bits. */
+    UINT8	format;		/* Subtable format. */
+    UINT16	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:
+  UINT32		version;	/* Version--0x00010000u */
+  UINT32		nTables;	/* Number of subtables in the kerning table. */
+  UINT8		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 {
+  UINT16		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-common-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh
index ed18bd88..86a74ccb 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh
@@ -29,6 +29,8 @@
 #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"
@@ -45,12 +47,6 @@
 namespace OT {
 
 
-#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);
-
-
 #define NOT_COVERED		((unsigned int) -1)
 
 
@@ -165,7 +161,7 @@
 
   GlyphID	start;		/* First GlyphID in the range */
   GlyphID	end;		/* Last GlyphID in the range */
-  USHORT	value;		/* Value */
+  UINT16	value;		/* Value */
   public:
   DEFINE_SIZE_STATIC (6);
 };
@@ -179,7 +175,7 @@
 				   unsigned int *_indexes /* OUT */) const
   {
     if (_count) {
-      const USHORT *arr = this->sub_array (start_offset, _count);
+      const UINT16 *arr = this->sub_array (start_offset, _count);
       unsigned int count = *_count;
       for (unsigned int i = 0; i < count; i++)
 	_indexes[i] = arr[i];
@@ -220,9 +216,9 @@
     return_trace (c->check_struct (this) && featureIndex.sanitize (c));
   }
 
-  Offset<>	lookupOrderZ;	/* = Null (reserved for an offset to a
+  Offset16	lookupOrderZ;	/* = Null (reserved for an offset to a
 				 * reordering table) */
-  USHORT	reqFeatureIndex;/* Index of a feature required for this
+  UINT16	reqFeatureIndex;/* Index of a feature required for this
 				 * language system--if no required features
 				 * = 0xFFFFu */
   IndexArray	featureIndex;	/* Array of indices into the FeatureList */
@@ -347,12 +343,12 @@
       return_trace (true);
   }
 
-  USHORT	designSize;	/* Represents the design size in 720/inch
+  UINT16	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. */
-  USHORT	subfamilyID;	/* Has no independent meaning, but serves
+  UINT16	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
@@ -362,7 +358,7 @@
 				 * same subfamily value. If this value is
 				 * zero, the remaining fields in the array
 				 * will be ignored. */
-  USHORT	subfamilyNameID;/* If the preceding value is non-zero, this
+  UINT16	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
@@ -376,10 +372,10 @@
 				 * subfamily in a menu.  Applications will
 				 * choose the appropriate version based on
 				 * their selection criteria. */
-  USHORT	rangeStart;	/* Large end of the recommended usage range
+  UINT16	rangeStart;	/* Large end of the recommended usage range
 				 * (inclusive), stored in 720/inch units
 				 * (decipoints). */
-  USHORT	rangeEnd;	/* Small end of the recommended usage range
+  UINT16	rangeEnd;	/* Small end of the recommended usage range
 				   (exclusive), stored in 720/inch units
 				 * (decipoints). */
   public:
@@ -397,12 +393,12 @@
     return_trace (c->check_struct (this));
   }
 
-  USHORT	version;	/* (set to 0): This corresponds to a “minor”
+  UINT16	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. */
 
-  USHORT	uiNameID;	/* The 'name' table name ID that specifies a
+  UINT16	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
@@ -430,25 +426,25 @@
 		  characters.sanitize (c));
   }
 
-  USHORT	format;			/* Format number is set to 0. */
-  USHORT	featUILableNameID;	/* The ‘name’ table name ID that
+  UINT16	format;			/* Format number is set to 0. */
+  UINT16	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.) */
-  USHORT	featUITooltipTextNameID;/* The ‘name’ table name ID that
+  UINT16	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.) */
-  USHORT	sampleTextNameID;	/* The ‘name’ table name ID that
+  UINT16	sampleTextNameID;	/* The ‘name’ table name ID that
 					 * specifies sample text that
 					 * illustrates the effect of this
 					 * feature. (May be nullptr.) */
-  USHORT	numNamedParameters;	/* Number of named parameters. (May
+  UINT16	numNamedParameters;	/* Number of named parameters. (May
 					 * be zero.) */
-  USHORT	firstParamUILabelNameID;/* The first ‘name’ table name ID
+  UINT16	firstParamUILabelNameID;/* The first ‘name’ table name ID
 					 * used to specify strings for
 					 * user-interface labels for the
 					 * feature parameters. (Must be zero
@@ -566,7 +562,7 @@
 typedef RecordListOf<Feature> FeatureList;
 
 
-struct LookupFlag : USHORT
+struct LookupFlag : UINT16
 {
   enum Flags {
     RightToLeft		= 0x0001u,
@@ -612,7 +608,7 @@
     unsigned int flag = lookupFlag;
     if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
     {
-      const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
+      const UINT16 &markFilteringSet = StructAfter<UINT16> (subTable);
       flag += (markFilteringSet << 16);
     }
     return flag;
@@ -644,7 +640,7 @@
     if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
     {
-      USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
+      UINT16 &markFilteringSet = StructAfter<UINT16> (subTable);
       markFilteringSet.set (lookup_props >> 16);
     }
     return_trace (true);
@@ -657,18 +653,18 @@
     if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
     {
-      const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
+      const UINT16 &markFilteringSet = StructAfter<UINT16> (subTable);
       if (!markFilteringSet.sanitize (c)) return_trace (false);
     }
     return_trace (true);
   }
 
   private:
-  USHORT	lookupType;		/* Different enumerations for GSUB and GPOS */
-  USHORT	lookupFlag;		/* Lookup qualifiers */
-  ArrayOf<Offset<> >
+  UINT16	lookupType;		/* Different enumerations for GSUB and GPOS */
+  UINT16	lookupFlag;		/* Lookup qualifiers */
+  ArrayOf<Offset16>
 		subTable;		/* Array of SubTables */
-  USHORT	markFilteringSetX[VAR];	/* Index (base 0) into GDEF mark glyph sets
+  UINT16	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:
@@ -741,7 +737,7 @@
   private:
 
   protected:
-  USHORT	coverageFormat;	/* Format identifier--format = 1 */
+  UINT16	coverageFormat;	/* Format identifier--format = 1 */
   SortedArrayOf<GlyphID>
 		glyphArray;	/* Array of GlyphIDs--in numerical order */
   public:
@@ -864,7 +860,7 @@
   private:
 
   protected:
-  USHORT	coverageFormat;	/* Format identifier--format = 2 */
+  UINT16	coverageFormat;	/* Format identifier--format = 2 */
   SortedArrayOf<RangeRecord>
 		rangeRecord;	/* Array of glyph ranges--ordered by
 				 * Start GlyphID. rangeCount entries
@@ -989,7 +985,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   CoverageFormat1	format1;
   CoverageFormat2	format2;
   } u;
@@ -1051,9 +1047,9 @@
   }
 
   protected:
-  USHORT	classFormat;		/* Format identifier--format = 1 */
+  UINT16	classFormat;		/* Format identifier--format = 1 */
   GlyphID	startGlyph;		/* First GlyphID of the classValueArray */
-  ArrayOf<USHORT>
+  ArrayOf<UINT16>
 		classValue;		/* Array of Class Values--one per GlyphID */
   public:
   DEFINE_SIZE_ARRAY (6, classValue);
@@ -1111,7 +1107,7 @@
   }
 
   protected:
-  USHORT	classFormat;	/* Format identifier--format = 2 */
+  UINT16	classFormat;	/* Format identifier--format = 2 */
   SortedArrayOf<RangeRecord>
 		rangeRecord;	/* Array of glyph ranges--ordered by
 				 * Start GlyphID */
@@ -1159,7 +1155,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   ClassDefFormat1	format1;
   ClassDefFormat2	format2;
   } u;
@@ -1244,8 +1240,8 @@
   }
 
   protected:
-  USHORT	axisCount;
-  USHORT	regionCount;
+  UINT16	axisCount;
+  UINT16	regionCount;
   VarRegionAxis	axesZ[VAR];
   public:
   DEFINE_SIZE_ARRAY (4, axesZ);
@@ -1269,13 +1265,13 @@
    unsigned int count = regionIndices.len;
    unsigned int scount = shortCount;
 
-   const BYTE *bytes = &StructAfter<BYTE> (regionIndices);
-   const BYTE *row = bytes + inner * (scount + count);
+   const UINT8 *bytes = &StructAfter<UINT8> (regionIndices);
+   const UINT8 *row = bytes + inner * (scount + count);
 
    float delta = 0.;
    unsigned int i = 0;
 
-   const SHORT *scursor = reinterpret_cast<const SHORT *> (row);
+   const INT16 *scursor = reinterpret_cast<const INT16 *> (row);
    for (; i < scount; i++)
    {
      float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count);
@@ -1297,15 +1293,15 @@
     return_trace (c->check_struct (this) &&
 		  regionIndices.sanitize(c) &&
 		  shortCount <= regionIndices.len &&
-		  c->check_array (&StructAfter<BYTE> (regionIndices),
+		  c->check_array (&StructAfter<UINT8> (regionIndices),
 				  get_row_size (), itemCount));
   }
 
   protected:
-  USHORT		itemCount;
-  USHORT		shortCount;
-  ArrayOf<USHORT>	regionIndices;
-  BYTE			bytesX[VAR];
+  UINT16		itemCount;
+  UINT16		shortCount;
+  ArrayOf<UINT16>	regionIndices;
+  UINT8			bytesX[VAR];
   public:
   DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX);
 };
@@ -1341,9 +1337,9 @@
   }
 
   protected:
-  USHORT				format;
+  UINT16				format;
   LOffsetTo<VarRegionList>		regions;
-  OffsetArrayOf<VarData, ULONG>		dataSets;
+  OffsetArrayOf<VarData, UINT32>		dataSets;
   public:
   DEFINE_SIZE_ARRAY (8, dataSets);
 };
@@ -1370,8 +1366,8 @@
   }
 
   protected:
-  USHORT	format;		/* Format identifier--format = 1 */
-  USHORT	axisIndex;
+  UINT16	format;		/* Format identifier--format = 1 */
+  UINT16	axisIndex;
   F2DOT14	filterRangeMinValue;
   F2DOT14	filterRangeMaxValue;
   public:
@@ -1400,7 +1396,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   ConditionFormat1	format1;
   } u;
   public:
@@ -1425,7 +1421,7 @@
   }
 
   protected:
-  OffsetArrayOf<Condition, ULONG> conditions;
+  OffsetArrayOf<Condition, UINT32> conditions;
   public:
   DEFINE_SIZE_ARRAY (2, conditions);
 };
@@ -1441,7 +1437,7 @@
   }
 
   protected:
-  USHORT		featureIndex;
+  UINT16		featureIndex;
   LOffsetTo<Feature>	feature;
   public:
   DEFINE_SIZE_STATIC (6);
@@ -1561,8 +1557,8 @@
   inline unsigned int get_size (void) const
   {
     unsigned int f = deltaFormat;
-    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size;
-    return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
+    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * UINT16::static_size;
+    return UINT16::static_size * (4 + ((endSize - startSize) >> (4 - f)));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -1607,14 +1603,14 @@
   }
 
   protected:
-  USHORT	startSize;		/* Smallest size to correct--in ppem */
-  USHORT	endSize;		/* Largest size to correct--in ppem */
-  USHORT	deltaFormat;		/* Format of DeltaValue array data: 1, 2, or 3
+  UINT16	startSize;		/* Smallest size to correct--in ppem */
+  UINT16	endSize;		/* Largest size to correct--in ppem */
+  UINT16	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
 					 */
-  USHORT	deltaValue[VAR];	/* Array of compressed data */
+  UINT16	deltaValue[VAR];	/* Array of compressed data */
   public:
   DEFINE_SIZE_ARRAY (6, deltaValue);
 };
@@ -1645,9 +1641,9 @@
   }
 
   protected:
-  USHORT	outerIndex;
-  USHORT	innerIndex;
-  USHORT	deltaFormat;	/* Format identifier for this table: 0x0x8000 */
+  UINT16	outerIndex;
+  UINT16	innerIndex;
+  UINT16	deltaFormat;	/* Format identifier for this table: 0x0x8000 */
   public:
   DEFINE_SIZE_STATIC (6);
 };
@@ -1655,10 +1651,10 @@
 struct DeviceHeader
 {
   protected:
-  USHORT		reserved1;
-  USHORT		reserved2;
+  UINT16		reserved1;
+  UINT16		reserved2;
   public:
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   public:
   DEFINE_SIZE_STATIC (6);
 };
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
index 99dda3a7..eed46dd 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
@@ -41,7 +41,7 @@
  * Attachment List Table
  */
 
-typedef ArrayOf<USHORT> AttachPoint;	/* Array of contour point indices--in
+typedef ArrayOf<UINT16> AttachPoint;	/* Array of contour point indices--in
 					 * increasing numerical order */
 
 struct AttachList
@@ -62,7 +62,7 @@
     const AttachPoint &points = this+attachPoint[index];
 
     if (point_count) {
-      const USHORT *array = points.sub_array (start_offset, point_count);
+      const UINT16 *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];
@@ -109,8 +109,8 @@
   }
 
   protected:
-  USHORT	caretValueFormat;	/* Format identifier--format = 1 */
-  SHORT		coordinate;		/* X or Y value, in design units */
+  UINT16	caretValueFormat;	/* Format identifier--format = 1 */
+  INT16		coordinate;		/* X or Y value, in design units */
   public:
   DEFINE_SIZE_STATIC (4);
 };
@@ -136,8 +136,8 @@
   }
 
   protected:
-  USHORT	caretValueFormat;	/* Format identifier--format = 2 */
-  USHORT	caretValuePoint;	/* Contour point index on glyph */
+  UINT16	caretValueFormat;	/* Format identifier--format = 2 */
+  UINT16	caretValuePoint;	/* Contour point index on glyph */
   public:
   DEFINE_SIZE_STATIC (4);
 };
@@ -160,8 +160,8 @@
   }
 
   protected:
-  USHORT	caretValueFormat;	/* Format identifier--format = 3 */
-  SHORT		coordinate;		/* X or Y value, in design units */
+  UINT16	caretValueFormat;	/* Format identifier--format = 3 */
+  INT16		coordinate;		/* X or Y value, in design units */
   OffsetTo<Device>
 		deviceTable;		/* Offset to Device table for X or Y
 					 * value--from beginning of CaretValue
@@ -199,7 +199,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   CaretValueFormat1	format1;
   CaretValueFormat2	format2;
   CaretValueFormat3	format3;
@@ -294,7 +294,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   ArrayOf<LOffsetTo<Coverage> >
 		coverage;		/* Array of long offsets to mark set
 					 * coverage tables */
@@ -324,7 +324,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   MarkGlyphSetsFormat1	format1;
   } u;
   public:
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
index e45ce27..3dcf2ec9 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
@@ -51,11 +51,11 @@
 
 /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */
 
-typedef USHORT Value;
+typedef UINT16 Value;
 
 typedef Value ValueRecord[VAR];
 
-struct ValueFormat : USHORT
+struct ValueFormat : UINT16
 {
   enum Flags {
     xPlacement	= 0x0001u,	/* Includes horizontal adjustment for placement */
@@ -74,14 +74,14 @@
 
 /* All fields are options.  Only those available advance the value pointer. */
 #if 0
-  SHORT		xPlacement;		/* Horizontal adjustment for
+  INT16		xPlacement;		/* Horizontal adjustment for
 					 * placement--in design units */
-  SHORT		yPlacement;		/* Vertical adjustment for
+  INT16		yPlacement;		/* Vertical adjustment for
 					 * placement--in design units */
-  SHORT		xAdvance;		/* Horizontal adjustment for
+  INT16		xAdvance;		/* Horizontal adjustment for
 					 * advance--in design units (only used
 					 * for horizontal writing) */
-  SHORT		yAdvance;		/* Vertical adjustment for advance--in
+  INT16		yAdvance;		/* Vertical adjustment for advance--in
 					 * design units (only used for vertical
 					 * writing) */
   Offset	xPlaDevice;		/* Offset to Device table for
@@ -178,8 +178,8 @@
   static inline const OffsetTo<Device>& get_device (const Value* value)
   { return *CastP<OffsetTo<Device> > (value); }
 
-  static inline const SHORT& get_short (const Value* value)
-  { return *CastP<SHORT> (value); }
+  static inline const INT16& get_short (const Value* value)
+  { return *CastP<INT16> (value); }
 
   public:
 
@@ -247,9 +247,9 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
-  SHORT		xCoordinate;		/* Horizontal value--in design units */
-  SHORT		yCoordinate;		/* Vertical value--in design units */
+  UINT16	format;			/* Format identifier--format = 1 */
+  INT16		xCoordinate;		/* Horizontal value--in design units */
+  INT16		yCoordinate;		/* Vertical value--in design units */
   public:
   DEFINE_SIZE_STATIC (6);
 };
@@ -278,10 +278,10 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 2 */
-  SHORT		xCoordinate;		/* Horizontal value--in design units */
-  SHORT		yCoordinate;		/* Vertical value--in design units */
-  USHORT	anchorPoint;		/* Index to glyph contour point */
+  UINT16	format;			/* Format identifier--format = 2 */
+  INT16		xCoordinate;		/* Horizontal value--in design units */
+  INT16		yCoordinate;		/* Vertical value--in design units */
+  UINT16	anchorPoint;		/* Index to glyph contour point */
   public:
   DEFINE_SIZE_STATIC (8);
 };
@@ -308,9 +308,9 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 3 */
-  SHORT		xCoordinate;		/* Horizontal value--in design units */
-  SHORT		yCoordinate;		/* Vertical value--in design units */
+  UINT16	format;			/* Format identifier--format = 3 */
+  INT16		xCoordinate;		/* Horizontal value--in design units */
+  INT16		yCoordinate;		/* Vertical value--in design units */
   OffsetTo<Device>
 		xDeviceTable;		/* Offset to Device table for X
 					 * coordinate-- from beginning of
@@ -351,7 +351,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   AnchorFormat1		format1;
   AnchorFormat2		format2;
   AnchorFormat3		format3;
@@ -382,7 +382,7 @@
     return_trace (true);
   }
 
-  USHORT	rows;			/* Number of rows */
+  UINT16	rows;			/* Number of rows */
   protected:
   OffsetTo<Anchor>
 		matrixZ[VAR];		/* Matrix of offsets to Anchor tables--
@@ -403,7 +403,7 @@
   }
 
   protected:
-  USHORT	klass;			/* Class defined for this mark */
+  UINT16	klass;			/* Class defined for this mark */
   OffsetTo<Anchor>
 		markAnchor;		/* Offset to Anchor table--from
 					 * beginning of MarkArray table */
@@ -492,7 +492,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
@@ -544,13 +544,13 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 2 */
+  UINT16	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 */
-  USHORT	valueCount;		/* Number of ValueRecords */
+  UINT16	valueCount;		/* Number of ValueRecords */
   ValueRecord	values;			/* Array of ValueRecords--positioning
 					 * values applied to glyphs */
   public:
@@ -573,7 +573,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   SinglePosFormat1	format1;
   SinglePosFormat2	format2;
   } u;
@@ -604,7 +604,7 @@
     TRACE_COLLECT_GLYPHS (this);
     unsigned int len1 = valueFormats[0].get_len ();
     unsigned int len2 = valueFormats[1].get_len ();
-    unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
+    unsigned int record_size = UINT16::static_size * (1 + len1 + len2);
 
     const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
     unsigned int count = len;
@@ -623,7 +623,7 @@
     hb_buffer_t *buffer = c->buffer;
     unsigned int len1 = valueFormats[0].get_len ();
     unsigned int len2 = valueFormats[1].get_len ();
-    unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
+    unsigned int record_size = UINT16::static_size * (1 + len1 + len2);
 
     const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
     unsigned int count = len;
@@ -668,7 +668,7 @@
   {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this)
-       && c->check_array (arrayZ, USHORT::static_size * closure->stride, len))) return_trace (false);
+       && c->check_array (arrayZ, UINT16::static_size * closure->stride, len))) return_trace (false);
 
     unsigned int count = len;
     const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
@@ -677,8 +677,8 @@
   }
 
   protected:
-  USHORT	len;			/* Number of PairValueRecords */
-  USHORT	arrayZ[VAR];		/* Array of PairValueRecords--ordered
+  UINT16	len;			/* Number of PairValueRecords */
+  UINT16	arrayZ[VAR];		/* Array of PairValueRecords--ordered
 					 * by GlyphID of the second glyph */
   public:
   DEFINE_SIZE_ARRAY (2, arrayZ);
@@ -733,7 +733,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
@@ -823,7 +823,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 2 */
+  UINT16	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
@@ -841,9 +841,9 @@
 		classDef2;		/* Offset to ClassDef table--from
 					 * beginning of PairPos subtable--for
 					 * the second glyph of the pair */
-  USHORT	class1Count;		/* Number of classes in ClassDef1
+  UINT16	class1Count;		/* Number of classes in ClassDef1
 					 * table--includes Class0 */
-  USHORT	class2Count;		/* Number of classes in ClassDef2
+  UINT16	class2Count;		/* Number of classes in ClassDef2
 					 * table--includes Class0 */
   ValueRecord	values;			/* Matrix of value pairs:
 					 * class1-major, class2-minor,
@@ -868,7 +868,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   PairPosFormat1	format1;
   PairPosFormat2	format2;
   } u;
@@ -1022,7 +1022,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of subtable */
@@ -1048,7 +1048,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   CursivePosFormat1	format1;
   } u;
 };
@@ -1113,14 +1113,14 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	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 */
-  USHORT	classCount;		/* Number of classes defined for marks */
+  UINT16	classCount;		/* Number of classes defined for marks */
   OffsetTo<MarkArray>
 		markArray;		/* Offset to MarkArray table--from
 					 * beginning of MarkBasePos subtable */
@@ -1146,7 +1146,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   MarkBasePosFormat1	format1;
   } u;
 };
@@ -1230,7 +1230,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		markCoverage;		/* Offset to Mark Coverage table--from
 					 * beginning of MarkLigPos subtable */
@@ -1238,7 +1238,7 @@
 		ligatureCoverage;	/* Offset to Ligature Coverage
 					 * table--from beginning of MarkLigPos
 					 * subtable */
-  USHORT	classCount;		/* Number of defined mark classes */
+  UINT16	classCount;		/* Number of defined mark classes */
   OffsetTo<MarkArray>
 		markArray;		/* Offset to MarkArray table--from
 					 * beginning of MarkLigPos subtable */
@@ -1264,7 +1264,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   MarkLigPosFormat1	format1;
   } u;
 };
@@ -1344,7 +1344,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		mark1Coverage;		/* Offset to Combining Mark1 Coverage
 					 * table--from beginning of MarkMarkPos
@@ -1353,7 +1353,7 @@
 		mark2Coverage;		/* Offset to Combining Mark2 Coverage
 					 * table--from beginning of MarkMarkPos
 					 * subtable */
-  USHORT	classCount;		/* Number of defined mark classes */
+  UINT16	classCount;		/* Number of defined mark classes */
   OffsetTo<MarkArray>
 		mark1Array;		/* Offset to Mark1Array table--from
 					 * beginning of MarkMarkPos subtable */
@@ -1379,7 +1379,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   MarkMarkPosFormat1	format1;
   } u;
 };
@@ -1438,7 +1438,7 @@
 
   protected:
   union {
-  USHORT		sub_format;
+  UINT16		sub_format;
   SinglePos		single;
   PairPos		pair;
   CursivePos		cursive;
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
index 4ae45b9..28e0790 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
@@ -44,7 +44,7 @@
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       /* TODO Switch to range-based API to work around malicious fonts.
-       * https://github.com/behdad/harfbuzz/issues/363 */
+       * 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);
@@ -58,7 +58,7 @@
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       /* TODO Switch to range-based API to work around malicious fonts.
-       * https://github.com/behdad/harfbuzz/issues/363 */
+       * https://github.com/harfbuzz/harfbuzz/issues/363 */
       hb_codepoint_t glyph_id = iter.get_glyph ();
       c->input->add (glyph_id);
       c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
@@ -110,11 +110,11 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
-  SHORT		deltaGlyphID;		/* Add to original GlyphID to get
+  INT16		deltaGlyphID;		/* Add to original GlyphID to get
 					 * substitute GlyphID */
   public:
   DEFINE_SIZE_STATIC (6);
@@ -130,7 +130,7 @@
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        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 ()]);
     }
@@ -144,7 +144,7 @@
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       c->input->add (iter.get_glyph ());
       c->output->add (substitute[iter.get_coverage ()]);
     }
@@ -195,7 +195,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 2 */
+  UINT16	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
@@ -249,7 +249,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   SingleSubstFormat1	format1;
   SingleSubstFormat2	format2;
   } u;
@@ -287,7 +287,7 @@
       return_trace (true);
     }
     /* Spec disallows this, but Uniscribe allows it.
-     * https://github.com/behdad/harfbuzz/issues/253 */
+     * https://github.com/harfbuzz/harfbuzz/issues/253 */
     else if (unlikely (count == 0))
     {
       c->buffer->delete_glyph ();
@@ -339,7 +339,7 @@
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        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);
     }
@@ -400,7 +400,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
@@ -442,7 +442,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   MultipleSubstFormat1	format1;
   } u;
 };
@@ -461,7 +461,7 @@
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        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;
@@ -479,7 +479,7 @@
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       c->input->add (iter.get_glyph ());
       const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
       unsigned int count = alt_set.len;
@@ -552,7 +552,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
@@ -594,7 +594,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   AlternateSubstFormat1	format1;
   } u;
 };
@@ -792,7 +792,7 @@
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        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);
     }
@@ -806,7 +806,7 @@
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       c->input->add (iter.get_glyph ());
       (this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c);
     }
@@ -868,7 +868,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
@@ -918,7 +918,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   LigatureSubstFormat1	format1;
   } u;
 };
@@ -961,7 +961,7 @@
     for (iter.init (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */
+        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 ()]);
     }
@@ -1016,11 +1016,11 @@
 
   unsigned int start_index = 0, end_index = 0;
     if (match_backtrack (c,
-			 backtrack.len, (USHORT *) backtrack.array,
+			 backtrack.len, (UINT16 *) backtrack.array,
 			 match_coverage, this,
 			 &start_index) &&
         match_lookahead (c,
-			 lookahead.len, (USHORT *) lookahead.array,
+			 lookahead.len, (UINT16 *) lookahead.array,
 			 match_coverage, this,
 			 1, &end_index))
     {
@@ -1048,7 +1048,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
@@ -1082,7 +1082,7 @@
 
   protected:
   union {
-  USHORT				format;		/* Format identifier */
+  UINT16				format;		/* Format identifier */
   ReverseChainSingleSubstFormat1	format1;
   } u;
 };
@@ -1128,7 +1128,7 @@
 
   protected:
   union {
-  USHORT			sub_format;
+  UINT16			sub_format;
   SingleSubst			single;
   MultipleSubst			multiple;
   AlternateSubst		alternate;
@@ -1280,9 +1280,11 @@
     if (unlikely (get_type () == SubstLookupSubTable::Extension))
     {
       /* The spec says all subtables of an Extension lookup should
-       * have the same type.  This is specially important if one has
-       * a reverse type! */
+       * have the same type, which shall not be the Extension type
+       * itself. This is specially important if one has a reverse type! */
       unsigned int type = get_subtable (0).u.extension.get_type ();
+      if (unlikely (type == SubstLookupSubTable::Extension))
+	return_trace (false);
       unsigned int count = get_subtable_count ();
       for (unsigned int i = 1; i < count; i++)
         if (get_subtable (i).u.extension.get_type () != type)
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
index e695d78..b08a591 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh
@@ -29,6 +29,8 @@
 #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"
@@ -37,15 +39,6 @@
 namespace OT {
 
 
-#ifndef HB_DEBUG_CLOSURE
-#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
-#endif
-
-#define TRACE_CLOSURE(this) \
-	hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
-	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
-	 "");
-
 struct hb_closure_context_t :
        hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE>
 {
@@ -85,16 +78,6 @@
 };
 
 
-
-#ifndef HB_DEBUG_WOULD_APPLY
-#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
-#endif
-
-#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);
-
 struct hb_would_apply_context_t :
        hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
 {
@@ -122,16 +105,6 @@
 };
 
 
-
-#ifndef HB_DEBUG_COLLECT_GLYPHS
-#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
-#endif
-
-#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, \
-	 "");
-
 struct hb_collect_glyphs_context_t :
        hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, HB_DEBUG_COLLECT_GLYPHS>
 {
@@ -219,10 +192,6 @@
 
 
 
-#ifndef HB_DEBUG_GET_COVERAGE
-#define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0)
-#endif
-
 /* XXX Can we remove this? */
 
 template <typename set_t>
@@ -249,17 +218,6 @@
 };
 
 
-
-#ifndef HB_DEBUG_APPLY
-#define HB_DEBUG_APPLY (HB_DEBUG+0)
-#endif
-
-#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);
-
 struct hb_apply_context_t :
        hb_dispatch_context_t<hb_apply_context_t, bool, HB_DEBUG_APPLY>
 {
@@ -276,7 +234,7 @@
 	     match_func (nullptr),
 	     match_data (nullptr) {};
 
-    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
+    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const UINT16 &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_; }
@@ -294,7 +252,7 @@
     };
 
     inline may_match_t may_match (const hb_glyph_info_t &info,
-				  const USHORT          *glyph_data) const
+				  const UINT16          *glyph_data) const
     {
       if (!(info.mask & mask) ||
 	  (syllable && syllable != info.syllable ()))
@@ -357,7 +315,7 @@
     }
     inline void set_match_func (matcher_t::match_func_t match_func_,
 				const void *match_data_,
-				const USHORT glyph_data[])
+				const UINT16 glyph_data[])
     {
       matcher.set_match_func (match_func_, match_data_);
       match_glyph_data = glyph_data;
@@ -440,7 +398,7 @@
     protected:
     hb_apply_context_t *c;
     matcher_t matcher;
-    const USHORT *match_glyph_data;
+    const UINT16 *match_glyph_data;
 
     unsigned int num_items;
     unsigned int end;
@@ -455,7 +413,7 @@
   bool stop_sublookup_iteration (return_t r) const { return r; }
   return_t recurse (unsigned int lookup_index)
   {
-    if (unlikely (nesting_level_left == 0 || !recurse_func))
+    if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
       return default_return_value ();
 
     nesting_level_left--;
@@ -610,9 +568,9 @@
 
 
 
-typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
-typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
-typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
+typedef bool (*intersects_func_t) (hb_set_t *glyphs, const UINT16 &value, const void *data);
+typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const UINT16 &value, const void *data);
+typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const UINT16 &value, const void *data);
 
 struct ContextClosureFuncs
 {
@@ -628,16 +586,16 @@
 };
 
 
-static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
+static inline bool intersects_glyph (hb_set_t *glyphs, const UINT16 &value, const void *data HB_UNUSED)
 {
   return glyphs->has (value);
 }
-static inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data)
+static inline bool intersects_class (hb_set_t *glyphs, const UINT16 &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 USHORT &value, const void *data)
+static inline bool intersects_coverage (hb_set_t *glyphs, const UINT16 &value, const void *data)
 {
   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   return (data+coverage).intersects (glyphs);
@@ -645,7 +603,7 @@
 
 static inline bool intersects_array (hb_closure_context_t *c,
 				     unsigned int count,
-				     const USHORT values[],
+				     const UINT16 values[],
 				     intersects_func_t intersects_func,
 				     const void *intersects_data)
 {
@@ -656,16 +614,16 @@
 }
 
 
-static inline void collect_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
+static inline void collect_glyph (hb_set_t *glyphs, const UINT16 &value, const void *data HB_UNUSED)
 {
   glyphs->add (value);
 }
-static inline void collect_class (hb_set_t *glyphs, const USHORT &value, const void *data)
+static inline void collect_class (hb_set_t *glyphs, const UINT16 &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 USHORT &value, const void *data)
+static inline void collect_coverage (hb_set_t *glyphs, const UINT16 &value, const void *data)
 {
   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   (data+coverage).add_coverage (glyphs);
@@ -673,7 +631,7 @@
 static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
 				  hb_set_t *glyphs,
 				  unsigned int count,
-				  const USHORT values[],
+				  const UINT16 values[],
 				  collect_glyphs_func_t collect_func,
 				  const void *collect_data)
 {
@@ -682,16 +640,16 @@
 }
 
 
-static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
+static inline bool match_glyph (hb_codepoint_t glyph_id, const UINT16 &value, const void *data HB_UNUSED)
 {
   return glyph_id == value;
 }
-static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
+static inline bool match_class (hb_codepoint_t glyph_id, const UINT16 &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 USHORT &value, const void *data)
+static inline bool match_coverage (hb_codepoint_t glyph_id, const UINT16 &value, const void *data)
 {
   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
@@ -699,7 +657,7 @@
 
 static inline bool would_match_input (hb_would_apply_context_t *c,
 				      unsigned int count, /* Including the first glyph (not matched) */
-				      const USHORT input[], /* Array of input values--start with second glyph */
+				      const UINT16 input[], /* Array of input values--start with second glyph */
 				      match_func_t match_func,
 				      const void *match_data)
 {
@@ -714,7 +672,7 @@
 }
 static inline bool match_input (hb_apply_context_t *c,
 				unsigned int count, /* Including the first glyph (not matched) */
-				const USHORT input[], /* Array of input values--start with second glyph */
+				const UINT16 input[], /* Array of input values--start with second glyph */
 				match_func_t match_func,
 				const void *match_data,
 				unsigned int *end_offset,
@@ -753,7 +711,7 @@
    *   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/behdad/harfbuzz/issues/545
+   *     https://github.com/harfbuzz/harfbuzz/issues/545
    */
 
   bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur());
@@ -938,7 +896,7 @@
 
 static inline bool match_backtrack (hb_apply_context_t *c,
 				    unsigned int count,
-				    const USHORT backtrack[],
+				    const UINT16 backtrack[],
 				    match_func_t match_func,
 				    const void *match_data,
 				    unsigned int *match_start)
@@ -960,7 +918,7 @@
 
 static inline bool match_lookahead (hb_apply_context_t *c,
 				    unsigned int count,
-				    const USHORT lookahead[],
+				    const UINT16 lookahead[],
 				    match_func_t match_func,
 				    const void *match_data,
 				    unsigned int offset,
@@ -991,9 +949,9 @@
     return_trace (c->check_struct (this));
   }
 
-  USHORT	sequenceIndex;		/* Index into current glyph
+  UINT16	sequenceIndex;		/* Index into current glyph
 					 * sequence--first glyph = 0 */
-  USHORT	lookupListIndex;	/* Lookup to apply to that
+  UINT16	lookupListIndex;	/* Lookup to apply to that
 					 * position--zero--based */
   public:
   DEFINE_SIZE_STATIC (4);
@@ -1044,7 +1002,11 @@
     if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
       continue;
 
-    buffer->move_to (match_positions[idx]);
+    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))
@@ -1150,7 +1112,7 @@
 
 static inline void context_closure_lookup (hb_closure_context_t *c,
 					   unsigned int inputCount, /* Including the first glyph (not matched) */
-					   const USHORT input[], /* Array of input values--start with second glyph */
+					   const UINT16 input[], /* Array of input values--start with second glyph */
 					   unsigned int lookupCount,
 					   const LookupRecord lookupRecord[],
 					   ContextClosureLookupContext &lookup_context)
@@ -1164,7 +1126,7 @@
 
 static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
 						  unsigned int inputCount, /* Including the first glyph (not matched) */
-						  const USHORT input[], /* Array of input values--start with second glyph */
+						  const UINT16 input[], /* Array of input values--start with second glyph */
 						  unsigned int lookupCount,
 						  const LookupRecord lookupRecord[],
 						  ContextCollectGlyphsLookupContext &lookup_context)
@@ -1178,7 +1140,7 @@
 
 static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
 					       unsigned int inputCount, /* Including the first glyph (not matched) */
-					       const USHORT input[], /* Array of input values--start with second glyph */
+					       const UINT16 input[], /* Array of input values--start with second glyph */
 					       unsigned int lookupCount HB_UNUSED,
 					       const LookupRecord lookupRecord[] HB_UNUSED,
 					       ContextApplyLookupContext &lookup_context)
@@ -1189,7 +1151,7 @@
 }
 static inline bool context_apply_lookup (hb_apply_context_t *c,
 					 unsigned int inputCount, /* Including the first glyph (not matched) */
-					 const USHORT input[], /* Array of input values--start with second glyph */
+					 const UINT16 input[], /* Array of input values--start with second glyph */
 					 unsigned int lookupCount,
 					 const LookupRecord lookupRecord[],
 					 ContextApplyLookupContext &lookup_context)
@@ -1247,19 +1209,19 @@
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return inputCount.sanitize (c)
-	&& lookupCount.sanitize (c)
-	&& c->check_range (inputZ,
-			   inputZ[0].static_size * inputCount
-			   + lookupRecordX[0].static_size * lookupCount);
+    return_trace (inputCount.sanitize (c) &&
+		  lookupCount.sanitize (c) &&
+		  c->check_range (inputZ,
+				  inputZ[0].static_size * inputCount +
+				  lookupRecordX[0].static_size * lookupCount));
   }
 
   protected:
-  USHORT	inputCount;		/* Total number of glyphs in input
+  UINT16	inputCount;		/* Total number of glyphs in input
 					 * glyph sequence--includes the first
 					 * glyph */
-  USHORT	lookupCount;		/* Number of LookupRecords */
-  USHORT	inputZ[VAR];		/* Array of match inputs--start with
+  UINT16	lookupCount;		/* Number of LookupRecords */
+  UINT16	inputZ[VAR];		/* Array of match inputs--start with
 					 * second glyph */
   LookupRecord	lookupRecordX[VAR];	/* Array of LookupRecords--in
 					 * design order */
@@ -1399,7 +1361,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
@@ -1492,7 +1454,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 2 */
+  UINT16	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
@@ -1521,7 +1483,7 @@
       this
     };
     context_closure_lookup (c,
-			    glyphCount, (const USHORT *) (coverageZ + 1),
+			    glyphCount, (const UINT16 *) (coverageZ + 1),
 			    lookupCount, lookupRecord,
 			    lookup_context);
   }
@@ -1538,7 +1500,7 @@
     };
 
     context_collect_glyphs_lookup (c,
-				   glyphCount, (const USHORT *) (coverageZ + 1),
+				   glyphCount, (const UINT16 *) (coverageZ + 1),
 				   lookupCount, lookupRecord,
 				   lookup_context);
   }
@@ -1552,7 +1514,7 @@
       {match_coverage},
       this
     };
-    return_trace (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
+    return_trace (context_would_apply_lookup (c, glyphCount, (const UINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
   }
 
   inline const Coverage &get_coverage (void) const
@@ -1571,7 +1533,7 @@
       {match_coverage},
       this
     };
-    return_trace (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
+    return_trace (context_apply_lookup (c, glyphCount, (const UINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -1588,10 +1550,10 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 3 */
-  USHORT	glyphCount;		/* Number of glyphs in the input glyph
+  UINT16	format;			/* Format identifier--format = 3 */
+  UINT16	glyphCount;		/* Number of glyphs in the input glyph
 					 * sequence */
-  USHORT	lookupCount;		/* Number of LookupRecords */
+  UINT16	lookupCount;		/* Number of LookupRecords */
   OffsetTo<Coverage>
 		coverageZ[VAR];		/* Array of offsets to Coverage
 					 * table in glyph sequence order */
@@ -1618,7 +1580,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   ContextFormat1	format1;
   ContextFormat2	format2;
   ContextFormat3	format3;
@@ -1648,11 +1610,11 @@
 
 static inline void chain_context_closure_lookup (hb_closure_context_t *c,
 						 unsigned int backtrackCount,
-						 const USHORT backtrack[],
+						 const UINT16 backtrack[],
 						 unsigned int inputCount, /* Including the first glyph (not matched) */
-						 const USHORT input[], /* Array of input values--start with second glyph */
+						 const UINT16 input[], /* Array of input values--start with second glyph */
 						 unsigned int lookaheadCount,
-						 const USHORT lookahead[],
+						 const UINT16 lookahead[],
 						 unsigned int lookupCount,
 						 const LookupRecord lookupRecord[],
 						 ChainContextClosureLookupContext &lookup_context)
@@ -1672,11 +1634,11 @@
 
 static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
 						        unsigned int backtrackCount,
-						        const USHORT backtrack[],
+						        const UINT16 backtrack[],
 						        unsigned int inputCount, /* Including the first glyph (not matched) */
-						        const USHORT input[], /* Array of input values--start with second glyph */
+						        const UINT16 input[], /* Array of input values--start with second glyph */
 						        unsigned int lookaheadCount,
-						        const USHORT lookahead[],
+						        const UINT16 lookahead[],
 						        unsigned int lookupCount,
 						        const LookupRecord lookupRecord[],
 						        ChainContextCollectGlyphsLookupContext &lookup_context)
@@ -1696,11 +1658,11 @@
 
 static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
 						     unsigned int backtrackCount,
-						     const USHORT backtrack[] HB_UNUSED,
+						     const UINT16 backtrack[] HB_UNUSED,
 						     unsigned int inputCount, /* Including the first glyph (not matched) */
-						     const USHORT input[], /* Array of input values--start with second glyph */
+						     const UINT16 input[], /* Array of input values--start with second glyph */
 						     unsigned int lookaheadCount,
-						     const USHORT lookahead[] HB_UNUSED,
+						     const UINT16 lookahead[] HB_UNUSED,
 						     unsigned int lookupCount HB_UNUSED,
 						     const LookupRecord lookupRecord[] HB_UNUSED,
 						     ChainContextApplyLookupContext &lookup_context)
@@ -1713,11 +1675,11 @@
 
 static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
 					       unsigned int backtrackCount,
-					       const USHORT backtrack[],
+					       const UINT16 backtrack[],
 					       unsigned int inputCount, /* Including the first glyph (not matched) */
-					       const USHORT input[], /* Array of input values--start with second glyph */
+					       const UINT16 input[], /* Array of input values--start with second glyph */
 					       unsigned int lookaheadCount,
-					       const USHORT lookahead[],
+					       const UINT16 lookahead[],
 					       unsigned int lookupCount,
 					       const LookupRecord lookupRecord[],
 					       ChainContextApplyLookupContext &lookup_context)
@@ -1748,8 +1710,8 @@
   inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
   {
     TRACE_CLOSURE (this);
-    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
-    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+    const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack);
+    const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     chain_context_closure_lookup (c,
 				  backtrack.len, backtrack.array,
@@ -1762,8 +1724,8 @@
   inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
-    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+    const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack);
+    const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     chain_context_collect_glyphs_lookup (c,
 					 backtrack.len, backtrack.array,
@@ -1776,8 +1738,8 @@
   inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   {
     TRACE_WOULD_APPLY (this);
-    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
-    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+    const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack);
+    const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     return_trace (chain_context_would_apply_lookup (c,
 						    backtrack.len, backtrack.array,
@@ -1789,8 +1751,8 @@
   inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
-    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
-    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+    const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack);
+    const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     return_trace (chain_context_apply_lookup (c,
 					      backtrack.len, backtrack.array,
@@ -1803,23 +1765,23 @@
   {
     TRACE_SANITIZE (this);
     if (!backtrack.sanitize (c)) return_trace (false);
-    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
+    const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack);
     if (!input.sanitize (c)) return_trace (false);
-    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+    const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input);
     if (!lookahead.sanitize (c)) return_trace (false);
     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
     return_trace (lookup.sanitize (c));
   }
 
   protected:
-  ArrayOf<USHORT>
+  ArrayOf<UINT16>
 		backtrack;		/* Array of backtracking values
 					 * (to be matched before the input
 					 * sequence) */
-  HeadlessArrayOf<USHORT>
+  HeadlessArrayOf<UINT16>
 		inputX;			/* Array of input values (start with
 					 * second glyph) */
-  ArrayOf<USHORT>
+  ArrayOf<UINT16>
 		lookaheadX;		/* Array of lookahead values's (to be
 					 * matched after the input sequence) */
   ArrayOf<LookupRecord>
@@ -1956,7 +1918,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 1 */
+  UINT16	format;			/* Format identifier--format = 1 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
@@ -2071,7 +2033,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 2 */
+  UINT16	format;			/* Format identifier--format = 2 */
   OffsetTo<Coverage>
 		coverage;		/* Offset to Coverage table--from
 					 * beginning of table */
@@ -2111,9 +2073,9 @@
       {this, this, this}
     };
     chain_context_closure_lookup (c,
-				  backtrack.len, (const USHORT *) backtrack.array,
-				  input.len, (const USHORT *) input.array + 1,
-				  lookahead.len, (const USHORT *) lookahead.array,
+				  backtrack.len, (const UINT16 *) backtrack.array,
+				  input.len, (const UINT16 *) input.array + 1,
+				  lookahead.len, (const UINT16 *) lookahead.array,
 				  lookup.len, lookup.array,
 				  lookup_context);
   }
@@ -2132,9 +2094,9 @@
       {this, this, this}
     };
     chain_context_collect_glyphs_lookup (c,
-					 backtrack.len, (const USHORT *) backtrack.array,
-					 input.len, (const USHORT *) input.array + 1,
-					 lookahead.len, (const USHORT *) lookahead.array,
+					 backtrack.len, (const UINT16 *) backtrack.array,
+					 input.len, (const UINT16 *) input.array + 1,
+					 lookahead.len, (const UINT16 *) lookahead.array,
 					 lookup.len, lookup.array,
 					 lookup_context);
   }
@@ -2151,9 +2113,9 @@
       {this, this, this}
     };
     return_trace (chain_context_would_apply_lookup (c,
-						    backtrack.len, (const USHORT *) backtrack.array,
-						    input.len, (const USHORT *) input.array + 1,
-						    lookahead.len, (const USHORT *) lookahead.array,
+						    backtrack.len, (const UINT16 *) backtrack.array,
+						    input.len, (const UINT16 *) input.array + 1,
+						    lookahead.len, (const UINT16 *) lookahead.array,
 						    lookup.len, lookup.array, lookup_context));
   }
 
@@ -2178,9 +2140,9 @@
       {this, this, this}
     };
     return_trace (chain_context_apply_lookup (c,
-					      backtrack.len, (const USHORT *) backtrack.array,
-					      input.len, (const USHORT *) input.array + 1,
-					      lookahead.len, (const USHORT *) lookahead.array,
+					      backtrack.len, (const UINT16 *) backtrack.array,
+					      input.len, (const UINT16 *) input.array + 1,
+					      lookahead.len, (const UINT16 *) lookahead.array,
 					      lookup.len, lookup.array, lookup_context));
   }
 
@@ -2198,7 +2160,7 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier--format = 3 */
+  UINT16	format;			/* Format identifier--format = 3 */
   OffsetArrayOf<Coverage>
 		backtrack;		/* Array of coverage tables
 					 * in backtracking sequence, in  glyph
@@ -2235,7 +2197,7 @@
 
   protected:
   union {
-  USHORT		format;	/* Format identifier */
+  UINT16		format;	/* Format identifier */
   ChainContextFormat1	format1;
   ChainContextFormat2	format2;
   ChainContextFormat3	format3;
@@ -2272,11 +2234,11 @@
   }
 
   protected:
-  USHORT	format;			/* Format identifier. Set to 1. */
-  USHORT	extensionLookupType;	/* Lookup type of subtable referenced
+  UINT16	format;			/* Format identifier. Set to 1. */
+  UINT16	extensionLookupType;	/* Lookup type of subtable referenced
 					 * by ExtensionOffset (i.e. the
 					 * extension subtable). */
-  ULONG		extensionOffset;	/* Offset to the extension subtable,
+  UINT32		extensionOffset;	/* Offset to the extension subtable,
 					 * of lookup type subtable. */
   public:
   DEFINE_SIZE_STATIC (8);
@@ -2314,7 +2276,7 @@
 
   protected:
   union {
-  USHORT		format;		/* Format identifier */
+  UINT16		format;		/* Format identifier */
   ExtensionFormat1<T>	format1;
   } u;
 };
@@ -2326,9 +2288,6 @@
 
 struct GSUBGPOS
 {
-  static const hb_tag_t GSUBTag	= HB_OT_TAG_GSUB;
-  static const hb_tag_t GPOSTag	= HB_OT_TAG_GPOS;
-
   inline unsigned int get_script_count (void) const
   { return (this+scriptList).len; }
   inline const Tag& get_script_tag (unsigned int i) const
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
index 460028a..0f0926f8 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
@@ -273,13 +273,13 @@
        * 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/behdad/harfbuzz/issues/234 */
+       * 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/behdad/harfbuzz/issues/463 */
+       * 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/behdad/harfbuzz/issues/554 */
+       * https://github.com/harfbuzz/harfbuzz/issues/554 */
       else if (unlikely (u == 0x034Fu)) props |= UPROPS_MASK_HIDDEN;
     }
     else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat)))
@@ -305,7 +305,7 @@
       /* 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/behdad/harfbuzz/issues/169
+       * https://github.com/harfbuzz/harfbuzz/issues/169
        */
       if (unlikely (hb_in_range (u, 0x1F3FBu, 0x1F3FFu)))
       {
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout.cc b/third_party/harfbuzz-ng/src/hb-ot-layout.cc
index 71e7826..e1109d8 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout.cc
@@ -32,12 +32,14 @@
 #include "hb-ot-layout-private.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-layout-gsub-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-map-private.hh"
 
+const void* const OT::_hb_NullPool[HB_NULL_POOL_SIZE / sizeof(void*)] = {};
 
 hb_ot_layout_t *
 _hb_ot_layout_create (hb_face_t *face)
@@ -597,6 +599,8 @@
 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:
diff --git a/third_party/harfbuzz-ng/src/hb-ot-map-private.hh b/third_party/harfbuzz-ng/src/hb-ot-map-private.hh
index 105909a..97b92cc9 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-map-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-map-private.hh
@@ -63,8 +63,12 @@
     unsigned short auto_zwj : 1;
     hb_mask_t mask;
 
-    static int cmp (const lookup_map_t *a, const lookup_map_t *b)
-    { return a->index < b->index ? -1 : a->index > b->index ? 1 : 0; }
+    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);
@@ -210,9 +214,13 @@
     unsigned int default_value; /* for non-global features, what should the unset glyphs take */
     unsigned int stage[2]; /* GSUB/GPOS */
 
-    static int cmp (const feature_info_t *a, const feature_info_t *b)
-    { return (a->tag != b->tag) ?  (a->tag < b->tag ? -1 : 1) :
-	     (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0); }
+    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 {
diff --git a/third_party/harfbuzz-ng/src/hb-ot-math-table.hh b/third_party/harfbuzz-ng/src/hb-ot-math-table.hh
index b3c8571..7dc3283 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-math-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-math-table.hh
@@ -48,7 +48,7 @@
   }
 
   protected:
-  SHORT			value;		/* The X or Y value in design units */
+  INT16			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. */
@@ -154,10 +154,10 @@
   }
 
   protected:
-  SHORT percentScaleDown[2];
-  USHORT minHeight[2];
+  INT16 percentScaleDown[2];
+  UINT16 minHeight[2];
   MathValueRecord mathValueRecords[51];
-  SHORT radicalDegreeBottomRaisePercent;
+  INT16 radicalDegreeBottomRaisePercent;
 
   public:
   DEFINE_SIZE_STATIC (214);
@@ -279,7 +279,7 @@
   }
 
   protected:
-  USHORT	  heightCount;
+  UINT16	  heightCount;
   MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
 					  * which the kern value changes.
 					  * Sorted by the height value in
@@ -425,7 +425,7 @@
 
   protected:
   GlyphID variantGlyph;       /* Glyph ID for the variant. */
-  USHORT  advanceMeasurement; /* Advance width/height, in design units, of the
+  UINT16  advanceMeasurement; /* Advance width/height, in design units, of the
 			       * variant, in the direction of requested
 			       * glyph extension. */
 
@@ -433,7 +433,7 @@
   DEFINE_SIZE_STATIC (4);
 };
 
-struct PartFlags : USHORT
+struct PartFlags : UINT16
 {
   enum Flags {
     Extender	= 0x0001u, /* If set, the part can be skipped or repeated. */
@@ -473,15 +473,15 @@
 
   protected:
   GlyphID   glyph;		  /* Glyph ID for the part. */
-  USHORT    startConnectorLength; /* Advance width/ height of the straight bar
+  UINT16    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. */
-  USHORT    endConnectorLength;   /* Advance width/ height of the straight bar
+  UINT16    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. */
-  USHORT    fullAdvance;	  /* Full advance width/height for this part,
+  UINT16    fullAdvance;	  /* Full advance width/height for this part,
 				   * in the direction of the extension.
 				   * In design units. */
   PartFlags partFlags;		  /* Part qualifiers. */
@@ -651,7 +651,7 @@
   }
 
   protected:
-  USHORT	     minConnectorOverlap; /* Minimum overlap of connecting
+  UINT16	     minConnectorOverlap; /* Minimum overlap of connecting
 					   * glyphs during glyph construction,
 					   * in design units. */
   OffsetTo<Coverage> vertGlyphCoverage;   /* Offset to Coverage table -
@@ -660,10 +660,10 @@
   OffsetTo<Coverage> horizGlyphCoverage;  /* Offset to Coverage table -
 					   * from the beginning of MathVariants
 					   * table. */
-  USHORT	     vertGlyphCount;      /* Number of glyphs for which
+  UINT16	     vertGlyphCount;      /* Number of glyphs for which
 					   * information is provided for
 					   * vertically growing variants. */
-  USHORT	     horizGlyphCount;     /* Number of glyphs for which
+  UINT16	     horizGlyphCount;     /* Number of glyphs for which
 					   * information is provided for
 					   * horizontally growing variants. */
 
diff --git a/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh b/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh
index 943e390..f6d283e 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh
@@ -60,7 +60,7 @@
   protected:
   FixedVersion<>version;		/* Version of the maxp table (0.5 or 1.0),
 					 * 0x00005000u or 0x00010000u. */
-  USHORT	numGlyphs;		/* The number of glyphs in the font. */
+  UINT16	numGlyphs;		/* The number of glyphs in the font. */
   public:
   DEFINE_SIZE_STATIC (6);
 };
diff --git a/third_party/harfbuzz-ng/src/hb-ot-name-table.hh b/third_party/harfbuzz-ng/src/hb-ot-name-table.hh
index 870f123..4c5b3c0f 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-name-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-name-table.hh
@@ -42,8 +42,10 @@
 
 struct NameRecord
 {
-  static int cmp (const NameRecord *a, const NameRecord *b)
+  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;
@@ -63,12 +65,12 @@
     return_trace (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset));
   }
 
-  USHORT	platformID;	/* Platform ID. */
-  USHORT	encodingID;	/* Platform-specific encoding ID. */
-  USHORT	languageID;	/* Language ID. */
-  USHORT	nameID;		/* Name ID. */
-  USHORT	length;		/* String length (in bytes). */
-  USHORT	offset;		/* String offset from start of storage area (in bytes). */
+  UINT16	platformID;	/* Platform ID. */
+  UINT16	encodingID;	/* Platform-specific encoding ID. */
+  UINT16	languageID;	/* Language ID. */
+  UINT16	nameID;		/* Name ID. */
+  UINT16	length;		/* String length (in bytes). */
+  UINT16	offset;		/* String offset from start of storage area (in bytes). */
   public:
   DEFINE_SIZE_STATIC (12);
 };
@@ -89,7 +91,7 @@
     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]), (hb_compare_func_t) NameRecord::cmp);
+    NameRecord *match = (NameRecord *) bsearch (&key, nameRecord, count, sizeof (nameRecord[0]), NameRecord::cmp);
 
     if (!match)
       return 0;
@@ -121,9 +123,9 @@
   }
 
   /* We only implement format 0 for now. */
-  USHORT	format;			/* Format selector (=0/1). */
-  USHORT	count;			/* Number of name records. */
-  Offset<>	stringOffset;		/* Offset to start of string storage (from start of table). */
+  UINT16	format;			/* Format selector (=0/1). */
+  UINT16	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);
diff --git a/third_party/harfbuzz-ng/src/hb-ot-os2-table.hh b/third_party/harfbuzz-ng/src/hb-ot-os2-table.hh
index 4709cd6e..aa78f1e 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-os2-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-os2-table.hh
@@ -50,50 +50,50 @@
   }
 
   public:
-  USHORT	version;
+  UINT16	version;
 
   /* Version 0 */
-  SHORT		xAvgCharWidth;
-  USHORT	usWeightClass;
-  USHORT	usWidthClass;
-  USHORT	fsType;
-  SHORT		ySubscriptXSize;
-  SHORT		ySubscriptYSize;
-  SHORT		ySubscriptXOffset;
-  SHORT		ySubscriptYOffset;
-  SHORT		ySuperscriptXSize;
-  SHORT		ySuperscriptYSize;
-  SHORT		ySuperscriptXOffset;
-  SHORT		ySuperscriptYOffset;
-  SHORT		yStrikeoutSize;
-  SHORT		yStrikeoutPosition;
-  SHORT		sFamilyClass;
-  BYTE		panose[10];
-  ULONG		ulUnicodeRange[4];
+  INT16		xAvgCharWidth;
+  UINT16	usWeightClass;
+  UINT16	usWidthClass;
+  UINT16	fsType;
+  INT16		ySubscriptXSize;
+  INT16		ySubscriptYSize;
+  INT16		ySubscriptXOffset;
+  INT16		ySubscriptYOffset;
+  INT16		ySuperscriptXSize;
+  INT16		ySuperscriptYSize;
+  INT16		ySuperscriptXOffset;
+  INT16		ySuperscriptYOffset;
+  INT16		yStrikeoutSize;
+  INT16		yStrikeoutPosition;
+  INT16		sFamilyClass;
+  UINT8		panose[10];
+  UINT32		ulUnicodeRange[4];
   Tag		achVendID;
-  USHORT	fsSelection;
-  USHORT	usFirstCharIndex;
-  USHORT	usLastCharIndex;
-  SHORT		sTypoAscender;
-  SHORT		sTypoDescender;
-  SHORT		sTypoLineGap;
-  USHORT	usWinAscent;
-  USHORT	usWinDescent;
+  UINT16	fsSelection;
+  UINT16	usFirstCharIndex;
+  UINT16	usLastCharIndex;
+  INT16		sTypoAscender;
+  INT16		sTypoDescender;
+  INT16		sTypoLineGap;
+  UINT16	usWinAscent;
+  UINT16	usWinDescent;
 
   /* Version 1 */
-  //ULONG ulCodePageRange1;
-  //ULONG ulCodePageRange2;
+  //UINT32 ulCodePageRange1;
+  //UINT32 ulCodePageRange2;
 
   /* Version 2 */
-  //SHORT sxHeight;
-  //SHORT sCapHeight;
-  //USHORT  usDefaultChar;
-  //USHORT  usBreakChar;
-  //USHORT  usMaxContext;
+  //INT16 sxHeight;
+  //INT16 sCapHeight;
+  //UINT16  usDefaultChar;
+  //UINT16  usBreakChar;
+  //UINT16  usMaxContext;
 
   /* Version 5 */
-  //USHORT  usLowerOpticalPointSize;
-  //USHORT  usUpperOpticalPointSize;
+  //UINT16  usLowerOpticalPointSize;
+  //UINT16  usUpperOpticalPointSize;
 
   public:
   DEFINE_SIZE_STATIC (78);
diff --git a/third_party/harfbuzz-ng/src/hb-ot-post-macroman.hh b/third_party/harfbuzz-ng/src/hb-ot-post-macroman.hh
new file mode 100644
index 0000000..dbbb97e
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-post-macroman.hh
@@ -0,0 +1,294 @@
+/*
+ * 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
index 3eae7f7..7f1c2c4 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-post-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-post-table.hh
@@ -28,50 +28,16 @@
 #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
 
-static const char* const format1_names[NUM_FORMAT1_NAMES] =
-{
-  ".notdef", ".null", "nonmarkingreturn", "space", "exclam", "quotedbl",
-  "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft",
-  "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash",
-  "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
-  "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at",
-  "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", "bracketleft",
-  "backslash", "bracketright", "asciicircum", "underscore", "grave", "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", "braceleft", "bar",
-  "braceright", "asciitilde", "Adieresis", "Aring", "Ccedilla", "Eacute",
-  "Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex",
-  "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave",
-  "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
-  "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", "otilde", "uacute",
-  "ugrave", "ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling",
-  "section", "bullet", "paragraph", "germandbls", "registered", "copyright",
-  "trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity",
-  "plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff",
-  "summation", "product", "pi", "integral", "ordfeminine", "ordmasculine",
-  "Omega", "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
-  "radical", "florin", "approxequal", "Delta", "guillemotleft",
-  "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
-  "Otilde", "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright",
-  "quoteleft", "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis",
-  "fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl",
-  "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase",
-  "perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave",
-  "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
-  "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi",
-  "circumflex", "tilde", "macron", "breve", "dotaccent", "ring", "cedilla",
-  "hungarumlaut", "ogonek", "caron", "Lslash", "lslash", "Scaron", "scaron",
-  "Zcaron", "zcaron", "brokenbar", "Eth", "eth", "Yacute", "yacute", "Thorn",
-  "thorn", "minus", "multiply", "onesuperior", "twosuperior", "threesuperior",
-  "onehalf", "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
-  "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute", "Ccaron", "ccaron",
-  "dcroat",
-};
-
 namespace OT {
 
 
@@ -87,16 +53,13 @@
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (numberOfGlyphs.sanitize (c) &&
-		  c->check_array (glyphNameIndex, sizeof (USHORT), numberOfGlyphs));
+    return_trace (glyphNameIndex.sanitize (c));
   }
 
-  USHORT	numberOfGlyphs;		/* Number of glyphs (this should be the
-					 * same as numGlyphs in 'maxp' table). */
-  USHORT	glyphNameIndex[VAR];	/* This is not an offset, but is the
+  ArrayOf<UINT16>glyphNameIndex;	/* This is not an offset, but is the
 					 * ordinal number of the glyph in 'post'
 					 * string tables. */
-  BYTE		namesX[VAR];		/* Glyph names with length bytes [variable]
+  UINT8		namesX[VAR];		/* Glyph names with length bytes [variable]
 					 * (a Pascal string). */
 
   DEFINE_SIZE_ARRAY2 (2, glyphNameIndex, namesX);
@@ -119,134 +82,163 @@
     return_trace (true);
   }
 
-  inline bool get_glyph_name (hb_codepoint_t glyph,
-			      char *buffer, unsigned int buffer_length,
-			      unsigned int blob_len) const
+  struct accelerator_t
   {
-    if (version.to_int () == 0x00010000)
+    inline void init (hb_face_t *face)
     {
-      if (glyph >= NUM_FORMAT1_NAMES)
-	return false;
+      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);
 
-      if (!buffer_length)
+      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;
-      strncpy (buffer, format1_names[glyph], buffer_length);
-      buffer[buffer_length - 1] = '\0';
+      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;
     }
 
-    if (version.to_int () == 0x00020000)
+    inline bool get_glyph_from_name (const char *name, int len,
+				     hb_codepoint_t *glyph) const
     {
-      const postV2Tail &v2 = StructAfter<postV2Tail> (*this);
+      unsigned int count = get_glyph_count ();
+      if (unlikely (!count))
+        return false;
 
-      if (glyph >= v2.numberOfGlyphs)
+      if (len < 0)
+	len = strlen (name);
+
+      if (unlikely (!len))
 	return false;
 
-      if (!buffer_length)
-	return true;
+    retry:
+      uint16_t *gids = (uint16_t *) hb_atomic_ptr_get (&gids_sorted_by_name);
 
-      unsigned int index = v2.glyphNameIndex[glyph];
-      if (index < NUM_FORMAT1_NAMES)
+      if (unlikely (!gids))
       {
-	if (!buffer_length)
-	  return true;
-	strncpy (buffer, format1_names[index], buffer_length);
-	buffer[buffer_length - 1] = '\0';
+	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;
 
-      unsigned int offset = min_size + v2.min_size + 2 * v2.numberOfGlyphs;
-      unsigned char *data = (unsigned char *) this + offset;
-      unsigned char *end = (unsigned char *) this + blob_len;
-      for (unsigned int i = 0; data < end; i++)
-      {
-	unsigned int name_length = data[0];
-	data++;
-	if (i == index)
-	{
-	  if (unlikely (!name_length))
-	    return false;
+      if (index >= index_to_offset.len)
+	return hb_string_t ();
+      unsigned int offset = index_to_offset.array[index];
 
-	  unsigned int remaining = end - data;
-	  name_length = MIN (name_length, buffer_length - 1);
-	  name_length = MIN (name_length, remaining);
-	  memcpy (buffer, data, name_length);
-	  buffer[name_length] = '\0';
-	  return true;
-	}
-	data += name_length;
-      }
+      const uint8_t *data = pool + offset;
+      unsigned int name_length = *data;
+      data++;
 
-      return false;
+      return hb_string_t ((const char *) data, name_length);
     }
 
-    return false;
-  }
-
-  inline bool get_glyph_from_name (const char *name, int len,
-				   hb_codepoint_t *glyph,
-				   unsigned int blob_len) const
-  {
-    if (len < 0)
-      len = strlen (name);
-
-    if (version.to_int () == 0x00010000)
-    {
-      for (int i = 0; i < NUM_FORMAT1_NAMES; i++)
-      {
-	if (strncmp (name, format1_names[i], len) == 0 && format1_names[i][len] == '\0')
-	{
-	  *glyph = i;
-	  return true;
-	}
-      }
-      return false;
-    }
-
-    if (version.to_int () == 0x00020000)
-    {
-      const postV2Tail &v2 = StructAfter<postV2Tail> (*this);
-      unsigned int offset = min_size + v2.min_size + 2 * v2.numberOfGlyphs;
-      char* data = (char*) this + offset;
-
-
-      /* XXX The following code is wrong. */
-      return false;
-      for (hb_codepoint_t gid = 0; gid < v2.numberOfGlyphs; gid++)
-      {
-	unsigned int index = v2.glyphNameIndex[gid];
-	if (index < NUM_FORMAT1_NAMES)
-	{
-	  if (strncmp (name, format1_names[index], len) == 0 && format1_names[index][len] == '\0')
-	  {
-	    *glyph = gid;
-	    return true;
-	  }
-	  continue;
-	}
-	index -= NUM_FORMAT1_NAMES;
-
-	for (unsigned int i = 0; data < (char*) this + blob_len; i++)
-	{
-	  unsigned int name_length = data[0];
-	  unsigned int remaining = (char*) this + blob_len - data - 1;
-	  name_length = MIN (name_length, remaining);
-	  if (name_length == (unsigned int) len && strncmp (name, data + 1, len) == 0)
-	  {
-	    *glyph = gid;
-	    return true;
-	  }
-	  data += name_length + 1;
-	}
-	return false;
-      }
-
-      return false;
-    }
-
-    return false;
-  }
+    private:
+    hb_blob_t *blob;
+    uint32_t version;
+    const ArrayOf<UINT16> *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
@@ -269,16 +261,16 @@
 					 * from the value of this field. */
   FWORD		underlineThickness;	/* Suggested values for the underline
 					   thickness. */
-  ULONG		isFixedPitch;		/* Set to 0 if the font is proportionally
+  UINT32		isFixedPitch;		/* Set to 0 if the font is proportionally
 					 * spaced, non-zero if the font is not
 					 * proportionally spaced (i.e. monospaced). */
-  ULONG		minMemType42;		/* Minimum memory usage when an OpenType font
+  UINT32		minMemType42;		/* Minimum memory usage when an OpenType font
 					 * is downloaded. */
-  ULONG		maxMemType42;		/* Maximum memory usage when an OpenType font
+  UINT32		maxMemType42;		/* Maximum memory usage when an OpenType font
 					 * is downloaded. */
-  ULONG		minMemType1;		/* Minimum memory usage when an OpenType font
+  UINT32		minMemType1;		/* Minimum memory usage when an OpenType font
 					 * is downloaded as a Type 1 font. */
-  ULONG		maxMemType1;		/* Maximum memory usage when an OpenType font
+  UINT32		maxMemType1;		/* Maximum memory usage when an OpenType font
 					 * is downloaded as a Type 1 font. */
 /*postV2Tail	v2[VAR];*/
   DEFINE_SIZE_STATIC (32);
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
index e70c48f..54c6cdc2 100644
--- 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
@@ -43,16 +43,16 @@
 #define OT_TABLE_END			}
 #define OT_LABEL_START(Name)		unsigned char Name[
 #define OT_LABEL_END			];
-#define OT_BYTE(u8)			+1/*byte*/
-#define OT_USHORT(u16)			+2/*bytes*/
+#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_BYTE(u8)			(u8),
-#define OT_USHORT(u16)			(unsigned char)((u16)>>8), (unsigned char)((u16)&0xFFu),
+#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). */)
@@ -80,24 +80,24 @@
  */
 
 #define OT_TAG(a,b,c,d) \
-	OT_BYTE(a) OT_BYTE(b) OT_BYTE(c) OT_BYTE(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_USHORT(OT_DISTANCE(From, To))
+	OT_UINT16(OT_DISTANCE(From, To))
 
 #define OT_GLYPHID /* GlyphID */ \
-	OT_USHORT
+	OT_UINT16
 
 #define OT_UARRAY(Name, Items) \
 	OT_LABEL_START(Name) \
-	OT_USHORT(OT_COUNT(Name##Data, 2)) \
+	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_USHORT(OT_COUNT(Name##Data, 2) + 1) \
+	OT_UINT16(OT_COUNT(Name##Data, 2) + 1) \
 	OT_LABEL(Name##Data) \
 	Items \
 	OT_LABEL_END
@@ -111,19 +111,19 @@
 
 #define OT_LOOKUP(Name, LookupType, LookupFlag, SubLookupOffsets) \
 	OT_LABEL_START(Name) \
-	OT_USHORT(LookupType) \
-	OT_USHORT(LookupFlag) \
+	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_USHORT(SubFormat) \
+	OT_UINT16(SubFormat) \
 	Items
 
 #define OT_COVERAGE1(Name, Items) \
 	OT_LABEL_START(Name) \
-	OT_USHORT(1) \
+	OT_UINT16(1) \
 	OT_LABEL_END \
 	OT_UARRAY(Name##Glyphs, OT_LIST(Items))
 
@@ -174,7 +174,7 @@
 /* Table manifest. */
 #define MANIFEST(Items) \
 	OT_LABEL_START(manifest) \
-	OT_USHORT(OT_COUNT(manifestData, 6)) \
+	OT_UINT16(OT_COUNT(manifestData, 6)) \
 	OT_LABEL(manifestData) \
 	Items \
 	OT_LABEL_END
@@ -304,8 +304,8 @@
 #undef OT_TABLE_END
 #undef OT_LABEL_START
 #undef OT_LABEL_END
-#undef OT_BYTE
-#undef OT_USHORT
+#undef OT_UINT8
+#undef OT_UINT16
 #undef OT_DISTANCE
 #undef OT_COUNT
 
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
index 4a92d410..a18c9a1 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
@@ -24,14 +24,10 @@
  * Google Author(s): Behdad Esfahbod
  */
 
+#include "hb-debug.hh"
 #include "hb-ot-shape-complex-arabic-private.hh"
 #include "hb-ot-shape-private.hh"
-
-
-#ifndef HB_DEBUG_ARABIC
-#define HB_DEBUG_ARABIC (HB_DEBUG+0)
-#endif
-
+#include "hb-private.hh"
 
 /* buffer var allocations */
 #define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */
@@ -39,7 +35,8 @@
 #define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0
 
 /* See:
- * https://github.com/behdad/harfbuzz/commit/6e6f82b6f3dde0fc6c3c7d991d9ec6cfff57823d#commitcomment-14248516 */
+ * 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) | \
@@ -201,7 +198,7 @@
    * pause for Arabic, not other scripts.
    *
    * A pause after calt is required to make KFGQPC Uthmanic Script HAFS
-   * work correctly.  See https://github.com/behdad/harfbuzz/issues/505
+   * work correctly.  See https://github.com/harfbuzz/harfbuzz/issues/505
    */
 
   map->add_gsub_pause (nuke_joiners);
@@ -563,8 +560,9 @@
       }
       else
       {
-	hb_position_t x_offset = 0;
-	for (unsigned int k = end; k > start; k--)
+        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);
 
@@ -689,7 +687,6 @@
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
 {
-  "arabic",
   collect_features_arabic,
   nullptr, /* override_features */
   data_create_arabic,
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc
index 99b53a5..68a62a1 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc
@@ -29,7 +29,6 @@
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
 {
-  "default",
   nullptr, /* collect_features */
   nullptr, /* override_features */
   nullptr, /* data_create */
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
index 0f3337f..7508c223 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc
@@ -414,7 +414,6 @@
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
 {
-  "hangul",
   collect_features_hangul,
   override_features_hangul,
   data_create_hangul,
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
index fccd76a45..34cf28b 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc
@@ -161,7 +161,7 @@
    * 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/behdad/harfbuzz/issues/347#issuecomment-267838368
+   * https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368
    */
   return plan->map.chosen_script[1] != HB_TAG ('h','e','b','r');
 }
@@ -169,7 +169,6 @@
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
 {
-  "hebrew",
   nullptr, /* collect_features */
   nullptr, /* override_features */
   nullptr, /* data_create */
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
index 8fe2509e..a1e0d52 100644
--- 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
@@ -123,7 +123,7 @@
   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/behdad/harfbuzz/issues/552 */
+  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,
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
index 05a5136..9c7c359 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
@@ -210,19 +210,24 @@
   }
   else if (unlikely (u == 0x0A51u))
   {
-    /* https://github.com/behdad/harfbuzz/issues/524 */
+    /* 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 == 0x11303u)) cat = OT_SM;
+  /* 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/behdad/harfbuzz/issues/552 */
+  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/behdad/harfbuzz/issues/538 */
+  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 (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
   else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
 				    cat = OT_PLACEHOLDER;
@@ -508,7 +513,7 @@
 
       /* 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! */
-      (const_cast<indic_shape_plan_t *> (this))->virama_glyph = glyph;
+      virama_glyph = glyph;
     }
 
     *pglyph = glyph;
@@ -518,7 +523,7 @@
   const indic_config_t *config;
 
   bool is_old_spec;
-  hb_codepoint_t virama_glyph;
+  mutable hb_codepoint_t virama_glyph;
 
   would_substitute_feature_t rphf;
   would_substitute_feature_t pref;
@@ -691,8 +696,8 @@
   const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
   hb_glyph_info_t *info = buffer->info;
 
-  /* https://github.com/behdad/harfbuzz/issues/435#issuecomment-335560167
-   * // For compatibility with legacy useage in Kannada,
+  /* 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 &&
@@ -1686,12 +1691,15 @@
 
 
   /* Apply 'init' to the Left Matra if it's a word start. */
-  if (info[start].indic_position () == POS_PRE_M &&
-      (!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];
-
+  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!
@@ -1843,7 +1851,6 @@
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
 {
-  "indic",
   collect_features_indic,
   override_features_indic,
   data_create_indic,
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc
index f446fe6..5ea1dbf 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc
@@ -512,7 +512,6 @@
  * generic shaper, except that it zeros mark advances GDEF_LATE. */
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old =
 {
-  "default",
   nullptr, /* collect_features */
   nullptr, /* override_features */
   nullptr, /* data_create */
@@ -531,7 +530,6 @@
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
 {
-  "myanmar",
   collect_features_myanmar,
   override_features_myanmar,
   nullptr, /* data_create */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
index 4951cb5f..fb2f611 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
@@ -65,8 +65,6 @@
 
 struct hb_ot_complex_shaper_t
 {
-  char name[8];
-
   /* collect_features()
    * Called during shape_plan().
    * Shapers should use plan->map to add their features and callbacks.
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc
index 58a0a41..6ba925c6 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc
@@ -366,7 +366,6 @@
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
 {
-  "thai",
   nullptr, /* collect_features */
   nullptr, /* override_features */
   nullptr, /* data_create */
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
index e87f1a4..eaac0bf 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc
@@ -46,7 +46,6 @@
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan =
 {
-  "default",
   collect_features_tibetan,
   nullptr, /* override_features */
   nullptr, /* data_create */
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
index 1f90fc8..bf27a99 100644
--- 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
@@ -57,618 +57,668 @@
 
 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,
+    /* 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 */
 
-  /* 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,
+    /* 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_0x0900u 80
 
+    /* Devanagari */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
+    /* 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 1352
 
+    /* Myanmar */
 
-  /* 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,
+    /* 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 1512
 
+    /* Tagalog */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
+    /* 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 1752
 
+    /* Limbu */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
+    /* 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 2168
 
+    /* Balinese */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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,
 
-  /* 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 */
 
-  /* 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, VPst, VPst, O, O, O, O, O, O, O, O, O, O, O, O,
 
-  /* 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,  VPst,  VPst,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+    /* Lepcha */
 
-  /* 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,
+    /* 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 2504
 
+    /* Vedic Extensions */
 
-  /* 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,
+    /* 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 2552
 
-
-  /* Combining Diacritical Marks Supplement */
-                                                                         O,     O,     O,    FM,     O,     O,     O,     O,
+    /* Combining Diacritical Marks Supplement */
+    O, O, O, FM, O, O, O, O,
 
 #define use_offset_0x2008u 2560
 
-
-  /* General Punctuation */
-                                                                         O,     O,     O,     O,  ZWNJ,   ZWJ,     O,     O,
-  /* 2010 */    GB,    GB,    GB,    GB,    GB,     O,     O,     O,
+    /* General Punctuation */
+    O, O, O, O, ZWNJ, ZWJ, O, O,
+    /* 2010 */ GB, GB, GB, GB, GB, O, O, O,
 
 #define use_offset_0x2060u 2576
 
-  /* 2060 */    WJ,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+    /* 2060 */ WJ, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
 
-  /* Superscripts and Subscripts */
+    /* 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,
+    /* 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_0xa800u 2616
+#define use_offset_0x20f0u 2616
 
+    /* Combining Diacritical Marks for Symbols */
 
-  /* Syloti Nagri */
+    /* 20F0 */ VMAbv, O, O, O, O, O, O, O,
 
-  /* 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,
+#define use_offset_0xa800u 2624
 
-  /* Phags-pa */
+    /* Syloti Nagri */
 
-  /* 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,
+    /* 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,
 
-  /* Saurashtra */
+    /* Phags-pa */
 
-  /* 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,  FPst,  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,
+    /* 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,
 
-  /* Devanagari Extended */
+    /* Saurashtra */
 
-  /* 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,
+    /* 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,
 
-  /* Kayah Li */
+    /* Devanagari Extended */
 
-  /* 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,
+    /* 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,
 
-  /* Rejang */
+    /* Kayah Li */
 
-  /* 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,
+    /* 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,
 
-  /* Javanese */
+    /* Rejang */
 
-  /* 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,
+    /* 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,
 
-  /* Myanmar Extended-B */
+    /* Javanese */
 
-  /* 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,
+    /* 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,
 
-  /* Cham */
+    /* Myanmar Extended-B */
 
-  /* 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,
+    /* 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,
 
-  /* Myanmar Extended-A */
+    /* Cham */
 
-  /* 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,
+    /* 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,
 
-  /* Tai Viet */
+    /* Myanmar Extended-A */
 
-  /* 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,
+    /* 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,
 
-  /* Meetei Mayek Extensions */
+    /* Tai Viet */
 
-  /* 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,
+    /* 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,
 
-#define use_offset_0xabc0u 3376
+    /* 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,
 
-  /* Meetei Mayek */
+#define use_offset_0xabc0u 3384
 
-  /* 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,
+    /* Meetei Mayek */
 
-#define use_offset_0xfe00u 3440
+    /* 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 3448
 
-  /* Variation Selectors */
+    /* Variation Selectors */
 
-  /* FE00 */    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,
+    /* FE00 */ VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS,
 
-#define use_offset_0x10a00u 3456
+#define use_offset_0x10a00u 3464
 
+    /* Kharoshthi */
 
-  /* 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,
 
-  /* 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 3536
 
-#define use_offset_0x11000u 3528
+    /* 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, O,
 
-  /* Brahmi */
+    /* Kaithi */
 
-  /* 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,     O,
+    /* 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,
 
-  /* Kaithi */
+#define use_offset_0x11100u 3728
 
-  /* 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,
+    /* Chakma */
 
-#define use_offset_0x11100u 3720
+    /* 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 */
 
-  /* Chakma */
+    /* 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,
 
-  /* 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,
+    /* Sharada */
 
-  /* Mahajani */
+    /* 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,
 
-  /* 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,
+    /* Sinhala Archaic Numbers */
 
-  /* Sharada */
+    /* 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,
 
-  /* 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,
+    /* Khojki */
 
-  /* 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 4040
-
-
-  /* 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,
+    /* 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,
 
-  /* Grantha */
+#define use_offset_0x11280u 4048
 
-  /* 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,
+    /* Multani */
 
-#define use_offset_0x11400u 4288
+    /* 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 */
 
-  /* Newa */
+    /* 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,
 
-  /* 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,
+    /* Grantha */
 
-  /* Tirhuta */
+    /* 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,
 
-  /* 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_0x11400u 4296
 
-#define use_offset_0x11580u 4512
+    /* 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,
 
-  /* Siddham */
+    /* Tirhuta */
 
-  /* 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,
+    /* 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,
 
-  /* Modi */
+#define use_offset_0x11580u 4520
 
-  /* 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,
+    /* Siddham */
 
-  /* Takri */
+    /* 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,
 
-  /* 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,
+    /* Modi */
 
-  /* Ahom */
+    /* 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,
 
-  /* 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,
+    /* Takri */
 
-#define use_offset_0x11a00u 4960
+    /* 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 */
 
-  /* Zanabazar Square */
+    /* 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,
 
-  /* 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,
+#define use_offset_0x11a00u 4968
 
-  /* Soyombo */
+    /* Zanabazar Square */
 
-  /* 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,
+    /* 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,
 
-#define use_offset_0x11c00u 5120
+    /* 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,
 
-  /* Bhaiksuki */
+#define use_offset_0x11c00u 5128
 
-  /* 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,
+    /* Bhaiksuki */
 
-  /* Marchen */
+    /* 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,
 
-  /* 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,
+    /* Marchen */
 
-#define use_offset_0x11d00u 5304
+    /* 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 5312
 
-  /* Masaram Gondi */
+    /* 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,
+    /* 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: 5400; occupancy: 73% */
+}; /* Table items: 5408; occupancy: 73% */
 
 USE_TABLE_ELEMENT_TYPE
 hb_use_get_categories (hb_codepoint_t u)
@@ -694,6 +744,8 @@
     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 (unlikely (u == 0x25CCu)) return GB;
       break;
 
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
index a2cacac..62acd69 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-use.cc
@@ -595,7 +595,6 @@
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
 {
-  "use",
   collect_features_use,
   nullptr, /* override_features */
   data_create_use,
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc
index 4da53f4..c46f523 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc
@@ -209,8 +209,7 @@
   hb_glyph_position_t &pos = buffer->pos[i];
   pos.x_offset = pos.y_offset = 0;
 
-
-  /* We dont position LEFT and RIGHT marks. */
+  /* We don't position LEFT and RIGHT marks. */
 
   /* X positioning */
   switch (combining_class)
@@ -218,10 +217,12 @@
     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 - mark_extents.width / 2 - mark_extents.x_bearing;
+        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 + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing;
+        pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 -
+                        mark_extents.x_bearing;
         break;
       }
       HB_FALLTHROUGH;
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh
index d0fe9e6..fe5d2b7f 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh
@@ -99,7 +99,9 @@
   }
 
   private:
-  NO_COPY (hb_ot_shape_planner_t);
+  /* 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 &);
 };
 
 
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape.cc b/third_party/harfbuzz-ng/src/hb-ot-shape.cc
index 624132d..a7496780 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape.cc
@@ -108,7 +108,7 @@
     /* 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/behdad/harfbuzz/issues/63 */
+     * https://github.com/harfbuzz/harfbuzz/issues/63 */
     map->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL | F_GLOBAL_SEARCH);
   }
 
@@ -817,10 +817,15 @@
 {
   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_EXPANSION_FACTOR)))
-  {
-    c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_EXPANSION_FACTOR,
-			      (unsigned) HB_BUFFER_MAX_LEN_MIN);
+  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);
@@ -861,6 +866,7 @@
   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 ();
 }
 
diff --git a/third_party/harfbuzz-ng/src/hb-ot-tag.cc b/third_party/harfbuzz-ng/src/hb-ot-tag.cc
index 64c6ce0..ae354e2 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-tag.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-tag.cc
@@ -878,10 +878,9 @@
   {"zh-hant",	HB_TAG('Z','H','T',' ')},	/* Chinese (Traditional) */
 };
 
-static int
-lang_compare_first_component (const char *a,
-			      const char *b)
-{
+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;
 
@@ -923,7 +922,7 @@
     if (i) {
       for (; i < 4; i++)
 	tag[i] = ' ';
-      return HB_TAG_CHAR4 (tag);
+      return HB_TAG(tag[0], tag[1], tag[2], tag[3]);
     }
   }
 
@@ -970,9 +969,9 @@
   /* Find a language matching in the first component */
   {
     const LangTag *lang_tag;
-    lang_tag = (LangTag *) bsearch (lang_str, ot_languages,
-				    ARRAY_LENGTH (ot_languages), sizeof (LangTag),
-				    (hb_compare_func_t) lang_compare_first_component);
+    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;
   }
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
index 464cf35..4b88a40 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-var-avar-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-var-avar-table.hh
@@ -133,8 +133,8 @@
   protected:
   FixedVersion<>version;	/* Version of the avar table
 				 * initially set to 0x00010000u */
-  USHORT	reserved;	/* This field is permanently reserved. Set to 0. */
-  USHORT	axisCount;	/* The number of variation axes in the font. This
+  UINT16	reserved;	/* This field is permanently reserved. Set to 0. */
+  UINT16	axisCount;	/* The number of variation axes in the font. This
 				 * must be the same number as axisCount in the
 				 * 'fvar' table. */
   SegmentMaps	axisSegmentMapsZ;
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
index 9f6fb32..2a9357a 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-var-fvar-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-var-fvar-table.hh
@@ -42,11 +42,11 @@
   }
 
   protected:
-  USHORT	subfamilyNameID;/* The name ID for entries in the 'name' table
+  UINT16	subfamilyNameID;/* The name ID for entries in the 'name' table
 				 * that provide subfamily names for this instance. */
-  USHORT	reserved;	/* Reserved for future use — set to 0. */
+  UINT16	reserved;	/* Reserved for future use — set to 0. */
   Fixed		coordinates[VAR];/* The coordinates array for this instance. */
-  //USHORT	postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
+  //UINT16	postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
   //				  * table that provide PostScript names for this
   //				  * instance. */
 
@@ -67,8 +67,8 @@
   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. */
-  USHORT	reserved;	/* Reserved for future use — set to 0. */
-  USHORT	axisNameID;	/* The name ID for entries in the 'name' table that
+  UINT16	reserved;	/* Reserved for future use — set to 0. */
+  UINT16	axisNameID;	/* The name ID for entries in the 'name' table that
 				 * provide a display name for this axis. */
 
   public:
@@ -186,16 +186,16 @@
   protected:
   FixedVersion<>version;	/* Version of the fvar table
 				 * initially set to 0x00010000u */
-  Offset<>	things;		/* Offset in bytes from the beginning of the table
+  Offset16	things;		/* Offset in bytes from the beginning of the table
 				 * to the start of the AxisRecord array. */
-  USHORT	reserved;	/* This field is permanently reserved. Set to 2. */
-  USHORT	axisCount;	/* The number of variation axes in the font (the
+  UINT16	reserved;	/* This field is permanently reserved. Set to 2. */
+  UINT16	axisCount;	/* The number of variation axes in the font (the
 				 * number of records in the axes array). */
-  USHORT	axisSize;	/* The size in bytes of each VariationAxisRecord —
+  UINT16	axisSize;	/* The size in bytes of each VariationAxisRecord —
 				 * set to 20 (0x0014) for this version. */
-  USHORT	instanceCount;	/* The number of named instances defined in the font
+  UINT16	instanceCount;	/* The number of named instances defined in the font
 				 * (the number of records in the instances array). */
-  USHORT	instanceSize;	/* The size in bytes of each InstanceRecord — set
+  UINT16	instanceSize;	/* The size in bytes of each InstanceRecord — set
 				 * to either axisCount * sizeof(Fixed) + 4, or to
 				 * axisCount * sizeof(Fixed) + 6. */
 
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
index f9d801e..fac843a 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-var-hvar-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-var-hvar-table.hh
@@ -55,7 +55,7 @@
     unsigned int u = 0;
     { /* Fetch it. */
       unsigned int w = get_width ();
-      const BYTE *p = mapData + w * v;
+      const UINT8 *p = mapData + w * v;
       for (; w; w--)
 	u = (u << 8) + *p++;
     }
@@ -78,10 +78,10 @@
   { return (format & 0xF) + 1; }
 
   protected:
-  USHORT	format;		/* A packed field that describes the compressed
+  UINT16	format;		/* A packed field that describes the compressed
 				 * representation of delta-set indices. */
-  USHORT	mapCount;	/* The number of mapping entries. */
-  BYTE		mapData[VAR];	/* The delta-set index mapping data. */
+  UINT16	mapCount;	/* The number of mapping entries. */
+  UINT8		mapData[VAR];	/* The delta-set index mapping data. */
 
   public:
   DEFINE_SIZE_ARRAY (4, mapData);
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
index 3cb7498..e17ff51 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-var-mvar-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-var-mvar-table.hh
@@ -43,7 +43,7 @@
 
   public:
   Tag		valueTag;	/* Four-byte tag identifying a font-wide measure. */
-  ULONG		varIdx;		/* Outer/inner index into VariationStore item. */
+  UINT32		varIdx;		/* Outer/inner index into VariationStore item. */
 
   public:
   DEFINE_SIZE_STATIC (8);
@@ -77,7 +77,7 @@
     const VariationValueRecord *record;
     record = (VariationValueRecord *) bsearch (&tag, values,
 					       valueRecordCount, valueRecordSize,
-					       (hb_compare_func_t) tag_compare);
+					       tag_compare);
     if (!record)
       return 0.;
 
@@ -85,19 +85,23 @@
   }
 
 protected:
-  static inline int tag_compare (const hb_tag_t *a, const Tag *b)
-  { return b->cmp (*a); }
+  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 */
-  USHORT	reserved;	/* Not used; set to 0. */
-  USHORT	valueRecordSize;/* The size in bytes of each value record —
+  UINT16	reserved;	/* Not used; set to 0. */
+  UINT16	valueRecordSize;/* The size in bytes of each value record —
 				 * must be greater than zero. */
-  USHORT	valueRecordCount;/* The number of value records — may be zero. */
+  UINT16	valueRecordCount;/* The number of value records — may be zero. */
   OffsetTo<VariationStore>
 		varStore;	/* Offset to item variation store table. */
-  BYTE		values[VAR];	/* Array of value records. The records must be
+  UINT8		values[VAR];	/* Array of value records. The records must be
 				 * in binary order of their valueTag field. */
 
   public:
diff --git a/third_party/harfbuzz-ng/src/hb-private.hh b/third_party/harfbuzz-ng/src/hb-private.hh
index b139ed6..117f4983 100644
--- a/third_party/harfbuzz-ng/src/hb-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-private.hh
@@ -44,16 +44,14 @@
 #include <stddef.h>
 #include <string.h>
 #include <assert.h>
-
-/* We only use these two for debug output.  However, the debug code is
- * always seen by the compiler (and optimized out in non-debug builds.
- * If including these becomes a problem, we can start thinking about
- * someway around that. */
-#include <stdio.h>
 #include <errno.h>
+#include <stdio.h>
 #include <stdarg.h>
 
 
+#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) \
@@ -76,36 +74,19 @@
 
 #if __cplusplus < 201103L
 
-// Null pointer literal
-// Source: SC22/WG21/N2431 = J16/07-0301
-// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf
-
-const                        // this is a const object...
-class {
-public:
-    template<class T>          // convertible to any type
-    operator T*() const {    // of null non-member
-        return 0;    // pointer...
-    }
-    template<class C, class T> // or any type of null
-    operator T C::*() const { // member pointer...
-        return 0;
-    }
-private:
-    void operator&() const;    // whose address can't be taken
-} _hb_nullptr = {};            // and whose name is nullptr
-#define nullptr _hb_nullptr
+#ifndef nullptr
+#define nullptr NULL
+#endif
 
 // Static assertions
 #ifndef static_assert
-#define _PASTE1(a,b) a##b
-#define _PASTE(a,b) _PASTE1(a,b)
 #define static_assert(e, msg) \
-	HB_UNUSED typedef int _PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
+	HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
 #endif // static_assert
 
 #endif // __cplusplus < 201103L
 
+#define _GNU_SOURCE 1
 
 #if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
 #define likely(expr) (__builtin_expect (!!(expr), 1))
@@ -131,6 +112,8 @@
 #endif
 #if __GNUC__ >= 4
 #define HB_UNUSED	__attribute__((unused))
+#elif defined(_MSC_VER)
+#define HB_UNUSED __pragma(warning(suppress: 4100 4101))
 #else
 #define HB_UNUSED
 #endif
@@ -386,11 +369,6 @@
 }
 
 
-/* Type of bsearch() / qsort() compare function */
-typedef int (*hb_compare_func_t) (const void *, const void *);
-
-
-
 
 /* arrays and maps */
 
@@ -494,12 +472,12 @@
 
   inline void qsort (void)
   {
-    ::qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
+    ::qsort (array, len, sizeof (Type), Type::cmp);
   }
 
   inline void qsort (unsigned int start, unsigned int end)
   {
-    ::qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
+    ::qsort (array + start, end - start, sizeof (Type), Type::cmp);
   }
 
   template <typename T>
@@ -559,7 +537,7 @@
 template <typename item_t, typename lock_t>
 struct hb_lockable_set_t
 {
-  hb_prealloced_array_t <item_t, 2> items;
+  hb_prealloced_array_t <item_t, 1> items;
 
   inline void init (void) { items.init (); }
 
@@ -664,22 +642,6 @@
 static inline unsigned char TOLOWER (unsigned char c)
 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
 
-#define HB_TAG_CHAR4(s)   (HB_TAG(((const char *) s)[0], \
-				  ((const char *) s)[1], \
-				  ((const char *) s)[2], \
-				  ((const char *) s)[3]))
-
-
-/* C++ helpers */
-
-/* Makes class uncopyable.  Use in private: section. */
-#define NO_COPY(T) \
-  T (const T &o); \
-  T &operator = (const T &o)
-
-
-/* Debug */
-
 
 /* HB_NDEBUG disables some sanity checks that are very safe to disable and
  * should be disabled in production systems.  If NDEBUG is defined, enable
@@ -690,255 +652,6 @@
 #define HB_NDEBUG
 #endif
 
-#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, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) 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,
-				   ...) : 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> /* Optimize when tracing is disabled */
-struct hb_auto_trace_t<0, ret_t> {
-  explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED,
-				   const char *what HB_UNUSED,
-				   const void *obj HB_UNUSED,
-				   const char *func HB_UNUSED,
-				   const char *message HB_UNUSED,
-				   ...) {}
-
-  inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
-};
-
-#define return_trace(RET) return trace.ret (RET, __LINE__)
 
 /* Misc */
 
@@ -981,7 +694,7 @@
  * 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/behdad/harfbuzz/pull/163
+ * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
  */
 #ifdef _MSC_VER
 # pragma warning(disable:4200)
@@ -1156,4 +869,31 @@
 /* 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-private.hh b/third_party/harfbuzz-ng/src/hb-set-private.hh
index 71a843f..5971e9b 100644
--- a/third_party/harfbuzz-ng/src/hb-set-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-set-private.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2012  Google, Inc.
+ * Copyright © 2012,2017  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -35,136 +35,398 @@
  * hb_set_t
  */
 
-
-/* TODO Make this faster and memmory efficient. */
+/* 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;
+
+      for (; j < ELT_BITS; j++)
+        if (v[i] & (elt_t (1) << j))
+	  goto found;
+      for (i++; i < len (); i++)
+        if (v[i])
+	  for (j = 0; j < ELT_BITS; j++)
+	    if (v[i] & (elt_t (1) << j))
+	      goto found;
+
+      *codepoint = INVALID;
+      return false;
+
+    found:
+      *codepoint = i * ELT_BITS + j;
+      return true;
+    }
+    inline hb_codepoint_t get_min (void) const
+    {
+      for (unsigned int i = 0; i < len (); i++)
+        if (v[i])
+	{
+	  elt_t e = v[i];
+	  for (unsigned int j = 0; j < ELT_BITS; j++)
+	    if (e & (elt_t (1) << j))
+	      return i * ELT_BITS + j;
+	}
+      return INVALID;
+    }
+    inline hb_codepoint_t get_max (void) const
+    {
+      for (int i = len () - 1; i >= 0; i--)
+        if (v[i])
+	{
+	  elt_t e = v[i];
+	  for (int j = ELT_BITS - 1; j >= 0; j--)
+	    if (e & (elt_t (1) << j))
+	      return i * ELT_BITS + j;
+	}
+      return 0;
+    }
+
+    static const unsigned int PAGE_BITS = 512; /* Use to tune. */
+    static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
+
+    typedef uint64_t elt_t;
+
+#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, 8> pages;
 
-  inline void init (void) {
-    hb_object_init (this);
-    clear ();
+  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 fini (void) {
-  }
+
   inline void clear (void) {
     if (unlikely (hb_object_is_inert (this)))
       return;
     in_error = false;
-    memset (elts, 0, sizeof elts);
+    page_map.resize (0);
+    pages.resize (0);
   }
   inline bool is_empty (void) const {
-    for (unsigned int i = 0; i < ARRAY_LENGTH (elts); i++)
-      if (elts[i])
+    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;
-    if (unlikely (g > MAX_G)) return;
-    elt (g) |= mask (g);
+    page_t *page = page_for_insert (g);
+    if (unlikely (!page)) return;
+    page->add (g);
   }
   inline void add_range (hb_codepoint_t a, hb_codepoint_t b)
   {
-    if (unlikely (in_error)) return;
-    /* TODO Speedup */
-    for (unsigned int i = a; i < b + 1; i++)
-      add (i);
+    if (unlikely (in_error || a > b || a == INVALID || b == INVALID)) return;
+    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;
+      page->add_range (a, b);
+    }
+    else
+    {
+      page_t *page = page_for_insert (a);
+      if (unlikely (!page)) return;
+      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;
+	page->init1 ();
+      }
+
+      page = page_for_insert (b);
+      if (unlikely (!page)) return;
+      page->add_range (major_start (mb), b);
+    }
   }
   inline void del (hb_codepoint_t g)
   {
     if (unlikely (in_error)) return;
-    if (unlikely (g > MAX_G)) return;
-    elt (g) &= ~mask (g);
+    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;
-    /* TODO Speedup */
     for (unsigned int i = a; i < b + 1; i++)
       del (i);
   }
   inline bool has (hb_codepoint_t g) const
   {
-    if (unlikely (g > MAX_G)) return false;
-    return !!(elt (g) & mask (g));
+    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
   {
-    if (unlikely (first > MAX_G)) return false;
-    if (unlikely (last  > MAX_G)) last = MAX_G;
-    unsigned int end = last + 1;
-    for (hb_codepoint_t i = first; i < end; i++)
-      if (has (i))
-        return true;
-    return false;
-  }
-  inline bool is_equal (const hb_set_t *other) const
-  {
-    for (unsigned int i = 0; i < ELTS; i++)
-      if (elts[i] != other->elts[i])
-        return false;
-    return true;
+    hb_codepoint_t c = first - 1;
+    return next (&c) && c <= last;
   }
   inline void set (const hb_set_t *other)
   {
     if (unlikely (in_error)) return;
-    for (unsigned int i = 0; i < ELTS; i++)
-      elts[i] = other->elts[i];
+    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 void union_ (const hb_set_t *other)
+
+  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;
-    for (unsigned int i = 0; i < ELTS; i++)
-      elts[i] |= other->elts[i];
+
+    unsigned int na = pages.len;
+    unsigned int nb = other->pages.len;
+
+    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--;
+        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)
+	  page_at (--count).v = page_at (a).v;
+      }
+      else
+      {
+        b--;
+        if (Op::passthru_right)
+	  page_at (--count).v = other->page_at (b).v;
+      }
+    }
+    if (Op::passthru_left)
+      while (a)
+	page_at (--count).v = page_at (--a).v;
+    if (Op::passthru_right)
+      while (b)
+	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)
   {
-    if (unlikely (in_error)) return;
-    for (unsigned int i = 0; i < ELTS; i++)
-      elts[i] &= other->elts[i];
+    process<HbOpAnd> (other);
   }
   inline void subtract (const hb_set_t *other)
   {
-    if (unlikely (in_error)) return;
-    for (unsigned int i = 0; i < ELTS; i++)
-      elts[i] &= ~other->elts[i];
+    process<HbOpMinus> (other);
   }
   inline void symmetric_difference (const hb_set_t *other)
   {
-    if (unlikely (in_error)) return;
-    for (unsigned int i = 0; i < ELTS; i++)
-      elts[i] ^= other->elts[i];
-  }
-  inline void invert (void)
-  {
-    if (unlikely (in_error)) return;
-    for (unsigned int i = 0; i < ELTS; i++)
-      elts[i] = ~elts[i];
+    process<HbOpXor> (other);
   }
   inline bool next (hb_codepoint_t *codepoint) const
   {
     if (unlikely (*codepoint == INVALID)) {
-      hb_codepoint_t i = get_min ();
-      if (i != INVALID) {
-        *codepoint = i;
+      *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)
+    {
+      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;
-      } else {
-	*codepoint = INVALID;
-        return false;
       }
     }
-    for (hb_codepoint_t i = *codepoint + 1; i < MAX_G + 1; i++)
-      if (has (i)) {
-        *codepoint = i;
-	return true;
-      }
     *codepoint = INVALID;
     return false;
   }
@@ -188,46 +450,66 @@
 
   inline unsigned int get_population (void) const
   {
-    unsigned int count = 0;
-    for (unsigned int i = 0; i < ELTS; i++)
-      count += _hb_popcount32 (elts[i]);
-    return count;
+    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
   {
-    for (unsigned int i = 0; i < ELTS; i++)
-      if (elts[i])
-	for (unsigned int j = 0; j < BITS; j++)
-	  if (elts[i] & (1u << j))
-	    return i * BITS + j;
+    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
   {
-    for (unsigned int i = ELTS; i; i--)
-      if (elts[i - 1])
-	for (unsigned int j = BITS; j; j--)
-	  if (elts[i - 1] & (1u << (j - 1)))
-	    return (i - 1) * BITS + (j - 1);
+    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;
   }
 
-  typedef uint32_t elt_t;
-  static const unsigned int MAX_G = 65536 - 1; /* XXX Fix this... */
-  static const unsigned int SHIFT = 5;
-  static const unsigned int BITS = (1 << SHIFT);
-  static const unsigned int MASK = BITS - 1;
-  static const unsigned int ELTS = (MAX_G + 1 + (BITS - 1)) / BITS;
   static  const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
 
-  elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; }
-  elt_t const &elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; }
-  elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); }
+  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;
 
-  elt_t elts[ELTS]; /* XXX 8kb */
-
-  static_assert ((sizeof (elt_t) * 8 == BITS), "");
-  static_assert ((sizeof (elt_t) * 8 * ELTS > MAX_G), "");
+      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; }
 };
 
 
diff --git a/third_party/harfbuzz-ng/src/hb-set.cc b/third_party/harfbuzz-ng/src/hb-set.cc
index f3fe1ba4..d61a24c0 100644
--- a/third_party/harfbuzz-ng/src/hb-set.cc
+++ b/third_party/harfbuzz-ng/src/hb-set.cc
@@ -45,7 +45,8 @@
   if (!(set = hb_object_create<hb_set_t> ()))
     return hb_set_get_empty ();
 
-  set->clear ();
+  set->page_map.init();
+  set->pages.init();
 
   return set;
 }
@@ -95,7 +96,8 @@
 {
   if (!hb_object_destroy (set)) return;
 
-  set->fini ();
+  set->page_map.finish();
+  set->pages.finish();
 
   free (set);
 }
@@ -373,14 +375,15 @@
  * hb_set_invert:
  * @set: a set.
  *
- * 
+ *
  *
  * Since: 0.9.10
+ *
+ * Deprecated: 1.6.1
  **/
 void
 hb_set_invert (hb_set_t *set)
 {
-  set->invert ();
 }
 
 /**
diff --git a/third_party/harfbuzz-ng/src/hb-shape-plan.cc b/third_party/harfbuzz-ng/src/hb-shape-plan.cc
index e58f9ff80b1..b38be2ce 100644
--- a/third_party/harfbuzz-ng/src/hb-shape-plan.cc
+++ b/third_party/harfbuzz-ng/src/hb-shape-plan.cc
@@ -24,16 +24,12 @@
  * Google Author(s): Behdad Esfahbod
  */
 
+#include "hb-buffer-private.hh"
+#include "hb-debug.hh"
+#include "hb-font-private.hh"
+#include "hb-private.hh"
 #include "hb-shape-plan-private.hh"
 #include "hb-shaper-private.hh"
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
-
-
-#ifndef HB_DEBUG_SHAPE_PLAN
-#define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0)
-#endif
-
 
 static void
 hb_shape_plan_plan (hb_shape_plan_t    *shape_plan,
diff --git a/third_party/harfbuzz-ng/src/hb-string-array.hh b/third_party/harfbuzz-ng/src/hb-string-array.hh
new file mode 100644
index 0000000..ba829b0c
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-string-array.hh
@@ -0,0 +1,81 @@
+/*
+ * 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-ucdn.cc b/third_party/harfbuzz-ng/src/hb-ucdn.cc
index c237ee82..eb1f1d0 100644
--- a/third_party/harfbuzz-ng/src/hb-ucdn.cc
+++ b/third_party/harfbuzz-ng/src/hb-ucdn.cc
@@ -231,22 +231,42 @@
     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)
 {
-  static const hb_unicode_funcs_t _hb_ucdn_unicode_funcs = {
-    HB_OBJECT_HEADER_STATIC,
+retry:
+  hb_unicode_funcs_t* funcs =
+      (hb_unicode_funcs_t*)hb_atomic_ptr_get(&static_ucdn_funcs);
 
-    nullptr, /* parent */
-    true, /* immutable */
-    {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_ucdn_##name,
-      HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+  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 const_cast<hb_unicode_funcs_t *> (&_hb_ucdn_unicode_funcs);
+  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
index ac17f28..82bb9a4 100644
--- a/third_party/harfbuzz-ng/src/hb-unicode-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-unicode-private.hh
@@ -137,7 +137,7 @@
    * 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/behdad/harfbuzz/issues/503
+   * Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503
    *
    * Unicode 7.0:
    * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
diff --git a/third_party/harfbuzz-ng/src/hb-version.h b/third_party/harfbuzz-ng/src/hb-version.h
index e283983..3a76a02 100644
--- a/third_party/harfbuzz-ng/src/hb-version.h
+++ b/third_party/harfbuzz-ng/src/hb-version.h
@@ -37,10 +37,10 @@
 
 
 #define HB_VERSION_MAJOR 1
-#define HB_VERSION_MINOR 6
-#define HB_VERSION_MICRO 3
+#define HB_VERSION_MINOR 7
+#define HB_VERSION_MICRO 2
 
-#define HB_VERSION_STRING "1.6.3"
+#define HB_VERSION_STRING "1.7.2"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
 	((major)*10000+(minor)*100+(micro) <= \
diff --git a/third_party/harfbuzz-ng/src/main.cc b/third_party/harfbuzz-ng/src/main.cc
index 93c3b46a..d12d8df 100644
--- a/third_party/harfbuzz-ng/src/main.cc
+++ b/third_party/harfbuzz-ng/src/main.cc
@@ -38,6 +38,7 @@
 
 using namespace OT;
 
+const void* const OT::_hb_NullPool[HB_NULL_POOL_SIZE / sizeof(void*)] = {};
 
 int
 main (int argc, char **argv)
@@ -104,72 +105,73 @@
 	      (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);
 
-      case GSUBGPOS::GSUBTag:
-      case GSUBGPOS::GPOSTag:
-	{
+          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));
 
-	const GSUBGPOS &g = *CastP<GSUBGPOS> (font_data + table.offset);
+            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_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));
+              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));
+              }
+            }
+          }
 
-	  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 = 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)));
 
-	    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));
-	    }
-	  }
-	}
+            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_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)));
+          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());
+          }
 
-	  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:
diff --git a/third_party/harfbuzz-ng/src/test-buffer-serialize.cc b/third_party/harfbuzz-ng/src/test-buffer-serialize.cc
index c52d88a..5c329a5a 100644
--- a/third_party/harfbuzz-ng/src/test-buffer-serialize.cc
+++ b/third_party/harfbuzz-ng/src/test-buffer-serialize.cc
@@ -24,10 +24,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include "hb-private.hh"
 
+#include "hb-ot.h"
 #include "hb.h"
 #ifdef HAVE_FREETYPE
 #include "hb-ft.h"
@@ -92,8 +91,9 @@
   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);
+// hb_ft_font_set_funcs (font);
 #endif
 
   hb_buffer_t *buf;
diff --git a/third_party/harfbuzz-ng/src/test-size-params.cc b/third_party/harfbuzz-ng/src/test-size-params.cc
index faa8280..9741b87 100644
--- a/third_party/harfbuzz-ng/src/test-size-params.cc
+++ b/third_party/harfbuzz-ng/src/test-size-params.cc
@@ -24,9 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include "hb-private.hh"
 
 #include "hb.h"
 #include "hb-ot.h"
diff --git a/third_party/harfbuzz-ng/src/test-would-substitute.cc b/third_party/harfbuzz-ng/src/test-would-substitute.cc
index cad5b5a0..efebf2d0 100644
--- a/third_party/harfbuzz-ng/src/test-would-substitute.cc
+++ b/third_party/harfbuzz-ng/src/test-would-substitute.cc
@@ -24,9 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include "hb-private.hh"
 
 #include "hb.h"
 #include "hb-ot.h"
diff --git a/third_party/harfbuzz-ng/src/test.cc b/third_party/harfbuzz-ng/src/test.cc
index 2c24fdac..9592b37 100644
--- a/third_party/harfbuzz-ng/src/test.cc
+++ b/third_party/harfbuzz-ng/src/test.cc
@@ -24,9 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include "hb-private.hh"
 
 #include "hb.h"